]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
The PCL Renderer is now mostly operational including reference-orientation but withou...
authorJeremias Maerki <jeremias@apache.org>
Fri, 5 May 2006 13:38:39 +0000 (13:38 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 5 May 2006 13:38:39 +0000 (13:38 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@400075 13f79535-47bb-0310-9956-ffa450edef68

src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java
src/sandbox/org/apache/fop/render/pcl/PCLPageDefinition.java
src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java

index 4e647a977e4ca312c9a008cbd287560b76e5a567..58447f787f29c49ae567788d0587d95662913160 100644 (file)
@@ -135,7 +135,34 @@ public class PCLGenerator {
     public void formFeed() throws IOException {
         out.write(12); //=OC ("FF", Form feed)
     }
+
+    /**
+     * Sets the unit of measure.
+     * @param value the resolution value (units per inch)
+     * @throws IOException In case of an I/O error
+     */
+    public void setUnitOfMeasure(int value) throws IOException {
+        writeCommand("&u" + value + "D");
+    }
+    
+    /**
+     * Sets the raster graphics resolution
+     * @param value the resolution value (units per inch)
+     * @throws IOException In case of an I/O error
+     */
+    public void setRasterGraphicsResolution(int value) throws IOException {
+        writeCommand("*t" + value + "R");
+    }
     
+    /**
+     * Selects the page size.
+     * @param selector the integer representing the page size
+     * @throws IOException In case of an I/O error
+     */
+    public void selectPageSize(int selector) throws IOException {
+        writeCommand("&l" + selector + "A");
+    }
+
     /**
      * Clears the horizontal margins.
      * @throws IOException In case of an I/O error
@@ -154,6 +181,25 @@ public class PCLGenerator {
         writeCommand("&l" + numberOfLines + "E");
     }
 
+    /**
+     * The Text Length command can be used to define the bottom border. See the PCL specification
+     * for details.
+     * @param numberOfLines the number of lines
+     * @throws IOException In case of an I/O error
+     */
+    public void setTextLength(int numberOfLines) throws IOException {
+        writeCommand("&l" + numberOfLines + "F");
+    }
+
+    /**
+     * Sets the Vertical Motion Index (VMI).
+     * @param value the VMI value
+     * @throws IOException In case of an I/O error
+     */
+    public void setVMI(double value) throws IOException {
+        writeCommand("&l" + formatDouble4(value) + "C");
+    }
+
     /**
      * Sets the cursor to a new absolute coordinate.
      * @param x the X coordinate (in millipoints)
@@ -171,6 +217,15 @@ public class PCLGenerator {
         }
     }
 
+    /**
+     * 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
+     */
+    public void changePrintDirection(int rotate) throws IOException {
+        writeCommand("&a" + rotate + "P");
+    }
+    
     /**
      * Enters the HP GL/2 mode.
      * @param restorePreviousHPGL2Cursor true if the previous HP GL/2 pen position should be 
@@ -200,16 +255,14 @@ public class PCLGenerator {
     }
     
     /**
-     * Generate a filled rectangle
+     * Generate a filled rectangle at the current cursor position.
      *
-     * @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 col the fill color
      * @throws IOException In case of an I/O error
      */
-    protected void fillRect(int x, int y, int w, int h, Color col) throws IOException {
+    protected void fillRect(int w, int h, Color col) throws IOException {
         if ((w == 0) || (h == 0)) {
             return;
         }
@@ -219,22 +272,14 @@ public class PCLGenerator {
             //y += h;
         }
 
-        int xpos = (x / 100);
-        if (xpos < 0) {
-            //A negative x coordinate can lead to a displaced rectangle (xpos must be >= 0) 
-            w += x;
-            xpos = 0;
-        }
-        writeCommand("*v1O");
-        writeCommand("&a" + formatDouble4(xpos) + "h" 
-                          + formatDouble4(y / 100) + "V");
+        setPatternTransparencyMode(false);
         writeCommand("*c" + formatDouble4(w / 100) + "h" 
                           + formatDouble4(h / 100) + "V");
         int lineshade = convertToPCLShade(col);
         writeCommand("*c" + lineshade + "G");
         writeCommand("*c2P");
         // Reset pattern transparency mode.
-        writeCommand("*v0O");
+        setPatternTransparencyMode(true);
     }
 
     /**
@@ -441,7 +486,7 @@ public class PCLGenerator {
         if (!isValidPCLResolution(resolution)) {
             throw new IllegalArgumentException("Invalid PCL resolution: " + resolution);
         }
-        writeCommand("*t" + resolution + "R");
+        setRasterGraphicsResolution(resolution);
         writeCommand("*r0f" + img.getHeight() + "t" + img.getWidth() + "s1A");
         Raster raster = img.getData();
         boolean monochrome = isMonochromeImage(img);
index 40a0eddd75ade107ab1dfa75833c1ce002da388e..43978e954f6a30e9f2d0fb450a95cba7364be5ec 100644 (file)
@@ -18,6 +18,8 @@
 
 package org.apache.fop.render.pcl;
 
+import java.awt.Dimension;
+import java.awt.Rectangle;
 import java.util.Iterator;
 import java.util.List;
 
@@ -29,45 +31,63 @@ import org.apache.fop.util.UnitConv;
 public class PCLPageDefinition {
 
     private static List pageDefinitions;
+    private static PCLPageDefinition defaultPageDefinition;
     
     private String name;
-    private long width; //in mpt
-    private long height; //in mpt
-    private int logicalPageXOffset; //in mpt
+    private int selector;
+    private Dimension physicalPageSize;
+    private Rectangle logicalPageRect;
     private boolean landscape;
     
     static {
         createPageDefinitions();
     }
     
-    public PCLPageDefinition(String name, long width, long height, int logicalPageXOffset) {
-        this(name, width, height, logicalPageXOffset, false);
-    }
-    
-    public PCLPageDefinition(String name, long width, long height, int logicalPageXOffset, 
-            boolean landscape) {
+    /**
+     * Main constructor
+     * @param name the name of the page definition
+     * @param selector the selector used by the <ESC>&l#A command (page size)
+     * @param physicalPageSize the physical page size
+     * @param logicalPageRect the rectangle defining the logical page
+     * @param landscape true if it is a landscape format
+     */
+    public PCLPageDefinition(String name, int selector, Dimension physicalPageSize, 
+            Rectangle logicalPageRect, boolean landscape) {
         this.name = name;
-        this.width = width;
-        this.height = height;
-        this.logicalPageXOffset = logicalPageXOffset;
+        this.selector = selector;
+        this.physicalPageSize = physicalPageSize;
+        this.logicalPageRect = logicalPageRect;
         this.landscape = landscape;
     }
     
+    /** @return the name of the page definition */
     public String getName() {
         return this.name;
     }
     
+    /** @return the selector used by the <ESC>&l#A command (page size) */
+    public int getSelector() {
+        return this.selector;
+    }
+    
+    /** @return true if it is a landscape format */
     public boolean isLandscapeFormat() {
         return this.landscape;
     }
+
+    /** @return the physical page size */
+    public Dimension getPhysicalPageSize() {
+        return this.physicalPageSize;
+    }
     
-    public int getLogicalPageXOffset() {
-        return this.logicalPageXOffset;
+    /** @return the rectangle defining the logical page */
+    public Rectangle getLogicalPageRect() {
+        return this.logicalPageRect;
     }
     
-    public boolean matches(long width, long height, int errorMargin) {
-        return (Math.abs(this.width - width) < errorMargin) 
-            && (Math.abs(this.height - height) < errorMargin);
+    private boolean matches(long width, long height, int errorMargin) {
+        return (Math.abs(this.physicalPageSize.width - width) < errorMargin) 
+            && (Math.abs(this.physicalPageSize.height - height) < errorMargin);
     }
     
     /** @see java.lang.Object#toString() */
@@ -75,6 +95,13 @@ public class PCLPageDefinition {
         return getName();
     }
 
+    /**
+     * Tries to determine a matching page definition.
+     * @param width the physical page width (in mpt)
+     * @param height the physical page height (in mpt)
+     * @param errorMargin the error margin for detecting the right page definition
+     * @return the page definition or null if no match was found
+     */
     public static PCLPageDefinition getPageDefinition(long width, long height, int errorMargin) {
         Iterator iter = pageDefinitions.iterator();
         while (iter.hasNext()) {
@@ -86,58 +113,80 @@ public class PCLPageDefinition {
         return null;
     }
     
+    /** @return the default page definition (letter) */
+    public static PCLPageDefinition getDefaultPageDefinition() {
+        return defaultPageDefinition;
+    }
+    
     /**
      * Converts an offset values for logical pages to millipoints. The values are given as pixels
      * in a 300dpi environment.
      * @param offset the offset as given in the PCL 5 specification (under "Printable Area")
      * @return the converted value in millipoints
      */
-    private static int convertLogicalPageXOffset(int offset) {
+    private static int convert300dpiDotsToMpt(int offset) {
         return (int)Math.round(((double)offset) * 72000 / 300);
     }
     
+    private static Dimension createPhysicalPageSizeInch(float width, float height) {
+        return new Dimension(
+                (int)Math.round(UnitConv.in2mpt(width)), 
+                (int)Math.round(UnitConv.in2mpt(height)));
+    }
+    
+    private static Dimension createPhysicalPageSizeMm(float width, float height) {
+        return new Dimension(
+                (int)Math.round(UnitConv.mm2mpt(width)), 
+                (int)Math.round(UnitConv.mm2mpt(height)));
+    }
+    
+    private static Rectangle createLogicalPageRect(int x, int y, int width, int height) {
+        return new Rectangle(convert300dpiDotsToMpt(x), convert300dpiDotsToMpt(y), 
+                convert300dpiDotsToMpt(width), convert300dpiDotsToMpt(height));
+    }
+    
     private static void createPageDefinitions() {
         pageDefinitions = new java.util.ArrayList();
-        pageDefinitions.add(new PCLPageDefinition("Letter", 
-                Math.round(UnitConv.in2mpt(8.5)), Math.round(UnitConv.in2mpt(11)),
-                convertLogicalPageXOffset(75)));
-        pageDefinitions.add(new PCLPageDefinition("Legal", 
-                Math.round(UnitConv.in2mpt(8.5)), Math.round(UnitConv.in2mpt(14)),
-                convertLogicalPageXOffset(75)));
-        pageDefinitions.add(new PCLPageDefinition("Executive", 
-                Math.round(UnitConv.in2mpt(7.25)), Math.round(UnitConv.in2mpt(10.5)),
-                convertLogicalPageXOffset(75)));
-        pageDefinitions.add(new PCLPageDefinition("Ledger", 
-                Math.round(UnitConv.in2mpt(11)), Math.round(UnitConv.in2mpt(17)),
-                convertLogicalPageXOffset(75)));
-        pageDefinitions.add(new PCLPageDefinition("A4", 
-                Math.round(UnitConv.mm2mpt(210)), Math.round(UnitConv.mm2mpt(297)),
-                convertLogicalPageXOffset(71)));
-        pageDefinitions.add(new PCLPageDefinition("A3", 
-                Math.round(UnitConv.mm2mpt(297)), Math.round(UnitConv.mm2mpt(420)),
-                convertLogicalPageXOffset(71)));
+        pageDefinitions.add(new PCLPageDefinition("Letter", 2,
+                createPhysicalPageSizeInch(8.5f, 11),
+                createLogicalPageRect(75, 0, 2400, 3300), false));
+        defaultPageDefinition = new PCLPageDefinition("Legal", 3, 
+                createPhysicalPageSizeInch(8.5f, 14),
+                createLogicalPageRect(75, 0, 2400, 4200), false);
+        pageDefinitions.add(defaultPageDefinition);
+        pageDefinitions.add(new PCLPageDefinition("Executive", 1, 
+                createPhysicalPageSizeInch(7.25f, 10.5f),
+                createLogicalPageRect(75, 0, 2025, 3150), false));
+        pageDefinitions.add(new PCLPageDefinition("Ledger", 6,
+                createPhysicalPageSizeInch(11, 17),
+                createLogicalPageRect(75, 0, 3150, 5100), false));
+        pageDefinitions.add(new PCLPageDefinition("A4", 26,
+                createPhysicalPageSizeMm(210, 297),
+                createLogicalPageRect(71, 0, 2338, 3507), false));
+        pageDefinitions.add(new PCLPageDefinition("A3", 27, 
+                createPhysicalPageSizeMm(297, 420),
+                createLogicalPageRect(71, 0, 3365, 4960), false));
 
         //TODO Add envelope definitions
         
-        pageDefinitions.add(new PCLPageDefinition("LetterL", 
-                Math.round(UnitConv.in2mpt(11)), Math.round(UnitConv.in2mpt(8.5)),
-                convertLogicalPageXOffset(60)));
-        pageDefinitions.add(new PCLPageDefinition("LegalL", 
-                Math.round(UnitConv.in2mpt(14)), Math.round(UnitConv.in2mpt(8.5)),
-                convertLogicalPageXOffset(60)));
-        pageDefinitions.add(new PCLPageDefinition("ExecutiveL", 
-                Math.round(UnitConv.in2mpt(10.5)), Math.round(UnitConv.in2mpt(7.25)),
-                convertLogicalPageXOffset(60)));
-        pageDefinitions.add(new PCLPageDefinition("LedgerL", 
-                Math.round(UnitConv.in2mpt(17)), Math.round(UnitConv.in2mpt(11)),
-                convertLogicalPageXOffset(60)));
-        pageDefinitions.add(new PCLPageDefinition("A4L", 
-                Math.round(UnitConv.mm2mpt(297)), Math.round(UnitConv.mm2mpt(210)),
-                convertLogicalPageXOffset(59), true));
-        pageDefinitions.add(new PCLPageDefinition("A3L", 
-                Math.round(UnitConv.mm2mpt(420)), Math.round(UnitConv.mm2mpt(297)),
-                convertLogicalPageXOffset(59)));
+        pageDefinitions.add(new PCLPageDefinition("LetterL", 2,
+                createPhysicalPageSizeInch(11, 8.5f),
+                createLogicalPageRect(60, 0, 3180, 2550), true));
+        pageDefinitions.add(new PCLPageDefinition("LegalL", 3,
+                createPhysicalPageSizeInch(14, 8.5f),
+                createLogicalPageRect(60, 0, 4080, 2550), true));
+        pageDefinitions.add(new PCLPageDefinition("ExecutiveL", 1, 
+                createPhysicalPageSizeInch(10.5f, 7.25f),
+                createLogicalPageRect(60, 0, 3030, 2175), true));
+        pageDefinitions.add(new PCLPageDefinition("LedgerL", 6,
+                createPhysicalPageSizeInch(17, 11),
+                createLogicalPageRect(60, 0, 4980, 3300), true));
+        pageDefinitions.add(new PCLPageDefinition("A4L", 26,
+                createPhysicalPageSizeMm(297, 210),
+                createLogicalPageRect(59, 0, 3389, 2480), true));
+        pageDefinitions.add(new PCLPageDefinition("A3L", 27,
+                createPhysicalPageSizeMm(420, 297),
+                createLogicalPageRect(59, 0, 4842, 3507), true));
     }
-
     
 }
index 450fb585235ddfefabe0f46287490af32a30224a..c7b892923494b0dfb6d65970ce5285baf8ebf909 100644 (file)
@@ -51,6 +51,8 @@ import org.apache.xmlgraphics.java2d.GraphicContext;
 // FOP
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.Area;
@@ -80,12 +82,16 @@ import org.apache.fop.render.RendererContextConstants;
 import org.apache.fop.render.java2d.Java2DRenderer;
 import org.apache.fop.traits.BorderProps;
 import org.apache.fop.util.QName;
+import org.apache.fop.util.UnitConv;
 
 /**
  * Renderer for the PCL 5 printer language. It also uses HP GL/2 for certain graphic elements.
  */
 public class PCLRenderer extends PrintRenderer {
 
+    /** logging instance */
+    private static Log log = LogFactory.getLog(PCLRenderer.class);
+
     /** The MIME type for PCL */
     public static final String MIME_TYPE = MimeConstants.MIME_PCL_ALT;
 
@@ -99,6 +105,8 @@ public class PCLRenderer extends PrintRenderer {
     private Stack graphicContextStack = new Stack();
     private GraphicContext graphicContext = new GraphicContext();
 
+    private PCLPageDefinition currentPageDefinition;
+    private int currentPrintDirection = 0;
     private GeneralPath currentPath = null;
     private java.awt.Color currentFillColor = null;
     
@@ -298,25 +306,27 @@ public class PCLRenderer extends PrintRenderer {
     }
 
     private void selectPageFormat(long pagewidth, long pageheight) throws IOException {
-        
-        PCLPageDefinition pageDef = PCLPageDefinition.getPageDefinition(
+        this.currentPageDefinition = PCLPageDefinition.getPageDefinition(
                 pagewidth, pageheight, 1000);
-        if (pageDef != null) {
-            // Adjust for the offset into the logical page
-            graphicContext.translate(-pageDef.getLogicalPageXOffset(), 0);
-            if (pageDef.isLandscapeFormat()) {
-                gen.writeCommand("&l1O"); //Orientation
-            } else {
-                gen.writeCommand("&l0O"); //Orientation
-            }
+        if (this.currentPageDefinition == null) {
+            this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition();
+            log.warn("Paper type could not be determined. Falling back to: " 
+                    + this.currentPageDefinition.getName());
+        }
+        log.debug("page size: " + currentPageDefinition.getPhysicalPageSize());
+        log.debug("logical page: " + currentPageDefinition.getLogicalPageRect());
+        gen.selectPageSize(this.currentPageDefinition.getSelector());
+        
+        if (this.currentPageDefinition.isLandscapeFormat()) {
+            gen.writeCommand("&l1O"); //Orientation
         } else {
-            // Adjust for the offset into the logical page
-            // X Offset to allow for PCL implicit 1/4" left margin (= 180 decipoints)
-            graphicContext.translate(-18000, 18000);
             gen.writeCommand("&l0O"); //Orientation
         }
         gen.clearHorizontalMargins();
         gen.setTopMargin(0);
+        gen.setVMI(0);
+        gen.setUnitOfMeasure(600);
+        gen.setRasterGraphicsResolution(600);
     }
 
     /** Saves the current graphics state on the stack. */
@@ -343,14 +353,95 @@ public class PCLRenderer extends PrintRenderer {
         //PCL cannot clip (only HP GL/2 can)
     }
 
+    private Point2D transformedPoint(float x, float y) {
+        return transformedPoint(Math.round(x), Math.round(y));
+    }
+    
+    private Point2D transformedPoint(int x, int y) {
+        AffineTransform at = graphicContext.getTransform();
+        if (log.isTraceEnabled()) {
+            log.trace("Current transform: " + at);
+        }
+        Point2D.Float orgPoint = new Point2D.Float(x, y);
+        Point2D.Float transPoint = new Point2D.Float();
+        at.transform(orgPoint, transPoint);
+        //At this point we have the absolute position in FOP's coordinate system
+        
+        //Now get PCL coordinates taking the current print direction and the logical page
+        //into account.
+        Dimension pageSize = currentPageDefinition.getPhysicalPageSize();
+        Rectangle logRect = currentPageDefinition.getLogicalPageRect();
+        switch (currentPrintDirection) {
+        case 0:
+            transPoint.x -= logRect.x;
+            transPoint.y -= logRect.y;
+            break;
+        case 90:
+            float ty = transPoint.x;
+            transPoint.x = pageSize.height - transPoint.y;
+            transPoint.y = ty;
+            transPoint.x -= logRect.y;
+            transPoint.y -= logRect.x;
+            break;
+        case 180:
+            transPoint.x = pageSize.width - transPoint.x;
+            transPoint.y = pageSize.height - transPoint.y;
+            transPoint.x -= pageSize.width - logRect.x - logRect.width;
+            transPoint.y -= pageSize.height - logRect.y - logRect.height;
+            //The next line is odd and is probably necessary due to the default value of the
+            //Text Length command: "1/2 inch less than maximum text length"
+            //I wonder why this isn't necessary for the 90° rotation. *shrug*
+            transPoint.y -= UnitConv.in2mpt(0.5);
+            break;
+        case 270:
+            float tx = transPoint.y;
+            transPoint.y = pageSize.width - transPoint.x;
+            transPoint.x = tx;
+            transPoint.x -= pageSize.height - logRect.y - logRect.height;
+            transPoint.y -= pageSize.width - logRect.x - logRect.width;
+            break;
+        default:
+            throw new IllegalStateException("Illegal print direction: " + currentPrintDirection);
+        }
+        return transPoint;
+    }
+    
+    private void changePrintDirection() {
+        AffineTransform at = graphicContext.getTransform();
+        int newDir;
+        try {
+            if (at.getScaleX() == 0 && at.getScaleY() == 0 
+                    && at.getShearX() == 1 && at.getShearY() == -1) {
+                newDir = 90;
+            } else if (at.getScaleX() == -1 && at.getScaleY() == -1 
+                    && at.getShearX() == 0 && at.getShearY() == 0) {
+                newDir = 180;
+            } else if (at.getScaleX() == 0 && at.getScaleY() == 0 
+                    && at.getShearX() == -1 && at.getShearY() == 1) {
+                newDir = 270;
+            } else {
+                newDir = 0;
+            }
+            if (newDir != this.currentPrintDirection) {
+                this.currentPrintDirection = newDir;
+                gen.changePrintDirection(this.currentPrintDirection);
+            }
+        } catch (IOException ioe) {
+            handleIOTrouble(ioe);
+        }
+    }
+
     /**
      * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM, Rectangle2D)
      */
     protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
         saveGraphicsState();
         AffineTransform at = new AffineTransform(ctm.toArray());
-        log.debug("startVPArea: " + at);
         graphicContext.transform(at);
+        changePrintDirection();
+        if (log.isDebugEnabled()) {
+            log.debug("startVPArea: " + at + " --> " + graphicContext.getTransform());
+        }
     }
 
     /**
@@ -358,6 +449,10 @@ public class PCLRenderer extends PrintRenderer {
      */
     protected void endVParea() {
         restoreGraphicsState();
+        changePrintDirection();
+        if (log.isDebugEnabled()) {
+            log.debug("endVPArea() --> " + graphicContext.getTransform());
+        }
     }
 
     /**
@@ -413,7 +508,6 @@ public class PCLRenderer extends PrintRenderer {
             }
             
             saveGraphicsState();
-            updatePrintDirection();
             graphicContext.translate(rx, bl);
             setCursorPos(0, 0);
         
@@ -448,7 +542,7 @@ public class PCLRenderer extends PrintRenderer {
         if (currentPath == null) {
             throw new IllegalStateException("No current path available!");
         }
-        //TODO Find a good way to do clipping
+        //TODO Find a good way to do clipping. PCL itself cannot clip.
         currentPath = null;
     }
 
@@ -488,9 +582,8 @@ public class PCLRenderer extends PrintRenderer {
      */
     protected void fillRect(float x, float y, float width, float height) {
         try {
-            Point2D p = transformedPoint(x * 1000, y * 1000);
-            gen.fillRect((int)p.getX(), (int)p.getY(), 
-                    (int)width * 1000, (int)height * 1000, 
+            setCursorPos(x * 1000, y * 1000);
+            gen.fillRect((int)width * 1000, (int)height * 1000, 
                     this.currentFillColor);
         } catch (IOException ioe) {
             handleIOTrouble(ioe);
@@ -505,41 +598,6 @@ public class PCLRenderer extends PrintRenderer {
         this.currentFillColor = color;
     }
 
-    private void updatePrintDirection() throws IOException {
-        AffineTransform at = graphicContext.getTransform();
-        if (log.isDebugEnabled()) {
-            log.debug(at.getScaleX() + " " + at.getScaleY() + " " 
-                    + at.getShearX() + " " + at.getShearY() );
-        }
-        if (at.getScaleX() == 0 && at.getScaleY() == 0 
-                && at.getShearX() == 1 && at.getShearY() == -1) {
-            gen.writeCommand("&a90P");
-        } else if (at.getScaleX() == -1 && at.getScaleY() == -1 
-                && at.getShearX() == 0 && at.getShearY() == 0) {
-            gen.writeCommand("&a180P");
-        } else if (at.getScaleX() == 0 && at.getScaleY() == 0 
-                && at.getShearX() == -1 && at.getShearY() == 1) {
-            gen.writeCommand("&a270P");
-        } else {
-            gen.writeCommand("&a0P");
-        }
-    }
-
-    private Point2D transformedPoint(float x, float y) {
-        return transformedPoint(Math.round(x), Math.round(y));
-    }
-    
-    private Point2D transformedPoint(int x, int y) {
-        AffineTransform at = graphicContext.getTransform();
-        if (log.isDebugEnabled()) {
-            log.debug("Current transform: " + at);
-        }
-        Point2D orgPoint = new Point2D.Float(x, y);
-        Point2D transPoint = new Point2D.Float();
-        at.transform(orgPoint, transPoint);
-        return transPoint;
-    }
-    
     /**
      * @see org.apache.fop.render.AbstractRenderer#renderWord(org.apache.fop.area.inline.WordArea)
      */
@@ -814,100 +872,94 @@ public class PCLRenderer extends PrintRenderer {
      */
     protected void drawBackAndBorders(Area area, float startx, float starty,
             float width, float height) {
-        try {
-            updatePrintDirection();
-            BorderProps bpsBefore = (BorderProps) area.getTrait(Trait.BORDER_BEFORE);
-            BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
-            BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
-            BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
-        
-            // draw background
-            Trait.Background back;
-            back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
-            if (back != null) {
-        
-                // Calculate padding rectangle
-                float sx = startx;
-                float sy = starty;
-                float paddRectWidth = width;
-                float paddRectHeight = height;
-        
-                if (bpsStart != null) {
-                    sx += bpsStart.width / 1000f;
-                    paddRectWidth -= bpsStart.width / 1000f;
-                }
-                if (bpsBefore != null) {
-                    sy += bpsBefore.width / 1000f;
-                    paddRectHeight -= bpsBefore.width / 1000f;
-                }
-                if (bpsEnd != null) {
-                    paddRectWidth -= bpsEnd.width / 1000f;
-                }
-                if (bpsAfter != null) {
-                    paddRectHeight -= bpsAfter.width / 1000f;
-                }
-        
-                if (back.getColor() != null) {
-                    updateFillColor(back.getColor());
-                    fillRect(sx, sy, paddRectWidth, paddRectHeight);
-                }
-        
-                // background image
-                if (back.getFopImage() != null) {
-                    FopImage fopimage = back.getFopImage();
-                    if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
-                        saveGraphicsState();
-                        clipRect(sx, sy, paddRectWidth, paddRectHeight);
-                        int horzCount = (int) ((paddRectWidth * 1000 / fopimage
-                                .getIntrinsicWidth()) + 1.0f);
-                        int vertCount = (int) ((paddRectHeight * 1000 / fopimage
-                                .getIntrinsicHeight()) + 1.0f);
-                        if (back.getRepeat() == EN_NOREPEAT) {
-                            horzCount = 1;
-                            vertCount = 1;
-                        } else if (back.getRepeat() == EN_REPEATX) {
-                            vertCount = 1;
-                        } else if (back.getRepeat() == EN_REPEATY) {
-                            horzCount = 1;
-                        }
-                        // change from points to millipoints
-                        sx *= 1000;
-                        sy *= 1000;
-                        if (horzCount == 1) {
-                            sx += back.getHoriz();
-                        }
-                        if (vertCount == 1) {
-                            sy += back.getVertical();
-                        }
-                        for (int x = 0; x < horzCount; x++) {
-                            for (int y = 0; y < vertCount; y++) {
-                                // place once
-                                Rectangle2D pos;
-                                // Image positions are relative to the currentIP/BP
-                                pos = new Rectangle2D.Float(
-                                        sx - currentIPPosition 
-                                            + (x * fopimage.getIntrinsicWidth()),
-                                        sy - currentBPPosition
-                                            + (y * fopimage.getIntrinsicHeight()),
-                                        fopimage.getIntrinsicWidth(),
-                                        fopimage.getIntrinsicHeight());
-                                drawImage(back.getURL(), pos, null);
-                            }
+        BorderProps bpsBefore = (BorderProps) area.getTrait(Trait.BORDER_BEFORE);
+        BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
+        BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
+        BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
+    
+        // draw background
+        Trait.Background back;
+        back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
+        if (back != null) {
+    
+            // Calculate padding rectangle
+            float sx = startx;
+            float sy = starty;
+            float paddRectWidth = width;
+            float paddRectHeight = height;
+    
+            if (bpsStart != null) {
+                sx += bpsStart.width / 1000f;
+                paddRectWidth -= bpsStart.width / 1000f;
+            }
+            if (bpsBefore != null) {
+                sy += bpsBefore.width / 1000f;
+                paddRectHeight -= bpsBefore.width / 1000f;
+            }
+            if (bpsEnd != null) {
+                paddRectWidth -= bpsEnd.width / 1000f;
+            }
+            if (bpsAfter != null) {
+                paddRectHeight -= bpsAfter.width / 1000f;
+            }
+    
+            if (back.getColor() != null) {
+                updateFillColor(back.getColor());
+                fillRect(sx, sy, paddRectWidth, paddRectHeight);
+            }
+    
+            // background image
+            if (back.getFopImage() != null) {
+                FopImage fopimage = back.getFopImage();
+                if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
+                    saveGraphicsState();
+                    clipRect(sx, sy, paddRectWidth, paddRectHeight);
+                    int horzCount = (int) ((paddRectWidth * 1000 / fopimage
+                            .getIntrinsicWidth()) + 1.0f);
+                    int vertCount = (int) ((paddRectHeight * 1000 / fopimage
+                            .getIntrinsicHeight()) + 1.0f);
+                    if (back.getRepeat() == EN_NOREPEAT) {
+                        horzCount = 1;
+                        vertCount = 1;
+                    } else if (back.getRepeat() == EN_REPEATX) {
+                        vertCount = 1;
+                    } else if (back.getRepeat() == EN_REPEATY) {
+                        horzCount = 1;
+                    }
+                    // change from points to millipoints
+                    sx *= 1000;
+                    sy *= 1000;
+                    if (horzCount == 1) {
+                        sx += back.getHoriz();
+                    }
+                    if (vertCount == 1) {
+                        sy += back.getVertical();
+                    }
+                    for (int x = 0; x < horzCount; x++) {
+                        for (int y = 0; y < vertCount; y++) {
+                            // place once
+                            Rectangle2D pos;
+                            // Image positions are relative to the currentIP/BP
+                            pos = new Rectangle2D.Float(
+                                    sx - currentIPPosition 
+                                        + (x * fopimage.getIntrinsicWidth()),
+                                    sy - currentBPPosition
+                                        + (y * fopimage.getIntrinsicHeight()),
+                                    fopimage.getIntrinsicWidth(),
+                                    fopimage.getIntrinsicHeight());
+                            drawImage(back.getURL(), pos, null);
                         }
-                        restoreGraphicsState();
-                    } else {
-                        log.warn(
-                                "Can't find background image: " + back.getURL());
                     }
+                    restoreGraphicsState();
+                } else {
+                    log.warn(
+                            "Can't find background image: " + back.getURL());
                 }
             }
-            
-            Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height);
-            drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
-            
-        } catch (IOException ioe) {
-            handleIOTrouble(ioe);
         }
+        
+        Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height);
+        drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
     }
 
     /**