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 2006/05/17 17:06:43 UTC

svn commit: r407277 - in /xmlgraphics/fop/trunk/src: java/org/apache/fop/render/ sandbox/org/apache/fop/render/afp/ sandbox/org/apache/fop/render/pcl/

Author: jeremias
Date: Wed May 17 08:06:42 2006
New Revision: 407277

URL: http://svn.apache.org/viewvc?rev=407277&view=rev
Log:
Several bug fixes in PCLRenderer (border painting mostly).
Option in AbstractGraphics2DAdapter to work with or without alpha.
Text Setup changed to the Java2D model. Custom font painting is now done through Java2D as bitmaps for all fonts which are not supported by the pre-defined set. This was done as a shortcut for full-fledged TrueType support which seems to be a little complicated in PCL. BTW, Microsoft PCL printer drivers do the same, i.e. paint text as bitmaps.
Image printing refined, but my attempt at handling bitmasked images (transparency) didn't work out. While the previewers did the expected thing, the printer hardware flat-out ignored it, so it's disabled now.

Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java Wed May 17 08:06:42 2006
@@ -20,12 +20,18 @@
 
 import java.awt.Color;
 import java.awt.Graphics2D;
+import java.awt.Point;
 import java.awt.RenderingHints;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.Graphics2DImagePainter;
 import org.apache.fop.render.RendererContext.RendererContextWrapper;
@@ -45,14 +51,22 @@
      * @return the generated BufferedImage
      */
     protected BufferedImage paintToBufferedImage(Graphics2DImagePainter painter, 
-             RendererContextWrapper context, int resolution, boolean gray) {
+             RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) {
         int bmw = UnitConv.mpt2px(context.getWidth(), resolution);
         int bmh = UnitConv.mpt2px(context.getHeight(), resolution);
         BufferedImage bi;
         if (gray) {
-            bi = new BufferedImage(bmw, bmh, BufferedImage.TYPE_BYTE_GRAY);
+            if (withAlpha) {
+                bi = createGrayBufferedImageWithAlpha(bmw, bmh);
+            } else {
+                bi = new BufferedImage(bmw, bmh, BufferedImage.TYPE_BYTE_GRAY);
+            }
         } else {
-            bi = new BufferedImage(bmw, bmh, BufferedImage.TYPE_INT_ARGB);
+            if (withAlpha) {
+                bi = new BufferedImage(bmw, bmh, BufferedImage.TYPE_INT_ARGB);
+            } else {
+                bi = new BufferedImage(bmw, bmh, BufferedImage.TYPE_INT_RGB);
+            }
         }
         Graphics2D g2d = bi.createGraphics();
         try {
@@ -62,7 +76,9 @@
             
             g2d.setBackground(Color.white);
             g2d.setColor(Color.black);
-            g2d.clearRect(0, 0, bmw, bmh);
+            if (!withAlpha) {
+                g2d.clearRect(0, 0, bmw, bmh);
+            }
             double sx = (double)bmw / context.getWidth();
             double sy = (double)bmh / context.getHeight();
             g2d.scale(sx, sy);
@@ -74,6 +90,28 @@
         } finally {
             g2d.dispose();
         }
+        return bi;
+    }
+
+    private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) {
+        BufferedImage bi;
+        boolean alphaPremultiplied = true;
+        int bands = 2;
+        int[] bits = new int[bands];
+        for (int i = 0; i < bands; i++) {
+            bits[i] = 8;
+        }
+        ColorModel cm = new ComponentColorModel(
+                ColorSpace.getInstance(ColorSpace.CS_GRAY),
+                bits,
+                true, alphaPremultiplied,
+                Transparency.TRANSLUCENT,
+                DataBuffer.TYPE_BYTE);
+        WritableRaster wr = Raster.createInterleavedRaster(
+                DataBuffer.TYPE_BYTE,
+                width, height, bands,
+                new Point(0, 0));
+        bi = new BufferedImage(cm, wr, alphaPremultiplied, null);
         return bi;
     }
 

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/afp/AFPGraphics2DAdapter.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/afp/AFPGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/afp/AFPGraphics2DAdapter.java Wed May 17 08:06:42 2006
@@ -46,7 +46,7 @@
         
         //Paint to a BufferedImage
         int resolution = (int)Math.round(context.getUserAgent().getTargetResolution());
-        BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, false);
+        BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, false, false);
 
         afp.drawBufferedImage(bi, resolution, x, y, width, height);
     }

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java Wed May 17 08:06:42 2006
@@ -24,17 +24,24 @@
 import java.awt.color.ColorSpace;
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ByteLookupTable;
 import java.awt.image.ColorConvertOp;
 import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
 import java.awt.image.IndexColorModel;
+import java.awt.image.LookupOp;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.util.Locale;
 
+import org.apache.xmlgraphics.image.GraphicsUtil;
+
 /**
  * This class provides methods for generating PCL print files.
  */
@@ -52,6 +59,11 @@
     
     private OutputStream out;
     
+    private boolean currentSourceTransparency = true;
+    private boolean currentPatternTransparency = true;
+    
+    private int maxBitmapResolution = PCL_RESOLUTIONS[PCL_RESOLUTIONS.length - 1];
+    
     /**
      * Main constructor.
      * @param out the OutputStream to write the PCL stream to
@@ -60,11 +72,36 @@
         this.out = out;
     }
     
+    /**
+     * Main constructor.
+     * @param out the OutputStream to write the PCL stream to
+     * @param maxResolution the maximum resolution to encode bitmap images at
+     */
+    public PCLGenerator(OutputStream out, int maxResolution) {
+        this(out);
+        boolean found = false;
+        for (int i = 0; i < PCL_RESOLUTIONS.length; i++) {
+            if (PCL_RESOLUTIONS[i] == maxResolution) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Illegal value for maximum resolution!");
+        }
+        this.maxBitmapResolution = maxResolution;
+    }
+    
     /** @return the OutputStream that this generator writes to */
     public OutputStream getOutputStream() {
         return this.out;
     }
     
+    /** @return the maximum resolution to encode bitmap images at */
+    public int getMaximumBitmapResolution() {
+        return this.maxBitmapResolution;
+    }
+    
     /**
      * Writes a PCL escape command to the output stream.
      * @param cmd the command (without the ESCAPE character)
@@ -218,6 +255,22 @@
     }
 
     /**
+     * Pushes the current cursor position on a stack (stack size: max 20 entries)
+     * @throws IOException In case of an I/O error
+     */
+    public void pushCursorPos() throws IOException {
+        writeCommand("&f0S");
+    }
+    
+    /**
+     * Pops the current cursor position from the stack.
+     * @throws IOException In case of an I/O error
+     */
+    public void popCursorPos() throws IOException {
+        writeCommand("&f1S");
+    }
+    
+    /**
      * Changes the current print direction while maintaining the current cursor position.
      * @param rotate the rotation angle (counterclockwise), one of 0, 90, 180 and 270.
      * @throws IOException In case of an I/O error
@@ -283,16 +336,39 @@
     }
 
     /**
+     * Sets the source transparency mode.
+     * @param transparent true if transparent, false for opaque
+     * @throws IOException In case of an I/O error
+     */
+    public void setSourceTransparencyMode(boolean transparent) throws IOException {
+        setTransparencyMode(transparent, currentPatternTransparency);
+    }
+
+    /**
      * Sets the pattern transparency mode.
      * @param transparent true if transparent, false for opaque
      * @throws IOException In case of an I/O error
      */
     public void setPatternTransparencyMode(boolean transparent) throws IOException {
-        if (transparent) {
-            writeCommand("*v0O");
-        } else {
-            writeCommand("*v1O");
+        setTransparencyMode(currentSourceTransparency, transparent);
+    }
+
+    /**
+     * Sets the transparency modes.
+     * @param source source transparency: true if transparent, false for opaque
+     * @param pattern pattern transparency: true if transparent, false for opaque
+     * @throws IOException In case of an I/O error
+     */
+    public void setTransparencyMode(boolean source, boolean pattern) throws IOException {
+        if (source != currentSourceTransparency && pattern != currentPatternTransparency) {
+            writeCommand("*v" + (source ? '0' : '1') + "n" + (pattern ? '0' : '1') + "O");
+        } else if (source != currentSourceTransparency) {
+            writeCommand("*v" + (source ? '0' : '1') + "N");
+        } else if (pattern != currentPatternTransparency) {
+            writeCommand("*v" + (pattern ? '0' : '1') + "O");
         }
+        this.currentSourceTransparency = source;
+        this.currentPatternTransparency = pattern;
     }
 
     /**
@@ -323,7 +399,9 @@
      * @throws IOException In case of an I/O error
      */
     public void selectCurrentPattern(int patternID, int pattern) throws IOException {
-        writeCommand("*c" + patternID + "G");
+        if (pattern > 1) {
+            writeCommand("*c" + patternID + "G");
+        }
         writeCommand("*v" + pattern + "T");
     }
 
@@ -389,6 +467,7 @@
      * @return the resulting PCL resolution (one of 75, 100, 150, 200, 300, 600)
      */
     private int calculatePCLResolution(int resolution, boolean increased) {
+        int choice = -1;
         for (int i = PCL_RESOLUTIONS.length - 2; i >= 0; i--) {
             if (resolution > PCL_RESOLUTIONS[i]) {
                 int idx = i + 1;
@@ -397,10 +476,18 @@
                 } else if (idx < PCL_RESOLUTIONS.length - 1) {
                     idx += increased ? 1 : 0;
                 }
-                return PCL_RESOLUTIONS[idx];
+                choice = idx;
+                break;
+                //return PCL_RESOLUTIONS[idx];
             }
         }
-        return PCL_RESOLUTIONS[increased ? 2 : 0];
+        if (choice < 0) {
+            choice = (increased ? 2 : 0);
+        }
+        while (choice > 0 && PCL_RESOLUTIONS[choice] > getMaximumBitmapResolution()) {
+            choice--;
+        }
+        return PCL_RESOLUTIONS[choice];
     }
     
     private boolean isValidPCLResolution(int resolution) {
@@ -419,6 +506,60 @@
         }
     }
     
+    //Threshold table to convert an alpha channel (8-bit) into a clip mask (1-bit)
+    private static final byte[] THRESHOLD_TABLE = new byte[256];
+    static { // Initialize the arrays
+        for (int i = 0; i < 256; i++) {
+            THRESHOLD_TABLE[i] = (byte) ((i < 240) ? 255 : 0);
+        }
+    }    
+    
+    private RenderedImage getMask(RenderedImage img, Dimension targetDim) {
+        ColorModel cm = img.getColorModel(); 
+        if (cm.hasAlpha()) {
+            BufferedImage alpha = new BufferedImage(img.getWidth(), img.getHeight(), 
+                    BufferedImage.TYPE_BYTE_GRAY);
+            Raster raster = img.getData();
+            GraphicsUtil.copyBand(raster, cm.getNumColorComponents(), alpha.getRaster(), 0);
+
+            BufferedImageOp op1 = new LookupOp(new ByteLookupTable(0, THRESHOLD_TABLE), null);
+            BufferedImage alphat = op1.filter(alpha, null);
+
+            BufferedImage mask;
+            if (true) {
+                mask = new BufferedImage(targetDim.width, targetDim.height,
+                        BufferedImage.TYPE_BYTE_BINARY);
+            } else {
+                byte[] arr = {(byte)0, (byte)0xff};
+                ColorModel colorModel = new IndexColorModel(1, 2, arr, arr, arr);
+                WritableRaster wraster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
+                                                   targetDim.width, targetDim.height, 1, 1, null);
+                mask = new BufferedImage(colorModel, wraster, false, null);
+            }
+            
+            Graphics2D g2d = mask.createGraphics();
+            try {
+                AffineTransform at = new AffineTransform();
+                double sx = targetDim.getWidth() / img.getWidth();
+                double sy = targetDim.getHeight() / img.getHeight();
+                at.scale(sx, sy);
+                g2d.drawRenderedImage(alphat, at);
+            } finally {
+                g2d.dispose();
+            }
+            /*
+            try {
+                BatchDiffer.saveAsPNG(alpha, new java.io.File("D:/out-alpha.png"));
+                BatchDiffer.saveAsPNG(mask, new java.io.File("D:/out-mask.png"));
+            } catch (IOException e) {
+                e.printStackTrace();
+            }*/
+            return mask;
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Paint a bitmap at the current cursor position. The bitmap is converted to a monochrome
      * (1-bit) bitmap image.
@@ -433,9 +574,21 @@
             Dimension orgDim = new Dimension(img.getWidth(), img.getHeight());
             Dimension effDim = getAdjustedDimension(orgDim, resolution, effResolution);
             boolean scaled = !orgDim.equals(effDim);
+            
+            //Transparency mask disabled. Doesn't work reliably
+            final boolean transparencyDisabled = true;
+            RenderedImage mask = (transparencyDisabled ? null : getMask(img, effDim)); 
+            if (mask != null) {
+                pushCursorPos();
+                selectCurrentPattern(0, 1); //Solid white
+                setTransparencyMode(true, true);
+                paintMonochromeBitmap(mask, effResolution);
+                popCursorPos();
+            }
+            
             BufferedImage src = null;
             if (img instanceof BufferedImage && !scaled) {
-                if (!isGrayscaleImage(img)) {
+                if (!isGrayscaleImage(img) || img.getColorModel().hasAlpha()) {
                     src = new BufferedImage(effDim.width, effDim.height, 
                             BufferedImage.TYPE_BYTE_GRAY);
                     ColorConvertOp op = new ColorConvertOp(
@@ -462,15 +615,16 @@
             MonochromeBitmapConverter converter = createMonochromeBitmapConverter();
             converter.setHint("quality", "false");
 
-            long start = System.currentTimeMillis();
             BufferedImage buf = (BufferedImage)converter.convertToMonochrome(src);
-            long duration = System.currentTimeMillis() - start;
-            System.out.println(duration + " ms");
             
             RenderedImage red = buf;
+            selectCurrentPattern(0, 0); //Solid black
+            setTransparencyMode(mask != null, true);
             paintMonochromeBitmap(red, effResolution);
         } else {
             int effResolution = calculatePCLResolution(resolution);
+            setSourceTransparencyMode(false);
+            selectCurrentPattern(0, 0); //Solid black
             paintMonochromeBitmap(img, effResolution);
         }
     }

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java Wed May 17 08:06:42 2006
@@ -47,6 +47,7 @@
 
 /**
  * Graphics2D implementation implementing PCL and HP GL/2.
+ * Note: This class cannot be used stand-alone to create full PCL documents.
  */
 public class PCLGraphics2D extends AbstractGraphics2D {
 

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java Wed May 17 08:06:42 2006
@@ -64,7 +64,7 @@
         boolean paintAsBitmap = pclContext.paintAsBitmap();
         if (!paintAsBitmap) {
             ByteArrayOutputStream baout = new ByteArrayOutputStream();
-            PCLGenerator tempGen = new PCLGenerator(baout);
+            PCLGenerator tempGen = new PCLGenerator(baout, gen.getMaximumBitmapResolution());
             try {
                 GraphicContext ctx = (GraphicContext)pcl.getGraphicContext().clone();
 
@@ -109,7 +109,7 @@
         if (!painted) {
             //Fallback solution: Paint to a BufferedImage
             int resolution = (int)Math.round(context.getUserAgent().getTargetResolution());
-            BufferedImage bi = paintToBufferedImage(painter, pclContext, resolution, true);
+            BufferedImage bi = paintToBufferedImage(painter, pclContext, resolution, true, false);
 
             pcl.setCursorPos(x, y);
             gen.paintBitmap(bi, resolution);

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java?rev=407277&r1=407276&r2=407277&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java Wed May 17 08:06:42 2006
@@ -23,6 +23,7 @@
 import java.awt.Dimension;
 import java.awt.Graphics2D;
 import java.awt.Rectangle;
+import java.awt.RenderingHints;
 import java.awt.color.ColorSpace;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
@@ -70,6 +71,7 @@
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.extensions.ExtensionElementMapping;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.image.EPSImage;
 import org.apache.fop.image.FopImage;
 import org.apache.fop.image.ImageFactory;
@@ -79,6 +81,8 @@
 import org.apache.fop.render.PrintRenderer;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.RendererContextConstants;
+import org.apache.fop.render.java2d.FontMetricsMapper;
+import org.apache.fop.render.java2d.FontSetup;
 import org.apache.fop.render.java2d.Java2DRenderer;
 import org.apache.fop.traits.BorderProps;
 import org.apache.fop.util.QName;
@@ -140,6 +144,23 @@
     }
 
     /**
+     * @see org.apache.fop.render.Renderer#setupFontInfo(org.apache.fop.fonts.FontInfo)
+     */
+    public void setupFontInfo(FontInfo inFontInfo) {
+        //Don't call super.setupFontInfo() here!
+        //The PCLRenderer uses the Java2D FontSetup which needs a special font setup
+        //create a temp Image to test font metrics on
+        fontInfo = inFontInfo;
+        BufferedImage fontImage = new BufferedImage(100, 100,
+                BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = fontImage.createGraphics();
+        //The next line is important to get accurate font metrics!
+        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
+                RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+        FontSetup.setup(fontInfo, g);
+    }
+
+    /**
      * Central exception handler for I/O exceptions.
      * @param ioe IOException to handle
      */
@@ -160,13 +181,24 @@
         return this.graphicContext;
     }
     
+    /** @return the target resolution */
+    protected int getResolution() {
+        int resolution = (int)Math.round(userAgent.getTargetResolution());
+        if (resolution <= 300) {
+            return 300;
+        } else {
+            return 600;
+        }
+    }
+    
     /**
      * Sets the current font (NOTE: Hard-coded font mappings ATM!)
      * @param name the font name (internal F* names for now)
      * @param size the font size
+     * @return true if the font can be mapped to PCL
      * @throws IOException if an I/O problem occurs
      */
-    public void setFont(String name, float size) throws IOException {
+    public boolean setFont(String name, float size) throws IOException {
         int fontcode = 0;
         if (name.length() > 1 && name.charAt(0) == 'F') {
             try {
@@ -261,20 +293,25 @@
             gen.writeCommand("(s1p" + formattedSize + "v0s0b45101T");
             break;
         default:
-            gen.writeCommand("(0N");
-            gen.writeCommand("(s" + formattedSize + "V");
-            break;
+            //gen.writeCommand("(0N");
+            //gen.writeCommand("(s" + formattedSize + "V");
+            return false;
         }
+        return true;
     }
 
     /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
     public void startRenderer(OutputStream outputStream) throws IOException {
         log.debug("Rendering areas to PCL...");
         this.out = outputStream;
-        this.gen = new PCLGenerator(out);
+        this.gen = new PCLGenerator(out, getResolution());
 
         gen.universalEndOfLanguage();
-        gen.writeText("@PJL JOB NAME = \"" + userAgent.getTitle() + "\"\n");
+        gen.writeText("@PJL COMMENT Produced by " + userAgent.getProducer() + "\n");
+        if (userAgent.getTitle() != null) {
+            gen.writeText("@PJL JOB NAME = \"" + userAgent.getTitle() + "\"\n");
+        }
+        gen.writeText("@PJL SET RESOLUTION = " + getResolution() + "\n");
         gen.writeText("@PJL ENTER LANGUAGE = PCL\n");
         gen.resetPrinter();
     }
@@ -325,8 +362,8 @@
         gen.clearHorizontalMargins();
         gen.setTopMargin(0);
         gen.setVMI(0);
-        gen.setUnitOfMeasure(600);
-        gen.setRasterGraphicsResolution(600);
+        gen.setUnitOfMeasure(getResolution());
+        gen.setRasterGraphicsResolution(getResolution());
     }
 
     /** Saves the current graphics state on the stack. */
@@ -486,35 +523,76 @@
     /**
      * @see org.apache.fop.render.AbstractRenderer#renderText(TextArea)
      */
-    protected void renderText(TextArea area) {
-        //renderInlineAreaBackAndBorders(area);
-        String fontname = getInternalFontNameForArea(area);
-        int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
+    protected void renderText(final TextArea text) {
+        renderInlineAreaBackAndBorders(text);
+        
+        String fontname = getInternalFontNameForArea(text);
+        int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE);
 
         //Determine position
-        //int saveIP = currentIPPosition;
-        //int saveBP = currentBPPosition;
-        int rx = currentIPPosition + area.getBorderAndPaddingWidthStart();
-        int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset();
+        int saveIP = currentIPPosition;
+        int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
+        int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
 
         try {
-            setFont(fontname, fontsize);
-            Color col = (Color)area.getTrait(Trait.COLOR);
-            //this.currentFill = col;
-            if (col != null) {
-                //useColor(ct);
-                gen.setPatternTransparencyMode(false);
-                gen.selectCurrentPattern(gen.convertToPCLShade(col), 2);
+            final Color col = (Color)text.getTrait(Trait.COLOR);
+            boolean pclFont = setFont(fontname, fontsize);
+            if (pclFont) {
+                //this.currentFill = col;
+                if (col != null) {
+                    //useColor(ct);
+                    gen.setTransparencyMode(true, false);
+                    gen.selectCurrentPattern(gen.convertToPCLShade(col), 2);
+                }
+                
+                saveGraphicsState();
+                graphicContext.translate(rx, bl);
+                setCursorPos(0, 0);
+                gen.setTransparencyMode(true, true);
+                
+                super.renderText(text); //Updates IPD and renders words and spaces
+                restoreGraphicsState();
+            } else {
+                //Use Java2D to paint different fonts via bitmap
+                final Font font = getFontFromArea(text);
+                final int baseline = text.getBaselineOffset();
+                
+                //for cursive fonts, so the text isn't clipped
+                int extraWidth = font.getFontSize() / 3;
+                
+                Graphics2DAdapter g2a = getGraphics2DAdapter();
+                final Rectangle paintRect = new Rectangle(
+                        rx, currentBPPosition + text.getOffset(),
+                        text.getIPD() + extraWidth, text.getBPD());
+                RendererContext rc = createRendererContext(paintRect.x, paintRect.y, 
+                        paintRect.width, paintRect.height, null);
+                Map atts = new java.util.HashMap();
+                atts.put(new QName(ExtensionElementMapping.URI, null, "conversion-mode"), "bitmap");
+                rc.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, atts);
+                
+                Graphics2DImagePainter painter = new Graphics2DImagePainter() {
+
+                    public void paint(Graphics2D g2d, Rectangle2D area) {
+                        FontMetricsMapper mapper = (FontMetricsMapper)fontInfo.getMetricsFor(
+                                font.getFontName());
+                        g2d.setFont(mapper.getFont(font.getFontSize()));
+                        g2d.translate(0, baseline);
+                        g2d.scale(1000, 1000);
+                        g2d.setColor(col);
+                        Java2DRenderer.renderText(text, g2d, font);
+                    }
+                    
+                    public Dimension getImageSize() {
+                        return paintRect.getSize();
+                    }
+                    
+                };
+                g2a.paintImage(painter, rc, 
+                        paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+                currentIPPosition = saveIP + text.getAllocIPD();
             }
-            
-            saveGraphicsState();
-            graphicContext.translate(rx, bl);
-            setCursorPos(0, 0);
-        
-            super.renderText(area); //Updates IPD
         
             //renderTextDecoration(tf, fontsize, area, bl, rx);
-            restoreGraphicsState();
         } catch (IOException ioe) {
             handleIOTrouble(ioe);
         }
@@ -583,7 +661,7 @@
     protected void fillRect(float x, float y, float width, float height) {
         try {
             setCursorPos(x * 1000, y * 1000);
-            gen.fillRect((int)width * 1000, (int)height * 1000, 
+            gen.fillRect((int)(width * 1000), (int)(height * 1000), 
                     this.currentFillColor);
         } catch (IOException ioe) {
             handleIOTrouble(ioe);
@@ -625,7 +703,7 @@
         Font font = getFontFromArea(textArea);
         
         int tws = (space.isAdjustable() 
-                ? ((TextArea) space.getParentArea()).getTextWordSpaceAdjust() 
+                ? textArea.getTextWordSpaceAdjust() 
                         + 2 * textArea.getTextLetterSpaceAdjust()
                 : 0);
 
@@ -999,29 +1077,25 @@
         float width = borderRect.width;
         float height = borderRect.height;
         if (bpsBefore != null) {
-            int borderWidth = (int) Math.round((bpsBefore.width / 1000f));
+            float borderWidth = bpsBefore.width / 1000f;
             updateFillColor(bpsBefore.color);
-            fillRect((int) startx, (int) starty, (int) width,
-                    borderWidth);
+            fillRect(startx, starty, width, borderWidth);
         }
         if (bpsAfter != null) {
-            int borderWidth = (int) Math.round((bpsAfter.width / 1000f));
+            float borderWidth = bpsAfter.width / 1000f;
             updateFillColor(bpsAfter.color);
-            fillRect((int) startx,
-                    (int) (starty + height - borderWidth), (int) width,
-                    borderWidth);
+            fillRect(startx, (starty + height - borderWidth), 
+                    width, borderWidth);
         }
         if (bpsStart != null) {
-            int borderWidth = (int) Math.round((bpsStart.width / 1000f));
+            float borderWidth = bpsStart.width / 1000f;
             updateFillColor(bpsStart.color);
-            fillRect((int) startx, (int) starty, borderWidth,
-                    (int) height);
+            fillRect(startx, starty, borderWidth, height);
         }
         if (bpsEnd != null) {
-            int borderWidth = (int) Math.round((bpsEnd.width / 1000f));
+            float borderWidth = bpsEnd.width / 1000f;
             updateFillColor(bpsEnd.color);
-            fillRect((int) (startx + width - borderWidth),
-                    (int) starty, borderWidth, (int) height);
+            fillRect((startx + width - borderWidth), starty, borderWidth, height);
         }
     }
     



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