encodeHighLevel static method

String encodeHighLevel(
  1. String msg,
  2. Compaction compaction,
  3. Encoding? encoding,
  4. bool autoECI,
)

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();
}