Parcourir la source

Brought the branch in sync with rev. 1562429 of trunk


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_FopFontsForSVG@1562866 13f79535-47bb-0310-9956-ffa450edef68
pull/22/head
Vincent Hennebert il y a 10 ans
Parent
révision
563da808e4
100 fichiers modifiés avec 6667 ajouts et 3055 suppressions
  1. 8
    9
      build.xml
  2. 11
    5
      checkstyle-5.5.xml
  3. 8
    4
      checkstyle-suppressions.xml
  4. 8
    8
      examples/fo/basic/leader.fo
  5. 223
    46
      findbugs-exclude.xml
  6. BIN
      lib/fontbox-1.8.3-patched.jar
  7. 395
    0
      lib/pdfbox-1645.patch
  8. 738
    0
      lib/pdfbox-1646.patch
  9. BIN
      lib/xmlgraphics-commons-svn-trunk.jar
  10. 6
    7
      src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java
  11. 22
    26
      src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java
  12. 1
    0
      src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd
  13. 1
    0
      src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory
  14. 3
    2
      src/java/org/apache/fop/Version.java
  15. 1
    1
      src/java/org/apache/fop/apps/FOUserAgent.java
  16. 36
    17
      src/java/org/apache/fop/apps/FopConfParser.java
  17. 18
    1
      src/java/org/apache/fop/area/AreaTreeParser.java
  18. 1
    1
      src/java/org/apache/fop/area/Footnote.java
  19. 4
    1
      src/java/org/apache/fop/area/Trait.java
  20. 7
    8
      src/java/org/apache/fop/area/inline/Container.java
  21. 4
    40
      src/java/org/apache/fop/cli/CommandLineOptions.java
  22. 0
    1
      src/java/org/apache/fop/complexscripts/bidi/BidiClass.java
  23. 3
    7
      src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java
  24. 1
    4
      src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java
  25. 2
    9
      src/java/org/apache/fop/complexscripts/bidi/InlineRun.java
  26. 1
    4
      src/java/org/apache/fop/complexscripts/bidi/TextInterval.java
  27. 12
    17
      src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java
  28. 28
    41
      src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java
  29. 5
    6
      src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java
  30. 3
    5
      src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java
  31. 0
    1
      src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java
  32. 0
    1
      src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java
  33. 1
    3
      src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java
  34. 0
    1
      src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java
  35. 3
    5
      src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java
  36. 52
    55
      src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java
  37. 10
    11
      src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java
  38. 1
    2
      src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java
  39. 3
    4
      src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java
  40. 14
    16
      src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java
  41. 0
    1
      src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java
  42. 21
    28
      src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java
  43. 45
    48
      src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java
  44. 9
    13
      src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java
  45. 11
    16
      src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java
  46. 11
    16
      src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java
  47. 11
    16
      src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java
  48. 4
    13
      src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java
  49. 3
    9
      src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java
  50. 17
    23
      src/java/org/apache/fop/complexscripts/util/CharScript.java
  51. 8
    11
      src/java/org/apache/fop/complexscripts/util/GlyphSequence.java
  52. 15
    24
      src/java/org/apache/fop/complexscripts/util/NumberConverter.java
  53. 0
    1
      src/java/org/apache/fop/complexscripts/util/UTF32.java
  54. 4
    1
      src/java/org/apache/fop/fo/Constants.java
  55. 7
    0
      src/java/org/apache/fop/fo/FOPropertyMapping.java
  56. 30
    3
      src/java/org/apache/fop/fo/FObj.java
  57. 2
    1
      src/java/org/apache/fop/fo/expr/FunctionBase.java
  58. 2
    1
      src/java/org/apache/fop/fo/expr/PropertyParser.java
  59. 2
    0
      src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
  60. 16
    2
      src/java/org/apache/fop/fo/flow/BlockContainer.java
  61. 77
    95
      src/java/org/apache/fop/fo/flow/InlineContainer.java
  62. 12
    1
      src/java/org/apache/fop/fo/flow/table/Table.java
  63. 17
    1
      src/java/org/apache/fop/fo/pagination/PageSequence.java
  64. 5
    1
      src/java/org/apache/fop/fo/properties/GenericShorthandParser.java
  65. 2
    2
      src/java/org/apache/fop/fonts/FontLoader.java
  66. 10
    6
      src/java/org/apache/fop/fonts/FontManagerConfigurator.java
  67. 2
    1
      src/java/org/apache/fop/fonts/FontTriplet.java
  68. 52
    17
      src/java/org/apache/fop/fonts/MultiByteFont.java
  69. 1
    1
      src/java/org/apache/fop/fonts/SingleByteFont.java
  70. 0
    6
      src/java/org/apache/fop/fonts/apps/AbstractFontReader.java
  71. 0
    11
      src/java/org/apache/fop/fonts/apps/PFMReader.java
  72. 3
    13
      src/java/org/apache/fop/fonts/apps/TTFReader.java
  73. 2
    2
      src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
  74. 927
    0
      src/java/org/apache/fop/fonts/cff/CFFDataReader.java
  75. 2
    2
      src/java/org/apache/fop/fonts/truetype/GlyfTable.java
  76. 3
    3
      src/java/org/apache/fop/fonts/truetype/OFDirTabEntry.java
  77. 73
    63
      src/java/org/apache/fop/fonts/truetype/OFFontLoader.java
  78. 1
    1
      src/java/org/apache/fop/fonts/truetype/OFMtxEntry.java
  79. 41
    35
      src/java/org/apache/fop/fonts/truetype/OFTableName.java
  80. 109
    0
      src/java/org/apache/fop/fonts/truetype/OTFFile.java
  81. 1097
    0
      src/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java
  82. 1971
    0
      src/java/org/apache/fop/fonts/truetype/OpenFont.java
  83. 74
    1971
      src/java/org/apache/fop/fonts/truetype/TTFFile.java
  84. 53
    53
      src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
  85. 1
    1
      src/java/org/apache/fop/fonts/type1/AFMFile.java
  86. 6
    3
      src/java/org/apache/fop/fonts/type1/CharMetricsHandler.java
  87. 20
    5
      src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
  88. 0
    3
      src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java
  89. 28
    0
      src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
  90. 12
    12
      src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
  91. 10
    54
      src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
  92. 10
    55
      src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
  93. 3
    0
      src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
  94. 8
    2
      src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java
  95. 1
    0
      src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
  96. 19
    0
      src/java/org/apache/fop/layoutmgr/LayoutManager.java
  97. 5
    7
      src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
  98. 46
    32
      src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
  99. 112
    0
      src/java/org/apache/fop/layoutmgr/SpacedBorderedPaddedBlockLayoutManager.java
  100. 0
    0
      src/java/org/apache/fop/layoutmgr/TraitSetter.java

+ 8
- 9
build.xml Voir le fichier

<include name="org/apache/fop/apps/Fop.class"/> <include name="org/apache/fop/apps/Fop.class"/>
<include name="org/apache/fop/apps/FOPException.class"/> <include name="org/apache/fop/apps/FOPException.class"/>
<include name="org/apache/fop/apps/io/**"/> <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/fonts/*.class"/>
<include name="org/apache/fop/complexscripts/util/GlyphTester.class"/> <include name="org/apache/fop/complexscripts/util/GlyphTester.class"/>
<include name="org/apache/fop/events/EventProducer.class"/> <include name="org/apache/fop/events/EventProducer.class"/>
<include name="org/apache/fop/fo/Constants.class"/> <include name="org/apache/fop/fo/Constants.class"/>
<include name="org/apache/fop/fo/FOTreeBuilder.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/svg/**"/>
<include name="org/apache/fop/fonts/**"/> <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/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/CMYKColorSpace*.class"/>
<include name="org/apache/fop/util/Color*.class"/> <include name="org/apache/fop/util/Color*.class"/>
<include name="org/apache/fop/util/ASCII*.class"/> <include name="org/apache/fop/util/ASCII*.class"/>
<!-- Checkstyle --> <!-- Checkstyle -->
<!-- =================================================================== --> <!-- =================================================================== -->
<property name="checkstyle.location" value="${lib-tools}/checkstyle-5.5-all.jar" /> <property name="checkstyle.location" value="${lib-tools}/checkstyle-5.5-all.jar" />
<property name="checkstyle.noframes.xslt" value="${basedir}/checkstyle-noframes.xsl" />
<property name="checkstyle.config" value="${basedir}/checkstyle-5.5.xml" /> <property name="checkstyle.config" value="${basedir}/checkstyle-5.5.xml" />
<path id="checkstyle-classpath"> <path id="checkstyle-classpath">
<path refid="libs-build-classpath"/>
<pathelement location="${checkstyle.location}"/> <pathelement location="${checkstyle.location}"/>
</path> </path>
<condition property="checkstyle.avail"> <condition property="checkstyle.avail">
<available classname="com.puppycrawl.tools.checkstyle.CheckStyleTask"> <available classname="com.puppycrawl.tools.checkstyle.CheckStyleTask">
<classpath refid="checkstyle-classpath"/> <classpath refid="checkstyle-classpath"/>
</available> </available>
<available file="${checkstyle.noframes.xslt}"/>
<available file="${checkstyle.config}"/> <available file="${checkstyle.config}"/>
</and> </and>
</condition> </condition>
<target name="checkstyle-avail" unless="checkstyle.avail"> <target name="checkstyle-avail" unless="checkstyle.avail">
<echo message="Checkstyle support NOT present. Please download it from http://checkstyle.sf.net/ and"/> <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.location}"/>
<echo message="... please provide ${checkstyle.noframes.xslt}"/>
<echo message="... please provide ${checkstyle.config}"/> <echo message="... please provide ${checkstyle.config}"/>
</target> </target>
<target name="checkstyle" depends="package, checkstyle-avail" if="checkstyle.avail" description="Runs Checkstyle for a code quality report"> <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"/> <taskdef name="checkstyle" classname="com.puppycrawl.tools.checkstyle.CheckStyleTask" classpathref="checkstyle-classpath"/>
<mkdir dir="${build.dir}"/> <mkdir dir="${build.dir}"/>
<checkstyle config="${checkstyle.config}" failonviolation="false">
<checkstyle config="${checkstyle.config}" failonviolation="true" maxWarnings="0">
<classpath> <classpath>
<path refid="checkstyle-classpath"/> <path refid="checkstyle-classpath"/>
<pathelement location="${build.classes.dir}"/> <pathelement location="${build.classes.dir}"/>
<pathelement location="${build.codegen-classes.dir}"/> <pathelement location="${build.codegen-classes.dir}"/>
</classpath> </classpath>
<fileset dir="${src.dir}" includes="**/*.java"/> <fileset dir="${src.dir}" includes="**/*.java"/>
<fileset dir="${test.dir}" includes="**/*.java"/>
<formatter type="xml" toFile="${build.dir}/report_checkstyle.xml"/> <formatter type="xml" toFile="${build.dir}/report_checkstyle.xml"/>
<formatter type="plain"/>
</checkstyle> </checkstyle>
<xslt in="${build.dir}/report_checkstyle.xml" out="${build.dir}/report_checkstyle.html" style="${checkstyle.noframes.xslt}"/>
</target> </target>
<!-- =================================================================== --> <!-- =================================================================== -->
<!-- PMD --> <!-- PMD -->
<path refid="libs-tools-build-classpath"/> <path refid="libs-tools-build-classpath"/>
</classpath> </classpath>
</taskdef> </taskdef>
<mkdir dir="${build.dir}"/>
<pmd shortFilenames="true" targetjdk="${javac.target}"> <pmd shortFilenames="true" targetjdk="${javac.target}">
<ruleset>basic</ruleset> <ruleset>basic</ruleset>
<ruleset>rulesets/migrating_to_14.xml</ruleset> <ruleset>rulesets/migrating_to_14.xml</ruleset>
<!-- Special target for Gump --> <!-- Special target for Gump -->
<!-- =================================================================== --> <!-- =================================================================== -->
<target name="gump" depends="package,transcoder-pkg"/> <target name="gump" depends="package,transcoder-pkg"/>
<target name="gump-test" depends="junit-all">
<target name="gump-test" depends="junit-all,checkstyle">
<fail> <fail>
<condition> <condition>
<or> <or>

+ 11
- 5
checkstyle-5.5.xml Voir le fichier



<!-- ===================================================================================================== --> <!-- ===================================================================================================== -->
<module name="SuppressionCommentFilter"> <module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CSOFF\: ([\w\|]+)"/>
<property name="offCommentFormat" value="CSOFF\: (LineLength)"/>
<property name="onCommentFormat" value="CSON\: ([\w\|]+)"/> <property name="onCommentFormat" value="CSON\: ([\w\|]+)"/>
<property name="checkFormat" value="$1"/> <property name="checkFormat" value="$1"/>
</module> </module>
<!-- ===================================================================================================== --> <!-- ===================================================================================================== -->


<module name="SuppressionFilter">
<property name="file" value="${samedir}/checkstyle-suppressions.xml"/>
</module>

<!-- ===================================================================================================== --> <!-- ===================================================================================================== -->
<module name="TreeWalker"> <module name="TreeWalker">


<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->
<module name="LineLength">
<property name="max" value="120"/>
</module>
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->

<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> <!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->
<module name="AnnotationUseStyle"/> <module name="AnnotationUseStyle"/>
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> <!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->
<property name="allowLineBreaks" value="false"/> <property name="allowLineBreaks" value="false"/>
<property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/> <property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
</module> </module>
<module name="NoWhitespaceAfter">
<property name="allowLineBreaks" value="true"/>
<property name="tokens" value="ARRAY_INIT"/>
</module>
<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> <!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->


<!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... --> <!-- ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... -->

+ 8
- 4
checkstyle-suppressions.xml Voir le fichier

<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions> <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> </suppressions>

+ 8
- 8
examples/fo/basic/leader.fo Voir le fichier



<!-- examples for the use of the fo leader --> <!-- 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> <fo:layout-master-set>


<fo:list-item> <fo:list-item>
<!-- insert a bullet --> <!-- insert a bullet -->
<fo:list-item-label end-indent="label-end()"> <fo:list-item-label end-indent="label-end()">
<fo:block><fo:inline font-size="10pt" font-family="Symbol">&#183;</fo:inline></fo:block>
<fo:block><fo:inline font-size="10pt">&#183;</fo:inline></fo:block>
</fo:list-item-label> </fo:list-item-label>
<!-- list text --> <!-- list text -->
<fo:list-item-body start-indent="body-start()"> <fo:list-item-body start-indent="body-start()">
<fo:list-item> <fo:list-item>
<!-- insert a bullet --> <!-- insert a bullet -->
<fo:list-item-label end-indent="label-end()"> <fo:list-item-label end-indent="label-end()">
<fo:block><fo:inline font-size="10pt" font-family="Symbol">&#183;</fo:inline></fo:block>
<fo:block><fo:inline font-size="10pt">&#183;</fo:inline></fo:block>
</fo:list-item-label> </fo:list-item-label>
<!-- list text --> <!-- list text -->
<fo:list-item-body start-indent="body-start()"> <fo:list-item-body start-indent="body-start()">


<fo:table-row line-height="12pt"> <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="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-pattern-width="8pt"
leader-alignment="reference-area" leader-alignment="reference-area"
/></fo:block></fo:table-cell> /></fo:block></fo:table-cell>


<fo:table-row line-height="12pt"> <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="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-pattern-width="8pt"
leader-alignment="reference-area" leader-alignment="reference-area"
/></fo:block></fo:table-cell> /></fo:block></fo:table-cell>


<fo:table-row line-height="12pt"> <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="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-pattern-width="8pt"
leader-alignment="reference-area" leader-alignment="reference-area"
/></fo:block></fo:table-cell> /></fo:block></fo:table-cell>


<fo:table-row line-height="12pt"> <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="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-pattern-width="8pt"
leader-alignment="reference-area" leader-alignment="reference-area"
/></fo:block></fo:table-cell> /></fo:block></fo:table-cell>


<fo:table-row line-height="12pt"> <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="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-pattern-width="8pt"
leader-alignment="reference-area" leader-alignment="reference-area"
/></fo:block></fo:table-cell> /></fo:block></fo:table-cell>

+ 223
- 46
findbugs-exclude.xml Voir le fichier

<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FindBugsFilter> <FindBugsFilter>
<Match> <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="&lt;init&gt;"/>
<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"/> <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
</Match> </Match>
<Match> <Match>
<Method name="buildCIDSet"/> <Method name="buildCIDSet"/>
<Bug pattern="OS_OPEN_STREAM"/> <Bug pattern="OS_OPEN_STREAM"/>
</Match> </Match>
<Match>
<Class name="org.apache.fop.pdf.PDFFactory"/>
<Method name="makeFont"/>
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/>
</Match>
<Match> <Match>
<Class name="org.apache.fop.pdf.PDFOutputIntent"/> <Class name="org.apache.fop.pdf.PDFOutputIntent"/>
<Method name="toPDF"/> <Method name="toPDF"/>
<Bug pattern="BIT_IOR_OF_SIGNED_BYTE"/> <Bug pattern="BIT_IOR_OF_SIGNED_BYTE"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/>
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/>
<Method name="toString"/> <Method name="toString"/>
<Bug pattern="DMI_INVOKING_TOSTRING_ON_ARRAY"/> <Bug pattern="DMI_INVOKING_TOSTRING_ON_ARRAY"/>
</Match> </Match>
<Bug pattern="UWF_UNWRITTEN_FIELD"/> <Bug pattern="UWF_UNWRITTEN_FIELD"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/>
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/>
<Field name="checksum"/> <Field name="checksum"/>
<Bug pattern="UWF_UNWRITTEN_FIELD"/> <Bug pattern="UWF_UNWRITTEN_FIELD"/>
</Match> </Match>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="glyphToUnicode"/> <Method name="glyphToUnicode"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="initAnsiWidths"/> <Method name="initAnsiWidths"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="readKerning"/> <Method name="readKerning"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="readUnicodeCmap"/> <Method name="readUnicodeCmap"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="unicodeToGlyph"/> <Method name="unicodeToGlyph"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="unicodeToWinAnsi"/> <Method name="unicodeToWinAnsi"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile$UnicodeMapping"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont$UnicodeMapping"/>
<Method name="&lt;init&gt;"/> <Method name="&lt;init&gt;"/>
<Bug pattern="DM_NUMBER_CTOR"/> <Bug pattern="DM_NUMBER_CTOR"/>
</Match> </Match>
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> <Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="unicodeToWinAnsi"/> <Method name="unicodeToWinAnsi"/>
<Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/> <Bug pattern="ITA_INEFFICIENT_TO_ARRAY"/>
</Match> </Match>
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile$UnicodeMapping"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont$UnicodeMapping"/>
<!--Neither method nor field--> <!--Neither method nor field-->
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS"/> <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS"/>
</Match> </Match>
<Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/> <Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="printMaxMin"/> <Method name="printMaxMin"/>
<Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/> <Bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/>
</Match> </Match>
<Bug pattern="WMI_WRONG_MAP_ITERATOR"/> <Bug pattern="WMI_WRONG_MAP_ITERATOR"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="readKerning"/> <Method name="readKerning"/>
<Bug pattern="WMI_WRONG_MAP_ITERATOR"/> <Bug pattern="WMI_WRONG_MAP_ITERATOR"/>
</Match> </Match>
<Bug pattern="DLS_DEAD_LOCAL_STORE"/> <Bug pattern="DLS_DEAD_LOCAL_STORE"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile"/>
<Class name="org.apache.fop.fonts.truetype.OpenFont"/>
<Method name="readFont"/> <Method name="readFont"/>
<Bug pattern="DLS_DEAD_LOCAL_STORE"/> <Bug pattern="DLS_DEAD_LOCAL_STORE"/>
</Match> </Match>
<Bug pattern="EI_EXPOSE_REP"/> <Bug pattern="EI_EXPOSE_REP"/>
</Match> </Match>
<Match> <Match>
<Class name="org.apache.fop.fonts.truetype.TTFDirTabEntry"/>
<Class name="org.apache.fop.fonts.truetype.OFDirTabEntry"/>
<Method name="getTag"/> <Method name="getTag"/>
<Bug pattern="EI_EXPOSE_REP"/> <Bug pattern="EI_EXPOSE_REP"/>
</Match> </Match>
</Or> </Or>
<Bug pattern="BC_UNCONFIRMED_CAST"/> <Bug pattern="BC_UNCONFIRMED_CAST"/>
</Match> </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> </FindBugsFilter>

BIN
lib/fontbox-1.8.3-patched.jar Voir le fichier


+ 395
- 0
lib/pdfbox-1645.patch Voir le fichier

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;
+ }
+ }
+}

+ 738
- 0
lib/pdfbox-1646.patch Voir le fichier

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
+}

BIN
lib/xmlgraphics-commons-svn-trunk.jar Voir le fichier


+ 6
- 7
src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java Voir le fichier

import org.apache.fop.util.License; import org.apache.fop.util.License;


// CSOFF: LineLength // CSOFF: LineLength
// CSOFF: NoWhitespaceAfter


/** /**
* <p>Utility for generating a Java class representing bidirectional * <p>Utility for generating a Java class representing bidirectional
sb.setLength(0); sb.setLength(0);
out.println("private static byte[] bcL1 = {"); out.println("private static byte[] bcL1 = {");
for (int i = 0; i < bcL1.length; i++) { for (int i = 0; i < bcL1.length; i++) {
if (! first) {
if (!first) {
sb.append(","); sb.append(",");
} else { } else {
first = false; first = false;
sb.setLength(0); sb.setLength(0);
out.println("private static byte[] bcR1 = {"); out.println("private static byte[] bcR1 = {");
for (int i = 0; i < bcR1.length; i++) { for (int i = 0; i < bcR1.length; i++) {
if (! first) {
if (!first) {
sb.append(","); sb.append(",");
} else { } else {
first = false; first = false;
sb.setLength(0); sb.setLength(0);
out.println("private static int[] bcS1 = {"); out.println("private static int[] bcS1 = {");
for (int i = 0; i < bcS1.length; i++) { for (int i = 0; i < bcS1.length; i++) {
if (! first) {
if (!first) {
sb.append(","); sb.append(",");
} else { } else {
first = false; first = false;
sb.setLength(0); sb.setLength(0);
out.println("private static int[] bcE1 = {"); out.println("private static int[] bcE1 = {");
for (int i = 0; i < bcE1.length; i++) { for (int i = 0; i < bcE1.length; i++) {
if (! first) {
if (!first) {
sb.append(","); sb.append(",");
} else { } else {
first = false; first = false;
sb.setLength(0); sb.setLength(0);
out.println("private static byte[] bcC1 = {"); out.println("private static byte[] bcC1 = {");
for (int i = 0; i < bcC1.length; i++) { for (int i = 0; i < bcC1.length; i++) {
if (! first) {
if (!first) {
sb.append(","); sb.append(",");
} else { } else {
first = false; first = false;
if (k >= 0) { if (k >= 0) {
return ca [ k ]; return ca [ k ];
} else { } else {
k = - (k + 1);
k = -(k + 1);
if (k == 0) { if (k == 0) {
return BidiConstants.L; return BidiConstants.L;
} else if (ch <= ea [ k - 1 ]) { } else if (ch <= ea [ k - 1 ]) {

+ 22
- 26
src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java Voir le fichier

import org.apache.fop.util.License; import org.apache.fop.util.License;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: EmptyForIteratorPadCheck


/** /**
* <p>Utility for generating a Java class and associated data files representing * <p>Utility for generating a Java class and associated data files representing
String ucName = sa[1]; String ucName = sa[1];
if (isBlockStart(ucName)) { if (isBlockStart(ucName)) {
String ucBlock = getBlockName(ucName); String ucBlock = getBlockName(ucName);
if (! im.containsKey(ucBlock)) {
if (!im.containsKey(ucBlock)) {
im.put(ucBlock, new int[] { uc, -1, bc }); im.put(ucBlock, new int[] { uc, -1, bc });
} else { } else {
throw new IllegalArgumentException("duplicate start of block '" + ucBlock + "' at entry: " + line); throw new IllegalArgumentException("duplicate start of block '" + ucBlock + "' at entry: " + line);
} else { } else {
Integer k = Integer.valueOf(bc); Integer k = Integer.valueOf(bc);
List sl; List sl;
if (! sm.containsKey(k)) {
if (!sm.containsKey(k)) {
sl = new ArrayList(); sl = new ArrayList();
sm.put(k, sl); sm.put(k, sl);
} else { } else {
} }
} }
// populate intervals from (block) interval map // populate intervals from (block) interval map
if (! im.isEmpty()) {
if (!im.isEmpty()) {
for (Iterator it = im.values().iterator(); it.hasNext(); ) { for (Iterator it = im.values().iterator(); it.hasNext(); ) {
int[] ba = (int[]) it.next(); int[] ba = (int[]) it.next();
assert (ba != null) && (ba.length > 2); assert (ba != null) && (ba.length > 2);
continue; continue;
} else if (line.startsWith("#")) { } else if (line.startsWith("#")) {
continue; continue;
} else if (line.startsWith(PFX_TYPE) && ! ignoreDeprecatedTypeData) {
} else if (line.startsWith(PFX_TYPE) && !ignoreDeprecatedTypeData) {
List lines = new ArrayList(); List lines = new ArrayList();
if ((n = readType(line, b, lines)) < 0) { if ((n = readType(line, b, lines)) < 0) {
break; break;
// dump instrumentation // dump instrumentation
if (verbose) { if (verbose) {
System.out.println(); System.out.println();
if (! ignoreDeprecatedTypeData) {
if (!ignoreDeprecatedTypeData) {
System.out.println("Read type ranges : " + numTypeRanges); System.out.println("Read type ranges : " + numTypeRanges);
} }
System.out.println("Read level specs : " + numLevelSpecs); System.out.println("Read level specs : " + numLevelSpecs);
System.out.println("Read test specs : " + numTestSpecs); System.out.println("Read test specs : " + numTestSpecs);
System.out.println("Read lines : " + lineNumber); System.out.println("Read lines : " + lineNumber);
} }
if (! ignoreDeprecatedTypeData) {
if (!ignoreDeprecatedTypeData) {
td = (int[][]) tdl.toArray(new int [ tdl.size() ] []); td = (int[][]) tdl.toArray(new int [ tdl.size() ] []);
} }
ld = (int[][]) ldl.toArray(new int [ ldl.size() ] []); ld = (int[][]) ldl.toArray(new int [ ldl.size() ] []);
boolean done = false; boolean done = false;
int n = 0; int n = 0;
lines.add(line); lines.add(line);
while (! done) {
while (!done) {
switch (testPrefix(b, PFX_LEVELS)) { switch (testPrefix(b, PFX_LEVELS)) {
case 0: // within current levels case 0: // within current levels
if ((line = b.readLine()) != null) { if ((line = b.readLine()) != null) {
n++; n++;
if ((line.length() > 0) && ! line.startsWith("#")) {
if ((line.length() > 0) && !line.startsWith("#")) {
lines.add(line); lines.add(line);
} }
} else { } else {
CharacterIterator ci = new StringCharacterIterator(charRanges); CharacterIterator ci = new StringCharacterIterator(charRanges);
// read initial list delimiter // read initial list delimiter
skipSpace(ci); skipSpace(ci);
if (! readStartOfList(ci)) {
if (!readStartOfList(ci)) {
badRangeSpec("missing initial list delimiter", charRanges); badRangeSpec("missing initial list delimiter", charRanges);
} }
// read negation token if present // read negation token if present
String s; String s;
skipSpace(ci); skipSpace(ci);
if ((s = maybeReadSeparator(ci)) != null) { if ((s = maybeReadSeparator(ci)) != null) {
if ((s.length() != 0) && ! s.equals("||")) {
if ((s.length() != 0) && !s.equals("||")) {
badRangeSpec("invalid item separator \"" + s + "\"", charRanges); badRangeSpec("invalid item separator \"" + s + "\"", charRanges);
} }
} }
} }
// read terminating list delimiter // read terminating list delimiter
skipSpace(ci); skipSpace(ci);
if (! readEndOfList(ci)) {
if (!readEndOfList(ci)) {
badRangeSpec("missing terminating list delimiter", charRanges); badRangeSpec("missing terminating list delimiter", charRanges);
} }
if (! atEnd(ci)) {
if (!atEnd(ci)) {
badRangeSpec("extraneous content prior to end of line", ci); badRangeSpec("extraneous content prior to end of line", ci);
} }
if (negated) { if (negated) {
} }


private static void skipSpace(CharacterIterator ci) { private static void skipSpace(CharacterIterator ci) {
while (! atEnd(ci)) {
while (!atEnd(ci)) {
char c = ci.current(); char c = ci.current();
if (! Character.isWhitespace(c)) {
if (!Character.isWhitespace(c)) {
break; break;
} else { } else {
ci.next(); ci.next();
} }


private static boolean maybeReadNext(CharacterIterator ci, char next) { private static boolean maybeReadNext(CharacterIterator ci, char next) {
while (! atEnd(ci)) {
while (!atEnd(ci)) {
char c = ci.current(); char c = ci.current();
if (c == next) { if (c == next) {
ci.next(); ci.next();
List ll = new ArrayList(); List ll = new ArrayList();
// read prefix // read prefix
skipSpace(ci); skipSpace(ci);
if (! maybeReadToken(ci, PFX_LEVELS)) {
if (!maybeReadToken(ci, PFX_LEVELS)) {
badLevelSpec("missing prefix \"" + PFX_LEVELS + "\"", ci); badLevelSpec("missing prefix \"" + PFX_LEVELS + "\"", ci);
} }
// read level values // read level values
} }
// read to end of line // read to end of line
skipSpace(ci); skipSpace(ci);
if (! atEnd(ci)) {
if (!atEnd(ci)) {
badLevelSpec("extraneous content prior to end of line", ci); badLevelSpec("extraneous content prior to end of line", ci);
} }
if (ll.size() == 0) { if (ll.size() == 0) {
List rl = new ArrayList(); List rl = new ArrayList();
// read prefix // read prefix
skipSpace(ci); skipSpace(ci);
if (! maybeReadToken(ci, PFX_REORDER)) {
if (!maybeReadToken(ci, PFX_REORDER)) {
badReorderSpec("missing prefix \"" + PFX_REORDER + "\"", ci); badReorderSpec("missing prefix \"" + PFX_REORDER + "\"", ci);
} }
// read reorder values // read reorder values
} }
// read to end of line // read to end of line
skipSpace(ci); skipSpace(ci);
if (! atEnd(ci)) {
if (!atEnd(ci)) {
badReorderSpec("extraneous content prior to end of line", ci); badReorderSpec("extraneous content prior to end of line", ci);
} }
return createReorderArray(rl, levels); return createReorderArray(rl, levels);
CharacterIterator ci = new StringCharacterIterator(line); CharacterIterator ci = new StringCharacterIterator(line);
List cl = new ArrayList(); List cl = new ArrayList();
// read bidi class identifier sequence // read bidi class identifier sequence
while (! atEnd(ci) && ! maybeReadNext(ci, ';')) {
while (!atEnd(ci) && !maybeReadNext(ci, ';')) {
skipSpace(ci); skipSpace(ci);
int bc; int bc;
if ((bc = maybeReadBidiClass(ci)) >= 0) { if ((bc = maybeReadBidiClass(ci)) >= 0) {
} }
// read to end of line // read to end of line
skipSpace(ci); skipSpace(ci);
if (! atEnd(ci)) {
if (!atEnd(ci)) {
badTestSpec("extraneous content prior to end of line", ci); badTestSpec("extraneous content prior to end of line", ci);
} }
return createTestArray(cl, bs, levels); return createTestArray(cl, bs, levels);
ok = false; ok = false;
} }
} }
if (! ok) {
if (!ok) {
System.out.println("Usage: GenerateBidiTestData [-v] [-i] [-d <ucdFile>] [-b <bidiFile>] [-o <outputFile>]"); System.out.println("Usage: GenerateBidiTestData [-v] [-i] [-d <ucdFile>] [-b <bidiFile>] [-o <outputFile>]");
System.out.println(" defaults:"); System.out.println(" defaults:");
if (ignoreDeprecatedTypeData) { if (ignoreDeprecatedTypeData) {

+ 1
- 0
src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd Voir le fichier

<xs:complexContent> <xs:complexContent>
<xs:extension base="mf:contentType"> <xs:extension base="mf:contentType">
<xs:attribute name="transform" type="xs:string"/> <xs:attribute name="transform" type="xs:string"/>
<xs:attribute name="layer" type="xs:string"/>
</xs:extension> </xs:extension>
</xs:complexContent> </xs:complexContent>
</xs:complexType> </xs:complexType>

+ 1
- 0
src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory Voir le fichier

org.apache.fop.render.afp.extensions.AFPExtensionHandlerFactory org.apache.fop.render.afp.extensions.AFPExtensionHandlerFactory
org.apache.fop.render.pdf.extensions.PDFExtensionHandlerFactory
org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory
org.apache.fop.fo.extensions.xmp.XMPContentHandlerFactory org.apache.fop.fo.extensions.xmp.XMPContentHandlerFactory

+ 3
- 2
src/java/org/apache/fop/Version.java Voir le fichier

} }
if (version == null) { if (version == null) {
//Fallback if FOP is used in a development environment //Fallback if FOP is used in a development environment
String headURL
= "$HeadURL$";
// CSOFF: LineLength
String headURL = "$HeadURL$";
// CSON: LineLength
version = headURL; version = headURL;
final String pathPrefix = "/xmlgraphics/fop/"; final String pathPrefix = "/xmlgraphics/fop/";
int pos = version.indexOf(pathPrefix); int pos = version.indexOf(pathPrefix);

+ 1
- 1
src/java/org/apache/fop/apps/FOUserAgent.java Voir le fichier

try { try {
// Have to do this so we can resolve data URIs // Have to do this so we can resolve data URIs
StreamSource src = new StreamSource(resourceResolver.getResource(uri)); StreamSource src = new StreamSource(resourceResolver.getResource(uri));
src.setSystemId(uri);
src.setSystemId(new File(uri).toURI().toURL().toExternalForm());
return src; return src;
} catch (URISyntaxException use) { } catch (URISyntaxException use) {
return null; return null;

+ 36
- 17
src/java/org/apache/fop/apps/FopConfParser.java Voir le fichier

*/ */
public FopConfParser(InputStream fopConfStream, EnvironmentProfile enviro) public FopConfParser(InputStream fopConfStream, EnvironmentProfile enviro)
throws SAXException, IOException { 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);
} }


/** /**
*/ */
public FopConfParser(InputStream fopConfStream, URI defaultBaseURI, public FopConfParser(InputStream fopConfStream, URI defaultBaseURI,
ResourceResolver resourceResolver) throws SAXException, IOException { ResourceResolver resourceResolver) throws SAXException, IOException {
this(fopConfStream, EnvironmentalProfileFactory.createDefault(defaultBaseURI, resourceResolver));
this(fopConfStream, defaultBaseURI,
EnvironmentalProfileFactory.createDefault(defaultBaseURI, resourceResolver));
} }


/** /**
this(fopConfFile, ResourceResolverFactory.createDefaultResourceResolver()); 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. * Constructor that parses the FOP conf and uses the URI resolver given.
* *
*/ */
public FopConfParser(File fopConfFile, ResourceResolver resourceResolver) public FopConfParser(File fopConfFile, ResourceResolver resourceResolver)
throws SAXException, IOException { 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 { Configuration cfg) throws FOPException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Initializing FopFactory Configuration"); log.debug("Initializing FopFactory Configuration");
if (cfg.getChild("base", false) != null) { if (cfg.getChild("base", false) != null) {
try { try {
URI confUri = InternalResourceResolver.getBaseURI(cfg.getChild("base").getValue(null)); URI confUri = InternalResourceResolver.getBaseURI(cfg.getChild("base").getValue(null));
fopFactoryBuilder.setBaseURI(defaultBaseURI.resolve(confUri));
fopFactoryBuilder.setBaseURI(baseURI.resolve(confUri));
} catch (URISyntaxException use) { } catch (URISyntaxException use) {
LogUtil.handleException(log, use, strict); LogUtil.handleException(log, use, strict);
} }
} }


// configure font manager // 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 // configure image loader framework
configureImageLoading(cfg.getChild("image-loading", false), strict); configureImageLoading(cfg.getChild("image-loading", false), strict);

+ 18
- 1
src/java/org/apache/fop/area/AreaTreeParser.java Voir le fichier

import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.Background;
import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.Trait.InternalLink;
import org.apache.fop.area.inline.AbstractTextArea; 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.ForeignObject;
import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineArea;
makers.put("space", new SpaceMaker()); makers.put("space", new SpaceMaker());
makers.put("leader", new LeaderMaker()); makers.put("leader", new LeaderMaker());
makers.put("viewport", new InlineViewportMaker()); makers.put("viewport", new InlineViewportMaker());
makers.put("container", new ContainerMaker());
makers.put("image", new ImageMaker()); makers.put("image", new ImageMaker());
makers.put("foreignObject", new ForeignObjectMaker()); makers.put("foreignObject", new ForeignObjectMaker());
makers.put("bookmarkTree", new BookmarkTreeMaker()); makers.put("bookmarkTree", new BookmarkTreeMaker());
} }
} }


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 { private class InlineViewportMaker extends AbstractMaker {


public void startElement(Attributes attributes) { public void startElement(Attributes attributes) {
} }


private static final Object[] SUBSET_COMMON = new Object[] { private static final Object[] SUBSET_COMMON = new Object[] {
Trait.PROD_ID};
Trait.PROD_ID, Trait.LAYER};
private static final Object[] SUBSET_LINK = new Object[] { private static final Object[] SUBSET_LINK = new Object[] {
Trait.INTERNAL_LINK, Trait.EXTERNAL_LINK}; Trait.INTERNAL_LINK, Trait.EXTERNAL_LINK};
private static final Object[] SUBSET_COLOR = new Object[] { private static final Object[] SUBSET_COLOR = new Object[] {

+ 1
- 1
src/java/org/apache/fop/area/Footnote.java Voir le fichier

@Override @Override
public void addBlock(Block child) { public void addBlock(Block child) {
addChildArea(child); addChildArea(child);
this.setBPD(this.getBPD() + child.getBPD());
setBPD(getBPD() + child.getAllocBPD());
} }


} }

+ 4
- 1
src/java/org/apache/fop/area/Trait.java Voir le fichier

/** shift direction trait */ /** shift direction trait */
public static final Integer SHIFT_DIRECTION = 42; public static final Integer SHIFT_DIRECTION = 42;


/** For optional content groups. */
public static final Integer LAYER = 43;


/** Maximum value used by trait keys */ /** 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]; private static final TraitInfo[] TRAIT_INFO = new TraitInfo[MAX_TRAIT_KEY + 1];


new TraitInfo("block-progression-direction", Direction.class)); new TraitInfo("block-progression-direction", Direction.class));
put(SHIFT_DIRECTION, put(SHIFT_DIRECTION,
new TraitInfo("shift-direction", Direction.class)); new TraitInfo("shift-direction", Direction.class));
put(LAYER, new TraitInfo("layer", String.class));


} }



+ 7
- 8
src/java/org/apache/fop/area/inline/Container.java Voir le fichier

public Container() { 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);
} }


/** /**
* *
* @return the list of block areas * @return the list of block areas
*/ */
public List getBlocks() {
public List<Block> getBlocks() {
return blocks; return blocks;
} }



+ 4
- 40
src/java/org/apache/fop/cli/CommandLineOptions.java Voir le fichier

import org.apache.fop.render.print.PagesMode; import org.apache.fop.render.print.PagesMode;
import org.apache.fop.render.print.PrintRenderer; import org.apache.fop.render.print.PrintRenderer;
import org.apache.fop.render.xml.XMLRenderer; import org.apache.fop.render.xml.XMLRenderer;
import org.apache.fop.util.CommandLineLogger;


/** /**
* Options parses the commandline arguments * Options parses the commandline arguments
* Construct a command line option object. * Construct a command line option object.
*/ */
public CommandLineOptions() { 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"); log = LogFactory.getLog("FOP");
} }


//Factory config is set up, now we can create the user agent //Factory config is set up, now we can create the user agent
foUserAgent = factory.newFOUserAgent(); foUserAgent = factory.newFOUserAgent();
foUserAgent.getRendererOptions().putAll(renderingOptions); foUserAgent.getRendererOptions().putAll(renderingOptions);
if (targetResolution != 0) {
foUserAgent.setTargetResolution(targetResolution);
}
addXSLTParameter("fop-output-format", getOutputFormat()); addXSLTParameter("fop-output-format", getOutputFormat());
addXSLTParameter("fop-version", Version.getVersion()); addXSLTParameter("fop-version", Version.getVersion());
foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy); foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy);
} else if (args[i].equals("-s")) { } else if (args[i].equals("-s")) {
suppressLowLevelAreas = Boolean.TRUE; suppressLowLevelAreas = Boolean.TRUE;
} else if (args[i].equals("-d")) { } else if (args[i].equals("-d")) {
setLogOption("debug", "debug");
// nop. Left there for backwards compatibility
} else if (args[i].equals("-r")) { } else if (args[i].equals("-r")) {
strictValidation = false; strictValidation = false;
} else if (args[i].equals("-conserve")) { } else if (args[i].equals("-conserve")) {
} else if (args[i].equals("-dpi")) { } else if (args[i].equals("-dpi")) {
i = i + parseResolution(args, i); i = i + parseResolution(args, i);
} else if (args[i].equals("-q") || args[i].equals("--quiet")) { } 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")) { } else if (args[i].equals("-fo")) {
i = i + parseFOInputOption(args, i); i = i + parseFOInputOption(args, i);
} else if (args[i].equals("-xsl")) { } else if (args[i].equals("-xsl")) {
} }
} }


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 { private void setInputFormat(int format) throws FOPException {
if (inputmode == NOT_SET || inputmode == format) { if (inputmode == NOT_SET || inputmode == format) {
inputmode = format; inputmode = format;
fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures); fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures);
} else { } else {
try { try {
fopFactoryBuilder = new FopConfParser(userConfigFile).getFopFactoryBuilder();
FopConfParser fopConfParser = new FopConfParser(userConfigFile, baseURI);
fopFactoryBuilder = fopConfParser.getFopFactoryBuilder();
} catch (SAXException e) { } catch (SAXException e) {
throw new FOPException(e); throw new FOPException(e);
} }
+ "[-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl|-ps|-txt|-at [mime]|-print] <outfile>\n" + "[-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl|-ps|-txt|-at [mime]|-print] <outfile>\n"
+ " [OPTIONS] \n" + " [OPTIONS] \n"
+ " -version print FOP version and exit\n" + " -version print FOP version and exit\n"
+ " -d debug mode \n"
+ " -x dump configuration settings \n" + " -x dump configuration settings \n"
+ " -q quiet mode \n"
+ " -c cfg.xml use additional configuration file cfg.xml\n" + " -c cfg.xml use additional configuration file cfg.xml\n"
+ " -l lang the language to use for user information \n" + " -l lang the language to use for user information \n"
+ " -nocs disable complex script features\n" + " -nocs disable complex script features\n"

+ 0
- 1
src/java/org/apache/fop/complexscripts/bidi/BidiClass.java Voir le fichier



import java.util.Arrays; import java.util.Arrays;


// CSOFF: WhitespaceAfterCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/* /*

+ 3
- 7
src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java Voir le fichier

import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.PageSequence;


// CSOFF: EmptyForIteratorPadCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: SimplifyBooleanReturnCheck


/** /**
* <p>A utility class for performing bidirectional resolution processing.</p> * <p>A utility class for performing bidirectional resolution processing.</p>
runsNew.addAll(ir.split()); runsNew.addAll(ir.split());
} }
} }
if (! runsNew.equals(runs)) {
if (!runsNew.equals(runs)) {
runs = runsNew; runs = runsNew;
} }
return runs; return runs;
i = e - 1; i = e - 1;
} }
} }
if (! runsNew.equals(runs)) {
if (!runsNew.equals(runs)) {
runs = runsNew; runs = runsNew;
} }
return runs; return runs;
Vector rv = new Vector(); Vector rv = new Vector();
for (Iterator it = ranges.iterator(); it.hasNext(); ) { for (Iterator it = ranges.iterator(); it.hasNext(); ) {
DelimitedTextRange r = (DelimitedTextRange) it.next(); DelimitedTextRange r = (DelimitedTextRange) it.next();
if (! r.isEmpty()) {
if (!r.isEmpty()) {
rv.add(r); rv.add(r);
} }
} }

+ 1
- 4
src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java Voir le fichier

import org.apache.fop.traits.WritingModeTraitsGetter; import org.apache.fop.traits.WritingModeTraitsGetter;
import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;


// CSOFF: EmptyForIteratorPadCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* The <code>DelimitedTextRange</code> class implements the "delimited text range" as described * The <code>DelimitedTextRange</code> class implements the "delimited text range" as described
TextInterval ti = (TextInterval) it.next(); TextInterval ti = (TextInterval) it.next();
intervalsNew.addAll(assignLevels(ti, levels)); intervalsNew.addAll(assignLevels(ti, levels));
} }
if (! intervalsNew.equals(intervals)) {
if (!intervalsNew.equals(intervals)) {
intervals = intervalsNew; intervals = intervalsNew;
} }
} }

+ 2
- 9
src/java/org/apache/fop/complexscripts/bidi/InlineRun.java Voir le fichier

import org.apache.fop.area.inline.WordArea; import org.apache.fop.area.inline.WordArea;
import org.apache.fop.util.CharUtilities; 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 * 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. * to capture a sequence of reordering levels associated with an inline area.
if (inline instanceof WordArea) { if (inline instanceof WordArea) {
WordArea w = (WordArea) inline; WordArea w = (WordArea) inline;
// if not already reversed, then reverse now // if not already reversed, then reverse now
if (! w.isReversed()) {
if (!w.isReversed()) {
if ((reversals & 1) != 0) { if ((reversals & 1) != 0) {
w.reverse(mirror); w.reverse(mirror);
} else if (mirror && maybeNeedsMirroring()) { } else if (mirror && maybeNeedsMirroring()) {
} }
return true; return true;
} }
} else if ((ir.levels == null) && (levels == null)) {
return true;
} else { } else {
return false;
return (ir.levels == null) && (levels == null);
} }
} else { } else {
return false; return false;

+ 1
- 4
src/java/org/apache/fop/complexscripts/bidi/TextInterval.java Voir le fichier

import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.Leader;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: SimplifyBooleanReturnCheck


/** /**
* <p>The <code>TextInterval</code> class is a utility class, the instances of which are used * <p>The <code>TextInterval</code> class is a utility class, the instances of which are used
return false; return false;
} else if (ti.getStart() != start) { } else if (ti.getStart() != start) {
return false; return false;
} else if (ti.getEnd() != end) {
return false;
} else { } else {
return true;
return ti.getEnd() == end;
} }
} else { } else {
return false; return false;

+ 12
- 17
src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java Voir le fichier

import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.area.inline.UnresolvedPageNumber;


// CSOFF: EmptyForIteratorPadCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: SimplifyBooleanReturnCheck


/** /**
* <p>The <code>UnflattenProcessor</code> class is used to reconstruct (by unflattening) a line * <p>The <code>UnflattenProcessor</code> class is used to reconstruct (by unflattening) a line
private boolean shouldFinishTextContainer(TextArea tc, InlineArea ia) { private boolean shouldFinishTextContainer(TextArea tc, InlineArea ia) {
if ((tcOrig != null) && (tc != tcOrig)) { if ((tcOrig != null) && (tc != tcOrig)) {
return true; return true;
} else if ((iaLevelLast != -1) && (ia.getBidiLevel() != iaLevelLast)) {
return true;
} else { } else {
return false;
return (iaLevelLast != -1) && (ia.getBidiLevel() != iaLevelLast);
} }
} }
private void finishTextContainer() { private void finishTextContainer() {
private void finishTextContainer(TextArea tc, InlineArea ia) { private void finishTextContainer(TextArea tc, InlineArea ia) {
if (tcNew != null) { if (tcNew != null) {
updateIPD(tcNew); updateIPD(tcNew);
if (! icNew.empty()) {
if (!icNew.empty()) {
icNew.peek().addChildArea(tcNew); icNew.peek().addChildArea(tcNew);
} else { } else {
ilNew.add(tcNew); ilNew.add(tcNew);
} }
private boolean shouldFinishInlineContainer(List<InlineParent> ich, TextArea tc, InlineArea ia) { private boolean shouldFinishInlineContainer(List<InlineParent> ich, TextArea tc, InlineArea ia) {
if ((ich == null) || ich.isEmpty()) { if ((ich == null) || ich.isEmpty()) {
return ! icOrig.empty();
return !icOrig.empty();
} else { } else {
if (! icOrig.empty()) {
if (!icOrig.empty()) {
InlineParent ic = ich.get(0); InlineParent ic = ich.get(0);
InlineParent ic0 = icOrig.peek(); InlineParent ic0 = icOrig.peek();
return (ic != ic0) && ! isInlineParentOf(ic, ic0);
return (ic != ic0) && !isInlineParentOf(ic, ic0);
} else { } else {
return false; return false;
} }
finishInlineContainer(null, null, null); finishInlineContainer(null, null, null);
} }
private void finishInlineContainer(List<InlineParent> ich, TextArea tc, InlineArea ia) { 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(); ) { for (Iterator<InlineParent> it = ich.iterator(); it.hasNext(); ) {
InlineParent ic = it.next(); InlineParent ic = it.next();
InlineParent ic0 = icOrig.empty() ? null : icOrig.peek(); InlineParent ic0 = icOrig.empty() ? null : icOrig.peek();
if (ic0 == null) { if (ic0 == null) {
assert icNew.empty(); assert icNew.empty();
} else if (ic != ic0) { } else if (ic != ic0) {
assert ! icNew.empty();
assert !icNew.empty();
InlineParent icO0 = icOrig.pop(); InlineParent icO0 = icOrig.pop();
InlineParent icN0 = icNew.pop(); InlineParent icN0 = icNew.pop();
assert icO0 != null; assert icO0 != null;
} else { } else {
icNew.peek().addChildArea(icN0); icNew.peek().addChildArea(icN0);
} }
if (! icOrig.empty() && (icOrig.peek() == ic)) {
if (!icOrig.empty() && (icOrig.peek() == ic)) {
break; break;
} }
} else { } else {
} }
} }
} else { // finish all inline containers } else { // finish all inline containers
while (! icNew.empty()) {
while (!icNew.empty()) {
InlineParent icO0 = icOrig.pop(); InlineParent icO0 = icOrig.pop();
InlineParent icN0 = icNew.pop(); InlineParent icN0 = icNew.pop();
assert icO0 != null; assert icO0 != null;
finishInlineContainer(); finishInlineContainer();
} }
private void update(List<InlineParent> ich, TextArea tc, InlineArea ia) { 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); pushInlineContainers(ich);
} }
if (tc != null) { if (tc != null) {
Area a = ia.getParentArea(); Area a = ia.getParentArea();
while (a != null) { while (a != null) {
if (a instanceof InlineArea) { if (a instanceof InlineArea) {
if ((a instanceof InlineParent) && ! (a instanceof TextArea)) {
if ((a instanceof InlineParent) && !(a instanceof TextArea)) {
ich.add((InlineParent) a); ich.add((InlineParent) a);
} }
a = ((InlineArea) a) .getParentArea(); a = ((InlineArea) a) .getParentArea();

+ 28
- 41
src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java Voir le fichier

import org.apache.fop.traits.Direction; import org.apache.fop.traits.Direction;
import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: EmptyForIteratorPadCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: ParameterNumberCheck


/** /**
* <p>The <code>UnicodeBidiAlgorithm</code> class implements functionality prescribed by * <p>The <code>UnicodeBidiAlgorithm</code> class implements functionality prescribed by
case RLE: // start right-to-left embedding case RLE: // start right-to-left embedding
case LRO: // start left-to-right override case LRO: // start left-to-right override
case RLO: // start right-to-left 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 { } 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 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 case B: // paragraph separator
{
el = ec = defaultLevel;
ei = 0;
break;
}
el = ec = defaultLevel;
ei = 0;
break;
default: default:
{
el = ec;
break;
}
el = ec;
break;
} }
switch (bc) { switch (bc) {
case BN: case BN:


private static boolean isRetainedFormatting(int[] ca, int s, int e) { private static boolean isRetainedFormatting(int[] ca, int s, int e) {
for (int i = s; i < e; i++) { for (int i = s; i < e; i++) {
if (! isRetainedFormatting(ca[i])) {
if (!isRetainedFormatting(ca[i])) {
return false; return false;
} }
} }
} else { } else {
chOut = chIn; chOut = chIn;
} }
if (! triggered && triggersBidi(chOut)) {
if (!triggered && triggersBidi(chOut)) {
triggered = true; triggered = true;
} }
if ((chOut & 0xFF0000) == 0) { if ((chOut & 0xFF0000) == 0) {

+ 5
- 6
src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java Voir le fichier

import java.util.List; import java.util.List;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>Base class implementation of glyph class table.</p> * <p>Base class implementation of glyph class table.</p>
} else { } else {
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (! (o instanceof Integer)) {
if (!(o instanceof Integer)) {
return false; return false;
} }
} }
} else { } else {
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (! (o instanceof MappingRange)) {
if (!(o instanceof MappingRange)) {
return false; return false;
} }
} }
} else { } else {
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (! (o instanceof GlyphCoverageTable)) {
if (!(o instanceof GlyphCoverageTable)) {
return false; return false;
} }
} }
if (it.hasNext()) { if (it.hasNext()) {
Object o = it.next(); Object o = it.next();
if (o instanceof Integer) { if (o instanceof Integer) {
firstGlyph = ((Integer) o) . intValue();
firstGlyph = ((Integer) o) .intValue();
} else { } else {
throw new AdvancedTypographicTableFormatException("illegal entry, first entry must be Integer denoting first glyph value, but is: " + o); throw new AdvancedTypographicTableFormatException("illegal entry, first entry must be Integer denoting first glyph value, but is: " + o);
} }
while (it.hasNext()) { while (it.hasNext()) {
Object o = it.next(); Object o = it.next();
if (o instanceof Integer) { if (o instanceof Integer) {
int gc = ((Integer) o) . intValue();
int gc = ((Integer) o) .intValue();
gca [ i++ ] = gc; gca [ i++ ] = gc;
if (gc > gcMax) { if (gc > gcMax) {
gcMax = gc; gcMax = gc;

+ 3
- 5
src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java Voir le fichier

import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>.Base class implementation of glyph coverage table.</p> * <p>.Base class implementation of glyph coverage table.</p>
} else { } else {
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (! (o instanceof Integer)) {
if (!(o instanceof Integer)) {
return false; return false;
} }
} }
} else { } else {
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (! (o instanceof MappingRange)) {
if (!(o instanceof MappingRange)) {
return false; return false;
} }
} }
for (Iterator it = entries.iterator(); it.hasNext();) { for (Iterator it = entries.iterator(); it.hasNext();) {
Object o = it.next(); Object o = it.next();
if (o instanceof Integer) { if (o instanceof Integer) {
int gid = ((Integer) o) . intValue();
int gid = ((Integer) o) .intValue();
if ((gid >= 0) && (gid < 65536)) { if ((gid >= 0) && (gid < 65536)) {
if (gid > gidMax) { if (gid > gidMax) {
map [ i++ ] = gidMax = gid; map [ i++ ] = gidMax = gid;

+ 0
- 1
src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java Voir le fichier

package org.apache.fop.complexscripts.fonts; package org.apache.fop.complexscripts.fonts;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: InnerAssignmentCheck


/** /**
* <p>The <code>GlyphDefinitionSubtable</code> implements an abstract base of a glyph definition subtable, * <p>The <code>GlyphDefinitionSubtable</code> implements an abstract base of a glyph definition subtable,

+ 0
- 1
src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java Voir le fichier

import org.apache.fop.complexscripts.scripts.ScriptProcessor; import org.apache.fop.complexscripts.scripts.ScriptProcessor;
import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**

+ 1
- 3
src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java Voir le fichier

import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;


// CSOFF: NoWhitespaceAfterCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
int mi; int mi;
if ((i = Arrays.binarySearch(sa, gid)) >= 0) { if ((i = Arrays.binarySearch(sa, gid)) >= 0) {
mi = getMappedIndex(gid, sa [ i ], ma [ i ]); // matches start of (some) range 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 mi = -1; // precedes first range
} else if (gid > ea [ --i ]) { } else if (gid > ea [ --i ]) {
mi = -1; // follows preceding (or last) range mi = -1; // follows preceding (or last) range

+ 0
- 1
src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java Voir le fichier

import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: ParameterNumberCheck


/** /**
* <p>The <code>GlyphPositioningState</code> implements an state object used during glyph positioning * <p>The <code>GlyphPositioningState</code> implements an state object used during glyph positioning

+ 3
- 5
src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java Voir le fichier

import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: ParameterNumberCheck


/** /**
* <p>The <code>GlyphPositioningSubtable</code> implements an abstract base of a glyph subtable, * <p>The <code>GlyphPositioningSubtable</code> implements an abstract base of a glyph subtable,
boolean appliedOneShot = false; boolean appliedOneShot = false;
while (ps.hasNext()) { while (ps.hasNext()) {
boolean applied = false; 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) { if (sequenceIndex < 0) {
applied = ps.apply(sta [ i ]); applied = ps.apply(sta [ i ]);
} else if (ps.getPosition() == (sequenceStart + sequenceIndex)) { } else if (ps.getPosition() == (sequenceStart + sequenceIndex)) {
} }
} }
} }
if (! applied || ! ps.didConsume()) {
if (!applied || !ps.didConsume()) {
ps.applyDefault(); ps.applyDefault();
} }
ps.next(); ps.next();

+ 52
- 55
src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphTester; import org.apache.fop.complexscripts.util.GlyphTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: ParameterNumberCheck


/** /**
* <p>The <code>GlyphPositioningTable</code> class is a glyph table that implements * <p>The <code>GlyphPositioningTable</code> class is a glyph table that implements
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, single entry must be a Value[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
Value[] va = (Value[]) o; Value[] va = (Value[]) o;
int offsetLast = counts[0] + counts[1]; int offsetLast = counts[0] + counts[1];
// skip any ignored glyphs prior to first non-ignored glyph // skip any ignored glyphs prior to first non-ignored glyph
for ( ; offset < offsetLast; ++offset) { for ( ; offset < offsetLast; ++offset) {
if (! ps.isIgnoredGlyph(offset)) {
if (!ps.isIgnoredGlyph(offset)) {
break; break;
} else { } else {
ps.consume(1); ps.consume(1);
} }
// skip any ignored glyphs prior to second non-ignored glyph // skip any ignored glyphs prior to second non-ignored glyph
for ( ; offset < offsetLast; ++offset) { for ( ; offset < offsetLast; ++offset) {
if (! ps.isIgnoredGlyph(offset)) {
if (!ps.isIgnoredGlyph(offset)) {
break; break;
} else { } else {
ps.consume(1); ps.consume(1);
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first (and only) entry must be a PairValues[][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
pvm = (PairValues[][]) o; pvm = (PairValues[][]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
cdt1 = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
cdt2 = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
nc1 = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
nc2 = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be a PairValues[][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
pvm = (PairValues[][]) o; pvm = (PairValues[][]) o;
int enw = ps.getWidth(gi2); int enw = ps.getWidth(gi2);
if ((exa != null) && (ena != null)) { if ((exa != null) && (ena != null)) {
Value v = ena.getAlignmentAdjustment(exa); Value v = ena.getAlignmentAdjustment(exa);
v.adjust(- enw, 0, 0, 0);
v.adjust(-enw, 0, 0, 0);
if (ps.adjust(v)) { if (ps.adjust(v)) {
ps.setAdjusted(true); ps.setAdjusted(true);
} }
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); 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 { } else {
aa = (Anchor[]) o; aa = (Anchor[]) o;
} }
MarkAnchor ma = getMarkAnchor(ciMark, giMark); MarkAnchor ma = getMarkAnchor(ciMark, giMark);
if (ma != null) { if (ma != null) {
for (int i = 0, n = ps.getPosition(); i < n; i++) { 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)) { if (ps.isMark(gi)) {
continue; continue;
} else { } else {
// start experimental fix for END OF AYAH in Lateef/Scheherazade // start experimental fix for END OF AYAH in Lateef/Scheherazade
int[] aa = ps.getAdjustment(); int[] aa = ps.getAdjustment();
if (aa[2] == 0) { 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 // end experimental fix for END OF AYAH in Lateef/Scheherazade
if (ps.adjust(v)) { if (ps.adjust(v)) {
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
bct = (GlyphCoverageTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
nmc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
maa = (MarkAnchor[]) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a Anchor[][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
bam = (Anchor[][]) o; bam = (Anchor[][]) o;
int mxc = getMaxComponentCount(); int mxc = getMaxComponentCount();
if (ma != null) { if (ma != null) {
for (int i = 0, n = ps.getPosition(); i < n; i++) { 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)) { if (ps.isMark(gi)) {
continue; continue;
} else { } else {
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
lct = (GlyphCoverageTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
nmc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
mxc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
maa = (MarkAnchor[]) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be a Anchor[][][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
lam = (Anchor[][][]) o; lam = (Anchor[][][]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 4 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphCoverageTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
mct2 = (GlyphCoverageTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
nmc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be a MarkAnchor[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
maa = (MarkAnchor[]) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be a Anchor[][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
mam = (Anchor[][]) o; mam = (Anchor[][]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
cdt = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
ngc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
icdt = (GlyphClassTable) o; 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()); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass());
} else { } else {
bcdt = (GlyphClassTable) o; 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()); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass());
} else { } else {
lcdt = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
ngc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
boolean first = true; boolean first = true;
sb.append("{ "); sb.append("{ ");
if (xPlacement != 0) { if (xPlacement != 0) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("xPlacement = " + xPlacement); sb.append("xPlacement = " + xPlacement);
} }
if (yPlacement != 0) { if (yPlacement != 0) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("yPlacement = " + yPlacement); sb.append("yPlacement = " + yPlacement);
} }
if (xAdvance != 0) { if (xAdvance != 0) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("xAdvance = " + xAdvance); sb.append("xAdvance = " + xAdvance);
} }
if (yAdvance != 0) { if (yAdvance != 0) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("yAdvance = " + yAdvance); sb.append("yAdvance = " + yAdvance);
} }
if (xPlaDevice != null) { if (xPlaDevice != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("xPlaDevice = " + xPlaDevice); sb.append("xPlaDevice = " + xPlaDevice);
} }
if (yPlaDevice != null) { if (yPlaDevice != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("xPlaDevice = " + yPlaDevice); sb.append("xPlaDevice = " + yPlaDevice);
} }
if (xAdvDevice != null) { if (xAdvDevice != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("xAdvDevice = " + xAdvDevice); sb.append("xAdvDevice = " + xAdvDevice);
} }
if (yAdvDevice != null) { if (yAdvDevice != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
boolean first = true; boolean first = true;
sb.append("{ "); sb.append("{ ");
if (glyph != 0) { if (glyph != 0) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("glyph = " + glyph); sb.append("glyph = " + glyph);
} }
if (value1 != null) { if (value1 != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;
sb.append("value1 = " + value1); sb.append("value1 = " + value1);
} }
if (value2 != null) { if (value2 != null) {
if (! first) {
if (!first) {
sb.append(", "); sb.append(", ");
} else { } else {
first = false; first = false;

+ 10
- 11
src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java Voir le fichier

import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>The <code>GlyphProcessingState</code> implements a common, base state object used during glyph substitution * <p>The <code>GlyphProcessingState</code> implements a common, base state object used during glyph substitution
int start = index + offset; int start = index + offset;
if (start < 0) { if (start < 0) {
throw new IndexOutOfBoundsException("will attempt index at " + start); 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)); throw new IndexOutOfBoundsException("will attempt index at " + (start + count));
} else if (reverseOrder && ((start + 1) < count)) { } else if (reverseOrder && ((start + 1) < count)) {
throw new IndexOutOfBoundsException("will attempt index at " + (start - count)); throw new IndexOutOfBoundsException("will attempt index at " + (start - count));
} else if (glyphs.length != count) { } else if (glyphs.length != count) {
throw new IllegalArgumentException("glyphs array is non-null, but its length (" + glyphs.length + "), is not equal to count (" + 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); return getGlyphsForward(start, count, ignoreTester, glyphs, counts);
} else { } else {
return getGlyphsReverse(start, count, ignoreTester, glyphs, counts); return getGlyphsReverse(start, count, ignoreTester, glyphs, counts);
if (gi == 65535) { if (gi == 65535) {
ignored++; ignored++;
} else { } else {
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) {
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) {
glyphs [ counted++ ] = gi; glyphs [ counted++ ] = gi;
} else { } else {
ignored++; ignored++;
if (gi == 65535) { if (gi == 65535) {
ignored++; ignored++;
} else { } else {
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) {
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) {
glyphs [ counted++ ] = gi; glyphs [ counted++ ] = gi;
} else { } else {
ignored++; ignored++;
int start = index + offset; int start = index + offset;
if ((start < 0) || (start > indexLast)) { if ((start < 0) || (start > indexLast)) {
return new int[] { 0, 0 }; return new int[] { 0, 0 };
} else if (! reverseOrder) {
} else if (!reverseOrder) {
return getGlyphsAvailableForward(start, ignoreTester); return getGlyphsAvailableForward(start, ignoreTester);
} else { } else {
return getGlyphsAvailableReverse(start, ignoreTester); return getGlyphsAvailableReverse(start, ignoreTester);
int start = index + offset; int start = index + offset;
if (start < 0) { if (start < 0) {
throw new IndexOutOfBoundsException("will attempt index at " + start); 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)); throw new IndexOutOfBoundsException("will attempt index at " + (start + count));
} else if (reverseOrder && ((start + 1) < count)) { } else if (reverseOrder && ((start + 1) < count)) {
throw new IndexOutOfBoundsException("will attempt index at " + (start - count)); throw new IndexOutOfBoundsException("will attempt index at " + (start - count));
} else if (associations.length != count) { } else if (associations.length != count) {
throw new IllegalArgumentException("associations array is non-null, but its length (" + associations.length + "), is not equal to count (" + 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); return getAssociationsForward(start, count, ignoreTester, associations, counts);
} else { } else {
return getAssociationsReverse(start, count, ignoreTester, associations, counts); return getAssociationsReverse(start, count, ignoreTester, associations, counts);
if (gi == 65535) { if (gi == 65535) {
ignored++; ignored++;
} else { } else {
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) {
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) {
if (k < count) { if (k < count) {
associations [ k++ ] = getAssociation(i - index); associations [ k++ ] = getAssociation(i - index);
counted++; counted++;
if (gi == 65535) { if (gi == 65535) {
ignored++; ignored++;
} else { } else {
if ((ignoreTester == null) || ! ignoreTester.test(gi, getLookupFlags())) {
if ((ignoreTester == null) || !ignoreTester.test(gi, getLookupFlags())) {
if (k < count) { if (k < count) {
associations [ k++ ] = getAssociation(i - index); associations [ k++ ] = getAssociation(i - index);
counted++; counted++;
for (int i = 0, n = ngt; i < n; i++) { for (int i = 0, n = ngt; i < n; i++) {
GlyphTester gt = gta [ i ]; GlyphTester gt = gta [ i ];
if (gt != null) { if (gt != null) {
if (! gt.test(gi, flags)) {
if (!gt.test(gi, flags)) {
return false; return false;
} }
} }

+ 1
- 2
src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java Voir le fichier

import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>The <code>GlyphSubstitutionState</code> implements an state object used during glyph substitution * <p>The <code>GlyphSubstitutionState</code> implements an state object used during glyph substitution
* @param predication a predication value to add to association A if predications enabled * @param predication a predication value to add to association A if predications enabled
*/ */
public void putGlyph(int glyph, GlyphSequence.CharAssociation a, Object predication) { public void putGlyph(int glyph, GlyphSequence.CharAssociation a, Object predication) {
if (! ogb.hasRemaining()) {
if (!ogb.hasRemaining()) {
ogb = growBuffer(ogb); ogb = growBuffer(ogb);
} }
ogb.put(glyph); ogb.put(glyph);

+ 3
- 4
src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java Voir le fichier

import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>The <code>GlyphSubstitutionSubtable</code> implements an abstract base of a glyph substitution subtable, * <p>The <code>GlyphSubstitutionSubtable</code> implements an abstract base of a glyph substitution subtable,
boolean appliedOneShot = false; boolean appliedOneShot = false;
while (ss.hasNext()) { while (ss.hasNext()) {
boolean applied = false; 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) { if (sequenceIndex < 0) {
applied = ss.apply(sta [ i ]); applied = ss.apply(sta [ i ]);
} else if (ss.getPosition() == (sequenceStart + sequenceIndex)) { } else if (ss.getPosition() == (sequenceStart + sequenceIndex)) {
} }
} }
} }
if (! applied || ! ss.didConsume()) {
if (!applied || !ss.didConsume()) {
ss.applyDefault(); ss.applyDefault();
} }
ss.next(); ss.next();

+ 14
- 16
src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.GlyphTester; import org.apache.fop.complexscripts.util.GlyphTester;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>The <code>GlyphSubstitutionTable</code> class is a glyph table that implements * <p>The <code>GlyphSubstitutionTable</code> class is a glyph table that implements
Object o = entries.get(0); Object o = entries.get(0);
int delta = 0; int delta = 0;
if (o instanceof Integer) { if (o instanceof Integer) {
delta = ((Integer) o) . intValue();
delta = ((Integer) o) .intValue();
} else { } else {
throw new AdvancedTypographicTableFormatException("illegal entries entry, must be Integer, but is: " + o); throw new AdvancedTypographicTableFormatException("illegal entries entry, must be Integer, but is: " + o);
} }
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an int[][], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
gsa = (int[][]) o; gsa = (int[][]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 3 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
cdt = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
ngc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 5 entries");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an GlyphClassTable, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
icdt = (GlyphClassTable) o; 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()); throw new AdvancedTypographicTableFormatException("illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass());
} else { } else {
bcdt = (GlyphClassTable) o; 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()); throw new AdvancedTypographicTableFormatException("illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass());
} else { } else {
lcdt = (GlyphClassTable) o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fourth entry must be an Integer, but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
ngc = ((Integer)(o)).intValue(); 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)); throw new AdvancedTypographicTableFormatException("illegal entries, fifth entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;
throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry"); throw new AdvancedTypographicTableFormatException("illegal entries, " + entries.size() + " entries present, but requires 1 entry");
} else { } else {
Object o; 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)); throw new AdvancedTypographicTableFormatException("illegal entries, first entry must be an RuleSet[], but is: " + ((o != null) ? o.getClass() : null));
} else { } else {
rsa = (RuleSet[]) o; rsa = (RuleSet[]) o;

+ 0
- 1
src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java Voir le fichier

import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**

+ 21
- 28
src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: EmptyForIteratorPadCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: ParameterNumberCheck
// CSOFF: SimplifyBooleanReturnCheck


/** /**
* <p>Base class for all advanced typographic glyph tables.</p> * <p>Base class for all advanced typographic glyph tables.</p>
* @param lookups map from lookup specs to lookup tables * @param lookups map from lookup specs to lookup tables
*/ */
public GlyphTable(GlyphTable gdef, Map/*<LookupSpec,List<String>>*/ lookups) { 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"); throw new AdvancedTypographicTableFormatException("bad glyph definition table");
} else if (lookups == null) { } else if (lookups == null) {
throw new AdvancedTypographicTableFormatException("lookups must be non-null map"); throw new AdvancedTypographicTableFormatException("lookups must be non-null map");
* create resulting cached state. * create resulting cached state.
*/ */
protected void freezeSubtables() { protected void freezeSubtables() {
if (! frozen) {
if (!frozen) {
for (Iterator it = lookupTables.values().iterator(); it.hasNext(); ) { for (Iterator it = lookupTables.values().iterator(); it.hasNext(); ) {
LookupTable lt = (LookupTable) it.next(); LookupTable lt = (LookupTable) it.next();
lt.freezeSubtables(lookupTables); lt.freezeSubtables(lookupTables);
List/*<LookupSpec>*/ matches = new ArrayList/*<LookupSpec>*/(); List/*<LookupSpec>*/ matches = new ArrayList/*<LookupSpec>*/();
for (Iterator it = keys.iterator(); it.hasNext();) { for (Iterator it = keys.iterator(); it.hasNext();) {
LookupSpec ls = (LookupSpec) it.next(); LookupSpec ls = (LookupSpec) it.next();
if (! "*".equals(script)) {
if (! ls.getScript().equals(script)) {
if (!"*".equals(script)) {
if (!ls.getScript().equals(script)) {
continue; continue;
} }
} }
if (! "*".equals(language)) {
if (! ls.getLanguage().equals(language)) {
if (!"*".equals(language)) {
if (!ls.getLanguage().equals(language)) {
continue; continue;
} }
} }
if (! "*".equals(feature)) {
if (! ls.getFeature().equals(feature)) {
if (!"*".equals(feature)) {
if (!ls.getFeature().equals(feature)) {
continue; continue;
} }
} }
* @param permitWildcard if true the permit wildcard script, language, or feature * @param permitWildcard if true the permit wildcard script, language, or feature
*/ */
LookupSpec(String script, String language, String feature, boolean permitEmpty, boolean permitWildcard) { 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"); 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"); 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"); 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"); 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"); 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"); throw new AdvancedTypographicTableFormatException("feature must not be wildcard");
} }
this.script = script.trim(); this.script = script.trim();
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof LookupSpec) { if (o instanceof LookupSpec) {
LookupSpec l = (LookupSpec) o; LookupSpec l = (LookupSpec) o;
if (! l.script.equals(script)) {
if (!l.script.equals(script)) {
return false; return false;
} else if (! l.language.equals(language)) {
return false;
} else if (! l.feature.equals(feature)) {
} else if (!l.language.equals(language)) {
return false; return false;
} else { } else {
return true;
return l.feature.equals(feature);
} }
} else { } else {
return false; return false;
} }
} }
// append at end of list // append at end of list
if (! added && (subtable != null)) {
if (!added && (subtable != null)) {
subtables.add(subtable); subtables.add(subtable);
added = true; added = true;
} }
} }
if (subtables.size() > 0) { if (subtables.size() > 0) {
GlyphSubtable st = (GlyphSubtable) subtables.get(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); throw new AdvancedTypographicTableFormatException("subtable " + subtable + " is not compatible with subtable " + st);
} }
} }
* @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables
*/ */
public void freezeSubtables(Map/*<String,LookupTable>*/ lookupTables) { public void freezeSubtables(Map/*<String,LookupTable>*/ lookupTables) {
if (! frozen) {
if (!frozen) {
GlyphSubtable[] sta = getSubtables(); GlyphSubtable[] sta = getSubtables();
resolveLookupReferences(sta, lookupTables); resolveLookupReferences(sta, lookupTables);
this.subtablesArray = sta; this.subtablesArray = sta;
Class c = r0.getClass(); Class c = r0.getClass();
for (int i = 1, n = rules.length; i < n; i++) { for (int i = 1, n = rules.length; i < n; i++) {
Rule r = rules[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()); throw new AdvancedTypographicTableFormatException("rules[" + i + "] is not an instance of " + c.getName());
} }
} }

+ 45
- 48
src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java Voir le fichier

import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


import org.apache.fop.fonts.truetype.FontFileReader; 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 // CSOFF: LineLengthCheck


/** /**
// logging state // logging state
private static Log log = LogFactory.getLog(OTFAdvancedTypographicTableReader.class); private static Log log = LogFactory.getLog(OTFAdvancedTypographicTableReader.class);
// instance state // instance state
private TTFFile ttf; // parent font file reader
private OpenFont otf; // parent font file reader
private FontFileReader in; // input reader private FontFileReader in; // input reader
private GlyphDefinitionTable gdef; // glyph definition table private GlyphDefinitionTable gdef; // glyph definition table
private GlyphSubstitutionTable gsub; // glyph substitution table private GlyphSubstitutionTable gsub; // glyph substitution table
* @param ttf parent font file reader (must be non-null) * @param ttf parent font file reader (must be non-null)
* @param in 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; assert in != null;
this.ttf = ttf;
this.otf = otf;
this.in = in; this.in = in;
} }


return gpos; 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); in.seekSet(langSysTable);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " lang sys table: " + langSysTag); log.debug(tableTag + " lang sys table: " + langSysTag);


private static String defaultTag = "dflt"; 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); in.seekSet(scriptTable);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " script table: " + scriptTag); log.debug(tableTag + " script table: " + scriptTag);
seLanguages = null; seLanguages = null;
} }


private void readScriptList(TTFTableName tableTag, long scriptList) throws IOException {
private void readScriptList(OFTableName tableTag, long scriptList) throws IOException {
in.seekSet(scriptList); in.seekSet(scriptList);
// read script record count // read script record count
int ns = in.readTTFUShort(); int ns = in.readTTFUShort();
} }
} }


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); in.seekSet(featureTable);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " feature table: " + featureTag); log.debug(tableTag + " feature table: " + featureTag);
seFeatures.put("f" + featureIndex, new Object[] { featureTag, lul }); 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); in.seekSet(featureList);
// read feature record count // read feature record count
int nf = in.readTTFUShort(); int nf = in.readTTFUShort();
// XPlacement // XPlacement
int xp; int xp;
if ((valueFormat & GlyphPositioningTable.Value.X_PLACEMENT) != 0) { if ((valueFormat & GlyphPositioningTable.Value.X_PLACEMENT) != 0) {
xp = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
xp = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
} else { } else {
xp = 0; xp = 0;
} }
// YPlacement // YPlacement
int yp; int yp;
if ((valueFormat & GlyphPositioningTable.Value.Y_PLACEMENT) != 0) { if ((valueFormat & GlyphPositioningTable.Value.Y_PLACEMENT) != 0) {
yp = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
yp = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
} else { } else {
yp = 0; yp = 0;
} }
// XAdvance // XAdvance
int xa; int xa;
if ((valueFormat & GlyphPositioningTable.Value.X_ADVANCE) != 0) { if ((valueFormat & GlyphPositioningTable.Value.X_ADVANCE) != 0) {
xa = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
xa = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
} else { } else {
xa = 0; xa = 0;
} }
// YAdvance // YAdvance
int ya; int ya;
if ((valueFormat & GlyphPositioningTable.Value.Y_ADVANCE) != 0) { if ((valueFormat & GlyphPositioningTable.Value.Y_ADVANCE) != 0) {
ya = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
ya = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
} else { } else {
ya = 0; ya = 0;
} }
int af = in.readTTFUShort(); int af = in.readTTFUShort();
if (af == 1) { if (af == 1) {
// read x coordinate // read x coordinate
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
// read y coordinate // read y coordinate
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
a = new GlyphPositioningTable.Anchor(x, y); a = new GlyphPositioningTable.Anchor(x, y);
} else if (af == 2) { } else if (af == 2) {
// read x coordinate // read x coordinate
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
// read y coordinate // read y coordinate
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
// read anchor point index // read anchor point index
int ap = in.readTTFUShort(); int ap = in.readTTFUShort();
a = new GlyphPositioningTable.Anchor(x, y, ap); a = new GlyphPositioningTable.Anchor(x, y, ap);
} else if (af == 3) { } else if (af == 3) {
// read x coordinate // read x coordinate
int x = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int x = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
// read y coordinate // read y coordinate
int y = ttf.convertTTFUnit2PDFUnit(in.readTTFShort());
int y = otf.convertTTFUnit2PDFUnit(in.readTTFShort());
// read x device table offset // read x device table offset
int xdo = in.readTTFUShort(); int xdo = in.readTTFUShort();
// read y device table offset // read y device table offset
resetATSubState(); 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); in.seekSet(lookupTable);
// read lookup type // read lookup type
int lt = in.readTTFUShort(); int lt = in.readTTFUShort();
} }
} }


private void readLookupList(TTFTableName tableTag, long lookupList) throws IOException {
private void readLookupList(OFTableName tableTag, long lookupList) throws IOException {
in.seekSet(lookupList); in.seekSet(lookupList);
// read lookup record count // read lookup record count
int nl = in.readTTFUShort(); int nl = in.readTTFUShort();
* @param lookupList offset to lookup list from beginning of font file * @param lookupList offset to lookup list from beginning of font file
* @throws IOException In case of a I/O problem * @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) { if (scriptList > 0) {
readScriptList(tableTag, scriptList); readScriptList(tableTag, scriptList);
} }
} }
} }


private void readGDEFClassDefTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
private void readGDEFClassDefTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
initATSubState(); initATSubState();
in.seekSet(subtableOffset); in.seekSet(subtableOffset);
// subtable is a bare class definition table // subtable is a bare class definition table
resetATSubState(); resetATSubState();
} }


private void readGDEFAttachmentTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
private void readGDEFAttachmentTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
initATSubState(); initATSubState();
in.seekSet(subtableOffset); in.seekSet(subtableOffset);
// read coverage offset // read coverage offset
resetATSubState(); resetATSubState();
} }


private void readGDEFLigatureCaretTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
private void readGDEFLigatureCaretTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
initATSubState(); initATSubState();
in.seekSet(subtableOffset); in.seekSet(subtableOffset);
// read coverage offset // read coverage offset
resetATSubState(); resetATSubState();
} }


private void readGDEFMarkAttachmentTable(TTFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
private void readGDEFMarkAttachmentTable(OFTableName tableTag, int lookupSequence, long subtableOffset) throws IOException {
initATSubState(); initATSubState();
in.seekSet(subtableOffset); in.seekSet(subtableOffset);
// subtable is a bare class definition table // subtable is a bare class definition table
resetATSubState(); 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(); initATSubState();
in.seekSet(subtableOffset); in.seekSet(subtableOffset);
// skip over format (already known) // skip over format (already known)
resetATSubState(); 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); in.seekSet(subtableOffset);
// read mark set subtable format // read mark set subtable format
int sf = in.readTTFUShort(); int sf = in.readTTFUShort();
* @throws IOException In case of a I/O problem * @throws IOException In case of a I/O problem
*/ */
private void readGDEF() throws IOException { private void readGDEF() throws IOException {
TTFTableName tableTag = TTFTableName.GDEF;
OFTableName tableTag = OFTableName.GDEF;
// Initialize temporary state // Initialize temporary state
initATState(); initATState();
// Read glyph definition (GDEF) table // Read glyph definition (GDEF) table
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag);
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag);
if (gdef != null) { if (gdef != null) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + ": ignoring duplicate table"); log.debug(tableTag + ": ignoring duplicate table");
} }
} else if (dirTab != null) { } else if (dirTab != null) {
ttf.seekTab(in, tableTag, 0);
otf.seekTab(in, tableTag, 0);
long version = in.readTTFULong(); long version = in.readTTFULong();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536));
* @throws IOException In case of a I/O problem * @throws IOException In case of a I/O problem
*/ */
private void readGSUB() throws IOException { private void readGSUB() throws IOException {
TTFTableName tableTag = TTFTableName.GSUB;
OFTableName tableTag = OFTableName.GSUB;
// Initialize temporary state // Initialize temporary state
initATState(); initATState();
// Read glyph substitution (GSUB) table // Read glyph substitution (GSUB) table
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag);
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag);
if (gpos != null) { if (gpos != null) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + ": ignoring duplicate table"); log.debug(tableTag + ": ignoring duplicate table");
} }
} else if (dirTab != null) { } else if (dirTab != null) {
ttf.seekTab(in, tableTag, 0);
otf.seekTab(in, tableTag, 0);
int version = in.readTTFLong(); int version = in.readTTFLong();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536));
* @throws IOException In case of a I/O problem * @throws IOException In case of a I/O problem
*/ */
private void readGPOS() throws IOException { private void readGPOS() throws IOException {
TTFTableName tableTag = TTFTableName.GPOS;
OFTableName tableTag = OFTableName.GPOS;
// Initialize temporary state // Initialize temporary state
initATState(); initATState();
// Read glyph positioning (GPOS) table // Read glyph positioning (GPOS) table
TTFDirTabEntry dirTab = ttf.getDirectoryEntry(tableTag);
OFDirTabEntry dirTab = otf.getDirectoryEntry(tableTag);
if (gpos != null) { if (gpos != null) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + ": ignoring duplicate table"); log.debug(tableTag + ": ignoring duplicate table");
} }
} else if (dirTab != null) { } else if (dirTab != null) {
ttf.seekTab(in, tableTag, 0);
otf.seekTab(in, tableTag, 0);
int version = in.readTTFLong(); int version = in.readTTFLong();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536)); log.debug(tableTag + " version: " + (version / 65536) + "." + (version % 65536));
} else { } else {
boolean first = true; boolean first = true;
for (int i = 0; i < ia.length; i++) { for (int i = 0; i < ia.length; i++) {
if (! first) {
if (!first) {
sb.append(' '); sb.append(' ');
} else { } else {
first = false; first = false;

+ 9
- 13
src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
} else { } else {
int s = a.getStart(); int s = a.getStart();
int e = a.getEnd(); int e = a.getEnd();
if (! hasFinalPrecedingContext(ca, nc, s, e)) {
if (!hasFinalPrecedingContext(ca, nc, s, e)) {
return false; return false;
} else if (forcesFinalThisContext(ca, nc, s, e)) { } else if (forcesFinalThisContext(ca, nc, s, e)) {
return true; return true;
} else if (! hasFinalFollowingContext(ca, nc, s, e)) {
} else if (!hasFinalFollowingContext(ca, nc, s, e)) {
return false; return false;
} else { } else {
return true; return true;
} else { } else {
int s = a.getStart(); int s = a.getStart();
int e = a.getEnd(); int e = a.getEnd();
if (! hasInitialPrecedingContext(ca, nc, s, e)) {
if (!hasInitialPrecedingContext(ca, nc, s, e)) {
return false; return false;
} else if (! hasInitialFollowingContext(ca, nc, s, e)) {
} else if (!hasInitialFollowingContext(ca, nc, s, e)) {
return false; return false;
} else { } else {
return true; return true;
} else { } else {
int s = a.getStart(); int s = a.getStart();
int e = a.getEnd(); int e = a.getEnd();
if (! hasLigaturePrecedingContext(ca, nc, s, e)) {
if (!hasLigaturePrecedingContext(ca, nc, s, e)) {
return false; return false;
} else if (! hasLigatureFollowingContext(ca, nc, s, e)) {
} else if (!hasLigatureFollowingContext(ca, nc, s, e)) {
return false; return false;
} else { } else {
return true; return true;
} else { } else {
int s = a.getStart(); int s = a.getStart();
int e = a.getEnd(); int e = a.getEnd();
if (! hasMedialPrecedingContext(ca, nc, s, e)) {
if (!hasMedialPrecedingContext(ca, nc, s, e)) {
return false; return false;
} else if (! hasMedialThisContext(ca, nc, s, e)) {
} else if (!hasMedialThisContext(ca, nc, s, e)) {
return false; return false;
} else if (! hasMedialFollowingContext(ca, nc, s, e)) {
} else if (!hasMedialFollowingContext(ca, nc, s, e)) {
return false; return false;
} else { } else {
return true; return true;

+ 11
- 16
src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java Voir le fichier



import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: WhitespaceAfter
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
} }


private static boolean containsHalfConsonant(GlyphSequence gs, int k) { 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; return (half != null) ? half.booleanValue() : false;
} }


// first candidate target is after first non-half consonant // first candidate target is after first non-half consonant
for (int i = 0; i < ng; i++) { for (int i = 0; i < ng; i++) {
if ((i != source) && containsConsonant(gs, i)) { if ((i != source) && containsConsonant(gs, i)) {
if (! containsHalfConsonant(gs, i)) {
if (!containsHalfConsonant(gs, i)) {
c1 = i + 1; c1 = i + 1;
break; break;
} }
} }
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark // 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++) { 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; c2 = i + 1;
} else if (containsOtherMark(gs, i)) { } else if (containsOtherMark(gs, i)) {
c2 = i; c2 = i;
} }


private static boolean containsReph(GlyphSequence gs, int k) { 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; return (rphf != null) ? rphf.booleanValue() : false;
} }


} }
} }
static boolean isC(int c) { static boolean isC(int c) {
return isType(c,C_C);
return isType(c, C_C);
} }
static boolean isR(int 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) { static boolean isV(int c) {
return isType(c,C_V);
return isType(c, C_V);
} }
static boolean isN(int c) { static boolean isN(int c) {
return c == 0x093C; return c == 0x093C;
return c == 0x094D; return c == 0x094D;
} }
static boolean isM(int c) { static boolean isM(int c) {
return isType(c,C_M);
return isType(c, C_M);
} }
static boolean isPreM(int c) { 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) { static boolean isX(int c) {
switch (typeOf(c)) { switch (typeOf(c)) {
} }
} }
static boolean hasR(int c) { static boolean hasR(int c) {
return hasFlag(c,C_R);
return hasFlag(c, C_R);
} }
static boolean hasN(int c) { static boolean hasN(int c) {
return hasFlag(c,C_N);
return hasFlag(c, C_N);
} }


} }

+ 11
- 16
src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java Voir le fichier



import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: WhitespaceAfter
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
} }


private static boolean containsHalfConsonant(GlyphSequence gs, int k) { 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; return (half != null) ? half.booleanValue() : false;
} }


// first candidate target is after first non-half consonant // first candidate target is after first non-half consonant
for (int i = 0; i < ng; i++) { for (int i = 0; i < ng; i++) {
if ((i != source) && containsConsonant(gs, i)) { if ((i != source) && containsConsonant(gs, i)) {
if (! containsHalfConsonant(gs, i)) {
if (!containsHalfConsonant(gs, i)) {
c1 = i + 1; c1 = i + 1;
break; break;
} }
} }
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark // 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++) { 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; c2 = i + 1;
} else if (containsOtherMark(gs, i)) { } else if (containsOtherMark(gs, i)) {
c2 = i; c2 = i;
} }


private static boolean containsReph(GlyphSequence gs, int k) { 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; return (rphf != null) ? rphf.booleanValue() : false;
} }


} }
} }
static boolean isC(int c) { static boolean isC(int c) {
return isType(c,C_C);
return isType(c, C_C);
} }
static boolean isR(int 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) { static boolean isV(int c) {
return isType(c,C_V);
return isType(c, C_V);
} }
static boolean isN(int c) { static boolean isN(int c) {
return c == 0x0ABC; return c == 0x0ABC;
return c == 0x0ACD; return c == 0x0ACD;
} }
static boolean isM(int c) { static boolean isM(int c) {
return isType(c,C_M);
return isType(c, C_M);
} }
static boolean isPreM(int c) { 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) { static boolean isX(int c) {
switch (typeOf(c)) { switch (typeOf(c)) {
} }
} }
static boolean hasR(int c) { static boolean hasR(int c) {
return hasFlag(c,C_R);
return hasFlag(c, C_R);
} }
static boolean hasN(int c) { static boolean hasN(int c) {
return hasFlag(c,C_N);
return hasFlag(c, C_N);
} }


} }

+ 11
- 16
src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java Voir le fichier

import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: WhitespaceAfter
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
} }


private static boolean containsHalfConsonant(GlyphSequence gs, int k) { 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; return (half != null) ? half.booleanValue() : false;
} }


// first candidate target is after first non-half consonant // first candidate target is after first non-half consonant
for (int i = 0; i < ng; i++) { for (int i = 0; i < ng; i++) {
if ((i != source) && containsConsonant(gs, i)) { if ((i != source) && containsConsonant(gs, i)) {
if (! containsHalfConsonant(gs, i)) {
if (!containsHalfConsonant(gs, i)) {
c1 = i + 1; c1 = i + 1;
break; break;
} }
} }
// second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark // 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++) { 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; c2 = i + 1;
} else if (containsOtherMark(gs, i)) { } else if (containsOtherMark(gs, i)) {
c2 = i; c2 = i;
} }


private static boolean containsReph(GlyphSequence gs, int k) { 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; return (rphf != null) ? rphf.booleanValue() : false;
} }


} }
} }
static boolean isC(int c) { static boolean isC(int c) {
return isType(c,C_C);
return isType(c, C_C);
} }
static boolean isR(int 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) { static boolean isV(int c) {
return isType(c,C_V);
return isType(c, C_V);
} }
static boolean isN(int c) { static boolean isN(int c) {
return c == 0x0A3C; return c == 0x0A3C;
return c == 0x0A4D; return c == 0x0A4D;
} }
static boolean isM(int c) { static boolean isM(int c) {
return isType(c,C_M);
return isType(c, C_M);
} }
static boolean isPreM(int c) { 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) { static boolean isX(int c) {
switch (typeOf(c)) { switch (typeOf(c)) {
} }
} }
static boolean hasR(int c) { static boolean hasR(int c) {
return hasFlag(c,C_R);
return hasFlag(c, C_R);
} }
static boolean hasN(int c) { static boolean hasN(int c) {
return hasFlag(c,C_N);
return hasFlag(c, C_N);
} }


@Override @Override

+ 4
- 13
src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: EmptyForIteratorPadCheck
// CSOFF: WhitespaceAfterCheck
// CSOFF: ParameterNumberCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
} }


private GlyphSequence[] syllabize(GlyphSequence gs, String script, String language) { 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) { private GlyphSequence unsyllabize(GlyphSequence gs, GlyphSequence[] sa) {
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof Syllabizer) { if (o instanceof Syllabizer) {
Syllabizer s = (Syllabizer) o; Syllabizer s = (Syllabizer) o;
if (! s.script.equals(script)) {
return false;
} else if (! s.language.equals(language)) {
if (!s.script.equals(script)) {
return false; return false;
} else { } else {
return true;
return s.language.equals(language);
} }
} else { } else {
return false; return false;
} }
return d; 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) { static Syllabizer getSyllabizer(String script, String language, Class<? extends Syllabizer> syllabizerClass) {
String sid = makeSyllabizerId(script, language); String sid = makeSyllabizerId(script, language);
Syllabizer s = syllabizers.get(sid); Syllabizer s = syllabizers.get(sid);

+ 3
- 9
src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java Voir le fichier

import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester; import org.apache.fop.complexscripts.util.ScriptContextTester;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: ParameterNumberCheck
// CSOFF: SimplifyBooleanReturnCheck


/** /**
* <p>Abstract script processor base class for which an implementation of the substitution and positioning methods * <p>Abstract script processor base class for which an implementation of the substitution and positioning methods
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof AssembledLookupsKey) { if (o instanceof AssembledLookupsKey) {
AssembledLookupsKey k = (AssembledLookupsKey) o; AssembledLookupsKey k = (AssembledLookupsKey) o;
if (! table.equals(k.table)) {
if (!table.equals(k.table)) {
return false; 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; return false;
} else { } else {
return true;
return lookups.equals(k.lookups);
} }
} else { } else {
return false; return false;

+ 17
- 23
src/java/org/apache/fop/complexscripts/util/CharScript.java Voir le fichier



import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;


// CSOFF: AvoidNestedBlocksCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck
// CSOFF: SimplifyBooleanReturnCheck
// CSOFF: WhitespaceAfterCheck

/** /**
* <p>Script related utilities.</p> * <p>Script related utilities.</p>
* *
*/ */
public final class CharScript { public final class CharScript {


// CSOFF: LineLength

// //
// The following script codes are based on ISO 15924. Codes less than 1000 are // 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 // official assignments from 15924; those equal to or greater than 1000 are FOP
case SCRIPT_UNCODED: case SCRIPT_UNCODED:
break; break;
default: 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) { if (sMax < 0) {
* @return a script tag * @return a script tag
*/ */
public static String scriptTagFromCode(int code) { public static String scriptTagFromCode(int code) {
Map<Integer,String> m = getScriptTagsMap();
Map<Integer, String> m = getScriptTagsMap();
if (m != null) { if (m != null) {
String tag; String tag;
if ((tag = m.get(Integer.valueOf(code))) != null) { if ((tag = m.get(Integer.valueOf(code))) != null) {
* @return a script code * @return a script code
*/ */
public static int scriptCodeFromTag(String tag) { public static int scriptCodeFromTag(String tag) {
Map<String,Integer> m = getScriptCodeMap();
Map<String, Integer> m = getScriptCodeMap();
if (m != null) { if (m != null) {
Integer c; Integer c;
if ((c = m.get(tag)) != null) { if ((c = m.get(tag)) != null) {
} }
} }


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) { private static void putScriptTag(Map tm, Map cm, int code, String tag) {
assert tag != null; assert tag != null;
} }


private static void makeScriptMaps() { 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_HEBREW, "hebr");
putScriptTag(tm, cm, SCRIPT_MONGOLIAN, "mong"); putScriptTag(tm, cm, SCRIPT_MONGOLIAN, "mong");
putScriptTag(tm, cm, SCRIPT_ARABIC, "arab"); putScriptTag(tm, cm, SCRIPT_ARABIC, "arab");
scriptCodeMap = cm; scriptCodeMap = cm;
} }


private static Map<Integer,String> getScriptTagsMap() {
private static Map<Integer, String> getScriptTagsMap() {
if (scriptTagsMap == null) { if (scriptTagsMap == null) {
makeScriptMaps(); makeScriptMaps();
} }
return scriptTagsMap; return scriptTagsMap;
} }


private static Map<String,Integer> getScriptCodeMap() {
private static Map<String, Integer> getScriptCodeMap() {
if (scriptCodeMap == null) { if (scriptCodeMap == null) {
makeScriptMaps(); makeScriptMaps();
} }

+ 8
- 11
src/java/org/apache/fop/complexscripts/util/GlyphSequence.java Voir le fichier

import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: WhitespaceAfterCheck
// CSOFF: NoWhitespaceAfterCheck


/** /**
* <p>A GlyphSequence encapsulates a sequence of character codes, a sequence of glyph codes, * <p>A GlyphSequence encapsulates a sequence of character codes, a sequence of glyph codes,
private final int offset; private final int offset;
private final int count; private final int count;
private final int[] subIntervals; private final int[] subIntervals;
private Map<String,Object> predications;
private Map<String, Object> predications;


// class state // class state
private static volatile Map<String,PredicationMerger> predicationMergers;
private static volatile Map<String, PredicationMerger> predicationMergers;


interface PredicationMerger { interface PredicationMerger {
Object merge(String key, Object v1, Object v2); Object merge(String key, Object v1, Object v2);
public boolean contained(int offset, int count) { public boolean contained(int offset, int count) {
int s = offset; int s = offset;
int e = offset + count; int e = offset + count;
if (! isDisjoint()) {
if (!isDisjoint()) {
int s0 = getStart(); int s0 = getStart();
int e0 = getEnd(); int e0 = getEnd();
return (s0 >= s) && (e0 <= e); return (s0 >= s) && (e0 <= e);
*/ */
public void setPredication(String key, Object value) { public void setPredication(String key, Object value) {
if (predications == null) { if (predications == null) {
predications = new HashMap<String,Object>();
predications = new HashMap<String, Object>();
} }
if (predications != null) { if (predications != null) {
predications.put(key, value); predications.put(key, value);
*/ */
public void mergePredication(String key, Object value) { public void mergePredication(String key, Object value) {
if (predications == null) { if (predications == null) {
predications = new HashMap<String,Object>();
predications = new HashMap<String, Object>();
} }
if (predications != null) { if (predications != null) {
if (predications.containsKey(key)) { if (predications.containsKey(key)) {
*/ */
public void mergePredications(CharAssociation ca) { public void mergePredications(CharAssociation ca) {
if (ca.predications != null) { 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()); mergePredication(e.getKey(), e.getValue());
} }
} }
try { try {
CharAssociation ca = (CharAssociation) super.clone(); CharAssociation ca = (CharAssociation) super.clone();
if (predications != null) { if (predications != null) {
ca.predications = new HashMap<String,Object>(predications);
ca.predications = new HashMap<String, Object>(predications);
} }
return ca; return ca;
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
*/ */
public static void setPredicationMerger(String key, PredicationMerger pm) { public static void setPredicationMerger(String key, PredicationMerger pm) {
if (predicationMergers == null) { if (predicationMergers == null) {
predicationMergers = new HashMap<String,PredicationMerger>();
predicationMergers = new HashMap<String, PredicationMerger>();
} }
if (predicationMergers != null) { if (predicationMergers != null) {
predicationMergers.put(key, pm); predicationMergers.put(key, pm);

+ 15
- 24
src/java/org/apache/fop/complexscripts/util/NumberConverter.java Voir le fichier

import java.util.List; import java.util.List;


// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck
// CSOFF: InnerAssignmentCheck
// CSOFF: NoWhitespaceAfterCheck
// CSOFF: AvoidNestedBlocksCheck


/** /**
* <p>Implementation of Number to String Conversion algorithm specified by * <p>Implementation of Number to String Conversion algorithm specified by
separators.add(token.toArray(new Integer [ token.size() ])); separators.add(token.toArray(new Integer [ token.size() ]));
} }
} }
if (! separators.isEmpty()) {
if (!separators.isEmpty()) {
this.prefix = separators.remove(0); this.prefix = separators.remove(0);
} }
if (! separators.isEmpty()) {
if (!separators.isEmpty()) {
this.suffix = separators.remove(separators.size() - 1); this.suffix = separators.remove(separators.size() - 1);
} }
this.separators = separators.toArray(new Integer [ separators.size() ] []); this.separators = separators.toArray(new Integer [ separators.size() ] []);
int s = token[0].intValue(); int s = token[0].intValue();
switch (s) { switch (s) {
case (int) '1': case (int) '1':
{
fn = formatNumberAsDecimal(number, (int) '1', 1);
break;
}
fn = formatNumberAsDecimal(number, (int) '1', 1);
break;
case (int) 'W': case (int) 'W':
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) '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
case (int) 'i': // handled as numeric special case (int) 'i': // handled as numeric special
default: 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')) { } else if ((token.length == 2) && (token[0] == (int) 'W') && (token[1] == (int) 'w')) {
fn = formatNumberAsWord(number, Character.TITLECASE_LETTER); fn = formatNumberAsWord(number, Character.TITLECASE_LETTER);

+ 0
- 1
src/java/org/apache/fop/complexscripts/util/UTF32.java Voir le fichier



import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;


// CSOFF: InnerAssignmentCheck


/** /**
* <p>UTF32 related utilities.</p> * <p>UTF32 related utilities.</p>

+ 4
- 1
src/java/org/apache/fop/fo/Constants.java Voir le fichier

/** Scope for table header */ /** Scope for table header */
int PR_X_HEADER_COLUMN = 290; int PR_X_HEADER_COLUMN = 290;


/** For specifying PDF optional content group (layer) binding. */
int PR_X_LAYER = 291;

/** Number of property constants defined */ /** Number of property constants defined */
int PROPERTY_COUNT = 290;
int PROPERTY_COUNT = 291;


// compound property constants // compound property constants



+ 7
- 0
src/java/org/apache/fop/fo/FOPropertyMapping.java Voir le fichier

m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO"));
m.setDefault("auto"); m.setDefault("auto");
addPropertyMaker("z-index", m); 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() { private void createShorthandProperties() {

+ 30
- 3
src/java/org/apache/fop/fo/FObj.java Voir le fichier

private int bidiLevel = -1; private int bidiLevel = -1;


// The value of properties relevant for all fo objects // The value of properties relevant for all fo objects
private String id = null;
private String id;
private String layer;
// End of property values // End of property values


/** /**
String attributeName = attList.getQName(i); String attributeName = attList.getQName(i);
String attributeValue = attList.getValue(i); String attributeValue = attList.getValue(i);
Property prop = propertyList.getPropertyForAttribute(attList, attributeName, attributeValue); Property prop = propertyList.getPropertyForAttribute(attList, attributeName, attributeValue);
if (prop.equals(value)) {
if (prop != null && prop.equals(value)) {
return attributeName; return attributeName;
} }
} }
*/ */
public void bind(PropertyList pList) throws FOPException { public void bind(PropertyList pList) throws FOPException {
id = pList.get(PR_ID).getString(); id = pList.get(PR_ID).getString();
layer = pList.get(PR_X_LAYER).getString();
} }


/** /**
return (id != null && id.length() > 0); 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} */ /** {@inheritDoc} */
public String getNamespaceURI() { public String getNamespaceURI() {
return FOElementMapping.URI; return FOElementMapping.URI;
if (bidiLevel >= 0) { if (bidiLevel >= 0) {
if ((this.bidiLevel < 0) || (bidiLevel < this.bidiLevel)) { if ((this.bidiLevel < 0) || (bidiLevel < this.bidiLevel)) {
this.bidiLevel = bidiLevel; this.bidiLevel = bidiLevel;
if (parent != null) {
if ((parent != null) && !isBidiPropagationBoundary()) {
FObj foParent = (FObj) parent; FObj foParent = (FObj) parent;
int parentBidiLevel = foParent.getBidiLevel(); int parentBidiLevel = foParent.getBidiLevel();
if ((parentBidiLevel < 0) || (bidiLevel < parentBidiLevel)) { if ((parentBidiLevel < 0) || (bidiLevel < parentBidiLevel)) {
return level; return level;
} }
} }
if (isBidiInheritanceBoundary()) {
break;
}
} }
return -1; 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. * Add a new extension attachment to this FObj.
* (see org.apache.fop.fo.FONode for details) * (see org.apache.fop.fo.FONode for details)

+ 2
- 1
src/java/org/apache/fop/fo/expr/FunctionBase.java Voir le fichier

/** {@inheritDoc} */ /** {@inheritDoc} */
public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException { public Property getOptionalArgDefault(int index, PropertyInfo pi) throws PropertyException {
if (index >= getOptionalArgsCount()) { 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); e.setPropertyInfo(pi);
throw e; throw e;
} else { } else {

+ 2
- 1
src/java/org/apache/fop/fo/expr/PropertyParser.java Voir le fichier

} }
int numArgs = args.size(); int numArgs = args.size();
if (numArgs < numReq) { 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 { } else {
for (int i = 0; i < numOpt; i++) { for (int i = 0; i < numOpt; i++) {
if (args.size() < (numReq + i + 1)) { if (args.size() < (numReq + i + 1)) {

+ 2
- 0
src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java Voir le fichier

PROPERTY_ATTRIBUTES.add("border-before-end-radius"); PROPERTY_ATTRIBUTES.add("border-before-end-radius");
PROPERTY_ATTRIBUTES.add("border-after-start-radius"); PROPERTY_ATTRIBUTES.add("border-after-start-radius");
PROPERTY_ATTRIBUTES.add("border-after-end-radius"); PROPERTY_ATTRIBUTES.add("border-after-end-radius");
//Optional content groups (layers)
PROPERTY_ATTRIBUTES.add("layer");
} }


/** /**

+ 16
- 2
src/java/org/apache/fop/fo/flow/BlockContainer.java Voir le fichier

referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric();
span = pList.get(PR_SPAN).getEnum(); span = pList.get(PR_SPAN).getEnum();
writingModeTraits = new WritingModeTraits( 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(); disableColumnBalancing = pList.get(PR_X_DISABLE_COLUMN_BALANCING).getEnum();
} }


return writingModeTraits.getWritingMode(); return writingModeTraits.getWritingMode();
} }


/**
* Obtain writing mode explicit indicator.
* @return the writing mode explicit indicator
*/
public boolean getExplicitWritingMode() {
return writingModeTraits.getExplicitWritingMode();
}

/** {@inheritDoc} */ /** {@inheritDoc} */
public String getLocalName() { public String getLocalName() {
return "block-container"; return "block-container";
public int getNameId() { public int getNameId() {
return FO_BLOCK_CONTAINER; return FO_BLOCK_CONTAINER;
} }
}


@Override
protected boolean isBidiBoundary(boolean propagate) {
return getExplicitWritingMode();
}

}

+ 77
- 95
src/java/org/apache/fop/fo/flow/InlineContainer.java Voir le fichier

import org.apache.fop.traits.WritingMode; import org.apache.fop.traits.WritingMode;
import org.apache.fop.traits.WritingModeTraits; 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 { 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 LengthRangeProperty blockProgressionDimension;
private int overflow;
private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginInline commonMarginInline; private CommonMarginInline commonMarginInline;
private int clip;
private int dominantBaseline;
private LengthRangeProperty inlineProgressionDimension;
private Numeric referenceOrientation;
private int displayAlign;
private KeepProperty keepTogether; private KeepProperty keepTogether;
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
private SpaceProperty lineHeight; private SpaceProperty lineHeight;
private int overflow;
private Numeric referenceOrientation;
private Length alignmentAdjust;
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
private WritingModeTraits writingModeTraits; 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 */ /** 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) { public InlineContainer(FONode parent) {
super(parent); super(parent);
} }


/** {@inheritDoc} */
@Override
public void bind(PropertyList pList) throws FOPException { public void bind(PropertyList pList) throws FOPException {
super.bind(pList); super.bind(pList);
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginInline = pList.getMarginInlineProps(); commonMarginInline = pList.getMarginInlineProps();
clip = pList.get(PR_CLIP).getEnum();
displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum(); dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); 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(); lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
overflow = pList.get(PR_OVERFLOW).getEnum(); overflow = pList.get(PR_OVERFLOW).getEnum();
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric();
writingModeTraits = new WritingModeTraits( 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} * {@inheritDoc}
* <br>XSL Content Model: marker* (%block;)+ * <br>XSL Content Model: marker* (%block;)+
*/ */
@Override
protected void validateChildNode(Locator loc, String nsURI, String localName) protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException { throws ValidationException {
if (FO_URI.equals(nsURI)) { if (FO_URI.equals(nsURI)) {
if (localName.equals("marker")) { if (localName.equals("marker")) {
if (blockItemFound) { if (blockItemFound) {
nodesOutOfOrderError(loc, "fo:marker", "(%block;)");
nodesOutOfOrderError(loc, "fo:marker", "(%block;)+");
} }
} else if (!isBlockItem(nsURI, localName)) { } else if (!isBlockItem(nsURI, localName)) {
invalidChildError(loc, nsURI, localName); invalidChildError(loc, nsURI, localName);
} }
} }


/** {@inheritDoc} */
@Override
public void endOfNode() throws FOPException { public void endOfNode() throws FOPException {
if (!blockItemFound) { if (!blockItemFound) {
missingChildElementError("marker* (%block;)+"); 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() { public LengthRangeProperty getBlockProgressionDimension() {
return blockProgressionDimension; 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() { public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
return this.commonBorderPaddingBackground; return this.commonBorderPaddingBackground;
} }


/** @return Returns the {@link CommonMarginInline} */
public CommonMarginInline getCommonMarginInline() { public CommonMarginInline getCommonMarginInline() {
return this.commonMarginInline; 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() { public KeepProperty getKeepTogether() {
return keepTogether; 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() { public SpaceProperty getLineHeight() {
return lineHeight; 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() { public Direction getInlineProgressionDirection() {
return writingModeTraits.getInlineProgressionDirection(); return writingModeTraits.getInlineProgressionDirection();
} }


/**
* Obtain block progression direction.
* @return the block progression direction
*/
public Direction getBlockProgressionDirection() { public Direction getBlockProgressionDirection() {
return writingModeTraits.getBlockProgressionDirection(); return writingModeTraits.getBlockProgressionDirection();
} }


/**
* Obtain column progression direction.
* @return the column progression direction
*/
public Direction getColumnProgressionDirection() { public Direction getColumnProgressionDirection() {
return writingModeTraits.getColumnProgressionDirection(); return writingModeTraits.getColumnProgressionDirection();
} }


/**
* Obtain row progression direction.
* @return the row progression direction
*/
public Direction getRowProgressionDirection() { public Direction getRowProgressionDirection() {
return writingModeTraits.getRowProgressionDirection(); return writingModeTraits.getRowProgressionDirection();
} }


/**
* Obtain (baseline) shift direction.
* @return the (baseline) shift direction
*/
public Direction getShiftDirection() { public Direction getShiftDirection() {
return writingModeTraits.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 @Override
public boolean isDelimitedTextRangeBoundary(int boundary) {
return false;
protected boolean isBidiBoundary(boolean propagate) {
return getExplicitWritingMode();
} }


} }

+ 12
- 1
src/java/org/apache/fop/fo/flow/table/Table.java Voir le fichier

tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum(); tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum();
tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum();
writingModeTraits = new WritingModeTraits( 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 //Bind extension properties
widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength(); widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength();
return writingModeTraits.getWritingMode(); return writingModeTraits.getWritingMode();
} }


/** {@inheritDoc} */
public boolean getExplicitWritingMode() {
return writingModeTraits.getExplicitWritingMode();
}

/** @return the "fox:widow-content-limit" extension FO trait */ /** @return the "fox:widow-content-limit" extension FO trait */
public Length getWidowContentLimit() { public Length getWidowContentLimit() {
return widowContentLimit; return widowContentLimit;
return ranges; return ranges;
} }


@Override
protected boolean isBidiBoundary(boolean propagate) {
return getExplicitWritingMode();
}

} }

+ 17
- 1
src/java/org/apache/fop/fo/pagination/PageSequence.java Voir le fichier

masterReference = pList.get(PR_MASTER_REFERENCE).getString(); masterReference = pList.get(PR_MASTER_REFERENCE).getString();
referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric();
writingModeTraits = new WritingModeTraits( 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("")) { if (masterReference == null || masterReference.equals("")) {
missingPropertyError("master-reference"); missingPropertyError("master-reference");
} }
} }
} }


/**
* {@inheritDoc}
*/
public boolean getExplicitWritingMode() {
if (writingModeTraits != null) {
return writingModeTraits.getExplicitWritingMode();
} else {
return false;
}
}


@Override @Override
protected Stack collectDelimitedTextRanges(Stack ranges, DelimitedTextRange currentRange) { protected Stack collectDelimitedTextRanges(Stack ranges, DelimitedTextRange currentRange) {
return ranges; return ranges;
} }


@Override
protected boolean isBidiBoundary(boolean propagate) {
return true;
}

/** /**
* Releases a page-sequence's children after the page-sequence has been fully processed. * Releases a page-sequence's children after the page-sequence has been fully processed.
*/ */

+ 5
- 1
src/java/org/apache/fop/fo/properties/GenericShorthandParser.java Voir le fichier

PropertyList propertyList) PropertyList propertyList)
throws PropertyException { throws PropertyException {
Property prop = null; Property prop = null;
String vProperty = "";
// Try each of the stored values in turn // Try each of the stored values in turn
Iterator iprop = property.getList().iterator(); Iterator iprop = property.getList().iterator();
while (iprop.hasNext() && prop == null) { while (iprop.hasNext() && prop == null) {
Property p = (Property)iprop.next(); Property p = (Property)iprop.next();
if (p.getNCname() != null) {
vProperty += p.getNCname() + " ";
}
prop = maker.convertShorthandProperty(propertyList, p, null); prop = maker.convertShorthandProperty(propertyList, p, null);
propertyList.validatePropertyValue(p.getNCname(), prop, property);
} }
propertyList.validatePropertyValue(vProperty.trim(), prop, property);
return prop; return prop;
} }



+ 2
- 2
src/java/org/apache/fop/fonts/FontLoader.java Voir le fichier

import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


import org.apache.fop.apps.io.InternalResourceResolver; 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; import org.apache.fop.fonts.type1.Type1FontLoader;


/** /**
} }
loader = new Type1FontLoader(fontFileURI, embedded, useKerning, resourceResolver); loader = new Type1FontLoader(fontFileURI, embedded, useKerning, resourceResolver);
} else { } else {
loader = new TTFFontLoader(fontFileURI, subFontName, embedded, embeddingMode,
loader = new OFFontLoader(fontFileURI, subFontName, embedded, embeddingMode,
encodingMode, useKerning, useAdvanced, resourceResolver); encodingMode, useKerning, useAdvanced, resourceResolver);
} }
return loader.getFont(); return loader.getFont();

+ 10
- 6
src/java/org/apache/fop/fonts/FontManagerConfigurator.java Voir le fichier



private final Configuration cfg; private final Configuration cfg;


private final URI defaultBaseUri;
private final URI baseURI;

private final URI fallbackURI;


private final ResourceResolver resourceResolver; private final ResourceResolver resourceResolver;


/** /**
* Main constructor * Main constructor
* @param cfg the font manager configuration object * @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 * @param resourceResolver the resource resolver
*/ */
public FontManagerConfigurator(Configuration cfg, URI defaultBaseUri,
public FontManagerConfigurator(Configuration cfg, URI baseURI, URI fallbackURI,
ResourceResolver resourceResolver) { ResourceResolver resourceResolver) {
this.cfg = cfg; this.cfg = cfg;
this.defaultBaseUri = defaultBaseUri;
this.baseURI = baseURI;
this.fallbackURI = fallbackURI;
this.resourceResolver = resourceResolver; this.resourceResolver = resourceResolver;
} }


URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("font-base") URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("font-base")
.getValue(null)); .getValue(null));
fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver( fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
defaultBaseUri.resolve(fontBase), resourceResolver));
baseURI.resolve(fontBase), resourceResolver));
} catch (URISyntaxException use) { } catch (URISyntaxException use) {
LogUtil.handleException(log, use, true); LogUtil.handleException(log, use, true);
} }
} else { } else {
fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver( fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
defaultBaseUri, resourceResolver));
fallbackURI, resourceResolver));
} }
// caching (fonts) // caching (fonts)
if (cfg.getChild("use-cache", false) != null) { if (cfg.getChild("use-cache", false) != null) {

+ 2
- 1
src/java/org/apache/fop/fonts/FontTriplet.java Voir le fichier

*/ */
public class FontTriplet implements Comparable<FontTriplet>, 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 */ /** serial version UID */
private static final long serialVersionUID = 1168991106658033508L; private static final long serialVersionUID = 1168991106658033508L;

+ 52
- 17
src/java/org/apache/fop/fonts/MultiByteFont.java Voir le fichier

import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.BitSet; import java.util.BitSet;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;


import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
/** Contains the character bounding boxes for all characters in the font */ /** Contains the character bounding boxes for all characters in the font */
protected Rectangle[] boundingBoxes; 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 * Default constructor
*/ */
return cidType; return cidType;
} }


public void setIsOTFFile(boolean isOTFFile) {
this.isOTFFile = isOTFFile;
}

public boolean isOTFFile() {
return this.isOTFFile;
}

/** /**
* Sets the CIDType. * Sets the CIDType.
* @param cidType The cidType to set * @param cidType The cidType to set
return this.cidSet; return this.cidSet;
} }


public void mapUsedGlyphName(int gid, String value) {
usedGlyphNames.put(gid, value);
}

public LinkedHashMap<Integer, String> getUsedGlyphNames() {
return usedGlyphNames;
}

/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public String getEncodingName() { public String getEncodingName() {
* @return the glyph index (or 0 if the glyph is not available) * @return the glyph index (or 0 if the glyph is not available)
*/ */
// [TBD] - needs optimization, i.e., change from linear search to binary search // [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 idx = c;
int retIdx = SingleByteEncoding.NOT_FOUND_CODE_POINT; 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++) { for (int i = 0; (i < cmap.length) && retIdx == 0; i++) {
if (cmap[i].getUnicodeStart() <= idx if (cmap[i].getUnicodeStart() <= idx
&& cmap[i].getUnicodeEnd() >= idx) { && cmap[i].getUnicodeEnd() >= idx) {
retIdx = cmap[i].getGlyphStartIndex() retIdx = cmap[i].getGlyphStartIndex()
+ idx + idx
- cmap[i].getUnicodeStart(); - cmap[i].getUnicodeStart();
if (idx < NUM_MOST_LIKELY_GLYPHS) {
mostLikelyGlyphs[idx] = retIdx;
}
} }
} }
return retIdx; return retIdx;
return findCharacterFromGlyphIndex(gi, true); 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() { protected BitSet getGlyphIndices() {
BitSet bitset = new BitSet(); BitSet bitset = new BitSet();
bitset.set(0); bitset.set(0);
return chars; 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} */ /** {@inheritDoc} */
@Override @Override
public boolean hasChar(char c) { public boolean hasChar(char c) {

+ 1
- 1
src/java/org/apache/fop/fonts/SingleByteFont.java Voir le fichier

import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.fonts.Glyphs;


import org.apache.fop.apps.io.InternalResourceResolver; 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 * Generic SingleByte font

+ 0
- 6
src/java/org/apache/fop/fonts/apps/AbstractFontReader.java Voir le fichier

import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


import org.apache.fop.util.CommandLineLogger;

/** /**
* Abstract base class for the PFM and TTF Reader command-line applications. * Abstract base class for the PFM and TTF Reader command-line applications.
*/ */
protected static void setLogLevel(String level) { protected static void setLogLevel(String level) {
// Set the evel for future loggers. // Set the evel for future loggers.
LogFactory.getFactory().setAttribute("level", level); LogFactory.getFactory().setAttribute("level", level);
if (log instanceof CommandLineLogger) {
// Set the level for the logger creates already.
((CommandLineLogger) log).setLogLevel(level);
}
} }


/** /**

+ 0
- 11
src/java/org/apache/fop/fonts/apps/PFMReader.java Voir le fichier

import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;


import org.apache.commons.logging.LogFactory;

import org.apache.fop.Version; import org.apache.fop.Version;
import org.apache.fop.fonts.type1.PFMFile; 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 * A tool which reads PFM files from Adobe Type 1 fonts and creates
Map options = new java.util.HashMap(); Map options = new java.util.HashMap();
String[] arguments = parseArguments(options, args); 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); determineLogLevel(options);


PFMReader app = new PFMReader(); PFMReader app = new PFMReader();

+ 3
- 13
src/java/org/apache/fop/fonts/apps/TTFReader.java Voir le fichier

import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;


import org.apache.commons.logging.LogFactory;

import org.apache.fop.Version; import org.apache.fop.Version;
import org.apache.fop.fonts.CMapSegment; import org.apache.fop.fonts.CMapSegment;
import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.truetype.FontFileReader; 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.TTFFile;
import org.apache.fop.util.CommandLineLogger;


// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck // CSOFF: LineLengthCheck


/** /**
Map options = new java.util.HashMap(); Map options = new java.util.HashMap();
String[] arguments = parseArguments(options, args); 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); determineLogLevel(options);


TTFReader app = new TTFReader(); TTFReader app = new TTFReader();
InputStream stream = new FileInputStream(fileName); InputStream stream = new FileInputStream(fileName);
try { try {
FontFileReader reader = new FontFileReader(stream); 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) { if (!supported) {
return null; return null;
} }

+ 2
- 2
src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java Voir le fichier

import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.truetype.FontFileReader; 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.TTFFile;
import org.apache.fop.fonts.truetype.TTFFontLoader;


/** /**
* Attempts to determine correct FontInfo * Attempts to determine correct FontInfo
log.debug("Loading " + fontName); log.debug("Loading " + fontName);
} }
try { try {
TTFFontLoader ttfLoader = new TTFFontLoader(fontURI, fontName, true,
OFFontLoader ttfLoader = new OFFontLoader(fontURI, fontName, true,
EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useAdvanced, EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useAdvanced,
resourceResolver); resourceResolver);
customFont = ttfLoader.getFont(); customFont = ttfLoader.getFont();

+ 927
- 0
src/java/org/apache/fop/fonts/cff/CFFDataReader.java Voir le fichier

/*
* 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;
}
}
}

+ 2
- 2
src/java/org/apache/fop/fonts/truetype/GlyfTable.java Voir le fichier

*/ */
public class GlyfTable { public class GlyfTable {


private final TTFMtxEntry[] mtxTab;
private final OFMtxEntry[] mtxTab;


private final long tableOffset; private final long tableOffset;


/** All the glyphs that are composed, but do not appear in the subset. */ /** All the glyphs that are composed, but do not appear in the subset. */
private Set<Integer> composedGlyphs = new TreeSet<Integer>(); 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 { Map<Integer, Integer> glyphs) throws IOException {
mtxTab = metrics; mtxTab = metrics;
tableOffset = dirTableEntry.getOffset(); tableOffset = dirTableEntry.getOffset();

src/java/org/apache/fop/fonts/truetype/TTFDirTabEntry.java → src/java/org/apache/fop/fonts/truetype/OFDirTabEntry.java Voir le fichier

/** /**
* This class represents an entry to a TrueType font's Dir Tab. * 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 byte[] tag = new byte[4];
private int checksum; private int checksum;
private long offset; private long offset;
private long length; private long length;


public TTFDirTabEntry() {
public OFDirTabEntry() {
} }


public TTFDirTabEntry(long offset, long length) {
public OFDirTabEntry(long offset, long length) {
this.offset = offset; this.offset = offset;
this.length = length; this.length = length;
} }

src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java → src/java/org/apache/fop/fonts/truetype/OFFontLoader.java Voir le fichier

import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.NamedCharacter; import org.apache.fop.fonts.NamedCharacter;
import org.apache.fop.fonts.SingleByteFont; 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; import org.apache.fop.util.HexEncoder;


/** /**
* Loads a TrueType font into memory directly from the original font file. * 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 MultiByteFont multiFont;
private SingleByteFont singleFont; private SingleByteFont singleFont;
* @param fontFileURI the URI representing the font file * @param fontFileURI the URI representing the font file
* @param resourceResolver the resource resolver for font URI resolution * @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); this(fontFileURI, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true, resourceResolver);
} }


* @param useAdvanced true to enable loading advanced info if available, false to disable * @param useAdvanced true to enable loading advanced info if available, false to disable
* @param resolver the FontResolver for font URI resolution * @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, EmbeddingMode embeddingMode, EncodingMode encodingMode, boolean useKerning,
boolean useAdvanced, InternalResourceResolver resolver) { boolean useAdvanced, InternalResourceResolver resolver) {
super(fontFileURI, embedded, useKerning, useAdvanced, resolver); super(fontFileURI, embedded, useKerning, useAdvanced, resolver);
private void read(String ttcFontName) throws IOException { private void read(String ttcFontName) throws IOException {
InputStream in = resourceResolver.getResource(this.fontFileURI); InputStream in = resourceResolver.getResource(this.fontFileURI);
try { try {
TTFFile ttf = new TTFFile(useKerning, useAdvanced);
FontFileReader reader = new FontFileReader(in); 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) { 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; loaded = true;
} finally { } finally {
IOUtils.closeQuietly(in); 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; boolean isCid = this.embedded;
if (this.encodingMode == EncodingMode.SINGLE_BYTE) { if (this.encodingMode == EncodingMode.SINGLE_BYTE) {
isCid = false; isCid = false;


if (isCid) { if (isCid) {
multiFont = new MultiByteFont(resourceResolver, embeddingMode); multiFont = new MultiByteFont(resourceResolver, embeddingMode);
multiFont.setIsOTFFile(otf instanceof OTFFile);
returnFont = multiFont; returnFont = multiFont;
multiFont.setTTCName(ttcFontName); multiFont.setTTCName(ttcFontName);
} else { } else {
returnFont = singleFont; 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.setMissingWidth(0);
returnFont.setWeight(ttf.getWeightClass());
returnFont.setWeight(otf.getWeightClass());
returnFont.setEmbeddingMode(this.embeddingMode); returnFont.setEmbeddingMode(this.embeddingMode);
if (isCid) { 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 { } else {
singleFont.setFontType(FontType.TRUETYPE); 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) { if (useAdvanced) {
copyAdvanced(ttf);
copyAdvanced(otf);
} }
if (this.embedded) { if (this.embedded) {
if (ttf.isEmbeddable()) {
if (otf.isEmbeddable()) {
returnFont.setEmbedURI(this.fontFileURI); returnFont.setEmbedURI(this.fontFileURI);
} else { } else {
String msg = "The font " + this.fontFileURI + " is not embeddable due to a" String msg = "The font " + this.fontFileURI + " is not embeddable due to a"
} }
} }


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++) { 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, singleFont.setBoundingBox(i,
new Rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1])); 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) { if (segment.getUnicodeStart() < 0xFFFE) {
for (char u = (char)segment.getUnicodeStart(); u <= segment.getUnicodeEnd(); u++) { for (char u = (char)segment.getUnicodeStart(); u <= segment.getUnicodeEnd(); u++) {
int codePoint = singleFont.getEncoding().mapChar(u); int codePoint = singleFont.getEncoding().mapChar(u);
if (codePoint <= 0) { if (codePoint <= 0) {
int glyphIndex = segment.getGlyphStartIndex() + u - segment.getUnicodeStart(); 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); glyphName = "u" + HexEncoder.encode(u);
} }
if (glyphName.length() > 0) { if (glyphName.length() > 0) {
/** /**
* Copy kerning information. * Copy kerning information.
*/ */
private void copyKerning(TTFFile ttf, boolean isCid) {
private void copyKerning(OpenFont otf, boolean isCid) {


// Get kerning // Get kerning
Set<Integer> kerningSet; Set<Integer> kerningSet;
if (isCid) { if (isCid) {
kerningSet = ttf.getKerning().keySet();
kerningSet = otf.getKerning().keySet();
} else { } else {
kerningSet = ttf.getAnsiKerning().keySet();
kerningSet = otf.getAnsiKerning().keySet();
} }


for (Integer kpx1 : kerningSet) { for (Integer kpx1 : kerningSet) {
Map<Integer, Integer> h2; Map<Integer, Integer> h2;
if (isCid) { if (isCid) {
h2 = ttf.getKerning().get(kpx1);
h2 = otf.getKerning().get(kpx1);
} else { } else {
h2 = ttf.getAnsiKerning().get(kpx1);
h2 = otf.getAnsiKerning().get(kpx1);
} }
returnFont.putKerningEntry(kpx1, h2); returnFont.putKerningEntry(kpx1, h2);
} }
/** /**
* Copy advanced typographic information. * Copy advanced typographic information.
*/ */
private void copyAdvanced(TTFFile ttf) {
private void copyAdvanced(OpenFont otf) {
if (returnFont instanceof MultiByteFont) { if (returnFont instanceof MultiByteFont) {
MultiByteFont mbf = (MultiByteFont) returnFont; 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());
} }
} }



src/java/org/apache/fop/fonts/truetype/TTFMtxEntry.java → src/java/org/apache/fop/fonts/truetype/OFMtxEntry.java Voir le fichier

/** /**
* This class represents a TrueType Mtx Entry. * This class represents a TrueType Mtx Entry.
*/ */
class TTFMtxEntry {
class OFMtxEntry {


private int wx; private int wx;
private int lsb; private int lsb;

src/java/org/apache/fop/fonts/truetype/TTFTableName.java → src/java/org/apache/fop/fonts/truetype/OFTableName.java Voir le fichier

* Represents table names as found in a TrueType font's Table Directory. * Represents table names as found in a TrueType font's Table Directory.
* TrueType fonts may have custom tables so we cannot use an enum. * 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. */ /** 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. */ /** Embedded bitmap data. */
public static final TTFTableName EBDT = new TTFTableName("EBDT");
public static final OFTableName EBDT = new OFTableName("EBDT");


/** Embedded bitmap location data. */ /** Embedded bitmap location data. */
public static final TTFTableName EBLC = new TTFTableName("EBLC");
public static final OFTableName EBLC = new OFTableName("EBLC");


/** Embedded bitmap scaling data. */ /** Embedded bitmap scaling data. */
public static final TTFTableName EBSC = new TTFTableName("EBSC");
public static final OFTableName EBSC = new OFTableName("EBSC");


/** A FontForge specific table. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** PCL 5 data. */
public static final TTFTableName PCLT = new TTFTableName("PCLT");
public static final OFTableName PCLT = new OFTableName("PCLT");


/** Vertical Device Metrics table. */ /** Vertical Device Metrics table. */
public static final TTFTableName VDMX = new TTFTableName("VDMX");
public static final OFTableName VDMX = new OFTableName("VDMX");


/** Character to glyph mapping. */ /** Character to glyph mapping. */
public static final TTFTableName CMAP = new TTFTableName("cmap");
public static final OFTableName CMAP = new OFTableName("cmap");


/** Control Value Table. */ /** Control Value Table. */
public static final TTFTableName CVT = new TTFTableName("cvt ");
public static final OFTableName CVT = new OFTableName("cvt ");


/** Font program. */ /** 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). */ /** 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. */ /** Glyph data. */
public static final TTFTableName GLYF = new TTFTableName("glyf");
public static final OFTableName GLYF = new OFTableName("glyf");


/** Horizontal device metrics. */ /** Horizontal device metrics. */
public static final TTFTableName HDMX = new TTFTableName("hdmx");
public static final OFTableName HDMX = new OFTableName("hdmx");


/** Font header. */ /** Font header. */
public static final TTFTableName HEAD = new TTFTableName("head");
public static final OFTableName HEAD = new OFTableName("head");


/** Horizontal header. */ /** Horizontal header. */
public static final TTFTableName HHEA = new TTFTableName("hhea");
public static final OFTableName HHEA = new OFTableName("hhea");


/** Horizontal metrics. */ /** Horizontal metrics. */
public static final TTFTableName HMTX = new TTFTableName("hmtx");
public static final OFTableName HMTX = new OFTableName("hmtx");


/** Kerning. */ /** Kerning. */
public static final TTFTableName KERN = new TTFTableName("kern");
public static final OFTableName KERN = new OFTableName("kern");


/** Index to location. */ /** Index to location. */
public static final TTFTableName LOCA = new TTFTableName("loca");
public static final OFTableName LOCA = new OFTableName("loca");


/** Maximum profile. */ /** Maximum profile. */
public static final TTFTableName MAXP = new TTFTableName("maxp");
public static final OFTableName MAXP = new OFTableName("maxp");


/** Naming table. */ /** Naming table. */
public static final TTFTableName NAME = new TTFTableName("name");
public static final OFTableName NAME = new OFTableName("name");


/** PostScript information. */ /** PostScript information. */
public static final TTFTableName POST = new TTFTableName("post");
public static final OFTableName POST = new OFTableName("post");


/** CVT Program. */ /** CVT Program. */
public static final TTFTableName PREP = new TTFTableName("prep");
public static final OFTableName PREP = new OFTableName("prep");


/** Vertical Metrics header. */ /** Vertical Metrics header. */
public static final TTFTableName VHEA = new TTFTableName("vhea");
public static final OFTableName VHEA = new OFTableName("vhea");


/** Vertical Metrics. */ /** Vertical Metrics. */
public static final TTFTableName VMTX = new TTFTableName("vmtx");
public static final OFTableName VMTX = new OFTableName("vmtx");


private final String name; private final String name;


private TTFTableName(String name) {
private OFTableName(String name) {
this.name = name; this.name = name;
} }


* @param tableName table name as in the Table Directory * @param tableName table name as in the Table Directory
* @return TTFTableName * @return TTFTableName
*/ */
public static TTFTableName getValue(String tableName) {
public static OFTableName getValue(String tableName) {
if (tableName != null) { if (tableName != null) {
return new TTFTableName(tableName);
return new OFTableName(tableName);
} }
throw new IllegalArgumentException("A TrueType font table name must not be null"); throw new IllegalArgumentException("A TrueType font table name must not be null");
} }
if (o == this) { if (o == this) {
return true; return true;
} }
if (!(o instanceof TTFTableName)) {
if (!(o instanceof OFTableName)) {
return false; return false;
} }
TTFTableName to = (TTFTableName) o;
OFTableName to = (OFTableName) o;
return this.name.equals(to.getName()); return this.name.equals(to.getName());
} }



+ 109
- 0
src/java/org/apache/fop/fonts/truetype/OTFFile.java Voir le fichier

/*
* 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();
}
}

+ 1097
- 0
src/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 1971
- 0
src/java/org/apache/fop/fonts/truetype/OpenFont.java
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 74
- 1971
src/java/org/apache/fop/fonts/truetype/TTFFile.java
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 53
- 53
src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java Voir le fichier

* Offsets in name table to be filled out by table. * Offsets in name table to be filled out by table.
* The offsets are to the checkSum field * 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 checkSumAdjustmentOffset = 0;
private int locaOffset = 0; private int locaOffset = 0;
} }


/** The dir tab entries in the new subset font. */ /** 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() { private int determineTableCount() {
int numTables = 4; //4 req'd tables: head,hhea,hmtx,maxp int numTables = 4; //4 req'd tables: head,hhea,hmtx,maxp
writeUShort((numTables * 16) - searchRange); writeUShort((numTables * 16) - searchRange);
realSize += 2; realSize += 2;
// Create space for the table entries (these must be in ASCII alphabetical order[A-Z] then[a-z]) // 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()) { if (hasCvt()) {
writeTableName(TTFTableName.CVT);
writeTableName(OFTableName.CVT);
} }
if (hasFpgm()) { 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()) { 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()); writeString(tableName.getName());
offsets.put(tableName, currentPos); offsets.put(tableName, currentPos);
currentPos += 12; currentPos += 12;




private boolean hasCvt() { private boolean hasCvt() {
return dirTabs.containsKey(TTFTableName.CVT);
return dirTabs.containsKey(OFTableName.CVT);
} }


private boolean hasFpgm() { private boolean hasFpgm() {
return dirTabs.containsKey(TTFTableName.FPGM);
return dirTabs.containsKey(OFTableName.FPGM);
} }


private boolean hasPrep() { private boolean hasPrep() {
return dirTabs.containsKey(TTFTableName.PREP);
return dirTabs.containsKey(OFTableName.PREP);
} }


/** /**
private void createLoca(int size) throws IOException { private void createLoca(int size) throws IOException {
pad4(); pad4();
locaOffset = currentPos; locaOffset = currentPos;
int dirTableOffset = offsets.get(TTFTableName.LOCA);
int dirTableOffset = offsets.get(OFTableName.LOCA);
writeULong(dirTableOffset + 4, currentPos); writeULong(dirTableOffset + 4, currentPos);
writeULong(dirTableOffset + 8, size * 4 + 4); writeULong(dirTableOffset + 8, size * 4 + 4);
currentPos += size * 4 + 4; currentPos += size * 4 + 4;
realSize += 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) { if (entry != null) {
pad4(); pad4();
seekTab(in, tableName, 0); seekTab(in, tableName, 0);
* Copy the cvt table as is from original font to subset font * Copy the cvt table as is from original font to subset font
*/ */
private boolean createCvt(FontFileReader in) throws IOException { 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 * Copy the fpgm table as is from original font to subset font
*/ */
private boolean createFpgm(FontFileReader in) throws IOException { 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. * Copy the name table as is from the original.
*/ */
private boolean createName(FontFileReader in) throws IOException { 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. * Copy the OS/2 table as is from the original.
*/ */
private boolean createOS2(FontFileReader in) throws IOException { private boolean createOS2(FontFileReader in) throws IOException {
return copyTable(in, TTFTableName.OS2);
return copyTable(in, OFTableName.OS2);
} }


/** /**
* and set num glyphs to size * and set num glyphs to size
*/ */
private void createMaxp(FontFileReader in, int size) throws IOException { 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) { if (entry != null) {
pad4(); pad4();
seekTab(in, maxp, 0); seekTab(in, maxp, 0);
} }


private void createPost(FontFileReader in) throws IOException { 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) { if (entry != null) {
pad4(); pad4();
seekTab(in, post, 0); seekTab(in, post, 0);
* Copy the prep table as is from original font to subset font * Copy the prep table as is from original font to subset font
*/ */
private boolean createPrep(FontFileReader in) throws IOException { private boolean createPrep(FontFileReader in) throws IOException {
return copyTable(in, TTFTableName.PREP);
return copyTable(in, OFTableName.PREP);
} }




* and fill in size of hmtx table * and fill in size of hmtx table
*/ */
private void createHhea(FontFileReader in, int size) throws IOException { private void createHhea(FontFileReader in, int size) throws IOException {
TTFDirTabEntry entry = dirTabs.get(TTFTableName.HHEA);
OFDirTabEntry entry = dirTabs.get(OFTableName.HHEA);
if (entry != null) { if (entry != null) {
pad4(); pad4();
seekTab(in, TTFTableName.HHEA, 0);
seekTab(in, OFTableName.HHEA, 0);
System.arraycopy(in.getBytes((int) entry.getOffset(), (int) entry.getLength()), 0, System.arraycopy(in.getBytes((int) entry.getOffset(), (int) entry.getLength()), 0,
output, currentPos, (int) entry.getLength()); output, currentPos, (int) entry.getLength());
writeUShort((int) entry.getLength() + currentPos - 2, size); 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(); currentPos += (int) entry.getLength();
realSize += (int) entry.getLength(); realSize += (int) entry.getLength();
} else { } else {
* in checkSumAdjustmentOffset * in checkSumAdjustmentOffset
*/ */
private void createHead(FontFileReader in) throws IOException { 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) { if (entry != null) {
pad4(); pad4();
seekTab(in, head, 0); seekTab(in, head, 0);
*/ */
private void createGlyf(FontFileReader in, private void createGlyf(FontFileReader in,
Map<Integer, Integer> glyphs) throws IOException { 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 size = 0;
int startPos = 0; int startPos = 0;
int endOffset = 0; // Store this as the last loca int endOffset = 0; // Store this as the last loca
writeULong(locaOffset + glyphs.size() * 4, endOffset); writeULong(locaOffset + glyphs.size() * 4, endOffset);
int locaSize = glyphs.size() * 4 + 4; int locaSize = glyphs.size() * 4 + 4;
int checksum = getCheckSum(output, locaOffset, locaSize); int checksum = getCheckSum(output, locaOffset, locaSize);
writeULong(offsets.get(TTFTableName.LOCA), checksum);
writeULong(offsets.get(OFTableName.LOCA), checksum);
int padSize = (locaOffset + locaSize) % 4; int padSize = (locaOffset + locaSize) % 4;
newDirTabs.put(TTFTableName.LOCA,
new TTFDirTabEntry(locaOffset, locaSize + padSize));
newDirTabs.put(OFTableName.LOCA,
new OFDirTabEntry(locaOffset, locaSize + padSize));
} else { } else {
throw new IOException("Can't find glyf table"); throw new IOException("Can't find glyf table");
} }
*/ */
private void createHmtx(FontFileReader in, private void createHmtx(FontFileReader in,
Map<Integer, Integer> glyphs) throws IOException { 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 longHorMetricSize = glyphs.size() * 2;
int leftSideBearingSize = glyphs.size() * 2; int leftSideBearingSize = glyphs.size() * 2;
* new index as (Integer) value) * new index as (Integer) value)
* @throws IOException in case of an I/O problem * @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 { Map<Integer, Integer> glyphs) throws IOException {
fontFile = in; fontFile = in;
//Check if TrueType collection, and that the name exists in the collection //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"); throw new IOException("Failed to read font");
} }


glyphOffsets[i + 1] - glyphOffsets[i]); glyphOffsets[i + 1] - glyphOffsets[i]);
} }
// Stream the last glyph // Stream the last glyph
TTFDirTabEntry glyf = newDirTabs.get(TTFTableName.GLYF);
OFDirTabEntry glyf = newDirTabs.get(OFTableName.GLYF);
long lastGlyphLength = glyf.getLength() long lastGlyphLength = glyf.getLength()
- (glyphOffsets[glyphOffsets.length - 1] - glyf.getOffset()); - (glyphOffsets[glyphOffsets.length - 1] - glyf.getOffset());
glyphOut.streamGlyph(output, glyphOffsets[glyphOffsets.length - 1], glyphOut.streamGlyph(output, glyphOffsets[glyphOffsets.length - 1],


@Override @Override
public void stream(TTFOutputStream ttfOut) throws IOException { public void stream(TTFOutputStream ttfOut) throws IOException {
SortedSet<Map.Entry<TTFTableName, TTFDirTabEntry>> sortedDirTabs
SortedSet<Map.Entry<OFTableName, OFDirTabEntry>> sortedDirTabs
= sortDirTabMap(newDirTabs); = sortDirTabMap(newDirTabs);
TTFTableOutputStream tableOut = ttfOut.getTableOutputStream(); TTFTableOutputStream tableOut = ttfOut.getTableOutputStream();
TTFGlyphOutputStream glyphOut = ttfOut.getGlyphOutputStream(); TTFGlyphOutputStream glyphOut = ttfOut.getGlyphOutputStream();


ttfOut.startFontStream(); 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); handleGlyphSubset(glyphOut);
} else { } else {
tableOut.streamTable(output, (int) entry.getValue().getOffset(), tableOut.streamTable(output, (int) entry.getValue().getOffset(),


private void scanGlyphs(FontFileReader in, Map<Integer, Integer> subsetGlyphs) private void scanGlyphs(FontFileReader in, Map<Integer, Integer> subsetGlyphs)
throws IOException { throws IOException {
TTFDirTabEntry glyfTableInfo = dirTabs.get(TTFTableName.GLYF);
OFDirTabEntry glyfTableInfo = dirTabs.get(OFTableName.GLYF);
if (glyfTableInfo == null) { if (glyfTableInfo == null) {
throw new IOException("Glyf table could not be found"); throw new IOException("Glyf table could not be found");
} }
} }




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 checksum = getCheckSum(output, tableStart, tableSize);
int offset = offsets.get(tableName); int offset = offsets.get(tableName);
int padSize = getPadSize(tableStart + tableSize); 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, checksum);
writeULong(offset + 4, tableStart); writeULong(offset + 4, tableStart);
writeULong(offset + 8, tableSize); writeULong(offset + 8, tableSize);

+ 1
- 1
src/java/org/apache/fop/fonts/type1/AFMFile.java Voir le fichier

*/ */
public void addCharMetrics(AFMCharMetrics metrics) { public void addCharMetrics(AFMCharMetrics metrics) {
String name = metrics.getCharName(); String name = metrics.getCharName();
if (metrics.getUnicodeSequence() == null) {
if (metrics.getUnicodeSequence() == null && name.equals(".notdef")) {
//Ignore as no Unicode assignment is possible //Ignore as no Unicode assignment is possible
return; return;
} }

+ 6
- 3
src/java/org/apache/fop/fonts/type1/CharMetricsHandler.java Voir le fichier

import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


import org.apache.xmlgraphics.fonts.Glyphs;

import org.apache.fop.fonts.NamedCharacter; import org.apache.fop.fonts.NamedCharacter;
import org.apache.fop.fonts.type1.AFMParser.ValueHandler; import org.apache.fop.fonts.type1.AFMParser.ValueHandler;


AFMCharMetrics chm = defaultHandler.parse(line, stack, afmFileName); AFMCharMetrics chm = defaultHandler.parse(line, stack, afmFileName);
NamedCharacter namedChar = chm.getCharacter(); NamedCharacter namedChar = chm.getCharacter();
if (namedChar != null) { 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() + " has an incorrect code point: " + chm.getCharCode()
+ ". Changed to " + codePoint); + ". Changed to " + codePoint);
chm.setCharCode(codePoint); chm.setCharCode(codePoint);

+ 20
- 5
src/java/org/apache/fop/fonts/type1/Type1FontLoader.java Voir le fichier

addUnencodedBasedOnAFM(afm); addUnencodedBasedOnAFM(afm);
} }
} else { } 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"); singleFont.setEncoding(pfm.getCharSetName() + "Encoding");
} else { } else {
log.warn("The PFM reports an unsupported encoding (" log.warn("The PFM reports an unsupported encoding ("
List<AFMCharMetrics> chars = afm.getCharMetrics(); List<AFMCharMetrics> chars = afm.getCharMetrics();
for (AFMCharMetrics charMetrics : chars) { for (AFMCharMetrics charMetrics : chars) {
if (charMetrics.getCharCode() >= 0) { if (charMetrics.getCharCode() >= 0) {
String u = charMetrics.getUnicodeSequence();
if (u != null && u.length() == 1) {
mappingCount++;
}
mappingCount++;
} }
} }
// ...and now build the table. // ...and now build the table.
String unicodes = charMetrics.getUnicodeSequence(); String unicodes = charMetrics.getUnicodeSequence();
if (unicodes == null) { if (unicodes == null) {
log.info("No Unicode mapping for glyph: " + charMetrics); log.info("No Unicode mapping for glyph: " + charMetrics);
table[idx] = charMetrics.getCharCode();
idx++;
table[idx] = charMetrics.getCharCode();
idx++;
} else if (unicodes.length() == 1) { } else if (unicodes.length() == 1) {
table[idx] = charMetrics.getCharCode(); table[idx] = charMetrics.getCharCode();
idx++; idx++;

+ 0
- 3
src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java Voir le fichier

public AbstractBaseLayoutManager(FObj fo) { public AbstractBaseLayoutManager(FObj fo) {
this.fobj = fo; this.fobj = fo;
setGeneratesReferenceArea(fo.generatesReferenceAreas()); setGeneratesReferenceArea(fo.generatesReferenceAreas());
if (getGeneratesReferenceArea()) {
setGeneratesBlockArea(true);
}
} }


// --------- Property Resolution related functions --------- // // --------- Property Resolution related functions --------- //

+ 28
- 0
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java Voir le fichier

&& isFinished()); && 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. * Transfers foreign attributes from the formatting object to the area.
* @param targetArea the area to set the attributes on * @param targetArea the area to set the attributes on

+ 12
- 12
src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java Voir le fichier



/** /**
* Creates the child areas for the given layout manager. * 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 parentIter the position iterator
* @param layoutContext the layout context * @param layoutContext the layout context
*/ */
public static void addAreas(BlockStackingLayoutManager bslm,
public static void addAreas(AbstractLayoutManager parentLM,
PositionIterator parentIter, LayoutContext layoutContext) { PositionIterator parentIter, LayoutContext layoutContext) {
LayoutManager childLM; LayoutManager childLM;
LayoutContext lc = LayoutContext.offspringOf(layoutContext); LayoutContext lc = LayoutContext.offspringOf(layoutContext);
Position firstPos = null; Position firstPos = null;
Position lastPos = null; Position lastPos = null;


if (bslm != null) {
bslm.addId();
if (parentLM != null) {
parentLM.addId();
} }


// "unwrap" the NonLeafPositions stored in parentIter // "unwrap" the NonLeafPositions stored in parentIter
//doesn't give us that info. //doesn't give us that info.
} }


if (bslm != null) {
bslm.registerMarkers(
if (parentLM != null) {
parentLM.registerMarkers(
true, true,
bslm.isFirst(firstPos),
bslm.isLast(lastPos));
parentLM.isFirst(firstPos),
parentLM.isLast(lastPos));
} }


PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
childLM.addAreas(childPosIter, lc); childLM.addAreas(childPosIter, lc);
} }


if (bslm != null) {
bslm.registerMarkers(
if (parentLM != null) {
parentLM.registerMarkers(
false, false,
bslm.isFirst(firstPos),
bslm.isLast(lastPos));
parentLM.isFirst(firstPos),
parentLM.isLast(lastPos));
} }





+ 10
- 54
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java Voir le fichier

import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.properties.CommonAbsolutePosition; 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.fo.properties.KeepProperty;
import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal; import org.apache.fop.traits.SpaceVal;
/** /**
* LayoutManager for a block-container FO. * LayoutManager for a block-container FO.
*/ */
public class BlockContainerLayoutManager extends BlockStackingLayoutManager implements
ConditionalElementListener, BreakOpportunity {
public class BlockContainerLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
implements BreakOpportunity {


/** /**
* logging instance * logging instance
private MinOptMax foBlockSpaceBefore; private MinOptMax foBlockSpaceBefore;
private MinOptMax foBlockSpaceAfter; 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 int horizontalOverflow;
private double contentRectOffsetX = 0; private double contentRectOffsetX = 0;
private double contentRectOffsetY = 0; private double contentRectOffsetY = 0;
*/ */
public BlockContainerLayoutManager(BlockContainer node) { public BlockContainerLayoutManager(BlockContainer node) {
super(node); super(node);
setGeneratesBlockArea(true);
} }


/** {@inheritDoc} */ /** {@inheritDoc} */
.spaceAfter.getSpace().getOptimum(this).getLength().getValue(this); .spaceAfter.getSpace().getOptimum(this).getLength().getValue(this);
} }


@Override
protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
return getBlockContainerFO().getCommonBorderPaddingBackground();
}

private void resetSpaces() { private void resetSpaces() {
this.discardBorderBefore = false; this.discardBorderBefore = false;
this.discardBorderAfter = false; this.discardBorderAfter = false;
transferForeignAttributes(viewportBlockArea); transferForeignAttributes(viewportBlockArea);


TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId()); TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId());
TraitSetter.setLayer(viewportBlockArea, getBlockContainerFO().getLayer());
TraitSetter.addBorders(viewportBlockArea, TraitSetter.addBorders(viewportBlockArea,
getBlockContainerFO().getCommonBorderPaddingBackground(), getBlockContainerFO().getCommonBorderPaddingBackground(),
discardBorderBefore, discardBorderAfter, false, false, this); discardBorderBefore, discardBorderAfter, false, false, this);
return true; 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} */ /** {@inheritDoc} */
public boolean handleOverflow(int milliPoints) { public boolean handleOverflow(int milliPoints) {
if (milliPoints > this.horizontalOverflow) { if (milliPoints > this.horizontalOverflow) {

+ 10
- 55
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java Voir le fichier

import org.apache.fop.area.LineArea; import org.apache.fop.area.LineArea;
import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode; import org.apache.fop.fo.FONode;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fonts.Font; import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontInfo;
/** /**
* LayoutManager for a block FO. * LayoutManager for a block FO.
*/ */
public class BlockLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener,
BreakOpportunity {
public class BlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
implements BreakOpportunity {


/** logging instance */ /** logging instance */
private static Log log = LogFactory.getLog(BlockLayoutManager.class); private static Log log = LogFactory.getLog(BlockLayoutManager.class);
private int follow = 2000; private int follow = 2000;
//private int middleShift = 0; //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. * Creates a new BlockLayoutManager.
* @param inBlock the block FO object to create the layout manager for. * @param inBlock the block FO object to create the layout manager for.
.getOptimum(this).getLength().getValue(this); .getOptimum(this).getLength().getValue(this);
} }


@Override
protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
return getBlockFO().getCommonBorderPaddingBackground();
}

/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public List getNextKnuthElements(LayoutContext context, int alignment) { public List getNextKnuthElements(LayoutContext context, int alignment) {


curBlockArea.setIPD(super.getContentAreaIPD()); curBlockArea.setIPD(super.getContentAreaIPD());


curBlockArea.setBidiLevel(getBlockFO().getBidiLevel());
curBlockArea.setBidiLevel(getBlockFO().getBidiLevelRecursive());


TraitSetter.addBreaks(curBlockArea, TraitSetter.addBreaks(curBlockArea,
getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter()); getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter());
getBlockFO().getCommonBorderPaddingBackground(), getBlockFO().getCommonBorderPaddingBackground(),
startIndent, endIndent, startIndent, endIndent,
this); this);
TraitSetter.setLayer(curBlockArea, getBlockFO().getLayer());


curBlockArea.setLocale(getBlockFO().getCommonHyphenation().getLocale()); curBlockArea.setLocale(getBlockFO().getCommonHyphenation().getLocale());
curBlockArea.setLocation(FONode.getLocatorString(getBlockFO().getLocator())); curBlockArea.setLocation(FONode.getLocatorString(getBlockFO().getLocator()));
return true; 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} */ /** {@inheritDoc} */
@Override @Override
public boolean isRestartable() { public boolean isRestartable() {

+ 3
- 0
src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java Voir le fichier

import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.SpaceProperty; 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.layoutmgr.inline.InlineLayoutManager;
import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.ListUtil; import org.apache.fop.util.ListUtil;
public boolean handleOverflow(int milliPoints) { public boolean handleOverflow(int milliPoints) {
if (getParent() instanceof BlockStackingLayoutManager) { if (getParent() instanceof BlockStackingLayoutManager) {
return ((BlockStackingLayoutManager) getParent()).handleOverflow(milliPoints); return ((BlockStackingLayoutManager) getParent()).handleOverflow(milliPoints);
} else if (getParent() instanceof InlineContainerLayoutManager) {
return ((InlineContainerLayoutManager) getParent()).handleOverflow(milliPoints);
} }
return false; return false;
} }

+ 8
- 2
src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java Voir le fichier

pv.setPage(pageArea); pv.setPage(pageArea);


RegionViewport rv = new RegionViewport(referenceRect); 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); rv.setClip(true);


BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY, BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY,

+ 1
- 0
src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java Voir le fichier

*/ */
public FlowLayoutManager(PageSequenceLayoutManager pslm, Flow node) { public FlowLayoutManager(PageSequenceLayoutManager pslm, Flow node) {
super(node); super(node);
setGeneratesBlockArea(true);
setParent(pslm); setParent(pslm);
} }



+ 19
- 0
src/java/org/apache/fop/layoutmgr/LayoutManager.java Voir le fichier

*/ */
List getChangedKnuthElements(List oldList, int alignment); 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 * Returns the IPD of the content area
* @return the IPD of the content area * @return the IPD of the content area

+ 5
- 7
src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java Voir le fichier

import org.apache.fop.layoutmgr.inline.ContentLayoutManager; import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager; import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager;
import org.apache.fop.layoutmgr.inline.FootnoteLayoutManager; 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.InlineLayoutManager;
import org.apache.fop.layoutmgr.inline.InstreamForeignObjectLM; import org.apache.fop.layoutmgr.inline.InstreamForeignObjectLM;
import org.apache.fop.layoutmgr.inline.LeaderLayoutManager; import org.apache.fop.layoutmgr.inline.LeaderLayoutManager;
/** a layout manager maker */ /** a layout manager maker */
public static class InlineLayoutManagerMaker extends Maker { public static class InlineLayoutManagerMaker extends Maker {
/** {@inheritDoc} */ /** {@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 */ /** a layout manager maker */
public static class InlineContainerLayoutManagerMaker extends Maker { public static class InlineContainerLayoutManagerMaker extends Maker {
/** {@inheritDoc} */ /** {@inheritDoc} */
public void make(FONode node, List lms) { 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));
} }
} }



+ 46
- 32
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java Voir le fichier

*/ */
protected class KnuthPageNode extends KnuthNode { 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; public int totalFootnotes;


/** Index of the last inserted footnote. */ /** Index of the last inserted footnote. */
public KnuthPageNode(int position, public KnuthPageNode(int position,
int line, int fitness, int line, int fitness,
int totalWidth, int totalStretch, int totalShrink, 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, double adjustRatio, int availableShrink, int availableStretch,
int difference, double totalDemerits, KnuthNode previous) { int difference, double totalDemerits, KnuthNode previous) {
super(position, line, fitness, super(position, line, fitness,
adjustRatio, availableShrink, availableStretch, adjustRatio, availableShrink, availableStretch,
difference, totalDemerits, previous); difference, totalDemerits, previous);
this.totalFootnotes = totalFootnotes; this.totalFootnotes = totalFootnotes;
this.insertedFootnotes = insertedFootnotes;
this.footnoteListIndex = footnoteListIndex; this.footnoteListIndex = footnoteListIndex;
this.footnoteElementIndex = footnoteElementIndex; this.footnoteElementIndex = footnoteElementIndex;
} }
*/ */
protected class BestPageRecords extends BestRecords { 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[] bestFootnoteListIndex = new int[4];
private int[] bestFootnoteElementIndex = new int[4]; private int[] bestFootnoteElementIndex = new int[4];


super.addRecord(demerits, node, adjust, super.addRecord(demerits, node, adjust,
availableShrink, availableStretch, availableShrink, availableStretch,
difference, fitness); difference, fitness);
bestFootnotesLength[fitness] = insertedFootnotesLength;
bestInsertedFootnotesLength[fitness] = insertedFootnotesLength;
bestTotalFootnotesLength[fitness] = totalFootnotesLength;
bestFootnoteListIndex[fitness] = footnoteListIndex; bestFootnoteListIndex[fitness] = footnoteListIndex;
bestFootnoteElementIndex[fitness] = footnoteElementIndex; 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) { public int getFootnoteListIndex(int fitness) {
int difference, double totalDemerits, KnuthNode previous) { int difference, double totalDemerits, KnuthNode previous) {
return new KnuthPageNode(position, line, fitness, return new KnuthPageNode(position, line, fitness,
totalWidth, totalStretch, totalShrink, totalWidth, totalStretch, totalShrink,
insertedFootnotesLength, footnoteListIndex, footnoteElementIndex,
insertedFootnotesLength, totalFootnotesLength,
footnoteListIndex, footnoteElementIndex,
adjustRatio, availableShrink, availableStretch, adjustRatio, availableShrink, availableStretch,
difference, totalDemerits, previous); difference, totalDemerits, previous);
} }
int totalWidth, int totalStretch, int totalShrink) { int totalWidth, int totalStretch, int totalShrink) {
return new KnuthPageNode(position, line, fitness, return new KnuthPageNode(position, line, fitness,
totalWidth, totalStretch, totalShrink, totalWidth, totalStretch, totalShrink,
((BestPageRecords) best).getFootnotesLength(fitness),
((BestPageRecords) best).getInsertedFootnotesLength(fitness),
((BestPageRecords) best).getTotalFootnotesLength(fitness),
((BestPageRecords) best).getFootnoteListIndex(fitness), ((BestPageRecords) best).getFootnoteListIndex(fitness),
((BestPageRecords) best).getFootnoteElementIndex(fitness), ((BestPageRecords) best).getFootnoteElementIndex(fitness),
best.getAdjust(fitness), best.getAvailableShrink(fitness), best.getAdjust(fitness), best.getAvailableShrink(fitness),
resetFootnotes(((KnuthBlockBox) resetElement).getElementLists()); 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; return returnValue;
} }
for (int i = 0; i < elementLists.size(); i++) { for (int i = 0; i < elementLists.size(); i++) {
ListUtil.removeLast(footnotesList); ListUtil.removeLast(footnotesList);
ListUtil.removeLast(lengthList); ListUtil.removeLast(lengthList);

// update totalFootnotesLength
if (!lengthList.isEmpty()) {
totalFootnotesLength = ListUtil.getLast(lengthList);
} else {
totalFootnotesLength = 0;
}
} }
// update footnotesPending; // update footnotesPending;
if (footnotesList.size() == 0) { if (footnotesList.size() == 0) {
} }
if (footnotesPending) { if (footnotesPending) {
// compute the total length of the footnotes not yet inserted // compute the total length of the footnotes not yet inserted
int allFootnotes = totalFootnotesLength - pageNode.totalFootnotes;
int allFootnotes = totalFootnotesLength - pageNode.insertedFootnotes;
if (allFootnotes > 0) { if (allFootnotes > 0) {
// this page contains some footnote citations // this page contains some footnote citations
// add the footnote separator width // add the footnote separator width
// there is enough space to insert all footnotes: // there is enough space to insert all footnotes:
// add the whole allFootnotes length // add the whole allFootnotes length
actualWidth += allFootnotes; actualWidth += allFootnotes;
insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes;
insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes;
footnoteListIndex = footnotesList.size() - 1; footnoteListIndex = footnotesList.size() - 1;
footnoteElementIndex footnoteElementIndex
= getFootnoteList(footnoteListIndex).size() - 1; = getFootnoteList(footnoteListIndex).size() - 1;
// this is the first feasible break; in this case it is allowed // this is the first feasible break; in this case it is allowed
// to break and defer, if necessary, old and new footnotes // to break and defer, if necessary, old and new footnotes
actualWidth += footnoteSplit; actualWidth += footnoteSplit;
insertedFootnotesLength = pageNode.totalFootnotes + footnoteSplit;
insertedFootnotesLength = pageNode.insertedFootnotes + footnoteSplit;
// footnoteListIndex has been set in getFootnoteSplit() // footnoteListIndex has been set in getFootnoteSplit()
// footnoteElementIndex has been set in getFootnoteSplit() // footnoteElementIndex has been set in getFootnoteSplit()
} else { } else {
// that cannot be broken: // that cannot be broken:
// add the whole allFootnotes length, so this breakpoint will be discarded // add the whole allFootnotes length, so this breakpoint will be discarded
actualWidth += allFootnotes; actualWidth += allFootnotes;
insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes;
insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes;
footnoteListIndex = footnotesList.size() - 1; footnoteListIndex = footnotesList.size() - 1;
footnoteElementIndex footnoteElementIndex
= getFootnoteList(footnoteListIndex).size() - 1; = getFootnoteList(footnoteListIndex).size() - 1;
private boolean canDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) { private boolean canDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) {
return (noBreakBetween(node.position, contentElementIndex) return (noBreakBetween(node.position, contentElementIndex)
&& deferredFootnotes(node.footnoteListIndex, && deferredFootnotes(node.footnoteListIndex,
node.footnoteElementIndex, node.totalFootnotes));
node.footnoteElementIndex, node.insertedFootnotes));
} }


/** /**
boolean canDeferOldFootnotes) { boolean canDeferOldFootnotes) {
return getFootnoteSplit(activeNode.footnoteListIndex, return getFootnoteSplit(activeNode.footnoteListIndex,
activeNode.footnoteElementIndex, activeNode.footnoteElementIndex,
activeNode.totalFootnotes,
activeNode.insertedFootnotes,
availableLength, canDeferOldFootnotes); availableLength, canDeferOldFootnotes);
} }


int prevIndex = -1; int prevIndex = -1;
int index = -1; int index = -1;


while (!(somethingAdded && splitLength > availableLength)) {
if (!somethingAdded) {
somethingAdded = true;
} else {
while (splitLength <= availableLength) {
if (somethingAdded) {
prevSplitLength = splitLength; prevSplitLength = splitLength;
prevIndex = index; prevIndex = index;
} }
// element is a box // element is a box
splitLength += element.getWidth(); splitLength += element.getWidth();
boxPreceding = true; boxPreceding = true;
if (splitLength > prevSplitLength) {
// and it is non-empty
somethingAdded = true;
}
} else if (element.isGlue()) { } else if (element.isGlue()) {
// element is a glue // element is a glue
if (boxPreceding) { if (boxPreceding) {
index = noteListIterator.previousIndex(); index = noteListIterator.previousIndex();
break; break;
} }
boxPreceding = false;
} }
} }
} }
// page here // page here
// if prevSplitLength is > 0 we can insert some footnote content in this page // if prevSplitLength is > 0 we can insert some footnote content in this page
// and insert the remaining in the following one // and insert the remaining in the following one
//TODO: check this conditional, as the first one is always false...?
if (!somethingAdded) { if (!somethingAdded) {
// there was not enough space to add a piece of the first new footnote // there was not enough space to add a piece of the first new footnote
// this is not a good break // this is not a good break
if (difference > 0) { if (difference > 0) {
int maxAdjustment = totalStretch - activeNode.totalStretch; int maxAdjustment = totalStretch - activeNode.totalStretch;
// add the footnote separator stretch if some footnote content will be added // 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(); maxAdjustment += footnoteSeparatorLength.getStretch();
} }
if (maxAdjustment > 0) { if (maxAdjustment > 0) {
} else if (difference < 0) { } else if (difference < 0) {
int maxAdjustment = totalShrink - activeNode.totalShrink; int maxAdjustment = totalShrink - activeNode.totalShrink;
// add the footnote separator shrink if some footnote content will be added // 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(); maxAdjustment += footnoteSeparatorLength.getShrink();
} }
if (maxAdjustment > 0) { if (maxAdjustment > 0) {
for (KnuthPageNode node = (KnuthPageNode) getNode(i); for (KnuthPageNode node = (KnuthPageNode) getNode(i);
node != null; node != null;
node = (KnuthPageNode) node.next) { node = (KnuthPageNode) node.next) {
if (node.totalFootnotes < totalFootnotesLength) {
if (node.insertedFootnotes < totalFootnotesLength) {
// layout remaining footnote bodies // layout remaining footnote bodies
createFootnotePages(node); createFootnotePages(node);
} }


private void createFootnotePages(KnuthPageNode lastNode) { private void createFootnotePages(KnuthPageNode lastNode) {


insertedFootnotesLength = lastNode.totalFootnotes;
insertedFootnotesLength = lastNode.insertedFootnotes;
footnoteListIndex = lastNode.footnoteListIndex; footnoteListIndex = lastNode.footnoteListIndex;
footnoteElementIndex = lastNode.footnoteElementIndex; footnoteElementIndex = lastNode.footnoteElementIndex;
int availableBPD = getLineWidth(lastNode.line); int availableBPD = getLineWidth(lastNode.line);
// cannot add any content: create a new node and start again // cannot add any content: create a new node and start again
KnuthPageNode node = (KnuthPageNode) KnuthPageNode node = (KnuthPageNode)
createNode(lastNode.position, prevNode.line + 1, 1, createNode(lastNode.position, prevNode.line + 1, 1,
insertedFootnotesLength - prevNode.totalFootnotes,
insertedFootnotesLength - prevNode.insertedFootnotes,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, prevNode); 0, 0, prevNode);
// create the last node // create the last node
KnuthPageNode node = (KnuthPageNode) KnuthPageNode node = (KnuthPageNode)
createNode(lastNode.position, prevNode.line + 1, 1, createNode(lastNode.position, prevNode.line + 1, 1,
totalFootnotesLength - prevNode.totalFootnotes, 0, 0,
totalFootnotesLength - prevNode.insertedFootnotes, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, prevNode); 0, 0, prevNode);
addNode(node.line, node); addNode(node.line, node);

+ 112
- 0
src/java/org/apache/fop/layoutmgr/SpacedBorderedPaddedBlockLayoutManager.java Voir le fichier

/*
* 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();

}

+ 0
- 0
src/java/org/apache/fop/layoutmgr/TraitSetter.java Voir le fichier


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff

Chargement…
Annuler
Enregistrer