encode static method
QRCode
encode(
- String content, [
- ErrorCorrectionLevel ecLevel = ErrorCorrectionLevel.H,
- EncodeHint? hints
Implementation
static QRCode encode(
String content, [
ErrorCorrectionLevel ecLevel = ErrorCorrectionLevel.H,
EncodeHint? hints,
]) {
Version version;
BitArray headerAndDataBits;
Mode mode;
final hasGS1FormatHint = hints?.gs1Format ?? false;
final hasCompactionHint = hints?.qrCompact ?? false;
// Determine what character encoding has been specified by the caller, if any
Encoding? encoding = defaultByteModeEncoding;
final hasEncodingHint = hints?.characterSet != null;
if (hasEncodingHint) {
encoding = CharacterSetECI.getCharacterSetECIByName(
hints!.characterSet!,
)?.charset;
}
if (hasCompactionHint) {
mode = Mode.byte;
final priorityEncoding =
encoding == defaultByteModeEncoding ? null : encoding;
final rn = MinimalEncoder.encode(
content,
null,
priorityEncoding,
hasGS1FormatHint,
ecLevel,
);
headerAndDataBits = BitArray();
rn.getBits(headerAndDataBits);
version = rn.getVersion();
} else {
// 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.
mode = _chooseMode(content, encoding);
// This will store the header information, like mode and
// length, as well as "header" segments like an ECI segment.
final headerBits = BitArray();
// Append ECI segment if applicable
if (mode == Mode.byte && hasEncodingHint && encoding != null) {
final eci = CharacterSetECI.getCharacterSetECI(encoding);
if (eci != null) {
_appendECI(eci, headerBits);
}
}
// Append the FNC1 mode header for GS1 formatted data if applicable
if (hasGS1FormatHint) {
// 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.
final dataBits = BitArray();
appendBytes(content, mode, dataBits, encoding!);
if (hints?.qrVersion != null) {
final versionNumber = hints!.qrVersion!;
version = Version.getVersionForNumber(versionNumber);
final 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);
}
headerAndDataBits = BitArray();
headerAndDataBits.appendBitArray(headerBits);
// Find "length" of main segment and write it
final numLetters =
mode == Mode.byte ? dataBits.sizeInBytes : content.length;
appendLengthInfo(numLetters, version, mode, headerAndDataBits);
// Put data together into the overall payload
headerAndDataBits.appendBitArray(dataBits);
}
final ecBlocks = version.getECBlocksForLevel(ecLevel);
final numDataBytes = version.totalCodewords - ecBlocks.totalECCodewords;
// Terminate the bits properly.
terminateBits(numDataBytes, headerAndDataBits);
// Interleave data bits with error correction code.
final finalBits = interleaveWithECBytes(
headerAndDataBits,
version.totalCodewords,
numDataBytes,
ecBlocks.numBlocks,
);
final qrCode = QRCode(ecLevel: ecLevel, mode: mode, version: version);
// Choose the mask pattern and set to "qrCode".
final dimension = version.dimensionForVersion;
final matrix = ByteMatrix(dimension, dimension);
// Enable manual selection of the pattern to be used via hint
int maskPattern = -1;
if (hints?.qrMaskPattern != null) {
final hintMaskPattern = hints!.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;
}