ean13barcode.java

来自「这是个国外JAVA爱好者写的条形码生成器」· Java 代码 · 共 292 行

JAVA
292
字号
/***********************************************************************************************************************
 * Copyright (c) 2004, International Barcode Consortium
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of the International Barcode Consortium nor the names of any contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************************************************************/

package net.sourceforge.barbecue.linear.ean;

import net.sourceforge.barbecue.BarcodeException;
import net.sourceforge.barbecue.Module;
import net.sourceforge.barbecue.linear.upc.UPCABarcode;
import net.sourceforge.barbecue.output.LabelLayoutFactory;
import net.sourceforge.barbecue.output.Output;
import net.sourceforge.barbecue.output.OutputException;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * This is a concrete implementation of the EAN13 barcode.
 *
 * @author <a href="mailto:james@metalskin.com">James Jenner</a>
 */
public class EAN13Barcode extends UPCABarcode {
    /**
     * A list of type identifiers for the EAN13 barcode format
     */
    public static final String[] TYPES = new String[]{
        "EAN-13", "EAN13"
    };

    public final static int LEFT_ODD = 0;
    public final static int LEFT_EVEN = 1;
    public final static int RIGHT = 2;

    public final static int PARITY_EVEN = 0;
    public final static int PARITY_ODD = 1;

    public final static int BARCODE_LENGTH = 12;

    public final static String ISBN_NUMBER_SYSTEM = "978";
    public final static int ISBN_SIZE = 10;

    /**
     * Constructs a basic mode EAN13 barcode with the specified data and an optional
     * checksum.  The length of the barcode is 11, 12 with a checksum.  If the length
     * passed is only 11, then a checksum will be automaticaly added.  If the length
     * is not 11 or 12 then a barcode exception will be thrown.
     *
     * @param data The data to encode
     * @throws BarcodeException If the data to be encoded is invalid
     */
    public EAN13Barcode(String data) throws BarcodeException {
        super(data);
    }

    protected int getBarcodeLength() {
        return BARCODE_LENGTH;
    }

    protected int getGuardCharSize() {
        return EAN13ModuleFactory.GUARD_CHAR_SIZE;
    }

    protected int getLeftWidth() {
        return EAN13ModuleFactory.LEFT_WIDTH;
    }

    protected Module getRightMargin() {
        return EAN13ModuleFactory.RIGHT_MARGIN;
    }

    /* TODO: The following is very close to the parent (UPCABarcode), 
     * should change parent so can handle both.  
     * 
     * note that the following code uses member functions to get static 
     * values from the ModuleFactory class, instead of referencing the 
     * values directly.  This is so sub-classes can override the 
     * member functions and thus change the static values.
     */
    protected Dimension draw(Output output, int x, int y, int barWidth, int barHeight) throws OutputException {
        int currentX = x;

        output.beginDraw();
        
        // need to change the output.barHeight value, appears to be no means to do so
        int guardBarHeight = 0;
        int shortBarHeight = barHeight;
        int textHeight = 10 * barWidth;

        if (drawingText) {
            shortBarHeight = barHeight - (11 * barWidth);
            guardBarHeight = shortBarHeight + (6 * barWidth);
        } else {
            shortBarHeight = barHeight - (6 * barWidth);
            guardBarHeight = barHeight;
        }

        String text = getLabel();
        int currentY = this.barHeight + y;

        Module[] modules = encodeData();

        String leadChar = String.valueOf(text.charAt(0));
        String firstSet = text.substring(1, getLeftWidth());
        String lastSet = text.substring(getLeftWidth());

        if (requiresChecksum) {
            lastSet = lastSet + calculateChecksum().getSymbol();
        }

        int startTextPos = 0;
        int firstTextPos = 0;
        int secondTextPos = 0;

        int startTextW = x;
        int firstTextW = 0;
        int secondTextW = 0;
        int width = 0;
        Module preAmble = getPreAmble();
        Module postAmble = getPostAmble();
        startTextW = 0;
        
        // draw leading white space
        if (super.drawingQuietSection) {
            currentX += drawModule(getLeftMargin(), output, currentX, y, barWidth, shortBarHeight + textHeight);
        }
        startTextPos = x;
        startTextW = currentX - startTextPos;
        width = currentX;
        int guardCharSize = getGuardCharSize();
        int leftWidth = getLeftWidth() - 1;
        
        // draw the left guard
        if (preAmble != null) {
            currentX += drawModule(preAmble, output, currentX, y, barWidth, guardBarHeight);
        }
        
        // draw first char in left side
        for (int i = 0; i < guardCharSize; i++) {
            currentX += drawModule(modules[0], output, currentX, y, barWidth, guardBarHeight);
        }
        firstTextPos = currentX;
        
        // draw the blank space below the guard
        width = currentX - width;
        output.paintBackground(currentX - width, guardBarHeight + currentY, width, ((shortBarHeight + textHeight) - guardBarHeight));

        for (int i = guardCharSize; i < leftWidth; i++) {
            currentX += drawModule(modules[i], output, currentX, y, barWidth, shortBarHeight);
        }

        firstTextW = currentX - firstTextPos;

        width = currentX;
        // draw the centre guard
        currentX += drawModule(getCentreGuard(), output, currentX, y, barWidth, guardBarHeight);
        secondTextPos = currentX;
        
        // draw the blank space below the guard
        width = currentX - width;
        output.paintBackground(currentX - width, guardBarHeight + currentY, width, ((shortBarHeight + textHeight) - guardBarHeight));

        for (int i = leftWidth; i < modules.length; i++) {
            currentX += drawModule(modules[i], output, currentX, y, barWidth, shortBarHeight);
        }

        secondTextW = currentX - secondTextPos;
        width = currentX;
        
        // draw the right guard
        if (postAmble != null) {
            currentX += drawModule(postAmble, output, currentX, y, barWidth, guardBarHeight);
        }
        
        // draw the blank space below the guard
        width = currentX - width;
        output.paintBackground(currentX - width, guardBarHeight + currentY, width, ((shortBarHeight + textHeight) - guardBarHeight));
        
        // draw trailing white space
        currentX += drawModule(getRightMargin(), output, currentX, y, barWidth, shortBarHeight + textHeight);

        if (drawingText) {
            output.drawText(leadChar, LabelLayoutFactory.createMarginLayout(startTextPos, shortBarHeight, startTextW, textHeight));
            output.drawText(firstSet, LabelLayoutFactory.createMarginLayout(firstTextPos, shortBarHeight, firstTextW, textHeight));
            output.drawText(lastSet, LabelLayoutFactory.createMarginLayout(secondTextPos, shortBarHeight, secondTextW, textHeight));
        }

        Dimension size = new Dimension((int) (currentX - x), (int) (currentY) - y);

        output.endDraw((int) size.getWidth(), (int) size.getHeight());

        return size;
    }


    /**
     * Returns the encoded data for the barcode.
     *
     * @return An array of modules that represent the data as a barcode
     */
    protected Module[] encodeData() {
        List modules = new ArrayList();
        Module module = null;
        int len = data.length();
        char c;

        String firstChar = data.substring(0, 1);
        
        /* EAN13 is a funny one.  The first digit actualy isn't 
         * encoded, even though its displayed on the human readable.
         *
         * go figure.
         */
        for (int i = 1; i < len; i++) {
            c = data.charAt(i);

            module = EAN13ModuleFactory.getModule(firstChar, String.valueOf(c), i);
            width += module.widthInBars();
            modules.add(module);
        }

        if (requiresChecksum) {
            module = EAN13ModuleFactory.getModule(firstChar, calculateChecksum().getSymbol(), modules.size() - 1);
            width += module.widthInBars();
            modules.add(module);
        }

        return (Module[]) modules.toArray(new Module[0]);
    }

    /**
     * Returns the checksum for the barcode, pre-encoded as a Module.
     *
     * @return a Mod-10 caclulated checksum, if no checksum is required Null
     */
    protected Module calculateChecksum() {
        if (requiresChecksum) {
            return EAN13ModuleFactory.getModuleForIndex(data.substring(0, 1), getMod10CheckDigit(data));
        }

        return null;
    }

    public static int getMod10CheckDigit(String data) {
        int sum = 0;
        int len = data.length();
        int value;
        
        /*
         * note that the for loop is from 0, as indexing for data is from 0,
         * but the modolo 10 considers the first character position to be 1.
         * in UPCA 0 is odd, as the first position (being 1) is considered 
         * an odd number.  However EAN13 is one extra character in size. To
         * be backward compatible EAN13 has a '0' added to the front for 
         * UPCA numbers and as such the first position is now even.
         * So the following code must compare against 0, not 1 as is in
         * the UPCA getMod10CheckDigit code.
         */
        for (int i = 0; i < len; i++) {
            try {
                value = Integer.parseInt(String.valueOf(data.charAt(i)));
                sum += calculateChecksum(value, (i % 2) == 0);
            } catch (java.lang.NumberFormatException e) {
            }
        }

        return 10 - (sum % 10);
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?