keiron      01/06/22 07:16:48

  Modified:    src/org/apache/fop/render/ps PSRenderer.java
  Added:       src/org/apache/fop/render/ps PSGraphics2D.java
  Log:
  added support for rendering SVG graphics to ps
  not fully functional
  
  Revision  Changes    Path
  1.2       +210 -5    xml-fop/src/org/apache/fop/render/ps/PSRenderer.java
  
  Index: PSRenderer.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/ps/PSRenderer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PSRenderer.java   2001/06/22 09:08:50     1.1
  +++ PSRenderer.java   2001/06/22 14:16:46     1.2
  @@ -1,4 +1,4 @@
  -/* $Id: PSRenderer.java,v 1.1 2001/06/22 09:08:50 keiron Exp $
  +/* $Id: PSRenderer.java,v 1.2 2001/06/22 14:16:46 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.
  @@ -18,14 +18,36 @@
   import org.apache.fop.datatypes.*;
   import org.apache.fop.fo.properties.*;
   import org.apache.fop.render.pdf.Font;
  +import org.apache.fop.image.*;
   
  +import org.apache.batik.bridge.*;
  +import org.apache.batik.swing.svg.*;
  +import org.apache.batik.swing.gvt.*;
  +import org.apache.batik.gvt.*;
  +import org.apache.batik.gvt.renderer.*;
  +import org.apache.batik.gvt.filter.*;
  +import org.apache.batik.gvt.event.*;
  +
   // SVG
   import org.w3c.dom.svg.SVGSVGElement;
   import org.w3c.dom.svg.SVGDocument;
  +import org.w3c.dom.*;
  +import org.w3c.dom.svg.*;
   
   // Java
   import java.io.*;
   import java.util.*;
  +import java.io.IOException;
  +import java.io.OutputStream;
  +import java.util.Enumeration;
  +import java.util.Vector;
  +import java.util.Hashtable;
  +import java.awt.geom.AffineTransform;
  +import java.awt.geom.Dimension2D;
  +import java.awt.Point;
  +import java.awt.RenderingHints;
  +import java.awt.font.FontRenderContext;
  +import java.awt.Dimension;
   
   /**
    * Renderer that renders to PostScript.
  @@ -401,17 +423,94 @@
       public void renderSVGArea(SVGArea area) {
           int x = this.currentXPosition;
           int y = this.currentYPosition;
  -        SVGSVGElement svg =
  -          ((SVGDocument) area.getSVGDocument()).getRootElement();
  +        Document doc = area.getSVGDocument();
  +        SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
           int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
           int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
  +        float sx = 1, sy = -1;
  +        int xOffset = x, yOffset = y;
   
  +        /*
  +         * Clip to the svg area.
  +         * Note: To have the svg overlay (under) a text area then use
  +         * an fo:block-container
  +         */
           comment("% --- SVG Area");
  -        /**@todo Implement SVG */
  +        write("gsave");
  +        if (w != 0 && h != 0) {
  +/*            write("newpath");
  +            write(x / 1000f + " " + y / 1000f + " M");
  +            write((x + w) / 1000f + " " + y / 1000f + " rlineto");
  +            write((x + w) / 1000f + " " + (y - h) / 1000f +
  +                              " rlineto");
  +            write(x / 1000f + " " + (y - h) / 1000f + " rlineto");
  +            write("closepath");
  +            write("clippath");
  +*/        }
  +        // transform so that the coordinates (0,0) is from the top left
  +        // and positive is down and to the right. (0,0) is where the
  +        // viewBox puts it.
  +        write(xOffset +
  +                          " " + yOffset + " translate");
  +        write(sx + " " + sy + " " + " scale");
  +
  +
  +        UserAgent userAgent = new MUserAgent(new AffineTransform());
  +
  +        GVTBuilder builder = new GVTBuilder();
  +        GraphicsNodeRenderContext rc = getRenderContext();
  +        BridgeContext ctx = new BridgeContext(userAgent, rc);
  +        GraphicsNode root;
  +        PSGraphics2D graphics =
  +          new PSGraphics2D(false, area.getFontState(), this,
  +                            currentFontName, currentFontSize, currentXPosition,
  +                            currentYPosition);
  +        graphics.setGraphicContext(
  +          new org.apache.batik.ext.awt.g2d.GraphicContext());
  +        graphics.setRenderingHints(rc.getRenderingHints());
  +        try {
  +            root = builder.build(ctx, doc);
  +            root.paint(graphics, rc);
  +        } catch (Exception e) {
  +            MessageHandler.errorln("Error: svg graphic could not be rendered: " + 
e.getMessage());
  +            //e.printStackTrace();
  +        }
  +
  +        write("grestore");
  +
           comment("% --- SVG Area end");
           movetoCurrPosition();
       }
   
  +    public GraphicsNodeRenderContext getRenderContext() {
  +        GraphicsNodeRenderContext nodeRenderContext = null;
  +        if (nodeRenderContext == null) {
  +            RenderingHints hints = new RenderingHints(null);
  +            hints.put(RenderingHints.KEY_ANTIALIASING,
  +                      RenderingHints.VALUE_ANTIALIAS_ON);
  +
  +            hints.put(RenderingHints.KEY_INTERPOLATION,
  +                      RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  +
  +            FontRenderContext fontRenderContext =
  +              new FontRenderContext(new AffineTransform(), true,
  +                                    true);
  +
  +            TextPainter textPainter = new StrokingTextPainter();
  +            //TextPainter textPainter = new PDFTextPainter();
  +
  +            GraphicsNodeRableFactory gnrFactory =
  +              new ConcreteGraphicsNodeRableFactory();
  +
  +            nodeRenderContext = new GraphicsNodeRenderContext(
  +                                  new AffineTransform(), null, hints,
  +                                  fontRenderContext, textPainter, gnrFactory);
  +            nodeRenderContext.setTextPainter(textPainter);
  +        }
  +
  +        return nodeRenderContext;
  +    }
  +
       public void renderBitmap(FopImage img, int x, int y, int w, int h) {
           try {
               boolean iscolor = img.getColorSpace().getColorSpace() !=
  @@ -502,7 +601,10 @@
           //if (imagecount!=4) return;
   
           comment("% --- ImageArea");
  -        renderBitmap(area.getImage(), x, y, w, h);
  +        if(area.getImage() instanceof SVGImage) {
  +        } else {
  +            renderBitmap(area.getImage(), x, y, w, h);
  +        }
           comment("% --- ImageArea end");
       }
   
  @@ -853,4 +955,107 @@
           }
       }
   
  +    protected class MUserAgent implements UserAgent {
  +        AffineTransform currentTransform = null;
  +        /**
  +         * Creates a new SVGUserAgent.
  +         */
  +        protected MUserAgent(AffineTransform at) {
  +            currentTransform = at;
  +        }
  +
  +        /**
  +         * Displays an error message.
  +         */
  +        public void displayError(String message) {
  +            System.err.println(message);
  +        }
  +
  +        /**
  +         * Displays an error resulting from the specified Exception.
  +         */
  +        public void displayError(Exception ex) {
  +            ex.printStackTrace(System.err);
  +        }
  +
  +        /**
  +         * Displays a message in the User Agent interface.
  +         * The given message is typically displayed in a status bar.
  +         */
  +        public void displayMessage(String message) {
  +            System.out.println(message);
  +        }
  +
  +        /**
  +         * Returns a customized the pixel to mm factor.
  +         */
  +        public float getPixelToMM() {
  +            return 0.264583333333333333333f; // 72 dpi
  +        }
  +
  +        /**
  +         * Returns the language settings.
  +         */
  +        public String getLanguages() {
  +            return "en";//userLanguages;
  +        }
  +
  +        /**
  +         * Returns the user stylesheet uri.
  +         * @return null if no user style sheet was specified.
  +         */
  +        public String getUserStyleSheetURI() {
  +            return null;//userStyleSheetURI;
  +        }
  +
  +        /**
  +         * Returns the class name of the XML parser.
  +         */
  +        public String getXMLParserClassName() {
  +            String parserClassName = System.getProperty("org.xml.sax.parser");
  +            if (parserClassName == null) {
  +                parserClassName = "org.apache.xerces.parsers.SAXParser";
  +            }
  +            return parserClassName;//application.getXMLParserClassName();
  +        }
  +
  +        /**
  +         * Opens a link in a new component.
  +         * @param doc The current document.
  +         * @param uri The document URI.
  +         */
  +        public void openLink(SVGAElement elt) {
  +            //application.openLink(uri);
  +        }
  +
  +        public Point getClientAreaLocationOnScreen() {
  +            return new Point(0, 0);
  +        }
  +
  +        public void setSVGCursor(java.awt.Cursor cursor) {
  +        }
  +
  +        public AffineTransform getTransform() {
  +            return currentTransform;
  +        }
  +
  +        public Dimension2D getViewportSize() {
  +            return new Dimension(100, 100);
  +        }
  +
  +        public EventDispatcher getEventDispatcher() {
  +            return null;
  +        }
  +
  +        public boolean supportExtension(String str) {
  +            return false;
  +        }
  +
  +        public boolean hasFeature(String str) {
  +            return false;
  +        }
  +
  +        public void registerExtension(BridgeExtension be) {
  +        }
  +    }
   }
  
  
  
  1.1                  xml-fop/src/org/apache/fop/render/ps/PSGraphics2D.java
  
  Index: PSGraphics2D.java
  ===================================================================
  /* $Id: PSGraphics2D.java,v 1.1 2001/06/22 14:16:45 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 org.apache.fop.pdf.*;
  import org.apache.fop.layout.*;
  import org.apache.fop.fonts.*;
  import org.apache.fop.render.pdf.*;
  import org.apache.fop.image.*;
  import org.apache.fop.datatypes.ColorSpace;
  
  import org.apache.batik.ext.awt.g2d.*;
  
  import java.text.AttributedCharacterIterator;
  import java.text.CharacterIterator;
  import java.awt.*;
  import java.awt.Font;
  import java.awt.Image;
  import java.awt.image.*;
  import java.awt.font.*;
  import java.awt.geom.*;
  import java.awt.image.renderable.*;
  import java.io.*;
  
  import java.util.Map;
  import java.util.Vector;
  
  /**
   * This concrete implementation of <tt>AbstractGraphics2D</tt> is a
   * simple help to programmers to get started with their own
   * implementation of <tt>Graphics2D</tt>.
   * <tt>DefaultGraphics2D</tt> implements all the abstract methods
   * is <tt>AbstractGraphics2D</tt> and makes it easy to start
   * implementing a <tt>Graphic2D</tt> piece-meal.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Keiron Liddle</a>
   * @version $Id: PSGraphics2D.java,v 1.1 2001/06/22 14:16:45 keiron Exp $
   * @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
   */
  public class PSGraphics2D extends AbstractGraphics2D {
      boolean standalone = false;
  
      /** the PDF Document being created */
      protected PSRenderer psRenderer;
  
      protected FontState fontState;
  
      /** the current (internal) font name */
      protected String currentFontName;
  
      /** the current font size in millipoints */
      protected int currentFontSize;
  
      /** the current vertical position in millipoints from bottom */
      protected int currentYPosition = 0;
  
      /** the current horizontal position in millipoints from left */
      protected int currentXPosition = 0;
  
      /** the current colour for use in svg */
      PDFColor currentColour = new PDFColor(0, 0, 0);
  
      FontInfo fontInfo;
  
      /**
       * Create a new PDFGraphics2D with the given pdf document info.
       * This is used to create a Graphics object for use inside an already
       * existing document.
       */
      public PSGraphics2D(boolean textAsShapes, FontState fs,
                           PSRenderer ren, String font, int size, int xpos, int ypos) {
          super(textAsShapes);
          psRenderer = ren;
          currentFontName = font;
          currentFontSize = size;
          currentYPosition = ypos;
          currentXPosition = xpos;
          fontState = fs;
      }
  
      public PSGraphics2D(boolean textAsShapes) {
          super(textAsShapes);
      }
  
      public void setGraphicContext(GraphicContext c) {
          gc = c;
      }
  
      /**
       * This constructor supports the create method
       */
      public PSGraphics2D(PSGraphics2D g) {
          super(g);
      }
  
      /**
       * Creates a new <code>Graphics</code> object that is
       * a copy of this <code>Graphics</code> object.
       * @return     a new graphics context that is a copy of
       *             this graphics context.
       */
      public Graphics create() {
          return new PSGraphics2D(this);
      }
  
      /**
       * Draws as much of the specified image as is currently available.
       * The image is drawn with its top-left corner at
       * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
       * space. Transparent pixels in the image do not affect whatever
       * pixels are already there.
       * <p>
       * This method returns immediately in all cases, even if the
       * complete image has not yet been loaded, and it has not been dithered
       * and converted for the current output device.
       * <p>
       * If the image has not yet been completely loaded, then
       * <code>drawImage</code> returns <code>false</code>. As more of
       * the image becomes available, the process that draws the image notifies
       * the specified image observer.
       * @param    img the specified image to be drawn.
       * @param    x   the <i>x</i> coordinate.
       * @param    y   the <i>y</i> coordinate.
       * @param    observer    object to be notified as more of
       *                          the image is converted.
       * @see      java.awt.Image
       * @see      java.awt.image.ImageObserver
       * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, 
int, int, int)
       */
      public boolean drawImage(Image img, int x, int y,
                               ImageObserver observer) {
          //System.err.println("drawImage:x, y");
  
          final int width = img.getWidth(observer);
          final int height = img.getHeight(observer);
          if (width == -1 || height == -1) {
              return false;
          }
  
          Dimension size = new Dimension(width, height);
          BufferedImage buf = buildBufferedImage(size);
  
          java.awt.Graphics2D g = buf.createGraphics();
          g.setComposite(AlphaComposite.SrcOver);
          g.setBackground(new Color(1, 1, 1, 0));
          g.setPaint(new Color(1, 1, 1, 0));
          g.fillRect(0, 0, width, height);
          g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
  
          if (!g.drawImage(img, 0, 0, observer)) {
              return false;
          }
          g.dispose();
  
          final byte[] result =
            new byte[buf.getWidth() * buf.getHeight() * 3];
          final byte[] mask =
            new byte[buf.getWidth() * buf.getHeight()];
  
          Raster raster = buf.getData();
          DataBuffer bd = raster.getDataBuffer();
  
          int count = 0;
          int maskpos = 0;
          switch (bd.getDataType()) {
              case DataBuffer.TYPE_INT:
                  int[][] idata = ((DataBufferInt) bd).getBankData();
                  for (int i = 0; i < idata.length; i++) {
                      for (int j = 0; j < idata[i].length; j++) {
                          //mask[maskpos++] = (byte)((idata[i][j] >> 24) & 0xFF);
                          if(((idata[i][j] >> 24) & 0xFF) != 255) {
                              result[count++] = (byte)0xFF;
                              result[count++] = (byte)0xFF;
                              result[count++] = (byte)0xFF;
                          } else {
                              result[count++] =
                                (byte)((idata[i][j] >> 16) & 0xFF);
                              result[count++] =
                                (byte)((idata[i][j] >> 8) & 0xFF);
                              result[count++] = (byte)((idata[i][j]) & 0xFF);
                          }
                      }
                  }
                  break;
              default:
                  // error
                  break;
          }
  
          try {
              FopImage fopimg = new TempImage(width, height, result, mask);
              AffineTransform at = getTransform();
              double[] matrix = new double[6];
              at.getMatrix(matrix);
              psRenderer.write("gsave");
                        Shape imclip = getClip();
                        writeClip(imclip);
              //psRenderer.write("" + matrix[0] + " " + matrix[1] +
              //                    " " + matrix[2] + " " + matrix[3] + " " +
              //                    matrix[4] + " " + matrix[5] + " cm\n");
  psRenderer.renderBitmap(fopimg, x, y, width, height);
              psRenderer.write("grestore");
          } catch (Exception e) {
              e.printStackTrace();
          }
          return true;
      }
  
      public BufferedImage buildBufferedImage(Dimension size) {
          return new BufferedImage(size.width, size.height,
                                   BufferedImage.TYPE_INT_ARGB);
      }
  
      class TempImage implements FopImage {
          int m_height;
          int m_width;
          int m_bitsPerPixel;
          ColorSpace m_colorSpace;
          int m_bitmapSiye;
          byte[] m_bitmaps;
          byte[] m_mask;
          PDFColor transparent = new PDFColor(255, 255, 255);
  
          TempImage(int width, int height,
                    byte[] result, byte[] mask) throws FopImageException {
              this.m_height = height;
              this.m_width = width;
              this.m_bitsPerPixel = 8;
              this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
              //this.m_isTransparent = false;
              //this.m_bitmapsSize = this.m_width * this.m_height * 3;
              this.m_bitmaps = result;
              this.m_mask = mask;
          }
  
          public String getURL() {
              return "" + m_bitmaps;
          }
  
          // image size
          public int getWidth() throws FopImageException {
              return m_width;
          }
  
          public int getHeight() throws FopImageException {
              return m_height;
          }
  
          // DeviceGray, DeviceRGB, or DeviceCMYK
          public ColorSpace getColorSpace() throws FopImageException {
              return m_colorSpace;
          }
  
          // bits per pixel
          public int getBitsPerPixel() throws FopImageException {
              return m_bitsPerPixel;
          }
  
          // For transparent images
          public boolean isTransparent() throws FopImageException {
              return transparent != null;
          }
          public PDFColor getTransparentColor() throws FopImageException {
              return transparent;
          }
          public byte[] getMask()  throws FopImageException {
              return m_mask;
          }
          // get the image bytes, and bytes properties
  
          // get uncompressed image bytes
          public byte[] getBitmaps() throws FopImageException {
              return m_bitmaps;
          }
          // width * (bitsPerPixel / 8) * height, no ?
          public int getBitmapsSize() throws FopImageException {
              return m_width * m_height * 3;
          }
  
          // get compressed image bytes
          // I don't know if we really need it, nor if it
          // should be changed...
          public byte[] getRessourceBytes() throws FopImageException {
              return null;
          }
          public int getRessourceBytesSize() throws FopImageException {
              return 0;
          }
          // return null if no corresponding PDFFilter
          public PDFFilter getPDFFilter() throws FopImageException {
              return null;
          }
  
          // release memory
          public void close() {}
  
      }
  
  
      /**
       * Draws as much of the specified image as has already been scaled
       * to fit inside the specified rectangle.
       * <p>
       * The image is drawn inside the specified rectangle of this
       * graphics context's coordinate space, and is scaled if
       * necessary. Transparent pixels do not affect whatever pixels
       * are already there.
       * <p>
       * This method returns immediately in all cases, even if the
       * entire image has not yet been scaled, dithered, and converted
       * for the current output device.
       * If the current output representation is not yet complete, then
       * <code>drawImage</code> returns <code>false</code>. As more of
       * the image becomes available, the process that draws the image notifies
       * the image observer by calling its <code>imageUpdate</code> method.
       * <p>
       * A scaled version of an image will not necessarily be
       * available immediately just because an unscaled version of the
       * image has been constructed for this output device.  Each size of
       * the image may be cached separately and generated from the original
       * data in a separate image production sequence.
       * @param    img    the specified image to be drawn.
       * @param    x      the <i>x</i> coordinate.
       * @param    y      the <i>y</i> coordinate.
       * @param    width  the width of the rectangle.
       * @param    height the height of the rectangle.
       * @param    observer    object to be notified as more of
       *                          the image is converted.
       * @see      java.awt.Image
       * @see      java.awt.image.ImageObserver
       * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, 
int, int, int)
       */
      public boolean drawImage(Image img, int x, int y, int width,
                               int height, ImageObserver observer) {
          System.out.println("drawImage");
          return true;
      }
  
      /**
       * Disposes of this graphics context and releases
       * any system resources that it is using.
       * A <code>Graphics</code> object cannot be used after
       * <code>dispose</code>has been called.
       * <p>
       * When a Java program runs, a large number of <code>Graphics</code>
       * objects can be created within a short time frame.
       * Although the finalization process of the garbage collector
       * also disposes of the same system resources, it is preferable
       * to manually free the associated resources by calling this
       * method rather than to rely on a finalization process which
       * may not run to completion for a long period of time.
       * <p>
       * Graphics objects which are provided as arguments to the
       * <code>paint</code> and <code>update</code> methods
       * of components are automatically released by the system when
       * those methods return. For efficiency, programmers should
       * call <code>dispose</code> when finished using
       * a <code>Graphics</code> object only if it was created
       * directly from a component or another <code>Graphics</code> object.
       * @see         java.awt.Graphics#finalize
       * @see         java.awt.Component#paint
       * @see         java.awt.Component#update
       * @see         java.awt.Component#getGraphics
       * @see         java.awt.Graphics#create
       */
      public void dispose() {
          //System.out.println("dispose");
          psRenderer = null;
          fontState = null;
          currentFontName = null;
          currentColour = null;
          fontInfo = null;
      }
  
      /**
       * Strokes the outline of a <code>Shape</code> using the settings of the
       * current <code>Graphics2D</code> context.  The rendering attributes
       * applied include the <code>Clip</code>, <code>Transform</code>,
       * <code>Paint</code>, <code>Composite</code> and
       * <code>Stroke</code> attributes.
       * @param s the <code>Shape</code> to be rendered
       * @see #setStroke
       * @see #setPaint
       * @see java.awt.Graphics#setColor
       * @see #transform
       * @see #setTransform
       * @see #clip
       * @see #setClip
       * @see #setComposite
       */
      public void draw(Shape s) {
          //System.out.println("draw(Shape)");
              psRenderer.write("gsave");
                        Shape imclip = getClip();
                        writeClip(imclip);
          Color c = getColor();
          psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue() + " 
setrgbcolor");
  
          applyPaint(getPaint(), false);
          applyStroke(getStroke());
  
          psRenderer.write("newpath");
          PathIterator iter = s.getPathIterator(getTransform());
          while (!iter.isDone()) {
              double vals[] = new double[6];
              int type = iter.currentSegment(vals);
              switch (type) {
                  case PathIterator.SEG_CUBICTO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" " +
                                          PDFNumber.doubleOut(1000 * vals[2]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[3]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[4]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[5]) + " 
curveto");
                      break;
                  case PathIterator.SEG_LINETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" lineto");
                      break;
                  case PathIterator.SEG_MOVETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" M");
                      break;
                  case PathIterator.SEG_QUADTO:
  //                    psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
  //                                        " " + (1000 * 
PDFNumber.doubleOut(vals[1])) + " " +
  //                                        (1000 * PDFNumber.doubleOut(vals[2])) + " 
" +
  //                                        (1000 * PDFNumber.doubleOut(vals[3])) + " 
y\n");
                      break;
                  case PathIterator.SEG_CLOSE:
                      psRenderer.write("closepath");
                      break;
                  default:
                      break;
              }
              iter.next();
          }
          doDrawing(false, true, false);
              psRenderer.write("grestore");
      }
  
      protected void writeClip(Shape s) {
          PathIterator iter = s.getPathIterator(getTransform());
          psRenderer.write("newpath");
          while (!iter.isDone()) {
              double vals[] = new double[6];
              int type = iter.currentSegment(vals);
              switch (type) {
                  case PathIterator.SEG_CUBICTO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" " +
                                          PDFNumber.doubleOut(1000 * vals[2]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[3]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[4]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[5]) + " 
curveto");
                      break;
                  case PathIterator.SEG_LINETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" lineto");
                      break;
                  case PathIterator.SEG_MOVETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" M");
                      break;
                  case PathIterator.SEG_QUADTO:
  //                    psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
  //                                        " " + 1000 * PDFNumber.doubleOut(vals[1]) 
+ " " +
  //                                        1000 * PDFNumber.doubleOut(vals[2]) + " " +
  //                                        1000 * PDFNumber.doubleOut(vals[3]) + " 
y\n");
                      break;
                  case PathIterator.SEG_CLOSE:
                      psRenderer.write("closepath");
                      break;
                  default:
                      break;
              }
              iter.next();
          }
          // clip area
                psRenderer.write("clippath");
      }
  
      protected void applyPaint(Paint paint, boolean fill) {
          if(paint instanceof GradientPaint) {
              GradientPaint gp = (GradientPaint)paint;
              Color c1 = gp.getColor1();
              Color c2 = gp.getColor2();
              Point2D p1 = gp.getPoint1();
              Point2D p2 = gp.getPoint2();
              boolean cyclic = gp.isCyclic();
  
                        Vector theCoords = new Vector();
                                                theCoords.addElement( new 
Double(p1.getX()));
              theCoords.addElement( new Double(p1.getY()));
              theCoords.addElement( new Double(p2.getX()));
              theCoords.addElement( new Double(p2.getY()));
  
                                Vector theExtend = new Vector();
                                theExtend.addElement(new Boolean(true));
                                theExtend.addElement(new Boolean(true));
  
                                Vector theDomain = new Vector();
                                theDomain.addElement(new Double(0));
                                theDomain.addElement(new Double(1));
  
                                Vector theEncode = new Vector();
                                theEncode.addElement(new Double(0));
                                theEncode.addElement(new Double(1));
                                theEncode.addElement(new Double(0));
                                theEncode.addElement(new Double(1));
  
                                Vector theBounds = new Vector();
                                theBounds.addElement(new Double(0));
                                theBounds.addElement(new Double(1));
  
                                Vector theFunctions = new Vector();
  
              Vector someColors = new Vector();
  
              PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(), c1.getBlue());
              someColors.addElement(color1);
              PDFColor color2 = new PDFColor(c2.getRed(), c2.getGreen(), c2.getBlue());
              someColors.addElement(color2);
  
              ColorSpace aColorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
          } else if(paint instanceof TexturePaint) {
          }
      }
  
      protected void applyStroke(Stroke stroke) {
          if(stroke instanceof BasicStroke) {
              BasicStroke bs = (BasicStroke)stroke;
  
              float[] da = bs.getDashArray();
              if(da != null) {
                  psRenderer.write("[");
                  for(int count = 0; count < da.length; count++) {
                      psRenderer.write("" + (1000 * (int)da[count]));
                      if(count < da.length - 1) {
                          psRenderer.write(" ");
                      }
                  }
                  psRenderer.write("] ");
                  float offset = bs.getDashPhase();
                  psRenderer.write((1000 * (int)offset) + " setdash");
              }
              int ec = bs.getEndCap();
              switch(ec) {
                  case BasicStroke.CAP_BUTT:
                      psRenderer.write(0 + " setlinecap");
                  break;
                  case BasicStroke.CAP_ROUND:
                      psRenderer.write(1 + " setlinecap");
                  break;
                  case BasicStroke.CAP_SQUARE:
                      psRenderer.write(2 + " setlinecap");
                  break;
              }
  
              int lj = bs.getLineJoin();
              switch(lj) {
                  case BasicStroke.JOIN_MITER:
                      psRenderer.write(0 + " setlinejoin");
                  break;
                  case BasicStroke.JOIN_ROUND:
                      psRenderer.write(1 + " setlinejoin");
                  break;
                  case BasicStroke.JOIN_BEVEL:
                      psRenderer.write(2 + " setlinejoin");
                  break;
              }
              float lw = bs.getLineWidth();
              psRenderer.write(PDFNumber.doubleOut(1000 * lw) + " setlinewidth");
  
              float ml = bs.getMiterLimit();
              psRenderer.write(PDFNumber.doubleOut(1000 * ml) + " setmiterlimit");  
          }
      }
  
      /**
       * Renders a {@link RenderedImage},
       * applying a transform from image
       * space into user space before drawing.
       * The transformation from user space into device space is done with
       * the current <code>Transform</code> in the <code>Graphics2D</code>.
       * The specified transformation is applied to the image before the
       * transform attribute in the <code>Graphics2D</code> context is applied.
       * The rendering attributes applied include the <code>Clip</code>,
       * <code>Transform</code>, and <code>Composite</code> attributes. Note
       * that no rendering is done if the specified transform is
       * noninvertible.
       * @param img the image to be rendered
       * @param xform the transformation from image space into user space
       * @see #transform
       * @see #setTransform
       * @see #setComposite
       * @see #clip
       * @see #setClip
       */
      public void drawRenderedImage(RenderedImage img,
                                    AffineTransform xform) {
          System.out.println("drawRenderedImage");
      }
  
  
      /**
       * Renders a
       * {@link RenderableImage},
       * applying a transform from image space into user space before drawing.
       * The transformation from user space into device space is done with
       * the current <code>Transform</code> in the <code>Graphics2D</code>.
       * The specified transformation is applied to the image before the
       * transform attribute in the <code>Graphics2D</code> context is applied.
       * The rendering attributes applied include the <code>Clip</code>,
       * <code>Transform</code>, and <code>Composite</code> attributes. Note
       * that no rendering is done if the specified transform is
       * noninvertible.
       *<p>
       * Rendering hints set on the <code>Graphics2D</code> object might
       * be used in rendering the <code>RenderableImage</code>.
       * If explicit control is required over specific hints recognized by a
       * specific <code>RenderableImage</code>, or if knowledge of which hints
       * are used is required, then a <code>RenderedImage</code> should be
       * obtained directly from the <code>RenderableImage</code>
       * and rendered using
       *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.
       * @param img the image to be rendered
       * @param xform the transformation from image space into user space
       * @see #transform
       * @see #setTransform
       * @see #setComposite
       * @see #clip
       * @see #setClip
       * @see #drawRenderedImage
       */
      public void drawRenderableImage(RenderableImage img,
                                      AffineTransform xform) {
          System.out.println("drawRenderableImage");
      }
  
      /**
       * Renders the text specified by the specified <code>String</code>,
       * using the current <code>Font</code> and <code>Paint</code> attributes
       * in the <code>Graphics2D</code> context.
       * The baseline of the first character is at position
       * (<i>x</i>,&nbsp;<i>y</i>) in the User Space.
       * The rendering attributes applied include the <code>Clip</code>,
       * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
       * <code>Composite</code> attributes. For characters in script systems
       * such as Hebrew and Arabic, the glyphs can be rendered from right to
       * left, in which case the coordinate supplied is the location of the
       * leftmost character on the baseline.
       * @param s the <code>String</code> to be rendered
       * @param x,&nbsp;y the coordinates where the <code>String</code>
       * should be rendered
       * @see #setPaint
       * @see java.awt.Graphics#setColor
       * @see java.awt.Graphics#setFont
       * @see #setTransform
       * @see #setComposite
       * @see #setClip
       */
      public void drawString(String s, float x, float y) {
          System.out.println("drawString(String)");
          psRenderer.write("BT");
        Shape imclip = getClip();
        writeClip(imclip);
          Color c = getColor();
          psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue() + " 
setrgbcolor");
  
          AffineTransform trans = getTransform();
          trans.translate(x, y);
          double[] vals = new double[6];
          trans.getMatrix(vals);
  
          psRenderer.write(PDFNumber.doubleOut(vals[0]) + " " + 
PDFNumber.doubleOut(vals[1]) + " "
  + PDFNumber.doubleOut(vals[2]) + " " + PDFNumber.doubleOut(vals[3]) + " " + 
PDFNumber.doubleOut(vals[4])
  + " " + PDFNumber.doubleOut(vals[5]) + " " +
                             PDFNumber.doubleOut(vals[6]) + " Tm [" + s + "]");
  
          psRenderer.write("ET");
      }
  
      /**
       * Renders the text of the specified iterator, using the
       * <code>Graphics2D</code> context's current <code>Paint</code>. The
       * iterator must specify a font
       * for each character. The baseline of the
       * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in the
       * User Space.
       * The rendering attributes applied include the <code>Clip</code>,
       * <code>Transform</code>, <code>Paint</code>, and
       * <code>Composite</code> attributes.
       * For characters in script systems such as Hebrew and Arabic,
       * the glyphs can be rendered from right to left, in which case the
       * coordinate supplied is the location of the leftmost character
       * on the baseline.
       * @param iterator the iterator whose text is to be rendered
       * @param x,&nbsp;y the coordinates where the iterator's text is to be
       * rendered
       * @see #setPaint
       * @see java.awt.Graphics#setColor
       * @see #setTransform
       * @see #setComposite
       * @see #setClip
       */
      public void drawString(AttributedCharacterIterator iterator,
                             float x, float y) {
          System.err.println("drawString(AttributedCharacterIterator)");
  
          psRenderer.write("BT");
        Shape imclip = getClip();
        writeClip(imclip);
          Color c = getColor();
          currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
          psRenderer.write(currentColour.getColorSpaceOut(true));
          c = getBackground();
          PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
          psRenderer.write(col.getColorSpaceOut(false));
  
          AffineTransform trans = getTransform();
          trans.translate(x, y);
          double[] vals = new double[6];
          trans.getMatrix(vals);
  
          for(char ch = iterator.first(); ch != CharacterIterator.DONE; ch = 
iterator.next()) {
              Map attr = iterator.getAttributes();
  
              psRenderer.write(PDFNumber.doubleOut(vals[0]) + " " + 
PDFNumber.doubleOut(vals[1]) + " "
  + PDFNumber.doubleOut(vals[2]) + " " + PDFNumber.doubleOut(vals[3]) + " " + 
PDFNumber.doubleOut(vals[4])
  + " " + PDFNumber.doubleOut(vals[5]) + " " +
                             PDFNumber.doubleOut(vals[6]) + " Tm [" + ch + "]");
          }
  
          psRenderer.write("ET");
      }
  
      /**
       * Fills the interior of a <code>Shape</code> using the settings of the
       * <code>Graphics2D</code> context. The rendering attributes applied
       * include the <code>Clip</code>, <code>Transform</code>,
       * <code>Paint</code>, and <code>Composite</code>.
       * @param s the <code>Shape</code> to be filled
       * @see #setPaint
       * @see java.awt.Graphics#setColor
       * @see #transform
       * @see #setTransform
       * @see #setComposite
       * @see #clip
       * @see #setClip
       */
      public void fill(Shape s) {
          //System.err.println("fill");
              psRenderer.write("gsave");
                        Shape imclip = getClip();
                        writeClip(imclip);
          Color c = getColor();
          psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue() + " 
setrgbcolor");
  
          applyPaint(getPaint(), true);
  
          psRenderer.write("newpath");
          PathIterator iter = s.getPathIterator(getTransform());
          while (!iter.isDone()) {
              double vals[] = new double[6];
              int type = iter.currentSegment(vals);
              switch (type) {
                  case PathIterator.SEG_CUBICTO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" " +
                                          PDFNumber.doubleOut(1000 * vals[2]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[3]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[4]) + " " +
                                          PDFNumber.doubleOut(1000 * vals[5]) + " 
curveto");
                      break;
                  case PathIterator.SEG_LINETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" lineto");
                      break;
                  case PathIterator.SEG_MOVETO:
                      psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) +
                                          " " + PDFNumber.doubleOut(1000 * vals[1]) + 
" M");
                      break;
                  case PathIterator.SEG_QUADTO:
                      //psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
                      //                    " " + 1000 * PDFNumber.doubleOut(vals[1]) 
+ " " +
                      //                    1000 * PDFNumber.doubleOut(vals[2]) + " " +
                      //                    1000 * PDFNumber.doubleOut(vals[3]) + " 
y\n");
                      break;
                  case PathIterator.SEG_CLOSE:
                      psRenderer.write("closepath");
                      break;
                  default:
                      break;
              }
              iter.next();
          }
          doDrawing(true, false,
                    iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
              psRenderer.write("grestore");
      }
  
      protected void doDrawing(boolean fill, boolean stroke,
                               boolean nonzero) {
          if (fill) {
              if (stroke) {
                  if (!nonzero)
                      psRenderer.write("stroke");
                  else
                      psRenderer.write("stroke");
              } else {
                  if (!nonzero)
                      psRenderer.write("fill");
                  else
                      psRenderer.write("fill");
              }
          } else {
              //if(stroke)
              psRenderer.write("stroke");
          }
      }
  
      /**
       * Returns the device configuration associated with this
       * <code>Graphics2D</code>.
       */
      public GraphicsConfiguration getDeviceConfiguration() {
          //System.out.println("getDeviceConviguration");
          return GraphicsEnvironment.getLocalGraphicsEnvironment().
                 getDefaultScreenDevice().getDefaultConfiguration();
      }
  
      /**
       * Used to create proper font metrics
       */
      private Graphics2D fmg;
  
      {
          BufferedImage bi =
            new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
  
          fmg = bi.createGraphics();
      }
  
      /**
       * Gets the font metrics for the specified font.
       * @return    the font metrics for the specified font.
       * @param     f the specified font
       * @see       java.awt.Graphics#getFont
       * @see       java.awt.FontMetrics
       * @see       java.awt.Graphics#getFontMetrics()
       */
      public FontMetrics getFontMetrics(Font f) {
          return fmg.getFontMetrics(f);
      }
  
      /**
       * Sets the paint mode of this graphics context to alternate between
       * this graphics context's current color and the new specified color.
       * This specifies that logical pixel operations are performed in the
       * XOR mode, which alternates pixels between the current color and
       * a specified XOR color.
       * <p>
       * When drawing operations are performed, pixels which are the
       * current color are changed to the specified color, and vice versa.
       * <p>
       * Pixels that are of colors other than those two colors are changed
       * in an unpredictable but reversible manner; if the same figure is
       * drawn twice, then all pixels are restored to their original values.
       * @param     c1 the XOR alternation color
       */
      public void setXORMode(Color c1) {
          System.out.println("setXORMode");
      }
  
  
      /**
       * Copies an area of the component by a distance specified by
       * <code>dx</code> and <code>dy</code>. From the point specified
       * by <code>x</code> and <code>y</code>, this method
       * copies downwards and to the right.  To copy an area of the
       * component to the left or upwards, specify a negative value for
       * <code>dx</code> or <code>dy</code>.
       * If a portion of the source rectangle lies outside the bounds
       * of the component, or is obscured by another window or component,
       * <code>copyArea</code> will be unable to copy the associated
       * pixels. The area that is omitted can be refreshed by calling
       * the component's <code>paint</code> method.
       * @param       x the <i>x</i> coordinate of the source rectangle.
       * @param       y the <i>y</i> coordinate of the source rectangle.
       * @param       width the width of the source rectangle.
       * @param       height the height of the source rectangle.
       * @param       dx the horizontal distance to copy the pixels.
       * @param       dy the vertical distance to copy the pixels.
       */
      public void copyArea(int x, int y, int width, int height, int dx,
                           int dy) {
          System.out.println("copyArea");
      }
  
  }
  
  
  

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

Reply via email to