org.apache.fop.render.extensions.prepress.PageBoundaries Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* 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: PageBoundaries.java 802752 2009-08-10 11:16:45Z vhennebert $ */
package org.apache.fop.render.extensions.prepress;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.text.MessageFormat;
import java.util.Map;
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 is used to calculate the effective boundaries of a page including special-purpose
* boxes used in prepress. These are specified using extension attributes:
* bleedBox, trimBox and cropBox. The semantics are further described on the website.
*/
public class PageBoundaries {
/**
* 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)$");
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
private Rectangle trimBox;
private Rectangle bleedBox;
private Rectangle mediaBox;
private Rectangle cropBox;
/**
* Creates a new instance.
* @param pageSize the page size (in mpt) defined by the simple-page-master.
* @param bleed the bleed value (raw value as given in the property value)
* @param cropOffset the crop-offset value (raw value as given in the property value)
* @param cropBoxSelector the crop-box, valid values: (trim-box|bleed-box|media-box)
*/
public PageBoundaries(Dimension pageSize, String bleed, String cropOffset,
String cropBoxSelector) {
calculate(pageSize, bleed, cropOffset, cropBoxSelector);
}
/**
* Creates a new instance.
* @param pageSize the page size (in mpt) defined by the simple-page-master.
* @param foreignAttributes the foreign attributes for the page
* (used to extract the extension attribute values)
*/
public PageBoundaries(Dimension pageSize, Map foreignAttributes) {
String bleed = (String)foreignAttributes.get(EXT_BLEED);
String cropOffset = (String)foreignAttributes.get(EXT_CROP_OFFSET);
String cropBoxSelector = (String)foreignAttributes.get(EXT_CROP_BOX);
calculate(pageSize, bleed, cropOffset, cropBoxSelector);
}
private void calculate(Dimension pageSize, String bleed, String cropOffset,
String cropBoxSelector) {
this.trimBox = new Rectangle(pageSize);
this.bleedBox = getBleedBoxRectangle(this.trimBox, bleed);
Rectangle cropMarksBox = getCropMarksAreaRectangle(trimBox, cropOffset);
//MediaBox includes all of the following three rectangles
this.mediaBox = new Rectangle();
this.mediaBox.add(this.trimBox);
this.mediaBox.add(this.bleedBox);
this.mediaBox.add(cropMarksBox);
if ("trim-box".equals(cropBoxSelector)) {
this.cropBox = this.trimBox;
} else if ("bleed-box".equals(cropBoxSelector)) {
this.cropBox = this.bleedBox;
} else if ("media-box".equals(cropBoxSelector)
|| cropBoxSelector == null
|| "".equals(cropBoxSelector)) {
this.cropBox = this.mediaBox;
} else {
final String err = "The crop-box has invalid value: {0}, "
+ "possible values of crop-box: (trim-box|bleed-box|media-box)";
throw new IllegalArgumentException(MessageFormat.format(err,
new Object[]{cropBoxSelector}));
}
}
/**
* Returns the trim box for the page. This is equal to the page size given in XSL-FO.
* After production the printed media is trimmed to this rectangle.
* @return the trim box
*/
public Rectangle getTrimBox() {
return this.trimBox;
}
/**
* Returns the bleed box for the page.
* @return the bleed box
*/
public Rectangle getBleedBox() {
return this.bleedBox;
}
/**
* Returns the media box for the page.
* @return the media box
*/
public Rectangle getMediaBox() {
return this.mediaBox;
}
/**
* Returns the crop box for the page. The crop box is used by Adobe Acrobat to select which
* parts of the document shall be displayed and it also defines the rectangle to which a
* RIP will clip the document. For bitmap output, this defines the size of the bitmap.
* @return the crop box
*/
public Rectangle getCropBox() {
return this.cropBox;
}
/**
* 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
*/
private static Rectangle getBleedBoxRectangle(Rectangle trimBox, String bleed) {
return getRectangleUsingOffset(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
*/
private static Rectangle getCropMarksAreaRectangle(Rectangle trimBox, String cropOffsets) {
return getRectangleUsingOffset(trimBox, cropOffsets);
}
private static Rectangle getRectangleUsingOffset(Rectangle originalRect, String offset) {
if (offset == null || "".equals(offset) || originalRect == null) {
return originalRect;
}
String[] offsets = WHITESPACE_PATTERN.split(offset);
int[] coords = new int[4]; // top, right, bottom, left
switch (offsets.length) {
case 1:
coords[0] = getLengthIntValue(offsets[0]);
coords[1] = coords[0];
coords[2] = coords[0];
coords[3] = coords[0];
break;
case 2:
coords[0] = getLengthIntValue(offsets[0]);
coords[1] = getLengthIntValue(offsets[1]);
coords[2] = coords[0];
coords[3] = coords[1];
break;
case 3:
coords[0] = getLengthIntValue(offsets[0]);
coords[1] = getLengthIntValue(offsets[1]);
coords[2] = getLengthIntValue(offsets[2]);
coords[3] = coords[1];
break;
case 4:
coords[0] = getLengthIntValue(offsets[0]);
coords[1] = getLengthIntValue(offsets[1]);
coords[2] = getLengthIntValue(offsets[2]);
coords[3] = getLengthIntValue(offsets[3]);
break;
default:
// TODO throw appropriate exception that can be caught by the event
// notification mechanism
throw new IllegalArgumentException("Too many arguments");
}
return new Rectangle(originalRect.x - coords[3],
originalRect.y - coords[0],
originalRect.width + coords[3] + coords[1],
originalRect.height + 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}));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy