encode static method
@param content text to encode @param ecLevel error correction level to use @return {@link QRCode} representing the encoded QR code @throws WriterException if encoding can't succeed, because of for example invalid content or configuration
Implementation
static QRCode encode(String content, ErrorCorrectionLevel ecLevel,
{EncodeHints? hints}) {
hints ??= EncodeHints();
// Determine what character encoding has been specified by the caller, if any
var encoding = defaultByteModeEncoding;
var hasEncodingHint = hints.contains(EncodeHintType.characterSet);
if (hasEncodingHint) {
encoding = hints.get(EncodeHintType.characterSet)!;
}
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use
// multiple modes / segments even if that were more efficient. Twould be nice.
var mode = chooseMode(content, encoding: encoding);
// This will store the header information, like mode and
// length, as well as "header" segments like an ECI segment.
var headerBits = BitArray();
// Append ECI segment if applicable
if (mode == Mode.byte && hasEncodingHint) {
var eci = encoding;
_appendECI(eci, headerBits);
}
// Append the FNC1 mode header for GS1 formatted data if applicable
if (hints.get(EncodeHintType.gs1Format) ?? false) {
// GS1 formatted codes are prefixed with a FNC1 in first position mode header
appendModeInfo(Mode.fnc1FirstPosition, headerBits);
}
// (With ECI in place,) Write the mode marker
appendModeInfo(mode, headerBits);
// Collect data within the main segment, separately, to count its size if needed. Don't add it to
// main payload yet.
var dataBits = BitArray();
appendBytes(content, mode, dataBits, encoding);
Version version;
var versionNumber = hints.get(EncodeHintType.qrVersion);
if (versionNumber != null) {
version = Version.getVersionForNumber(versionNumber);
var bitsNeeded =
_calculateBitsNeeded(mode, headerBits, dataBits, version);
if (!_willFit(bitsNeeded, version, ecLevel)) {
throw WriterException('Data too big for requested version');
}
} else {
version = _recommendVersion(ecLevel, mode, headerBits, dataBits);
}
var headerAndDataBits = BitArray();
headerAndDataBits.appendBitArray(headerBits);
// Find "length" of main segment and write it
var numLetters = mode == Mode.byte ? dataBits.sizeInBytes : content.length;
appendLengthInfo(numLetters, version, mode, headerAndDataBits);
// Put data together into the overall payload
headerAndDataBits.appendBitArray(dataBits);
var ecBlocks = version.getECBlocksForLevel(ecLevel);
var numDataBytes = version.totalCodewords - ecBlocks.getTotalECCodewords();
// Terminate the bits properly.
terminateBits(numDataBytes, headerAndDataBits);
// Interleave data bits with error correction code.
var finalBits = interleaveWithECBytes(headerAndDataBits,
version.totalCodewords, numDataBytes, ecBlocks.numBlocks);
var qrCode = QRCode();
qrCode.ecLevel = ecLevel;
qrCode.mode = mode;
qrCode.version = version;
// Choose the mask pattern and set to "qrCode".
var dimension = version.dimensionForVersion;
var matrix = ByteMatrix(dimension, dimension);
// Enable manual selection of the pattern to be used via hint
var maskPattern = -1;
if (hints.contains(EncodeHintType.qrMaskPattern)) {
var hintMaskPattern = hints.get(EncodeHintType.qrMaskPattern)!;
maskPattern =
QRCode.isValidMaskPattern(hintMaskPattern) ? hintMaskPattern : -1;
}
if (maskPattern == -1) {
maskPattern = _chooseMaskPattern(finalBits, ecLevel, version, matrix);
}
qrCode.maskPattern = maskPattern;
// Build the matrix and set it to "qrCode".
MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
qrCode.matrix = matrix;
return qrCode;
}