1562429
of trunk
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_FopFontsForSVG@1562866 13f79535-47bb-0310-9956-ffa450edef68pull/22/head
@@ -563,16 +563,17 @@ list of possible build targets. | |||
<include name="org/apache/fop/apps/Fop.class"/> | |||
<include name="org/apache/fop/apps/FOPException.class"/> | |||
<include name="org/apache/fop/apps/io/**"/> | |||
<include name="org/apache/fop/area/AreaTreeControl*"/> | |||
<include name="org/apache/fop/complexscripts/fonts/*.class"/> | |||
<include name="org/apache/fop/complexscripts/util/GlyphTester.class"/> | |||
<include name="org/apache/fop/events/EventProducer.class"/> | |||
<include name="org/apache/fop/fo/Constants.class"/> | |||
<include name="org/apache/fop/fo/FOTreeBuilder.class"/> | |||
<include name="org/apache/fop/area/AreaTreeControl*"/> | |||
<include name="org/apache/fop/image/loader/batik/BatikImageFlavors*.class"/> | |||
<include name="org/apache/fop/svg/**"/> | |||
<include name="org/apache/fop/fonts/**"/> | |||
<include name="org/apache/fop/render/shading/**"/> | |||
<include name="org/apache/fop/traits/MinOptMax.class"/> | |||
<include name="org/apache/fop/image/loader/batik/BatikImageFlavors*.class"/> | |||
<include name="org/apache/fop/util/CMYKColorSpace*.class"/> | |||
<include name="org/apache/fop/util/Color*.class"/> | |||
<include name="org/apache/fop/util/ASCII*.class"/> | |||
@@ -1046,10 +1047,8 @@ NOTE: | |||
<!-- Checkstyle --> | |||
<!-- =================================================================== --> | |||
<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.5.xml" /> | |||
<path id="checkstyle-classpath"> | |||
<path refid="libs-build-classpath"/> | |||
<pathelement location="${checkstyle.location}"/> | |||
</path> | |||
<condition property="checkstyle.avail"> | |||
@@ -1057,20 +1056,18 @@ NOTE: | |||
<available classname="com.puppycrawl.tools.checkstyle.CheckStyleTask"> | |||
<classpath refid="checkstyle-classpath"/> | |||
</available> | |||
<available file="${checkstyle.noframes.xslt}"/> | |||
<available file="${checkstyle.config}"/> | |||
</and> | |||
</condition> | |||
<target name="checkstyle-avail" unless="checkstyle.avail"> | |||
<echo message="Checkstyle support NOT present. Please download it from http://checkstyle.sf.net/ and"/> | |||
<echo message="... please provide ${checkstyle.location}"/> | |||
<echo message="... please provide ${checkstyle.noframes.xslt}"/> | |||
<echo message="... please provide ${checkstyle.config}"/> | |||
</target> | |||
<target name="checkstyle" depends="package, checkstyle-avail" if="checkstyle.avail" description="Runs Checkstyle for a code quality report"> | |||
<taskdef name="checkstyle" classname="com.puppycrawl.tools.checkstyle.CheckStyleTask" classpathref="checkstyle-classpath"/> | |||
<mkdir dir="${build.dir}"/> | |||
<checkstyle config="${checkstyle.config}" failonviolation="false"> | |||
<checkstyle config="${checkstyle.config}" failonviolation="true" maxWarnings="0"> | |||
<classpath> | |||
<path refid="checkstyle-classpath"/> | |||
<pathelement location="${build.classes.dir}"/> | |||
@@ -1078,9 +1075,10 @@ NOTE: | |||
<pathelement location="${build.codegen-classes.dir}"/> | |||
</classpath> | |||
<fileset dir="${src.dir}" includes="**/*.java"/> | |||
<fileset dir="${test.dir}" includes="**/*.java"/> | |||
<formatter type="xml" toFile="${build.dir}/report_checkstyle.xml"/> | |||
<formatter type="plain"/> | |||
</checkstyle> | |||
<xslt in="${build.dir}/report_checkstyle.xml" out="${build.dir}/report_checkstyle.html" style="${checkstyle.noframes.xslt}"/> | |||
</target> | |||
<!-- =================================================================== --> | |||
<!-- PMD --> | |||
@@ -1092,6 +1090,7 @@ NOTE: | |||
<path refid="libs-tools-build-classpath"/> | |||
</classpath> | |||
</taskdef> | |||
<mkdir dir="${build.dir}"/> | |||
<pmd shortFilenames="true" targetjdk="${javac.target}"> | |||
<ruleset>basic</ruleset> | |||
<ruleset>rulesets/migrating_to_14.xml</ruleset> | |||
@@ -1510,7 +1509,7 @@ NOTE: | |||
<!-- Special target for Gump --> | |||
<!-- =================================================================== --> | |||
<target name="gump" depends="package,transcoder-pkg"/> | |||
<target name="gump-test" depends="junit-all"> | |||
<target name="gump-test" depends="junit-all,checkstyle"> | |||
<fail> | |||
<condition> | |||
<or> |
@@ -37,15 +37,25 @@ | |||
<!-- ===================================================================================================== --> | |||
<module name="SuppressionCommentFilter"> | |||
<property name="offCommentFormat" value="CSOFF\: ([\w\|]+)"/> | |||
<property name="offCommentFormat" value="CSOFF\: (LineLength)"/> | |||
<property name="onCommentFormat" value="CSON\: ([\w\|]+)"/> | |||
<property name="checkFormat" value="$1"/> | |||
</module> | |||
<!-- ===================================================================================================== --> | |||
<module name="SuppressionFilter"> | |||
<property name="file" value="${samedir}/checkstyle-suppressions.xml"/> | |||
</module> | |||
<!-- ===================================================================================================== --> | |||
<module name="TreeWalker"> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> | |||
<module name="LineLength"> | |||
<property name="max" value="120"/> | |||
</module> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> | |||
<module name="AnnotationUseStyle"/> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> | |||
@@ -172,10 +182,6 @@ | |||
<property name="allowLineBreaks" value="false"/> | |||
<property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/> | |||
</module> | |||
<module name="NoWhitespaceAfter"> | |||
<property name="allowLineBreaks" value="true"/> | |||
<property name="tokens" value="ARRAY_INIT"/> | |||
</module> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> | |||
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> |
@@ -1,8 +1,12 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> | |||
<suppressions> | |||
<suppress files="org/apache/fop/fo/FOPropertyMapping.java" checks="FileLengthCheck"/> | |||
<suppress files="org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java" checks="FileLengthCheck"/> | |||
<suppress files="org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java" checks="FileLengthCheck"/> | |||
<suppress files="org/apache/fop/Version.java" lines="40-50" checks="LineLengthCheck"/> | |||
<suppress files="org/apache/fop/afp/fonts/CharactersetEncoder.java" checks="FinalClass"/> | |||
<suppress files="org/apache/fop/complexscripts/bidi/BidiClass.java" checks="WhitespaceAfter"/> | |||
<suppress files="org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java" checks="SimplifyBooleanReturn"/> | |||
<suppress files="org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java" checks="SimplifyBooleanReturn"/> | |||
<suppress files="org/apache/fop/complexscripts/util/CharScript.java" checks="SimplifyBooleanReturn"/> | |||
<suppress files="org/apache/fop/render/rtf/rtflib/testdocs/MergedTableCells.java" checks="AvoidNestedBlocks"/> | |||
<suppress files="org/apache/fop/render/rtf/rtflib/testdocs/NestedTable.java" checks="AvoidNestedBlocks"/> | |||
<suppress files="org/apache/fop/fo/flow/MarkersTestCase.java" checks="LocalVariableName"/> | |||
</suppressions> |
@@ -2,7 +2,7 @@ | |||
<!-- examples for the use of the fo leader --> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="sans-serif"> | |||
<fo:layout-master-set> | |||
@@ -272,7 +272,7 @@ | |||
<fo:list-item> | |||
<!-- insert a bullet --> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block><fo:inline font-size="10pt" font-family="Symbol">·</fo:inline></fo:block> | |||
<fo:block><fo:inline font-size="10pt">·</fo:inline></fo:block> | |||
</fo:list-item-label> | |||
<!-- list text --> | |||
<fo:list-item-body start-indent="body-start()"> | |||
@@ -291,7 +291,7 @@ | |||
<fo:list-item> | |||
<!-- insert a bullet --> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block><fo:inline font-size="10pt" font-family="Symbol">·</fo:inline></fo:block> | |||
<fo:block><fo:inline font-size="10pt">·</fo:inline></fo:block> | |||
</fo:list-item-label> | |||
<!-- list text --> | |||
<fo:list-item-body start-indent="body-start()"> | |||
@@ -391,7 +391,7 @@ | |||
<fo:table-row line-height="12pt"> | |||
<fo:table-cell><fo:block text-align="end">A) </fo:block></fo:table-cell> | |||
<fo:table-cell><fo:block text-align="start">This is some longer sample text<fo:leader leader-pattern="dots" | |||
<fo:table-cell><fo:block text-align="start" text-align-last="justify">This is some longer sample text<fo:leader leader-pattern="dots" | |||
leader-pattern-width="8pt" | |||
leader-alignment="reference-area" | |||
/></fo:block></fo:table-cell> | |||
@@ -401,7 +401,7 @@ | |||
<fo:table-row line-height="12pt"> | |||
<fo:table-cell><fo:block text-align="end">B) </fo:block></fo:table-cell> | |||
<fo:table-cell><fo:block text-align="start">Some text<fo:leader leader-pattern="dots" | |||
<fo:table-cell><fo:block text-align="start" text-align-last="justify">Some text<fo:leader leader-pattern="dots" | |||
leader-pattern-width="8pt" | |||
leader-alignment="reference-area" | |||
/></fo:block></fo:table-cell> | |||
@@ -410,7 +410,7 @@ | |||
<fo:table-row line-height="12pt"> | |||
<fo:table-cell><fo:block text-align="end" >C) </fo:block></fo:table-cell> | |||
<fo:table-cell><fo:block text-align="start">Text<fo:leader leader-pattern="dots" | |||
<fo:table-cell><fo:block text-align="start" text-align-last="justify">Text<fo:leader leader-pattern="dots" | |||
leader-pattern-width="8pt" | |||
leader-alignment="reference-area" | |||
/></fo:block></fo:table-cell> | |||
@@ -419,7 +419,7 @@ | |||
<fo:table-row line-height="12pt"> | |||
<fo:table-cell><fo:block text-align="end">D) </fo:block></fo:table-cell> | |||
<fo:table-cell><fo:block text-align="start">This text is even longer than the first entry <fo:leader leader-pattern="dots" | |||
<fo:table-cell><fo:block text-align="start" text-align-last="justify">This text is even longer than the first entry <fo:leader leader-pattern="dots" | |||
leader-pattern-width="8pt" | |||
leader-alignment="reference-area" | |||
/></fo:block></fo:table-cell> | |||
@@ -428,7 +428,7 @@ | |||
<fo:table-row line-height="12pt"> | |||
<fo:table-cell><fo:block text-align="end">E) </fo:block></fo:table-cell> | |||
<fo:table-cell><fo:block text-align="start">Shorter text example<fo:leader leader-pattern="dots" | |||
<fo:table-cell><fo:block text-align="start" text-align-last="justify">Shorter text example<fo:leader leader-pattern="dots" | |||
leader-pattern-width="8pt" | |||
leader-alignment="reference-area" | |||
/></fo:block></fo:table-cell> |
@@ -1,37 +1,7 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<FindBugsFilter> | |||
<Match> | |||
<Class name="org.apache.fop.layoutmgr.inline.TextLayoutManager$TextAreaBuilder"/> | |||
<Method name="getMappingBidiLevels"/> | |||
<Bug pattern="PZLA_PREFER_ZERO_LENGTH_ARRAYS"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.svg.PDFTextPainter"/> | |||
<Field name="pdf"/> | |||
<Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.ps.PSTextPainter"/> | |||
<Or> | |||
<Field name="gen"/> | |||
<Field name="ps"/> | |||
<Field name="psRun"/> | |||
<Field name="textUtil"/> | |||
</Or> | |||
<Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.GlyphMapping"/> | |||
<Method name="<init>"/> | |||
<Bug pattern="EI_EXPOSE_REP2"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.MultiByteFont"/> | |||
<Method name="setBBoxArray"/> | |||
<Bug pattern="EI_EXPOSE_REP2"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile$1"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont$1"/> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> | |||
</Match> | |||
<Match> | |||
@@ -438,6 +408,11 @@ | |||
<Method name="buildCIDSet"/> | |||
<Bug pattern="OS_OPEN_STREAM"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.pdf.PDFFactory"/> | |||
<Method name="makeFont"/> | |||
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.pdf.PDFOutputIntent"/> | |||
<Method name="toPDF"/> | |||
@@ -864,7 +839,7 @@ | |||
<Bug pattern="BIT_IOR_OF_SIGNED_BYTE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/> | |||
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/> | |||
<Method name="toString"/> | |||
<Bug pattern="DMI_INVOKING_TOSTRING_ON_ARRAY"/> | |||
</Match> | |||
@@ -1019,7 +994,7 @@ | |||
<Bug pattern="UWF_UNWRITTEN_FIELD"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/> | |||
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/> | |||
<Field name="checksum"/> | |||
<Bug pattern="UWF_UNWRITTEN_FIELD"/> | |||
</Match> | |||
@@ -2173,37 +2148,37 @@ | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="glyphToUnicode"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="initAnsiWidths"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="readKerning"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="readUnicodeCmap"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="unicodeToGlyph"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="unicodeToWinAnsi"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile$UnicodeMapping"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont$UnicodeMapping"/> | |||
<Method name="<init>"/> | |||
<Bug pattern="DM_NUMBER_CTOR"/> | |||
</Match> | |||
@@ -2653,7 +2628,7 @@ | |||
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="unicodeToWinAnsi"/> | |||
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> | |||
</Match> | |||
@@ -2882,7 +2857,7 @@ | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile$UnicodeMapping"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont$UnicodeMapping"/> | |||
<!--Neither method nor field--> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS"/> | |||
</Match> | |||
@@ -2932,7 +2907,7 @@ | |||
<Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="printMaxMin"/> | |||
<Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/> | |||
</Match> | |||
@@ -3112,7 +3087,7 @@ | |||
<Bug pattern="WMI_WRONG_MAP_ITERATOR"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="readKerning"/> | |||
<Bug pattern="WMI_WRONG_MAP_ITERATOR"/> | |||
</Match> | |||
@@ -3777,7 +3752,7 @@ | |||
<Bug pattern="DLS_DEAD_LOCAL_STORE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFFile"/> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Method name="readFont"/> | |||
<Bug pattern="DLS_DEAD_LOCAL_STORE"/> | |||
</Match> | |||
@@ -5051,7 +5026,7 @@ | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/> | |||
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/> | |||
<Method name="getTag"/> | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
</Match> | |||
@@ -5256,4 +5231,206 @@ | |||
</Or> | |||
<Bug pattern="BC_UNCONFIRMED_CAST"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.fo.properties.CommonAural"/> | |||
<Class name="org.apache.fop.fo.properties.CommonMarginInline"/> | |||
<Class name="org.apache.fop.render.pdf.PDFSVGHandler$PDFInfo"/> | |||
<Class name="org.apache.fop.fo.properties.CommonRelativePosition"/> | |||
</Or> | |||
<Or> | |||
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD"/> | |||
<Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$CheckBoxLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$ComboBoxLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$InputLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$MultilineInputLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$RadioButtonLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.forms.FormLayoutManagerMakerProvider$TriggerLayoutManagerMaker"/> | |||
<Class name="org.apache.fop.render.intermediate.IFRenderer$1"/> | |||
<Class name="org.apache.fop.render.intermediate.IFRenderer$3"/> | |||
<Class name="org.apache.fop.render.intermediate.IFRenderer$4"/> | |||
<Class name="org.apache.fop.render.intermediate.IFRenderer$5"/> | |||
<Class name="org.apache.fop.render.intermediate.IFRenderer$6"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$InputPainter"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$MultilineInputPainter"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$RadioButtonPainter"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$TriggerPainter"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$ComboBoxPainter"/> | |||
<Class name="org.apache.fop.render.pdf.PDFPainter$CheckboxPainter"/> | |||
</Or> | |||
<Or> | |||
<Bug pattern="BC_UNCONFIRMED_CAST"/> | |||
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.fo.flow.Float"/> | |||
<Class name="org.apache.fop.fo.flow.MultiCase"/> | |||
<Class name="org.apache.fop.fo.flow.MultiProperties"/> | |||
<Class name="org.apache.fop.fo.flow.MultiPropertySet"/> | |||
<Class name="org.apache.fop.fo.flow.MultiSwitch"/> | |||
<Class name="org.apache.fop.fo.flow.MultiToggle"/> | |||
<Class name="org.apache.fop.fo.flow.table.TableAndCaption"/> | |||
<Class name="org.apache.fop.fo.flow.table.TableCaption"/> | |||
<Class name="org.apache.fop.fonts.apps.AbstractFontReader"/> | |||
<Class name="org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement"/> | |||
</Or> | |||
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.pdf.PDFFunction"/> | |||
<Class name="org.apache.fop.pdf.PDFGoTo"/> | |||
<Class name="org.apache.fop.pdf.PDFLink"/> | |||
<Class name="org.apache.fop.pdf.PDFPattern"/> | |||
<Class name="org.apache.fop.svg.ACIUtils"/> | |||
<Class name="org.apache.fop.svg.PDFTextPainter"/> | |||
</Or> | |||
<Bug pattern="FE_FLOATING_POINT_EQUALITY"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.area.BodyRegion"/> | |||
<Class name="org.apache.fop.area.Page"/> | |||
<Class name="org.apache.fop.area.PageViewport"/> | |||
<Class name="org.apache.fop.area.RegionReference"/> | |||
<Class name="org.apache.fop.area.RegionViewport"/> | |||
<Class name="org.apache.fop.hyphenation.CharVector"/> | |||
<Class name="org.apache.fop.hyphenation.TernaryTree"/> | |||
<Class name="org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes"/> | |||
</Or> | |||
<Bug pattern="CN_IDIOM_NO_SUPER_CALL"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.forms.CheckBoxArea"/> | |||
<Class name="org.apache.fop.forms.ComboBox"/> | |||
<Class name="org.apache.fop.forms.RadioButtonArea"/> | |||
</Or> | |||
<Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.layoutmgr.PageBreaker"/> | |||
<Class name="org.apache.fop.layoutmgr.BlockContainerLayoutManager"/> | |||
</Or> | |||
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.layoutmgr.BlockContainerLayoutManager"/> | |||
<Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.OpenFont"/> | |||
<Bug pattern="DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.apps.io.ResourceResolverFactory$FileDeletingInputStream"/> | |||
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fo.properties.FontFamilyProperty"/> | |||
<Bug pattern="EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.ps.PSImageObject"/> | |||
<Or> | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
<Bug pattern="EI_EXPOSE_REP2"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.cff.CFFDataReader"/> | |||
<Bug pattern="DM_DEFAULT_ENCODING"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.cff.CFFDataReader$CFFIndexData"/> | |||
<Or> | |||
<Bug pattern="SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH"/> | |||
<Bug pattern="SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.cff.CFFDataReader$CFFSubTable"/> | |||
<Or> | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
<Bug pattern="EI_EXPOSE_REP2"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.cff.CFFDataReader$DICTEntry"/> | |||
<Or> | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
<Bug pattern="EI_EXPOSE_REP2"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.OTFFile"/> | |||
<Or> | |||
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> | |||
<Bug pattern="DM_DEFAULT_ENCODING"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.OTFSubSetFile"/> | |||
<Or> | |||
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/> | |||
<Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> | |||
<Bug pattern="DM_DEFAULT_ENCODING"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.OTFSubSetFile$1"/> | |||
<Or> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> | |||
</Or> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.fonts.truetype.OTFSubSetFile$FDIndexReference"/> | |||
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.ps.PSFontUtils"/> | |||
<Bug pattern="DM_DEFAULT_ENCODING"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.forms.IField$Field"/> | |||
<Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED"/> | |||
</Match> | |||
<Match> | |||
<Or> | |||
<Class name="org.apache.fop.forms.IField$Field"/> | |||
<Class name="org.apache.fop.forms.TriggerArea"/> | |||
<Class name="org.apache.fop.forms.traits.AdditionalActionTrait"/> | |||
</Or> | |||
<Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.pdf.extensions.PDFExtensionHandlerFactory"/> | |||
<Method name="getSupportedNamespaces"/> | |||
<Bug pattern="EI_EXPOSE_REP"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryEntryExtension"/> | |||
<Method name="getValueAsNumber"/> | |||
<Bug pattern="FE_FLOATING_POINT_EQUALITY"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryType"/> | |||
<Method name="hasValueOfElementName"/> | |||
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/> | |||
</Match> | |||
<Match> | |||
<Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryEntryType"/> | |||
<Method name="hasValueOfElementName"/> | |||
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/> | |||
</Match> | |||
</FindBugsFilter> |
@@ -0,0 +1,395 @@ | |||
Index: fontbox/src/test/java/org/apache/fontbox/cff/CharStringRendererTest.java | |||
=================================================================== | |||
--- fontbox/src/test/java/org/apache/fontbox/cff/CharStringRendererTest.java (revision 0) | |||
+++ fontbox/src/test/java/org/apache/fontbox/cff/CharStringRendererTest.java (revision 0) | |||
@@ -0,0 +1,28 @@ | |||
+package org.apache.fontbox.cff; | |||
+ | |||
+import java.util.ArrayList; | |||
+import java.util.List; | |||
+ | |||
+import org.junit.Test; | |||
+ | |||
+import static org.junit.Assert.assertTrue; | |||
+ | |||
+public class CharStringRendererTest { | |||
+ | |||
+ @Test | |||
+ public void testArgumentValidation() { | |||
+ CharStringRenderer renderer = new CharStringRenderer(); | |||
+ List<Integer> numbers = new ArrayList<Integer>(); | |||
+ for (int i = 0;i < 4;i++) { | |||
+ numbers.add(1); | |||
+ } | |||
+ assertTrue(renderer.hasValidArguments("vhcurveto", numbers)); | |||
+ numbers.add(1); | |||
+ assertTrue(renderer.hasValidArguments("vvcurveto", numbers)); | |||
+ for (int i = 0;i < 3;i++) { | |||
+ numbers.add(1); | |||
+ } | |||
+ assertTrue(renderer.hasValidArguments("rcurveline", numbers)); | |||
+ } | |||
+ | |||
+} | |||
Index: fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java | |||
=================================================================== | |||
--- fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java (revision 1546564) | |||
+++ fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java (working copy) | |||
@@ -27,7 +27,7 @@ | |||
/** | |||
* This class creates all needed AFM font metric data from a CFFFont ready to be read from a AFMPaser. | |||
- * | |||
+ * | |||
* @author Villu Ruusmann | |||
* @version $Revision$ | |||
*/ | |||
@@ -125,7 +125,7 @@ | |||
metric.name = mapping.getName(); | |||
renderer.render(mapping.toType1Sequence()); | |||
metric.width = renderer.getWidth(); | |||
- metric.bounds = renderer.getBounds(); | |||
+ metric.bounds = renderer.getBounds2D(); | |||
metrics.add(metric); | |||
} | |||
return metrics; | |||
@@ -150,7 +150,7 @@ | |||
} | |||
/** | |||
- * This class represents the metric of one single character. | |||
+ * This class represents the metric of one single character. | |||
* | |||
*/ | |||
private static class CharMetric implements Comparable<CharMetric> | |||
Index: fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java | |||
=================================================================== | |||
--- fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java (revision 1546564) | |||
+++ fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java (working copy) | |||
@@ -16,9 +16,11 @@ | |||
*/ | |||
package org.apache.fontbox.cff; | |||
+import java.awt.Point; | |||
import java.awt.geom.GeneralPath; | |||
import java.awt.geom.Point2D; | |||
import java.awt.geom.Rectangle2D; | |||
+import java.util.HashMap; | |||
import java.util.List; | |||
import org.apache.commons.logging.Log; | |||
@@ -33,7 +35,7 @@ | |||
{ | |||
// TODO CharStringRenderer as abstract Class with two inherited classes according to the Charsstring type.... | |||
private static final Log LOG = LogFactory.getLog(CharStringRenderer.class); | |||
- | |||
+ | |||
private boolean isCharstringType1 = true; | |||
private boolean isFirstCommand = true; | |||
@@ -42,6 +44,8 @@ | |||
private Point2D referencePoint = null; | |||
private int width = 0; | |||
private boolean hasNonEndCharOp = false; | |||
+ private int[] bbox = {0,0,0,0}; | |||
+ private HashMap<String, String> vStrings; | |||
/** | |||
* Constructor for the char string renderer. | |||
@@ -100,7 +104,7 @@ | |||
private void handleCommandType2(List<Integer> numbers, CharStringCommand command) | |||
{ | |||
String name = CharStringCommand.TYPE2_VOCABULARY.get(command.getKey()); | |||
- | |||
+ checkArguments(name, numbers); | |||
if (!hasNonEndCharOp) | |||
{ | |||
hasNonEndCharOp = !"endchar".equals(name); | |||
@@ -176,7 +180,7 @@ | |||
setWidth(numbers.get(0)); | |||
rmoveTo(numbers.get(1), numbers.get(2)); | |||
} | |||
- else | |||
+ else if (numbers.size() == 2) | |||
{ | |||
rmoveTo(numbers.get(0), numbers.get(1)); | |||
} | |||
@@ -192,7 +196,7 @@ | |||
setWidth(numbers.get(0)); | |||
rmoveTo(numbers.get(1), Integer.valueOf(0)); | |||
} | |||
- else | |||
+ else if (numbers.size() == 1) | |||
{ | |||
rmoveTo(numbers.get(0), Integer.valueOf(0)); | |||
} | |||
@@ -284,6 +288,61 @@ | |||
} | |||
} | |||
+ void checkArguments(String name, List<Integer> numbers) { | |||
+ if (name == null) { | |||
+ return; | |||
+ } | |||
+ boolean valid = hasValidArguments(name, numbers); | |||
+ if (!valid) { | |||
+ //Initialize the validation strings if not already done | |||
+ if (vStrings == null) { | |||
+ vStrings = new HashMap<String, String>(); | |||
+ vStrings.put("vmoveto", "1 || 2"); | |||
+ vStrings.put("rlineto", "3 || % 2"); | |||
+ vStrings.put("rrcurveto", "7 || % 6"); | |||
+ vStrings.put("rlinecurve", "% 2 || 6 + % 2"); | |||
+ vStrings.put("rcurveline", "% 6 || 2 + % 6"); | |||
+ vStrings.put("rmoveto", "2 || 3"); | |||
+ vStrings.put("hmoveto", "1 || 2"); | |||
+ vStrings.put("vhcurveto", "% 4 || 1 + % 4"); | |||
+ vStrings.put("hvcurveto", "% 4 || 1 + % 4"); | |||
+ vStrings.put("vvcurveto", "% 4 || 1 + % 4"); | |||
+ } | |||
+ LOG.info(String.format("Font has an unexpected number of parameters for operator '%s'. Arguments "+ | |||
+ "size %d did not match pattern '%s'", name, numbers.size(), | |||
+ vStrings.get(name))); | |||
+ } | |||
+ } | |||
+ | |||
+ boolean hasValidArguments(String name, List<Integer> numbers) { | |||
+ boolean valid = true; | |||
+ if (name.equals("vmoveto")) { | |||
+ valid = (numbers.size() == 1 || numbers.size() == 2); | |||
+ } | |||
+ if (name.equals("rlineto")) { | |||
+ valid = (numbers.size() == 3 || numbers.size() % 2 == 0); | |||
+ } | |||
+ if (name.equals("rrcurveto")) { | |||
+ valid = (numbers.size() == 7 || numbers.size() % 6 == 0); | |||
+ } | |||
+ if (name.equals("rlinecurve")) { | |||
+ valid = (numbers.size() % 2 == 0 || (numbers.size() - 6) % 2 == 0); | |||
+ } | |||
+ if (name.equals("rcurveline")) { | |||
+ valid = (numbers.size() % 6 == 0 || (numbers.size() - 2) % 6 == 0); | |||
+ } | |||
+ if (name.equals("rmoveto")) { | |||
+ valid = (numbers.size() == 2 || numbers.size() == 3); | |||
+ } | |||
+ if (name.equals("hmoveto")) { | |||
+ valid = (numbers.size() == 1 || numbers.size() == 2); | |||
+ } | |||
+ if (name.equals("vvcurveto") || name.equals("vhcurveto") || name.equals("hvcurveto")) { | |||
+ valid = (numbers.size() % 4 == 0 || (numbers.size() - 1) % 4 == 0); | |||
+ } | |||
+ return valid; | |||
+ } | |||
+ | |||
/** | |||
* | |||
* @param numbers | |||
@@ -353,11 +412,14 @@ | |||
Point2D point = referencePoint; | |||
if (point == null) | |||
{ | |||
- point = path.getCurrentPoint(); | |||
- if (point == null) | |||
+ if (path.getCurrentPoint() == null) | |||
{ | |||
point = sidebearingPoint; | |||
} | |||
+ else | |||
+ { | |||
+ point = path.getCurrentPoint(); | |||
+ } | |||
} | |||
referencePoint = null; | |||
path.moveTo((float)(point.getX() + dx.doubleValue()), | |||
@@ -397,15 +459,20 @@ | |||
private void rlineTo(Number dx, Number dy) | |||
{ | |||
Point2D point = path.getCurrentPoint(); | |||
- path.lineTo((float)(point.getX() + dx.doubleValue()), | |||
- (float)(point.getY() + dy.doubleValue())); | |||
+ if (point != null) { | |||
+ updateBBox(dx.intValue(), dy.intValue()); | |||
+ path.lineTo((float)(point.getX() + dx.doubleValue()), | |||
+ (float)(point.getY() + dy.doubleValue())); | |||
+ } | |||
} | |||
private void rrlineTo(List<Integer> numbers) | |||
{ | |||
for (int i = 0;i < numbers.size();i += 2) | |||
{ | |||
- rlineTo(numbers.get(i), numbers.get(i + 1)); | |||
+ if (numbers.size() - i >= 2) { | |||
+ rlineTo(numbers.get(i), numbers.get(i + 1)); | |||
+ } | |||
} | |||
} | |||
@@ -415,13 +482,15 @@ | |||
{ | |||
for (int i = 0;i < numbers.size();i += 6) | |||
{ | |||
- float x1 = numbers.get(i); | |||
- float y1 = numbers.get(i + 1); | |||
- float x2 = numbers.get(i + 2); | |||
- float y2 = numbers.get(i + 3); | |||
- float x3 = numbers.get(i + 4); | |||
- float y3 = numbers.get(i + 5); | |||
- rrcurveTo(x1, y1, x2, y2, x3, y3); | |||
+ if (numbers.size() - i >= 6) { | |||
+ float x1 = numbers.get(i); | |||
+ float y1 = numbers.get(i + 1); | |||
+ float x2 = numbers.get(i + 2); | |||
+ float y2 = numbers.get(i + 3); | |||
+ float x3 = numbers.get(i + 4); | |||
+ float y3 = numbers.get(i + 5); | |||
+ rrcurveTo(x1, y1, x2, y2, x3, y3); | |||
+ } | |||
} | |||
} | |||
} | |||
@@ -429,14 +498,42 @@ | |||
private void rrcurveTo(Number dx1, Number dy1, Number dx2, Number dy2, | |||
Number dx3, Number dy3) | |||
{ | |||
- Point2D point = path.getCurrentPoint(); | |||
- float x1 = (float) point.getX() + dx1.floatValue(); | |||
- float y1 = (float) point.getY() + dy1.floatValue(); | |||
- float x2 = x1 + dx2.floatValue(); | |||
- float y2 = y1 + dy2.floatValue(); | |||
- float x3 = x2 + dx3.floatValue(); | |||
- float y3 = y2 + dy3.floatValue(); | |||
- path.curveTo(x1, y1, x2, y2, x3, y3); | |||
+ Point2D p0 = path.getCurrentPoint(); | |||
+ if (p0 != null) { | |||
+ float x1 = (float) p0.getX() + dx1.floatValue(); | |||
+ float y1 = (float) p0.getY() + dy1.floatValue(); | |||
+ float x2 = x1 + dx2.floatValue(); | |||
+ float y2 = y1 + dy2.floatValue(); | |||
+ float x3 = x2 + dx3.floatValue(); | |||
+ float y3 = y2 + dy3.floatValue( ); | |||
+ | |||
+ Point p1 = new Point((int)x1, (int)y1); | |||
+ Point p2 = new Point((int)x2, (int)y2); | |||
+ Point p3 = new Point((int)x3, (int)y3); | |||
+ | |||
+ updateBBox((int)p0.getX(), (int)p0.getY()); | |||
+ updateBBox((int)p3.getX(), (int)p3.getY()); | |||
+ | |||
+ int[] abc = calculateABC((int)p0.getX(), p1.x, p2.x, p3.x); | |||
+ double[] txs = getT(abc); | |||
+ for (double tx : txs) { | |||
+ if (tx > 0 && tx < 1) { | |||
+ int[] XandY = getXandY(tx, new Point((int)p0.getX(), (int)p0.getY()), p1, p2, p3); | |||
+ updateBBox(XandY[0], XandY[1]); | |||
+ } | |||
+ } | |||
+ | |||
+ abc = calculateABC((int)p0.getY(), p1.y, p2.y, p3.y); | |||
+ double[] tys = getT(abc); | |||
+ for (double ty : tys) { | |||
+ if (ty > 0 && ty < 1) { | |||
+ int[] XandY = getXandY(ty, new Point((int)p0.getX(), (int)p0.getY()), p1, p2, p3); | |||
+ updateBBox(XandY[0], XandY[1]); | |||
+ } | |||
+ } | |||
+ | |||
+ path.curveTo(x1, y1, x2, y2, x3, y3); | |||
+ } | |||
} | |||
@@ -646,7 +743,9 @@ | |||
private void closePath() | |||
{ | |||
referencePoint = path.getCurrentPoint(); | |||
- path.closePath(); | |||
+ if (referencePoint != null) { | |||
+ path.closePath(); | |||
+ } | |||
} | |||
private void pointSb(Number x, Number y) | |||
@@ -658,11 +757,15 @@ | |||
* Returns the bounds of the renderer path. | |||
* @return the bounds as Rectangle2D | |||
*/ | |||
- public Rectangle2D getBounds() | |||
+ public int[] getBounds() | |||
{ | |||
- return path.getBounds2D(); | |||
+ return bbox; | |||
} | |||
+ public Rectangle2D getBounds2D() { | |||
+ return path.getBounds2D(); | |||
+ } | |||
+ | |||
/** | |||
* Returns the width of the current command. | |||
* @return the width | |||
@@ -676,4 +779,61 @@ | |||
{ | |||
this.width = aWidth; | |||
} | |||
-} | |||
\ No newline at end of file | |||
+ | |||
+ private int[] calculateABC(int p0, int p1, int p2, int p3) { | |||
+ int[] abc = new int[3]; | |||
+ abc[0] = p0 - 3 * p1 + 3 * p2 - p3; | |||
+ abc[1] = 2 * (-p0 + 2 * p1 - p2); | |||
+ abc[2] = p0 - p1; | |||
+ return abc; | |||
+ } | |||
+ | |||
+ private double[] getT(int[] abc) { | |||
+ double[] t = {-1, -1}; | |||
+ int a = abc[0]; | |||
+ int b = abc[1]; | |||
+ int c = abc[2]; | |||
+ double s = Math.pow(b, 2) - 4 * a * c; | |||
+ if (a == 0) { | |||
+ if (b != 0) { | |||
+ t[0] = -c / b; | |||
+ } | |||
+ return t; | |||
+ } else if (s > 0) { | |||
+ t[0] = (-b + Math.sqrt(s)) / 2 / a; | |||
+ t[1] = (-b - Math.sqrt(s)) / 2 / a; | |||
+ return t; | |||
+ } else if (s == 0) { | |||
+ t[0] = -b / 2 / a; | |||
+ return t; | |||
+ } else { | |||
+ return t; | |||
+ } | |||
+ } | |||
+ | |||
+ private int[] getXandY(double t, Point p0, Point p1, Point p2, Point p3) { | |||
+ int[] XandY = new int[2]; | |||
+ double p0Coeff = Math.pow(1 - t, 3); | |||
+ double p1Coeff = 3 * t * Math.pow(1 - t, 2); | |||
+ double p2Coeff = 3 * Math.pow(t, 2) * (1 - t); | |||
+ double p3Coeff = Math.pow(t, 3); | |||
+ double x = p0Coeff * p0.x + p1Coeff * p1.x + p2Coeff * p2.x + p3Coeff * p3.x; | |||
+ double y = p0Coeff * p0.y + p1Coeff * p1.y + p2Coeff * p2.y + p3Coeff * p3.y; | |||
+ XandY[0] = (int)x; | |||
+ XandY[1] = (int)y; | |||
+ return XandY; | |||
+ } | |||
+ | |||
+ private void updateBBox(int x, int y) { | |||
+ if (x < bbox[0]) { | |||
+ bbox[0] = x; | |||
+ } else if (x > bbox[2]) { | |||
+ bbox[2] = x; | |||
+ } | |||
+ if (y < bbox[1]) { | |||
+ bbox[1] = y; | |||
+ } else if (y > bbox[3]) { | |||
+ bbox[3] = y; | |||
+ } | |||
+ } | |||
+} |
@@ -0,0 +1,738 @@ | |||
Index: fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java | |||
=================================================================== | |||
--- fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java (revision 1546564) | |||
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java (working copy) | |||
@@ -36,7 +36,7 @@ | |||
import org.apache.fontbox.cff.encoding.CFFStandardEncoding; | |||
/** | |||
- * This class represents a parser for a CFF font. | |||
+ * This class represents a parser for a CFF font. | |||
* @author Villu Ruusmann | |||
* @version $Revision: 1.0 $ | |||
*/ | |||
@@ -107,7 +107,11 @@ | |||
{ | |||
input.setPosition(0); | |||
} | |||
+ return parse(input); | |||
+ } | |||
+ public List<CFFFont> parse(CFFDataInput input) throws IOException { | |||
+ this.input = input; | |||
header = readHeader(input); | |||
nameIndex = readIndexData(input); | |||
topDictIndex = readIndexData(input); | |||
@@ -119,6 +123,7 @@ | |||
{ | |||
CFFFont font = parseFont(i); | |||
font.setGlobalSubrIndex(globalSubrIndex); | |||
+ font.constructMappings(); | |||
fonts.add(font); | |||
} | |||
return fonts; | |||
@@ -145,7 +150,7 @@ | |||
return cffHeader; | |||
} | |||
- private static IndexData readIndexData(CFFDataInput input) throws IOException | |||
+ public static IndexData readIndexData(CFFDataInput input) throws IOException | |||
{ | |||
int count = input.readCard16(); | |||
IndexData index = new IndexData(count); | |||
@@ -179,7 +184,8 @@ | |||
return dict; | |||
} | |||
- private static DictData.Entry readEntry(CFFDataInput input) throws IOException | |||
+ private static DictData.Entry readEntry(CFFDataInput input) | |||
+ throws IOException | |||
{ | |||
DictData.Entry entry = new DictData.Entry(); | |||
while (true) | |||
@@ -211,13 +217,15 @@ | |||
return entry; | |||
} | |||
- private static CFFOperator readOperator(CFFDataInput input, int b0) throws IOException | |||
+ private static CFFOperator readOperator(CFFDataInput input, int b0) | |||
+ throws IOException | |||
{ | |||
CFFOperator.Key key = readOperatorKey(input, b0); | |||
return CFFOperator.getOperator(key); | |||
} | |||
- private static CFFOperator.Key readOperatorKey(CFFDataInput input, int b0) throws IOException | |||
+ private static CFFOperator.Key readOperatorKey(CFFDataInput input, int b0) | |||
+ throws IOException | |||
{ | |||
if (b0 == 12) | |||
{ | |||
@@ -227,7 +235,8 @@ | |||
return new CFFOperator.Key(b0); | |||
} | |||
- private static Integer readIntegerNumber(CFFDataInput input, int b0) throws IOException | |||
+ private static Integer readIntegerNumber(CFFDataInput input, int b0) | |||
+ throws IOException | |||
{ | |||
if (b0 == 28) | |||
{ | |||
@@ -263,7 +272,8 @@ | |||
} | |||
} | |||
- private static Double readRealNumber(CFFDataInput input, int b0) throws IOException | |||
+ private static Double readRealNumber(CFFDataInput input, int b0) | |||
+ throws IOException | |||
{ | |||
StringBuffer sb = new StringBuffer(); | |||
boolean done = false; | |||
@@ -446,9 +456,9 @@ | |||
throw new IOException("FDArray is missing for a CIDKeyed Font."); | |||
} | |||
- int fontDictOffset = fdArrayEntry.getNumber(0).intValue(); | |||
- input.setPosition(fontDictOffset); | |||
- IndexData fdIndex = readIndexData(input); | |||
+ int fontDictOffset = fdArrayEntry.getNumber(0).intValue(); | |||
+ input.setPosition(fontDictOffset); | |||
+ IndexData fdIndex = readIndexData(input); | |||
List<Map<String, Object>> privateDictionaries = new LinkedList<Map<String, Object>>(); | |||
List<Map<String, Object>> fontDictionaries = new LinkedList<Map<String, Object>>(); | |||
@@ -577,8 +587,8 @@ | |||
{ | |||
return CFFStandardString.getName(index); | |||
} | |||
- if (index - 391 <= stringIndex.getCount()) | |||
- { | |||
+ if (index - 391 < stringIndex.getCount()) | |||
+ { | |||
DataInput dataInput = new DataInput(stringIndex.getBytes(index - 391)); | |||
return dataInput.getString(); | |||
} | |||
@@ -620,7 +630,8 @@ | |||
return entry != null ? entry.getArray() : defaultValue; | |||
} | |||
- private CFFEncoding readEncoding(CFFDataInput dataInput, int[] gids) throws IOException | |||
+ private CFFEncoding readEncoding(CFFDataInput dataInput, int[] gids) | |||
+ throws IOException | |||
{ | |||
int format = dataInput.readCard8(); | |||
int baseFormat = format & 0x7f; | |||
@@ -639,7 +650,8 @@ | |||
} | |||
} | |||
- private Format0Encoding readFormat0Encoding(CFFDataInput dataInput, int format, int[] gids) throws IOException | |||
+ private Format0Encoding readFormat0Encoding(CFFDataInput dataInput, int format, | |||
+ int[] gids) throws IOException | |||
{ | |||
Format0Encoding encoding = new Format0Encoding(); | |||
encoding.format = format; | |||
@@ -657,7 +669,8 @@ | |||
return encoding; | |||
} | |||
- private Format1Encoding readFormat1Encoding(CFFDataInput dataInput, int format, int[] gids) throws IOException | |||
+ private Format1Encoding readFormat1Encoding(CFFDataInput dataInput, int format, | |||
+ int[] gids) throws IOException | |||
{ | |||
Format1Encoding encoding = new Format1Encoding(); | |||
encoding.format = format; | |||
@@ -683,7 +696,8 @@ | |||
return encoding; | |||
} | |||
- private void readSupplement(CFFDataInput dataInput, EmbeddedEncoding encoding) throws IOException | |||
+ private void readSupplement(CFFDataInput dataInput, EmbeddedEncoding encoding) | |||
+ throws IOException | |||
{ | |||
encoding.nSups = dataInput.readCard8(); | |||
encoding.supplement = new EmbeddedEncoding.Supplement[encoding.nSups]; | |||
@@ -738,15 +752,14 @@ | |||
fdselect.fds = new int[nGlyphs]; | |||
for (int i = 0; i < fdselect.fds.length; i++) | |||
{ | |||
- fdselect.fds[i] = dataInput.readCard8(); | |||
- | |||
+ fdselect.fds[i] = dataInput.readCard8(); | |||
} | |||
return fdselect; | |||
} | |||
/** | |||
* Read the Format 3 of the FDSelect data structure. | |||
- * | |||
+ * | |||
* @param dataInput | |||
* @param format | |||
* @param nGlyphs | |||
@@ -768,7 +781,6 @@ | |||
r3.first = dataInput.readCard16(); | |||
r3.fd = dataInput.readCard8(); | |||
fdselect.range3[i] = r3; | |||
- | |||
} | |||
fdselect.sentinel = dataInput.readCard16(); | |||
@@ -902,7 +914,8 @@ | |||
} | |||
} | |||
- private CFFCharset readCharset(CFFDataInput dataInput, int nGlyphs) throws IOException | |||
+ private CFFCharset readCharset(CFFDataInput dataInput, int nGlyphs) | |||
+ throws IOException | |||
{ | |||
int format = dataInput.readCard8(); | |||
if (format == 0) | |||
@@ -923,7 +936,8 @@ | |||
} | |||
} | |||
- private Format0Charset readFormat0Charset(CFFDataInput dataInput, int format, int nGlyphs) throws IOException | |||
+ private Format0Charset readFormat0Charset(CFFDataInput dataInput, int format, | |||
+ int nGlyphs) throws IOException | |||
{ | |||
Format0Charset charset = new Format0Charset(); | |||
charset.format = format; | |||
@@ -936,7 +950,8 @@ | |||
return charset; | |||
} | |||
- private Format1Charset readFormat1Charset(CFFDataInput dataInput, int format, int nGlyphs) throws IOException | |||
+ private Format1Charset readFormat1Charset(CFFDataInput dataInput, int format, | |||
+ int nGlyphs) throws IOException | |||
{ | |||
Format1Charset charset = new Format1Charset(); | |||
charset.format = format; | |||
@@ -957,7 +972,8 @@ | |||
return charset; | |||
} | |||
- private Format2Charset readFormat2Charset(CFFDataInput dataInput, int format, int nGlyphs) throws IOException | |||
+ private Format2Charset readFormat2Charset(CFFDataInput dataInput, int format, | |||
+ int nGlyphs) throws IOException | |||
{ | |||
Format2Charset charset = new Format2Charset(); | |||
charset.format = format; | |||
@@ -981,7 +997,7 @@ | |||
} | |||
/** | |||
- * Inner class holding the header of a CFF font. | |||
+ * Inner class holding the header of a CFF font. | |||
*/ | |||
private static class Header | |||
{ | |||
@@ -999,7 +1015,7 @@ | |||
} | |||
/** | |||
- * Inner class holding the DictData of a CFF font. | |||
+ * Inner class holding the DictData of a CFF font. | |||
*/ | |||
private static class DictData | |||
{ | |||
@@ -1030,7 +1046,7 @@ | |||
} | |||
/** | |||
- * {@inheritDoc} | |||
+ * {@inheritDoc} | |||
*/ | |||
public String toString() | |||
{ | |||
@@ -1038,7 +1054,7 @@ | |||
} | |||
/** | |||
- * Inner class holding an operand of a CFF font. | |||
+ * Inner class holding an operand of a CFF font. | |||
*/ | |||
private static class Entry | |||
{ | |||
@@ -1100,7 +1116,7 @@ | |||
} | |||
/** | |||
- * Inner class representing an embedded CFF encoding. | |||
+ * Inner class representing an embedded CFF encoding. | |||
*/ | |||
abstract static class EmbeddedEncoding extends CFFEncoding | |||
{ | |||
@@ -1124,7 +1140,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a supplement for an encoding. | |||
+ * Inner class representing a supplement for an encoding. | |||
*/ | |||
static class Supplement | |||
{ | |||
@@ -1150,7 +1166,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a Format0 encoding. | |||
+ * Inner class representing a Format0 encoding. | |||
*/ | |||
private static class Format0Encoding extends EmbeddedEncoding | |||
{ | |||
@@ -1167,7 +1183,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a Format1 encoding. | |||
+ * Inner class representing a Format1 encoding. | |||
*/ | |||
private static class Format1Encoding extends EmbeddedEncoding | |||
{ | |||
@@ -1183,7 +1199,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a range of an encoding. | |||
+ * Inner class representing a range of an encoding. | |||
*/ | |||
private static class Range1 | |||
{ | |||
@@ -1193,13 +1209,20 @@ | |||
@Override | |||
public String toString() | |||
{ | |||
- return getClass().getName() + "[first=" + first + ", nLeft=" + nLeft + "]"; | |||
+ return getClass().getName() + "[first=" + first + ", nLeft=" | |||
+ + nLeft + "]"; | |||
} | |||
+ | |||
+ @Override | |||
+ public boolean equals(Object obj) { | |||
+ Range1 r = (Range1)obj; | |||
+ return (first == r.first && nLeft == r.nLeft); | |||
+ } | |||
} | |||
} | |||
/** | |||
- * Inner class representing an embedded CFF charset. | |||
+ * Inner class representing an embedded CFF charset. | |||
*/ | |||
abstract static class EmbeddedCharset extends CFFCharset | |||
{ | |||
@@ -1211,7 +1234,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a Format0 charset. | |||
+ * Inner class representing a Format0 charset. | |||
*/ | |||
private static class Format0Charset extends EmbeddedCharset | |||
{ | |||
@@ -1226,7 +1249,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a Format1 charset. | |||
+ * Inner class representing a Format1 charset. | |||
*/ | |||
private static class Format1Charset extends EmbeddedCharset | |||
{ | |||
@@ -1240,7 +1263,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a range of a charset. | |||
+ * Inner class representing a range of a charset. | |||
*/ | |||
private static class Range1 | |||
{ | |||
@@ -1256,7 +1279,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a Format2 charset. | |||
+ * Inner class representing a Format2 charset. | |||
*/ | |||
private static class Format2Charset extends EmbeddedCharset | |||
{ | |||
@@ -1270,7 +1293,7 @@ | |||
} | |||
/** | |||
- * Inner class representing a range of a charset. | |||
+ * Inner class representing a range of a charset. | |||
*/ | |||
private static class Range2 | |||
{ | |||
@@ -1284,4 +1307,8 @@ | |||
} | |||
} | |||
} | |||
+ | |||
+ public IndexData getStringIndex() { | |||
+ return stringIndex; | |||
+ } | |||
} | |||
Index: fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java | |||
=================================================================== | |||
--- fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (revision 1546564) | |||
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (working copy) | |||
@@ -31,7 +31,7 @@ | |||
/** | |||
* This class represents a CFF/Type2 Font. | |||
- * | |||
+ * | |||
* @author Villu Ruusmann | |||
* @version $Revision$ | |||
*/ | |||
@@ -44,6 +44,8 @@ | |||
private CFFEncoding fontEncoding = null; | |||
private CFFCharset fontCharset = null; | |||
private Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>(); | |||
+ Map<Integer, Mapping> sidMappings = null; | |||
+ ArrayList<Mapping> gidMappings = null; | |||
private IndexData globalSubrIndex = null; | |||
private IndexData localSubrIndex = null; | |||
@@ -97,6 +99,7 @@ | |||
topDict.put(name, value); | |||
} | |||
} | |||
+ | |||
/** | |||
* Returns the top dictionary. | |||
* @return the dictionary | |||
@@ -107,7 +110,7 @@ | |||
} | |||
/** | |||
- * Adds the given key/value pair to the private dictionary. | |||
+ * Adds the given key/value pair to the private dictionary. | |||
* @param name the given key | |||
* @param value the given value | |||
*/ | |||
@@ -118,7 +121,8 @@ | |||
privateDict.put(name, value); | |||
} | |||
} | |||
- /** | |||
+ | |||
+ /** | |||
* Returns the private dictionary. | |||
* @return the dictionary | |||
*/ | |||
@@ -127,14 +131,60 @@ | |||
return privateDict; | |||
} | |||
+ /** | |||
+ * Returns a mapping for a given GID | |||
+ * @param GID The given GID | |||
+ * @return The found mapping | |||
+ */ | |||
+ public Mapping getMapping(int GID) { | |||
+ return sidMappings.get(GID); | |||
+ } | |||
+ | |||
/** | |||
- * Get the mapping (code/SID/charname/bytes) for this font. | |||
- * @return mappings for codes < 256 and for codes > = 256 | |||
- */ | |||
- public Collection<Mapping> getMappings() | |||
+ * Get the mapping (code/SID/charname/bytes) for this font. | |||
+ * @return mappings for codes < 256 and for codes > = 256 | |||
+ */ | |||
+ public Collection<Mapping> getMappings() { | |||
+ constructMappings(); | |||
+ return sidMappings.values(); | |||
+ } | |||
+ | |||
+ /** | |||
+ * Gets the GID mappings list. | |||
+ */ | |||
+ public ArrayList<Mapping> getGIDMappings() { | |||
+ return gidMappings; | |||
+ } | |||
+ | |||
+ private void constructGIDMap() { | |||
+ gidMappings = new ArrayList<Mapping>(); | |||
+ Mapping notdef = new Mapping(); | |||
+ notdef.setName(".notdef"); | |||
+ gidMappings.add(notdef); | |||
+ for (CFFCharset.Entry entry : fontCharset.getEntries()) | |||
+ { | |||
+ String name = entry.getName(); | |||
+ byte[] bytes = this.charStringsDict.get(name); | |||
+ if (bytes == null) | |||
+ { | |||
+ continue; | |||
+ } | |||
+ Mapping mapping = new Mapping(); | |||
+ mapping.setSID(entry.getSID()); | |||
+ mapping.setName(name); | |||
+ mapping.setBytes(bytes); | |||
+ gidMappings.add(mapping); | |||
+ } | |||
+ } | |||
+ | |||
+ /** | |||
+ * Construct the mappings. | |||
+ */ | |||
+ public void constructMappings() | |||
{ | |||
- List<Mapping> mappings = new ArrayList<Mapping>(); | |||
- Set<String> mappedNames = new HashSet<String>(); | |||
+ constructGIDMap(); | |||
+ sidMappings = new LinkedHashMap<Integer, Mapping>(); | |||
+ Set<String> mappedNames = new HashSet<String>(); | |||
for (CFFEncoding.Entry entry : fontEncoding.getEntries()) | |||
{ | |||
String charName = fontCharset.getName(entry.getSID()); | |||
@@ -153,7 +203,7 @@ | |||
mapping.setSID(entry.getSID()); | |||
mapping.setName(charName); | |||
mapping.setBytes(bytes); | |||
- mappings.add(mapping); | |||
+ sidMappings.put(mapping.getSID(), mapping); | |||
mappedNames.add(charName); | |||
} | |||
if (fontEncoding instanceof CFFParser.EmbeddedEncoding) | |||
@@ -177,7 +227,7 @@ | |||
mapping.setSID(supplement.getGlyph()); | |||
mapping.setName(charName); | |||
mapping.setBytes(bytes); | |||
- mappings.add(mapping); | |||
+ sidMappings.put(mapping.getSID(), mapping); | |||
mappedNames.add(charName); | |||
} | |||
} | |||
@@ -185,7 +235,7 @@ | |||
int code = 256; | |||
for (CFFCharset.Entry entry : fontCharset.getEntries()) | |||
{ | |||
- String name = entry.getName(); | |||
+ String name = entry.getName(); | |||
if (mappedNames.contains(name)) | |||
{ | |||
continue; | |||
@@ -201,11 +251,10 @@ | |||
mapping.setName(name); | |||
mapping.setBytes(bytes); | |||
- mappings.add(mapping); | |||
+ sidMappings.put(mapping.getSID(), mapping); | |||
mappedNames.add(name); | |||
} | |||
- return mappings; | |||
} | |||
/** | |||
@@ -215,34 +264,43 @@ | |||
* @return -1 if the SID is missing from the Font. | |||
* @throws IOException | |||
*/ | |||
- public int getWidth(int SID) throws IOException { | |||
- int nominalWidth = privateDict.containsKey("nominalWidthX") ? ((Number)privateDict.get("nominalWidthX")).intValue() : 0; | |||
- int defaultWidth = privateDict.containsKey("defaultWidthX") ? ((Number)privateDict.get("defaultWidthX")).intValue() : 1000 ; | |||
- | |||
- for (Mapping m : getMappings() ){ | |||
- if (m.getSID() == SID) { | |||
+ public int getWidth(int SID) throws IOException { | |||
+ int nominalWidth = privateDict.containsKey("nominalWidthX") ? ((Number) privateDict.get("nominalWidthX")).intValue() : 0; | |||
+ int defaultWidth = privateDict.containsKey("defaultWidthX") ? ((Number) privateDict.get("defaultWidthX")).intValue() : 1000; | |||
+ Mapping m = sidMappings.get(SID); | |||
+ if (m != null) { | |||
+ CharStringRenderer csr = getRendererForMapping(m); | |||
+ // ---- If the CharString has a Width nominalWidthX must be added, | |||
+ // otherwise it is the default width. | |||
+ return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth; | |||
+ } | |||
- CharStringRenderer csr = null; | |||
- if (((Number)getProperty("CharstringType")).intValue() == 2 ) { | |||
- List<Object> lSeq = m.toType2Sequence(); | |||
- csr = new CharStringRenderer(false); | |||
- csr.render(lSeq); | |||
- } else { | |||
- List<Object> lSeq = m.toType1Sequence(); | |||
- csr = new CharStringRenderer(); | |||
- csr.render(lSeq); | |||
- } | |||
+ // ---- SID Width not found, return the nodef width | |||
+ return getNotDefWidth(defaultWidth, nominalWidth); | |||
+ } | |||
- // ---- If the CharString has a Width nominalWidthX must be added, | |||
- // otherwise it is the default width. | |||
- return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth; | |||
- } | |||
- } | |||
+ private CharStringRenderer getRendererForMapping(Mapping m) throws IOException { | |||
+ CharStringRenderer csr = null; | |||
+ if (((Number) getProperty("CharstringType")).intValue() == 2) { | |||
+ List<Object> lSeq = m.toType2Sequence(); | |||
+ csr = new CharStringRenderer(false); | |||
+ csr.render(lSeq); | |||
+ } else { | |||
+ List<Object> lSeq = m.toType1Sequence(); | |||
+ csr = new CharStringRenderer(); | |||
+ csr.render(lSeq); | |||
+ } | |||
+ return csr; | |||
+ } | |||
- // ---- SID Width not found, return the nodef width | |||
- return getNotDefWidth(defaultWidth, nominalWidth); | |||
- } | |||
- | |||
+ /** | |||
+ * Returns the witdth of the .notdef character. | |||
+ * | |||
+ * @param defaultWidth default width | |||
+ * @param nominalWidth nominal width | |||
+ * @return the calculated width for the .notdef character | |||
+ * @throws IOException if something went wrong | |||
+ */ | |||
protected int getNotDefWidth(int defaultWidth, int nominalWidth) throws IOException { | |||
CharStringRenderer csr; | |||
byte[] glyphDesc = this.getCharStringsDict().get(".notdef"); | |||
@@ -260,6 +318,36 @@ | |||
return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth; | |||
} | |||
+ /** | |||
+ * Return the Width value of the given Glyph identifier | |||
+ * | |||
+ * @param SID | |||
+ * @return -1 if the SID is missing from the Font. | |||
+ * @throws IOException | |||
+ */ | |||
+ public int[] getBoundingBox(int SID) throws IOException { | |||
+ Mapping m = sidMappings.get(SID); | |||
+ if (m != null) { | |||
+ CharStringRenderer csr = getRendererForMapping(m); | |||
+ return csr.getBounds(); | |||
+ } | |||
+ // ---- SID Width not found, return the nodef width | |||
+ return new int[4]; | |||
+ } | |||
+ | |||
+ /** | |||
+ * Gets the name of a character from the given SID | |||
+ * @param SID The given SID | |||
+ * @return The name of the found character | |||
+ */ | |||
+ public String getNameOfCharFromCode(int SID) { | |||
+ if (sidMappings.get(SID) != null) { | |||
+ return sidMappings.get(SID).getName(); | |||
+ } else { | |||
+ return ""; | |||
+ } | |||
+ } | |||
+ | |||
/** | |||
* Returns the CFFEncoding of the font. | |||
* @return the encoding | |||
@@ -336,50 +424,51 @@ | |||
+ charStringsDict + "]"; | |||
} | |||
+ /** | |||
+ * Sets the global subroutine index data. | |||
+ * @param globalSubrIndex the IndexData object containing the global subroutines | |||
+ */ | |||
+ public void setGlobalSubrIndex(IndexData globalSubrIndexValue) { | |||
+ globalSubrIndex = globalSubrIndexValue; | |||
+ } | |||
- /** | |||
- * Sets the global subroutine index data. | |||
- * @param globalSubrIndex the IndexData object containing the global subroutines | |||
- */ | |||
- public void setGlobalSubrIndex(IndexData globalSubrIndex) { | |||
- this.globalSubrIndex = globalSubrIndex; | |||
- } | |||
+ /** | |||
+ * Returns the global subroutine index data. | |||
+ * @return the dictionary | |||
+ */ | |||
+ public IndexData getGlobalSubrIndex() | |||
+ { | |||
+ return globalSubrIndex; | |||
+ } | |||
- /** | |||
- * Returns the global subroutine index data. | |||
- * @return the dictionary | |||
- */ | |||
- public IndexData getGlobalSubrIndex() { | |||
- return globalSubrIndex; | |||
- } | |||
+ /** | |||
+ * Returns the local subroutine index data. | |||
+ * @return the dictionary | |||
+ */ | |||
+ public IndexData getLocalSubrIndex() | |||
+ { | |||
+ return localSubrIndex; | |||
+ } | |||
- /** | |||
- * Returns the local subroutine index data. | |||
- * @return the dictionary | |||
- */ | |||
- public IndexData getLocalSubrIndex() { | |||
- return localSubrIndex; | |||
- } | |||
+ /** | |||
+ * Sets the local subroutine index data. | |||
+ * @param localSubrIndexValue the IndexData object containing the local subroutines | |||
+ */ | |||
+ public void setLocalSubrIndex(IndexData localSubrIndexValue) { | |||
+ localSubrIndex = localSubrIndexValue; | |||
+ } | |||
- /** | |||
- * Sets the local subroutine index data. | |||
- * @param localSubrIndex the IndexData object containing the local subroutines | |||
- */ | |||
- public void setLocalSubrIndex(IndexData localSubrIndex) { | |||
- this.localSubrIndex = localSubrIndex; | |||
- } | |||
+ /** | |||
+ * This class is used for the font mapping. | |||
+ * | |||
+ */ | |||
+ public class Mapping | |||
+ { | |||
+ private int mappedCode; | |||
+ private int mappedSID; | |||
+ private String mappedName; | |||
+ private byte[] mappedBytes; | |||
- /** | |||
- * This class is used for the font mapping. | |||
- * | |||
- */ | |||
- public class Mapping | |||
- { | |||
- private int mappedCode; | |||
- private int mappedSID; | |||
- private String mappedName; | |||
- private byte[] mappedBytes; | |||
- | |||
/** | |||
* Converts the mapping into a Type1-sequence. | |||
* @return the Type1-sequence | |||
@@ -458,4 +547,4 @@ | |||
this.mappedBytes = bytes; | |||
} | |||
} | |||
-} | |||
\ No newline at end of file | |||
+} |
@@ -32,7 +32,6 @@ import java.util.TreeSet; | |||
import org.apache.fop.util.License; | |||
// CSOFF: LineLength | |||
// CSOFF: NoWhitespaceAfter | |||
/** | |||
* <p>Utility for generating a Java class representing bidirectional | |||
@@ -303,7 +302,7 @@ public final class GenerateBidiClass { | |||
sb.setLength(0); | |||
out.println("private static byte[] bcL1 = {"); | |||
for (int i = 0; i < bcL1.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(","); | |||
} else { | |||
first = false; | |||
@@ -327,7 +326,7 @@ public final class GenerateBidiClass { | |||
sb.setLength(0); | |||
out.println("private static byte[] bcR1 = {"); | |||
for (int i = 0; i < bcR1.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(","); | |||
} else { | |||
first = false; | |||
@@ -351,7 +350,7 @@ public final class GenerateBidiClass { | |||
sb.setLength(0); | |||
out.println("private static int[] bcS1 = {"); | |||
for (int i = 0; i < bcS1.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(","); | |||
} else { | |||
first = false; | |||
@@ -375,7 +374,7 @@ public final class GenerateBidiClass { | |||
sb.setLength(0); | |||
out.println("private static int[] bcE1 = {"); | |||
for (int i = 0; i < bcE1.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(","); | |||
} else { | |||
first = false; | |||
@@ -399,7 +398,7 @@ public final class GenerateBidiClass { | |||
sb.setLength(0); | |||
out.println("private static byte[] bcC1 = {"); | |||
for (int i = 0; i < bcC1.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(","); | |||
} else { | |||
first = false; | |||
@@ -434,7 +433,7 @@ public final class GenerateBidiClass { | |||
if (k >= 0) { | |||
return ca [ k ]; | |||
} else { | |||
k = - (k + 1); | |||
k = -(k + 1); | |||
if (k == 0) { | |||
return BidiConstants.L; | |||
} else if (ch <= ea [ k - 1 ]) { |
@@ -40,10 +40,6 @@ import java.util.TreeMap; | |||
import org.apache.fop.util.License; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: EmptyForIteratorPadCheck | |||
/** | |||
* <p>Utility for generating a Java class and associated data files representing | |||
@@ -202,7 +198,7 @@ public final class GenerateBidiTestData { | |||
String ucName = sa[1]; | |||
if (isBlockStart(ucName)) { | |||
String ucBlock = getBlockName(ucName); | |||
if (! im.containsKey(ucBlock)) { | |||
if (!im.containsKey(ucBlock)) { | |||
im.put(ucBlock, new int[] { uc, -1, bc }); | |||
} else { | |||
throw new IllegalArgumentException("duplicate start of block '" + ucBlock + "' at entry: " + line); | |||
@@ -223,7 +219,7 @@ public final class GenerateBidiTestData { | |||
} else { | |||
Integer k = Integer.valueOf(bc); | |||
List sl; | |||
if (! sm.containsKey(k)) { | |||
if (!sm.containsKey(k)) { | |||
sl = new ArrayList(); | |||
sm.put(k, sl); | |||
} else { | |||
@@ -267,7 +263,7 @@ public final class GenerateBidiTestData { | |||
} | |||
} | |||
// populate intervals from (block) interval map | |||
if (! im.isEmpty()) { | |||
if (!im.isEmpty()) { | |||
for (Iterator it = im.values().iterator(); it.hasNext(); ) { | |||
int[] ba = (int[]) it.next(); | |||
assert (ba != null) && (ba.length > 2); | |||
@@ -335,7 +331,7 @@ public final class GenerateBidiTestData { | |||
continue; | |||
} else if (line.startsWith("#")) { | |||
continue; | |||
} else if (line.startsWith(PFX_TYPE) && ! ignoreDeprecatedTypeData) { | |||
} else if (line.startsWith(PFX_TYPE) && !ignoreDeprecatedTypeData) { | |||
List lines = new ArrayList(); | |||
if ((n = readType(line, b, lines)) < 0) { | |||
break; | |||
@@ -356,14 +352,14 @@ public final class GenerateBidiTestData { | |||
// dump instrumentation | |||
if (verbose) { | |||
System.out.println(); | |||
if (! ignoreDeprecatedTypeData) { | |||
if (!ignoreDeprecatedTypeData) { | |||
System.out.println("Read type ranges : " + numTypeRanges); | |||
} | |||
System.out.println("Read level specs : " + numLevelSpecs); | |||
System.out.println("Read test specs : " + numTestSpecs); | |||
System.out.println("Read lines : " + lineNumber); | |||
} | |||
if (! ignoreDeprecatedTypeData) { | |||
if (!ignoreDeprecatedTypeData) { | |||
td = (int[][]) tdl.toArray(new int [ tdl.size() ] []); | |||
} | |||
ld = (int[][]) ldl.toArray(new int [ ldl.size() ] []); | |||
@@ -378,12 +374,12 @@ public final class GenerateBidiTestData { | |||
boolean done = false; | |||
int n = 0; | |||
lines.add(line); | |||
while (! done) { | |||
while (!done) { | |||
switch (testPrefix(b, PFX_LEVELS)) { | |||
case 0: // within current levels | |||
if ((line = b.readLine()) != null) { | |||
n++; | |||
if ((line.length() > 0) && ! line.startsWith("#")) { | |||
if ((line.length() > 0) && !line.startsWith("#")) { | |||
lines.add(line); | |||
} | |||
} else { | |||
@@ -509,7 +505,7 @@ public final class GenerateBidiTestData { | |||
CharacterIterator ci = new StringCharacterIterator(charRanges); | |||
// read initial list delimiter | |||
skipSpace(ci); | |||
if (! readStartOfList(ci)) { | |||
if (!readStartOfList(ci)) { | |||
badRangeSpec("missing initial list delimiter", charRanges); | |||
} | |||
// read negation token if present | |||
@@ -538,7 +534,7 @@ public final class GenerateBidiTestData { | |||
String s; | |||
skipSpace(ci); | |||
if ((s = maybeReadSeparator(ci)) != null) { | |||
if ((s.length() != 0) && ! s.equals("||")) { | |||
if ((s.length() != 0) && !s.equals("||")) { | |||
badRangeSpec("invalid item separator \"" + s + "\"", charRanges); | |||
} | |||
} | |||
@@ -557,10 +553,10 @@ public final class GenerateBidiTestData { | |||
} | |||
// read terminating list delimiter | |||
skipSpace(ci); | |||
if (! readEndOfList(ci)) { | |||
if (!readEndOfList(ci)) { | |||
badRangeSpec("missing terminating list delimiter", charRanges); | |||
} | |||
if (! atEnd(ci)) { | |||
if (!atEnd(ci)) { | |||
badRangeSpec("extraneous content prior to end of line", ci); | |||
} | |||
if (negated) { | |||
@@ -578,9 +574,9 @@ public final class GenerateBidiTestData { | |||
} | |||
private static void skipSpace(CharacterIterator ci) { | |||
while (! atEnd(ci)) { | |||
while (!atEnd(ci)) { | |||
char c = ci.current(); | |||
if (! Character.isWhitespace(c)) { | |||
if (!Character.isWhitespace(c)) { | |||
break; | |||
} else { | |||
ci.next(); | |||
@@ -589,7 +585,7 @@ public final class GenerateBidiTestData { | |||
} | |||
private static boolean maybeReadNext(CharacterIterator ci, char next) { | |||
while (! atEnd(ci)) { | |||
while (!atEnd(ci)) { | |||
char c = ci.current(); | |||
if (c == next) { | |||
ci.next(); | |||
@@ -906,7 +902,7 @@ public final class GenerateBidiTestData { | |||
List ll = new ArrayList(); | |||
// read prefix | |||
skipSpace(ci); | |||
if (! maybeReadToken(ci, PFX_LEVELS)) { | |||
if (!maybeReadToken(ci, PFX_LEVELS)) { | |||
badLevelSpec("missing prefix \"" + PFX_LEVELS + "\"", ci); | |||
} | |||
// read level values | |||
@@ -924,7 +920,7 @@ public final class GenerateBidiTestData { | |||
} | |||
// read to end of line | |||
skipSpace(ci); | |||
if (! atEnd(ci)) { | |||
if (!atEnd(ci)) { | |||
badLevelSpec("extraneous content prior to end of line", ci); | |||
} | |||
if (ll.size() == 0) { | |||
@@ -1007,7 +1003,7 @@ public final class GenerateBidiTestData { | |||
List rl = new ArrayList(); | |||
// read prefix | |||
skipSpace(ci); | |||
if (! maybeReadToken(ci, PFX_REORDER)) { | |||
if (!maybeReadToken(ci, PFX_REORDER)) { | |||
badReorderSpec("missing prefix \"" + PFX_REORDER + "\"", ci); | |||
} | |||
// read reorder values | |||
@@ -1023,7 +1019,7 @@ public final class GenerateBidiTestData { | |||
} | |||
// read to end of line | |||
skipSpace(ci); | |||
if (! atEnd(ci)) { | |||
if (!atEnd(ci)) { | |||
badReorderSpec("extraneous content prior to end of line", ci); | |||
} | |||
return createReorderArray(rl, levels); | |||
@@ -1066,7 +1062,7 @@ public final class GenerateBidiTestData { | |||
CharacterIterator ci = new StringCharacterIterator(line); | |||
List cl = new ArrayList(); | |||
// read bidi class identifier sequence | |||
while (! atEnd(ci) && ! maybeReadNext(ci, ';')) { | |||
while (!atEnd(ci) && !maybeReadNext(ci, ';')) { | |||
skipSpace(ci); | |||
int bc; | |||
if ((bc = maybeReadBidiClass(ci)) >= 0) { | |||
@@ -1086,7 +1082,7 @@ public final class GenerateBidiTestData { | |||
} | |||
// read to end of line | |||
skipSpace(ci); | |||
if (! atEnd(ci)) { | |||
if (!atEnd(ci)) { | |||
badTestSpec("extraneous content prior to end of line", ci); | |||
} | |||
return createTestArray(cl, bs, levels); | |||
@@ -1244,7 +1240,7 @@ public final class GenerateBidiTestData { | |||
ok = false; | |||
} | |||
} | |||
if (! ok) { | |||
if (!ok) { | |||
System.out.println("Usage: GenerateBidiTestData [-v] [-i] [-d <ucdFile>] [-b <bidiFile>] [-o <outputFile>]"); | |||
System.out.println(" defaults:"); | |||
if (ignoreDeprecatedTypeData) { |
@@ -38,6 +38,7 @@ | |||
<xs:complexContent> | |||
<xs:extension base="mf:contentType"> | |||
<xs:attribute name="transform" type="xs:string"/> | |||
<xs:attribute name="layer" type="xs:string"/> | |||
</xs:extension> | |||
</xs:complexContent> | |||
</xs:complexType> |
@@ -1,3 +1,4 @@ | |||
org.apache.fop.render.afp.extensions.AFPExtensionHandlerFactory | |||
org.apache.fop.render.pdf.extensions.PDFExtensionHandlerFactory | |||
org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory | |||
org.apache.fop.fo.extensions.xmp.XMPContentHandlerFactory |
@@ -40,8 +40,9 @@ public final class Version { | |||
} | |||
if (version == null) { | |||
//Fallback if FOP is used in a development environment | |||
String headURL | |||
= "$HeadURL$"; | |||
// CSOFF: LineLength | |||
String headURL = "$HeadURL$"; | |||
// CSON: LineLength | |||
version = headURL; | |||
final String pathPrefix = "/xmlgraphics/fop/"; | |||
int pos = version.indexOf(pathPrefix); |
@@ -408,7 +408,7 @@ public class FOUserAgent { | |||
try { | |||
// Have to do this so we can resolve data URIs | |||
StreamSource src = new StreamSource(resourceResolver.getResource(uri)); | |||
src.setSystemId(uri); | |||
src.setSystemId(new File(uri).toURI().toURL().toExternalForm()); | |||
return src; | |||
} catch (URISyntaxException use) { | |||
return null; |
@@ -70,16 +70,7 @@ public class FopConfParser { | |||
*/ | |||
public FopConfParser(InputStream fopConfStream, EnvironmentProfile enviro) | |||
throws SAXException, IOException { | |||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); | |||
Configuration cfg; | |||
try { | |||
cfg = cfgBuilder.build(fopConfStream); | |||
} catch (ConfigurationException e) { | |||
throw new FOPException(e); | |||
} | |||
// The default base URI is taken from the directory in which the fopConf resides | |||
fopFactoryBuilder = new FopFactoryBuilder(enviro).setConfiguration(cfg); | |||
configure(enviro.getDefaultBaseURI(), enviro.getResourceResolver(), cfg); | |||
this(fopConfStream, enviro.getDefaultBaseURI(), enviro); | |||
} | |||
/** | |||
@@ -94,7 +85,8 @@ public class FopConfParser { | |||
*/ | |||
public FopConfParser(InputStream fopConfStream, URI defaultBaseURI, | |||
ResourceResolver resourceResolver) throws SAXException, IOException { | |||
this(fopConfStream, EnvironmentalProfileFactory.createDefault(defaultBaseURI, resourceResolver)); | |||
this(fopConfStream, defaultBaseURI, | |||
EnvironmentalProfileFactory.createDefault(defaultBaseURI, resourceResolver)); | |||
} | |||
/** | |||
@@ -122,6 +114,20 @@ public class FopConfParser { | |||
this(fopConfFile, ResourceResolverFactory.createDefaultResourceResolver()); | |||
} | |||
/** | |||
* Constructor that takes the FOP conf and a default base URI and uses the default URI resolver. | |||
* | |||
* @param fopConfFile the FOP conf file | |||
* @param defaultBaseURI the default base URI | |||
* @throws SAXException if a SAX error was thrown parsing the FOP conf | |||
* @throws IOException if an I/O error is thrown while parsing the FOP conf | |||
*/ | |||
public FopConfParser(File fopConfFile, URI defaultBaseURI) throws SAXException, IOException { | |||
this(new FileInputStream(fopConfFile), fopConfFile.toURI(), | |||
EnvironmentalProfileFactory.createDefault(defaultBaseURI, | |||
ResourceResolverFactory.createDefaultResourceResolver())); | |||
} | |||
/** | |||
* Constructor that parses the FOP conf and uses the URI resolver given. | |||
* | |||
@@ -132,11 +138,24 @@ public class FopConfParser { | |||
*/ | |||
public FopConfParser(File fopConfFile, ResourceResolver resourceResolver) | |||
throws SAXException, IOException { | |||
this(new FileInputStream(fopConfFile), | |||
fopConfFile.getAbsoluteFile().getParentFile().toURI(), resourceResolver); | |||
this(new FileInputStream(fopConfFile), fopConfFile.toURI(), resourceResolver); | |||
} | |||
private FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro) | |||
throws SAXException, IOException { | |||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); | |||
Configuration cfg; | |||
try { | |||
cfg = cfgBuilder.build(fopConfStream); | |||
} catch (ConfigurationException e) { | |||
throw new FOPException(e); | |||
} | |||
// The default base URI is taken from the directory in which the fopConf resides | |||
fopFactoryBuilder = new FopFactoryBuilder(enviro).setConfiguration(cfg); | |||
configure(baseURI, enviro.getResourceResolver(), cfg); | |||
} | |||
private void configure(final URI defaultBaseURI, final ResourceResolver resourceResolver, | |||
private void configure(final URI baseURI, final ResourceResolver resourceResolver, | |||
Configuration cfg) throws FOPException { | |||
if (log.isDebugEnabled()) { | |||
log.debug("Initializing FopFactory Configuration"); | |||
@@ -174,7 +193,7 @@ public class FopConfParser { | |||
if (cfg.getChild("base", false) != null) { | |||
try { | |||
URI confUri = InternalResourceResolver.getBaseURI(cfg.getChild("base").getValue(null)); | |||
fopFactoryBuilder.setBaseURI(defaultBaseURI.resolve(confUri)); | |||
fopFactoryBuilder.setBaseURI(baseURI.resolve(confUri)); | |||
} catch (URISyntaxException use) { | |||
LogUtil.handleException(log, use, strict); | |||
} | |||
@@ -242,8 +261,8 @@ public class FopConfParser { | |||
} | |||
// configure font manager | |||
new FontManagerConfigurator(cfg, fopFactoryBuilder.getBaseURI(), resourceResolver).configure( | |||
fopFactoryBuilder.getFontManager(), strict); | |||
new FontManagerConfigurator(cfg, baseURI, fopFactoryBuilder.getBaseURI(), resourceResolver) | |||
.configure(fopFactoryBuilder.getFontManager(), strict); | |||
// configure image loader framework | |||
configureImageLoading(cfg.getChild("image-loading", false), strict); |
@@ -62,6 +62,7 @@ import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.area.Trait.Background; | |||
import org.apache.fop.area.Trait.InternalLink; | |||
import org.apache.fop.area.inline.AbstractTextArea; | |||
import org.apache.fop.area.inline.Container; | |||
import org.apache.fop.area.inline.ForeignObject; | |||
import org.apache.fop.area.inline.Image; | |||
import org.apache.fop.area.inline.InlineArea; | |||
@@ -195,6 +196,7 @@ public class AreaTreeParser { | |||
makers.put("space", new SpaceMaker()); | |||
makers.put("leader", new LeaderMaker()); | |||
makers.put("viewport", new InlineViewportMaker()); | |||
makers.put("container", new ContainerMaker()); | |||
makers.put("image", new ImageMaker()); | |||
makers.put("foreignObject", new ForeignObjectMaker()); | |||
makers.put("bookmarkTree", new BookmarkTreeMaker()); | |||
@@ -863,6 +865,21 @@ public class AreaTreeParser { | |||
} | |||
} | |||
private class ContainerMaker extends AbstractMaker { | |||
public void startElement(Attributes attributes) { | |||
Container container = new Container(); | |||
transferForeignObjects(attributes, container); | |||
InlineViewport parent = (InlineViewport) areaStack.peek(); | |||
parent.setContent(container); | |||
areaStack.push(container); | |||
} | |||
public void endElement() { | |||
assertObjectOfClass(areaStack.pop(), Container.class); | |||
} | |||
} | |||
private class InlineViewportMaker extends AbstractMaker { | |||
public void startElement(Attributes attributes) { | |||
@@ -1040,7 +1057,7 @@ public class AreaTreeParser { | |||
} | |||
private static final Object[] SUBSET_COMMON = new Object[] { | |||
Trait.PROD_ID}; | |||
Trait.PROD_ID, Trait.LAYER}; | |||
private static final Object[] SUBSET_LINK = new Object[] { | |||
Trait.INTERNAL_LINK, Trait.EXTERNAL_LINK}; | |||
private static final Object[] SUBSET_COLOR = new Object[] { |
@@ -83,7 +83,7 @@ public class Footnote extends BlockParent { | |||
@Override | |||
public void addBlock(Block child) { | |||
addChildArea(child); | |||
this.setBPD(this.getBPD() + child.getBPD()); | |||
setBPD(getBPD() + child.getAllocBPD()); | |||
} | |||
} |
@@ -169,9 +169,11 @@ public final class Trait implements Serializable { | |||
/** shift direction trait */ | |||
public static final Integer SHIFT_DIRECTION = 42; | |||
/** For optional content groups. */ | |||
public static final Integer LAYER = 43; | |||
/** Maximum value used by trait keys */ | |||
public static final int MAX_TRAIT_KEY = 42; | |||
public static final int MAX_TRAIT_KEY = 43; | |||
private static final TraitInfo[] TRAIT_INFO = new TraitInfo[MAX_TRAIT_KEY + 1]; | |||
@@ -243,6 +245,7 @@ public final class Trait implements Serializable { | |||
new TraitInfo("block-progression-direction", Direction.class)); | |||
put(SHIFT_DIRECTION, | |||
new TraitInfo("shift-direction", Direction.class)); | |||
put(LAYER, new TraitInfo("layer", String.class)); | |||
} | |||
@@ -51,13 +51,12 @@ public class Container extends Area { | |||
public Container() { | |||
} | |||
/** | |||
* Add the block to this area. | |||
* | |||
* @param block the block area to add | |||
*/ | |||
public void addBlock(Block block) { | |||
blocks.add(block); | |||
@Override | |||
public void addChildArea(Area child) { | |||
if (!(child instanceof Block)) { | |||
throw new IllegalArgumentException("Container only accepts block areas"); | |||
} | |||
blocks.add((Block) child); | |||
} | |||
/** | |||
@@ -65,7 +64,7 @@ public class Container extends Area { | |||
* | |||
* @return the list of block areas | |||
*/ | |||
public List getBlocks() { | |||
public List<Block> getBlocks() { | |||
return blocks; | |||
} | |||
@@ -58,7 +58,6 @@ import org.apache.fop.render.pdf.PDFEncryptionOption; | |||
import org.apache.fop.render.print.PagesMode; | |||
import org.apache.fop.render.print.PrintRenderer; | |||
import org.apache.fop.render.xml.XMLRenderer; | |||
import org.apache.fop.util.CommandLineLogger; | |||
/** | |||
* Options parses the commandline arguments | |||
@@ -145,16 +144,6 @@ public class CommandLineOptions { | |||
* Construct a command line option object. | |||
*/ | |||
public CommandLineOptions() { | |||
LogFactory logFactory = LogFactory.getFactory(); | |||
// Enable the simple command line logging when no other logger is | |||
// defined. | |||
if (System.getProperty("org.apache.commons.logging.Log") == null) { | |||
logFactory.setAttribute("org.apache.commons.logging.Log", | |||
CommandLineLogger.class.getName()); | |||
setLogLevel("info"); | |||
} | |||
log = LogFactory.getLog("FOP"); | |||
} | |||
@@ -184,9 +173,6 @@ public class CommandLineOptions { | |||
//Factory config is set up, now we can create the user agent | |||
foUserAgent = factory.newFOUserAgent(); | |||
foUserAgent.getRendererOptions().putAll(renderingOptions); | |||
if (targetResolution != 0) { | |||
foUserAgent.setTargetResolution(targetResolution); | |||
} | |||
addXSLTParameter("fop-output-format", getOutputFormat()); | |||
addXSLTParameter("fop-version", Version.getVersion()); | |||
foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy); | |||
@@ -292,7 +278,7 @@ public class CommandLineOptions { | |||
} else if (args[i].equals("-s")) { | |||
suppressLowLevelAreas = Boolean.TRUE; | |||
} else if (args[i].equals("-d")) { | |||
setLogOption("debug", "debug"); | |||
// nop. Left there for backwards compatibility | |||
} else if (args[i].equals("-r")) { | |||
strictValidation = false; | |||
} else if (args[i].equals("-conserve")) { | |||
@@ -304,7 +290,7 @@ public class CommandLineOptions { | |||
} else if (args[i].equals("-dpi")) { | |||
i = i + parseResolution(args, i); | |||
} else if (args[i].equals("-q") || args[i].equals("--quiet")) { | |||
setLogOption("quiet", "error"); | |||
// nop. Left there for backwards compatibility | |||
} else if (args[i].equals("-fo")) { | |||
i = i + parseFOInputOption(args, i); | |||
} else if (args[i].equals("-xsl")) { | |||
@@ -904,27 +890,6 @@ public class CommandLineOptions { | |||
} | |||
} | |||
private void setLogOption(String option, String level) { | |||
if (log instanceof CommandLineLogger | |||
|| System.getProperty("org.apache.commons.logging.Log") == null) { | |||
setLogLevel(level); | |||
} else if (log != null) { | |||
log.warn("The option " + option + " can only be used"); | |||
log.warn("with FOP's command line logger,"); | |||
log.warn("which is the default on the command line."); | |||
log.warn("Configure other loggers using Java system properties."); | |||
} | |||
} | |||
private void setLogLevel(String level) { | |||
// Set the level for future loggers. | |||
LogFactory.getFactory().setAttribute("level", level); | |||
if (log instanceof CommandLineLogger) { | |||
// Set the level for the logger created already. | |||
((CommandLineLogger) log).setLogLevel(level); | |||
} | |||
} | |||
private void setInputFormat(int format) throws FOPException { | |||
if (inputmode == NOT_SET || inputmode == format) { | |||
inputmode = format; | |||
@@ -1050,7 +1015,8 @@ public class CommandLineOptions { | |||
fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures); | |||
} else { | |||
try { | |||
fopFactoryBuilder = new FopConfParser(userConfigFile).getFopFactoryBuilder(); | |||
FopConfParser fopConfParser = new FopConfParser(userConfigFile, baseURI); | |||
fopFactoryBuilder = fopConfParser.getFopFactoryBuilder(); | |||
} catch (SAXException e) { | |||
throw new FOPException(e); | |||
} | |||
@@ -1208,9 +1174,7 @@ public class CommandLineOptions { | |||
+ "[-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl|-ps|-txt|-at [mime]|-print] <outfile>\n" | |||
+ " [OPTIONS] \n" | |||
+ " -version print FOP version and exit\n" | |||
+ " -d debug mode \n" | |||
+ " -x dump configuration settings \n" | |||
+ " -q quiet mode \n" | |||
+ " -c cfg.xml use additional configuration file cfg.xml\n" | |||
+ " -l lang the language to use for user information \n" | |||
+ " -nocs disable complex script features\n" |
@@ -21,7 +21,6 @@ package org.apache.fop.complexscripts.bidi; | |||
import java.util.Arrays; | |||
// CSOFF: WhitespaceAfterCheck | |||
// CSOFF: LineLengthCheck | |||
/* |
@@ -32,11 +32,7 @@ import org.apache.fop.area.LineArea; | |||
import org.apache.fop.area.inline.InlineArea; | |||
import org.apache.fop.fo.pagination.PageSequence; | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* <p>A utility class for performing bidirectional resolution processing.</p> | |||
@@ -140,7 +136,7 @@ public final class BidiResolver { | |||
runsNew.addAll(ir.split()); | |||
} | |||
} | |||
if (! runsNew.equals(runs)) { | |||
if (!runsNew.equals(runs)) { | |||
runs = runsNew; | |||
} | |||
return runs; | |||
@@ -180,7 +176,7 @@ public final class BidiResolver { | |||
i = e - 1; | |||
} | |||
} | |||
if (! runsNew.equals(runs)) { | |||
if (!runsNew.equals(runs)) { | |||
runs = runsNew; | |||
} | |||
return runs; | |||
@@ -232,7 +228,7 @@ public final class BidiResolver { | |||
Vector rv = new Vector(); | |||
for (Iterator it = ranges.iterator(); it.hasNext(); ) { | |||
DelimitedTextRange r = (DelimitedTextRange) it.next(); | |||
if (! r.isEmpty()) { | |||
if (!r.isEmpty()) { | |||
rv.add(r); | |||
} | |||
} |
@@ -34,10 +34,7 @@ import org.apache.fop.traits.WritingModeTraits; | |||
import org.apache.fop.traits.WritingModeTraitsGetter; | |||
import org.apache.fop.util.CharUtilities; | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* The <code>DelimitedTextRange</code> class implements the "delimited text range" as described | |||
@@ -151,7 +148,7 @@ public class DelimitedTextRange { | |||
TextInterval ti = (TextInterval) it.next(); | |||
intervalsNew.addAll(assignLevels(ti, levels)); | |||
} | |||
if (! intervalsNew.equals(intervals)) { | |||
if (!intervalsNew.equals(intervals)) { | |||
intervals = intervalsNew; | |||
} | |||
} |
@@ -35,11 +35,6 @@ import org.apache.fop.area.inline.UnresolvedPageNumber; | |||
import org.apache.fop.area.inline.WordArea; | |||
import org.apache.fop.util.CharUtilities; | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* The <code>InlineRun</code> class is a utility class, the instances of which are used | |||
* to capture a sequence of reordering levels associated with an inline area. | |||
@@ -179,7 +174,7 @@ public class InlineRun { | |||
if (inline instanceof WordArea) { | |||
WordArea w = (WordArea) inline; | |||
// if not already reversed, then reverse now | |||
if (! w.isReversed()) { | |||
if (!w.isReversed()) { | |||
if ((reversals & 1) != 0) { | |||
w.reverse(mirror); | |||
} else if (mirror && maybeNeedsMirroring()) { | |||
@@ -209,10 +204,8 @@ public class InlineRun { | |||
} | |||
return true; | |||
} | |||
} else if ((ir.levels == null) && (levels == null)) { | |||
return true; | |||
} else { | |||
return false; | |||
return (ir.levels == null) && (levels == null); | |||
} | |||
} else { | |||
return false; |
@@ -28,7 +28,6 @@ import org.apache.fop.fo.flow.Character; | |||
import org.apache.fop.fo.flow.Leader; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* <p>The <code>TextInterval</code> class is a utility class, the instances of which are used | |||
@@ -102,10 +101,8 @@ class TextInterval { | |||
return false; | |||
} else if (ti.getStart() != start) { | |||
return false; | |||
} else if (ti.getEnd() != end) { | |||
return false; | |||
} else { | |||
return true; | |||
return ti.getEnd() == end; | |||
} | |||
} else { | |||
return false; |
@@ -35,10 +35,7 @@ import org.apache.fop.area.inline.SpaceArea; | |||
import org.apache.fop.area.inline.TextArea; | |||
import org.apache.fop.area.inline.UnresolvedPageNumber; | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* <p>The <code>UnflattenProcessor</code> class is used to reconstruct (by unflattening) a line | |||
@@ -86,10 +83,8 @@ class UnflattenProcessor { | |||
private boolean shouldFinishTextContainer(TextArea tc, InlineArea ia) { | |||
if ((tcOrig != null) && (tc != tcOrig)) { | |||
return true; | |||
} else if ((iaLevelLast != -1) && (ia.getBidiLevel() != iaLevelLast)) { | |||
return true; | |||
} else { | |||
return false; | |||
return (iaLevelLast != -1) && (ia.getBidiLevel() != iaLevelLast); | |||
} | |||
} | |||
private void finishTextContainer() { | |||
@@ -98,7 +93,7 @@ class UnflattenProcessor { | |||
private void finishTextContainer(TextArea tc, InlineArea ia) { | |||
if (tcNew != null) { | |||
updateIPD(tcNew); | |||
if (! icNew.empty()) { | |||
if (!icNew.empty()) { | |||
icNew.peek().addChildArea(tcNew); | |||
} else { | |||
ilNew.add(tcNew); | |||
@@ -113,12 +108,12 @@ class UnflattenProcessor { | |||
} | |||
private boolean shouldFinishInlineContainer(List<InlineParent> ich, TextArea tc, InlineArea ia) { | |||
if ((ich == null) || ich.isEmpty()) { | |||
return ! icOrig.empty(); | |||
return !icOrig.empty(); | |||
} else { | |||
if (! icOrig.empty()) { | |||
if (!icOrig.empty()) { | |||
InlineParent ic = ich.get(0); | |||
InlineParent ic0 = icOrig.peek(); | |||
return (ic != ic0) && ! isInlineParentOf(ic, ic0); | |||
return (ic != ic0) && !isInlineParentOf(ic, ic0); | |||
} else { | |||
return false; | |||
} | |||
@@ -128,14 +123,14 @@ class UnflattenProcessor { | |||
finishInlineContainer(null, null, null); | |||
} | |||
private void finishInlineContainer(List<InlineParent> ich, TextArea tc, InlineArea ia) { | |||
if ((ich != null) && ! ich.isEmpty()) { // finish non-matching inner inline container(s) | |||
if ((ich != null) && !ich.isEmpty()) { // finish non-matching inner inline container(s) | |||
for (Iterator<InlineParent> it = ich.iterator(); it.hasNext(); ) { | |||
InlineParent ic = it.next(); | |||
InlineParent ic0 = icOrig.empty() ? null : icOrig.peek(); | |||
if (ic0 == null) { | |||
assert icNew.empty(); | |||
} else if (ic != ic0) { | |||
assert ! icNew.empty(); | |||
assert !icNew.empty(); | |||
InlineParent icO0 = icOrig.pop(); | |||
InlineParent icN0 = icNew.pop(); | |||
assert icO0 != null; | |||
@@ -145,7 +140,7 @@ class UnflattenProcessor { | |||
} else { | |||
icNew.peek().addChildArea(icN0); | |||
} | |||
if (! icOrig.empty() && (icOrig.peek() == ic)) { | |||
if (!icOrig.empty() && (icOrig.peek() == ic)) { | |||
break; | |||
} | |||
} else { | |||
@@ -153,7 +148,7 @@ class UnflattenProcessor { | |||
} | |||
} | |||
} else { // finish all inline containers | |||
while (! icNew.empty()) { | |||
while (!icNew.empty()) { | |||
InlineParent icO0 = icOrig.pop(); | |||
InlineParent icN0 = icNew.pop(); | |||
assert icO0 != null; | |||
@@ -176,8 +171,8 @@ class UnflattenProcessor { | |||
finishInlineContainer(); | |||
} | |||
private void update(List<InlineParent> ich, TextArea tc, InlineArea ia) { | |||
if (! alreadyUnflattened(ia)) { | |||
if ((ich != null) && ! ich.isEmpty()) { | |||
if (!alreadyUnflattened(ia)) { | |||
if ((ich != null) && !ich.isEmpty()) { | |||
pushInlineContainers(ich); | |||
} | |||
if (tc != null) { | |||
@@ -345,7 +340,7 @@ class UnflattenProcessor { | |||
Area a = ia.getParentArea(); | |||
while (a != null) { | |||
if (a instanceof InlineArea) { | |||
if ((a instanceof InlineParent) && ! (a instanceof TextArea)) { | |||
if ((a instanceof InlineParent) && !(a instanceof TextArea)) { | |||
ich.add((InlineParent) a); | |||
} | |||
a = ((InlineArea) a) .getParentArea(); |
@@ -25,12 +25,7 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.traits.Direction; | |||
import org.apache.fop.util.CharUtilities; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
/** | |||
* <p>The <code>UnicodeBidiAlgorithm</code> class implements functionality prescribed by | |||
@@ -125,47 +120,39 @@ public final class UnicodeBidiAlgorithm implements BidiConstants { | |||
case RLE: // start right-to-left embedding | |||
case LRO: // start left-to-right override | |||
case RLO: // start right-to-left override | |||
{ | |||
int en; /* new embedding level */ | |||
if ((bc == RLE) || (bc == RLO)) { | |||
en = ((ec & ~OVERRIDE) + 1) | 1; | |||
} else { | |||
en = ((ec & ~OVERRIDE) + 2) & ~1; | |||
} | |||
if (en < (MAX_LEVELS + 1)) { | |||
es [ ei++ ] = ec; | |||
if ((bc == LRO) || (bc == RLO)) { | |||
ec = en | OVERRIDE; | |||
} else { | |||
ec = en & ~OVERRIDE; | |||
} | |||
int en; /* new embedding level */ | |||
if ((bc == RLE) || (bc == RLO)) { | |||
en = ((ec & ~OVERRIDE) + 1) | 1; | |||
} else { | |||
en = ((ec & ~OVERRIDE) + 2) & ~1; | |||
} | |||
if (en < (MAX_LEVELS + 1)) { | |||
es [ ei++ ] = ec; | |||
if ((bc == LRO) || (bc == RLO)) { | |||
ec = en | OVERRIDE; | |||
} else { | |||
// max levels exceeded, so don't change level or override | |||
ec = en & ~OVERRIDE; | |||
} | |||
el = ec; | |||
break; | |||
} else { | |||
// max levels exceeded, so don't change level or override | |||
} | |||
el = ec; | |||
break; | |||
case PDF: // pop directional formatting | |||
{ | |||
el = ec; | |||
if (ei > 0) { | |||
ec = es [ --ei ]; | |||
} else { | |||
// ignore isolated PDF | |||
} | |||
break; | |||
el = ec; | |||
if (ei > 0) { | |||
ec = es [ --ei ]; | |||
} else { | |||
// ignore isolated PDF | |||
} | |||
break; | |||
case B: // paragraph separator | |||
{ | |||
el = ec = defaultLevel; | |||
ei = 0; | |||
break; | |||
} | |||
el = ec = defaultLevel; | |||
ei = 0; | |||
break; | |||
default: | |||
{ | |||
el = ec; | |||
break; | |||
} | |||
el = ec; | |||
break; | |||
} | |||
switch (bc) { | |||
case BN: | |||
@@ -608,7 +595,7 @@ public final class UnicodeBidiAlgorithm implements BidiConstants { | |||
private static boolean isRetainedFormatting(int[] ca, int s, int e) { | |||
for (int i = s; i < e; i++) { | |||
if (! isRetainedFormatting(ca[i])) { | |||
if (!isRetainedFormatting(ca[i])) { | |||
return false; | |||
} | |||
} | |||
@@ -680,7 +667,7 @@ public final class UnicodeBidiAlgorithm implements BidiConstants { | |||
} else { | |||
chOut = chIn; | |||
} | |||
if (! triggered && triggersBidi(chOut)) { | |||
if (!triggered && triggersBidi(chOut)) { | |||
triggered = true; | |||
} | |||
if ((chOut & 0xFF0000) == 0) { |
@@ -23,7 +23,6 @@ import java.util.Iterator; | |||
import java.util.List; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>Base class implementation of glyph class table.</p> | |||
@@ -100,7 +99,7 @@ public final class GlyphClassTable extends GlyphMappingTable implements GlyphCla | |||
} else { | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (! (o instanceof Integer)) { | |||
if (!(o instanceof Integer)) { | |||
return false; | |||
} | |||
} | |||
@@ -114,7 +113,7 @@ public final class GlyphClassTable extends GlyphMappingTable implements GlyphCla | |||
} else { | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (! (o instanceof MappingRange)) { | |||
if (!(o instanceof MappingRange)) { | |||
return false; | |||
} | |||
} | |||
@@ -128,7 +127,7 @@ public final class GlyphClassTable extends GlyphMappingTable implements GlyphCla | |||
} else { | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (! (o instanceof GlyphCoverageTable)) { | |||
if (!(o instanceof GlyphCoverageTable)) { | |||
return false; | |||
} | |||
} | |||
@@ -197,7 +196,7 @@ public final class GlyphClassTable extends GlyphMappingTable implements GlyphCla | |||
if (it.hasNext()) { | |||
Object o = it.next(); | |||
if (o instanceof Integer) { | |||
firstGlyph = ((Integer) o) . intValue(); | |||
firstGlyph = ((Integer) o) .intValue(); | |||
} else { | |||
throw new AdvancedTypographicTableFormatException("illegal entry, first entry must be Integer denoting first glyph value, but is: " + o); | |||
} | |||
@@ -210,7 +209,7 @@ public final class GlyphClassTable extends GlyphMappingTable implements GlyphCla | |||
while (it.hasNext()) { | |||
Object o = it.next(); | |||
if (o instanceof Integer) { | |||
int gc = ((Integer) o) . intValue(); | |||
int gc = ((Integer) o) .intValue(); | |||
gca [ i++ ] = gc; | |||
if (gc > gcMax) { | |||
gcMax = gc; |
@@ -27,8 +27,6 @@ import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>.Base class implementation of glyph coverage table.</p> | |||
@@ -103,7 +101,7 @@ public final class GlyphCoverageTable extends GlyphMappingTable implements Glyph | |||
} else { | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (! (o instanceof Integer)) { | |||
if (!(o instanceof Integer)) { | |||
return false; | |||
} | |||
} | |||
@@ -117,7 +115,7 @@ public final class GlyphCoverageTable extends GlyphMappingTable implements Glyph | |||
} else { | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (! (o instanceof MappingRange)) { | |||
if (!(o instanceof MappingRange)) { | |||
return false; | |||
} | |||
} | |||
@@ -183,7 +181,7 @@ public final class GlyphCoverageTable extends GlyphMappingTable implements Glyph | |||
for (Iterator it = entries.iterator(); it.hasNext();) { | |||
Object o = it.next(); | |||
if (o instanceof Integer) { | |||
int gid = ((Integer) o) . intValue(); | |||
int gid = ((Integer) o) .intValue(); | |||
if ((gid >= 0) && (gid < 65536)) { | |||
if (gid > gidMax) { | |||
map [ i++ ] = gidMax = gid; |
@@ -20,7 +20,6 @@ | |||
package org.apache.fop.complexscripts.fonts; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: InnerAssignmentCheck | |||
/** | |||
* <p>The <code>GlyphDefinitionSubtable</code> implements an abstract base of a glyph definition subtable, |
@@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.complexscripts.scripts.ScriptProcessor; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
/** |
@@ -23,8 +23,6 @@ import java.util.Arrays; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -162,7 +160,7 @@ public class GlyphMappingTable { | |||
int mi; | |||
if ((i = Arrays.binarySearch(sa, gid)) >= 0) { | |||
mi = getMappedIndex(gid, sa [ i ], ma [ i ]); // matches start of (some) range | |||
} else if ((i = - (i + 1)) == 0) { | |||
} else if ((i = -(i + 1)) == 0) { | |||
mi = -1; // precedes first range | |||
} else if (gid > ea [ --i ]) { | |||
mi = -1; // follows preceding (or last) range |
@@ -23,7 +23,6 @@ import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: ParameterNumberCheck | |||
/** | |||
* <p>The <code>GlyphPositioningState</code> implements an state object used during glyph positioning |
@@ -23,8 +23,6 @@ import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
/** | |||
* <p>The <code>GlyphPositioningSubtable</code> implements an abstract base of a glyph subtable, | |||
@@ -90,8 +88,8 @@ public abstract class GlyphPositioningSubtable extends GlyphSubtable implements | |||
boolean appliedOneShot = false; | |||
while (ps.hasNext()) { | |||
boolean applied = false; | |||
if (! appliedOneShot && ps.maybeApplicable()) { | |||
for (int i = 0, n = sta.length; ! applied && (i < n); i++) { | |||
if (!appliedOneShot && ps.maybeApplicable()) { | |||
for (int i = 0, n = sta.length; !applied && (i < n); i++) { | |||
if (sequenceIndex < 0) { | |||
applied = ps.apply(sta [ i ]); | |||
} else if (ps.getPosition() == (sequenceStart + sequenceIndex)) { | |||
@@ -102,7 +100,7 @@ public abstract class GlyphPositioningSubtable extends GlyphSubtable implements | |||
} | |||
} | |||
} | |||
if (! applied || ! ps.didConsume()) { | |||
if (!applied || !ps.didConsume()) { | |||
ps.applyDefault(); | |||
} | |||
ps.next(); |
@@ -33,9 +33,6 @@ import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.GlyphTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
/** | |||
* <p>The <code>GlyphPositioningTable</code> class is a glyph table that implements | |||
@@ -368,7 +365,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof Value[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof Value[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, single entry must be a Value[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
Value[] va = (Value[]) o; | |||
@@ -412,7 +409,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
int offsetLast = counts[0] + counts[1]; | |||
// skip any ignored glyphs prior to first non-ignored glyph | |||
for ( ; offset < offsetLast; ++offset) { | |||
if (! ps.isIgnoredGlyph(offset)) { | |||
if (!ps.isIgnoredGlyph(offset)) { | |||
break; | |||
} else { | |||
ps.consume(1); | |||
@@ -429,7 +426,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
} | |||
// skip any ignored glyphs prior to second non-ignored glyph | |||
for ( ; offset < offsetLast; ++offset) { | |||
if (! ps.isIgnoredGlyph(offset)) { | |||
if (!ps.isIgnoredGlyph(offset)) { | |||
break; | |||
} else { | |||
ps.consume(1); | |||
@@ -513,7 +510,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof PairValues[][])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof PairValues[][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first (and only) entry must be a PairValues[][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
pvm = (PairValues[][]) o; | |||
@@ -569,27 +566,27 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
cdt1 = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
cdt2 = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
nc1 = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
nc2 = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(4)) == null) || ! (o instanceof PairValues[][])) { | |||
if (((o = entries.get(4)) == null) || !(o instanceof PairValues[][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be a PairValues[][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
pvm = (PairValues[][]) o; | |||
@@ -633,7 +630,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
int enw = ps.getWidth(gi2); | |||
if ((exa != null) && (ena != null)) { | |||
Value v = ena.getAlignmentAdjustment(exa); | |||
v.adjust(- enw, 0, 0, 0); | |||
v.adjust(-enw, 0, 0, 0); | |||
if (ps.adjust(v)) { | |||
ps.setAdjusted(true); | |||
} | |||
@@ -704,10 +701,10 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof Anchor[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof Anchor[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first (and only) entry must be a Anchor[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else if ((((Anchor[]) o) . length % 2) != 0) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, Anchor[] array must have an even number of entries, but has: " + ((Anchor[]) o) . length); | |||
} else if ((((Anchor[]) o) .length % 2) != 0) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, Anchor[] array must have an even number of entries, but has: " + ((Anchor[]) o) .length); | |||
} else { | |||
aa = (Anchor[]) o; | |||
} | |||
@@ -736,7 +733,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
MarkAnchor ma = getMarkAnchor(ciMark, giMark); | |||
if (ma != null) { | |||
for (int i = 0, n = ps.getPosition(); i < n; i++) { | |||
int gi = ps.getGlyph(- (i + 1)); | |||
int gi = ps.getGlyph(-(i + 1)); | |||
if (ps.isMark(gi)) { | |||
continue; | |||
} else { | |||
@@ -746,7 +743,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
// start experimental fix for END OF AYAH in Lateef/Scheherazade | |||
int[] aa = ps.getAdjustment(); | |||
if (aa[2] == 0) { | |||
v.adjust(0, 0, - ps.getWidth(giMark), 0); | |||
v.adjust(0, 0, -ps.getWidth(giMark), 0); | |||
} | |||
// end experimental fix for END OF AYAH in Lateef/Scheherazade | |||
if (ps.adjust(v)) { | |||
@@ -835,22 +832,22 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphCoverageTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphCoverageTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
bct = (GlyphCoverageTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
nmc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof MarkAnchor[])) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof MarkAnchor[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
maa = (MarkAnchor[]) o; | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof Anchor[][])) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof Anchor[][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a Anchor[][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
bam = (Anchor[][]) o; | |||
@@ -881,7 +878,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
int mxc = getMaxComponentCount(); | |||
if (ma != null) { | |||
for (int i = 0, n = ps.getPosition(); i < n; i++) { | |||
int gi = ps.getGlyph(- (i + 1)); | |||
int gi = ps.getGlyph(-(i + 1)); | |||
if (ps.isMark(gi)) { | |||
continue; | |||
} else { | |||
@@ -989,27 +986,27 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphCoverageTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphCoverageTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
lct = (GlyphCoverageTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
nmc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
mxc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof MarkAnchor[])) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof MarkAnchor[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
maa = (MarkAnchor[]) o; | |||
} | |||
if (((o = entries.get(4)) == null) || ! (o instanceof Anchor[][][])) { | |||
if (((o = entries.get(4)) == null) || !(o instanceof Anchor[][][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be a Anchor[][][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
lam = (Anchor[][][]) o; | |||
@@ -1125,22 +1122,22 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphCoverageTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphCoverageTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
mct2 = (GlyphCoverageTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
nmc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof MarkAnchor[])) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof MarkAnchor[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
maa = (MarkAnchor[]) o; | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof Anchor[][])) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof Anchor[][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a Anchor[][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
mam = (Anchor[][]) o; | |||
@@ -1274,7 +1271,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1367,17 +1364,17 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
cdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
ngc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1467,7 +1464,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1585,7 +1582,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1661,27 +1658,27 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
icdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(1)) != null) && ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(1)) != null) && !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass()); | |||
} else { | |||
bcdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(2)) != null) && ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(2)) != null) && !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass()); | |||
} else { | |||
lcdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
ngc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(4)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(4)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1752,7 +1749,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -2005,7 +2002,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
boolean first = true; | |||
sb.append("{ "); | |||
if (xPlacement != 0) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2013,7 +2010,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("xPlacement = " + xPlacement); | |||
} | |||
if (yPlacement != 0) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2021,7 +2018,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("yPlacement = " + yPlacement); | |||
} | |||
if (xAdvance != 0) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2029,7 +2026,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("xAdvance = " + xAdvance); | |||
} | |||
if (yAdvance != 0) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2037,7 +2034,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("yAdvance = " + yAdvance); | |||
} | |||
if (xPlaDevice != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2045,7 +2042,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("xPlaDevice = " + xPlaDevice); | |||
} | |||
if (yPlaDevice != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2053,7 +2050,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("xPlaDevice = " + yPlaDevice); | |||
} | |||
if (xAdvDevice != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2061,7 +2058,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("xAdvDevice = " + xAdvDevice); | |||
} | |||
if (yAdvDevice != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2118,7 +2115,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
boolean first = true; | |||
sb.append("{ "); | |||
if (glyph != 0) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2126,7 +2123,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("glyph = " + glyph); | |||
} | |||
if (value1 != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; | |||
@@ -2134,7 +2131,7 @@ public class GlyphPositioningTable extends GlyphTable { | |||
sb.append("value1 = " + value1); | |||
} | |||
if (value2 != null) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(", "); | |||
} else { | |||
first = false; |
@@ -29,7 +29,6 @@ import org.apache.fop.complexscripts.util.GlyphTester; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>The <code>GlyphProcessingState</code> implements a common, base state object used during glyph substitution | |||
@@ -459,7 +458,7 @@ public class GlyphProcessingState { | |||
int start = index + offset; | |||
if (start < 0) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + start); | |||
} else if (! reverseOrder && ((start + count) > indexLast)) { | |||
} else if (!reverseOrder && ((start + count) > indexLast)) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + (start + count)); | |||
} else if (reverseOrder && ((start + 1) < count)) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + (start - count)); | |||
@@ -469,7 +468,7 @@ public class GlyphProcessingState { | |||
} else if (glyphs.length != count) { | |||
throw new IllegalArgumentException("glyphs array is non-null, but its length (" + glyphs.length + "), is not equal to count (" + count + ")"); | |||
} | |||
if (! reverseOrder) { | |||
if (!reverseOrder) { | |||
return getGlyphsForward(start, count, ignoreTester, glyphs, counts); | |||
} else { | |||
return getGlyphsReverse(start, count, ignoreTester, glyphs, counts); | |||
@@ -484,7 +483,7 @@ public class GlyphProcessingState { | |||
if (gi == 65535) { | |||
ignored++; | |||
} else { | |||
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) { | |||
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) { | |||
glyphs [ counted++ ] = gi; | |||
} else { | |||
ignored++; | |||
@@ -506,7 +505,7 @@ public class GlyphProcessingState { | |||
if (gi == 65535) { | |||
ignored++; | |||
} else { | |||
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) { | |||
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) { | |||
glyphs [ counted++ ] = gi; | |||
} else { | |||
ignored++; | |||
@@ -629,7 +628,7 @@ public class GlyphProcessingState { | |||
int start = index + offset; | |||
if ((start < 0) || (start > indexLast)) { | |||
return new int[] { 0, 0 }; | |||
} else if (! reverseOrder) { | |||
} else if (!reverseOrder) { | |||
return getGlyphsAvailableForward(start, ignoreTester); | |||
} else { | |||
return getGlyphsAvailableReverse(start, ignoreTester); | |||
@@ -731,7 +730,7 @@ public class GlyphProcessingState { | |||
int start = index + offset; | |||
if (start < 0) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + start); | |||
} else if (! reverseOrder && ((start + count) > indexLast)) { | |||
} else if (!reverseOrder && ((start + count) > indexLast)) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + (start + count)); | |||
} else if (reverseOrder && ((start + 1) < count)) { | |||
throw new IndexOutOfBoundsException("will attempt index at " + (start - count)); | |||
@@ -741,7 +740,7 @@ public class GlyphProcessingState { | |||
} else if (associations.length != count) { | |||
throw new IllegalArgumentException("associations array is non-null, but its length (" + associations.length + "), is not equal to count (" + count + ")"); | |||
} | |||
if (! reverseOrder) { | |||
if (!reverseOrder) { | |||
return getAssociationsForward(start, count, ignoreTester, associations, counts); | |||
} else { | |||
return getAssociationsReverse(start, count, ignoreTester, associations, counts); | |||
@@ -757,7 +756,7 @@ public class GlyphProcessingState { | |||
if (gi == 65535) { | |||
ignored++; | |||
} else { | |||
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) { | |||
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) { | |||
if (k < count) { | |||
associations [ k++ ] = getAssociation(i - index); | |||
counted++; | |||
@@ -785,7 +784,7 @@ public class GlyphProcessingState { | |||
if (gi == 65535) { | |||
ignored++; | |||
} else { | |||
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) { | |||
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) { | |||
if (k < count) { | |||
associations [ k++ ] = getAssociation(i - index); | |||
counted++; | |||
@@ -1169,7 +1168,7 @@ public class GlyphProcessingState { | |||
for (int i = 0, n = ngt; i < n; i++) { | |||
GlyphTester gt = gta [ i ]; | |||
if (gt != null) { | |||
if (! gt.test(gi, flags)) { | |||
if (!gt.test(gi, flags)) { | |||
return false; | |||
} | |||
} |
@@ -27,7 +27,6 @@ import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>The <code>GlyphSubstitutionState</code> implements an state object used during glyph substitution | |||
@@ -130,7 +129,7 @@ public class GlyphSubstitutionState extends GlyphProcessingState { | |||
* @param predication a predication value to add to association A if predications enabled | |||
*/ | |||
public void putGlyph(int glyph, GlyphSequence.CharAssociation a, Object predication) { | |||
if (! ogb.hasRemaining()) { | |||
if (!ogb.hasRemaining()) { | |||
ogb = growBuffer(ogb); | |||
} | |||
ogb.put(glyph); |
@@ -23,7 +23,6 @@ import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>The <code>GlyphSubstitutionSubtable</code> implements an abstract base of a glyph substitution subtable, | |||
@@ -90,8 +89,8 @@ public abstract class GlyphSubstitutionSubtable extends GlyphSubtable implements | |||
boolean appliedOneShot = false; | |||
while (ss.hasNext()) { | |||
boolean applied = false; | |||
if (! appliedOneShot && ss.maybeApplicable()) { | |||
for (int i = 0, n = sta.length; ! applied && (i < n); i++) { | |||
if (!appliedOneShot && ss.maybeApplicable()) { | |||
for (int i = 0, n = sta.length; !applied && (i < n); i++) { | |||
if (sequenceIndex < 0) { | |||
applied = ss.apply(sta [ i ]); | |||
} else if (ss.getPosition() == (sequenceStart + sequenceIndex)) { | |||
@@ -102,7 +101,7 @@ public abstract class GlyphSubstitutionSubtable extends GlyphSubtable implements | |||
} | |||
} | |||
} | |||
if (! applied || ! ss.didConsume()) { | |||
if (!applied || !ss.didConsume()) { | |||
ss.applyDefault(); | |||
} | |||
ss.next(); |
@@ -31,9 +31,7 @@ import org.apache.fop.complexscripts.scripts.ScriptProcessor; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.GlyphTester; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>The <code>GlyphSubstitutionTable</code> class is a glyph table that implements | |||
@@ -306,7 +304,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
Object o = entries.get(0); | |||
int delta = 0; | |||
if (o instanceof Integer) { | |||
delta = ((Integer) o) . intValue(); | |||
delta = ((Integer) o) .intValue(); | |||
} else { | |||
throw new AdvancedTypographicTableFormatException("illegal entries entry, must be Integer, but is: " + o); | |||
} | |||
@@ -440,7 +438,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof int[][])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof int[][])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an int[][], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
gsa = (int[][]) o; | |||
@@ -801,7 +799,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -894,17 +892,17 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
cdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(1)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(1)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
ngc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(2)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(2)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -994,7 +992,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1113,7 +1111,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1189,27 +1187,27 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
icdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(1)) != null) && ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(1)) != null) && !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass()); | |||
} else { | |||
bcdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(2)) != null) && ! (o instanceof GlyphClassTable)) { | |||
if (((o = entries.get(2)) != null) && !(o instanceof GlyphClassTable)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass()); | |||
} else { | |||
lcdt = (GlyphClassTable) o; | |||
} | |||
if (((o = entries.get(3)) == null) || ! (o instanceof Integer)) { | |||
if (((o = entries.get(3)) == null) || !(o instanceof Integer)) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
ngc = ((Integer)(o)).intValue(); | |||
} | |||
if (((o = entries.get(4)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(4)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; | |||
@@ -1280,7 +1278,7 @@ public class GlyphSubstitutionTable extends GlyphTable { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); | |||
} else { | |||
Object o; | |||
if (((o = entries.get(0)) == null) || ! (o instanceof RuleSet[])) { | |||
if (((o = entries.get(0)) == null) || !(o instanceof RuleSet[])) { | |||
throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null)); | |||
} else { | |||
rsa = (RuleSet[]) o; |
@@ -24,7 +24,6 @@ import java.lang.ref.WeakReference; | |||
import java.util.List; | |||
import java.util.Map; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
/** |
@@ -37,12 +37,7 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* <p>Base class for all advanced typographic glyph tables.</p> | |||
@@ -86,7 +81,7 @@ public class GlyphTable { | |||
* @param lookups map from lookup specs to lookup tables | |||
*/ | |||
public GlyphTable(GlyphTable gdef, Map/*<LookupSpec,List<String>>*/ lookups) { | |||
if ((gdef != null) && ! (gdef instanceof GlyphDefinitionTable)) { | |||
if ((gdef != null) && !(gdef instanceof GlyphDefinitionTable)) { | |||
throw new AdvancedTypographicTableFormatException("bad glyph definition table"); | |||
} else if (lookups == null) { | |||
throw new AdvancedTypographicTableFormatException("lookups must be non-null map"); | |||
@@ -166,7 +161,7 @@ public class GlyphTable { | |||
* create resulting cached state. | |||
*/ | |||
protected void freezeSubtables() { | |||
if (! frozen) { | |||
if (!frozen) { | |||
for (Iterator it = lookupTables.values().iterator(); it.hasNext(); ) { | |||
LookupTable lt = (LookupTable) it.next(); | |||
lt.freezeSubtables(lookupTables); | |||
@@ -188,18 +183,18 @@ public class GlyphTable { | |||
List/*<LookupSpec>*/ matches = new ArrayList/*<LookupSpec>*/(); | |||
for (Iterator it = keys.iterator(); it.hasNext();) { | |||
LookupSpec ls = (LookupSpec) it.next(); | |||
if (! "*".equals(script)) { | |||
if (! ls.getScript().equals(script)) { | |||
if (!"*".equals(script)) { | |||
if (!ls.getScript().equals(script)) { | |||
continue; | |||
} | |||
} | |||
if (! "*".equals(language)) { | |||
if (! ls.getLanguage().equals(language)) { | |||
if (!"*".equals(language)) { | |||
if (!ls.getLanguage().equals(language)) { | |||
continue; | |||
} | |||
} | |||
if (! "*".equals(feature)) { | |||
if (! ls.getFeature().equals(feature)) { | |||
if (!"*".equals(feature)) { | |||
if (!ls.getFeature().equals(feature)) { | |||
continue; | |||
} | |||
} | |||
@@ -359,17 +354,17 @@ public class GlyphTable { | |||
* @param permitWildcard if true the permit wildcard script, language, or feature | |||
*/ | |||
LookupSpec(String script, String language, String feature, boolean permitEmpty, boolean permitWildcard) { | |||
if ((script == null) || (! permitEmpty && (script.length() == 0))) { | |||
if ((script == null) || (!permitEmpty && (script.length() == 0))) { | |||
throw new AdvancedTypographicTableFormatException("script must be non-empty string"); | |||
} else if ((language == null) || (! permitEmpty && (language.length() == 0))) { | |||
} else if ((language == null) || (!permitEmpty && (language.length() == 0))) { | |||
throw new AdvancedTypographicTableFormatException("language must be non-empty string"); | |||
} else if ((feature == null) || (! permitEmpty && (feature.length() == 0))) { | |||
} else if ((feature == null) || (!permitEmpty && (feature.length() == 0))) { | |||
throw new AdvancedTypographicTableFormatException("feature must be non-empty string"); | |||
} else if (! permitWildcard && script.equals("*")) { | |||
} else if (!permitWildcard && script.equals("*")) { | |||
throw new AdvancedTypographicTableFormatException("script must not be wildcard"); | |||
} else if (! permitWildcard && language.equals("*")) { | |||
} else if (!permitWildcard && language.equals("*")) { | |||
throw new AdvancedTypographicTableFormatException("language must not be wildcard"); | |||
} else if (! permitWildcard && feature.equals("*")) { | |||
} else if (!permitWildcard && feature.equals("*")) { | |||
throw new AdvancedTypographicTableFormatException("feature must not be wildcard"); | |||
} | |||
this.script = script.trim(); | |||
@@ -405,14 +400,12 @@ public class GlyphTable { | |||
public boolean equals(Object o) { | |||
if (o instanceof LookupSpec) { | |||
LookupSpec l = (LookupSpec) o; | |||
if (! l.script.equals(script)) { | |||
if (!l.script.equals(script)) { | |||
return false; | |||
} else if (! l.language.equals(language)) { | |||
return false; | |||
} else if (! l.feature.equals(feature)) { | |||
} else if (!l.language.equals(language)) { | |||
return false; | |||
} else { | |||
return true; | |||
return l.feature.equals(feature); | |||
} | |||
} else { | |||
return false; | |||
@@ -540,7 +533,7 @@ public class GlyphTable { | |||
} | |||
} | |||
// append at end of list | |||
if (! added && (subtable != null)) { | |||
if (!added && (subtable != null)) { | |||
subtables.add(subtable); | |||
added = true; | |||
} | |||
@@ -567,7 +560,7 @@ public class GlyphTable { | |||
} | |||
if (subtables.size() > 0) { | |||
GlyphSubtable st = (GlyphSubtable) subtables.get(0); | |||
if (! st.isCompatible(subtable)) { | |||
if (!st.isCompatible(subtable)) { | |||
throw new AdvancedTypographicTableFormatException("subtable " + subtable + " is not compatible with subtable " + st); | |||
} | |||
} | |||
@@ -580,7 +573,7 @@ public class GlyphTable { | |||
* @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables | |||
*/ | |||
public void freezeSubtables(Map/*<String,LookupTable>*/ lookupTables) { | |||
if (! frozen) { | |||
if (!frozen) { | |||
GlyphSubtable[] sta = getSubtables(); | |||
resolveLookupReferences(sta, lookupTables); | |||
this.subtablesArray = sta; | |||
@@ -1305,7 +1298,7 @@ public class GlyphTable { | |||
Class c = r0.getClass(); | |||
for (int i = 1, n = rules.length; i < n; i++) { | |||
Rule r = rules[i]; | |||
if ((r != null) && ! c.isInstance(r)) { | |||
if ((r != null) && !c.isInstance(r)) { | |||
throw new AdvancedTypographicTableFormatException("rules[" + i + "] is not an instance of " + c.getName()); | |||
} | |||
} |
@@ -29,14 +29,10 @@ import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.fonts.truetype.FontFileReader; | |||
import org.apache.fop.fonts.truetype.TTFDirTabEntry; | |||
import org.apache.fop.fonts.truetype.TTFFile; | |||
import org.apache.fop.fonts.truetype.TTFTableName; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
import org.apache.fop.fonts.truetype.OFDirTabEntry; | |||
import org.apache.fop.fonts.truetype.OFTableName; | |||
import org.apache.fop.fonts.truetype.OpenFont; | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -50,7 +46,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
// logging state | |||
private static Log log = LogFactory.getLog(OTFAdvancedTypographicTableReader.class); | |||
// instance state | |||
private TTFFile ttf; // parent font file reader | |||
private OpenFont otf; // parent font file reader | |||
private FontFileReader in; // input reader | |||
private GlyphDefinitionTable gdef; // glyph definition table | |||
private GlyphSubstitutionTable gsub; // glyph substitution table | |||
@@ -68,10 +64,10 @@ public final class OTFAdvancedTypographicTableReader { | |||
* @param ttf parent font file reader (must be non-null) | |||
* @param in font file reader (must be non-null) | |||
*/ | |||
public OTFAdvancedTypographicTableReader(TTFFile ttf, FontFileReader in) { | |||
assert ttf != null; | |||
public OTFAdvancedTypographicTableReader(OpenFont otf, FontFileReader in) { | |||
assert otf != null; | |||
assert in != null; | |||
this.ttf = ttf; | |||
this.otf = otf; | |||
this.in = in; | |||
} | |||
@@ -127,7 +123,8 @@ public final class OTFAdvancedTypographicTableReader { | |||
return gpos; | |||
} | |||
private void readLangSysTable(TTFTableName tableTag, long langSysTable, String langSysTag) throws IOException { | |||
private void readLangSysTable(OFTableName tableTag, long langSysTable, String langSysTag) | |||
throws IOException { | |||
in.seekSet(langSysTable); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " lang sys table: " + langSysTag); | |||
@@ -169,7 +166,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
private static String defaultTag = "dflt"; | |||
private void readScriptTable(TTFTableName tableTag, long scriptTable, String scriptTag) throws IOException { | |||
private void readScriptTable(OFTableName tableTag, long scriptTable, String scriptTag) throws IOException { | |||
in.seekSet(scriptTable); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " script table: " + scriptTag); | |||
@@ -222,7 +219,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
seLanguages = null; | |||
} | |||
private void readScriptList(TTFTableName tableTag, long scriptList) throws IOException { | |||
private void readScriptList(OFTableName tableTag, long scriptList) throws IOException { | |||
in.seekSet(scriptList); | |||
// read script record count | |||
int ns = in.readTTFUShort(); | |||
@@ -251,7 +248,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
} | |||
} | |||
private void readFeatureTable(TTFTableName tableTag, long featureTable, String featureTag, int featureIndex) throws IOException { | |||
private void readFeatureTable(OFTableName tableTag, long featureTable, String featureTag, int featureIndex) throws IOException { | |||
in.seekSet(featureTable); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " feature table: " + featureTag); | |||
@@ -279,7 +276,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
seFeatures.put("f" + featureIndex, new Object[] { featureTag, lul }); | |||
} | |||
private void readFeatureList(TTFTableName tableTag, long featureList) throws IOException { | |||
private void readFeatureList(OFTableName tableTag, long featureList) throws IOException { | |||
in.seekSet(featureList); | |||
// read feature record count | |||
int nf = in.readTTFUShort(); | |||
@@ -1736,28 +1733,28 @@ public final class OTFAdvancedTypographicTableReader { | |||
// XPlacement | |||
int xp; | |||
if ((valueFormat & GlyphPositioningTable.Value.X_PLACEMENT) != 0) { | |||
xp = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
xp = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
} else { | |||
xp = 0; | |||
} | |||
// YPlacement | |||
int yp; | |||
if ((valueFormat & GlyphPositioningTable.Value.Y_PLACEMENT) != 0) { | |||
yp = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
yp = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
} else { | |||
yp = 0; | |||
} | |||
// XAdvance | |||
int xa; | |||
if ((valueFormat & GlyphPositioningTable.Value.X_ADVANCE) != 0) { | |||
xa = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
xa = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
} else { | |||
xa = 0; | |||
} | |||
// YAdvance | |||
int ya; | |||
if ((valueFormat & GlyphPositioningTable.Value.Y_ADVANCE) != 0) { | |||
ya = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
ya = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
} else { | |||
ya = 0; | |||
} | |||
@@ -2029,23 +2026,23 @@ public final class OTFAdvancedTypographicTableReader { | |||
int af = in.readTTFUShort(); | |||
if (af == 1) { | |||
// read x coordinate | |||
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
// read y coordinate | |||
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
a = new GlyphPositioningTable.Anchor(x, y); | |||
} else if (af == 2) { | |||
// read x coordinate | |||
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
// read y coordinate | |||
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
// read anchor point index | |||
int ap = in.readTTFUShort(); | |||
a = new GlyphPositioningTable.Anchor(x, y, ap); | |||
} else if (af == 3) { | |||
// read x coordinate | |||
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
// read y coordinate | |||
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort()); | |||
// read x device table offset | |||
int xdo = in.readTTFUShort(); | |||
// read y device table offset | |||
@@ -3145,9 +3142,9 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readLookupTable(TTFTableName tableTag, int lookupSequence, long lookupTable) throws IOException { | |||
boolean isGSUB = tableTag.equals(TTFTableName.GSUB); | |||
boolean isGPOS = tableTag.equals(TTFTableName.GPOS); | |||
private void readLookupTable(OFTableName tableTag, int lookupSequence, long lookupTable) throws IOException { | |||
boolean isGSUB = tableTag.equals(OFTableName.GSUB); | |||
boolean isGPOS = tableTag.equals(OFTableName.GPOS); | |||
in.seekSet(lookupTable); | |||
// read lookup type | |||
int lt = in.readTTFUShort(); | |||
@@ -3198,7 +3195,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
} | |||
} | |||
private void readLookupList(TTFTableName tableTag, long lookupList) throws IOException { | |||
private void readLookupList(OFTableName tableTag, long lookupList) throws IOException { | |||
in.seekSet(lookupList); | |||
// read lookup record count | |||
int nl = in.readTTFUShort(); | |||
@@ -3233,7 +3230,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
* @param lookupList offset to lookup list from beginning of font file | |||
* @throws IOException In case of a I/O problem | |||
*/ | |||
private void readCommonLayoutTables(TTFTableName tableTag, long scriptList, long featureList, long lookupList) throws IOException { | |||
private void readCommonLayoutTables(OFTableName tableTag, long scriptList, long featureList, long lookupList) throws IOException { | |||
if (scriptList > 0) { | |||
readScriptList(tableTag, scriptList); | |||
} | |||
@@ -3245,7 +3242,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
} | |||
} | |||
private void readGDEFClassDefTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
private void readGDEFClassDefTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
initATSubState(); | |||
in.seekSet(subtableOffset); | |||
// subtable is a bare class definition table | |||
@@ -3257,7 +3254,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readGDEFAttachmentTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
private void readGDEFAttachmentTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
initATSubState(); | |||
in.seekSet(subtableOffset); | |||
// read coverage offset | |||
@@ -3275,7 +3272,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readGDEFLigatureCaretTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
private void readGDEFLigatureCaretTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
initATSubState(); | |||
in.seekSet(subtableOffset); | |||
// read coverage offset | |||
@@ -3305,7 +3302,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readGDEFMarkAttachmentTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
private void readGDEFMarkAttachmentTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
initATSubState(); | |||
in.seekSet(subtableOffset); | |||
// subtable is a bare class definition table | |||
@@ -3317,7 +3314,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readGDEFMarkGlyphsTableFormat1(TTFTableName tableTag, int lookupSequence, long subtableOffset, int subtableFormat) throws IOException { | |||
private void readGDEFMarkGlyphsTableFormat1(OFTableName tableTag, int lookupSequence, long subtableOffset, int subtableFormat) throws IOException { | |||
initATSubState(); | |||
in.seekSet(subtableOffset); | |||
// skip over format (already known) | |||
@@ -3351,7 +3348,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
resetATSubState(); | |||
} | |||
private void readGDEFMarkGlyphsTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
private void readGDEFMarkGlyphsTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException { | |||
in.seekSet(subtableOffset); | |||
// read mark set subtable format | |||
int sf = in.readTTFUShort(); | |||
@@ -3367,17 +3364,17 @@ public final class OTFAdvancedTypographicTableReader { | |||
* @throws IOException In case of a I/O problem | |||
*/ | |||
private void readGDEF() throws IOException { | |||
TTFTableName tableTag = TTFTableName.GDEF; | |||
OFTableName tableTag = OFTableName.GDEF; | |||
// Initialize temporary state | |||
initATState(); | |||
// Read glyph definition (GDEF) table | |||
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag); | |||
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag); | |||
if (gdef != null) { | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + ": ignoring duplicate table"); | |||
} | |||
} else if (dirTab != null) { | |||
ttf.seekTab(in, tableTag, 0); | |||
otf.seekTab(in, tableTag, 0); | |||
long version = in.readTTFULong(); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); | |||
@@ -3440,17 +3437,17 @@ public final class OTFAdvancedTypographicTableReader { | |||
* @throws IOException In case of a I/O problem | |||
*/ | |||
private void readGSUB() throws IOException { | |||
TTFTableName tableTag = TTFTableName.GSUB; | |||
OFTableName tableTag = OFTableName.GSUB; | |||
// Initialize temporary state | |||
initATState(); | |||
// Read glyph substitution (GSUB) table | |||
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag); | |||
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag); | |||
if (gpos != null) { | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + ": ignoring duplicate table"); | |||
} | |||
} else if (dirTab != null) { | |||
ttf.seekTab(in, tableTag, 0); | |||
otf.seekTab(in, tableTag, 0); | |||
int version = in.readTTFLong(); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); | |||
@@ -3477,17 +3474,17 @@ public final class OTFAdvancedTypographicTableReader { | |||
* @throws IOException In case of a I/O problem | |||
*/ | |||
private void readGPOS() throws IOException { | |||
TTFTableName tableTag = TTFTableName.GPOS; | |||
OFTableName tableTag = OFTableName.GPOS; | |||
// Initialize temporary state | |||
initATState(); | |||
// Read glyph positioning (GPOS) table | |||
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag); | |||
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag); | |||
if (gpos != null) { | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + ": ignoring duplicate table"); | |||
} | |||
} else if (dirTab != null) { | |||
ttf.seekTab(in, tableTag, 0); | |||
otf.seekTab(in, tableTag, 0); | |||
int version = in.readTTFLong(); | |||
if (log.isDebugEnabled()) { | |||
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); | |||
@@ -3790,7 +3787,7 @@ public final class OTFAdvancedTypographicTableReader { | |||
} else { | |||
boolean first = true; | |||
for (int i = 0; i < ia.length; i++) { | |||
if (! first) { | |||
if (!first) { | |||
sb.append(' '); | |||
} else { | |||
first = false; |
@@ -33,10 +33,6 @@ import org.apache.fop.complexscripts.util.GlyphContextTester; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -159,11 +155,11 @@ public class ArabicScriptProcessor extends DefaultScriptProcessor { | |||
} else { | |||
int s = a.getStart(); | |||
int e = a.getEnd(); | |||
if (! hasFinalPrecedingContext(ca, nc, s, e)) { | |||
if (!hasFinalPrecedingContext(ca, nc, s, e)) { | |||
return false; | |||
} else if (forcesFinalThisContext(ca, nc, s, e)) { | |||
return true; | |||
} else if (! hasFinalFollowingContext(ca, nc, s, e)) { | |||
} else if (!hasFinalFollowingContext(ca, nc, s, e)) { | |||
return false; | |||
} else { | |||
return true; | |||
@@ -180,9 +176,9 @@ public class ArabicScriptProcessor extends DefaultScriptProcessor { | |||
} else { | |||
int s = a.getStart(); | |||
int e = a.getEnd(); | |||
if (! hasInitialPrecedingContext(ca, nc, s, e)) { | |||
if (!hasInitialPrecedingContext(ca, nc, s, e)) { | |||
return false; | |||
} else if (! hasInitialFollowingContext(ca, nc, s, e)) { | |||
} else if (!hasInitialFollowingContext(ca, nc, s, e)) { | |||
return false; | |||
} else { | |||
return true; | |||
@@ -211,9 +207,9 @@ public class ArabicScriptProcessor extends DefaultScriptProcessor { | |||
} else { | |||
int s = a.getStart(); | |||
int e = a.getEnd(); | |||
if (! hasLigaturePrecedingContext(ca, nc, s, e)) { | |||
if (!hasLigaturePrecedingContext(ca, nc, s, e)) { | |||
return false; | |||
} else if (! hasLigatureFollowingContext(ca, nc, s, e)) { | |||
} else if (!hasLigatureFollowingContext(ca, nc, s, e)) { | |||
return false; | |||
} else { | |||
return true; | |||
@@ -230,11 +226,11 @@ public class ArabicScriptProcessor extends DefaultScriptProcessor { | |||
} else { | |||
int s = a.getStart(); | |||
int e = a.getEnd(); | |||
if (! hasMedialPrecedingContext(ca, nc, s, e)) { | |||
if (!hasMedialPrecedingContext(ca, nc, s, e)) { | |||
return false; | |||
} else if (! hasMedialThisContext(ca, nc, s, e)) { | |||
} else if (!hasMedialThisContext(ca, nc, s, e)) { | |||
return false; | |||
} else if (! hasMedialFollowingContext(ca, nc, s, e)) { | |||
} else if (!hasMedialFollowingContext(ca, nc, s, e)) { | |||
return false; | |||
} else { | |||
return true; |
@@ -24,11 +24,6 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: WhitespaceAfter | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -109,7 +104,7 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsHalfConsonant(GlyphSequence gs, int k) { | |||
Boolean half = (Boolean) gs.getAssociation(k) . getPredication("half"); | |||
Boolean half = (Boolean) gs.getAssociation(k) .getPredication("half"); | |||
return (half != null) ? half.booleanValue() : false; | |||
} | |||
@@ -134,7 +129,7 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
// first candidate target is after first non-half consonant | |||
for (int i = 0; i < ng; i++) { | |||
if ((i != source) && containsConsonant(gs, i)) { | |||
if (! containsHalfConsonant(gs, i)) { | |||
if (!containsHalfConsonant(gs, i)) { | |||
c1 = i + 1; | |||
break; | |||
} | |||
@@ -142,7 +137,7 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
} | |||
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark | |||
for (int i = (c1 >= 0) ? c1 : 0; i < ng; i++) { | |||
if (containsMatra(gs, i) && ! containsPreBaseMatra(gs, i)) { | |||
if (containsMatra(gs, i) && !containsPreBaseMatra(gs, i)) { | |||
c2 = i + 1; | |||
} else if (containsOtherMark(gs, i)) { | |||
c2 = i; | |||
@@ -159,7 +154,7 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsReph(GlyphSequence gs, int k) { | |||
Boolean rphf = (Boolean) gs.getAssociation(k) . getPredication("rphf"); | |||
Boolean rphf = (Boolean) gs.getAssociation(k) .getPredication("rphf"); | |||
return (rphf != null) ? rphf.booleanValue() : false; | |||
} | |||
@@ -503,13 +498,13 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean isC(int c) { | |||
return isType(c,C_C); | |||
return isType(c, C_C); | |||
} | |||
static boolean isR(int c) { | |||
return isType(c,C_C) && hasR(c); | |||
return isType(c, C_C) && hasR(c); | |||
} | |||
static boolean isV(int c) { | |||
return isType(c,C_V); | |||
return isType(c, C_V); | |||
} | |||
static boolean isN(int c) { | |||
return c == 0x093C; | |||
@@ -518,10 +513,10 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
return c == 0x094D; | |||
} | |||
static boolean isM(int c) { | |||
return isType(c,C_M); | |||
return isType(c, C_M); | |||
} | |||
static boolean isPreM(int c) { | |||
return isType(c,C_M) && hasFlag(c,C_PRE); | |||
return isType(c, C_M) && hasFlag(c, C_PRE); | |||
} | |||
static boolean isX(int c) { | |||
switch (typeOf(c)) { | |||
@@ -535,10 +530,10 @@ public class DevanagariScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean hasR(int c) { | |||
return hasFlag(c,C_R); | |||
return hasFlag(c, C_R); | |||
} | |||
static boolean hasN(int c) { | |||
return hasFlag(c,C_N); | |||
return hasFlag(c, C_N); | |||
} | |||
} |
@@ -24,11 +24,6 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: WhitespaceAfter | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -109,7 +104,7 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsHalfConsonant(GlyphSequence gs, int k) { | |||
Boolean half = (Boolean) gs.getAssociation(k) . getPredication("half"); | |||
Boolean half = (Boolean) gs.getAssociation(k) .getPredication("half"); | |||
return (half != null) ? half.booleanValue() : false; | |||
} | |||
@@ -134,7 +129,7 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
// first candidate target is after first non-half consonant | |||
for (int i = 0; i < ng; i++) { | |||
if ((i != source) && containsConsonant(gs, i)) { | |||
if (! containsHalfConsonant(gs, i)) { | |||
if (!containsHalfConsonant(gs, i)) { | |||
c1 = i + 1; | |||
break; | |||
} | |||
@@ -142,7 +137,7 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark | |||
for (int i = (c1 >= 0) ? c1 : 0; i < ng; i++) { | |||
if (containsMatra(gs, i) && ! containsPreBaseMatra(gs, i)) { | |||
if (containsMatra(gs, i) && !containsPreBaseMatra(gs, i)) { | |||
c2 = i + 1; | |||
} else if (containsOtherMark(gs, i)) { | |||
c2 = i; | |||
@@ -159,7 +154,7 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsReph(GlyphSequence gs, int k) { | |||
Boolean rphf = (Boolean) gs.getAssociation(k) . getPredication("rphf"); | |||
Boolean rphf = (Boolean) gs.getAssociation(k) .getPredication("rphf"); | |||
return (rphf != null) ? rphf.booleanValue() : false; | |||
} | |||
@@ -503,13 +498,13 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean isC(int c) { | |||
return isType(c,C_C); | |||
return isType(c, C_C); | |||
} | |||
static boolean isR(int c) { | |||
return isType(c,C_C) && hasR(c); | |||
return isType(c, C_C) && hasR(c); | |||
} | |||
static boolean isV(int c) { | |||
return isType(c,C_V); | |||
return isType(c, C_V); | |||
} | |||
static boolean isN(int c) { | |||
return c == 0x0ABC; | |||
@@ -518,10 +513,10 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
return c == 0x0ACD; | |||
} | |||
static boolean isM(int c) { | |||
return isType(c,C_M); | |||
return isType(c, C_M); | |||
} | |||
static boolean isPreM(int c) { | |||
return isType(c,C_M) && hasFlag(c,C_PRE); | |||
return isType(c, C_M) && hasFlag(c, C_PRE); | |||
} | |||
static boolean isX(int c) { | |||
switch (typeOf(c)) { | |||
@@ -535,10 +530,10 @@ public class GujaratiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean hasR(int c) { | |||
return hasFlag(c,C_R); | |||
return hasFlag(c, C_R); | |||
} | |||
static boolean hasN(int c) { | |||
return hasFlag(c,C_N); | |||
return hasFlag(c, C_N); | |||
} | |||
} |
@@ -25,11 +25,6 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: WhitespaceAfter | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -110,7 +105,7 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsHalfConsonant(GlyphSequence gs, int k) { | |||
Boolean half = (Boolean) gs.getAssociation(k) . getPredication("half"); | |||
Boolean half = (Boolean) gs.getAssociation(k) .getPredication("half"); | |||
return (half != null) ? half.booleanValue() : false; | |||
} | |||
@@ -135,7 +130,7 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
// first candidate target is after first non-half consonant | |||
for (int i = 0; i < ng; i++) { | |||
if ((i != source) && containsConsonant(gs, i)) { | |||
if (! containsHalfConsonant(gs, i)) { | |||
if (!containsHalfConsonant(gs, i)) { | |||
c1 = i + 1; | |||
break; | |||
} | |||
@@ -143,7 +138,7 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark | |||
for (int i = (c1 >= 0) ? c1 : 0; i < ng; i++) { | |||
if (containsMatra(gs, i) && ! containsPreBaseMatra(gs, i)) { | |||
if (containsMatra(gs, i) && !containsPreBaseMatra(gs, i)) { | |||
c2 = i + 1; | |||
} else if (containsOtherMark(gs, i)) { | |||
c2 = i; | |||
@@ -160,7 +155,7 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
private static boolean containsReph(GlyphSequence gs, int k) { | |||
Boolean rphf = (Boolean) gs.getAssociation(k) . getPredication("rphf"); | |||
Boolean rphf = (Boolean) gs.getAssociation(k) .getPredication("rphf"); | |||
return (rphf != null) ? rphf.booleanValue() : false; | |||
} | |||
@@ -504,13 +499,13 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean isC(int c) { | |||
return isType(c,C_C); | |||
return isType(c, C_C); | |||
} | |||
static boolean isR(int c) { | |||
return isType(c,C_C) && hasR(c); | |||
return isType(c, C_C) && hasR(c); | |||
} | |||
static boolean isV(int c) { | |||
return isType(c,C_V); | |||
return isType(c, C_V); | |||
} | |||
static boolean isN(int c) { | |||
return c == 0x0A3C; | |||
@@ -519,10 +514,10 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
return c == 0x0A4D; | |||
} | |||
static boolean isM(int c) { | |||
return isType(c,C_M); | |||
return isType(c, C_M); | |||
} | |||
static boolean isPreM(int c) { | |||
return isType(c,C_M) && hasFlag(c,C_PRE); | |||
return isType(c, C_M) && hasFlag(c, C_PRE); | |||
} | |||
static boolean isX(int c) { | |||
switch (typeOf(c)) { | |||
@@ -536,10 +531,10 @@ public class GurmukhiScriptProcessor extends IndicScriptProcessor { | |||
} | |||
} | |||
static boolean hasR(int c) { | |||
return hasFlag(c,C_R); | |||
return hasFlag(c, C_R); | |||
} | |||
static boolean hasN(int c) { | |||
return hasFlag(c,C_N); | |||
return hasFlag(c, C_N); | |||
} | |||
@Override |
@@ -36,13 +36,6 @@ import org.apache.fop.complexscripts.util.GlyphContextTester; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: EmptyForIteratorPadCheck | |||
// CSOFF: WhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -222,7 +215,7 @@ public class IndicScriptProcessor extends DefaultScriptProcessor { | |||
} | |||
private GlyphSequence[] syllabize(GlyphSequence gs, String script, String language) { | |||
return Syllabizer.getSyllabizer(script, language, getSyllabizerClass()) . syllabize(gs); | |||
return Syllabizer.getSyllabizer(script, language, getSyllabizerClass()) .syllabize(gs); | |||
} | |||
private GlyphSequence unsyllabize(GlyphSequence gs, GlyphSequence[] sa) { | |||
@@ -384,12 +377,10 @@ public class IndicScriptProcessor extends DefaultScriptProcessor { | |||
public boolean equals(Object o) { | |||
if (o instanceof Syllabizer) { | |||
Syllabizer s = (Syllabizer) o; | |||
if (! s.script.equals(script)) { | |||
return false; | |||
} else if (! s.language.equals(language)) { | |||
if (!s.script.equals(script)) { | |||
return false; | |||
} else { | |||
return true; | |||
return s.language.equals(language); | |||
} | |||
} else { | |||
return false; | |||
@@ -408,7 +399,7 @@ public class IndicScriptProcessor extends DefaultScriptProcessor { | |||
} | |||
return d; | |||
} | |||
private static Map<String,Syllabizer> syllabizers = new HashMap<String,Syllabizer>(); | |||
private static Map<String, Syllabizer> syllabizers = new HashMap<String, Syllabizer>(); | |||
static Syllabizer getSyllabizer(String script, String language, Class<? extends Syllabizer> syllabizerClass) { | |||
String sid = makeSyllabizerId(script, language); | |||
Syllabizer s = syllabizers.get(sid); |
@@ -31,11 +31,7 @@ import org.apache.fop.complexscripts.util.CharScript; | |||
import org.apache.fop.complexscripts.util.GlyphSequence; | |||
import org.apache.fop.complexscripts.util.ScriptContextTester; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: ParameterNumberCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
/** | |||
* <p>Abstract script processor base class for which an implementation of the substitution and positioning methods | |||
@@ -278,14 +274,12 @@ public abstract class ScriptProcessor { | |||
public boolean equals(Object o) { | |||
if (o instanceof AssembledLookupsKey) { | |||
AssembledLookupsKey k = (AssembledLookupsKey) o; | |||
if (! table.equals(k.table)) { | |||
if (!table.equals(k.table)) { | |||
return false; | |||
} else if (! Arrays.equals(features, k.features)) { | |||
return false; | |||
} else if (! lookups.equals(k.lookups)) { | |||
} else if (!Arrays.equals(features, k.features)) { | |||
return false; | |||
} else { | |||
return true; | |||
return lookups.equals(k.lookups); | |||
} | |||
} else { | |||
return false; |
@@ -28,12 +28,6 @@ import java.util.Set; | |||
import org.apache.fop.util.CharUtilities; | |||
// CSOFF: AvoidNestedBlocksCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: SimplifyBooleanReturnCheck | |||
// CSOFF: WhitespaceAfterCheck | |||
/** | |||
* <p>Script related utilities.</p> | |||
* | |||
@@ -41,6 +35,8 @@ import org.apache.fop.util.CharUtilities; | |||
*/ | |||
public final class CharScript { | |||
// CSOFF: LineLength | |||
// | |||
// The following script codes are based on ISO 15924. Codes less than 1000 are | |||
// official assignments from 15924; those equal to or greater than 1000 are FOP | |||
@@ -754,16 +750,14 @@ public final class CharScript { | |||
case SCRIPT_UNCODED: | |||
break; | |||
default: | |||
{ | |||
Integer v = (Integer) e.getValue(); | |||
assert v != null; | |||
int c = v.intValue(); | |||
if (c > cMax) { | |||
cMax = c; | |||
sMax = s; | |||
} | |||
break; | |||
Integer v = (Integer) e.getValue(); | |||
assert v != null; | |||
int c = v.intValue(); | |||
if (c > cMax) { | |||
cMax = c; | |||
sMax = s; | |||
} | |||
break; | |||
} | |||
} | |||
if (sMax < 0) { | |||
@@ -823,7 +817,7 @@ public final class CharScript { | |||
* @return a script tag | |||
*/ | |||
public static String scriptTagFromCode(int code) { | |||
Map<Integer,String> m = getScriptTagsMap(); | |||
Map<Integer, String> m = getScriptTagsMap(); | |||
if (m != null) { | |||
String tag; | |||
if ((tag = m.get(Integer.valueOf(code))) != null) { | |||
@@ -842,7 +836,7 @@ public final class CharScript { | |||
* @return a script code | |||
*/ | |||
public static int scriptCodeFromTag(String tag) { | |||
Map<String,Integer> m = getScriptCodeMap(); | |||
Map<String, Integer> m = getScriptCodeMap(); | |||
if (m != null) { | |||
Integer c; | |||
if ((c = m.get(tag)) != null) { | |||
@@ -855,8 +849,8 @@ public final class CharScript { | |||
} | |||
} | |||
private static Map<Integer,String> scriptTagsMap = null; | |||
private static Map<String,Integer> scriptCodeMap = null; | |||
private static Map<Integer, String> scriptTagsMap = null; | |||
private static Map<String, Integer> scriptCodeMap = null; | |||
private static void putScriptTag(Map tm, Map cm, int code, String tag) { | |||
assert tag != null; | |||
@@ -868,8 +862,8 @@ public final class CharScript { | |||
} | |||
private static void makeScriptMaps() { | |||
HashMap<Integer,String> tm = new HashMap<Integer,String>(); | |||
HashMap<String,Integer> cm = new HashMap<String,Integer>(); | |||
HashMap<Integer, String> tm = new HashMap<Integer, String>(); | |||
HashMap<String, Integer> cm = new HashMap<String, Integer>(); | |||
putScriptTag(tm, cm, SCRIPT_HEBREW, "hebr"); | |||
putScriptTag(tm, cm, SCRIPT_MONGOLIAN, "mong"); | |||
putScriptTag(tm, cm, SCRIPT_ARABIC, "arab"); | |||
@@ -915,14 +909,14 @@ public final class CharScript { | |||
scriptCodeMap = cm; | |||
} | |||
private static Map<Integer,String> getScriptTagsMap() { | |||
private static Map<Integer, String> getScriptTagsMap() { | |||
if (scriptTagsMap == null) { | |||
makeScriptMaps(); | |||
} | |||
return scriptTagsMap; | |||
} | |||
private static Map<String,Integer> getScriptCodeMap() { | |||
private static Map<String, Integer> getScriptCodeMap() { | |||
if (scriptCodeMap == null) { | |||
makeScriptMaps(); | |||
} |
@@ -26,10 +26,7 @@ import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: WhitespaceAfterCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
/** | |||
* <p>A GlyphSequence encapsulates a sequence of character codes, a sequence of glyph codes, | |||
@@ -639,10 +636,10 @@ public class GlyphSequence implements Cloneable { | |||
private final int offset; | |||
private final int count; | |||
private final int[] subIntervals; | |||
private Map<String,Object> predications; | |||
private Map<String, Object> predications; | |||
// class state | |||
private static volatile Map<String,PredicationMerger> predicationMergers; | |||
private static volatile Map<String, PredicationMerger> predicationMergers; | |||
interface PredicationMerger { | |||
Object merge(String key, Object v1, Object v2); | |||
@@ -724,7 +721,7 @@ public class GlyphSequence implements Cloneable { | |||
public boolean contained(int offset, int count) { | |||
int s = offset; | |||
int e = offset + count; | |||
if (! isDisjoint()) { | |||
if (!isDisjoint()) { | |||
int s0 = getStart(); | |||
int e0 = getEnd(); | |||
return (s0 >= s) && (e0 <= e); | |||
@@ -748,7 +745,7 @@ public class GlyphSequence implements Cloneable { | |||
*/ | |||
public void setPredication(String key, Object value) { | |||
if (predications == null) { | |||
predications = new HashMap<String,Object>(); | |||
predications = new HashMap<String, Object>(); | |||
} | |||
if (predications != null) { | |||
predications.put(key, value); | |||
@@ -775,7 +772,7 @@ public class GlyphSequence implements Cloneable { | |||
*/ | |||
public void mergePredication(String key, Object value) { | |||
if (predications == null) { | |||
predications = new HashMap<String,Object>(); | |||
predications = new HashMap<String, Object>(); | |||
} | |||
if (predications != null) { | |||
if (predications.containsKey(key)) { | |||
@@ -813,7 +810,7 @@ public class GlyphSequence implements Cloneable { | |||
*/ | |||
public void mergePredications(CharAssociation ca) { | |||
if (ca.predications != null) { | |||
for (Map.Entry<String,Object> e : ca.predications.entrySet()) { | |||
for (Map.Entry<String, Object> e : ca.predications.entrySet()) { | |||
mergePredication(e.getKey(), e.getValue()); | |||
} | |||
} | |||
@@ -824,7 +821,7 @@ public class GlyphSequence implements Cloneable { | |||
try { | |||
CharAssociation ca = (CharAssociation) super.clone(); | |||
if (predications != null) { | |||
ca.predications = new HashMap<String,Object>(predications); | |||
ca.predications = new HashMap<String, Object>(predications); | |||
} | |||
return ca; | |||
} catch (CloneNotSupportedException e) { | |||
@@ -839,7 +836,7 @@ public class GlyphSequence implements Cloneable { | |||
*/ | |||
public static void setPredicationMerger(String key, PredicationMerger pm) { | |||
if (predicationMergers == null) { | |||
predicationMergers = new HashMap<String,PredicationMerger>(); | |||
predicationMergers = new HashMap<String, PredicationMerger>(); | |||
} | |||
if (predicationMergers != null) { | |||
predicationMergers.put(key, pm); |
@@ -23,9 +23,6 @@ import java.util.ArrayList; | |||
import java.util.List; | |||
// CSOFF: LineLengthCheck | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: NoWhitespaceAfterCheck | |||
// CSOFF: AvoidNestedBlocksCheck | |||
/** | |||
* <p>Implementation of Number to String Conversion algorithm specified by | |||
@@ -186,10 +183,10 @@ public class NumberConverter { | |||
separators.add(token.toArray(new Integer [ token.size() ])); | |||
} | |||
} | |||
if (! separators.isEmpty()) { | |||
if (!separators.isEmpty()) { | |||
this.prefix = separators.remove(0); | |||
} | |||
if (! separators.isEmpty()) { | |||
if (!separators.isEmpty()) { | |||
this.suffix = separators.remove(separators.size() - 1); | |||
} | |||
this.separators = separators.toArray(new Integer [ separators.size() ] []); | |||
@@ -260,33 +257,27 @@ public class NumberConverter { | |||
int s = token[0].intValue(); | |||
switch (s) { | |||
case (int) '1': | |||
{ | |||
fn = formatNumberAsDecimal(number, (int) '1', 1); | |||
break; | |||
} | |||
fn = formatNumberAsDecimal(number, (int) '1', 1); | |||
break; | |||
case (int) 'W': | |||
case (int) 'w': | |||
{ | |||
fn = formatNumberAsWord(number, (s == (int) 'W') ? Character.UPPERCASE_LETTER : Character.LOWERCASE_LETTER); | |||
break; | |||
} | |||
fn = formatNumberAsWord(number, (s == (int) 'W') ? Character.UPPERCASE_LETTER : Character.LOWERCASE_LETTER); | |||
break; | |||
case (int) 'A': // handled as numeric sequence | |||
case (int) 'a': // handled as numeric sequence | |||
case (int) 'I': // handled as numeric special | |||
case (int) 'i': // handled as numeric special | |||
default: | |||
{ | |||
if (isStartOfDecimalSequence(s)) { | |||
fn = formatNumberAsDecimal(number, s, 1); | |||
} else if (isStartOfAlphabeticSequence(s)) { | |||
fn = formatNumberAsSequence(number, s, getSequenceBase(s), null); | |||
} else if (isStartOfNumericSpecial(s)) { | |||
fn = formatNumberAsSpecial(number, s); | |||
} else { | |||
fn = null; | |||
} | |||
break; | |||
if (isStartOfDecimalSequence(s)) { | |||
fn = formatNumberAsDecimal(number, s, 1); | |||
} else if (isStartOfAlphabeticSequence(s)) { | |||
fn = formatNumberAsSequence(number, s, getSequenceBase(s), null); | |||
} else if (isStartOfNumericSpecial(s)) { | |||
fn = formatNumberAsSpecial(number, s); | |||
} else { | |||
fn = null; | |||
} | |||
break; | |||
} | |||
} else if ((token.length == 2) && (token[0] == (int) 'W') && (token[1] == (int) 'w')) { | |||
fn = formatNumberAsWord(number, Character.TITLECASE_LETTER); |
@@ -21,7 +21,6 @@ package org.apache.fop.complexscripts.util; | |||
import org.apache.fop.util.CharUtilities; | |||
// CSOFF: InnerAssignmentCheck | |||
/** | |||
* <p>UTF32 related utilities.</p> |
@@ -816,8 +816,11 @@ public interface Constants { | |||
/** Scope for table header */ | |||
int PR_X_HEADER_COLUMN = 290; | |||
/** For specifying PDF optional content group (layer) binding. */ | |||
int PR_X_LAYER = 291; | |||
/** Number of property constants defined */ | |||
int PROPERTY_COUNT = 290; | |||
int PROPERTY_COUNT = 291; | |||
// compound property constants | |||
@@ -2721,6 +2721,13 @@ public final class FOPropertyMapping implements Constants { | |||
m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); | |||
m.setDefault("auto"); | |||
addPropertyMaker("z-index", m); | |||
// fox:layer | |||
m = new StringProperty.Maker(PR_X_LAYER); | |||
m.setInherited(false); | |||
m.setDefault(""); | |||
addPropertyMaker("fox:layer", m); | |||
} | |||
private void createShorthandProperties() { |
@@ -74,7 +74,8 @@ public abstract class FObj extends FONode implements Constants { | |||
private int bidiLevel = -1; | |||
// The value of properties relevant for all fo objects | |||
private String id = null; | |||
private String id; | |||
private String layer; | |||
// End of property values | |||
/** | |||
@@ -148,7 +149,7 @@ public abstract class FObj extends FONode implements Constants { | |||
String attributeName = attList.getQName(i); | |||
String attributeValue = attList.getValue(i); | |||
Property prop = propertyList.getPropertyForAttribute(attList, attributeName, attributeValue); | |||
if (prop.equals(value)) { | |||
if (prop != null && prop.equals(value)) { | |||
return attributeName; | |||
} | |||
} | |||
@@ -173,6 +174,7 @@ public abstract class FObj extends FONode implements Constants { | |||
*/ | |||
public void bind(PropertyList pList) throws FOPException { | |||
id = pList.get(PR_ID).getString(); | |||
layer = pList.get(PR_X_LAYER).getString(); | |||
} | |||
/** | |||
@@ -583,6 +585,16 @@ public abstract class FObj extends FONode implements Constants { | |||
return (id != null && id.length() > 0); | |||
} | |||
/** @return the "layer" property. */ | |||
public String getLayer() { | |||
return layer; | |||
} | |||
/** @return whether this object has an layer set */ | |||
public boolean hasLayer() { | |||
return (layer != null && layer.length() > 0); | |||
} | |||
/** {@inheritDoc} */ | |||
public String getNamespaceURI() { | |||
return FOElementMapping.URI; | |||
@@ -611,7 +623,7 @@ public abstract class FObj extends FONode implements Constants { | |||
if (bidiLevel >= 0) { | |||
if ((this.bidiLevel < 0) || (bidiLevel < this.bidiLevel)) { | |||
this.bidiLevel = bidiLevel; | |||
if (parent != null) { | |||
if ((parent != null) && !isBidiPropagationBoundary()) { | |||
FObj foParent = (FObj) parent; | |||
int parentBidiLevel = foParent.getBidiLevel(); | |||
if ((parentBidiLevel < 0) || (bidiLevel < parentBidiLevel)) { | |||
@@ -646,10 +658,25 @@ public abstract class FObj extends FONode implements Constants { | |||
return level; | |||
} | |||
} | |||
if (isBidiInheritanceBoundary()) { | |||
break; | |||
} | |||
} | |||
return -1; | |||
} | |||
protected boolean isBidiBoundary(boolean propagate) { | |||
return false; | |||
} | |||
private boolean isBidiInheritanceBoundary() { | |||
return isBidiBoundary(false); | |||
} | |||
private boolean isBidiPropagationBoundary() { | |||
return isBidiBoundary(true); | |||
} | |||
/** | |||
* Add a new extension attachment to this FObj. | |||
* (see org.apache.fop.fo.FONode for details) |
@@ -36,7 +36,8 @@ public abstract class FunctionBase implements Function { | |||
/** {@inheritDoc} */ | |||
public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { | |||
if (index >= getOptionalArgsCount()) { | |||
PropertyException e = new PropertyException(new IndexOutOfBoundsException("illegal optional argument index")); | |||
PropertyException e = new PropertyException( | |||
new IndexOutOfBoundsException("illegal optional argument index")); | |||
e.setPropertyInfo(pi); | |||
throw e; | |||
} else { |
@@ -385,7 +385,8 @@ public final class PropertyParser extends PropertyTokenizer { | |||
} | |||
int numArgs = args.size(); | |||
if (numArgs < numReq) { | |||
throw new PropertyException("Expected " + numReq + " required arguments, but only " + numArgs + " specified"); | |||
throw new PropertyException("Expected " + numReq + " required arguments, but only " | |||
+ numArgs + " specified"); | |||
} else { | |||
for (int i = 0; i < numOpt; i++) { | |||
if (args.size() < (numReq + i + 1)) { |
@@ -66,6 +66,8 @@ public class ExtensionElementMapping extends ElementMapping { | |||
PROPERTY_ATTRIBUTES.add("border-before-end-radius"); | |||
PROPERTY_ATTRIBUTES.add("border-after-start-radius"); | |||
PROPERTY_ATTRIBUTES.add("border-after-end-radius"); | |||
//Optional content groups (layers) | |||
PROPERTY_ATTRIBUTES.add("layer"); | |||
} | |||
/** |
@@ -98,7 +98,8 @@ public class BlockContainer extends FObj implements BreakPropertySet, WritingMod | |||
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); | |||
span = pList.get(PR_SPAN).getEnum(); | |||
writingModeTraits = new WritingModeTraits( | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum())); | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()), | |||
pList.getExplicit(PR_WRITING_MODE) != null); | |||
disableColumnBalancing = pList.get(PR_X_DISABLE_COLUMN_BALANCING).getEnum(); | |||
} | |||
@@ -280,6 +281,14 @@ public class BlockContainer extends FObj implements BreakPropertySet, WritingMod | |||
return writingModeTraits.getWritingMode(); | |||
} | |||
/** | |||
* Obtain writing mode explicit indicator. | |||
* @return the writing mode explicit indicator | |||
*/ | |||
public boolean getExplicitWritingMode() { | |||
return writingModeTraits.getExplicitWritingMode(); | |||
} | |||
/** {@inheritDoc} */ | |||
public String getLocalName() { | |||
return "block-container"; | |||
@@ -292,5 +301,10 @@ public class BlockContainer extends FObj implements BreakPropertySet, WritingMod | |||
public int getNameId() { | |||
return FO_BLOCK_CONTAINER; | |||
} | |||
} | |||
@Override | |||
protected boolean isBidiBoundary(boolean propagate) { | |||
return getExplicitWritingMode(); | |||
} | |||
} |
@@ -37,49 +37,38 @@ import org.apache.fop.traits.Direction; | |||
import org.apache.fop.traits.WritingMode; | |||
import org.apache.fop.traits.WritingModeTraits; | |||
/** | |||
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_inline-container"> | |||
* <code>fo:inline-container</code></a> object. | |||
*/ | |||
public class InlineContainer extends FObj { | |||
// The value of FO traits (refined properties) that apply to fo:inline-container. | |||
private Length alignmentAdjust; | |||
private int alignmentBaseline; | |||
private Length baselineShift; | |||
private LengthRangeProperty inlineProgressionDimension; | |||
private LengthRangeProperty blockProgressionDimension; | |||
private int overflow; | |||
private CommonBorderPaddingBackground commonBorderPaddingBackground; | |||
private CommonMarginInline commonMarginInline; | |||
private int clip; | |||
private int dominantBaseline; | |||
private LengthRangeProperty inlineProgressionDimension; | |||
private Numeric referenceOrientation; | |||
private int displayAlign; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
private KeepProperty keepWithPrevious; | |||
private SpaceProperty lineHeight; | |||
private int overflow; | |||
private Numeric referenceOrientation; | |||
private Length alignmentAdjust; | |||
private int alignmentBaseline; | |||
private Length baselineShift; | |||
private int dominantBaseline; | |||
private WritingModeTraits writingModeTraits; | |||
// Unused but valid items, commented out for performance: | |||
// private CommonRelativePosition commonRelativePosition; | |||
// private int displayAlign; | |||
// private Length height; | |||
// private KeepProperty keepWithNext; | |||
// private KeepProperty keepWithPrevious; | |||
// private Length width; | |||
// End of FO trait values | |||
/** used for FO validation */ | |||
private boolean blockItemFound = false; | |||
private boolean blockItemFound; | |||
/** | |||
* Base constructor | |||
* Creates a new instance. | |||
* | |||
* @param parent {@link FONode} that is the parent of this object | |||
* @param parent the parent of this inline-container | |||
*/ | |||
public InlineContainer(FONode parent) { | |||
super(parent); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void bind(PropertyList pList) throws FOPException { | |||
super.bind(pList); | |||
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); | |||
@@ -88,27 +77,31 @@ public class InlineContainer extends FObj { | |||
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); | |||
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); | |||
commonMarginInline = pList.getMarginInlineProps(); | |||
clip = pList.get(PR_CLIP).getEnum(); | |||
displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum(); | |||
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum(); | |||
inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); | |||
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); | |||
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); | |||
keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); | |||
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); | |||
overflow = pList.get(PR_OVERFLOW).getEnum(); | |||
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); | |||
writingModeTraits = new WritingModeTraits( | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum())); | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()), | |||
pList.getExplicit(PR_WRITING_MODE) != null); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* <br>XSL Content Model: marker* (%block;)+ | |||
*/ | |||
@Override | |||
protected void validateChildNode(Locator loc, String nsURI, String localName) | |||
throws ValidationException { | |||
if (FO_URI.equals(nsURI)) { | |||
if (localName.equals("marker")) { | |||
if (blockItemFound) { | |||
nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); | |||
nodesOutOfOrderError(loc, "fo:marker", "(%block;)+"); | |||
} | |||
} else if (!isBlockItem(nsURI, localName)) { | |||
invalidChildError(loc, nsURI, localName); | |||
@@ -118,142 +111,131 @@ public class InlineContainer extends FObj { | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void endOfNode() throws FOPException { | |||
if (!blockItemFound) { | |||
missingChildElementError("marker* (%block;)+"); | |||
} | |||
} | |||
/** @return the "alignment-adjust" FO trait */ | |||
public Length getAlignmentAdjust() { | |||
return alignmentAdjust; | |||
/** {@inheritDoc} */ | |||
public String getLocalName() { | |||
return "inline-container"; | |||
} | |||
/** @return the "alignment-baseline" FO trait */ | |||
public int getAlignmentBaseline() { | |||
return alignmentBaseline; | |||
/** | |||
* {@inheritDoc} | |||
* @return {@link org.apache.fop.fo.Constants#FO_INLINE_CONTAINER} | |||
*/ | |||
public int getNameId() { | |||
return FO_INLINE_CONTAINER; | |||
} | |||
/** @return the "baseline-shift" FO trait */ | |||
public Length getBaselineShift() { | |||
return baselineShift; | |||
public LengthRangeProperty getInlineProgressionDimension() { | |||
return inlineProgressionDimension; | |||
} | |||
/** @return the "block-progression-dimension" FO trait */ | |||
public LengthRangeProperty getBlockProgressionDimension() { | |||
return blockProgressionDimension; | |||
} | |||
/** @return the "clip" FO trait */ | |||
public int getClip() { | |||
return clip; | |||
public int getOverflow() { | |||
return overflow; | |||
} | |||
/**@return Returns the {@link CommonBorderPaddingBackground} */ | |||
public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { | |||
return this.commonBorderPaddingBackground; | |||
} | |||
/** @return Returns the {@link CommonMarginInline} */ | |||
public CommonMarginInline getCommonMarginInline() { | |||
return this.commonMarginInline; | |||
} | |||
/** @return the "dominant-baseline" FO trait */ | |||
public int getDominantBaseline() { | |||
return dominantBaseline; | |||
public int getReferenceOrientation() { | |||
return referenceOrientation.getValue(); | |||
} | |||
public int getDisplayAlign() { | |||
return this.displayAlign; | |||
} | |||
public KeepProperty getKeepWithPrevious() { | |||
return keepWithPrevious; | |||
} | |||
/** @return the "keep-together" FO trait */ | |||
public KeepProperty getKeepTogether() { | |||
return keepTogether; | |||
} | |||
/** @return the "inline-progression-dimension" FO trait */ | |||
public LengthRangeProperty getInlineProgressionDimension() { | |||
return inlineProgressionDimension; | |||
public KeepProperty getKeepWithNext() { | |||
return keepWithNext; | |||
} | |||
/** @return the "line-height" FO trait */ | |||
public SpaceProperty getLineHeight() { | |||
return lineHeight; | |||
} | |||
/** @return the "overflow" FO trait */ | |||
public int getOverflow() { | |||
return overflow; | |||
public Length getAlignmentAdjust() { | |||
return alignmentAdjust; | |||
} | |||
/** @return the "reference-orientation" FO trait */ | |||
public int getReferenceOrientation() { | |||
return referenceOrientation.getValue(); | |||
public int getAlignmentBaseline() { | |||
return alignmentBaseline; | |||
} | |||
public Length getBaselineShift() { | |||
return baselineShift; | |||
} | |||
public int getDominantBaseline() { | |||
return dominantBaseline; | |||
} | |||
public WritingMode getWritingMode() { | |||
return writingModeTraits.getWritingMode(); | |||
} | |||
/** | |||
* Obtain inline progression direction. | |||
* @return the inline progression direction | |||
* Obtain writing mode explicit indicator. | |||
* @return the writing mode explicit indicator | |||
*/ | |||
public boolean getExplicitWritingMode() { | |||
return writingModeTraits.getExplicitWritingMode(); | |||
} | |||
public Direction getInlineProgressionDirection() { | |||
return writingModeTraits.getInlineProgressionDirection(); | |||
} | |||
/** | |||
* Obtain block progression direction. | |||
* @return the block progression direction | |||
*/ | |||
public Direction getBlockProgressionDirection() { | |||
return writingModeTraits.getBlockProgressionDirection(); | |||
} | |||
/** | |||
* Obtain column progression direction. | |||
* @return the column progression direction | |||
*/ | |||
public Direction getColumnProgressionDirection() { | |||
return writingModeTraits.getColumnProgressionDirection(); | |||
} | |||
/** | |||
* Obtain row progression direction. | |||
* @return the row progression direction | |||
*/ | |||
public Direction getRowProgressionDirection() { | |||
return writingModeTraits.getRowProgressionDirection(); | |||
} | |||
/** | |||
* Obtain (baseline) shift direction. | |||
* @return the (baseline) shift direction | |||
*/ | |||
public Direction getShiftDirection() { | |||
return writingModeTraits.getShiftDirection(); | |||
} | |||
/** | |||
* Obtain writing mode. | |||
* @return the writing mode | |||
*/ | |||
public WritingMode getWritingMode() { | |||
return writingModeTraits.getWritingMode(); | |||
} | |||
/** {@inheritDoc} */ | |||
public String getLocalName() { | |||
return "inline-container"; | |||
@Override | |||
public boolean isDelimitedTextRangeBoundary(int boundary) { | |||
return false; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* @return {@link org.apache.fop.fo.Constants#FO_INLINE_CONTAINER} | |||
*/ | |||
public int getNameId() { | |||
return FO_INLINE_CONTAINER; | |||
@Override | |||
public boolean generatesReferenceAreas() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isDelimitedTextRangeBoundary(int boundary) { | |||
return false; | |||
protected boolean isBidiBoundary(boolean propagate) { | |||
return getExplicitWritingMode(); | |||
} | |||
} |
@@ -139,7 +139,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break | |||
tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum(); | |||
tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); | |||
writingModeTraits = new WritingModeTraits( | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum())); | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()), | |||
pList.getExplicit(PR_WRITING_MODE) != null); | |||
//Bind extension properties | |||
widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength(); | |||
@@ -554,6 +555,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break | |||
return writingModeTraits.getWritingMode(); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean getExplicitWritingMode() { | |||
return writingModeTraits.getExplicitWritingMode(); | |||
} | |||
/** @return the "fox:widow-content-limit" extension FO trait */ | |||
public Length getWidowContentLimit() { | |||
return widowContentLimit; | |||
@@ -620,4 +626,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break | |||
return ranges; | |||
} | |||
@Override | |||
protected boolean isBidiBoundary(boolean propagate) { | |||
return getExplicitWritingMode(); | |||
} | |||
} |
@@ -96,7 +96,8 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra | |||
masterReference = pList.get(PR_MASTER_REFERENCE).getString(); | |||
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); | |||
writingModeTraits = new WritingModeTraits( | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum())); | |||
WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()), | |||
pList.getExplicit(PR_WRITING_MODE) != null); | |||
if (masterReference == null || masterReference.equals("")) { | |||
missingPropertyError("master-reference"); | |||
} | |||
@@ -403,6 +404,16 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra | |||
} | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean getExplicitWritingMode() { | |||
if (writingModeTraits != null) { | |||
return writingModeTraits.getExplicitWritingMode(); | |||
} else { | |||
return false; | |||
} | |||
} | |||
@Override | |||
protected Stack collectDelimitedTextRanges(Stack ranges, DelimitedTextRange currentRange) { | |||
@@ -423,6 +434,11 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra | |||
return ranges; | |||
} | |||
@Override | |||
protected boolean isBidiBoundary(boolean propagate) { | |||
return true; | |||
} | |||
/** | |||
* Releases a page-sequence's children after the page-sequence has been fully processed. | |||
*/ |
@@ -83,13 +83,17 @@ public class GenericShorthandParser implements ShorthandParser { | |||
PropertyList propertyList) | |||
throws PropertyException { | |||
Property prop = null; | |||
String vProperty = ""; | |||
// Try each of the stored values in turn | |||
Iterator iprop = property.getList().iterator(); | |||
while (iprop.hasNext() && prop == null) { | |||
Property p = (Property)iprop.next(); | |||
if (p.getNCname() != null) { | |||
vProperty += p.getNCname() + " "; | |||
} | |||
prop = maker.convertShorthandProperty(propertyList, p, null); | |||
propertyList.validatePropertyValue(p.getNCname(), prop, property); | |||
} | |||
propertyList.validatePropertyValue(vProperty.trim(), prop, property); | |||
return prop; | |||
} | |||
@@ -26,7 +26,7 @@ import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.apps.io.InternalResourceResolver; | |||
import org.apache.fop.fonts.truetype.TTFFontLoader; | |||
import org.apache.fop.fonts.truetype.OFFontLoader; | |||
import org.apache.fop.fonts.type1.Type1FontLoader; | |||
/** | |||
@@ -105,7 +105,7 @@ public abstract class FontLoader { | |||
} | |||
loader = new Type1FontLoader(fontFileURI, embedded, useKerning, resourceResolver); | |||
} else { | |||
loader = new TTFFontLoader(fontFileURI, subFontName, embedded, embeddingMode, | |||
loader = new OFFontLoader(fontFileURI, subFontName, embedded, embeddingMode, | |||
encodingMode, useKerning, useAdvanced, resourceResolver); | |||
} | |||
return loader.getFont(); |
@@ -48,20 +48,24 @@ public class FontManagerConfigurator { | |||
private final Configuration cfg; | |||
private final URI defaultBaseUri; | |||
private final URI baseURI; | |||
private final URI fallbackURI; | |||
private final ResourceResolver resourceResolver; | |||
/** | |||
* Main constructor | |||
* @param cfg the font manager configuration object | |||
* @param defaultBaseUri the default URI base to use for URI resolution | |||
* @param baseURI the URI against which to resolve relative URIs | |||
* @param fallbackURI the URI to use as a fallback if font-base is unspecified | |||
* @param resourceResolver the resource resolver | |||
*/ | |||
public FontManagerConfigurator(Configuration cfg, URI defaultBaseUri, | |||
public FontManagerConfigurator(Configuration cfg, URI baseURI, URI fallbackURI, | |||
ResourceResolver resourceResolver) { | |||
this.cfg = cfg; | |||
this.defaultBaseUri = defaultBaseUri; | |||
this.baseURI = baseURI; | |||
this.fallbackURI = fallbackURI; | |||
this.resourceResolver = resourceResolver; | |||
} | |||
@@ -77,13 +81,13 @@ public class FontManagerConfigurator { | |||
URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("font-base") | |||
.getValue(null)); | |||
fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver( | |||
defaultBaseUri.resolve(fontBase), resourceResolver)); | |||
baseURI.resolve(fontBase), resourceResolver)); | |||
} catch (URISyntaxException use) { | |||
LogUtil.handleException(log, use, true); | |||
} | |||
} else { | |||
fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver( | |||
defaultBaseUri, resourceResolver)); | |||
fallbackURI, resourceResolver)); | |||
} | |||
// caching (fonts) | |||
if (cfg.getChild("use-cache", false) != null) { |
@@ -27,7 +27,8 @@ import java.io.Serializable; | |||
*/ | |||
public class FontTriplet implements Comparable<FontTriplet>, Serializable { | |||
public static final FontTriplet DEFAULT_FONT_TRIPLET = new FontTriplet("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); | |||
public static final FontTriplet DEFAULT_FONT_TRIPLET | |||
= new FontTriplet("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); | |||
/** serial version UID */ | |||
private static final long serialVersionUID = 1168991106658033508L; |
@@ -23,6 +23,7 @@ import java.awt.Rectangle; | |||
import java.nio.CharBuffer; | |||
import java.nio.IntBuffer; | |||
import java.util.BitSet; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import org.apache.commons.logging.Log; | |||
@@ -71,6 +72,15 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
/** Contains the character bounding boxes for all characters in the font */ | |||
protected Rectangle[] boundingBoxes; | |||
private boolean isOTFFile = false; | |||
// since for most users the most likely glyphs are in the first cmap segments we store their mapping. | |||
private static final int NUM_MOST_LIKELY_GLYPHS = 256; | |||
private int[] mostLikelyGlyphs = new int[NUM_MOST_LIKELY_GLYPHS]; | |||
//A map to store each used glyph from the CID set against the glyph name. | |||
private LinkedHashMap<Integer, String> usedGlyphNames = new LinkedHashMap<Integer, String>(); | |||
/** | |||
* Default constructor | |||
*/ | |||
@@ -115,6 +125,14 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
return cidType; | |||
} | |||
public void setIsOTFFile(boolean isOTFFile) { | |||
this.isOTFFile = isOTFFile; | |||
} | |||
public boolean isOTFFile() { | |||
return this.isOTFFile; | |||
} | |||
/** | |||
* Sets the CIDType. | |||
* @param cidType The cidType to set | |||
@@ -151,6 +169,14 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
return this.cidSet; | |||
} | |||
public void mapUsedGlyphName(int gid, String value) { | |||
usedGlyphNames.put(gid, value); | |||
} | |||
public LinkedHashMap<Integer, String> getUsedGlyphNames() { | |||
return usedGlyphNames; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public String getEncodingName() { | |||
@@ -187,10 +213,15 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
* @return the glyph index (or 0 if the glyph is not available) | |||
*/ | |||
// [TBD] - needs optimization, i.e., change from linear search to binary search | |||
private int findGlyphIndex(int c) { | |||
public int findGlyphIndex(int c) { | |||
int idx = c; | |||
int retIdx = SingleByteEncoding.NOT_FOUND_CODE_POINT; | |||
// for most users the most likely glyphs are in the first cmap segments (meaning the one with | |||
// the lowest unicode start values) | |||
if (idx < NUM_MOST_LIKELY_GLYPHS && mostLikelyGlyphs[idx] != 0) { | |||
return mostLikelyGlyphs[idx]; | |||
} | |||
for (int i = 0; (i < cmap.length) && retIdx == 0; i++) { | |||
if (cmap[i].getUnicodeStart() <= idx | |||
&& cmap[i].getUnicodeEnd() >= idx) { | |||
@@ -198,6 +229,9 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
retIdx = cmap[i].getGlyphStartIndex() | |||
+ idx | |||
- cmap[i].getUnicodeStart(); | |||
if (idx < NUM_MOST_LIKELY_GLYPHS) { | |||
mostLikelyGlyphs[idx] = retIdx; | |||
} | |||
} | |||
} | |||
return retIdx; | |||
@@ -291,22 +325,6 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
return findCharacterFromGlyphIndex(gi, true); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public char mapChar(char c) { | |||
notifyMapOperation(); | |||
int glyphIndex = findGlyphIndex(c); | |||
if (glyphIndex == SingleByteEncoding.NOT_FOUND_CODE_POINT) { | |||
warnMissingGlyph(c); | |||
glyphIndex = findGlyphIndex(Typeface.NOT_FOUND); | |||
} | |||
if (isEmbeddable()) { | |||
glyphIndex = cidSet.mapChar(glyphIndex, c); | |||
} | |||
return (char) glyphIndex; | |||
} | |||
protected BitSet getGlyphIndices() { | |||
BitSet bitset = new BitSet(); | |||
bitset.set(0); | |||
@@ -337,6 +355,23 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl | |||
return chars; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public char mapChar(char c) { | |||
notifyMapOperation(); | |||
int glyphIndex = findGlyphIndex(c); | |||
if (glyphIndex == SingleByteEncoding.NOT_FOUND_CODE_POINT) { | |||
warnMissingGlyph(c); | |||
if (!isOTFFile) { | |||
glyphIndex = findGlyphIndex(Typeface.NOT_FOUND); | |||
} | |||
} | |||
if (isEmbeddable()) { | |||
glyphIndex = cidSet.mapChar(glyphIndex, c); | |||
} | |||
return (char) glyphIndex; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public boolean hasChar(char c) { |
@@ -33,7 +33,7 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.xmlgraphics.fonts.Glyphs; | |||
import org.apache.fop.apps.io.InternalResourceResolver; | |||
import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; | |||
import org.apache.fop.fonts.truetype.OpenFont.PostScriptVersion; | |||
/** | |||
* Generic SingleByte font |
@@ -32,8 +32,6 @@ import javax.xml.transform.TransformerFactory; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.util.CommandLineLogger; | |||
/** | |||
* Abstract base class for the PFM and TTF Reader command-line applications. | |||
*/ | |||
@@ -90,10 +88,6 @@ public abstract class AbstractFontReader { | |||
protected static void setLogLevel(String level) { | |||
// Set the evel for future loggers. | |||
LogFactory.getFactory().setAttribute("level", level); | |||
if (log instanceof CommandLineLogger) { | |||
// Set the level for the logger creates already. | |||
((CommandLineLogger) log).setLogLevel(level); | |||
} | |||
} | |||
/** |
@@ -29,11 +29,8 @@ import javax.xml.parsers.DocumentBuilderFactory; | |||
import org.w3c.dom.Document; | |||
import org.w3c.dom.Element; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.Version; | |||
import org.apache.fop.fonts.type1.PFMFile; | |||
import org.apache.fop.util.CommandLineLogger; | |||
/** | |||
* A tool which reads PFM files from Adobe Type 1 fonts and creates | |||
@@ -92,14 +89,6 @@ public class PFMReader extends AbstractFontReader { | |||
Map options = new java.util.HashMap(); | |||
String[] arguments = parseArguments(options, args); | |||
// Enable the simple command line logging when no other logger is | |||
// defined. | |||
LogFactory logFactory = LogFactory.getFactory(); | |||
if (System.getProperty("org.apache.commons.logging.Log") == null) { | |||
logFactory.setAttribute("org.apache.commons.logging.Log", | |||
CommandLineLogger.class.getName()); | |||
} | |||
determineLogLevel(options); | |||
PFMReader app = new PFMReader(); |
@@ -32,16 +32,13 @@ import org.w3c.dom.Element; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.SAXException; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.Version; | |||
import org.apache.fop.fonts.CMapSegment; | |||
import org.apache.fop.fonts.FontUtil; | |||
import org.apache.fop.fonts.truetype.FontFileReader; | |||
import org.apache.fop.fonts.truetype.OFFontLoader; | |||
import org.apache.fop.fonts.truetype.TTFFile; | |||
import org.apache.fop.util.CommandLineLogger; | |||
// CSOFF: InnerAssignmentCheck | |||
// CSOFF: LineLengthCheck | |||
/** | |||
@@ -123,14 +120,6 @@ public class TTFReader extends AbstractFontReader { | |||
Map options = new java.util.HashMap(); | |||
String[] arguments = parseArguments(options, args); | |||
// Enable the simple command line logging when no other logger is | |||
// defined. | |||
LogFactory logFactory = LogFactory.getFactory(); | |||
if (System.getProperty("org.apache.commons.logging.Log") == null) { | |||
logFactory.setAttribute("org.apache.commons.logging.Log", | |||
CommandLineLogger.class.getName()); | |||
} | |||
determineLogLevel(options); | |||
TTFReader app = new TTFReader(); | |||
@@ -224,7 +213,8 @@ public class TTFReader extends AbstractFontReader { | |||
InputStream stream = new FileInputStream(fileName); | |||
try { | |||
FontFileReader reader = new FontFileReader(stream); | |||
boolean supported = ttfFile.readFont(reader, fontName); | |||
String header = OFFontLoader.readHeader(reader); | |||
boolean supported = ttfFile.readFont(reader, header, fontName); | |||
if (!supported) { | |||
return null; | |||
} |
@@ -43,8 +43,8 @@ import org.apache.fop.fonts.FontTriplet; | |||
import org.apache.fop.fonts.FontUtil; | |||
import org.apache.fop.fonts.MultiByteFont; | |||
import org.apache.fop.fonts.truetype.FontFileReader; | |||
import org.apache.fop.fonts.truetype.OFFontLoader; | |||
import org.apache.fop.fonts.truetype.TTFFile; | |||
import org.apache.fop.fonts.truetype.TTFFontLoader; | |||
/** | |||
* Attempts to determine correct FontInfo | |||
@@ -220,7 +220,7 @@ public class FontInfoFinder { | |||
log.debug("Loading " + fontName); | |||
} | |||
try { | |||
TTFFontLoader ttfLoader = new TTFFontLoader(fontURI, fontName, true, | |||
OFFontLoader ttfLoader = new OFFontLoader(fontURI, fontName, true, | |||
EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useAdvanced, | |||
resourceResolver); | |||
customFont = ttfLoader.getFont(); |
@@ -0,0 +1,927 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.fonts.cff; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.fontbox.cff.CFFDataInput; | |||
import org.apache.fontbox.cff.CFFOperator; | |||
import org.apache.fop.fonts.truetype.FontFileReader; | |||
import org.apache.fop.fonts.truetype.OTFFile; | |||
/** | |||
* A class to read the CFF data from an OTF CFF font file. | |||
*/ | |||
public class CFFDataReader { | |||
private CFFDataInput cffData; | |||
private byte[] header; | |||
private CFFIndexData nameIndex; | |||
private CFFIndexData topDICTIndex; | |||
private CFFIndexData stringIndex; | |||
private CFFIndexData charStringIndex; | |||
private CFFIndexData globalIndexSubr; | |||
private CFFIndexData localIndexSubr; | |||
private CustomEncoding encoding; | |||
private FDSelect fdSelect; | |||
private List<FontDict> fdFonts; | |||
private static final int DOUBLE_BYTE_OPERATOR = 12; | |||
private static final int NUM_STANDARD_STRINGS = 391; | |||
/** Commonly used parsed dictionaries */ | |||
private LinkedHashMap<String, DICTEntry> topDict; | |||
public CFFDataReader() { | |||
} | |||
/** | |||
* Constructor for the CFF data reader which accepts the CFF byte data | |||
* as an argument. | |||
* @param cffDataArray A byte array which holds the CFF data | |||
*/ | |||
public CFFDataReader(byte[] cffDataArray) throws IOException { | |||
cffData = new CFFDataInput(cffDataArray); | |||
readCFFData(); | |||
} | |||
/** | |||
* Constructor for the CFF data reader which accepts a FontFileReader object | |||
* which points to the original font file as an argument. | |||
* @param fontFile The font file as represented by a FontFileReader object | |||
*/ | |||
public CFFDataReader(FontFileReader fontFile) throws IOException { | |||
cffData = new CFFDataInput(OTFFile.getCFFData(fontFile)); | |||
readCFFData(); | |||
} | |||
private void readCFFData() throws IOException { | |||
header = readHeader(); | |||
nameIndex = readIndex(); | |||
topDICTIndex = readIndex(); | |||
topDict = parseDictData(topDICTIndex.getData()); | |||
stringIndex = readIndex(); | |||
globalIndexSubr = readIndex(); | |||
charStringIndex = readCharStringIndex(); | |||
encoding = readEncoding(); | |||
fdSelect = readFDSelect(); | |||
localIndexSubr = readLocalIndexSubrs(); | |||
fdFonts = parseCIDData(); | |||
} | |||
public Map<String, DICTEntry> getPrivateDict(DICTEntry privateEntry) throws IOException { | |||
return parseDictData(getPrivateDictBytes(privateEntry)); | |||
} | |||
public byte[] getPrivateDictBytes(DICTEntry privateEntry) throws IOException { | |||
int privateLength = privateEntry.getOperands().get(0).intValue(); | |||
int privateOffset = privateEntry.getOperands().get(1).intValue(); | |||
return getCFFOffsetBytes(privateOffset, privateLength); | |||
} | |||
/** | |||
* Retrieves a number of bytes from the CFF data stream | |||
* @param offset The offset of the bytes to retrieve | |||
* @param length The number of bytes to retrieve | |||
* @return Returns a byte array of requested bytes | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
private byte[] getCFFOffsetBytes(int offset, int length) throws IOException { | |||
cffData.setPosition(offset); | |||
return cffData.readBytes(length); | |||
} | |||
/** | |||
* Parses the dictionary data and returns a map of objects for each entry | |||
* @param dictData The data for the dictionary data | |||
* @return Returns a map of type DICTEntry identified by the operand name | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public LinkedHashMap<String, DICTEntry> parseDictData(byte[] dictData) throws IOException { | |||
LinkedHashMap<String, DICTEntry> dictEntries = new LinkedHashMap<String, DICTEntry>(); | |||
List<Number> operands = new ArrayList<Number>(); | |||
List<Integer> operandLengths = new ArrayList<Integer>(); | |||
int lastOperandLength = 0; | |||
for (int i = 0; i < dictData.length; i++) { | |||
int readByte = dictData[i] & 0xFF; | |||
if (readByte < 28) { | |||
int[] operator = new int[(readByte == DOUBLE_BYTE_OPERATOR) ? 2 : 1]; | |||
if (readByte == DOUBLE_BYTE_OPERATOR) { | |||
operator[0] = dictData[i]; | |||
operator[1] = dictData[i + 1]; | |||
i++; | |||
} else { | |||
operator[0] = dictData[i]; | |||
} | |||
String operatorName = ""; | |||
CFFOperator tempOp = null; | |||
if (operator.length > 1) { | |||
tempOp = CFFOperator.getOperator(new CFFOperator.Key(operator[0], operator[1])); | |||
} else { | |||
tempOp = CFFOperator.getOperator(new CFFOperator.Key(operator[0])); | |||
} | |||
if (tempOp != null) { | |||
operatorName = tempOp.getName(); | |||
} | |||
DICTEntry newEntry = new DICTEntry(); | |||
newEntry.setOperator(operator); | |||
newEntry.setOperands(new ArrayList<Number>(operands)); | |||
newEntry.setOperatorName(operatorName); | |||
newEntry.setOffset(i - lastOperandLength); | |||
newEntry.setOperandLength(lastOperandLength); | |||
newEntry.setOperandLengths(new ArrayList<Integer>(operandLengths)); | |||
byte[] byteData = new byte[lastOperandLength + operator.length]; | |||
System.arraycopy(dictData, i - operator.length - (lastOperandLength - 1), | |||
byteData, 0, operator.length + lastOperandLength); | |||
newEntry.setByteData(byteData); | |||
dictEntries.put(operatorName, newEntry); | |||
operands.clear(); | |||
operandLengths.clear(); | |||
lastOperandLength = 0; | |||
} else { | |||
if (readByte >= 32 && readByte <= 246) { | |||
operands.add(readByte - 139); | |||
lastOperandLength += 1; | |||
operandLengths.add(1); | |||
} else if (readByte >= 247 && readByte <= 250) { | |||
operands.add((readByte - 247) * 256 + (dictData[i + 1] & 0xFF) + 108); | |||
lastOperandLength += 2; | |||
operandLengths.add(2); | |||
i++; | |||
} else if (readByte >= 251 && readByte <= 254) { | |||
operands.add(-(readByte - 251) * 256 - (dictData[i + 1] & 0xFF) - 108); | |||
lastOperandLength += 2; | |||
operandLengths.add(2); | |||
i++; | |||
} else if (readByte == 28) { | |||
operands.add((dictData[i + 1] & 0xFF) << 8 | (dictData[i + 2] & 0xFF)); | |||
lastOperandLength += 3; | |||
operandLengths.add(3); | |||
i += 2; | |||
} else if (readByte == 29) { | |||
operands.add((dictData[i + 1] & 0xFF) << 24 | (dictData[i + 2] & 0xFF) << 16 | |||
| (dictData[i + 3] & 0xFF) << 8 | (dictData[i + 4] & 0xFF)); | |||
lastOperandLength += 5; | |||
operandLengths.add(5); | |||
i += 4; | |||
} else if (readByte == 30) { | |||
boolean terminatorFound = false; | |||
StringBuilder realNumber = new StringBuilder(); | |||
int byteCount = 1; | |||
do { | |||
byte nibblesByte = dictData[++i]; | |||
byteCount++; | |||
terminatorFound = readNibble(realNumber, (nibblesByte >> 4) & 0x0F); | |||
if (!terminatorFound) { | |||
terminatorFound = readNibble(realNumber, nibblesByte & 0x0F); | |||
} | |||
} while (!terminatorFound); | |||
operands.add(Double.valueOf(realNumber.toString())); | |||
lastOperandLength += byteCount; | |||
operandLengths.add(byteCount); | |||
} | |||
} | |||
} | |||
return dictEntries; | |||
} | |||
private boolean readNibble(StringBuilder realNumber, int nibble) { | |||
if (nibble <= 0x9) { | |||
realNumber.append(nibble); | |||
} else { | |||
switch (nibble) { | |||
case 0xa: realNumber.append("."); break; | |||
case 0xb: realNumber.append("E"); break; | |||
case 0xc: realNumber.append("E-"); break; | |||
case 0xd: break; | |||
case 0xe: realNumber.append("-"); break; | |||
case 0xf: return true; | |||
default: throw new AssertionError("Unexpected nibble value"); | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* A class containing data for a dictionary entry | |||
*/ | |||
public static class DICTEntry { | |||
private int[] operator; | |||
private List<Number> operands; | |||
private List<Integer> operandLengths; | |||
private String operatorName; | |||
private int offset; | |||
private int operandLength; | |||
private byte[] data = new byte[0]; | |||
public void setOperator(int[] operator) { | |||
this.operator = operator; | |||
} | |||
public int[] getOperator() { | |||
return this.operator; | |||
} | |||
public void setOperands(List<Number> operands) { | |||
this.operands = operands; | |||
} | |||
public List<Number> getOperands() { | |||
return this.operands; | |||
} | |||
public void setOperatorName(String operatorName) { | |||
this.operatorName = operatorName; | |||
} | |||
public String getOperatorName() { | |||
return this.operatorName; | |||
} | |||
public void setOffset(int offset) { | |||
this.offset = offset; | |||
} | |||
public int getOffset() { | |||
return this.offset; | |||
} | |||
public void setOperandLength(int operandLength) { | |||
this.operandLength = operandLength; | |||
} | |||
public int getOperandLength() { | |||
return this.operandLength; | |||
} | |||
public void setByteData(byte[] data) { | |||
this.data = data.clone(); | |||
} | |||
public byte[] getByteData() { | |||
return data.clone(); | |||
} | |||
public void setOperandLengths(List<Integer> operandLengths) { | |||
this.operandLengths = operandLengths; | |||
} | |||
public List<Integer> getOperandLengths() { | |||
return operandLengths; | |||
} | |||
} | |||
private byte[] readHeader() throws IOException { | |||
//Read known header | |||
byte[] fixedHeader = cffData.readBytes(4); | |||
int hdrSize = (fixedHeader[2] & 0xFF); | |||
byte[] extra = cffData.readBytes(hdrSize - 4); | |||
byte[] header = new byte[hdrSize]; | |||
for (int i = 0; i < fixedHeader.length; i++) { | |||
header[i] = fixedHeader[i]; | |||
} | |||
for (int i = 4; i < extra.length; i++) { | |||
header[i] = extra[i - 4]; | |||
} | |||
return header; | |||
} | |||
/** | |||
* Reads a CFF index object are the specified offset position | |||
* @param offset The position of the index object to read | |||
* @return Returns an object representing the index | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public CFFIndexData readIndex(int offset) throws IOException { | |||
cffData.setPosition(offset); | |||
return readIndex(); | |||
} | |||
private CFFIndexData readIndex() throws IOException { | |||
return readIndex(cffData); | |||
} | |||
/** | |||
* Reads an index from the current position of the CFFDataInput object | |||
* @param input The object holding the CFF byte data | |||
* @return Returns an object representing the index | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public CFFIndexData readIndex(CFFDataInput input) throws IOException { | |||
CFFIndexData nameIndex = new CFFIndexData(); | |||
if (input != null) { | |||
int origPos = input.getPosition(); | |||
nameIndex.parseIndexHeader(input); | |||
int tableSize = input.getPosition() - origPos; | |||
nameIndex.setByteData(input.getPosition() - tableSize, tableSize); | |||
} | |||
return nameIndex; | |||
} | |||
/** | |||
* Retrieves the SID for the given GID object | |||
* @param charsetOffset The offset of the charset data | |||
* @param GID The GID for which to retrieve the SID | |||
* @return Returns the SID as an integer | |||
*/ | |||
public int getSIDFromGID(int charsetOffset, int gid) throws IOException { | |||
if (gid == 0) { | |||
return 0; | |||
} | |||
cffData.setPosition(charsetOffset); | |||
int charsetFormat = cffData.readCard8(); | |||
switch (charsetFormat) { | |||
case 0: //Adjust for .notdef character | |||
cffData.setPosition(cffData.getPosition() + (--gid * 2)); | |||
return cffData.readSID(); | |||
case 1: return getSIDFromGIDFormat(gid, 1); | |||
case 2: return getSIDFromGIDFormat(gid, 2); | |||
default: return 0; | |||
} | |||
} | |||
private int getSIDFromGIDFormat(int gid, int format) throws IOException { | |||
int glyphCount = 0; | |||
while (true) { | |||
int oldGlyphCount = glyphCount; | |||
int start = cffData.readSID(); | |||
glyphCount += ((format == 1) ? cffData.readCard8() : cffData.readCard16()) + 1; | |||
if (gid <= glyphCount) { | |||
return start + (gid - oldGlyphCount) - 1; | |||
} | |||
} | |||
} | |||
public byte[] getHeader() { | |||
return header.clone(); | |||
} | |||
public CFFIndexData getNameIndex() { | |||
return nameIndex; | |||
} | |||
public CFFIndexData getTopDictIndex() { | |||
return topDICTIndex; | |||
} | |||
public LinkedHashMap<String, DICTEntry> getTopDictEntries() { | |||
return topDict; | |||
} | |||
public CFFIndexData getStringIndex() { | |||
return stringIndex; | |||
} | |||
public CFFIndexData getGlobalIndexSubr() { | |||
return globalIndexSubr; | |||
} | |||
public CFFIndexData getLocalIndexSubr() { | |||
return localIndexSubr; | |||
} | |||
public CFFIndexData getCharStringIndex() { | |||
return charStringIndex; | |||
} | |||
public CFFDataInput getCFFData() { | |||
return cffData; | |||
} | |||
public CustomEncoding getEncoding() { | |||
return encoding; | |||
} | |||
public FDSelect getFDSelect() { | |||
return fdSelect; | |||
} | |||
public List<FontDict> getFDFonts() { | |||
return fdFonts; | |||
} | |||
public CFFDataInput getLocalSubrsForGlyph(int glyph) throws IOException { | |||
//Subsets are currently written using a Format0 FDSelect | |||
FDSelect fontDictionary = getFDSelect(); | |||
if (fontDictionary instanceof Format0FDSelect) { | |||
Format0FDSelect fdSelect = (Format0FDSelect)fontDictionary; | |||
int found = fdSelect.getFDIndexes()[glyph]; | |||
FontDict font = getFDFonts().get(found); | |||
byte[] localSubrData = font.getLocalSubrData().getByteData(); | |||
if (localSubrData != null) { | |||
return new CFFDataInput(localSubrData); | |||
} else { | |||
return null; | |||
} | |||
} else if (fontDictionary instanceof Format3FDSelect) { | |||
Format3FDSelect fdSelect = (Format3FDSelect)fontDictionary; | |||
int index = 0; | |||
for (int first : fdSelect.getRanges().keySet()) { | |||
if (first > glyph) { | |||
break; | |||
} | |||
index++; | |||
} | |||
FontDict font = getFDFonts().get(index); | |||
byte[] localSubrsData = font.getLocalSubrData().getByteData(); | |||
if (localSubrsData != null) { | |||
return new CFFDataInput(localSubrsData); | |||
} else { | |||
return null; | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* Parses the char string index from the CFF byte data | |||
* @param offset The offset to the char string index | |||
* @return Returns the char string index object | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public CFFIndexData readCharStringIndex() throws IOException { | |||
int offset = topDict.get("CharStrings").getOperands().get(0).intValue(); | |||
cffData.setPosition(offset); | |||
return readIndex(); | |||
} | |||
private CustomEncoding readEncoding() throws IOException { | |||
CustomEncoding foundEncoding = null; | |||
if (topDict.get("Encoding") != null) { | |||
int offset = topDict.get("Encoding").getOperands().get(0).intValue(); | |||
if (offset != 0 && offset != 1) { | |||
//No need to set the offset as we are reading the data sequentially. | |||
int format = cffData.readCard8(); | |||
int numEntries = cffData.readCard8(); | |||
switch (format) { | |||
case 0: | |||
foundEncoding = readFormat0Encoding(format, numEntries); | |||
break; | |||
case 1: | |||
foundEncoding = readFormat1Encoding(format, numEntries); | |||
break; | |||
default: break; | |||
} | |||
} | |||
} | |||
return foundEncoding; | |||
} | |||
private Format0Encoding readFormat0Encoding(int format, int numEntries) | |||
throws IOException { | |||
Format0Encoding newEncoding = new Format0Encoding(); | |||
newEncoding.setFormat(format); | |||
newEncoding.setNumEntries(numEntries); | |||
int[] codes = new int[numEntries]; | |||
for (int i = 0; i < numEntries; i++) { | |||
codes[i] = cffData.readCard8(); | |||
} | |||
newEncoding.setCodes(codes); | |||
return newEncoding; | |||
} | |||
private Format1Encoding readFormat1Encoding(int format, int numEntries) | |||
throws IOException { | |||
Format1Encoding newEncoding = new Format1Encoding(); | |||
newEncoding.setFormat(format); | |||
newEncoding.setNumEntries(numEntries); | |||
LinkedHashMap<Integer, Integer> ranges = new LinkedHashMap<Integer, Integer>(); | |||
for (int i = 0; i < numEntries; i++) { | |||
int first = cffData.readCard8(); | |||
int left = cffData.readCard8(); | |||
ranges.put(first, left); | |||
} | |||
newEncoding.setRanges(ranges); | |||
return newEncoding; | |||
} | |||
private FDSelect readFDSelect() throws IOException { | |||
FDSelect fdSelect = null; | |||
DICTEntry fdSelectEntry = topDict.get("FDSelect"); | |||
if (fdSelectEntry != null) { | |||
int fdOffset = fdSelectEntry.getOperands().get(0).intValue(); | |||
cffData.setPosition(fdOffset); | |||
int format = cffData.readCard8(); | |||
switch (format) { | |||
case 0: | |||
fdSelect = readFormat0FDSelect(); | |||
break; | |||
case 3: | |||
fdSelect = readFormat3FDSelect(); | |||
break; | |||
default: | |||
} | |||
} | |||
return fdSelect; | |||
} | |||
private Format0FDSelect readFormat0FDSelect() throws IOException { | |||
Format0FDSelect newFDs = new Format0FDSelect(); | |||
newFDs.setFormat(0); | |||
int glyphCount = charStringIndex.getNumObjects(); | |||
int[] fds = new int[glyphCount]; | |||
for (int i = 0; i < glyphCount; i++) { | |||
fds[i] = cffData.readCard8(); | |||
} | |||
newFDs.setFDIndexes(fds); | |||
return newFDs; | |||
} | |||
private Format3FDSelect readFormat3FDSelect() throws IOException { | |||
Format3FDSelect newFDs = new Format3FDSelect(); | |||
newFDs.setFormat(3); | |||
int rangeCount = cffData.readCard16(); | |||
newFDs.setRangeCount(rangeCount); | |||
LinkedHashMap<Integer, Integer> ranges = new LinkedHashMap<Integer, Integer>(); | |||
for (int i = 0; i < rangeCount; i++) { | |||
int first = cffData.readCard16(); | |||
int fd = cffData.readCard8(); | |||
ranges.put(first, fd); | |||
} | |||
newFDs.setRanges(ranges); | |||
newFDs.setSentinelGID(cffData.readCard16()); | |||
return newFDs; | |||
} | |||
private List<FontDict> parseCIDData() throws IOException { | |||
ArrayList<FontDict> fdFonts = new ArrayList<FontDict>(); | |||
if (topDict.get("ROS") != null) { | |||
DICTEntry fdArray = topDict.get("FDArray"); | |||
if (fdArray != null) { | |||
int fdIndex = fdArray.getOperands().get(0).intValue(); | |||
CFFIndexData fontDicts = readIndex(fdIndex); | |||
for (int i = 0; i < fontDicts.getNumObjects(); i++) { | |||
FontDict newFontDict = new FontDict(); | |||
byte[] fdData = fontDicts.getValue(i); | |||
LinkedHashMap<String, DICTEntry> fdEntries = parseDictData(fdData); | |||
newFontDict.setByteData(fontDicts.getValuePosition(i), fontDicts.getValueLength(i)); | |||
DICTEntry fontFDEntry = fdEntries.get("FontName"); | |||
newFontDict.setFontName(getString(fontFDEntry.getOperands().get(0).intValue())); | |||
DICTEntry privateFDEntry = fdEntries.get("Private"); | |||
if (privateFDEntry != null) { | |||
newFontDict = setFDData(privateFDEntry, newFontDict); | |||
} | |||
fdFonts.add(newFontDict); | |||
} | |||
} | |||
} | |||
return fdFonts; | |||
} | |||
private FontDict setFDData(DICTEntry privateFDEntry, FontDict newFontDict) throws IOException { | |||
int privateFDLength = privateFDEntry.getOperands().get(0).intValue(); | |||
int privateFDOffset = privateFDEntry.getOperands().get(1).intValue(); | |||
cffData.setPosition(privateFDOffset); | |||
byte[] privateDict = cffData.readBytes(privateFDLength); | |||
newFontDict.setPrivateDictData(privateFDOffset, privateFDLength); | |||
LinkedHashMap<String, DICTEntry> privateEntries = parseDictData(privateDict); | |||
DICTEntry subroutines = privateEntries.get("Subrs"); | |||
if (subroutines != null) { | |||
CFFIndexData localSubrs = readIndex(privateFDOffset | |||
+ subroutines.getOperands().get(0).intValue()); | |||
newFontDict.setLocalSubrData(localSubrs); | |||
} else { | |||
newFontDict.setLocalSubrData(new CFFIndexData()); | |||
} | |||
return newFontDict; | |||
} | |||
private String getString(int sid) throws IOException { | |||
return new String(stringIndex.getValue(sid - NUM_STANDARD_STRINGS)); | |||
} | |||
private CFFIndexData readLocalIndexSubrs() throws IOException { | |||
CFFIndexData localSubrs = null; | |||
DICTEntry privateEntry = topDict.get("Private"); | |||
if (privateEntry != null) { | |||
int length = privateEntry.getOperands().get(0).intValue(); | |||
int offset = privateEntry.getOperands().get(1).intValue(); | |||
cffData.setPosition(offset); | |||
byte[] privateData = cffData.readBytes(length); | |||
LinkedHashMap<String, DICTEntry> privateDict = parseDictData(privateData); | |||
DICTEntry localSubrsEntry = privateDict.get("Subrs"); | |||
if (localSubrsEntry != null) { | |||
int localOffset = offset + localSubrsEntry.getOperands().get(0).intValue(); | |||
cffData.setPosition(localOffset); | |||
localSubrs = readIndex(); | |||
} | |||
} | |||
return localSubrs; | |||
} | |||
/** | |||
* Parent class which provides the ability to retrieve byte data from | |||
* a sub-table. | |||
*/ | |||
public class CFFSubTable { | |||
private DataLocation dataLocation = new DataLocation(); | |||
public void setByteData(int position, int length) { | |||
dataLocation = new DataLocation(position, length); | |||
} | |||
public byte[] getByteData() throws IOException { | |||
int oldPos = cffData.getPosition(); | |||
try { | |||
cffData.setPosition(dataLocation.getDataPosition()); | |||
return cffData.readBytes(dataLocation.getDataLength()); | |||
} finally { | |||
cffData.setPosition(oldPos); | |||
} | |||
} | |||
} | |||
/** | |||
* An object used to hold index data from the CFF data | |||
*/ | |||
public class CFFIndexData extends CFFSubTable { | |||
private int numObjects; | |||
private int offSize; | |||
private int[] offsets = new int[0]; | |||
private DataLocation dataLocation = new DataLocation(); | |||
public void setNumObjects(int numObjects) { | |||
this.numObjects = numObjects; | |||
} | |||
public int getNumObjects() { | |||
return this.numObjects; | |||
} | |||
public void setOffSize(int offSize) { | |||
this.offSize = offSize; | |||
} | |||
public int getOffSize() { | |||
return this.offSize; | |||
} | |||
public void setOffsets(int[] offsets) { | |||
this.offsets = offsets.clone(); | |||
} | |||
public int[] getOffsets() { | |||
return offsets.clone(); | |||
} | |||
public void setData(int position, int length) { | |||
dataLocation = new DataLocation(position, length); | |||
} | |||
public byte[] getData() throws IOException { | |||
int origPos = cffData.getPosition(); | |||
try { | |||
cffData.setPosition(dataLocation.getDataPosition()); | |||
return cffData.readBytes(dataLocation.getDataLength()); | |||
} finally { | |||
cffData.setPosition(origPos); | |||
} | |||
} | |||
/** | |||
* Parses index data from an index object found within the CFF byte data | |||
* @param cffData A byte array containing the CFF data | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public void parseIndexHeader(CFFDataInput cffData) throws IOException { | |||
setNumObjects(cffData.readCard16()); | |||
setOffSize(cffData.readOffSize()); | |||
int[] offsets = new int[getNumObjects() + 1]; | |||
byte[] bytes; | |||
//Fills the offsets array | |||
for (int i = 0; i <= getNumObjects(); i++) { | |||
switch (getOffSize()) { | |||
case 1: | |||
offsets[i] = cffData.readCard8(); | |||
break; | |||
case 2: | |||
offsets[i] = cffData.readCard16(); | |||
break; | |||
case 3: | |||
bytes = cffData.readBytes(3); | |||
offsets[i] = ((bytes[0] & 0xFF) << 16) + ((bytes[1] & 0xFF) << 8) + (bytes[2] & 0xFF); | |||
break; | |||
case 4: | |||
bytes = cffData.readBytes(4); | |||
offsets[i] = ((bytes[0] & 0xFF) << 24) + ((bytes[1] & 0xFF) << 16) | |||
+ ((bytes[2] & 0xFF) << 8) + (bytes[3] & 0xFF); | |||
break; | |||
default: continue; | |||
} | |||
} | |||
setOffsets(offsets); | |||
int position = cffData.getPosition(); | |||
int dataSize = offsets[offsets.length - 1] - offsets[0]; | |||
cffData.setPosition(cffData.getPosition() + dataSize); | |||
setData(position, dataSize); | |||
} | |||
/** | |||
* Retrieves data from the index data | |||
* @param index The index position of the data to retrieve | |||
* @return Returns the byte data for the given index | |||
* @throws IOException Throws an IO Exception if an error occurs | |||
*/ | |||
public byte[] getValue(int index) throws IOException { | |||
int oldPos = cffData.getPosition(); | |||
try { | |||
cffData.setPosition(dataLocation.getDataPosition() + (offsets[index] - 1)); | |||
return cffData.readBytes(offsets[index + 1] - offsets[index]); | |||
} finally { | |||
cffData.setPosition(oldPos); | |||
} | |||
} | |||
public int getValuePosition(int index) { | |||
return dataLocation.getDataPosition() + (offsets[index] - 1); | |||
} | |||
public int getValueLength(int index) { | |||
return offsets[index + 1] - offsets[index]; | |||
} | |||
} | |||
public abstract class CustomEncoding { | |||
private int format; | |||
private int numEntries; | |||
public void setFormat(int format) { | |||
this.format = format; | |||
} | |||
public int getFormat() { | |||
return format; | |||
} | |||
public void setNumEntries(int numEntries) { | |||
this.numEntries = numEntries; | |||
} | |||
public int getNumEntries() { | |||
return numEntries; | |||
} | |||
} | |||
public class Format0Encoding extends CustomEncoding { | |||
private int[] codes = new int[0]; | |||
public void setCodes(int[] codes) { | |||
this.codes = codes.clone(); | |||
} | |||
public int[] getCodes() { | |||
return codes.clone(); | |||
} | |||
} | |||
public class Format1Encoding extends CustomEncoding { | |||
private LinkedHashMap<Integer, Integer> ranges; | |||
public void setRanges(LinkedHashMap<Integer, Integer> ranges) { | |||
this.ranges = ranges; | |||
} | |||
public LinkedHashMap<Integer, Integer> getRanges() { | |||
return ranges; | |||
} | |||
} | |||
public class FDSelect { | |||
private int format; | |||
public void setFormat(int format) { | |||
this.format = format; | |||
} | |||
public int getFormat() { | |||
return format; | |||
} | |||
} | |||
public class Format0FDSelect extends FDSelect { | |||
private int[] fds = new int[0]; | |||
public void setFDIndexes(int[] fds) { | |||
this.fds = fds.clone(); | |||
} | |||
public int[] getFDIndexes() { | |||
return fds.clone(); | |||
} | |||
} | |||
public class Format3FDSelect extends FDSelect { | |||
private int rangeCount; | |||
private LinkedHashMap<Integer, Integer> ranges; | |||
private int sentinelGID; | |||
public void setRangeCount(int rangeCount) { | |||
this.rangeCount = rangeCount; | |||
} | |||
public int getRangeCount() { | |||
return rangeCount; | |||
} | |||
public void setRanges(LinkedHashMap<Integer, Integer> ranges) { | |||
this.ranges = ranges; | |||
} | |||
public LinkedHashMap<Integer, Integer> getRanges() { | |||
return ranges; | |||
} | |||
public void setSentinelGID(int sentinelGID) { | |||
this.sentinelGID = sentinelGID; | |||
} | |||
public int getSentinelGID() { | |||
return sentinelGID; | |||
} | |||
} | |||
public class FontDict extends CFFSubTable { | |||
private String fontName; | |||
private DataLocation dataLocation = new DataLocation(); | |||
private CFFIndexData localSubrData; | |||
public void setFontName(String groupName) { | |||
this.fontName = groupName; | |||
} | |||
public String getFontName() { | |||
return fontName; | |||
} | |||
public void setPrivateDictData(int position, int length) { | |||
dataLocation = new DataLocation(position, length); | |||
} | |||
public byte[] getPrivateDictData() throws IOException { | |||
int origPos = cffData.getPosition(); | |||
try { | |||
cffData.setPosition(dataLocation.getDataPosition()); | |||
return cffData.readBytes(dataLocation.getDataLength()); | |||
} finally { | |||
cffData.setPosition(origPos); | |||
} | |||
} | |||
public void setLocalSubrData(CFFIndexData localSubrData) { | |||
this.localSubrData = localSubrData; | |||
} | |||
public CFFIndexData getLocalSubrData() { | |||
return localSubrData; | |||
} | |||
} | |||
private static class DataLocation { | |||
private int dataPosition; | |||
private int dataLength; | |||
public DataLocation() { | |||
dataPosition = 0; | |||
dataLength = 0; | |||
} | |||
public DataLocation(int position, int length) { | |||
this.dataPosition = position; | |||
this.dataLength = length; | |||
} | |||
public int getDataPosition() { | |||
return dataPosition; | |||
} | |||
public int getDataLength() { | |||
return dataLength; | |||
} | |||
} | |||
} |
@@ -31,7 +31,7 @@ import java.util.TreeSet; | |||
*/ | |||
public class GlyfTable { | |||
private final TTFMtxEntry[] mtxTab; | |||
private final OFMtxEntry[] mtxTab; | |||
private final long tableOffset; | |||
@@ -47,7 +47,7 @@ public class GlyfTable { | |||
/** All the glyphs that are composed, but do not appear in the subset. */ | |||
private Set<Integer> composedGlyphs = new TreeSet<Integer>(); | |||
GlyfTable(FontFileReader in, TTFMtxEntry[] metrics, TTFDirTabEntry dirTableEntry, | |||
GlyfTable(FontFileReader in, OFMtxEntry[] metrics, OFDirTabEntry dirTableEntry, | |||
Map<Integer, Integer> glyphs) throws IOException { | |||
mtxTab = metrics; | |||
tableOffset = dirTableEntry.getOffset(); |
@@ -26,17 +26,17 @@ import java.io.UnsupportedEncodingException; | |||
/** | |||
* This class represents an entry to a TrueType font's Dir Tab. | |||
*/ | |||
public class TTFDirTabEntry { | |||
public class OFDirTabEntry { | |||
private byte[] tag = new byte[4]; | |||
private int checksum; | |||
private long offset; | |||
private long length; | |||
public TTFDirTabEntry() { | |||
public OFDirTabEntry() { | |||
} | |||
public TTFDirTabEntry(long offset, long length) { | |||
public OFDirTabEntry(long offset, long length) { | |||
this.offset = offset; | |||
this.length = length; | |||
} |
@@ -38,13 +38,13 @@ import org.apache.fop.fonts.FontType; | |||
import org.apache.fop.fonts.MultiByteFont; | |||
import org.apache.fop.fonts.NamedCharacter; | |||
import org.apache.fop.fonts.SingleByteFont; | |||
import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; | |||
import org.apache.fop.fonts.truetype.OpenFont.PostScriptVersion; | |||
import org.apache.fop.util.HexEncoder; | |||
/** | |||
* Loads a TrueType font into memory directly from the original font file. | |||
*/ | |||
public class TTFFontLoader extends FontLoader { | |||
public class OFFontLoader extends FontLoader { | |||
private MultiByteFont multiFont; | |||
private SingleByteFont singleFont; | |||
@@ -57,7 +57,7 @@ public class TTFFontLoader extends FontLoader { | |||
* @param fontFileURI the URI representing the font file | |||
* @param resourceResolver the resource resolver for font URI resolution | |||
*/ | |||
public TTFFontLoader(URI fontFileURI, InternalResourceResolver resourceResolver) { | |||
public OFFontLoader(URI fontFileURI, InternalResourceResolver resourceResolver) { | |||
this(fontFileURI, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true, resourceResolver); | |||
} | |||
@@ -73,7 +73,7 @@ public class TTFFontLoader extends FontLoader { | |||
* @param useAdvanced true to enable loading advanced info if available, false to disable | |||
* @param resolver the FontResolver for font URI resolution | |||
*/ | |||
public TTFFontLoader(URI fontFileURI, String subFontName, boolean embedded, | |||
public OFFontLoader(URI fontFileURI, String subFontName, boolean embedded, | |||
EmbeddingMode embeddingMode, EncodingMode encodingMode, boolean useKerning, | |||
boolean useAdvanced, InternalResourceResolver resolver) { | |||
super(fontFileURI, embedded, useKerning, useAdvanced, resolver); | |||
@@ -102,26 +102,30 @@ public class TTFFontLoader extends FontLoader { | |||
private void read(String ttcFontName) throws IOException { | |||
InputStream in = resourceResolver.getResource(this.fontFileURI); | |||
try { | |||
TTFFile ttf = new TTFFile(useKerning, useAdvanced); | |||
FontFileReader reader = new FontFileReader(in); | |||
boolean supported = ttf.readFont(reader, ttcFontName); | |||
String header = readHeader(reader); | |||
boolean isCFF = header.equals("OTTO"); | |||
OpenFont otf = (isCFF) ? new OTFFile() : new TTFFile(useKerning, useAdvanced); | |||
boolean supported = otf.readFont(reader, header, ttcFontName); | |||
if (!supported) { | |||
throw new IOException("TrueType font is not supported: " + fontFileURI); | |||
throw new IOException("The font does not have a Unicode cmap table: " + fontFileURI); | |||
} | |||
buildFont(ttf, ttcFontName); | |||
buildFont(otf, ttcFontName); | |||
loaded = true; | |||
} finally { | |||
IOUtils.closeQuietly(in); | |||
} | |||
} | |||
private void buildFont(TTFFile ttf, String ttcFontName) { | |||
if (ttf.isCFF()) { | |||
throw new UnsupportedOperationException( | |||
"OpenType fonts with CFF data are not supported, yet"); | |||
public static String readHeader(FontFileReader fontFile) throws IOException { | |||
if (fontFile != null) { | |||
fontFile.seekSet(0); | |||
return fontFile.readTTFString(4); // TTF_FIXED_SIZE (4 bytes) | |||
} | |||
return null; | |||
} | |||
private void buildFont(OpenFont otf, String ttcFontName) { | |||
boolean isCid = this.embedded; | |||
if (this.encodingMode == EncodingMode.SINGLE_BYTE) { | |||
isCid = false; | |||
@@ -129,6 +133,7 @@ public class TTFFontLoader extends FontLoader { | |||
if (isCid) { | |||
multiFont = new MultiByteFont(resourceResolver, embeddingMode); | |||
multiFont.setIsOTFFile(otf instanceof OTFFile); | |||
returnFont = multiFont; | |||
multiFont.setTTCName(ttcFontName); | |||
} else { | |||
@@ -136,47 +141,51 @@ public class TTFFontLoader extends FontLoader { | |||
returnFont = singleFont; | |||
} | |||
returnFont.setFontName(ttf.getPostScriptName()); | |||
returnFont.setFullName(ttf.getFullName()); | |||
returnFont.setFamilyNames(ttf.getFamilyNames()); | |||
returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); | |||
returnFont.setCapHeight(ttf.getCapHeight()); | |||
returnFont.setXHeight(ttf.getXHeight()); | |||
returnFont.setAscender(ttf.getLowerCaseAscent()); | |||
returnFont.setDescender(ttf.getLowerCaseDescent()); | |||
returnFont.setFontBBox(ttf.getFontBBox()); | |||
returnFont.setUnderlinePosition(ttf.getUnderlinePosition() - ttf.getUnderlineThickness() / 2); | |||
returnFont.setUnderlineThickness(ttf.getUnderlineThickness()); | |||
returnFont.setStrikeoutPosition(ttf.getStrikeoutPosition() - ttf.getStrikeoutThickness() / 2); | |||
returnFont.setStrikeoutThickness(ttf.getStrikeoutThickness()); | |||
returnFont.setFlags(ttf.getFlags()); | |||
returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF | |||
returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); | |||
returnFont.setFontName(otf.getPostScriptName()); | |||
returnFont.setFullName(otf.getFullName()); | |||
returnFont.setFamilyNames(otf.getFamilyNames()); | |||
returnFont.setFontSubFamilyName(otf.getSubFamilyName()); | |||
returnFont.setCapHeight(otf.getCapHeight()); | |||
returnFont.setXHeight(otf.getXHeight()); | |||
returnFont.setAscender(otf.getLowerCaseAscent()); | |||
returnFont.setDescender(otf.getLowerCaseDescent()); | |||
returnFont.setFontBBox(otf.getFontBBox()); | |||
returnFont.setUnderlinePosition(otf.getUnderlinePosition() - otf.getUnderlineThickness() / 2); | |||
returnFont.setUnderlineThickness(otf.getUnderlineThickness()); | |||
returnFont.setStrikeoutPosition(otf.getStrikeoutPosition() - otf.getStrikeoutThickness() / 2); | |||
returnFont.setStrikeoutThickness(otf.getStrikeoutThickness()); | |||
returnFont.setFlags(otf.getFlags()); | |||
returnFont.setStemV(Integer.parseInt(otf.getStemV())); //not used for TTF | |||
returnFont.setItalicAngle(Integer.parseInt(otf.getItalicAngle())); | |||
returnFont.setMissingWidth(0); | |||
returnFont.setWeight(ttf.getWeightClass()); | |||
returnFont.setWeight(otf.getWeightClass()); | |||
returnFont.setEmbeddingMode(this.embeddingMode); | |||
if (isCid) { | |||
multiFont.setCIDType(CIDFontType.CIDTYPE2); | |||
multiFont.setWidthArray(ttf.getWidths()); | |||
multiFont.setBBoxArray(ttf.getBoundingBoxes()); | |||
if (otf instanceof OTFFile) { | |||
multiFont.setCIDType(CIDFontType.CIDTYPE0); | |||
} else { | |||
multiFont.setCIDType(CIDFontType.CIDTYPE2); | |||
} | |||
multiFont.setWidthArray(otf.getWidths()); | |||
multiFont.setBBoxArray(otf.getBoundingBoxes()); | |||
} else { | |||
singleFont.setFontType(FontType.TRUETYPE); | |||
singleFont.setEncoding(ttf.getCharSetName()); | |||
returnFont.setFirstChar(ttf.getFirstChar()); | |||
returnFont.setLastChar(ttf.getLastChar()); | |||
singleFont.setTrueTypePostScriptVersion(ttf.getPostScriptVersion()); | |||
copyGlyphMetricsSingleByte(ttf); | |||
singleFont.setEncoding(otf.getCharSetName()); | |||
returnFont.setFirstChar(otf.getFirstChar()); | |||
returnFont.setLastChar(otf.getLastChar()); | |||
singleFont.setTrueTypePostScriptVersion(otf.getPostScriptVersion()); | |||
copyGlyphMetricsSingleByte(otf); | |||
} | |||
returnFont.setCMap(getCMap(ttf)); | |||
returnFont.setCMap(getCMap(otf)); | |||
if (useKerning) { | |||
copyKerning(ttf, isCid); | |||
if (otf.getKerning() != null && useKerning) { | |||
copyKerning(otf, isCid); | |||
} | |||
if (useAdvanced) { | |||
copyAdvanced(ttf); | |||
copyAdvanced(otf); | |||
} | |||
if (this.embedded) { | |||
if (ttf.isEmbeddable()) { | |||
if (otf.isEmbeddable()) { | |||
returnFont.setEmbedURI(this.fontFileURI); | |||
} else { | |||
String msg = "The font " + this.fontFileURI + " is not embeddable due to a" | |||
@@ -186,28 +195,29 @@ public class TTFFontLoader extends FontLoader { | |||
} | |||
} | |||
private CMapSegment[] getCMap(TTFFile ttf) { | |||
CMapSegment[] array = new CMapSegment[ttf.getCMaps().size()]; | |||
return ttf.getCMaps().toArray(array); | |||
private CMapSegment[] getCMap(OpenFont otf) { | |||
CMapSegment[] array = new CMapSegment[otf.getCMaps().size()]; | |||
return otf.getCMaps().toArray(array); | |||
} | |||
private void copyGlyphMetricsSingleByte(TTFFile ttf) { | |||
int[] wx = ttf.getWidths(); | |||
Rectangle[] bboxes = ttf.getBoundingBoxes(); | |||
private void copyGlyphMetricsSingleByte(OpenFont otf) { | |||
int[] wx = otf.getWidths(); | |||
Rectangle[] bboxes = otf.getBoundingBoxes(); | |||
for (int i = singleFont.getFirstChar(); i <= singleFont.getLastChar(); i++) { | |||
singleFont.setWidth(i, ttf.getCharWidth(i)); | |||
int[] bbox = ttf.getBBox(i); | |||
singleFont.setWidth(i, otf.getCharWidth(i)); | |||
int[] bbox = otf.getBBox(i); | |||
singleFont.setBoundingBox(i, | |||
new Rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1])); | |||
} | |||
for (CMapSegment segment : ttf.getCMaps()) { | |||
for (CMapSegment segment : otf.getCMaps()) { | |||
if (segment.getUnicodeStart() < 0xFFFE) { | |||
for (char u = (char)segment.getUnicodeStart(); u <= segment.getUnicodeEnd(); u++) { | |||
int codePoint = singleFont.getEncoding().mapChar(u); | |||
if (codePoint <= 0) { | |||
int glyphIndex = segment.getGlyphStartIndex() + u - segment.getUnicodeStart(); | |||
String glyphName = ttf.getGlyphName(glyphIndex); | |||
if (glyphName.length() == 0 && ttf.getPostScriptVersion() != PostScriptVersion.V2) { | |||
String glyphName = otf.getGlyphName(glyphIndex); | |||
if (glyphName.length() == 0 && otf.getPostScriptVersion() != PostScriptVersion.V2) { | |||
glyphName = "u" + HexEncoder.encode(u); | |||
} | |||
if (glyphName.length() > 0) { | |||
@@ -224,22 +234,22 @@ public class TTFFontLoader extends FontLoader { | |||
/** | |||
* Copy kerning information. | |||
*/ | |||
private void copyKerning(TTFFile ttf, boolean isCid) { | |||
private void copyKerning(OpenFont otf, boolean isCid) { | |||
// Get kerning | |||
Set<Integer> kerningSet; | |||
if (isCid) { | |||
kerningSet = ttf.getKerning().keySet(); | |||
kerningSet = otf.getKerning().keySet(); | |||
} else { | |||
kerningSet = ttf.getAnsiKerning().keySet(); | |||
kerningSet = otf.getAnsiKerning().keySet(); | |||
} | |||
for (Integer kpx1 : kerningSet) { | |||
Map<Integer, Integer> h2; | |||
if (isCid) { | |||
h2 = ttf.getKerning().get(kpx1); | |||
h2 = otf.getKerning().get(kpx1); | |||
} else { | |||
h2 = ttf.getAnsiKerning().get(kpx1); | |||
h2 = otf.getAnsiKerning().get(kpx1); | |||
} | |||
returnFont.putKerningEntry(kpx1, h2); | |||
} | |||
@@ -248,12 +258,12 @@ public class TTFFontLoader extends FontLoader { | |||
/** | |||
* Copy advanced typographic information. | |||
*/ | |||
private void copyAdvanced(TTFFile ttf) { | |||
private void copyAdvanced(OpenFont otf) { | |||
if (returnFont instanceof MultiByteFont) { | |||
MultiByteFont mbf = (MultiByteFont) returnFont; | |||
mbf.setGDEF(ttf.getGDEF()); | |||
mbf.setGSUB(ttf.getGSUB()); | |||
mbf.setGPOS(ttf.getGPOS()); | |||
mbf.setGDEF(otf.getGDEF()); | |||
mbf.setGSUB(otf.getGSUB()); | |||
mbf.setGPOS(otf.getGPOS()); | |||
} | |||
} | |||
@@ -24,7 +24,7 @@ import java.util.List; | |||
/** | |||
* This class represents a TrueType Mtx Entry. | |||
*/ | |||
class TTFMtxEntry { | |||
class OFMtxEntry { | |||
private int wx; | |||
private int lsb; |
@@ -24,98 +24,104 @@ package org.apache.fop.fonts.truetype; | |||
* Represents table names as found in a TrueType font's Table Directory. | |||
* TrueType fonts may have custom tables so we cannot use an enum. | |||
*/ | |||
public final class TTFTableName { | |||
public final class OFTableName { | |||
/** The first table in a TrueType font file containing metadata about other tables. */ | |||
public static final TTFTableName TABLE_DIRECTORY = new TTFTableName("tableDirectory"); | |||
public static final OFTableName TABLE_DIRECTORY = new OFTableName("tableDirectory"); | |||
/** Baseline data */ | |||
public static final OFTableName BASE = new OFTableName("BASE"); | |||
/** CFF data/ */ | |||
public static final OFTableName CFF = new OFTableName("CFF "); | |||
/** Embedded bitmap data. */ | |||
public static final TTFTableName EBDT = new TTFTableName("EBDT"); | |||
public static final OFTableName EBDT = new OFTableName("EBDT"); | |||
/** Embedded bitmap location data. */ | |||
public static final TTFTableName EBLC = new TTFTableName("EBLC"); | |||
public static final OFTableName EBLC = new OFTableName("EBLC"); | |||
/** Embedded bitmap scaling data. */ | |||
public static final TTFTableName EBSC = new TTFTableName("EBSC"); | |||
public static final OFTableName EBSC = new OFTableName("EBSC"); | |||
/** A FontForge specific table. */ | |||
public static final TTFTableName FFTM = new TTFTableName("FFTM"); | |||
public static final OFTableName FFTM = new OFTableName("FFTM"); | |||
/** Divides glyphs into various classes that make using the GPOS/GSUB tables easier. */ | |||
public static final TTFTableName GDEF = new TTFTableName("GDEF"); | |||
public static final OFTableName GDEF = new OFTableName("GDEF"); | |||
/** Provides kerning information, mark-to-base, etc. for opentype fonts. */ | |||
public static final TTFTableName GPOS = new TTFTableName("GPOS"); | |||
public static final OFTableName GPOS = new OFTableName("GPOS"); | |||
/** Provides ligature information, swash, etc. for opentype fonts. */ | |||
public static final TTFTableName GSUB = new TTFTableName("GSUB"); | |||
public static final OFTableName GSUB = new OFTableName("GSUB"); | |||
/** Linear threshold table. */ | |||
public static final TTFTableName LTSH = new TTFTableName("LTSH"); | |||
public static final OFTableName LTSH = new OFTableName("LTSH"); | |||
/** OS/2 and Windows specific metrics. */ | |||
public static final TTFTableName OS2 = new TTFTableName("OS/2"); | |||
public static final OFTableName OS2 = new OFTableName("OS/2"); | |||
/** PCL 5 data. */ | |||
public static final TTFTableName PCLT = new TTFTableName("PCLT"); | |||
public static final OFTableName PCLT = new OFTableName("PCLT"); | |||
/** Vertical Device Metrics table. */ | |||
public static final TTFTableName VDMX = new TTFTableName("VDMX"); | |||
public static final OFTableName VDMX = new OFTableName("VDMX"); | |||
/** Character to glyph mapping. */ | |||
public static final TTFTableName CMAP = new TTFTableName("cmap"); | |||
public static final OFTableName CMAP = new OFTableName("cmap"); | |||
/** Control Value Table. */ | |||
public static final TTFTableName CVT = new TTFTableName("cvt "); | |||
public static final OFTableName CVT = new OFTableName("cvt "); | |||
/** Font program. */ | |||
public static final TTFTableName FPGM = new TTFTableName("fpgm"); | |||
public static final OFTableName FPGM = new OFTableName("fpgm"); | |||
/** Grid-fitting and scan conversion procedure (grayscale). */ | |||
public static final TTFTableName GASP = new TTFTableName("gasp"); | |||
public static final OFTableName GASP = new OFTableName("gasp"); | |||
/** Glyph data. */ | |||
public static final TTFTableName GLYF = new TTFTableName("glyf"); | |||
public static final OFTableName GLYF = new OFTableName("glyf"); | |||
/** Horizontal device metrics. */ | |||
public static final TTFTableName HDMX = new TTFTableName("hdmx"); | |||
public static final OFTableName HDMX = new OFTableName("hdmx"); | |||
/** Font header. */ | |||
public static final TTFTableName HEAD = new TTFTableName("head"); | |||
public static final OFTableName HEAD = new OFTableName("head"); | |||
/** Horizontal header. */ | |||
public static final TTFTableName HHEA = new TTFTableName("hhea"); | |||
public static final OFTableName HHEA = new OFTableName("hhea"); | |||
/** Horizontal metrics. */ | |||
public static final TTFTableName HMTX = new TTFTableName("hmtx"); | |||
public static final OFTableName HMTX = new OFTableName("hmtx"); | |||
/** Kerning. */ | |||
public static final TTFTableName KERN = new TTFTableName("kern"); | |||
public static final OFTableName KERN = new OFTableName("kern"); | |||
/** Index to location. */ | |||
public static final TTFTableName LOCA = new TTFTableName("loca"); | |||
public static final OFTableName LOCA = new OFTableName("loca"); | |||
/** Maximum profile. */ | |||
public static final TTFTableName MAXP = new TTFTableName("maxp"); | |||
public static final OFTableName MAXP = new OFTableName("maxp"); | |||
/** Naming table. */ | |||
public static final TTFTableName NAME = new TTFTableName("name"); | |||
public static final OFTableName NAME = new OFTableName("name"); | |||
/** PostScript information. */ | |||
public static final TTFTableName POST = new TTFTableName("post"); | |||
public static final OFTableName POST = new OFTableName("post"); | |||
/** CVT Program. */ | |||
public static final TTFTableName PREP = new TTFTableName("prep"); | |||
public static final OFTableName PREP = new OFTableName("prep"); | |||
/** Vertical Metrics header. */ | |||
public static final TTFTableName VHEA = new TTFTableName("vhea"); | |||
public static final OFTableName VHEA = new OFTableName("vhea"); | |||
/** Vertical Metrics. */ | |||
public static final TTFTableName VMTX = new TTFTableName("vmtx"); | |||
public static final OFTableName VMTX = new OFTableName("vmtx"); | |||
private final String name; | |||
private TTFTableName(String name) { | |||
private OFTableName(String name) { | |||
this.name = name; | |||
} | |||
@@ -131,9 +137,9 @@ public final class TTFTableName { | |||
* @param tableName table name as in the Table Directory | |||
* @return TTFTableName | |||
*/ | |||
public static TTFTableName getValue(String tableName) { | |||
public static OFTableName getValue(String tableName) { | |||
if (tableName != null) { | |||
return new TTFTableName(tableName); | |||
return new OFTableName(tableName); | |||
} | |||
throw new IllegalArgumentException("A TrueType font table name must not be null"); | |||
} | |||
@@ -148,10 +154,10 @@ public final class TTFTableName { | |||
if (o == this) { | |||
return true; | |||
} | |||
if (!(o instanceof TTFTableName)) { | |||
if (!(o instanceof OFTableName)) { | |||
return false; | |||
} | |||
TTFTableName to = (TTFTableName) o; | |||
OFTableName to = (OFTableName) o; | |||
return this.name.equals(to.getName()); | |||
} | |||
@@ -0,0 +1,109 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.fonts.truetype; | |||
import java.io.IOException; | |||
import org.apache.fontbox.cff.CFFDataInput; | |||
import org.apache.fontbox.cff.CFFFont; | |||
import org.apache.fontbox.cff.CFFFont.Mapping; | |||
import org.apache.fontbox.cff.CFFParser; | |||
public class OTFFile extends OpenFont { | |||
protected CFFFont fileFont; | |||
public OTFFile() throws IOException { | |||
checkForFontbox(); | |||
} | |||
private void checkForFontbox() throws IOException { | |||
try { | |||
Class.forName("org.apache.fontbox.cff.CFFFont"); | |||
} catch (ClassNotFoundException ex) { | |||
throw new IOException("The Fontbox jar was not found in the classpath. This is " | |||
+ "required for OTF CFF ssupport."); | |||
} | |||
} | |||
@Override | |||
protected void updateBBoxAndOffset() throws IOException { | |||
UnicodeMapping[] mappings = unicodeMappings.toArray(new UnicodeMapping[0]); | |||
for (int i = 0; i < mappings.length; i++) { | |||
int glyphIdx = mappings[i].getGlyphIndex(); | |||
Mapping m = fileFont.getGIDMappings().get(glyphIdx); | |||
int[] bbox = fileFont.getBoundingBox(m.getSID()); | |||
String name = fileFont.getNameOfCharFromCode(m.getSID()); | |||
mtxTab[glyphIdx].setBoundingBox(bbox); | |||
mtxTab[glyphIdx].setName(name); | |||
} | |||
} | |||
@Override | |||
protected void initializeFont(FontFileReader in) throws IOException { | |||
fontFile = in; | |||
fontFile.seekSet(0); | |||
CFFParser parser = new CFFParser(); | |||
fileFont = parser.parse(in.getAllBytes()).get(0); | |||
} | |||
protected void readName() throws IOException { | |||
Object familyName = fileFont.getProperty("FamilyName"); | |||
if (familyName != null && !familyName.equals("")) { | |||
familyNames.add(familyName.toString()); | |||
fullName = familyName.toString(); | |||
} else { | |||
fullName = fileFont.getName(); | |||
familyNames.add(fullName); | |||
} | |||
} | |||
/** | |||
* Reads the CFFData from a given font file | |||
* @param fontFile The font file being read | |||
* @return The byte data found in the CFF table | |||
*/ | |||
public static byte[] getCFFData(FontFileReader fontFile) throws IOException { | |||
byte[] cff = new byte[0]; | |||
CFFDataInput input = new CFFDataInput(fontFile.getAllBytes()); | |||
input.readBytes(4); //OTTO | |||
short numTables = input.readShort(); | |||
input.readShort(); //searchRange | |||
input.readShort(); //entrySelector | |||
input.readShort(); //rangeShift | |||
for (int q = 0; q < numTables; q++) { | |||
String tagName = new String(input.readBytes(4)); | |||
readLong(input); //Checksum | |||
long offset = readLong(input); | |||
long length = readLong(input); | |||
if (tagName.equals("CFF ")) { | |||
cff = new byte[(int)length]; | |||
System.arraycopy(fontFile.getAllBytes(), (int)offset, cff, 0, cff.length); | |||
break; | |||
} | |||
} | |||
return cff; | |||
} | |||
private static long readLong(CFFDataInput input) throws IOException { | |||
return (input.readCard16() << 16) | input.readCard16(); | |||
} | |||
} |
@@ -43,7 +43,7 @@ public class TTFSubSetFile extends TTFFile { | |||
* Offsets in name table to be filled out by table. | |||
* The offsets are to the checkSum field | |||
*/ | |||
private Map<TTFTableName, Integer> offsets = new HashMap<TTFTableName, Integer>(); | |||
private Map<OFTableName, Integer> offsets = new HashMap<OFTableName, Integer>(); | |||
private int checkSumAdjustmentOffset = 0; | |||
private int locaOffset = 0; | |||
@@ -67,8 +67,8 @@ public class TTFSubSetFile extends TTFFile { | |||
} | |||
/** The dir tab entries in the new subset font. */ | |||
private Map<TTFTableName, TTFDirTabEntry> newDirTabs | |||
= new HashMap<TTFTableName, TTFDirTabEntry>(); | |||
private Map<OFTableName, OFDirTabEntry> newDirTabs | |||
= new HashMap<OFTableName, OFDirTabEntry>(); | |||
private int determineTableCount() { | |||
int numTables = 4; //4 req'd tables: head,hhea,hmtx,maxp | |||
@@ -117,29 +117,29 @@ public class TTFSubSetFile extends TTFFile { | |||
writeUShort((numTables * 16) - searchRange); | |||
realSize += 2; | |||
// Create space for the table entries (these must be in ASCII alphabetical order[A-Z] then[a-z]) | |||
writeTableName(TTFTableName.OS2); | |||
writeTableName(OFTableName.OS2); | |||
if (hasCvt()) { | |||
writeTableName(TTFTableName.CVT); | |||
writeTableName(OFTableName.CVT); | |||
} | |||
if (hasFpgm()) { | |||
writeTableName(TTFTableName.FPGM); | |||
writeTableName(OFTableName.FPGM); | |||
} | |||
writeTableName(TTFTableName.GLYF); | |||
writeTableName(TTFTableName.HEAD); | |||
writeTableName(TTFTableName.HHEA); | |||
writeTableName(TTFTableName.HMTX); | |||
writeTableName(TTFTableName.LOCA); | |||
writeTableName(TTFTableName.MAXP); | |||
writeTableName(TTFTableName.NAME); | |||
writeTableName(TTFTableName.POST); | |||
writeTableName(OFTableName.GLYF); | |||
writeTableName(OFTableName.HEAD); | |||
writeTableName(OFTableName.HHEA); | |||
writeTableName(OFTableName.HMTX); | |||
writeTableName(OFTableName.LOCA); | |||
writeTableName(OFTableName.MAXP); | |||
writeTableName(OFTableName.NAME); | |||
writeTableName(OFTableName.POST); | |||
if (hasPrep()) { | |||
writeTableName(TTFTableName.PREP); | |||
writeTableName(OFTableName.PREP); | |||
} | |||
newDirTabs.put(TTFTableName.TABLE_DIRECTORY, new TTFDirTabEntry(0, currentPos)); | |||
newDirTabs.put(OFTableName.TABLE_DIRECTORY, new OFDirTabEntry(0, currentPos)); | |||
} | |||
private void writeTableName(TTFTableName tableName) { | |||
private void writeTableName(OFTableName tableName) { | |||
writeString(tableName.getName()); | |||
offsets.put(tableName, currentPos); | |||
currentPos += 12; | |||
@@ -148,15 +148,15 @@ public class TTFSubSetFile extends TTFFile { | |||
private boolean hasCvt() { | |||
return dirTabs.containsKey(TTFTableName.CVT); | |||
return dirTabs.containsKey(OFTableName.CVT); | |||
} | |||
private boolean hasFpgm() { | |||
return dirTabs.containsKey(TTFTableName.FPGM); | |||
return dirTabs.containsKey(OFTableName.FPGM); | |||
} | |||
private boolean hasPrep() { | |||
return dirTabs.containsKey(TTFTableName.PREP); | |||
return dirTabs.containsKey(OFTableName.PREP); | |||
} | |||
/** | |||
@@ -165,15 +165,15 @@ public class TTFSubSetFile extends TTFFile { | |||
private void createLoca(int size) throws IOException { | |||
pad4(); | |||
locaOffset = currentPos; | |||
int dirTableOffset = offsets.get(TTFTableName.LOCA); | |||
int dirTableOffset = offsets.get(OFTableName.LOCA); | |||
writeULong(dirTableOffset + 4, currentPos); | |||
writeULong(dirTableOffset + 8, size * 4 + 4); | |||
currentPos += size * 4 + 4; | |||
realSize += size * 4 + 4; | |||
} | |||
private boolean copyTable(FontFileReader in, TTFTableName tableName) throws IOException { | |||
TTFDirTabEntry entry = dirTabs.get(tableName); | |||
private boolean copyTable(FontFileReader in, OFTableName tableName) throws IOException { | |||
OFDirTabEntry entry = dirTabs.get(tableName); | |||
if (entry != null) { | |||
pad4(); | |||
seekTab(in, tableName, 0); | |||
@@ -193,28 +193,28 @@ public class TTFSubSetFile extends TTFFile { | |||
* Copy the cvt table as is from original font to subset font | |||
*/ | |||
private boolean createCvt(FontFileReader in) throws IOException { | |||
return copyTable(in, TTFTableName.CVT); | |||
return copyTable(in, OFTableName.CVT); | |||
} | |||
/** | |||
* Copy the fpgm table as is from original font to subset font | |||
*/ | |||
private boolean createFpgm(FontFileReader in) throws IOException { | |||
return copyTable(in, TTFTableName.FPGM); | |||
return copyTable(in, OFTableName.FPGM); | |||
} | |||
/** | |||
* Copy the name table as is from the original. | |||
*/ | |||
private boolean createName(FontFileReader in) throws IOException { | |||
return copyTable(in, TTFTableName.NAME); | |||
return copyTable(in, OFTableName.NAME); | |||
} | |||
/** | |||
* Copy the OS/2 table as is from the original. | |||
*/ | |||
private boolean createOS2(FontFileReader in) throws IOException { | |||
return copyTable(in, TTFTableName.OS2); | |||
return copyTable(in, OFTableName.OS2); | |||
} | |||
/** | |||
@@ -222,8 +222,8 @@ public class TTFSubSetFile extends TTFFile { | |||
* and set num glyphs to size | |||
*/ | |||
private void createMaxp(FontFileReader in, int size) throws IOException { | |||
TTFTableName maxp = TTFTableName.MAXP; | |||
TTFDirTabEntry entry = dirTabs.get(maxp); | |||
OFTableName maxp = OFTableName.MAXP; | |||
OFDirTabEntry entry = dirTabs.get(maxp); | |||
if (entry != null) { | |||
pad4(); | |||
seekTab(in, maxp, 0); | |||
@@ -240,8 +240,8 @@ public class TTFSubSetFile extends TTFFile { | |||
} | |||
private void createPost(FontFileReader in) throws IOException { | |||
TTFTableName post = TTFTableName.POST; | |||
TTFDirTabEntry entry = dirTabs.get(post); | |||
OFTableName post = OFTableName.POST; | |||
OFDirTabEntry entry = dirTabs.get(post); | |||
if (entry != null) { | |||
pad4(); | |||
seekTab(in, post, 0); | |||
@@ -266,7 +266,7 @@ public class TTFSubSetFile extends TTFFile { | |||
* Copy the prep table as is from original font to subset font | |||
*/ | |||
private boolean createPrep(FontFileReader in) throws IOException { | |||
return copyTable(in, TTFTableName.PREP); | |||
return copyTable(in, OFTableName.PREP); | |||
} | |||
@@ -275,15 +275,15 @@ public class TTFSubSetFile extends TTFFile { | |||
* and fill in size of hmtx table | |||
*/ | |||
private void createHhea(FontFileReader in, int size) throws IOException { | |||
TTFDirTabEntry entry = dirTabs.get(TTFTableName.HHEA); | |||
OFDirTabEntry entry = dirTabs.get(OFTableName.HHEA); | |||
if (entry != null) { | |||
pad4(); | |||
seekTab(in, TTFTableName.HHEA, 0); | |||
seekTab(in, OFTableName.HHEA, 0); | |||
System.arraycopy(in.getBytes((int) entry.getOffset(), (int) entry.getLength()), 0, | |||
output, currentPos, (int) entry.getLength()); | |||
writeUShort((int) entry.getLength() + currentPos - 2, size); | |||
updateCheckSum(currentPos, (int) entry.getLength(), TTFTableName.HHEA); | |||
updateCheckSum(currentPos, (int) entry.getLength(), OFTableName.HHEA); | |||
currentPos += (int) entry.getLength(); | |||
realSize += (int) entry.getLength(); | |||
} else { | |||
@@ -299,8 +299,8 @@ public class TTFSubSetFile extends TTFFile { | |||
* in checkSumAdjustmentOffset | |||
*/ | |||
private void createHead(FontFileReader in) throws IOException { | |||
TTFTableName head = TTFTableName.HEAD; | |||
TTFDirTabEntry entry = dirTabs.get(head); | |||
OFTableName head = OFTableName.HEAD; | |||
OFDirTabEntry entry = dirTabs.get(head); | |||
if (entry != null) { | |||
pad4(); | |||
seekTab(in, head, 0); | |||
@@ -329,8 +329,8 @@ public class TTFSubSetFile extends TTFFile { | |||
*/ | |||
private void createGlyf(FontFileReader in, | |||
Map<Integer, Integer> glyphs) throws IOException { | |||
TTFTableName glyf = TTFTableName.GLYF; | |||
TTFDirTabEntry entry = dirTabs.get(glyf); | |||
OFTableName glyf = OFTableName.GLYF; | |||
OFDirTabEntry entry = dirTabs.get(glyf); | |||
int size = 0; | |||
int startPos = 0; | |||
int endOffset = 0; // Store this as the last loca | |||
@@ -393,10 +393,10 @@ public class TTFSubSetFile extends TTFFile { | |||
writeULong(locaOffset + glyphs.size() * 4, endOffset); | |||
int locaSize = glyphs.size() * 4 + 4; | |||
int checksum = getCheckSum(output, locaOffset, locaSize); | |||
writeULong(offsets.get(TTFTableName.LOCA), checksum); | |||
writeULong(offsets.get(OFTableName.LOCA), checksum); | |||
int padSize = (locaOffset + locaSize) % 4; | |||
newDirTabs.put(TTFTableName.LOCA, | |||
new TTFDirTabEntry(locaOffset, locaSize + padSize)); | |||
newDirTabs.put(OFTableName.LOCA, | |||
new OFDirTabEntry(locaOffset, locaSize + padSize)); | |||
} else { | |||
throw new IOException("Can't find glyf table"); | |||
} | |||
@@ -420,8 +420,8 @@ public class TTFSubSetFile extends TTFFile { | |||
*/ | |||
private void createHmtx(FontFileReader in, | |||
Map<Integer, Integer> glyphs) throws IOException { | |||
TTFTableName hmtx = TTFTableName.HMTX; | |||
TTFDirTabEntry entry = dirTabs.get(hmtx); | |||
OFTableName hmtx = OFTableName.HMTX; | |||
OFDirTabEntry entry = dirTabs.get(hmtx); | |||
int longHorMetricSize = glyphs.size() * 2; | |||
int leftSideBearingSize = glyphs.size() * 2; | |||
@@ -457,11 +457,11 @@ public class TTFSubSetFile extends TTFFile { | |||
* new index as (Integer) value) | |||
* @throws IOException in case of an I/O problem | |||
*/ | |||
public void readFont(FontFileReader in, String name, | |||
public void readFont(FontFileReader in, String name, String header, | |||
Map<Integer, Integer> glyphs) throws IOException { | |||
fontFile = in; | |||
//Check if TrueType collection, and that the name exists in the collection | |||
if (!checkTTC(name)) { | |||
if (!checkTTC(header, name)) { | |||
throw new IOException("Failed to read font"); | |||
} | |||
@@ -533,7 +533,7 @@ public class TTFSubSetFile extends TTFFile { | |||
glyphOffsets[i + 1] - glyphOffsets[i]); | |||
} | |||
// Stream the last glyph | |||
TTFDirTabEntry glyf = newDirTabs.get(TTFTableName.GLYF); | |||
OFDirTabEntry glyf = newDirTabs.get(OFTableName.GLYF); | |||
long lastGlyphLength = glyf.getLength() | |||
- (glyphOffsets[glyphOffsets.length - 1] - glyf.getOffset()); | |||
glyphOut.streamGlyph(output, glyphOffsets[glyphOffsets.length - 1], | |||
@@ -543,14 +543,14 @@ public class TTFSubSetFile extends TTFFile { | |||
@Override | |||
public void stream(TTFOutputStream ttfOut) throws IOException { | |||
SortedSet<Map.Entry<TTFTableName, TTFDirTabEntry>> sortedDirTabs | |||
SortedSet<Map.Entry<OFTableName, OFDirTabEntry>> sortedDirTabs | |||
= sortDirTabMap(newDirTabs); | |||
TTFTableOutputStream tableOut = ttfOut.getTableOutputStream(); | |||
TTFGlyphOutputStream glyphOut = ttfOut.getGlyphOutputStream(); | |||
ttfOut.startFontStream(); | |||
for (Map.Entry<TTFTableName, TTFDirTabEntry> entry : sortedDirTabs) { | |||
if (entry.getKey().equals(TTFTableName.GLYF)) { | |||
for (Map.Entry<OFTableName, OFDirTabEntry> entry : sortedDirTabs) { | |||
if (entry.getKey().equals(OFTableName.GLYF)) { | |||
handleGlyphSubset(glyphOut); | |||
} else { | |||
tableOut.streamTable(output, (int) entry.getValue().getOffset(), | |||
@@ -562,7 +562,7 @@ public class TTFSubSetFile extends TTFFile { | |||
private void scanGlyphs(FontFileReader in, Map<Integer, Integer> subsetGlyphs) | |||
throws IOException { | |||
TTFDirTabEntry glyfTableInfo = dirTabs.get(TTFTableName.GLYF); | |||
OFDirTabEntry glyfTableInfo = dirTabs.get(OFTableName.GLYF); | |||
if (glyfTableInfo == null) { | |||
throw new IOException("Glyf table could not be found"); | |||
} | |||
@@ -663,11 +663,11 @@ public class TTFSubSetFile extends TTFFile { | |||
} | |||
private void updateCheckSum(int tableStart, int tableSize, TTFTableName tableName) { | |||
private void updateCheckSum(int tableStart, int tableSize, OFTableName tableName) { | |||
int checksum = getCheckSum(output, tableStart, tableSize); | |||
int offset = offsets.get(tableName); | |||
int padSize = getPadSize(tableStart + tableSize); | |||
newDirTabs.put(tableName, new TTFDirTabEntry(tableStart, tableSize + padSize)); | |||
newDirTabs.put(tableName, new OFDirTabEntry(tableStart, tableSize + padSize)); | |||
writeULong(offset, checksum); | |||
writeULong(offset + 4, tableStart); | |||
writeULong(offset + 8, tableSize); |
@@ -319,7 +319,7 @@ public class AFMFile { | |||
*/ | |||
public void addCharMetrics(AFMCharMetrics metrics) { | |||
String name = metrics.getCharName(); | |||
if (metrics.getUnicodeSequence() == null) { | |||
if (metrics.getUnicodeSequence() == null && name.equals(".notdef")) { | |||
//Ignore as no Unicode assignment is possible | |||
return; | |||
} |
@@ -28,6 +28,8 @@ import java.util.regex.Pattern; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.xmlgraphics.fonts.Glyphs; | |||
import org.apache.fop.fonts.NamedCharacter; | |||
import org.apache.fop.fonts.type1.AFMParser.ValueHandler; | |||
@@ -102,9 +104,10 @@ abstract class CharMetricsHandler { | |||
AFMCharMetrics chm = defaultHandler.parse(line, stack, afmFileName); | |||
NamedCharacter namedChar = chm.getCharacter(); | |||
if (namedChar != null) { | |||
int codePoint = AdobeStandardEncoding.getAdobeCodePoint(namedChar.getName()); | |||
if (chm.getCharCode() != codePoint) { | |||
LOG.info(afmFileName + ": named character '" + namedChar.getName() + "'" | |||
String charName = namedChar.getName(); | |||
int codePoint = AdobeStandardEncoding.getAdobeCodePoint(charName); | |||
if (chm.getCharCode() != codePoint && !Glyphs.NOTDEF.equals(charName)) { | |||
LOG.info(afmFileName + ": named character '" + charName + "'" | |||
+ " has an incorrect code point: " + chm.getCharCode() | |||
+ ". Changed to " + codePoint); | |||
chm.setCharCode(codePoint); |
@@ -173,7 +173,21 @@ public class Type1FontLoader extends FontLoader { | |||
addUnencodedBasedOnAFM(afm); | |||
} | |||
} else { | |||
if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { | |||
if (pfm.getCharSet() == 2 && !pfm.getCharSetName().equals("Symbol")) { | |||
int[] table = new int[256]; | |||
String[] charNameMap = new String[256]; | |||
int j = 0; | |||
for (int i = pfm.getFirstChar(); i < pfm.getLastChar(); i++) { | |||
if (j < table.length) { | |||
table[j] = i; | |||
table[j + 1] = i; | |||
j += 2; | |||
} | |||
charNameMap[i] = String.format("x%03o", i); | |||
} | |||
CodePointMapping mapping = new CodePointMapping("custom", table, charNameMap); | |||
singleFont.setEncoding(mapping); | |||
} else if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { | |||
singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); | |||
} else { | |||
log.warn("The PFM reports an unsupported encoding (" | |||
@@ -400,10 +414,7 @@ public class Type1FontLoader extends FontLoader { | |||
List<AFMCharMetrics> chars = afm.getCharMetrics(); | |||
for (AFMCharMetrics charMetrics : chars) { | |||
if (charMetrics.getCharCode() >= 0) { | |||
String u = charMetrics.getUnicodeSequence(); | |||
if (u != null && u.length() == 1) { | |||
mappingCount++; | |||
} | |||
mappingCount++; | |||
} | |||
} | |||
// ...and now build the table. | |||
@@ -416,6 +427,10 @@ public class Type1FontLoader extends FontLoader { | |||
String unicodes = charMetrics.getUnicodeSequence(); | |||
if (unicodes == null) { | |||
log.info("No Unicode mapping for glyph: " + charMetrics); | |||
table[idx] = charMetrics.getCharCode(); | |||
idx++; | |||
table[idx] = charMetrics.getCharCode(); | |||
idx++; | |||
} else if (unicodes.length() == 1) { | |||
table[idx] = charMetrics.getCharCode(); | |||
idx++; |
@@ -65,9 +65,6 @@ public abstract class AbstractBaseLayoutManager | |||
public AbstractBaseLayoutManager(FObj fo) { | |||
this.fobj = fo; | |||
setGeneratesReferenceArea(fo.generatesReferenceAreas()); | |||
if (getGeneratesReferenceArea()) { | |||
setGeneratesBlockArea(true); | |||
} | |||
} | |||
// --------- Property Resolution related functions --------- // |
@@ -342,6 +342,34 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im | |||
&& isFinished()); | |||
} | |||
public boolean hasLineAreaDescendant() { | |||
if (childLMs == null || childLMs.isEmpty()) { | |||
return false; | |||
} else { | |||
for (LayoutManager childLM : childLMs) { | |||
if (childLM.hasLineAreaDescendant()) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
public int getBaselineOffset() { | |||
if (childLMs != null) { | |||
for (LayoutManager childLM : childLMs) { | |||
if (childLM.hasLineAreaDescendant()) { | |||
return childLM.getBaselineOffset(); | |||
} | |||
} | |||
} | |||
throw newNoLineAreaDescendantException(); | |||
} | |||
protected IllegalStateException newNoLineAreaDescendantException() { | |||
return new IllegalStateException("getBaselineOffset called on an object that has no line-area descendant"); | |||
} | |||
/** | |||
* Transfers foreign attributes from the formatting object to the area. | |||
* @param targetArea the area to set the attributes on |
@@ -33,11 +33,11 @@ public final class AreaAdditionUtil { | |||
/** | |||
* Creates the child areas for the given layout manager. | |||
* @param bslm the BlockStackingLayoutManager instance for which "addAreas" is performed. | |||
* @param parentLM the parent layout manager | |||
* @param parentIter the position iterator | |||
* @param layoutContext the layout context | |||
*/ | |||
public static void addAreas(BlockStackingLayoutManager bslm, | |||
public static void addAreas(AbstractLayoutManager parentLM, | |||
PositionIterator parentIter, LayoutContext layoutContext) { | |||
LayoutManager childLM; | |||
LayoutContext lc = LayoutContext.offspringOf(layoutContext); | |||
@@ -46,8 +46,8 @@ public final class AreaAdditionUtil { | |||
Position firstPos = null; | |||
Position lastPos = null; | |||
if (bslm != null) { | |||
bslm.addId(); | |||
if (parentLM != null) { | |||
parentLM.addId(); | |||
} | |||
// "unwrap" the NonLeafPositions stored in parentIter | |||
@@ -86,11 +86,11 @@ public final class AreaAdditionUtil { | |||
//doesn't give us that info. | |||
} | |||
if (bslm != null) { | |||
bslm.registerMarkers( | |||
if (parentLM != null) { | |||
parentLM.registerMarkers( | |||
true, | |||
bslm.isFirst(firstPos), | |||
bslm.isLast(lastPos)); | |||
parentLM.isFirst(firstPos), | |||
parentLM.isLast(lastPos)); | |||
} | |||
PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); | |||
@@ -113,11 +113,11 @@ public final class AreaAdditionUtil { | |||
childLM.addAreas(childPosIter, lc); | |||
} | |||
if (bslm != null) { | |||
bslm.registerMarkers( | |||
if (parentLM != null) { | |||
parentLM.registerMarkers( | |||
false, | |||
bslm.isFirst(firstPos), | |||
bslm.isLast(lastPos)); | |||
parentLM.isFirst(firstPos), | |||
parentLM.isLast(lastPos)); | |||
} | |||
@@ -37,6 +37,7 @@ import org.apache.fop.datatypes.FODimension; | |||
import org.apache.fop.datatypes.Length; | |||
import org.apache.fop.fo.flow.BlockContainer; | |||
import org.apache.fop.fo.properties.CommonAbsolutePosition; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.traits.MinOptMax; | |||
import org.apache.fop.traits.SpaceVal; | |||
@@ -44,8 +45,8 @@ import org.apache.fop.traits.SpaceVal; | |||
/** | |||
* LayoutManager for a block-container FO. | |||
*/ | |||
public class BlockContainerLayoutManager extends BlockStackingLayoutManager implements | |||
ConditionalElementListener, BreakOpportunity { | |||
public class BlockContainerLayoutManager extends SpacedBorderedPaddedBlockLayoutManager | |||
implements BreakOpportunity { | |||
/** | |||
* logging instance | |||
@@ -79,13 +80,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl | |||
private MinOptMax foBlockSpaceBefore; | |||
private MinOptMax foBlockSpaceAfter; | |||
private boolean discardBorderBefore; | |||
private boolean discardBorderAfter; | |||
private boolean discardPaddingBefore; | |||
private boolean discardPaddingAfter; | |||
private MinOptMax effSpaceBefore; | |||
private MinOptMax effSpaceAfter; | |||
private int horizontalOverflow; | |||
private double contentRectOffsetX = 0; | |||
private double contentRectOffsetY = 0; | |||
@@ -96,6 +90,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl | |||
*/ | |||
public BlockContainerLayoutManager(BlockContainer node) { | |||
super(node); | |||
setGeneratesBlockArea(true); | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -128,6 +123,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl | |||
.spaceAfter.getSpace().getOptimum(this).getLength().getValue(this); | |||
} | |||
@Override | |||
protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() { | |||
return getBlockContainerFO().getCommonBorderPaddingBackground(); | |||
} | |||
private void resetSpaces() { | |||
this.discardBorderBefore = false; | |||
this.discardBorderAfter = false; | |||
@@ -867,6 +867,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl | |||
transferForeignAttributes(viewportBlockArea); | |||
TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId()); | |||
TraitSetter.setLayer(viewportBlockArea, getBlockContainerFO().getLayer()); | |||
TraitSetter.addBorders(viewportBlockArea, | |||
getBlockContainerFO().getCommonBorderPaddingBackground(), | |||
discardBorderBefore, discardBorderAfter, false, false, this); | |||
@@ -993,51 +994,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl | |||
return true; | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifySpace(RelSide side, MinOptMax effectiveLength) { | |||
if (RelSide.BEFORE == side) { | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceBefore + "-> " + effectiveLength); | |||
} | |||
this.effSpaceBefore = effectiveLength; | |||
} else { | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceAfter + "-> " + effectiveLength); | |||
} | |||
this.effSpaceAfter = effectiveLength; | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifyBorder(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardBorderBefore = true; | |||
} else { | |||
this.discardBorderAfter = true; | |||
} | |||
} | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Border " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifyPadding(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardPaddingBefore = true; | |||
} else { | |||
this.discardPaddingAfter = true; | |||
} | |||
} | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Padding " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean handleOverflow(int milliPoints) { | |||
if (milliPoints > this.horizontalOverflow) { |
@@ -32,6 +32,7 @@ import org.apache.fop.area.Block; | |||
import org.apache.fop.area.LineArea; | |||
import org.apache.fop.datatypes.Length; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontInfo; | |||
@@ -44,8 +45,8 @@ import org.apache.fop.traits.SpaceVal; | |||
/** | |||
* LayoutManager for a block FO. | |||
*/ | |||
public class BlockLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener, | |||
BreakOpportunity { | |||
public class BlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager | |||
implements BreakOpportunity { | |||
/** logging instance */ | |||
private static Log log = LogFactory.getLog(BlockLayoutManager.class); | |||
@@ -60,13 +61,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
private int follow = 2000; | |||
//private int middleShift = 0; | |||
private boolean discardBorderBefore; | |||
private boolean discardBorderAfter; | |||
private boolean discardPaddingBefore; | |||
private boolean discardPaddingAfter; | |||
private MinOptMax effSpaceBefore; | |||
private MinOptMax effSpaceAfter; | |||
/** | |||
* Creates a new BlockLayoutManager. | |||
* @param inBlock the block FO object to create the layout manager for. | |||
@@ -100,6 +94,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
.getOptimum(this).getLength().getValue(this); | |||
} | |||
@Override | |||
protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() { | |||
return getBlockFO().getCommonBorderPaddingBackground(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public List getNextKnuthElements(LayoutContext context, int alignment) { | |||
@@ -360,7 +359,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
curBlockArea.setIPD(super.getContentAreaIPD()); | |||
curBlockArea.setBidiLevel(getBlockFO().getBidiLevel()); | |||
curBlockArea.setBidiLevel(getBlockFO().getBidiLevelRecursive()); | |||
TraitSetter.addBreaks(curBlockArea, | |||
getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter()); | |||
@@ -381,6 +380,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
getBlockFO().getCommonBorderPaddingBackground(), | |||
startIndent, endIndent, | |||
this); | |||
TraitSetter.setLayer(curBlockArea, getBlockFO().getLayer()); | |||
curBlockArea.setLocale(getBlockFO().getCommonHyphenation().getLocale()); | |||
curBlockArea.setLocation(FONode.getLocatorString(getBlockFO().getLocator())); | |||
@@ -456,51 +456,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
return true; | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifySpace(RelSide side, MinOptMax effectiveLength) { | |||
if (RelSide.BEFORE == side) { | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceBefore + "-> " + effectiveLength); | |||
} | |||
this.effSpaceBefore = effectiveLength; | |||
} else { | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceAfter + "-> " + effectiveLength); | |||
} | |||
this.effSpaceAfter = effectiveLength; | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifyBorder(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardBorderBefore = true; | |||
} else { | |||
this.discardBorderAfter = true; | |||
} | |||
} | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Border " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void notifyPadding(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardPaddingBefore = true; | |||
} else { | |||
this.discardPaddingAfter = true; | |||
} | |||
} | |||
if (log.isDebugEnabled()) { | |||
log.debug(this + ": Padding " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public boolean isRestartable() { |
@@ -36,6 +36,7 @@ import org.apache.fop.fo.properties.BreakPropertySet; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fo.properties.SpaceProperty; | |||
import org.apache.fop.layoutmgr.inline.InlineContainerLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.InlineLayoutManager; | |||
import org.apache.fop.traits.MinOptMax; | |||
import org.apache.fop.util.ListUtil; | |||
@@ -1246,6 +1247,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
public boolean handleOverflow(int milliPoints) { | |||
if (getParent() instanceof BlockStackingLayoutManager) { | |||
return ((BlockStackingLayoutManager) getParent()).handleOverflow(milliPoints); | |||
} else if (getParent() instanceof InlineContainerLayoutManager) { | |||
return ((InlineContainerLayoutManager) getParent()).handleOverflow(milliPoints); | |||
} | |||
return false; | |||
} |
@@ -242,8 +242,14 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan | |||
pv.setPage(pageArea); | |||
RegionViewport rv = new RegionViewport(referenceRect); | |||
rv.setIPD(referenceRect.width); | |||
rv.setBPD(referenceRect.height); | |||
if (pageSeq.getReferenceOrientation() % 180 == 0) { | |||
rv.setIPD(referenceRect.width); | |||
rv.setBPD(referenceRect.height); | |||
} else { | |||
rv.setIPD(referenceRect.height); | |||
rv.setBPD(referenceRect.width); | |||
} | |||
rv.setClip(true); | |||
BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY, |
@@ -58,6 +58,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager | |||
*/ | |||
public FlowLayoutManager(PageSequenceLayoutManager pslm, Flow node) { | |||
super(node); | |||
setGeneratesBlockArea(true); | |||
setParent(pslm); | |||
} | |||
@@ -177,6 +177,25 @@ public interface LayoutManager extends PercentBaseContext { | |||
*/ | |||
List getChangedKnuthElements(List oldList, int alignment); | |||
/** | |||
* Whether the FO handled by this layout manager has a descendant (including itself) | |||
* that will generate a line-area. | |||
* | |||
* @return {@code true} if a descendant line-area will be generated, {@code false} otherwise | |||
*/ | |||
boolean hasLineAreaDescendant(); | |||
/** | |||
* Returns the position of the dominant-baseline of this FO's first descendant | |||
* line-area. <p>The behavior of this method is undefined if this FO has no descendant | |||
* line-area, and an exception may be thrown. See {@link #hasLineAreaDescendant()}</p> | |||
* | |||
* @return this FO's space-before plus the distance from the before-edge of its | |||
* allocation-rectangle to the dominant-baseline of the first line-area descendant | |||
* @see #hasLineAreaDescendant() | |||
*/ | |||
int getBaselineOffset(); | |||
/** | |||
* Returns the IPD of the content area | |||
* @return the IPD of the content area |
@@ -73,7 +73,7 @@ import org.apache.fop.layoutmgr.inline.CharacterLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.ContentLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.FootnoteLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.ICLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.InlineContainerLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.InlineLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.InstreamForeignObjectLM; | |||
import org.apache.fop.layoutmgr.inline.LeaderLayoutManager; | |||
@@ -257,9 +257,9 @@ public class LayoutManagerMapping implements LayoutManagerMaker { | |||
/** a layout manager maker */ | |||
public static class InlineLayoutManagerMaker extends Maker { | |||
/** {@inheritDoc} */ | |||
public void make(FONode node, List lms) { | |||
lms.add(new InlineLayoutManager((InlineLevel) node)); | |||
} | |||
public void make(FONode node, List lms) { | |||
lms.add(new InlineLayoutManager((InlineLevel) node)); | |||
} | |||
} | |||
/** a layout manager maker */ | |||
@@ -274,9 +274,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { | |||
public static class InlineContainerLayoutManagerMaker extends Maker { | |||
/** {@inheritDoc} */ | |||
public void make(FONode node, List lms) { | |||
ArrayList childList = new ArrayList(); | |||
super.make(node, childList); | |||
lms.add(new ICLayoutManager((InlineContainer) node, childList)); | |||
lms.add(new InlineContainerLayoutManager((InlineContainer) node)); | |||
} | |||
} | |||
@@ -140,7 +140,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
*/ | |||
protected class KnuthPageNode extends KnuthNode { | |||
/** Additional length due to footnotes. */ | |||
/** Additional length due to already inserted footnotes. */ | |||
public int insertedFootnotes; | |||
/** Total length of the footnotes. */ | |||
public int totalFootnotes; | |||
/** Index of the last inserted footnote. */ | |||
@@ -152,7 +155,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
public KnuthPageNode(int position, | |||
int line, int fitness, | |||
int totalWidth, int totalStretch, int totalShrink, | |||
int totalFootnotes, int footnoteListIndex, int footnoteElementIndex, | |||
int insertedFootnotes, int totalFootnotes, | |||
int footnoteListIndex, int footnoteElementIndex, | |||
double adjustRatio, int availableShrink, int availableStretch, | |||
int difference, double totalDemerits, KnuthNode previous) { | |||
super(position, line, fitness, | |||
@@ -160,6 +164,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
adjustRatio, availableShrink, availableStretch, | |||
difference, totalDemerits, previous); | |||
this.totalFootnotes = totalFootnotes; | |||
this.insertedFootnotes = insertedFootnotes; | |||
this.footnoteListIndex = footnoteListIndex; | |||
this.footnoteElementIndex = footnoteElementIndex; | |||
} | |||
@@ -172,7 +177,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
*/ | |||
protected class BestPageRecords extends BestRecords { | |||
private int[] bestFootnotesLength = new int[4]; | |||
private int[] bestInsertedFootnotesLength = new int[4]; | |||
private int[] bestTotalFootnotesLength = new int[4]; | |||
private int[] bestFootnoteListIndex = new int[4]; | |||
private int[] bestFootnoteElementIndex = new int[4]; | |||
@@ -182,13 +188,18 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
super.addRecord(demerits, node, adjust, | |||
availableShrink, availableStretch, | |||
difference, fitness); | |||
bestFootnotesLength[fitness] = insertedFootnotesLength; | |||
bestInsertedFootnotesLength[fitness] = insertedFootnotesLength; | |||
bestTotalFootnotesLength[fitness] = totalFootnotesLength; | |||
bestFootnoteListIndex[fitness] = footnoteListIndex; | |||
bestFootnoteElementIndex[fitness] = footnoteElementIndex; | |||
} | |||
public int getFootnotesLength(int fitness) { | |||
return bestFootnotesLength[fitness]; | |||
public int getInsertedFootnotesLength(int fitness) { | |||
return bestInsertedFootnotesLength[fitness]; | |||
} | |||
public int getTotalFootnotesLength(int fitness) { | |||
return bestTotalFootnotesLength[fitness]; | |||
} | |||
public int getFootnoteListIndex(int fitness) { | |||
@@ -287,7 +298,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
int difference, double totalDemerits, KnuthNode previous) { | |||
return new KnuthPageNode(position, line, fitness, | |||
totalWidth, totalStretch, totalShrink, | |||
insertedFootnotesLength, footnoteListIndex, footnoteElementIndex, | |||
insertedFootnotesLength, totalFootnotesLength, | |||
footnoteListIndex, footnoteElementIndex, | |||
adjustRatio, availableShrink, availableStretch, | |||
difference, totalDemerits, previous); | |||
} | |||
@@ -298,7 +310,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
int totalWidth, int totalStretch, int totalShrink) { | |||
return new KnuthPageNode(position, line, fitness, | |||
totalWidth, totalStretch, totalShrink, | |||
((BestPageRecords) best).getFootnotesLength(fitness), | |||
((BestPageRecords) best).getInsertedFootnotesLength(fitness), | |||
((BestPageRecords) best).getTotalFootnotesLength(fitness), | |||
((BestPageRecords) best).getFootnoteListIndex(fitness), | |||
((BestPageRecords) best).getFootnoteElementIndex(fitness), | |||
best.getAdjust(fitness), best.getAvailableShrink(fitness), | |||
@@ -405,6 +418,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
resetFootnotes(((KnuthBlockBox) resetElement).getElementLists()); | |||
} | |||
} | |||
assert restartingNode instanceof KnuthPageNode; | |||
KnuthPageNode restartingPageNode = (KnuthPageNode) restartingNode; | |||
footnoteElementIndex = restartingPageNode.footnoteElementIndex; | |||
footnoteListIndex = restartingPageNode.footnoteListIndex; | |||
totalFootnotesLength = restartingPageNode.totalFootnotes; | |||
insertedFootnotesLength = restartingPageNode.insertedFootnotes; | |||
} | |||
return returnValue; | |||
} | |||
@@ -413,13 +432,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
for (int i = 0; i < elementLists.size(); i++) { | |||
ListUtil.removeLast(footnotesList); | |||
ListUtil.removeLast(lengthList); | |||
// update totalFootnotesLength | |||
if (!lengthList.isEmpty()) { | |||
totalFootnotesLength = ListUtil.getLast(lengthList); | |||
} else { | |||
totalFootnotesLength = 0; | |||
} | |||
} | |||
// update footnotesPending; | |||
if (footnotesList.size() == 0) { | |||
@@ -502,7 +514,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
} | |||
if (footnotesPending) { | |||
// compute the total length of the footnotes not yet inserted | |||
int allFootnotes = totalFootnotesLength - pageNode.totalFootnotes; | |||
int allFootnotes = totalFootnotesLength - pageNode.insertedFootnotes; | |||
if (allFootnotes > 0) { | |||
// this page contains some footnote citations | |||
// add the footnote separator width | |||
@@ -511,7 +523,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// there is enough space to insert all footnotes: | |||
// add the whole allFootnotes length | |||
actualWidth += allFootnotes; | |||
insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; | |||
insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes; | |||
footnoteListIndex = footnotesList.size() - 1; | |||
footnoteElementIndex | |||
= getFootnoteList(footnoteListIndex).size() - 1; | |||
@@ -528,7 +540,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// this is the first feasible break; in this case it is allowed | |||
// to break and defer, if necessary, old and new footnotes | |||
actualWidth += footnoteSplit; | |||
insertedFootnotesLength = pageNode.totalFootnotes + footnoteSplit; | |||
insertedFootnotesLength = pageNode.insertedFootnotes + footnoteSplit; | |||
// footnoteListIndex has been set in getFootnoteSplit() | |||
// footnoteElementIndex has been set in getFootnoteSplit() | |||
} else { | |||
@@ -538,7 +550,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// that cannot be broken: | |||
// add the whole allFootnotes length, so this breakpoint will be discarded | |||
actualWidth += allFootnotes; | |||
insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; | |||
insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes; | |||
footnoteListIndex = footnotesList.size() - 1; | |||
footnoteElementIndex | |||
= getFootnoteList(footnoteListIndex).size() - 1; | |||
@@ -569,7 +581,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
private boolean canDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) { | |||
return (noBreakBetween(node.position, contentElementIndex) | |||
&& deferredFootnotes(node.footnoteListIndex, | |||
node.footnoteElementIndex, node.totalFootnotes)); | |||
node.footnoteElementIndex, node.insertedFootnotes)); | |||
} | |||
/** | |||
@@ -649,7 +661,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
boolean canDeferOldFootnotes) { | |||
return getFootnoteSplit(activeNode.footnoteListIndex, | |||
activeNode.footnoteElementIndex, | |||
activeNode.totalFootnotes, | |||
activeNode.insertedFootnotes, | |||
availableLength, canDeferOldFootnotes); | |||
} | |||
@@ -714,10 +726,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
int prevIndex = -1; | |||
int index = -1; | |||
while (!(somethingAdded && splitLength > availableLength)) { | |||
if (!somethingAdded) { | |||
somethingAdded = true; | |||
} else { | |||
while (splitLength <= availableLength) { | |||
if (somethingAdded) { | |||
prevSplitLength = splitLength; | |||
prevIndex = index; | |||
} | |||
@@ -733,6 +743,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// element is a box | |||
splitLength += element.getWidth(); | |||
boxPreceding = true; | |||
if (splitLength > prevSplitLength) { | |||
// and it is non-empty | |||
somethingAdded = true; | |||
} | |||
} else if (element.isGlue()) { | |||
// element is a glue | |||
if (boxPreceding) { | |||
@@ -749,6 +763,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
index = noteListIterator.previousIndex(); | |||
break; | |||
} | |||
boxPreceding = false; | |||
} | |||
} | |||
} | |||
@@ -758,7 +773,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// page here | |||
// if prevSplitLength is > 0 we can insert some footnote content in this page | |||
// and insert the remaining in the following one | |||
//TODO: check this conditional, as the first one is always false...? | |||
if (!somethingAdded) { | |||
// there was not enough space to add a piece of the first new footnote | |||
// this is not a good break | |||
@@ -781,7 +795,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
if (difference > 0) { | |||
int maxAdjustment = totalStretch - activeNode.totalStretch; | |||
// add the footnote separator stretch if some footnote content will be added | |||
if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { | |||
if (((KnuthPageNode) activeNode).insertedFootnotes < totalFootnotesLength) { | |||
maxAdjustment += footnoteSeparatorLength.getStretch(); | |||
} | |||
if (maxAdjustment > 0) { | |||
@@ -792,7 +806,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
} else if (difference < 0) { | |||
int maxAdjustment = totalShrink - activeNode.totalShrink; | |||
// add the footnote separator shrink if some footnote content will be added | |||
if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { | |||
if (((KnuthPageNode) activeNode).insertedFootnotes < totalFootnotesLength) { | |||
maxAdjustment += footnoteSeparatorLength.getShrink(); | |||
} | |||
if (maxAdjustment > 0) { | |||
@@ -866,7 +880,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
for (KnuthPageNode node = (KnuthPageNode) getNode(i); | |||
node != null; | |||
node = (KnuthPageNode) node.next) { | |||
if (node.totalFootnotes < totalFootnotesLength) { | |||
if (node.insertedFootnotes < totalFootnotesLength) { | |||
// layout remaining footnote bodies | |||
createFootnotePages(node); | |||
} | |||
@@ -876,7 +890,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
private void createFootnotePages(KnuthPageNode lastNode) { | |||
insertedFootnotesLength = lastNode.totalFootnotes; | |||
insertedFootnotesLength = lastNode.insertedFootnotes; | |||
footnoteListIndex = lastNode.footnoteListIndex; | |||
footnoteElementIndex = lastNode.footnoteElementIndex; | |||
int availableBPD = getLineWidth(lastNode.line); | |||
@@ -902,7 +916,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// cannot add any content: create a new node and start again | |||
KnuthPageNode node = (KnuthPageNode) | |||
createNode(lastNode.position, prevNode.line + 1, 1, | |||
insertedFootnotesLength - prevNode.totalFootnotes, | |||
insertedFootnotesLength - prevNode.insertedFootnotes, | |||
0, 0, | |||
0, 0, 0, | |||
0, 0, prevNode); | |||
@@ -916,7 +930,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
// create the last node | |||
KnuthPageNode node = (KnuthPageNode) | |||
createNode(lastNode.position, prevNode.line + 1, 1, | |||
totalFootnotesLength - prevNode.totalFootnotes, 0, 0, | |||
totalFootnotesLength - prevNode.insertedFootnotes, 0, 0, | |||
0, 0, 0, | |||
0, 0, prevNode); | |||
addNode(node.line, node); |
@@ -0,0 +1,112 @@ | |||
/* | |||
* 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.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.fo.FObj; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.traits.MinOptMax; | |||
/** | |||
* A block-stacking layout manager for an FO that supports spaces, border and padding. | |||
*/ | |||
public abstract class SpacedBorderedPaddedBlockLayoutManager extends BlockStackingLayoutManager | |||
implements ConditionalElementListener { | |||
private static final Log LOG = LogFactory.getLog(BlockLayoutManager.class); | |||
protected MinOptMax effSpaceBefore; | |||
protected MinOptMax effSpaceAfter; | |||
protected boolean discardBorderBefore; | |||
protected boolean discardBorderAfter; | |||
protected boolean discardPaddingBefore; | |||
protected boolean discardPaddingAfter; | |||
public SpacedBorderedPaddedBlockLayoutManager(FObj node) { | |||
super(node); | |||
} | |||
public void notifySpace(RelSide side, MinOptMax effectiveLength) { | |||
if (RelSide.BEFORE == side) { | |||
if (LOG.isDebugEnabled()) { | |||
LOG.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceBefore + "-> " + effectiveLength); | |||
} | |||
this.effSpaceBefore = effectiveLength; | |||
} else { | |||
if (LOG.isDebugEnabled()) { | |||
LOG.debug(this + ": Space " + side + ", " | |||
+ this.effSpaceAfter + "-> " + effectiveLength); | |||
} | |||
this.effSpaceAfter = effectiveLength; | |||
} | |||
} | |||
public void notifyBorder(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardBorderBefore = true; | |||
} else { | |||
this.discardBorderAfter = true; | |||
} | |||
} | |||
if (LOG.isDebugEnabled()) { | |||
LOG.debug(this + ": Border " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
public void notifyPadding(RelSide side, MinOptMax effectiveLength) { | |||
if (effectiveLength == null) { | |||
if (RelSide.BEFORE == side) { | |||
this.discardPaddingBefore = true; | |||
} else { | |||
this.discardPaddingAfter = true; | |||
} | |||
} | |||
if (LOG.isDebugEnabled()) { | |||
LOG.debug(this + ": Padding " + side + " -> " + effectiveLength); | |||
} | |||
} | |||
@Override | |||
public int getBaselineOffset() { | |||
int baselineOffset = super.getBaselineOffset(); | |||
if (effSpaceBefore != null) { | |||
baselineOffset += effSpaceBefore.getOpt(); | |||
} | |||
if (!discardBorderBefore) { | |||
baselineOffset += getCommonBorderPaddingBackground().getBorderBeforeWidth(false); | |||
} | |||
if (!discardPaddingBefore) { | |||
baselineOffset += getCommonBorderPaddingBackground().getPaddingBefore(false, this); | |||
} | |||
return baselineOffset; | |||
} | |||
/** | |||
* Returns the {@link CommonBorderPaddingBackground} instance from the FO handled by this layout manager. | |||
*/ | |||
protected abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); | |||
} |