diff options
Diffstat (limited to 'src/java/org/apache')
6 files changed, 383 insertions, 20 deletions
diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index 5b4c6b13a..170df3f4d 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -30,6 +30,7 @@ package org.apache.fop.render.awt; import java.awt.Color; import java.awt.Dimension; import java.awt.geom.Rectangle2D; +import java.awt.geom.Point2D; import java.awt.print.PageFormat; import java.awt.print.Pageable; import java.awt.print.Paper; @@ -46,6 +47,7 @@ import org.apache.fop.render.awt.viewer.PreviewDialog; import org.apache.fop.render.awt.viewer.Renderable; import org.apache.fop.render.awt.viewer.StatusListener; import org.apache.fop.render.java2d.Java2DRenderer; +import org.apache.fop.render.extensions.prepress.PageScaleAttributes; /** * The AWTRender outputs the pages generated by the layout engine to a Swing @@ -149,11 +151,23 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { Rectangle2D bounds = getPageViewport(pageNum).getViewArea(); pageWidth = (int) Math.round(bounds.getWidth() / 1000f); pageHeight = (int) Math.round(bounds.getHeight() / 1000f); - double scale = scaleFactor + double scaleX = scaleFactor * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); - int bitmapWidth = (int) ((pageWidth * scale) + 0.5); - int bitmapHeight = (int) ((pageHeight * scale) + 0.5); + double scaleY = scaleFactor + * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) + / userAgent.getTargetPixelUnitToMillimeter(); + if (getPageViewport(pageNum).getForeignAttributes() != null) { + String scale = (String) getPageViewport(pageNum).getForeignAttributes().get( + PageScaleAttributes.EXT_PAGE_SCALE); + Point2D scales = PageScaleAttributes.getScaleAttributes(scale); + if (scales != null) { + scaleX *= scales.getX(); + scaleY *= scales.getY(); + } + } + int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); + int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); return new Dimension(bitmapWidth, bitmapHeight); } diff --git a/src/java/org/apache/fop/render/extensions/prepress/PageBoundariesAttributes.java b/src/java/org/apache/fop/render/extensions/prepress/PageBoundariesAttributes.java new file mode 100644 index 000000000..ac57011da --- /dev/null +++ b/src/java/org/apache/fop/render/extensions/prepress/PageBoundariesAttributes.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.extensions.prepress; + +import java.awt.Rectangle; +import java.text.MessageFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.xmlgraphics.util.QName; + +import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.fo.properties.FixedLength; + + +/** + * This class contains definition of page boundaries FOF's extension attributes for XSL-FO. + * That is: bleedBox, trimBox and cropBox. + * Also this class provides method to parse the possible values of these attributes + * and to generate original size of bounded area. + */ +public final class PageBoundariesAttributes { + + /** + * The extension attribute for calculating the PDF BleedBox area - specifies the bleed width + */ + public static final QName EXT_BLEED + = new QName(ExtensionElementMapping.URI, null, "bleed"); + + /** + * The extension attribute for the PDF CropBox area + */ + public static final QName EXT_CROP_OFFSET + = new QName(ExtensionElementMapping.URI, null, "crop-offset"); + + /** + * The extension attribute for the PDF CropBox area + */ + public static final QName EXT_CROP_BOX + = new QName(ExtensionElementMapping.URI, null, "crop-box"); + + + private static final Pattern SIZE_UNIT_PATTERN + = Pattern.compile("^(-?\\d*\\.?\\d*)(px|in|cm|mm|pt|pc|mpt)$"); + + /** + * Utility classes should not have a public or default constructor. + */ + private PageBoundariesAttributes() { + } + + /** + * The BleedBox is calculated by expanding the TrimBox by the bleed widths. + * + * @param trimBox the TrimBox rectangle + * @param bleed the given bleed widths + * @return the calculated BleedBox rectangle + */ + public static Rectangle getBleedBoxRectangle(Rectangle trimBox, String bleed) { + return getRectagleUsingOffset(trimBox, bleed); + } + + /** + * The MediaBox is calculated by expanding the TrimBox by the crop offsets. + * + * @param trimBox the TrimBox rectangle + * @param cropOffsets the given crop offsets + * @return the calculated MediaBox rectangle + */ + public static Rectangle getMediaBoxRectangle(Rectangle trimBox, String cropOffsets) { + return getRectagleUsingOffset(trimBox, cropOffsets); + } + + /** + * The crop box controls how Acrobat display the page or how the Java2DRenderer + * sizes the output media. The PDF spec defines that the CropBox defaults to the MediaBox. + * <p/> + * The possible values of crop-box: (trim-box|bleed-box|media-box) + * Default value: media-box + * + * @param trimBox the TrimBox rectangle + * @param bleedBox the BleedBox rectangle + * @param mediaBox the MediaBox rectangle + * @param value the crop-box value + * @return the calculated CropBox rectangle + */ + public static Rectangle getCropBoxRectangle(final Rectangle trimBox, final Rectangle bleedBox, + final Rectangle mediaBox, final String value) { + final String err = "The crop-box has invalid value: {0}, " + + "possible values of crop-box: (trim-box|bleed-box|media-box)"; + + if ("trim-box".equals(value)) { + return trimBox; + } else if ("bleed-box".equals(value)) { + return bleedBox; + } else if ("media-box".equals(value) || value == null || "".equals(value)) { + return mediaBox; + } else { + throw new IllegalArgumentException(MessageFormat.format(err, new Object[]{value})); + } + } + + /** + * The crop box controls how Acrobat display the page or how the Java2DRenderer + * sizes the output media. The PDF spec defines that the CropBox defaults to the MediaBox + * <p/> + * The possible values of crop-box: (trim-box|bleed-box|media-box) + * Default value: media-box + * + * @param trimBox the TrimBox rectangle + * @param bleed the given bleed widths + * @param cropOffset the given crop offsets + * @param value the crop-box value + * @return the calculated CropBox rectangle + */ + public static Rectangle getCropBoxRectangle(final Rectangle trimBox, final String bleed, + final String cropOffset, final String value) { + Rectangle bleedBox = getBleedBoxRectangle(trimBox, bleed); + Rectangle mediaBox = getMediaBoxRectangle(trimBox, cropOffset); + + return getCropBoxRectangle(trimBox, bleedBox, mediaBox, value); + } + + private static Rectangle getRectagleUsingOffset(Rectangle originalRect, String offset) { + if (offset == null || "".equals(offset) || originalRect == null) { + return originalRect; + } + + String[] bleeds = offset.split(" "); + int[] coords = new int[4]; // top, rigth, bottom, left + if (bleeds.length == 1) { + coords[0] = getLengthIntValue(bleeds[0]); + coords[1] = coords[0]; + coords[2] = coords[0]; + coords[3] = coords[0]; + } else if (bleeds.length == 2) { + coords[0] = getLengthIntValue(bleeds[0]); + coords[2] = coords[0]; + coords[1] = getLengthIntValue(bleeds[1]); + coords[3] = coords[1]; + } else if (bleeds.length == 3) { + coords[0] = getLengthIntValue(bleeds[0]); + coords[1] = getLengthIntValue(bleeds[1]); + coords[3] = coords[1]; + coords[2] = getLengthIntValue(bleeds[2]); + } else if (bleeds.length == 4) { + coords[0] = getLengthIntValue(bleeds[0]); + coords[1] = getLengthIntValue(bleeds[1]); + coords[2] = getLengthIntValue(bleeds[2]); + coords[3] = getLengthIntValue(bleeds[3]); + } + return new Rectangle((int) (originalRect.getX() - coords[3]), + (int) (originalRect.getY() - coords[0]), + (int) (originalRect.getWidth() + coords[3] + coords[1]), + (int) (originalRect.getHeight() + coords[0] + coords[2])); + } + + private static int getLengthIntValue(final String length) { + final String err = "Incorrect length value: {0}"; + Matcher m = SIZE_UNIT_PATTERN.matcher(length); + + if (m.find()) { + return FixedLength.getInstance(Double.parseDouble(m.group(1)), + m.group(2)).getLength().getValue(); + } else { + throw new IllegalArgumentException(MessageFormat.format(err, new Object[]{length})); + } + } +} diff --git a/src/java/org/apache/fop/render/extensions/prepress/PageScaleAttributes.java b/src/java/org/apache/fop/render/extensions/prepress/PageScaleAttributes.java new file mode 100644 index 000000000..96f0fbc30 --- /dev/null +++ b/src/java/org/apache/fop/render/extensions/prepress/PageScaleAttributes.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.extensions.prepress; + +import java.awt.geom.Point2D; +import java.text.MessageFormat; + +import org.apache.xmlgraphics.util.QName; + +import org.apache.fop.fo.extensions.ExtensionElementMapping; + + +/** + * This class contains definition of 'scale' FOF's extension attribute for XSL-FO, and provides + * utility method to parse the possible values of this attibute + */ +public final class PageScaleAttributes { + + /** + * The extension 'scale' attribute for simple-page-master element + */ + public static final QName EXT_PAGE_SCALE + = new QName(ExtensionElementMapping.URI, null, "scale"); + + + /** + * Utility classes should not have a public or default constructor + */ + private PageScaleAttributes() { + } + + /** + * Compute scale parameters from given fox:scale attribute which has format: scaleX [scaleY] + * If scaleY is not defined, it equals scaleX + * @param scale scale attribute, input format: scaleX [scaleY] + * @return the pair of (sx, sy) values + */ + public static Point2D.Double getScaleAttributes(String scale) { + final String err = "Extension 'scale' attribute has incorrect value(s): {0}"; + + if (scale == null) { + return null; + } + + Point2D.Double result = null; + + try { + String[] scales = scale.split(" "); + if (scales.length > 0) { + result = new Point2D.Double(Double.parseDouble(scales[0]), + Double.parseDouble(scales[0])); + } + if (scales.length > 1) { + result.y = Double.parseDouble(scales[1]); + } + if (result.x <= 0 || result.y <= 0) { + throw new IllegalArgumentException(MessageFormat.format(err, new Object[]{scale})); + } + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException(MessageFormat.format(err, new Object[]{scale})); + } + + return result; + } +} diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index 270161dbd..e22088824 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -549,10 +549,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer { } try { pageIndices.put(page.getKey(), new Integer(page.getPageIndex())); - Rectangle2D viewArea = page.getViewArea(); - Dimension dim = new Dimension( - (int)Math.ceil(viewArea.getWidth()), - (int)Math.ceil(viewArea.getHeight())); + Rectangle viewArea = page.getViewArea(); + Dimension dim = new Dimension(viewArea.width, viewArea.height); establishForeignAttributes(page.getForeignAttributes()); documentHandler.startPage(page.getPageIndex(), page.getPageNumberString(), diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 933398125..265315ecc 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -75,6 +75,8 @@ import org.apache.fop.fonts.Typeface; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.extensions.prepress.PageBoundariesAttributes; +import org.apache.fop.render.extensions.prepress.PageScaleAttributes; import org.apache.fop.render.pdf.CTMHelper; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ColorUtil; @@ -290,7 +292,20 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem this.currentPageViewport = pageViewport; try { - Rectangle2D bounds = pageViewport.getViewArea(); + String bleed = (String) currentPageViewport.getForeignAttributes().get( + PageBoundariesAttributes.EXT_BLEED); + String cropOffset = (String) currentPageViewport.getForeignAttributes().get( + PageBoundariesAttributes.EXT_CROP_OFFSET); + String cropBoxValue = (String) currentPageViewport.getForeignAttributes().get( + PageBoundariesAttributes.EXT_CROP_BOX); + Rectangle2D bounds = PageBoundariesAttributes.getCropBoxRectangle( + pageViewport.getViewArea(), + bleed, + cropOffset, + cropBoxValue + ); + Rectangle2D bleedBox = PageBoundariesAttributes.getBleedBoxRectangle( + pageViewport.getViewArea(), bleed); this.pageWidth = (int) Math.round(bounds.getWidth() / 1000f); this.pageHeight = (int) Math.round(bounds.getHeight() / 1000f); @@ -299,11 +314,26 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem + " (pageWidth " + pageWidth + ", pageHeight " + pageHeight + ")"); - double scale = scaleFactor + // set scale factor + double scaleX = scaleFactor; + double scaleY = scaleFactor; + String scale = (String) currentPageViewport.getForeignAttributes().get( + PageScaleAttributes.EXT_PAGE_SCALE); + Point2D scales = PageScaleAttributes.getScaleAttributes(scale); + if (scales != null) { + scaleX *= scales.getX(); + scaleY *= scales.getY(); + } + + + scaleX = scaleX + * (25.4f / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) + / userAgent.getTargetPixelUnitToMillimeter(); + scaleY = scaleY * (25.4f / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); - int bitmapWidth = (int) ((pageWidth * scale) + 0.5); - int bitmapHeight = (int) ((pageHeight * scale) + 0.5); + int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); + int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); BufferedImage currentPageImage = getBufferedImage(bitmapWidth, bitmapHeight); @@ -326,20 +356,27 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem // transform page based on scale factor supplied AffineTransform at = graphics.getTransform(); - at.scale(scale, scale); + at.scale(scaleX, scaleY); + at.translate(bounds.getMinX() / -1000f, bounds.getMinY() / -1000f); graphics.setTransform(at); // draw page frame if (!transparentPageBackground) { graphics.setColor(Color.white); - graphics.fillRect(0, 0, pageWidth, pageHeight); + graphics.fillRect( + (int)Math.round(bleedBox.getMinX() / 1000f), + (int)Math.round(bleedBox.getMinY() / 1000f), + (int)Math.round(bleedBox.getWidth() / 1000f), + (int)Math.round(bleedBox.getHeight() / 1000f)); } + /* why did we have this??? graphics.setColor(Color.black); graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2); graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2); graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3); graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2); graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); + */ state = new Java2DGraphicsState(graphics, this.fontInfo, at); try { diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java index b98b15d5e..aaa55d5f8 100644 --- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java @@ -20,7 +20,10 @@ package org.apache.fop.render.pdf; import java.awt.Dimension; +import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.util.Map; @@ -37,6 +40,8 @@ import org.apache.fop.pdf.PDFPage; import org.apache.fop.pdf.PDFReference; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; +import org.apache.fop.render.extensions.prepress.PageBoundariesAttributes; +import org.apache.fop.render.extensions.prepress.PageScaleAttributes; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; @@ -166,13 +171,53 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { throws IFException { this.pdfResources = this.pdfDoc.getResources(); + String bleedWidth = (String) getContext().getForeignAttribute( + PageBoundariesAttributes.EXT_BLEED); + String cropOffset = (String) getContext().getForeignAttribute( + PageBoundariesAttributes.EXT_CROP_OFFSET); + String cropBoxValue = (String) getContext().getForeignAttribute( + PageBoundariesAttributes.EXT_CROP_BOX); + + Rectangle trimBox = new Rectangle(0, 0, + (int) size.getWidth(), (int) size.getHeight()); + Rectangle bleedBox + = PageBoundariesAttributes.getBleedBoxRectangle(trimBox, bleedWidth); + Rectangle mediaBox + = PageBoundariesAttributes.getMediaBoxRectangle(trimBox, cropOffset); + + Rectangle cropBox = PageBoundariesAttributes.getCropBoxRectangle( + trimBox, bleedBox, mediaBox, cropBoxValue); + + // set scale attributes + double scaleX = 1; + double scaleY = 1; + String scale = (String) getContext().getForeignAttribute( + PageScaleAttributes.EXT_PAGE_SCALE); + Point2D scales = PageScaleAttributes.getScaleAttributes(scale); + if (scales != null) { + scaleX = scales.getX(); + scaleY = scales.getY(); + } + this.currentPage = this.pdfDoc.getFactory().makePage( - this.pdfResources, - (int)Math.round(size.getWidth() / 1000), - (int)Math.round(size.getHeight() / 1000), - index); - //pageReferences.put(new Integer(index)/*page.getKey()*/, currentPage.referencePDF()); - //pvReferences.put(page.getKey(), page); + this.pdfResources, + index, + new Rectangle2D.Double(mediaBox.getX() * scaleX / 1000, + mediaBox.getY() * scaleY / 1000, + mediaBox.getWidth() * scaleX / 1000, + mediaBox.getHeight() * scaleY / 1000), + new Rectangle2D.Double(cropBox.getX() * scaleX / 1000, + cropBox.getY() * scaleY / 1000, + cropBox.getWidth() * scaleX / 1000, + cropBox.getHeight() * scaleY / 1000), + new Rectangle2D.Double(bleedBox.getX() * scaleX / 1000, + bleedBox.getY() * scaleY / 1000, + bleedBox.getWidth() * scaleX / 1000, + bleedBox.getHeight() * scaleY / 1000), + new Rectangle2D.Double(trimBox.getX() * scaleX / 1000, + trimBox.getY() * scaleY / 1000, + trimBox.getWidth() * scaleX / 1000, + trimBox.getHeight() * scaleY / 1000)); pdfUtil.generatePageLabel(index, name); @@ -182,7 +227,8 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream, this.currentPage); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFPainter's AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0, - size.height / 1000f); + (scaleY * size.height) / 1000f); + basicPageTransform.scale(scaleX, scaleY); generator.concatenate(basicPageTransform); } |