⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 barcode39.java

📁 JAVA报表
💻 JAVA
字号:
/**
 * ========================================
 * JFreeReport : a free Java report library
 * ========================================
 *
 * Project Info:  http://www.object-refinery.com/jfreereport/index.html
 * Project Lead:  Thomas Morgner;
 *
 * (C) Copyright 2000-2002, by Simba Management Limited and Contributors.
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * The Original Code is 'iText, a free JAVA-PDF library'.
 *
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
 * All Rights Reserved.
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
 *
 * Contributor(s): all the names of the contributors are added in the source code
 * where applicable.
 *
 */
package org.jfree.report.ext.modules.barcode.base.content;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import org.jfree.report.ElementAlignment;
import org.jfree.report.style.FontDefinition;
import org.jfree.report.util.Log;
import org.jfree.ui.FloatDimension;

/** Implements the code 39 and code 39 extended. The default parameters are:
 * <pre>
 *x = 0.8f;
 *n = 2;
 *font = BaseFont.createFont("Helvetica", "winansi", false);
 *size = 8;
 *baseline = size;
 *barHeight = size * 3;
 *textAlignment = Element.ALIGN_CENTER;
 *generateChecksum = false;
 *checksumText = false;
 *startStopText = true;
 *extended = false;
 * </pre>
 *
 * @author Paulo Soares (psoares@consiste.pt)
 */
public class Barcode39 extends Barcode
{
  /** The bars to generate the code.
   */
  private static byte BARS[][] =
      {
        {0, 0, 0, 1, 1, 0, 1, 0, 0},
        {1, 0, 0, 1, 0, 0, 0, 0, 1},
        {0, 0, 1, 1, 0, 0, 0, 0, 1},
        {1, 0, 1, 1, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 1, 0, 0, 0, 1},
        {1, 0, 0, 1, 1, 0, 0, 0, 0},
        {0, 0, 1, 1, 1, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0, 1, 0, 1},
        {1, 0, 0, 1, 0, 0, 1, 0, 0},
        {0, 0, 1, 1, 0, 0, 1, 0, 0},
        {1, 0, 0, 0, 0, 1, 0, 0, 1},
        {0, 0, 1, 0, 0, 1, 0, 0, 1},
        {1, 0, 1, 0, 0, 1, 0, 0, 0},
        {0, 0, 0, 0, 1, 1, 0, 0, 1},
        {1, 0, 0, 0, 1, 1, 0, 0, 0},
        {0, 0, 1, 0, 1, 1, 0, 0, 0},
        {0, 0, 0, 0, 0, 1, 1, 0, 1},
        {1, 0, 0, 0, 0, 1, 1, 0, 0},
        {0, 0, 1, 0, 0, 1, 1, 0, 0},
        {0, 0, 0, 0, 1, 1, 1, 0, 0},
        {1, 0, 0, 0, 0, 0, 0, 1, 1},
        {0, 0, 1, 0, 0, 0, 0, 1, 1},
        {1, 0, 1, 0, 0, 0, 0, 1, 0},
        {0, 0, 0, 0, 1, 0, 0, 1, 1},
        {1, 0, 0, 0, 1, 0, 0, 1, 0},
        {0, 0, 1, 0, 1, 0, 0, 1, 0},
        {0, 0, 0, 0, 0, 0, 1, 1, 1},
        {1, 0, 0, 0, 0, 0, 1, 1, 0},
        {0, 0, 1, 0, 0, 0, 1, 1, 0},
        {0, 0, 0, 0, 1, 0, 1, 1, 0},
        {1, 1, 0, 0, 0, 0, 0, 0, 1},
        {0, 1, 1, 0, 0, 0, 0, 0, 1},
        {1, 1, 1, 0, 0, 0, 0, 0, 0},
        {0, 1, 0, 0, 1, 0, 0, 0, 1},
        {1, 1, 0, 0, 1, 0, 0, 0, 0},
        {0, 1, 1, 0, 1, 0, 0, 0, 0},
        {0, 1, 0, 0, 0, 0, 1, 0, 1},
        {1, 1, 0, 0, 0, 0, 1, 0, 0},
        {0, 1, 1, 0, 0, 0, 1, 0, 0},
        {0, 1, 0, 1, 0, 1, 0, 0, 0},
        {0, 1, 0, 1, 0, 0, 0, 1, 0},
        {0, 1, 0, 0, 0, 1, 0, 1, 0},
        {0, 0, 0, 1, 0, 1, 0, 1, 0},
        {0, 1, 0, 0, 1, 0, 1, 0, 0}
      };

  /** The index chars to <CODE>BARS</CODE>.
   */
  private static String CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";

  /** The character combinations to make the code 39 extended.
   */
  private static String EXTENDED = "%U" +
      "$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" +
      "%A%B%C%D%E  /A/B/C/D/E/F/G/H/I/J/K/L - ./O" +
      " 0 1 2 3 4 5 6 7 8 9/Z%F%G%H%I%J%V" +
      " 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" +
      "%K%L%M%N%O%W" +
      "+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" +
      "%P%Q%R%S%T";

  /** Show the start and stop character '*' in the text for
   * the barcode 39.
   */
  private boolean startStopText;

  /** Generates extended barcode 39.
   */
  private boolean extended;

  /** The bar multiplier for wide bars or the distance between
   * bars for Postnet and Planet. (was N)
   */
  private float multiplier;

  /** Creates a new Barcode39.
   */
  public Barcode39()
  {
    setMultiplier(2);
    setGenerateChecksum(false);
    setStartStopText(true);
    setExtended(false);
  }

  /** Gets the bar multiplier for wide bars.
   * @return the bar multiplier for wide bars
   */
  public float getMultiplier()
  {
    return multiplier;
  }

  /** Sets the bar multiplier for wide bars.
   * @param n the bar multiplier for wide bars
   */
  public void setMultiplier(final float n)
  {
    this.multiplier = n;
  }

  /**
   * Creates the bars.
   * @param text the text to create the bars. This text does not include the start and
   * stop characters
   * @return the bars
   */
  private static byte[] getBarsCode39(String text)
  {
    text = "*" + text + "*";
    final byte[] bars = new byte[text.length() * 10 - 1];

    for (int k = 0; k < text.length(); ++k)
    {
      final int idx = CHARS.indexOf(text.charAt(k));
      if (idx < 0)
      {
        throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
      }
      System.arraycopy(BARS[idx], 0, bars, k * 10, 9);
    }
    return bars;
  }

  /** Converts the extended text into a normal, escaped text,
   * ready to generate bars.
   * @param text the extended text
   * @return the escaped text
   */
  static String getCode39Ex(final String text)
  {
    final StringBuffer out = new StringBuffer();
    for (int k = 0; k < text.length(); ++k)
    {
      final char c = text.charAt(k);
      if (c > 127)
      {
        throw new IllegalArgumentException("The character '" + c + "' is illegal in code 39 extended.");
      }

      final char c1 = EXTENDED.charAt(c * 2);
      final char c2 = EXTENDED.charAt(c * 2 + 1);
      if (c1 != ' ')
      {
        out.append(c1);
      }
      out.append(c2);
    }
    return out.toString();
  }

  /** Calculates the checksum.
   * @param text the text
   * @return the checksum
   */
  private static char getChecksum(final String text)
  {
    int chk = 0;
    for (int k = 0; k < text.length(); ++k)
    {
      final int idx = CHARS.indexOf(text.charAt(k));
      if (idx < 0)
      {
        throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
      }
      chk += idx;
    }
    return CHARS.charAt(chk % 43);
  }

  private float getFullWidth()
  {
    String fullCode = getCode();
    if (isExtended())
    {
      fullCode = getCode39Ex(getCode());
    }

    int len = fullCode.length() + 2;
    if (isGenerateChecksum())
    {
      len += 1;
    }

    return (len * (6 * getMinWidth() + 3 * getMinWidth() * getMultiplier()) + (len - 1) * getMinWidth());
  }

  public String getFullCode()
  {
    String fullCode = getCode();
    if (isGenerateChecksum() && isDisplayChecksumText())
    {
      fullCode += getChecksum(fullCode);
    }
    if (isStartStopText())
    {
      fullCode = "*" + fullCode + "*";
    }
    return fullCode;
  }

  /** Creates an <CODE>Image</CODE> with the barcode.
   * @param barColor the color of the bars. It can be <CODE>null</CODE>
   * @param textColor the color of the text. It can be <CODE>null</CODE>
   * @return the <CODE>Image</CODE>
   */
  public Image createImageWithBarcode(final Color barColor, final Color textColor)
  {
    if (barColor == null)
    {
      throw new NullPointerException("BarColor must not be null");
    }
    if (textColor == null)
    {
      throw new NullPointerException("TextColor must not be null");
    }

    float textWidth = 0;
    String fullCode = getCode();
    final float fullWidth = getFullWidth();
    float barStartX = 0;
    float textStartX = 0;
    float barStartY = 0;
    float textStartY = 0;

    final FontDefinition font = getFont();
    if (font != null)
    {
      fullCode = getFullCode();
      final BarcodeSizeCalculator calc = new BarcodeSizeCalculator(font);
      textWidth = calc.getStringWidth(fullCode, 0, fullCode.length());

      if (getBaseline() <= 0)
      {
        // print on top of the bars ...
        // baseline is negative, reduces y.
        textStartY = font.getFontSize() + getBaseline();
        barStartY = font.getFontSize();
      }
      else
      {
        barStartY = 0;
        textStartY = getBarHeight() + getBaseline();
      }
    }

    String bCode = getCode();
    if (isExtended())
    {
      bCode = getCode39Ex(getCode());
    }
    if (isGenerateChecksum())
    {
      bCode += getChecksum(bCode);
    }

    if (getTextAlignment() == ElementAlignment.CENTER)
    {
      if (textWidth > fullWidth)
      {
        barStartX = textWidth - fullWidth;
      }
      else
      {
        textStartX = fullWidth - textWidth;
      }
    }
    else if (getTextAlignment() == ElementAlignment.RIGHT)
    {
      if (textWidth > fullWidth)
      {
        barStartX = (textWidth - fullWidth) / 2;
      }
      else
      {
        textStartX = (fullWidth - textWidth) / 2;
      }
    }

    final Dimension2D size = getBarcodeSize();
    final int imageX = (int) size.getWidth();
    final int imageY = (int) size.getHeight();
    // docmark: now the image size is known ...
    Log.debug ("Create Image With: " + imageX + " H= " + imageY);
    // 10x zoomed for better quality...
    final int scale = 2;
    final BufferedImage image = new BufferedImage(imageX * scale, imageY * scale, BufferedImage.TYPE_INT_ARGB);
    final Graphics2D g2 = image.createGraphics();
    g2.setTransform(AffineTransform.getScaleInstance(scale,scale));

    final byte[] bars = getBarsCode39(bCode);
    g2.setPaint(barColor);

    for (int k = 0; k < bars.length; ++k)
    {
      float w = 0;
      if (bars[k] == 0)
      {
        w = getMinWidth();
      }
      else
      {
        w = getMinWidth() * getMultiplier();
      }
      if (k % 2 == 0)
      {
        final Rectangle2D.Float rect = new Rectangle2D.Float(barStartX, barStartY, w, getBarHeight());
        g2.fill(rect);
      }
      barStartX += w;
    }

    if (font != null)
    {
      g2.setFont(font.getFont());
      g2.setPaint(textColor);
      g2.drawString(fullCode, textStartX, textStartY);
      Log.debug ("Draw String: " + fullCode + " @ (" + textStartX + ", " + textStartY+ ")");
    }
    g2.dispose();
    return image;
  }

  /** Sets the property to show the start and stop character '*' in the text for
   * the barcode 39.
   * @return value of property startStopText
   */
  public boolean isStartStopText()
  {
    return startStopText;
  }

  /** Gets the property to show the start and stop character '*' in the text for
   * the barcode 39.
   * @param startStopText new value of property startStopText
   */
  public void setStartStopText(final boolean startStopText)
  {
    this.startStopText = startStopText;
  }

  /** Gets the property to generate extended barcode 39.
   * @return value of property extended.
   */
  public boolean isExtended()
  {
    return extended;
  }

  /** Sets the property to generate extended barcode 39.
   * @param extended new value of property extended
   */
  public void setExtended(final boolean extended)
  {
    this.extended = extended;
  }

  /**
   * Gets the maximum area that the barcode and the text, if
   * any, will occupy.
   * @return the size the barcode occupies.
   */
  public Dimension2D getBarcodeSize()
  {
    float textWidth = 0;
    String fullCode = getCode();
    final float fullWidth = getFullWidth();
    float textHeight = 0;

    final FontDefinition font = getFont();
    if (font != null)
    {
      fullCode = getFullCode();
      final BarcodeSizeCalculator calc = new BarcodeSizeCalculator(font);
      textWidth = calc.getStringWidth(fullCode, 0, fullCode.length());

      if (getBaseline() <= 0)
      {
        // print on top of the bars, font area is baseline position
        // + font ascent. Baseline replaces font descent ..
        textHeight = -getBaseline() + getFontAscent(font.getFont());
      }
      else
      {
        // baseline replaces font ascent ...
        textHeight = getBaseline() + getFontDescent(font.getFont());
      }
    }

    return new FloatDimension (Math.max(fullWidth, textWidth),
                               getBarHeight() + textHeight);

    // docmark: now the image size is known ...
  }
}

⌨️ 快捷键说明

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