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 { 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_B = 104;
private static final int CODE_START_C = 105; 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_B = 100;
private static final int CODE_CODE_C = 99; private static final int CODE_CODE_C = 99;
private static final int CODE_STOP = 106; 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_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_2 = 97; // Code A, Code B
private static final int CODE_FNC_3 = 96; // 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 private static final int CODE_FNC_4_B = 100; // Code B
// Results of minimal lookahead for code C // Results of minimal lookahead for code C
@ -80,16 +83,17 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
// Check content // Check content
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
char c = contents.charAt(i); char c = contents.charAt(i);
if (c < ' ' || c > '~') { switch (c) {
switch (c) { case ESCAPE_FNC_1:
case ESCAPE_FNC_1: case ESCAPE_FNC_2:
case ESCAPE_FNC_2: case ESCAPE_FNC_3:
case ESCAPE_FNC_3: case ESCAPE_FNC_4:
case ESCAPE_FNC_4: break;
break; default:
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); throw new IllegalArgumentException("Bad character in input: " + c);
} }
} }
} }
@ -119,15 +123,30 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
patternIndex = CODE_FNC_3; patternIndex = CODE_FNC_3;
break; break;
case ESCAPE_FNC_4: 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; break;
default: default:
// Then handle normal characters otherwise // Then handle normal characters otherwise
if (codeSet == CODE_CODE_B) { switch (codeSet) {
patternIndex = contents.charAt(position) - ' '; case CODE_CODE_A:
} else { // CODE_CODE_C patternIndex = contents.charAt(position) - ' ';
patternIndex = Integer.parseInt(contents.substring(position, position + 2)); if (patternIndex < 0) {
position++; // Also incremented below // 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++; position++;
@ -136,11 +155,16 @@ public final class Code128Writer extends OneDimensionalCodeWriter {
// Do we have a code set? // Do we have a code set?
if (codeSet == 0) { if (codeSet == 0) {
// No, we don't have a code set // No, we don't have a code set
if (newCodeSet == CODE_CODE_B) { switch (newCodeSet) {
patternIndex = CODE_START_B; case CODE_CODE_A:
} else { patternIndex = CODE_START_A;
// CODE_CODE_C break;
patternIndex = CODE_START_C; case CODE_CODE_B:
patternIndex = CODE_START_B;
break;
default:
patternIndex = CODE_START_C;
break;
} }
} else { } else {
// Yes, we have a code set // 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) { private static int chooseCode(CharSequence value, int start, int oldCode) {
CType lookahead = findCType(value, start); 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 return CODE_CODE_B; // no choice
} }
if (oldCode == CODE_CODE_C) { // can continue in code C 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 FNC2 = "11110101000";
private static final String FNC3 = "10111100010"; private static final String FNC3 = "10111100010";
private static final String FNC4 = "10111101110"; 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_B = "11010010000";
private static final String START_CODE_C = "11010011100"; 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 SWITCH_CODE_B = "10111101110";
private static final String QUIET_SPACE = "00000"; private static final String QUIET_SPACE = "00000";
private static final String STOP = "1100011101011"; private static final String STOP = "1100011101011";
@ -108,6 +110,27 @@ public class Code128WriterTestCase extends Assert {
String actual = BitMatrixTestCase.matrixToString(result); String actual = BitMatrixTestCase.matrixToString(result);
assertEquals(expected, actual); 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);
}
} }