Package org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver

Source Code of org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver.IBMCompatiblePrinterDriver$DriverState

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver;

import java.awt.print.Paper;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.EncodingUtilities;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.PrinterEncoding;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.PrinterSpecification;
import org.pentaho.reporting.engine.classic.core.util.PageFormatFactory;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.fonts.encoding.EncodingRegistry;

public class IBMCompatiblePrinterDriver implements PrinterDriver
{
  public static class GenericIBMPrinterSpecification implements PrinterSpecification
  {
    public GenericIBMPrinterSpecification()
    {
    }

    public String getDisplayName()
    {
      return getName();
    }

    /**
     * Returns the encoding definition for the given java encoding.
     *
     * @param encoding the java encoding that should be mapped into a printer specific encoding.
     * @return the printer specific encoding.
     * @throws IllegalArgumentException if the given encoding is not supported.
     */
    public PrinterEncoding getEncoding(final String encoding)
    {
      try
      {
        return new PrinterEncoding
            (encoding, encoding, encoding, IBMCompatiblePrinterDriver.GenericIBMPrinterSpecification.translateCodePage(
                encoding));
      }
      catch (UnsupportedEncodingException e)
      {
        throw new IllegalArgumentException("The given encoding is not supported.");
      }
    }

    /**
     * Translates the given Codepage String into a IBM Byte Code. The encoding string must be in the format CpXXXX where
     * XXXX is the number of the codepage.
     * <p/>
     *
     * @param cp the code page
     * @return the epson byte code.
     * @throws java.io.UnsupportedEncodingException
     *          if the encoding is not supported.
     */
    private static byte[] translateCodePage(final String cp)
        throws UnsupportedEncodingException
    {
      // Mapping Rule:
      // n = NumberofCodePage + (10000 if codepage contains a character (Cp437G))
      if (StringUtils.startsWithIgnoreCase(cp, "cp"))
      {
        // check the supplied encoding ...
        // only Cp- encodings are supported ...
        if (EncodingRegistry.getInstance().isSupportedEncoding(cp) == false)
        {
          throw new UnsupportedEncodingException("The encoding " + cp + "is not valid");
        }

        final String encodingName = cp.substring(2);
        try
        {
          int i;
          if (Character.isDigit(encodingName.charAt(encodingName.length() - 1)) == false)
          {
            i = Integer.parseInt(encodingName.substring(0, encodingName.length() - 1));
            i += 10000;
          }
          else
          {
            i = Integer.parseInt(encodingName);
          }
          final byte[] retval = new byte[2];
          retval[0] = (byte) (i >> 8);
          retval[1] = (byte) (i & 0xff);
          return retval;
        }
        catch (Exception e)
        {
          throw new UnsupportedEncodingException("The encoding " + cp + "is not valid");
        }
      }
      throw new UnsupportedEncodingException("The encoding " + cp + " is no codepage encoding");
    }

    /**
     * Returns the name of the encoding mapping. This is usually the same as the printer model name.
     *
     * @return the printer model.
     */
    public String getName()
    {
      return "Generic IBM Printer Specification";
    }

    /**
     * Checks whether the given Java-encoding is supported.
     *
     * @param encoding the java encoding that should be mapped into a printer specific encoding.
     * @return true, if there is a mapping, false otherwise.
     */
    public boolean isEncodingSupported(final String encoding)
    {
      try
      {
        IBMCompatiblePrinterDriver.GenericIBMPrinterSpecification.translateCodePage(encoding);
        return true;
      }
      catch (UnsupportedEncodingException use)
      {
        return false;
      }
    }

    /**
     * Returns true, if a given operation is supported, false otherwise.
     *
     * @param operationName the operation, that should be performed
     * @return true, if the printer will be able to perform that operation, false otherwise.
     */
    public boolean isFeatureAvailable(final String operationName)
    {
      // is not used yet.
      return true;
    }
  }

  private static class DriverState
  {
    private boolean bold;
    private boolean underline;
    private boolean italic;

    private byte font;
    private int manualLeftBorder;

    protected DriverState()
    {
    }

    public boolean isBold()
    {
      return bold;
    }

    public void setBold(final boolean bold)
    {
      this.bold = bold;
    }

    public boolean isItalic()
    {
      return italic;
    }

    public void setItalic(final boolean italic)
    {
      this.italic = italic;
    }

    public boolean isUnderline()
    {
      return underline;
    }

    public void setUnderline(final boolean underline)
    {
      this.underline = underline;
    }

    public byte getFont()
    {
      return font;
    }

    public void setFont(final byte font)
    {
      this.font = font;
    }

    public int getManualLeftBorder()
    {
      return manualLeftBorder;
    }

    public void setManualLeftBorder(final int manualLeftBorder)
    {
      this.manualLeftBorder = manualLeftBorder;
    }
  }

  public static final int QUALITY_UNDEFINED = -1;
  public static final int QUALITY_FAST_DRAFT = 0;
  public static final int QUALITY_DRAFT = 0x40;
  public static final int QUALITY_LETTER = 0x80;
  public static final int QUALITY_ENHANCED_LETTER = 0xC0;
  public static final int QUALITY_DEFAULT = 0xFF;

  private OutputStream out;
  private float charsPerInch;
  private float linesPerInch;
  private byte[] endOfPage;

  private boolean autoLF;
  private int printQuality;
  private PrinterSpecification printerSpecification;
  private EncodingUtilities encodingUtilities;
  private DefaultFontMapper fontMapper;
  private IBMCompatiblePrinterDriver.DriverState driverState;
  private boolean firstPage;
  private String encoding;

  public IBMCompatiblePrinterDriver(final OutputStream out,
                                    final float charsPerInch,
                                    final float linesPerInch)
  {
    this.out = out;
    this.charsPerInch = charsPerInch;
    this.linesPerInch = linesPerInch;
    this.endOfPage = new byte[]{(byte) PrinterDriverCommands.FORM_FEED};
    this.printerSpecification = new IBMCompatiblePrinterDriver.GenericIBMPrinterSpecification();
    this.fontMapper = new DefaultFontMapper();
    this.fontMapper.setDefaultFont(PrinterDriverCommands.SELECT_FONT_FROM_MENU);
    this.driverState = new IBMCompatiblePrinterDriver.DriverState();
    this.firstPage = true;
  }

  public void setAutoLF(final boolean autoLF)
  {
    this.autoLF = autoLF;
  }

  public boolean isAutoLF()
  {
    return autoLF;
  }

  public int getPrintQuality()
  {
    return printQuality;
  }

  public void setPrintQuality(final int printQuality)
  {
    this.printQuality = printQuality;
  }

  /**
   * Ends a new line.
   *
   * @param overflow
   * @throws java.io.IOException if an IOError occures.
   */
  public void endLine(final boolean overflow)
      throws IOException
  {
    if (overflow == false)
    {
      out.write(PrinterDriverCommands.CARRIAGE_RETURN);
      if (autoLF == false)
      {
        out.write(PrinterDriverCommands.LINE_FEED);
      }
    }
  }

  /**
   * Ends the current page. Should print empty lines or an FORM_FEED command.
   *
   * @param overflow
   * @throws java.io.IOException if there was an IOError while writing the command
   */
  public void endPage(final boolean overflow)
      throws IOException
  {
    if (overflow == false)
    {
      printRaw(endOfPage);
    }
  }

  /**
   * Flushes the output stream.
   *
   * @throws java.io.IOException if an IOError occured.
   */
  public void flush()
      throws IOException
  {
    out.flush();
  }

  /**
   * Gets the default character width in CPI.
   *
   * @return the default character width in CPI.
   */
  public float getCharactersPerInch()
  {
    return charsPerInch;
  }

  /**
   * Gets the default line height.
   *
   * @return the default line height.
   */
  public float getLinesPerInch()
  {
    return linesPerInch;
  }

  /**
   * Prints a single text chunk at the given position on the current line. The chunk should not be printed, if an
   * previous chunk overlays this chunk.
   *
   * @param chunk the chunk that should be written
   * @throws java.io.IOException if an IO error occured.
   */
  public void printChunk(final PlaintextDataChunk chunk)
      throws IOException
  {
    final String text = chunk.getText().substring(0, chunk.getWidth());
    final String fd = chunk.getFont();
    sendDefineFont(fontMapper.getPrinterFont(fd));
    sendFontStyle(chunk.isBold(), chunk.isItalic(), chunk.isUnderline());
    getEncodingUtilities(encoding).writeEncodedText(text, out);
  }

  /**
   * Prints an empty chunk. This is called for all undefined chunk-cells. The last defined font is used to print that
   * empty text.
   *
   * @throws java.io.IOException if an IOError occured.
   */
  public void printEmptyChunk(final int count)
      throws IOException
  {
    sendFontStyle(driverState.isBold(), driverState.isItalic(), false);
    for (int i = 0; i < count; i++)
    {
      out.write(PrinterDriverCommands.SPACE);
    }
  }

  /**
   * Prints some raw content. This content is not processed in any way, so be very carefull.
   *
   * @param raw the content that should be printed.
   */
  public void printRaw(final byte[] raw)
      throws IOException
  {
    out.write(raw);
  }

  /**
   * Starts a new line.
   *
   * @throws java.io.IOException if an IOError occures.
   */
  public void startLine()
      throws IOException
  {
    final int manualLeftBorder = driverState.getManualLeftBorder();
    for (int i = 0; i < manualLeftBorder; i++)
    {
      out.write(PrinterDriverCommands.SPACE);
    }
  }

  /**
   * Resets the printer and starts a new page. Prints the top border lines (if necessary).
   *
   * @throws java.io.IOException if there was an IOError while writing the command
   */
  public void startPage(final Paper paper, final String encoding)
      throws IOException
  {
    this.encoding = encoding;
    final float charWidthPoints = 72.0f / getCharactersPerInch();
    final float lineHeightPoints = 72.0f / getLinesPerInch();

    if (firstPage)
    {
      // update the autoLF setting
      sendAutoLF(isAutoLF());
      sendDefinePrintQuality(getPrintQuality());
      sendDefineCharacterWidth(getCharactersPerInch());
      firstPage = false;
    }


    // set the line spacing ..
    sendLineSpacing((int) lineHeightPoints);

    // define the page size ..
    // we redefine it for every page, as we do not assume that the page sizes
    // will be the same for the whole report.
    final int lines = (int) ((paper.getHeight() / 72.0f) * getLinesPerInch());
    sendDefinePageLengthInLines(lines);

    final PageFormatFactory fact = PageFormatFactory.getInstance();
    final int borderLeft = (int) (fact.getLeftBorder(paper) / charWidthPoints);
    final int borderRight = (int) (fact.getRightBorder(paper) / charWidthPoints);

    final int borderTop = (int) (fact.getTopBorder(paper) / lineHeightPoints);
    sendDefineHorizontalBorders(borderLeft, borderRight);

    // print the top margin ..
    for (int i = 0; i < borderTop; i++)
    {
      startLine();
      endLine(false);
    }

  }

  /**
   * Defines the line spacing for the printer.
   *
   * @param lineHeight the height of a single line in points (1/72 inch).
   * @throws java.io.IOException if an IOException occured while updating the printer state.
   */
  public void sendLineSpacing(final int lineHeight)
      throws IOException
  {
    out.write(0x1b);
    out.write(0x41);
    out.write(lineHeight);
    out.write(0x1b);
    out.write(0x32);
  }

  private void sendDefineHorizontalBorders(final int left, final int right)
      throws IOException
  {
    out.write(0x1b);
    out.write(0x58);
    out.write(left);
    out.write(right);
  }

  private void sendDefinePageLengthInLines(final int lines)
      throws IOException
  {
    out.write(0x1b);
    out.write(0x43);
    out.write(lines);
  }


  private void sendDefinePrintQuality(final int quality)
      throws IOException
  {
    out.write(0x1b);
    out.write(0x5b);
    out.write(0x64);
    out.write(0x01);
    out.write(0x00);
    out.write(quality);
  }

  /**
   * Defines the font style for the printed text. The IBM-CommandSet does not support strike-through.
   *
   * @param bold      true, if the text should be printed in bold mode.
   * @param italic    true, if the text should be italic, false otherwise
   * @param underline true, if the text should be underlined, false otherwise
   * @throws java.io.IOException if there was an IOError while writing the command
   */
  private void sendFontStyle(final boolean bold, final boolean italic,
                             final boolean underline)
      throws IOException
  {
    if (driverState.isBold())
    {
      if (bold == false)
      {
        // disable bold
        out.write(0x1b); // ESC
        out.write(0x46); // F
      }
    }
    else
    {
      if (bold == true)
      {
        // enable bold
        out.write(0x1b); // ESC
        out.write(0x45); // E
      }
    }

    if (driverState.isItalic())
    {
      if (italic == false)
      {
        // disable italic
        out.write(0x1b);
        out.write(0x25);
        out.write(0x48);
      }
    }
    else
    {
      if (italic == true)
      {
        // enable italic
        out.write(0x1b);
        out.write(0x25);
        out.write(0x47);
      }
    }

    if (driverState.isUnderline())
    {
      if (underline == false)
      {
        // disable underline
        out.write(0x1b); // ESC
        out.write(0x2d); // -
        out.write(0x00); // 0
      }
    }
    else
    {
      if (underline == true)
      {
        // enable underline
        out.write(0x1b); // ESC
        out.write(0x2d); // -
        out.write(0x01); // 1
      }
    }

    driverState.setBold(bold);
    driverState.setItalic(italic);
    driverState.setUnderline(underline);

  }

  private float sendDefineCharacterWidth(final float charsPerInch)
      throws IOException
  {
    if (charsPerInch <= 10)
    {
      out.write(0x12);
      return 10;
    }
    else if (charsPerInch <= 12)
    {
      out.write(0x1b);
      out.write(0x3a);
      return 12;
    }
    else if (charsPerInch <= 15)
    {
      out.write(0x1b);
      out.write(0x67);
      return 15;
    }
    else if (charsPerInch <= 17.4)
    {
      out.write(0x0f);
      return 17.4f;
    }
    else
    {
      out.write(0x1b);
      out.write(0x0f);
      return 20;
    }
  }

  private void sendDefineCodepage(final String codePage)
      throws IOException
  {
    final PrinterEncoding spec = getPrinterSpecification().getEncoding(codePage);
    final byte[] cp = spec.getCode();
    out.write(0x1b); // ESC
    out.write(0x5b); // [
    out.write(0x54); // T
    out.write(0x04); // 0x04 (according to LexMark Manual P.30)
    out.write(0x00); //  const.
    out.write(0x00); //  const.
    out.write(0x00); //  const.
    out.write(cp);   // codepage as 2 byte sequence
  }

  private PrinterSpecification getPrinterSpecification()
  {
    return printerSpecification;
  }

  private void sendAutoLF(final boolean autoLF)
      throws IOException
  {
    if (autoLF == false)
    {
      out.write(0x1b);
      out.write(0x35);
      out.write(0x30);
    }
    else
    {
      out.write(0x1b);
      out.write(0x35);
      out.write(0x31);
    }
  }

  private void sendDefineFont(final byte b)
      throws IOException
  {
    if (driverState.getFont() != b)
    {
      out.write(0x1b);
      out.write(0x6b);
      out.write(b);

      driverState.setFont(b);
    }
  }

  protected EncodingUtilities getEncodingUtilities(final String encoding)
      throws IOException
  {
    if (encodingUtilities != null &&
        encodingUtilities.getEncoding().equals(encoding))
    {
      return encodingUtilities;
    }

    encodingUtilities = new EncodingUtilities(encoding);
    sendDefineCodepage(encoding);
    return encodingUtilities;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver.IBMCompatiblePrinterDriver$DriverState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.