Add codeset A support to Code 128 (#877)

* add support of Codeset A for Code 128

* simplification, everything from 0 to 127 is supported by Codeset A and B
This commit is contained in:
Michael Jahn 2017-09-20 08:44:23 +02:00 committed by Sean Owen
parent 437db89b45
commit 24f170efb3
2 changed files with 78 additions and 21 deletions

View file

@ -32,8 +32,10 @@ import java.util.Map;
*/
public final class Code128Writer extends OneDimensionalCodeWriter {
private static final int CODE_START_A = 103;
private static final int CODE_START_B = 104;
private static final int CODE_START_C = 105;
private static final int CODE_CODE_A = 101;
private static final int CODE_CODE_B = 100;
private static final int CODE_CODE_C = 99;
private static final int CODE_STOP = 106;
@ -47,6 +49,7 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
private static final int CODE_FNC_1 = 102; // Code A, Code B, Code C
private static final int CODE_FNC_2 = 97; // Code A, Code B
private static final int CODE_FNC_3 = 96; // Code A, Code B
private static final int CODE_FNC_4_A = 101; // Code A
private static final int CODE_FNC_4_B = 100; // Code B
// Results of minimal lookahead for code C
@ -80,16 +83,17 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
// Check content
for (int i = 0; i < length; i++) {
char c = contents.charAt(i);
if (c < ' ' || c > '~') {
switch (c) {
case ESCAPE_FNC_1:
case ESCAPE_FNC_2:
case ESCAPE_FNC_3:
case ESCAPE_FNC_4:
break;
default:
switch (c) {
case ESCAPE_FNC_1:
case ESCAPE_FNC_2:
case ESCAPE_FNC_3:
case ESCAPE_FNC_4:
break;
default:
if (c > 127) {
// support for FNC4 isn't implemented, no full Latin-1 character set available at the moment
throw new IllegalArgumentException("Bad character in input: " + c);
}
}
}
}
@ -119,15 +123,30 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
patternIndex = CODE_FNC_3;
break;
case ESCAPE_FNC_4:
patternIndex = CODE_FNC_4_B; // FIXME if this ever outputs Code A
if (codeSet == CODE_CODE_A) {
patternIndex = CODE_FNC_4_A;
} else {
patternIndex = CODE_FNC_4_B;
}
break;
default:
// Then handle normal characters otherwise
if (codeSet == CODE_CODE_B) {
patternIndex = contents.charAt(position) - ' ';
} else { // CODE_CODE_C
patternIndex = Integer.parseInt(contents.substring(position, position + 2));
position++; // Also incremented below
switch (codeSet) {
case CODE_CODE_A:
patternIndex = contents.charAt(position) - ' ';
if (patternIndex < 0) {
// everything below a space character comes behind the underscore in the code patterns table
patternIndex += '`';
}
break;
case CODE_CODE_B:
patternIndex = contents.charAt(position) - ' ';
break;
default:
// CODE_CODE_C
patternIndex = Integer.parseInt(contents.substring(position, position + 2));
position++; // Also incremented below
break;
}
}
position++;
@ -136,11 +155,16 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
// Do we have a code set?
if (codeSet == 0) {
// No, we don't have a code set
if (newCodeSet == CODE_CODE_B) {
patternIndex = CODE_START_B;
} else {
// CODE_CODE_C
patternIndex = CODE_START_C;
switch (newCodeSet) {
case CODE_CODE_A:
patternIndex = CODE_START_A;
break;
case CODE_CODE_B:
patternIndex = CODE_START_B;
break;
default:
patternIndex = CODE_START_C;
break;
}
} else {
// Yes, we have a code set
@ -208,7 +232,17 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
private static int chooseCode(CharSequence value, int start, int oldCode) {
CType lookahead = findCType(value, start);
if (lookahead == CType.UNCODABLE || lookahead == CType.ONE_DIGIT) {
if (lookahead == CType.ONE_DIGIT) {
return CODE_CODE_B;
}
if (lookahead == CType.UNCODABLE) {
if (start < value.length()) {
char c = value.charAt(start);
if (c < ' ' || (oldCode == CODE_CODE_A && c < '`')) {
// can continue in code A, encodes ASCII 0 to 95
return CODE_CODE_A;
}
}
return CODE_CODE_B; // no choice
}
if (oldCode == CODE_CODE_C) { // can continue in code C

View file

@ -34,8 +34,10 @@ public class Code128WriterTestCase extends Assert {
private static final String FNC2 = "11110101000";
private static final String FNC3 = "10111100010";
private static final String FNC4 = "10111101110";
private static final String START_CODE_A = "11010000100";
private static final String START_CODE_B = "11010010000";
private static final String START_CODE_C = "11010011100";
private static final String SWITCH_CODE_A = "11101011110";
private static final String SWITCH_CODE_B = "10111101110";
private static final String QUIET_SPACE = "00000";
private static final String STOP = "1100011101011";
@ -108,6 +110,27 @@ public class Code128WriterTestCase extends Assert {
String actual = BitMatrixTestCase.matrixToString(result);
assertEquals(expected, actual);
}
@Test
public void testEncodeSwitchBetweenCodesetsAAndB() throws Exception {
// start with A switch to B and back to A
// "\0" "A" "B" Switch to B "a" "b" Switch to A "\u0010" check digit
testEncode("\0ABab\u0010", QUIET_SPACE + START_CODE_A + "10100001100" + "10100011000" + "10001011000" + SWITCH_CODE_B + "10010110000" + "10010000110" + SWITCH_CODE_A + "10100111100" + "11001110100" + STOP + QUIET_SPACE);
// start with B switch to A and back to B
// "a" "b" Switch to A "\0 "Switch to B" "a" "b" check digit
testEncode("ab\0ab", QUIET_SPACE + START_CODE_B + "10010110000" + "10010000110" + SWITCH_CODE_A + "10100001100" + SWITCH_CODE_B + "10010110000" + "10010000110" + "11010001110" + STOP + QUIET_SPACE);
}
private void testEncode(String toEncode, String expected) throws Exception {
BitMatrix result = writer.encode(toEncode, BarcodeFormat.CODE_128, 0, 0);
String actual = BitMatrixTestCase.matrixToString(result);
assertEquals(toEncode, expected, actual);
BitArray row = result.getRow(0, null);
Result rtResult = reader.decodeRow(0, row, null);
String actualRoundtripResultText = rtResult.getText();
assertEquals(toEncode, actualRoundtripResultText);
}
}