/* * Copyright 2014 Robin Stuart * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package uk.org.okapibarcode.backend; /** * Implements Code 39 bar code symbology * According to ISO/IEC 16388:2007 * <p> * Input data can be of any length and supports the characters 0-9, A-Z, dash * (-), full stop (.), space, asterisk (*), dollar ($), slash (/), plus (+) * and percent (%). The standard does not require a check digit but a * modulo-43 check digit can be added if required. * * @author <a href="mailto:rstuart114@gmail.com">Robin Stuart</a> */ public class Code3Of9 extends Symbol { public enum CheckDigit { NONE, MOD43 } private static final String[] CODE_39 = { "1112212111", "2112111121", "1122111121", "2122111111", "1112211121", "2112211111", "1122211111", "1112112121", "2112112111", "1122112111", "2111121121", "1121121121", "2121121111", "1111221121", "2111221111", "1121221111", "1111122121", "2111122111", "1121122111", "1111222111", "2111111221", "1121111221", "2121111211", "1111211221", "2111211211", "1121211211", "1111112221", "2111112211", "1121112211", "1111212211", "2211111121", "1221111121", "2221111111", "1211211121", "2211211111", "1221211111", "1211112121", "2211112111", "1221112111", "1212121111", "1212111211", "1211121211", "1112121211" }; private static final char[] LOOKUP = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%' }; private CheckDigit checkOption = CheckDigit.NONE; /** Ratio of wide bar width to narrow bar width. */ private double moduleWidthRatio = 2; /** * Sets the ratio of wide bar width to narrow bar width. Valid values are usually * between {@code 2} and {@code 3}. The default value is {@code 2}. * * @param moduleWidthRatio the ratio of wide bar width to narrow bar width */ public void setModuleWidthRatio(double moduleWidthRatio) { this.moduleWidthRatio = moduleWidthRatio; } /** * Returns the ratio of wide bar width to narrow bar width. * * @return the ratio of wide bar width to narrow bar width */ public double getModuleWidthRatio() { return moduleWidthRatio; } /** * Select addition of optional Modulo-43 check digit or encoding without * check digit. * @param checkMode Check digit option. */ public void setCheckDigit(CheckDigit checkMode) { checkOption = checkMode; } @Override public boolean encode() { if (!(content.matches("[0-9A-Z\\. \\-$/+%]+"))) { error_msg = "Invalid characters in input"; return false; } String p = ""; String dest; int l = content.length(); int charval; char thischar; int counter = 0; char check_digit = ' '; dest = "1211212111"; // Start for (int i = 0; i < l; i++) { thischar = content.charAt(i); charval = positionOf(thischar, LOOKUP); counter += charval; p += CODE_39[charval]; } dest += p; if (checkOption == CheckDigit.MOD43) { //User has requested Mod-43 check digit counter = counter % 43; if(counter < 10) { check_digit = (char)(counter + '0'); } else { if(counter < 36) { check_digit = (char)((counter - 10) + 'A'); } else { switch(counter) { case 36: check_digit = '-'; break; case 37: check_digit = '.'; break; case 38: check_digit = ' '; break; case 39: check_digit = '$'; break; case 40: check_digit = '/'; break; case 41: check_digit = '+'; break; default: check_digit = 37; break; } } } charval = positionOf(check_digit, LOOKUP); p += CODE_39[charval]; /* Display a space check digit as _, otherwise it looks like an error */ if(check_digit == ' ') { check_digit = '_'; } } dest += "121121211"; // Stop if (checkOption == CheckDigit.MOD43) { readable = "*" + content + check_digit + "*"; encodeInfo += "Check Digit: " + check_digit + "\n"; } else { readable = "*" + content + "*"; } pattern = new String[] { dest }; row_count = 1; row_height = new int[] { -1 }; plotSymbol(); return true; } /** {@inheritDoc} */ @Override protected double getModuleWidth(int originalWidth) { if (originalWidth == 1) { return 1; } else { return moduleWidthRatio; } } /** {@inheritDoc} */ @Override protected int[] getCodewords() { return getPatternAsCodewords(10); } }