From: Jeremias Maerki Date: Fri, 5 May 2006 13:38:39 +0000 (+0000) Subject: The PCL Renderer is now mostly operational including reference-orientation but withou... X-Git-Tag: fop-0_93~241 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a5c6c4684909acce53bd53b22e0c9e926f2b5fc2;p=xmlgraphics-fop.git The PCL Renderer is now mostly operational including reference-orientation but without kerning, TrueType and color support. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@400075 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java b/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java index 4e647a977..58447f787 100644 --- a/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/sandbox/org/apache/fop/render/pcl/PCLGenerator.java @@ -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); diff --git a/src/sandbox/org/apache/fop/render/pcl/PCLPageDefinition.java b/src/sandbox/org/apache/fop/render/pcl/PCLPageDefinition.java index 40a0eddd7..43978e954 100644 --- a/src/sandbox/org/apache/fop/render/pcl/PCLPageDefinition.java +++ b/src/sandbox/org/apache/fop/render/pcl/PCLPageDefinition.java @@ -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 &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 &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)); } - } diff --git a/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java b/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java index 450fb5852..c7b892923 100644 --- a/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java @@ -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); } /**