keiron      01/06/22 02:08:51

  Added:       src/org/apache/fop/render/ps ASCII85EncodeFilter.java
                        ASCIIHexEncodeFilter.java Filter.java
                        FilterThread.java FlateEncodeFilter.java
                        PSRenderer.java PSStream.java
  Log:
  New addition: postscript renderer
  Submitted by: Jeremias Maerki <[EMAIL PROTECTED]>
  
  Revision  Changes    Path
  1.1                  xml-fop/src/org/apache/fop/render/ps/ASCII85EncodeFilter.java
  
  Index: ASCII85EncodeFilter.java
  ===================================================================
  /* $Id: ASCII85EncodeFilter.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.*;
  
  public class ASCII85EncodeFilter implements Filter {
  
      private static final char ASCII85_ZERO = 'z';
      private static final char ASCII85_START = '!';
      private static final char ASCII85_EOL = '\n';
      private static final String ASCII85_EOD = "~>";
      private static final String ENCODING = "US-ASCII";
  
      private static final long base85_4 = 85;
      private static final long base85_3 = base85_4 * base85_4;
      private static final long base85_2 = base85_3 * base85_4;
      private static final long base85_1 = base85_2 * base85_4;
  
      protected ASCII85EncodeFilter() {
      }
  
      public long write(OutputStream out, byte[] buf, int len,
                        long bw) throws IOException {
          //Assumption: len<80
          int line = (int)(bw % 80) + len;
          if (line >= 80) {
              int first = len - (line - 80);
              out.write(buf, 0, first);
              out.write(ASCII85_EOL);
              out.write(buf, first, len - first);
          } else {
              out.write(buf, 0, len);
          }
          return bw + len;
      }
  
      public void doFilter(InputStream in,
                           OutputStream out) throws IOException {
          int total = 0;
          int diff = 0;
          long bw = 0;
  
          // first encode the majority of the data
          // each 4 byte group becomes a 5 byte group
          byte[] data = new byte[4];
          int bytes_read;
          while ((bytes_read = in.read(data)) == data.length) {
              long val = ((data[0] << 24) & 0xff000000L)// note: must have the L at the
                         + ((data[1] << 16) & 0xff0000L)// end, otherwise you get into
                         + ((data[2] << 8) & 0xff00L)// weird signed value problems
                         + (data[3] & 0xffL); // cause we're using a full 32 bits
              byte[] conv = convertWord(val);
  
              bw = write(out, conv, conv.length, bw);
          }
  
          // now take care of the trailing few bytes.
          // with n leftover bytes, we append 0 bytes to make a full group of 4
          // then convert like normal (except not applying the special zero rule)
          // and write out the first n+1 bytes from the result
          if ((bytes_read < data.length) && (bytes_read >= 0)) {
              int n = data.length - bytes_read;
              byte[] lastdata = new byte[4];
              int i = 0;
              for (int j = 0; j < 4; j++) {
                  if (j < n) {
                      lastdata[j] = data[i++];
                  } else {
                      lastdata[j] = 0;
                  }
              }
  
              long val = ((lastdata[0] << 24) & 0xff000000L) +
                         ((lastdata[1] << 16) & 0xff0000L) +
                         ((lastdata[2] << 8) & 0xff00L) + (lastdata[3] & 0xffL);
  
              byte[] conv;
              // special rule for handling zeros at the end
              if (val != 0) {
                  conv = convertWord(val);
              } else {
                  conv = new byte[5];
                  for (int j = 0; j < 5; j++) {
                      conv[j] = (byte)'!';
                  }
              }
              // assert n+1 <= 5
              bw = write(out, conv, n + 1, bw);
              // System.out.println("ASCII85 end of data was "+n+" bytes long");
  
          }
          // finally write the two character end of data marker
          byte[] EOD = ASCII85_EOD.getBytes();
          bw = write(out, EOD, EOD.length, bw);
      }
  
      /**
       * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.
       * each byte in the result starts with zero at the '!' character so
       * the resulting base85 number fits into printable ascii chars
       *
       * @param word the 32 bit unsigned (hence the long datatype) word
       * @return 5 bytes (or a single byte of the 'z' character for word
       * values of 0)
       */
      private byte[] convertWord(long word) {
          word = word & 0xffffffff;
          if (word < 0) {
              word = -word;
          }
  
          if (word == 0) {
              byte[] result = { (byte) ASCII85_ZERO };
              return result;
          } else {
              byte c1 = (byte)((word / base85_1) & 0xFF);
              byte c2 = (byte)(((word - (c1 * base85_1)) / base85_2) & 0xFF);
              byte c3 = (byte)( ((word - (c1 * base85_1) - (c2 * base85_2)) /
                                 base85_3) & 0xFF);
              byte c4 = (byte)( ((word - (c1 * base85_1) - (c2 * base85_2) -
                                  (c3 * base85_3)) / base85_4) & 0xFF);
              byte c5 = (byte)( ((word - (c1 * base85_1) - (c2 * base85_2) -
                                  (c3 * base85_3) - (c4 * base85_4))) & 0xFF);
  
              byte[] ret = {(byte)(c1 + ASCII85_START),
                            (byte)(c2 + ASCII85_START), (byte)(c3 + ASCII85_START),
                            (byte)(c4 + ASCII85_START), (byte)(c5 + ASCII85_START)};
  
              for (int i = 0; i < ret.length; i++) {
                  if (ret[i] < 33 || ret[i] > 117) {
                      System.out.println("Illegal char value "+
                                         new Integer(ret[i]));
                  }
              }
              return ret;
          }
      }
  
  
      public static InputStream filter(InputStream in) throws IOException {
          ASCII85EncodeFilter myfilter = new ASCII85EncodeFilter();
          return FilterThread.filter(in, myfilter);
      }
  }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/ASCIIHexEncodeFilter.java
  
  Index: ASCIIHexEncodeFilter.java
  ===================================================================
  /* $Id: ASCIIHexEncodeFilter.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.*;
  
  public class ASCIIHexEncodeFilter implements Filter {
  
      private static final char ASCIIHEX_EOL = '\n';
      private static final String ASCIIHEX_EOD = ">";
      private static final String ENCODING = "US-ASCII";
  
      protected ASCIIHexEncodeFilter() {
      }
  
      public long write(OutputStream out, byte[] buf, int len,
                        long bw) throws IOException {
          boolean last = false;
          int pos = 0;
          int rest = len;
          while (rest > 0) {
              int restofline = 80 - (int)((bw + pos) % 80);
              if (rest < restofline) {
                  //last line
                  restofline = rest;
                  last = true;
              }
              if (restofline > 0) {
                  out.write(buf, pos, restofline);
                  pos += restofline;
                  if (!last)
                      out.write(ASCIIHEX_EOL);
              }
              rest = len - pos;
          }
          return bw + len;
      }
  
      public void doFilter(InputStream in,
                           OutputStream out) throws IOException {
          long bw = 0;
          byte[] buf = new byte[2048];
          int bytes_read;
          StringBuffer sb = new StringBuffer(2048 * 2);
          while ((bytes_read = in.read(buf)) != -1) {
              sb.setLength(0);
              for (int i = 0; i < bytes_read; i++) {
                  int val = (int)(buf[i] & 0xFF);
                  if (val < 16)
                      sb.append("0");
                  sb.append(Integer.toHexString(val));
              }
              bw = write(out, sb.toString().getBytes(ENCODING),
                         bytes_read * 2, bw);
          }
          byte[] eod = ASCIIHEX_EOD.getBytes(ENCODING);
          bw = write(out, eod, eod.length, bw);
      }
  
      public static InputStream filter(InputStream in) throws IOException {
          ASCIIHexEncodeFilter myfilter = new ASCIIHexEncodeFilter();
          return FilterThread.filter(in, myfilter);
      }
  }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/Filter.java
  
  Index: Filter.java
  ===================================================================
  /* $Id: Filter.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.IOException;
  
  public interface Filter {
  
      public void doFilter(InputStream in,
                           OutputStream out) throws IOException;
  }
  
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/FilterThread.java
  
  Index: FilterThread.java
  ===================================================================
  /* $Id: FilterThread.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.*;
  
  public class FilterThread extends Thread {
  
      private Filter filter;
      private InputStream in;
      private OutputStream out;
  
      private FilterThread(Filter filter, InputStream in, OutputStream out) {
          this.filter = filter;
          this.in = in;
          this.out = out;
      }
  
      public void run() {
          try {
              try {
                  this.filter.doFilter(in, out);
                  this.out.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          finally { this.filter = null;
                    this.in = null;
                    this.out = null;
                  } }
  
      public static InputStream filter(InputStream in,
                                       Filter filter) throws IOException {
          PipedInputStream pin = new PipedInputStream();
          PipedOutputStream pout = new PipedOutputStream(pin);
          FilterThread thread = new FilterThread(filter, in, pout);
          thread.start();
          return pin;
      }
  }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/FlateEncodeFilter.java
  
  Index: FlateEncodeFilter.java
  ===================================================================
  /* $Id: FlateEncodeFilter.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.*;
  import java.util.zip.DeflaterOutputStream;
  
  public class FlateEncodeFilter implements Filter {
  
      protected FlateEncodeFilter() {
      }
  
      private long copyStream(InputStream in, OutputStream out,
                              int bufferSize) throws IOException {
          long bytes_total = 0;
          byte[] buf = new byte[bufferSize];
          int bytes_read;
          while ((bytes_read = in.read(buf)) != -1) {
              bytes_total += bytes_read;
              out.write(buf, 0, bytes_read);
          }
          return bytes_total;
      }
  
      public void doFilter(InputStream in,
                           OutputStream out) throws IOException {
          DeflaterOutputStream dout = new DeflaterOutputStream(out);
          copyStream(in, dout, 2048);
          //dout.flush();
          dout.close();
      }
  
      public static InputStream filter(InputStream in) throws IOException {
          FlateEncodeFilter myfilter = new FlateEncodeFilter();
          return FilterThread.filter(in, myfilter);
      }
  }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/PSRenderer.java
  
  Index: PSRenderer.java
  ===================================================================
  /* $Id: PSRenderer.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  // FOP
  import org.apache.fop.messaging.MessageHandler;
  import org.apache.fop.svg.SVGArea;
  import org.apache.fop.render.Renderer;
  import org.apache.fop.image.ImageArea;
  import org.apache.fop.image.FopImage;
  import org.apache.fop.image.FopImageException;
  import org.apache.fop.layout.*;
  import org.apache.fop.layout.inline.*;
  import org.apache.fop.datatypes.*;
  import org.apache.fop.fo.properties.*;
  import org.apache.fop.render.pdf.Font;
  
  // SVG
  import org.w3c.dom.svg.SVGSVGElement;
  import org.w3c.dom.svg.SVGDocument;
  
  // Java
  import java.io.*;
  import java.util.*;
  
  /**
   * Renderer that renders to PostScript.
   * <br>
   * This class currently generates PostScript Level 2 code. The only exception
   * is the FlateEncode filter which is a Level 3 feature. The filters in use
   * are hardcoded at the moment.
   * <br>
   * This class follows the Document Structuring Conventions (DSC) version 3.0
   * (If I did everything right). If anyone modifies this renderer please make
   * sure to also follow the DSC to make it simpler to programmatically modify
   * the generated Postscript files (ex. extract pages etc.).
   * <br>
   * TODO: Character size/spacing, SVG Transcoder for Batik, configuration, move
   * to PrintRenderer, maybe improve filters (I'm not very proud of them), add a
   * RunLengthEncode filter (useful for Level 2 Postscript), Improve
   * DocumentProcessColors stuff (probably needs to be configurable, then maybe
   * add a color to grayscale conversion for bitmaps to make output smaller (See
   * PCLRenderer), font embedding, support different character encodings, try to
   * implement image transparency, positioning of images is wrong etc.
   *
   * @author Jeremias Märki
   */
  public class PSRenderer implements Renderer {
  
      /** the application producing the PostScript */
      protected String producer;
  
      int imagecount = 0; //DEBUG
  
      private boolean enableComments = true;
  
      /** the stream used to output the PostScript */
      protected PSStream out;
      private boolean ioTrouble = false;
  
      private String currentFontName;
      private int currentFontSize;
      private int pageHeight;
      private int pageWidth;
      private int currentXPosition = 0;
      private int currentYPosition = 0;
      private int currentAreaContainerXPosition = 0;
      private float currRed;
      private float currGreen;
      private float currBlue;
  
      protected Hashtable options;
  
  
      /**
       * set the document's producer
       *
       * @param producer string indicating application producing the PostScript
       */
      public void setProducer(String producer) {
          this.producer = producer;
      }
  
  
      /** set up renderer options */
      public void setOptions(Hashtable options) {
          this.options = options;
      }
  
  
      /**
       * render the areas into PostScript
       *
       * @param areaTree the laid-out area tree
       * @param stream the OutputStream to give the PostScript to
       */
      public void render(AreaTree areaTree,
                         OutputStream stream) throws IOException {
          MessageHandler.logln("rendering areas to PostScript");
          this.out = new PSStream(stream);
          write("%!PS-Adobe-3.0");
          write("%%Creator: "+this.producer);
          write("%%Pages: "+areaTree.getPages().size());
          write("%%DocumentProcessColors: Black");
          write("%%DocumentSuppliedResources: procset FOPFonts");
          write("%%EndComments");
          write("%%BeginDefaults");
          write("%%EndDefaults");
          write("%%BeginProlog");
          write("%%EndProlog");
          write("%%BeginSetup");
          writeFontDict(areaTree.getFontInfo());
          write("%%EndSetup");
          write("FOPFonts begin");
  
          comment("% --- AreaTree begin");
          Enumeration e = areaTree.getPages().elements();
          while (e.hasMoreElements()) {
              this.renderPage((Page) e.nextElement());
          }
          comment("% --- AreaTree end");
          write("%%Trailer");
          write("%%EOF");
          this.out.flush();
          MessageHandler.logln("written out PostScript");
      }
  
  
      /**
       * write out a command
       */
      protected void write(String cmd) {
          try {
              out.write(cmd);
          } catch (IOException e) {
              if (!ioTrouble)
                  e.printStackTrace();
              ioTrouble = true;
          }
      }
  
  
      /**
       * write out a comment
       */
      protected void comment(String comment) {
          if (this.enableComments)
              write(comment);
      }
  
  
      protected void writeFontDict(FontInfo fontInfo) {
          write("%%BeginResource: procset FOPFonts");
          write("%%Title: Font setup (shortcuts) for this file");
          write("/FOPFonts 100 dict dup begin");
          write("/bd{bind def}bind def");
          write("/ld{load def}bd");
          write("/M/moveto ld");
          write("/RM/rmoveto ld");
          write("/t/show ld");
  
          write("/ux 0.0 def");
          write("/uy 0.0 def");
          //write("/cf /Helvetica def");
          //write("/cs 12000 def");
  
          //<font> <size> F
          write("/F {");
          write("  /Tp exch def");
          //write("  currentdict exch get");
          write("  /Tf exch def");
          write("  Tf findfont Tp scalefont setfont");
          write("  /cf Tf def  /cs Tp def  /cw ( ) stringwidth pop def");
          write("} bd");
  
          write("/ULS {currentpoint /uy exch def /ux exch def} bd");
          write("/ULE {");
          write("  /Tcx currentpoint pop def");
          write("  gsave");
          write("  newpath");
          write("  cf findfont cs scalefont dup");
          write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
          write("  /UnderlinePosition get Ts mul /To exch def");
          write("  /UnderlineThickness get Ts mul /Tt exch def");
          write("  ux uy To add moveto  Tcx uy To add lineto");
          write("  Tt setlinewidth stroke");
          write("  grestore");
          write("} bd");
  
          write("/OLE {");
          write("  /Tcx currentpoint pop def");
          write("  gsave");
          write("  newpath");
          write("  cf findfont cs scalefont dup");
          write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
          write("  /UnderlinePosition get Ts mul /To exch def");
          write("  /UnderlineThickness get Ts mul /Tt exch def");
          write("  ux uy To add cs add moveto Tcx uy To add cs add lineto");
          write("  Tt setlinewidth stroke");
          write("  grestore");
          write("} bd");
  
          write("/SOE {");
          write("  /Tcx currentpoint pop def");
          write("  gsave");
          write("  newpath");
          write("  cf findfont cs scalefont dup");
          write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
          write("  /UnderlinePosition get Ts mul /To exch def");
          write("  /UnderlineThickness get Ts mul /Tt exch def");
          write("  ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 
26 idiv add lineto");
          write("  Tt setlinewidth stroke");
          write("  grestore");
          write("} bd");
  
  
  
          //write("/gfF1{/Helvetica findfont} bd");
          //write("/gfF3{/Helvetica-Bold findfont} bd");
          Hashtable fonts = fontInfo.getFonts();
          Enumeration enum = fonts.keys();
          while (enum.hasMoreElements()) {
              String key = (String) enum.nextElement();
              Font fm = (Font) fonts.get(key);
              write("/"+key + " /"+fm.fontName() + " def");
          }
          write("end def");
          write("%%EndResource");
          enum = fonts.keys();
          while (enum.hasMoreElements()) {
              String key = (String) enum.nextElement();
              Font fm = (Font) fonts.get(key);
              write("/"+fm.fontName() + " findfont");
              write("dup length dict begin");
              write("  {1 index /FID ne {def} {pop pop} ifelse} forall");
              write("  /Encoding ISOLatin1Encoding def");
              write("  currentdict");
              write("end");
              write("/"+fm.fontName() + " exch definefont pop");
          }
      }
  
      protected void movetoCurrPosition() {
          write(this.currentXPosition + " "+this.currentYPosition + " M");
      }
  
      /**
       * set up the font info
       *
       * @param fontInfo the font info object to set up
       */
      public void setupFontInfo(FontInfo fontInfo) {
          /* use PDF's font setup to get PDF metrics */
          org.apache.fop.render.pdf.FontSetup.setup(fontInfo);
      }
  
      /**
       * render an area container to PostScript
       *
       * @param area the area container to render
       */
      public void renderAreaContainer(AreaContainer area) {
          int saveY = this.currentYPosition;
          int saveX = this.currentAreaContainerXPosition;
          if (area.getPosition() == Position.ABSOLUTE) {
              // Y position is computed assuming positive Y axis, adjust for negative 
postscript one
              this.currentYPosition =
                area.getYPosition() - 2 * area.getPaddingTop() -
                2 * area.getBorderTopWidth();
              this.currentAreaContainerXPosition = area.getXPosition();
          } else if (area.getPosition() == Position.RELATIVE) {
              this.currentYPosition -= area.getYPosition();
              this.currentAreaContainerXPosition += area.getXPosition();
          } else if (area.getPosition() == Position.STATIC) {
              this.currentYPosition -=
                area.getPaddingTop() + area.getBorderTopWidth();
              this.currentAreaContainerXPosition +=
                area.getPaddingLeft() + area.getBorderLeftWidth();
          }
  
          this.currentXPosition = this.currentAreaContainerXPosition;
  
          //comment("% --- AreaContainer begin");
          doFrame(area);
          Enumeration e = area.getChildren().elements();
          while (e.hasMoreElements()) {
              Box b = (Box) e.nextElement();
              b.render(this);
          }
          //comment("% --- AreaContainer end");
  
          if (area.getPosition() != Position.STATIC) {
              this.currentYPosition = saveY;
              this.currentAreaContainerXPosition = saveX;
          } else {
              this.currentYPosition -= area.getHeight();
          }
      }
  
      /**
       * render a body area container to PostScript
       *
       * @param area the body area container to render
       */
      public void renderBodyAreaContainer(BodyAreaContainer area) {
          int saveY = this.currentYPosition;
          int saveX = this.currentAreaContainerXPosition;
  
          if (area.getPosition() == Position.ABSOLUTE) {
              // Y position is computed assuming positive Y axis, adjust for negative 
postscript one
              this.currentYPosition = area.getYPosition();
              this.currentAreaContainerXPosition = area.getXPosition();
          } else if (area.getPosition() == Position.RELATIVE) {
              this.currentYPosition -= area.getYPosition();
              this.currentAreaContainerXPosition += area.getXPosition();
          }
  
          this.currentXPosition = this.currentAreaContainerXPosition;
          int w, h;
          int rx = this.currentAreaContainerXPosition;
          w = area.getContentWidth();
          h = area.getContentHeight();
          int ry = this.currentYPosition;
  
          //comment("% --- BodyAreaContainer begin");
          doFrame(area);
          //movetoCurrPosition();
  
          Enumeration e = area.getChildren().elements();
          while (e.hasMoreElements()) {
              Box b = (Box) e.nextElement();
              b.render(this);
          }
          //comment("% --- BodyAreaContainer end");
  
          if (area.getPosition() != Position.STATIC) {
              this.currentYPosition = saveY;
              this.currentAreaContainerXPosition = saveX;
          } else {
              this.currentYPosition -= area.getHeight();
          }
      }
  
      /**
       * render a span area to PostScript
       *
       * @param area the span area to render
       */
      public void renderSpanArea(SpanArea area) {
          //comment("% --- SpanArea begin");
          Enumeration e = area.getChildren().elements();
          while (e.hasMoreElements()) {
              Box b = (Box) e.nextElement();
              b.render(this);
          }
          //comment("% --- SpanArea end");
      }
  
      /**
       * render a block area to PostScript
       *
       * @param area the block area to render
       */
      public void renderBlockArea(BlockArea area) {
          //comment("% --- BlockArea begin");
          doFrame(area);
          Enumeration e = area.getChildren().elements();
          while (e.hasMoreElements()) {
              Box b = (Box) e.nextElement();
              b.render(this);
          }
          //comment("% --- BlockArea end");
      }
  
      /**
       * render a display space to PostScript
       *
       * @param space the space to render
       */
      public void renderDisplaySpace(DisplaySpace space) {
          //write("% --- DisplaySpace size="+space.getSize());
          this.currentYPosition -= space.getSize();
          movetoCurrPosition();
      }
  
      /** render a foreign object area */
      public void renderForeignObjectArea(ForeignObjectArea area) {
          // if necessary need to scale and align the content
          area.getObject().render(this);
      }
  
      /**
       * render an SVG area to PostScript
       *
       * @param area the area to render
       */
      public void renderSVGArea(SVGArea area) {
          int x = this.currentXPosition;
          int y = this.currentYPosition;
          SVGSVGElement svg =
            ((SVGDocument) area.getSVGDocument()).getRootElement();
          int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
          int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
  
          comment("% --- SVG Area");
          /**@todo Implement SVG */
          comment("% --- SVG Area end");
          movetoCurrPosition();
      }
  
      public void renderBitmap(FopImage img, int x, int y, int w, int h) {
          try {
              boolean iscolor = img.getColorSpace().getColorSpace() !=
                                ColorSpace.DEVICE_GRAY;
              byte[] imgmap = img.getBitmaps();
  
              write("gsave");
              write("/DeviceRGB setcolorspace");
              write(x + " "+(y - h) + " translate");
              write(w + " "+h + " scale");
              write("<<");
              write("  /ImageType 1");
              write("  /Width "+img.getWidth());
              write("  /Height "+img.getHeight());
              write("  /BitsPerComponent 8");
              if (iscolor) {
                  write("  /Decode [0 1 0 1 0 1]");
              } else {
                  write("  /Decode [0 1]");
              }
              //Setup scanning for left-to-right and top-to-bottom
              write("  /ImageMatrix ["+img.getWidth() + " 0 0 -"+
                    img.getHeight() + " 0 "+img.getHeight() + "]");
              write("  /DataSource currentfile /ASCII85Decode filter /FlateDecode 
filter");
              //write("  /DataSource currentfile /ASCIIHexDecode filter /FlateDecode 
filter");
              //write("  /DataSource currentfile /ASCII85Decode filter 
/RunLengthDecode filter");
              //write("  /DataSource currentfile /ASCIIHexDecode filter 
/RunLengthDecode filter");
              //write("  /DataSource currentfile /ASCIIHexDecode filter");
              //write("  /DataSource currentfile /ASCII85Decode filter");
              //write("  /DataSource currentfile /RunLengthDecode filter");
              write(">>");
              write("image");
  
              /*
              for (int y=0; y<img.getHeight(); y++) {
                  int indx = y * img.getWidth();
                  if (iscolor) indx*= 3;
                  for (int x=0; x<img.getWidth(); x++) {
                      if (iscolor) {
                          writeASCIIHex(imgmap[indx++] & 0xFF);
                          writeASCIIHex(imgmap[indx++] & 0xFF);
                          writeASCIIHex(imgmap[indx++] & 0xFF);
                      } else {
                          writeASCIIHex(imgmap[indx++] & 0xFF);
                      }
                  }
          }*/
              try {
                  //imgmap[0] = 1;
                  InputStream bain = new ByteArrayInputStream(imgmap);
                  InputStream in;
                  in = bain;
                  in = FlateEncodeFilter.filter(in);
                  //in = RunLengthEncodeFilter.filter(in);
                  //in = ASCIIHexEncodeFilter.filter(in);
                  in = ASCII85EncodeFilter.filter(in);
                  copyStream(in, this.out);
              } catch (IOException e) {
                  if (!ioTrouble)
                      e.printStackTrace();
                  ioTrouble = true;
              }
  
              write("");
              write("grestore");
          }
          catch (FopImageException e) {
              e.printStackTrace();
              MessageHandler.errorln(
                "PSRenderer.renderImageArea(): Error rendering bitmap (" +
                e.toString() + ")");
          }
      }
  
      /**
       * render an image area to PostScript
       *
       * @param area the 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 -= area.getHeight();
  
          imagecount++;
          //if (imagecount!=4) return;
  
          comment("% --- ImageArea");
          renderBitmap(area.getImage(), x, y, w, h);
          comment("% --- ImageArea end");
      }
  
      private long copyStream(InputStream in, OutputStream out,
                              int bufferSize) throws IOException {
          long bytes_total = 0;
          byte[] buf = new byte[bufferSize];
          int bytes_read;
          while ((bytes_read = in.read(buf)) != -1) {
              bytes_total += bytes_read;
              out.write(buf, 0, bytes_read);
          }
          return bytes_total;
      }
  
  
      private long copyStream(InputStream in,
                              OutputStream out) throws IOException {
          return copyStream(in, out, 4096);
      }
  
      /**
       * render an inline area to PostScript
       *
       * @param area the area to render
       */
      public void renderWordArea(WordArea area) {
          FontState fs = area.getFontState();
          String fontWeight = fs.getFontWeight();
          StringBuffer sb = new StringBuffer();
          String s = area.getText();
          int l = s.length();
          for (int i = 0; i < l; i++) {
              char ch = s.charAt(i);
              char mch = fs.mapChar(ch);
              if (mch > 127) {
                  sb = sb.append("\\"+Integer.toOctalString(mch));
              } else {
                  String escape = "\\()[]{}";
                  if (escape.indexOf(mch) >= 0) {
                      sb.append("\\");
                  }
                  sb = sb.append(mch);
              }
          }
          //System.out.println("["+s+"] --> ["+sb.toString()+"]");
  
          //comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString());
          useFont(fs.getFontName(), fs.getFontSize());
          useColor(area.getRed(), area.getGreen(), area.getBlue());
          if (area.getUnderlined() || area.getLineThrough() ||
                  area.getOverlined())
              write("ULS");
          write("("+sb.toString() + ") t");
          if (area.getUnderlined())
              write("ULE");
          if (area.getLineThrough())
              write("SOE");
          if (area.getOverlined())
              write("OLE");
          this.currentXPosition += area.getContentWidth();
      }
  
      public void useFont(String name, int size) {
          if ((currentFontName != name) || (currentFontSize != size)) {
              write(name + " "+size + " F");
              currentFontName = name;
              currentFontSize = size;
          }
      }
  
      /**
       * render an inline space to PostScript
       *
       * @param space the space to render
       */
      public void renderInlineSpace(InlineSpace space) {
          //write("% --- InlineSpace size="+space.getSize());
          this.currentXPosition += space.getSize();
          if (space.getUnderlined() || space.getLineThrough() ||
                  space.getOverlined())
              write("ULS");
          write(space.getSize() + " 0 RM");
          if (space.getUnderlined())
              write("ULE");
          if (space.getLineThrough())
              write("SOE");
          if (space.getOverlined())
              write("OLE");
      }
  
      /**
       * render a line area to PostScript
       *
       * @param area the area to render
       */
      public void renderLineArea(LineArea area) {
          int rx = this.currentAreaContainerXPosition + area.getStartIndent();
          int ry = this.currentYPosition;
          int w = area.getContentWidth();
          int h = area.getHeight();
  
          this.currentYPosition -= area.getPlacementOffset();
          this.currentXPosition = rx;
  
          int bl = this.currentYPosition;
          movetoCurrPosition();
  
          String fontWeight = area.getFontState().getFontWeight();
          //comment("% --- LineArea begin font-weight="+fontWeight);
          Enumeration e = area.getChildren().elements();
          while (e.hasMoreElements()) {
              Box b = (Box) e.nextElement();
              this.currentYPosition = ry - area.getPlacementOffset();
              b.render(this);
          }
          //comment("% --- LineArea end");
  
          this.currentYPosition = ry - h;
          this.currentXPosition = rx;
      }
  
      /**
       * render a page to PostScript
       *
       * @param page the page to render
       */
      public void renderPage(Page page) {
          BodyAreaContainer body;
          AreaContainer before, after;
          write("%%Page: "+page.getNumber() + " "+page.getNumber());
          write("%%BeginPageSetup");
          write("FOPFonts begin");
          write("0.001 0.001 scale");
          write("%%EndPageSetup");
          body = page.getBody();
          before = page.getBefore();
          after = page.getAfter();
          if (before != null) {
              renderAreaContainer(before);
          }
          renderBodyAreaContainer(body);
          if (after != null) {
              renderAreaContainer(after);
          }
          write("showpage");
          write("%%PageTrailer");
          write("%%EndPage");
      }
  
      /**
       * render a leader area to PostScript
       *
       * @param area the area to render
       */
      public void renderLeaderArea(LeaderArea area) {
          int rx = this.currentXPosition;
          int ry = this.currentYPosition;
          int w = area.getContentWidth();
          int th = area.getRuleThickness();
          int th2 = th / 2;
          int th3 = th / 3;
          int th4 = th / 4;
  
          switch (area.getLeaderPattern()) {
              case LeaderPattern.SPACE:
                  //NOP
                  break;
              case LeaderPattern.RULE:
                  if (area.getRuleStyle() == RuleStyle.NONE)
                      break;
                  useColor(area.getRed(), area.getGreen(), area.getBlue());
                  write("gsave");
                  write("0 setlinecap");
                  switch (area.getRuleStyle()) {
                      case RuleStyle.DOTTED:
                          write("newpath");
                          write("[1000 3000] 0 setdash");
                          write(th + " setlinewidth");
                          write(rx + " "+ry + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          break;
                      case RuleStyle.DASHED:
                          write("newpath");
                          write("[3000 3000] 0 setdash");
                          write(th + " setlinewidth");
                          write(rx + " "+ry + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          break;
                      case RuleStyle.SOLID:
                          write("newpath");
                          write(th + " setlinewidth");
                          write(rx + " "+ry + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          break;
                      case RuleStyle.DOUBLE:
                          write("newpath");
                          write(th3 + " setlinewidth");
                          write(rx + " "+(ry - th3) + " M");
                          write(w + " 0 rlineto");
                          write(rx + " "+(ry + th3) + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          break;
                      case RuleStyle.GROOVE:
                          write(th2 + " setlinewidth");
                          write("newpath");
                          write(rx + " "+(ry - th4) + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          write("newpath");
                          write(rx + " "+(ry + th4) + " M");
                          write(w + " 0 rlineto");
                          useColor(1, 1, 1); //white
                          write("stroke");
                          break;
                      case RuleStyle.RIDGE:
                          write(th2 + " setlinewidth");
                          write("newpath");
                          write(rx + " "+(ry - th4) + " M");
                          write(w + " 0 rlineto");
                          useColor(1, 1, 1); //white
                          write("stroke");
                          write("newpath");
                          write(rx + " "+(ry + th4) + " M");
                          write(w + " 0 rlineto");
                          useColor(area.getRed(), area.getGreen(),
                                   area.getBlue());
                          write("stroke");
                          break;
                  }
                  write("grestore");
                  break;
              case LeaderPattern.DOTS:
                  comment("% --- Leader dots NYI");
                  MessageHandler.errorln("Leader dots: Not yet implemented");
                  break;
              case LeaderPattern.USECONTENT:
                  comment("% --- Leader use-content NYI");
                  MessageHandler.errorln("Leader use-content: Not yet implemented");
                  break;
          }
          this.currentXPosition += area.getContentWidth();
          write(area.getContentWidth() + " 0 RM");
      }
  
      private void doFrame(Area area) {
          int w, h;
          int rx = this.currentAreaContainerXPosition;
          w = area.getContentWidth();
          BorderAndPadding bap = area.getBorderAndPadding();
  
          if (area instanceof BlockArea)
              rx += ((BlockArea) area).getStartIndent();
  
          h = area.getContentHeight();
          int ry = this.currentYPosition;
  
          rx = rx - area.getPaddingLeft();
          ry = ry + area.getPaddingTop();
          w = w + area.getPaddingLeft() + area.getPaddingRight();
          h = h + area.getPaddingTop() + area.getPaddingBottom();
  
          rx = rx - area.getBorderLeftWidth();
          ry = ry + area.getBorderTopWidth();
          w = w + area.getBorderLeftWidth() + area.getBorderRightWidth();
          h = h + area.getBorderTopWidth() + area.getBorderBottomWidth();
  
          //Create a textrect with these dimensions.
          //The y co-ordinate is measured +ve downwards so subtract page-height
  
          ColorType bg = area.getBackgroundColor();
          if ((bg != null) && (bg.alpha() == 0)) {
              write("newpath");
              write(rx + " "+ry + " M");
              write(w + " 0 rlineto");
              write("0 "+(-h) + " rlineto");
              write((-w) + " 0 rlineto");
              write("0 "+h + " rlineto");
              write("closepath");
              useColor(bg);
              write("fill");
          }
  
  
          if (area.getBorderTopWidth() != 0) {
              write("newpath");
              write(rx + " "+ry + " M");
              write(w + " 0 rlineto");
              write(area.getBorderTopWidth() + " setlinewidth");
              write("0 setlinecap");
              useColor(bap.getBorderColor(BorderAndPadding.TOP));
              write("stroke");
          }
          if (area.getBorderLeftWidth() != 0) {
              write("newpath");
              write(rx + " "+ry + " M");
              write("0 "+(-h) + " rlineto");
              write(area.getBorderLeftWidth() + " setlinewidth");
              write("0 setlinecap");
              useColor(bap.getBorderColor(BorderAndPadding.LEFT));
              write("stroke");
          }
          if (area.getBorderRightWidth() != 0) {
              write("newpath");
              write((rx + w) + " "+ry + " M");
              write("0 "+(-h) + " rlineto");
              write(area.getBorderRightWidth() + " setlinewidth");
              write("0 setlinecap");
              useColor(bap.getBorderColor(BorderAndPadding.RIGHT));
              write("stroke");
          }
          if (area.getBorderBottomWidth() != 0) {
              write("newpath");
              write(rx + " "+(ry - h) + " M");
              write(w + " 0 rlineto");
              write(area.getBorderBottomWidth() + " setlinewidth");
              write("0 setlinecap");
              useColor(bap.getBorderColor(BorderAndPadding.BOTTOM));
              write("stroke");
          }
      }
  
      private void useColor(ColorType col) {
          useColor(col.red(), col.green(), col.blue());
      }
  
      private void useColor(float red, float green, float blue) {
          if ((red != currRed) || (green != currGreen) ||
                  (blue != currBlue)) {
              write(red + " "+green + " "+blue + " setrgbcolor");
              currRed = red;
              currGreen = green;
              currBlue = blue;
          }
      }
  
  }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/PSStream.java
  
  Index: PSStream.java
  ===================================================================
  /* $Id: PSStream.java,v 1.1 2001/06/22 09:08:50 keiron 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 org.apache.fop.render.ps;
  
  import java.io.*;
  
  public class PSStream extends FilterOutputStream {
  
      public PSStream(OutputStream out) {
          super(out);
      }
  
      public void write(String cmd) throws IOException {
          if (cmd.length() > 255)
              throw new RuntimeException("PostScript command exceeded limit of 255 
characters");
          write(cmd.getBytes("US-ASCII"));
          write('\n');
      }
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to