Added an initial set of extensions for prepress support (fox:bleed, fox:crop-offset, fox:crop-box and fox:scale). This is currently supported only by PDF and Java2D renderers. Submitted by: Peter Coppens <pc.subscriptions.at.gmail.com> Changes to patch by jeremias: - crop box expands from trim box rather than the bleed box. - fixed positioning in AWT preview Additional changes included: - disabled the border around every page in Java2DRenderer. - if background painting is enabled for the Java2DRenderer, it uses the bleed box rather than the trim box. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@800142 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -227,7 +227,90 @@ to following pages. Here is an example of FO code creating such a table-header:< | |||
</p> | |||
</section> | |||
</section> | |||
<section id="prepress"> | |||
<title>Prepress Support</title> | |||
<p> | |||
This section defines a number of extensions related to | |||
<a href="http://en.wikipedia.org/wiki/Prepress">prepress</a> support. | |||
<code>fox:scale</code> defines a general scale factor for the generated pages. | |||
<code>fox:bleed</code> defines the | |||
<a href="http://en.wikipedia.org/wiki/Bleed_%28printing%29">bleed area</a> for a page. | |||
<code>fox:crop-offset</code> defines the outer edges of the area in which crop marks, | |||
registration marks, color bars and page information are placed. | |||
For details, please read on below. | |||
</p> | |||
<section id="scale"> | |||
<title>fox:scale</title> | |||
<p>Default: 1</p> | |||
<p> | |||
<code>fox:scale="sx [sy]"</code> attribute is used in <code>fo:simple-page-master</code> element and specifies | |||
the a scale operation by sx and sy. If sy is not provided, it is assumed to be equal to sx. | |||
sx and sy should be a positive number. A scale factor smaller than 1 shrinks the page. | |||
A scale factor greater than 1 enlarges the page. | |||
</p> | |||
<note> | |||
It is implemented for PDF and Java2D renderers. | |||
</note> | |||
</section> | |||
<section id="bleed"> | |||
<title>fox:bleed</title> | |||
<p> | |||
Value: <length>{1,4} | |||
</p> | |||
<p> | |||
Default: 0pt | |||
</p> | |||
<p> | |||
If there is only one value, it applies to all sides. If there are two values, the top and bottom | |||
bleed widths are set to the first value and the right and left bleed widths are set to the second. | |||
If there are three values, the top is set to the first value, the left and right are set to the second, | |||
and the bottom is set to the third. If there are four values, they apply to the top, right, bottom, and | |||
left, respectively. | |||
(Corresponds to <a href="http://www.w3.org/TR/xsl11/#padding">http://www.w3.org/TR/xsl11/#padding</a>). | |||
</p> | |||
<p> | |||
This extension indirectly defines the BleedBox and is calculated by expanding the TrimBox by | |||
the bleed widths. The lengths must be non-negative. | |||
</p> | |||
</section> | |||
<section id="cropOffset"> | |||
<title>fox:crop-offset</title> | |||
<p> | |||
Value: <length>{1,4} | |||
</p> | |||
<p> | |||
Default: 0pt | |||
</p> | |||
<p> | |||
Same behaviour as with fox:bleed. | |||
</p> | |||
<p> | |||
This extension indirectly defines the MediaBox and is calculated by expanding | |||
the TrimBox by the crop offsets. The lengths must be non-negative. | |||
</p> | |||
</section> | |||
<section id="cropBox"> | |||
<title>fox:crop-box</title> | |||
<p> | |||
Value: (trim-box|bleed-box|media-box) | |||
</p> | |||
<p> | |||
Default: media-box | |||
</p> | |||
<p> | |||
The crop box controls how Acrobat displays the page (CropBox in PDF) or how the Java2DRenderer sizes | |||
the output media. The PDF specification defines that the CropBox defaults to the MediaBox. This extension | |||
follows that definition. To simplify usage and cover most use cases, the three supported enumeration | |||
values "trim-box", "bleed-box" and "media-box" set the CropBox to one of those three other boxes. | |||
</p> | |||
<p> | |||
If requested in the future, we could offer to specify the CropBox in absolute coordinates rather | |||
than just be referencing another box. | |||
</p> | |||
</section> | |||
</section> | |||
</section> | |||
</body> | |||
</document> |
@@ -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); | |||
} | |||
@@ -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})); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(), |
@@ -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 { |
@@ -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); | |||
} | |||
@@ -58,6 +58,10 @@ | |||
documents. Example: the fix of marks layering will be such a case when it's done. | |||
--> | |||
<release version="FOP Trunk" date="TBD"> | |||
<action context="Renderers" dev="JM" type="add" fixes-bug="47311" due-to="Peter Coppens"> | |||
Added an initial set of extensions for prepress support (fox:bleed, fox:crop-offset, | |||
fox:crop-box and fox:scale). This is currently supported only by PDF and Java2D renderers. | |||
</action> | |||
<action context="Renderers" dev="JM" type="add"> | |||
PCL Output: Added support for specifying the output bin. | |||
</action> |
@@ -31,6 +31,7 @@ import org.apache.fop.render.pdf.PDFCMapTestCase; | |||
import org.apache.fop.render.pdf.PDFEncodingTestCase; | |||
import org.apache.fop.render.pdf.PDFsRGBSettingsTestCase; | |||
import org.apache.fop.render.rtf.RichTextFormatTestSuite; | |||
import org.apache.fop.render.extensions.PrepressTest; | |||
/** | |||
* Test suite for basic functionality of FOP. | |||
@@ -56,6 +57,7 @@ public class StandardTestSuite { | |||
suite.addTest(new TestSuite(ImageLoaderTestCase.class)); | |||
suite.addTest(new TestSuite(ImagePreloaderTestCase.class)); | |||
suite.addTest(new TestSuite(IFMimickingTestCase.class)); | |||
suite.addTest(new TestSuite(PrepressTest.class)); | |||
//$JUnit-END$ | |||
return suite; | |||
} |
@@ -0,0 +1,129 @@ | |||
/* | |||
* 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; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.Point2D; | |||
import junit.framework.TestCase; | |||
import org.apache.fop.render.extensions.prepress.PageBoundariesAttributes; | |||
import org.apache.fop.render.extensions.prepress.PageScaleAttributes; | |||
/** | |||
* Base class for automated tests for | |||
* {@link org.apache.fop.render.extensions.prepress.PageBoundariesAttributes} | |||
* and | |||
* {@link org.apache.fop.render.extensions.prepress.PageScaleAttributes} | |||
*/ | |||
public class PrepressTest extends TestCase { | |||
private static final int W = 20000; | |||
private static final int H = 15000; | |||
private static final Rectangle TEST_AREA = new Rectangle(0, 0, W, H); | |||
private static final String BLEED1 = "5pt"; | |||
private static final String CROP_OFFSET1 = "8pt"; | |||
/** | |||
* Main constructor | |||
* @param name the name of the test case | |||
*/ | |||
public PrepressTest(String name) { | |||
super(name); | |||
} | |||
/** | |||
* Tests for 'scale' extension attribute | |||
*/ | |||
public void testScaleOk() throws Exception { | |||
Point2D res = PageScaleAttributes.getScaleAttributes("0.5"); | |||
assertEquals("Points should be equal", res.getX(), res.getY(), 0); | |||
} | |||
public void testScaleFailIllArgExc() throws Exception { | |||
try { | |||
Point2D res = PageScaleAttributes.getScaleAttributes("0.5mm 0.5cm"); | |||
fail("Expected IllegalArgumentException. Scale shouldn't contain units"); | |||
} catch (IllegalArgumentException iae) { | |||
// Good! | |||
} | |||
} | |||
public void testScaleNotEqual() throws Exception { | |||
Point2D res = PageScaleAttributes.getScaleAttributes("0.5 0.6"); | |||
assertFalse("Points shouldn't be equal", res.getX() == res.getY()); | |||
} | |||
public void testScaleNull() throws Exception { | |||
Point2D res = PageScaleAttributes.getScaleAttributes(null); | |||
assertNull("Result shouldn't be null", res); | |||
} | |||
/** | |||
* Tests for page boundaries | |||
*/ | |||
public void testBoxOk1() throws Exception { | |||
Rectangle res = PageBoundariesAttributes.getBleedBoxRectangle(TEST_AREA, null); | |||
assertSame("Result should be the same as TEST_AREA object", res, TEST_AREA); | |||
res = PageBoundariesAttributes.getBleedBoxRectangle(null, BLEED1); | |||
assertNull(res); | |||
} | |||
public void testBoxOk2() throws Exception { | |||
Rectangle res1 = PageBoundariesAttributes.getBleedBoxRectangle(TEST_AREA, BLEED1); | |||
assertNotNull("Expected not null object", res1); | |||
assertEquals(-5000, res1.getX(), 1); | |||
assertEquals(-5000, res1.getY(), 1); | |||
assertEquals(30000, res1.getWidth(), 1); | |||
assertEquals(25000, res1.getHeight(), 1); | |||
Rectangle res2 = PageBoundariesAttributes.getMediaBoxRectangle(TEST_AREA, CROP_OFFSET1); | |||
assertNotNull("Expected not null object", res2); | |||
assertEquals(-8000, res2.getX(), 1); | |||
assertEquals(-8000, res2.getY(), 1); | |||
assertEquals(36000, res2.getWidth(), 1); | |||
assertEquals(31000, res2.getHeight(), 1); | |||
Rectangle res3 = PageBoundariesAttributes.getCropBoxRectangle( | |||
TEST_AREA, res1, res2, "media-box"); | |||
assertNotNull("Expected not null object", res3); | |||
assertEquals(res3, res2); | |||
res3 = PageBoundariesAttributes.getCropBoxRectangle( | |||
TEST_AREA, res1, res2, "bleed-box"); | |||
assertNotNull("Expected not null object", res3); | |||
assertEquals(res3, res1); | |||
res3 = PageBoundariesAttributes.getCropBoxRectangle( | |||
TEST_AREA, res1, res2, "trim-box"); | |||
assertNotNull("Expected not null object", res3); | |||
assertEquals(res3, TEST_AREA); | |||
} | |||
public void testBoxIllArgExc() throws Exception { | |||
try { | |||
Rectangle res = PageBoundariesAttributes.getBleedBoxRectangle(TEST_AREA, "0"); | |||
fail("Expected IllegalArgumentException. Box should have units"); | |||
} catch (IllegalArgumentException iae) { | |||
// Good! | |||
} | |||
} | |||
} |