shortestCode method
Find the shortest code using a mix of tables A B or C
Implementation
Iterable<int> shortestCode(List<int> data) {
// table is defined as:
// 0 = 000 no table set
// 1 = 001 table A
// 2 = 010 table B
// 4 = 100 table C
var table = 0;
// the last table seen
// 0 = none
// 1 = table A
// 2 = table B
// 3 = table C
var lastTable = 0;
// the number of chars for the current table
var length = 0;
var digitCount = 0;
// var fnc1Count = 0;
final result = <int>[];
void addFrom(List<int> data, int start) {
Map<int, int>? t;
if (table & 4 != 0 && digitCount & 1 == 0 /*&& digitCount > 0*/) {
// New data from table C
t = BarcodeMaps.code128C;
if (lastTable == 1) {
result.add(t[BarcodeMaps.code128CodeA]!);
} else if (lastTable == 2) {
result.add(t[BarcodeMaps.code128CodeB]!);
}
lastTable = 3;
} else if (table & 1 != 0) {
// New data from table A
t = BarcodeMaps.code128A;
if (lastTable == 2) {
result.add(t[BarcodeMaps.code128CodeB]!);
} else if (lastTable == 3) {
result.add(t[BarcodeMaps.code128CodeC]!);
}
lastTable = 1;
} else if (table & 2 != 0) {
// New data from table B
t = BarcodeMaps.code128B;
if (lastTable == 1) {
result.add(t[BarcodeMaps.code128CodeA]!);
} else if (lastTable == 3) {
result.add(t[BarcodeMaps.code128CodeC]!);
}
lastTable = 2;
}
if (t == null) {
throw BarcodeException(
'Unable to encode "${String.fromCharCodes(data)}" to $name Barcode');
}
// Add sublist(start, length + start)
if (lastTable == 3) {
// Encode Code 128C $digitCount
for (var i = start + length - 1; i >= start; i--) {
if (data[i] == BarcodeMaps.code128FNC1) {
result.add(t[BarcodeMaps.code128FNC1]!);
} else {
final digit = data[i] - 0x30 + (data[i - 1] - 0x30) * 10;
assert(t[digit] != null);
result.add(t[digit]!);
i--;
}
}
} else {
for (final c in data.sublist(start, start + length).reversed) {
assert(t[c] != null);
result.add(t[c]!);
}
}
}
for (var index = data.length - 1; index >= 0; index--) {
final code = data[index];
final codeA = useCode128A && BarcodeMaps.code128A.containsKey(code);
final codeB = useCode128B && BarcodeMaps.code128B.containsKey(code);
final isFnc1 = code == BarcodeMaps.code128FNC1;
final codeC = useCode128C && (code >= 0x30 && code <= 0x39);
var available = 0;
if (codeA) {
available = 1;
}
if (codeB) {
available |= 2;
}
if (codeC || isFnc1) {
available |= 4;
}
if (available == 0) {
throw BarcodeException(
'Unable to encode "${String.fromCharCode(code)}" to $name Barcode');
}
if (codeC) {
// It's a digit
digitCount++;
} else if (isFnc1) {
length++;
addFrom(data, index);
length = 0;
digitCount = 0;
continue;
} else {
if (digitCount >= 4) {
// Use to CODE C to output 4 digits or more
if (digitCount & 1 != 0) {
// if Odd number, remove the first digit
digitCount--;
} else {
// addFrom(data, index + 1);
}
if (length > digitCount) {
length -= digitCount;
// First: Add $length chars using one of the tables A or B
table &= 3;
if (table == 0) {
throw BarcodeException(
'Unable to encode "${String.fromCharCodes(data)}" to $name Barcode');
}
addFrom(data, index + digitCount + 1);
length = digitCount;
}
// Then: Optimize $digitCount with table C');
table = 4;
addFrom(data, index + 1);
table = 0;
length = 0;
}
digitCount = 0;
// fnc1Count = 0;
}
if (table == 0) {
// Add first $code to table $available
table = available;
length++;
} else {
final newTable = table & available;
if (newTable == 0) {
// Change table to any of $table
addFrom(data, index + 1);
length = 0;
table = available;
} else {
table = newTable;
}
length++;
}
}
if (digitCount >= 2) {
if (digitCount & 1 != 0) {
// Odd number of digits, add the last one
length -= digitCount - 1;
addFrom(data, digitCount - 1);
digitCount--;
} else if (length > digitCount) {
length -= digitCount;
addFrom(data, digitCount);
}
table = 4;
length = digitCount;
}
if (length > 0) {
// Add remaining data
addFrom(data, 0);
}
// Add the start code
if (lastTable == 1) {
result.add(BarcodeMaps.code128StartCodeA);
} else if (lastTable == 2) {
result.add(BarcodeMaps.code128StartCodeB);
} else if (lastTable == 3) {
result.add(BarcodeMaps.code128StartCodeC);
}
return result.reversed;
}