git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ChangingIPDHack@800320 13f79535-47bb-0310-9956-ffa450edef68Temp_ChangingIPDHack
@@ -355,12 +355,13 @@ list of possible build targets. | |||
<fileset dir="${src.java.dir}"> | |||
<include name="**/*.java"/> | |||
<exclude name="org/apache/fop/render/*/**/*.java"/> | |||
<exclude name="org/apache/fop/afp/**/*.java"/> | |||
</fileset> | |||
</eventResourceGenerator> | |||
<fixcrlf file="${src.java.dir}/org/apache/fop/events/EventFormatter.xml" tab="remove" tablength="2"/> | |||
<eventResourceGenerator modelfile="${build.gensrc.dir}/org/apache/fop/afp/event-model.xml" translationfile="${src.java.dir}/org/apache/fop/afp/AFPEventProducer.xml"> | |||
<fileset dir="${src.java.dir}"> | |||
<include name="org/apache/fop/render/afp/**/*.java"/> | |||
<include name="org/apache/fop/afp/**/*.java"/> | |||
</fileset> | |||
</eventResourceGenerator> | |||
<fixcrlf file="${src.java.dir}/org/apache/fop/afp/AFPEventProducer.xml" tab="remove" tablength="2"/> | |||
@@ -1006,7 +1007,15 @@ NOTE: | |||
<property name="javadoc.level" value=""/> | |||
<echo message="Producing the javadoc files${javadoc.level}"/> | |||
<mkdir dir="${build.javadocs.dir}"/> | |||
<javadoc packagenames="${javadoc.packages}" destdir="${build.javadocs.dir}" author="true" version="true" windowtitle="${Name} ${version} API" doctitle="Apache Formatting Objects Processor (FOP)" bottom="Copyright ${year} The Apache Software Foundation. All Rights Reserved." overview="${src.dir}/java/org/apache/fop/overview.html" use="true" failonerror="true" source="${javac.source}" public="${javadoc.public}" package="${javadoc.package}" private="${javadoc.private}" maxmemory="128M"> | |||
<javadoc failonerror="true" source="${javac.source}" destdir="${build.javadocs.dir}" | |||
packagenames="${javadoc.packages}" | |||
public="${javadoc.public}" package="${javadoc.package}" private="${javadoc.private}" | |||
author="true" version="true" use="true" | |||
windowtitle="${Name} ${version} API" | |||
doctitle="Apache Formatting Objects Processor (FOP)" | |||
bottom="Copyright ${year} The Apache Software Foundation. All Rights Reserved." | |||
overview="${src.dir}/java/org/apache/fop/overview.html" | |||
maxmemory="256M"> | |||
<header><![CDATA[${name} ${version}]]></header> | |||
<footer><![CDATA[${name} ${version}]]></footer> | |||
<classpath> |
@@ -0,0 +1,155 @@ | |||
<?xml version="1.0" encoding="ISO-8859-1"?> | |||
<!-- | |||
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$ --> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" | |||
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" | |||
font-family="sans-serif" font-size="9pt"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="business-card" | |||
page-width="84mm" page-height="53mm" | |||
fox:bleed="3mm" fox:crop-box="media-box" fox:crop-offset="10mm" fox:scale="4"> | |||
<fo:region-body margin-bottom="3mm" margin-left="3mm" margin-right="3mm"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="business-card"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block-container id="crop-marks" absolute-position="fixed"> | |||
<fo:block line-height="1" font-size="0pt"> | |||
<fo:instream-foreign-object> | |||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" | |||
xmlns:xlink="http://www.w3.org/1999/xlink" | |||
width="84mm" height="53mm" viewBox="0 0 84 53" overflow="visible"> | |||
<style type="text/css"><![CDATA[ | |||
.line { fill:none; stroke:black; stroke-width:0.1 } | |||
.colorbox { stroke:black; stroke-width:0.1 } | |||
]]></style> | |||
<defs> | |||
<rect id="box" class="colorbox" width="5" height="4"/> | |||
</defs> | |||
<g id="cut-marks"> | |||
<polyline class="line" points="0,-3 0,-10" /> | |||
<polyline class="line" points="84,-3 84,-10" /> | |||
<polyline class="line" points="-3,0 -10,0" /> | |||
<polyline class="line" points="-3,53 -10,53" /> | |||
<polyline class="line" points="0,56 0,63" /> | |||
<polyline class="line" points="84,56 84,63" /> | |||
<polyline class="line" points="87,0 94,0" /> | |||
<polyline class="line" points="87,53 94,53" /> | |||
</g> | |||
<g id="grays" transform="translate(88,4)"> | |||
<use xlink:href="#box" y="0" style="fill:rgb(0%,0%,0%)"/> | |||
<use xlink:href="#box" y="4" style="fill:rgb(10%,10%,10%)"/> | |||
<use xlink:href="#box" y="8" style="fill:rgb(20%,20%,20%)"/> | |||
<use xlink:href="#box" y="12" style="fill:rgb(30%,30%,30%)"/> | |||
<use xlink:href="#box" y="16" style="fill:rgb(40%,40%,40%)"/> | |||
<use xlink:href="#box" y="20" style="fill:rgb(50%,50%,50%)"/> | |||
<use xlink:href="#box" y="24" style="fill:rgb(60%,60%,60%)"/> | |||
<use xlink:href="#box" y="28" style="fill:rgb(70%,70%,70%)"/> | |||
<use xlink:href="#box" y="32" style="fill:rgb(80%,80%,80%)"/> | |||
<use xlink:href="#box" y="36" style="fill:rgb(90%,90%,90%)"/> | |||
<use xlink:href="#box" y="40" style="fill:rgb(100%,100%,100%)"/> | |||
</g> | |||
<g id="cyan" transform="translate(4,-9)"> | |||
<use xlink:href="#box" x="0" style="fill:rgb(0%,100%,100%)"/> | |||
<use xlink:href="#box" x="5" style="fill:rgb(5%,100%,100%)"/> | |||
<use xlink:href="#box" x="10" style="fill:rgb(25%,100%,100%)"/> | |||
<use xlink:href="#box" x="15" style="fill:rgb(50%,100%,100%)"/> | |||
<use xlink:href="#box" x="20" style="fill:rgb(75%,100%,100%)"/> | |||
<use xlink:href="#box" x="25" style="fill:rgb(95%,100%,100%)"/> | |||
</g> | |||
<g id="magenta" transform="translate(50,-9)"> | |||
<use xlink:href="#box" x="0" style="fill:rgb(100%,0%,100%)"/> | |||
<use xlink:href="#box" x="5" style="fill:rgb(100%,5%,100%)"/> | |||
<use xlink:href="#box" x="10" style="fill:rgb(100%,25%,100%)"/> | |||
<use xlink:href="#box" x="15" style="fill:rgb(100%,50%,100%)"/> | |||
<use xlink:href="#box" x="20" style="fill:rgb(100%,75%,100%)"/> | |||
<use xlink:href="#box" x="25" style="fill:rgb(100%,95%,100%)"/> | |||
</g> | |||
<g id="yellow" transform="translate(4,58)"> | |||
<use xlink:href="#box" x="0" style="fill:rgb(100%,100%,0%)"/> | |||
<use xlink:href="#box" x="5" style="fill:rgb(100%,100%,5%)"/> | |||
<use xlink:href="#box" x="10" style="fill:rgb(100%,100%,25%)"/> | |||
<use xlink:href="#box" x="15" style="fill:rgb(100%,100%,50%)"/> | |||
<use xlink:href="#box" x="20" style="fill:rgb(100%,100%,75%)"/> | |||
<use xlink:href="#box" x="25" style="fill:rgb(100%,100%,95%)"/> | |||
</g> | |||
<g id="base-colors" transform="translate(50,58)"> | |||
<use xlink:href="#box" x="0" style="fill:red"/> | |||
<use xlink:href="#box" x="5" style="fill:green"/> | |||
<use xlink:href="#box" x="10" style="fill:blue"/> | |||
<use xlink:href="#box" x="15" style="fill:cyan"/> | |||
<use xlink:href="#box" x="20" style="fill:magenta"/> | |||
<use xlink:href="#box" x="25" style="fill:yellow"/> | |||
</g> | |||
</svg> | |||
</fo:instream-foreign-object> | |||
</fo:block> | |||
</fo:block-container> | |||
<fo:block-container id="background" absolute-position="fixed" | |||
inline-progression-dimension="84mm" block-progression-dimension="14mm" | |||
overflow="visible"> | |||
<fo:block line-height="1" font-size="0pt"> | |||
<fo:instream-foreign-object> | |||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" | |||
width="84mm" height="14mm" viewBox="0 0 84 14" overflow="visible"> | |||
<defs> | |||
<linearGradient id="MyGradient"> | |||
<stop offset="0%" stop-color="#FF0000"/> | |||
<stop offset="30%" stop-color="#FF0000"/> | |||
<stop offset="55%" stop-color="#FFFFFF"/> | |||
<stop offset="100%" stop-color="#FFFFFF"/> | |||
</linearGradient> | |||
</defs> | |||
<rect x="-3" y="-3" width="87" height="17" style="fill:url(#MyGradient); stroke:none"/> | |||
</svg> | |||
</fo:instream-foreign-object> | |||
</fo:block> | |||
</fo:block-container> | |||
<fo:block-container block-progression-dimension="14mm" display-align="center"> | |||
<fo:block font-weight="bold" font-size="9mm" line-height="1.5" color="white">ACME</fo:block> | |||
</fo:block-container> | |||
<fo:block start-indent="3mm" end-indent="3mm"/> | |||
<fo:block text-align="end" space-before="3mm" space-before.conditionality="retain"> | |||
<fo:block font-size="14pt" font-weight="bold" space-after="2mm"> | |||
Pepé Le Pew | |||
</fo:block> | |||
<fo:block font-size="12pt" space-after="4mm"> | |||
Expert d'Amour | |||
</fo:block> | |||
</fo:block> | |||
<fo:block> | |||
<fo:block>13 Pleasantstreet</fo:block> | |||
<fo:block>Acme Acres</fo:block> | |||
<fo:block>+1 (23) 456-7890</fo:block> | |||
<fo:block>pepe@looney.toon</fo:block> | |||
</fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> |
@@ -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> |
@@ -422,6 +422,28 @@ out = proc.getOutputStream();]]></source> | |||
Consult the technical reference for your printer for all available values. | |||
</p> | |||
</section> | |||
<section id="pcl-output-bin"> | |||
<title>Output Bin</title> | |||
<p> | |||
The <code>output-bin</code> extension attribute on fo:simple-page-master allows to | |||
select the output bin into which the printed output should be fed. Example: | |||
</p> | |||
<source><![CDATA[ | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="simple" pcl:output-bin="2"> | |||
... | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
]]></source> | |||
<p> | |||
Note: the output bin number is a positive integer and the value depends on | |||
the target printer. Not all PCL printers support the same output bins. | |||
Usually, | |||
"1" is the upper output bin, | |||
"2" is the lower (rear) output bin. | |||
Consult the technical reference for your printer for all available values. | |||
</p> | |||
</section> | |||
<section id="pcl-duplex-mode"> | |||
<title>Page Duplex Mode</title> | |||
<p> | |||
@@ -651,6 +673,11 @@ out = proc.getOutputStream();]]></source> | |||
<font-triplet name="monospace" style="normal" weight="bold"/> | |||
<font-triplet name="Courier" style="normal" weight="bold"/> | |||
</font>]]></source> | |||
<p> | |||
By default, all manually configured fonts are embedded, unless they are matched in the | |||
<a href="fonts.html#embedding"><code>referenced-fonts</code> section of the configuration file</a>. | |||
However, the default fonts shown above will not be embedded. | |||
</p> | |||
</section> | |||
<section id="afp-renderer-resolution-config"> | |||
<title>Output Resolution</title> | |||
@@ -836,6 +863,35 @@ out = proc.getOutputStream();]]></source> | |||
available on the target platform. | |||
</p> | |||
</section> | |||
<section id="afp-form-maps"> | |||
<title>Form Maps/Defs</title> | |||
<p> | |||
Apache FOP supports embedding an external form map resource in the | |||
generated AFP output. This is done using the <code>afp:include-form-map</code> | |||
extension. An example: | |||
</p> | |||
<source><![CDATA[ | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" | |||
xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp"> | |||
[..] | |||
<fo:declarations> | |||
<afp:include-form-map name="F1SAMP1" src="file:f1samp1.fde"/> | |||
</fo:declarations> | |||
]]></source> | |||
<p> | |||
The <code>afp:include-form-map</code> is to be placed as a direct child of | |||
<code>fo:declarations</code>. The <code>name</code> is an AFP resource name | |||
(max. 8 characters) and the <code>src</code> attribute is the URI identifying the | |||
external form map resource. When such a form map is embedded, you can use the | |||
<code>afp:invoke-medium-map</code> extension (described above) to invoke any medium | |||
map included in the form map. | |||
</p> | |||
<note> | |||
Apache FOP doesn't support a way to define a form map or medium map using XML means | |||
inside an XSL-FO document. You will have to build the form map with some third-party | |||
tool. | |||
</note> | |||
</section> | |||
</section> | |||
<section id="afp-foreign-attributes"> | |||
<title>Foreign Attributes</title> |
@@ -1,5 +1,5 @@ | |||
org.apache.fop.events.FOPEventModelFactory | |||
org.apache.fop.render.afp.AFPEventProducer$EventModelFactory | |||
org.apache.fop.afp.AFPEventProducer$EventModelFactory | |||
org.apache.fop.render.bitmap.BitmapRendererEventProducer$EventModelFactory | |||
org.apache.fop.render.pcl.PCLEventProducer$EventModelFactory | |||
org.apache.fop.render.pdf.PDFEventProducer$EventModelFactory |
@@ -80,4 +80,14 @@ public interface AFPEventProducer extends EventProducer { | |||
* @event.severity ERROR | |||
*/ | |||
void characterSetEncodingError(Object source, String charSetName, String encoding); | |||
/** | |||
* Triggered when an external resource fails to be embedded. | |||
* | |||
* @param source the event source | |||
* @param resourceName the name of the resource where the error occurred | |||
* @param e the original exception | |||
* @event.severity ERROR | |||
*/ | |||
void resourceEmbeddingError(Object source, String resourceName, Exception e); | |||
} |
@@ -3,4 +3,5 @@ | |||
<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message> | |||
<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont">No AFP default "any", {style}, {weight} font configured.</message> | |||
<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError">An error occurred when attempting to encode character set {charSetName} with encoding scheme {encoding}.</message> | |||
<message key="org.apache.fop.afp.AFPEventProducer.resourceEmbeddingError">An error occurs while embedding the resource named "{resourceName}".[ Reason: {e}]</message> | |||
</catalogue> |
@@ -28,6 +28,8 @@ import java.util.Map; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.afp.fonts.AFPFont; | |||
import org.apache.fop.afp.fonts.CharacterSet; | |||
import org.apache.fop.afp.modca.AbstractNamedAFPObject; | |||
import org.apache.fop.afp.modca.AbstractPageObject; | |||
import org.apache.fop.afp.modca.IncludeObject; | |||
@@ -169,7 +171,7 @@ public class AFPResourceManager { | |||
useInclude &= resourceGroup != null; | |||
if (useInclude) { | |||
boolean usePageSegment = dataObjectInfo.isCreatePageSegment(); | |||
// if it is to reside within a resource group at print-file or external level | |||
if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) { | |||
if (usePageSegment) { | |||
@@ -179,14 +181,14 @@ public class AFPResourceManager { | |||
seg.addObject(namedObj); | |||
namedObj = seg; | |||
} | |||
// wrap newly created data object in a resource object | |||
namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType); | |||
} | |||
// add data object into its resource group destination | |||
resourceGroup.addObject(namedObj); | |||
// create the include object | |||
objectName = namedObj.getName(); | |||
if (usePageSegment) { | |||
@@ -217,10 +219,32 @@ public class AFPResourceManager { | |||
private void includeObject(AFPDataObjectInfo dataObjectInfo, | |||
String objectName) { | |||
IncludeObject includeObject | |||
= dataObjectFactory.createInclude(objectName, dataObjectInfo); | |||
dataStream.getCurrentPage().addObject(includeObject); | |||
IncludeObject includeObject | |||
= dataObjectFactory.createInclude(objectName, dataObjectInfo); | |||
dataStream.getCurrentPage().addObject(includeObject); | |||
} | |||
/** | |||
* Handles font embedding. If a font is embeddable and has not already been embedded it will be. | |||
* @param afpFont the AFP font to be checked for embedding | |||
* @param charSet the associated character set | |||
* @throws IOException if there's a problem while embedding the external resources | |||
*/ | |||
public void embedFont(AFPFont afpFont, CharacterSet charSet) | |||
throws IOException { | |||
if (afpFont.isEmbeddable()) { | |||
//Embed fonts (char sets and code pages) | |||
if (charSet.getResourceAccessor() != null) { | |||
ResourceAccessor accessor = charSet.getResourceAccessor(); | |||
createIncludedResource( | |||
charSet.getName(), accessor, | |||
ResourceObject.TYPE_FONT_CHARACTER_SET); | |||
createIncludedResource( | |||
charSet.getCodePage(), accessor, | |||
ResourceObject.TYPE_CODE_PAGE); | |||
} | |||
} | |||
} | |||
private void includePageSegment(AFPDataObjectInfo dataObjectInfo, | |||
String pageSegmentName) { | |||
@@ -240,7 +264,6 @@ public class AFPResourceManager { | |||
*/ | |||
public void createIncludedResource(String resourceName, ResourceAccessor accessor, | |||
byte resourceObjectType) throws IOException { | |||
AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE); | |||
URI uri; | |||
try { | |||
uri = new URI(resourceName.trim()); | |||
@@ -249,6 +272,21 @@ public class AFPResourceManager { | |||
+ " (" + e.getMessage() + ")"); | |||
} | |||
createIncludedResource(resourceName, uri, accessor, resourceObjectType); | |||
} | |||
/** | |||
* Creates an included resource object by loading the contained object from a file. | |||
* @param resourceName the name of the resource | |||
* @param uri the URI for the resource | |||
* @param accessor resource accessor to access the resource with | |||
* @param resourceObjectType the resource object type ({@link ResourceObject}.*) | |||
* @throws IOException if an I/O error occurs while loading the resource | |||
*/ | |||
public void createIncludedResource(String resourceName, URI uri, ResourceAccessor accessor, | |||
byte resourceObjectType) throws IOException { | |||
AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE); | |||
AFPResourceInfo resourceInfo = new AFPResourceInfo(); | |||
resourceInfo.setLevel(resourceLevel); | |||
resourceInfo.setName(resourceName); |
@@ -80,22 +80,22 @@ public class AFPBase12FontCollection implements FontCollection { | |||
/** standard font family reference names for Helvetica font */ | |||
final String[] helveticaNames = {"Helvetica", "Arial", "sans-serif"}; | |||
font = new RasterFont("Helvetica"); | |||
font = createReferencedRasterFont("Helvetica"); | |||
addCharacterSet(font, "C0H200", new Helvetica()); | |||
num = addFontProperties(fontInfo, font, helveticaNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Helvetica Italic"); | |||
font = createReferencedRasterFont("Helvetica Italic"); | |||
addCharacterSet(font, "C0H300", new HelveticaOblique()); | |||
num = addFontProperties(fontInfo, font, helveticaNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Helvetica (Semi) Bold"); | |||
font = createReferencedRasterFont("Helvetica (Semi) Bold"); | |||
addCharacterSet(font, "C0H400", new HelveticaBold()); | |||
num = addFontProperties(fontInfo, font, helveticaNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); | |||
font = new RasterFont("Helvetica Italic (Semi) Bold"); | |||
font = createReferencedRasterFont("Helvetica Italic (Semi) Bold"); | |||
addCharacterSet(font, "C0H500", new HelveticaOblique()); | |||
num = addFontProperties(fontInfo, font, helveticaNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); | |||
@@ -107,22 +107,22 @@ public class AFPBase12FontCollection implements FontCollection { | |||
final String[] timesNames = {"Times", "TimesRoman", "Times Roman", "Times-Roman", | |||
"Times New Roman", "TimesNewRoman", "serif", "any"}; | |||
font = new RasterFont("Times Roman"); | |||
font = createReferencedRasterFont("Times Roman"); | |||
addCharacterSet(font, "CON200", new TimesRoman()); | |||
num = addFontProperties(fontInfo, font, timesNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Times Roman Italic"); | |||
font = createReferencedRasterFont("Times Roman Italic"); | |||
addCharacterSet(font, "CON300", new TimesItalic()); | |||
num = addFontProperties(fontInfo, font, timesNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Times Roman Bold"); | |||
font = createReferencedRasterFont("Times Roman Bold"); | |||
addCharacterSet(font, "CON400", new TimesBold()); | |||
num = addFontProperties(fontInfo, font, timesNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); | |||
font = new RasterFont("Times Roman Italic Bold"); | |||
font = createReferencedRasterFont("Times Roman Italic Bold"); | |||
addCharacterSet(font, "CON500", new TimesBoldItalic()); | |||
num = addFontProperties(fontInfo, font, timesNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); | |||
@@ -131,22 +131,22 @@ public class AFPBase12FontCollection implements FontCollection { | |||
/** standard font family reference names for Courier font */ | |||
final String[] courierNames = {"Courier", "monospace"}; | |||
font = new RasterFont("Courier"); | |||
font = createReferencedRasterFont("Courier"); | |||
addCharacterSet(font, "C04200", new Courier()); | |||
num = addFontProperties(fontInfo, font, courierNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Courier Italic"); | |||
font = createReferencedRasterFont("Courier Italic"); | |||
addCharacterSet(font, "C04300", new CourierOblique()); | |||
num = addFontProperties(fontInfo, font, courierNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); | |||
font = new RasterFont("Courier Bold"); | |||
font = createReferencedRasterFont("Courier Bold"); | |||
addCharacterSet(font, "C04400", new CourierBold()); | |||
num = addFontProperties(fontInfo, font, courierNames, | |||
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); | |||
font = new RasterFont("Courier Italic Bold"); | |||
font = createReferencedRasterFont("Courier Italic Bold"); | |||
addCharacterSet(font, "C04500", new CourierBoldOblique()); | |||
num = addFontProperties(fontInfo, font, courierNames, | |||
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); | |||
@@ -154,4 +154,10 @@ public class AFPBase12FontCollection implements FontCollection { | |||
return num; | |||
} | |||
private RasterFont createReferencedRasterFont(String fontFamily) { | |||
RasterFont font = new RasterFont(fontFamily); | |||
font.setEmbeddable(false); //Font is assumed to be available on the target platform | |||
return font; | |||
} | |||
} |
@@ -36,6 +36,8 @@ public abstract class AFPFont extends Typeface { | |||
/** The font name */ | |||
protected String name; | |||
private boolean embeddable = true; | |||
/** | |||
* Constructor for the base font requires the name. | |||
* @param name the name of the font | |||
@@ -97,12 +99,20 @@ public abstract class AFPFont extends Typeface { | |||
*/ | |||
public abstract CharacterSet getCharacterSet(int size); | |||
/** | |||
* Controls whether this font is embeddable or not. | |||
* @param value true to enable embedding, false otherwise. | |||
*/ | |||
public void setEmbeddable(boolean value) { | |||
this.embeddable = value; | |||
} | |||
/** | |||
* Indicates if this font may be embedded. | |||
* @return True, if embedding is possible/permitted | |||
*/ | |||
public boolean isEmbeddable() { | |||
return false; //TODO Complete AFP font embedding | |||
return this.embeddable; | |||
} | |||
/** {@inheritDoc} */ |
@@ -99,9 +99,13 @@ public class RasterFont extends AFPFont { | |||
int largerSize = largerSizes.isEmpty() ? Integer.MAX_VALUE | |||
: ((Integer)largerSizes.firstKey()).intValue(); | |||
Integer fontSize | |||
= (size - smallerSize) <= (largerSize - size) | |||
? new Integer(smallerSize) : new Integer(largerSize); | |||
Integer fontSize; | |||
if (!smallerSizes.isEmpty() | |||
&& (size - smallerSize) <= (largerSize - size)) { | |||
fontSize = new Integer(smallerSize); | |||
} else { | |||
fontSize = new Integer(largerSize); | |||
} | |||
csm = (CharacterSet) charSets.get(fontSize); | |||
if (csm != null) { |
@@ -63,8 +63,10 @@ public class DefaultFOPResourceAccessor extends SimpleResourceAccessor { | |||
URI resolved = resolveAgainstBase(uri); | |||
//Step 2: resolve against the user agent --> stream | |||
Source src; | |||
src = userAgent.resolveURI(resolved.toASCIIString(), this.categoryBaseURI); | |||
String base = (this.categoryBaseURI != null | |||
? this.categoryBaseURI | |||
: this.userAgent.getBaseURL()); | |||
Source src = userAgent.resolveURI(resolved.toASCIIString(), base); | |||
if (src == null) { | |||
throw new FileNotFoundException("Resource not found: " + uri.toASCIIString()); |
@@ -20,6 +20,7 @@ | |||
package org.apache.fop.area; | |||
import java.awt.Color; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.Rectangle2D; | |||
import java.io.FileNotFoundException; | |||
import java.io.IOException; | |||
@@ -38,9 +39,10 @@ import javax.xml.transform.sax.SAXResult; | |||
import javax.xml.transform.sax.SAXTransformerFactory; | |||
import javax.xml.transform.sax.TransformerHandler; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.w3c.dom.DOMImplementation; | |||
import org.w3c.dom.Document; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.ContentHandler; | |||
import org.xml.sax.Locator; | |||
@@ -48,9 +50,6 @@ import org.xml.sax.SAXException; | |||
import org.xml.sax.helpers.AttributesImpl; | |||
import org.xml.sax.helpers.DefaultHandler; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.xmlgraphics.image.loader.ImageException; | |||
import org.apache.xmlgraphics.image.loader.ImageInfo; | |||
import org.apache.xmlgraphics.image.loader.ImageManager; | |||
@@ -403,7 +402,7 @@ public class AreaTreeParser { | |||
if (currentPageViewport != null) { | |||
throw new IllegalStateException("currentPageViewport must be null"); | |||
} | |||
Rectangle2D viewArea = XMLUtil.getAttributeAsRectangle2D(attributes, "bounds"); | |||
Rectangle viewArea = XMLUtil.getAttributeAsRectangle(attributes, "bounds"); | |||
int pageNumber = XMLUtil.getAttributeAsInt(attributes, "nr", -1); | |||
String key = attributes.getValue("key"); | |||
String pageNumberString = attributes.getValue("formatted-nr"); |
@@ -20,7 +20,6 @@ | |||
package org.apache.fop.area; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.Rectangle2D; | |||
import java.io.IOException; | |||
import java.io.ObjectInputStream; | |||
import java.io.ObjectOutputStream; | |||
@@ -48,7 +47,7 @@ import org.apache.fop.fo.pagination.SimplePageMaster; | |||
public class PageViewport extends AreaTreeObject implements Resolvable, Cloneable { | |||
private Page page; | |||
private Rectangle2D viewArea; | |||
private Rectangle viewArea; | |||
private String simplePageMasterName; | |||
/** | |||
@@ -100,6 +99,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl | |||
public PageViewport(SimplePageMaster spm, int pageNumber, String pageStr, boolean blank) { | |||
this.simplePageMasterName = spm.getMasterName(); | |||
setExtensionAttachments(spm.getExtensionAttachments()); | |||
setForeignAttributes(spm.getForeignAttributes()); | |||
this.blank = blank; | |||
int pageWidth = spm.getPageWidth().getValue(); | |||
int pageHeight = spm.getPageHeight().getValue(); | |||
@@ -118,11 +118,14 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl | |||
if (original.extensionAttachments != null) { | |||
setExtensionAttachments(original.extensionAttachments); | |||
} | |||
if (original.foreignAttributes != null) { | |||
setForeignAttributes(original.foreignAttributes); | |||
} | |||
this.pageIndex = original.pageIndex; | |||
this.pageNumber = original.pageNumber; | |||
this.pageNumberString = original.pageNumberString; | |||
this.page = (Page)original.page.clone(); | |||
this.viewArea = (Rectangle2D)original.viewArea.clone(); | |||
this.viewArea = new Rectangle(original.viewArea); | |||
this.simplePageMasterName = original.simplePageMasterName; | |||
this.blank = original.blank; | |||
} | |||
@@ -135,7 +138,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl | |||
* @param simplePageMasterName name of the original simple-page-master that generated this page | |||
* @param blank true if this is a blank page | |||
*/ | |||
public PageViewport(Rectangle2D viewArea, int pageNumber, String pageStr, | |||
public PageViewport(Rectangle viewArea, int pageNumber, String pageStr, | |||
String simplePageMasterName, boolean blank) { | |||
this.viewArea = viewArea; | |||
this.pageNumber = pageNumber; | |||
@@ -161,7 +164,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl | |||
* Get the view area rectangle of this viewport. | |||
* @return the rectangle for this viewport | |||
*/ | |||
public Rectangle2D getViewArea() { | |||
public Rectangle getViewArea() { | |||
return viewArea; | |||
} | |||
@@ -105,7 +105,4 @@ Any reference to it will be considered a reference to the first occurrence in th | |||
<message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message> | |||
<message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message> | |||
<message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> | |||
<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup"/> | |||
<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont"/> | |||
<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError"/> | |||
</catalogue> |
@@ -19,7 +19,7 @@ | |||
package org.apache.fop.layoutmgr; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.Rectangle; | |||
import org.apache.fop.area.PageViewport; | |||
import org.apache.fop.fo.pagination.SimplePageMaster; | |||
@@ -54,7 +54,7 @@ public class Page { | |||
* @param pageNumberStr the page number (as a String) | |||
* @param blank true if this is a blank page | |||
*/ | |||
public Page(Rectangle2D viewArea, int pageNumber, String pageNumberStr, boolean blank) { | |||
public Page(Rectangle viewArea, int pageNumber, String pageNumberStr, boolean blank) { | |||
this.spm = null; | |||
this.pageViewport = new PageViewport(viewArea, pageNumber, pageNumberStr, null, blank); | |||
} |
@@ -174,27 +174,42 @@ public class PDFFactory { | |||
* PDFDocument later using addObject(). | |||
* | |||
* @param resources resources object to use | |||
* @param pageWidth width of the page in points | |||
* @param pageHeight height of the page in points | |||
* @param pageIndex index of the page (zero-based) | |||
* @param mediaBox the MediaBox area | |||
* @param cropBox the CropBox area | |||
* @param bleedBox the BleedBox area | |||
* @param trimBox the TrimBox area | |||
* | |||
* @return the created /Page object | |||
*/ | |||
public PDFPage makePage(PDFResources resources, | |||
int pageWidth, int pageHeight, int pageIndex) { | |||
/* | |||
* create a PDFPage with the next object number, the given | |||
* resources, contents and dimensions | |||
*/ | |||
PDFPage page = new PDFPage(resources, | |||
pageWidth, pageHeight, pageIndex); | |||
public PDFPage makePage(PDFResources resources, int pageIndex, | |||
Rectangle2D mediaBox, Rectangle2D cropBox, | |||
Rectangle2D bleedBox, Rectangle2D trimBox) { | |||
PDFPage page = new PDFPage(resources, pageIndex, mediaBox, cropBox, bleedBox, trimBox); | |||
getDocument().assignObjectNumber(page); | |||
getDocument().getPages().addPage(page); | |||
return page; | |||
} | |||
/** | |||
* Make a /Page object. The page is assigned an object number immediately | |||
* so references can already be made. The page must be added to the | |||
* PDFDocument later using addObject(). | |||
* | |||
* @param resources resources object to use | |||
* @param pageWidth width of the page in points | |||
* @param pageHeight height of the page in points | |||
* @param pageIndex index of the page (zero-based) | |||
* | |||
* @return the created /Page object | |||
*/ | |||
public PDFPage makePage(PDFResources resources, | |||
int pageWidth, int pageHeight, int pageIndex) { | |||
Rectangle2D mediaBox = new Rectangle2D.Double(0, 0, pageWidth, pageHeight); | |||
return makePage(resources, pageIndex, mediaBox, mediaBox, mediaBox, mediaBox); | |||
} | |||
/** | |||
* Make a /Page object. The page is assigned an object number immediately | |||
* so references can already be made. The page must be added to the |
@@ -38,42 +38,42 @@ public class PDFPage extends PDFResourceContext { | |||
* Create a /Page object | |||
* | |||
* @param resources the /Resources object | |||
* @param contents the content stream | |||
* @param pageWidth the page's width in points | |||
* @param pageHeight the page's height in points | |||
* @param pageIndex the page's zero-based index (or -1 if the page number is auto-determined) | |||
* @param mediaBox the MediaBox | |||
* @param cropBox the CropBox. If null, mediaBox is used. | |||
* @param bleedBox the BleedBox. If null, cropBox is used. | |||
* @param trimBox the TrimBox. If null, bleedBox is used. | |||
*/ | |||
public PDFPage(PDFResources resources, PDFStream contents, | |||
int pageWidth, int pageHeight, int pageIndex) { | |||
public PDFPage(PDFResources resources, int pageIndex, | |||
Rectangle2D mediaBox, Rectangle2D cropBox, | |||
Rectangle2D bleedBox, Rectangle2D trimBox) { | |||
/* generic creation of object */ | |||
super(resources); | |||
put("Type", new PDFName("Page")); | |||
/* set fields using parameters */ | |||
setSimplePageSize(mediaBox, cropBox, bleedBox, trimBox); | |||
this.pageIndex = pageIndex; | |||
} | |||
/* generic creation of object */ | |||
super(resources); | |||
private void setSimplePageSize(Rectangle2D mediaBox, Rectangle2D cropBox, | |||
Rectangle2D bleedBox, Rectangle2D trimBox) { | |||
setMediaBox(mediaBox); | |||
put("Type", new PDFName("Page")); | |||
/* set fields using parameters */ | |||
setContents(contents); | |||
setSimplePageSize(pageWidth, pageHeight); | |||
this.pageIndex = pageIndex; | |||
} | |||
if (cropBox == null) { | |||
cropBox = mediaBox; | |||
} | |||
setCropBox(cropBox); | |||
/** | |||
* Create a /Page object | |||
* | |||
* @param resources the /Resources object | |||
* @param pageWidth the page's width in points | |||
* @param pageHeight the page's height in points | |||
* @param pageIndex the page's zero-based index (or -1 if the page number is auto-determined) | |||
*/ | |||
public PDFPage(PDFResources resources, | |||
int pageWidth, int pageHeight, int pageIndex) { | |||
this(resources, null, pageWidth, pageHeight, pageIndex); | |||
} | |||
if (bleedBox == null) { | |||
bleedBox = cropBox; | |||
} | |||
setBleedBox(bleedBox); //Recommended by PDF/X | |||
private void setSimplePageSize(int width, int height) { | |||
Rectangle2D box = new Rectangle2D.Double(0, 0, width, height); | |||
setMediaBox(box); | |||
setBleedBox(box); //Recommended by PDF/X | |||
setTrimBox(box); //Needed for PDF/X | |||
if (trimBox == null) { | |||
trimBox = bleedBox; | |||
} | |||
setTrimBox(trimBox); //Needed for PDF/X | |||
} | |||
private PDFArray toPDFArray(Rectangle2D box) { | |||
@@ -90,11 +90,11 @@ public class PDFPage extends PDFResourceContext { | |||
} | |||
/** | |||
* Sets the "TrimBox" entry | |||
* @param box the trim rectangle | |||
* Sets the "CropBox" entry | |||
* @param box the bleed rectangle | |||
*/ | |||
public void setTrimBox(Rectangle2D box) { | |||
put("TrimBox", toPDFArray(box)); | |||
public void setCropBox(Rectangle2D box) { | |||
put("CropBox", toPDFArray(box)); | |||
} | |||
/** | |||
@@ -105,6 +105,14 @@ public class PDFPage extends PDFResourceContext { | |||
put("BleedBox", toPDFArray(box)); | |||
} | |||
/** | |||
* Sets the "TrimBox" entry | |||
* @param box the trim rectangle | |||
*/ | |||
public void setTrimBox(Rectangle2D box) { | |||
put("TrimBox", toPDFArray(box)); | |||
} | |||
/** | |||
* set this page contents | |||
* |
@@ -35,12 +35,16 @@ import org.apache.fop.afp.AbstractAFPPainter; | |||
import org.apache.fop.afp.DataStream; | |||
import org.apache.fop.afp.fonts.AFPFontCollection; | |||
import org.apache.fop.afp.fonts.AFPPageFonts; | |||
import org.apache.fop.afp.modca.ResourceObject; | |||
import org.apache.fop.afp.util.DefaultFOPResourceAccessor; | |||
import org.apache.fop.afp.util.ResourceAccessor; | |||
import org.apache.fop.apps.MimeConstants; | |||
import org.apache.fop.fonts.FontCollection; | |||
import org.apache.fop.fonts.FontEventAdapter; | |||
import org.apache.fop.fonts.FontInfo; | |||
import org.apache.fop.fonts.FontManager; | |||
import org.apache.fop.render.afp.extensions.AFPElementMapping; | |||
import org.apache.fop.render.afp.extensions.AFPIncludeFormMap; | |||
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap; | |||
import org.apache.fop.render.afp.extensions.AFPPageSetup; | |||
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; | |||
@@ -275,7 +279,8 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler | |||
} else { | |||
if (this.location != LOC_IN_PAGE_HEADER) { | |||
throw new IFException( | |||
"AFP page setup extension encountered outside the page header: " + aps, null); | |||
"AFP page setup extension encountered outside the page header: " + aps, | |||
null); | |||
} | |||
if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { | |||
String overlay = aps.getName(); | |||
@@ -304,6 +309,18 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler | |||
if (mediumMap != null) { | |||
dataStream.createInvokeMediumMap(mediumMap); | |||
} | |||
} else if (extension instanceof AFPIncludeFormMap) { | |||
AFPIncludeFormMap formMap = (AFPIncludeFormMap)extension; | |||
ResourceAccessor accessor = new DefaultFOPResourceAccessor( | |||
getUserAgent(), null, null); | |||
try { | |||
getResourceManager().createIncludedResource(formMap.getName(), | |||
formMap.getSrc(), accessor, | |||
ResourceObject.TYPE_FORMDEF); | |||
} catch (IOException ioe) { | |||
throw new IFException( | |||
"I/O error while embedding form map resource: " + formMap.getName(), ioe); | |||
} | |||
} | |||
} | |||
@@ -46,10 +46,8 @@ import org.apache.fop.afp.fonts.AFPPageFonts; | |||
import org.apache.fop.afp.fonts.CharacterSet; | |||
import org.apache.fop.afp.modca.AbstractPageObject; | |||
import org.apache.fop.afp.modca.PresentationTextObject; | |||
import org.apache.fop.afp.modca.ResourceObject; | |||
import org.apache.fop.afp.ptoca.PtocaBuilder; | |||
import org.apache.fop.afp.ptoca.PtocaProducer; | |||
import org.apache.fop.afp.util.ResourceAccessor; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontInfo; | |||
import org.apache.fop.fonts.FontTriplet; | |||
@@ -345,17 +343,7 @@ public class AFPPainter extends AbstractIFPainter { | |||
if (afpFont.isEmbeddable()) { | |||
try { | |||
//Embed fonts (char sets and code pages) | |||
//TODO This should be moved to a place where it has less performance impact | |||
if (charSet.getResourceAccessor() != null) { | |||
ResourceAccessor accessor = charSet.getResourceAccessor(); | |||
documentHandler.getResourceManager().createIncludedResource( | |||
charSet.getName(), accessor, | |||
ResourceObject.TYPE_FONT_CHARACTER_SET); | |||
documentHandler.getResourceManager().createIncludedResource( | |||
charSet.getCodePage(), accessor, | |||
ResourceObject.TYPE_CODE_PAGE); | |||
} | |||
documentHandler.getResourceManager().embedFont(afpFont, charSet); | |||
} catch (IOException ioe) { | |||
throw new IFException("Error while embedding font resources", ioe); | |||
} |
@@ -61,10 +61,14 @@ import org.apache.fop.afp.fonts.AFPFontCollection; | |||
import org.apache.fop.afp.fonts.AFPPageFonts; | |||
import org.apache.fop.afp.fonts.CharacterSet; | |||
import org.apache.fop.afp.modca.PageObject; | |||
import org.apache.fop.afp.modca.ResourceObject; | |||
import org.apache.fop.afp.util.DefaultFOPResourceAccessor; | |||
import org.apache.fop.afp.util.ResourceAccessor; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.apps.MimeConstants; | |||
import org.apache.fop.area.CTM; | |||
import org.apache.fop.area.OffDocumentExtensionAttachment; | |||
import org.apache.fop.area.OffDocumentItem; | |||
import org.apache.fop.area.PageSequence; | |||
import org.apache.fop.area.PageViewport; | |||
@@ -83,6 +87,8 @@ import org.apache.fop.render.AbstractPathOrientedRenderer; | |||
import org.apache.fop.render.Graphics2DAdapter; | |||
import org.apache.fop.render.RendererContext; | |||
import org.apache.fop.render.afp.extensions.AFPElementMapping; | |||
import org.apache.fop.render.afp.extensions.AFPExtensionAttachment; | |||
import org.apache.fop.render.afp.extensions.AFPIncludeFormMap; | |||
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap; | |||
import org.apache.fop.render.afp.extensions.AFPPageSetup; | |||
@@ -279,8 +285,30 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust | |||
/** {@inheritDoc} */ | |||
public void processOffDocumentItem(OffDocumentItem odi) { | |||
// TODO | |||
log.debug("NYI processOffDocumentItem(" + odi + ")"); | |||
if (odi instanceof OffDocumentExtensionAttachment) { | |||
ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)odi).getAttachment(); | |||
if (attachment != null) { | |||
if (AFPExtensionAttachment.CATEGORY.equals(attachment.getCategory())) { | |||
if (attachment instanceof AFPIncludeFormMap) { | |||
handleIncludeFormMap((AFPIncludeFormMap)attachment); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
private void handleIncludeFormMap(AFPIncludeFormMap formMap) { | |||
ResourceAccessor accessor = new DefaultFOPResourceAccessor( | |||
getUserAgent(), null, null); | |||
try { | |||
this.resourceManager.createIncludedResource(formMap.getName(), | |||
formMap.getSrc(), accessor, | |||
ResourceObject.TYPE_FORMDEF); | |||
} catch (IOException ioe) { | |||
AFPEventProducer eventProducer | |||
= AFPEventProducer.Provider.get(userAgent.getEventBroadcaster()); | |||
eventProducer.resourceEmbeddingError(this, formMap.getName(), ioe); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -566,6 +594,16 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust | |||
AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize); | |||
Font fnt = getFontFromArea(text); | |||
if (font.isEmbeddable()) { | |||
CharacterSet charSet = font.getCharacterSet(fontSize); | |||
try { | |||
this.resourceManager.embedFont(font, charSet); | |||
} catch (IOException ioe) { | |||
AFPEventProducer eventProducer | |||
= AFPEventProducer.Provider.get(userAgent.getEventBroadcaster()); | |||
eventProducer.resourceEmbeddingError(this, charSet.getName(), ioe); | |||
} | |||
} | |||
// create text data info | |||
AFPTextDataInfo textDataInfo = new AFPTextDataInfo(); |
@@ -68,8 +68,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
} | |||
private AFPFontInfo buildFont(Configuration fontCfg, String fontPath) | |||
throws ConfigurationException { | |||
throws ConfigurationException { | |||
FontManager fontManager = this.userAgent.getFactory().getFontManager(); | |||
FontTriplet.Matcher referencedFontsMatcher = fontManager.getReferencedFontsMatcher(); | |||
boolean embeddable = true; | |||
Configuration[] triple = fontCfg.getChildren("font-triplet"); | |||
List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/(); | |||
if (triple.length == 0) { | |||
@@ -81,6 +85,9 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
FontTriplet triplet = new FontTriplet(triple[j].getAttribute("name"), | |||
triple[j].getAttribute("style"), | |||
weight); | |||
if (referencedFontsMatcher != null && referencedFontsMatcher.matches(triplet)) { | |||
embeddable = false; | |||
} | |||
tripletList.add(triplet); | |||
} | |||
@@ -110,7 +117,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
} | |||
ResourceAccessor accessor = new DefaultFOPResourceAccessor( | |||
this.userAgent, | |||
this.userAgent.getFactory().getFontManager().getFontBaseURL(), | |||
fontManager.getFontBaseURL(), | |||
baseURI); | |||
String type = afpFontCfg.getAttribute("type"); | |||
@@ -135,11 +142,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
// Create a new font object | |||
RasterFont font = new RasterFont(name); | |||
font.setEmbeddable(embeddable); | |||
Configuration[] rasters = afpFontCfg.getChildren("afp-raster-font"); | |||
if (rasters.length == 0) { | |||
log.error( | |||
"Mandatory font configuration elements '<afp-raster-font...' are missing"); | |||
log.error("Mandatory font configuration elements '<afp-raster-font...'" | |||
+ " are missing at " + afpFontCfg.getLocation()); | |||
return null; | |||
} | |||
for (int j = 0; j < rasters.length; j++) { | |||
@@ -212,6 +220,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
} | |||
// Create a new font object | |||
OutlineFont font = new OutlineFont(name, characterSet); | |||
font.setEmbeddable(embeddable); | |||
return new AFPFontInfo(font, tripletList); | |||
} else { | |||
log.error("No or incorrect type attribute"); |
@@ -42,6 +42,9 @@ public class AFPElementMapping extends ElementMapping { | |||
/** include page segment element */ | |||
public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment"; | |||
/** include form map element */ | |||
public static final String INCLUDE_FORM_MAP = "include-form-map"; | |||
/** NOP */ | |||
public static final String NO_OPERATION = "no-operation"; | |||
@@ -80,6 +83,9 @@ public class AFPElementMapping extends ElementMapping { | |||
foObjs.put( | |||
INCLUDE_PAGE_OVERLAY, | |||
new AFPIncludePageOverlayMaker()); | |||
foObjs.put( | |||
INCLUDE_FORM_MAP, | |||
new AFPIncludeFormMapMaker()); | |||
foObjs.put( | |||
NO_OPERATION, | |||
new AFPNoOperationMaker()); | |||
@@ -101,6 +107,12 @@ public class AFPElementMapping extends ElementMapping { | |||
} | |||
} | |||
static class AFPIncludeFormMapMaker extends ElementMapping.Maker { | |||
public FONode make(FONode parent) { | |||
return new AFPIncludeFormMapElement(parent, INCLUDE_FORM_MAP); | |||
} | |||
} | |||
static class AFPTagLogicalElementMaker extends ElementMapping.Maker { | |||
public FONode make(FONode parent) { | |||
return new AFPPageSetupElement(parent, TAG_LOGICAL_ELEMENT); |
@@ -19,6 +19,9 @@ | |||
package org.apache.fop.render.afp.extensions; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.helpers.DefaultHandler; | |||
@@ -48,13 +51,14 @@ public class AFPExtensionHandler extends DefaultHandler | |||
public void startElement(String uri, String localName, String qName, Attributes attributes) | |||
throws SAXException { | |||
boolean handled = false; | |||
if (AFPPageSetup.CATEGORY.equals(uri)) { | |||
if (AFPExtensionAttachment.CATEGORY.equals(uri)) { | |||
lastAttributes = attributes; | |||
handled = true; | |||
if (localName.equals(AFPElementMapping.NO_OPERATION) | |||
|| localName.equals(AFPElementMapping.TAG_LOGICAL_ELEMENT) | |||
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) | |||
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) | |||
|| localName.equals(AFPElementMapping.INCLUDE_FORM_MAP) | |||
|| localName.equals(AFPElementMapping.INVOKE_MEDIUM_MAP)) { | |||
//handled in endElement | |||
} else { | |||
@@ -62,7 +66,7 @@ public class AFPExtensionHandler extends DefaultHandler | |||
} | |||
} | |||
if (!handled) { | |||
if (AFPPageSetup.CATEGORY.equals(uri)) { | |||
if (AFPExtensionAttachment.CATEGORY.equals(uri)) { | |||
throw new SAXException("Unhandled element " + localName | |||
+ " in namespace: " + uri); | |||
} else { | |||
@@ -74,26 +78,38 @@ public class AFPExtensionHandler extends DefaultHandler | |||
/** {@inheritDoc} */ | |||
public void endElement(String uri, String localName, String qName) throws SAXException { | |||
if (AFPPageSetup.CATEGORY.equals(uri)) { | |||
AFPPageSetup pageSetupExtn = null; | |||
if (localName.equals(AFPElementMapping.INVOKE_MEDIUM_MAP)) { | |||
this.returnedObject = new AFPInvokeMediumMap(); | |||
} | |||
else { | |||
pageSetupExtn = new AFPPageSetup(localName); | |||
this.returnedObject = pageSetupExtn; | |||
} | |||
String name = lastAttributes.getValue("name"); | |||
if (name != null) { | |||
returnedObject.setName(name); | |||
} | |||
String value = lastAttributes.getValue("value"); | |||
if (value != null && pageSetupExtn != null) { | |||
pageSetupExtn.setValue(value); | |||
} | |||
if (content.length() > 0 && pageSetupExtn != null) { | |||
pageSetupExtn.setContent(content.toString()); | |||
content.setLength(0); //Reset text buffer (see characters()) | |||
if (AFPExtensionAttachment.CATEGORY.equals(uri)) { | |||
if (AFPElementMapping.INCLUDE_FORM_MAP.equals(localName)) { | |||
AFPIncludeFormMap formMap = new AFPIncludeFormMap(); | |||
String name = lastAttributes.getValue("name"); | |||
formMap.setName(name); | |||
String src = lastAttributes.getValue("src"); | |||
try { | |||
formMap.setSrc(new URI(src)); | |||
} catch (URISyntaxException e) { | |||
throw new SAXException("Invalid URI: " + src, e); | |||
} | |||
this.returnedObject = formMap; | |||
} else { | |||
AFPPageSetup pageSetupExtn = null; | |||
if (AFPElementMapping.INVOKE_MEDIUM_MAP.equals(localName)) { | |||
this.returnedObject = new AFPInvokeMediumMap(); | |||
} else { | |||
pageSetupExtn = new AFPPageSetup(localName); | |||
this.returnedObject = pageSetupExtn; | |||
} | |||
String name = lastAttributes.getValue("name"); | |||
if (name != null) { | |||
returnedObject.setName(name); | |||
} | |||
String value = lastAttributes.getValue("value"); | |||
if (value != null && pageSetupExtn != null) { | |||
pageSetupExtn.setValue(value); | |||
} | |||
if (content.length() > 0 && pageSetupExtn != null) { | |||
pageSetupExtn.setContent(content.toString()); | |||
content.setLength(0); //Reset text buffer (see characters()) | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
/* | |||
* 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.afp.extensions; | |||
import java.net.URI; | |||
import org.xml.sax.ContentHandler; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.helpers.AttributesImpl; | |||
import org.apache.fop.fo.extensions.ExtensionAttachment; | |||
/** | |||
* This extension allows to include an AFP form map resource. It is implemented as an extension | |||
* attachment ({@link ExtensionAttachment}). | |||
*/ | |||
public class AFPIncludeFormMap extends AFPExtensionAttachment { | |||
private static final long serialVersionUID = 8548056652642588914L; | |||
/** src attribute containing the URI to the form map resource */ | |||
protected static final String ATT_SRC = "src"; | |||
/** | |||
* the URI identifying the form map resource. | |||
*/ | |||
protected URI src; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public AFPIncludeFormMap() { | |||
super(AFPElementMapping.INCLUDE_FORM_MAP); | |||
} | |||
/** | |||
* Returns the URI of the form map. | |||
* @return the form map URI | |||
*/ | |||
public URI getSrc() { | |||
return this.src; | |||
} | |||
/** | |||
* Sets the URI of the form map. | |||
* @param value the form map URI | |||
*/ | |||
public void setSrc(URI value) { | |||
this.src = value; | |||
} | |||
/** {@inheritDoc} */ | |||
public void toSAX(ContentHandler handler) throws SAXException { | |||
AttributesImpl atts = new AttributesImpl(); | |||
if (name != null && name.length() > 0) { | |||
atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); | |||
} | |||
if (this.src != null) { | |||
atts.addAttribute(null, ATT_SRC, ATT_SRC, "CDATA", this.src.toASCIIString()); | |||
} | |||
handler.startElement(CATEGORY, elementName, elementName, atts); | |||
handler.endElement(CATEGORY, elementName, elementName); | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return getClass().getName() + "(element-name=" + getElementName() | |||
+ " name=" + getName() + " src=" + getSrc() + ")"; | |||
} | |||
} |
@@ -0,0 +1,89 @@ | |||
/* | |||
* 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.afp.extensions; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.Locator; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.PropertyList; | |||
import org.apache.fop.fo.extensions.ExtensionAttachment; | |||
import org.apache.fop.fo.extensions.ExtensionObj; | |||
/** | |||
* This class extends the {@link ExtensionObj} class. It represents the "include-form-map" | |||
* extension in the FO tree. | |||
*/ | |||
public class AFPIncludeFormMapElement extends AbstractAFPExtensionObject { | |||
private static final String ATT_SRC = "src"; | |||
/** | |||
* Constructs an AFP object (called by Maker). | |||
* | |||
* @param parent the parent formatting object | |||
* @param name the name of the AFP element | |||
*/ | |||
public AFPIncludeFormMapElement(FONode parent, String name) { | |||
super(parent, name); | |||
} | |||
private AFPIncludeFormMap getFormMapAttachment() { | |||
return (AFPIncludeFormMap)getExtensionAttachment(); | |||
} | |||
/** {@inheritDoc} */ | |||
protected void startOfNode() throws FOPException { | |||
super.startOfNode(); | |||
if (parent.getNameId() != Constants.FO_DECLARATIONS) { | |||
invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), | |||
"rule.childOfDeclarations"); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void processNode(String elementName, Locator locator, | |||
Attributes attlist, PropertyList propertyList) | |||
throws FOPException { | |||
super.processNode(elementName, locator, attlist, propertyList); | |||
AFPIncludeFormMap formMap = getFormMapAttachment(); | |||
String attr = attlist.getValue(ATT_SRC); | |||
if (attr != null && attr.length() > 0) { | |||
try { | |||
formMap.setSrc(new URI(attr)); | |||
} catch (URISyntaxException e) { | |||
getFOValidationEventProducer().invalidPropertyValue(this, | |||
elementName, ATT_SRC, attr, null, getLocator()); | |||
} | |||
} else { | |||
missingPropertyError(ATT_SRC); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
protected ExtensionAttachment instantiateExtensionAttachment() { | |||
return new AFPIncludeFormMap(); | |||
} | |||
} |
@@ -36,6 +36,9 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; | |||
*/ | |||
public class AFPPageSetupElement extends AbstractAFPExtensionObject { | |||
private static final String ATT_VALUE = "value"; | |||
private static final String ATT_SRC = "src"; | |||
/** | |||
* Constructs an AFP object (called by Maker). | |||
* | |||
@@ -86,18 +89,18 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject { | |||
super.processNode(elementName, locator, attlist, propertyList); | |||
AFPPageSetup pageSetup = getPageSetupAttachment(); | |||
if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) { | |||
String attr = attlist.getValue("src"); | |||
String attr = attlist.getValue(ATT_SRC); | |||
if (attr != null && attr.length() > 0) { | |||
pageSetup.setValue(attr); | |||
} else { | |||
throw new FOPException(elementName + " must have a src attribute."); | |||
missingPropertyError(ATT_SRC); | |||
} | |||
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) { | |||
String attr = attlist.getValue("value"); | |||
String attr = attlist.getValue(ATT_VALUE); | |||
if (attr != null && attr.length() > 0) { | |||
pageSetup.setValue(attr); | |||
} else { | |||
throw new FOPException(elementName + " must have a value attribute."); | |||
missingPropertyError(ATT_VALUE); | |||
} | |||
} | |||
} |
@@ -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 { |
@@ -186,6 +186,13 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler | |||
gen.selectPaperSource(Integer.parseInt(paperSource.toString())); | |||
} | |||
//Output bin | |||
Object outputBin = getContext().getForeignAttribute( | |||
PCLElementMapping.PCL_OUTPUT_BIN); | |||
if (outputBin != null) { | |||
gen.selectOutputBin(Integer.parseInt(outputBin.toString())); | |||
} | |||
// Is Page duplex? | |||
Object pageDuplex = getContext().getForeignAttribute( | |||
PCLElementMapping.PCL_DUPLEX_MODE); |
@@ -239,6 +239,18 @@ public class PCLGenerator { | |||
writeCommand("&l" + selector + "H"); | |||
} | |||
/** | |||
* Selects the output bin. The parameter is usually printer-specific. Usually, "1" is the | |||
* default output bin (upper bin) and "2" is the lower (rear) output bin. Some printers | |||
* may support additional output bins. Consult the technical reference for your printer | |||
* for all available values. | |||
* @param selector the integer representing the output bin | |||
* @throws IOException In case of an I/O error | |||
*/ | |||
public void selectOutputBin(int selector) throws IOException { | |||
writeCommand("&l" + selector + "G"); | |||
} | |||
/** | |||
* Selects the duplexing mode for the page. | |||
* The parameter is usually printer-specific. |
@@ -177,6 +177,9 @@ public class PCLPageDefinition { | |||
pageDefinitions.add(new PCLPageDefinition("Ledger", 6, | |||
createPhysicalPageSizeInch(11, 17), | |||
createLogicalPageRect(75, 0, 3150, 5100), false)); | |||
pageDefinitions.add(new PCLPageDefinition("A5", 25, | |||
createPhysicalPageSizeMm(148, 210), | |||
createLogicalPageRect(71, 0, 1745, 2480), false)); | |||
pageDefinitions.add(new PCLPageDefinition("A4", 26, | |||
createPhysicalPageSizeMm(210, 297), | |||
createLogicalPageRect(71, 0, 2338, 3507), false)); | |||
@@ -198,6 +201,9 @@ public class PCLPageDefinition { | |||
pageDefinitions.add(new PCLPageDefinition("LedgerL", 6, | |||
createPhysicalPageSizeInch(17, 11), | |||
createLogicalPageRect(60, 0, 4980, 3300), true)); | |||
pageDefinitions.add(new PCLPageDefinition("A5L", 25, | |||
createPhysicalPageSizeMm(210, 148), | |||
createLogicalPageRect(59, 0, 2362, 1747), true)); | |||
pageDefinitions.add(new PCLPageDefinition("A4L", 26, | |||
createPhysicalPageSizeMm(297, 210), | |||
createLogicalPageRect(59, 0, 3389, 2480), true)); |
@@ -289,6 +289,12 @@ public class PCLRenderer extends PrintRenderer implements PCLConstants { | |||
gen.selectPaperSource(Integer.parseInt(paperSource)); | |||
} | |||
//Output bin | |||
String outputBin = page.getForeignAttributeValue(PCLElementMapping.PCL_OUTPUT_BIN); | |||
if (outputBin != null) { | |||
gen.selectOutputBin(Integer.parseInt(outputBin)); | |||
} | |||
// Is Page duplex? | |||
String pageDuplex = page.getForeignAttributeValue(PCLElementMapping.PCL_DUPLEX_MODE); | |||
if (pageDuplex != null) { |
@@ -40,6 +40,10 @@ public class PCLElementMapping extends ElementMapping { | |||
public static final QName PCL_PAPER_SOURCE | |||
= new QName(PCLElementMapping.NAMESPACE, null, "paper-source"); | |||
/** The extension attribute for the PCL output bin */ | |||
public static final QName PCL_OUTPUT_BIN | |||
= new QName(PCLElementMapping.NAMESPACE, null, "output-bin"); | |||
/** The extension attribute for the PCL duplex mode */ | |||
public static final QName PCL_DUPLEX_MODE | |||
= new QName(PCLElementMapping.NAMESPACE, null, "duplex-mode"); |
@@ -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); | |||
} | |||
@@ -144,15 +144,20 @@ public class PDFDocumentNavigationHandler implements IFDocumentNavigationHandler | |||
if (pdfAction != null) { | |||
return pdfAction; | |||
} else if (action instanceof GoToXYAction) { | |||
GoToXYAction a = (GoToXYAction)action; | |||
PDFGoTo pdfGoTo = new PDFGoTo(null); | |||
getPDFDoc().assignObjectNumber(pdfGoTo); | |||
if (action.isComplete()) { | |||
updateTargetLocation(pdfGoTo, a); | |||
pdfAction = (PDFAction) incompleteActions.get(action.getID()); | |||
if (pdfAction != null) { | |||
return pdfAction; | |||
} else { | |||
this.incompleteActions.put(action.getID(), pdfGoTo); | |||
GoToXYAction a = (GoToXYAction)action; | |||
PDFGoTo pdfGoTo = new PDFGoTo(null); | |||
getPDFDoc().assignObjectNumber(pdfGoTo); | |||
if (action.isComplete()) { | |||
updateTargetLocation(pdfGoTo, a); | |||
} else { | |||
this.incompleteActions.put(action.getID(), pdfGoTo); | |||
} | |||
return pdfGoTo; | |||
} | |||
return pdfGoTo; | |||
} else if (action instanceof URIAction) { | |||
URIAction u = (URIAction)action; | |||
assert u.isComplete(); |
@@ -30,7 +30,12 @@ import org.apache.fop.events.model.EventModel; | |||
public interface PDFEventProducer extends EventProducer { | |||
/** Provider class for the event producer. */ | |||
class Provider { | |||
final class Provider { | |||
/** | |||
* Utility classes should not have a public or default constructor. | |||
*/ | |||
private Provider() { } | |||
/** | |||
* Returns an event producer. |
@@ -1,3 +1,4 @@ | |||
<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en"> | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<catalogue xml:lang="en"> | |||
<message key="org.apache.fop.render.pdf.PDFEventProducer.nonFullyResolvedLinkTargets">{count} link target{count,equals,1,,s} could not be fully resolved and now point{count,equals,1,,s} to the top of the page or {count,equals,1,is,are} dysfunctional.</message> | |||
</catalogue> |
@@ -457,9 +457,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf | |||
} | |||
currentPageRef = currentPage.referencePDF(); | |||
Rectangle2D bounds = page.getViewArea(); | |||
double h = bounds.getHeight(); | |||
pageHeight = (int) h; | |||
Rectangle bounds = page.getViewArea(); | |||
pageHeight = bounds.height; | |||
this.generator = new PDFContentGenerator(this.pdfDoc, this.ostream, this.currentPage); | |||
this.borderPainter = new PDFBorderPainter(this.generator); |
@@ -815,8 +815,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer | |||
{page.getPageNumberString(), | |||
new Integer(this.currentPageNumber)}); | |||
double pageWidth = Math.round(page.getViewArea().getWidth()) / 1000f; | |||
double pageHeight = Math.round(page.getViewArea().getHeight()) / 1000f; | |||
double pageWidth = page.getViewArea().width / 1000f; | |||
double pageHeight = page.getViewArea().height / 1000f; | |||
boolean rotate = false; | |||
List pageSizes = new java.util.ArrayList(); | |||
if (getPSUtil().isAutoRotateLandscape() && (pageHeight < pageWidth)) { |
@@ -58,6 +58,22 @@ | |||
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> | |||
<action context="Renderers" dev="JM" type="add"> | |||
AFP Output: Added support for embedding external AFP form maps (form defs) using the | |||
afp:include-form-map extension. | |||
</action> | |||
<action context="Renderers" dev="JM" type="add"> | |||
AFP Output: Added support for AFP font embedding. Note: this changes the default behaviour. | |||
Like with PDF and PS, all fonts are embedded by default unless matched in the | |||
"referenced-fonts" section in the configuration. | |||
</action> | |||
<action context="Renderers" dev="AD" type="fix" fixes-bug="47508" due-to="Bharat Attaluri"> | |||
Bugfix: Error while writing TLE's attribute qualifier in the output. | |||
</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! | |||
} | |||
} | |||
} |
@@ -36,8 +36,13 @@ | |||
<fo:region-body/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:declarations> | |||
<afp:include-form-map name="FORMMAP1" src="file:../../resources/afp/F1SAMPLE.afp"/> | |||
</fo:declarations> | |||
<fo:page-sequence master-reference="normal" fox:test-ignore="this"> | |||
<afp:invoke-medium-map name="MYMAP"/> | |||
<afp:invoke-medium-map name="NOPAR"/> | |||
<afp:tag-logical-element name="foo" value="bar"/> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block>Text on page <fo:page-number/>.</fo:block> | |||
@@ -47,6 +52,9 @@ | |||
</fo:root> | |||
</fo> | |||
<checks xmlns:afp="apache:fop:extensions:afp"> | |||
<eval expected="FORMMAP1" xpath="/areaTree/extension-attachments/afp:include-form-map/@name"/> | |||
<eval expected="file:../../resources/afp/F1SAMPLE.afp" xpath="/areaTree/extension-attachments/afp:include-form-map/@src"/> | |||
<eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*)"/> | |||
<eval expected="O1SAMP1 " xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]/@name"/> | |||
<eval expected="S1ISLOGO" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]/@name"/> | |||
@@ -57,7 +65,7 @@ | |||
<eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*)"/> | |||
<eval expected="2" xpath="count(/areaTree/pageSequence/extension-attachments/child::*)"/> | |||
<eval expected="MYMAP" xpath="/areaTree/pageSequence/extension-attachments/child::*[1]/@name"/> | |||
<eval expected="NOPAR" xpath="/areaTree/pageSequence/extension-attachments/child::*[1]/@name"/> | |||
<eval expected="bar" xpath="/areaTree/pageSequence/extension-attachments/afp:tag-logical-element[@name = 'foo']/@value"/> | |||
<!-- This just tests if extension attributes make it through to the PageSequence object. --> | |||
@@ -65,6 +73,9 @@ | |||
</checks> | |||
<if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate" | |||
xmlns:afp="apache:fop:extensions:afp"> | |||
<eval expected="FORMMAP1" xpath="/if:document/if:header/afp:include-form-map/@name"/> | |||
<eval expected="file:../../resources/afp/F1SAMPLE.afp" xpath="/if:document/if:header/afp:include-form-map/@src"/> | |||
<eval expected="4" xpath="count(//if:page[@name = '1']/if:page-header/child::*)"/> | |||
<eval expected="O1SAMP1 " xpath="//if:page[@name = '1']/if:page-header/afp:include-page-overlay[1]/@name"/> | |||
<eval expected="S1ISLOGO" xpath="//if:page[@name = '1']/if:page-header/afp:include-page-segment[1]/@name"/> | |||
@@ -74,7 +85,7 @@ | |||
<eval expected="4" xpath="count(//if:page[@name = '2']/if:page-header/child::*)"/> | |||
<eval expected="MYMAP" xpath="//if:page-sequence/afp:invoke-medium-map/@name"/> | |||
<eval expected="NOPAR" xpath="//if:page-sequence/afp:invoke-medium-map/@name"/> | |||
<eval expected="bar" xpath="//if:page-sequence/afp:tag-logical-element[@name = 'foo']/@value"/> | |||
<!-- This just tests if extension attributes make it through to the PageSequence object. --> |