diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2012-05-28 16:16:23 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2012-05-28 16:16:23 +0000 |
commit | b0ea791fe191cd6f7593aa3ba8ca83ceacc2c1c0 (patch) | |
tree | 2786a2fbe4e86197f6ebfa06261cbf8672b967a8 | |
parent | 340025483a07776d56b655bbee3b402ba589a5b4 (diff) | |
parent | d48e0e1f467c58a22c4d1b19591d4fa9d22aa8c6 (diff) | |
download | xmlgraphics-fop-b0ea791fe191cd6f7593aa3ba8ca83ceacc2c1c0.tar.gz xmlgraphics-fop-b0ea791fe191cd6f7593aa3ba8ca83ceacc2c1c0.zip |
Merged changes from trunk up to revision 1343133
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_TrueTypeInPostScript@1343310 13f79535-47bb-0310-9956-ffa450edef68
160 files changed, 2602 insertions, 1319 deletions
@@ -54,9 +54,9 @@ list of possible build targets. <project default="all" basedir="." name="fop"> <!-- See build.properties and build-local.properties for overriding build settings. --> <!-- build-local.properties is not stored in SVN and overrides values from build.properties --> + <property environment="env"/> <property file="${basedir}/build-local.properties"/> <property file="${basedir}/build.properties"/> - <property environment="env"/> <fileset dir="${basedir}" id="dist.bin"> <include name="conf/**"/> <include name="examples/**"/> @@ -790,7 +790,8 @@ list of possible build targets. <attribute name="classpath" default="standard-junit-classpath"/> <sequential> <echo message="Running @{title} tests..."/> - <junit dir="${basedir}" errorproperty="fop.junit.error" failureproperty="fop.junit.failure" printsummary="${junit.printsummary}"> + <junit dir="${basedir}" haltonfailure="yes" fork="${junit.fork}" forkmode="once" + errorproperty="fop.junit.error" failureproperty="fop.junit.failure" printsummary="${junit.printsummary}"> <sysproperty key="basedir" value="${basedir}/@{basedir}"/> <sysproperty key="jawa.awt.headless" value="true"/> <formatter type="brief" usefile="false" if="junit.formatter.brief.use"/> @@ -809,7 +810,7 @@ list of possible build targets. <target name="junit-all" depends="junit-compile, junit-transcoder, junit-layout-hyphenation" description="Runs FOP's JUnit basic tests" if="junit.present"> <junit dir="${basedir}" haltonfailure="yes" fork="${junit.fork}" forkmode="once" - errorproperty="fop.junit.error" failureproperty="fop.junit.failure"> + errorproperty="fop.junit.error" failureproperty="fop.junit.failure" printsummary="${junit.printsummary}"> <sysproperty key="jawa.awt.headless" value="true"/> <formatter type="brief" usefile="false" if="junit.formatter.brief.use"/> <formatter type="plain" usefile="true"/> @@ -1031,9 +1032,9 @@ NOTE: <!-- =================================================================== --> <!-- Checkstyle --> <!-- =================================================================== --> - <property name="checkstyle.location" value="${lib-tools}/checkstyle-all-5.1.jar" /> + <property name="checkstyle.location" value="${lib-tools}/checkstyle-5.5-all.jar" /> <property name="checkstyle.noframes.xslt" value="${basedir}/checkstyle-noframes.xsl" /> - <property name="checkstyle.config" value="${basedir}/checkstyle-5.1.xml" /> + <property name="checkstyle.config" value="${basedir}/checkstyle-5.5.xml" /> <path id="checkstyle-classpath"> <path refid="libs-build-classpath"/> <pathelement location="${checkstyle.location}"/> diff --git a/checkstyle-4.0.xml b/checkstyle-4.0.xml deleted file mode 100644 index 764e703ec..000000000 --- a/checkstyle-4.0.xml +++ /dev/null @@ -1,190 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.1//EN" "http://www.puppycrawl.com/dtds/configuration_1_1.dtd"> -<module name="Checker"> - <module name="TreeWalker"> - <module name="RegexpHeader"> - <property name="headerFile" value="${samedir}/checkstyle.header"/> - <property name="severity" value="warning"/> - </module> - <module name="ArrayTypeStyleCheck"> - <property name="javaStyle" value="true"/> - <property name="severity" value="warning"/> - </module> - <module name="ModifierOrderCheck"> - <property name="severity" value="warning"/> - </module> - <module name="RedundantModifierCheck"> - <property name="severity" value="warning"/> - <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/> - </module> - <module name="UpperEllCheck"> - <property name="severity" value="warning"/> - </module> - <module name="AvoidNestedBlocksCheck"> - <property name="severity" value="warning"/> - </module> - <module name="EmptyBlockCheck"> - <property name="option" value="text"/> - <property name="severity" value="warning"/> - <property name="tokens" value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/> - </module> - <module name="LeftCurlyCheck"> - <property name="maxLineLength" value="100"/> - <property name="option" value="eol"/> - <property name="severity" value="warning"/> - <property name="tokens" value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/> - </module> - <module name="NeedBracesCheck"> - <property name="severity" value="warning"/> - <property name="tokens" value="LITERAL_DO, LITERAL_ELSE, LITERAL_IF, LITERAL_FOR, LITERAL_WHILE"/> - </module> - <module name="RightCurlyCheck"> - <property name="option" value="same"/> - <property name="severity" value="warning"/> - <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/> - </module> - <module name="DoubleCheckedLockingCheck"> - <property name="severity" value="warning"/> - </module> - <module name="EmptyStatementCheck"> - <property name="severity" value="warning"/> - </module> - <module name="EqualsHashCodeCheck"> - <property name="severity" value="warning"/> - </module> - <module name="InnerAssignmentCheck"> - <property name="severity" value="warning"/> - <property name="tokens" value="ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BSR_ASSIGN, BXOR_ASSIGN, DIV_ASSIGN, MINUS_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, SL_ASSIGN, SR_ASSIGN, STAR_ASSIGN"/> - </module> - <module name="MissingSwitchDefaultCheck"> - <property name="severity" value="warning"/> - </module> - <module name="SimplifyBooleanExpressionCheck"> - <property name="severity" value="warning"/> - </module> - <module name="SimplifyBooleanReturnCheck"> - <property name="severity" value="warning"/> - </module> - <module name="FinalClassCheck"> - <property name="severity" value="warning"/> - </module> - <module name="HideUtilityClassConstructorCheck"> - <property name="severity" value="warning"/> - </module> - <module name="VisibilityModifierCheck"> - <property name="packageAllowed" value="false"/> - <property name="protectedAllowed" value="true"/> - <property name="publicMemberPattern" value="^serialVersionUID"/> - <property name="severity" value="warning"/> - </module> - <module name="AvoidStarImportCheck"> - <property name="severity" value="error"/> - </module> - <module name="JavadocMethodCheck"> - <property name="allowMissingParamTags" value="false"/> - <property name="allowMissingReturnTag" value="false"/> - <property name="allowMissingThrowsTags" value="false"/> - <property name="allowThrowsTagsForSubclasses" value="false"/> - <property name="allowUndeclaredRTE" value="false"/> - <property name="scope" value="protected"/> - <property name="severity" value="warning"/> - <property name="tokens" value="METHOD_DEF, CTOR_DEF"/> - </module> - <module name="JavadocTypeCheck"> - <property name="scope" value="protected"/> - <property name="severity" value="warning"/> - <property name="tokens" value="CLASS_DEF, INTERFACE_DEF"/> - </module> - <module name="JavadocVariableCheck"> - <property name="scope" value="protected"/> - <property name="severity" value="warning"/> - </module> - <module name="ConstantNameCheck"> - <property name="format" value="^[A-Z](_?[A-Z0-9]+)*$"/> - <property name="severity" value="warning"/> - </module> - <module name="LocalFinalVariableNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="LocalVariableNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="MemberNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="MethodNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="PackageNameCheck"> - <property name="format" value="^[a-z]+(\.[a-zA-Z_][a-zA-Z0-9_]*)*$"/> - <property name="severity" value="warning"/> - </module> - <module name="ParameterNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="StaticVariableNameCheck"> - <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - </module> - <module name="TypeNameCheck"> - <property name="format" value="^[A-Z][a-zA-Z0-9]*$"/> - <property name="severity" value="warning"/> - <property name="tokens" value="CLASS_DEF, INTERFACE_DEF"/> - </module> - <module name="FileLengthCheck"> - <property name="max" value="2000"/> - <property name="severity" value="warning"/> - </module> - <module name="LineLengthCheck"> - <property name="ignorePattern" value="^$"/> - <property name="max" value="100"/> - <property name="severity" value="warning"/> - <property name="tabWidth" value="4"/> - </module> - <module name="MethodLengthCheck"> - <property name="max" value="150"/> - <property name="severity" value="warning"/> - <property name="tokens" value="METHOD_DEF, CTOR_DEF"/> - </module> - <module name="ParameterNumberCheck"> - <property name="max" value="7"/> - <property name="severity" value="warning"/> - <property name="tokens" value="METHOD_DEF, CTOR_DEF"/> - </module> - <module name="EmptyForIteratorPadCheck"> - <property name="option" value="nospace"/> - <property name="severity" value="warning"/> - </module> - <module name="NoWhitespaceAfterCheck"> - <property name="allowLineBreaks" value="true"/> - <property name="severity" value="warning"/> - <property name="tokens" value="ARRAY_INIT, BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS"/> - </module> - <module name="NoWhitespaceBeforeCheck"> - <property name="allowLineBreaks" value="true"/> - <property name="severity" value="warning"/> - <property name="tokens" value="SEMI, POST_DEC, POST_INC"/> - </module> - <module name="OperatorWrapCheck"> - <property name="option" value="nl"/> - <property name="severity" value="warning"/> - <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, SL, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/> - </module> - <module name="TabCharacterCheck"> - <property name="severity" value="error"/> - </module> - <module name="WhitespaceAfterCheck"> - <property name="severity" value="warning"/> - <property name="tokens" value="COMMA, SEMI"/> - </module> - <module name="WhitespaceAroundCheck"> - <property name="severity" value="warning"/> - <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/> - </module> - </module> -</module> diff --git a/conf/fop.xconf b/conf/fop.xconf index 10b31cf86..01f12fd14 100644 --- a/conf/fop.xconf +++ b/conf/fop.xconf @@ -94,6 +94,7 @@ the location of this file. --> <images mode="b+w" bits-per-pixel="8"/> <renderer-resolution>240</renderer-resolution> + <line-width-correction>2.5</line-width-correction> <resource-group-file>resources.afp</resource-group-file> <fonts> diff --git a/examples/embedding/build.xml b/examples/embedding/build.xml index 8356445c1..0ad70d03c 100644 --- a/examples/embedding/build.xml +++ b/examples/embedding/build.xml @@ -146,8 +146,10 @@ <path refid="project.class.path"/> <pathelement location="${build.dest}"/> </classpath> + <jvmarg value="-Xmx1024m"/> </java> </target> + <target name="run" depends="example1,example2,example3,example4,example5,example5,example7,example8" description="Runs examples"/> <!-- =================================================================== --> <!-- Clean targets --> <!-- =================================================================== --> diff --git a/examples/embedding/java/embedding/ExampleEPS.java b/examples/embedding/java/embedding/ExampleEPS.java index ebf2b9a7d..d35413f60 100644 --- a/examples/embedding/java/embedding/ExampleEPS.java +++ b/examples/embedding/java/embedding/ExampleEPS.java @@ -1,18 +1,18 @@ /* * 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 - * + * 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. + * 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$ */ @@ -26,11 +26,13 @@ import java.io.OutputStream; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; + +import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D; + import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.ps.NativeTextHandler; import org.apache.fop.svg.PDFDocumentGraphics2DConfigurator; -import org.apache.xmlgraphics.java2d.GraphicContext; -import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D; public class ExampleEPS { diff --git a/examples/embedding/java/embedding/ExampleEPSSimple.java b/examples/embedding/java/embedding/ExampleEPSSimple.java index cbc353cd5..eec6d89f6 100644 --- a/examples/embedding/java/embedding/ExampleEPSSimple.java +++ b/examples/embedding/java/embedding/ExampleEPSSimple.java @@ -1,33 +1,33 @@ /* * 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 - * + * 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. + * 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 embedding; import java.awt.Font; import java.io.FileOutputStream; import java.io.OutputStream; -import org.apache.fop.render.ps.NativeTextHandler; import org.apache.xmlgraphics.java2d.GraphicContext; import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D; +import org.apache.fop.render.ps.NativeTextHandler; + public class ExampleEPSSimple { /** diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml index f46b0f1ba..46879d1f6 100644 --- a/findbugs-exclude.xml +++ b/findbugs-exclude.xml @@ -1,5 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> <FindBugsFilter> + <Match> + <Class name="org.apache.fop.fo.properties.FontFamilyProperty"/> + <Bug pattern="EQ_DOESNT_OVERRIDE_EQUALS"/> + </Match> + <Match> + <Class name="org.apache.fop.fo.properties.CondLengthProperty"/> + <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> + </Match> + <Match> + <Class name="org.apache.fop.pdf.xref.TrailerDictionary$1FileID"/> + <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> + </Match> + <Match> + <Class name="org.apache.fop.fo.properties.ToBeImplementedProperty"/> + <Bug pattern="EQ_ALWAYS_TRUE"/> + </Match> <Match> <Class name="org.apache.fop.render.intermediate.IFStructureTreeBuilder"/> <Field name="delegate"/> diff --git a/lib/xmlgraphics-commons-1.5svn.jar b/lib/xmlgraphics-commons-1.5svn.jar Binary files differindex 5d555e348..88f8d2075 100644 --- a/lib/xmlgraphics-commons-1.5svn.jar +++ b/lib/xmlgraphics-commons-1.5svn.jar diff --git a/src/documentation/content/xdocs/bugs.xml b/src/documentation/content/xdocs/bugs.xml index e2f36d50d..caeb728b2 100644 --- a/src/documentation/content/xdocs/bugs.xml +++ b/src/documentation/content/xdocs/bugs.xml @@ -45,21 +45,66 @@ an email as changes are made to the issue.</li> </section> <section id="issues_new"> <title>Unreported Issues (Reporting New Issues)</title> - <p>User reports of bugs and requests for enhancements are extremely -important parts of FOP development, and we appreciate the time you take to help -us track these issues down.</p> + <p> + User reports of bugs and requests for enhancements are extremely + important parts of FOP development, and we appreciate the time you take to help + us track these issues down. + </p> <ul> - <li>To help us ensure that the bug database is as useful as it should be, please -use the <link href="gethelp.html">Getting Help</link> checklist to determine whether a bug report should be entered.</li> - <li>Review the <link href="http://issues.apache.org/bugzilla/page.cgi?id=bug-writing.html">Apache Bug Writing Guidelines</link> before submitting your report.</li> - <li>Enter a new issue report at <link href="http://issues.apache.org/bugzilla/enter_bug.cgi?product=Fop">The FOP issue database (Bugzilla)</link>. -You will be asked to login to an existing Bugzilla account or to create a new -one. -When entering the bug report, please make your description complete and concise. -If appropriate, attach a minimal fo file to your report which demonstrates the -problem.</li> - <li>After submission, a copy of your bug report will be automatically -sent to the FOP developer discussion list.</li> + <li> + To help us ensure that the bug database is as useful as it should be, please + use the <link href="gethelp.html">Getting Help</link> checklist to determine whether a bug report should be entered. + </li> + <li> + Review the <link href="http://issues.apache.org/bugzilla/page.cgi?id=bug-writing.html">Apache Bug + Writing Guidelines</link> before submitting your report. + </li> + <li> + Enter a new issue report at <link href="http://issues.apache.org/bugzilla/enter_bug.cgi?product=Fop">The + FOP issue database (Bugzilla)</link>. You will be asked to login to an existing Bugzilla account or to + create a new one. When entering the bug report, please make your description complete and concise. + If the issue involves a specific input or output file, then you <strong>MUST</strong> include the + following information in the bug report (preferably as one or more attachments): + <ul> + <li> + an input XSL-FO file (an input XML plus XSLT file is not acceptable, unless and only if the + issue being reported is related to the built-in XSLT transform processing convenience function provided + by FOP); this input <strong>SHOULD</strong> be <em>maximally minimal</em>, which means that it should + contain nothing more than the minimum needed to demonstrate the problem; if you do not take the effort + to provide a maximally minimal input FO file, then you will be subsequently asked to do so before the + bug is processed; + </li> + <li> + a resulting output file, preferably in PDF format; if the issue being reported involves a different output + format, then provide both a PDF output file and the output file for the output format for which the report + applies; + </li> + <li> + a copy of the FOP configuration file you used (e.g., fop.xconf); + </li> + <li> + if FOP was invoked using the command line (or an equivalent), then a dump of both the input + command line and any console output (stderr or stdout) produced; if the report involves an + exception, then this <strong>MUST</strong> include the full stack back trace; + </li> + <li> + information describing the version of FOP you are using and the platform (and OS) on which + you are invoking FOP; + </li> + <li> + if the report applies to the use of a specific font other than one of the built-in, base 14 + fonts, then information that describes where to obtain the font. + </li> + </ul> + </li> + <li> + After submission, a copy of your bug report will be automatically + sent to the FOP developer discussion list. If additional information is needed to + process the bug, then the bug will be set to the <code>NEEDSINFO</code> state, and + you will be asked to provide the additional information. You can avoid this extra + step by being diligent about providing <strong>all</strong> of the information + indicated above. + </li> </ul> </section> </body> diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index fe3107142..a8e7a39ca 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -3962,10 +3962,10 @@ <td><a name="fo-property-border-collapse" id= "fo-property-border-collapse">border-collapse</a></td> <td class="extended">Extended</td> - <td class="yes">yes</td> - <td class="yes">yes</td> - <td class="yes">yes</td> - <td>Some small limitations</td> + <td class="partial">partial</td> + <td class="partial">partial</td> + <td class="partial">partial</td> + <td>value "collapse-with-precedence" not yet supported</td> </tr> <tr> <td align="center"><a href= diff --git a/src/documentation/content/xdocs/faq.xml b/src/documentation/content/xdocs/faq.xml index c4ddc6054..845c24045 100644 --- a/src/documentation/content/xdocs/faq.xml +++ b/src/documentation/content/xdocs/faq.xml @@ -25,7 +25,7 @@ <question>What is Apacheâ„¢ FOP?</question> <answer> <p> - FOP is a print formatter for <link href="#XSLFO">XSL formatting + FOP is a print formatter for <link href="#xslfo">XSL formatting objects</link>. </p> <p> @@ -65,16 +65,23 @@ <question>How does FOP interact with other Apache Projects?</question> <answer> <p> - FOP is distributed with <link - href="http://xml.apache.org/cocoon">Cocoon</link> as a PDF serializer - for XSL (FO) documents. + <link href="http://xmlgraphics.apache.org/commons">XML Graphics Commons</link> is used with + FOP to provide graphics functions that are common to a number of Apache projects. </p> <p> - <link href="http://xmlgraphics.apache.org/batik">Batik</link> can be used with + <link href="http://xmlgraphics.apache.org/batik">Batik</link> is used with FOP to <link href="http://xmlgraphics.apache.org/batik/svgrasterizer.html">transcode an SVG image</link> into a PDF document. </p> + <p>FOP also makes use of the following Apache projects:</p> + <ul> + <li><link href="http://excalibur.apache.org/framework/">Avalon Framework</link></li> + <li><link href="http://jakarta.apache.org/commons/io/">Jakarta Commons IO</link></li> + <li><link href="http://jakarta.apache.org/commons/logging/">Jakarta Commons Logging</link></li> + <li><link href="http://xalan.apache.org/">Xalan-J</link></li> + <li><link href="http://xml.apache.org/commons/components/external/">XML Commons Externals</link></li> + </ul> </answer> </faq> <faq id="xsl-def"> @@ -83,7 +90,7 @@ <p> XSL is a W3C standard concerned with publishing XML documents. It consists of two parts: <link href="#XSLT">XSLT</link> and <link - href="#XSLFO">XSL-FO</link>. The acronym expands to + href="#xslfo">XSL-FO</link>. The acronym expands to e<strong>X</strong>tensible <strong>S</strong>tylesheet <strong>L</strong>anguage. </p> @@ -93,7 +100,9 @@ <question>What is XSL-FO?</question> <answer> <p> - XSLFO (aka XSL-FO) is an XML vocabulary that is used to specify a pagination and + XSLFO (aka XSL-FO) is an XML vocabulary, defined by W3C Recommendation + <link href="http://www.w3.org/TR/xsl/">Extensible Stylesheet Language (XSL) + Version 1.1</link>, that is used to specify a pagination and other styling for page layout output. The acronym “FO” stands for <strong>F</strong>ormatting <strong>O</strong>bjects. XSLFO can be @@ -226,8 +235,7 @@ <answer> <p> This is usually caused by an older version of one of the FOP jars or - old XML tools in the classpath. Check in particular for parser.jar, - jaxp.jar, xml4j.jar or lotusxsl.jar. + old XML tools in the classpath. </p> <p> Incompatible versions of Batik may also cause this problem. Use the @@ -269,8 +277,9 @@ the <code>file:</code> prefix, for example <code>file.ext</code>, <code>path/file.ext</code> or <code>../file.ext</code>. The string <code>file:path/file.ext</code> is <em>not</em> a relative URL, - in fact, it isn't a valid URL at all. A relative URL is subject to a - resolving process, which transforms it into an absolute + in fact, it isn't a valid URL at all since the <code>file</code> + scheme does not (officially) support relative paths. A relative URL + is subject to a resolving process, which transforms it into an absolute URL. </p> <!--p> @@ -283,31 +292,8 @@ <question>I get an "[ERROR]: null", or a NullPointerException.</question> <answer> <p> - This is often caused by an invalid FO document. Currently only very - common errors are intercepted and produce a comprehensible error - message. If you forgot container elements like <code>fo:page-sequence</code> or - <code>fo:flow</code> and put blocks and inline elements directly as children of - <code>fo:root</code> or <code>fo:page-sequence</code>, you'll only get a - NullPointerException. Check whether your FO file has a proper - structure. In some cases there are mandatory properties, like the - master-reference in <code>fo:conditional-page-master-reference</code>, check also - whether you got them right. - </p> - <p> - You may find it helpful to use the <link href="#fo-validate">validation tools</link> to validate your - FO document. This will catch most problems, but should not be - relied upon to catch all. - </p> - <p> - If you use XSLT, problems in your style sheet and in your - source XML also can produce a NullPointerException. <link - href="1.0/running.html#check-input">Run the transformation - separately</link> to check for this, usually you'll get a - detailed error message from the XSLT processor. - </p> - <p> - If you turn on debugging with the "<code>-d</code>" option you may be able to - see more detailed information. + This is a very likely a bug in FOP. If you encounter this error, please + <link href="bugs.html#issues_new">Open a New Bug</link>. </p> </answer> </faq> @@ -322,9 +308,9 @@ <answer> <p> The most likely reason is a known problem with the Java run time - environment which is triggered by rendering SVGs. Suns JDK 1.4 does - not have this problem. See also <link href="#svghangs">FOP does not - exit if a SVG is included</link>. + environment which is triggered by rendering SVGs. Sun's JDK 1.4 and + later do not have this problem. See also <link href="#svghangs">FOP + does not exit if a SVG is included</link>. </p> <p> Another possibility is that FOP went into a non terminating @@ -340,6 +326,10 @@ the FOP output regularly to empty the pipe buffer. It is best to avoid exec'ing FOP, use the library interface instead. </p> + <p> + If you can reproduce this problem given a specific input and configuration, + then please <link href="bugs.html#issues_new">Open a New Bug</link>. + </p> </answer> </faq> <faq id="boxoverflow"> @@ -441,8 +431,7 @@ public class DefaultErrorListener implements ErrorListener { To avoid the warning you can simply delete the old Font Cache file, which lives in ${base}\conf\font.cache (see <link href="1.0/configuration.html#general-elements">font-base - configuration</link>). Or you can disable Font Caching altogether using - the option "use-cache." + configuration</link>). </p> </answer> </faq> @@ -524,7 +513,7 @@ Check the following:</p> HTTP. Possible issues include security settings on the server, server configuration, and missing cookies or other authorization information. Any easy way to check this is to - cut&paste the source URL from the fo:external-graphic + cut and paste the source URL from the <code>fo:external-graphic</code> into the Location field of a browser <strong>on the machine where the FOP process will be running</strong>.</li> </ul> @@ -627,7 +616,7 @@ Check the following:</p> explicit wrapping+clipping, </li> <li> - insert zero width spaces (U+200B or &#x200B;) to allow FOP to + insert zero width spaces (&#x200B;) to allow FOP to wrap. </li> </ul> @@ -1281,7 +1270,7 @@ Can I control this?</question> <question>Where can I learn how the FOP docs and web site are built?</question> <answer> <p> - See FOP <link href="dev/doc.html">Doc Management</link>. ;-) + See FOP <link href="dev/doc.html">Doc Management</link>. </p> </answer> </faq> @@ -1307,7 +1296,7 @@ Can I control this?</question> If you have a runtime exception or other runtime problem: <ul> <li> - double-check the <link href="#part-running">Runtime FAQs</link>. + Double check the <link href="#part-running">Runtime FAQs</link>. </li> <li> ClassNotFoundException, NoSuchMethodException and @@ -1325,7 +1314,7 @@ Can I control this?</question> </li> <li> In the case where something works properly with another formatter, - (AntennaHouse, PassiveTex, etc.) but doesn't work with FOP, please + (e.g., AntennaHouse, PassiveTex, etc.) but doesn't work with FOP, please check the <!--link href="relnotes.html"-->Release Notes<!--/link-->, the <link href="compliance.html">FOP Standards Compliance</link> document, and the remaining FAQ in this document. If not found there, look at the @@ -1348,13 +1337,8 @@ Can I control this?</question> Problems specific to a certain XSLT processor, like Xalan, Saxon or MSXML, should be handled by processor specific lists. This includes problems with deployment, processor specific extensions, suspected - bugs and processor specific APIs. Note that JDK 1.4 comes with an - XML parser and an XSLT processor which are older versions of - Xerces and Xalan, respectively, and both have a number of annoying - bugs. See http://java.sun.com/developer/EJTechTips/2003/tt0311.html - and http://java.sun.com/j2se/1.4.2/docs/guide/standards/ (or similar - pages for later Java releases) for some hints on how to use more - recent versions or other packages instead. + bugs and processor specific APIs. Note that JDK 1.4 and later come with an + XML parser and an XSLT processor which may be the source of the problem. </li> <li> Problems with servlet containers should be asked on the vendor diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 4735b74a8..a8f0602e4 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -81,9 +81,7 @@ Geneon media solutions gmbh in Nuremberg, Germany. He needs FOP to wrestle gigabytes of electronic data into thousands of printed pages.</li> <li id="lm">Louis Masters</li> - <li id="vr">Vanukuri Venkat Reddy is a Senior Software Engineer in UK, using XML Graphics - Project and FOP for his work, and is committed to contributing more to the Apache to be part - a great team.</li> + <li id="lb">Luis Bernardo</li> </ul> </section> <section id="founder"> diff --git a/src/documentation/content/xdocs/trunk/complexscripts.xml b/src/documentation/content/xdocs/trunk/complexscripts.xml index 084fa100a..c622fe192 100644 --- a/src/documentation/content/xdocs/trunk/complexscripts.xml +++ b/src/documentation/content/xdocs/trunk/complexscripts.xml @@ -21,7 +21,7 @@ <header> <title>Apacheâ„¢ FOP: Complex Scripts</title> </header> - <body id="complex_scripts"> + <body> <section id="overview"> <title>Overview</title> <p> diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index 10769c5ff..b30a091a5 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -443,7 +443,7 @@ <p> Additionally, there are certain settings that control how the renderer handles various elements. </p> -<source><![CDATA[<renderer mime="application/vnd.hp-PCL"> +<source><![CDATA[<renderer mime="application/x-pcl"> <rendering>quality</rendering> <text-rendering>bitmap</text-rendering> </renderer>]]></source> @@ -471,6 +471,7 @@ <source><![CDATA[<renderer mime="application/x-afp"> <images mode="b+w" bits-per-pixel="8" native="true"/> <renderer-resolution>240</renderer-resolution> + <line-width-correction>2.5</line-width-correction> <!-- a default external resource group file --> <resource-group-file>resources.afp</resource-group-file> @@ -482,6 +483,9 @@ <p> The default value for the "renderer-resolution" is 240 dpi. </p> + <p> + The default line width is device dependent and may need to be fine tuned so that the output matches the expected result. The default correction value is 2.5. + </p> <!-- <p> The default value for the MO:DCA "interchange-set" is "MO:DCA-L". Other compliance settings include presentation interchange sets "MO:DCA-P IS/1" and "MO:DCA-P IS/2" (Resource Groups). diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 7d6147be9..cabbbb0fa 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -406,7 +406,7 @@ out = proc.getOutputStream();]]></source> <p> The PCL renderer configuration currently allows the following settings: </p> -<source><![CDATA[<renderer mime="application/vnd.hp-PCL"> +<source><![CDATA[<renderer mime="application/x-pcl"> <rendering>quality</rendering> <text-rendering>bitmap</text-rendering> <disable-pjl>false</disable-pjl> @@ -757,6 +757,14 @@ Note that the value of the encoding attribute in the example is the double-byte <source><![CDATA[ <renderer-resolution>240</renderer-resolution>]]></source> </section> + <section id="afp-line-width-correction-config"> + <title>Line Width Correction</title> + <p>The default line width in AFP is device dependent. This means that a line width specified in, say, + a SVG source file may not render the way it was intended. The output AFP line with can be corrected + by the <line-width-correction/> configuration element. Example:</p> + <source><![CDATA[ + <line-width-correction>2.5</line-width-correction>]]></source> + </section> <section id="afp-image-config"> <title>Images</title> <p>By default the AFP Renderer converts all images to 8 bit grey level. 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 bea5275a5..6e17c793b 100644 --- a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd +++ b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd @@ -34,6 +34,7 @@ <xs:element ref="mf:page-sequence" minOccurs="1" maxOccurs="unbounded"/> <xs:element ref="mf:trailer"/> </xs:sequence> + <xs:attribute name="version" type="xs:string"/> </xs:complexType> </xs:element> <xs:element name="header"> diff --git a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java index 66eaece89..c63c721e5 100644 --- a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java +++ b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java @@ -34,7 +34,7 @@ public final class DummyStructureTreeEventHandler implements StructureTreeEventH private DummyStructureTreeEventHandler() { } /** {@inheritDoc} */ - public void startPageSequence(Locale locale) { + public void startPageSequence(Locale locale, String role) { } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java index 79c589f9b..7a375ef20 100644 --- a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java +++ b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java @@ -30,6 +30,7 @@ import org.apache.fop.fo.FOElementMapping; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.render.intermediate.IFConstants; +import org.apache.fop.util.XMLConstants; /** * Converts structure tree events to SAX events. @@ -52,16 +53,19 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa } /** {@inheritDoc} */ - public void startPageSequence(Locale locale) { + public void startPageSequence(Locale locale, String role) { try { - + AttributesImpl attributes = new AttributesImpl(); + if (role != null) { + attributes.addAttribute("", "type", "type", XMLConstants.CDATA, role); + } contentHandler.startPrefixMapping( InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI); contentHandler.startPrefixMapping( ExtensionElementMapping.STANDARD_PREFIX, ExtensionElementMapping.URI); contentHandler.startElement(IFConstants.NAMESPACE, IFConstants.EL_STRUCTURE_TREE, IFConstants.EL_STRUCTURE_TREE, - new AttributesImpl()); + attributes); } catch (SAXException e) { throw new RuntimeException(e); } diff --git a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java index 4b94d61f1..46b724626 100644 --- a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java +++ b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java @@ -34,8 +34,9 @@ public interface StructureTreeEventHandler { * Starts a page sequence structure tree node. * * @param locale The locale of the page sequence + * @param role the value of the role property. May be null. */ - void startPageSequence(Locale locale); + void startPageSequence(Locale locale, String role); /** * Starts a structure tree node. diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java index 957f40870..51f7f2bed 100644 --- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java +++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java @@ -89,7 +89,8 @@ class StructureTreeEventTrigger extends FOEventHandler { locale = new Locale(pageSeq.getLanguage()); } } - structureTreeEventHandler.startPageSequence(locale); + String role = pageSeq.getCommonAccessibility().getRole(); + structureTreeEventHandler.startPageSequence(locale, role); } @Override diff --git a/src/java/org/apache/fop/afp/AFPConstants.java b/src/java/org/apache/fop/afp/AFPConstants.java index 6b26c18fd..49b671e66 100644 --- a/src/java/org/apache/fop/afp/AFPConstants.java +++ b/src/java/org/apache/fop/afp/AFPConstants.java @@ -50,4 +50,15 @@ public interface AFPConstants { * 72dpi in millipoints */ int DPI_72_MPTS = DPI_72 * 1000; + + /** + * The line width is set as a multiplier of a default line with; the width of the default + * line width is implementation defined, which probably means different devices use different + * actual widths; this means that the source line width (as specified in, say, a SVG line + * element) needs to be corrected by a fudge factor that depends on the output device so that + * the final output (print to paper, screen viewer) looks as intended. + */ + float LINE_WIDTH_CORRECTION = 2.5f; + } + diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java index 41be79160..e9a269ac4 100644 --- a/src/java/org/apache/fop/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -263,14 +263,6 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand return length * factor; } - /** IBM's AFP Workbench paints lines that are wider than expected. We correct manually. */ - private static final double GUESSED_WIDTH_CORRECTION = 1.7; - - private static final double SPEC_NORMAL_LINE_WIDTH = UnitConv.in2pt(0.01); //"approx" 0.01 inch - private static final double NORMAL_LINE_WIDTH - = SPEC_NORMAL_LINE_WIDTH * GUESSED_WIDTH_CORRECTION; - - /** * Apply the stroke to the AFP graphics object. * This takes the java stroke and outputs the appropriate settings @@ -282,17 +274,11 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand if (stroke instanceof BasicStroke) { BasicStroke basicStroke = (BasicStroke) stroke; - // set line width + // set line width and correct it; NOTE: apparently we need to correct the width so that the + // output looks OK since the default with depends on the output device float lineWidth = basicStroke.getLineWidth(); - if (false) { - //Old approach. Retained until verified problems with 1440 resolution - graphicsObj.setLineWidth(Math.round(lineWidth / 2)); - } else { - double absoluteLineWidth = lineWidth * Math.abs(getTransform().getScaleY()); - double multiplier = absoluteLineWidth / NORMAL_LINE_WIDTH; - graphicsObj.setLineWidth((int)Math.round(multiplier)); - //TODO Use GSFLW instead of GSLW for higher accuracy? - } + float correction = paintingState.getLineWidthCorrection(); + graphicsObj.setLineWidth(lineWidth * correction); //No line join, miter limit and end cap support in GOCA. :-( diff --git a/src/java/org/apache/fop/afp/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java index 7e6b940a5..ea2ebe475 100644 --- a/src/java/org/apache/fop/afp/AFPPaintingState.java +++ b/src/java/org/apache/fop/afp/AFPPaintingState.java @@ -79,6 +79,12 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState /** the output resolution */ private int resolution = 240; // 240 dpi + /** + * A configurable value to correct the line width so that the output matches the expected. Different + * devices may need different values. + */ + private float lineWidthCorrection = AFPConstants.LINE_WIDTH_CORRECTION; + /** determines whether GOCA is enabled or disabled */ private boolean gocaEnabled = true; /** determines whether to stroke text in GOCA mode or to use text operators where possible */ @@ -323,6 +329,18 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState } /** + * Sets the line width correction + * + * @param correction the line width multiplying factor correction + */ + public void setLineWidthCorrection(float correction) { + if (log.isDebugEnabled()) { + log.debug("line width correction set to: " + correction); + } + this.lineWidthCorrection = correction; + } + + /** * Returns the output/device resolution. * * @return the resolution in dpi @@ -332,6 +350,14 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState } /** + * Returns the line width correction. + * @return the correction + */ + public float getLineWidthCorrection() { + return this.lineWidthCorrection; + } + + /** * Controls whether GOCA is enabled or disabled. * @param enabled true if GOCA is enabled, false if it is disabled */ diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index 341abde0b..fad5e95e6 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -94,12 +94,12 @@ public class CharacterSet { * * @param codePage the code page identifier * @param encoding the encoding of the font - * @param isEBDCS if this is an EBCDIC double byte character set. + * @param charsetType the type of the characterset * @param name the character set name * @param accessor the resource accessor to load resource with * @param eventProducer for handling AFP related events */ - CharacterSet(String codePage, String encoding, boolean isEBDCS, String name, + CharacterSet(String codePage, String encoding, CharacterSetType charsetType, String name, ResourceAccessor accessor, AFPEventProducer eventProducer) { if (name.length() > MAX_NAME_LEN) { String msg = "Character set name '" + name + "' must be a maximum of " @@ -115,7 +115,7 @@ public class CharacterSet { } this.codePage = codePage; this.encoding = encoding; - this.encoder = CharactersetEncoder.newInstance(encoding, isEBDCS); + this.encoder = CharactersetEncoder.newInstance(encoding, charsetType); this.accessor = accessor; this.characterSetOrientations = new HashMap<String, CharacterSetOrientation>(4); @@ -306,7 +306,7 @@ public class CharacterSet { */ private CharacterSetOrientation getCharacterSetOrientation() { CharacterSetOrientation c - = (CharacterSetOrientation) characterSetOrientations.get(currentOrientation); + = characterSetOrientations.get(currentOrientation); return c; } diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java index 4988bb949..7da2d71ca 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java @@ -190,10 +190,10 @@ public abstract class CharacterSetBuilder { * @return CharacterSet object * @throws IOException if an I/O error occurs */ - public CharacterSet build(String characterSetName, String codePageName, String encoding, + public CharacterSet buildSBCS(String characterSetName, String codePageName, String encoding, ResourceAccessor accessor, AFPEventProducer eventProducer) throws IOException { - return processFont(characterSetName, codePageName, encoding, false, accessor, - eventProducer); + return processFont(characterSetName, codePageName, encoding, CharacterSetType.SINGLE_BYTE, + accessor, eventProducer); } /** @@ -204,16 +204,16 @@ public abstract class CharacterSetBuilder { * @param characterSetName name of the characterset * @param codePageName name of the code page file * @param encoding encoding name - * @param isEDBCS if this is an EBCDIC double byte character set (DBCS) + * @param charsetType the characterset type * @param accessor used to load codepage and characterset * @param eventProducer for handling AFP related events * @return CharacterSet object * @throws IOException if an I/O error occurs */ public CharacterSet buildDBCS(String characterSetName, String codePageName, String encoding, - boolean isEDBCS, ResourceAccessor accessor, AFPEventProducer eventProducer) + CharacterSetType charsetType, ResourceAccessor accessor, AFPEventProducer eventProducer) throws IOException { - return processFont(characterSetName, codePageName, encoding, isEDBCS, accessor, + return processFont(characterSetName, codePageName, encoding, charsetType, accessor, eventProducer); } @@ -236,7 +236,7 @@ public abstract class CharacterSetBuilder { } private CharacterSet processFont(String characterSetName, String codePageName, String encoding, - boolean isEDBCS, ResourceAccessor accessor, AFPEventProducer eventProducer) + CharacterSetType charsetType, ResourceAccessor accessor, AFPEventProducer eventProducer) throws IOException { // check for cached version of the characterset String descriptor = characterSetName + "_" + encoding + "_" + codePageName; @@ -247,7 +247,7 @@ public abstract class CharacterSetBuilder { } // characterset not in the cache, so recreating - characterSet = new CharacterSet(codePageName, encoding, isEDBCS, characterSetName, + characterSet = new CharacterSet(codePageName, encoding, charsetType, characterSetName, accessor, eventProducer); InputStream inputStream = null; @@ -465,8 +465,7 @@ public abstract class CharacterSetBuilder { } } - return (CharacterSetOrientation[]) orientations - .toArray(EMPTY_CSO_ARRAY); + return orientations.toArray(EMPTY_CSO_ARRAY); } /** @@ -570,7 +569,7 @@ public abstract class CharacterSetBuilder { String gcgiString = new String(gcgid, AFPConstants.EBCIDIC_ENCODING); - String idx = (String) codepage.get(gcgiString); + String idx = codepage.get(gcgiString); if (idx != null) { diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetType.java b/src/java/org/apache/fop/afp/fonts/CharacterSetType.java new file mode 100644 index 000000000..8eaaa089b --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetType.java @@ -0,0 +1,31 @@ +/* + * 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.afp.fonts; + +/** + * An enumeration of AFP characterset types. + */ +public enum CharacterSetType { + /** Double byte character sets; these do NOT have the shift-in;shift-out operators */ + DOUBLE_BYTE, + /** Double byte character sets; these can have the shift-in;shift-out operators */ + DOUBLE_BYTE_LINE_DATA, + SINGLE_BYTE; +} diff --git a/src/java/org/apache/fop/afp/fonts/CharactersetEncoder.java b/src/java/org/apache/fop/afp/fonts/CharactersetEncoder.java index 229123a82..f101bdab4 100644 --- a/src/java/org/apache/fop/afp/fonts/CharactersetEncoder.java +++ b/src/java/org/apache/fop/afp/fonts/CharactersetEncoder.java @@ -82,13 +82,12 @@ public abstract class CharactersetEncoder { * * @param chars the character sequence * @param encoding the encoding type - * @param isEDBCS if this encoding represents a double-byte character set * @return encoded data * @throws CharacterCodingException if encoding fails */ - public static EncodedChars encodeSBCS(CharSequence chars, String encoding, boolean isEDBCS) + public static EncodedChars encodeSBCS(CharSequence chars, String encoding) throws CharacterCodingException { - CharactersetEncoder encoder = newInstance(encoding, isEDBCS); + CharactersetEncoder encoder = newInstance(encoding, CharacterSetType.SINGLE_BYTE); return encoder.encode(chars); } @@ -98,16 +97,16 @@ public abstract class CharactersetEncoder { * sequence it will return its EBCDIC code-point, however, the "Shift In - Shift Out" operators * are removed from the sequence of bytes. These are only used in Line Data. */ - private static final class EbcdicDoubleByteEncoder extends CharactersetEncoder { - private EbcdicDoubleByteEncoder(String encoding) { + private static final class EbcdicDoubleByteLineDataEncoder extends CharactersetEncoder { + private EbcdicDoubleByteLineDataEncoder(String encoding) { super(encoding); } @Override EncodedChars getEncodedChars(byte[] byteArray, int length) { if (byteArray[0] == 0x0E && byteArray[length - 1] == 0x0F) { - return new EncodedChars(byteArray, 1, length - 2); + return new EncodedChars(byteArray, 1, length - 2, true); } - return new EncodedChars(byteArray); + return new EncodedChars(byteArray, true); } } @@ -117,13 +116,16 @@ public abstract class CharactersetEncoder { * byte character sets (DBCS). */ private static final class DefaultEncoder extends CharactersetEncoder { - private DefaultEncoder(String encoding) { + private final boolean isDBCS; + + private DefaultEncoder(String encoding, boolean isDBCS) { super(encoding); + this.isDBCS = isDBCS; } @Override EncodedChars getEncodedChars(byte[] byteArray, int length) { - return new EncodedChars(byteArray); + return new EncodedChars(byteArray, isDBCS); } } @@ -134,47 +136,40 @@ public abstract class CharactersetEncoder { * @param isEbcdicDBCS whether or not this wraps a double-byte EBCDIC code page. * @return the CharactersetEncoder */ - static CharactersetEncoder newInstance(String encoding, boolean isEbcdicDBCS) { - if (isEbcdicDBCS) { - return new EbcdicDoubleByteEncoder(encoding); - } else { - return new DefaultEncoder(encoding); + static CharactersetEncoder newInstance(String encoding, CharacterSetType charsetType) { + switch (charsetType) { + case DOUBLE_BYTE_LINE_DATA: + return new EbcdicDoubleByteLineDataEncoder(encoding); + case DOUBLE_BYTE: + return new DefaultEncoder(encoding, true); + default: + return new DefaultEncoder(encoding, false); } } /** * A container for encoded character bytes */ - public static final class EncodedChars { + // CSOFF: FinalClass - disabling "final" modifier so that this class can be mocked + public static class EncodedChars { private final byte[] bytes; - private final int offset; - private final int length; + private final boolean isDBCS; - private EncodedChars(byte[] bytes, int offset, int length) { - if (offset < 0) { - throw new IllegalArgumentException(); - } - - if (length < 0) { + private EncodedChars(byte[] bytes, int offset, int length, boolean isDBCS) { + if (offset < 0 || length < 0 || offset + length > bytes.length) { throw new IllegalArgumentException(); } - - if (offset + length > bytes.length) { - throw new IllegalArgumentException(); - } - this.bytes = bytes; - this.offset = offset; - this.length = length; + this.isDBCS = isDBCS; } - private EncodedChars(byte[] bytes) { - this(bytes, 0, bytes.length); + private EncodedChars(byte[] bytes, boolean isDBCS) { + this(bytes, 0, bytes.length, isDBCS); } /** @@ -186,18 +181,9 @@ public abstract class CharactersetEncoder { * @throws IOException if an I/O error occurs */ public void writeTo(OutputStream out, int offset, int length) throws IOException { - if (offset < 0) { + if (offset < 0 || length < 0 || offset + length > bytes.length) { throw new IllegalArgumentException(); } - - if (length < 0) { - throw new IllegalArgumentException(); - } - - if (offset + length > this.length) { - throw new IllegalArgumentException(); - } - out.write(bytes, this.offset + offset, length); } @@ -211,6 +197,15 @@ public abstract class CharactersetEncoder { } /** + * Indicates whether or not the EncodedChars object wraps double byte characters. + * + * @return true if the wrapped characters are double byte (DBCSs) + */ + public boolean isDBCS() { + return isDBCS; + } + + /** * The bytes * * @return the bytes diff --git a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java index f949976ba..f83c38621 100644 --- a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java @@ -42,7 +42,8 @@ public class FopCharacterSet extends CharacterSet { */ public FopCharacterSet(String codePage, String encoding, String name, Typeface charSet, AFPEventProducer eventProducer) { - super(codePage, encoding, false, name, (ResourceAccessor) null, eventProducer); + super(codePage, encoding, CharacterSetType.SINGLE_BYTE, name, (ResourceAccessor) null, + eventProducer); this.charSet = charSet; } @@ -132,5 +133,4 @@ public class FopCharacterSet extends CharacterSet { public char mapChar(char c) { return charSet.mapChar(c); } - } diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidth.java b/src/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidth.java new file mode 100644 index 000000000..529001676 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidth.java @@ -0,0 +1,69 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the line width to use when stroking GOCA shapes (structured fields) + */ +public class GraphicsSetFractionalLineWidth extends AbstractGraphicsDrawingOrder { + + /** line width multiplier */ + private final float multiplier; + + /** + * Main constructor + * + * @param multiplier the line width multiplier + */ + public GraphicsSetFractionalLineWidth(float multiplier) { + this.multiplier = multiplier; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 4; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + int integral = (int) multiplier; + int fractional = (int) ((multiplier - (float) integral) * 256); + byte[] data = new byte[] { + getOrderCode(), // GSLW order code + 0x02, // two bytes next + (byte) integral, // integral line with + (byte) fractional // and fractional + }; + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetFractionalLineWidth{multiplier=" + multiplier + "}"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x11; + } +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java index 96b54f3cd..ca8812f14 100644 --- a/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java @@ -28,7 +28,7 @@ import java.io.OutputStream; public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder { /** line width multiplier */ - private int multiplier = 1; + private final int multiplier; /** * Main constructor @@ -48,7 +48,7 @@ public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder { public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[] { getOrderCode(), // GSLW order code - (byte)multiplier // MH (line-width) + (byte) multiplier // MH (line-width) }; os.write(data); } diff --git a/src/java/org/apache/fop/afp/modca/AxisOrientation.java b/src/java/org/apache/fop/afp/modca/AxisOrientation.java new file mode 100644 index 000000000..a017fe5e3 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AxisOrientation.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Represents the 4 bytes that specify the axis-area rotation reference coordinate system + */ +public enum AxisOrientation { + + RIGHT_HANDED_0(Rotation.ROTATION_0, Rotation.ROTATION_90), + RIGHT_HANDED_90(Rotation.ROTATION_90, Rotation.ROTATION_180), + RIGHT_HANDED_180(Rotation.ROTATION_180, Rotation.ROTATION_270), + RIGHT_HANDED_270(Rotation.ROTATION_270, Rotation.ROTATION_0); + + /** + * The object area's X-axis rotation from the X axis of the reference coordinate system + */ + private final Rotation xoaOrent; + /** + * The object area's Y-axis rotation from the Y axis of the reference coordinate system + */ + private final Rotation yoaOrent; + + public void writeTo(byte[] out, int offset) { + xoaOrent.writeTo(out, offset); + yoaOrent.writeTo(out, offset + 2); + } + + private AxisOrientation(Rotation xoaOrent, Rotation yoaOrent) { + this.xoaOrent = xoaOrent; + this.yoaOrent = yoaOrent; + } + + /** + * Writes the axis orientation area bytes to the output stream. + * + * @param stream the output stream to write to + * @throws IOException if an I/O error occurs + */ + public void writeTo(OutputStream stream) throws IOException { + byte[] data = new byte[4]; + writeTo(data, 0); + stream.write(data); + } + + /** + * Gets the right-handed axis orientation object for a given orientation in degrees. + * + * @param orientation the orientation in degrees + * @return the {@link AxisOrientation} object + */ + public static AxisOrientation getRightHandedAxisOrientationFor(int orientation) { + switch (orientation) { + case 0: return RIGHT_HANDED_0; + case 90: return RIGHT_HANDED_90; + case 180: return RIGHT_HANDED_180; + case 270: return RIGHT_HANDED_270; + default: throw new IllegalArgumentException( + "The orientation must be one of the values 0, 90, 180, 270"); + } + } +} diff --git a/src/java/org/apache/fop/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/afp/modca/GraphicsObject.java index 9b870767e..7284c69f3 100644 --- a/src/java/org/apache/fop/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/afp/modca/GraphicsObject.java @@ -48,6 +48,7 @@ import org.apache.fop.afp.goca.GraphicsLine; import org.apache.fop.afp.goca.GraphicsSetArcParameters; import org.apache.fop.afp.goca.GraphicsSetCharacterSet; import org.apache.fop.afp.goca.GraphicsSetCurrentPosition; +import org.apache.fop.afp.goca.GraphicsSetFractionalLineWidth; import org.apache.fop.afp.goca.GraphicsSetLineType; import org.apache.fop.afp.goca.GraphicsSetLineWidth; import org.apache.fop.afp.goca.GraphicsSetPatternSymbol; @@ -182,8 +183,21 @@ public class GraphicsObject extends AbstractDataObject { * @param lineWidth the line width multiplier */ public void setLineWidth(int lineWidth) { - if (lineWidth != graphicsState.lineWidth) { + if ((float) lineWidth != graphicsState.lineWidth) { addObject(new GraphicsSetLineWidth(lineWidth)); + graphicsState.lineWidth = (float) lineWidth; + } + } + + /** + * Sets the line width + * + * @param lineWidth the line width multiplier + */ + public void setLineWidth(float lineWidth) { + float epsilon = Float.intBitsToFloat ( 0x00800000 ); // Float.MIN_NORMAL (JDK1.6) + if ( Math.abs ( graphicsState.lineWidth - lineWidth ) > epsilon ) { + addObject(new GraphicsSetFractionalLineWidth(lineWidth)); graphicsState.lineWidth = lineWidth; } } @@ -414,7 +428,7 @@ public class GraphicsObject extends AbstractDataObject { private byte lineType; /** the current line width */ - private int lineWidth; + private float lineWidth; /** the current fill pattern */ private byte patternSymbol; diff --git a/src/java/org/apache/fop/afp/modca/IncludeObject.java b/src/java/org/apache/fop/afp/modca/IncludeObject.java index 68fa72688..4dca1b357 100644 --- a/src/java/org/apache/fop/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/afp/modca/IncludeObject.java @@ -67,7 +67,7 @@ public class IncludeObject extends AbstractNamedAFPObject { private int yoaOset = 0; /** the orientation of the referenced object */ - private ObjectAreaRotation oaOrent = ObjectAreaRotation.RIGHT_HANDED_0; + private AxisOrientation oaOrent = AxisOrientation.RIGHT_HANDED_0; /** the X-axis origin defined in the object */ private int xocaOset = -1; @@ -93,7 +93,7 @@ public class IncludeObject extends AbstractNamedAFPObject { * The orientation (0,90, 180, 270) */ public void setObjectAreaOrientation(int orientation) { - this.oaOrent = ObjectAreaRotation.objectAreaRotationFor(orientation); + this.oaOrent = AxisOrientation.getRightHandedAxisOrientationFor(orientation); } /** @@ -234,69 +234,4 @@ public class IncludeObject extends AbstractNamedAFPObject { addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); } - /** - * Represents the 4 bytes that specify the area rotation reference coordinate system - * - */ - private enum ObjectAreaRotation { - - RIGHT_HANDED_0(Rotation.ROTATION_0, Rotation.ROTATION_90), - RIGHT_HANDED_90(Rotation.ROTATION_90, Rotation.ROTATION_180), - RIGHT_HANDED_180(Rotation.ROTATION_180, Rotation.ROTATION_270), - RIGHT_HANDED_270(Rotation.ROTATION_270, Rotation.ROTATION_0); - - /** - * The object area's X-axis rotation from the X axis of the reference coordinate system - */ - private final Rotation xoaOrent; - /** - * The object area's Y-axis rotation from the Y axis of the reference coordinate system - */ - private final Rotation yoaOrent; - - public void writeTo(byte[] out, int offset) { - xoaOrent.writeTo(out, offset); - yoaOrent.writeTo(out, offset + 2); - } - - ObjectAreaRotation(Rotation xoaOrent, Rotation yoaOrent) { - this.xoaOrent = xoaOrent; - this.yoaOrent = yoaOrent; - } - - private static ObjectAreaRotation objectAreaRotationFor(int orientation) { - switch (orientation) { - case 0: return RIGHT_HANDED_0; - case 90: return RIGHT_HANDED_90; - case 180: return RIGHT_HANDED_180; - case 270: return RIGHT_HANDED_270; - default: throw new IllegalArgumentException( - "The orientation must be one of the values 0, 90, 180, 270"); - } - } - } - - /** - * Represents a rotation value - * - */ - private enum Rotation { - - ROTATION_0(0), - ROTATION_90(0x2D), - ROTATION_180(0x5A), - ROTATION_270(0x87); - - private final byte firstByte; - - public void writeTo(byte[] out, int offset) { - out[offset] = firstByte; - out[offset + 1] = (byte)0; - } - - Rotation(int firstByte) { - this.firstByte = (byte) firstByte; - } - } - } diff --git a/src/java/org/apache/fop/afp/modca/Rotation.java b/src/java/org/apache/fop/afp/modca/Rotation.java new file mode 100644 index 000000000..a307e1cf9 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/Rotation.java @@ -0,0 +1,46 @@ +/* + * 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.afp.modca; + +/** + * Represents a rotation value + * + */ +public enum Rotation { + ROTATION_0(0), + ROTATION_90(0x2D), + ROTATION_180(0x5A), + ROTATION_270(0x87); + + private final byte firstByte; + + public void writeTo(byte[] out, int offset) { + out[offset] = firstByte; + out[offset + 1] = (byte)0; + } + + private Rotation(int firstByte) { + this.firstByte = (byte) firstByte; + } + + public byte getByte() { + return firstByte; + } +} diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java index 1ea63c7f9..befd2cc1a 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java @@ -31,6 +31,8 @@ import org.apache.xmlgraphics.java2d.color.ColorUtil; import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives; import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; +import org.apache.fop.afp.modca.AxisOrientation; +import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData; /** * Generator class for PTOCA data structures. @@ -87,8 +89,10 @@ public abstract class PtocaBuilder implements PtocaConstants { baout.writeTo(out); } - private void writeByte(int data) { - baout.write(data); + private void writeBytes(int... data) { + for (int d : data) { + baout.write(d); + } } private void writeShort(int data) { @@ -123,7 +127,7 @@ public abstract class PtocaBuilder implements PtocaConstants { } newControlSequence(); - writeByte(font); + writeBytes(font); commit(chained(SCFL)); } @@ -187,26 +191,11 @@ public abstract class PtocaBuilder implements PtocaConstants { * @throws IOException if an I/O error occurs */ public void addTransparentData(EncodedChars encodedChars) throws IOException { - - // data size greater than TRANSPARENT_MAX_SIZE, so slice - int numTransData = encodedChars.getLength() / TRANSPARENT_DATA_MAX_SIZE; - int currIndex = 0; - for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) { - addTransparentDataChunk(encodedChars, currIndex, TRANSPARENT_DATA_MAX_SIZE); - currIndex += TRANSPARENT_DATA_MAX_SIZE; + for (TransparentData trn : new TransparentDataControlSequence(encodedChars)) { + newControlSequence(); + trn.writeTo(baout); + commit(chained(TRN)); } - int left = encodedChars.getLength() - currIndex; - addTransparentDataChunk(encodedChars, currIndex, left); - - } - - - - private void addTransparentDataChunk(EncodedChars encodedChars, int offset, int length) - throws IOException { - newControlSequence(); - encodedChars.writeTo(baout, offset, length); - commit(chained(TRN)); } /** @@ -222,7 +211,7 @@ public abstract class PtocaBuilder implements PtocaConstants { newControlSequence(); writeShort(length); // Rule length writeShort(width); // Rule width - writeByte(0); // Rule width fraction is always null. enough? + writeBytes(0); // Rule width fraction is always null. enough? commit(chained(DBR)); } @@ -239,7 +228,7 @@ public abstract class PtocaBuilder implements PtocaConstants { newControlSequence(); writeShort(length); // Rule length writeShort(width); // Rule width - writeByte(0); // Rule width fraction is always null. enough? + writeBytes(0); // Rule width fraction is always null. enough? commit(chained(DIR)); } @@ -260,32 +249,7 @@ public abstract class PtocaBuilder implements PtocaConstants { return; } newControlSequence(); - switch (orientation) { - case 90: - writeByte(0x2D); - writeByte(0x00); - writeByte(0x5A); - writeByte(0x00); - break; - case 180: - writeByte(0x5A); - writeByte(0x00); - writeByte(0x87); - writeByte(0x00); - break; - case 270: - writeByte(0x87); - writeByte(0x00); - writeByte(0x00); - writeByte(0x00); - break; - default: - writeByte(0x00); - writeByte(0x00); - writeByte(0x2D); - writeByte(0x00); - break; - } + AxisOrientation.getRightHandedAxisOrientationFor(orientation).writeTo(baout); commit(chained(STO)); this.currentOrientation = orientation; currentX = -1; @@ -317,55 +281,30 @@ public abstract class PtocaBuilder implements PtocaConstants { newControlSequence(); if (col.getColorSpace().getType() == ColorSpace.TYPE_CMYK) { - writeByte(0x00); // Reserved; must be zero - writeByte(0x04); // Color space - 0x04 = CMYK - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(8); // Number of bits in component 1 - writeByte(8); // Number of bits in component 2 - writeByte(8); // Number of bits in component 3 - writeByte(8); // Number of bits in component 4 + // Color space - 0x04 = CMYK, all else are reserved and must be zero + writeBytes(0x00, 0x04, 0x00, 0x00, 0x00, 0x00); + writeBytes(8, 8, 8, 8); // Number of bits in component 1, 2, 3 & 4 respectively float[] comps = col.getColorComponents(null); assert comps.length == 4; for (int i = 0; i < 4; i++) { int component = Math.round(comps[i] * 255); - writeByte(component); + writeBytes(component); } } else if (cs instanceof CIELabColorSpace) { - writeByte(0x00); // Reserved; must be zero - writeByte(0x08); // Color space - 0x08 = CIELAB - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(8); // Number of bits in component 1 - writeByte(8); // Number of bits in component 2 - writeByte(8); // Number of bits in component 3 - writeByte(0); // Number of bits in component 4 + // Color space - 0x08 = CIELAB, all else are reserved and must be zero + writeBytes(0x00, 0x08, 0x00, 0x00, 0x00, 0x00); + writeBytes(8, 8, 8, 0); // Number of bits in component 1,2,3 & 4 //Sadly, 16 bit components don't seem to work float[] colorComponents = col.getColorComponents(null); int l = Math.round(colorComponents[0] * 255f); int a = Math.round(colorComponents[1] * 255f) - 128; int b = Math.round(colorComponents[2] * 255f) - 128; - writeByte(l); // L* - writeByte(a); // a* - writeByte(b); // b* + writeBytes(l, a, b); // l*, a* and b* } else { - writeByte(0x00); // Reserved; must be zero - writeByte(0x01); // Color space - 0x01 = RGB - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(0x00); // Reserved; must be zero - writeByte(8); // Number of bits in component 1 - writeByte(8); // Number of bits in component 2 - writeByte(8); // Number of bits in component 3 - writeByte(0); // Number of bits in component 4 - writeByte(col.getRed()); // Red intensity - writeByte(col.getGreen()); // Green intensity - writeByte(col.getBlue()); // Blue intensity + // Color space - 0x01 = RGB, all else are reserved and must be zero + writeBytes(0x00, 0x01, 0x00, 0x00, 0x00, 0x00); + writeBytes(8, 8, 8, 0); // Number of bits in component 1, 2, 3 & 4 respectively + writeBytes(col.getRed(), col.getGreen(), col.getBlue()); // RGB intensity } commit(chained(SEC)); this.currentColor = col; @@ -407,7 +346,7 @@ public abstract class PtocaBuilder implements PtocaConstants { assert incr >= Short.MIN_VALUE && incr <= Short.MAX_VALUE; newControlSequence(); writeShort(Math.abs(incr)); //Increment - writeByte(incr >= 0 ? 0 : 1); // Direction + writeBytes(incr >= 0 ? 0 : 1); // Direction commit(chained(SIA)); this.currentInterCharacterAdjustment = incr; diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaConstants.java b/src/java/org/apache/fop/afp/ptoca/PtocaConstants.java index 2e692af2c..c53b97fd0 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaConstants.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaConstants.java @@ -64,6 +64,6 @@ public interface PtocaConstants { byte NOP = (byte)0xF8; /** Maximum size of transparent data chunks */ - int TRANSPARENT_DATA_MAX_SIZE = 253; + int TRANSPARENT_DATA_MAX_SIZE = 253; // max length = 255 (minus the ControlSequence length) } diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java b/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java index 9b6d97dec..5f29bef96 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java @@ -22,8 +22,8 @@ package org.apache.fop.afp.ptoca; import java.io.IOException; /** - * Producer interface that is passed to a {@link PresentationTextObject} to produce PTOCA control - * sequences using a {@link PtocaBuilder}. + * Producer interface that is passed to a {@link org.apache.fop.afp.modca.PresentationTextObject} + * to produce PTOCA control sequences using a {@link PtocaBuilder}. */ public interface PtocaProducer { diff --git a/src/java/org/apache/fop/afp/ptoca/TextDataInfoProducer.java b/src/java/org/apache/fop/afp/ptoca/TextDataInfoProducer.java index f7ed5a85c..4af21b12b 100644 --- a/src/java/org/apache/fop/afp/ptoca/TextDataInfoProducer.java +++ b/src/java/org/apache/fop/afp/ptoca/TextDataInfoProducer.java @@ -56,7 +56,7 @@ public class TextDataInfoProducer implements PtocaProducer, PtocaConstants { // Add transparent data String textString = textDataInfo.getString(); String encoding = textDataInfo.getEncoding(); - builder.addTransparentData(CharactersetEncoder.encodeSBCS(textString, encoding, false)); + builder.addTransparentData(CharactersetEncoder.encodeSBCS(textString, encoding)); } } diff --git a/src/java/org/apache/fop/afp/ptoca/TransparentDataControlSequence.java b/src/java/org/apache/fop/afp/ptoca/TransparentDataControlSequence.java new file mode 100644 index 000000000..4b4276880 --- /dev/null +++ b/src/java/org/apache/fop/afp/ptoca/TransparentDataControlSequence.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.afp.ptoca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; +import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData; + +import static org.apache.fop.afp.ptoca.PtocaConstants.TRANSPARENT_DATA_MAX_SIZE; + +/** + * This object represents a series of PTOCA TransparentData (TRN) control sequences. This implements + * {@link Iterable} to enable iteration through the TRNs. + */ +final class TransparentDataControlSequence implements Iterable<TransparentData> { + + private static final int MAX_SBCS_TRN_SIZE = TRANSPARENT_DATA_MAX_SIZE; + // The maximum size of a TRN must be an EVEN number so that we're splitting TRNs on character + // boundaries rather than in the middle of a double-byte character + private static final int MAX_DBCS_TRN_SIZE = MAX_SBCS_TRN_SIZE - 1; + + static final class TransparentData { + private final int offset; + private final int length; + private final EncodedChars encodedChars; + + private TransparentData(int offset, int length, EncodedChars encChars) { + this.offset = offset; + this.length = length; + this.encodedChars = encChars; + } + + void writeTo(OutputStream outStream) throws IOException { + encodedChars.writeTo(outStream, offset, length); + } + } + + private final List<TransparentData> trns; + + /** + * Converts an encoded String wrapped in an {@link EncodedChars} into a series of + * {@link TransparentData} control sequences. + * + * @param encChars the encoded characters to convert to TRNs + */ + public TransparentDataControlSequence(EncodedChars encChars) { + int maxTrnLength = encChars.isDBCS() ? MAX_DBCS_TRN_SIZE : MAX_SBCS_TRN_SIZE; + int numTransData = encChars.getLength() / maxTrnLength; + int currIndex = 0; + List<TransparentData> trns = new ArrayList<TransparentData>(); + for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) { + trns.add(new TransparentData(currIndex, maxTrnLength, encChars)); + currIndex += maxTrnLength; + } + int left = encChars.getLength() - currIndex; + trns.add(new TransparentData(currIndex, left, encChars)); + this.trns = Collections.unmodifiableList(trns); + } + + /** + * The {@link Iterator} for retrieving the series of TRN control sequences. + */ + public Iterator<TransparentData> iterator() { + return trns.iterator(); + } +} diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index bfcdb163e..7d5752d6d 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -357,8 +357,11 @@ public class CommandLineOptions { } else if (args[i].equals("-a")) { this.renderingOptions.put(Accessibility.ACCESSIBILITY, Boolean.TRUE); } else if (args[i].equals("-v")) { - /* Currently just print the version */ + /* verbose mode although users may expect version; currently just print the version */ printVersion(); + if (args.length == 1) { + return false; + } } else if (args[i].equals("-param")) { if (i + 2 < args.length) { String name = args[++i]; @@ -588,7 +591,7 @@ public class CommandLineOptions { private int parsePrintOutputOption(String[] args, int i) throws FOPException { setOutputMode(MimeConstants.MIME_FOP_PRINT); - if ((i + 1 <= args.length) + if ((i + 1 < args.length) && (args[i + 1].charAt(0) != '-')) { String arg = args[i + 1]; String[] parts = arg.split(","); diff --git a/src/java/org/apache/fop/fo/expr/AbsFunction.java b/src/java/org/apache/fop/fo/expr/AbsFunction.java index 0e8355faa..9c266da76 100644 --- a/src/java/org/apache/fop/fo/expr/AbsFunction.java +++ b/src/java/org/apache/fop/fo/expr/AbsFunction.java @@ -27,22 +27,13 @@ import org.apache.fop.fo.properties.Property; */ public class AbsFunction extends FunctionBase { - /** - * @return 1 (the number of arguments required for the abs function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 1; } - /** - * @param args array of arguments to be evaluated, the first of which - * should be a numeric value - * @param propInfo the PropertyInfo object to be evaluated - * @return the absolute value of the input - * @throws PropertyException for non-numeric input - */ - public Property eval(Property[] args, - PropertyInfo propInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo propInfo) throws PropertyException { Numeric num = args[0].getNumeric(); if (num == null) { throw new PropertyException("Non numeric operand to abs function"); diff --git a/src/java/org/apache/fop/fo/expr/BodyStartFunction.java b/src/java/org/apache/fop/fo/expr/BodyStartFunction.java index 5307e75b0..5177f8a51 100644 --- a/src/java/org/apache/fop/fo/expr/BodyStartFunction.java +++ b/src/java/org/apache/fop/fo/expr/BodyStartFunction.java @@ -31,22 +31,13 @@ import org.apache.fop.fo.properties.Property; */ public class BodyStartFunction extends FunctionBase { - /** - * @return 0 (there are no arguments for body-start) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 0; } - /** - * @param args array of arguments (none are used, but this is required by - * the Function interface) - * @param pInfo PropertyInfo object to be evaluated - * @return numeric object containing the calculated body-start value - * @throws PropertyException if called from outside of an fo:list-item - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Numeric distance = pInfo.getPropertyList() .get(Constants.PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS).getNumeric(); diff --git a/src/java/org/apache/fop/fo/expr/CIELabColorFunction.java b/src/java/org/apache/fop/fo/expr/CIELabColorFunction.java index d027a9571..9783f5384 100644 --- a/src/java/org/apache/fop/fo/expr/CIELabColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/CIELabColorFunction.java @@ -30,29 +30,25 @@ import org.apache.fop.fo.properties.Property; */ class CIELabColorFunction extends FunctionBase { - /** - * cie-lab-color() takes 2 times 3 arguments. - * {@inheritDoc} - */ - public int nbArgs() { - return 2 * 3; + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 6; } + @Override + /** {@inheritDoc} */ public PercentBase getPercentBase() { return new CIELabPercentBase(); } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { float red = args[0].getNumber().floatValue(); float green = args[1].getNumber().floatValue(); float blue = args[2].getNumber().floatValue(); /* Verify sRGB replacement arguments */ - if ((red < 0 || red > 255) - || (green < 0 || green > 255) - || (blue < 0 || blue > 255)) { + if ((red < 0 || red > 255) || (green < 0 || green > 255) || (blue < 0 || blue > 255)) { throw new PropertyException("sRGB color values out of range. " + "Arguments to cie-lab-color() must be [0..255] or [0%..100%]"); } diff --git a/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java b/src/java/org/apache/fop/fo/expr/CMYKColorFunction.java index fe86860f4..1ca8cfaa0 100644 --- a/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java +++ b/src/java/org/apache/fop/fo/expr/CMYKColorFunction.java @@ -25,19 +25,15 @@ import org.apache.fop.fo.properties.Property; /** * Implements the cmyk() function. */ -class CMYKcolorFunction extends FunctionBase { +class CMYKColorFunction extends FunctionBase { - /** - * cmyk takes four arguments. - * {@inheritDoc} - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 4; } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { StringBuffer sb = new StringBuffer(); sb.append("cmyk(" + args[0] + "," + args[1] + "," + args[2] + "," + args[3] + ")"); FOUserAgent ua = (pInfo == null) diff --git a/src/java/org/apache/fop/fo/expr/CeilingFunction.java b/src/java/org/apache/fop/fo/expr/CeilingFunction.java index 875c88751..9c69cd1bc 100644 --- a/src/java/org/apache/fop/fo/expr/CeilingFunction.java +++ b/src/java/org/apache/fop/fo/expr/CeilingFunction.java @@ -24,12 +24,13 @@ import org.apache.fop.fo.properties.Property; class CeilingFunction extends FunctionBase { - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 1; } - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Number dbl = args[0].getNumber(); if (dbl == null) { throw new PropertyException("Non number operand to ceiling function"); diff --git a/src/java/org/apache/fop/fo/expr/FloorFunction.java b/src/java/org/apache/fop/fo/expr/FloorFunction.java index 043473140..501b8d59d 100644 --- a/src/java/org/apache/fop/fo/expr/FloorFunction.java +++ b/src/java/org/apache/fop/fo/expr/FloorFunction.java @@ -25,12 +25,13 @@ import org.apache.fop.fo.properties.Property; class FloorFunction extends FunctionBase { - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 1; } - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Number dbl = args[0].getNumber(); if (dbl == null) { throw new PropertyException("Non number operand to floor function"); diff --git a/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java b/src/java/org/apache/fop/fo/expr/FromNearestSpecifiedValueFunction.java index 3e0dda565..7eb463fb6 100644 --- a/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java +++ b/src/java/org/apache/fop/fo/expr/FromNearestSpecifiedValueFunction.java @@ -26,32 +26,31 @@ import org.apache.fop.fo.properties.Property; * Class modelling the from-nearest-specified-value function. See Sec. 5.10.4 * of the XSL-FO standard. */ -public class NearestSpecPropFunction extends FunctionBase { +public class FromNearestSpecifiedValueFunction extends FunctionBase { - /** - * @return 1 (maximum number of arguments for from-nearest-specified-value - * function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 0; + } + + @Override + /** {@inheritDoc} */ + public int getOptionalArgsCount() { return 1; } - /** - * @return true (allow padding of arglist with property name) - */ - public boolean padArgsWithPropertyName() { - return true; + @Override + /** {@inheritDoc} */ + public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { + if ( index == 0 ) { + return getPropertyName ( pi ); + } else { + return super.getOptionalArgDefault ( index, pi ); + } } - /** - * - * @param args array of arguments for the function - * @param pInfo PropertyInfo for the function - * @return Property containing the nearest-specified-value - * @throws PropertyException for invalid arguments to the function - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { String propName = args[0].getString(); if (propName == null) { throw new PropertyException( diff --git a/src/java/org/apache/fop/fo/expr/FromParentFunction.java b/src/java/org/apache/fop/fo/expr/FromParentFunction.java index b1e9d689d..e24074e9d 100644 --- a/src/java/org/apache/fop/fo/expr/FromParentFunction.java +++ b/src/java/org/apache/fop/fo/expr/FromParentFunction.java @@ -29,29 +29,29 @@ import org.apache.fop.fo.properties.Property; */ public class FromParentFunction extends FunctionBase { - /** - * @return 1 (maximum arguments for the from-parent function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 0; + } + + @Override + /** {@inheritDoc} */ + public int getOptionalArgsCount() { return 1; } - /** - * @return true (allow padding of arglist with property name) - */ - public boolean padArgsWithPropertyName() { - return true; + @Override + /** {@inheritDoc} */ + public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { + if ( index == 0 ) { + return getPropertyName ( pi ); + } else { + return super.getOptionalArgDefault ( index, pi ); + } } - /** - * @param args array of arguments, which should either be empty, or the - * first of which should contain an NCName corresponding to property name - * @param pInfo PropertyInfo object to be evaluated - * @return property containing the computed value - * @throws PropertyException if the arguments are incorrect - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { String propName = args[0].getString(); if (propName == null) { throw new PropertyException("Incorrect parameter to from-parent function"); diff --git a/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java b/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java index 627459cf1..48ea4e152 100644 --- a/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java +++ b/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java @@ -37,32 +37,29 @@ import org.apache.fop.fo.properties.Property; */ public class FromTableColumnFunction extends FunctionBase { - /** - * @return 1 (maximum arguments for the from-table-column function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 0; + } + + @Override + /** {@inheritDoc} */ + public int getOptionalArgsCount() { return 1; } - /** - * @return true (allow padding of arglist with property name) - */ - public boolean padArgsWithPropertyName() { - return true; + @Override + /** {@inheritDoc} */ + public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { + if ( index == 0 ) { + return getPropertyName ( pi ); + } else { + return super.getOptionalArgDefault ( index, pi ); + } } - /** - * - * @param args array of arguments, which should either be empty, or the - * first of which should contain an NCName corresponding to a property name - * @param pInfo PropertyInfo object to be evaluated - * @return the Property corresponding to the property name specified, or, if - * none, for the property for which the expression is being evaluated - * @throws PropertyException for incorrect arguments, and (for now) in all - * cases, because this function is not implemented - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { FObj fo = pInfo.getPropertyList().getFObj(); diff --git a/src/java/org/apache/fop/fo/expr/Function.java b/src/java/org/apache/fop/fo/expr/Function.java index 82ec1b7fd..f558543c0 100644 --- a/src/java/org/apache/fop/fo/expr/Function.java +++ b/src/java/org/apache/fop/fo/expr/Function.java @@ -28,11 +28,34 @@ import org.apache.fop.fo.properties.Property; public interface Function { /** - * @return the number of arguments that must be passed to this function. For - * example, if the function should determine the minimum of two numbers, it - * must be passed two arguments, one for each of the two values. + * @return the number of required (non-optional) arguments that must be specified + * in the argument list */ - int nbArgs(); + int getRequiredArgsCount(); + + /** + * @return the number of non-required (optional) arguments that may be specified + * in the argument list, which, if specified, must follow the required arguments + */ + int getOptionalArgsCount(); + + /** + * @param index of optional argument + * @param pi property information instance that applies to property being evaluated + * @return the default property value for the optional argument at INDEX, where + * INDEX is with respect to optional arguments; i.e., the first optional argument + * position is index 0; if no default for a given index, then null is returned + * @throws PropertyException if index is greater than or equal to optional args count + */ + Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException; + + /** + * Determine if function allows variable arguments. If it does, then they must appear + * after required and optional arguments, and all optional arguments must be specified. + * @return true if function permits additional variable number of arguments after + * required and (completely specified) optional arguments + */ + boolean hasVariableArgs(); /** * @return the basis for percentage calculations @@ -42,16 +65,10 @@ public interface Function { /** * Evaluate the function * @param args an array of Properties that should be evaluated - * @param propInfo the PropertyInfo + * @param pi property information instance that applies to property being evaluated * @return the Property satisfying the function * @throws PropertyException for problems when evaluating the function */ - Property eval(Property[] args, - PropertyInfo propInfo) throws PropertyException; + Property eval(Property[] args, PropertyInfo pi) throws PropertyException; - /** - * @return if it is allowed to fill up the property list with - * the property name if only one arg is missing. - */ - boolean padArgsWithPropertyName(); } diff --git a/src/java/org/apache/fop/fo/expr/FunctionBase.java b/src/java/org/apache/fop/fo/expr/FunctionBase.java index b5040c635..6e0fd6702 100644 --- a/src/java/org/apache/fop/fo/expr/FunctionBase.java +++ b/src/java/org/apache/fop/fo/expr/FunctionBase.java @@ -20,23 +20,45 @@ package org.apache.fop.fo.expr; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.fo.properties.Property; +import org.apache.fop.fo.properties.StringProperty; /** * Abstract Base class for XSL-FO functions */ public abstract class FunctionBase implements Function { - /** - * @return null (by default, functions have no percent-based arguments) - */ + /** {@inheritDoc} */ + public int getOptionalArgsCount() { + return 0; + } + + /** {@inheritDoc} */ + public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { + if ( index >= getOptionalArgsCount() ) { + PropertyException e = new PropertyException ( new IndexOutOfBoundsException ( "illegal optional argument index" ) ); + e.setPropertyInfo ( pi ); + throw e; + } else { + return null; + } + } + + /** {@inheritDoc} */ + public boolean hasVariableArgs() { + return false; + } + + /** {@inheritDoc} */ public PercentBase getPercentBase() { return null; } /** - * @return false (by default don't pad arglist with property-name) + * @param pi property information instance that applies to property being evaluated + * @return string property whose value is name of property being evaluated */ - public boolean padArgsWithPropertyName() { - return false; + protected final Property getPropertyName ( PropertyInfo pi ) { + return StringProperty.getInstance ( pi.getPropertyMaker().getName() ); } } diff --git a/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java b/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java index 94c4fdf22..6e982bd31 100644 --- a/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java +++ b/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java @@ -28,30 +28,29 @@ import org.apache.fop.fo.properties.Property; */ public class InheritedPropFunction extends FunctionBase { - /** - * @return 1 (maximum number of arguments for the inherited-property-value - * function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 0; + } + + @Override + /** {@inheritDoc} */ + public int getOptionalArgsCount() { return 1; } - /** - * @return true (allow padding of arglist with property name) - */ - public boolean padArgsWithPropertyName() { - return true; + @Override + /** {@inheritDoc} */ + public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { + if ( index == 0 ) { + return getPropertyName ( pi ); + } else { + return super.getOptionalArgDefault ( index, pi ); + } } - /** - * - * @param args arguments to be evaluated - * @param pInfo PropertyInfo object to be evaluated - * @return Property satisfying the inherited-property-value - * @throws PropertyException for invalid parameter - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { String propName = args[0].getString(); if (propName == null) { throw new PropertyException("Incorrect parameter to inherited-property-value function"); diff --git a/src/java/org/apache/fop/fo/expr/LabelEndFunction.java b/src/java/org/apache/fop/fo/expr/LabelEndFunction.java index 5deb3ae30..57facc058 100644 --- a/src/java/org/apache/fop/fo/expr/LabelEndFunction.java +++ b/src/java/org/apache/fop/fo/expr/LabelEndFunction.java @@ -34,23 +34,13 @@ import org.apache.fop.fo.properties.Property; */ public class LabelEndFunction extends FunctionBase { - /** - * @return 0 (the number of arguments required for the label-end function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 0; } - /** - * - * @param args array of arguments for the function (none are needed, but - * required for the Function interface) - * @param pInfo PropertyInfo object for the function - * @return the calculated label-end value for the list - * @throws PropertyException if called from outside of an fo:list-item - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Length distance = pInfo.getPropertyList().get( Constants.PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS).getLength(); diff --git a/src/java/org/apache/fop/fo/expr/MaxFunction.java b/src/java/org/apache/fop/fo/expr/MaxFunction.java index fd2fee0b1..442197de6 100644 --- a/src/java/org/apache/fop/fo/expr/MaxFunction.java +++ b/src/java/org/apache/fop/fo/expr/MaxFunction.java @@ -28,22 +28,13 @@ import org.apache.fop.fo.properties.Property; */ public class MaxFunction extends FunctionBase { - /** - * @return 2 (the number of arguments required for the max function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 2; } - /** - * Handle "numerics" if no proportional/percent parts - * @param args array of arguments to be processed - * @param pInfo PropertyInfo to be processed - * @return the maximum of the two args elements passed - * @throws PropertyException for invalid operands - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Numeric n1 = args[0].getNumeric(); Numeric n2 = args[1].getNumeric(); if (n1 == null || n2 == null) { diff --git a/src/java/org/apache/fop/fo/expr/MinFunction.java b/src/java/org/apache/fop/fo/expr/MinFunction.java index 979d16b27..19a06ada1 100644 --- a/src/java/org/apache/fop/fo/expr/MinFunction.java +++ b/src/java/org/apache/fop/fo/expr/MinFunction.java @@ -28,22 +28,13 @@ import org.apache.fop.fo.properties.Property; */ public class MinFunction extends FunctionBase { - /** - * @return 2 (the number of arguments required for the min function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 2; } - /** - * Handle "numerics" if no proportional/percent parts - * @param args array of arguments to be processed - * @param pInfo PropertyInfo to be processed - * @return the minimum of the two args elements passed - * @throws PropertyException for invalid operands - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Numeric n1 = args[0].getNumeric(); Numeric n2 = args[1].getNumeric(); if (n1 == null || n2 == null) { diff --git a/src/java/org/apache/fop/fo/expr/PropertyParser.java b/src/java/org/apache/fop/fo/expr/PropertyParser.java index 9ef45befe..f3e3e4a50 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyParser.java +++ b/src/java/org/apache/fop/fo/expr/PropertyParser.java @@ -20,7 +20,6 @@ package org.apache.fop.fo.expr; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import org.apache.xmlgraphics.util.UnitConv; @@ -59,19 +58,16 @@ public final class PropertyParser extends PropertyTokenizer { FUNCTION_TABLE.put("rgb", new RGBColorFunction()); FUNCTION_TABLE.put("system-color", new SystemColorFunction()); FUNCTION_TABLE.put("from-table-column", new FromTableColumnFunction()); - FUNCTION_TABLE.put("inherited-property-value", - new InheritedPropFunction()); + FUNCTION_TABLE.put("inherited-property-value", new InheritedPropFunction()); + FUNCTION_TABLE.put("from-nearest-specified-value", new FromNearestSpecifiedValueFunction()); FUNCTION_TABLE.put("from-parent", new FromParentFunction()); - FUNCTION_TABLE.put("from-nearest-specified-value", - new NearestSpecPropFunction()); - FUNCTION_TABLE.put("proportional-column-width", - new PPColWidthFunction()); + FUNCTION_TABLE.put("proportional-column-width", new ProportionalColumnWidthFunction()); FUNCTION_TABLE.put("label-end", new LabelEndFunction()); FUNCTION_TABLE.put("body-start", new BodyStartFunction()); - FUNCTION_TABLE.put("rgb-icc", new ICCColorFunction()); - FUNCTION_TABLE.put("rgb-named-color", new NamedColorFunction()); //since XSL-FO 2.0 + FUNCTION_TABLE.put("rgb-icc", new RGBICCColorFunction()); + FUNCTION_TABLE.put("rgb-named-color", new RGBNamedColorFunction()); //since XSL-FO 2.0 FUNCTION_TABLE.put("cie-lab-color", new CIELabColorFunction()); //since XSL-FO 2.0 - FUNCTION_TABLE.put("cmyk", new CMYKcolorFunction()); //non-standard!!! + FUNCTION_TABLE.put("cmyk", new CMYKColorFunction()); //non-standard!!! /** * * NOT YET IMPLEMENTED!!! @@ -341,12 +337,7 @@ public final class PropertyParser extends PropertyTokenizer { next(); // Push new function (for function context: getPercentBase()) propInfo.pushFunction(function); - if (function.nbArgs() < 0) { - // Negative nbArgs --> function with variable number of arguments - prop = function.eval(parseVarArgs(function), propInfo); - } else { - prop = function.eval(parseArgs(function), propInfo); - } + prop = function.eval(parseArgs(function), propInfo); propInfo.popFunction(); return prop; @@ -362,27 +353,27 @@ public final class PropertyParser extends PropertyTokenizer { * Parse a comma separated list of function arguments. Each argument * may itself be an expression. This method consumes the closing right * parenthesis of the argument list. - * @param function The function object for which the arguments are - * collected. - * @return An array of Property objects representing the arguments - * found. + * @param function The function object for which the arguments are collected. + * @return An array of Property objects representing the arguments found. * @throws PropertyException If the number of arguments found isn't equal - * to the number expected. + * to the number expected or if another argument parsing error occurs. */ Property[] parseArgs(Function function) throws PropertyException { - int nbArgs = function.nbArgs(); - Property[] args = new Property[nbArgs]; - Property prop; - int i = 0; + int numReq = function.getRequiredArgsCount(); // # required args + int numOpt = function.getOptionalArgsCount(); // # optional args + boolean hasVar = function.hasVariableArgs(); // has variable args + List<Property> args = new java.util.ArrayList<Property>(numReq + numOpt); if (currentToken == TOK_RPAR) { // No args: func() next(); } else { while (true) { - - prop = parseAdditiveExpr(); - if (i < nbArgs) { - args[i++] = prop; + Property p = parseAdditiveExpr(); + int i = args.size(); + if ( ( i < numReq ) || ( ( i - numReq ) < numOpt ) || hasVar ) { + args.add ( p ); + } else { + throw new PropertyException ( "Unexpected function argument at index " + i ); } // ignore extra args if (currentToken != TOK_COMMA) { @@ -392,66 +383,19 @@ public final class PropertyParser extends PropertyTokenizer { } expectRpar(); } - if (i == nbArgs - 1 && function.padArgsWithPropertyName()) { - args[i++] = StringProperty.getInstance( - propInfo.getPropertyMaker().getName()); - } - if (nbArgs != i) { - throw new PropertyException("Expected " + nbArgs - + ", but got " + i + " args for function"); - } - return args; - } - - /** - * - * Parse a comma separated list of function arguments. Each argument - * may itself be an expression. This method consumes the closing right - * parenthesis of the argument list. - * - * The method differs from parseArgs in that it accepts a variable - * number of arguments. - * - * @param function The function object for which the arguments are - * collected. - * @return An array of Property objects representing the arguments - * found. - * @throws PropertyException If the number of arguments found isn't equal - * to the number expected. - * - * TODO Merge this with parseArgs? - */ - Property[] parseVarArgs(Function function) throws PropertyException { - // For variable argument functions the minimum number of arguments is returned as a - // negative integer from the nbArgs method - int nbArgs = -function.nbArgs(); - List args = new LinkedList(); - Property prop; - if (currentToken == TOK_RPAR) { - // No args: func() - next(); + int numArgs = args.size(); + if ( numArgs < numReq ) { + throw new PropertyException("Expected " + numReq + " required arguments, but only " + numArgs + " specified"); } else { - while (true) { - prop = parseAdditiveExpr(); - args.add(prop); - // ignore extra args - if (currentToken != TOK_COMMA) { - break; + for ( int i = 0; i < numOpt; i++ ) { + if ( args.size() < ( numReq + i + 1 ) ) { + args.add ( function.getOptionalArgDefault ( i, propInfo ) ); } - next(); } - expectRpar(); - } - if (nbArgs > args.size()) { - throw new PropertyException("Expected at least " + nbArgs - + ", but got " + args.size() + " args for function"); } - Property[] propArray = new Property[args.size()]; - args.toArray(propArray); - return propArray; + return (Property[]) args.toArray ( new Property [ args.size() ] ); } - /** * Evaluate an addition operation. If either of the arguments is null, * this means that it wasn't convertible to a Numeric value. diff --git a/src/java/org/apache/fop/fo/expr/PropertyTokenizer.java b/src/java/org/apache/fop/fo/expr/PropertyTokenizer.java index e07f3c433..3c9c81d27 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyTokenizer.java +++ b/src/java/org/apache/fop/fo/expr/PropertyTokenizer.java @@ -67,7 +67,7 @@ class PropertyTokenizer { } /** - * Return the next token in the expression string. + * Parse the next token in the expression string. * This sets the following package visible variables: * currentToken An enumerated value identifying the recognized token * currentTokenValue A String containing the token contents diff --git a/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java b/src/java/org/apache/fop/fo/expr/ProportionalColumnWidthFunction.java index 5defda0fe..8f9df5d5f 100644 --- a/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java +++ b/src/java/org/apache/fop/fo/expr/ProportionalColumnWidthFunction.java @@ -30,34 +30,21 @@ import org.apache.fop.fo.properties.TableColLength; * Class modelling the proportional-column-width function. See Sec. 5.10.4 of * the XSL-FO standard. */ -public class PPColWidthFunction extends FunctionBase { +public class ProportionalColumnWidthFunction extends FunctionBase { - /** - * @return 1 (the number of arguments for the proportional-column-width - * function) - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 1; } - /** - * @return the {@link PercentBase} for the proportional-column-width() - * function - */ + @Override + /** {@inheritDoc} */ public PercentBase getPercentBase() { - return new PPColWidthPercentBase(); + return new ProportionalColumnWidthPercentBase(); } - /** - * - * @param args array of arguments for this function - * @param pInfo PropertyInfo for this function - * @return numeric Property containing the units of proportional measure - * for this column - * @throws PropertyException for non-numeric operand, or if the parent - * element is not a table-column - */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Number d = args[0].getNumber(); if (d == null) { throw new PropertyException("Non numeric operand to " @@ -78,7 +65,7 @@ public class PPColWidthFunction extends FunctionBase { return new TableColLength(d.doubleValue(), pInfo.getFO()); } - private static class PPColWidthPercentBase implements PercentBase { + private static class ProportionalColumnWidthPercentBase implements PercentBase { /** {@inheritDoc} */ public int getBaseLength(PercentBaseContext context) throws PropertyException { diff --git a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java index 868b9a8bf..9f8a7f600 100644 --- a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java @@ -30,22 +30,18 @@ import org.apache.fop.fo.properties.Property; class RGBColorFunction extends FunctionBase { /** {@inheritDoc} */ - public int nbArgs() { + public int getRequiredArgsCount() { return 3; } - /** - * @return an object which implements the PercentBase interface. - * Percents in arguments to this function are interpreted relative - * to 255. - */ + @Override + /** {@inheritDoc} */ public PercentBase getPercentBase() { return new RGBPercentBase(); } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { return ColorProperty.getInstance(pInfo.getUserAgent(), "rgb(" + args[0] + "," + args[1] + "," + args[2] + ")"); diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBICCColorFunction.java index 756de1b20..57cf6a949 100644 --- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/RGBICCColorFunction.java @@ -29,26 +29,27 @@ import org.apache.fop.util.ColorUtil; /** * Implements the rgb-icc() function. */ -class ICCColorFunction extends FunctionBase { +class RGBICCColorFunction extends FunctionBase { - /** - * rgb-icc takes a variable number of arguments. - * At least 4 should be passed - returns -4 - * {@inheritDoc} - */ - public int nbArgs() { - return -4; + /** {@inheritDoc} */ + public int getRequiredArgsCount() { + return 4; } + @Override /** {@inheritDoc} */ + public boolean hasVariableArgs() { + return true; + } + @Override + /** {@inheritDoc} */ public PercentBase getPercentBase() { return new ICCPercentBase(); } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { // Map color profile NCNAME to src from declarations/color-profile element String colorProfileName = args[3].getString(); Declarations decls = (pInfo.getFO() != null @@ -86,9 +87,7 @@ class ICCColorFunction extends FunctionBase { green = args[1].getNumber().floatValue(); blue = args[2].getNumber().floatValue(); /* Verify rgb replacement arguments */ - if ((red < 0 || red > 255) - || (green < 0 || green > 255) - || (blue < 0 || blue > 255)) { + if ((red < 0 || red > 255) || (green < 0 || green > 255) || (blue < 0 || blue > 255)) { throw new PropertyException("Color values out of range. " + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); } diff --git a/src/java/org/apache/fop/fo/expr/NamedColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBNamedColorFunction.java index f2ff19ef1..076900d68 100644 --- a/src/java/org/apache/fop/fo/expr/NamedColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/RGBNamedColorFunction.java @@ -29,25 +29,21 @@ import org.apache.fop.fo.properties.Property; * Implements the rgb-named-color() function. * @since XSL-FO 2.0 */ -class NamedColorFunction extends FunctionBase { +class RGBNamedColorFunction extends FunctionBase { - /** - * rgb-named-color() takes a 5 arguments. - * {@inheritDoc} - */ - public int nbArgs() { + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 5; } /** {@inheritDoc} */ @Override public PercentBase getPercentBase() { - return new NamedPercentBase(); + return new RGBNamedPercentBase(); } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { // Map color profile NCNAME to src from declarations/color-profile element String colorProfileName = args[3].getString(); String colorName = args[4].getString(); @@ -96,7 +92,7 @@ class NamedColorFunction extends FunctionBase { return ColorProperty.getInstance(pInfo.getUserAgent(), sb.toString()); } - private static final class NamedPercentBase implements PercentBase { + private static final class RGBNamedPercentBase implements PercentBase { /** {@inheritDoc} */ public int getBaseLength(PercentBaseContext context) throws PropertyException { diff --git a/src/java/org/apache/fop/fo/expr/RoundFunction.java b/src/java/org/apache/fop/fo/expr/RoundFunction.java index a29c33e5b..201039b5a 100644 --- a/src/java/org/apache/fop/fo/expr/RoundFunction.java +++ b/src/java/org/apache/fop/fo/expr/RoundFunction.java @@ -24,12 +24,14 @@ import org.apache.fop.fo.properties.NumberProperty; import org.apache.fop.fo.properties.Property; class RoundFunction extends FunctionBase { - public int nbArgs() { + + /** {@inheritDoc} */ + public int getRequiredArgsCount() { return 1; } - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + /** {@inheritDoc} */ + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { Number dbl = args[0].getNumber(); if (dbl == null) { throw new PropertyException("Non number operand to round function"); diff --git a/src/java/org/apache/fop/fo/expr/SystemColorFunction.java b/src/java/org/apache/fop/fo/expr/SystemColorFunction.java index eeb1870f7..8ec88e983 100644 --- a/src/java/org/apache/fop/fo/expr/SystemColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/SystemColorFunction.java @@ -29,13 +29,12 @@ import org.apache.fop.fo.properties.Property; class SystemColorFunction extends FunctionBase { /** {@inheritDoc} */ - public int nbArgs() { + public int getRequiredArgsCount() { return 1; } /** {@inheritDoc} */ - public Property eval(Property[] args, - PropertyInfo pInfo) throws PropertyException { + public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { FOUserAgent ua = (pInfo == null) ? null : (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent()); diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java index b5cd56d47..e69439276 100644 --- a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java +++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java @@ -60,6 +60,7 @@ public class ConditionalBorder { private ConditionalBorder(BorderSpecification normal, BorderSpecification leadingTrailing, BorderSpecification rest, CollapsingBorderModel collapsingBorderModel) { + assert collapsingBorderModel != null; this.normal = normal; this.leadingTrailing = leadingTrailing; this.rest = rest; @@ -74,14 +75,10 @@ public class ConditionalBorder { */ ConditionalBorder(BorderSpecification borderSpecification, CollapsingBorderModel collapsingBorderModel) { - normal = borderSpecification; - leadingTrailing = normal; - if (borderSpecification.getBorderInfo().getWidth().isDiscard()) { - rest = BorderSpecification.getDefaultBorder(); - } else { - rest = leadingTrailing; - } - this.collapsingBorderModel = collapsingBorderModel; + this ( borderSpecification, borderSpecification, + borderSpecification.getBorderInfo().getWidth().isDiscard() + ? BorderSpecification.getDefaultBorder() : borderSpecification, + collapsingBorderModel ); } /** diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index b14326af5..a574723b1 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -20,11 +20,14 @@ package org.apache.fop.fo.flow.table; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Stack; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.ValidationPercentBaseContext; import org.apache.fop.fo.FONode; @@ -40,12 +43,16 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthPairProperty; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.TableColLength; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingMode; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; /** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table"> * <code>fo:table</code></a> object. */ -public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet, +public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet, WritingModeTraitsGetter, CommonAccessibilityHolder { // The value of FO traits (refined properties) that apply to fo:table. @@ -64,7 +71,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break private int tableLayout; private int tableOmitFooterAtBreak; private int tableOmitHeaderAtBreak; - private int writingMode; + private WritingModeTraits writingModeTraits; // Unused but valid items, commented out for performance: // private CommonAural commonAural; // private CommonRelativePosition commonRelativePosition; @@ -131,7 +138,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break tableLayout = pList.get(PR_TABLE_LAYOUT).getEnum(); tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum(); tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); - writingMode = pList.get(PR_WRITING_MODE).getEnum(); + writingModeTraits = new WritingModeTraits + ( WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()) ); //Bind extension properties widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength(); @@ -147,13 +155,19 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break getFOValidationEventProducer().unimplementedFeature(this, getName(), "table-layout=\"auto\"", getLocator()); } - if (!isSeparateBorderModel() - && getCommonBorderPaddingBackground().hasPadding( - ValidationPercentBaseContext.getPseudoContext())) { - //See "17.6.2 The collapsing border model" in CSS2 - TableEventProducer eventProducer = TableEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.noTablePaddingWithCollapsingBorderModel(this, getLocator()); + if (!isSeparateBorderModel()) { + if (borderCollapse == EN_COLLAPSE_WITH_PRECEDENCE) { + getFOValidationEventProducer().unimplementedFeature(this, getName(), + "border-collapse=\"collapse-with-precedence\"; defaulting to \"collapse\"", getLocator()); + borderCollapse = EN_COLLAPSE; + } + if (getCommonBorderPaddingBackground().hasPadding( + ValidationPercentBaseContext.getPseudoContext())) { + //See "17.6.2 The collapsing border model" in CSS2 + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noTablePaddingWithCollapsingBorderModel(this, getLocator()); + } } /* Store reference to the property list, so @@ -510,9 +524,34 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break return borderSeparation; } - /** @return the "writing-mode" FO trait */ - public int getWritingMode() { - return writingMode; + /** {@inheritDoc} */ + public Direction getInlineProgressionDirection() { + return writingModeTraits.getInlineProgressionDirection(); + } + + /** {@inheritDoc} */ + public Direction getBlockProgressionDirection() { + return writingModeTraits.getBlockProgressionDirection(); + } + + /** {@inheritDoc} */ + public Direction getColumnProgressionDirection() { + return writingModeTraits.getColumnProgressionDirection(); + } + + /** {@inheritDoc} */ + public Direction getRowProgressionDirection() { + return writingModeTraits.getRowProgressionDirection(); + } + + /** {@inheritDoc} */ + public Direction getShiftDirection() { + return writingModeTraits.getShiftDirection(); + } + + /** {@inheritDoc} */ + public WritingMode getWritingMode() { + return writingModeTraits.getWritingMode(); } /** @return the "fox:widow-content-limit" extension FO trait */ @@ -561,4 +600,24 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break RowGroupBuilder getRowGroupBuilder() { return rowGroupBuilder; } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + // header sub-tree + TableHeader header = getTableHeader(); + if ( header != null ) { + ranges = header.collectDelimitedTextRanges ( ranges ); + } + // footer sub-tree + TableFooter footer = getTableFooter(); + if ( footer != null ) { + ranges = footer.collectDelimitedTextRanges ( ranges ); + } + // body sub-tree + for ( Iterator it = getChildNodes(); ( it != null ) && it.hasNext();) { + ranges = ( (FONode) it.next() ).collectDelimitedTextRanges ( ranges ); + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java index 8640ab19b..d1ccf7273 100644 --- a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java @@ -24,6 +24,8 @@ import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.properties.CommonAccessibility; +import org.apache.fop.fo.properties.CommonAccessibilityHolder; /** * Abstract base class for the <a href="http://www.w3.org/TR/xsl/#fo_page-sequence"> @@ -31,9 +33,8 @@ import org.apache.fop.fo.PropertyList; * <a href="http://xmlgraphics.apache.org/fop/0.95/extensions.html#external-document"> * <code>fox:external-document</code></a> extension object. */ -public abstract class AbstractPageSequence extends FObj { +public abstract class AbstractPageSequence extends FObj implements CommonAccessibilityHolder { - // The value of properties relevant for fo:page-sequence. /** initial page number */ protected Numeric initialPageNumber; /** forced page count */ @@ -42,11 +43,12 @@ public abstract class AbstractPageSequence extends FObj { private int letterValue; private char groupingSeparator; private int groupingSize; - private Numeric referenceOrientation; //XSL 1.1 + private Numeric referenceOrientation; private String language; private String country; private String numberConversionFeatures; - // End of property values + + private CommonAccessibility commonAccessibility; private PageNumberGenerator pageNumberGenerator; @@ -76,6 +78,7 @@ public abstract class AbstractPageSequence extends FObj { language = pList.get(PR_LANGUAGE).getString(); country = pList.get(PR_COUNTRY).getString(); numberConversionFeatures = pList.get(PR_X_NUMBER_CONVERSION_FEATURES).getString(); + commonAccessibility = CommonAccessibility.getInstance(pList); } /** {@inheritDoc} */ @@ -130,6 +133,10 @@ public abstract class AbstractPageSequence extends FObj { return pageNumberGenerator.makeFormattedPageNumber(pageNumber); } + public CommonAccessibility getCommonAccessibility() { + return commonAccessibility; + } + /** * Public accessor for the ancestor Root. * @return the ancestor Root diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java index 153f06fc1..981485e32 100644 --- a/src/java/org/apache/fop/fo/pagination/Flow.java +++ b/src/java/org/apache/fop/fo/pagination/Flow.java @@ -26,16 +26,19 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.CommonAccessibility; +import org.apache.fop.fo.properties.CommonAccessibilityHolder; /** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_flow"> * <code>fo:flow</code></a> object. * */ -public class Flow extends FObj { - // The value of properties relevant for fo:flow. +public class Flow extends FObj implements CommonAccessibilityHolder { + private String flowName; - // End of property values + + private CommonAccessibility commonAccessibility; /** used for FO validation */ private boolean blockItemFound = false; @@ -52,6 +55,7 @@ public class Flow extends FObj { public void bind(PropertyList pList) throws FOPException { super.bind(pList); flowName = pList.get(PR_FLOW_NAME).getString(); + commonAccessibility = CommonAccessibility.getInstance(pList); } /** {@inheritDoc} */ @@ -120,6 +124,10 @@ public class Flow extends FObj { return flowName; } + public CommonAccessibility getCommonAccessibility() { + return commonAccessibility; + } + /** {@inheritDoc} */ public String getLocalName() { return "flow"; diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 789b8d4ed..0e7f3d978 100644 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -348,9 +348,7 @@ public class CommonBorderPaddingBackground { */ public static CommonBorderPaddingBackground getInstance(PropertyList pList) throws PropertyException { - - CommonBorderPaddingBackground newInstance - = new CommonBorderPaddingBackground(pList); + CommonBorderPaddingBackground newInstance = new CommonBorderPaddingBackground(pList); CommonBorderPaddingBackground cachedInstance = null; /* if padding-* and background-position-* resolve to absolute lengths * the whole instance can be cached */ @@ -368,33 +366,33 @@ public class CommonBorderPaddingBackground { || newInstance.backgroundPositionVertical.isAbsolute())) { cachedInstance = CACHE.fetch(newInstance); } - - /* for non-cached, or not-yet-cached instances, preload the image */ - if ((cachedInstance == null - || cachedInstance == newInstance) + synchronized (newInstance.backgroundImage.intern()) { + /* for non-cached, or not-yet-cached instances, preload the image */ + if ((cachedInstance == null || cachedInstance == newInstance) && !("".equals(newInstance.backgroundImage))) { - //Additional processing: preload image - String uri = URISpecification.getURL(newInstance.backgroundImage); - FObj fobj = pList.getFObj(); - FOUserAgent userAgent = pList.getFObj().getUserAgent(); - ImageManager manager = userAgent.getFactory().getImageManager(); - ImageSessionContext sessionContext = userAgent.getImageSessionContext(); - ImageInfo info; - try { - info = manager.getImageInfo(uri, sessionContext); - newInstance.backgroundImageInfo = info; - } catch (ImageException e) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - fobj.getUserAgent().getEventBroadcaster()); - eventProducer.imageError(fobj, uri, e, fobj.getLocator()); - } catch (FileNotFoundException fnfe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - fobj.getUserAgent().getEventBroadcaster()); - eventProducer.imageNotFound(fobj, uri, fnfe, fobj.getLocator()); - } catch (IOException ioe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - fobj.getUserAgent().getEventBroadcaster()); - eventProducer.imageIOError(fobj, uri, ioe, fobj.getLocator()); + //Additional processing: preload image + String uri = URISpecification.getURL(newInstance.backgroundImage); + FObj fobj = pList.getFObj(); + FOUserAgent userAgent = pList.getFObj().getUserAgent(); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + ImageInfo info; + try { + info = manager.getImageInfo(uri, sessionContext); + newInstance.backgroundImageInfo = info; + } catch (ImageException e) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + fobj.getUserAgent().getEventBroadcaster()); + eventProducer.imageError(fobj, uri, e, fobj.getLocator()); + } catch (FileNotFoundException fnfe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + fobj.getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(fobj, uri, fnfe, fobj.getLocator()); + } catch (IOException ioe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + fobj.getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(fobj, uri, ioe, fobj.getLocator()); + } } } diff --git a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java index ff7619928..b59c22de6 100644 --- a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java +++ b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java @@ -19,8 +19,6 @@ package org.apache.fop.fo.properties; -import java.util.Iterator; - import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; @@ -34,8 +32,6 @@ public final class FontFamilyProperty extends ListProperty { private static final PropertyCache<FontFamilyProperty> CACHE = new PropertyCache<FontFamilyProperty>(); - private int hash = 0; - /** * Inner class for creating instances of ListProperty */ @@ -151,30 +147,4 @@ public final class FontFamilyProperty extends ListProperty { } } - /** {@inheritDoc} */ - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o instanceof FontFamilyProperty) { - FontFamilyProperty ffp = (FontFamilyProperty) o; - return (this.list != null - && this.list.equals(ffp.list)); - } - return false; - } - - /** {@inheritDoc} */ - public int hashCode() { - if (this.hash == 0) { - int hash = 17; - for (Iterator i = list.iterator(); i.hasNext();) { - Property p = (Property) i.next(); - hash = 37 * hash + (p == null ? 0 : p.hashCode()); - } - this.hash = hash; - } - return this.hash; - } } diff --git a/src/java/org/apache/fop/fo/properties/SpaceProperty.java b/src/java/org/apache/fop/fo/properties/SpaceProperty.java index 641ec3baf..f7bdc60d7 100644 --- a/src/java/org/apache/fop/fo/properties/SpaceProperty.java +++ b/src/java/org/apache/fop/fo/properties/SpaceProperty.java @@ -23,6 +23,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; +import org.apache.fop.util.CompareUtil; /** * Base class used for handling properties of the fo:space-before and @@ -168,4 +169,27 @@ public class SpaceProperty extends LengthRangeProperty { return this; } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + CompareUtil.getHashCode(precedence); + result = prime * result + CompareUtil.getHashCode(conditionality); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SpaceProperty)) { + return false; + } + SpaceProperty other = (SpaceProperty) obj; + return super.equals(obj) + && CompareUtil.equal(precedence, other.precedence) + && CompareUtil.equal(conditionality, other.conditionality); + } + } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java index 3c1a94f63..8100c4b9b 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java @@ -168,7 +168,6 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { */ public List<URL> find(String dir) throws IOException { List<URL> results = new java.util.ArrayList<URL>(); - super.walk(new File(dir), results); File directory = new File(dir); if (!directory.isDirectory()) { eventListener.fontDirectoryNotFound(this, dir); diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 5860e5cd5..f80226e26 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -533,18 +533,6 @@ public class TTFFile { unicodeMappings.add(new UnicodeMapping(glyphIdx, j)); mtxTab[glyphIdx].getUnicodeIndex().add(new Integer(j)); - if (encodingID == 0 && j >= 0xF020 && j <= 0xF0FF) { - //Experimental: Mapping 0xF020-0xF0FF to 0x0020-0x00FF - //Tested with Wingdings and Symbol TTF fonts which map their - //glyphs in the region 0xF020-0xF0FF. - int mapped = j - 0xF000; - if (!eightBitGlyphs.get(mapped)) { - //Only map if Unicode code point hasn't been mapped before - unicodeMappings.add(new UnicodeMapping(glyphIdx, mapped)); - mtxTab[glyphIdx].getUnicodeIndex().add(new Integer(mapped)); - } - } - // Also add winAnsiWidth List<Integer> v = ansiIndex.get(new Integer(j)); if (v != null) { diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java index 3117f3bcb..f2711be3c 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMParser.java +++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java @@ -20,11 +20,12 @@ package org.apache.fop.fonts.type1; import java.awt.Rectangle; -import java.beans.Statement; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Stack; @@ -313,20 +314,24 @@ public class AFMParser { } private abstract static class BeanSetter extends AbstractValueHandler { - private String method; + protected String method; public BeanSetter(String variable) { this.method = "set" + variable; } - protected void setValue(Object target, Object value) { - //Uses Java Beans API - Statement statement = new Statement(target, method, new Object[] {value}); + protected void setValue(Object target, Class<?> argType, Object value) { + Class<?> c = target.getClass(); + try { - statement.execute(); - } catch (Exception e) { - //Should never happen - throw new RuntimeException("Bean error: " + e.getMessage()); + Method mth = c.getMethod(method, argType); + mth.invoke(target, value); + } catch ( NoSuchMethodException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); + } catch ( IllegalAccessException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); + } catch ( InvocationTargetException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); } } } @@ -340,7 +345,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { String s = getStringValue(line, startpos); Object obj = stack.peek(); - setValue(obj, s); + setValue(obj, String.class, s); } } @@ -353,7 +358,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { NamedCharacter ch = new NamedCharacter(getStringValue(line, startpos)); Object obj = stack.peek(); - setValue(obj, ch); + setValue(obj, NamedCharacter.class, ch); } } @@ -368,7 +373,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { Number num = getNumberValue(line, startpos); - setValue(getContextObject(stack), num); + setValue(getContextObject(stack), Number.class, num); } } @@ -379,7 +384,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { int value = getIntegerValue(line, startpos); - setValue(getContextObject(stack), new Integer(value)); + setValue(getContextObject(stack), int.class, new Integer(value)); } } @@ -390,7 +395,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { double value = getDoubleValue(line, startpos); - setValue(getContextObject(stack), new Double(value)); + setValue(getContextObject(stack), double.class, new Double(value)); } } @@ -424,7 +429,7 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { double value = getDoubleValue(line, startpos); - setValue(getContextObject(stack), new Double(value)); + setValue(getContextObject(stack), double.class, new Double(value)); } } @@ -441,14 +446,18 @@ public class AFMParser { public void parse(String line, int startpos, Stack<Object> stack) throws IOException { Boolean b = getBooleanValue(line, startpos); - //Uses Java Beans API - Statement statement = new Statement(getContextObject(stack), - method, new Object[] {b}); + + Object target = getContextObject(stack); + Class<?> c = target.getClass(); try { - statement.execute(); - } catch (Exception e) { - //Should never happen - throw new RuntimeException("Bean error: " + e.getMessage()); + Method mth = c.getMethod(method, boolean.class); + mth.invoke(target, b); + } catch ( NoSuchMethodException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); + } catch ( IllegalAccessException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); + } catch ( InvocationTargetException e ) { + throw new RuntimeException("Bean error: " + e.getMessage(), e); } } } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index dc87f9f1d..5fa411101 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -420,7 +420,7 @@ public abstract class AbstractBreaker { alg.setConstantLineWidth(flowBPD); int optimalPageCount = alg.findBreakingPoints(effectiveList, 1, true, BreakingAlgorithm.ALL_BREAKS); - if (alg.getIPDdifference() != 0) { + if ( Math.abs ( alg.getIPDdifference() ) > 1 ) { addAreas(alg, optimalPageCount, blockList, effectiveList); // *** redo Phase 1 *** log.trace("IPD changes after page " + optimalPageCount); diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index d227b7060..0089f228f 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -41,8 +41,7 @@ import org.apache.fop.fo.flow.RetrieveMarker; /** * The base class for most LayoutManagers. */ -public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager - implements Constants { +public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager implements Constants { /** logging instance */ private static Log log = LogFactory.getLog(AbstractLayoutManager.class); diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index aab505d8b..adce89ac0 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -44,8 +44,8 @@ import org.apache.fop.traits.SpaceVal; /** * LayoutManager for a block-container FO. */ -public class BlockContainerLayoutManager extends BlockStackingLayoutManager - implements ConditionalElementListener { +public class BlockContainerLayoutManager extends BlockStackingLayoutManager implements + ConditionalElementListener, BreakOpportunity { /** * logging instance @@ -86,6 +86,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager private MinOptMax effSpaceBefore; private MinOptMax effSpaceAfter; + private int horizontalOverflow; private double contentRectOffsetX = 0; private double contentRectOffsetY = 0; @@ -401,7 +402,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( getBlockContainerFO().getUserAgent().getEventBroadcaster()); boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); - eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), + eventProducer.viewportBPDOverflow(this, getBlockContainerFO().getName(), breaker.getOverflowAmount(), needClip(), canRecover, getBlockContainerFO().getLocator()); } @@ -553,10 +554,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( getBlockContainerFO().getUserAgent().getEventBroadcaster()); boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); - eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), + eventProducer.viewportBPDOverflow(this, getBlockContainerFO().getName(), breaker.getOverflowAmount(), needClip(), canRecover, getBlockContainerFO().getLocator()); } + // this handles the IPD (horizontal) overflow + if (this.horizontalOverflow > 0) { + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider + .get(getBlockContainerFO().getUserAgent().getEventBroadcaster()); + boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); + eventProducer.viewportIPDOverflow(this, getBlockContainerFO().getName(), + this.horizontalOverflow, needClip(), canRecover, getBlockContainerFO().getLocator()); + } } setFinished(true); @@ -1027,6 +1036,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } + /** {@inheritDoc} */ + public boolean handleOverflow(int milliPoints) { + if (milliPoints > this.horizontalOverflow) { + this.horizontalOverflow = milliPoints; + } + return true; + } + + public int getBreakBefore() { + return BreakOpportunityHelper.getBreakBefore(this); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 9c3639f93..03b2d380c 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -43,8 +43,8 @@ import org.apache.fop.traits.SpaceVal; /** * LayoutManager for a block FO. */ -public class BlockLayoutManager extends BlockStackingLayoutManager - implements ConditionalElementListener { +public class BlockLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener, + BreakOpportunity { /** logging instance */ private static Log log = LogFactory.getLog(BlockLayoutManager.class); @@ -504,4 +504,8 @@ public class BlockLayoutManager extends BlockStackingLayoutManager return true; } + public int getBreakBefore() { + return BreakOpportunityHelper.getBreakBefore(this); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java index 7d3964181..d9de09a46 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java @@ -89,19 +89,30 @@ public interface BlockLevelEventProducer extends EventProducer { void overconstrainedAdjustEndIndent(Object source, String elementName, int amount, Locator loc); /** - * Contents overflow a viewport. + * Contents IPD overflow a viewport. * @param source the event source * @param elementName the formatting object * @param amount the amount by which the contents overflow (in mpt) * @param clip true if the content will be clipped * @param canRecover indicates whether FOP can recover from this problem and continue working * @param loc the location of the error or null - * @throws LayoutException the layout error provoked by the method call - * @event.severity FATAL + * @event.severity ERROR */ - void viewportOverflow(Object source, String elementName, - int amount, boolean clip, boolean canRecover, - Locator loc) throws LayoutException; + void viewportIPDOverflow(Object source, String elementName, int amount, boolean clip, + boolean canRecover, Locator loc); + + /** + * Contents BPD overflow a viewport. + * @param source the event source + * @param elementName the formatting object + * @param amount the amount by which the contents overflow (in mpt) + * @param clip true if the content will be clipped + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @event.severity ERROR + */ + void viewportBPDOverflow(Object source, String elementName, int amount, boolean clip, + boolean canRecover, Locator loc); /** * Contents overflow a region viewport. diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.xml b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.xml index a89f9ed32..d3e243a63 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.xml +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.xml @@ -22,7 +22,8 @@ <message key="tableFixedAutoWidthNotSupported">table-layout="fixed" and width="auto", but auto-layout not supported => assuming width="100%".{{locator}}</message> <message key="objectTooWide">The extent in inline-progression-direction (width) of a {elementName} is bigger than the available space ({effIPD}mpt > {maxIPD}mpt).{{locator}}</message> <message key="overconstrainedAdjustEndIndent">An {elementName} {{locator}} is wider than the available room in inline-progression-dimension. Adjusting end-indent based on overconstrained geometry rules (XSL 1.1, ch. 5.3.4)</message> - <message key="viewportOverflow">Content overflows the viewport of an {elementName} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> + <message key="viewportIPDOverflow">Content overflows the viewport of an {elementName} in inline-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> + <message key="viewportBPDOverflow">Content overflows the viewport of an {elementName} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> <message key="regionOverflow">Content overflows the viewport of the {elementName} on page {page} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> <message key="flowNotMappingToRegionBody">Flow "{flowName}" does not map to the region-body in page-master "{masterName}". FOP presently does not support this.{{locator}}</message> <message key="pageSequenceMasterExhausted">Subsequences exhausted in page-sequence-master "{pageSequenceMasterName}", {canRecover,if,using previous subsequence,cannot recover}.{{locator}}</message> diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 56c02795c..78ab6711a 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -38,7 +38,6 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.traits.MinOptMax; -import org.apache.fop.util.BreakUtil; import org.apache.fop.util.ListUtil; /** @@ -1036,7 +1035,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @return true if an element has been added due to a break-before. */ protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) { - int breakBefore = getBreakBefore(); + int breakBefore = BreakOpportunityHelper.getBreakBefore(this); if (breakBefore == EN_PAGE || breakBefore == EN_COLUMN || breakBefore == EN_EVEN_PAGE @@ -1051,27 +1050,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** - * Returns the break-before value of the current formatting object. - * @return the break-before value (Constants.EN_*) - */ - private int getBreakBefore() { - int breakBefore = EN_AUTO; - if (fobj instanceof BreakPropertySet) { - breakBefore = ((BreakPropertySet)fobj).getBreakBefore(); - } - if (true /* uncomment to only partially merge: && breakBefore != EN_AUTO*/) { - LayoutManager lm = getChildLM(); - //It is assumed this is only called when the first LM is active. - if (lm instanceof BlockStackingLayoutManager) { - BlockStackingLayoutManager bslm = (BlockStackingLayoutManager)lm; - breakBefore = BreakUtil.compareBreakClasses( - breakBefore, bslm.getBreakBefore()); - } - } - return breakBefore; - } - - /** * Creates Knuth elements for break-after and adds them to the return list. * @param returnList return list to add the additional elements to * @param context the layout context @@ -1249,5 +1227,16 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // TODO startIndent, endIndent } + /** + * Whether this LM can handle horizontal overflow error messages (only a BlockContainerLayoutManager can). + * @param milliPoints horizontal overflow + * @return true if handled by a BlockContainerLayoutManager + */ + public boolean handleOverflow(int milliPoints) { + if (getParent() instanceof BlockStackingLayoutManager) { + return ((BlockStackingLayoutManager) getParent()).handleOverflow(milliPoints); + } + return false; + } } diff --git a/src/java/org/apache/fop/layoutmgr/BreakOpportunity.java b/src/java/org/apache/fop/layoutmgr/BreakOpportunity.java new file mode 100644 index 000000000..668f112c9 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BreakOpportunity.java @@ -0,0 +1,36 @@ +/* + * 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.layoutmgr; + +/** + * Defines methods to evaluate break opportunities at a particular location in the tree of + * layout managers. + */ +public interface BreakOpportunity { + + /** + * Returns the highest priority break-before value on this layout manager or its + * relevant descendants. + * + * @return the break-before value (Constants.EN_*) + */ + int getBreakBefore(); + +} diff --git a/src/java/org/apache/fop/layoutmgr/BreakOpportunityHelper.java b/src/java/org/apache/fop/layoutmgr/BreakOpportunityHelper.java new file mode 100644 index 000000000..a3992567f --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BreakOpportunityHelper.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.layoutmgr; + +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.BreakPropertySet; +import org.apache.fop.util.BreakUtil; + +/** + * Helper implementations of the {@link BreakOpportunity} methods. + */ +public final class BreakOpportunityHelper { + + private BreakOpportunityHelper() { } + + /** + * Returns the break opportunity before the given layout manager. There is a break + * opportunity if the LM's FO has the break-before property set, or if there is a + * break opportunity before its first child LM. + * + * @return the break-before value (Constants.EN_*) + */ + public static int getBreakBefore(AbstractLayoutManager layoutManager) { + int breakBefore = Constants.EN_AUTO; + if (layoutManager.getFObj() instanceof BreakPropertySet) { + breakBefore = ((BreakPropertySet) layoutManager.getFObj()).getBreakBefore(); + } + LayoutManager childLM = layoutManager.getChildLM(); + // It is assumed this is only called when the first LM is active. + if (childLM instanceof BreakOpportunity) { + BreakOpportunity bo = (BreakOpportunity) childLM; + breakBefore = BreakUtil.compareBreakClasses(breakBefore, bo.getBreakBefore()); + } + return breakBefore; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java index 4c6bc1f3f..31ede9aee 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java @@ -228,6 +228,9 @@ public class ImageLayout implements Constants { } else if (rat1 > rat2) { adjusted.width = (int)(rat2 * size.width); adjusted.height = effHeight; + } else { + adjusted.width = effWidth; + adjusted.height = effHeight; } } else { adjusted.width = effWidth; diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 1eb91e0ab..e87b29b2d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -388,6 +388,13 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } lastSequence = ListUtil.getLast(returnList); lastChildLM = curLM; + // the context used to create this childLC above was applied a LayoutContext.SUPPRESS_BREAK_BEFORE + // in the getNextChildElements() method of the parent BlockLayoutManger; as a consequence all + // line breaks in blocks nested inside the inline associated with this ILM are being supressed; + // here we revert that supression; we do not need to do that for the first element since that + // is handled by the getBreakBefore() method of the wrapping BlockStackingLayoutManager. + // Note: this fix seems to work but is far from being the ideal way to do this + childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE, false); } if (lastSequence != null) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 4a203d55e..3e9b85742 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -28,6 +28,8 @@ import org.apache.fop.area.inline.Space; import org.apache.fop.fo.FObj; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.AbstractLayoutManager; +import org.apache.fop.layoutmgr.BreakOpportunity; +import org.apache.fop.layoutmgr.BreakOpportunityHelper; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.NonLeafPosition; @@ -39,8 +41,8 @@ import org.apache.fop.traits.MinOptMax; * which stack children in the inline direction, such as Inline or * Line. It should not be instantiated directly. */ -public abstract class InlineStackingLayoutManager extends AbstractLayoutManager - implements InlineLevelLayoutManager { +public abstract class InlineStackingLayoutManager extends AbstractLayoutManager implements + InlineLevelLayoutManager, BreakOpportunity { /** * Size of border and padding in BPD (ie, before and after). @@ -385,4 +387,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager return returnList; } + + public int getBreakBefore() { + return BreakOpportunityHelper.getBreakBefore(this); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 3b2f11ea2..27958f7e0 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -45,6 +45,7 @@ import org.apache.fop.fonts.FontTriplet; import org.apache.fop.hyphenation.Hyphenation; import org.apache.fop.hyphenation.Hyphenator; import org.apache.fop.layoutmgr.Adjustment; +import org.apache.fop.layoutmgr.BlockLayoutManager; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.BreakingAlgorithm; @@ -389,7 +390,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (log.isWarnEnabled()) { int lack = difference + bestActiveNode.availableShrink; - if (lack < 0) { + // if this LLM is nested inside a BlockContainerLayoutManager that is constraining + // the available width and thus responsible for the overflow then we do not issue + // warning event here and instead let the BCLM handle that at a later stage + if (lack < 0 && !handleOverflow(-lack)) { InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get( getFObj().getUserAgent().getEventBroadcaster()); @@ -1635,4 +1639,15 @@ public class LineLayoutManager extends InlineStackingLayoutManager return true; } + /** + * Whether this LM can handle horizontal overflow error messages (only a BlockContainerLayoutManager can). + * @param milliPoints horizontal overflow + * @return true if handled by a BlockContainerLayoutManager + */ + public boolean handleOverflow(int milliPoints) { + if (getParent() instanceof BlockLayoutManager) { + return ((BlockLayoutManager) getParent()).handleOverflow(milliPoints); + } + return false; + } } diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java index 7221d4fee..88b89e1db 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java +++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java @@ -49,7 +49,7 @@ public abstract class CollapsingBorderModel { //These statics are used singleton-style. No MT issues here. private static CollapsingBorderModel collapse = null; - private static CollapsingBorderModel collapseWithPrecedence = null; + // private static CollapsingBorderModel collapseWithPrecedence = null; /** * @param borderCollapse border collapse control @@ -63,10 +63,7 @@ public abstract class CollapsingBorderModel { } return collapse; case Constants.EN_COLLAPSE_WITH_PRECEDENCE: - if (collapseWithPrecedence == null) { - //collapseWithPrecedence = new CollapsingBorderModelWithPrecedence(); - } - return collapseWithPrecedence; + throw new UnsupportedOperationException ( "collapse-with-precedence not yet supported" ); default: throw new IllegalArgumentException("Illegal border-collapse mode."); } diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index aaccbd0d3..b0ad22386 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -245,13 +245,14 @@ public class ColumnSetup { * the left-most column; otherwise, the first column is the left-most * column. * @param col column index (1 is first column) + * @param nrColSpan number columns spanned (for calculating offset in rtl mode) * @param context the context for percentage based calculations * @return the X offset of the requested column */ - public int getXOffset(int col, PercentBaseContext context) { + public int getXOffset(int col, int nrColSpan, PercentBaseContext context) { // TODO handle vertical WMs [GA] if ( (wmTraits != null) && (wmTraits.getColumnProgressionDirection() == Direction.RL) ) { - return getXOffsetRTL(col, context); + return getXOffsetRTL(col, nrColSpan, context); } else { return getXOffsetLTR(col, context); } @@ -262,9 +263,9 @@ public class ColumnSetup { * column; i.e., those columns whose column numbers are greater than the * specified column number. */ - private int getXOffsetRTL(int col, PercentBaseContext context) { + private int getXOffsetRTL(int col, int nrColSpan, PercentBaseContext context) { int xoffset = 0; - for (int i = col, nc = colWidths.size(); ++i < nc;) { + for (int i = (col + nrColSpan - 1), nc = colWidths.size(); ++i < nc;) { int effCol = i; if (colWidths.get(effCol) != null) { xoffset += ((Length) colWidths.get(effCol)).getValue(context); diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index f6c831b3f..955dafabd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -468,7 +468,7 @@ class RowPainter { block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); block.setIPD(ipd); block.setBPD(bpd); - block.setXOffset(tclm.getXOffsetOfGridUnit(colIndex) + block.setXOffset(tclm.getXOffsetOfGridUnit(colIndex, 1) + (borderStart.getRetainedWidth() / 2)); block.setYOffset(getRowOffset(rowIndex) - (borderBefore.getRetainedWidth() / 2)); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index db5b4736c..f5e7500e2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -317,16 +317,17 @@ public class TableContentLayoutManager implements PercentBaseContext { * @return the requested X offset */ protected int getXOffsetOfGridUnit(PrimaryGridUnit gu) { - return getXOffsetOfGridUnit(gu.getColIndex()); + return getXOffsetOfGridUnit(gu.getColIndex(), gu.getCell().getNumberColumnsSpanned()); } /** * Returns the X offset of the grid unit in the given column. * @param colIndex the column index (zero-based) + * @param nrColSpan number columns spanned * @return the requested X offset */ - protected int getXOffsetOfGridUnit(int colIndex) { - return startXOffset + getTableLM().getColumns().getXOffset(colIndex + 1, getTableLM()); + protected int getXOffsetOfGridUnit(int colIndex, int nrColSpan) { + return startXOffset + getTableLM().getColumns().getXOffset(colIndex + 1, nrColSpan, getTableLM()); } /** diff --git a/src/java/org/apache/fop/pdf/PDFColorHandler.java b/src/java/org/apache/fop/pdf/PDFColorHandler.java index a15349212..8dfcf7f24 100644 --- a/src/java/org/apache/fop/pdf/PDFColorHandler.java +++ b/src/java/org/apache/fop/pdf/PDFColorHandler.java @@ -23,7 +23,6 @@ import java.awt.Color; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; -import java.text.DecimalFormat; import java.util.Map; import org.apache.commons.logging.Log; @@ -36,7 +35,7 @@ import org.apache.xmlgraphics.java2d.color.DeviceCMYKColorSpace; import org.apache.xmlgraphics.java2d.color.NamedColorSpace; import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil; -import org.apache.fop.util.DecimalFormatCache; +import org.apache.xmlgraphics.util.DoubleFormatUtil; /** * This class handles the registration of color spaces and the generation of PDF code to select @@ -225,9 +224,9 @@ public class PDFColorHandler { if (comps.length != componentCount) { throw new IllegalStateException("Color with unexpected component count encountered"); } - DecimalFormat df = DecimalFormatCache.getDecimalFormat(4); for (int i = 0, c = comps.length; i < c; i++) { - codeBuffer.append(df.format(comps[i])).append(" "); + DoubleFormatUtil.formatDouble(comps[i], 4, 4, codeBuffer); + codeBuffer.append(" "); } codeBuffer.append(command).append("\n"); } diff --git a/src/java/org/apache/fop/pdf/PDFInfo.java b/src/java/org/apache/fop/pdf/PDFInfo.java index d457c2888..2cfcc7d3b 100644 --- a/src/java/org/apache/fop/pdf/PDFInfo.java +++ b/src/java/org/apache/fop/pdf/PDFInfo.java @@ -21,12 +21,11 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Calendar; import java.util.Date; -import java.util.Locale; import java.util.TimeZone; +import org.apache.xmlgraphics.util.DateFormatUtil; + /** * class representing an /Info object */ @@ -236,57 +235,13 @@ public class PDFInfo extends PDFObject { } /** - * Returns a SimpleDateFormat instance for formatting PDF date-times. - * @return a new SimpleDateFormat instance - */ - protected static SimpleDateFormat getPDFDateFormat() { - SimpleDateFormat df = new SimpleDateFormat("'D:'yyyyMMddHHmmss", Locale.ENGLISH); - df.setTimeZone(TimeZone.getTimeZone("GMT")); - return df; - } - - /** * Formats a date/time according to the PDF specification (D:YYYYMMDDHHmmSSOHH'mm'). * @param time date/time value to format * @param tz the time zone * @return the requested String representation */ - protected static String formatDateTime(Date time, TimeZone tz) { - Calendar cal = Calendar.getInstance(tz, Locale.ENGLISH); - cal.setTime(time); - - int offset = cal.get(Calendar.ZONE_OFFSET); - offset += cal.get(Calendar.DST_OFFSET); - - // DateFormat is operating on GMT so adjust for time zone offset - Date dt1 = new Date(time.getTime() + offset); - StringBuffer sb = new StringBuffer(); - sb.append(getPDFDateFormat().format(dt1)); - - offset /= (1000 * 60); // Convert to minutes - - if (offset == 0) { - sb.append('Z'); - } else { - if (offset > 0) { - sb.append('+'); - } else { - sb.append('-'); - } - int offsetHour = Math.abs(offset / 60); - int offsetMinutes = Math.abs(offset % 60); - if (offsetHour < 10) { - sb.append('0'); - } - sb.append(Integer.toString(offsetHour)); - sb.append('\''); - if (offsetMinutes < 10) { - sb.append('0'); - } - sb.append(Integer.toString(offsetMinutes)); - sb.append('\''); - } - return sb.toString(); + protected static String formatDateTime(final Date time, TimeZone tz) { + return DateFormatUtil.formatPDFDate(time, tz); } /** @@ -294,7 +249,7 @@ public class PDFInfo extends PDFObject { * @param time date/time value to format * @return the requested String representation */ - protected static String formatDateTime(Date time) { + protected static String formatDateTime(final Date time) { return formatDateTime(time, TimeZone.getDefault()); } } diff --git a/src/java/org/apache/fop/pdf/PDFJavaScriptLaunchAction.java b/src/java/org/apache/fop/pdf/PDFJavaScriptLaunchAction.java index dcd3c6fea..0926b4e75 100644 --- a/src/java/org/apache/fop/pdf/PDFJavaScriptLaunchAction.java +++ b/src/java/org/apache/fop/pdf/PDFJavaScriptLaunchAction.java @@ -43,10 +43,9 @@ public class PDFJavaScriptLaunchAction extends PDFAction { /** {@inheritDoc} */ public String toPDFString() { StringBuffer sb = new StringBuffer(64); - sb.append(getObjectID()); sb.append("<<\n/S /JavaScript\n/JS ("); sb.append(this.script); - sb.append(")\n>>\nendobj\n"); + sb.append(")\n>>"); return sb.toString(); } diff --git a/src/java/org/apache/fop/pdf/PDFNumber.java b/src/java/org/apache/fop/pdf/PDFNumber.java index 95242305c..e638a51b1 100644 --- a/src/java/org/apache/fop/pdf/PDFNumber.java +++ b/src/java/org/apache/fop/pdf/PDFNumber.java @@ -19,7 +19,7 @@ package org.apache.fop.pdf; -import org.apache.fop.util.DecimalFormatCache; +import org.apache.xmlgraphics.util.DoubleFormatUtil; /** * This class represents a simple number object. It also contains contains some @@ -75,7 +75,12 @@ public class PDFNumber extends PDFObject { * @return the value as a string */ public static String doubleOut(double doubleDown, int dec) { - return DecimalFormatCache.getDecimalFormat(dec).format(doubleDown); + if (dec < 0 || dec > 16) { + throw new IllegalArgumentException("Parameter dec must be between 1 and 16"); + } + StringBuffer buf = new StringBuffer(); + DoubleFormatUtil.formatDouble(doubleDown, dec, dec, buf); + return buf.toString(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java index 90a41fb72..a77111170 100644 --- a/src/java/org/apache/fop/pdf/PDFStructElem.java +++ b/src/java/org/apache/fop/pdf/PDFStructElem.java @@ -50,7 +50,6 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement if (parent instanceof PDFStructElem) { parentElement = (PDFStructElem) parent; } - put("Type", new PDFName("StructElem")); put("S", structureType); setParent(parent); } diff --git a/src/java/org/apache/fop/render/afp/AFPCustomizable.java b/src/java/org/apache/fop/render/afp/AFPCustomizable.java index 6eca86458..e0924c0d0 100644 --- a/src/java/org/apache/fop/render/afp/AFPCustomizable.java +++ b/src/java/org/apache/fop/render/afp/AFPCustomizable.java @@ -90,6 +90,13 @@ public interface AFPCustomizable { void setResolution(int resolution); /** + * Sets the line width correction + * + * @param correction the line width multiplying factor correction + */ + void setLineWidthCorrection(float correction); + + /** * Sets whether FS11 and FS45 non-inline images should be wrapped in a page segment * @param pSeg true iff images should be wrapped */ diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 0c778303c..7823a2ce6 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -443,6 +443,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + public void setLineWidthCorrection(float correction) { + paintingState.setLineWidthCorrection(correction); + } + + /** {@inheritDoc} */ public int getResolution() { return paintingState.getResolution(); } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index bf7fbde4a..e93d8b6aa 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -29,6 +29,7 @@ import java.util.List; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.fop.afp.AFPConstants; import org.apache.fop.afp.AFPEventProducer; import org.apache.fop.afp.AFPResourceLevel; import org.apache.fop.afp.AFPResourceLevelDefaults; @@ -37,6 +38,7 @@ import org.apache.fop.afp.fonts.AFPFontCollection; import org.apache.fop.afp.fonts.AFPFontInfo; import org.apache.fop.afp.fonts.CharacterSet; import org.apache.fop.afp.fonts.CharacterSetBuilder; +import org.apache.fop.afp.fonts.CharacterSetType; import org.apache.fop.afp.fonts.DoubleByteFont; import org.apache.fop.afp.fonts.OutlineFont; import org.apache.fop.afp.fonts.RasterFont; @@ -220,7 +222,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator } } else { font.addCharacterSet(sizeMpt, CharacterSetBuilder.getSingleByteInstance() - .build(characterset, codepage, encoding, accessor, eventProducer)); + .buildSBCS(characterset, codepage, encoding, accessor, eventProducer)); } } return font; @@ -254,7 +256,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator log.error(msg); } } else { - characterSet = CharacterSetBuilder.getSingleByteInstance().build( + characterSet = CharacterSetBuilder.getSingleByteInstance().buildSBCS( characterset, codepage, encoding, accessor, eventProducer); } // Return new font object @@ -269,10 +271,10 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator } String name = afpFontCfg.getAttribute("name", characterset); CharacterSet characterSet = null; - boolean ebcdicDBCS = afpFontCfg.getAttributeAsBoolean("ebcdic-dbcs", false); - + CharacterSetType charsetType = afpFontCfg.getAttributeAsBoolean("ebcdic-dbcs", false) + ? CharacterSetType.DOUBLE_BYTE_LINE_DATA : CharacterSetType.DOUBLE_BYTE; characterSet = CharacterSetBuilder.getDoubleByteInstance().buildDBCS(characterset, - codepage, encoding, ebcdicDBCS, accessor, eventProducer); + codepage, encoding, charsetType, accessor, eventProducer); // Create a new font object DoubleByteFont font = new DoubleByteFont(name, characterSet); @@ -322,7 +324,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator } List<FontTriplet> fontTriplets = afi.getFontTriplets(); for (int j = 0; j < fontTriplets.size(); ++j) { - FontTriplet triplet = (FontTriplet) fontTriplets.get(j); + FontTriplet triplet = fontTriplets.get(j); if (log.isDebugEnabled()) { log.debug(" Font triplet " + triplet.getName() + ", " @@ -445,6 +447,13 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator customizable.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } + // renderer resolution + Configuration lineWidthCorrectionCfg = cfg.getChild("line-width-correction", false); + if (lineWidthCorrectionCfg != null) { + customizable.setLineWidthCorrection(lineWidthCorrectionCfg + .getValueAsFloat(AFPConstants.LINE_WIDTH_CORRECTION)); + } + // a default external resource group file setting Configuration resourceGroupFileCfg = cfg.getChild("resource-group-file", false); diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java index 33e6931de..827eec820 100644 --- a/src/java/org/apache/fop/render/intermediate/IFParser.java +++ b/src/java/org/apache/fop/render/intermediate/IFParser.java @@ -156,7 +156,7 @@ public class IFParser implements IFConstants { private ContentHandler navParser; - private ContentHandler structureTreeHandler; + private StructureTreeHandler structureTreeHandler; private Attributes pageSequenceAttributes; @@ -165,12 +165,18 @@ public class IFParser implements IFConstants { private final class StructureTreeHandler extends DefaultHandler { + private final Locale pageSequenceLanguage; + private final StructureTreeEventHandler structureTreeEventHandler; private StructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler, Locale pageSequenceLanguage) throws SAXException { + this.pageSequenceLanguage = pageSequenceLanguage; this.structureTreeEventHandler = structureTreeEventHandler; - structureTreeEventHandler.startPageSequence(pageSequenceLanguage); + } + + void startStructureTree(String type) { + structureTreeEventHandler.startPageSequence(pageSequenceLanguage, type); } public void endDocument() throws SAXException { @@ -263,6 +269,8 @@ public class IFParser implements IFConstants { } else if (localName.equals(EL_STRUCTURE_TREE)) { if (userAgent.isAccessibilityEnabled()) { + String type = attributes.getValue("type"); + structureTreeHandler.startStructureTree(type); delegate = structureTreeHandler; } else { /* Delegate to a handler that does nothing */ diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java index f8f286cb3..7114f51e3 100644 --- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -64,6 +64,15 @@ import org.apache.fop.util.XMLUtil; public class IFSerializer extends AbstractXMLWritingIFDocumentHandler implements IFConstants, IFPainter, IFDocumentNavigationHandler { + /** + * Intermediate Format (IF) version, used to express an @version attribute + * in the root element of the IF document, the initial value of which + * is set to '2.0' to signify that something preceded it (but didn't + * happen to be marked as such), and that this version is not necessarily + * backwards compatible with the unmarked (<2.0) version. + */ + public static final String VERSION = "2.0"; + private IFDocumentHandler mimicHandler; private int pageSequenceIndex; // used for accessibility @@ -167,7 +176,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler DocumentNavigationExtensionConstants.NAMESPACE); handler.startPrefixMapping(InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI); - handler.startElement(EL_DOCUMENT); + AttributesImpl atts = new AttributesImpl(); + addAttribute(atts, "version", VERSION); + handler.startElement(EL_DOCUMENT, atts); } catch (SAXException e) { throw new IFException("SAX error in startDocument()", e); } diff --git a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java index 3d9885914..9ba9afd81 100644 --- a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java +++ b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java @@ -189,11 +189,11 @@ final class IFStructureTreeBuilder implements StructureTreeEventHandler { pageSequenceEventRecorders.get(pageSequenceIndex).replay(handler); } - public void startPageSequence(Locale locale) { + public void startPageSequence(Locale locale, String role) { SAXEventRecorder eventRecorder = new SAXEventRecorder(); pageSequenceEventRecorders.add(eventRecorder); delegate = StructureTree2SAXEventAdapter.newInstance(eventRecorder); - delegate.startPageSequence(locale); + delegate.startPageSequence(locale, role); } public void endPageSequence() { diff --git a/src/java/org/apache/fop/render/intermediate/IFUtil.java b/src/java/org/apache/fop/render/intermediate/IFUtil.java index a384461ac..e8651a3df 100644 --- a/src/java/org/apache/fop/render/intermediate/IFUtil.java +++ b/src/java/org/apache/fop/render/intermediate/IFUtil.java @@ -22,9 +22,10 @@ package org.apache.fop.render.intermediate; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import org.apache.xmlgraphics.util.DoubleFormatUtil; + import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.util.DecimalFormatCache; /** * Utility functions for the intermediate format. @@ -40,7 +41,9 @@ public final class IFUtil { //See http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3 value = 0.0; } - return DecimalFormatCache.getDecimalFormat(6).format(value); + StringBuffer buf = new StringBuffer(); + DoubleFormatUtil.formatDouble(value, 6, 6, buf); + return buf.toString(); } /** diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java index 9b76d0620..0f752e886 100644 --- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java +++ b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java @@ -103,9 +103,9 @@ final class FOToPDFRoleMap { addStructureType("Formula"); addStructureType("Form"); - NON_STRUCT = (PDFName) STANDARD_STRUCTURE_TYPES.get("NonStruct"); + NON_STRUCT = STANDARD_STRUCTURE_TYPES.get("NonStruct"); assert NON_STRUCT != null; - THEAD = (PDFName) STANDARD_STRUCTURE_TYPES.get("THead"); + THEAD = STANDARD_STRUCTURE_TYPES.get("THead"); assert THEAD != null; // Create the standard mappings @@ -155,7 +155,7 @@ final class FOToPDFRoleMap { } private static void addMapping(String fo, String structureType) { - PDFName type = (PDFName) STANDARD_STRUCTURE_TYPES.get(structureType); + PDFName type = STANDARD_STRUCTURE_TYPES.get(structureType); assert type != null; addMapping(fo, new SimpleMapper(type)); } @@ -168,21 +168,6 @@ final class FOToPDFRoleMap { /** * Maps a Formatting Object to a PDFName representing the associated structure type. * @param fo the formatting object's local name - * @param parent the parent of the structure element to be mapped - * @return the structure type or null if no match could be found - */ - public static PDFName mapFormattingObject(String fo, PDFObject parent) { - Mapper mapper = (Mapper) DEFAULT_MAPPINGS.get(fo); - if (mapper != null) { - return mapper.getStructureType(parent); - } else { - return NON_STRUCT; - } - } - - /** - * Maps a Formatting Object to a PDFName representing the associated structure type. - * @param fo the formatting object's local name * @param role the value of the formatting object's role property * @param parent the parent of the structure element to be mapped * @param eventBroadcaster the event broadcaster @@ -192,11 +177,11 @@ final class FOToPDFRoleMap { PDFObject parent, EventBroadcaster eventBroadcaster) { PDFName type = null; if (role == null) { - type = mapFormattingObject(fo, parent); + type = getDefaultMappingFor(fo, parent); } else { - type = (PDFName) STANDARD_STRUCTURE_TYPES.get(role); + type = STANDARD_STRUCTURE_TYPES.get(role); if (type == null) { - type = mapFormattingObject(fo, parent); + type = getDefaultMappingFor(fo, parent); PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo, fo, role, type.toString().substring(1)); } @@ -205,6 +190,21 @@ final class FOToPDFRoleMap { return type; } + /** + * Maps a Formatting Object to a PDFName representing the associated structure type. + * @param fo the formatting object's local name + * @param parent the parent of the structure element to be mapped + * @return the structure type or NonStruct if no match could be found + */ + private static PDFName getDefaultMappingFor(String fo, PDFObject parent) { + Mapper mapper = DEFAULT_MAPPINGS.get(fo); + if (mapper != null) { + return mapper.getStructureType(parent); + } else { + return NON_STRUCT; + } + } + private interface Mapper { PDFName getStructureType(PDFObject parent); } @@ -226,14 +226,13 @@ final class FOToPDFRoleMap { private static class TableCellMapper implements Mapper { public PDFName getStructureType(PDFObject parent) { - PDFStructElem grandParent = (PDFStructElem) - ((PDFStructElem) parent).getParentStructElem(); + PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem(); //TODO What to do with cells from table-footer? Currently they are mapped on TD. PDFName type; if (THEAD.equals(grandParent.getStructureType())) { - type = (PDFName) STANDARD_STRUCTURE_TYPES.get("TH"); + type = STANDARD_STRUCTURE_TYPES.get("TH"); } else { - type = (PDFName) STANDARD_STRUCTURE_TYPES.get("TD"); + type = STANDARD_STRUCTURE_TYPES.get("TD"); } assert type != null; return type; diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java index 1c9f9b49d..6559e8d56 100644 --- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java @@ -19,8 +19,6 @@ package org.apache.fop.render.pdf; -import java.util.Locale; - import org.apache.fop.pdf.PDFArray; import org.apache.fop.pdf.PDFDictionary; import org.apache.fop.pdf.PDFDocument; @@ -29,7 +27,6 @@ import org.apache.fop.pdf.PDFName; import org.apache.fop.pdf.PDFPage; import org.apache.fop.pdf.PDFParentTree; import org.apache.fop.pdf.PDFStructElem; -import org.apache.fop.pdf.PDFStructTreeRoot; /** @@ -59,8 +56,6 @@ class PDFLogicalStructureHandler { */ private PDFArray pageParentTreeArray; - private PDFStructElem rootStructureElement; - /** * Class providing the necessary information for bracketing content * associated to a structure element as a marked-content sequence. @@ -95,22 +90,10 @@ class PDFLogicalStructureHandler { */ PDFLogicalStructureHandler(PDFDocument pdfDoc) { this.pdfDoc = pdfDoc; - PDFStructTreeRoot structTreeRoot = pdfDoc.makeStructTreeRoot(parentTree); - rootStructureElement = pdfDoc.makeStructureElement( - FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot); - structTreeRoot.addKid(rootStructureElement); } - - PDFStructElem createPageSequence(Locale language) { - PDFStructElem structElemPart = pdfDoc.makeStructureElement( - FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement), - rootStructureElement); - rootStructureElement.addKid(structElemPart); - if (language != null) { - structElemPart.setLanguage(language); - } - return structElemPart; + PDFParentTree getParentTree() { + return parentTree; } private int getNextParentTreeKey() { diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java index 2a2a4a392..3839d47bc 100644 --- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java +++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java @@ -29,7 +29,11 @@ import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.events.EventBroadcaster; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.pdf.PDFFactory; +import org.apache.fop.pdf.PDFName; +import org.apache.fop.pdf.PDFObject; +import org.apache.fop.pdf.PDFParentTree; import org.apache.fop.pdf.PDFStructElem; +import org.apache.fop.pdf.PDFStructTreeRoot; class PDFStructureTreeBuilder implements StructureTreeEventHandler { @@ -41,21 +45,42 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>(); + private PDFStructElem rootStructureElement; + void setPdfFactory(PDFFactory pdfFactory) { this.pdfFactory = pdfFactory; } void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) { this.logicalStructureHandler = logicalStructureHandler; + createRootStructureElement(); + } + + private void createRootStructureElement() { + assert rootStructureElement == null; + PDFParentTree parentTree = logicalStructureHandler.getParentTree(); + PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree); + rootStructureElement = createStructureElement("root", structTreeRoot, null); + structTreeRoot.addKid(rootStructureElement); } void setEventBroadcaster(EventBroadcaster eventBroadcaster) { this.eventBroadcaster = eventBroadcaster; } - public void startPageSequence(Locale locale) { + public void startPageSequence(Locale language, String role) { ancestors = new LinkedList<PDFStructElem>(); - ancestors.add(logicalStructureHandler.createPageSequence(locale)); + PDFStructElem structElem = createStructureElement("page-sequence", rootStructureElement, role); + if (language != null) { + structElem.setLanguage(language); + } + rootStructureElement.addKid(structElem); + ancestors.add(structElem); + } + + private PDFStructElem createStructureElement(String name, PDFObject parent, String role) { + PDFName structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster); + return pdfFactory.getDocument().makeStructureElement(structureType, parent); } public void endPageSequence() { @@ -64,12 +89,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { public StructureTreeElement startNode(String name, Attributes attributes) { PDFStructElem parent = ancestors.getFirst(); String role = attributes.getValue("role"); - PDFStructElem created; - created = pdfFactory.getDocument().makeStructureElement( - FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent); - parent.addKid(created); - ancestors.addFirst(created); - return created; + PDFStructElem structElem = createStructureElement(name, parent, role); + parent.addKid(structElem); + ancestors.addFirst(structElem); + return structElem; } public void endNode(String name) { @@ -83,34 +106,30 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { public StructureTreeElement startImageNode(String name, Attributes attributes) { PDFStructElem parent = ancestors.getFirst(); String role = attributes.getValue("role"); - PDFStructElem created; - created = pdfFactory.getDocument().makeStructureElement( - FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent); - parent.addKid(created); + PDFStructElem structElem = createStructureElement(name, parent, role); + parent.addKid(structElem); String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text"); if (altTextNode != null) { - created.put("Alt", altTextNode); + structElem.put("Alt", altTextNode); } else { - created.put("Alt", "No alternate text specified"); + structElem.put("Alt", "No alternate text specified"); } - ancestors.addFirst(created); - return created; + ancestors.addFirst(structElem); + return structElem; } public StructureTreeElement startReferencedNode(String name, Attributes attributes) { PDFStructElem parent = ancestors.getFirst(); String role = attributes.getValue("role"); - PDFStructElem created; + PDFStructElem structElem; if ("#PCDATA".equals(name)) { - created = new PDFStructElem.Placeholder(parent, name); + structElem = new PDFStructElem.Placeholder(parent, name); } else { - created = pdfFactory.getDocument().makeStructureElement( - FOToPDFRoleMap.mapFormattingObject(name, role, parent, - eventBroadcaster), parent); + structElem = createStructureElement(name, parent, role); } - parent.addKid(created); - ancestors.addFirst(created); - return created; + parent.addKid(structElem); + ancestors.addFirst(structElem); + return structElem; } } diff --git a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java index 01c93cb2d..de82a3098 100644 --- a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java +++ b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -58,6 +59,7 @@ import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.render.ps.extensions.PSCommentAfter; import org.apache.fop.render.ps.extensions.PSCommentBefore; +import org.apache.fop.render.ps.extensions.PSPageTrailerCodeBefore; import org.apache.fop.render.ps.extensions.PSSetPageDevice; import org.apache.fop.render.ps.extensions.PSSetupCode; @@ -99,10 +101,11 @@ public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { private PSPageDeviceDictionary pageDeviceDictionary; /** This is a collection holding all document header comments */ - private Collection[] comments = new Collection[3]; + private Collection[] comments = new Collection[4]; private static final int COMMENT_DOCUMENT_HEADER = 0; private static final int COMMENT_DOCUMENT_TRAILER = 1; private static final int COMMENT_PAGE_TRAILER = 2; + private static final int PAGE_TRAILER_CODE_BEFORE = 3; private PSEventProducer eventProducer; @@ -448,8 +451,9 @@ public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { /** {@inheritDoc} */ public void startPageTrailer() throws IFException { - super.startPageTrailer(); try { + writeExtensions(PAGE_TRAILER_CODE_BEFORE); + super.startPageTrailer(); gen.writeDSCComment(DSCConstants.PAGE_TRAILER); } catch (IOException ioe) { throw new IFException("I/O error in startPageTrailer()", ioe); @@ -531,6 +535,11 @@ public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { comments[targetCollection] = new java.util.ArrayList(); } comments[targetCollection].add(extension); + } else if (extension instanceof PSPageTrailerCodeBefore) { + if (comments[PAGE_TRAILER_CODE_BEFORE] == null) { + comments[PAGE_TRAILER_CODE_BEFORE] = new ArrayList(); + } + comments[PAGE_TRAILER_CODE_BEFORE].add(extension); } } catch (IOException ioe) { throw new IFException("I/O error in handleExtensionObject()", ioe); diff --git a/src/java/org/apache/fop/render/ps/PSPainter.java b/src/java/org/apache/fop/render/ps/PSPainter.java index 27963ca07..c2288019a 100644 --- a/src/java/org/apache/fop/render/ps/PSPainter.java +++ b/src/java/org/apache/fop/render/ps/PSPainter.java @@ -76,10 +76,14 @@ public class PSPainter extends AbstractIFPainter { * @param documentHandler the parent document handler */ public PSPainter(PSDocumentHandler documentHandler) { + this(documentHandler, IFState.create()); + } + + protected PSPainter(PSDocumentHandler documentHandler, IFState state) { super(); this.documentHandler = documentHandler; this.borderPainter = new PSBorderPainter(documentHandler.gen); - this.state = IFState.create(); + this.state = state; } /** {@inheritDoc} */ @@ -348,6 +352,10 @@ public class PSPainter extends AbstractIFPainter { public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { try { + //Do not draw text if font-size is 0 as it creates an invalid PostScript file + if (state.getFontSize() == 0) { + return; + } PSGenerator generator = getGenerator(); generator.useColor(state.getTextColor()); beginTextObject(); diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java index 00d0594f2..5721afaf6 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -41,6 +41,7 @@ public class PSExtensionElementMapping extends ElementMapping { foObjs = new java.util.HashMap<String, Maker>(); foObjs.put(PSSetupCodeElement.ELEMENT, new PSSetupCodeMaker()); foObjs.put(PSPageSetupCodeElement.ELEMENT, new PSPageSetupCodeMaker()); + foObjs.put(PSPageTrailerCodeBefore.ELEMENT, new PSPageTrailerCodeBeforeMaker()); foObjs.put(PSSetPageDeviceElement.ELEMENT, new PSSetPageDeviceMaker()); foObjs.put(PSCommentBefore.ELEMENT, new PSCommentBeforeMaker()); foObjs.put(PSCommentAfter.ELEMENT, new PSCommentAfterMaker()); @@ -59,6 +60,12 @@ public class PSExtensionElementMapping extends ElementMapping { } } + static class PSPageTrailerCodeBeforeMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new PSPageTrailerCodeBeforeElement(parent); + } + } + static class PSSetPageDeviceMaker extends ElementMapping.Maker { public FONode make(FONode parent) { return new PSSetPageDeviceElement(parent); diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java index d499ef6ab..b520d8736 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java @@ -53,6 +53,7 @@ public class PSExtensionHandler extends DefaultHandler lastAttributes = new AttributesImpl(attributes); handled = false; if (localName.equals(PSSetupCode.ELEMENT) + || localName.equals(PSPageTrailerCodeBefore.ELEMENT) || localName.equals(PSSetPageDevice.ELEMENT) || localName.equals(PSCommentBefore.ELEMENT) || localName.equals(PSCommentAfter.ELEMENT)) { @@ -84,6 +85,8 @@ public class PSExtensionHandler extends DefaultHandler this.returnedObject = new PSCommentBefore(content.toString()); } else if (PSCommentAfter.ELEMENT.equals(localName)) { this.returnedObject = new PSCommentAfter(content.toString()); + } else if (PSPageTrailerCodeBefore.ELEMENT.equals(localName)) { + this.returnedObject = new PSPageTrailerCodeBefore(content.toString()); } } content.setLength(0); //Reset text buffer (see characters()) diff --git a/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBefore.java b/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBefore.java new file mode 100644 index 000000000..f28f0003e --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBefore.java @@ -0,0 +1,50 @@ +/* + * 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.ps.extensions; + + +public class PSPageTrailerCodeBefore extends PSExtensionAttachment { + + /** The element name */ + protected static final String ELEMENT = "ps-page-trailer-code-before"; + + /** + * Default constructor + * @param content the actual comment + */ + public PSPageTrailerCodeBefore(String content) { + super(content); + } + + /** + * Constructor + */ + public PSPageTrailerCodeBefore() { + super(); + } + + /** + * @return element name + */ + protected String getElement() { + return ELEMENT; + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBeforeElement.java new file mode 100644 index 000000000..65a22eadd --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSPageTrailerCodeBeforeElement.java @@ -0,0 +1,55 @@ +/* + * 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.ps.extensions; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.extensions.ExtensionAttachment; + +/** + * Comment before element + */ +public class PSPageTrailerCodeBeforeElement extends AbstractPSCommentElement { + + /** the element name */ + protected static final String ELEMENT = "ps-page-trailer-code-before"; + + /** + * Main constructor + * @param parent parent node + */ + public PSPageTrailerCodeBeforeElement(FONode parent) { + super(parent); + } + + /** + * @return local name + * @see org.apache.fop.fo.FONode#getLocalName() + */ + public String getLocalName() { + return PSPageTrailerCodeBefore.ELEMENT; + } + + /** + * @return instance of its extension attachment object + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new PSPageTrailerCodeBefore(); + } +} diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java index e85da98af..150a46986 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java @@ -28,6 +28,7 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; import java.io.IOException; import java.io.Writer; +import java.util.List; /** * <p>Models a section in an RTF document</p> @@ -192,7 +193,11 @@ implements * @throws IOException for I/O problems */ protected void writeRtfSuffix() throws IOException { - writeControlWord("sect"); + // write suffix /sect only if this section is not last section (see bug #51484) + List siblings = parent.getChildren(); + if ( ( siblings.indexOf ( this ) + 1 ) < siblings.size() ) { + writeControlWord("sect"); + } } private void closeCurrentTable() throws IOException { diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java index dd3d883f6..9492018fc 100644 --- a/src/java/org/apache/fop/render/txt/TXTRenderer.java +++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java @@ -195,7 +195,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { */ protected void renderText(TextArea area) { int col = Helper.ceilPosition(this.currentIPPosition, CHAR_WIDTH); - int row = Helper.ceilPosition(this.currentBPPosition - LINE_LEADING, CHAR_HEIGHT + 2*LINE_LEADING); + int row = Helper.ceilPosition(this.currentBPPosition - LINE_LEADING, CHAR_HEIGHT + 2 * LINE_LEADING); String s = area.getText(); @@ -219,7 +219,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { double height = bounds.getHeight(); pageWidth = Helper.ceilPosition((int) width, CHAR_WIDTH); - pageHeight = Helper.ceilPosition((int) height, CHAR_HEIGHT + 2*LINE_LEADING); + pageHeight = Helper.ceilPosition((int) height, CHAR_HEIGHT + 2 * LINE_LEADING); // init buffers charData = new StringBuffer[pageHeight]; @@ -463,9 +463,9 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { */ public void renderImage(Image image, Rectangle2D pos) { int x1 = Helper.ceilPosition(currentIPPosition, CHAR_WIDTH); - int y1 = Helper.ceilPosition(currentBPPosition - LINE_LEADING, CHAR_HEIGHT + 2*LINE_LEADING); + int y1 = Helper.ceilPosition(currentBPPosition - LINE_LEADING, CHAR_HEIGHT + 2 * LINE_LEADING); int width = Helper.ceilPosition((int) pos.getWidth(), CHAR_WIDTH); - int height = Helper.ceilPosition((int) pos.getHeight(), CHAR_HEIGHT + 2*LINE_LEADING); + int height = Helper.ceilPosition((int) pos.getHeight(), CHAR_HEIGHT + 2 * LINE_LEADING); fillRect(x1, y1, width, height, IMAGE_CHAR); } @@ -562,9 +562,9 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { protected void drawBackAndBorders(Area area, float startx, float starty, float width, float height) { bm.setWidth(Helper.ceilPosition(toMilli(width), CHAR_WIDTH)); - bm.setHeight(Helper.ceilPosition(toMilli(height), CHAR_HEIGHT + 2*LINE_LEADING)); + bm.setHeight(Helper.ceilPosition(toMilli(height), CHAR_HEIGHT + 2 * LINE_LEADING)); bm.setStartX(Helper.ceilPosition(toMilli(startx), CHAR_WIDTH)); - bm.setStartY(Helper.ceilPosition(toMilli(starty), CHAR_HEIGHT + 2*LINE_LEADING)); + bm.setStartY(Helper.ceilPosition(toMilli(starty), CHAR_HEIGHT + 2 * LINE_LEADING)); super.drawBackAndBorders(area, startx, starty, width, height); } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 4ac650269..cf3cbe5a2 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -97,6 +97,15 @@ import org.apache.fop.util.XMLUtil; */ public class XMLRenderer extends AbstractXMLRenderer { + /** + * Area Tree (AT) version, used to express an @version attribute + * in the root element of the AT document, the initial value of which + * is set to '2.0' to signify that something preceded it (but didn't + * happen to be marked as such), and that this version is not necessarily + * backwards compatible with the unmarked (<2.0) version. + */ + public static final String VERSION = "2.0"; + /** XML MIME type */ public static final String XML_MIME_TYPE = MimeConstants.MIME_FOP_AREA_TREE; @@ -365,7 +374,9 @@ public class XMLRenderer extends AbstractXMLRenderer { if (userAgent.getProducer() != null) { comment("Produced by " + userAgent.getProducer()); } - startElement("areaTree"); + atts.clear(); + addAttribute("version", VERSION); + startElement("areaTree", atts); } /** {@inheritDoc} */ @@ -825,11 +836,10 @@ public class XMLRenderer extends AbstractXMLRenderer { } maybeAddLevelAttribute(word); maybeAddPositionAdjustAttribute(word); - if ( word.isReversed() ) { - addAttribute("reversed", "true"); - } + String text = word.getWord(); + maybeAddReversedAttribute(word, text); startElement("word", atts); - characters(word.getWord()); + characters(text); endElement("word"); super.renderWord(word); } @@ -917,5 +927,11 @@ public class XMLRenderer extends AbstractXMLRenderer { } } + private void maybeAddReversedAttribute ( WordArea w, String text ) { + if ( w.isReversed() && ( text.length() > 1 ) ) { + addAttribute("reversed", "true"); + } + } + } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index ef81180ce..67fc5d860 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -1171,8 +1171,8 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand currentStream.write("q\n"); writeClip(shape); - currentStream.write("" + usrW + " 0 0 " + (-usrH) + " " + usrX - + " " + (usrY + usrH) + " cm\n" + currentStream.write("" + PDFNumber.doubleOut(usrW) + " 0 0 " + PDFNumber.doubleOut(-usrH) + " " + + PDFNumber.doubleOut(usrX) + " " + PDFNumber.doubleOut(usrY + usrH) + " cm\n" + imageInfo.getName() + " Do\nQ\n"); return true; } diff --git a/src/java/org/apache/fop/util/DecimalFormatCache.java b/src/java/org/apache/fop/util/DecimalFormatCache.java deleted file mode 100644 index a6634f50b..000000000 --- a/src/java/org/apache/fop/util/DecimalFormatCache.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.util; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.Locale; - -/** - * This class provides a cache for {@link DecimalFormat} instance. {@link DecimalFormat} itself - * is not thread-safe but since FOP needs to format a lot of numbers the same way, it shall - * be cached in a {@link ThreadLocal}. - */ -public final class DecimalFormatCache { - - private DecimalFormatCache() { - } - - private static final String BASE_FORMAT = "0.################"; - - private static class DecimalFormatThreadLocal extends ThreadLocal { - - private int dec; - - public DecimalFormatThreadLocal(int dec) { - this.dec = dec; - } - - protected synchronized Object initialValue() { - String s = "0"; - if (dec > 0) { - s = BASE_FORMAT.substring(0, dec + 2); - } - DecimalFormat df = new DecimalFormat(s, new DecimalFormatSymbols(Locale.US)); - return df; - } - }; - - //DecimalFormat is not thread-safe! - private static final ThreadLocal[] DECIMAL_FORMAT_CACHE = new DecimalFormatThreadLocal[17]; - static { - for (int i = 0, c = DECIMAL_FORMAT_CACHE.length; i < c; i++) { - DECIMAL_FORMAT_CACHE[i] = new DecimalFormatThreadLocal(i); - } - } - - /** - * Returns a cached {@link DecimalFormat} instance for the given number of decimal digits. - * @param dec the number of decimal digits. - * @return the DecimalFormat instance - */ - public static DecimalFormat getDecimalFormat(int dec) { - if (dec < 0 || dec >= DECIMAL_FORMAT_CACHE.length) { - throw new IllegalArgumentException("Parameter dec must be between 1 and " - + (DECIMAL_FORMAT_CACHE.length + 1)); - } - return (DecimalFormat)DECIMAL_FORMAT_CACHE[dec].get(); - } - -} diff --git a/status.xml b/status.xml index 3d91908f2..6b1c4b849 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,7 @@ <context id="Extensions" title="Changes to the Bundled Extensions"/> <context id="Images" title="Changes to the Image Support"/> <context id="Config" title="Changes to the User Configuration"/> + <context id="Test" title="Changes to unit tests or other test code"/> </contexts> <changes> @@ -62,10 +63,105 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> <release version="FOP Trunk" date="TBD"> + <action context="Renderers" dev="GA" type="fix" fixes-bug="53304,53306"> + Add version attribute to AT and IF intermediate formats. Also eliminate redundant use of reversed attribute in AT format. + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="53295" due-to="Luis Bernardo"> + Add extension to place code just before PostScript %PageTrailer. + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="53294" due-to="Robert Meyer"> + Fix invalid PostScript file being created when font-size is 0. + </action> + <action context="Docs" dev="GA" type="update"> + Update FAQ and New Bug documentation. + </action> + <action context="Code" dev="VH" type="add"> + Added support for the role property on fo:page-sequence, fo:flow and fo:static-content. This + allows to change the mapping of those FOs to PDF structure types when enabling + accessibility. + </action> + <action context="Renderers" dev="VH" type="fix" due-to="Martin Koegler"> + Stop outputting the Type entry for structure elements in order to create a smaller PDF + ouptut when accessibility is enabled. + </action> + <action context="Config" dev="GA" type="fix" fixes-bug="52144" due-to="Luis Bernardo"> + Fix crash on use of version switch (-v). + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="53242" due-to="Luis Bernardo"> + Support fractional line widths in AFP renderer, fixing problem with SVG line drawing. + </action> + <action context="Config" dev="GA" type="fix" fixes-bug="53248" due-to="Luis Bernardo"> + Fix exception thrown from use of -print option in CLI. + </action> + <action context="Docs" dev="GA" type="fix" fixes-bug="53247"> + Fix renderer mime type for PCL output; should be application/x-pcl. + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="40699" due-to="Luis Bernardo"> + Fix for invalid PDF for certain numerical values in SVG lineargradient. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="53185" due-to="Robert Meyer"> + Unify date formatting between FOP and XGC as well as tidying the date format code. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="45715" due-to="Luis Bernardo"> + Break before (break-before) not respected on blocks nested in inlines. + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="48723" due-to="Robert Meyer"> + Fix for XGC when rendering PostScript using SVG being drawn upside down when using a custom affine transform. + </action> + <action context="Code" dev="GA" type="fix" fixes-bug="43940" due-to="Julien Aymé, Ognjen Blagojevic"> + Use new double format utility to improve thread safety and performance. + </action> + <action context="Fonts" dev="GA" type="fix" fixes-bug="53148" due-to="Tassos Charoulis"> + Fix performance regression in JDK 1.6 Update 19 due to use of Java Beans API. Fix checkstyle errors. + </action> + <action context="Renderers" dev="GA" type="fix" fixes-bug="51484" due-to="Benjamin Riefenstahl"> + Don't write final /sect suffix in RTF if section is last section. + </action> + <action context="Fonts" dev="GA" type="fix" fixes-bug="53143"> + Ensure fonts are not loaded twice (redundantly). + </action> + <action context="Test" dev="GA" type="update" fixes-bug="50196" due-to="Matthias Reischenbacher"> + Add test for basic-link with padding. + </action> + <action context="Code" dev="GA" type="update"> + Improve property function argument parsing, specifically, better separate required, optional, and variable arguments and the handling of optional argument defaults. + Regularize property function class names. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="51043" due-to="Pascal Sancho"> + Don't restart layout unless abs(ipd difference) > 1 in order to prevent rounding issues from triggering false restart. + </action> + <action context="Fonts" dev="GA" type="update"> + Removing experimental feature that violates XSL-FO and Unicode semantics by misinterpreting Basic Latin code points. Users must use private use codepoints to access font specific + character mappings that have no assigned Unicode code point. See bug 50492. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="53103" due-to="Matthias Reischenbacher"> + Ensure that table cell spanning works in right-to-left writing mode. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="53086"> + Ensure that table footer and header are included in bididirectional resolution. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="53097"> + Ensure writing-mode specified on fo:table is used to determine writing mode of table and its descendants. + </action> + <action context="Code" dev="GA" type="fix" fixes-bug="53094" due-to="Luis Bernardo"> + Convert block container overflow exception to event model, improving overflow property behavior. + </action> + <action context="Code" dev="GA" type="update" fixes-bug="51617"> + Add run target for embedded examples. Add increased JVM memory heap flag for example8 in case font cache is rebuilt. + </action> + <action context="Code" dev="GA" type="fix" fixes-bug="53083"> + Update to use of checkstyle-5.5 as default configuration. Remove checkstyle-4.0 configuration. Also, import environment build properties before local properties, so that latter can refer to former.' + </action> + <action context="Code" dev="GA" type="fix" fixes-bug="52572" due-to="Pascal Sancho"> + Prevent NPE on use of unsupported collapse-with-precedence; fall back to collapse. Fix checkstyle errors from prior commit. + </action> + <action context="Layout" dev="GA" type="fix" fixes-bug="52514" due-to="Luis Bernardo"> + Ensure square image is appropriately scaled. + </action> <action context="Code" dev="GA" type="fix" fixes-bug="50062"> Invoke JVM in headless mode from FOP command scripts and JS shell to prevent stealing focus from GUI applications. </action> - <action context="Code" dev="GA" type="fix" fixes-bug="52114"> + <action context="Renderers" dev="GA" type="fix" fixes-bug="52114"> Take leading derived space before/after into account when computing rows for TXT renderer. </action> <action context="Code" dev="PH" type="add" fixes-bug="49893"> diff --git a/test/events/inline-level.fo b/test/events/inline-level.fo index 26a00acff..e415891ac 100644 --- a/test/events/inline-level.fo +++ b/test/events/inline-level.fo @@ -2,16 +2,14 @@ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="page" - page-height="420pt" page-width="320pt" margin="10pt"> + page-height="420pt" page-width="100pt" margin="10pt"> <fo:region-body background-color="#F0F0F0"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="page"> <fo:flow flow-name="xsl-region-body"> <fo:block>The following line overflows its container:</fo:block> - <fo:block-container width="100pt" height="100pt" border="1pt solid black"> - <fo:block>ThisLineOverflowsItsContainer</fo:block> - </fo:block-container> + <fo:block border="1pt solid black">ThisLineOverflowsItsContainer</fo:block> </fo:flow> </fo:page-sequence> </fo:root> diff --git a/test/events/viewport-overflow.fo b/test/events/viewport-overflow.fo new file mode 100644 index 000000000..ac9dc76bb --- /dev/null +++ b/test/events/viewport-overflow.fo @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master page-width="10.0cm" page-height="10.0cm" master-name="testpage"> + <fo:region-body /> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="testpage"> + <fo:flow flow-name="xsl-region-body"> + <fo:block-container overflow="error-if-overflow" position="absolute" height="20pt" width="40pt" left="30pt" top="20pt"> + <fo:block>abcdefghijklmnopqrstuvwxyz</fo:block> + </fo:block-container> + <fo:block-container overflow="error-if-overflow" position="absolute" height="65pt" width="40pt" left="90pt" top="20pt"> + <fo:block>abc def ghi jkl mno pqr stu vwx yz</fo:block> + </fo:block-container> + </fo:flow> + </fo:page-sequence> +</fo:root> diff --git a/test/java/org/apache/fop/afp/AFPGraphics2DTestCase.java b/test/java/org/apache/fop/afp/AFPGraphics2DTestCase.java new file mode 100644 index 000000000..7b261d482 --- /dev/null +++ b/test/java/org/apache/fop/afp/AFPGraphics2DTestCase.java @@ -0,0 +1,57 @@ +/* + * 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.afp; + +import java.awt.BasicStroke; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.fop.fonts.FontInfo; + +public class AFPGraphics2DTestCase { + + private final float lineWidth = 1.0f; + private final float correction = 2.5f; + private final BasicStroke stroke = mock(BasicStroke.class); + private final GraphicsObject gObject = mock(GraphicsObject.class); + private final AFPPaintingState paintingState = mock(AFPPaintingState.class); + private final AFPResourceManager resourceManager = mock(AFPResourceManager.class); + private final AFPResourceInfo resourceInfo = mock(AFPResourceInfo.class); + private final FontInfo fontInfo = mock(FontInfo.class); + private AFPGraphics2D graphics2D = new AFPGraphics2D(false, paintingState, resourceManager, resourceInfo, + fontInfo); + + @Test + public void testApplyStroke() { + // note: this only tests the setLineWidth in the GraphicsObject + float correctedLineWidth = lineWidth * correction; + when(stroke.getLineWidth()).thenReturn(lineWidth); + when(paintingState.getLineWidthCorrection()).thenReturn(correction); + graphics2D.setGraphicsObject(gObject); + graphics2D.applyStroke(stroke); + verify(gObject).setLineWidth(correctedLineWidth); + } + +} diff --git a/test/java/org/apache/fop/afp/fonts/CharactersetEncoderTestCase.java b/test/java/org/apache/fop/afp/fonts/CharactersetEncoderTestCase.java index dd776e41c..6d0daa2be 100644 --- a/test/java/org/apache/fop/afp/fonts/CharactersetEncoderTestCase.java +++ b/test/java/org/apache/fop/afp/fonts/CharactersetEncoderTestCase.java @@ -19,10 +19,6 @@ package org.apache.fop.afp.fonts; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.CharacterCodingException; @@ -30,6 +26,10 @@ import java.nio.charset.CharacterCodingException; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * Test {@link CharactersetEncoder} */ @@ -39,8 +39,9 @@ public class CharactersetEncoderTestCase { @Before public void setUp() { - singlebyteEncoder = CharactersetEncoder.newInstance("cp500", false); - doublebyteEncoder = CharactersetEncoder.newInstance("cp937", true); + singlebyteEncoder = CharactersetEncoder.newInstance("cp500", CharacterSetType.SINGLE_BYTE); + doublebyteEncoder = CharactersetEncoder.newInstance("cp937", + CharacterSetType.DOUBLE_BYTE_LINE_DATA); } // This is just an arbitrary CJK string @@ -95,7 +96,7 @@ public class CharactersetEncoderTestCase { @Test public void testEncode() throws CharacterCodingException, IOException { - CharactersetEncoder.EncodedChars encChars;// = doublebyteEncoder.encode(testCJKText); + CharactersetEncoder.EncodedChars encChars; // = doublebyteEncoder.encode(testCJKText); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); // JAVA 1.5 has a bug in the JVM in which these err for some reason... JAVA 1.6 no issues /*encChars.writeTo(bOut, 0, encChars.getLength()); diff --git a/test/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidthTestCase.java b/test/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidthTestCase.java new file mode 100644 index 000000000..f34275de0 --- /dev/null +++ b/test/java/org/apache/fop/afp/goca/GraphicsSetFractionalLineWidthTestCase.java @@ -0,0 +1,59 @@ +/* + * 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.afp.goca; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class GraphicsSetFractionalLineWidthTestCase { + + private final float multiplier = 5.25f; + private final GraphicsSetFractionalLineWidth gsflw = new GraphicsSetFractionalLineWidth(multiplier); + + @Test + public void testGetDataLength() { + assertEquals(4, gsflw.getDataLength()); + } + + @Test + public void testWriteToStream() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + gsflw.writeToStream(baos); + baos.close(); + // note: 0.25 = 64/256 and 64 = 4*16, so 0x40 + // expected: 0x11 (order code), 0x02 (2 bytes next), 0x05 (integral multiplier), 0x40 (fractional + // multiplier) + byte[] expected = new byte[] {0x11, 0x02, 0x05, 0x40}; + assertTrue(Arrays.equals(expected, baos.toByteArray())); + } + + @Test + public void testToString() { + // lets make sure we keep good coverage... + assertEquals("GraphicsSetFractionalLineWidth{multiplier=" + multiplier + "}", gsflw.toString()); + } + +} diff --git a/test/java/org/apache/fop/afp/goca/GraphicsSetLineWidthTestCase.java b/test/java/org/apache/fop/afp/goca/GraphicsSetLineWidthTestCase.java new file mode 100644 index 000000000..c0a18a551 --- /dev/null +++ b/test/java/org/apache/fop/afp/goca/GraphicsSetLineWidthTestCase.java @@ -0,0 +1,57 @@ +/* + * 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.afp.goca; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class GraphicsSetLineWidthTestCase { + + private final int multiplier = 5; + private final GraphicsSetLineWidth gslw = new GraphicsSetLineWidth(multiplier); + + @Test + public void testGetDataLength() { + assertEquals(2, gslw.getDataLength()); + } + + @Test + public void testWriteToStream() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + gslw.writeToStream(baos); + baos.close(); + // expected: 0x19 (order code), 0x05 (integral multiplier) + byte[] expected = new byte[] {0x19, 0x05}; + assertTrue(Arrays.equals(expected, baos.toByteArray())); + } + + @Test + public void testToString() { + // lets make sure we keep good coverage... + assertEquals("GraphicsSetLineWidth{multiplier=" + multiplier + "}", gslw.toString()); + } + +} diff --git a/test/java/org/apache/fop/afp/ptoca/TransparentDataControlSequenceTestCase.java b/test/java/org/apache/fop/afp/ptoca/TransparentDataControlSequenceTestCase.java new file mode 100644 index 000000000..338c5e6f4 --- /dev/null +++ b/test/java/org/apache/fop/afp/ptoca/TransparentDataControlSequenceTestCase.java @@ -0,0 +1,73 @@ +/* + * 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.afp.ptoca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.junit.Test; + +import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; +import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData; + +import static org.apache.fop.afp.ptoca.PtocaConstants.TRANSPARENT_DATA_MAX_SIZE; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class TransparentDataControlSequenceTestCase { + + private EncodedChars encodedChars; + private final OutputStream outStream = mock(OutputStream.class); + + @Test + public void testSingleByteCharacterSet() throws IOException { + testTRNs(false); + } + + @Test + public void testDoubleByteCharacterSets() throws IOException { + testTRNs(true); + } + + public void testTRNs(boolean isDBCS) throws IOException { + for (int length = 100; length < 10000; length += 1000) { + createTRNControlSequence(isDBCS, length); + int maxTRNSize = TRANSPARENT_DATA_MAX_SIZE - (isDBCS ? 1 : 0); + int numberOfTRNs = length / maxTRNSize; + for (int i = 0; i < numberOfTRNs; i++) { + verify(encodedChars, times(1)).writeTo(outStream, i * maxTRNSize, maxTRNSize); + } + int lastOffset = numberOfTRNs * maxTRNSize; + verify(encodedChars, times(1)).writeTo(outStream, numberOfTRNs * maxTRNSize, + length - lastOffset); + } + } + + private void createTRNControlSequence(boolean isDBCS, int length) throws IOException { + encodedChars = mock(EncodedChars.class); + when(encodedChars.isDBCS()).thenReturn(isDBCS); + when(encodedChars.getLength()).thenReturn(length); + for (TransparentData trn : new TransparentDataControlSequence(encodedChars)) { + trn.writeTo(outStream); + } + } +} diff --git a/test/java/org/apache/fop/cli/CommandLineOptionsTestCase.java b/test/java/org/apache/fop/cli/CommandLineOptionsTestCase.java new file mode 100644 index 000000000..9a80fd964 --- /dev/null +++ b/test/java/org/apache/fop/cli/CommandLineOptionsTestCase.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: CommandLineOptions.java 1293736 2012-02-26 02:29:01Z gadams $ */ + +package org.apache.fop.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.apache.fop.apps.FOPException; +import org.junit.Before; +import org.junit.Test; + +public class CommandLineOptionsTestCase { + + private final CommandLineOptions clo = new CommandLineOptions(); + private final String commandLine = "-fo examples/fo/basic/simple.fo -print"; + private String[] cmd; + private boolean parsed; + + @Before + public void setUp() throws Exception { + cmd = commandLine.split(" "); + parsed = clo.parse(cmd); + } + + @Test + public void testParse() { + assertTrue(parsed); + } + + @Test + public void testGetOutputFormat() throws FOPException { + assertEquals(clo.getOutputFormat(), "application/X-fop-print"); + } + + @Test + public void testVandVersionSwitchs() throws FOPException, IOException { + // test -v + String cl1 = "-v"; + String[] cmd1 = cl1.split(" "); + CommandLineOptions clo1 = new CommandLineOptions(); + assertTrue(!clo1.parse(cmd1)); + // test -version + String cl2 = "-version"; + String[] cmd2 = cl2.split(" "); + CommandLineOptions clo2 = new CommandLineOptions(); + assertTrue(!clo2.parse(cmd2)); + // test -v + more switches + String cl3 = "-v " + commandLine; + String[] cmd3 = cl3.split(" "); + CommandLineOptions clo3 = new CommandLineOptions(); + assertTrue(clo3.parse(cmd3)); + } +} diff --git a/test/java/org/apache/fop/events/EventProcessingTestCase.java b/test/java/org/apache/fop/events/EventProcessingTestCase.java index 8219fa71e..1d38d4ccb 100644 --- a/test/java/org/apache/fop/events/EventProcessingTestCase.java +++ b/test/java/org/apache/fop/events/EventProcessingTestCase.java @@ -124,4 +124,16 @@ public class EventProcessingTestCase { doTest("inline-level.fo", InlineLevelEventProducer.class.getName() + ".lineOverflows"); } + + @Test + public void testViewportIPDOverflow() throws FOPException, TransformerException, IOException, + SAXException { + doTest("viewport-overflow.fo", BlockLevelEventProducer.class.getName() + ".viewportIPDOverflow"); + } + + @Test + public void testViewportBPDOverflow() throws FOPException, TransformerException, IOException, + SAXException { + doTest("viewport-overflow.fo", BlockLevelEventProducer.class.getName() + ".viewportBPDOverflow"); + } } diff --git a/test/java/org/apache/fop/fo/properties/PropertyListMocks.java b/test/java/org/apache/fop/fo/properties/PropertyListMocks.java index 380f6e5a8..f364c9034 100644 --- a/test/java/org/apache/fop/fo/properties/PropertyListMocks.java +++ b/test/java/org/apache/fop/fo/properties/PropertyListMocks.java @@ -69,6 +69,10 @@ public final class PropertyListMocks { final Property borderCollapseProperty = mock(Property.class); when(borderCollapseProperty.getEnum()).thenReturn(Constants.EN_SEPARATE); when(mockPList.get(Constants.PR_BORDER_COLLAPSE)).thenReturn(borderCollapseProperty); + + final Property writingModeProperty = mock(Property.class); + when(writingModeProperty.getEnum()).thenReturn(Constants.EN_LR_TB); + when(mockPList.get(Constants.PR_WRITING_MODE)).thenReturn(writingModeProperty); } catch (PropertyException e) { throw new RuntimeException(e); } diff --git a/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java index 65c6b25a6..6819fed79 100644 --- a/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java +++ b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java @@ -61,7 +61,7 @@ public class IFStructureTreeBuilderTestCase { // Expected } - sut.startPageSequence(null); + sut.startPageSequence(null, null); sut.endPageSequence(); sut.replayEventsForPageSequence(handler, 0); @@ -89,7 +89,7 @@ public class IFStructureTreeBuilderTestCase { final String nodeName = "block"; final ContentHandler handler = mock(ContentHandler.class); - sut.startPageSequence(null); + sut.startPageSequence(null, null); sut.startNode(nodeName, createSimpleAttributes(attributes)); sut.endPageSequence(); @@ -105,7 +105,7 @@ public class IFStructureTreeBuilderTestCase { final String nodeName = "block"; final ContentHandler handler = mock(ContentHandler.class); - sut.startPageSequence(null); + sut.startPageSequence(null, null); sut.endNode(nodeName); sut.endPageSequence(); diff --git a/test/java/org/apache/fop/render/ps/PSPainterTestCase.java b/test/java/org/apache/fop/render/ps/PSPainterTestCase.java new file mode 100644 index 000000000..4e50f09c9 --- /dev/null +++ b/test/java/org/apache/fop/render/ps/PSPainterTestCase.java @@ -0,0 +1,69 @@ +/* + * 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. + */ +package org.apache.fop.render.ps; + +import java.io.IOException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.verification.VerificationMode; + +import org.apache.xmlgraphics.ps.PSGenerator; + +import org.apache.fop.render.intermediate.IFState; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class PSPainterTestCase { + + private PSDocumentHandler docHandler; + private PSPainter psPainter; + private PSGenerator gen; + private IFState state; + + @Before + public void setup() { + docHandler = new PSDocumentHandler(); + gen = mock(PSGenerator.class); + docHandler.gen = gen; + state = IFState.create(); + psPainter = new PSPainter(docHandler, state); + } + + @Test + public void testNonZeroFontSize() throws IOException { + testFontSize(6, times(1)); + } + + @Test + public void testZeroFontSize() throws IOException { + testFontSize(0, never()); + } + + private void testFontSize(int fontSize, VerificationMode test) throws IOException { + state.setFontSize(fontSize); + try { + psPainter.drawText(10, 10, 2, 2, null, "Test"); + } catch (Exception ex) { + //Expected + } + verify(gen, test).useColor(state.getTextColor()); + } +} diff --git a/test/java/org/apache/fop/render/ps/PSRenderingUtilTestCase.java b/test/java/org/apache/fop/render/ps/PSRenderingUtilTestCase.java new file mode 100644 index 000000000..3f1088fe1 --- /dev/null +++ b/test/java/org/apache/fop/render/ps/PSRenderingUtilTestCase.java @@ -0,0 +1,45 @@ +/* + * 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.ps; + +import java.io.IOException; + +import org.junit.Test; + +import org.apache.xmlgraphics.ps.PSGenerator; + +import org.apache.fop.render.ps.extensions.PSPageTrailerCodeBefore; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class PSRenderingUtilTestCase { + + private final String content = "<< /MyEntry 0 >> command"; + private final PSPageTrailerCodeBefore ptcb = new PSPageTrailerCodeBefore(content); + private final PSGenerator gen = mock(PSGenerator.class); + + @Test + public void testWriteEnclosedExtensionAttachment() throws IOException { + PSRenderingUtil.writeEnclosedExtensionAttachment(gen, ptcb); + verify(gen).writeln(content); + } + +} diff --git a/test/layoutengine/standard-testcases/basic-link_padding_bug50196.xml b/test/layoutengine/standard-testcases/basic-link_padding_bug50196.xml new file mode 100644 index 000000000..e7039bc02 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_padding_bug50196.xml @@ -0,0 +1,45 @@ +<?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> + Bugzilla #50196: padding-start on basic-link causes exception + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="210mm" page-height="297mm"> + <fo:region-body margin="2cm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:block> + <fo:basic-link padding-left="20pt" internal-destination="dest1"><fo:inline>test</fo:inline></fo:basic-link> + </fo:block> + <fo:block id="dest1"></fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="20000" xpath="//lineArea/inlineparent[@internal-link='(P1,dest1)']/@padding-start"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/bidi_propagation_1.xml b/test/layoutengine/standard-testcases/bidi_propagation_1.xml index 947d9dac5..587bc6d2f 100644 --- a/test/layoutengine/standard-testcases/bidi_propagation_1.xml +++ b/test/layoutengine/standard-testcases/bidi_propagation_1.xml @@ -66,7 +66,7 @@ <fo:table-cell margin-left="0" text-align="right"> <fo:block> <fo:inline> - <fo:inline><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">X</fo:bidi-override></fo:inline> + <fo:inline><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">XY</fo:bidi-override></fo:inline> </fo:inline> </fo:block> </fo:table-cell> @@ -93,7 +93,7 @@ <fo:table-cell margin-left="0" text-align="right"> <fo:block> <fo:inline> - <fo:inline><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">X</fo:bidi-override></fo:inline> + <fo:inline><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">XY</fo:bidi-override></fo:inline> </fo:inline> </fo:block> </fo:table-cell> diff --git a/test/layoutengine/standard-testcases/block-break-inline-break-before.xml b/test/layoutengine/standard-testcases/block-break-inline-break-before.xml new file mode 100644 index 000000000..627862aa1 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-break-inline-break-before.xml @@ -0,0 +1,38 @@ +<?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 tests that two breaks across an inline are treated as one.</p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" page-width="220pt" page-height="220pt" + margin="10pt"> + <fo:region-body /> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>one</fo:block> + <fo:block break-before="page"> + <fo:inline> + <fo:block break-before="page">two</fo:block> + </fo:inline> + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="1" xpath="//lineArea[starts-with(., 'one')]/ancestor::pageViewport/@nr" /> + <eval expected="2" xpath="//lineArea[starts-with(., 'two')]/ancestor::pageViewport/@nr" /> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/block-inline-break-before.xml b/test/layoutengine/standard-testcases/block-inline-break-before.xml new file mode 100644 index 000000000..64b3694a1 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-inline-break-before.xml @@ -0,0 +1,40 @@ +<?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 basic breaks.</p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" + margin="0.5in"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>one</fo:block> + <fo:block> + <fo:inline> + <fo:block break-before="page">two</fo:block> + <fo:block break-before="page">three</fo:block> + </fo:inline> + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="1" xpath="//lineArea[starts-with(., 'one')]/ancestor::pageViewport/@nr" /> + <eval expected="2" xpath="//lineArea[starts-with(., 'two')]/ancestor::pageViewport/@nr" /> + <eval expected="3" xpath="//lineArea[starts-with(., 'three')]/ancestor::pageViewport/@nr" /> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/block-inline-inline-break-before.xml b/test/layoutengine/standard-testcases/block-inline-inline-break-before.xml new file mode 100644 index 000000000..a44118b51 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-inline-inline-break-before.xml @@ -0,0 +1,40 @@ +<?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 tests a break inside nested inlines.</p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" + margin="0.5in"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>one</fo:block> + <fo:block> + <fo:inline> + <fo:inline> + <fo:block break-before="page">two</fo:block> + </fo:inline> + </fo:inline> + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="1" xpath="//lineArea[starts-with(., 'one')]/ancestor::pageViewport/@nr" /> + <eval expected="2" xpath="//lineArea[starts-with(., 'two')]/ancestor::pageViewport/@nr" /> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/character_writing-mode_rl.xml b/test/layoutengine/standard-testcases/character_writing-mode_rl.xml index adc126ec8..db65238c0 100644 --- a/test/layoutengine/standard-testcases/character_writing-mode_rl.xml +++ b/test/layoutengine/standard-testcases/character_writing-mode_rl.xml @@ -59,18 +59,18 @@ <eval expected="6672" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/@ipd"/> <eval expected="4" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]"/> <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]/@level"/> - <true xpath="boolean(//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]/@reversed)"/> + <eval expected="" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]/@reversed"/> <eval expected="6672" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[2]/@ipd"/> <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[2]/word[1]"/> - <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]/@level"/> - <true xpath="boolean(//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[1]/word[1]/@reversed)"/> + <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[2]/word[1]/@level"/> + <eval expected="" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[2]/word[1]/@reversed"/> <eval expected="6672" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[3]/@ipd"/> <eval expected="2" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[3]/word[1]"/> <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[3]/word[1]/@level"/> - <true xpath="boolean(//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[3]/word[1]/@reversed)"/> + <eval expected="" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[3]/word[1]/@reversed"/> <eval expected="6672" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[4]/@ipd"/> <eval expected="1" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[4]/word[1]"/> <eval expected="3" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[4]/word[1]/@level"/> - <true xpath="boolean(//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[4]/word[1]/@reversed)"/> + <eval expected="" xpath="//flow/block[2]/block[1]/block[1]/lineArea/inlineparent/text[4]/word[1]/@reversed"/> </checks> </testcase> diff --git a/test/layoutengine/standard-testcases/table-column_column-progression-rl.xml b/test/layoutengine/standard-testcases/table-column_column-progression-rl_1.xml index 4f6b3d53a..79db99a45 100644 --- a/test/layoutengine/standard-testcases/table-column_column-progression-rl.xml +++ b/test/layoutengine/standard-testcases/table-column_column-progression-rl_1.xml @@ -19,9 +19,10 @@ <testcase> <info> <p> - This test checks table column progression with right-to-left writing mode. The first column - should be to the right of the second column; the second column should be to the right of the - third column. The columns should be colored red, yellow, orange from right to left. + This test checks table column progression with right-to-left writing mode when writing-mode + is specified on fo:page-sequence. The first column should be to the right of the second column; the + second column should be to the right of the third column. The columns should be colored red, + yellow, orange from right to left. </p> </info> <fo> diff --git a/test/layoutengine/standard-testcases/table-column_column-progression-rl_2.xml b/test/layoutengine/standard-testcases/table-column_column-progression-rl_2.xml new file mode 100644 index 000000000..e7230a574 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-column_column-progression-rl_2.xml @@ -0,0 +1,83 @@ +<?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 table column progression with right-to-left writing mode when writing-mode + is specified on fo:table. The first column should be to the right of the second column; the + second column should be to the right of the third column. The columns should be colored red, + yellow, orange from right to left. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" margin="0.5in"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:table table-layout="fixed" width="100%" writing-mode="rl"> + <fo:table-column column-width="1in" background-color="red"/> + <fo:table-column column-width="1in" background-color="yellow"/> + <fo:table-column column-width="2in" background-color="orange"/> + <fo:table-body> + <fo:table-row> + <fo:table-cell> + <fo:block>cell1</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell2</fo:block> + </fo:table-cell> + <fo:table-cell> + <fo:block>cell3</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <!-- cell 1 background --> + <eval expected="#ff0000" xpath="//flow/block[1]/block[1]/@bkg-color"/> + <!-- cell 1 --> + <eval expected="cell1" xpath="//flow/block[1]/block[2]/block[1]/lineArea/text"/> + <eval expected="72000" xpath="//flow/block[1]/block[2]/@ipd"/> + <eval expected="216000" xpath="//flow/block[1]/block[2]/@left-offset"/> + <!-- cell 2 background --> + <eval expected="#ffff00" xpath="//flow/block[1]/block[3]/@bkg-color"/> + <!-- cell 2 --> + <eval expected="cell2" xpath="//flow/block[1]/block[4]/block[1]/lineArea/text"/> + <eval expected="72000" xpath="//flow/block[1]/block[4]/@ipd"/> + <eval expected="144000" xpath="//flow/block[1]/block[4]/@left-offset"/> + <!-- cell 3 background --> + <eval expected="#ffa500" xpath="//flow/block[1]/block[5]/@bkg-color"/> + <!-- cell 3 --> + <eval expected="cell3" xpath="//flow/block[1]/block[6]/block[1]/lineArea/text"/> + <eval expected="144000" xpath="//flow/block[1]/block[6]/@ipd"/> + <true xpath="not(boolean(//flow/block[1]/block[6]/@left-offset))"/> + <!-- right-to-left offset invariant - cell 2 to the left of cell 1 --> + <true xpath="//flow/block[1]/block[4]/@left-offset < //flow/block[1]/block[2]/@left-offset"/> + <!-- right-to-left offset invariant - cell 3 to left right of cell 2 --> + <true xpath="//flow/block[1]/block[4]/@left-offset > 0"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/table-column_column-progression-rl_3.xml b/test/layoutengine/standard-testcases/table-column_column-progression-rl_3.xml new file mode 100644 index 000000000..0b39606f7 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-column_column-progression-rl_3.xml @@ -0,0 +1,89 @@ +<?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 table column progression with right-to-left writing mode when using multiple + column spans. See also bugzilla #53103. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="first" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="1cm" margin-right="1cm"> + <fo:region-body margin-top="3cm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="first"> + <fo:flow flow-name="xsl-region-body"> + <fo:table table-layout="fixed" width="125mm" writing-mode="rl-tb"> + <fo:table-header> + <fo:table-row> + <fo:table-cell number-columns-spanned="2" border="solid 1px black"> + <fo:block>header-R1;C1-span2</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block>header-R1;C2</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block>header-R1;C3</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-header> + <fo:table-body> + <fo:table-row> + <fo:table-cell border="solid 1px black"> + <fo:block>body-R2;C1</fo:block> + </fo:table-cell> + <fo:table-cell number-columns-spanned="2" border="solid 1px black"> + <fo:block>body-R2;C2</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block>body-R2;C3</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell number-columns-spanned="3" border="solid 1px black"> + <fo:block>body-R3;C1-span3</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block>body-R3;C2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <!-- row 1 (header), column 1, span 2 --> + <eval expected="header-R1;C1-span2" xpath="//flow/block[1]/block[3]//lineArea"/> + <eval expected="177664" xpath="//flow/block[1]/block[3]/@left-offset"/> + <eval expected="176164" xpath="//flow/block[1]/block[3]/@ipd"/> + <!-- row 2 (body), column 2, span 1 --> + <eval expected="body-R2;C2" xpath="//flow/block[1]/block[9]//lineArea"/> + <eval expected="89082" xpath="//flow/block[1]/block[9]/@left-offset"/> + <eval expected="176164" xpath="//flow/block[1]/block[9]/@ipd"/> + <!-- row 3 (body), column 1, span 3 --> + <eval expected="body-R3;C1-span3" xpath="//flow/block[1]/block[14]//lineArea"/> + <eval expected="89082" xpath="//flow/block[1]/block[14]/@left-offset"/> + <eval expected="264746" xpath="//flow/block[1]/block[14]/@ipd"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/table_writing-mode_rl.xml b/test/layoutengine/standard-testcases/table_writing-mode_rl.xml new file mode 100644 index 000000000..65927ec48 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_writing-mode_rl.xml @@ -0,0 +1,91 @@ +<?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 table header, footer, and body cells all respect writing-mode="rl" specified on table. See also Bugzilla #53086. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="first" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm"> + <fo:region-body margin-top="3cm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="first"> + <fo:flow flow-name="xsl-region-body"> + <fo:block-container writing-mode="rl-tb"> + <fo:table table-layout="fixed" width="100%" border-collapse="collapse"> + <fo:table-header> + <fo:table-row> + <fo:table-cell border="solid 1px black"> + <fo:block>HEADER ROW</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">ABC</fo:bidi-override></fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">DEF</fo:bidi-override></fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-header> + <fo:table-footer> + <fo:table-row> + <fo:table-cell border="solid 1px black"> + <fo:block>FOOTER ROW</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">ABC</fo:bidi-override></fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">DEF</fo:bidi-override></fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-footer> + <fo:table-body> + <fo:table-row> + <fo:table-cell border="solid 1px black"> + <fo:block>BODY ROW</fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">ABC</fo:bidi-override></fo:block> + </fo:table-cell> + <fo:table-cell border="solid 1px black"> + <fo:block><fo:bidi-override unicode-bidi="bidi-override" direction="rtl">DEF</fo:bidi-override></fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:block-container> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="9" xpath="count(//lineArea)"/> + <eval expected="HEADER ROWCBAFEDBODY ROWCBAFEDFOOTER ROWCBAFED" xpath="/"/> + <eval expected="HEADER ROW" xpath="//flow/block/block/block/block[1]//lineArea"/> + <eval expected="1" xpath="//flow/block/block/block/block[1]//lineArea/@level"/> + <eval expected="BODY ROW" xpath="//flow/block/block/block/block[4]//lineArea"/> + <eval expected="1" xpath="//flow/block/block/block/block[4]//lineArea/@level"/> + <eval expected="FOOTER ROW" xpath="//flow/block/block/block/block[7]//lineArea"/> + <eval expected="1" xpath="//flow/block/block/block/block[7]//lineArea/@level"/> + </checks> +</testcase> diff --git a/test/pdf/1.5/test.pdf b/test/pdf/1.5/test.pdf Binary files differindex 4c25c0847..6175a270f 100644 --- a/test/pdf/1.5/test.pdf +++ b/test/pdf/1.5/test.pdf diff --git a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf Binary files differindex 9b4a7fc20..bf3cdccad 100644 --- a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf +++ b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf diff --git a/test/pdf/accessibility/pdf/background-image_jpg_single.pdf b/test/pdf/accessibility/pdf/background-image_jpg_single.pdf Binary files differindex d1d0ecb1b..4d40ebc7a 100644 --- a/test/pdf/accessibility/pdf/background-image_jpg_single.pdf +++ b/test/pdf/accessibility/pdf/background-image_jpg_single.pdf diff --git a/test/pdf/accessibility/pdf/background-image_png_repeat.pdf b/test/pdf/accessibility/pdf/background-image_png_repeat.pdf Binary files differindex ccb2cf089..7847bcedd 100644 --- a/test/pdf/accessibility/pdf/background-image_png_repeat.pdf +++ b/test/pdf/accessibility/pdf/background-image_png_repeat.pdf diff --git a/test/pdf/accessibility/pdf/background-image_png_single.pdf b/test/pdf/accessibility/pdf/background-image_png_single.pdf Binary files differindex 902520b95..9458b54f8 100644 --- a/test/pdf/accessibility/pdf/background-image_png_single.pdf +++ b/test/pdf/accessibility/pdf/background-image_png_single.pdf diff --git a/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf b/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf Binary files differindex a720a5b9a..41c2ee500 100644 --- a/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf +++ b/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf diff --git a/test/pdf/accessibility/pdf/background-image_svg_single.pdf b/test/pdf/accessibility/pdf/background-image_svg_single.pdf Binary files differindex 7e6e3e9d4..8c2dc1006 100644 --- a/test/pdf/accessibility/pdf/background-image_svg_single.pdf +++ b/test/pdf/accessibility/pdf/background-image_svg_single.pdf diff --git a/test/pdf/accessibility/pdf/complete.pdf b/test/pdf/accessibility/pdf/complete.pdf Binary files differindex f1dc10559..3aada8c00 100644 --- a/test/pdf/accessibility/pdf/complete.pdf +++ b/test/pdf/accessibility/pdf/complete.pdf diff --git a/test/pdf/accessibility/pdf/image_jpg.pdf b/test/pdf/accessibility/pdf/image_jpg.pdf Binary files differindex e943c83e5..21bae3826 100644 --- a/test/pdf/accessibility/pdf/image_jpg.pdf +++ b/test/pdf/accessibility/pdf/image_jpg.pdf diff --git a/test/pdf/accessibility/pdf/image_png.pdf b/test/pdf/accessibility/pdf/image_png.pdf Binary files differindex 5ea44673b..5bd99a623 100644 --- a/test/pdf/accessibility/pdf/image_png.pdf +++ b/test/pdf/accessibility/pdf/image_png.pdf diff --git a/test/pdf/accessibility/pdf/image_svg.pdf b/test/pdf/accessibility/pdf/image_svg.pdf Binary files differindex db1e061cf..a9428fd3f 100644 --- a/test/pdf/accessibility/pdf/image_svg.pdf +++ b/test/pdf/accessibility/pdf/image_svg.pdf diff --git a/test/pdf/accessibility/pdf/image_wmf.pdf b/test/pdf/accessibility/pdf/image_wmf.pdf Binary files differindex 65c46d12a..c15a05223 100644 --- a/test/pdf/accessibility/pdf/image_wmf.pdf +++ b/test/pdf/accessibility/pdf/image_wmf.pdf diff --git a/test/pdf/accessibility/pdf/leader.pdf b/test/pdf/accessibility/pdf/leader.pdf Binary files differindex d270c25a1..4b91dfe8e 100644 --- a/test/pdf/accessibility/pdf/leader.pdf +++ b/test/pdf/accessibility/pdf/leader.pdf diff --git a/test/pdf/accessibility/pdf/links.pdf b/test/pdf/accessibility/pdf/links.pdf Binary files differindex b2a5a4209..d2ff84ea4 100644 --- a/test/pdf/accessibility/pdf/links.pdf +++ b/test/pdf/accessibility/pdf/links.pdf diff --git a/test/pdf/accessibility/pdf/role.pdf b/test/pdf/accessibility/pdf/role.pdf Binary files differindex 329925bcd..38fcf1bde 100644 --- a/test/pdf/accessibility/pdf/role.pdf +++ b/test/pdf/accessibility/pdf/role.pdf diff --git a/test/pdf/accessibility/pdf/role_non-standard.pdf b/test/pdf/accessibility/pdf/role_non-standard.pdf Binary files differindex 84daea788..6f1edea19 100644 --- a/test/pdf/accessibility/pdf/role_non-standard.pdf +++ b/test/pdf/accessibility/pdf/role_non-standard.pdf diff --git a/test/pdf/accessibility/pdf/text_1.pdf b/test/pdf/accessibility/pdf/text_1.pdf Binary files differindex 13f01711d..bacd7a9d0 100644 --- a/test/pdf/accessibility/pdf/text_1.pdf +++ b/test/pdf/accessibility/pdf/text_1.pdf diff --git a/test/pdf/accessibility/pdf/text_2.pdf b/test/pdf/accessibility/pdf/text_2.pdf Binary files differindex 943263994..0283764cd 100644 --- a/test/pdf/accessibility/pdf/text_2.pdf +++ b/test/pdf/accessibility/pdf/text_2.pdf diff --git a/test/pdf/accessibility/pdf/text_font-embedding.pdf b/test/pdf/accessibility/pdf/text_font-embedding.pdf Binary files differindex 7ffb40af8..d1e4c6e28 100644 --- a/test/pdf/accessibility/pdf/text_font-embedding.pdf +++ b/test/pdf/accessibility/pdf/text_font-embedding.pdf diff --git a/test/pdf/accessibility/role.fo b/test/pdf/accessibility/role.fo index ced8a4d44..885638592 100644 --- a/test/pdf/accessibility/role.fo +++ b/test/pdf/accessibility/role.fo @@ -19,12 +19,17 @@ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB"> <fo:layout-master-set> <fo:simple-page-master master-name="page" - page-height="220pt" page-width="320pt" margin="10pt"> - <fo:region-body/> + page-height="240pt" page-width="320pt" margin="10pt" margin-bottom="8pt"> + <fo:region-body margin-bottom="20pt"/> + <fo:region-after extent="10pt"/> </fo:simple-page-master> </fo:layout-master-set> - <fo:page-sequence master-reference="page"> - <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif"> + <fo:page-sequence master-reference="page" role="Art"> + <fo:static-content flow-name="xsl-region-after" role="NonStruct" font-size="8pt"> + <fo:block text-align="center"><fo:page-number/></fo:block> + </fo:static-content> + <fo:flow flow-name="xsl-region-body" role="NonStruct" hyphenate="true" + font-family="sans-serif"> <fo:block role="H1" font-weight="bold" font-size="150%" space-before.minimum="1.5em" space-before.optimum="2em" |