Package org.apache.fop.render.pcl

Source Code of org.apache.fop.render.pcl.PCLRenderer

/* $Id: PCLRenderer.java,v 1.3 2001/03/16 22:59:43 klease Exp $
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources."
*/

//package com.eastpoint.chrysalis;
package org.apache.fop.render.pcl;

// FOP
import org.apache.fop.render.PrintRenderer;
import org.apache.fop.messaging.MessageHandler;
import org.apache.fop.image.ImageArea;
import org.apache.fop.image.FopImage;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.properties.*;
import org.apache.fop.datatypes.*;
import org.apache.fop.pdf.PDFPathPaint;
import org.apache.fop.pdf.PDFColor;
import org.apache.fop.layout.*;
import org.apache.fop.layout.inline.*;
import org.apache.fop.image.*;

import org.apache.fop.dom.svg.SVGArea;
import org.w3c.dom.svg.SVGSVGElement;


// Java
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;

/**
* Renderer that renders areas to PCL

  Created by Arthur E Welch III while at M&I EastPoint Technology
  Donated by EastPoint to the Apache FOP project March 2, 2001.
*/
public class PCLRenderer extends PrintRenderer
{
    /** the current stream to add PCL commands to */
    public PCLStream currentStream;

  private int pageHeight = 7920;

  // These variables control the virtual paggination functionality.
  public int  curdiv = 0;
  private int  divisions = -1;
  public int  paperheight = -1// Paper height in decipoints?
  public int  orientation = -1// -1=default/unknown, 0=portrait, 1=landscape.
  public int  topmargin = -1// Top margin in decipoints?
  public int  leftmargin = -1// Left margin in decipoints?
  private int fullmargin = 0;
  private final boolean debug = false;

  private int xoffset = -180// X Offset to allow for PCL implicit 1/4" left margin.

  /**
   * Create the PCL renderer
   */
  public PCLRenderer()
  {
  }

    /**
       * set the PCL document's producer
       *
       * @param producer string indicating application producing PCL
       */
    public void setProducer(String producer)
    {
    }

    /**
     * render the areas into PCL
     *
     * @param areaTree the laid-out area tree
     * @param stream the Outputstream to write the PCL to
     */
    public void render(AreaTree areaTree, OutputStream stream) throws IOException, FOPException
    {
    MessageHandler.logln("rendering areas to PCL");
    idReferences=areaTree.getIDReferences();
    //this.pdfResources = this.pdfDoc.getResources();
    //this.pdfDoc.setIDReferences(idReferences);
    Enumeration e = areaTree.getPages().elements();

    currentStream = new PCLStream(stream);

    // Set orientation.
    if ( orientation > -1 )
      currentStream.add("\033&l" + orientation + "O");
    else
      currentStream.add("\033&l0O");
    if ( orientation == 1 || orientation == 3 )
      xoffset = -144;
    else
      xoffset = -180;

    // Reset the margins.
    currentStream.add("\033" + "9\033&l0E");


    while (e.hasMoreElements())
    {
        this.renderPage((Page) e.nextElement());
    }
        if ( !idReferences.isEveryIdValid() )
        {
            //throw new FOPException("The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n");
            MessageHandler.errorln("Warning: The following id's were referenced but not found: "+idReferences.getInvalidIds() + "\n");
        }

        MessageHandler.logln("writing out PCL");
    stream.flush();
    }

    /**
       * add a line to the current stream
       *
       * @param x1 the start x location in millipoints
       * @param y1 the start y location in millipoints
       * @param x2 the end x location in millipoints
       * @param y2 the end y location in millipoints
       * @param th the thickness in millipoints
       * @param stroke the line color
       */
    protected void addLine(int x1, int y1, int x2, int y2, int th,
                           PDFPathPaint stroke)
    {
    if ( x1 == x2 )
      addRect(x1 - (th/2), y1, th, y2 - y1 + 1, stroke, stroke);
    else if ( y1 == y2 )
      addRect(x1, y1 + (th/2), x2 - x1 + 1, th, stroke, stroke);
    }

    /**
      * add a line to the current stream
      *
      * @param x1 the start x location in millipoints
      * @param y1 the start y location in millipoints
      * @param x2 the end x location in millipoints
      * @param y2 the end y location in millipoints
      * @param th the thickness in millipoints
      * @param rs the rule style
      * @param stroke the line color
      */
    protected void addLine(int x1, int y1, int x2, int y2, int th,
                           int rs, PDFPathPaint stroke)
    {
    int  dashon = 0;
    int  dashoff = 0;
    //if ( rs != null && rs.length() > 5 && rs.charAt(0) == '[' && rs.charAt(1) != ']' && rs.charAt(4) == ']' )
    //{
    //  dashon = rs.charAt(1) - '0';
    //  dashoff = rs.charAt(3) - '0';
    //}
        switch (rs)
        {
            case org.apache.fop.fo.properties.RuleStyle.DASHED:
        dashon = 3;
        dashoff = 3;
                break;
            case org.apache.fop.fo.properties.RuleStyle.DOTTED:
        dashon = 1;
        dashoff = 3;
                break;
    }
    if ( x1 == x2 )
    {
      if ( dashon > 0 && dashoff > 0 )
      {
        int  start = y1;
        int  len = th * dashon;
        while ( start < y2 )
        {
          if ( start + len > y2 )
            len = y2 - start;
          addRect(x1 - (th/2), start, th, len, stroke, stroke);
          start += (len + dashoff * th);
        }
      }
      else
        addRect(x1 - (th/2), y1, th, y2 - y1 + 1, stroke, stroke);
    }
    else if ( y1 == y2 )
    {
      if ( dashon > 0 && dashoff > 0 )
      {
        int  start = x1;
        int  len = th * dashon;
        while ( start < x2 )
        {
          if ( start + len > x2 )
            len = x2 - start;
          addRect(start, y1 + (th/2), len, th, stroke, stroke);
          start += (len + dashoff * th);
        }
      }
      else
        addRect(x1, y1 + (th/2), x2 - x1 + 1, th, stroke, stroke);
    }
    }

    /**
       * add a rectangle to the current stream
       *
       * @param x the x position of left edge in millipoints
       * @param y the y position of top edge in millipoints
       * @param w the width in millipoints
       * @param h the height in millipoints
       * @param stroke the stroke color/gradient
       */
    protected void addRect(int x, int y, int w, int h,
                           PDFPathPaint stroke)
    {
    if ( h < 0 )
      h *= -1;

    if (h < 720 || w < 720)
    {
      if ( w < 720 )
        w = 720;
      if ( h < 720 )
        h = 720;
        addRect(x, y, w, h, stroke, stroke);
    }
    else
    {
        addRect(x, y, w, 720, stroke, stroke);
        addRect(x, y, 720, h, stroke, stroke);
        addRect(x + w - 720, y, 720, h, stroke, stroke);
        addRect(x, y - h + 720, w, 720, stroke, stroke);
    }
    }

    /**
       * add a filled rectangle to the current stream
       *
       * @param x the x position of left edge in millipoints
       * @param y the y position of top edge in millipoints
       * @param w the width in millipoints
       * @param h the height in millipoints
       * @param fill the fill color/gradient
       * @param stroke the stroke color/gradient
       */
    protected void addRect(int x, int y, int w, int h,
                           PDFPathPaint stroke, PDFPathPaint fill)
    {
    if ((w == 0) || (h == 0))
        return;
    if ( h < 0 )
      h *= -1;

    PDFColor sc = (PDFColor)stroke;
    PDFColor fc = (PDFColor)fill;

    sc.setColorSpace(ColorSpace.DEVICE_RGB);
    fc.setColorSpace(ColorSpace.DEVICE_RGB);

    int  lineshade = (int)(100 - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) * 100f));
    int  fillshade = (int)(100 - ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue()) * 100f));

    int xpos = xoffset + (x / 100);
    if ( xpos < 0 )
    {
      xpos = 0;
      MessageHandler.errorln("PCLRenderer.addRect() WARNING: Horizontal position out of bounds.");
    }

    currentStream.add("\033*v1O\033&a" + xpos + "h" + (pageHeight - (y / 100)) + "V"
              + "\033*c" + (w / 100) + "h" + (h / 100) + "V"
              + "\033*c" + lineshade + "G"
              + "\033*c2P");
    if ( fillshade != lineshade && (w >= 720 || h >= 720) )
    {
      xpos = xoffset + ((x + 240) / 100);
      if ( xpos < 0 )
      {
        xpos = 0;
        MessageHandler.errorln("PCLRenderer.addRect() WARNING: Horizontal position out of bounds.");
      }
      currentStream.add("\033&a" + xpos + "h" + (pageHeight - ((y + 240)) / 100) + "V"
                + "\033*c" + ((w - 480) / 100) + "h" + ((h - 480) / 100) + "V"
                + "\033*c" + fillshade + "G"
                + "\033*c2P");
    }
    // Reset pattern transparency mode.
    currentStream.add("\033*v0O");
    }

  boolean printBMP(FopImage img, int x, int y, int w, int h) throws FopImageException
  {
    // Print the passed image file in PCL.
    byte imgmap[] = img.getBitmaps();

    int  ix = 0;
    int iy = 0;
    int  indx = 0;
    int  iw = img.getWidth();
    int  ih = img.getHeight();
    int  bytewidth = (iw / 8);
    if ( (iw % 8) != 0 )
      bytewidth++;
    byte  ib;
    char  ic[] = new char[bytewidth * 2];
    char  icu[] = new char[bytewidth];
    int  lastcount = -1;
    byte lastbyte = 0;
    int  icwidth = 0;
    int  cr = 0;
    int  cg = 0;
    int  cb = 0;
    int  grey = 0;
    boolean iscolor = img.getColorSpace().getColorSpace() != ColorSpace.DEVICE_GRAY;
    int dcount = 0;
    int xres = (iw * 72000) / w;
    int yres = (ih * 72000) / h;
    int  resolution = xres;
    if ( yres > xres )
      resolution = yres;

    if ( resolution > 300 )
      resolution = 600;
    else if ( resolution > 150 )
      resolution = 300;
    else if ( resolution > 100 )
      resolution = 150;
    else if ( resolution > 75 )
      resolution = 100;
    else
      resolution = 75;
if ( debug )
System.out.println("PCLRenderer.printBMP() iscolor = " + iscolor);
    // Setup for graphics
    currentStream.add("\033*t" + resolution + "R\033*r0F\033*r1A");

    // Transfer graphics data
    for ( iy = 0 ; iy < ih ; iy++ )
    {
      ib = 0;
      //int  padding = iw % 8;
      //if ( padding != 0 )
      //  padding = 8 - padding;
      //padding = 0;
      //indx = (ih - iy - 1 + padding) * iw;
      indx = iy * iw;
      if ( iscolor )
        indx *= 3;
      //currentStream.add("\033*b" + bytewidth + "W");
      for ( ix = 0 ; ix < iw ; ix++ )
      {
        if ( iscolor )
        {
          cr = imgmap[indx++] & 0xFF;
          cg = imgmap[indx++] & 0xFF;
          cb = imgmap[indx++] & 0xFF;
          grey = (cr * 30 + cg * 59 + cb * 11) / 100;
        }
        else
          grey = imgmap[indx++] & 0xFF;
        if ( grey < 128 )
          ib |= (1 << (7 - (ix % 8)));
        if ( (ix % 8) == 7 || ((ix + 1) == iw))
        {
          if ( icwidth < bytewidth )
          {
            if ( lastcount >= 0 )
            {
              if ( ib == lastbyte )
                lastcount++;
              else
              {
                ic[icwidth++] = (char)(lastcount & 0xFF);
                ic[icwidth++] = (char)lastbyte;
                lastbyte = ib;
                lastcount = 0;
              }
            }
            else
            {
              lastbyte = ib;
              lastcount = 0;
            }
            if ( lastcount == 255 || ((ix + 1) == iw) )
            {
              ic[icwidth++] = (char)(lastcount & 0xFF);
              ic[icwidth++] = (char)lastbyte;
              lastbyte = 0;
              lastcount = -1;
            }
          }
          icu[ix / 8] = (char)ib;
          ib = 0;
        }
      }
      if ( icwidth < bytewidth )
      {
        currentStream.add("\033*b1m" + icwidth + "W");
        currentStream.add(new String(ic, 0, icwidth));
      }
      else
      {
        currentStream.add("\033*b0m" + bytewidth + "W");
        currentStream.add(new String(icu));
      }
      lastcount = -1;
      icwidth = 0;
    }

    // End graphics
    currentStream.add("\033*rB");


    return(true);
  }

    /**
     * render image area to PCL
     *
     * @param area the image area to render
     */
    public void renderImageArea(ImageArea area)
    {
    int x = this.currentAreaContainerXPosition + area.getXOffset();
    int y = this.currentYPosition;
    int w = area.getContentWidth();
    int h = area.getHeight();

    this.currentYPosition -= h;

    FopImage img = area.getImage();

    int xpos = xoffset + (x / 100);
    if ( xpos < 0 )
    {
      xpos = 0;
      MessageHandler.errorln("PCLRenderer.renderImageArea() WARNING: Horizontal position out of bounds.");
    }

    currentStream.add("\033&a" + xpos + "h" + (pageHeight - (y / 100)) + "V");

    try
    {
      printBMP(img, x, y, w, h);
    }
    catch ( FopImageException e )
    {
      //e.printStackTrace(System.out);
      MessageHandler.errorln("PCLRenderer.renderImageArea() Error printing BMP (" + e.toString() + ")");
    }
    }

    /** render a foreign object area */
    public void renderForeignObjectArea(ForeignObjectArea area)
    {
        // if necessary need to scale and align the content
        this.currentXPosition = this.currentXPosition + area.getXOffset();
        this.currentYPosition = this.currentYPosition;
        switch (area.getAlign())
        {
            case TextAlign.START:
                break;
            case TextAlign.END:
                break;
            case TextAlign.CENTER:
            case TextAlign.JUSTIFY:
                break;
        }
        switch (area.getVerticalAlign())
        {
            case VerticalAlign.BASELINE:
                break;
            case VerticalAlign.MIDDLE:
                break;
            case VerticalAlign.SUB:
                break;
            case VerticalAlign.SUPER:
                break;
            case VerticalAlign.TEXT_TOP:
                break;
            case VerticalAlign.TEXT_BOTTOM:
                break;
            case VerticalAlign.TOP:
                break;
            case VerticalAlign.BOTTOM:
                break;
        }
        // in general the content will not be text

        // align and scale

        switch (area.scalingMethod())
        {
            case Scaling.UNIFORM:
                break;
            case Scaling.NON_UNIFORM:
                break;
        }
        // if the overflow is auto (default), scroll or visible
        // then the contents should not be clipped, since this
        // is considered a printing medium.
        switch (area.getOverflow())
        {
            case Overflow.VISIBLE:
            case Overflow.SCROLL:
            case Overflow.AUTO:
                break;
            case Overflow.HIDDEN:
                break;
        }
        area.getObject().render(this);

        this.currentXPosition += area.getEffectiveWidth();
    //    this.currentYPosition -= area.getEffectiveHeight();
    }

    /**
     * render SVG area to PCL
     *
     * @param area the SVG area to render
     */
  public void renderSVGArea(SVGArea area)
  {
if ( debug )
System.out.println("PCLRenderer.renderSVGArea(" + area + ")");
        int x = this.currentXPosition;
        int y = this.currentYPosition;
        SVGSVGElement svg = area.getSVGDocument().getRootElement();
        int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
        int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);

        /*
         * Clip to the svg area.
         * Note: To have the svg overlay (under) a text area then use
         * an fo:block-container
         */

        // TODO - translate and clip to viewbox

        PCLSVGRenderer svgRenderer =
      new PCLSVGRenderer(this, area.getFontState(), currentFontName, currentFontSize, currentXPosition, currentYPosition, pageHeight, xoffset);
        svgRenderer.renderSVG(svg, x, y);
        //currentStream.add(svgRenderer.getString());

        //currentStream.add("Q\n");
  }

  public void setFont(String name, float size)
  {
    int  fontcode = 0;
    if ( name.length() > 1 && name.charAt(0) == 'F' )
    {
      try
      {
        fontcode = Integer.parseInt(name.substring(1));
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }
    switch (fontcode)
    {
      case  1// F1 = Helvetica
        //currentStream.add("\033(8U\033(s1p" + (size / 1000) + "v0s0b24580T");
        // Arial is more common among PCL5 printers than Helvetica - so use Arial
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s0b16602T");
        break;
      case  2// F2 = Helvetica Oblique
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s0b16602T");
        break;
      case  3// F3 = Helvetica Bold
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s3b16602T");
        break;
      case  4// F4 = Helvetica Bold Oblique
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s3b16602T");
        break;
      case  5// F5 = Times Roman
        //currentStream.add("\033(8U\033(s1p" + (size / 1000) + "v0s0b25093T");
        // Times New is more common among PCL5 printers than Times - so use Times New
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s0b16901T");
        break;
      case  6// F6 = Times Italic
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s0b16901T");
        break;
      case  7// F7 = Times Bold
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s3b16901T");
        break;
      case  8// F8 = Times Bold Italic
        currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s3b16901T");
        break;
      case  9// F9 = Courier
        currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h0s0b4099T");
        break;
      case  10// F10 = Courier Oblique
        currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h1s0b4099T");
        break;
      case  11// F11 = Courier Bold
        currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h0s3b4099T");
        break;
      case  12// F12 = Courier Bold Oblique
        currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h1s3b4099T");
        break;
      case  13// F13 = Symbol
        currentStream.add("\033(19M\033(s1p" + (size / 1000) + "v0s0b16686T");
        //currentStream.add("\033(9U\033(s1p" + (size / 1000) + "v0s0b25093T"); // ECMA Latin 1 Symbol Set in Times Roman???
        break;
      case  14// F14 = Zapf Dingbats
        currentStream.add("\033(14L\033(s1p" + (size / 1000) + "v0s0b45101T");
        break;
      default:
        currentStream.add("\033(0N\033(s" + (size / 1000) + "V");
        break;
    }
  }

    /**
     * render inline area to PCL
     *
     * @param area inline area to render
     */
    public void renderWordArea(WordArea area)
    {
    String name = area.getFontState().getFontName();
    int size = area.getFontState().getFontSize();

    float red = area.getRed();
    float green = area.getGreen();
    float blue = area.getBlue();
        PDFColor theAreaColor = new PDFColor((double) area.getRed(),
                                             (double) area.getGreen(), (double) area.getBlue());

    //currentStream.add("\033*c" + (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) + "G\033*v2T");
    currentStream.add("\033*v1O\033*c" + (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) + "G\033*v2T");

    if ((!name.equals(this.currentFontName)) || (size != this.currentFontSize))
    {
        this.currentFontName = name;
        this.currentFontSize = size;
      setFont(name, size);
    }

    this.currentFill = theAreaColor;

    int rx = this.currentXPosition;
    int bl = this.currentYPosition;

    String s;
    if ( area.getPageNumberID()!=null )
    {
      // this text is a page number, so resolve it
        s = idReferences.getPageNumber(area.getPageNumberID());           
        if(s==null)
            s="";
    }
    else
    {
        s = area.getText();
    }

    addWordLines(area, rx, bl, size, theAreaColor);

    int xpos = xoffset + (rx / 100);
    if ( xpos < 0 )
    {
      xpos = 0;
      MessageHandler.errorln("PCLRenderer.renderWordArea() WARNING: Horizontal position out of bounds.");
    }
    currentStream.add("\033&a" + xpos + "h" + (pageHeight - (bl / 100)) + "V" + s);

    this.currentXPosition += area.getContentWidth();
    }

    /**
     * render page into PCL
     *
     * @param page page to render
     */
    public void renderPage(Page page)
    {
if ( debug )
System.out.println("PCLRenderer.renderPage() page.Height() = " + page.getHeight());
    BodyAreaContainer body;
    AreaContainer before, after, start, end;

    if ( paperheight > 0 && divisions == -1 )
      divisions = paperheight / (page.getHeight() / 100);

if ( debug )
System.out.println("PCLRenderer.renderPage() paperheight=" + paperheight + " divisions=" + divisions);

    // Set top margin.
    //float fullmargin = 0;
    if ( divisions > 0 )
      fullmargin = paperheight * curdiv / divisions;
    if ( topmargin > 0 )
      fullmargin += topmargin;
if ( debug )
System.out.println("PCLRenderer.renderPage() curdiv=" + curdiv + " fullmargin=" + fullmargin);
    //if ( fullmargin > 0 )
    //  currentStream.add("\033&l" + (fullmargin / 15f) + "c1e8C");
    //this.currentYPosition = fullmargin * 100;

    if ( paperheight > 0 )
      pageHeight = (paperheight / divisions) + fullmargin;
    else
      pageHeight = page.getHeight() / 100;
if ( debug )
System.out.println("PCLRenderer.renderPage() Set currentYPosition=" + this.currentYPosition);
    if ( leftmargin > 0 && curdiv == 0 )
      currentStream.add("\033&k" + (leftmargin / 6f) + "H\033&a1L\033&k12H");
       
    body = page.getBody();
    before = page.getBefore();
    after = page.getAfter();
    start = page.getStart();
    end = page.getEnd();

    this.currentFontName = "";
    this.currentFontSize = 0;

    renderBodyAreaContainer(body);

    if (before != null)
        renderAreaContainer(before);

    if (after != null)
        renderAreaContainer(after);
   
    if (start != null)
        renderAreaContainer(start);

    if (end != null)
        renderAreaContainer(end);

    // End page.
    if ( ++curdiv == divisions || divisions == -1 )
    {
      curdiv = 0;
      currentStream.add("\f");
    }

    // Links, etc not implemented...
    /*
    currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
           page.getWidth()/1000, page.getHeight()/1000, page);

    if (page.hasLinks()) {
      currentAnnotList = this.pdfDoc.makeAnnotList();
      currentPage.setAnnotList(currentAnnotList);

      Enumeration e = page.getLinkSets().elements();
      while (e.hasMoreElements()) {
      LinkSet linkSet = (LinkSet) e.nextElement();

      linkSet.align();
      String dest = linkSet.getDest();
                  int linkType = linkSet.getLinkType();
      Enumeration f = linkSet.getRects().elements();
      while (f.hasMoreElements()) {
        LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
        currentAnnotList.addLink(
          this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
      }
      }
    } else {
      // just to be on the safe side
      currentAnnotList = null;
    }
    */
    }
}
TOP

Related Classes of org.apache.fop.render.pcl.PCLRenderer

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.