aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.xml6
-rw-r--r--examples/embedding/java/embedding/intermediate/ExampleConcat.java4
-rw-r--r--examples/embedding/java/embedding/intermediate/ExampleStamp.java2
-rw-r--r--src/documentation/content/xdocs/trunk/configuration.xml12
-rw-r--r--src/documentation/content/xdocs/trunk/fonts.xml15
-rw-r--r--src/documentation/content/xdocs/trunk/output.xml87
-rw-r--r--src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd3
-rw-r--r--src/documentation/skinconf.xml2
-rw-r--r--src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory2
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceManager.java8
-rw-r--r--src/java/org/apache/fop/afp/DataStream.java6
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontCollection.java27
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontReader.java98
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSet.java76
-rw-r--r--src/java/org/apache/fop/afp/fonts/FopCharacterSet.java3
-rw-r--r--src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java42
-rw-r--r--src/java/org/apache/fop/afp/util/SimpleResourceAccessor.java34
-rw-r--r--src/java/org/apache/fop/apps/FOURIResolver.java34
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java41
-rw-r--r--src/java/org/apache/fop/apps/FopFactory.java8
-rw-r--r--src/java/org/apache/fop/apps/FopFactoryConfigurator.java12
-rw-r--r--src/java/org/apache/fop/area/AreaTreeHandler.java7
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java40
-rw-r--r--src/java/org/apache/fop/area/CachedRenderPagesModel.java2
-rw-r--r--src/java/org/apache/fop/area/PageSequence.java2
-rw-r--r--src/java/org/apache/fop/area/inline/InlineArea.java4
-rw-r--r--src/java/org/apache/fop/cli/CommandLineOptions.java7
-rw-r--r--src/java/org/apache/fop/events/EventFormatter.xml2
-rw-r--r--src/java/org/apache/fop/fo/Constants.java22
-rw-r--r--src/java/org/apache/fop/fo/flow/Leader.java2
-rw-r--r--src/java/org/apache/fop/fo/pagination/PageSequence.java16
-rw-r--r--src/java/org/apache/fop/fo/pagination/Region.java19
-rw-r--r--src/java/org/apache/fop/fo/pagination/RegionAfter.java24
-rw-r--r--src/java/org/apache/fop/fo/pagination/RegionBody.java22
-rw-r--r--src/java/org/apache/fop/fo/pagination/RegionEnd.java24
-rw-r--r--src/java/org/apache/fop/fo/pagination/RegionStart.java24
-rw-r--r--src/java/org/apache/fop/fo/pagination/SimplePageMaster.java40
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java72
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonFont.java10
-rw-r--r--src/java/org/apache/fop/fonts/FontAdder.java72
-rw-r--r--src/java/org/apache/fop/fonts/FontDetector.java101
-rw-r--r--src/java/org/apache/fop/fonts/FontInfoConfigurator.java313
-rw-r--r--src/java/org/apache/fop/fonts/FontManager.java25
-rw-r--r--src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java6
-rw-r--r--src/java/org/apache/fop/fonts/autodetect/FontFinder.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java46
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java52
-rw-r--r--src/java/org/apache/fop/layoutmgr/ElementListUtils.java11
-rw-r--r--src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java33
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreaker.java14
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java1
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/pdf/AbstractPDFFontStream.java5
-rw-r--r--src/java/org/apache/fop/pdf/AbstractPDFStream.java20
-rw-r--r--src/java/org/apache/fop/pdf/PDFImageXObject.java9
-rw-r--r--src/java/org/apache/fop/pdf/PDFMetadata.java5
-rw-r--r--src/java/org/apache/fop/render/AbstractConfigurator.java89
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java14
-rw-r--r--src/java/org/apache/fop/render/AbstractRendererConfigurator.java57
-rw-r--r--src/java/org/apache/fop/render/DefaultFontResolver.java2
-rw-r--r--src/java/org/apache/fop/render/PrintRendererConfigurator.java368
-rw-r--r--src/java/org/apache/fop/render/RendererFactory.java86
-rw-r--r--src/java/org/apache/fop/render/afp/AFPDocumentHandler.java72
-rw-r--r--src/java/org/apache/fop/render/afp/AFPDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/afp/AFPPainter.java8
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRenderer.java24
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java32
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java52
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java82
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java30
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMap.java54
-rw-r--r--[-rwxr-xr-x]src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMapElement.java (renamed from src/java/org/apache/fop/render/afp/extensions/AFPElement.java)27
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java66
-rwxr-xr-x[-rw-r--r--]src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java78
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java54
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java1
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/print/PageableRenderer.java6
-rw-r--r--src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java2
-rw-r--r--src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java15
-rw-r--r--src/java/org/apache/fop/svg/PDFGraphics2D.java24
-rw-r--r--src/java/org/apache/fop/tools/fontlist/FontListGenerator.java115
-rw-r--r--src/java/org/apache/fop/tools/fontlist/FontListMain.java305
-rw-r--r--src/java/org/apache/fop/tools/fontlist/FontListSerializer.java142
-rw-r--r--src/java/org/apache/fop/tools/fontlist/FontSpec.java103
-rw-r--r--src/java/org/apache/fop/tools/fontlist/fonts2fo.xsl200
-rw-r--r--status.xml44
-rw-r--r--test/java/org/apache/fop/StandardTestSuite.java2
-rw-r--r--test/java/org/apache/fop/config/FOURIResolverTestCase.java56
-rw-r--r--test/java/org/apache/fop/config/FontBaseBadTestCase.java11
-rw-r--r--test/java/org/apache/fop/intermediate/IFMimickingTestCase.java149
-rw-r--r--test/java/org/apache/fop/intermediate/IFParserTestCase.java2
-rw-r--r--test/java/org/apache/fop/intermediate/IFTester.java9
-rw-r--r--test/java/org/apache/fop/render/RendererFactoryTest.java159
-rw-r--r--test/java/org/apache/fop/threading/FOPTestbed.java106
-rw-r--r--test/java/org/apache/fop/threading/FOProcessor.java6
-rw-r--r--test/java/org/apache/fop/threading/FOProcessorImpl.java45
-rw-r--r--test/layoutengine/standard-testcases/afp-extension_1.xml33
-rw-r--r--test/layoutengine/standard-testcases/leader_border_padding.xml12
-rw-r--r--test/layoutengine/standard-testcases/page-position-last_break-before_bugzilla46489.xml93
-rw-r--r--test/test-no-xml-metrics.xconf44
106 files changed, 3386 insertions, 1099 deletions
diff --git a/build.xml b/build.xml
index 5541c4904..e9cc16a21 100644
--- a/build.xml
+++ b/build.xml
@@ -358,12 +358,12 @@ list of possible build targets.
</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/render/afp/event-model.xml" translationfile="${src.java.dir}/org/apache/fop/render/afp/AFPEventProducer.xml">
+ <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"/>
</fileset>
</eventResourceGenerator>
- <fixcrlf file="${src.java.dir}/org/apache/fop/render/afp/AFPEventProducer.xml" tab="remove" tablength="2"/>
+ <fixcrlf file="${src.java.dir}/org/apache/fop/afp/AFPEventProducer.xml" tab="remove" tablength="2"/>
<eventResourceGenerator modelfile="${build.gensrc.dir}/org/apache/fop/render/bitmap/event-model.xml" translationfile="${src.java.dir}/org/apache/fop/render/bitmap/BitmapRendererEventProducer.xml">
<fileset dir="${src.java.dir}">
<include name="org/apache/fop/render/bitmap/**/*.java"/>
@@ -608,7 +608,7 @@ list of possible build targets.
<exclude name="org/apache/fop/render/pdf/PDFRenderer.class"/>
<exclude name="org/apache/fop/render/pdf/PDFXMLHandler*"/>
<include name="org/apache/fop/render/intermediate/IFDocumentHandlerConfigurator.class"/>
- <include name="org/apache/fop/render/*RendererConfigurator**"/>
+ <include name="org/apache/fop/render/**Configurator**"/>
<include name="org/apache/fop/util/AbstractPaintingState**"/>
<include name="org/apache/fop/pdf/**"/>
</patternset>
diff --git a/examples/embedding/java/embedding/intermediate/ExampleConcat.java b/examples/embedding/java/embedding/intermediate/ExampleConcat.java
index a5765f49b..6b168f968 100644
--- a/examples/embedding/java/embedding/intermediate/ExampleConcat.java
+++ b/examples/embedding/java/embedding/intermediate/ExampleConcat.java
@@ -92,7 +92,7 @@ public class ExampleConcat {
//Create an instance of the target document handler so the IFSerializer
//can use its font setup
IFDocumentHandler targetHandler = userAgent.getRendererFactory().createDocumentHandler(
- userAgent, MimeConstants.MIME_PDF + ";mode=painter");
+ userAgent, MimeConstants.MIME_PDF);
//Create the IFSerializer to write the intermediate format
IFSerializer ifSerializer = new IFSerializer();
@@ -150,7 +150,7 @@ public class ExampleConcat {
FOUserAgent userAgent = fopFactory.newFOUserAgent();
//Setup target handler
- String mime = MimeConstants.MIME_PDF + ";mode=painter";
+ String mime = MimeConstants.MIME_PDF;
IFDocumentHandler targetHandler = fopFactory.getRendererFactory().createDocumentHandler(
userAgent, mime);
diff --git a/examples/embedding/java/embedding/intermediate/ExampleStamp.java b/examples/embedding/java/embedding/intermediate/ExampleStamp.java
index 860a75401..c5d1a12c5 100644
--- a/examples/embedding/java/embedding/intermediate/ExampleStamp.java
+++ b/examples/embedding/java/embedding/intermediate/ExampleStamp.java
@@ -73,7 +73,7 @@ public class ExampleStamp {
FOUserAgent userAgent = fopFactory.newFOUserAgent();
//Setup target handler
- String mime = MimeConstants.MIME_PDF + ";mode=painter";
+ String mime = MimeConstants.MIME_PDF;
IFDocumentHandler targetHandler = fopFactory.getRendererFactory().createDocumentHandler(
userAgent, mime);
diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml
index 08463b9b9..7fc0d97d9 100644
--- a/src/documentation/content/xdocs/trunk/configuration.xml
+++ b/src/documentation/content/xdocs/trunk/configuration.xml
@@ -152,6 +152,18 @@
<td>"height" 11 inches, "width" 8.26 inches</td>
</tr>
<tr>
+ <td>prefer-renderer</td>
+ <td>boolean (true, false)</td>
+ <td>
+ By default, FOP prefers the newer output implementations based on the
+ <code>IFDocumentHandler</code> interface. If no such implementation can be found for
+ a given MIME type, it looks for an implementation of the <code>Renderer</code> interface.
+ If necessary, you can invert the lookup order to prefer the Renderer variant over the
+ IFDocumentHandler variant by setting this value to true.
+ </td>
+ <td>false</td>
+ </tr>
+ <tr>
<td>use-cache</td>
<td>boolean (true, false)</td>
<td>All fonts information that has been gathered as a result of "directory"
diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml
index 429c86a51..9fa34552b 100644
--- a/src/documentation/content/xdocs/trunk/fonts.xml
+++ b/src/documentation/content/xdocs/trunk/fonts.xml
@@ -344,7 +344,7 @@
</warning>
</section>
<section id="truetype-collections-metrics">
- <title>TrueType Collections Font Metrics</title>
+ <title>TrueType Collections</title>
<p>TrueType collections (.ttc files) contain more than one font.
To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.</p>
<p>To get a list of the fonts in a collection, just start the TTFReader as if it were a normal TrueType file (without the -ttcname option).
@@ -356,8 +356,11 @@
<p>
Alternatively, the individual sub-fonts of a TrueType Collections can be selected
using the "sub-font" attribute on the "font" element. That means that generating
- an XML font metrics file for TrueType collections is not necessary anymore.
+ an XML font metrics file for TrueType collections is not necessary anymore. Example:
</p>
+ <source><![CDATA[<font embed-url="gulim.ttc" sub-font="GulimChe">
+ <font-triplet name="GulimChe" style="normal" weight="normal"/>
+</font>]]></source>
</section>
<section id="register">
<title>Register Fonts with FOP</title>
@@ -542,5 +545,13 @@
</ul>
<p>Character-by-Character is NOT yet supported!</p>
</section>
+ <section id="font-list">
+ <title>Font List Command-Line Tool</title>
+ <p>
+ FOP contains a small command-line tool that lets you generate a list of all configured
+ fonts. Its class name is: <code>org.apache.fop.tools.fontlist.FontListMain</code>.
+ Run it with the "-?" parameter to get help for the various options.
+ </p>
+ </section>
</body>
</document>
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index 83e730de9..c2548b390 100644
--- a/src/documentation/content/xdocs/trunk/output.xml
+++ b/src/documentation/content/xdocs/trunk/output.xml
@@ -451,11 +451,35 @@ out = proc.getOutputStream();]]></source>
</section>
<section id="afp">
<title>AFP</title>
- <warning>The AFP Renderer is a new addition (27-Apr-2006) to the sandbox and as such not yet fully tested or feature complete.</warning>
<p>
The FOP AFP Renderer deals with creating documents conforming to the IBM AFP document architecture
also refered to as MO:DCA (Mixed Object Document Content Architecture).
</p>
+ <p>
+ The mapping of XSL-FO elements to the major MO:DCA structures is as follows:
+ </p>
+ <table>
+ <tr>
+ <th>XSL-FO element</th>
+ <th>MO:DCA-P object</th>
+ </tr>
+ <tr>
+ <td>fo:root</td>
+ <td>Document</td>
+ </tr>
+ <tr>
+ <td>fo:page-sequence</td>
+ <td>Page Group</td>
+ </tr>
+ <tr>
+ <td>fo:simple-page-master</td>
+ <td>Page</td>
+ </tr>
+ </table>
+ <p>
+ FOP creates exactly one Document per Printfile with an optional Resource Group at the
+ beginning. FOP does not create document indices.
+ </p>
<section id="afp-references">
<title>References</title>
<ul>
@@ -512,8 +536,8 @@ out = proc.getOutputStream();]]></source>
<source><![CDATA[ <!-- This is an example of mapping actual IBM raster fonts / code pages to a FOP font -->
<font>
<!-- The afp-font element defines the IBM code page, the matching Java encoding and the
- path to the font -->
- <afp-font type="raster" codepage="T1V10500" encoding="Cp500" path="fonts/ibm">
+ base URI for the font -->
+ <afp-font type="raster" codepage="T1V10500" encoding="Cp500" base-uri="fonts/ibm/">
<!-- For a raster font a separate element for each font size is required providing
the font size and the corresponding IBM Character set name -->
<afp-raster-font size="7" characterset="C0N20070"/>
@@ -539,15 +563,24 @@ out = proc.getOutputStream();]]></source>
However, the characterset definition is now required within the afp-font element.</p>
<source><![CDATA[ <font>
<afp-font type="outline" codepage="T1V10500" encoding="Cp500" characterset="CZH200 "
- path="fonts/ibm" />
+ base-uri="file:/fonts/ibm" />
<font-triplet name="sans-serif" style="normal" weight="normal"/>
<font-triplet name="Helvetica" style="normal" weight="normal"/>
<font-triplet name="any" style="normal" weight="normal"/>
</font>
]]></source>
+ <p>
+ If "base-uri" is missing or a relative URI, the fonts are resolved relative to
+ the font base URI specified in the configuration (or on the FopFactory).
+ </p>
+ <note>
+ Previously, the location of the font files was given by the "path" attribute. This is still
+ supported for the time being, but you should move to using the more flexible "base-uri"
+ attribute so you can profit from the power of URI resolvers.
+ </note>
<p>Experimentation has shown that the font metrics for the FOP built-in Base14 fonts are actually
very similar to some of the IBM outline and raster fonts. In cases were the IBM font files are not
- available the path attribute in the afp-font element can be replaced by a base14-font attribute
+ available the base-uri attribute in the afp-font element can be replaced by a base14-font attribute
giving the name of the matching Base14 font. In this case the AFP Renderer will take the
font metrics from the built-in font.</p>
<source><![CDATA[ <!-- The following are examples of defining outline fonts based on FOP built-in
@@ -687,7 +720,7 @@ out = proc.getOutputStream();]]></source>
xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
]]></source>
<section id="afp-page-overlay">
- <title>Page Overlay Extension</title>
+ <title>Page Overlay (IPO) Extension</title>
<p>The include-page-overlay extension element allows to define on a per simple-page-master basis a page overlay resource. Example:</p>
<source><![CDATA[
<fo:layout-master-set>
@@ -701,7 +734,7 @@ out = proc.getOutputStream();]]></source>
must be known in the AFP processing environment.</p>
</section>
<section id="afp-page-segment">
- <title>Page Segment Extension</title>
+ <title>Page Segment (IPS) Extension</title>
<p>The include-page-segment extension element allows to define resource substitution for fo:external-graphics elements.
Example:</p>
<source><![CDATA[
@@ -724,7 +757,7 @@ out = proc.getOutputStream();]]></source>
</p>
</section>
<section id="afp-tag-logical-element">
- <title>Tag Logical Element Extension</title>
+ <title>Tag Logical Element (TLE) Extension</title>
<p>The tag-logical-element extension element allows to injects TLEs into the AFP output stream. Example:</p>
<source><![CDATA[
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
@@ -735,14 +768,21 @@ out = proc.getOutputStream();]]></source>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
+ [..]
+ <fo:page-sequence master-reference="simple">
+ <afp:tag-logical-element name="foo" value="bar"/>
+ <fo:flow flow-name="xsl-region-body">
+ [..]
]]></source>
- <p>The tag-logical-element extension element can only occur within a simple-page-master.
- Multiple tag-logical-element extension elements within a simple-page-master are allowed.
- The name and value attributes are mandatory.
+ <p>
+ The tag-logical-element extension element can appear within a simple-page-master
+ (page level) or it can appear as child of page-sequence (page group level).
+ Multiple tag-logical-element extension elements within a simple-page-master or
+ page-sequence are allowed. The name and value attributes are mandatory.
</p>
</section>
<section id="afp-no-operation">
- <title>No Operation Extension</title>
+ <title>No Operation (NOP) Extension</title>
<p>The no-operation extension provides the ability to carry up to 32K of comments or any other type
of unarchitected data into the AFP output stream. Example:</p>
<source><![CDATA[
@@ -759,6 +799,29 @@ out = proc.getOutputStream();]]></source>
The name attribute is mandatory.
</p>
</section>
+ <section id="afp-invoke-medium-map">
+ <title>Invoke Medium Map (IMM) Extension</title>
+ <p>
+ The invoke-medium-map extension allows to generate IMM fields (Invoke Medium Map) in the
+ generated AFP output. 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:page-sequence master-reference="normal">
+ <afp:invoke-medium-map name="MYMAP"/>
+ <fo:flow flow-name="xsl-region-body">
+ [..]
+]]></source>
+ <p>
+ The invoke-medium-map element is allowed as child of fo:page-sequence (page group
+ level). It is NOT supported on document level (fo:root), yet. FOP also doesn't support
+ specifying medium maps inside XML (using BMM/EMM). It can only reference an existing
+ medium map by name. The medium map has to be constructed through different means and
+ available on the target platform.
+ </p>
+ </section>
</section>
<section id="afp-foreign-attributes">
<title>Foreign Attributes</title>
diff --git a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
index 483935c16..93aacb62d 100644
--- a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
+++ b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
@@ -55,6 +55,9 @@
<xs:element name="page-sequence">
<xs:complexType>
<xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:choice>
<xs:element ref="mf:page" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="id" type="xs:ID"/>
diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml
index a6a5ac65f..1944ad856 100644
--- a/src/documentation/skinconf.xml
+++ b/src/documentation/skinconf.xml
@@ -91,7 +91,7 @@ which will be used to configure the chosen Forrest skin.
<favicon-url></favicon-url>
<!-- The following used to construct a copyright statement -->
- <year>1999-2008</year>
+ <year>1999-2009</year>
<vendor>The Apache Software Foundation.</vendor>
<copyright-link>http://www.apache.org/licenses/</copyright-link>
diff --git a/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
index b607a5e64..46760b291 100644
--- a/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
+++ b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
@@ -1,2 +1,2 @@
org.apache.fop.image.loader.batik.ImageLoaderFactorySVG
-org.apache.fop.image.loader.batik.ImageLoaderFactoryWMF \ No newline at end of file
+org.apache.fop.image.loader.batik.ImageLoaderFactoryWMF
diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java
index 78c06bedf..c44698a10 100644
--- a/src/java/org/apache/fop/afp/AFPResourceManager.java
+++ b/src/java/org/apache/fop/afp/AFPResourceManager.java
@@ -37,7 +37,6 @@ import org.apache.fop.afp.modca.Registry;
import org.apache.fop.afp.modca.ResourceGroup;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.util.ResourceAccessor;
-import org.apache.fop.afp.util.SimpleResourceAccessor;
/**
* Manages the creation and storage of document resources
@@ -236,11 +235,11 @@ public class AFPResourceManager {
/**
* Creates an included resource object by loading the contained object from a file.
* @param resourceName the name of the resource
- * @param basePath the base path in which to look for the resource files
+ * @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, String basePath,
+ public void createIncludedResource(String resourceName, ResourceAccessor accessor,
byte resourceObjectType) throws IOException {
AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE);
URI uri;
@@ -261,9 +260,6 @@ public class AFPResourceManager {
if (log.isDebugEnabled()) {
log.debug("Adding included resource: " + resourceName);
}
- //TODO This works with local filenames only. In the long term, this
- //should work through FOP's URI resolver.
- ResourceAccessor accessor = new SimpleResourceAccessor(basePath);
IncludedResourceObject resourceContent = new IncludedResourceObject(
resourceName, accessor, uri);
diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java
index 492669311..b1ff96859 100644
--- a/src/java/org/apache/fop/afp/DataStream.java
+++ b/src/java/org/apache/fop/afp/DataStream.java
@@ -486,10 +486,10 @@ public class DataStream {
* The tag value
*/
public void createTagLogicalElement(String name, String value) {
- if (currentPageGroup != null) {
- currentPageGroup.createTagLogicalElement(name, value);
- } else {
+ if (currentPage != null) {
currentPage.createTagLogicalElement(name, value, tleSequence++);
+ } else {
+ currentPageGroup.createTagLogicalElement(name, value);
}
}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
index 670373fbf..66b3f5564 100644
--- a/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
@@ -67,18 +67,14 @@ public class AFPFontCollection implements FontCollection {
num++;
}
}
- if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)) {
- eventProducer.warnMissingDefaultFont(this, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- }
- if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL)) {
- eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
- }
- if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD)) {
- eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
- }
- if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD)) {
- eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
- }
+ checkDefaultFontAvailable(fontInfo, eventProducer,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
+ checkDefaultFontAvailable(fontInfo, eventProducer,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
+ checkDefaultFontAvailable(fontInfo, eventProducer,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
+ checkDefaultFontAvailable(fontInfo, eventProducer,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
} else {
eventProducer.warnDefaultFontSetup(this);
@@ -89,4 +85,11 @@ public class AFPFontCollection implements FontCollection {
return num;
}
+ private void checkDefaultFontAvailable(FontInfo fontInfo, AFPEventProducer eventProducer,
+ String style, int weight) {
+ if (!fontInfo.hasFont("any", style, weight)) {
+ eventProducer.warnMissingDefaultFont(this, style, weight);
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
index d1e8bd8db..4e6a03259 100644
--- a/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
@@ -19,21 +19,19 @@
package org.apache.fop.afp.fonts;
-import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.ResourceAccessor;
import org.apache.fop.afp.util.StructuredFieldReader;
/**
@@ -58,7 +56,7 @@ public final class AFPFontReader {
/**
* Static logging instance
*/
- protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.fonts");
+ protected static final Log log = LogFactory.getLog(AFPFontReader.class);
/**
* Template used to convert lists to arrays.
@@ -96,7 +94,7 @@ public final class AFPFontReader {
/**
* The collection of code pages
*/
- private final Map/*<String, Map<String, String>>*/ codePages
+ private final Map/*<String, Map<String, String>>*/ codePagesCache
= new java.util.HashMap/*<String, Map<String, String>>*/();
/**
@@ -108,65 +106,16 @@ public final class AFPFontReader {
*
* @throws IOException in the event that an I/O exception of some sort has occurred
*/
- private InputStream openInputStream(String path, String filename) throws IOException {
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- if (classLoader == null) {
- classLoader = AFPFontReader.class.getClassLoader();
- }
-
- URL url = classLoader.getResource(path);
-
- if (url == null) {
- try {
- File file = new File(path);
- url = file.toURI().toURL();
- if (url == null) {
- String msg = "file not found " + filename + " in classpath: " + path;
- log.error(msg);
- throw new FileNotFoundException(msg);
- }
- } catch (MalformedURLException ex) {
- String msg = "file not found " + filename + " in classpath: " + path;
- log.error(msg);
- throw new FileNotFoundException(msg);
- }
- }
-
- File directory = FileUtils.toFile(url);
- if (!directory.canRead()) {
- String msg = "Failed to read directory " + url.getPath();
- log.error(msg);
- throw new FileNotFoundException(msg);
- }
-
- final String filterpattern = filename.trim();
- FilenameFilter filter = new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.startsWith(filterpattern);
- }
- };
-
- File[] files = directory.listFiles(filter);
-
- if (files.length < 1) {
- String msg = "file search for " + filename + " located "
- + files.length + " files";
- log.error(msg);
- throw new FileNotFoundException(msg);
- } else if (files.length > 1) {
- String msg = "file search for " + filename + " located "
- + files.length + " files";
- log.warn(msg);
- }
-
- InputStream inputStream = files[0].toURI().toURL().openStream();
-
- if (inputStream == null) {
- String msg = "AFPFontReader:: getInputStream():: file not found for " + filename;
- log.error(msg);
- throw new FileNotFoundException(msg);
+ private InputStream openInputStream(ResourceAccessor accessor, String filename)
+ throws IOException {
+ URI uri;
+ try {
+ uri = new URI(filename.trim());
+ } catch (URISyntaxException e) {
+ throw new FileNotFoundException("Invalid filename: "
+ + filename + " (" + e.getMessage() + ")");
}
-
+ InputStream inputStream = accessor.createInputStream(uri);
return inputStream;
}
@@ -206,13 +155,14 @@ public final class AFPFontReader {
* chracter global identifier.
*/
String codePageId = new String(characterSet.getCodePage());
- String path = characterSet.getPath();
+ ResourceAccessor accessor = characterSet.getResourceAccessor();
- Map/*<String,String>*/ codePage = (Map/*<String,String>*/)codePages.get(codePageId);
+ Map/*<String,String>*/ codePage
+ = (Map/*<String,String>*/)codePagesCache.get(codePageId);
if (codePage == null) {
- codePage = loadCodePage(codePageId, characterSet.getEncoding(), path);
- codePages.put(codePageId, codePage);
+ codePage = loadCodePage(codePageId, characterSet.getEncoding(), accessor);
+ codePagesCache.put(codePageId, codePage);
}
/**
@@ -222,7 +172,7 @@ public final class AFPFontReader {
*/
final String characterSetName = characterSet.getName();
- inputStream = openInputStream(path, characterSetName);
+ inputStream = openInputStream(accessor, characterSetName);
StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream);
@@ -246,7 +196,8 @@ public final class AFPFontReader {
}
//process D3AC89 Font Position
- processFontPosition(structuredFieldReader, characterSetOrientations, metricNormalizationFactor);
+ processFontPosition(structuredFieldReader, characterSetOrientations,
+ metricNormalizationFactor);
//process D38C89 Font Index (per orientation)
for (int i = 0; i < characterSetOrientations.length; i++) {
@@ -274,17 +225,18 @@ public final class AFPFontReader {
* the code page identifier
* @param encoding
* the encoding to use for the character decoding
+ * @param accessor the resource accessor
* @returns a code page mapping
*/
private Map/*<String,String>*/ loadCodePage(String codePage, String encoding,
- String path) throws IOException {
+ ResourceAccessor accessor) throws IOException {
// Create the HashMap to store code page information
Map/*<String,String>*/ codePages = new java.util.HashMap/*<String,String>*/();
InputStream inputStream = null;
try {
- inputStream = openInputStream(path, codePage.trim());
+ inputStream = openInputStream(accessor, codePage.trim());
StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream);
byte[] data = structuredFieldReader.getNext(CHARACTER_TABLE_SF);
diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
index 52bebca56..9573506b3 100644
--- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java
+++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
@@ -19,20 +19,25 @@
package org.apache.fop.afp.fonts;
+import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
+import java.nio.charset.UnsupportedCharsetException;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.ResourceAccessor;
+import org.apache.fop.afp.util.SimpleResourceAccessor;
import org.apache.fop.afp.util.StringUtils;
/**
@@ -79,7 +84,7 @@ public class CharacterSet {
protected String name;
/** The path to the installed fonts */
- protected String path;
+ private ResourceAccessor accessor;
/** Indicator as to whether to metrics have been loaded */
private boolean isMetricsLoaded = false;
@@ -98,8 +103,23 @@ public class CharacterSet {
* @param encoding the encoding of the font
* @param name the character set name
* @param path the path to the installed afp fonts
+ * @deprecated Please use {@link #CharacterSet(String, String, String, URI)} instead.
*/
public CharacterSet(String codePage, String encoding, String name, String path) {
+ this(codePage, encoding, name,
+ new SimpleResourceAccessor(path != null ? new File(path) : null));
+ }
+
+ /**
+ * Constructor for the CharacterSetMetric object, the character set is used
+ * to load the font information from the actual AFP font.
+ *
+ * @param codePage the code page identifier
+ * @param encoding the encoding of the font
+ * @param name the character set name
+ * @param accessor the resource accessor to load resource with
+ */
+ public CharacterSet(String codePage, String encoding, String name, ResourceAccessor accessor) {
if (name.length() > MAX_NAME_LEN) {
String msg = "Character set name '" + name + "' must be a maximum of "
+ MAX_NAME_LEN + " characters";
@@ -114,9 +134,15 @@ public class CharacterSet {
}
this.codePage = codePage;
this.encoding = encoding;
- this.encoder = Charset.forName(encoding).newEncoder();
- this.encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
- this.path = path;
+ try {
+ this.encoder = Charset.forName(encoding).newEncoder();
+ this.encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ } catch (UnsupportedCharsetException uce) {
+ //No nio-capable encoder available
+ //This may happen with "Cp500" on Sun Java 1.4.2
+ this.encoder = null;
+ }
+ this.accessor = accessor;
this.characterSetOrientations = new java.util.HashMap(4);
}
@@ -195,12 +221,11 @@ public class CharacterSet {
}
/**
- * Returns the path where the font resources are installed
- *
- * @return the path where the font resources are installed
+ * Returns the resource accessor to load the font resources with.
+ * @return the resource accessor to load the font resources with
*/
- public String getPath() {
- return path;
+ public ResourceAccessor getResourceAccessor() {
+ return this.accessor;
}
/**
@@ -321,7 +346,12 @@ public class CharacterSet {
* @return true if the character is in the character set
*/
public boolean hasChar(char c) {
- return encoder.canEncode(c);
+ if (encoder != null) {
+ return encoder.canEncode(c);
+ } else {
+ //Sun Java 1.4.2 compatibility
+ return true;
+ }
}
/**
@@ -331,14 +361,26 @@ public class CharacterSet {
* @throws CharacterCodingException if the encoding operation fails
*/
public byte[] encodeChars(CharSequence chars) throws CharacterCodingException {
- ByteBuffer bb = encoder.encode(CharBuffer.wrap(chars));
- if (bb.hasArray()) {
- return bb.array();
+ if (encoder != null) {
+ ByteBuffer bb = encoder.encode(CharBuffer.wrap(chars));
+ if (bb.hasArray()) {
+ return bb.array();
+ } else {
+ bb.rewind();
+ byte[] bytes = new byte[bb.remaining()];
+ bb.get(bytes);
+ return bytes;
+ }
} else {
- bb.rewind();
- byte[] bytes = new byte[bb.remaining()];
- bb.get(bytes);
- return bytes;
+ //Sun Java 1.4.2 compatibility
+ byte[] bytes;
+ try {
+ bytes = chars.toString().getBytes(this.encoding);
+ return bytes;
+ } catch (UnsupportedEncodingException uee) {
+ throw new UnsupportedOperationException(
+ "Unsupported encoding: " + uee.getMessage());
+ }
}
}
diff --git a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
index aec220b40..42950dc5b 100644
--- a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
+++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
@@ -19,6 +19,7 @@
package org.apache.fop.afp.fonts;
+import org.apache.fop.afp.util.ResourceAccessor;
import org.apache.fop.fonts.Typeface;
/**
@@ -43,7 +44,7 @@ public class FopCharacterSet extends CharacterSet {
String name,
Typeface charSet) {
- super(codePage, encoding, name, null);
+ super(codePage, encoding, name, (ResourceAccessor)null);
this.charSet = charSet;
}
diff --git a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
index 55c8eab7d..97646542b 100644
--- a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
+++ b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
@@ -19,42 +19,68 @@
package org.apache.fop.afp.util;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
+import java.net.URL;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
+import org.apache.commons.io.IOUtils;
+
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.fonts.FontManager;
/**
* Default implementation of the {@link ResourceAccessor} interface for use inside FOP.
*/
-public class DefaultFOPResourceAccessor implements ResourceAccessor {
+public class DefaultFOPResourceAccessor extends SimpleResourceAccessor {
private FOUserAgent userAgent;
+ private String categoryBaseURI;
/**
- * Main constructor.
+ * Constructor for resource to be accessed via the {@link FOUserAgent}. This contructor
+ * can take two base URIs: the category base URI is the one to use when differentiating between
+ * normal resources (ex. images) and font resources. So, if fonts need to be accessed, you can
+ * set the {@link FontManager}'s base URI instead of the one on the {@link FopFactory}.
* @param userAgent the FO user agent
+ * @param categoryBaseURI the category base URI (may be null)
+ * @param baseURI the custom base URI to resolve relative URIs against (may be null)
*/
- public DefaultFOPResourceAccessor(FOUserAgent userAgent) {
+ public DefaultFOPResourceAccessor(FOUserAgent userAgent, String categoryBaseURI, URI baseURI) {
+ super(baseURI);
this.userAgent = userAgent;
+ this.categoryBaseURI = categoryBaseURI;
}
/** {@inheritDoc} */
public InputStream createInputStream(URI uri) throws IOException {
- Source src = userAgent.resolveURI(uri.toASCIIString());
+ //Step 1: resolve against local base URI --> URI
+ URI resolved = resolveAgainstBase(uri);
+
+ //Step 2: resolve against the user agent --> stream
+ Source src;
+ src = userAgent.resolveURI(resolved.toASCIIString(), this.categoryBaseURI);
+
if (src == null) {
- return null;
+ throw new FileNotFoundException("Resource not found: " + uri.toASCIIString());
} else if (src instanceof StreamSource) {
StreamSource ss = (StreamSource)src;
InputStream in = ss.getInputStream();
- return in;
- } else {
- return null;
+ if (in != null) {
+ return in;
+ }
+ if (ss.getReader() != null) {
+ //Don't support reader, retry using system ID below
+ IOUtils.closeQuietly(ss.getReader());
+ }
}
+ URL url = new URL(src.getSystemId());
+ return url.openStream();
}
}
diff --git a/src/java/org/apache/fop/afp/util/SimpleResourceAccessor.java b/src/java/org/apache/fop/afp/util/SimpleResourceAccessor.java
index 51772c253..7a963928b 100644
--- a/src/java/org/apache/fop/afp/util/SimpleResourceAccessor.java
+++ b/src/java/org/apache/fop/afp/util/SimpleResourceAccessor.java
@@ -26,7 +26,8 @@ import java.net.URI;
import java.net.URL;
/**
- * Simple implementation of the {@link ResourceAccessor} interface for access via files.
+ * Simple implementation of the {@link ResourceAccessor} interface for access relative to a
+ * base URI.
*/
public class SimpleResourceAccessor implements ResourceAccessor {
@@ -34,23 +35,40 @@ public class SimpleResourceAccessor implements ResourceAccessor {
/**
* Creates a new simple resource accessor.
- * @param basePath the base path to resolve relative URIs to
+ * @param baseURI the base URI to resolve relative URIs against (may be null)
*/
- public SimpleResourceAccessor(File basePath) {
- this.baseURI = basePath.toURI();
+ public SimpleResourceAccessor(URI baseURI) {
+ this.baseURI = baseURI;
}
/**
* Creates a new simple resource accessor.
- * @param basePath the base path to resolve relative URIs to
+ * @param baseDir the base directory to resolve relative filenames against (may be null)
*/
- public SimpleResourceAccessor(String basePath) {
- this(new File(basePath));
+ public SimpleResourceAccessor(File baseDir) {
+ this(baseDir != null ? baseDir.toURI() : null);
+ }
+
+ /**
+ * Returns the base URI.
+ * @return the base URI (or null if no base URI was set)
+ */
+ public URI getBaseURI() {
+ return this.baseURI;
+ }
+
+ /**
+ * Resolve the given URI against the baseURI.
+ * @param uri the URI to resolve
+ * @return the resolved URI
+ */
+ protected URI resolveAgainstBase(URI uri) {
+ return (getBaseURI() != null ? getBaseURI().resolve(uri) : uri);
}
/** {@inheritDoc} */
public InputStream createInputStream(URI uri) throws IOException {
- URI resolved = this.baseURI.resolve(uri);
+ URI resolved = resolveAgainstBase(uri);
URL url = resolved.toURL();
return url.openStream();
}
diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java
index 58ae6e8e6..f96711d31 100644
--- a/src/java/org/apache/fop/apps/FOURIResolver.java
+++ b/src/java/org/apache/fop/apps/FOURIResolver.java
@@ -24,6 +24,8 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
@@ -32,8 +34,10 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.xmlgraphics.util.io.Base64EncodeStream;
import org.apache.xmlgraphics.util.uri.CommonURIResolver;
@@ -74,15 +78,31 @@ public class FOURIResolver implements javax.xml.transform.URIResolver {
base += "/";
}
File dir = new File(base);
- try {
- base = (dir.isDirectory() ? dir.toURI().toURL() : new URL(base)).toExternalForm();
- } catch (MalformedURLException mfue) {
- if (throwExceptions) {
- throw mfue;
+ if (dir.isDirectory()) {
+ return dir.toURI().toASCIIString();
+ } else {
+ URI baseURI;
+ try {
+ baseURI = new URI(base);
+ String scheme = baseURI.getScheme();
+ boolean directoryExists = true;
+ if ("file".equals(scheme)) {
+ dir = FileUtils.toFile(baseURI.toURL());
+ directoryExists = dir.isDirectory();
+ }
+ if (scheme == null || !directoryExists) {
+ String message = "base " + base + " is not a valid directory";
+ if (throwExceptions) {
+ throw new MalformedURLException(message);
+ }
+ log.error(message);
+ }
+ return baseURI.toASCIIString();
+ } catch (URISyntaxException e) {
+ //TODO not ideal: our base URLs are actually base URIs.
+ throw new MalformedURLException(e.getMessage());
}
- log.error(mfue.getMessage());
}
- return base;
}
/**
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index c0c14de62..64ab413dc 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -21,6 +21,7 @@ package org.apache.fop.apps;
// Java
import java.io.File;
+import java.net.MalformedURLException;
import java.util.Date;
import java.util.Map;
@@ -43,6 +44,7 @@ import org.apache.fop.events.EventListener;
import org.apache.fop.events.FOPEventListenerProxy;
import org.apache.fop.events.LoggingEventListener;
import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fonts.FontManager;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererFactory;
import org.apache.fop.render.XMLHandlerRegistry;
@@ -84,9 +86,6 @@ public class FOUserAgent {
*/
private String base = null;
- /** The base URL for all font URL resolutions. */
- private String fontBase = null;
-
/** A user settable URI Resolver */
private URIResolver uriResolver = null;
@@ -97,6 +96,7 @@ public class FOUserAgent {
private Renderer rendererOverride = null;
private FOEventHandler foEventHandlerOverride = null;
private boolean locatorEnabled = true; // true by default (for error messages).
+ private boolean conserveMemoryPolicy = false;
private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
//TODO Verify that a byte array is the best solution here
@@ -154,7 +154,6 @@ public class FOUserAgent {
}
this.factory = factory;
setBaseURL(factory.getBaseURL());
- setFontBaseURL(factory.getFontManager().getFontBaseURL());
setTargetResolution(factory.getTargetResolution());
if (this.getRendererOptions().get("accessibility") == null) {
this.rendererOptions.put("accessibility", Boolean.FALSE);
@@ -351,11 +350,16 @@ public class FOUserAgent {
}
/**
- * sets font base URL
+ * Sets font base URL.
* @param fontBaseUrl font base URL
+ * @deprecated Use {@link FontManager#setFontBaseURL(String)} instead.
*/
public void setFontBaseURL(String fontBaseUrl) {
- this.fontBase = fontBaseUrl;
+ try {
+ getFactory().getFontManager().setFontBaseURL(fontBaseUrl);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ }
}
/**
@@ -490,8 +494,13 @@ public class FOUserAgent {
// ---------------------------------------------- environment-level stuff
// (convenience access to FopFactory methods)
- /** @return the font base URL */
+ /**
+ * Returns the font base URL.
+ * @return the font base URL
+ * @deprecated Use {@link FontManager#getFontBaseURL()} instead. This method is not used by FOP.
+ */
public String getFontBaseURL() {
+ String fontBase = getFactory().getFontManager().getFontBaseURL();
return fontBase != null ? fontBase : getBaseURL();
}
@@ -623,6 +632,24 @@ public class FOUserAgent {
}
/**
+ * Check whether memory-conservation is enabled.
+ *
+ * @return true if FOP is to conserve as much as possible
+ */
+ public boolean isConserveMemoryPolicyEnabled() {
+ return this.conserveMemoryPolicy;
+ }
+
+ /**
+ * Control whether memory-conservation should be enabled
+ *
+ * @param conserveMemoryPolicy the cachingEnabled to set
+ */
+ public void setConserveMemoryPolicy(boolean conserveMemoryPolicy) {
+ this.conserveMemoryPolicy = conserveMemoryPolicy;
+ }
+
+ /**
* Check if accessibility is enabled.
* @return true if accessibility is enabled
*/
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java
index cf22a1e56..1a5c3cfd4 100644
--- a/src/java/org/apache/fop/apps/FopFactory.java
+++ b/src/java/org/apache/fop/apps/FopFactory.java
@@ -278,9 +278,11 @@ public class FopFactory implements ImageContext {
*/
public Fop newFop(FOUserAgent userAgent) throws FOPException {
if (userAgent.getRendererOverride() == null
- && userAgent.getFOEventHandlerOverride() == null) {
- throw new IllegalStateException("Either the overriding renderer or the overriding"
- + " FOEventHandler must be set when this factory method is used!");
+ && userAgent.getFOEventHandlerOverride() == null
+ && userAgent.getDocumentHandlerOverride() == null) {
+ throw new IllegalStateException("An overriding renderer,"
+ + " FOEventHandler or IFDocumentHandler must be set on the user agent"
+ + " when this factory method is used!");
}
return newFop(null, userAgent);
}
diff --git a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java
index e6f1aff16..a8b964a5d 100644
--- a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java
+++ b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java
@@ -61,6 +61,8 @@ public class FopFactoryConfigurator {
/** Defines the default target resolution (72dpi) for FOP */
public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi
+ private static final String PREFER_RENDERER = "prefer-renderer";
+
/** logger instance */
private final Log log = LogFactory.getLog(FopFactoryConfigurator.class);
@@ -182,6 +184,16 @@ public class FopFactoryConfigurator {
}
}
+ // prefer Renderer over IFDocumentHandler
+ if (cfg.getChild(PREFER_RENDERER, false) != null) {
+ try {
+ factory.getRendererFactory().setRendererPreferred(
+ cfg.getChild(PREFER_RENDERER).getValueAsBoolean());
+ } catch (ConfigurationException e) {
+ LogUtil.handleException(log, e, strict);
+ }
+ }
+
// configure font manager
FontManager fontManager = factory.getFontManager();
FontManagerConfigurator fontManagerConfigurator = new FontManagerConfigurator(cfg);
diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java
index 128fc8ce9..298cf263b 100644
--- a/src/java/org/apache/fop/area/AreaTreeHandler.java
+++ b/src/java/org/apache/fop/area/AreaTreeHandler.java
@@ -124,7 +124,11 @@ public class AreaTreeHandler extends FOEventHandler {
*/
protected void setupModel(FOUserAgent userAgent, String outputFormat,
OutputStream stream) throws FOPException {
- this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+ if (userAgent.isConserveMemoryPolicyEnabled()) {
+ this.model = new CachedRenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+ } else {
+ this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+ }
}
/**
@@ -442,7 +446,6 @@ public class AreaTreeHandler extends FOEventHandler {
/**
* Default constructor
- * @param areaTreeHandler area tree handler
*/
protected Statistics() {
this.runtime = Runtime.getRuntime();
diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
index 7269bdf10..bb7e47dd3 100644
--- a/src/java/org/apache/fop/area/AreaTreeParser.java
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -21,6 +21,8 @@ package org.apache.fop.area;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.nio.CharBuffer;
import java.util.List;
import java.util.Map;
@@ -41,6 +43,7 @@ import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
@@ -48,6 +51,7 @@ 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;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
@@ -68,6 +72,7 @@ import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.Viewport;
import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
@@ -149,6 +154,7 @@ public class AreaTreeParser {
private Stack delegateStack = new Stack();
private ContentHandler delegate;
private DOMImplementation domImplementation;
+ private Locator locator;
public Handler(AreaTreeModel treeModel, FOUserAgent userAgent,
@@ -224,6 +230,15 @@ public class AreaTreeParser {
}
/** {@inheritDoc} */
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+ private Locator getLocator() {
+ return this.locator;
+ }
+
+ /** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (delegate != null) {
@@ -356,6 +371,7 @@ public class AreaTreeParser {
pageSequence.setLanguage(lang);
String country = attributes.getValue("country");
pageSequence.setCountry(country);
+ transferForeignObjects(attributes, pageSequence);
areaStack.push(pageSequence);
}
}
@@ -970,9 +986,16 @@ public class AreaTreeParser {
this.currentPageViewport.addExtensionAttachment(attachment);
}
} else {
+ Object o = areaStack.peek();
+ if (o instanceof AreaTreeObject && obj instanceof ExtensionAttachment) {
+ AreaTreeObject ato = (AreaTreeObject)o;
+ ExtensionAttachment attachment = (ExtensionAttachment)obj;
+ ato.addExtensionAttachment(attachment);
+ } else {
log.warn("Don't know how to handle externally generated object: " + obj);
}
}
+ }
private void setAreaAttributes(Attributes attributes, Area area) {
area.setIPD(Integer.parseInt(attributes.getValue("ipd")));
@@ -1048,8 +1071,21 @@ public class AreaTreeParser {
= userAgent.getImageSessionContext();
ImageInfo info = manager.getImageInfo(uri, sessionContext);
bkg.setImageInfo(info);
- } catch (Exception e) {
- log.error("Background image not available: " + uri, e);
+ } catch (ImageException e) {
+ ResourceEventProducer eventProducer
+ = ResourceEventProducer.Provider.get(
+ this.userAgent.getEventBroadcaster());
+ eventProducer.imageError(this, uri, e, getLocator());
+ } catch (FileNotFoundException fnfe) {
+ ResourceEventProducer eventProducer
+ = ResourceEventProducer.Provider.get(
+ this.userAgent.getEventBroadcaster());
+ eventProducer.imageNotFound(this, uri, fnfe, getLocator());
+ } catch (IOException ioe) {
+ ResourceEventProducer eventProducer
+ = ResourceEventProducer.Provider.get(
+ this.userAgent.getEventBroadcaster());
+ eventProducer.imageIOError(this, uri, ioe, getLocator());
}
String repeat = attributes.getValue("bkg-repeat");
diff --git a/src/java/org/apache/fop/area/CachedRenderPagesModel.java b/src/java/org/apache/fop/area/CachedRenderPagesModel.java
index f522b978b..73c50fa17 100644
--- a/src/java/org/apache/fop/area/CachedRenderPagesModel.java
+++ b/src/java/org/apache/fop/area/CachedRenderPagesModel.java
@@ -129,7 +129,7 @@ public class CachedRenderPagesModel extends RenderPagesModel {
try {
// save page to cache
ObjectOutputStream tempstream;
- String fname = "fop-page-" + page.toString() + ".ser";
+ String fname = "fop-page-" + page.getPageIndex() + ".ser";
File tempFile = new File(baseDir, fname);
tempFile.deleteOnExit();
tempstream = new ObjectOutputStream(new BufferedOutputStream(
diff --git a/src/java/org/apache/fop/area/PageSequence.java b/src/java/org/apache/fop/area/PageSequence.java
index 887fdb43d..8fd3cd571 100644
--- a/src/java/org/apache/fop/area/PageSequence.java
+++ b/src/java/org/apache/fop/area/PageSequence.java
@@ -24,7 +24,7 @@ import java.util.List;
/**
* Represents a page sequence in the area tree.
*/
-public class PageSequence {
+public class PageSequence extends AreaTreeObject {
private List pages = new java.util.ArrayList();
private LineArea title;
diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java
index 6d5d9ca98..5106fd5bc 100644
--- a/src/java/org/apache/fop/area/inline/InlineArea.java
+++ b/src/java/org/apache/fop/area/inline/InlineArea.java
@@ -19,6 +19,8 @@
package org.apache.fop.area.inline;
+import java.io.Serializable;
+
import org.apache.fop.area.Area;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.Trait;
@@ -35,7 +37,7 @@ public class InlineArea extends Area {
* that can be used in order to re-compute adjustments when a
* page-number or a page-number-citation is resolved
*/
- protected class InlineAdjustingInfo {
+ protected class InlineAdjustingInfo implements Serializable {
/** stretch of the inline area */
protected int availableStretch;
/** shrink of the inline area */
diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java
index 734cd9b98..cb6756476 100644
--- a/src/java/org/apache/fop/cli/CommandLineOptions.java
+++ b/src/java/org/apache/fop/cli/CommandLineOptions.java
@@ -110,6 +110,8 @@ public class CommandLineOptions {
private Map renderingOptions = new java.util.HashMap();
/* target resolution (for the user agent) */
private int targetResolution = 0;
+ /* control memory-conservation policy */
+ private boolean conserveMemoryPolicy = false;
private FopFactory factory = FopFactory.newInstance();
private FOUserAgent foUserAgent;
@@ -168,6 +170,7 @@ public class CommandLineOptions {
}
addXSLTParameter("fop-output-format", getOutputFormat());
addXSLTParameter("fop-version", Version.getVersion());
+ foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy);
} else {
return false;
}
@@ -268,6 +271,8 @@ public class CommandLineOptions {
setLogOption("debug", "debug");
} else if (args[i].equals("-r")) {
factory.setStrictValidation(false);
+ } else if (args[i].equals("-conserve")) {
+ conserveMemoryPolicy = true;
} else if (args[i].equals("-dpi")) {
i = i + parseResolution(args, i);
} else if (args[i].equals("-q") || args[i].equals("--quiet")) {
@@ -1134,6 +1139,8 @@ public class CommandLineOptions {
+ " -a enables accessibility features (Tagged PDF etc., default off)\n"
+ " -pdfprofile prof PDF file will be generated with the specified profile\n"
+ " (Examples for prof: PDF/A-1b or PDF/X-3:2003)\n\n"
+ + " -conserve Enable memory-conservation policy (trades memory-consumption for disk I/O)"
+ + " (Note: currently only influences whether the area tree is serialized.)"
+ " [INPUT] \n"
+ " infile xsl:fo input file (the same as the next) \n"
+ " (use '-' for infile to pipe input from stdin)\n"
diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml
index 3b3b34e36..d26fbeb93 100644
--- a/src/java/org/apache/fop/events/EventFormatter.xml
+++ b/src/java/org/apache/fop/events/EventFormatter.xml
@@ -24,6 +24,8 @@
<message key="rule.childOfDeclarations">The element must be a child of fo:declarations.</message>
<message key="rule.childOfSPMorDeclarations">The element must be a child of fo:declarations or fo:simple-page-master.</message>
<message key="rule.childOfInstreamForeignObjectorExternalGraphic">The element must be a child of fo:instream-foreign-object or fo:external-graphic.</message>
+ <message key="rule.childOfPageSequence">The element must be a child of fo:page-sequence.</message>
+ <message key="rule.childOfPageSequenceOrSPM">The element must be a child of fo:page-sequence or fo:simple-page-master.</message>
<message key="rule.wrapperInvalidChildForParent">An fo:wrapper is only permitted to have children that would be permitted for its parent.</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.tooManyNodes">For "{elementName}", only one "{offendingNode}" may be declared.{{locator}}</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.nodeOutOfOrder">For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}}</message>
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java
index 8bcaa1538..5f23502f3 100644
--- a/src/java/org/apache/fop/fo/Constants.java
+++ b/src/java/org/apache/fop/fo/Constants.java
@@ -784,27 +784,27 @@ public interface Constants {
// compound property constants
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_BLOCK_PROGRESSION_DIRECTION = 1 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_CONDITIONALITY = 2 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_INLINE_PROGRESSION_DIRECTION = 3 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_LENGTH = 4 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_MAXIMUM = 5 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_MINIMUM = 6 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_OPTIMUM = 7 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_PRECEDENCE = 8 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_WITHIN_COLUMN = 9 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_WITHIN_LINE = 10 << COMPOUND_SHIFT;
- /** Property constant for compund property */
+ /** Property constant for compound property */
int CP_WITHIN_PAGE = 11 << COMPOUND_SHIFT;
// Enumeration constants
diff --git a/src/java/org/apache/fop/fo/flow/Leader.java b/src/java/org/apache/fop/fo/flow/Leader.java
index d72ed1e63..c25fc8cab 100644
--- a/src/java/org/apache/fop/fo/flow/Leader.java
+++ b/src/java/org/apache/fop/fo/flow/Leader.java
@@ -73,6 +73,7 @@ public class Leader extends InlineLevel {
leaderLength = pList.get(PR_LEADER_LENGTH).getLengthRange();
leaderPattern = pList.get(PR_LEADER_PATTERN).getEnum();
leaderPatternWidth = pList.get(PR_LEADER_PATTERN_WIDTH).getLength();
+ ruleThickness = pList.get(PR_RULE_THICKNESS).getLength();
switch(leaderPattern) {
case EN_SPACE:
// use Space
@@ -81,7 +82,6 @@ public class Leader extends InlineLevel {
// the following properties only apply
// for leader-pattern = "rule"
ruleStyle = pList.get(PR_RULE_STYLE).getEnum();
- ruleThickness = pList.get(PR_RULE_THICKNESS).getLength();
break;
case EN_DOTS:
break;
diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java
index d41ac86ab..26812166d 100644
--- a/src/java/org/apache/fop/fo/pagination/PageSequence.java
+++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java
@@ -48,7 +48,7 @@ public class PageSequence extends AbstractPageSequence {
// the set of flows includes StaticContent flows also
/** Map of flows to their flow name (flow-name, Flow) */
- private Map flowMap;
+ private Map/*<String, Flow>*/ flowMap;
/**
* The currentSimplePageMaster is either the page master for the
@@ -96,18 +96,18 @@ public class PageSequence extends AbstractPageSequence {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- flowMap = new java.util.HashMap();
+ flowMap = new java.util.HashMap/*<String, Flow>*/();
- this.simplePageMaster = getRoot().getLayoutMasterSet().getSimplePageMaster(masterReference);
- if (this.simplePageMaster == null) {
+ this.simplePageMaster
+ = getRoot().getLayoutMasterSet().getSimplePageMaster(masterReference);
+ if (simplePageMaster == null) {
this.pageSequenceMaster
- = getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference);
- if (this.pageSequenceMaster == null) {
+ = getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference);
+ if (pageSequenceMaster == null) {
getFOValidationEventProducer().masterNotFound(this, getName(),
masterReference, getLocator());
}
}
-
getFOEventHandler().startPageSequence(this);
}
@@ -170,7 +170,7 @@ public class PageSequence extends AbstractPageSequence {
flowMap.put(((StaticContent)child).getFlowName(), child);
break;
default:
- assert false;
+ super.addChildNode(child);
}
}
diff --git a/src/java/org/apache/fop/fo/pagination/Region.java b/src/java/org/apache/fop/fo/pagination/Region.java
index 87e9c4590..6f94418be 100644
--- a/src/java/org/apache/fop/fo/pagination/Region.java
+++ b/src/java/org/apache/fop/fo/pagination/Region.java
@@ -26,6 +26,7 @@ import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.Numeric;
+import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
@@ -130,6 +131,24 @@ public abstract class Region extends FObj {
|| name.equals("xsl-footnote-separator"));
}
+ /**
+ * Get the page-width context
+ * @param lengthBase the lengthBase to use for resolving percentages
+ * @return context for the width of the page-reference-area
+ */
+ protected PercentBaseContext getPageWidthContext(int lengthBase) {
+ return layoutMaster.getPageWidthContext(lengthBase);
+ }
+
+ /**
+ * Get the page-width context
+ * @param lengthBase the lengthBase to use for resolving percentages
+ * @return context for the width of the page-reference-area
+ */
+ protected PercentBaseContext getPageHeightContext(int lengthBase) {
+ return layoutMaster.getPageHeightContext(lengthBase);
+ }
+
/** {@inheritDoc} */
public boolean generatesReferenceAreas() {
return true;
diff --git a/src/java/org/apache/fop/fo/pagination/RegionAfter.java b/src/java/org/apache/fop/fo/pagination/RegionAfter.java
index 2189fa67b..841bff0d6 100644
--- a/src/java/org/apache/fop/fo/pagination/RegionAfter.java
+++ b/src/java/org/apache/fop/fo/pagination/RegionAfter.java
@@ -26,7 +26,7 @@ import java.awt.Rectangle;
import org.apache.fop.fo.FONode;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.LengthBase;
-import org.apache.fop.datatypes.SimplePercentBaseContext;
+import org.apache.fop.datatypes.PercentBaseContext;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_region-after">
@@ -48,25 +48,9 @@ public class RegionAfter extends RegionBA {
/* Special rules apply to resolving extent as values are resolved relative
* to the page size and reference orientation.
*/
- SimplePercentBaseContext pageWidthContext;
- SimplePercentBaseContext pageHeightContext;
- if (spm.getReferenceOrientation() % 180 == 0) {
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- } else {
- // invert width and height since top left are rotated by 90 (cl or ccl)
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- }
- SimplePercentBaseContext neighbourContext;
+ PercentBaseContext pageWidthContext = getPageWidthContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext neighbourContext;
Rectangle vpRect;
if (spm.getWritingMode() == EN_LR_TB || spm.getWritingMode() == EN_RL_TB) {
neighbourContext = pageWidthContext;
diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java
index 43499678a..165bb4734 100644
--- a/src/java/org/apache/fop/fo/pagination/RegionBody.java
+++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java
@@ -27,7 +27,7 @@ import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.Numeric;
-import org.apache.fop.datatypes.SimplePercentBaseContext;
+import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.properties.CommonMarginBlock;
@@ -106,24 +106,8 @@ public class RegionBody extends Region {
* Also the values are resolved relative to the page size
* and reference orientation.
*/
- SimplePercentBaseContext pageWidthContext;
- SimplePercentBaseContext pageHeightContext;
- if (spm.getReferenceOrientation() % 180 == 0) {
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CONTAINING_BLOCK_WIDTH,
- spm.getPageWidth().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CONTAINING_BLOCK_WIDTH,
- spm.getPageHeight().getValue());
- } else {
- // invert width and height since top left are rotated by 90 (cl or ccl)
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CONTAINING_BLOCK_WIDTH,
- spm.getPageHeight().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CONTAINING_BLOCK_WIDTH,
- spm.getPageWidth().getValue());
- }
+ PercentBaseContext pageWidthContext = getPageWidthContext(LengthBase.CONTAINING_BLOCK_WIDTH);
+ PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CONTAINING_BLOCK_WIDTH);
int start;
int end;
diff --git a/src/java/org/apache/fop/fo/pagination/RegionEnd.java b/src/java/org/apache/fop/fo/pagination/RegionEnd.java
index 611b1edf6..8b348ed5d 100644
--- a/src/java/org/apache/fop/fo/pagination/RegionEnd.java
+++ b/src/java/org/apache/fop/fo/pagination/RegionEnd.java
@@ -26,7 +26,7 @@ import java.awt.Rectangle;
import org.apache.fop.fo.FONode;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.LengthBase;
-import org.apache.fop.datatypes.SimplePercentBaseContext;
+import org.apache.fop.datatypes.PercentBaseContext;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_region-end">
@@ -48,25 +48,9 @@ public class RegionEnd extends RegionSE {
/* Special rules apply to resolving extent as values are resolved relative
* to the page size and reference orientation.
*/
- SimplePercentBaseContext pageWidthContext;
- SimplePercentBaseContext pageHeightContext;
- if (spm.getReferenceOrientation() % 180 == 0) {
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- } else {
- // invert width and height since top left are rotated by 90 (cl or ccl)
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- }
- SimplePercentBaseContext neighbourContext;
+ PercentBaseContext pageWidthContext = getPageWidthContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext neighbourContext;
Rectangle vpRect;
if (spm.getWritingMode() == EN_LR_TB || spm.getWritingMode() == EN_RL_TB) {
neighbourContext = pageHeightContext;
diff --git a/src/java/org/apache/fop/fo/pagination/RegionStart.java b/src/java/org/apache/fop/fo/pagination/RegionStart.java
index 12b578634..afe9ddfe1 100644
--- a/src/java/org/apache/fop/fo/pagination/RegionStart.java
+++ b/src/java/org/apache/fop/fo/pagination/RegionStart.java
@@ -26,7 +26,7 @@ import java.awt.Rectangle;
import org.apache.fop.fo.FONode;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.LengthBase;
-import org.apache.fop.datatypes.SimplePercentBaseContext;
+import org.apache.fop.datatypes.PercentBaseContext;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_region-start">
@@ -48,25 +48,9 @@ public class RegionStart extends RegionSE {
/* Special rules apply to resolving extent as values are resolved relative
* to the page size and reference orientation.
*/
- SimplePercentBaseContext pageWidthContext;
- SimplePercentBaseContext pageHeightContext;
- if (spm.getReferenceOrientation() % 180 == 0) {
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- } else {
- // invert width and height since top left are rotated by 90 (cl or ccl)
- pageWidthContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageHeight().getValue());
- pageHeightContext = new SimplePercentBaseContext(null,
- LengthBase.CUSTOM_BASE,
- spm.getPageWidth().getValue());
- }
- SimplePercentBaseContext neighbourContext;
+ PercentBaseContext pageWidthContext = getPageWidthContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE);
+ PercentBaseContext neighbourContext;
Rectangle vpRect;
if (spm.getWritingMode() == EN_LR_TB || spm.getWritingMode() == EN_RL_TB) {
neighbourContext = pageHeightContext;
diff --git a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java
index b0ec96406..8c95e1b8a 100644
--- a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java
+++ b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java
@@ -29,6 +29,8 @@ import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.Numeric;
+import org.apache.fop.datatypes.SimplePercentBaseContext;
+import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
@@ -195,6 +197,44 @@ public class SimplePageMaster extends FObj {
}
/**
+ * Gets the context for the width of the page-reference-area,
+ * taking into account the reference-orientation.
+ *
+ * @param lengthBase the lengthBase to use to resolve percentages
+ * @return context for the width of the page-reference-area
+ */
+ protected final PercentBaseContext getPageWidthContext(int lengthBase) {
+ return (this.referenceOrientation.getValue() % 180 == 0)
+ ? new SimplePercentBaseContext(
+ null,
+ lengthBase,
+ this.getPageWidth().getValue())
+ : new SimplePercentBaseContext(
+ null,
+ lengthBase,
+ this.getPageHeight().getValue());
+ }
+
+ /**
+ * Gets the context for the height of the page-reference-area,
+ * taking into account the reference-orientation.
+ *
+ * @param lengthBase the lengthBase to use to resolve percentages
+ * @return the context for the height of the page-reference-area
+ */
+ protected final PercentBaseContext getPageHeightContext(int lengthBase) {
+ return (this.referenceOrientation.getValue() % 180 == 0)
+ ? new SimplePercentBaseContext(
+ null,
+ lengthBase,
+ this.getPageHeight().getValue())
+ : new SimplePercentBaseContext(
+ null,
+ lengthBase,
+ this.getPageWidth().getValue());
+ }
+
+ /**
* Returns the region for a given region class.
* @param regionId Constants ID of the FO representing the region
* @return the region, null if it doesn't exist
diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
index eeafbb68b..8e3955cd8 100755
--- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
+++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
@@ -650,6 +650,78 @@ public class CommonBorderPaddingBackground {
|| borderInfo[START] != null || borderInfo[END] != null);
}
+ /**
+ * Returns the "background-color" property.
+ * @return the "background-color" property.
+ */
+ public Color getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ /**
+ * Returns the "background-attachment" property.
+ * @return the "background-attachment" property.
+ */
+ public int getBackgroundAttachment() {
+ return backgroundAttachment;
+ }
+
+ /**
+ * Returns the "background-image" property.
+ * @return the "background-image" property.
+ */
+ public String getBackgroundImage() {
+ return backgroundImage;
+ }
+
+ /**
+ * Returns the "background-repeat" property.
+ * @return the "background-repeat" property.
+ */
+ public int getBackgroundRepeat() {
+ return backgroundRepeat;
+ }
+
+ /**
+ * Returns the "background-position-horizontal" property.
+ * @return the "background-position-horizontal" property.
+ */
+ public Length getBackgroundPositionHorizontal() {
+ return backgroundPositionHorizontal;
+ }
+
+ /**
+ * Returns the "background-position-vertical" property.
+ * @return the "background-position-vertical" property.
+ */
+ public Length getBackgroundPositionVertical() {
+ return backgroundPositionVertical;
+ }
+
+ /**
+ * Returns the background image info
+ * @return the background image info
+ */
+ public ImageInfo getBackgroundImageInfo() {
+ return backgroundImageInfo;
+ }
+
+ /**
+ * Returns the border info
+ * @return the border info
+ */
+ public BorderInfo[] getBorderInfo() {
+ return borderInfo;
+ }
+
+ /**
+ * Returns the padding
+ * @return the padding
+ */
+ public CondLengthProperty[] getPadding() {
+ return padding;
+ }
+
/** {@inheritDoc} */
public boolean equals(Object obj) {
if (this == obj) {
diff --git a/src/java/org/apache/fop/fo/properties/CommonFont.java b/src/java/org/apache/fop/fo/properties/CommonFont.java
index 11275fdd3..55a2393fa 100755
--- a/src/java/org/apache/fop/fo/properties/CommonFont.java
+++ b/src/java/org/apache/fop/fo/properties/CommonFont.java
@@ -170,6 +170,16 @@ public final class CommonFont {
return fontWeight.getEnum();
}
+ /** @return the "font-size" property. */
+ public Length getFontSize() {
+ return fontSize;
+ }
+
+ /** @return the "font-size-adjust" property. */
+ public Numeric getFontSizeAdjust() {
+ return fontSizeAdjust;
+ }
+
/**
* Create and return an array of <code>FontTriplets</code> based on
* the properties stored in the instance variables.
diff --git a/src/java/org/apache/fop/fonts/FontAdder.java b/src/java/org/apache/fop/fonts/FontAdder.java
new file mode 100644
index 000000000..0d6a730cf
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/FontAdder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.fonts;
+
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.fonts.autodetect.FontInfoFinder;
+
+/**
+ * Adds a list of fonts to a given font info list
+ */
+public class FontAdder {
+ private FontEventListener listener;
+ private FontResolver resolver;
+ private FontManager manager;
+
+ /**
+ * Main constructor
+ * @param manager a font manager
+ * @param resolver a font resolver
+ * @param listener a font event handler
+ */
+ public FontAdder(FontManager manager, FontResolver resolver, FontEventListener listener) {
+ this.manager = manager;
+ this.resolver = resolver;
+ this.listener = listener;
+ }
+
+ /**
+ * Iterates over font url list adding to font info list
+ * @param fontURLList font file list
+ * @param fontInfoList a configured font info list
+ */
+ public void add(List/*<URL>*/ fontURLList, List/*<EmbedFontInfo>*/ fontInfoList) {
+ FontCache cache = manager.getFontCache();
+ FontInfoFinder finder = new FontInfoFinder();
+ finder.setEventListener(listener);
+
+ for (Iterator iter = fontURLList.iterator(); iter.hasNext();) {
+ URL fontUrl = (URL)iter.next();
+ EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, cache);
+ if (embedFontInfos == null) {
+ continue;
+ }
+ for (int i = 0, c = embedFontInfos.length; i < c; i++) {
+ EmbedFontInfo fontInfo = embedFontInfos[i];
+ if (fontInfo != null) {
+ fontInfoList.add(fontInfo);
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/fonts/FontDetector.java b/src/java/org/apache/fop/fonts/FontDetector.java
new file mode 100644
index 000000000..09671f1f8
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/FontDetector.java
@@ -0,0 +1,101 @@
+/*
+ * 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.fonts;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fonts.autodetect.FontFileFinder;
+import org.apache.fop.util.LogUtil;
+import org.apache.xmlgraphics.util.ClasspathResource;
+
+/**
+ * Detector of operating system and classpath fonts
+ */
+public class FontDetector {
+ private static Log log = LogFactory.getLog(FontDetector.class);
+
+ private static final String[] FONT_MIMETYPES = {
+ "application/x-font", "application/x-font-truetype"
+ };
+
+ private FontManager fontManager;
+ private FontAdder fontAdder;
+ private boolean strict;
+
+ /**
+ * Main constructor
+ * @param manager the font manager
+ * @param adder the font adder
+ * @param strict true if an Exception should be thrown if an error is found.
+ */
+ public FontDetector(FontManager manager, FontAdder adder, boolean strict) {
+ this.fontManager = manager;
+ this.fontAdder = adder;
+ this.strict = strict;
+ }
+
+ /**
+ * Detect installed fonts on the system
+ * @param fontInfoList a list of fontinfo to populate
+ * @throws FOPException thrown if a problem occurred during detection
+ */
+ public void detect(List/*<EmbedFontInfo>*/ fontInfoList) throws FOPException {
+ // search in font base if it is defined and
+ // is a directory but don't recurse
+ FontFileFinder fontFileFinder = new FontFileFinder();
+ String fontBaseURL = fontManager.getFontBaseURL();
+ if (fontBaseURL != null) {
+ try {
+ File fontBase = FileUtils.toFile(new URL(fontBaseURL));
+ if (fontBase != null) {
+ List/*<URL>*/ fontURLList = fontFileFinder.find(
+ fontBase.getAbsolutePath());
+ fontAdder.add(fontURLList, fontInfoList);
+
+ //Can only use the font base URL if it's a file URL
+ }
+ } catch (IOException e) {
+ LogUtil.handleException(log, e, strict);
+ }
+ }
+
+ // native o/s font directory finding
+ List/*<URL>*/ systemFontList;
+ try {
+ systemFontList = fontFileFinder.find();
+ fontAdder.add(systemFontList, fontInfoList);
+ } catch (IOException e) {
+ LogUtil.handleException(log, e, strict);
+ }
+
+ // classpath font finding
+ ClasspathResource resource = ClasspathResource.getInstance();
+ for (int i = 0; i < FONT_MIMETYPES.length; i++) {
+ fontAdder.add(resource.listResourcesOfMimeType(FONT_MIMETYPES[i]), fontInfoList);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/fonts/FontInfoConfigurator.java b/src/java/org/apache/fop/fonts/FontInfoConfigurator.java
new file mode 100644
index 000000000..c97901163
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/FontInfoConfigurator.java
@@ -0,0 +1,313 @@
+/*
+ * 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.fonts;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fonts.autodetect.FontFileFinder;
+import org.apache.fop.fonts.autodetect.FontInfoFinder;
+import org.apache.fop.util.LogUtil;
+
+/**
+ * An abstract FontInfo configurator
+ */
+public class FontInfoConfigurator {
+ /** logger instance */
+ protected static Log log = LogFactory.getLog(FontInfoConfigurator.class);
+
+ private Configuration cfg;
+ private FontManager fontManager;
+ private FontResolver fontResolver;
+ private FontEventListener listener;
+ private boolean strict;
+
+ /**
+ * Main constructor
+ * @param cfg the configuration object
+ * @param fontManager the font manager
+ * @param fontResolver the font resolver
+ * @param listener the font event listener
+ * @param strict true if an Exception should be thrown if an error is found.
+ */
+ public FontInfoConfigurator(Configuration cfg, FontManager fontManager,
+ FontResolver fontResolver, FontEventListener listener, boolean strict) {
+ this.cfg = cfg;
+ this.fontManager = fontManager;
+ this.fontResolver = fontResolver;
+ this.listener = listener;
+ this.strict = strict;
+ }
+
+ /**
+ * Initializes font info settings from the user configuration
+ * @param fontInfoList a font info list
+ * @throws FOPException if an exception occurs while processing the configuration
+ */
+ public void configure(List/*<EmbedFontInfo>*/ fontInfoList) throws FOPException {
+ Configuration fonts = cfg.getChild("fonts", false);
+ if (fonts != null) {
+ long start = 0;
+ if (log.isDebugEnabled()) {
+ log.debug("Starting font configuration...");
+ start = System.currentTimeMillis();
+ }
+
+ FontAdder fontAdder = new FontAdder(fontManager, fontResolver, listener);
+
+ // native o/s search (autodetect) configuration
+ boolean autodetectFonts = (fonts.getChild("auto-detect", false) != null);
+ if (autodetectFonts) {
+ FontDetector fontDetector = new FontDetector(fontManager, fontAdder, strict);
+ fontDetector.detect(fontInfoList);
+ }
+
+ // Add configured directories to FontInfo
+ addDirectories(fonts, fontAdder, fontInfoList);
+
+ // Add configured fonts to FontInfo
+ FontCache fontCache = fontManager.getFontCache();
+ addFonts(fonts, fontCache, fontInfoList);
+
+ // Update referenced fonts (fonts which are not to be embedded)
+ fontManager.updateReferencedFonts(fontInfoList);
+
+ // Update font cache if it has changed
+ if (fontCache != null && fontCache.hasChanged()) {
+ fontCache.save();
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Finished font configuration in "
+ + (System.currentTimeMillis() - start) + "ms");
+ }
+ }
+ }
+
+ private void addDirectories(Configuration fontsCfg,
+ FontAdder fontAdder, List/*<URL>*/ fontInfoList) throws FOPException {
+ // directory (multiple font) configuration
+ Configuration[] directories = fontsCfg.getChildren("directory");
+ for (int i = 0; i < directories.length; i++) {
+ boolean recursive = directories[i].getAttributeAsBoolean("recursive", false);
+ String directory = null;
+ try {
+ directory = directories[i].getValue();
+ } catch (ConfigurationException e) {
+ LogUtil.handleException(log, e, strict);
+ continue;
+ }
+ if (directory == null) {
+ LogUtil.handleException(log,
+ new FOPException("directory defined without value"), strict);
+ continue;
+ }
+
+ // add fonts found in directory
+ FontFileFinder fontFileFinder = new FontFileFinder(recursive ? -1 : 1);
+ List/*<URL>*/ fontURLList;
+ try {
+ fontURLList = fontFileFinder.find(directory);
+ fontAdder.add(fontURLList, fontInfoList);
+ } catch (IOException e) {
+ LogUtil.handleException(log, e, strict);
+ }
+ }
+ }
+
+ /**
+ * Populates the font info list from the fonts configuration
+ * @param fontsCfg a fonts configuration
+ * @param fontCache a font cache
+ * @param fontInfoList a font info list
+ * @throws FOPException if an exception occurs while processing the configuration
+ */
+ protected void addFonts(Configuration fontsCfg, FontCache fontCache,
+ List/*<EmbedFontInfo>*/ fontInfoList) throws FOPException {
+ // font file (singular) configuration
+ Configuration[] font = fontsCfg.getChildren("font");
+ for (int i = 0; i < font.length; i++) {
+ EmbedFontInfo embedFontInfo = getFontInfo(
+ font[i], fontCache);
+ if (embedFontInfo != null) {
+ fontInfoList.add(embedFontInfo);
+ }
+ }
+ }
+
+ private static void closeSource(Source src) {
+ if (src instanceof StreamSource) {
+ StreamSource streamSource = (StreamSource)src;
+ IOUtils.closeQuietly(streamSource.getInputStream());
+ IOUtils.closeQuietly(streamSource.getReader());
+ }
+ }
+
+ /**
+ * Returns a font info from a font node Configuration definition
+ *
+ * @param fontCfg Configuration object (font node)
+ * @param fontCache the font cache (or null if it is disabled)
+ * @return the embedded font info
+ * @throws FOPException if something's wrong with the config data
+ */
+ protected EmbedFontInfo getFontInfo(
+ Configuration fontCfg, FontCache fontCache)
+ throws FOPException {
+ String metricsUrl = fontCfg.getAttribute("metrics-url", null);
+ String embedUrl = fontCfg.getAttribute("embed-url", null);
+ String subFont = fontCfg.getAttribute("sub-font", null);
+
+ if (metricsUrl == null && embedUrl == null) {
+ LogUtil.handleError(log,
+ "Font configuration without metric-url or embed-url attribute",
+ strict);
+ return null;
+ }
+ if (strict) {
+ //This section just checks early whether the URIs can be resolved
+ //Stream are immediately closed again since they will never be used anyway
+ if (embedUrl != null) {
+ Source source = fontResolver.resolve(embedUrl);
+ closeSource(source);
+ if (source == null) {
+ LogUtil.handleError(log,
+ "Failed to resolve font with embed-url '" + embedUrl + "'", strict);
+ return null;
+ }
+ }
+ if (metricsUrl != null) {
+ Source source = fontResolver.resolve(metricsUrl);
+ closeSource(source);
+ if (source == null) {
+ LogUtil.handleError(log,
+ "Failed to resolve font with metric-url '" + metricsUrl + "'", strict);
+ return null;
+ }
+ }
+ }
+
+ Configuration[] tripletCfg = fontCfg.getChildren("font-triplet");
+
+ // no font triplet info
+ if (tripletCfg.length == 0) {
+ LogUtil.handleError(log, "font without font-triplet", strict);
+
+ File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl});
+ URL fontUrl;
+ try {
+ fontUrl = fontFile.toURI().toURL();
+ } catch (MalformedURLException e) {
+ // Should never happen
+ log.debug("Malformed Url: " + e.getMessage());
+ return null;
+ }
+ if (fontFile != null) {
+ FontInfoFinder finder = new FontInfoFinder();
+ finder.setEventListener(listener);
+ EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache);
+ return infos[0]; //When subFont is set, only one font is returned
+ } else {
+ return null;
+ }
+ }
+
+ List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
+ for (int j = 0; j < tripletCfg.length; j++) {
+ FontTriplet fontTriplet = getFontTriplet(tripletCfg[j]);
+ tripletList.add(fontTriplet);
+ }
+
+ boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
+ EncodingMode encodingMode = EncodingMode.valueOf(
+ fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()));
+ EmbedFontInfo embedFontInfo
+ = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont);
+ embedFontInfo.setEncodingMode(encodingMode);
+ if (fontCache != null) {
+ if (!fontCache.containsFont(embedFontInfo)) {
+ fontCache.addFont(embedFontInfo);
+ }
+ }
+
+ if (log.isDebugEnabled()) {
+ String embedFile = embedFontInfo.getEmbedFile();
+ log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "")
+ + "metric file " + embedFontInfo.getMetricsFile());
+ for (int j = 0; j < tripletList.size(); ++j) {
+ FontTriplet triplet = (FontTriplet) tripletList.get(j);
+ log.debug(" Font triplet "
+ + triplet.getName() + ", "
+ + triplet.getStyle() + ", "
+ + triplet.getWeight());
+ }
+ }
+ return embedFontInfo;
+ }
+
+ /**
+ * Creates a new FontTriplet given a triple Configuration
+ *
+ * @param tripletCfg a triplet configuration
+ * @return a font triplet font key
+ * @throws FOPException thrown if a FOP exception occurs
+ */
+ private FontTriplet getFontTriplet(Configuration tripletCfg) throws FOPException {
+ try {
+ String name = tripletCfg.getAttribute("name");
+ if (name == null) {
+ LogUtil.handleError(log, "font-triplet without name", strict);
+ return null;
+ }
+
+ String weightStr = tripletCfg.getAttribute("weight");
+ if (weightStr == null) {
+ LogUtil.handleError(log, "font-triplet without weight", strict);
+ return null;
+ }
+ int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr));
+
+ String style = tripletCfg.getAttribute("style");
+ if (style == null) {
+ LogUtil.handleError(log, "font-triplet without style", strict);
+ return null;
+ } else {
+ style = FontUtil.stripWhiteSpace(style);
+ }
+ return FontInfo.createFontKey(name, style, weight);
+ } catch (ConfigurationException e) {
+ LogUtil.handleException(log, e, strict);
+ }
+ return null;
+ }
+
+}
diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java
index b3833cf50..daf0a0cdb 100644
--- a/src/java/org/apache/fop/fonts/FontManager.java
+++ b/src/java/org/apache/fop/fonts/FontManager.java
@@ -20,6 +20,8 @@
package org.apache.fop.fonts;
import java.net.MalformedURLException;
+import java.util.Iterator;
+import java.util.List;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
@@ -186,4 +188,27 @@ public class FontManager {
public Matcher getReferencedFontsMatcher() {
return this.referencedFontsMatcher;
}
+
+ /**
+ * Updates the referenced font list
+ * @param fontInfoList a font info list
+ */
+ public void updateReferencedFonts(List fontInfoList) {
+ Matcher matcher = getReferencedFontsMatcher();
+ if (matcher == null) {
+ return; //No referenced fonts
+ }
+ Iterator iter = fontInfoList.iterator();
+ while (iter.hasNext()) {
+ EmbedFontInfo fontInfo = (EmbedFontInfo)iter.next();
+ Iterator triplets = fontInfo.getFontTriplets().iterator();
+ while (triplets.hasNext()) {
+ FontTriplet triplet = (FontTriplet)triplets.next();
+ if (matcher.matches(triplet)) {
+ fontInfo.setEmbedded(false);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
index 0d3bd6dcd..bd0f1ee14 100644
--- a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
+++ b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
@@ -130,7 +130,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder {
* @throws IOException io exception
* {@inheritDoc}
*/
- public List find() throws IOException {
+ public List/*<URL>*/ find() throws IOException {
final FontFinder fontDirFinder;
final String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")) {
@@ -142,8 +142,8 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder {
fontDirFinder = new UnixFontDirFinder();
}
}
- List fontDirs = fontDirFinder.find();
- List results = new java.util.ArrayList();
+ List/*<URL>*/ fontDirs = fontDirFinder.find();
+ List/*<URL>*/ results = new java.util.ArrayList/*<URL>*/();
for (Iterator iter = fontDirs.iterator(); iter.hasNext();) {
final File dir = (File)iter.next();
super.walk(dir, results);
diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFinder.java
index ee0d1e07f..0ab71daec 100644
--- a/src/java/org/apache/fop/fonts/autodetect/FontFinder.java
+++ b/src/java/org/apache/fop/fonts/autodetect/FontFinder.java
@@ -37,6 +37,6 @@ public interface FontFinder {
* @throws IOException
* In case of an I/O problem
*/
- List find() throws IOException;
+ List/*<URL>*/ find() throws IOException;
}
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
index a5393ced2..8dca1c749 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
@@ -26,7 +26,9 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.area.Area;
+import org.apache.fop.area.AreaTreeObject;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
@@ -266,8 +268,10 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
childLMs = new java.util.ArrayList(10);
}
childLMs.add(lm);
- log.trace(this.getClass().getName()
- + ": Adding child LM " + lm.getClass().getName());
+ if (log.isTraceEnabled()) {
+ log.trace(this.getClass().getName()
+ + ": Adding child LM " + lm.getClass().getName());
+ }
}
/**
@@ -300,6 +304,13 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
return pos;
}
+ private void verifyNonNullPosition(Position pos) {
+ if (pos == null || pos.getIndex() < 0) {
+ throw new IllegalArgumentException(
+ "Only non-null Positions with an index can be checked");
+ }
+ }
+
/**
* Indicates whether the given Position is the first area-generating Position of this LM.
* @param pos the Position (must be one with a position index)
@@ -307,9 +318,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
*/
public boolean isFirst(Position pos) {
//log.trace("isFirst() smallestPosNumberChecked=" + smallestPosNumberChecked + " " + pos);
- if (pos == null || pos.getIndex() < 0) {
- throw new IllegalArgumentException("Only non-null Positions with an index can be checked");
- }
+ verifyNonNullPosition(pos);
if (pos.getIndex() == this.smallestPosNumberChecked) {
return true;
} else if (pos.getIndex() < this.smallestPosNumberChecked) {
@@ -326,10 +335,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
* @return True if it is the last Position
*/
public boolean isLast(Position pos) {
- //log.trace("isLast() lastGenPos=" + lastGeneratedPosition + " " + pos);
- if (pos == null || pos.getIndex() < 0) {
- throw new IllegalArgumentException("Only non-null Positions with an index can be checked");
- }
+ verifyNonNullPosition(pos);
return (pos.getIndex() == this.lastGeneratedPosition
&& isFinished());
}
@@ -338,12 +344,32 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
* Transfers foreign attributes from the formatting object to the area.
* @param targetArea the area to set the attributes on
*/
- protected void transferForeignAttributes(Area targetArea) {
+ protected void transferForeignAttributes(AreaTreeObject targetArea) {
Map atts = fobj.getForeignAttributes();
targetArea.setForeignAttributes(atts);
}
/**
+ * Transfers extension attachments from the formatting object to the area.
+ * @param targetArea the area to set the extensions on
+ */
+ protected void transferExtensionAttachments(AreaTreeObject targetArea) {
+ if (fobj.hasExtensionAttachments()) {
+ targetArea.setExtensionAttachments(fobj.getExtensionAttachments());
+ }
+ }
+
+ /**
+ * Transfers extensions (foreign attributes and extension attachments) from
+ * the formatting object to the area.
+ * @param targetArea the area to set the extensions on
+ */
+ protected void transferExtensions(AreaTreeObject targetArea) {
+ transferForeignAttributes(targetArea);
+ transferExtensionAttachments(targetArea);
+ }
+
+ /**
* Registers the FO's markers on the current PageViewport
*
* @param isStarting boolean indicating whether the markers qualify as 'starting'
diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
index 64b8bbc0d..5a44c8391 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
@@ -167,6 +167,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
addChildToArea(childArea, getCurrentArea());
}
+ /** {@inheritDoc} */
+ protected void notifyEndOfLayout() {
+ super.notifyEndOfLayout();
+ // Free memory of the area tree
+ //this.parentArea = null;
+ }
+
/**
* Force current area to be added to parent area.
*/
@@ -340,18 +347,19 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
return returnList;
} else {
- if (prevLM != null) {
- // there is a block handled by prevLM
- // before the one handled by curLM
- addInBetweenBreak(contentList, context, childLC);
- }
if (returnedList == null || returnedList.isEmpty()) {
//Avoid NoSuchElementException below (happens with empty blocks)
continue;
}
+ if (prevLM != null
+ && !ElementListUtils.startsWithForcedBreak(returnedList)) {
+ // there is a block handled by prevLM before the one
+ // handled by curLM, and the one handled
+ // by the current LM does not begin with a break
+ addInBetweenBreak(contentList, context, childLC);
+ }
contentList.addAll(returnedList);
- if (((ListElement) ListUtil.getLast(returnedList))
- .isForcedBreak()) {
+ if (ElementListUtils.endsWithForcedBreak(returnedList)) {
// a descendant of this block has break-after
if (curLM.isFinished() && !hasNextChildLM()) {
forcedBreakAfterLast = (BreakElement) ListUtil
@@ -486,7 +494,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
// ? "penalty" : (lastElement.isGlue() ? "glue" : "box" )));
/*LF*/ //log.debug(" position e' " + lastElement.getPosition().getClass().getName());
/*LF*/ //log.debug(" " + (bpUnit > 0 ? "unit" : ""));
- Position innerPosition = ((NonLeafPosition) lastElement.getPosition()).getPosition();
+ Position innerPosition = lastElement.getPosition().getPosition();
if (innerPosition == null && lastElement.isGlue()) {
// this adjustment applies to space-before or space-after of this block
@@ -536,7 +544,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
/*LF*/ //log.debug(" BLM.negotiateBPDAdjustment> chiamata passata");
return ((BlockLevelLayoutManager)storedPenalty.getLayoutManager())
.negotiateBPDAdjustment(storedPenalty.getW(),
- (KnuthElement)storedPenalty);
+ storedPenalty);
} else {
// the original penalty has width = 0
// the adjustment involves only the spaces before and after
@@ -787,12 +795,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
returnList.add(new KnuthGlue(0, 0, 0,
SPACE_AFTER_ADJUSTMENT,
new NonLeafPosition(this, null),
- (!spaceAfterIsConditional) ? false : true));
+ spaceAfterIsConditional));
} else {
returnList.add(new KnuthGlue(adjustedSpaceAfter, 0, 0,
SPACE_AFTER_ADJUSTMENT,
new NonLeafPosition(this, null),
- (!spaceAfterIsConditional) ? false : true));
+ spaceAfterIsConditional));
}
if (!spaceAfterIsConditional) {
returnList.add(new KnuthBox(0,
@@ -1201,8 +1209,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
totalLength.add(new MinOptMax(element.getW()));
//log.debug("box " + element.getW());
} else if (element.isGlue()) {
- totalLength.min -= ((KnuthGlue) element).getZ();
- totalLength.max += ((KnuthGlue) element).getY();
+ totalLength.min -= element.getZ();
+ totalLength.max += element.getY();
//leafValue = ((LeafPosition) element.getPosition()).getLeafPos();
//log.debug("glue " + element.getW() + " + "
// + ((KnuthGlue) element).getY() + " - " + ((KnuthGlue) element).getZ());
@@ -1239,10 +1247,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
lengthAfterBreak.subtract(new MinOptMax(element.getW()));
bPrevIsBox = true;
} else if (element.isGlue()) {
- lengthBeforeBreak.min -= ((KnuthGlue) element).getZ();
- lengthAfterBreak.min += ((KnuthGlue) element).getZ();
- lengthBeforeBreak.max += ((KnuthGlue) element).getY();
- lengthAfterBreak.max -= ((KnuthGlue) element).getY();
+ lengthBeforeBreak.min -= element.getZ();
+ lengthAfterBreak.min += element.getZ();
+ lengthBeforeBreak.max += element.getY();
+ lengthAfterBreak.max -= element.getY();
bPrevIsBox = false;
} else {
lengthBeforeBreak.add(new MinOptMax(element.getW()));
@@ -1250,7 +1258,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
}
// create the new elements
- if (element.isPenalty() && ((KnuthPenalty) element).getP() < KnuthElement.INFINITE
+ if (element.isPenalty() && element.getP() < KnuthElement.INFINITE
|| element.isGlue() && bPrevIsBox
|| !oldListIterator.hasNext()) {
// suppress elements after the breaking point
@@ -1260,8 +1268,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
iStepsForward++;
if (el.isGlue()) {
// suppressed glue
- lengthAfterBreak.min += ((KnuthGlue) el).getZ();
- lengthAfterBreak.max -= ((KnuthGlue) el).getY();
+ lengthAfterBreak.min += el.getZ();
+ lengthAfterBreak.max -= el.getY();
} else if (el.isPenalty()) {
// suppressed penalty, do nothing
} else {
@@ -1281,8 +1289,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
for (int i = 0; i < iStepsForward; i++) {
KnuthElement el = (KnuthElement) oldListIterator.previous();
if (el.isGlue()) {
- lengthAfterBreak.min -= ((KnuthGlue) el).getZ();
- lengthAfterBreak.max += ((KnuthGlue) el).getY();
+ lengthAfterBreak.min -= el.getZ();
+ lengthAfterBreak.max += el.getY();
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
index d7f854a42..d3403cd6b 100644
--- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
+++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
@@ -194,6 +194,15 @@ public final class ElementListUtils {
}
/**
+ * Indicates whether the given element list starts with a forced break.
+ * @param elems the element list
+ * @return true if the list starts with a forced break
+ */
+ public static boolean startsWithForcedBreak(List elems) {
+ return !elems.isEmpty() && ((ListElement) elems.get(0)).isForcedBreak();
+ }
+
+ /**
* Indicates whether the given element list ends with a penalty with a non-infinite penalty
* value.
* @param elems the element list
@@ -229,4 +238,4 @@ public final class ElementListUtils {
return prevBreak;
}
-}
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java
index 4dcb5e14c..d6c727f68 100644
--- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java
@@ -105,7 +105,9 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan
Dimension intrinsicSize = info.getSize().getDimensionMpt();
ImageLayout layout = new ImageLayout(getExternalDocument(), this, intrinsicSize);
- areaTreeHandler.getAreaTreeModel().startPageSequence(new PageSequence(null));
+ PageSequence pageSequence = new PageSequence(null);
+ transferExtensions(pageSequence);
+ areaTreeHandler.getAreaTreeModel().startPageSequence(pageSequence);
if (log.isDebugEnabled()) {
log.debug("Starting layout");
}
diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
index 245fa7235..dd23d2e85 100644
--- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
@@ -88,8 +88,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
.getDisableColumnBalancing();
} else if (curLM instanceof BlockContainerLayoutManager) {
span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan();
- disableColumnBalancing = ((BlockContainerLayoutManager) curLM)
- .getBlockContainerFO().getDisableColumnBalancing();
+ disableColumnBalancing = ((BlockContainerLayoutManager) curLM).getBlockContainerFO()
+ .getDisableColumnBalancing();
}
int currentSpan = context.getCurrentSpan();
@@ -130,24 +130,23 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
returnList.addAll(returnedList);
SpaceResolver.resolveElementList(returnList);
return returnList;
- } else {
- if (returnList.size() > 0) {
+ } else if (returnedList.size() > 0) {
+ if (returnList.size() > 0
+ && !ElementListUtils.startsWithForcedBreak(returnedList)) {
addInBetweenBreak(returnList, context, childLC);
}
- if (returnedList.size() > 0) {
- returnList.addAll(returnedList);
- if (ElementListUtils.endsWithForcedBreak(returnList)) {
- if (curLM.isFinished() && !hasNextChildLM()) {
- //If the layout manager is finished at this point, the pending
- //marks become irrelevant.
- childLC.clearPendingMarks();
- //setFinished(true);
- break;
- }
- // a descendant of this flow has break-after
- SpaceResolver.resolveElementList(returnList);
- return returnList;
+ returnList.addAll(returnedList);
+ if (ElementListUtils.endsWithForcedBreak(returnList)) {
+ if (curLM.isFinished() && !hasNextChildLM()) {
+ //If the layout manager is finished at this point, the pending
+ //marks become irrelevant.
+ childLC.clearPendingMarks();
+ //setFinished(true);
+ break;
}
+ // a descendant of this flow has break-after
+ SpaceResolver.resolveElementList(returnList);
+ return returnList;
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
index 5dc1576c7..1137065ab 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
@@ -273,7 +273,8 @@ public class PageBreaker extends AbstractBreaker {
//Get page break from which we restart
PageBreakPosition pbp = (PageBreakPosition)
alg.getPageBreaks().get(restartPoint - 1);
- newStartPos = pbp.getLeafPos();
+ //Set starting position to the first element *after* the page-break
+ newStartPos = pbp.getLeafPos() + 1;
//Handle page break right here to avoid any side-effects
if (newStartPos > 0) {
handleBreakTrait(Constants.EN_PAGE);
@@ -306,16 +307,15 @@ public class PageBreaker extends AbstractBreaker {
1, true, BreakingAlgorithm.ALL_BREAKS);
AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+ " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+ //Make sure we only add the areas we haven't added already
+ effectiveList.ignoreAtStart = newStartPos;
boolean replaceLastPage
= iOptPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
if (replaceLastPage) {
//Replace last page
pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
- //Make sure we only add the areas we haven't added already
- effectiveList.ignoreAtStart = newStartPos;
addAreas(algRestart, iOptPageCount, originalList, effectiveList);
} else {
- effectiveList.ignoreAtStart = newStartPos;
addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
//Add blank last page
pageProvider.setLastPageIndex(currentPageNum + 1);
@@ -430,8 +430,8 @@ public class PageBreaker extends AbstractBreaker {
childLC);
}
// set the offset from the top margin
- Footnote parentArea = (Footnote) pslm.getCurrentPV().getBodyRegion().getFootnote();
- int topOffset = (int) pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
+ Footnote parentArea = pslm.getCurrentPV().getBodyRegion().getFootnote();
+ int topOffset = pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
if (separatorArea != null) {
topOffset -= separatorArea.getBPD();
}
@@ -451,7 +451,7 @@ public class PageBreaker extends AbstractBreaker {
/** {@inheritDoc} */
protected void observeElementList(List elementList) {
ElementListObserver.observe(elementList, "breaker",
- ((PageSequence)pslm.getFObj()).getId());
+ pslm.getFObj().getId());
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
index f9517554f..67c41ccf0 100644
--- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
@@ -92,6 +92,7 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel();
org.apache.fop.area.PageSequence pageSequenceAreaObject
= new org.apache.fop.area.PageSequence(title);
+ transferExtensions(pageSequenceAreaObject);
pageSequenceAreaObject.setLanguage(getPageSequence().getLanguage());
pageSequenceAreaObject.setCountry(getPageSequence().getCountry());
areaTreeModel.startPageSequence(pageSequenceAreaObject);
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
index f3bbc454a..fe82245b9 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
@@ -121,16 +121,15 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
= new org.apache.fop.area.inline.Leader();
leader.setRuleStyle(fobj.getRuleStyle());
leader.setRuleThickness(fobj.getRuleThickness().getValue(this));
- leader.setBPD(fobj.getRuleThickness().getValue(this));
leaderArea = leader;
} else {
leaderArea = new Space();
- leaderArea.setBPD(1);
}
+ leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
leaderArea.addTrait(Trait.COLOR, fobj.getColor());
} else if (fobj.getLeaderPattern() == EN_SPACE) {
leaderArea = new Space();
- leaderArea.setBPD(1);
+ leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
} else if (fobj.getLeaderPattern() == EN_DOTS) {
TextArea t = new TextArea();
char dot = '.'; // userAgent.getLeaderDotCharacter();
@@ -198,7 +197,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
} else {
//Content collapsed to nothing, so use a space
leaderArea = new Space();
- leaderArea.setBPD(1);
+ leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
}
}
TraitSetter.setProducerID(leaderArea, fobj.getId());
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index ba5e232e9..239a1a88e 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -201,8 +201,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
p.setP(0);
}
- notifyEndOfLayout();
-
setFinished(true);
return returnList;
}
@@ -427,6 +425,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
flush();
curBlockArea = null;
+
+ notifyEndOfLayout();
}
/** Adds background areas for the column, body and row, if any. */
diff --git a/src/java/org/apache/fop/pdf/AbstractPDFFontStream.java b/src/java/org/apache/fop/pdf/AbstractPDFFontStream.java
index f3d005bd3..34c9c5dee 100644
--- a/src/java/org/apache/fop/pdf/AbstractPDFFontStream.java
+++ b/src/java/org/apache/fop/pdf/AbstractPDFFontStream.java
@@ -33,9 +33,8 @@ public abstract class AbstractPDFFontStream extends AbstractPDFStream {
}
/** {@inheritDoc} */
- protected void setupFilterList() {
- addDefaultFilter(PDFFilterList.FONT_FILTER);
- super.setupFilterList();
+ protected String getDefaultFilterName() {
+ return PDFFilterList.FONT_FILTER;
}
}
diff --git a/src/java/org/apache/fop/pdf/AbstractPDFStream.java b/src/java/org/apache/fop/pdf/AbstractPDFStream.java
index fc853b512..4107c7e7a 100644
--- a/src/java/org/apache/fop/pdf/AbstractPDFStream.java
+++ b/src/java/org/apache/fop/pdf/AbstractPDFStream.java
@@ -47,21 +47,23 @@ public abstract class AbstractPDFStream extends PDFDictionary {
* from outside.
*/
protected void setupFilterList() {
- addDefaultFilter(PDFFilterList.DEFAULT_FILTER);
+ if (!getFilterList().isInitialized()) {
+ getFilterList().addDefaultFilters(
+ getDocumentSafely().getFilterMap(),
+ getDefaultFilterName());
+ }
prepareImplicitFilters();
getDocument().applyEncryption(this);
}
/**
- * Adds the default filter to the filter list if the filter list hasn't been initialized, yet.
- * @param filterName the name of the default filter to use
+ * Returns the name of a suitable filter for this PDF object.
+ *
+ * @return the default filter
+ * @see PDFFilterList
*/
- protected void addDefaultFilter(String filterName) {
- if (!getFilterList().isInitialized()) {
- getFilterList().addDefaultFilters(
- getDocumentSafely().getFilterMap(),
- filterName);
- }
+ protected String getDefaultFilterName() {
+ return PDFFilterList.DEFAULT_FILTER;
}
/**
diff --git a/src/java/org/apache/fop/pdf/PDFImageXObject.java b/src/java/org/apache/fop/pdf/PDFImageXObject.java
index a69d9e8de..9ec8f1595 100644
--- a/src/java/org/apache/fop/pdf/PDFImageXObject.java
+++ b/src/java/org/apache/fop/pdf/PDFImageXObject.java
@@ -159,14 +159,11 @@ public class PDFImageXObject extends PDFXObject {
}
/**
- * This sets up the default filters for XObjects. It uses the PDFImage
- * instance to determine what default filters to apply.
* {@inheritDoc}
+ * This class uses the PDFImage instance to determine the default filter.
*/
- protected void setupFilterList() {
- addDefaultFilter(pdfimage.getFilterHint());
- super.setupFilterList();
+ protected String getDefaultFilterName() {
+ return pdfimage.getFilterHint();
}
-
}
diff --git a/src/java/org/apache/fop/pdf/PDFMetadata.java b/src/java/org/apache/fop/pdf/PDFMetadata.java
index 5008183ef..92796c0d1 100644
--- a/src/java/org/apache/fop/pdf/PDFMetadata.java
+++ b/src/java/org/apache/fop/pdf/PDFMetadata.java
@@ -59,9 +59,8 @@ public class PDFMetadata extends PDFStream {
}
/** {@inheritDoc} */
- protected void setupFilterList() {
- addDefaultFilter(PDFFilterList.METADATA_FILTER);
- super.setupFilterList();
+ protected String getDefaultFilterName() {
+ return PDFFilterList.METADATA_FILTER;
}
/**
diff --git a/src/java/org/apache/fop/render/AbstractConfigurator.java b/src/java/org/apache/fop/render/AbstractConfigurator.java
new file mode 100644
index 000000000..b1ac1c61a
--- /dev/null
+++ b/src/java/org/apache/fop/render/AbstractConfigurator.java
@@ -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;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOUserAgent;
+
+/**
+ * An abstract configurator
+ */
+public abstract class AbstractConfigurator {
+ /** logger instance */
+ protected static Log log = LogFactory.getLog(AbstractConfigurator.class);
+
+ private static final String MIME = "mime";
+
+ /** fop factory configuration */
+ protected FOUserAgent userAgent = null;
+
+ /**
+ * Default constructor
+ * @param userAgent user agent
+ */
+ public AbstractConfigurator(FOUserAgent userAgent) {
+ super();
+ this.userAgent = userAgent;
+ }
+
+ /**
+ * Returns the configuration subtree for a specific renderer.
+ * @param mimeType the MIME type of the renderer
+ * @return the requested configuration subtree, null if there's no configuration
+ */
+ protected Configuration getConfig(String mimeType) {
+ Configuration cfg = userAgent.getFactory().getUserConfig();
+ if (cfg == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("userconfig is null");
+ }
+ return null;
+ }
+
+ Configuration userConfig = null;
+
+ String type = getType();
+ Configuration[] cfgs
+ = cfg.getChild(type + "s").getChildren(type);
+ for (int i = 0; i < cfgs.length; ++i) {
+ Configuration child = cfgs[i];
+ try {
+ if (child.getAttribute(MIME).equals(mimeType)) {
+ userConfig = child;
+ break;
+ }
+ } catch (ConfigurationException e) {
+ // silently pass over configurations without mime type
+ }
+ }
+ log.debug((userConfig == null ? "No u" : "U")
+ + "ser configuration found for MIME type " + mimeType);
+ return userConfig;
+ }
+
+ /**
+ * Returns the configurator type
+ * @return the configurator type
+ */
+ public abstract String getType();
+}
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index d7df7596d..8f60ace2f 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -29,8 +29,11 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.w3c.dom.Document;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Area;
@@ -66,7 +69,6 @@ import org.apache.fop.area.inline.WordArea;
import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontInfo;
-import org.w3c.dom.Document;
/**
* Abstract base class for all renderers. The Abstract renderer does all the
@@ -648,7 +650,6 @@ public abstract class AbstractRenderer
* @param space the space to render
*/
protected void renderInlineSpace(Space space) {
- space.setBPD(0);
renderInlineAreaBackAndBorders(space);
// an inline space moves the inline progression position
// for the current block by the width or height of the space
@@ -831,15 +832,6 @@ public abstract class AbstractRenderer
}
/**
- * Get the MIME type of the renderer.
- *
- * @return The MIME type of the renderer
- */
- public String getMimeType() {
- return null;
- }
-
- /**
* Converts a millipoint-based transformation matrix to points.
* @param at a millipoint-based transformation matrix
* @return a point-based transformation matrix
diff --git a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java
index 09540dfbb..c1a8bc182 100644
--- a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java
@@ -20,9 +20,6 @@
package org.apache.fop.render;
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOUserAgent;
@@ -30,21 +27,16 @@ import org.apache.fop.apps.FOUserAgent;
* Abstract base classes for renderer-related configurator classes. This class basically just
* provides an accessor to the specific renderer configuration object.
*/
-public abstract class AbstractRendererConfigurator {
-
- /** logger instance */
- protected static Log log = LogFactory.getLog(AbstractRendererConfigurator.class);
-
- /** fop factory configuration */
- protected FOUserAgent userAgent = null;
+public abstract class AbstractRendererConfigurator extends AbstractConfigurator {
+ private static final String TYPE = "renderer";
+
/**
* Default constructor
* @param userAgent user agent
*/
public AbstractRendererConfigurator(FOUserAgent userAgent) {
- super();
- this.userAgent = userAgent;
+ super(userAgent);
}
/**
@@ -53,16 +45,8 @@ public abstract class AbstractRendererConfigurator {
* @return the requested configuration subtree, null if there's no configuration
*/
protected Configuration getRendererConfig(Renderer renderer) {
- String mimeType = renderer.getMimeType();
- if (mimeType == null) {
- if (log.isInfoEnabled()) {
- log.info("renderer mimeType is null");
+ return super.getConfig(renderer.getMimeType());
}
- return null;
- }
-
- return getRendererConfig(mimeType);
- }
/**
* Returns the configuration subtree for a specific renderer.
@@ -70,31 +54,14 @@ public abstract class AbstractRendererConfigurator {
* @return the requested configuration subtree, null if there's no configuration
*/
protected Configuration getRendererConfig(String mimeType) {
- Configuration cfg = userAgent.getFactory().getUserConfig();
- if (cfg == null) {
- if (log.isDebugEnabled()) {
- log.debug("userconfig is null");
+ return super.getConfig(mimeType);
}
- return null;
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getType() {
+ return TYPE;
}
- Configuration userRendererConfig = null;
-
- Configuration[] cfgs
- = cfg.getChild("renderers").getChildren("renderer");
- for (int i = 0; i < cfgs.length; ++i) {
- Configuration child = cfgs[i];
- try {
- if (child.getAttribute("mime").equals(mimeType)) {
- userRendererConfig = child;
- break;
- }
- } catch (ConfigurationException e) {
- // silently pass over configurations without mime type
- }
- }
- log.debug((userRendererConfig == null ? "No u" : "U")
- + "ser configuration found for MIME type " + mimeType);
- return userRendererConfig;
- }
}
diff --git a/src/java/org/apache/fop/render/DefaultFontResolver.java b/src/java/org/apache/fop/render/DefaultFontResolver.java
index 6fb7e0f01..a4960c665 100644
--- a/src/java/org/apache/fop/render/DefaultFontResolver.java
+++ b/src/java/org/apache/fop/render/DefaultFontResolver.java
@@ -41,7 +41,7 @@ public class DefaultFontResolver implements FontResolver {
/** {@inheritDoc} */
public Source resolve(String href) {
- return userAgent.resolveURI(href, userAgent.getFontBaseURL());
+ return userAgent.resolveURI(href, userAgent.getFactory().getFontManager().getFontBaseURL());
}
}
diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java
index f1a76be1d..66618b093 100644
--- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java
@@ -19,46 +19,26 @@
package org.apache.fop.render;
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Iterator;
import java.util.List;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.xmlgraphics.util.ClasspathResource;
-
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.CustomFontCollection;
-import org.apache.fop.fonts.EmbedFontInfo;
-import org.apache.fop.fonts.EncodingMode;
-import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontEventListener;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontInfoConfigurator;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
-import org.apache.fop.fonts.FontTriplet;
-import org.apache.fop.fonts.FontUtil;
-import org.apache.fop.fonts.autodetect.FontFileFinder;
-import org.apache.fop.fonts.autodetect.FontInfoFinder;
import org.apache.fop.fonts.base14.Base14FontCollection;
import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
-import org.apache.fop.util.LogUtil;
/**
* Base Print renderer configurator (mostly handles font configuration)
@@ -95,7 +75,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
FontEventListener listener = new FontEventAdapter(
renderer.getUserAgent().getEventBroadcaster());
- List embedFontInfoList = buildFontList(cfg, fontResolver, listener);
+ List/*<EmbedFontInfo>*/ embedFontInfoList = buildFontList(cfg, fontResolver, listener);
printRenderer.addFontList(embedFontInfoList);
}
@@ -107,7 +87,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
* @return the list of {@code EmbedFontInfo} objects
* @throws FOPException if an error occurs while processing the configuration
*/
- protected List buildFontList(Configuration cfg, FontResolver fontResolver,
+ protected List/*<EmbedFontInfo>*/ buildFontList(Configuration cfg, FontResolver fontResolver,
FontEventListener listener) throws FOPException {
FopFactory factory = userAgent.getFactory();
FontManager fontManager = factory.getFontManager();
@@ -117,346 +97,15 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
}
boolean strict = factory.validateUserConfigStrictly();
- FontCache fontCache = fontManager.getFontCache();
-
- List/*<EmbedFontInfo>*/ embedFontInfoList = buildFontListFromConfiguration(cfg,
- fontResolver, strict, fontManager, listener);
-
- if (fontCache != null && fontCache.hasChanged()) {
- fontCache.save();
- }
- return embedFontInfoList;
- }
-
- /**
- * Builds a list of EmbedFontInfo objects for use with the setup() method.
- *
- * @param cfg Configuration object
- * @param fontResolver the FontResolver to use
- * @param strict true if an Exception should be thrown if an error is found.
- * @param fontManager the font manager
- * @param listener a font event listener
- * @return a List of EmbedFontInfo objects.
- * @throws FOPException If an error occurs while processing the configuration
- */
- public static List/*<EmbedFontInfo>*/ buildFontListFromConfiguration(Configuration cfg,
- FontResolver fontResolver,
- boolean strict, FontManager fontManager,
- FontEventListener listener) throws FOPException {
- FontCache fontCache = fontManager.getFontCache();
- String fontBaseURL = fontManager.getFontBaseURL();
- List/*<EmbedFontInfo>*/ fontInfoList
- = new java.util.ArrayList/*<EmbedFontInfo>*/();
-
- Configuration fonts = cfg.getChild("fonts", false);
- if (fonts != null) {
- long start = 0;
- if (log.isDebugEnabled()) {
- log.debug("Starting font configuration...");
- start = System.currentTimeMillis();
- }
-
- // native o/s search (autodetect) configuration
- boolean autodetectFonts = (fonts.getChild("auto-detect", false) != null);
- if (autodetectFonts) {
- // search in font base if it is defined and
- // is a directory but don't recurse
- FontFileFinder fontFileFinder = new FontFileFinder();
- if (fontBaseURL != null) {
- try {
- File fontBase = FileUtils.toFile(new URL(fontBaseURL));
- if (fontBase != null) {
- //Can only use the font base URL if it's a file URL
- addFontInfoListFromFileList(
- fontFileFinder.find(fontBase.getAbsolutePath()),
- fontInfoList,
- fontResolver,
- fontCache,
- listener
- );
- }
- } catch (IOException e) {
- LogUtil.handleException(log, e, strict);
- }
- }
-
- // native o/s font directory finder
- try {
- addFontInfoListFromFileList(
- fontFileFinder.find(),
- fontInfoList,
- fontResolver,
- fontCache,
- listener
- );
- } catch (IOException e) {
- LogUtil.handleException(log, e, strict);
- }
-
- // load fonts from classpath
- addFontInfoListFromFileList(ClasspathResource.getInstance()
- .listResourcesOfMimeType("application/x-font"),
- fontInfoList, fontResolver, fontCache, listener);
- addFontInfoListFromFileList(
- ClasspathResource.getInstance()
- .listResourcesOfMimeType(
- "application/x-font-truetype"),
- fontInfoList, fontResolver, fontCache, listener);
- }
-
- // directory (multiple font) configuration
- Configuration[] directories = fonts.getChildren("directory");
- for (int i = 0; i < directories.length; i++) {
- boolean recursive = directories[i].getAttributeAsBoolean("recursive", false);
- String directory = null;
- try {
- directory = directories[i].getValue();
- } catch (ConfigurationException e) {
- LogUtil.handleException(log, e, strict);
- continue;
- }
- if (directory == null) {
- LogUtil.handleException(log,
- new FOPException("directory defined without value"), strict);
- continue;
- }
- FontFileFinder fontFileFinder = new FontFileFinder(recursive ? -1 : 1);
- try {
- addFontInfoListFromFileList(
- fontFileFinder.find(directory),
- fontInfoList,
- fontResolver,
- fontCache,
- listener
- );
- } catch (IOException e) {
- LogUtil.handleException(log, e, strict);
- }
- }
- // font file (singular) configuration
- Configuration[] font = fonts.getChildren("font");
- for (int i = 0; i < font.length; i++) {
- EmbedFontInfo embedFontInfo = getFontInfoFromConfiguration(
- font[i], fontResolver, strict, fontCache, listener);
- if (embedFontInfo != null) {
- fontInfoList.add(embedFontInfo);
- }
- }
-
- // Update referenced fonts (fonts which are not to be embedded)
- updateReferencedFonts(fontInfoList, fontManager.getReferencedFontsMatcher());
-
- if (log.isDebugEnabled()) {
- log.debug("Finished font configuration in "
- + (System.currentTimeMillis() - start) + "ms");
- }
- }
+ //Read font configuration
+ FontInfoConfigurator fontInfoConfigurator
+ = new FontInfoConfigurator(cfg, fontManager, fontResolver, listener, strict);
+ List/*<EmbedFontInfo>*/ fontInfoList = new java.util.ArrayList/*<EmbedFontInfo>*/();
+ fontInfoConfigurator.configure(fontInfoList);
return fontInfoList;
}
- private static void updateReferencedFonts(List fontInfoList, FontTriplet.Matcher matcher) {
- if (matcher == null) {
- return; //No referenced fonts
- }
- Iterator iter = fontInfoList.iterator();
- while (iter.hasNext()) {
- EmbedFontInfo fontInfo = (EmbedFontInfo)iter.next();
- Iterator triplets = fontInfo.getFontTriplets().iterator();
- while (triplets.hasNext()) {
- FontTriplet triplet = (FontTriplet)triplets.next();
- if (matcher.matches(triplet)) {
- fontInfo.setEmbedded(false);
- break;
- }
- }
- }
- }
-
-
- /**
- * Iterates over font file list adding font info to list
- * @param fontFileList font file list
- * @param embedFontInfoList a configured font info list
- * @param resolver font resolver
- */
- private static void addFontInfoListFromFileList(
- List fontFileList, List/*<EmbedFontInfo>*/ embedFontInfoList,
- FontResolver resolver, FontCache fontCache, FontEventListener listener) {
- for (Iterator iter = fontFileList.iterator(); iter.hasNext();) {
- URL fontUrl = (URL)iter.next();
- // parse font to ascertain font info
- FontInfoFinder finder = new FontInfoFinder();
- finder.setEventListener(listener);
- //EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache);
-
- //List<EmbedFontInfo> embedFontInfoList = finder.find(fontUrl, resolver, fontCache);
- EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, fontCache);
-
- if (embedFontInfos == null) {
- continue;
- }
-
- for (int i = 0, c = embedFontInfos.length; i < c; i++) {
- EmbedFontInfo fontInfo = embedFontInfos[i];
- if (fontInfo != null) {
- embedFontInfoList.add(fontInfo);
- }
- }
- }
- }
-
- private static void closeSource(Source src) {
- if (src instanceof StreamSource) {
- StreamSource streamSource = (StreamSource)src;
- IOUtils.closeQuietly(streamSource.getInputStream());
- IOUtils.closeQuietly(streamSource.getReader());
- }
- }
-
- /**
- * Creates a new FontTriplet given a triple Configuration
- *
- * @param tripletCfg a triplet configuration
- * @param strict use strict validation
- * @return a font triplet font key
- * @throws FOPException thrown if a FOP exception occurs
- */
- private static FontTriplet getFontTripletFromConfiguration(
- Configuration tripletCfg, boolean strict) throws FOPException {
- try {
- String name = tripletCfg.getAttribute("name");
- if (name == null) {
- LogUtil.handleError(log, "font-triplet without name", strict);
- return null;
- }
-
- String weightStr = tripletCfg.getAttribute("weight");
- if (weightStr == null) {
- LogUtil.handleError(log, "font-triplet without weight", strict);
- return null;
- }
- int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr));
-
- String style = tripletCfg.getAttribute("style");
- if (style == null) {
- LogUtil.handleError(log, "font-triplet without style", strict);
- return null;
- } else {
- style = FontUtil.stripWhiteSpace(style);
- }
- return FontInfo.createFontKey(name, style, weight);
- } catch (ConfigurationException e) {
- LogUtil.handleException(log, e, strict);
- }
- return null;
- }
-
- /**
- * Returns a font info from a font node Configuration definition
- *
- * @param fontCfg Configuration object (font node)
- * @param fontResolver font resolver used to resolve font
- * @param strict validate configuration strictly
- * @param fontCache the font cache (or null if it is disabled)
- * @return the embedded font info
- * @throws FOPException if something's wrong with the config data
- */
- private static EmbedFontInfo getFontInfoFromConfiguration(
- Configuration fontCfg, FontResolver fontResolver, boolean strict,
- FontCache fontCache, FontEventListener listener)
- throws FOPException {
- String metricsUrl = fontCfg.getAttribute("metrics-url", null);
- String embedUrl = fontCfg.getAttribute("embed-url", null);
- String subFont = fontCfg.getAttribute("sub-font", null);
-
- if (metricsUrl == null && embedUrl == null) {
- LogUtil.handleError(log,
- "Font configuration without metric-url or embed-url attribute",
- strict);
- return null;
- }
- if (strict) {
- //This section just checks early whether the URIs can be resolved
- //Stream are immediately closed again since they will never be used anyway
- if (embedUrl != null) {
- Source source = fontResolver.resolve(embedUrl);
- closeSource(source);
- if (source == null) {
- LogUtil.handleError(log,
- "Failed to resolve font with embed-url '" + embedUrl + "'", strict);
- return null;
- }
- }
- if (metricsUrl != null) {
- Source source = fontResolver.resolve(metricsUrl);
- closeSource(source);
- if (source == null) {
- LogUtil.handleError(log,
- "Failed to resolve font with metric-url '" + metricsUrl + "'", strict);
- return null;
- }
- }
- }
-
- Configuration[] tripletCfg = fontCfg.getChildren("font-triplet");
-
- // no font triplet info
- if (tripletCfg.length == 0) {
- LogUtil.handleError(log, "font without font-triplet", strict);
-
- File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl});
- URL fontUrl;
- try {
- fontUrl = fontFile.toURI().toURL();
- } catch (MalformedURLException e) {
- // Should never happen
- log.debug("Malformed Url: " + e.getMessage());
- return null;
- }
- if (fontFile != null) {
- FontInfoFinder finder = new FontInfoFinder();
- finder.setEventListener(listener);
- EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache);
- return infos[0]; //When subFont is set, only one font is returned
- } else {
- return null;
- }
- }
-
- List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
- for (int j = 0; j < tripletCfg.length; j++) {
- FontTriplet fontTriplet = getFontTripletFromConfiguration(tripletCfg[j], strict);
- tripletList.add(fontTriplet);
- }
-
- boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
- EncodingMode encodingMode = EncodingMode.valueOf(
- fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()));
- EmbedFontInfo embedFontInfo
- = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont);
- embedFontInfo.setEncodingMode(encodingMode);
- if (fontCache != null) {
- if (!fontCache.containsFont(embedFontInfo)) {
- fontCache.addFont(embedFontInfo);
- }
- }
-
- if (log.isDebugEnabled()) {
- String embedFile = embedFontInfo.getEmbedFile();
- log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "")
- + "metric file " + embedFontInfo.getMetricsFile());
- for (int j = 0; j < tripletList.size(); ++j) {
- FontTriplet triplet = (FontTriplet) tripletList.get(j);
- log.debug(" Font triplet "
- + triplet.getName() + ", "
- + triplet.getStyle() + ", "
- + triplet.getWeight());
- }
- }
- return embedFontInfo;
- }
-
// ---=== IFDocumentHandler configuration ===---
/** {@inheritDoc} */
@@ -485,5 +134,4 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
new FontCollection[fontCollections.size()]));
documentHandler.setFontInfo(fontInfo);
}
-
}
diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java
index b12664818..3832a0714 100644
--- a/src/java/org/apache/fop/render/RendererFactory.java
+++ b/src/java/org/apache/fop/render/RendererFactory.java
@@ -51,6 +51,8 @@ public class RendererFactory {
private Map eventHandlerMakerMapping = new java.util.HashMap();
private Map documentHandlerMakerMapping = new java.util.HashMap();
+ private boolean rendererPreferred = false;
+
/**
* Main constructor.
*/
@@ -61,6 +63,26 @@ public class RendererFactory {
}
/**
+ * Controls whether a {@link Renderer} is preferred over a {@link IFDocumentHandler} if
+ * both are available for the same MIME type.
+ * @param value true to prefer the {@link Renderer},
+ * false to prefer the {@link IFDocumentHandler}.
+ */
+ public void setRendererPreferred(boolean value) {
+ this.rendererPreferred = value;
+ }
+
+ /**
+ * Indicates whether a {@link Renderer} is preferred over a {@link IFDocumentHandler} if
+ * both are available for the same MIME type.
+ * @return true if the {@link Renderer} is preferred,
+ * false if the {@link IFDocumentHandler} is preferred.
+ */
+ public boolean isRendererPreferred() {
+ return this.rendererPreferred;
+ }
+
+ /**
* Add a new RendererMaker. If another maker has already been registered for a
* particular MIME type, this call overwrites the existing one.
* @param maker the RendererMaker
@@ -236,27 +258,54 @@ public class RendererFactory {
} else if (userAgent.getRendererOverride() != null) {
return userAgent.getRendererOverride();
} else {
- AbstractRendererMaker maker = getRendererMaker(outputFormat);
- if (maker != null) {
- Renderer rend = maker.makeRenderer(userAgent);
- rend.setUserAgent(userAgent);
- RendererConfigurator configurator = maker.getConfigurator(userAgent);
- if (configurator != null) {
- configurator.configure(rend);
+ Renderer renderer;
+ if (isRendererPreferred()) {
+ //Try renderer first
+ renderer = tryRendererMaker(userAgent, outputFormat);
+ if (renderer == null) {
+ renderer = tryIFDocumentHandlerMaker(userAgent, outputFormat);
}
- return rend;
} else {
- AbstractIFDocumentHandlerMaker documentHandlerMaker
- = getDocumentHandlerMaker(outputFormat);
- if (documentHandlerMaker != null) {
- IFDocumentHandler documentHandler = createDocumentHandler(
- userAgent, outputFormat);
- return createRendererForDocumentHandler(documentHandler);
- } else {
- throw new UnsupportedOperationException(
- "No renderer for the requested format available: " + outputFormat);
+ //Try document handler first
+ renderer = tryIFDocumentHandlerMaker(userAgent, outputFormat);
+ if (renderer == null) {
+ renderer = tryRendererMaker(userAgent, outputFormat);
}
}
+ if (renderer == null) {
+ throw new UnsupportedOperationException(
+ "No renderer for the requested format available: " + outputFormat);
+ }
+ return renderer;
+ }
+ }
+
+ private Renderer tryIFDocumentHandlerMaker(FOUserAgent userAgent, String outputFormat)
+ throws FOPException {
+ AbstractIFDocumentHandlerMaker documentHandlerMaker
+ = getDocumentHandlerMaker(outputFormat);
+ if (documentHandlerMaker != null) {
+ IFDocumentHandler documentHandler = createDocumentHandler(
+ userAgent, outputFormat);
+ return createRendererForDocumentHandler(documentHandler);
+ } else {
+ return null;
+ }
+ }
+
+ private Renderer tryRendererMaker(FOUserAgent userAgent, String outputFormat)
+ throws FOPException {
+ AbstractRendererMaker maker = getRendererMaker(outputFormat);
+ if (maker != null) {
+ Renderer rend = maker.makeRenderer(userAgent);
+ rend.setUserAgent(userAgent);
+ RendererConfigurator configurator = maker.getConfigurator(userAgent);
+ if (configurator != null) {
+ configurator.configure(rend);
+ }
+ return rend;
+ } else {
+ return null;
}
}
@@ -327,6 +376,9 @@ public class RendererFactory {
*/
public IFDocumentHandler createDocumentHandler(FOUserAgent userAgent, String outputFormat)
throws FOPException {
+ if (userAgent.getDocumentHandlerOverride() != null) {
+ return userAgent.getDocumentHandlerOverride();
+ }
AbstractIFDocumentHandlerMaker maker = getDocumentHandlerMaker(outputFormat);
if (maker == null) {
throw new UnsupportedOperationException(
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index 8391422ff..8d29145cf 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -38,9 +38,9 @@ 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.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
-import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
@@ -70,7 +70,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
private Map/*<String,String>*/pageSegmentMap
= new java.util.HashMap/*<String,String>*/();
- private boolean inPageHeader;
+ private static final int LOC_ELSEWHERE = 0;
+ private static final int LOC_FOLLOWING_PAGE_SEQUENCE = 1;
+ private static final int LOC_IN_PAGE_HEADER = 2;
+
+ private int location = LOC_ELSEWHERE;
/**
* Default constructor.
@@ -92,11 +96,6 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}
/** {@inheritDoc} */
- public void setContext(IFContext context) {
- super.setContext(context);
- }
-
- /** {@inheritDoc} */
public IFDocumentHandlerConfigurator getConfigurator() {
return new AFPRendererConfigurator(getUserAgent());
}
@@ -164,6 +163,7 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
} catch (IOException ioe) {
throw new IFException("I/O error in startPageSequence()", ioe);
}
+ this.location = LOC_FOLLOWING_PAGE_SEQUENCE;
}
/** {@inheritDoc} */
@@ -186,6 +186,7 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
/** {@inheritDoc} */
public void startPage(int index, String name, String pageMasterName, Dimension size)
throws IFException {
+ this.location = LOC_ELSEWHERE;
paintingState.clear();
pageSegmentMap.clear();
@@ -208,12 +209,12 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
/** {@inheritDoc} */
public void startPageHeader() throws IFException {
super.startPageHeader();
- this.inPageHeader = true;
+ this.location = LOC_IN_PAGE_HEADER;
}
/** {@inheritDoc} */
public void endPageHeader() throws IFException {
- this.inPageHeader = false;
+ this.location = LOC_ELSEWHERE;
super.endPageHeader();
}
@@ -244,30 +245,49 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
public void handleExtensionObject(Object extension) throws IFException {
if (extension instanceof AFPPageSetup) {
AFPPageSetup aps = (AFPPageSetup)extension;
- if (!inPageHeader) {
- throw new IFException(
- "AFP page setup extension encountered outside the page header: " + aps, null);
- }
String element = aps.getElementName();
- if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) {
- String overlay = aps.getName();
- if (overlay != null) {
- dataStream.createIncludePageOverlay(overlay);
+ if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(element)) {
+ if (this.location != LOC_IN_PAGE_HEADER
+ && this.location != LOC_FOLLOWING_PAGE_SEQUENCE) {
+ throw new IFException(
+ "TLE extension must be in the page header or between page-sequence"
+ + " and the first page: " + aps, null);
}
- } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) {
- String name = aps.getName();
- String source = aps.getValue();
- pageSegmentMap.put(source, name);
- } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(element)) {
String name = aps.getName();
String value = aps.getValue();
dataStream.createTagLogicalElement(name, value);
- } else if (AFPElementMapping.NO_OPERATION.equals(element)) {
- String content = aps.getContent();
- if (content != null) {
- dataStream.createNoOperation(content);
+ } else {
+ if (this.location != LOC_IN_PAGE_HEADER) {
+ throw new IFException(
+ "AFP page setup extension encountered outside the page header: " + aps, null);
+ }
+ if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) {
+ String overlay = aps.getName();
+ if (overlay != null) {
+ dataStream.createIncludePageOverlay(overlay);
+ }
+ } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) {
+ String name = aps.getName();
+ String source = aps.getValue();
+ pageSegmentMap.put(source, name);
+ } else if (AFPElementMapping.NO_OPERATION.equals(element)) {
+ String content = aps.getContent();
+ if (content != null) {
+ dataStream.createNoOperation(content);
+ }
}
}
+ } else if (extension instanceof AFPInvokeMediumMap) {
+ if (this.location != LOC_FOLLOWING_PAGE_SEQUENCE) {
+ throw new IFException(
+ "AFP IMM extension must be between page-sequence and the first page: "
+ + extension, null);
+ }
+ AFPInvokeMediumMap imm = (AFPInvokeMediumMap)extension;
+ String mediumMap = imm.getName();
+ if (mediumMap != null) {
+ dataStream.createInvokeMediumMap(mediumMap);
+ }
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandlerMaker.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandlerMaker.java
index e0b13d979..440db3eda 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandlerMaker.java
@@ -30,9 +30,8 @@ import org.apache.fop.render.intermediate.IFDocumentHandler;
*/
public class AFPDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
- //TODO Revert to normal MIME after stabilization!
private static final String[] MIMES = new String[]
- {MimeConstants.MIME_AFP + ";mode=painter"};
+ {MimeConstants.MIME_AFP};
/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java
index 1816ff515..3efe5cbb4 100644
--- a/src/java/org/apache/fop/render/afp/AFPPainter.java
+++ b/src/java/org/apache/fop/render/afp/AFPPainter.java
@@ -49,6 +49,7 @@ 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;
@@ -342,12 +343,13 @@ public class AFPPainter extends AbstractIFPainter {
try {
//Embed fonts (char sets and code pages)
//TODO This should be moved to a place where it has less performance impact
- if (charSet.getPath() != null) {
+ if (charSet.getResourceAccessor() != null) {
+ ResourceAccessor accessor = charSet.getResourceAccessor();
documentHandler.getResourceManager().createIncludedResource(
- charSet.getName(), charSet.getPath(),
+ charSet.getName(), accessor,
ResourceObject.TYPE_FONT_CHARACTER_SET);
documentHandler.getResourceManager().createIncludedResource(
- charSet.getCodePage(), charSet.getPath(),
+ charSet.getCodePage(), accessor,
ResourceObject.TYPE_CODE_PAGE);
}
} catch (IOException ioe) {
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index 1967ae607..7e34d361c 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -63,8 +63,8 @@ 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.LineArea;
import org.apache.fop.area.OffDocumentItem;
+import org.apache.fop.area.PageSequence;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.Image;
@@ -80,6 +80,7 @@ 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.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
/**
@@ -213,12 +214,31 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust
}
/** {@inheritDoc} */
- public void startPageSequence(LineArea seqTitle) {
+ public void startPageSequence(PageSequence pageSequence) {
+ super.startPageSequence(pageSequence);
try {
dataStream.startPageGroup();
} catch (IOException e) {
log.error(e.getMessage());
}
+ if (pageSequence.hasExtensionAttachments()) {
+ for (Iterator iter = pageSequence.getExtensionAttachments().iterator();
+ iter.hasNext();) {
+ ExtensionAttachment attachment = (ExtensionAttachment)iter.next();
+ if (attachment instanceof AFPInvokeMediumMap) {
+ AFPInvokeMediumMap imm = (AFPInvokeMediumMap)attachment;
+ String mediumMap = imm.getName();
+ if (mediumMap != null) {
+ dataStream.createInvokeMediumMap(mediumMap);
+ }
+ } else if (attachment instanceof AFPPageSetup) {
+ AFPPageSetup aps = (AFPPageSetup)attachment;
+ String name = aps.getName();
+ String value = aps.getValue();
+ dataStream.createTagLogicalElement(name, value);
+ }
+ }
+ }
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index bd6df6136..fcc1140c7 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -20,6 +20,8 @@
package org.apache.fop.render.afp;
import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
import org.apache.avalon.framework.configuration.Configuration;
@@ -33,6 +35,8 @@ import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.fonts.FopCharacterSet;
import org.apache.fop.afp.fonts.OutlineFont;
import org.apache.fop.afp.fonts.RasterFont;
+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.fonts.FontCollection;
@@ -85,7 +89,29 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
log.error("Mandatory font configuration element '<afp-font...' is missing");
return null;
}
- String path = afpFontCfg.getAttribute("path", fontPath);
+
+ URI baseURI = null;
+ String uri = afpFontCfg.getAttribute("base-uri", fontPath);
+ if (uri == null) {
+ //Fallback for old attribute which only supports local filenames
+ String path = afpFontCfg.getAttribute("path", fontPath);
+ if (path != null) {
+ File f = new File(path);
+ baseURI = f.toURI();
+ }
+ } else {
+ try {
+ baseURI = new URI(uri);
+ } catch (URISyntaxException e) {
+ log.error("Invalid URI: " + e.getMessage());
+ return null;
+ }
+ }
+ ResourceAccessor accessor = new DefaultFOPResourceAccessor(
+ this.userAgent,
+ this.userAgent.getFactory().getFontManager().getFontBaseURL(),
+ baseURI);
+
String type = afpFontCfg.getAttribute("type");
if (type == null) {
log.error("Mandatory afp-font configuration attribute 'type=' is missing");
@@ -147,7 +173,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
}
} else {
font.addCharacterSet(size, new CharacterSet(
- codepage, encoding, characterset, path));
+ codepage, encoding, characterset, accessor));
}
}
return new AFPFontInfo(font, tripletList);
@@ -180,7 +206,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
log.error(msg);
}
} else {
- characterSet = new CharacterSet(codepage, encoding, characterset, path);
+ characterSet = new CharacterSet(codepage, encoding, characterset, accessor);
}
// Create a new font object
OutlineFont font = new OutlineFont(name, characterSet);
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
index c3ba2c43b..83615b75d 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
@@ -33,12 +33,6 @@ import org.apache.fop.fo.FONode;
*/
public class AFPElementMapping extends ElementMapping {
- /** page element */
- public static final String PAGE = "page";
-
- /** page group element */
-// public static final String PAGE_GROUP = "page-group";
-
/** tag logical element */
public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element";
@@ -51,8 +45,8 @@ public class AFPElementMapping extends ElementMapping {
/** NOP */
public static final String NO_OPERATION = "no-operation";
- /** resource information (name, level, dest) */
-// public static final String RESOURCE_INFO = "resource-info";
+ /** IMM: Invoke Medium Map (on fo:page-sequence) */
+ public static final String INVOKE_MEDIUM_MAP = "invoke-medium-map";
/**
* The namespace used for AFP extensions
@@ -77,11 +71,6 @@ public class AFPElementMapping extends ElementMapping {
if (foObjs == null) {
super.foObjs = new java.util.HashMap();
- foObjs.put(PAGE, new AFPPageSetupMaker());
-// foObjs.put(
-// PAGE_GROUP,
-// new AFPPageGroupMaker()
-// );
foObjs.put(
TAG_LOGICAL_ELEMENT,
new AFPTagLogicalElementMaker());
@@ -94,51 +83,40 @@ public class AFPElementMapping extends ElementMapping {
foObjs.put(
NO_OPERATION,
new AFPNoOperationMaker());
-// foObjs.put(
-// RESOURCE_INFO,
-// new AFPResourceInfoMaker());
- }
- }
-
- static class AFPPageSetupMaker extends ElementMapping.Maker {
- public FONode make(FONode parent) {
- return new AFPPageSetupElement(parent);
+ foObjs.put(
+ INVOKE_MEDIUM_MAP,
+ new AFPInvokeMediumMapMaker());
}
}
static class AFPIncludePageOverlayMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
- return new AFPElement(parent, INCLUDE_PAGE_OVERLAY);
+ return new AFPPageSetupElement(parent, INCLUDE_PAGE_OVERLAY);
}
}
static class AFPIncludePageSegmentMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
- return new AFPElement(parent, INCLUDE_PAGE_SEGMENT);
+ return new AFPPageSetupElement(parent, INCLUDE_PAGE_SEGMENT);
}
}
static class AFPTagLogicalElementMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
- return new AFPElement(parent, TAG_LOGICAL_ELEMENT);
+ return new AFPPageSetupElement(parent, TAG_LOGICAL_ELEMENT);
}
}
static class AFPNoOperationMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
- return new AFPElement(parent, NO_OPERATION);
+ return new AFPPageSetupElement(parent, NO_OPERATION);
+ }
+ }
+
+ static class AFPInvokeMediumMapMaker extends ElementMapping.Maker {
+ public FONode make(FONode parent) {
+ return new AFPInvokeMediumMapElement(parent);
}
}
-// static class AFPResourceInfoMaker extends ElementMapping.Maker {
-// public FONode make(FONode parent) {
-// return new AFPResourceInfoElement(parent);
-// }
-// }
-
-// static class AFPPageGroupMaker extends ElementMapping.Maker {
-// public FONode make(FONode parent) {
-// return new AFPElement(parent, PAGE_GROUP);
-// }
-// }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java
index 9a8429b00..e027e7f32 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java
@@ -5,9 +5,9 @@
* 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.
@@ -21,45 +21,37 @@ package org.apache.fop.render.afp.extensions;
import java.io.Serializable;
-import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.xmlgraphics.util.XMLizable;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
* This is the pass-through value object for the AFP extension.
*/
public abstract class AFPExtensionAttachment
implements ExtensionAttachment, Serializable, XMLizable {
+
private static final long serialVersionUID = 7190606822558332901L;
/** The category URI for this extension attachment. */
public static final String CATEGORY = "apache:fop:extensions:afp";
+ /** name attribute */
+ protected static final String ATT_NAME = "name";
+
/**
* the extension element name
*/
protected String elementName;
/**
- * the extension content
- */
- protected String content;
-
- /**
* the extension name attribute
*/
protected String name;
/**
- * the extension value attribute
- */
- protected String value;
-
- /**
* Default constructor.
- *
+ *
* @param elementName the name of the afp extension attachment, may be null
*/
public AFPExtensionAttachment(String elementName) {
@@ -91,65 +83,9 @@ public abstract class AFPExtensionAttachment
this.name = name;
}
- /**
- * @return the value
- */
- public String getValue() {
- return value;
- }
-
- /**
- * Sets the value
- * @param source The value name to set.
- */
- public void setValue(String source) {
- this.value = source;
- }
-
/** {@inheritDoc} */
public String getCategory() {
return CATEGORY;
}
- /**
- * @return the data
- */
- public String getContent() {
- return content;
- }
-
- /**
- * Sets the data
- * @param content The byte data to set.
- */
- public void setContent(String content) {
- this.content = content;
- }
-
- /**
- * name attribute
- */
- protected static final String ATT_NAME = "name";
-
- /**
- * value attribute
- */
- protected static final String ATT_VALUE = "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 (value != null && value.length() > 0) {
- atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
- }
- handler.startElement(CATEGORY, elementName, elementName, atts);
- if (content != null && content.length() > 0) {
- char[] chars = content.toCharArray();
- handler.characters(chars, 0, chars.length);
- }
- handler.endElement(CATEGORY, elementName, elementName);
- }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
index 08989c03c..1a8cfdf47 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
@@ -19,13 +19,15 @@
package org.apache.fop.render.afp.extensions;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
/**
* ContentHandler (parser) for restoring AFPExtension objects from XML.
@@ -39,7 +41,7 @@ public class AFPExtensionHandler extends DefaultHandler
private StringBuffer content = new StringBuffer();
private Attributes lastAttributes;
- private AFPPageSetup returnedObject;
+ private AFPExtensionAttachment returnedObject;
private ObjectBuiltListener listener;
/** {@inheritDoc} */
@@ -53,8 +55,7 @@ public class AFPExtensionHandler extends DefaultHandler
|| localName.equals(AFPElementMapping.TAG_LOGICAL_ELEMENT)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT)
- || localName.equals(AFPElementMapping.PAGE)
- /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) {
+ || localName.equals(AFPElementMapping.INVOKE_MEDIUM_MAP)) {
//handled in endElement
} else {
handled = false;
@@ -74,17 +75,24 @@ public class AFPExtensionHandler extends DefaultHandler
/** {@inheritDoc} */
public void endElement(String uri, String localName, String qName) throws SAXException {
if (AFPPageSetup.CATEGORY.equals(uri)) {
- this.returnedObject = new AFPPageSetup(localName);
+ 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) {
- returnedObject.setValue(value);
+ if (value != null && pageSetupExtn != null) {
+ pageSetupExtn.setValue(value);
}
- if (content.length() > 0) {
- returnedObject.setContent(content.toString());
+ if (content.length() > 0 && pageSetupExtn != null) {
+ pageSetupExtn.setContent(content.toString());
content.setLength(0); //Reset text buffer (see characters())
}
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMap.java b/src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMap.java
new file mode 100644
index 000000000..83c5325aa
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMap.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This is the pass-through value object for the AFP extension.
+ */
+public class AFPInvokeMediumMap extends AFPExtensionAttachment {
+
+ private static final long serialVersionUID = -7493160084509249309L;
+
+ /**
+ * Default constructor.
+ */
+ public AFPInvokeMediumMap() {
+ super(AFPElementMapping.INVOKE_MEDIUM_MAP);
+ }
+
+ /** {@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);
+ }
+ handler.startElement(CATEGORY, elementName, elementName, atts);
+ handler.endElement(CATEGORY, elementName, elementName);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPInvokeMediumMap(name=" + getName() + ")";
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMapElement.java
index 3104ced6f..99805edd4 100755..100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPInvokeMediumMapElement.java
@@ -22,37 +22,34 @@ package org.apache.fop.render.afp.extensions;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
- * This class extends the org.apache.fop.extensions.ExtensionObj class. The
- * object faciliates extraction of elements from formatted objects based on
- * the static list as defined in the AFPElementMapping implementation.
- * <p/>
+ * This class represents an AFP-specific extension element to embed Invoke Medium Map (IMM)
+ * fields at the beginning of a page group. The element is optional and expected as a direct child
+ * of an fo:page-sequence.
*/
-public class AFPElement extends AbstractAFPExtensionObject {
+public class AFPInvokeMediumMapElement extends AbstractAFPExtensionObject {
/**
- * Constructs an AFP object (called by Maker).
- *
+ * Constructs the AFP extension object (called by Maker).
* @param parent the parent formatting object
- * @param name the name of the afp element
*/
- public AFPElement(FONode parent, String name) {
- super(parent, name);
+ public AFPInvokeMediumMapElement(FONode parent) {
+ super(parent, AFPElementMapping.INVOKE_MEDIUM_MAP);
}
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
- throw new ValidationException(getName() + " must be a child of fo:simple-page-master.");
+ if (parent.getNameId() != Constants.FO_PAGE_SEQUENCE) {
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfPageSequence");
}
}
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
protected ExtensionAttachment instantiateExtensionAttachment() {
- return new AFPPageSetup(getLocalName());
+ return new AFPInvokeMediumMap();
}
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
index d4b8e8a59..b72a30c84 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
@@ -19,11 +19,28 @@
package org.apache.fop.render.afp.extensions;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
/**
* This is the pass-through value object for the AFP extension.
*/
public class AFPPageSetup extends AFPExtensionAttachment {
+ /** value attribute */
+ protected static final String ATT_VALUE = "value";
+
+ /**
+ * the extension content
+ */
+ protected String content;
+
+ /**
+ * the extension value attribute
+ */
+ protected String value;
+
/**
* Default constructor.
*
@@ -36,8 +53,55 @@ public class AFPPageSetup extends AFPExtensionAttachment {
private static final long serialVersionUID = -549941295384013190L;
/**
- * {@inheritDoc}
+ * Returns the value of the extension.
+ * @return the value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value
+ * @param source The value name to set.
*/
+ public void setValue(String source) {
+ this.value = source;
+ }
+
+ /**
+ * Returns the content of the extension.
+ * @return the data
+ */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Sets the data
+ * @param content The byte data to set.
+ */
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ /** {@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 (value != null && value.length() > 0) {
+ atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
+ }
+ handler.startElement(CATEGORY, elementName, elementName, atts);
+ if (content != null && content.length() > 0) {
+ char[] chars = content.toCharArray();
+ handler.characters(chars, 0, chars.length);
+ }
+ handler.endElement(CATEGORY, elementName, elementName);
+ }
+
+ /** {@inheritDoc} */
public String toString() {
return "AFPPageSetup(element-name=" + getElementName()
+ " name=" + getName() + " value=" + getValue() + ")";
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
index d167a8d4b..0c6dfadc4 100644..100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
@@ -19,37 +19,91 @@
package org.apache.fop.render.afp.extensions;
+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.ValidationException;
+import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
- * Extension element for afp:ps-page-setup-code.
+ * This class extends the org.apache.fop.extensions.ExtensionObj class. The
+ * object faciliates extraction of elements from formatted objects based on
+ * the static list as defined in the AFPElementMapping implementation.
+ * <p/>
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {
/**
- * Main constructor
- * @param parent parent FO node
+ * Constructs an AFP object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param name the name of the afp element
*/
- public AFPPageSetupElement(FONode parent) {
- super(parent, "page");
+ public AFPPageSetupElement(FONode parent, String name) {
+ super(parent, name);
+ }
+
+ private AFPPageSetup getPageSetupAttachment() {
+ return (AFPPageSetup)getExtensionAttachment();
}
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
- throw new ValidationException(getName() + " must be a child of fo:simple-page-master.");
+ if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(getLocalName())) {
+ if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER
+ && parent.getNameId() != Constants.FO_PAGE_SEQUENCE) {
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfPageSequenceOrSPM");
+ }
+ } else {
+ if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfSPM");
+ }
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
+ protected void characters(char[] data, int start, int length,
+ PropertyList pList, Locator locator) throws FOPException {
+ StringBuffer sb = new StringBuffer();
+ AFPPageSetup pageSetup = getPageSetupAttachment();
+ if (pageSetup.getContent() != null) {
+ sb.append(pageSetup.getContent());
+ }
+ sb.append(data, start, length);
+ pageSetup.setContent(sb.toString());
+ }
+
+ /** {@inheritDoc} */
+ public void processNode(String elementName, Locator locator,
+ Attributes attlist, PropertyList propertyList)
+ throws FOPException {
+ super.processNode(elementName, locator, attlist, propertyList);
+ AFPPageSetup pageSetup = getPageSetupAttachment();
+ if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) {
+ String attr = attlist.getValue("src");
+ if (attr != null && attr.length() > 0) {
+ pageSetup.setValue(attr);
+ } else {
+ throw new FOPException(elementName + " must have a src attribute.");
+ }
+ } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
+ String attr = attlist.getValue("value");
+ if (attr != null && attr.length() > 0) {
+ pageSetup.setValue(attr);
+ } else {
+ throw new FOPException(elementName + " must have a value attribute.");
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
protected ExtensionAttachment instantiateExtensionAttachment() {
- return new AFPPageSetup(this.name);
+ return new AFPPageSetup(getLocalName());
}
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
index c0e9c2c89..e35a13ec6 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
@@ -54,9 +54,7 @@ public abstract class AbstractAFPExtensionObject extends FONode {
this.name = name;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
@@ -64,32 +62,17 @@ public abstract class AbstractAFPExtensionObject extends FONode {
}
}
- /**
- * {@inheritDoc}
- */
- protected void characters(char[] data, int start, int length,
- PropertyList pList, Locator locator) throws FOPException {
- ((AFPExtensionAttachment)getExtensionAttachment()).setContent(
- new String(data, start, length));
- }
-
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String getNamespaceURI() {
return AFPElementMapping.NAMESPACE;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String getNormalNamespacePrefix() {
return AFPElementMapping.NAMESPACE_PREFIX;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void processNode(String elementName, Locator locator,
Attributes attlist, PropertyList propertyList)
throws FOPException {
@@ -100,26 +83,9 @@ public abstract class AbstractAFPExtensionObject extends FONode {
} else {
throw new FOPException(elementName + " must have a name attribute.");
}
- if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) {
- attr = attlist.getValue("src");
- if (attr != null && attr.length() > 0) {
- extensionAttachment.setValue(attr);
- } else {
- throw new FOPException(elementName + " must have a src attribute.");
- }
- } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
- attr = attlist.getValue("value");
- if (attr != null && attr.length() > 0) {
- extensionAttachment.setValue(attr);
- } else {
- throw new FOPException(elementName + " must have a value attribute.");
- }
- }
}
-
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
}
@@ -130,9 +96,7 @@ public abstract class AbstractAFPExtensionObject extends FONode {
*/
protected abstract ExtensionAttachment instantiateExtensionAttachment();
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public ExtensionAttachment getExtensionAttachment() {
if (extensionAttachment == null) {
this.extensionAttachment = (AFPExtensionAttachment)instantiateExtensionAttachment();
@@ -140,9 +104,7 @@ public abstract class AbstractAFPExtensionObject extends FONode {
return this.extensionAttachment;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String getLocalName() {
return name;
}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandlerMaker.java b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandlerMaker.java
index 4a6c9cbb7..b14ba3c18 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandlerMaker.java
@@ -30,8 +30,7 @@ import org.apache.fop.render.intermediate.IFDocumentHandler;
*/
public class TIFFDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
- //TODO Revert to normal MIME after stabilization!
- private static final String[] MIMES = new String[] {MimeConstants.MIME_TIFF + ";mode=painter"};
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_TIFF};
/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
diff --git a/src/java/org/apache/fop/render/pcl/PCLDocumentHandlerMaker.java b/src/java/org/apache/fop/render/pcl/PCLDocumentHandlerMaker.java
index db47c9712..797daa3a1 100644
--- a/src/java/org/apache/fop/render/pcl/PCLDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/pcl/PCLDocumentHandlerMaker.java
@@ -30,8 +30,7 @@ import org.apache.fop.render.intermediate.IFDocumentHandler;
*/
public class PCLDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
- //TODO Revert to normal MIME after stabilization!
- private static final String[] MIMES = new String[] {MimeConstants.MIME_PCL + ";mode=painter"};
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_PCL};
/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
index 3e27fce97..7df6c9fee 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
@@ -279,6 +279,7 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
pdfDoc.outputTrailer(this.outputStream);
}
this.pdfDoc = null;
+
pdfResources = null;
this.generator = null;
currentContext = null;
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
index 532b50f80..f4ba03d5b 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
@@ -30,8 +30,7 @@ import org.apache.fop.render.intermediate.IFDocumentHandler;
*/
public class PDFDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
- //TODO Revert to normal MIME after stabilization!
- private static final String[] MIMES = new String[] {MimeConstants.MIME_PDF + ";mode=painter"};
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_PDF};
/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java
index 01a60646b..89ab98071 100644
--- a/src/java/org/apache/fop/render/print/PageableRenderer.java
+++ b/src/java/org/apache/fop/render/print/PageableRenderer.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.PageViewport;
import org.apache.fop.render.java2d.Java2DRenderer;
@@ -76,6 +77,11 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
}
/** {@inheritDoc} */
+ public String getMimeType() {
+ return MimeConstants.MIME_FOP_PRINT;
+ }
+
+ /** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
diff --git a/src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java b/src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java
index eb085c0a4..c581f9e02 100644
--- a/src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/ps/PSDocumentHandlerMaker.java
@@ -30,9 +30,8 @@ import org.apache.fop.render.intermediate.IFDocumentHandler;
*/
public class PSDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
- //TODO Revert to normal MIME after stabilization!
private static final String[] MIMES = new String[]
- {MimeConstants.MIME_POSTSCRIPT + ";mode=painter"};
+ {MimeConstants.MIME_POSTSCRIPT};
/** {@inheritDoc} */
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 6e03d68dd..8e8ae3f1d 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -438,7 +438,9 @@ public class XMLRenderer extends AbstractXMLRenderer {
if (pageSequence.getCountry() != null) {
addAttribute("country", pageSequence.getCountry());
}
+ transferForeignObjects(pageSequence);
startElement("pageSequence", atts);
+ handleExtensionAttachments(pageSequence.getExtensionAttachments());
LineArea seqTitle = pageSequence.getTitle();
if (seqTitle != null) {
startElement("title");
diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
index 03ad4ee71..e101a9573 100644
--- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
+++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
@@ -25,12 +25,13 @@ import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
+import org.apache.fop.fonts.FontEventListener;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontInfoConfigurator;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.pdf.PDFDocument;
-import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.pdf.PDFRendererConfigurator;
/**
@@ -61,15 +62,19 @@ public class PDFDocumentGraphics2DConfigurator {
//TODO Make use of fontBaseURL, font substitution and referencing configuration
//Requires a change to the expected configuration layout
- List/*<EmbedFontInfo>*/ embedFontInfoList
- = PrintRendererConfigurator.buildFontListFromConfiguration(
- cfg, fontResolver, false, fontManager, null);
//TODO Wire in the FontEventListener
+ final FontEventListener listener = null;
+ final boolean strict = false;
+ FontInfoConfigurator fontInfoConfigurator
+ = new FontInfoConfigurator(cfg, fontManager, fontResolver, listener, strict);
+ List/*<EmbedFontInfo>*/ fontInfoList = new java.util.ArrayList/*<EmbedFontInfo>*/();
+ fontInfoConfigurator.configure(fontInfoList);
+
if (fontManager.useCache()) {
fontManager.getFontCache().save();
}
FontInfo fontInfo = new FontInfo();
- FontSetup.setup(fontInfo, embedFontInfoList, fontResolver);
+ FontSetup.setup(fontInfo, fontInfoList, fontResolver);
graphics.setFontInfo(fontInfo);
} catch (FOPException e) {
throw new ConfigurationException("Error while setting up fonts", e);
diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java
index 554d26798..ede368f58 100644
--- a/src/java/org/apache/fop/svg/PDFGraphics2D.java
+++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java
@@ -59,6 +59,15 @@ import org.apache.batik.ext.awt.RadialGradientPaint;
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.PatternPaint;
+
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
+import org.apache.xmlgraphics.java2d.GraphicContext;
+
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
@@ -83,13 +92,6 @@ import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter;
import org.apache.fop.render.pdf.ImageRawJPEGAdapter;
import org.apache.fop.render.pdf.ImageRenderedAdapter;
import org.apache.fop.util.ColorExt;
-import org.apache.xmlgraphics.image.loader.ImageInfo;
-import org.apache.xmlgraphics.image.loader.ImageSize;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
-import org.apache.xmlgraphics.java2d.GraphicContext;
/**
* PDF Graphics 2D.
@@ -741,13 +743,7 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
throw new PDFConformanceException(
"PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK.");
}
- float[] cComps = c.getColorComponents(new float[3]);
- double[] cmyk = new double[3];
- for (int i = 0; i < 3; i++) {
- // convert the float elements to doubles for pdf
- cmyk[i] = cComps[i];
- }
- PDFColor currentColour = new PDFColor(cmyk[0], cmyk[1], cmyk[2], cmyk[3]);
+ PDFColor currentColour = new PDFColor(c);
currentStream.write(currentColour.getColorSpaceOut(fill));
} else if (c.getColorSpace().getType()
== ColorSpace.TYPE_2CLR) {
diff --git a/src/java/org/apache/fop/tools/fontlist/FontListGenerator.java b/src/java/org/apache/fop/tools/fontlist/FontListGenerator.java
new file mode 100644
index 000000000..ce44eee19
--- /dev/null
+++ b/src/java/org/apache/fop/tools/fontlist/FontListGenerator.java
@@ -0,0 +1,115 @@
+/*
+ * 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.tools.fontlist;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.fonts.FontEventListener;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontMetrics;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
+
+/**
+ * Generates a list of available fonts.
+ */
+public class FontListGenerator {
+
+ /**
+ * List all fonts configured for a particular output format (identified by MIME type).
+ * The sorted map returned looks like this:
+ * <code>SortedMap&lt;String/font-family, List&lt;{@link FontSpec}&gt;&gt;</code>
+ * @param fopFactory the FOP factory (already configured)
+ * @param mime the MIME type identified the selected output format
+ * @param listener a font event listener to catch any font-related errors while listing fonts
+ * @return the map of font families
+ * @throws FOPException if an error occurs setting up the fonts
+ */
+ public SortedMap listFonts(FopFactory fopFactory, String mime, FontEventListener listener)
+ throws FOPException {
+ FontInfo fontInfo = setupFonts(fopFactory, mime, listener);
+ SortedMap fontFamilies = buildFamilyMap(fontInfo);
+ return fontFamilies;
+ }
+
+ private FontInfo setupFonts(FopFactory fopFactory, String mime, FontEventListener listener)
+ throws FOPException {
+ FOUserAgent userAgent = fopFactory.newFOUserAgent();
+
+ //The document handler is only instantiated to get access to its configurator!
+ IFDocumentHandler documentHandler
+ = fopFactory.getRendererFactory().createDocumentHandler(userAgent, mime);
+ IFDocumentHandlerConfigurator configurator = documentHandler.getConfigurator();
+
+ FontInfo fontInfo = new FontInfo();
+ configurator.setupFontInfo(documentHandler, fontInfo);
+ return fontInfo;
+ }
+
+ private SortedMap buildFamilyMap(FontInfo fontInfo) {
+ Map fonts = fontInfo.getFonts();
+ Set keyBag = new java.util.HashSet(fonts.keySet());
+
+ Map keys = new java.util.HashMap();
+ SortedMap fontFamilies = new java.util.TreeMap();
+ //SortedMap<String/font-family, List<FontSpec>>
+
+ Iterator iter = fontInfo.getFontTriplets().entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ FontTriplet triplet = (FontTriplet)entry.getKey();
+ String key = (String)entry.getValue();
+ FontSpec container;
+ if (keyBag.contains(key)) {
+ keyBag.remove(key);
+
+ FontMetrics metrics = (FontMetrics)fonts.get(key);
+
+ container = new FontSpec(key, metrics);
+ container.addFamilyNames(metrics.getFamilyNames());
+ keys.put(key, container);
+ String firstFamilyName = (String)container.getFamilyNames().first();
+ List containers = (List)fontFamilies.get(firstFamilyName);
+ if (containers == null) {
+ containers = new java.util.ArrayList();
+ fontFamilies.put(firstFamilyName, containers);
+ }
+ containers.add(container);
+ Collections.sort(containers);
+
+ } else {
+ container = (FontSpec)keys.get(key);
+ }
+ container.addTriplet(triplet);
+ }
+
+ return fontFamilies;
+ }
+
+}
diff --git a/src/java/org/apache/fop/tools/fontlist/FontListMain.java b/src/java/org/apache/fop/tools/fontlist/FontListMain.java
new file mode 100644
index 000000000..d31da92c2
--- /dev/null
+++ b/src/java/org/apache/fop/tools/fontlist/FontListMain.java
@@ -0,0 +1,305 @@
+/*
+ * 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.tools.fontlist;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+
+import org.apache.fop.Version;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.fonts.FontEventListener;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.util.GenerationHelperContentHandler;
+
+/**
+ * Command-line application to list available fonts and to optionally produce sample pages
+ * with those fonts.
+ */
+public final class FontListMain {
+
+ private static final int GENERATE_CONSOLE = 0;
+ private static final int GENERATE_XML = 1;
+ private static final int GENERATE_FO = 2;
+ private static final int GENERATE_RENDERED = 3;
+
+ private FopFactory fopFactory = FopFactory.newInstance();
+
+ private File configFile;
+ private File outputFile;
+ private String configMime = MimeConstants.MIME_PDF;
+ private String outputMime;
+ private int mode = GENERATE_CONSOLE;
+ private String singleFamilyFilter;
+
+ private FontListMain() throws SAXException, IOException {
+ }
+
+ private void prepare() throws SAXException, IOException {
+ if (this.configFile != null) {
+ fopFactory.setUserConfig(this.configFile);
+ }
+ }
+
+ private ContentHandler getFOPContentHandler(OutputStream out) throws FOPException {
+ Fop fop = fopFactory.newFop(this.outputMime, out);
+ return fop.getDefaultHandler();
+ }
+
+ private void generateXML(SortedMap fontFamilies, File outFile, String singleFamily)
+ throws TransformerConfigurationException, SAXException, IOException {
+ SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+ TransformerHandler handler;
+ if (this.mode == GENERATE_XML) {
+ handler = tFactory.newTransformerHandler();
+ } else {
+ URL url = getClass().getResource("fonts2fo.xsl");
+ if (url == null) {
+ throw new FileNotFoundException("Did not find resource: fonts2fo.xsl");
+ }
+ handler = tFactory.newTransformerHandler(new StreamSource(url.toExternalForm()));
+ }
+
+ if (singleFamily != null) {
+ Transformer transformer = handler.getTransformer();
+ transformer.setParameter("single-family", singleFamily);
+ }
+
+ OutputStream out = new java.io.FileOutputStream(outFile);
+ out = new java.io.BufferedOutputStream(out);
+ if (this.mode == GENERATE_RENDERED) {
+ handler.setResult(new SAXResult(getFOPContentHandler(out)));
+ } else {
+ handler.setResult(new StreamResult(out));
+ }
+ try {
+ GenerationHelperContentHandler helper = new GenerationHelperContentHandler(
+ handler, null);
+ FontListSerializer serializer = new FontListSerializer();
+ serializer.generateSAX(fontFamilies, singleFamily, helper);
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
+ }
+
+ private void generate() throws Exception {
+ prepare();
+
+ FontEventListener listener = new FontEventListener() {
+
+ public void fontLoadingErrorAtAutoDetection(Object source,
+ String fontURL, Exception e) {
+ System.err.println("Could not load " + fontURL
+ + " (" + e.getLocalizedMessage() + ")");
+ }
+
+ public void fontSubstituted(Object source,
+ FontTriplet requested, FontTriplet effective) {
+ //ignore
+ }
+
+ public void glyphNotAvailable(Object source, char ch, String fontName) {
+ //ignore
+ }
+
+ };
+
+ FontListGenerator listGenerator = new FontListGenerator();
+ SortedMap fontFamilies = listGenerator.listFonts(fopFactory, configMime, listener);
+
+ if (this.mode == GENERATE_CONSOLE) {
+ writeToConsole(fontFamilies);
+ } else {
+ writeOutput(fontFamilies);
+ }
+ }
+
+ private void writeToConsole(SortedMap fontFamilies)
+ throws TransformerConfigurationException, SAXException, IOException {
+ Iterator iter = fontFamilies.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String firstFamilyName = (String)entry.getKey();
+ System.out.println(firstFamilyName + ":");
+ List list = (List)entry.getValue();
+ Iterator fonts = list.iterator();
+ while (fonts.hasNext()) {
+ FontSpec f = (FontSpec)fonts.next();
+ System.out.println(" " + f.getKey() + " " + f.getFamilyNames());
+ Iterator triplets = f.getTriplets().iterator();
+ while (triplets.hasNext()) {
+ FontTriplet triplet = (FontTriplet)triplets.next();
+ System.out.println(" " + triplet.toString());
+ }
+ }
+ }
+ }
+
+ private void writeOutput(SortedMap fontFamilies)
+ throws TransformerConfigurationException, SAXException, IOException {
+ if (this.outputFile.isDirectory()) {
+ System.out.println("Creating one file for each family...");
+ Iterator iter = fontFamilies.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String familyName = (String)entry.getKey();
+ System.out.println("Creating output file for " + familyName + "...");
+ String filename;
+ switch(this.mode) {
+ case GENERATE_RENDERED:
+ filename = familyName + ".pdf";
+ break;
+ case GENERATE_FO:
+ filename = familyName + ".fo";
+ break;
+ case GENERATE_XML:
+ filename = familyName + ".xml";
+ break;
+ default:
+ throw new IllegalStateException("Unsupported mode");
+ }
+ File outFile = new File(this.outputFile, filename);
+ generateXML(fontFamilies, outFile, familyName);
+ }
+ } else {
+ System.out.println("Creating output file...");
+ generateXML(fontFamilies, this.outputFile, this.singleFamilyFilter);
+ }
+ System.out.println(this.outputFile + " written.");
+ }
+
+ private static void printVersion() {
+ System.out.println("Apache FOP " + Version.getVersion()
+ + " - http://xmlgraphics.apache.org/fop/\n");
+ }
+
+ private static void printHelp() {
+ printVersion();
+
+ String className = FontListMain.class.getName();
+ PrintStream out = System.out;
+ out.println("USAGE");
+ out.println(" java [vmargs] " + className
+ + " [-c <config-file>] [-f <mime>] [[output-dir|output-file] [font-family]]");
+ out.println();
+ out.println("PARAMETERS");
+ out.println(" config-file: an optional FOP configuration file");
+ out.println(" mime: The MIME type of the output format for which to");
+ out.println(" create the font list (defaults to application/pdf)");
+ out.println(" output-dir: Creates one sample PDF per font-family");
+ out.println(" output-file: writes the list as file (valid file extensions: xml, fo, pdf)");
+ out.println(" font-family: filters to a single font family");
+ out.println();
+ out.println("EXAMPLE");
+ out.println(" java [vmargs] " + className
+ + " -c userconfig.xml all-fonts.pdf");
+ out.println(" --> this generates a single PDF containing a sample");
+ out.println(" of all configured fonts.");
+ out.println(" java [vmargs] " + className
+ + " -c userconfig.xml");
+ out.println(" --> this prints all configured fonts to the console.");
+ out.println();
+ }
+
+ private void parseArguments(String[] args) {
+ if (args.length > 0) {
+ int idx = 0;
+ if ("--help".equals(args[idx]) || "-?".equals(args[idx]) || "-h".equals(args[idx])) {
+ printHelp();
+ System.exit(0);
+ }
+ if (idx < args.length - 1 && "-c".equals(args[idx])) {
+ String filename = args[idx + 1];
+ this.configFile = new File(filename);
+ idx += 2;
+ }
+ if (idx < args.length - 1 && "-f".equals(args[idx])) {
+ this.configMime = args[idx + 1];
+ idx += 2;
+ }
+ if (idx < args.length) {
+ String name = args[idx];
+ this.outputFile = new File(name);
+ if (this.outputFile.isDirectory()) {
+ this.mode = GENERATE_RENDERED;
+ this.outputMime = MimeConstants.MIME_PDF;
+ } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("pdf")) {
+ this.mode = GENERATE_RENDERED;
+ this.outputMime = MimeConstants.MIME_PDF;
+ } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("fo")) {
+ this.mode = GENERATE_FO;
+ } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("xml")) {
+ this.mode = GENERATE_XML;
+ } else {
+ throw new IllegalArgumentException(
+ "Operating mode for the output file cannot be determined"
+ + " or is unsupported: " + name);
+ }
+ idx++;
+ }
+ if (idx < args.length) {
+ this.singleFamilyFilter = args[idx];
+ }
+ } else {
+ System.out.println("use --help or -? for usage information.");
+ }
+ }
+
+ /**
+ * The command-line interface.
+ * @param args the command-line arguments
+ */
+ public static void main(String[] args) {
+ try {
+ FontListMain app = new FontListMain();
+ app.parseArguments(args);
+ app.generate();
+ } catch (Throwable t) {
+ printHelp();
+ t.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/tools/fontlist/FontListSerializer.java b/src/java/org/apache/fop/tools/fontlist/FontListSerializer.java
new file mode 100644
index 000000000..eab3caa56
--- /dev/null
+++ b/src/java/org/apache/fop/tools/fontlist/FontListSerializer.java
@@ -0,0 +1,142 @@
+/*
+ * 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.tools.fontlist;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.regex.Pattern;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.util.GenerationHelperContentHandler;
+
+/**
+ * Turns the font list into SAX events.
+ */
+public class FontListSerializer {
+
+ private static final String FONTS = "fonts";
+ private static final String FAMILY = "family";
+ private static final String FONT = "font";
+ private static final String TRIPLETS = "triplets";
+ private static final String TRIPLET = "triplet";
+
+ private static final String NAME = "name";
+ private static final String STRIPPED_NAME = "stripped-name";
+ private static final String TYPE = "type";
+ private static final String KEY = "key";
+ private static final String STYLE = "style";
+ private static final String WEIGHT = "weight";
+
+ private static final String CDATA = "CDATA";
+
+ /**
+ * Generates SAX events from the font damily map.
+ * @param fontFamilies the font families
+ * @param handler the target SAX handler
+ * @throws SAXException if an XML-related exception occurs
+ */
+ public void generateSAX(SortedMap fontFamilies,
+ GenerationHelperContentHandler handler) throws SAXException {
+ generateSAX(fontFamilies, null, handler);
+ }
+
+ /**
+ * Generates SAX events from the font damily map.
+ * @param fontFamilies the font families
+ * @param singleFamily if not null, the output will be filtered so only this single font family
+ * will be used
+ * @param handler the target SAX handler
+ * @throws SAXException if an XML-related exception occurs
+ */
+ public void generateSAX(SortedMap fontFamilies, String singleFamily,
+ GenerationHelperContentHandler handler) throws SAXException {
+ handler.startDocument();
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement(FONTS, atts);
+
+ Iterator iter = fontFamilies.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String familyName = (String)entry.getKey();
+ if (singleFamily != null && familyName != singleFamily) {
+ continue;
+ }
+ atts.clear();
+ atts.addAttribute(null, NAME, NAME, CDATA, familyName);
+ atts.addAttribute(null, STRIPPED_NAME, STRIPPED_NAME, CDATA,
+ stripQuotes(familyName));
+ handler.startElement(FAMILY, atts);
+
+ List containers = (List)entry.getValue();
+ generateXMLForFontContainers(handler, containers);
+ handler.endElement(FAMILY);
+ }
+
+ handler.endElement(FONTS);
+ handler.endDocument();
+ }
+
+ private final Pattern quotePattern = Pattern.compile("'");
+
+ private String stripQuotes(String name) {
+ return quotePattern.matcher(name).replaceAll("");
+ }
+
+ private void generateXMLForFontContainers(GenerationHelperContentHandler handler,
+ List containers) throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ Iterator fontIter = containers.iterator();
+ while (fontIter.hasNext()) {
+ FontSpec cont = (FontSpec)fontIter.next();
+ atts.clear();
+ atts.addAttribute(null, KEY, KEY, CDATA, cont.getKey());
+ atts.addAttribute(null, TYPE, TYPE, CDATA,
+ cont.getFontMetrics().getFontType().getName());
+ handler.startElement(FONT, atts);
+ generateXMLForTriplets(handler, cont.getTriplets());
+ handler.endElement(FONT);
+ }
+ }
+
+ private void generateXMLForTriplets(GenerationHelperContentHandler handler, Collection triplets)
+ throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ atts.clear();
+ handler.startElement(TRIPLETS, atts);
+ Iterator iter = triplets.iterator();
+ while (iter.hasNext()) {
+ FontTriplet triplet = (FontTriplet)iter.next();
+ atts.clear();
+ atts.addAttribute(null, NAME, NAME, CDATA, triplet.getName());
+ atts.addAttribute(null, STYLE, STYLE, CDATA, triplet.getStyle());
+ atts.addAttribute(null, WEIGHT, WEIGHT, CDATA,
+ Integer.toString(triplet.getWeight()));
+ handler.element(TRIPLET, atts);
+ }
+ handler.endElement(TRIPLETS);
+ }
+
+}
diff --git a/src/java/org/apache/fop/tools/fontlist/FontSpec.java b/src/java/org/apache/fop/tools/fontlist/FontSpec.java
new file mode 100644
index 000000000..ce5c7a6c7
--- /dev/null
+++ b/src/java/org/apache/fop/tools/fontlist/FontSpec.java
@@ -0,0 +1,103 @@
+/*
+ * 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.tools.fontlist;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+
+import org.apache.fop.fonts.FontMetrics;
+import org.apache.fop.fonts.FontTriplet;
+
+/**
+ * Represents a font with information on how it can be used from XSL-FO.
+ */
+public class FontSpec implements Comparable {
+
+ private String key;
+ private FontMetrics metrics;
+ private SortedSet familyNames = new java.util.TreeSet();
+ private Collection triplets = new java.util.TreeSet();
+
+ /**
+ * Creates a new font spec.
+ * @param key the internal font key
+ * @param metrics the font metrics
+ */
+ public FontSpec(String key, FontMetrics metrics) {
+ this.key = key;
+ this.metrics = metrics;
+ }
+
+ /**
+ * Adds font family names.
+ * @param names the names
+ */
+ public void addFamilyNames(Collection names) {
+ this.familyNames.addAll(names);
+ }
+
+ /**
+ * Adds a font triplet.
+ * @param triplet the font triplet
+ */
+ public void addTriplet(FontTriplet triplet) {
+ this.triplets.add(triplet);
+ }
+
+ /**
+ * Returns the font family names.
+ * @return the font family names
+ */
+ public SortedSet getFamilyNames() {
+ return Collections.unmodifiableSortedSet(this.familyNames);
+ }
+
+ /**
+ * Returns the font triplets.
+ * @return the font triplets
+ */
+ public Collection getTriplets() {
+ return Collections.unmodifiableCollection(this.triplets);
+ }
+
+ /**
+ * Returns the internal font key.
+ * @return the internal font key
+ */
+ public String getKey() {
+ return this.key;
+ }
+
+ /**
+ * Returns the font metrics.
+ * @return the font metrics
+ */
+ public FontMetrics getFontMetrics() {
+ return this.metrics;
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(Object o) {
+ FontSpec other = (FontSpec)o;
+ return metrics.getFullName().compareTo(other.metrics.getFullName());
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/tools/fontlist/fonts2fo.xsl b/src/java/org/apache/fop/tools/fontlist/fonts2fo.xsl
new file mode 100644
index 000000000..5c2b59e8e
--- /dev/null
+++ b/src/java/org/apache/fop/tools/fontlist/fonts2fo.xsl
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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$ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:svg="http://www.w3.org/2000/svg">
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:param name="single-family" select="''"/>
+
+ <xsl:template match="fonts">
+ <fo:root font-family="sans-serif" font-size="10pt">
+ <!-- defines the layout master -->
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="A4" page-height="29.7cm" page-width="21cm"
+ margin="1.5cm">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <!-- starts actual layout -->
+ <xsl:choose>
+ <xsl:when test="string-length($single-family) &gt; 0">
+ <xsl:apply-templates select="family[@name = $single-family]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="bookmarks"/>
+ <xsl:call-template name="toc"/>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </fo:root>
+ </xsl:template>
+
+ <xsl:template name="bookmarks">
+ <fo:bookmark-tree>
+ <fo:bookmark internal-destination="toc">
+ <fo:bookmark-title>Table of Contents</fo:bookmark-title>
+ </fo:bookmark>
+ <xsl:apply-templates mode="bookmark"/>
+ </fo:bookmark-tree>
+ </xsl:template>
+
+ <xsl:template name="toc">
+ <fo:page-sequence master-reference="A4" id="toc">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>
+ <fo:block font-size="14pt" font-weight="bold" space-after="1em">FOP Font List</fo:block>
+ <fo:block space-after="0.5em">The number of font families: <xsl:value-of select="count(family)"/></fo:block>
+ </fo:block>
+ <xsl:if test="count(family) > 0">
+ <fo:list-block provisional-distance-between-starts="1.6em"
+ provisional-label-separation="0.5em">
+ <xsl:apply-templates mode="toc"/>
+ </fo:list-block>
+ </xsl:if>
+ </fo:flow>
+ </fo:page-sequence>
+ </xsl:template>
+
+ <xsl:template match="family" mode="bookmark">
+ <fo:bookmark internal-destination="{generate-id()}">
+ <fo:bookmark-title>
+ <xsl:value-of select="@name"/>
+ </fo:bookmark-title>
+ </fo:bookmark>
+ </xsl:template>
+
+ <xsl:template match="family" mode="toc">
+ <fo:list-item>
+ <fo:list-item-label start-indent="2mm" end-indent="label-end()">
+ <fo:block hyphenation-character="&#x2212;" font-family="Symbol">&#x2022;</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:basic-link internal-destination="{generate-id()}">
+ <xsl:value-of select="@name"/>
+ </fo:basic-link>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </xsl:template>
+
+ <xsl:template match="family">
+ <fo:page-sequence master-reference="A4" id="{generate-id()}">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>
+ <fo:block font-size="14pt" font-weight="bold" space-after="0.5em" border-bottom="solid 0.5mm">
+ <xsl:value-of select="@name"/>
+ </fo:block>
+ <fo:block>
+ <fo:block font-weight="bold">Fonts:</fo:block>
+ <xsl:apply-templates/>
+ </fo:block>
+ </fo:block>
+ <xsl:call-template name="weight-sample">
+ <xsl:with-param name="font-family" select="@stripped-name"/>
+ </xsl:call-template>
+ </fo:flow>
+ </fo:page-sequence>
+ </xsl:template>
+
+ <xsl:template name="weight-sample">
+ <xsl:param name="font-family" select="'sans-serif'"/>
+ <fo:block border="solid 0.25mm" start-indent="0.25mm" end-indent="0.25mm"
+ space-before="0.5em"
+ keep-together.within-column="always">
+ <fo:block font-size="8pt"
+ background-color="black" color="white"
+ padding="0mm 1mm" start-indent="1.25mm" end-indent="1.25mm">
+ Weight Sample: font-family="<xsl:value-of select="$font-family"/>" font-weight="100..900"</fo:block>
+ <fo:block padding="1mm 1mm" start-indent="1.25mm" end-indent="1.25mm">
+ <xsl:attribute name="font-family">
+ <xsl:value-of select="$font-family"/>
+ </xsl:attribute>
+ <fo:block font-weight="100">100: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="200">200: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="300">300: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="400">400: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="500">500: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="600">600: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="700">700: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="800">800: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block font-weight="900">900: The quick brown fox jumps over the lazy dog</fo:block>
+ <fo:block>
+ <fo:instream-foreign-object>
+ <svg xmlns="http://www.w3.org/2000/svg" width="16cm" height="108pt">
+ <g font-family="sans-serif" font-weight="bold" font-size="80pt"
+ transform="translate(30, 100) rotate(-15)">
+ <text fill="lightgray">SVG</text>
+ </g>
+ <g font-size="10pt">
+ <xsl:attribute name="font-family">
+ '<xsl:value-of select="$font-family"/>'
+ </xsl:attribute>
+ <text x="0" y="10">
+ <tspan x="0" dy="0" font-weight="100">100: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="200">200: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="300">300: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="400">400: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="500">500: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="600">600: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="700">700: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="800">800: The quick brown fox jumps over the lazy dog</tspan>
+ <tspan x="0" dy="12" font-weight="900">900: The quick brown fox jumps over the lazy dog</tspan>
+ </text>
+ </g>
+ </svg>
+ </fo:instream-foreign-object>
+ </fo:block>
+ </fo:block>
+ </fo:block>
+ </xsl:template>
+
+ <xsl:template match="font">
+ <fo:block>Internal key: <xsl:value-of select="@key"/></fo:block>
+ <fo:block border="solid 0.25mm" start-indent="0.25mm" end-indent="0.25mm">
+ <fo:block font-size="8pt"
+ background-color="black" color="white"
+ padding="0mm 1mm" start-indent="1.25mm" end-indent="1.25mm">
+ Sample:</fo:block>
+ <fo:block font-family="{triplets/triplet[1]/@name}"
+ font-style="{triplets/triplet[1]/@style}"
+ font-weight="{triplets/triplet[1]/@weight}"
+ font-size="14pt" padding="1mm" start-indent="1.25mm" end-indent="1.25mm">
+ The quick brown fox jumps over the lazy dog.
+ </fo:block>
+ </fo:block>
+ <fo:block start-indent="5mm">
+ <fo:block>Accessible by:</fo:block>
+ <fo:block start-indent="10mm">
+ <xsl:apply-templates select="triplets/triplet"/>
+ </fo:block>
+ </fo:block>
+ </xsl:template>
+
+ <xsl:template match="triplet">
+ <fo:block color="gray">
+ font-family=<fo:inline color="black">"<xsl:value-of select="@name"/>"</fo:inline>
+ font-style=<fo:inline color="black"><xsl:value-of select="@style"/>"</fo:inline>
+ font-weight=<fo:inline color="black"><xsl:value-of select="@weight"/>"</fo:inline>
+ </fo:block>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/status.xml b/status.xml
index 015597818..b6a2d23c0 100644
--- a/status.xml
+++ b/status.xml
@@ -61,6 +61,46 @@
<action context="Renderers" dev="JM" type="add" fixes-bug="46705" due-to="Jost Klopfstein">
Added basic accessibility and Tagged PDF support.
</action>
+ <action context="Renderers" dev="JM" type="fix">
+ Fixed a bug that left the PrintRenderer unconfigured even if a configuration was
+ specified for "application/X-fop-print".
+ </action>
+ <action context="Renderers" dev="JM" type="fix" fixes-bug="46882" due-to="Yegor Kozlov">
+ Fixed the handling of CMYK colors in PDFGraphics2D.
+ </action>
+ <action context="Layout" dev="AD" type="fix" fixes-bug="46489">
+ Fixed a bug when combining a forced break with a "last" page-master. The restart
+ of the algorithm would start at the index of the penalty corresponding to the last
+ page-break. This has been changed to the index of the first element after the last
+ page-break.
+ </action>
+ <action context="Fonts" dev="JM" type="add">
+ Added a command-line tool to list all configured fonts
+ (org.apache.fop.tools.fontlist.FontListMain).
+ </action>
+ <action context="Code" dev="AD" type="add" fixes-bug="46828" due-to="Dario Laera">
+ Added the possibility to use CachedRenderPagesModel, to conserve memory in case
+ of large documents with a lot of cross-references (area tree will be serialized to
+ disk to avoid keeping it entirely in memory).
+ </action>
+ <action context="Fonts" dev="JM" type="add">
+ AFP Fonts: Added support for full URI resolution on configured AFP fonts.
+ </action>
+ <action context="Renderers" dev="JM" type="add">
+ AFP Output: Tag Logical Element (TLE) is now also allowed on fo:page-sequence
+ (page group level).
+ </action>
+ <action context="Layout" dev="JM" type="fix">
+ Fixed BPD trait and border painting for leaders with leader-pattern="space"
+ (and similar cases).
+ </action>
+ <action context="Renderers" dev="JM" type="add">
+ AFP Output: Added support for Invoke Medium Map (IMM).
+ </action>
+ <action context="Renderers" dev="JM" type="add">
+ Introduced a new, additional intermediate format optimized for performance. Please see
+ the intermediate format documentation for details.
+ </action>
<action context="Fonts" dev="JM" type="fix" fixes-bug="46686" due-to="Alok Singh">
Use temporary directory for the font cache if the user home directory is not
write-accessible.
@@ -74,11 +114,11 @@
code.
</action>
<action context="Code" dev="VH" type="fix" fixes-bug="46638">
- MinOptMaxUtil.toMinOptMax was converting LengthRangeProperty objects into illegal MinOptMax
+ MinOptMaxUtil.toMinOptMax was converting LengthRangeProperty objects into illegal MinOptMax
objects (in some cases opt could be inferior to min).
</action>
<action context="Layout" dev="VH" type="add" fixes-bug="46315" due-to="Georg Datterl">
- Added extension to disable column balancing before blocks spanning the whole page, in
+ Added extension to disable column balancing before blocks spanning the whole page, in
multiple-column documents.
</action>
<action context="Renderers" dev="JM" type="add">
diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java
index 290b29050..e6a718643 100644
--- a/test/java/org/apache/fop/StandardTestSuite.java
+++ b/test/java/org/apache/fop/StandardTestSuite.java
@@ -25,6 +25,7 @@ import junit.framework.TestSuite;
import org.apache.fop.fonts.TrueTypeAnsiTestCase;
import org.apache.fop.image.loader.batik.ImageLoaderTestCase;
import org.apache.fop.image.loader.batik.ImagePreloaderTestCase;
+import org.apache.fop.intermediate.IFMimickingTestCase;
import org.apache.fop.render.pdf.PDFAConformanceTestCase;
import org.apache.fop.render.pdf.PDFCMapTestCase;
import org.apache.fop.render.pdf.PDFEncodingTestCase;
@@ -54,6 +55,7 @@ public class StandardTestSuite {
suite.addTest(RichTextFormatTestSuite.suite());
suite.addTest(new TestSuite(ImageLoaderTestCase.class));
suite.addTest(new TestSuite(ImagePreloaderTestCase.class));
+ suite.addTest(new TestSuite(IFMimickingTestCase.class));
//$JUnit-END$
return suite;
}
diff --git a/test/java/org/apache/fop/config/FOURIResolverTestCase.java b/test/java/org/apache/fop/config/FOURIResolverTestCase.java
new file mode 100644
index 000000000..e6f8db712
--- /dev/null
+++ b/test/java/org/apache/fop/config/FOURIResolverTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * 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.config;
+
+import java.net.MalformedURLException;
+
+import junit.framework.TestCase;
+
+import org.apache.fop.apps.FOURIResolver;
+
+/**
+ * This tests some aspects of the {@link FOURIResolver} class.
+ */
+public class FOURIResolverTestCase extends TestCase {
+
+ /**
+ * Checks the {@link FOURIResolver#checkBaseURL(String)} method.
+ * @throws Exception if an error occurs
+ */
+ public void testCheckBaseURI() throws Exception {
+ FOURIResolver resolver = new FOURIResolver(true);
+ System.out.println(resolver.checkBaseURL("./test/config"));
+ System.out.println(resolver.checkBaseURL("file:test/config"));
+ System.out.println(resolver.checkBaseURL("fantasy:myconfig"));
+ try {
+ resolver.checkBaseURL("./doesnotexist");
+ fail("Expected an exception for a inexistent base directory");
+ } catch (MalformedURLException mfue) {
+ //expected
+ }
+ try {
+ resolver.checkBaseURL("file:doesnotexist");
+ fail("Expected an exception for a inexistent base URI");
+ } catch (MalformedURLException mfue) {
+ //expected
+ }
+ }
+
+}
diff --git a/test/java/org/apache/fop/config/FontBaseBadTestCase.java b/test/java/org/apache/fop/config/FontBaseBadTestCase.java
index b22d0f4f3..792acf59a 100644
--- a/test/java/org/apache/fop/config/FontBaseBadTestCase.java
+++ b/test/java/org/apache/fop/config/FontBaseBadTestCase.java
@@ -20,7 +20,7 @@
package org.apache.fop.config;
/*
- * this font base does not exist and a relative font path is used
+ * This font base does not exist and a relative font path is used.
*/
public class FontBaseBadTestCase extends BaseDestructiveUserConfigTestCase {
@@ -28,14 +28,7 @@ public class FontBaseBadTestCase extends BaseDestructiveUserConfigTestCase {
super(name);
}
- public void testUserConfig() throws Exception {
- // Override this method from the super-class and do nothing as this test doesn't pass ATM
- // TODO re-enable later
- }
-
- /**
- * @see org.apache.fop.config.BaseUserConfigTestCase#getUserConfigFilename()
- */
+ /** {@inheritDoc} */
public String getUserConfigFilename() {
return "test_fontbase_bad.xconf";
}
diff --git a/test/java/org/apache/fop/intermediate/IFMimickingTestCase.java b/test/java/org/apache/fop/intermediate/IFMimickingTestCase.java
new file mode 100644
index 000000000..610bc600b
--- /dev/null
+++ b/test/java/org/apache/fop/intermediate/IFMimickingTestCase.java
@@ -0,0 +1,149 @@
+/*
+ * 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.intermediate;
+
+import java.io.File;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+import junit.framework.TestCase;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventFormatter;
+import org.apache.fop.events.EventListener;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFSerializer;
+
+/**
+ * This test checks the correct mimicking of a different output format.
+ */
+public class IFMimickingTestCase extends TestCase {
+
+ private FopFactory fopFactory;
+
+ /** {@inheritDoc} */
+ protected void setUp() throws Exception {
+ super.setUp();
+ fopFactory = FopFactory.newInstance();
+ File configFile = new File("test/test-no-xml-metrics.xconf");
+ fopFactory.setUserConfig(configFile);
+ }
+
+ /**
+ * Tests IF document handler mimicking with PDF output.
+ * @throws Exception if an error occurs
+ */
+ public void testMimickingPDF() throws Exception {
+ doTestMimicking(MimeConstants.MIME_PDF);
+ }
+
+ /**
+ * Tests IF document handler mimicking with PostScript output.
+ * @throws Exception if an error occurs
+ */
+ public void testMimickingPS() throws Exception {
+ doTestMimicking(MimeConstants.MIME_POSTSCRIPT);
+ }
+
+ /**
+ * Tests IF document handler mimicking with TIFF output.
+ * @throws Exception if an error occurs
+ */
+ public void testMimickingTIFF() throws Exception {
+ doTestMimicking(MimeConstants.MIME_TIFF);
+ }
+
+ private void doTestMimicking(String mime) throws FOPException, IFException,
+ TransformerException {
+ //Set up XMLRenderer to render to a DOM
+ DOMResult domResult = new DOMResult();
+
+ FOUserAgent userAgent = fopFactory.newFOUserAgent();
+ userAgent.getEventBroadcaster().addEventListener(new EventListener() {
+
+ public void processEvent(Event event) {
+ if (event.getEventGroupID().equals("org.apache.fop.fonts.FontEventAdapter")) {
+ fail("There must be no font-related event! Got: "
+ + EventFormatter.format(event));
+ }
+ }
+
+ });
+
+ //Create an instance of the target renderer so the XMLRenderer can use its font setup
+ IFDocumentHandler targetHandler = userAgent.getRendererFactory().createDocumentHandler(
+ userAgent, mime);
+
+ //Setup painter
+ IFSerializer serializer = new IFSerializer();
+ serializer.setContext(new IFContext(userAgent));
+ serializer.mimicDocumentHandler(targetHandler);
+ serializer.setResult(domResult);
+
+ userAgent.setDocumentHandlerOverride(serializer);
+
+ Fop fop = fopFactory.newFop(userAgent);
+
+ //minimal-pdf-a.fo uses the Gladiator font so is an ideal FO file for this test:
+ StreamSource src = new StreamSource(new File("test/xml/pdf-a/minimal-pdf-a.fo"));
+
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ Transformer transformer = tFactory.newTransformer();
+ setErrorListener(transformer);
+
+ transformer.transform(src, new SAXResult(fop.getDefaultHandler()));
+ }
+
+ /**
+ * Sets an error listener which doesn't swallow errors like Xalan's default one.
+ * @param transformer the transformer to set the error listener on
+ */
+ protected void setErrorListener(Transformer transformer) {
+ transformer.setErrorListener(new ErrorListener() {
+
+ public void error(TransformerException exception) throws TransformerException {
+ throw exception;
+ }
+
+ public void fatalError(TransformerException exception) throws TransformerException {
+ throw exception;
+ }
+
+ public void warning(TransformerException exception) throws TransformerException {
+ //ignore
+ }
+
+ });
+ }
+
+}
diff --git a/test/java/org/apache/fop/intermediate/IFParserTestCase.java b/test/java/org/apache/fop/intermediate/IFParserTestCase.java
index 8a0268aa6..15fc74bc9 100644
--- a/test/java/org/apache/fop/intermediate/IFParserTestCase.java
+++ b/test/java/org/apache/fop/intermediate/IFParserTestCase.java
@@ -88,7 +88,7 @@ public class IFParserTestCase extends AbstractIntermediateTestCase {
/** {@inheritDoc} */
protected String getTargetMIME() {
- return MimeConstants.MIME_PDF + ";mode=painter";
+ return MimeConstants.MIME_PDF;
}
/** {@inheritDoc} */
diff --git a/test/java/org/apache/fop/intermediate/IFTester.java b/test/java/org/apache/fop/intermediate/IFTester.java
index a3291a373..7534309e7 100644
--- a/test/java/org/apache/fop/intermediate/IFTester.java
+++ b/test/java/org/apache/fop/intermediate/IFTester.java
@@ -48,12 +48,14 @@ import org.apache.fop.apps.FopFactory;
import org.apache.fop.area.AreaTreeModel;
import org.apache.fop.area.AreaTreeParser;
import org.apache.fop.area.RenderPagesModel;
+import org.apache.fop.events.model.EventSeverity;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.layoutengine.EvalCheck;
import org.apache.fop.layoutengine.TrueCheck;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFRenderer;
import org.apache.fop.render.intermediate.IFSerializer;
+import org.apache.fop.util.ConsoleEventListenerForTests;
import org.apache.fop.util.DelegatingContentHandler;
/**
@@ -106,9 +108,12 @@ public class IFTester {
}
}
- private Document createIF(Document areaTreeXML) throws TransformerException {
+ private Document createIF(File testFile, Document areaTreeXML) throws TransformerException {
try {
FOUserAgent ua = fopFactory.newFOUserAgent();
+ ua.setBaseURL(testFile.getParentFile().toURI().toURL().toExternalForm());
+ ua.getEventBroadcaster().addEventListener(
+ new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN));
IFRenderer ifRenderer = new IFRenderer();
ifRenderer.setUserAgent(ua);
@@ -160,7 +165,7 @@ public class IFTester {
*/
public void doIFChecks(File testFile, Element checksRoot, Document areaTreeXML)
throws TransformerException {
- Document ifDocument = createIF(areaTreeXML);
+ Document ifDocument = createIF(testFile, areaTreeXML);
if (this.backupDir != null) {
Transformer transformer = tfactory.newTransformer();
Source src = new DOMSource(ifDocument);
diff --git a/test/java/org/apache/fop/render/RendererFactoryTest.java b/test/java/org/apache/fop/render/RendererFactoryTest.java
new file mode 100644
index 000000000..4a40ac7c1
--- /dev/null
+++ b/test/java/org/apache/fop/render/RendererFactoryTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.output.NullOutputStream;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.area.AreaTreeHandler;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+import org.apache.fop.render.intermediate.IFRenderer;
+import org.apache.fop.render.pdf.PDFDocumentHandler;
+import org.apache.fop.render.pdf.PDFRenderer;
+import org.apache.fop.render.rtf.RTFHandler;
+
+/**
+ * Tests for {@link RendererFactory}.
+ */
+public class RendererFactoryTest extends TestCase {
+
+ public void testDocumentHandlerLevel() throws Exception {
+ FopFactory fopFactory = FopFactory.newInstance();
+ RendererFactory factory = fopFactory.getRendererFactory();
+ FOUserAgent ua;
+ IFDocumentHandler handler;
+ IFDocumentHandler overrideHandler;
+
+ ua = fopFactory.newFOUserAgent();
+ handler = factory.createDocumentHandler(ua, MimeConstants.MIME_PDF);
+ assertTrue(handler instanceof PDFDocumentHandler);
+
+ ua = fopFactory.newFOUserAgent();
+ overrideHandler = new PDFDocumentHandler();
+ overrideHandler.setContext(new IFContext(ua));
+ ua.setDocumentHandlerOverride(overrideHandler);
+ handler = factory.createDocumentHandler(ua, null);
+ assertTrue(handler == overrideHandler);
+
+ ua = fopFactory.newFOUserAgent();
+ try {
+ handler = factory.createDocumentHandler(ua, "invalid/format");
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uoe) {
+ //expected
+ }
+ }
+
+ public void testRendererLevel() throws Exception {
+ FopFactory fopFactory = FopFactory.newInstance();
+ RendererFactory factory = fopFactory.getRendererFactory();
+ FOUserAgent ua;
+ Renderer renderer;
+ Renderer overrideRenderer;
+
+ ua = fopFactory.newFOUserAgent();
+ renderer = factory.createRenderer(ua, MimeConstants.MIME_PDF);
+ assertTrue(renderer instanceof IFRenderer);
+
+ factory.setRendererPreferred(true); //Test legacy setting
+ ua = fopFactory.newFOUserAgent();
+ renderer = factory.createRenderer(ua, MimeConstants.MIME_PDF);
+ assertTrue(renderer instanceof PDFRenderer);
+
+ ua = fopFactory.newFOUserAgent();
+ renderer = factory.createRenderer(ua, MimeConstants.MIME_FOP_IF);
+ assertTrue(renderer instanceof IFRenderer);
+
+ factory.setRendererPreferred(false);
+ ua = fopFactory.newFOUserAgent();
+ overrideRenderer = new PDFRenderer();
+ overrideRenderer.setUserAgent(ua);
+ ua.setRendererOverride(overrideRenderer);
+ renderer = factory.createRenderer(ua, null);
+ assertTrue(renderer == overrideRenderer);
+
+ ua = fopFactory.newFOUserAgent();
+ IFDocumentHandler overrideHandler;
+ overrideHandler = new PDFDocumentHandler();
+ overrideHandler.setContext(new IFContext(ua));
+ ua.setDocumentHandlerOverride(overrideHandler);
+ renderer = factory.createRenderer(ua, null);
+ assertTrue(renderer instanceof IFRenderer);
+
+ ua = fopFactory.newFOUserAgent();
+ try {
+ renderer = factory.createRenderer(ua, "invalid/format");
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uoe) {
+ //expected
+ }
+ }
+
+ public void testFOEventHandlerLevel() throws Exception {
+ FopFactory fopFactory = FopFactory.newInstance();
+ RendererFactory factory = fopFactory.getRendererFactory();
+ FOUserAgent ua;
+ FOEventHandler foEventHandler;
+ FOEventHandler overrideFOEventHandler;
+
+ ua = fopFactory.newFOUserAgent();
+ foEventHandler = factory.createFOEventHandler(
+ ua, MimeConstants.MIME_PDF, new NullOutputStream());
+ assertTrue(foEventHandler instanceof AreaTreeHandler);
+
+ ua = fopFactory.newFOUserAgent();
+ foEventHandler = factory.createFOEventHandler(
+ ua, MimeConstants.MIME_RTF, new NullOutputStream());
+ assertTrue(foEventHandler instanceof RTFHandler);
+
+ ua = fopFactory.newFOUserAgent();
+ try {
+ foEventHandler = factory.createFOEventHandler(
+ ua, "invalid/format", new NullOutputStream());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uoe) {
+ //expected
+ }
+
+ ua = fopFactory.newFOUserAgent();
+ try {
+ foEventHandler = factory.createFOEventHandler(
+ ua, MimeConstants.MIME_PDF, null);
+ fail("Expected FOPException because of missing OutputStream");
+ } catch (FOPException fe) {
+ //expected
+ }
+
+ ua = fopFactory.newFOUserAgent();
+ overrideFOEventHandler = new RTFHandler(ua, new NullOutputStream());
+ ua.setFOEventHandlerOverride(overrideFOEventHandler);
+ foEventHandler = factory.createFOEventHandler(
+ ua, null, null);
+ assertTrue(foEventHandler == overrideFOEventHandler);
+ }
+
+}
diff --git a/test/java/org/apache/fop/threading/FOPTestbed.java b/test/java/org/apache/fop/threading/FOPTestbed.java
index 7ced868c4..737317bec 100644
--- a/test/java/org/apache/fop/threading/FOPTestbed.java
+++ b/test/java/org/apache/fop/threading/FOPTestbed.java
@@ -20,9 +20,9 @@
package org.apache.fop.threading;
import java.io.File;
-import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -41,6 +41,8 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CountingOutputStream;
+import org.apache.commons.io.output.NullOutputStream;
/**
* Testbed for multi-threading tests. The class can run a configurable set of task a number of
@@ -55,13 +57,17 @@ public class FOPTestbed extends AbstractLogEnabled
private File outputDir;
private Configuration fopCfg;
private FOProcessor foprocessor;
+ private boolean writeToDevNull;
private int counter = 0;
+ private List results = Collections.synchronizedList(new java.util.LinkedList());
+
/** {@inheritDoc} */
public void configure(Configuration configuration) throws ConfigurationException {
this.threads = configuration.getChild("threads").getValueAsInteger(10);
this.outputDir = new File(configuration.getChild("output-dir").getValue());
+ this.writeToDevNull = configuration.getChild("devnull").getValueAsBoolean(false);
Configuration tasks = configuration.getChild("tasks");
this.repeat = tasks.getAttributeAsInteger("repeat", 1);
Configuration[] entries = tasks.getChildren("task");
@@ -85,11 +91,12 @@ public class FOPTestbed extends AbstractLogEnabled
this.counter = 0;
//Initialize threads
+ ThreadGroup workerGroup = new ThreadGroup("FOP workers");
List threadList = new java.util.LinkedList();
for (int ti = 0; ti < this.threads; ti++) {
TaskRunner runner = new TaskRunner();
ContainerUtil.enableLogging(runner, getLogger());
- Thread thread = new Thread(runner);
+ Thread thread = new Thread(workerGroup, runner, "Worker- " + ti);
threadList.add(thread);
}
@@ -112,7 +119,38 @@ public class FOPTestbed extends AbstractLogEnabled
//ignore
}
}
- getLogger().info("Stress test duration: " + (System.currentTimeMillis() - start) + "ms");
+ long duration = System.currentTimeMillis() - start;
+
+ report(duration);
+ }
+
+ private void report(long duration) {
+ int count = this.results.size();
+ int failures = 0;
+ long bytesWritten = 0;
+ System.out.println("Report on " + count + " tasks:");
+ Iterator iter = this.results.iterator();
+ while (iter.hasNext()) {
+ Result res = (Result)iter.next();
+ if (res.failure != null) {
+ System.out.println("FAIL: " + (res.end - res.start) + " " + res.task);
+ System.out.println(" -> " + res.failure.getMessage());
+ failures++;
+ } else {
+ System.out.println("good: " + (res.end - res.start) + " " + res.filesize
+ + " " + res.task);
+ bytesWritten += res.filesize;
+ }
+ }
+ System.out.println("Stress test duration: " + duration + "ms");
+ if (failures > 0) {
+ System.out.println(failures + " failures of " + count + " documents!!!");
+ } else {
+ float mb = 1024f * 1024f;
+ System.out.println("Bytes written: " + (bytesWritten / mb) + " MB, "
+ + (bytesWritten * 1000 / duration) + " bytes / sec");
+ System.out.println("NO failures with " + count + " documents.");
+ }
}
private class TaskRunner extends AbstractLogEnabled implements Runnable {
@@ -222,29 +260,61 @@ public class FOPTestbed extends AbstractLogEnabled
public void execute() throws Exception {
getLogger().info("Processing: " + def);
- DecimalFormat df = new DecimalFormat("00000");
- File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
- OutputStream out = new java.io.FileOutputStream(outfile);
+ long start = System.currentTimeMillis();
try {
- InputStream in;
- Templates templates;
-
- if (def.getFO() != null) {
- in = new java.io.FileInputStream(new File(def.getFO()));
- templates = null;
+ DecimalFormat df = new DecimalFormat("00000");
+ File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
+ OutputStream out;
+ if (writeToDevNull) {
+ out = new NullOutputStream();
} else {
- in = new java.io.FileInputStream(new File(def.getXML()));
- templates = def.getTemplates();
+ out = new java.io.FileOutputStream(outfile);
+ out = new java.io.BufferedOutputStream(out);
}
+ CountingOutputStream cout = new CountingOutputStream(out);
try {
- fop.process(in, templates, out);
+ Source src;
+ Templates templates;
+
+ if (def.getFO() != null) {
+ src = new StreamSource(new File(def.getFO()));
+ templates = null;
+ } else {
+ src = new StreamSource(new File(def.getXML()));
+ templates = def.getTemplates();
+ }
+ fop.process(src, templates, cout);
} finally {
- IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(cout);
}
- } finally {
- IOUtils.closeQuietly(out);
+ results.add(new Result(def, start, System.currentTimeMillis(),
+ cout.getByteCount()));
+ } catch (Exception e) {
+ results.add(new Result(def, start, System.currentTimeMillis(), e));
+ throw e;
}
}
}
+ private static class Result {
+
+ private TaskDef task;
+ private long start;
+ private long end;
+ private long filesize;
+ private Throwable failure;
+
+ public Result(TaskDef task, long start, long end, long filesize) {
+ this(task, start, end, null);
+ this.filesize = filesize;
+ }
+
+ public Result(TaskDef task, long start, long end, Throwable failure) {
+ this.task = task;
+ this.start = start;
+ this.end = end;
+ this.failure = failure;
+ }
+ }
+
} \ No newline at end of file
diff --git a/test/java/org/apache/fop/threading/FOProcessor.java b/test/java/org/apache/fop/threading/FOProcessor.java
index 05c8f6fe1..dd663da05 100644
--- a/test/java/org/apache/fop/threading/FOProcessor.java
+++ b/test/java/org/apache/fop/threading/FOProcessor.java
@@ -19,9 +19,9 @@
package org.apache.fop.threading;
-import java.io.InputStream;
import java.io.OutputStream;
+import javax.xml.transform.Source;
import javax.xml.transform.Templates;
/**
@@ -31,12 +31,12 @@ public interface FOProcessor {
/**
* Process a file.
- * @param in the InputStream for the FO or XML file
+ * @param src the Source for the FO or XML file
* @param templates a JAXP Templates object for an XSLT transformation or null
* @param out the OutputStream for the target file
* @throws Exception if an error occurs
*/
- void process(InputStream in, Templates templates, OutputStream out)
+ void process(Source src, Templates templates, OutputStream out)
throws Exception;
/**
diff --git a/test/java/org/apache/fop/threading/FOProcessorImpl.java b/test/java/org/apache/fop/threading/FOProcessorImpl.java
index 4ba7da658..2b580bbd0 100644
--- a/test/java/org/apache/fop/threading/FOProcessorImpl.java
+++ b/test/java/org/apache/fop/threading/FOProcessorImpl.java
@@ -19,8 +19,9 @@
package org.apache.fop.threading;
-import java.io.InputStream;
import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
@@ -29,19 +30,23 @@ import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.stream.StreamSource;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.commons.io.FilenameUtils;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventFormatter;
+import org.apache.fop.events.EventListener;
+import org.apache.fop.events.model.EventSeverity;
/**
* Default implementation of the FOProcessor interface using FOP.
@@ -71,9 +76,17 @@ public class FOProcessorImpl extends AbstractLogEnabled
}
/** {@inheritDoc} */
- public void process(InputStream in, Templates templates, OutputStream out)
+ public void process(Source src, Templates templates, OutputStream out)
throws org.apache.fop.apps.FOPException, java.io.IOException {
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+ foUserAgent.setBaseURL(src.getSystemId());
+ try {
+ URL url = new URL(src.getSystemId());
+ String filename = FilenameUtils.getName(url.getPath());
+ foUserAgent.getEventBroadcaster().addEventListener(new AvalonAdapter(filename));
+ } catch (MalformedURLException mfue) {
+ throw new RuntimeException(mfue);
+ }
Fop fop = fopFactory.newFop(this.mime, foUserAgent, out);
try {
@@ -83,7 +96,6 @@ public class FOProcessorImpl extends AbstractLogEnabled
} else {
transformer = templates.newTransformer();
}
- Source src = new StreamSource(in);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} catch (TransformerException e) {
@@ -96,4 +108,29 @@ public class FOProcessorImpl extends AbstractLogEnabled
return this.fileExtension;
}
+ private class AvalonAdapter implements EventListener {
+
+ private String filename;
+
+ public AvalonAdapter(String filename) {
+ this.filename = filename;
+ }
+
+ public void processEvent(Event event) {
+ String msg = EventFormatter.format(event);
+ EventSeverity severity = event.getSeverity();
+ if (severity == EventSeverity.INFO) {
+ //getLogger().info(filename + ": " + msg);
+ } else if (severity == EventSeverity.WARN) {
+ //getLogger().warn(filename + ": " + msg);
+ } else if (severity == EventSeverity.ERROR) {
+ getLogger().error(filename + ": " + msg);
+ } else if (severity == EventSeverity.FATAL) {
+ getLogger().fatalError(filename + ": " + msg);
+ } else {
+ assert false;
+ }
+ }
+
+ }
} \ No newline at end of file
diff --git a/test/layoutengine/standard-testcases/afp-extension_1.xml b/test/layoutengine/standard-testcases/afp-extension_1.xml
index a6779177a..70bbef450 100644
--- a/test/layoutengine/standard-testcases/afp-extension_1.xml
+++ b/test/layoutengine/standard-testcases/afp-extension_1.xml
@@ -25,7 +25,8 @@
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
+ xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<afp:include-page-overlay name="O1SAMP1 "/>
@@ -35,7 +36,9 @@
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="normal">
+ <fo:page-sequence master-reference="normal" fox:test-ignore="this">
+ <afp:invoke-medium-map name="MYMAP"/>
+ <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>
<fo:block break-before="page">Text on page <fo:page-number/>.</fo:block>
@@ -43,7 +46,7 @@
</fo:page-sequence>
</fo:root>
</fo>
- <checks>
+ <checks xmlns:afp="apache:fop:extensions:afp">
<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"/>
@@ -52,5 +55,29 @@
<eval expected="My NOP" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[4]/@name"/>
<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="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. -->
+ <eval expected="this" xpath="/areaTree/pageSequence/@fox:test-ignore" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"/>
</checks>
+ <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"
+ xmlns:afp="apache:fop:extensions:afp">
+ <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"/>
+ <eval expected="The TLE Value" xpath="//if:page[@name = '1']/if:page-header/afp:tag-logical-element[@name = 'The TLE Name']/@value"/>
+ <eval expected="My NOP" xpath="//if:page[@name = '1']/if:page-header/afp:no-operation[1]/@name"/>
+ <eval expected="insert up to 32k of character data here!" xpath="//if:page[@name = '1']/if:page-header/afp:no-operation[1]"/>
+
+ <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="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. -->
+ <eval expected="this" xpath="//if:page-sequence/@fox:test-ignore" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"/>
+ </if-checks>
</testcase>
diff --git a/test/layoutengine/standard-testcases/leader_border_padding.xml b/test/layoutengine/standard-testcases/leader_border_padding.xml
index e2bd0c231..18f300244 100644
--- a/test/layoutengine/standard-testcases/leader_border_padding.xml
+++ b/test/layoutengine/standard-testcases/leader_border_padding.xml
@@ -130,7 +130,9 @@
<eval expected="360000" xpath="//flow/block[4]/lineArea/@ipd"/>
<eval expected="34000" xpath="//flow/block[4]/lineArea/space/@ipd"/>
<eval expected="36000" xpath="//flow/block[4]/lineArea/space/@ipda"/>
- <eval expected="8615" xpath="//flow/block[4]/lineArea/space/@offset"/>
+ <eval expected="1000" xpath="//flow/block[4]/lineArea/space/@bpd"/>
+ <eval expected="3000" xpath="//flow/block[4]/lineArea/space/@bpda"/>
+ <eval expected="7616" xpath="//flow/block[4]/lineArea/space/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[4]/lineArea/space/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[4]/lineArea/space/@border-before"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[4]/lineArea/space/@border-end"/>
@@ -192,7 +194,9 @@
<eval expected="360000" xpath="//flow/block[9]/lineArea/@ipd"/>
<eval expected="16000" xpath="//flow/block[9]/lineArea/space/@ipd"/>
<eval expected="36000" xpath="//flow/block[9]/lineArea/space/@ipda"/>
- <eval expected="8615" xpath="//flow/block[9]/lineArea/space/@offset"/>
+ <eval expected="1000" xpath="//flow/block[9]/lineArea/space/@bpd"/>
+ <eval expected="21000" xpath="//flow/block[9]/lineArea/space/@bpda"/>
+ <eval expected="7616" xpath="//flow/block[9]/lineArea/space/@offset"/>
<eval expected="(solid,#ff0000,5000)" xpath="//flow/block[9]/lineArea/space/@border-after"/>
<eval expected="(solid,#ff0000,5000)" xpath="//flow/block[9]/lineArea/space/@border-before"/>
<eval expected="(solid,#ff0000,5000)" xpath="//flow/block[9]/lineArea/space/@border-end"/>
@@ -262,7 +266,9 @@
<eval expected="360000" xpath="//flow/block[14]/lineArea/@ipd"/>
<eval expected="24000" xpath="//flow/block[14]/lineArea/space/@ipd"/>
<eval expected="36000" xpath="//flow/block[14]/lineArea/space/@ipda"/>
- <eval expected="8615" xpath="//flow/block[14]/lineArea/space/@offset"/>
+ <eval expected="1000" xpath="//flow/block[14]/lineArea/space/@bpd"/>
+ <eval expected="9000" xpath="//flow/block[14]/lineArea/space/@bpda"/>
+ <eval expected="7616" xpath="//flow/block[14]/lineArea/space/@offset"/>
<eval expected="(solid,#ff0000,3000)" xpath="//flow/block[14]/lineArea/space/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[14]/lineArea/space/@border-before"/>
<eval expected="(solid,#ff0000,2000)" xpath="//flow/block[14]/lineArea/space/@border-end"/>
diff --git a/test/layoutengine/standard-testcases/page-position-last_break-before_bugzilla46489.xml b/test/layoutengine/standard-testcases/page-position-last_break-before_bugzilla46489.xml
new file mode 100644
index 000000000..d855ffd76
--- /dev/null
+++ b/test/layoutengine/standard-testcases/page-position-last_break-before_bugzilla46489.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>
+ This test checks page-masters (reference orientation).
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="FrontPage"
+ page-width="210mm" page-height="297mm" margin="12.7mm">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ <fo:simple-page-master master-name="Following"
+ page-width="210mm" page-height="297mm" margin="12.7mm">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ <fo:page-sequence-master master-name="pages">
+ <fo:repeatable-page-master-alternatives>
+ <fo:conditional-page-master-reference page-position="first"
+ master-reference="FrontPage"/>
+ <fo:conditional-page-master-reference page-position="rest"
+ master-reference="Following"/>
+ <fo:conditional-page-master-reference page-position="last"
+ master-reference="Following"/>
+ </fo:repeatable-page-master-alternatives>
+ </fo:page-sequence-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="pages">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>
+ <fo:table table-layout="fixed" width="100%">
+ <fo:table-column column-width="proportional-column-width(30)"/>
+ <fo:table-column column-width="proportional-column-width(70)"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell padding="4pt">
+ <fo:block color="#6D6E71">Some text</fo:block>
+ </fo:table-cell>
+ <fo:table-cell padding="4pt">
+ <fo:block>More text before break. More text before break. More text before
+ break.</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:table table-layout="fixed" width="100%">
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell padding="4pt">
+ <fo:block id="the-block" color="#6D6E71" page-break-before="always">TEXT AFTER
+ BREAK</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:table table-layout="fixed" width="100%">
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell padding="4pt">
+ <fo:block>blah blah blah</fo:block>
+ <fo:block>blah blah blah</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <true xpath="count(//page) = 2" />
+ </checks>
+</testcase>
diff --git a/test/test-no-xml-metrics.xconf b/test/test-no-xml-metrics.xconf
new file mode 100644
index 000000000..beb24c0ef
--- /dev/null
+++ b/test/test-no-xml-metrics.xconf
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+ <!-- Switch off font caching for the purposes of the unit test -->
+ <use-cache>false</use-cache>
+
+ <!-- Base URL for resolving relative URLs -->
+ <base>./</base>
+
+ <!-- Font Base URL for resolving relative font URLs -->
+ <font-base>./test/resources/fonts</font-base>
+
+ <renderers>
+ <renderer mime="application/pdf">
+ <filterList type="content">
+ <value>null</value>
+ </filterList>
+ <fonts>
+ <font embed-url="glb12.ttf" kerning="yes">
+ <font-triplet name="Gladiator Bold" style="normal" weight="normal"/>
+ <font-triplet name="Gladiator" style="normal" weight="bold"/>
+ <font-triplet name="Gladiator" style="normal" weight="normal"/>
+ </font>
+ </fonts>
+ </renderer>
+ <renderer mime="application/postscript">
+ <fonts>
+ <font embed-url="glb12.ttf" kerning="yes">
+ <font-triplet name="Gladiator Bold" style="normal" weight="normal"/>
+ <font-triplet name="Gladiator" style="normal" weight="bold"/>
+ <font-triplet name="Gladiator" style="normal" weight="normal"/>
+ </font>
+ </fonts>
+ </renderer>
+ <renderer mime="image/tiff">
+ <fonts>
+ <font embed-url="glb12.ttf" kerning="yes">
+ <font-triplet name="Gladiator Bold" style="normal" weight="normal"/>
+ <font-triplet name="Gladiator" style="normal" weight="bold"/>
+ <font-triplet name="Gladiator" style="normal" weight="normal"/>
+ </font>
+ </fonts>
+ </renderer>
+ </renderers>
+</fop>