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.AbstractEpsonPrinterDriver

/*
* 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 org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.EncodingUtilities;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.PrinterSpecification;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.helper.PrinterSpecificationManager;
import org.pentaho.reporting.engine.classic.core.util.PageFormatFactory;

public abstract class AbstractEpsonPrinterDriver implements PrinterDriver
{
  public static final String OP_NO_ASSIGN_CHAR_TABLE = "no.assign.character.table";

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

    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 boolean isStrikethrough()
    {
      return strikethrough;
    }

    public void setStrikethrough(final boolean strikethrough)
    {
      this.strikethrough = strikethrough;
    }

    public void reset()
    {
      this.bold = false;
      this.italic = false;
      this.strikethrough = false;
      this.underline = false;
      this.font = PrinterDriverCommands.SELECT_FONT_ROMAN;
      this.manualLeftBorder = 0;
    }
  }

  public static final String FONT_15_CPI = "Epson.Font-15CPI-available";

  private PrinterSpecification printerSpecification;
  private FontMapper fontMapper;

  private OutputStream out;
  private float charsPerInch;
  private float linesPerInch;
  private EncodingUtilities encodingUtilities;
  private boolean firstPage;

  private byte fallBackCharset;

  //private int borderTop;
  //private int borderBottom;
  private DriverState driverState;
  private String encoding;

  protected AbstractEpsonPrinterDriver(final OutputStream out,
                                       final float charsPerInch,
                                       final float linesPerInch,
                                       final String printerModel)
  {
    if (out == null)
    {
      throw new NullPointerException();
    }
    if (printerModel == null)
    {
      throw new NullPointerException();
    }

    this.out = out;
    this.charsPerInch = charsPerInch;
    this.linesPerInch = linesPerInch;
    this.printerSpecification = lookupPrinterSpecification(printerModel);
    this.fontMapper = new DefaultFontMapper();
    this.firstPage = true;
    this.driverState = new DriverState();

    //validate the CPI values
    if (isValidCPI(charsPerInch) == false)
    {
      throw new IllegalArgumentException
          ("The given CPI of '" + charsPerInch +
              "' is invalid for the selected printer model ('" + printerModel + "'.");
    }
    // we cannot influence the LPI, so we have to accept what the user gives in
  }

  private boolean isValidCPI(final float charsPerInch)
  {
    if (charsPerInch == PrinterDriverCommands.CPI_10)
    {
      return true;
    }
    if (charsPerInch == PrinterDriverCommands.CPI_12)
    {
      return true;
    }
    if (charsPerInch == PrinterDriverCommands.CPI_17)
    {
      return true;
    }
    if (charsPerInch == PrinterDriverCommands.CPI_20)
    {
      return true;
    }
    if (charsPerInch == PrinterDriverCommands.CPI_15 &&
        getPrinterSpecification().isFeatureAvailable(AbstractEpsonPrinterDriver.FONT_15_CPI))
    {
      return true;
    }
    return false;
  }


  public AbstractEpsonPrinterDriver.DriverState getDriverState()
  {
    return driverState;
  }

  public FontMapper getFontMapper()
  {
    return fontMapper;
  }

  public void setFontMapper(final FontMapper fontMapper)
  {
    if (fontMapper == null)
    {
      throw new NullPointerException();
    }
    this.fontMapper = fontMapper;
  }

  protected OutputStream getOut()
  {
    return out;
  }

  protected boolean isFirstPage()
  {
    return firstPage;
  }

  public PrinterSpecification getPrinterSpecification()
  {
    return printerSpecification;
  }

  /**
   * 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);
      out.write(PrinterDriverCommands.LINE_FEED);
    }
    else
    {
      out.write(0x7F);
    }
  }

  /**
   * 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)
    {
      out.write(PrinterDriverCommands.FORM_FEED);
    }
  }

  /**
   * 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;
  }

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

  /**
   * 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(), chunk.isStrikethrough());
    getEncodingUtilities(encoding).writeEncodedText(text, out);
  }

  protected abstract void sendFontStyle(boolean bold, boolean italic,
                                        boolean underline, boolean strikeTrough)
      throws IOException;

  protected void sendDefineFont(final byte printerFont)
      throws IOException
  {
    if (getDriverState().getFont() != printerFont)
    {
      getOut().write(0x1b);
      getOut().write(0x6b);
      getOut().write(printerFont);
      getDriverState().setFont(printerFont);
    }
  }

  /**
   * 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(getDriverState().isBold(), getDriverState().isItalic(), false, 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
  {
    sendFontStyle(false, false, false, false);
    final int manualLeftBorder = getDriverState().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 lineHeightPoints = 72.0f / getLinesPerInch();
    final float charWidthPoints = 72.0f / getCharactersPerInch();

    // Quoted from the Epson Reference Manual page R-4:

    // 1. Send an ESC @ to initialize the printer
    sendResetPrinter();
    driverState.reset();

    // 2. Set the unit of line spacing to the minimum vertical increment necessary
    sendDefineLineSpacing(lineHeightPoints);

    // 3. Set the printing area
    final int lines = (int) ((paper.getHeight() / 72.0f) * getLinesPerInch());
    sendDefinePageLengthInLines(lines);

    sendDefineCharacterWidth(getCharactersPerInch());

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

    final int borderTop = (int) (fact.getTopBorder(paper) / lineHeightPoints);
    //borderBottom = (int) (fact.getBottomBorder(paper) / lineHeightPoints);

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

    // 4. Assign character tables to each of the four active tables as
    // necessary. (ESC/P2 printers only)
    //
    // this is done before we start printing the text (and may change mid-page).
    // sendDefineCodepage(encoding);

    // 5. Define any user-defined characters.
    //
    // this is done before we start printing the text (and may change mid-page).
    // sendDefineUserCharacters();
  }

  protected void sendDefineCharacterWidth(final float charactersPerInch)
      throws IOException
  {
    if (charactersPerInch == PrinterDriverCommands.CPI_10)
    {
      getOut().write(0x12); // disable condensed printing
      getOut().write(0x1b);
      getOut().write(0x50); // select 10 CPI
    }
    else if (charactersPerInch == PrinterDriverCommands.CPI_12)
    {
      getOut().write(0x12); // disable condensed printing
      getOut().write(0x1b);
      getOut().write(0x4d); // select 12 CPI
    }
    else if (charactersPerInch == PrinterDriverCommands.CPI_15)
    {
      // All ESC/P2 and 24Pin ESC/P printers support that mode
      // Additionally, the 9Pin printer models FX-2170 and DFX-5000+
      // support that character width.
      getOut().write(0x12); // disable condensed printing
      getOut().write(0x1b);
      getOut().write(0x67);
    }
    else if (charactersPerInch == PrinterDriverCommands.CPI_17)
    {
      getOut().write(0x0f); // enable condensed printing
      getOut().write(0x1b);
      getOut().write(0x50); // select 10 CPI (-> 17.14 cpi because of condensed printing)
    }
    else if (charactersPerInch == PrinterDriverCommands.CPI_20)
    {
      getOut().write(0x0f); // enable condensed printing
      getOut().write(0x1b);
      getOut().write(0x4d); // select 12 CPI (-> 20 cpi because of condensed printing)
    }
    else
    {
      throw new IllegalArgumentException("The given character width is invalid");
    }
  }


  protected void sendResetPrinter()
      throws IOException
  {
    out.write(0x1b);
    out.write(0x40);
  }

  protected abstract void sendDefineLineSpacing(float lineHeightInPoints)
      throws IOException;

  protected void sendDefinePageLengthInLines(final int paperSizeInLines)
      throws IOException
  {
    // SideEffects: Setting the page size will mark the current position
    //              as TopOfForm position
    //
    // All printers support that command.
    getOut().write(0x1b); // ESC
    getOut().write(0x43); // C
    getOut().write(paperSizeInLines);
  }

  protected void sendDefineHorizontalBorders(final int left, final int right)
      throws IOException
  {
    if (left < 256)
    {
      // depends on the pitch to be defined correctly.
      // In that implementation we can assume that this is ok.
      getOut().write(0x1b); // ESC
      getOut().write(0x6c); // l
      getOut().write(left);
      getDriverState().setManualLeftBorder(0);
    }
    else
    {
      getOut().write(0x1b); // ESC
      getOut().write(0x6c); // l
      getOut().write(255);
      getDriverState().setManualLeftBorder(left - 255);
    }
    // Compatibility: All printers support that command.

    // don't care about the right border, the PlainTextPage makes sure that
    // we do not violate that constraint.
  }


  protected void sendDefineCodepage(final String encoding, final int characterTable)
      throws IOException
  {
    if (getPrinterSpecification().isFeatureAvailable(AbstractEpsonPrinterDriver.OP_NO_ASSIGN_CHAR_TABLE))
    {
      out.write(0x1b); // ESC
      out.write(0x52); // R
      out.write(getFallBackCharset());
    }
    else
    {
      final byte[] cp = getPrinterSpecification().getEncoding(encoding).getCode();
      out.write(0x1b); // ESC
      out.write(0x28); // (
      out.write(0x74); // t
      out.write(0x03); // const: 3
      out.write(0x00); // const: 0
      out.write(characterTable); // Define charset; (0 works on all printers)
      out.write(cp);   // the codepage
    }
    out.write(0x1b); // ESC
    out.write(0x74); // t
    out.write(0x00); // Select charset 0 (works on all printers)
  }

  protected void sendDefineUserCharacters()
  {
  }

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

    encodingUtilities = new EncodingUtilities(encoding);
    sendDefineCodepage(encoding, 0);
    return encodingUtilities;
  }

  protected abstract PrinterSpecificationManager getPrinterSpecificationManager();

  private PrinterSpecification lookupPrinterSpecification(final String model)
  {
    final PrinterSpecificationManager printerSpecificationManager =
        getPrinterSpecificationManager();
    if (model == null)
    {
      return PrinterSpecificationManager.getGenericPrinter();
    }

    final PrinterSpecification printerModel =
        printerSpecificationManager.getPrinter(model);
    if (printerModel == null)
    {
      throw new IllegalArgumentException("The printer model is not supported.");
    }
    return printerModel;
  }

  public byte getFallBackCharset()
  {
    return fallBackCharset;
  }

  public void setFallBackCharset(final byte fallBackCharset)
  {
    this.fallBackCharset = fallBackCharset;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.output.pageable.plaintext.driver.AbstractEpsonPrinterDriver

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.