You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2002/06/07 22:12:35 UTC

cvs commit: xml-fop/src/org/apache/fop/render/pdf PDFRenderer.java

jeremias    2002/06/07 13:12:35

  Modified:    src/org/apache/fop/render/pdf Tag: fop-0_20_2-maintain
                        PDFRenderer.java
  Log:
  Removed Tc that were inserted in [...] TJ commands. (Bug 9054)
  Instead, fixed letter-spacing.
  Completed javadocs
  Pretty-print using JRefactory (I hope I got the settings right. Otherwise, please tell me.)
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.91.2.4  +324 -276  xml-fop/src/org/apache/fop/render/pdf/PDFRenderer.java
  
  Index: PDFRenderer.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/pdf/PDFRenderer.java,v
  retrieving revision 1.91.2.3
  retrieving revision 1.91.2.4
  diff -u -r1.91.2.3 -r1.91.2.4
  --- PDFRenderer.java	8 May 2002 15:18:48 -0000	1.91.2.3
  +++ PDFRenderer.java	7 Jun 2002 20:12:35 -0000	1.91.2.4
  @@ -1,10 +1,9 @@
   /*
  - * $Id: PDFRenderer.java,v 1.91.2.3 2002/05/08 15:18:48 chrisg Exp $
  + * $Id: PDFRenderer.java,v 1.91.2.4 2002/06/07 20:12:35 jeremias 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.pdf;
   
   // FOP
  @@ -49,16 +48,17 @@
   import java.awt.Dimension;
   
   /**
  - * Renderer that renders areas to PDF
  + * <p>
  + *
  + * Renderer that renders areas to PDF.</p> <p>
    *
  - * Modified by Mark Lillywhite, mark-fop@inomial.com to use the
  - * new Renderer interface. The PDF renderer is by far the trickiest
  - * renderer and the best supported by FOP. It also required some
  - * reworking in the way that Pages, Catalogs and the Root object
  - * were written to the stream. The output document should now still
  - * be a 100% compatible PDF document, but hte order of the document
  - * writing is significantly different. See also the changes
  - * to PDFPage, PDFPages and PDFRoot.
  + * Modified by Mark Lillywhite, mark-fop@inomial.com to use the new Renderer
  + * interface. The PDF renderer is by far the trickiest renderer and the best
  + * supported by FOP. It also required some reworking in the way that Pages,
  + * Catalogs and the Root object were written to the stream. The output document
  + * should now still be a 100% compatible PDF document, but the order of the
  + * document writing is significantly different. See also the changes to
  + * PDFPage, PDFPages and PDFRoot.</p>
    */
   public class PDFRenderer extends PrintRenderer {
   
  @@ -89,25 +89,27 @@
   
       PDFColor currentColor;
   
  +    float currentLetterSpacing = Float.NaN;
  +
       /**
        * true if a TJ command is left to be written
        */
       boolean textOpen = false;
   
       /**
  -     * the previous Y coordinate of the last word written.
  -     * Used to decide if we can draw the next word on the same line.
  +     * the previous Y coordinate of the last word written. Used to decide if we
  +     * can draw the next word on the same line.
        */
       int prevWordY = 0;
   
       /**
  -     * the previous X coordinate of the last word written.
  -     * used to calculate how much space between two words
  +     * the previous X coordinate of the last word written. used to calculate
  +     * how much space between two words
        */
       int prevWordX = 0;
   
       /**
  -     * The  width of the previous word. Used to calculate space between
  +     * The width of the previous word. Used to calculate space between
        */
       int prevWordWidth = 0;
   
  @@ -132,6 +134,8 @@
   
       /**
        * set up renderer options
  +     *
  +     * @param options  Options for the renderer
        */
       public void setOptions(Hashtable options) {
           this.options = options;
  @@ -140,19 +144,31 @@
       /**
        * set the PDF document's producer
        *
  -     * @param producer string indicating application producing PDF
  +     * @param producer  string indicating application producing PDF
        */
       public void setProducer(String producer) {
           this.pdfDoc.setProducer(producer);
       }
   
  +    /**
  +     * Starts the renderer
  +     *
  +     * @param stream           OutputStream to be written to
  +     * @exception IOException  In case of an IO problem
  +     */
       public void startRenderer(OutputStream stream)
  -    throws IOException {
  +        throws IOException {
           pdfDoc.outputHeader(stream);
       }
   
  +    /**
  +     * Called when the renderer has finished its work
  +     *
  +     * @param stream           OutputStream to be written to
  +     * @exception IOException  In cas of an IO problem
  +     */
       public void stopRenderer(OutputStream stream)
  -    throws IOException {
  +        throws IOException {
           renderRootExtensions(extensions);
           FontSetup.addToResources(this.pdfDoc, fontInfo);
           pdfDoc.outputTrailer(stream);
  @@ -171,220 +187,217 @@
       /**
        * add a line to the current stream
        *
  -     * @param x1 the start x location in millipoints
  -     * @param y1 the start y location in millipoints
  -     * @param x2 the end x location in millipoints
  -     * @param y2 the end y location in millipoints
  -     * @param th the thickness in millipoints
  -     * @param r the red component
  -     * @param g the green component
  -     * @param b the blue component
  +     * @param x1      the start x location in millipoints
  +     * @param y1      the start y location in millipoints
  +     * @param x2      the end x location in millipoints
  +     * @param y2      the end y location in millipoints
  +     * @param th      the thickness in millipoints
  +     * @param stroke  the stroke color/gradient
        */
       protected void addLine(int x1, int y1, int x2, int y2, int th,
  -                           PDFPathPaint stroke) {
  +            PDFPathPaint stroke) {
           closeText();
   
           currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false)
  -                          + (x1 / 1000f) + " " + (y1 / 1000f) + " m "
  -                          + (x2 / 1000f) + " " + (y2 / 1000f) + " l "
  -                          + (th / 1000f) + " w S\n" + "Q\nBT\n");
  +                + (x1 / 1000f) + " " + (y1 / 1000f) + " m "
  +                + (x2 / 1000f) + " " + (y2 / 1000f) + " l "
  +                + (th / 1000f) + " w S\n" + "Q\nBT\n");
       }
   
       /**
        * add a line to the current stream
        *
  -     * @param x1 the start x location in millipoints
  -     * @param y1 the start y location in millipoints
  -     * @param x2 the end x location in millipoints
  -     * @param y2 the end y location in millipoints
  -     * @param th the thickness in millipoints
  -     * @param rs the rule style
  -     * @param r the red component
  -     * @param g the green component
  -     * @param b the blue component
  +     * @param x1      the start x location in millipoints
  +     * @param y1      the start y location in millipoints
  +     * @param x2      the end x location in millipoints
  +     * @param y2      the end y location in millipoints
  +     * @param th      the thickness in millipoints
  +     * @param rs      the rule style
  +     * @param stroke  the stroke color/gradient
        */
       protected void addLine(int x1, int y1, int x2, int y2, int th, int rs,
  -                           PDFPathPaint stroke) {
  +            PDFPathPaint stroke) {
           closeText();
           currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false)
  -                          + setRuleStylePattern(rs) + (x1 / 1000f) + " "
  -                          + (y1 / 1000f) + " m " + (x2 / 1000f) + " "
  -                          + (y2 / 1000f) + " l " + (th / 1000f) + " w S\n"
  -                          + "Q\nBT\n");
  +                + setRuleStylePattern(rs) + (x1 / 1000f) + " "
  +                + (y1 / 1000f) + " m " + (x2 / 1000f) + " "
  +                + (y2 / 1000f) + " l " + (th / 1000f) + " w S\n"
  +                + "Q\nBT\n");
       }
   
       /**
        * add a rectangle to the current stream
        *
  -     * @param x the x position of left edge in millipoints
  -     * @param y the y position of top edge in millipoints
  -     * @param w the width in millipoints
  -     * @param h the height in millipoints
  -     * @param stroke the stroke color/gradient
  +     * @param x       the x position of left edge in millipoints
  +     * @param y       the y position of top edge in millipoints
  +     * @param w       the width in millipoints
  +     * @param h       the height in millipoints
  +     * @param stroke  the stroke color/gradient
        */
       protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke) {
           closeText();
           currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false)
  -                          + (x / 1000f) + " " + (y / 1000f) + " "
  -                          + (w / 1000f) + " " + (h / 1000f) + " re s\n"
  -                          + "Q\nBT\n");
  +                + (x / 1000f) + " " + (y / 1000f) + " "
  +                + (w / 1000f) + " " + (h / 1000f) + " re s\n"
  +                + "Q\nBT\n");
       }
   
       /**
        * add a filled rectangle to the current stream
        *
  -     * @param x the x position of left edge in millipoints
  -     * @param y the y position of top edge in millipoints
  -     * @param w the width in millipoints
  -     * @param h the height in millipoints
  -     * @param fill the fill color/gradient
  -     * @param stroke the stroke color/gradient
  +     * @param x       the x position of left edge in millipoints
  +     * @param y       the y position of top edge in millipoints
  +     * @param w       the width in millipoints
  +     * @param h       the height in millipoints
  +     * @param fill    the fill color/gradient
  +     * @param stroke  the stroke color/gradient
        */
       protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke,
  -                           PDFPathPaint fill) {
  +            PDFPathPaint fill) {
           closeText();
           currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true)
  -                          + stroke.getColorSpaceOut(false) + (x / 1000f)
  -                          + " " + (y / 1000f) + " " + (w / 1000f) + " "
  -                          + (h / 1000f) + " re b\n" + "Q\nBT\n");
  +                + stroke.getColorSpaceOut(false) + (x / 1000f)
  +                + " " + (y / 1000f) + " " + (w / 1000f) + " "
  +                + (h / 1000f) + " re b\n" + "Q\nBT\n");
       }
   
       /**
        * add a filled rectangle to the current stream
        *
  -     * @param x the x position of left edge in millipoints
  -     * @param y the y position of top edge in millipoints
  -     * @param w the width in millipoints
  -     * @param h the height in millipoints
  -     * @param fill the fill color/gradient
  +     * @param x     the x position of left edge in millipoints
  +     * @param y     the y position of top edge in millipoints
  +     * @param w     the width in millipoints
  +     * @param h     the height in millipoints
  +     * @param fill  the fill color/gradient
        */
       protected void addFilledRect(int x, int y, int w, int h,
  -                                 PDFPathPaint fill) {
  +            PDFPathPaint fill) {
           closeText();
           currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true)
  -                          + (x / 1000f) + " " + (y / 1000f) + " "
  -                          + (w / 1000f) + " " + (h / 1000f) + " re f\n"
  -                          + "Q\nBT\n");
  +                + (x / 1000f) + " " + (y / 1000f) + " "
  +                + (w / 1000f) + " " + (h / 1000f) + " re f\n"
  +                + "Q\nBT\n");
       }
   
       /**
  -     * Renders an image, scaling it to the given width and height.
  -     * If the scaled width and height is the same intrinsic size
  -     * of the image, the image is not scaled.
  -     * 
  -     * @param x the x position of left edge in millipoints
  -     * @param y the y position of top edge in millipoints
  -     * @param w the width in millipoints
  -     * @param h the height in millipoints
  -     * @param image the image to be rendered
  -     * @param fs the font state to use when rendering text
  -     *           in non-bitmapped images.
  +     * Renders an image, scaling it to the given width and height. If the
  +     * scaled width and height is the same intrinsic size of the image, the
  +     * image is not scaled.
  +     *
  +     * @param x      the x position of left edge in millipoints
  +     * @param y      the y position of top edge in millipoints
  +     * @param w      the width in millipoints
  +     * @param h      the height in millipoints
  +     * @param image  the image to be rendered
  +     * @param fs     the font state to use when rendering text in non-bitmapped
  +     *      images.
        */
       protected void drawImageScaled(int x, int y, int w, int h,
  -				   FopImage image,
  -				   FontState fs) {
  -	if (image instanceof SVGImage) {
  -	    try {
  -		closeText();
  -  
  -		SVGDocument svg = ((SVGImage)image).getSVGDocument();
  -		currentStream.add("ET\nq\n");
  -		renderSVGDocument(svg, x, y, fs);
  -		currentStream.add("Q\nBT\n");
  -	    } catch (FopImageException e) {}
  -  
  -	} else {
  -	    int xObjectNum = this.pdfDoc.addImage(image);
  -	    closeText();
  -	    currentStream.add("ET\nq\n" + (((float)w) / 1000f) + " 0 0 "
  -			      + (((float)h) / 1000f) + " "
  -			      + (((float)x) / 1000f) + " "
  -			      + (((float)y - h) / 1000f) + " cm\n" + "/Im"
  -			      + xObjectNum + " Do\nQ\nBT\n");
  -	}
  -    }
  - 
  -    /**
  -     * Renders an image, clipping it as specified. 
  -     * 
  -     * @param x the x position of left edge in millipoints.
  -     * @param y the y position of top edge in millipoints.
  -     * @param clipX the left edge of the clip in millipoints
  -     * @param clipY the top edge of the clip in millipoints
  -     * @param clipW the clip width in millipoints
  -     * @param clipH the clip height in millipoints
  -     * @param fill the image to be rendered
  -     * @param fs the font state to use when rendering text
  -     *           in non-bitmapped images.
  +            FopImage image,
  +            FontState fs) {
  +        if (image instanceof SVGImage) {
  +            try {
  +                closeText();
  +
  +                SVGDocument svg = ((SVGImage) image).getSVGDocument();
  +                currentStream.add("ET\nq\n");
  +                renderSVGDocument(svg, x, y, fs);
  +                currentStream.add("Q\nBT\n");
  +            } catch (FopImageException e) {}
  +
  +        } else {
  +            int xObjectNum = this.pdfDoc.addImage(image);
  +            closeText();
  +            currentStream.add("ET\nq\n" + (((float) w) / 1000f) + " 0 0 "
  +                    + (((float) h) / 1000f) + " "
  +                    + (((float) x) / 1000f) + " "
  +                    + (((float) y - h) / 1000f) + " cm\n" + "/Im"
  +                    + xObjectNum + " Do\nQ\nBT\n");
  +        }
  +    }
  +
  +    /**
  +     * Renders an image, clipping it as specified.
  +     *
  +     * @param x      the x position of left edge in millipoints.
  +     * @param y      the y position of top edge in millipoints.
  +     * @param clipX  the left edge of the clip in millipoints
  +     * @param clipY  the top edge of the clip in millipoints
  +     * @param clipW  the clip width in millipoints
  +     * @param clipH  the clip height in millipoints
  +     * @param fs     the font state to use when rendering text in non-bitmapped
  +     *      images.
  +     * @param image  the image to be painted
        */
       protected void drawImageClipped(int x, int y,
  -				    int clipX, int clipY,
  -				    int clipW, int clipH,
  -				    FopImage image,
  -				    FontState fs) {
  -	
  -	float cx1 = ((float)x) / 1000f;
  -	float cy1 = ((float)y - clipH) / 1000f;
  -	
  -	float cx2 = ((float)x + clipW) / 1000f;
  -	float cy2 = ((float)y) / 1000f;
  -
  -	int imgX = x - clipX;
  -	int imgY = y - clipY;
  -
  -	int imgW;
  -	int imgH;
  -	try {
  -	    // XXX: do correct unit conversion here..
  -	    imgW = image.getWidth() * 1000;
  -	    imgH = image.getHeight() * 1000;
  -	}
  -	catch (FopImageException fie) {
  -	    log.error("Error obtaining image width and height", fie);
  -	    return;
  -	}
  -
  -	if (image instanceof SVGImage) {
  -	    try {
  -		closeText();
  -  
  -		SVGDocument svg = ((SVGImage)image).getSVGDocument();
  -		currentStream.add("ET\nq\n" +
  -		                  // clipping
  -		                  cx1 + " " + cy1 + " m\n" +
  -				  cx2 + " " + cy1 + " l\n" +
  -				  cx2 + " " + cy2 + " l\n" +
  -				  cx1 + " " + cy2 + " l\n" +	
  -				  "W\n" +
  -				  "n\n");
  -		renderSVGDocument(svg, imgX, imgY, fs);
  -		currentStream.add("Q\nBT\n");
  -	    } catch (FopImageException e) {}
  -  
  -	} else {
  -	    int xObjectNum = this.pdfDoc.addImage(image);
  -	    closeText();
  -	    currentStream.add("ET\nq\n" +
  - 			      // clipping
  -			      cx1 + " " + cy1 + " m\n" +
  -			      cx2 + " " + cy1 + " l\n" +
  -			      cx2 + " " + cy2 + " l\n" +
  -			      cx1 + " " + cy2 + " l\n" +	
  -		              "W\n" +
  - 		              "n\n" +
  -			      // image matrix
  -			      (((float)imgW) / 1000f) + " 0 0 " +
  -			      (((float)imgH) / 1000f) + " " +
  -		              (((float)imgX) / 1000f) + " " +
  -			      (((float)imgY - imgH) / 1000f) + " cm\n" +
  -			      "s\n" +
  -			      // the image itself
  -			      "/Im" + xObjectNum + " Do\nQ\nBT\n");
  -	}
  +            int clipX, int clipY,
  +            int clipW, int clipH,
  +            FopImage image,
  +            FontState fs) {
  +
  +        float cx1 = ((float) x) / 1000f;
  +        float cy1 = ((float) y - clipH) / 1000f;
  +
  +        float cx2 = ((float) x + clipW) / 1000f;
  +        float cy2 = ((float) y) / 1000f;
  +
  +        int imgX = x - clipX;
  +        int imgY = y - clipY;
  +
  +        int imgW;
  +        int imgH;
  +        try {
  +            // XXX: do correct unit conversion here..
  +            imgW = image.getWidth() * 1000;
  +            imgH = image.getHeight() * 1000;
  +        } catch (FopImageException fie) {
  +            log.error("Error obtaining image width and height", fie);
  +            return;
  +        }
  +
  +        if (image instanceof SVGImage) {
  +            try {
  +                closeText();
  +
  +                SVGDocument svg = ((SVGImage) image).getSVGDocument();
  +                currentStream.add("ET\nq\n" +
  +                // clipping
  +                        cx1 + " " + cy1 + " m\n" +
  +                        cx2 + " " + cy1 + " l\n" +
  +                        cx2 + " " + cy2 + " l\n" +
  +                        cx1 + " " + cy2 + " l\n" +
  +                        "W\n" +
  +                        "n\n");
  +                renderSVGDocument(svg, imgX, imgY, fs);
  +                currentStream.add("Q\nBT\n");
  +            } catch (FopImageException e) {}
  +
  +        } else {
  +            int xObjectNum = this.pdfDoc.addImage(image);
  +            closeText();
  +            currentStream.add("ET\nq\n" +
  +            // clipping
  +                    cx1 + " " + cy1 + " m\n" +
  +                    cx2 + " " + cy1 + " l\n" +
  +                    cx2 + " " + cy2 + " l\n" +
  +                    cx1 + " " + cy2 + " l\n" +
  +                    "W\n" +
  +                    "n\n" +
  +            // image matrix
  +                    (((float) imgW) / 1000f) + " 0 0 " +
  +                    (((float) imgH) / 1000f) + " " +
  +                    (((float) imgX) / 1000f) + " " +
  +                    (((float) imgY - imgH) / 1000f) + " cm\n" +
  +                    "s\n" +
  +            // the image itself
  +                    "/Im" + xObjectNum + " Do\nQ\nBT\n");
  +        }
       }
  -  
  +
       /**
        * render a foreign object area
  +     *
  +     * @param area  the foreign object area to be rendered
        */
       public void renderForeignObjectArea(ForeignObjectArea area) {
           // if necessary need to scale and align the content
  @@ -451,7 +464,7 @@
       /**
        * render SVG area to PDF
        *
  -     * @param area the SVG area to render
  +     * @param area  the SVG area to render
        */
       public void renderSVGArea(SVGArea area) {
           // place at the current instream offset
  @@ -460,20 +473,30 @@
           renderSVGDocument(area.getSVGDocument(), x, y, area.getFontState());
       }
   
  +    /**
  +     * render SVG document to PDF
  +     *
  +     * @param doc  the document to render
  +     * @param x    the x offset
  +     * @param y    the y offset
  +     * @param fs   the fontstate to use
  +     */
       protected void renderSVGDocument(Document doc, int x, int y,
  -                                     FontState fs) {
  -        float sx = 1, sy = -1;
  -        int xOffset = x, yOffset = y;
  +            FontState fs) {
  +        float sx = 1;
  +        float sy = -1;
  +        int xOffset = x;
  +        int yOffset = y;
   
           org.apache.fop.svg.SVGUserAgent userAgent
  -             = new org.apache.fop.svg.SVGUserAgent(new AffineTransform());
  +                 = new org.apache.fop.svg.SVGUserAgent(new AffineTransform());
           userAgent.setLogger(log);
   
           GVTBuilder builder = new GVTBuilder();
           BridgeContext ctx = new BridgeContext(userAgent);
           TextPainter textPainter = null;
           Boolean bl =
  -            org.apache.fop.configuration.Configuration.getBooleanValue("strokeSVGText");
  +                org.apache.fop.configuration.Configuration.getBooleanValue("strokeSVGText");
           if (bl == null || bl.booleanValue()) {
               textPainter = new StrokingTextPainter();
           } else {
  @@ -482,21 +505,21 @@
           ctx.setTextPainter(textPainter);
   
           PDFAElementBridge aBridge = new PDFAElementBridge();
  -        aBridge.setCurrentTransform(new AffineTransform(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f));
  +        aBridge.setCurrentTransform(new AffineTransform(sx, 0, 0,
  +                sy, xOffset / 1000f, yOffset / 1000f));
           ctx.putBridge(aBridge);
   
  -
           GraphicsNode root;
           try {
               root = builder.build(ctx, doc);
           } catch (Exception e) {
               log.error("svg graphic could not be built: "
  -                                   + e.getMessage(), e);
  +                    + e.getMessage(), e);
               return;
           }
           // get the 'width' and 'height' attributes of the SVG document
  -        float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
  -        float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
  +        float w = (float) ctx.getDocumentSize().getWidth() * 1000f;
  +        float h = (float) ctx.getDocumentSize().getHeight() * 1000f;
           ctx = null;
           builder = null;
   
  @@ -510,7 +533,7 @@
               currentStream.add(x / 1000f + " " + y / 1000f + " m\n");
               currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n");
               currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f
  -                              + " l\n");
  +                    + " l\n");
               currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n");
               currentStream.add("h\n");
               currentStream.add("W\n");
  @@ -520,34 +543,36 @@
           // and positive is down and to the right. (0,0) is where the
           // viewBox puts it.
           currentStream.add(sx + " 0 0 " + sy + " " + xOffset / 1000f + " "
  -                          + yOffset / 1000f + " cm\n");
  +                + yOffset / 1000f + " cm\n");
   
  -        SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
  -        AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, w / 1000f, h / 1000f);
  -        if(!at.isIdentity()) {
  +        SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
  +        AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
  +                w / 1000f, h / 1000f);
  +        if (!at.isIdentity()) {
               double[] vals = new double[6];
               at.getMatrix(vals);
               currentStream.add(PDFNumber.doubleOut(vals[0]) + " "
  -                            + PDFNumber.doubleOut(vals[1]) + " "
  -                            + PDFNumber.doubleOut(vals[2]) + " "
  -                            + PDFNumber.doubleOut(vals[3]) + " "
  -                            + PDFNumber.doubleOut(vals[4]) + " "
  -                            + PDFNumber.doubleOut(vals[5]) + " cm\n");
  +                    + PDFNumber.doubleOut(vals[1]) + " "
  +                    + PDFNumber.doubleOut(vals[2]) + " "
  +                    + PDFNumber.doubleOut(vals[3]) + " "
  +                    + PDFNumber.doubleOut(vals[4]) + " "
  +                    + PDFNumber.doubleOut(vals[5]) + " cm\n");
           }
   
           PDFGraphics2D graphics = new PDFGraphics2D(true, fs, pdfDoc,
  -                                 currentFontName,
  -                                 currentFontSize,
  -                                 currentXPosition,
  -                                 currentYPosition);
  -        graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext());
  +                currentFontName,
  +                currentFontSize,
  +                currentXPosition,
  +                currentYPosition);
  +        graphics.setGraphicContext(
  +                new org.apache.batik.ext.awt.g2d.GraphicContext());
   
           try {
               root.paint(graphics);
               currentStream.add(graphics.getString());
           } catch (Exception e) {
               log.error("svg graphic could not be rendered: "
  -                                   + e.getMessage(), e);
  +                    + e.getMessage(), e);
           }
   
           currentAnnotList = graphics.getAnnotList();
  @@ -558,7 +583,7 @@
       /**
        * render inline area to PDF
        *
  -     * @param area inline area to render
  +     * @param area  inline area to render
        */
       public void renderWordArea(WordArea area) {
           synchronized (_wordAreaPDF) {
  @@ -569,7 +594,7 @@
               boolean kerningAvailable = false;
   
               kerning = area.getFontState().getKerning();
  -            if (kerning != null &&!kerning.isEmpty()) {
  +            if (kerning != null && !kerning.isEmpty()) {
                   kerningAvailable = true;
               }
   
  @@ -578,13 +603,13 @@
   
               // This assumes that *all* CIDFonts use a /ToUnicode mapping
               boolean useMultiByte = false;
  -            Font f =
  -                (Font)area.getFontState().getFontInfo().getFonts().get(name);
  -            if (f instanceof LazyFont){
  -                if(((LazyFont) f).getRealFont() instanceof CIDFont){
  +            Font f = (Font) area.getFontState().
  +                    getFontInfo().getFonts().get(name);
  +            if (f instanceof LazyFont) {
  +                if (((LazyFont) f).getRealFont() instanceof CIDFont) {
                       useMultiByte = true;
                   }
  -            }else if (f instanceof CIDFont){
  +            } else if (f instanceof CIDFont) {
                   useMultiByte = true;
               }
               // String startText = useMultiByte ? "<FEFF" : "(";
  @@ -600,54 +625,56 @@
                   pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n");
               }
   
  +            //Do letter spacing (must be outside of [..] TJ)
  +            float letterspacing =
  +                    ((float) area.getFontState().getLetterSpacing()) / 1000;
  +            if (letterspacing != this.currentLetterSpacing) {
  +                this.currentLetterSpacing = letterspacing;
  +                closeText();
  +                pdf.append(letterspacing).append(" Tc\n");
  +            }
  +
               PDFColor areaColor = null;
               if (this.currentFill instanceof PDFColor) {
  -                areaColor = (PDFColor)this.currentFill;
  +                areaColor = (PDFColor) this.currentFill;
               }
   
  -            if (areaColor == null || areaColor.red() != (double)area.getRed()
  -                    || areaColor.green() != (double)area.getGreen()
  -                    || areaColor.blue() != (double)area.getBlue()) {
  -
  -                areaColor = new PDFColor((double)area.getRed(),
  -                                         (double)area.getGreen(),
  -                                         (double)area.getBlue());
  +            if (areaColor == null || areaColor.red() != (double) area.getRed()
  +                    || areaColor.green() != (double) area.getGreen()
  +                    || areaColor.blue() != (double) area.getBlue()) {
   
  +                areaColor = new PDFColor((double) area.getRed(),
  +                        (double) area.getGreen(),
  +                        (double) area.getBlue());
   
                   closeText();
                   this.currentFill = areaColor;
                   pdf.append(this.currentFill.getColorSpaceOut(true));
               }
   
  -
               int rx = this.currentXPosition;
               int bl = this.currentYPosition;
   
               addWordLines(area, rx, bl, size, areaColor);
   
  -
  -            // Set letterSpacing
  -            float ls = area.getFontState().getLetterSpacing() / this.currentFontSize;
  -            pdf.append(ls).append(" Tc\n");
  -
               if (!textOpen || bl != prevWordY) {
                   closeText();
   
                   pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f)
  -                           + " Tm [" + startText);
  +                        + " Tm [" + startText);
                   prevWordY = bl;
                   textOpen = true;
               } else {
                   // express the space between words in thousandths of an em
                   int space = prevWordX - rx + prevWordWidth;
  -                float emDiff = (float)space / (float)currentFontSize * 1000f;
  +                float emDiff = (float) space / (float) currentFontSize * 1000f;
                   // this prevents a problem in Acrobat Reader where large
                   // numbers cause text to disappear or default to a limit
                   if (emDiff < -33000) {
                       closeText();
   
                       pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f)
  -                               + " Tm [" + startText);
  +                            + " Tm [" + startText);
                       textOpen = true;
                   } else {
                       pdf.append(Float.toString(emDiff));
  @@ -660,7 +687,7 @@
   
               String s;
               if (area.getPageNumberID()
  -                    != null) {    // this text is a page number, so resolve it
  +                    != null) {// this text is a page number, so resolve it
                   s = idReferences.getPageNumber(area.getPageNumberID());
                   if (s == null) {
                       s = "";
  @@ -677,7 +704,7 @@
                   if (!useMultiByte) {
                       if (ch > 127) {
                           pdf.append("\\");
  -                        pdf.append(Integer.toOctalString((int)ch));
  +                        pdf.append(Integer.toOctalString((int) ch));
   
                       } else {
                           switch (ch) {
  @@ -694,11 +721,10 @@
                   }
   
                   if (kerningAvailable && (i + 1) < l) {
  -                    addKerning(pdf, (new Integer((int)ch)),
  -                               (new Integer((int)area.getFontState().mapChar(s.charAt(i + 1)))),
  -                               kerning, startText, endText);
  +                    addKerning(pdf, (new Integer((int) ch)),
  +                            (new Integer((int) area.getFontState().mapChar(s.charAt(i + 1)))),
  +                            kerning, startText, endText);
                   }
  -
               }
               pdf.append(endText);
   
  @@ -711,6 +737,9 @@
   
       /**
        * Convert a char to a multibyte hex representation
  +     *
  +     * @param c  character to be converted
  +     * @return   the string representation of the character
        */
       private String getUnicodeString(char c) {
   
  @@ -718,33 +747,31 @@
   
           byte[] uniBytes = null;
           try {
  -            char[] a = {
  -                c
  -            };
  +            char[] a = {c};
               uniBytes = new String(a).getBytes("UnicodeBigUnmarked");
           } catch (Exception e) {
               // This should never fail
  +            throw new org.apache.avalon.framework.CascadingRuntimeException("Incompatible VM", e);
           }
   
  -
           for (int i = 0; i < uniBytes.length; i++) {
  -            int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i])
  -                    : (int)uniBytes[i];
  +            int b = (uniBytes[i] < 0) ? (int) (256 + uniBytes[i])
  +                    : (int) uniBytes[i];
   
               String hexString = Integer.toHexString(b);
  -            if (hexString.length() == 1)
  +            if (hexString.length() == 1) {
                   buf = buf.append("0" + hexString);
  -            else
  +            } else {
                   buf = buf.append(hexString);
  +            }
           }
   
           return buf.toString();
  -
       }
   
       /**
  -     * Checks to see if we have some text rendering commands open
  -     * still and writes out the TJ command to the stream if we do
  +     * Checks to see if we have some text rendering commands open still and
  +     * writes out the TJ command to the stream if we do
        */
       private void closeText() {
           if (textOpen) {
  @@ -756,21 +783,30 @@
       }
   
       private void addKerning(StringBuffer buf, Integer ch1, Integer ch2,
  -                            Hashtable kerning, String startText,
  -                            String endText) {
  -        Hashtable kernPair = (Hashtable)kerning.get(ch1);
  +            Hashtable kerning, String startText,
  +            String endText) {
  +        Hashtable kernPair = (Hashtable) kerning.get(ch1);
   
           if (kernPair != null) {
  -            Integer width = (Integer)kernPair.get(ch2);
  +            Integer width = (Integer) kernPair.get(ch2);
               if (width != null) {
  -                buf.append(endText).append(-(width.intValue())).append(' ').append(startText);
  +                buf.append(endText).append(-(width.intValue())).
  +                        append(' ').append(startText);
               }
           }
       }
   
   
  +    /**
  +     * render page to PDF
  +     *
  +     * @param page              the page render
  +     * @param outputStream      the target OutputStream
  +     * @exception FOPException  in case of an internal problem
  +     * @exception IOException   in case of an IO problem
  +     */
       public void render(Page page, OutputStream outputStream)
  -    throws FOPException, IOException {
  +        throws FOPException, IOException {
           // log.debug("rendering single page to PDF");
           this.idReferences = page.getIDReferences();
           this.pdfResources = this.pdfDoc.getResources();
  @@ -778,7 +814,7 @@
           this.renderPage(page);
   
           Vector exts = page.getExtensions();
  -        if(exts != null) {
  +        if (exts != null) {
               extensions = exts;
           }
   
  @@ -789,11 +825,14 @@
       /**
        * render page into PDF
        *
  -     * @param page page to render
  +     * @param page  page to render
        */
       public void renderPage(Page page) {
           BodyAreaContainer body;
  -        AreaContainer before, after, start, end;
  +        AreaContainer before;
  +        AreaContainer after;
  +        AreaContainer start;
  +        AreaContainer end;
   
           currentStream = this.pdfDoc.makeStream();
           body = page.getBody();
  @@ -831,27 +870,28 @@
           currentStream.add("ET\n");
   
           currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
  -                                           Math.round(w / 1000),
  -                                           Math.round(h / 1000), page);
  +                Math.round(w / 1000),
  +                Math.round(h / 1000), page);
   
           if (page.hasLinks() || currentAnnotList != null) {
  -            if(currentAnnotList == null) {
  +            if (currentAnnotList == null) {
                   currentAnnotList = this.pdfDoc.makeAnnotList();
               }
               currentPage.setAnnotList(currentAnnotList);
   
               Enumeration e = page.getLinkSets().elements();
               while (e.hasMoreElements()) {
  -                LinkSet linkSet = (LinkSet)e.nextElement();
  +                LinkSet linkSet = (LinkSet) e.nextElement();
   
                   linkSet.align();
                   String dest = linkSet.getDest();
                   int linkType = linkSet.getLinkType();
                   Enumeration f = linkSet.getRects().elements();
                   while (f.hasMoreElements()) {
  -                    LinkedRectangle lrect = (LinkedRectangle)f.nextElement();
  -                    currentAnnotList.addLink(this.pdfDoc.makeLink(lrect.getRectangle(),
  -                                             dest, linkType));
  +                    LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
  +                    currentAnnotList.addLink(
  +                            this.pdfDoc.makeLink(lrect.getRectangle(),
  +                            dest, linkType));
                   }
               }
               currentAnnotList = null;
  @@ -866,6 +906,9 @@
   
       /**
        * defines a string containing dashArray and dashPhase for the rule style
  +     *
  +     * @param style  the rule style
  +     * @return       PDF code to setup the rule style
        */
       private String setRuleStylePattern(int style) {
           String rs = "";
  @@ -888,13 +931,18 @@
           return rs;
       }
   
  +    /**
  +     * render root extensions such as outlines
  +     *
  +     * @param exts  the list of root extensions to process
  +     */
       protected void renderRootExtensions(Vector exts) {
           if (exts != null) {
               Enumeration e = exts.elements();
               while (e.hasMoreElements()) {
  -                ExtensionObj ext = (ExtensionObj)e.nextElement();
  +                ExtensionObj ext = (ExtensionObj) e.nextElement();
                   if (ext instanceof Outline) {
  -                    renderOutline((Outline)ext);
  +                    renderOutline((Outline) ext);
                   }
               }
           }
  @@ -906,19 +954,19 @@
           Outline parent = outline.getParentOutline();
           if (parent == null) {
               pdfOutline =
  -                this.pdfDoc.makeOutline(outlineRoot,
  -                                        outline.getLabel().toString(),
  -                                        outline.getInternalDestination());
  +                    this.pdfDoc.makeOutline(outlineRoot,
  +                    outline.getLabel().toString(),
  +                    outline.getInternalDestination());
           } else {
               PDFOutline pdfParentOutline =
  -                (PDFOutline)parent.getRendererObject();
  +                    (PDFOutline) parent.getRendererObject();
               if (pdfParentOutline == null) {
                   log.error("pdfParentOutline is null");
               } else {
                   pdfOutline =
  -                    this.pdfDoc.makeOutline(pdfParentOutline,
  -                                            outline.getLabel().toString(),
  -                                            outline.getInternalDestination());
  +                        this.pdfDoc.makeOutline(pdfParentOutline,
  +                        outline.getLabel().toString(),
  +                        outline.getInternalDestination());
               }
   
           }
  @@ -928,7 +976,7 @@
           Vector v = outline.getOutlines();
           Enumeration e = v.elements();
           while (e.hasMoreElements()) {
  -            renderOutline((Outline)e.nextElement());
  +            renderOutline((Outline) e.nextElement());
           }
       }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: fop-cvs-help@xml.apache.org