encodeHighLevel static method
Performs high-level encoding of a PDF417 message using the algorithm described in annex P of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction is used.
@param msg the message
@param compaction compaction mode to use
@param encoding character encoding used to encode in default or byte compaction
or null
for default / not applicable
@return the encoded message (the char values range from 0 to 928)
Implementation
static String encodeHighLevel(
String msg,
Compaction compaction,
Encoding? encoding,
bool autoECI,
) {
if (msg.isEmpty) {
throw WriterException('Empty message not allowed');
}
if (encoding == null && !autoECI) {
for (int i = 0; i < msg.length; i++) {
if (msg.codeUnitAt(i) > 255) {
throw WriterException(
'Non-encodable character detected: ${msg.codeUnitAt(i)} (Unicode: '
'${msg.codeUnitAt(i)}). Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET.');
}
}
}
//the codewords 0..928 are encoded as Unicode characters
final sb = StringBuffer();
ECIInput input;
if (autoECI) {
input = MinimalECIInput(msg, encoding, -1);
} else {
input = NoECIInput(msg);
if (encoding == null) {
encoding = _defaultEncoding;
} else if (_defaultEncoding.name != encoding.name) {
final eci = CharacterSetECI.getCharacterSetECI(encoding);
if (eci != null) {
_encodingECI(eci.value, sb);
}
}
}
final len = input.length;
int p = 0;
int textSubMode = _SUBMODE_ALPHA;
// User selected encoding mode
switch (compaction) {
case Compaction.TEXT:
_encodeText(input, p, len, sb, textSubMode);
break;
case Compaction.BYTE:
if (autoECI) {
_encodeMultiECIBinary(input, 0, input.length, _TEXT_COMPACTION, sb);
} else {
final msgBytes =
Uint8List.fromList(encoding!.encode(input.toString()));
_encodeBinary(msgBytes, p, msgBytes.length, _BYTE_COMPACTION, sb);
}
break;
case Compaction.NUMERIC:
sb.writeCharCode(_LATCH_TO_NUMERIC);
_encodeNumeric(input, p, len, sb);
break;
default:
int encodingMode = _TEXT_COMPACTION; //Default mode, see 4.4.2.1
while (p < len) {
while (p < len && input.isECI(p)) {
_encodingECI(input.getECIValue(p), sb);
p++;
}
if (p >= len) {
break;
}
final n = _determineConsecutiveDigitCount(input, p);
if (n >= 13) {
sb.writeCharCode(_LATCH_TO_NUMERIC);
encodingMode = _NUMERIC_COMPACTION;
textSubMode = _SUBMODE_ALPHA; //Reset after latch
_encodeNumeric(input, p, n, sb);
p += n;
} else {
final t = _determineConsecutiveTextCount(input, p);
if (t >= 5 || n == len) {
if (encodingMode != _TEXT_COMPACTION) {
sb.writeCharCode(_LATCH_TO_TEXT);
encodingMode = _TEXT_COMPACTION;
//start with submode alpha after latch
textSubMode = _SUBMODE_ALPHA;
}
textSubMode = _encodeText(input, p, t, sb, textSubMode);
p += t;
} else {
int b = _determineConsecutiveBinaryCount(
input,
p,
autoECI ? null : encoding,
);
if (b == 0) {
b = 1;
}
final bytes = autoECI
? null
: Uint8List.fromList(
encoding!.encode(input.toString().substring(p, p + b)),
);
if ((bytes == null && b == 1) ||
(bytes != null && bytes.length == 1) &&
encodingMode == _TEXT_COMPACTION) {
//Switch for one byte (instead of latch)
if (autoECI) {
_encodeMultiECIBinary(input, p, 1, _TEXT_COMPACTION, sb);
} else {
_encodeBinary(bytes!, 0, 1, _TEXT_COMPACTION, sb);
}
} else {
//Mode latch performed by encodeBinary()
if (autoECI) {
_encodeMultiECIBinary(input, p, p + b, encodingMode, sb);
} else {
_encodeBinary(bytes!, 0, bytes.length, encodingMode, sb);
}
encodingMode = _BYTE_COMPACTION;
textSubMode = _SUBMODE_ALPHA; //Reset after latch
}
p += b;
}
}
}
break;
}
return sb.toString();
}