diff options
102 files changed, 7165 insertions, 5089 deletions
@@ -565,11 +565,13 @@ list of possible build targets. <include name="org/apache/fop/apps/io/**"/> <include name="org/apache/fop/complexscripts/fonts/*.class"/> <include name="org/apache/fop/complexscripts/util/GlyphTester.class"/> + <include name="org/apache/fop/events/EventProducer.class"/> <include name="org/apache/fop/fo/Constants.class"/> <include name="org/apache/fop/fo/FOTreeBuilder.class"/> <include name="org/apache/fop/area/AreaTreeControl*"/> <include name="org/apache/fop/svg/**"/> <include name="org/apache/fop/fonts/**"/> + <include name="org/apache/fop/traits/MinOptMax.class"/> <include name="org/apache/fop/image/loader/batik/BatikImageFlavors*.class"/> <include name="org/apache/fop/util/CMYKColorSpace*.class"/> <include name="org/apache/fop/util/Color*.class"/> @@ -579,6 +581,7 @@ list of possible build targets. <include name="org/apache/fop/util/Finalizable.class"/> <include name="org/apache/fop/util/CharUtilities.class"/> <include name="org/apache/fop/util/DecimalFormatCache*.class"/> + <include name="org/apache/fop/util/ImageObject.class"/> </patternset> <!-- PDF transcoder --> <patternset> @@ -647,7 +650,8 @@ list of possible build targets. <include name="org/apache/xmlgraphics/java2d/**"/> <include name="org/apache/xmlgraphics/ps/**"/> <include name="org/apache/xmlgraphics/fonts/**"/> - <include name="org/apache/xmlgraphics/util/io/**"/> + <include name="org/apache/xmlgraphics/util/**"/> + <include name="org/apache/xmlgraphics/image/loader/**"/> </patternset> <fileset refid="transcoder-lib-files"/> </unjar> @@ -709,6 +713,7 @@ list of possible build targets. <include name="**/*.txt"/> <include name="**/*.afm"/> <include name="**/*.fo"/> + <include name="**/*.svg"/> </fileset> </copy> </target> diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml index 31edec268..0af5e4012 100644 --- a/findbugs-exclude.xml +++ b/findbugs-exclude.xml @@ -1,6 +1,36 @@ <?xml version="1.0" encoding="utf-8"?> <FindBugsFilter> <Match> + <Class name="org.apache.fop.layoutmgr.inline.TextLayoutManager$TextAreaBuilder"/> + <Method name="getMappingBidiLevels"/> + <Bug pattern="PZLA_PREFER_ZERO_LENGTH_ARRAYS"/> + </Match> + <Match> + <Class name="org.apache.fop.svg.PDFTextPainter"/> + <Field name="pdf"/> + <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> + </Match> + <Match> + <Class name="org.apache.fop.render.ps.PSTextPainter"/> + <Or> + <Field name="gen"/> + <Field name="ps"/> + <Field name="psRun"/> + <Field name="textUtil"/> + </Or> + <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/> + </Match> + <Match> + <Class name="org.apache.fop.fonts.GlyphMapping"/> + <Method name="<init>"/> + <Bug pattern="EI_EXPOSE_REP2"/> + </Match> + <Match> + <Class name="org.apache.fop.fonts.MultiByteFont"/> + <Method name="setBBoxArray"/> + <Bug pattern="EI_EXPOSE_REP2"/> + </Match> + <Match> <Class name="org.apache.fop.fonts.truetype.TTFFile$1"/> <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/> </Match> diff --git a/lib/batik-all-1.7.jar b/lib/batik-all-1.7.jar Binary files differdeleted file mode 100644 index 589328581..000000000 --- a/lib/batik-all-1.7.jar +++ /dev/null diff --git a/lib/batik-all-trunk-patch1041.jar b/lib/batik-all-trunk-patch1041.jar Binary files differnew file mode 100644 index 000000000..cf69a308d --- /dev/null +++ b/lib/batik-all-trunk-patch1041.jar diff --git a/src/codegen/fonts/Courier.xml b/src/codegen/fonts/Courier.xml index be977e22e..075699427 100644 --- a/src/codegen/fonts/Courier.xml +++ b/src/codegen/fonts/Courier.xml @@ -22,275 +22,246 @@ <family-name>Courier</family-name> <class-name>Courier</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>562</cap-height> <x-height>426</x-height> <ascender>629</ascender> <descender>-157</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="600"/> - <char name="AE" width="600"/> - <char name="Aacute" width="600"/> - <char name="Acircumflex" width="600"/> - <char name="Adieresis" width="600"/> - <char name="Agrave" width="600"/> - <char name="Aring" width="600"/> - <char name="Atilde" width="600"/> - <char name="B" width="600"/> - <char name="C" width="600"/> - <char name="Ccedilla" width="600"/> - <char name="D" width="600"/> - <char name="E" width="600"/> - <char name="Eacute" width="600"/> - <char name="Ecircumflex" width="600"/> - <char name="Edieresis" width="600"/> - <char name="Egrave" width="600"/> - <char name="Eth" width="600"/> - <char name="Euro" width="600"/> - <char name="F" width="600"/> - <char name="G" width="600"/> - <char name="Gcaron" width="600"/> - <char name="H" width="600"/> - <char name="I" width="600"/> - <char name="IJ" width="600"/> - <char name="Iacute" width="600"/> - <char name="Icircumflex" width="600"/> - <char name="Idieresis" width="600"/> - <char name="Idot" width="600"/> - <char name="Igrave" width="600"/> - <char name="J" width="600"/> - <char name="K" width="600"/> - <char name="L" width="600"/> - <char name="LL" width="600"/> - <char name="Lslash" width="600"/> - <char name="M" width="600"/> - <char name="N" width="600"/> - <char name="Ntilde" width="600"/> - <char name="O" width="600"/> - <char name="OE" width="600"/> - <char name="Oacute" width="600"/> - <char name="Ocircumflex" width="600"/> - <char name="Odieresis" width="600"/> - <char name="Ograve" width="600"/> - <char name="Oslash" width="600"/> - <char name="Otilde" width="600"/> - <char name="P" width="600"/> - <char name="Q" width="600"/> - <char name="R" width="600"/> - <char name="S" width="600"/> - <char name="Scaron" width="600"/> - <char name="Scedilla" width="600"/> - <char name="T" width="600"/> - <char name="Thorn" width="600"/> - <char name="U" width="600"/> - <char name="Uacute" width="600"/> - <char name="Ucircumflex" width="600"/> - <char name="Udieresis" width="600"/> - <char name="Ugrave" width="600"/> - <char name="V" width="600"/> - <char name="W" width="600"/> - <char name="X" width="600"/> - <char name="Y" width="600"/> - <char name="Yacute" width="600"/> - <char name="Ydieresis" width="600"/> - <char name="Z" width="600"/> - <char name="Zcaron" width="600"/> - <char name="a" width="600"/> - <char name="aacute" width="600"/> - <char name="acircumflex" width="600"/> - <char name="acute" width="600"/> - <char name="adieresis" width="600"/> - <char name="ae" width="600"/> - <char name="agrave" width="600"/> - <char name="ampersand" width="600"/> - <char name="aring" width="600"/> - <char name="arrowboth" width="600"/> - <char name="arrowdown" width="600"/> - <char name="arrowleft" width="600"/> - <char name="arrowright" width="600"/> - <char name="arrowup" width="600"/> - <char name="asciicircum" width="600"/> - <char name="asciitilde" width="600"/> - <char name="asterisk" width="600"/> - <char name="at" width="600"/> - <char name="atilde" width="600"/> - <char name="b" width="600"/> - <char name="backslash" width="600"/> - <char name="bar" width="600"/> - <char name="braceleft" width="600"/> - <char name="braceright" width="600"/> - <char name="bracketleft" width="600"/> - <char name="bracketright" width="600"/> - <char name="breve" width="600"/> - <char name="brokenbar" width="600"/> - <char name="bullet" width="600"/> - <char name="c" width="600"/> - <char name="caron" width="600"/> - <char name="ccedilla" width="600"/> - <char name="cedilla" width="600"/> - <char name="cent" width="600"/> - <char name="center" width="600"/> - <char name="circumflex" width="600"/> - <char name="colon" width="600"/> - <char name="comma" width="600"/> - <char name="copyright" width="600"/> - <char name="currency" width="600"/> - <char name="d" width="600"/> - <char name="dagger" width="600"/> - <char name="daggerdbl" width="600"/> - <char name="dectab" width="600"/> - <char name="degree" width="600"/> - <char name="dieresis" width="600"/> - <char name="divide" width="600"/> - <char name="dollar" width="600"/> - <char name="dotaccent" width="600"/> - <char name="dotlessi" width="600"/> - <char name="down" width="600"/> - <char name="e" width="600"/> - <char name="eacute" width="600"/> - <char name="ecircumflex" width="600"/> - <char name="edieresis" width="600"/> - <char name="egrave" width="600"/> - <char name="eight" width="600"/> - <char name="ellipsis" width="600"/> - <char name="emdash" width="600"/> - <char name="endash" width="600"/> - <char name="equal" width="600"/> - <char name="eth" width="600"/> - <char name="exclam" width="600"/> - <char name="exclamdown" width="600"/> - <char name="f" width="600"/> - <char name="fi" width="600"/> - <char name="five" width="600"/> - <char name="fl" width="600"/> - <char name="florin" width="600"/> - <char name="format" width="600"/> - <char name="four" width="600"/> - <char name="fraction" width="600"/> - <char name="g" width="600"/> - <char name="gcaron" width="600"/> - <char name="germandbls" width="600"/> - <char name="grave" width="600"/> - <char name="graybox" width="600"/> - <char name="greater" width="600"/> - <char name="guillemotleft" width="600"/> - <char name="guillemotright" width="600"/> - <char name="guilsinglleft" width="600"/> - <char name="guilsinglright" width="600"/> - <char name="h" width="600"/> - <char name="hungarumlaut" width="600"/> - <char name="hyphen" width="600"/> - <char name="i" width="600"/> - <char name="iacute" width="600"/> - <char name="icircumflex" width="600"/> - <char name="idieresis" width="600"/> - <char name="igrave" width="600"/> - <char name="ij" width="600"/> - <char name="indent" width="600"/> - <char name="j" width="600"/> - <char name="k" width="600"/> - <char name="l" width="600"/> - <char name="largebullet" width="600"/> - <char name="left" width="600"/> - <char name="less" width="600"/> - <char name="lira" width="600"/> - <char name="ll" width="600"/> - <char name="logicalnot" width="600"/> - <char name="lslash" width="600"/> - <char name="m" width="600"/> - <char name="macron" width="600"/> - <char name="merge" width="600"/> - <char name="minus" width="600"/> - <char name="mu" width="600"/> - <char name="multiply" width="600"/> - <char name="n" width="600"/> - <char name="nine" width="600"/> - <char name="notegraphic" width="600"/> - <char name="ntilde" width="600"/> - <char name="numbersign" width="600"/> - <char name="o" width="600"/> - <char name="oacute" width="600"/> - <char name="ocircumflex" width="600"/> - <char name="odieresis" width="600"/> - <char name="oe" width="600"/> - <char name="ogonek" width="600"/> - <char name="ograve" width="600"/> - <char name="one" width="600"/> - <char name="onehalf" width="600"/> - <char name="onequarter" width="600"/> - <char name="onesuperior" width="600"/> - <char name="ordfeminine" width="600"/> - <char name="ordmasculine" width="600"/> - <char name="oslash" width="600"/> - <char name="otilde" width="600"/> - <char name="overscore" width="600"/> - <char name="p" width="600"/> - <char name="paragraph" width="600"/> - <char name="parenleft" width="600"/> - <char name="parenright" width="600"/> - <char name="percent" width="600"/> - <char name="period" width="600"/> - <char name="periodcentered" width="600"/> - <char name="perthousand" width="600"/> - <char name="plus" width="600"/> - <char name="plusminus" width="600"/> - <char name="prescription" width="600"/> - <char name="q" width="600"/> - <char name="question" width="600"/> - <char name="questiondown" width="600"/> - <char name="quotedbl" width="600"/> - <char name="quotedblbase" width="600"/> - <char name="quotedblleft" width="600"/> - <char name="quotedblright" width="600"/> - <char name="quoteleft" width="600"/> - <char name="quoteright" width="600"/> - <char name="quotesinglbase" width="600"/> - <char name="quotesingle" width="600"/> - <char name="r" width="600"/> - <char name="registered" width="600"/> - <char name="return" width="600"/> - <char name="ring" width="600"/> - <char name="s" width="600"/> - <char name="scaron" width="600"/> - <char name="scedilla" width="600"/> - <char name="section" width="600"/> - <char name="semicolon" width="600"/> - <char name="seven" width="600"/> - <char name="six" width="600"/> - <char name="slash" width="600"/> - <char name="space" width="600"/> + <char-metrics> + <char name="A" width="600" llx="3" lly="0" urx="597" ury="562"/> + <char name="AE" width="600" llx="3" lly="0" urx="550" ury="562"/> + <char name="Aacute" width="600" llx="3" lly="0" urx="597" ury="805"/> + <char name="Acircumflex" width="600" llx="3" lly="0" urx="597" ury="787"/> + <char name="Adieresis" width="600" llx="3" lly="0" urx="597" ury="753"/> + <char name="Agrave" width="600" llx="3" lly="0" urx="597" ury="805"/> + <char name="Aring" width="600" llx="3" lly="0" urx="597" ury="750"/> + <char name="Atilde" width="600" llx="3" lly="0" urx="597" ury="729"/> + <char name="B" width="600" llx="43" lly="0" urx="559" ury="562"/> + <char name="C" width="600" llx="41" lly="-18" urx="540" ury="580"/> + <char name="Ccedilla" width="600" llx="41" lly="-151" urx="540" ury="580"/> + <char name="D" width="600" llx="43" lly="0" urx="574" ury="562"/> + <char name="E" width="600" llx="53" lly="0" urx="550" ury="562"/> + <char name="Eacute" width="600" llx="53" lly="0" urx="550" ury="805"/> + <char name="Ecircumflex" width="600" llx="53" lly="0" urx="550" ury="787"/> + <char name="Edieresis" width="600" llx="53" lly="0" urx="550" ury="753"/> + <char name="Egrave" width="600" llx="53" lly="0" urx="550" ury="805"/> + <char name="Eth" width="600" llx="30" lly="0" urx="574" ury="562"/> + <char name="Euro" width="600" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="600" llx="53" lly="0" urx="545" ury="562"/> + <char name="G" width="600" llx="31" lly="-18" urx="575" ury="580"/> + <char name="H" width="600" llx="32" lly="0" urx="568" ury="562"/> + <char name="I" width="600" llx="96" lly="0" urx="504" ury="562"/> + <char name="Iacute" width="600" llx="96" lly="0" urx="504" ury="805"/> + <char name="Icircumflex" width="600" llx="96" lly="0" urx="504" ury="787"/> + <char name="Idieresis" width="600" llx="96" lly="0" urx="504" ury="753"/> + <char name="Igrave" width="600" llx="96" lly="0" urx="504" ury="805"/> + <char name="J" width="600" llx="34" lly="-18" urx="566" ury="562"/> + <char name="K" width="600" llx="38" lly="0" urx="582" ury="562"/> + <char name="L" width="600" llx="47" lly="0" urx="554" ury="562"/> + <char name="Lslash" width="600" llx="47" lly="0" urx="554" ury="562"/> + <char name="M" width="600" llx="4" lly="0" urx="596" ury="562"/> + <char name="N" width="600" llx="7" lly="-13" urx="593" ury="562"/> + <char name="Ntilde" width="600" llx="7" lly="-13" urx="593" ury="729"/> + <char name="O" width="600" llx="43" lly="-18" urx="557" ury="580"/> + <char name="OE" width="600" llx="7" lly="0" urx="567" ury="562"/> + <char name="Oacute" width="600" llx="43" lly="-18" urx="557" ury="805"/> + <char name="Ocircumflex" width="600" llx="43" lly="-18" urx="557" ury="787"/> + <char name="Odieresis" width="600" llx="43" lly="-18" urx="557" ury="753"/> + <char name="Ograve" width="600" llx="43" lly="-18" urx="557" ury="805"/> + <char name="Oslash" width="600" llx="43" lly="-80" urx="557" ury="629"/> + <char name="Otilde" width="600" llx="43" lly="-18" urx="557" ury="729"/> + <char name="P" width="600" llx="79" lly="0" urx="558" ury="562"/> + <char name="Q" width="600" llx="43" lly="-138" urx="557" ury="580"/> + <char name="R" width="600" llx="38" lly="0" urx="588" ury="562"/> + <char name="S" width="600" llx="72" lly="-20" urx="529" ury="580"/> + <char name="Scaron" width="600" llx="72" lly="-20" urx="529" ury="802"/> + <char name="Scedilla" width="600" llx="72" lly="-151" urx="529" ury="580"/> + <char name="T" width="600" llx="38" lly="0" urx="563" ury="562"/> + <char name="Thorn" width="600" llx="79" lly="0" urx="538" ury="562"/> + <char name="U" width="600" llx="17" lly="-18" urx="583" ury="562"/> + <char name="Uacute" width="600" llx="17" lly="-18" urx="583" ury="805"/> + <char name="Ucircumflex" width="600" llx="17" lly="-18" urx="583" ury="787"/> + <char name="Udieresis" width="600" llx="17" lly="-18" urx="583" ury="753"/> + <char name="Ugrave" width="600" llx="17" lly="-18" urx="583" ury="805"/> + <char name="V" width="600" llx="-4" lly="-13" urx="604" ury="562"/> + <char name="W" width="600" llx="-3" lly="-13" urx="603" ury="562"/> + <char name="X" width="600" llx="23" lly="0" urx="577" ury="562"/> + <char name="Y" width="600" llx="24" lly="0" urx="576" ury="562"/> + <char name="Yacute" width="600" llx="24" lly="0" urx="576" ury="805"/> + <char name="Ydieresis" width="600" llx="24" lly="0" urx="576" ury="753"/> + <char name="Z" width="600" llx="86" lly="0" urx="514" ury="562"/> + <char name="Zcaron" width="600" llx="86" lly="0" urx="514" ury="802"/> + <char name="a" width="600" llx="53" lly="-15" urx="559" ury="441"/> + <char name="aacute" width="600" llx="53" lly="-15" urx="559" ury="672"/> + <char name="acircumflex" width="600" llx="53" lly="-15" urx="559" ury="654"/> + <char name="acute" width="600" llx="242" lly="497" urx="469" ury="672"/> + <char name="adieresis" width="600" llx="53" lly="-15" urx="559" ury="620"/> + <char name="ae" width="600" llx="19" lly="-15" urx="570" ury="441"/> + <char name="agrave" width="600" llx="53" lly="-15" urx="559" ury="672"/> + <char name="ampersand" width="600" llx="63" lly="-15" urx="538" ury="543"/> + <char name="aring" width="600" llx="53" lly="-15" urx="559" ury="627"/> + <char name="asciicircum" width="600" llx="94" lly="354" urx="506" ury="622"/> + <char name="asciitilde" width="600" llx="63" lly="197" urx="540" ury="320"/> + <char name="asterisk" width="600" llx="116" lly="257" urx="484" ury="607"/> + <char name="at" width="600" llx="77" lly="-15" urx="533" ury="622"/> + <char name="atilde" width="600" llx="53" lly="-15" urx="559" ury="606"/> + <char name="b" width="600" llx="14" lly="-15" urx="575" ury="629"/> + <char name="backslash" width="600" llx="118" lly="-80" urx="482" ury="629"/> + <char name="bar" width="600" llx="275" lly="-250" urx="326" ury="750"/> + <char name="braceleft" width="600" llx="182" lly="-108" urx="437" ury="622"/> + <char name="braceright" width="600" llx="163" lly="-108" urx="418" ury="622"/> + <char name="bracketleft" width="600" llx="269" lly="-108" urx="442" ury="622"/> + <char name="bracketright" width="600" llx="158" lly="-108" urx="331" ury="622"/> + <char name="breve" width="600" llx="153" lly="501" urx="447" ury="609"/> + <char name="brokenbar" width="600" llx="275" lly="-175" urx="326" ury="675"/> + <char name="bullet" width="600" llx="172" lly="130" urx="428" ury="383"/> + <char name="c" width="600" llx="66" lly="-15" urx="529" ury="441"/> + <char name="caron" width="600" llx="124" lly="492" urx="476" ury="669"/> + <char name="ccedilla" width="600" llx="66" lly="-151" urx="529" ury="441"/> + <char name="cedilla" width="600" llx="224" lly="-151" urx="362" ury="10"/> + <char name="cent" width="600" llx="96" lly="-49" urx="500" ury="614"/> + <char name="circumflex" width="600" llx="124" lly="477" urx="476" ury="654"/> + <char name="colon" width="600" llx="229" lly="-15" urx="371" ury="385"/> + <char name="comma" width="600" llx="181" lly="-112" urx="344" ury="122"/> + <char name="copyright" width="600" llx="0" lly="-18" urx="600" ury="580"/> + <char name="currency" width="600" llx="73" lly="58" urx="527" ury="506"/> + <char name="d" width="600" llx="45" lly="-15" urx="591" ury="629"/> + <char name="dagger" width="600" llx="141" lly="-78" urx="459" ury="580"/> + <char name="daggerdbl" width="600" llx="141" lly="-78" urx="459" ury="580"/> + <char name="degree" width="600" llx="123" lly="269" urx="477" ury="622"/> + <char name="dieresis" width="600" llx="148" lly="537" urx="453" ury="640"/> + <char name="divide" width="600" llx="87" lly="48" urx="513" ury="467"/> + <char name="dollar" width="600" llx="105" lly="-126" urx="496" ury="662"/> + <char name="dotaccent" width="600" llx="249" lly="537" urx="352" ury="640"/> + <char name="dotlessi" width="600" llx="95" lly="0" urx="505" ury="426"/> + <char name="e" width="600" llx="66" lly="-15" urx="548" ury="441"/> + <char name="eacute" width="600" llx="66" lly="-15" urx="548" ury="672"/> + <char name="ecircumflex" width="600" llx="66" lly="-15" urx="548" ury="654"/> + <char name="edieresis" width="600" llx="66" lly="-15" urx="548" ury="620"/> + <char name="egrave" width="600" llx="66" lly="-15" urx="548" ury="672"/> + <char name="eight" width="600" llx="102" lly="-15" urx="498" ury="622"/> + <char name="ellipsis" width="600" llx="37" lly="-15" urx="563" ury="111"/> + <char name="emdash" width="600" llx="0" lly="231" urx="600" ury="285"/> + <char name="endash" width="600" llx="75" lly="231" urx="525" ury="285"/> + <char name="equal" width="600" llx="80" lly="138" urx="520" ury="376"/> + <char name="eth" width="600" llx="62" lly="-15" urx="538" ury="629"/> + <char name="exclam" width="600" llx="236" lly="-15" urx="364" ury="572"/> + <char name="exclamdown" width="600" llx="236" lly="-157" urx="364" ury="430"/> + <char name="f" width="600" llx="114" lly="0" urx="531" ury="629"/> + <char name="fi" width="600" llx="3" lly="0" urx="597" ury="629"/> + <char name="five" width="600" llx="92" lly="-15" urx="497" ury="607"/> + <char name="fl" width="600" llx="3" lly="0" urx="597" ury="629"/> + <char name="florin" width="600" llx="4" lly="-143" urx="539" ury="622"/> + <char name="four" width="600" llx="78" lly="0" urx="500" ury="622"/> + <char name="fraction" width="600" llx="92" lly="-57" urx="509" ury="665"/> + <char name="g" width="600" llx="45" lly="-157" urx="566" ury="441"/> + <char name="germandbls" width="600" llx="48" lly="-15" urx="588" ury="629"/> + <char name="grave" width="600" llx="151" lly="497" urx="378" ury="672"/> + <char name="greater" width="600" llx="66" lly="42" urx="544" ury="472"/> + <char name="guillemotleft" width="600" llx="37" lly="70" urx="563" ury="446"/> + <char name="guillemotright" width="600" llx="37" lly="70" urx="563" ury="446"/> + <char name="guilsinglleft" width="600" llx="149" lly="70" urx="451" ury="446"/> + <char name="guilsinglright" width="600" llx="149" lly="70" urx="451" ury="446"/> + <char name="h" width="600" llx="18" lly="0" urx="582" ury="629"/> + <char name="hungarumlaut" width="600" llx="133" lly="497" urx="540" ury="672"/> + <char name="hyphen" width="600" llx="103" lly="231" urx="497" ury="285"/> + <char name="i" width="600" llx="95" lly="0" urx="505" ury="657"/> + <char name="iacute" width="600" llx="95" lly="0" urx="505" ury="672"/> + <char name="icircumflex" width="600" llx="94" lly="0" urx="505" ury="654"/> + <char name="idieresis" width="600" llx="95" lly="0" urx="505" ury="620"/> + <char name="igrave" width="600" llx="95" lly="0" urx="505" ury="672"/> + <char name="j" width="600" llx="82" lly="-157" urx="410" ury="657"/> + <char name="k" width="600" llx="43" lly="0" urx="580" ury="629"/> + <char name="l" width="600" llx="95" lly="0" urx="505" ury="629"/> + <char name="less" width="600" llx="41" lly="42" urx="519" ury="472"/> + <char name="logicalnot" width="600" llx="87" lly="108" urx="513" ury="369"/> + <char name="lslash" width="600" llx="95" lly="0" urx="505" ury="629"/> + <char name="m" width="600" llx="-5" lly="0" urx="605" ury="441"/> + <char name="macron" width="600" llx="120" lly="525" urx="480" ury="565"/> + <char name="minus" width="600" llx="80" lly="232" urx="520" ury="283"/> + <char name="mu" width="600" llx="21" lly="-157" urx="562" ury="426"/> + <char name="multiply" width="600" llx="87" lly="43" urx="515" ury="470"/> + <char name="n" width="600" llx="26" lly="0" urx="575" ury="441"/> + <char name="nine" width="600" llx="96" lly="-15" urx="489" ury="622"/> + <char name="ntilde" width="600" llx="26" lly="0" urx="575" ury="606"/> + <char name="numbersign" width="600" llx="93" lly="-32" urx="507" ury="639"/> + <char name="o" width="600" llx="62" lly="-15" urx="538" ury="441"/> + <char name="oacute" width="600" llx="62" lly="-15" urx="538" ury="672"/> + <char name="ocircumflex" width="600" llx="62" lly="-15" urx="538" ury="654"/> + <char name="odieresis" width="600" llx="62" lly="-15" urx="538" ury="620"/> + <char name="oe" width="600" llx="19" lly="-15" urx="559" ury="441"/> + <char name="ogonek" width="600" llx="211" lly="-172" urx="407" ury="4"/> + <char name="ograve" width="600" llx="62" lly="-15" urx="538" ury="672"/> + <char name="one" width="600" llx="96" lly="0" urx="505" ury="622"/> + <char name="onehalf" width="600" llx="0" lly="-57" urx="611" ury="665"/> + <char name="onequarter" width="600" llx="0" lly="-57" urx="600" ury="665"/> + <char name="onesuperior" width="600" llx="172" lly="249" urx="428" ury="622"/> + <char name="ordfeminine" width="600" llx="156" lly="249" urx="442" ury="580"/> + <char name="ordmasculine" width="600" llx="157" lly="249" urx="443" ury="580"/> + <char name="oslash" width="600" llx="62" lly="-80" urx="538" ury="506"/> + <char name="otilde" width="600" llx="62" lly="-15" urx="538" ury="606"/> + <char name="p" width="600" llx="9" lly="-157" urx="555" ury="441"/> + <char name="paragraph" width="600" llx="50" lly="-78" urx="511" ury="562"/> + <char name="parenleft" width="600" llx="269" lly="-108" urx="440" ury="622"/> + <char name="parenright" width="600" llx="160" lly="-108" urx="331" ury="622"/> + <char name="percent" width="600" llx="81" lly="-15" urx="518" ury="622"/> + <char name="period" width="600" llx="229" lly="-15" urx="371" ury="109"/> + <char name="periodcentered" width="600" llx="222" lly="189" urx="378" ury="327"/> + <char name="perthousand" width="600" llx="3" lly="-15" urx="600" ury="622"/> + <char name="plus" width="600" llx="80" lly="44" urx="520" ury="470"/> + <char name="plusminus" width="600" llx="87" lly="44" urx="513" ury="558"/> + <char name="q" width="600" llx="45" lly="-157" urx="591" ury="441"/> + <char name="question" width="600" llx="129" lly="-15" urx="492" ury="572"/> + <char name="questiondown" width="600" llx="108" lly="-157" urx="471" ury="430"/> + <char name="quotedbl" width="600" llx="187" lly="328" urx="413" ury="562"/> + <char name="quotedblbase" width="600" llx="143" lly="-134" urx="457" ury="100"/> + <char name="quotedblleft" width="600" llx="143" lly="328" urx="471" ury="562"/> + <char name="quotedblright" width="600" llx="143" lly="328" urx="457" ury="562"/> + <char name="quoteleft" width="600" llx="224" lly="328" urx="387" ury="562"/> + <char name="quoteright" width="600" llx="213" lly="328" urx="376" ury="562"/> + <char name="quotesinglbase" width="600" llx="213" lly="-134" urx="376" ury="100"/> + <char name="quotesingle" width="600" llx="259" lly="328" urx="341" ury="562"/> + <char name="r" width="600" llx="60" lly="0" urx="559" ury="441"/> + <char name="registered" width="600" llx="0" lly="-18" urx="600" ury="580"/> + <char name="ring" width="600" llx="218" lly="463" urx="382" ury="627"/> + <char name="s" width="600" llx="80" lly="-15" urx="513" ury="441"/> + <char name="scaron" width="600" llx="80" lly="-15" urx="513" ury="669"/> + <char name="scedilla" width="600" llx="80" lly="-151" urx="513" ury="441"/> + <char name="section" width="600" llx="113" lly="-78" urx="488" ury="580"/> + <char name="semicolon" width="600" llx="181" lly="-112" urx="371" ury="385"/> + <char name="seven" width="600" llx="82" lly="0" urx="483" ury="607"/> + <char name="six" width="600" llx="111" lly="-15" urx="497" ury="622"/> + <char name="slash" width="600" llx="125" lly="-80" urx="475" ury="629"/> + <char name="space" width="600" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="600"/> - <char name="square" width="600"/> - <char name="sterling" width="600"/> - <char name="stop" width="600"/> - <char name="t" width="600"/> - <char name="tab" width="600"/> - <char name="thorn" width="600"/> - <char name="three" width="600"/> - <char name="threequarters" width="600"/> - <char name="threesuperior" width="600"/> - <char name="tilde" width="600"/> - <char name="trademark" width="600"/> - <char name="two" width="600"/> - <char name="twosuperior" width="600"/> - <char name="u" width="600"/> - <char name="uacute" width="600"/> - <char name="ucircumflex" width="600"/> - <char name="udieresis" width="600"/> - <char name="ugrave" width="600"/> - <char name="underscore" width="600"/> - <char name="up" width="600"/> - <char name="v" width="600"/> - <char name="w" width="600"/> - <char name="x" width="600"/> - <char name="y" width="600"/> - <char name="yacute" width="600"/> - <char name="ydieresis" width="600"/> - <char name="yen" width="600"/> - <char name="z" width="600"/> - <char name="zcaron" width="600"/> - <char name="zero" width="600"/> - </widths> -</font-metrics>
\ No newline at end of file + <char name="sterling" width="600" llx="84" lly="-21" urx="521" ury="611"/> + <char name="t" width="600" llx="87" lly="-15" urx="530" ury="561"/> + <char name="thorn" width="600" llx="-6" lly="-157" urx="555" ury="629"/> + <char name="three" width="600" llx="75" lly="-15" urx="466" ury="622"/> + <char name="threequarters" width="600" llx="8" lly="-56" urx="593" ury="666"/> + <char name="threesuperior" width="600" llx="155" lly="240" urx="406" ury="622"/> + <char name="tilde" width="600" llx="105" lly="489" urx="503" ury="606"/> + <char name="trademark" width="600" llx="-23" lly="263" urx="623" ury="562"/> + <char name="two" width="600" llx="70" lly="0" urx="471" ury="622"/> + <char name="twosuperior" width="600" llx="177" lly="249" urx="424" ury="622"/> + <char name="u" width="600" llx="21" lly="-15" urx="562" ury="426"/> + <char name="uacute" width="600" llx="21" lly="-15" urx="562" ury="672"/> + <char name="ucircumflex" width="600" llx="21" lly="-15" urx="562" ury="654"/> + <char name="udieresis" width="600" llx="21" lly="-15" urx="562" ury="620"/> + <char name="ugrave" width="600" llx="21" lly="-15" urx="562" ury="672"/> + <char name="underscore" width="600" llx="0" lly="-125" urx="600" ury="-75"/> + <char name="v" width="600" llx="10" lly="-10" urx="590" ury="426"/> + <char name="w" width="600" llx="-4" lly="-10" urx="604" ury="426"/> + <char name="x" width="600" llx="20" lly="0" urx="580" ury="426"/> + <char name="y" width="600" llx="7" lly="-157" urx="592" ury="426"/> + <char name="yacute" width="600" llx="7" lly="-157" urx="592" ury="672"/> + <char name="ydieresis" width="600" llx="7" lly="-157" urx="592" ury="620"/> + <char name="yen" width="600" llx="26" lly="0" urx="574" ury="562"/> + <char name="z" width="600" llx="99" lly="0" urx="502" ury="426"/> + <char name="zcaron" width="600" llx="99" lly="0" urx="502" ury="669"/> + <char name="zero" width="600" llx="106" lly="-15" urx="494" ury="622"/> + </char-metrics> +</font-metrics> diff --git a/src/codegen/fonts/CourierBold.xml b/src/codegen/fonts/CourierBold.xml index fa8bed196..c06ef5f23 100644 --- a/src/codegen/fonts/CourierBold.xml +++ b/src/codegen/fonts/CourierBold.xml @@ -22,275 +22,246 @@ <family-name>Courier</family-name> <class-name>CourierBold</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>562</cap-height> <x-height>439</x-height> <ascender>626</ascender> <descender>-142</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="600"/> - <char name="AE" width="600"/> - <char name="Aacute" width="600"/> - <char name="Acircumflex" width="600"/> - <char name="Adieresis" width="600"/> - <char name="Agrave" width="600"/> - <char name="Aring" width="600"/> - <char name="Atilde" width="600"/> - <char name="B" width="600"/> - <char name="C" width="600"/> - <char name="Ccedilla" width="600"/> - <char name="D" width="600"/> - <char name="E" width="600"/> - <char name="Eacute" width="600"/> - <char name="Ecircumflex" width="600"/> - <char name="Edieresis" width="600"/> - <char name="Egrave" width="600"/> - <char name="Eth" width="600"/> - <char name="Euro" width="600"/> - <char name="F" width="600"/> - <char name="G" width="600"/> - <char name="Gcaron" width="600"/> - <char name="H" width="600"/> - <char name="I" width="600"/> - <char name="IJ" width="600"/> - <char name="Iacute" width="600"/> - <char name="Icircumflex" width="600"/> - <char name="Idieresis" width="600"/> - <char name="Idot" width="600"/> - <char name="Igrave" width="600"/> - <char name="J" width="600"/> - <char name="K" width="600"/> - <char name="L" width="600"/> - <char name="LL" width="600"/> - <char name="Lslash" width="600"/> - <char name="M" width="600"/> - <char name="N" width="600"/> - <char name="Ntilde" width="600"/> - <char name="O" width="600"/> - <char name="OE" width="600"/> - <char name="Oacute" width="600"/> - <char name="Ocircumflex" width="600"/> - <char name="Odieresis" width="600"/> - <char name="Ograve" width="600"/> - <char name="Oslash" width="600"/> - <char name="Otilde" width="600"/> - <char name="P" width="600"/> - <char name="Q" width="600"/> - <char name="R" width="600"/> - <char name="S" width="600"/> - <char name="Scaron" width="600"/> - <char name="Scedilla" width="600"/> - <char name="T" width="600"/> - <char name="Thorn" width="600"/> - <char name="U" width="600"/> - <char name="Uacute" width="600"/> - <char name="Ucircumflex" width="600"/> - <char name="Udieresis" width="600"/> - <char name="Ugrave" width="600"/> - <char name="V" width="600"/> - <char name="W" width="600"/> - <char name="X" width="600"/> - <char name="Y" width="600"/> - <char name="Yacute" width="600"/> - <char name="Ydieresis" width="600"/> - <char name="Z" width="600"/> - <char name="Zcaron" width="600"/> - <char name="a" width="600"/> - <char name="aacute" width="600"/> - <char name="acircumflex" width="600"/> - <char name="acute" width="600"/> - <char name="adieresis" width="600"/> - <char name="ae" width="600"/> - <char name="agrave" width="600"/> - <char name="ampersand" width="600"/> - <char name="aring" width="600"/> - <char name="arrowboth" width="600"/> - <char name="arrowdown" width="600"/> - <char name="arrowleft" width="600"/> - <char name="arrowright" width="600"/> - <char name="arrowup" width="600"/> - <char name="asciicircum" width="600"/> - <char name="asciitilde" width="600"/> - <char name="asterisk" width="600"/> - <char name="at" width="600"/> - <char name="atilde" width="600"/> - <char name="b" width="600"/> - <char name="backslash" width="600"/> - <char name="bar" width="600"/> - <char name="braceleft" width="600"/> - <char name="braceright" width="600"/> - <char name="bracketleft" width="600"/> - <char name="bracketright" width="600"/> - <char name="breve" width="600"/> - <char name="brokenbar" width="600"/> - <char name="bullet" width="600"/> - <char name="c" width="600"/> - <char name="caron" width="600"/> - <char name="ccedilla" width="600"/> - <char name="cedilla" width="600"/> - <char name="cent" width="600"/> - <char name="center" width="600"/> - <char name="circumflex" width="600"/> - <char name="colon" width="600"/> - <char name="comma" width="600"/> - <char name="copyright" width="600"/> - <char name="currency" width="600"/> - <char name="d" width="600"/> - <char name="dagger" width="600"/> - <char name="daggerdbl" width="600"/> - <char name="dectab" width="600"/> - <char name="degree" width="600"/> - <char name="dieresis" width="600"/> - <char name="divide" width="600"/> - <char name="dollar" width="600"/> - <char name="dotaccent" width="600"/> - <char name="dotlessi" width="600"/> - <char name="down" width="600"/> - <char name="e" width="600"/> - <char name="eacute" width="600"/> - <char name="ecircumflex" width="600"/> - <char name="edieresis" width="600"/> - <char name="egrave" width="600"/> - <char name="eight" width="600"/> - <char name="ellipsis" width="600"/> - <char name="emdash" width="600"/> - <char name="endash" width="600"/> - <char name="equal" width="600"/> - <char name="eth" width="600"/> - <char name="exclam" width="600"/> - <char name="exclamdown" width="600"/> - <char name="f" width="600"/> - <char name="fi" width="600"/> - <char name="five" width="600"/> - <char name="fl" width="600"/> - <char name="florin" width="600"/> - <char name="format" width="600"/> - <char name="four" width="600"/> - <char name="fraction" width="600"/> - <char name="g" width="600"/> - <char name="gcaron" width="600"/> - <char name="germandbls" width="600"/> - <char name="grave" width="600"/> - <char name="graybox" width="600"/> - <char name="greater" width="600"/> - <char name="guillemotleft" width="600"/> - <char name="guillemotright" width="600"/> - <char name="guilsinglleft" width="600"/> - <char name="guilsinglright" width="600"/> - <char name="h" width="600"/> - <char name="hungarumlaut" width="600"/> - <char name="hyphen" width="600"/> - <char name="i" width="600"/> - <char name="iacute" width="600"/> - <char name="icircumflex" width="600"/> - <char name="idieresis" width="600"/> - <char name="igrave" width="600"/> - <char name="ij" width="600"/> - <char name="indent" width="600"/> - <char name="j" width="600"/> - <char name="k" width="600"/> - <char name="l" width="600"/> - <char name="largebullet" width="600"/> - <char name="left" width="600"/> - <char name="less" width="600"/> - <char name="lira" width="600"/> - <char name="ll" width="600"/> - <char name="logicalnot" width="600"/> - <char name="lslash" width="600"/> - <char name="m" width="600"/> - <char name="macron" width="600"/> - <char name="merge" width="600"/> - <char name="minus" width="600"/> - <char name="mu" width="600"/> - <char name="multiply" width="600"/> - <char name="n" width="600"/> - <char name="nine" width="600"/> - <char name="notegraphic" width="600"/> - <char name="ntilde" width="600"/> - <char name="numbersign" width="600"/> - <char name="o" width="600"/> - <char name="oacute" width="600"/> - <char name="ocircumflex" width="600"/> - <char name="odieresis" width="600"/> - <char name="oe" width="600"/> - <char name="ogonek" width="600"/> - <char name="ograve" width="600"/> - <char name="one" width="600"/> - <char name="onehalf" width="600"/> - <char name="onequarter" width="600"/> - <char name="onesuperior" width="600"/> - <char name="ordfeminine" width="600"/> - <char name="ordmasculine" width="600"/> - <char name="oslash" width="600"/> - <char name="otilde" width="600"/> - <char name="overscore" width="600"/> - <char name="p" width="600"/> - <char name="paragraph" width="600"/> - <char name="parenleft" width="600"/> - <char name="parenright" width="600"/> - <char name="percent" width="600"/> - <char name="period" width="600"/> - <char name="periodcentered" width="600"/> - <char name="perthousand" width="600"/> - <char name="plus" width="600"/> - <char name="plusminus" width="600"/> - <char name="prescription" width="600"/> - <char name="q" width="600"/> - <char name="question" width="600"/> - <char name="questiondown" width="600"/> - <char name="quotedbl" width="600"/> - <char name="quotedblbase" width="600"/> - <char name="quotedblleft" width="600"/> - <char name="quotedblright" width="600"/> - <char name="quoteleft" width="600"/> - <char name="quoteright" width="600"/> - <char name="quotesinglbase" width="600"/> - <char name="quotesingle" width="600"/> - <char name="r" width="600"/> - <char name="registered" width="600"/> - <char name="return" width="600"/> - <char name="ring" width="600"/> - <char name="s" width="600"/> - <char name="scaron" width="600"/> - <char name="scedilla" width="600"/> - <char name="section" width="600"/> - <char name="semicolon" width="600"/> - <char name="seven" width="600"/> - <char name="six" width="600"/> - <char name="slash" width="600"/> - <char name="space" width="600"/> + <char-metrics> + <char name="A" width="600" llx="-9" lly="0" urx="609" ury="562"/> + <char name="AE" width="600" llx="-29" lly="0" urx="602" ury="562"/> + <char name="Aacute" width="600" llx="-9" lly="0" urx="609" ury="784"/> + <char name="Acircumflex" width="600" llx="-9" lly="0" urx="609" ury="780"/> + <char name="Adieresis" width="600" llx="-9" lly="0" urx="609" ury="761"/> + <char name="Agrave" width="600" llx="-9" lly="0" urx="609" ury="784"/> + <char name="Aring" width="600" llx="-9" lly="0" urx="609" ury="801"/> + <char name="Atilde" width="600" llx="-9" lly="0" urx="609" ury="759"/> + <char name="B" width="600" llx="30" lly="0" urx="573" ury="562"/> + <char name="C" width="600" llx="22" lly="-18" urx="560" ury="580"/> + <char name="Ccedilla" width="600" llx="22" lly="-206" urx="560" ury="580"/> + <char name="D" width="600" llx="30" lly="0" urx="594" ury="562"/> + <char name="E" width="600" llx="25" lly="0" urx="560" ury="562"/> + <char name="Eacute" width="600" llx="25" lly="0" urx="560" ury="784"/> + <char name="Ecircumflex" width="600" llx="25" lly="0" urx="560" ury="780"/> + <char name="Edieresis" width="600" llx="25" lly="0" urx="560" ury="761"/> + <char name="Egrave" width="600" llx="25" lly="0" urx="560" ury="784"/> + <char name="Eth" width="600" llx="30" lly="0" urx="594" ury="562"/> + <char name="Euro" width="600" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="600" llx="39" lly="0" urx="570" ury="562"/> + <char name="G" width="600" llx="22" lly="-18" urx="594" ury="580"/> + <char name="H" width="600" llx="20" lly="0" urx="580" ury="562"/> + <char name="I" width="600" llx="77" lly="0" urx="523" ury="562"/> + <char name="Iacute" width="600" llx="77" lly="0" urx="523" ury="784"/> + <char name="Icircumflex" width="600" llx="77" lly="0" urx="523" ury="780"/> + <char name="Idieresis" width="600" llx="77" lly="0" urx="523" ury="761"/> + <char name="Igrave" width="600" llx="77" lly="0" urx="523" ury="784"/> + <char name="J" width="600" llx="37" lly="-18" urx="601" ury="562"/> + <char name="K" width="600" llx="21" lly="0" urx="599" ury="562"/> + <char name="L" width="600" llx="39" lly="0" urx="578" ury="562"/> + <char name="Lslash" width="600" llx="39" lly="0" urx="578" ury="562"/> + <char name="M" width="600" llx="-2" lly="0" urx="602" ury="562"/> + <char name="N" width="600" llx="8" lly="-12" urx="610" ury="562"/> + <char name="Ntilde" width="600" llx="8" lly="-12" urx="610" ury="759"/> + <char name="O" width="600" llx="22" lly="-18" urx="578" ury="580"/> + <char name="OE" width="600" llx="-25" lly="0" urx="595" ury="562"/> + <char name="Oacute" width="600" llx="22" lly="-18" urx="578" ury="784"/> + <char name="Ocircumflex" width="600" llx="22" lly="-18" urx="578" ury="780"/> + <char name="Odieresis" width="600" llx="22" lly="-18" urx="578" ury="761"/> + <char name="Ograve" width="600" llx="22" lly="-18" urx="578" ury="784"/> + <char name="Oslash" width="600" llx="22" lly="-22" urx="578" ury="584"/> + <char name="Otilde" width="600" llx="22" lly="-18" urx="578" ury="759"/> + <char name="P" width="600" llx="48" lly="0" urx="559" ury="562"/> + <char name="Q" width="600" llx="32" lly="-138" urx="578" ury="580"/> + <char name="R" width="600" llx="24" lly="0" urx="599" ury="562"/> + <char name="S" width="600" llx="47" lly="-22" urx="553" ury="582"/> + <char name="Scaron" width="600" llx="47" lly="-22" urx="553" ury="790"/> + <char name="Scedilla" width="600" llx="47" lly="-206" urx="553" ury="582"/> + <char name="T" width="600" llx="21" lly="0" urx="579" ury="562"/> + <char name="Thorn" width="600" llx="48" lly="0" urx="557" ury="562"/> + <char name="U" width="600" llx="4" lly="-18" urx="596" ury="562"/> + <char name="Uacute" width="600" llx="4" lly="-18" urx="596" ury="784"/> + <char name="Ucircumflex" width="600" llx="4" lly="-18" urx="596" ury="780"/> + <char name="Udieresis" width="600" llx="4" lly="-18" urx="596" ury="761"/> + <char name="Ugrave" width="600" llx="4" lly="-18" urx="596" ury="784"/> + <char name="V" width="600" llx="-13" lly="0" urx="613" ury="562"/> + <char name="W" width="600" llx="-18" lly="0" urx="618" ury="562"/> + <char name="X" width="600" llx="12" lly="0" urx="588" ury="562"/> + <char name="Y" width="600" llx="12" lly="0" urx="589" ury="562"/> + <char name="Yacute" width="600" llx="12" lly="0" urx="589" ury="784"/> + <char name="Ydieresis" width="600" llx="12" lly="0" urx="589" ury="761"/> + <char name="Z" width="600" llx="62" lly="0" urx="539" ury="562"/> + <char name="Zcaron" width="600" llx="62" lly="0" urx="539" ury="790"/> + <char name="a" width="600" llx="35" lly="-15" urx="570" ury="454"/> + <char name="aacute" width="600" llx="35" lly="-15" urx="570" ury="661"/> + <char name="acircumflex" width="600" llx="35" lly="-15" urx="570" ury="657"/> + <char name="acute" width="600" llx="205" lly="508" urx="468" ury="661"/> + <char name="adieresis" width="600" llx="35" lly="-15" urx="570" ury="638"/> + <char name="ae" width="600" llx="-4" lly="-15" urx="601" ury="454"/> + <char name="agrave" width="600" llx="35" lly="-15" urx="570" ury="661"/> + <char name="ampersand" width="600" llx="36" lly="-15" urx="546" ury="543"/> + <char name="aring" width="600" llx="35" lly="-15" urx="570" ury="678"/> + <char name="asciicircum" width="600" llx="108" lly="250" urx="492" ury="616"/> + <char name="asciitilde" width="600" llx="71" lly="153" urx="530" ury="356"/> + <char name="asterisk" width="600" llx="91" lly="219" urx="509" ury="601"/> + <char name="at" width="600" llx="16" lly="-15" urx="584" ury="616"/> + <char name="atilde" width="600" llx="35" lly="-15" urx="570" ury="636"/> + <char name="b" width="600" llx="0" lly="-15" urx="584" ury="626"/> + <char name="backslash" width="600" llx="99" lly="-77" urx="503" ury="626"/> + <char name="bar" width="600" llx="255" lly="-250" urx="345" ury="750"/> + <char name="braceleft" width="600" llx="160" lly="-102" urx="464" ury="616"/> + <char name="braceright" width="600" llx="136" lly="-102" urx="440" ury="616"/> + <char name="bracketleft" width="600" llx="245" lly="-102" urx="475" ury="616"/> + <char name="bracketright" width="600" llx="125" lly="-102" urx="355" ury="616"/> + <char name="breve" width="600" llx="83" lly="468" urx="517" ury="631"/> + <char name="brokenbar" width="600" llx="255" lly="-175" urx="345" ury="675"/> + <char name="bullet" width="600" llx="140" lly="132" urx="460" ury="430"/> + <char name="c" width="600" llx="40" lly="-15" urx="545" ury="459"/> + <char name="caron" width="600" llx="103" lly="493" urx="497" ury="667"/> + <char name="ccedilla" width="600" llx="40" lly="-206" urx="545" ury="459"/> + <char name="cedilla" width="600" llx="205" lly="-206" urx="387" ury="0"/> + <char name="cent" width="600" llx="66" lly="-49" urx="518" ury="614"/> + <char name="circumflex" width="600" llx="103" lly="483" urx="497" ury="657"/> + <char name="colon" width="600" llx="191" lly="-15" urx="407" ury="425"/> + <char name="comma" width="600" llx="123" lly="-111" urx="393" ury="174"/> + <char name="copyright" width="600" llx="0" lly="-18" urx="600" ury="580"/> + <char name="currency" width="600" llx="54" lly="49" urx="546" ury="517"/> + <char name="d" width="600" llx="20" lly="-15" urx="591" ury="626"/> + <char name="dagger" width="600" llx="106" lly="-70" urx="494" ury="580"/> + <char name="daggerdbl" width="600" llx="106" lly="-70" urx="494" ury="580"/> + <char name="degree" width="600" llx="86" lly="243" urx="474" ury="616"/> + <char name="dieresis" width="600" llx="128" lly="498" urx="472" ury="638"/> + <char name="divide" width="600" llx="71" lly="16" urx="529" ury="500"/> + <char name="dollar" width="600" llx="82" lly="-126" urx="519" ury="666"/> + <char name="dotaccent" width="600" llx="230" lly="498" urx="370" ury="638"/> + <char name="dotlessi" width="600" llx="77" lly="0" urx="523" ury="439"/> + <char name="e" width="600" llx="40" lly="-15" urx="563" ury="454"/> + <char name="eacute" width="600" llx="40" lly="-15" urx="563" ury="661"/> + <char name="ecircumflex" width="600" llx="40" lly="-15" urx="563" ury="657"/> + <char name="edieresis" width="600" llx="40" lly="-15" urx="563" ury="638"/> + <char name="egrave" width="600" llx="40" lly="-15" urx="563" ury="661"/> + <char name="eight" width="600" llx="83" lly="-15" urx="517" ury="616"/> + <char name="ellipsis" width="600" llx="26" lly="-15" urx="574" ury="116"/> + <char name="emdash" width="600" llx="-10" lly="203" urx="610" ury="313"/> + <char name="endash" width="600" llx="65" lly="203" urx="535" ury="313"/> + <char name="equal" width="600" llx="71" lly="118" urx="529" ury="398"/> + <char name="eth" width="600" llx="58" lly="-27" urx="543" ury="626"/> + <char name="exclam" width="600" llx="202" lly="-15" urx="398" ury="572"/> + <char name="exclamdown" width="600" llx="202" lly="-146" urx="398" ury="449"/> + <char name="f" width="600" llx="83" lly="0" urx="547" ury="626"/> + <char name="fi" width="600" llx="12" lly="0" urx="593" ury="626"/> + <char name="five" width="600" llx="70" lly="-15" urx="521" ury="601"/> + <char name="fl" width="600" llx="12" lly="0" urx="593" ury="626"/> + <char name="florin" width="600" llx="-30" lly="-131" urx="572" ury="616"/> + <char name="four" width="600" llx="53" lly="0" urx="507" ury="616"/> + <char name="fraction" width="600" llx="25" lly="-60" urx="576" ury="661"/> + <char name="g" width="600" llx="30" lly="-146" urx="580" ury="454"/> + <char name="germandbls" width="600" llx="22" lly="-15" urx="596" ury="626"/> + <char name="grave" width="600" llx="132" lly="508" urx="395" ury="661"/> + <char name="greater" width="600" llx="77" lly="15" urx="534" ury="501"/> + <char name="guillemotleft" width="600" llx="8" lly="70" urx="553" ury="446"/> + <char name="guillemotright" width="600" llx="47" lly="70" urx="592" ury="446"/> + <char name="guilsinglleft" width="600" llx="141" lly="70" urx="459" ury="446"/> + <char name="guilsinglright" width="600" llx="141" lly="70" urx="459" ury="446"/> + <char name="h" width="600" llx="5" lly="0" urx="592" ury="626"/> + <char name="hungarumlaut" width="600" llx="68" lly="488" urx="588" ury="661"/> + <char name="hyphen" width="600" llx="100" lly="203" urx="500" ury="313"/> + <char name="i" width="600" llx="77" lly="0" urx="523" ury="658"/> + <char name="iacute" width="600" llx="77" lly="0" urx="523" ury="661"/> + <char name="icircumflex" width="600" llx="73" lly="0" urx="523" ury="657"/> + <char name="idieresis" width="600" llx="77" lly="0" urx="523" ury="618"/> + <char name="igrave" width="600" llx="77" lly="0" urx="523" ury="661"/> + <char name="j" width="600" llx="63" lly="-146" urx="440" ury="658"/> + <char name="k" width="600" llx="20" lly="0" urx="585" ury="626"/> + <char name="l" width="600" llx="77" lly="0" urx="523" ury="626"/> + <char name="less" width="600" llx="66" lly="15" urx="523" ury="501"/> + <char name="logicalnot" width="600" llx="71" lly="103" urx="529" ury="413"/> + <char name="lslash" width="600" llx="77" lly="0" urx="523" ury="626"/> + <char name="m" width="600" llx="-22" lly="0" urx="626" ury="454"/> + <char name="macron" width="600" llx="88" lly="505" urx="512" ury="585"/> + <char name="minus" width="600" llx="71" lly="203" urx="529" ury="313"/> + <char name="mu" width="600" llx="-1" lly="-142" urx="569" ury="439"/> + <char name="multiply" width="600" llx="81" lly="39" urx="520" ury="478"/> + <char name="n" width="600" llx="18" lly="0" urx="592" ury="454"/> + <char name="nine" width="600" llx="79" lly="-15" urx="510" ury="616"/> + <char name="ntilde" width="600" llx="18" lly="0" urx="592" ury="636"/> + <char name="numbersign" width="600" llx="56" lly="-45" urx="544" ury="651"/> + <char name="o" width="600" llx="30" lly="-15" urx="570" ury="454"/> + <char name="oacute" width="600" llx="30" lly="-15" urx="570" ury="661"/> + <char name="ocircumflex" width="600" llx="30" lly="-15" urx="570" ury="657"/> + <char name="odieresis" width="600" llx="30" lly="-15" urx="570" ury="638"/> + <char name="oe" width="600" llx="-18" lly="-15" urx="611" ury="454"/> + <char name="ogonek" width="600" llx="169" lly="-199" urx="400" ury="0"/> + <char name="ograve" width="600" llx="30" lly="-15" urx="570" ury="661"/> + <char name="one" width="600" llx="81" lly="0" urx="539" ury="616"/> + <char name="onehalf" width="600" llx="-47" lly="-60" urx="648" ury="661"/> + <char name="onequarter" width="600" llx="-56" lly="-60" urx="656" ury="661"/> + <char name="onesuperior" width="600" llx="153" lly="230" urx="447" ury="616"/> + <char name="ordfeminine" width="600" llx="147" lly="196" urx="453" ury="580"/> + <char name="ordmasculine" width="600" llx="147" lly="196" urx="453" ury="580"/> + <char name="oslash" width="600" llx="30" lly="-24" urx="570" ury="463"/> + <char name="otilde" width="600" llx="30" lly="-15" urx="570" ury="636"/> + <char name="p" width="600" llx="-1" lly="-142" urx="570" ury="454"/> + <char name="paragraph" width="600" llx="6" lly="-70" urx="576" ury="580"/> + <char name="parenleft" width="600" llx="219" lly="-102" urx="461" ury="616"/> + <char name="parenright" width="600" llx="139" lly="-102" urx="381" ury="616"/> + <char name="percent" width="600" llx="5" lly="-15" urx="595" ury="616"/> + <char name="period" width="600" llx="192" lly="-15" urx="408" ury="171"/> + <char name="periodcentered" width="600" llx="196" lly="165" urx="404" ury="351"/> + <char name="perthousand" width="600" llx="-113" lly="-15" urx="713" ury="616"/> + <char name="plus" width="600" llx="71" lly="39" urx="529" ury="478"/> + <char name="plusminus" width="600" llx="71" lly="24" urx="529" ury="515"/> + <char name="q" width="600" llx="20" lly="-142" urx="591" ury="454"/> + <char name="question" width="600" llx="98" lly="-14" urx="501" ury="580"/> + <char name="questiondown" width="600" llx="99" lly="-146" urx="502" ury="449"/> + <char name="quotedbl" width="600" llx="135" lly="277" urx="465" ury="562"/> + <char name="quotedblbase" width="600" llx="65" lly="-142" urx="529" ury="143"/> + <char name="quotedblleft" width="600" llx="71" lly="277" urx="535" ury="562"/> + <char name="quotedblright" width="600" llx="61" lly="277" urx="525" ury="562"/> + <char name="quoteleft" width="600" llx="178" lly="277" urx="428" ury="562"/> + <char name="quoteright" width="600" llx="171" lly="277" urx="423" ury="562"/> + <char name="quotesinglbase" width="600" llx="175" lly="-142" urx="427" ury="143"/> + <char name="quotesingle" width="600" llx="227" lly="277" urx="373" ury="562"/> + <char name="r" width="600" llx="47" lly="0" urx="580" ury="454"/> + <char name="registered" width="600" llx="0" lly="-18" urx="600" ury="580"/> + <char name="ring" width="600" llx="198" lly="481" urx="402" ury="678"/> + <char name="s" width="600" llx="68" lly="-17" urx="535" ury="459"/> + <char name="scaron" width="600" llx="68" lly="-17" urx="535" ury="667"/> + <char name="scedilla" width="600" llx="68" lly="-206" urx="535" ury="459"/> + <char name="section" width="600" llx="83" lly="-70" urx="517" ury="580"/> + <char name="semicolon" width="600" llx="123" lly="-111" urx="408" ury="425"/> + <char name="seven" width="600" llx="55" lly="0" urx="494" ury="601"/> + <char name="six" width="600" llx="90" lly="-15" urx="521" ury="616"/> + <char name="slash" width="600" llx="98" lly="-77" urx="502" ury="626"/> + <char name="space" width="600" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="600"/> - <char name="square" width="600"/> - <char name="sterling" width="600"/> - <char name="stop" width="600"/> - <char name="t" width="600"/> - <char name="tab" width="600"/> - <char name="thorn" width="600"/> - <char name="three" width="600"/> - <char name="threequarters" width="600"/> - <char name="threesuperior" width="600"/> - <char name="tilde" width="600"/> - <char name="trademark" width="600"/> - <char name="two" width="600"/> - <char name="twosuperior" width="600"/> - <char name="u" width="600"/> - <char name="uacute" width="600"/> - <char name="ucircumflex" width="600"/> - <char name="udieresis" width="600"/> - <char name="ugrave" width="600"/> - <char name="underscore" width="600"/> - <char name="up" width="600"/> - <char name="v" width="600"/> - <char name="w" width="600"/> - <char name="x" width="600"/> - <char name="y" width="600"/> - <char name="yacute" width="600"/> - <char name="ydieresis" width="600"/> - <char name="yen" width="600"/> - <char name="z" width="600"/> - <char name="zcaron" width="600"/> - <char name="zero" width="600"/> - </widths> -</font-metrics>
\ No newline at end of file + <char name="sterling" width="600" llx="72" lly="-28" urx="558" ury="611"/> + <char name="t" width="600" llx="47" lly="-15" urx="532" ury="562"/> + <char name="thorn" width="600" llx="-14" lly="-142" urx="570" ury="626"/> + <char name="three" width="600" llx="63" lly="-15" urx="501" ury="616"/> + <char name="threequarters" width="600" llx="-47" lly="-60" urx="648" ury="661"/> + <char name="threesuperior" width="600" llx="138" lly="222" urx="433" ury="616"/> + <char name="tilde" width="600" llx="89" lly="493" urx="512" ury="636"/> + <char name="trademark" width="600" llx="-9" lly="230" urx="749" ury="562"/> + <char name="two" width="600" llx="61" lly="0" urx="499" ury="616"/> + <char name="twosuperior" width="600" llx="143" lly="230" urx="436" ury="616"/> + <char name="u" width="600" llx="-1" lly="-15" urx="569" ury="439"/> + <char name="uacute" width="600" llx="-1" lly="-15" urx="569" ury="661"/> + <char name="ucircumflex" width="600" llx="-1" lly="-15" urx="569" ury="657"/> + <char name="udieresis" width="600" llx="-1" lly="-15" urx="569" ury="638"/> + <char name="ugrave" width="600" llx="-1" lly="-15" urx="569" ury="661"/> + <char name="underscore" width="600" llx="0" lly="-125" urx="600" ury="-75"/> + <char name="v" width="600" llx="-1" lly="0" urx="601" ury="439"/> + <char name="w" width="600" llx="-18" lly="0" urx="618" ury="439"/> + <char name="x" width="600" llx="6" lly="0" urx="594" ury="439"/> + <char name="y" width="600" llx="-4" lly="-142" urx="601" ury="439"/> + <char name="yacute" width="600" llx="-4" lly="-142" urx="601" ury="661"/> + <char name="ydieresis" width="600" llx="-4" lly="-142" urx="601" ury="638"/> + <char name="yen" width="600" llx="10" lly="0" urx="590" ury="562"/> + <char name="z" width="600" llx="81" lly="0" urx="520" ury="439"/> + <char name="zcaron" width="600" llx="81" lly="0" urx="520" ury="667"/> + <char name="zero" width="600" llx="87" lly="-15" urx="513" ury="616"/> + </char-metrics> +</font-metrics> diff --git a/src/codegen/fonts/CourierBoldOblique.xml b/src/codegen/fonts/CourierBoldOblique.xml index 5bd26092e..a82a75ad2 100644 --- a/src/codegen/fonts/CourierBoldOblique.xml +++ b/src/codegen/fonts/CourierBoldOblique.xml @@ -22,275 +22,246 @@ <family-name>Courier</family-name> <class-name>CourierBoldOblique</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>562</cap-height> <x-height>439</x-height> <ascender>626</ascender> <descender>-142</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="600"/> - <char name="AE" width="600"/> - <char name="Aacute" width="600"/> - <char name="Acircumflex" width="600"/> - <char name="Adieresis" width="600"/> - <char name="Agrave" width="600"/> - <char name="Aring" width="600"/> - <char name="Atilde" width="600"/> - <char name="B" width="600"/> - <char name="C" width="600"/> - <char name="Ccedilla" width="600"/> - <char name="D" width="600"/> - <char name="E" width="600"/> - <char name="Eacute" width="600"/> - <char name="Ecircumflex" width="600"/> - <char name="Edieresis" width="600"/> - <char name="Egrave" width="600"/> - <char name="Eth" width="600"/> - <char name="Euro" width="600"/> - <char name="F" width="600"/> - <char name="G" width="600"/> - <char name="Gcaron" width="600"/> - <char name="H" width="600"/> - <char name="I" width="600"/> - <char name="IJ" width="600"/> - <char name="Iacute" width="600"/> - <char name="Icircumflex" width="600"/> - <char name="Idieresis" width="600"/> - <char name="Idot" width="600"/> - <char name="Igrave" width="600"/> - <char name="J" width="600"/> - <char name="K" width="600"/> - <char name="L" width="600"/> - <char name="LL" width="600"/> - <char name="Lslash" width="600"/> - <char name="M" width="600"/> - <char name="N" width="600"/> - <char name="Ntilde" width="600"/> - <char name="O" width="600"/> - <char name="OE" width="600"/> - <char name="Oacute" width="600"/> - <char name="Ocircumflex" width="600"/> - <char name="Odieresis" width="600"/> - <char name="Ograve" width="600"/> - <char name="Oslash" width="600"/> - <char name="Otilde" width="600"/> - <char name="P" width="600"/> - <char name="Q" width="600"/> - <char name="R" width="600"/> - <char name="S" width="600"/> - <char name="Scaron" width="600"/> - <char name="Scedilla" width="600"/> - <char name="T" width="600"/> - <char name="Thorn" width="600"/> - <char name="U" width="600"/> - <char name="Uacute" width="600"/> - <char name="Ucircumflex" width="600"/> - <char name="Udieresis" width="600"/> - <char name="Ugrave" width="600"/> - <char name="V" width="600"/> - <char name="W" width="600"/> - <char name="X" width="600"/> - <char name="Y" width="600"/> - <char name="Yacute" width="600"/> - <char name="Ydieresis" width="600"/> - <char name="Z" width="600"/> - <char name="Zcaron" width="600"/> - <char name="a" width="600"/> - <char name="aacute" width="600"/> - <char name="acircumflex" width="600"/> - <char name="acute" width="600"/> - <char name="adieresis" width="600"/> - <char name="ae" width="600"/> - <char name="agrave" width="600"/> - <char name="ampersand" width="600"/> - <char name="aring" width="600"/> - <char name="arrowboth" width="600"/> - <char name="arrowdown" width="600"/> - <char name="arrowleft" width="600"/> - <char name="arrowright" width="600"/> - <char name="arrowup" width="600"/> - <char name="asciicircum" width="600"/> - <char name="asciitilde" width="600"/> - <char name="asterisk" width="600"/> - <char name="at" width="600"/> - <char name="atilde" width="600"/> - <char name="b" width="600"/> - <char name="backslash" width="600"/> - <char name="bar" width="600"/> - <char name="braceleft" width="600"/> - <char name="braceright" width="600"/> - <char name="bracketleft" width="600"/> - <char name="bracketright" width="600"/> - <char name="breve" width="600"/> - <char name="brokenbar" width="600"/> - <char name="bullet" width="600"/> - <char name="c" width="600"/> - <char name="caron" width="600"/> - <char name="ccedilla" width="600"/> - <char name="cedilla" width="600"/> - <char name="cent" width="600"/> - <char name="center" width="600"/> - <char name="circumflex" width="600"/> - <char name="colon" width="600"/> - <char name="comma" width="600"/> - <char name="copyright" width="600"/> - <char name="currency" width="600"/> - <char name="d" width="600"/> - <char name="dagger" width="600"/> - <char name="daggerdbl" width="600"/> - <char name="dectab" width="600"/> - <char name="degree" width="600"/> - <char name="dieresis" width="600"/> - <char name="divide" width="600"/> - <char name="dollar" width="600"/> - <char name="dotaccent" width="600"/> - <char name="dotlessi" width="600"/> - <char name="down" width="600"/> - <char name="e" width="600"/> - <char name="eacute" width="600"/> - <char name="ecircumflex" width="600"/> - <char name="edieresis" width="600"/> - <char name="egrave" width="600"/> - <char name="eight" width="600"/> - <char name="ellipsis" width="600"/> - <char name="emdash" width="600"/> - <char name="endash" width="600"/> - <char name="equal" width="600"/> - <char name="eth" width="600"/> - <char name="exclam" width="600"/> - <char name="exclamdown" width="600"/> - <char name="f" width="600"/> - <char name="fi" width="600"/> - <char name="five" width="600"/> - <char name="fl" width="600"/> - <char name="florin" width="600"/> - <char name="format" width="600"/> - <char name="four" width="600"/> - <char name="fraction" width="600"/> - <char name="g" width="600"/> - <char name="gcaron" width="600"/> - <char name="germandbls" width="600"/> - <char name="grave" width="600"/> - <char name="graybox" width="600"/> - <char name="greater" width="600"/> - <char name="guillemotleft" width="600"/> - <char name="guillemotright" width="600"/> - <char name="guilsinglleft" width="600"/> - <char name="guilsinglright" width="600"/> - <char name="h" width="600"/> - <char name="hungarumlaut" width="600"/> - <char name="hyphen" width="600"/> - <char name="i" width="600"/> - <char name="iacute" width="600"/> - <char name="icircumflex" width="600"/> - <char name="idieresis" width="600"/> - <char name="igrave" width="600"/> - <char name="ij" width="600"/> - <char name="indent" width="600"/> - <char name="j" width="600"/> - <char name="k" width="600"/> - <char name="l" width="600"/> - <char name="largebullet" width="600"/> - <char name="left" width="600"/> - <char name="less" width="600"/> - <char name="lira" width="600"/> - <char name="ll" width="600"/> - <char name="logicalnot" width="600"/> - <char name="lslash" width="600"/> - <char name="m" width="600"/> - <char name="macron" width="600"/> - <char name="merge" width="600"/> - <char name="minus" width="600"/> - <char name="mu" width="600"/> - <char name="multiply" width="600"/> - <char name="n" width="600"/> - <char name="nine" width="600"/> - <char name="notegraphic" width="600"/> - <char name="ntilde" width="600"/> - <char name="numbersign" width="600"/> - <char name="o" width="600"/> - <char name="oacute" width="600"/> - <char name="ocircumflex" width="600"/> - <char name="odieresis" width="600"/> - <char name="oe" width="600"/> - <char name="ogonek" width="600"/> - <char name="ograve" width="600"/> - <char name="one" width="600"/> - <char name="onehalf" width="600"/> - <char name="onequarter" width="600"/> - <char name="onesuperior" width="600"/> - <char name="ordfeminine" width="600"/> - <char name="ordmasculine" width="600"/> - <char name="oslash" width="600"/> - <char name="otilde" width="600"/> - <char name="overscore" width="600"/> - <char name="p" width="600"/> - <char name="paragraph" width="600"/> - <char name="parenleft" width="600"/> - <char name="parenright" width="600"/> - <char name="percent" width="600"/> - <char name="period" width="600"/> - <char name="periodcentered" width="600"/> - <char name="perthousand" width="600"/> - <char name="plus" width="600"/> - <char name="plusminus" width="600"/> - <char name="prescription" width="600"/> - <char name="q" width="600"/> - <char name="question" width="600"/> - <char name="questiondown" width="600"/> - <char name="quotedbl" width="600"/> - <char name="quotedblbase" width="600"/> - <char name="quotedblleft" width="600"/> - <char name="quotedblright" width="600"/> - <char name="quoteleft" width="600"/> - <char name="quoteright" width="600"/> - <char name="quotesinglbase" width="600"/> - <char name="quotesingle" width="600"/> - <char name="r" width="600"/> - <char name="registered" width="600"/> - <char name="return" width="600"/> - <char name="ring" width="600"/> - <char name="s" width="600"/> - <char name="scaron" width="600"/> - <char name="scedilla" width="600"/> - <char name="section" width="600"/> - <char name="semicolon" width="600"/> - <char name="seven" width="600"/> - <char name="six" width="600"/> - <char name="slash" width="600"/> - <char name="space" width="600"/> + <char-metrics> + <char name="A" width="600" llx="-9" lly="0" urx="632" ury="562"/> + <char name="AE" width="600" llx="-29" lly="0" urx="708" ury="562"/> + <char name="Aacute" width="600" llx="-9" lly="0" urx="655" ury="784"/> + <char name="Acircumflex" width="600" llx="-9" lly="0" urx="632" ury="780"/> + <char name="Adieresis" width="600" llx="-9" lly="0" urx="632" ury="761"/> + <char name="Agrave" width="600" llx="-9" lly="0" urx="632" ury="784"/> + <char name="Aring" width="600" llx="-9" lly="0" urx="632" ury="801"/> + <char name="Atilde" width="600" llx="-9" lly="0" urx="669" ury="759"/> + <char name="B" width="600" llx="30" lly="0" urx="630" ury="562"/> + <char name="C" width="600" llx="74" lly="-18" urx="675" ury="580"/> + <char name="Ccedilla" width="600" llx="74" lly="-206" urx="675" ury="580"/> + <char name="D" width="600" llx="30" lly="0" urx="664" ury="562"/> + <char name="E" width="600" llx="25" lly="0" urx="670" ury="562"/> + <char name="Eacute" width="600" llx="25" lly="0" urx="670" ury="784"/> + <char name="Ecircumflex" width="600" llx="25" lly="0" urx="670" ury="780"/> + <char name="Edieresis" width="600" llx="25" lly="0" urx="670" ury="761"/> + <char name="Egrave" width="600" llx="25" lly="0" urx="670" ury="784"/> + <char name="Eth" width="600" llx="30" lly="0" urx="664" ury="562"/> + <char name="Euro" width="600" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="600" llx="39" lly="0" urx="684" ury="562"/> + <char name="G" width="600" llx="74" lly="-18" urx="675" ury="580"/> + <char name="H" width="600" llx="20" lly="0" urx="700" ury="562"/> + <char name="I" width="600" llx="77" lly="0" urx="643" ury="562"/> + <char name="Iacute" width="600" llx="77" lly="0" urx="643" ury="784"/> + <char name="Icircumflex" width="600" llx="77" lly="0" urx="643" ury="780"/> + <char name="Idieresis" width="600" llx="77" lly="0" urx="643" ury="761"/> + <char name="Igrave" width="600" llx="77" lly="0" urx="643" ury="784"/> + <char name="J" width="600" llx="58" lly="-18" urx="721" ury="562"/> + <char name="K" width="600" llx="21" lly="0" urx="692" ury="562"/> + <char name="L" width="600" llx="39" lly="0" urx="636" ury="562"/> + <char name="Lslash" width="600" llx="39" lly="0" urx="636" ury="562"/> + <char name="M" width="600" llx="-2" lly="0" urx="722" ury="562"/> + <char name="N" width="600" llx="8" lly="-12" urx="730" ury="562"/> + <char name="Ntilde" width="600" llx="8" lly="-12" urx="730" ury="759"/> + <char name="O" width="600" llx="74" lly="-18" urx="645" ury="580"/> + <char name="OE" width="600" llx="26" lly="0" urx="701" ury="562"/> + <char name="Oacute" width="600" llx="74" lly="-18" urx="645" ury="784"/> + <char name="Ocircumflex" width="600" llx="74" lly="-18" urx="645" ury="780"/> + <char name="Odieresis" width="600" llx="74" lly="-18" urx="645" ury="761"/> + <char name="Ograve" width="600" llx="74" lly="-18" urx="645" ury="784"/> + <char name="Oslash" width="600" llx="48" lly="-22" urx="673" ury="584"/> + <char name="Otilde" width="600" llx="74" lly="-18" urx="669" ury="759"/> + <char name="P" width="600" llx="48" lly="0" urx="643" ury="562"/> + <char name="Q" width="600" llx="83" lly="-138" urx="636" ury="580"/> + <char name="R" width="600" llx="24" lly="0" urx="617" ury="562"/> + <char name="S" width="600" llx="54" lly="-22" urx="673" ury="582"/> + <char name="Scaron" width="600" llx="54" lly="-22" urx="689" ury="790"/> + <char name="Scedilla" width="600" llx="54" lly="-206" urx="673" ury="582"/> + <char name="T" width="600" llx="86" lly="0" urx="679" ury="562"/> + <char name="Thorn" width="600" llx="48" lly="0" urx="620" ury="562"/> + <char name="U" width="600" llx="101" lly="-18" urx="716" ury="562"/> + <char name="Uacute" width="600" llx="101" lly="-18" urx="716" ury="784"/> + <char name="Ucircumflex" width="600" llx="101" lly="-18" urx="716" ury="780"/> + <char name="Udieresis" width="600" llx="101" lly="-18" urx="716" ury="761"/> + <char name="Ugrave" width="600" llx="101" lly="-18" urx="716" ury="784"/> + <char name="V" width="600" llx="84" lly="0" urx="733" ury="562"/> + <char name="W" width="600" llx="79" lly="0" urx="738" ury="562"/> + <char name="X" width="600" llx="12" lly="0" urx="690" ury="562"/> + <char name="Y" width="600" llx="109" lly="0" urx="709" ury="562"/> + <char name="Yacute" width="600" llx="109" lly="0" urx="709" ury="784"/> + <char name="Ydieresis" width="600" llx="109" lly="0" urx="709" ury="761"/> + <char name="Z" width="600" llx="62" lly="0" urx="637" ury="562"/> + <char name="Zcaron" width="600" llx="62" lly="0" urx="659" ury="790"/> + <char name="a" width="600" llx="61" lly="-15" urx="593" ury="454"/> + <char name="aacute" width="600" llx="61" lly="-15" urx="609" ury="661"/> + <char name="acircumflex" width="600" llx="61" lly="-15" urx="607" ury="657"/> + <char name="acute" width="600" llx="312" lly="508" urx="609" ury="661"/> + <char name="adieresis" width="600" llx="61" lly="-15" urx="595" ury="638"/> + <char name="ae" width="600" llx="21" lly="-15" urx="652" ury="454"/> + <char name="agrave" width="600" llx="61" lly="-15" urx="593" ury="661"/> + <char name="ampersand" width="600" llx="61" lly="-15" urx="595" ury="543"/> + <char name="aring" width="600" llx="61" lly="-15" urx="593" ury="678"/> + <char name="asciicircum" width="600" llx="171" lly="250" urx="556" ury="616"/> + <char name="asciitilde" width="600" llx="120" lly="153" urx="590" ury="356"/> + <char name="asterisk" width="600" llx="179" lly="219" urx="598" ury="601"/> + <char name="at" width="600" llx="65" lly="-15" urx="642" ury="616"/> + <char name="atilde" width="600" llx="61" lly="-15" urx="643" ury="636"/> + <char name="b" width="600" llx="13" lly="-15" urx="636" ury="626"/> + <char name="backslash" width="600" llx="222" lly="-77" urx="496" ury="626"/> + <char name="bar" width="600" llx="201" lly="-250" urx="505" ury="750"/> + <char name="braceleft" width="600" llx="203" lly="-102" urx="595" ury="616"/> + <char name="braceright" width="600" llx="114" lly="-102" urx="506" ury="616"/> + <char name="bracketleft" width="600" llx="223" lly="-102" urx="606" ury="616"/> + <char name="bracketright" width="600" llx="103" lly="-102" urx="486" ury="616"/> + <char name="breve" width="600" llx="217" lly="468" urx="652" ury="631"/> + <char name="brokenbar" width="600" llx="217" lly="-175" urx="489" ury="675"/> + <char name="bullet" width="600" llx="196" lly="132" urx="523" ury="430"/> + <char name="c" width="600" llx="81" lly="-15" urx="631" ury="459"/> + <char name="caron" width="600" llx="238" lly="493" urx="633" ury="667"/> + <char name="ccedilla" width="600" llx="81" lly="-206" urx="631" ury="459"/> + <char name="cedilla" width="600" llx="168" lly="-206" urx="368" ury="0"/> + <char name="cent" width="600" llx="121" lly="-49" urx="605" ury="614"/> + <char name="circumflex" width="600" llx="212" lly="483" urx="607" ury="657"/> + <char name="colon" width="600" llx="205" lly="-15" urx="480" ury="425"/> + <char name="comma" width="600" llx="99" lly="-111" urx="430" ury="174"/> + <char name="copyright" width="600" llx="53" lly="-18" urx="667" ury="580"/> + <char name="currency" width="600" llx="77" lly="49" urx="644" ury="517"/> + <char name="d" width="600" llx="60" lly="-15" urx="645" ury="626"/> + <char name="dagger" width="600" llx="175" lly="-70" urx="586" ury="580"/> + <char name="daggerdbl" width="600" llx="121" lly="-70" urx="587" ury="580"/> + <char name="degree" width="600" llx="173" lly="243" urx="570" ury="616"/> + <char name="dieresis" width="600" llx="246" lly="498" urx="595" ury="638"/> + <char name="divide" width="600" llx="114" lly="16" urx="596" ury="500"/> + <char name="dollar" width="600" llx="87" lly="-126" urx="630" ury="666"/> + <char name="dotaccent" width="600" llx="348" lly="498" urx="493" ury="638"/> + <char name="dotlessi" width="600" llx="77" lly="0" urx="546" ury="439"/> + <char name="e" width="600" llx="81" lly="-15" urx="605" ury="454"/> + <char name="eacute" width="600" llx="81" lly="-15" urx="609" ury="661"/> + <char name="ecircumflex" width="600" llx="81" lly="-15" urx="607" ury="657"/> + <char name="edieresis" width="600" llx="81" lly="-15" urx="605" ury="638"/> + <char name="egrave" width="600" llx="81" lly="-15" urx="605" ury="661"/> + <char name="eight" width="600" llx="115" lly="-15" urx="604" ury="616"/> + <char name="ellipsis" width="600" llx="35" lly="-15" urx="587" ury="116"/> + <char name="emdash" width="600" llx="33" lly="203" urx="677" ury="313"/> + <char name="endash" width="600" llx="108" lly="203" urx="602" ury="313"/> + <char name="equal" width="600" llx="96" lly="118" urx="614" ury="398"/> + <char name="eth" width="600" llx="93" lly="-27" urx="661" ury="626"/> + <char name="exclam" width="600" llx="215" lly="-15" urx="495" ury="572"/> + <char name="exclamdown" width="600" llx="196" lly="-146" urx="477" ury="449"/> + <char name="f" width="600" llx="83" lly="0" urx="677" ury="626"/> + <char name="fi" width="600" llx="12" lly="0" urx="644" ury="626"/> + <char name="five" width="600" llx="77" lly="-15" urx="621" ury="601"/> + <char name="fl" width="600" llx="12" lly="0" urx="644" ury="626"/> + <char name="florin" width="600" llx="-57" lly="-131" urx="702" ury="616"/> + <char name="four" width="600" llx="81" lly="0" urx="559" ury="616"/> + <char name="fraction" width="600" llx="22" lly="-60" urx="708" ury="661"/> + <char name="g" width="600" llx="40" lly="-146" urx="674" ury="454"/> + <char name="germandbls" width="600" llx="22" lly="-15" urx="629" ury="626"/> + <char name="grave" width="600" llx="272" lly="508" urx="503" ury="661"/> + <char name="greater" width="600" llx="97" lly="15" urx="589" ury="501"/> + <char name="guillemotleft" width="600" llx="62" lly="70" urx="639" ury="446"/> + <char name="guillemotright" width="600" llx="71" lly="70" urx="647" ury="446"/> + <char name="guilsinglleft" width="600" llx="195" lly="70" urx="545" ury="446"/> + <char name="guilsinglright" width="600" llx="165" lly="70" urx="514" ury="446"/> + <char name="h" width="600" llx="18" lly="0" urx="615" ury="626"/> + <char name="hungarumlaut" width="600" llx="171" lly="488" urx="729" ury="661"/> + <char name="hyphen" width="600" llx="143" lly="203" urx="567" ury="313"/> + <char name="i" width="600" llx="77" lly="0" urx="546" ury="658"/> + <char name="iacute" width="600" llx="77" lly="0" urx="609" ury="661"/> + <char name="icircumflex" width="600" llx="77" lly="0" urx="577" ury="657"/> + <char name="idieresis" width="600" llx="77" lly="0" urx="561" ury="618"/> + <char name="igrave" width="600" llx="77" lly="0" urx="546" ury="661"/> + <char name="j" width="600" llx="36" lly="-146" urx="580" ury="658"/> + <char name="k" width="600" llx="33" lly="0" urx="643" ury="626"/> + <char name="l" width="600" llx="77" lly="0" urx="546" ury="626"/> + <char name="less" width="600" llx="120" lly="15" urx="613" ury="501"/> + <char name="logicalnot" width="600" llx="135" lly="103" urx="617" ury="413"/> + <char name="lslash" width="600" llx="77" lly="0" urx="587" ury="626"/> + <char name="m" width="600" llx="-22" lly="0" urx="649" ury="454"/> + <char name="macron" width="600" llx="195" lly="505" urx="637" ury="585"/> + <char name="minus" width="600" llx="114" lly="203" urx="596" ury="313"/> + <char name="mu" width="600" llx="49" lly="-142" urx="592" ury="439"/> + <char name="multiply" width="600" llx="104" lly="39" urx="606" ury="478"/> + <char name="n" width="600" llx="18" lly="0" urx="615" ury="454"/> + <char name="nine" width="600" llx="75" lly="-15" urx="592" ury="616"/> + <char name="ntilde" width="600" llx="18" lly="0" urx="643" ury="636"/> + <char name="numbersign" width="600" llx="88" lly="-45" urx="641" ury="651"/> + <char name="o" width="600" llx="71" lly="-15" urx="622" ury="454"/> + <char name="oacute" width="600" llx="71" lly="-15" urx="649" ury="661"/> + <char name="ocircumflex" width="600" llx="71" lly="-15" urx="622" ury="657"/> + <char name="odieresis" width="600" llx="71" lly="-15" urx="622" ury="638"/> + <char name="oe" width="600" llx="18" lly="-15" urx="662" ury="454"/> + <char name="ogonek" width="600" llx="143" lly="-199" urx="367" ury="0"/> + <char name="ograve" width="600" llx="71" lly="-15" urx="622" ury="661"/> + <char name="one" width="600" llx="93" lly="0" urx="562" ury="616"/> + <char name="onehalf" width="600" llx="22" lly="-60" urx="716" ury="661"/> + <char name="onequarter" width="600" llx="13" lly="-60" urx="707" ury="661"/> + <char name="onesuperior" width="600" llx="212" lly="230" urx="514" ury="616"/> + <char name="ordfeminine" width="600" llx="188" lly="196" urx="526" ury="580"/> + <char name="ordmasculine" width="600" llx="188" lly="196" urx="543" ury="580"/> + <char name="oslash" width="600" llx="54" lly="-24" urx="638" ury="463"/> + <char name="otilde" width="600" llx="71" lly="-15" urx="643" ury="636"/> + <char name="p" width="600" llx="-32" lly="-142" urx="622" ury="454"/> + <char name="paragraph" width="600" llx="61" lly="-70" urx="700" ury="580"/> + <char name="parenleft" width="600" llx="265" lly="-102" urx="592" ury="616"/> + <char name="parenright" width="600" llx="117" lly="-102" urx="444" ury="616"/> + <char name="percent" width="600" llx="101" lly="-15" urx="625" ury="616"/> + <char name="period" width="600" llx="206" lly="-15" urx="427" ury="171"/> + <char name="periodcentered" width="600" llx="248" lly="165" urx="461" ury="351"/> + <char name="perthousand" width="600" llx="-45" lly="-15" urx="743" ury="616"/> + <char name="plus" width="600" llx="114" lly="39" urx="596" ury="478"/> + <char name="plusminus" width="600" llx="76" lly="24" urx="614" ury="515"/> + <char name="q" width="600" llx="60" lly="-142" urx="685" ury="454"/> + <char name="question" width="600" llx="183" lly="-14" urx="592" ury="580"/> + <char name="questiondown" width="600" llx="100" lly="-146" urx="509" ury="449"/> + <char name="quotedbl" width="600" llx="211" lly="277" urx="585" ury="562"/> + <char name="quotedblbase" width="600" llx="34" lly="-142" urx="560" ury="143"/> + <char name="quotedblleft" width="600" llx="190" lly="277" urx="594" ury="562"/> + <char name="quotedblright" width="600" llx="119" lly="277" urx="645" ury="562"/> + <char name="quoteleft" width="600" llx="297" lly="277" urx="487" ury="562"/> + <char name="quoteright" width="600" llx="229" lly="277" urx="543" ury="562"/> + <char name="quotesinglbase" width="600" llx="144" lly="-142" urx="458" ury="143"/> + <char name="quotesingle" width="600" llx="303" lly="277" urx="493" ury="562"/> + <char name="r" width="600" llx="47" lly="0" urx="655" ury="454"/> + <char name="registered" width="600" llx="53" lly="-18" urx="667" ury="580"/> + <char name="ring" width="600" llx="319" lly="481" urx="528" ury="678"/> + <char name="s" width="600" llx="66" lly="-17" urx="608" ury="459"/> + <char name="scaron" width="600" llx="66" lly="-17" urx="633" ury="667"/> + <char name="scedilla" width="600" llx="66" lly="-206" urx="608" ury="459"/> + <char name="section" width="600" llx="74" lly="-70" urx="620" ury="580"/> + <char name="semicolon" width="600" llx="99" lly="-111" urx="481" ury="425"/> + <char name="seven" width="600" llx="147" lly="0" urx="622" ury="601"/> + <char name="six" width="600" llx="135" lly="-15" urx="652" ury="616"/> + <char name="slash" width="600" llx="90" lly="-77" urx="626" ury="626"/> + <char name="space" width="600" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="600"/> - <char name="square" width="600"/> - <char name="sterling" width="600"/> - <char name="stop" width="600"/> - <char name="t" width="600"/> - <char name="tab" width="600"/> - <char name="thorn" width="600"/> - <char name="three" width="600"/> - <char name="threequarters" width="600"/> - <char name="threesuperior" width="600"/> - <char name="tilde" width="600"/> - <char name="trademark" width="600"/> - <char name="two" width="600"/> - <char name="twosuperior" width="600"/> - <char name="u" width="600"/> - <char name="uacute" width="600"/> - <char name="ucircumflex" width="600"/> - <char name="udieresis" width="600"/> - <char name="ugrave" width="600"/> - <char name="underscore" width="600"/> - <char name="up" width="600"/> - <char name="v" width="600"/> - <char name="w" width="600"/> - <char name="x" width="600"/> - <char name="y" width="600"/> - <char name="yacute" width="600"/> - <char name="ydieresis" width="600"/> - <char name="yen" width="600"/> - <char name="z" width="600"/> - <char name="zcaron" width="600"/> - <char name="zero" width="600"/> - </widths> + <char name="sterling" width="600" llx="106" lly="-28" urx="650" ury="611"/> + <char name="t" width="600" llx="118" lly="-15" urx="567" ury="562"/> + <char name="thorn" width="600" llx="-32" lly="-142" urx="622" ury="626"/> + <char name="three" width="600" llx="71" lly="-15" urx="571" ury="616"/> + <char name="threequarters" width="600" llx="8" lly="-60" urx="699" ury="661"/> + <char name="threesuperior" width="600" llx="193" lly="222" urx="526" ury="616"/> + <char name="tilde" width="600" llx="199" lly="493" urx="643" ury="636"/> + <char name="trademark" width="600" llx="86" lly="230" urx="869" ury="562"/> + <char name="two" width="600" llx="61" lly="0" urx="594" ury="616"/> + <char name="twosuperior" width="600" llx="191" lly="230" urx="542" ury="616"/> + <char name="u" width="600" llx="70" lly="-15" urx="592" ury="439"/> + <char name="uacute" width="600" llx="70" lly="-15" urx="599" ury="661"/> + <char name="ucircumflex" width="600" llx="70" lly="-15" urx="597" ury="657"/> + <char name="udieresis" width="600" llx="70" lly="-15" urx="595" ury="638"/> + <char name="ugrave" width="600" llx="70" lly="-15" urx="592" ury="661"/> + <char name="underscore" width="600" llx="-27" lly="-125" urx="585" ury="-75"/> + <char name="v" width="600" llx="70" lly="0" urx="695" ury="439"/> + <char name="w" width="600" llx="53" lly="0" urx="712" ury="439"/> + <char name="x" width="600" llx="6" lly="0" urx="671" ury="439"/> + <char name="y" width="600" llx="-21" lly="-142" urx="695" ury="439"/> + <char name="yacute" width="600" llx="-21" lly="-142" urx="695" ury="661"/> + <char name="ydieresis" width="600" llx="-21" lly="-142" urx="695" ury="638"/> + <char name="yen" width="600" llx="98" lly="0" urx="710" ury="562"/> + <char name="z" width="600" llx="81" lly="0" urx="614" ury="439"/> + <char name="zcaron" width="600" llx="81" lly="0" urx="643" ury="667"/> + <char name="zero" width="600" llx="135" lly="-15" urx="593" ury="616"/> + </char-metrics> </font-metrics> diff --git a/src/codegen/fonts/CourierOblique.xml b/src/codegen/fonts/CourierOblique.xml index 2dc300645..e08fa9b9b 100644 --- a/src/codegen/fonts/CourierOblique.xml +++ b/src/codegen/fonts/CourierOblique.xml @@ -22,275 +22,246 @@ <family-name>Courier</family-name> <class-name>CourierOblique</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>562</cap-height> <x-height>426</x-height> <ascender>629</ascender> <descender>-157</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="600"/> - <char name="AE" width="600"/> - <char name="Aacute" width="600"/> - <char name="Acircumflex" width="600"/> - <char name="Adieresis" width="600"/> - <char name="Agrave" width="600"/> - <char name="Aring" width="600"/> - <char name="Atilde" width="600"/> - <char name="B" width="600"/> - <char name="C" width="600"/> - <char name="Ccedilla" width="600"/> - <char name="D" width="600"/> - <char name="E" width="600"/> - <char name="Eacute" width="600"/> - <char name="Ecircumflex" width="600"/> - <char name="Edieresis" width="600"/> - <char name="Egrave" width="600"/> - <char name="Eth" width="600"/> - <char name="Euro" width="600"/> - <char name="F" width="600"/> - <char name="G" width="600"/> - <char name="Gcaron" width="600"/> - <char name="H" width="600"/> - <char name="I" width="600"/> - <char name="IJ" width="600"/> - <char name="Iacute" width="600"/> - <char name="Icircumflex" width="600"/> - <char name="Idieresis" width="600"/> - <char name="Idot" width="600"/> - <char name="Igrave" width="600"/> - <char name="J" width="600"/> - <char name="K" width="600"/> - <char name="L" width="600"/> - <char name="LL" width="600"/> - <char name="Lslash" width="600"/> - <char name="M" width="600"/> - <char name="N" width="600"/> - <char name="Ntilde" width="600"/> - <char name="O" width="600"/> - <char name="OE" width="600"/> - <char name="Oacute" width="600"/> - <char name="Ocircumflex" width="600"/> - <char name="Odieresis" width="600"/> - <char name="Ograve" width="600"/> - <char name="Oslash" width="600"/> - <char name="Otilde" width="600"/> - <char name="P" width="600"/> - <char name="Q" width="600"/> - <char name="R" width="600"/> - <char name="S" width="600"/> - <char name="Scaron" width="600"/> - <char name="Scedilla" width="600"/> - <char name="T" width="600"/> - <char name="Thorn" width="600"/> - <char name="U" width="600"/> - <char name="Uacute" width="600"/> - <char name="Ucircumflex" width="600"/> - <char name="Udieresis" width="600"/> - <char name="Ugrave" width="600"/> - <char name="V" width="600"/> - <char name="W" width="600"/> - <char name="X" width="600"/> - <char name="Y" width="600"/> - <char name="Yacute" width="600"/> - <char name="Ydieresis" width="600"/> - <char name="Z" width="600"/> - <char name="Zcaron" width="600"/> - <char name="a" width="600"/> - <char name="aacute" width="600"/> - <char name="acircumflex" width="600"/> - <char name="acute" width="600"/> - <char name="adieresis" width="600"/> - <char name="ae" width="600"/> - <char name="agrave" width="600"/> - <char name="ampersand" width="600"/> - <char name="aring" width="600"/> - <char name="arrowboth" width="600"/> - <char name="arrowdown" width="600"/> - <char name="arrowleft" width="600"/> - <char name="arrowright" width="600"/> - <char name="arrowup" width="600"/> - <char name="asciicircum" width="600"/> - <char name="asciitilde" width="600"/> - <char name="asterisk" width="600"/> - <char name="at" width="600"/> - <char name="atilde" width="600"/> - <char name="b" width="600"/> - <char name="backslash" width="600"/> - <char name="bar" width="600"/> - <char name="braceleft" width="600"/> - <char name="braceright" width="600"/> - <char name="bracketleft" width="600"/> - <char name="bracketright" width="600"/> - <char name="breve" width="600"/> - <char name="brokenbar" width="600"/> - <char name="bullet" width="600"/> - <char name="c" width="600"/> - <char name="caron" width="600"/> - <char name="ccedilla" width="600"/> - <char name="cedilla" width="600"/> - <char name="cent" width="600"/> - <char name="center" width="600"/> - <char name="circumflex" width="600"/> - <char name="colon" width="600"/> - <char name="comma" width="600"/> - <char name="copyright" width="600"/> - <char name="currency" width="600"/> - <char name="d" width="600"/> - <char name="dagger" width="600"/> - <char name="daggerdbl" width="600"/> - <char name="dectab" width="600"/> - <char name="degree" width="600"/> - <char name="dieresis" width="600"/> - <char name="divide" width="600"/> - <char name="dollar" width="600"/> - <char name="dotaccent" width="600"/> - <char name="dotlessi" width="600"/> - <char name="down" width="600"/> - <char name="e" width="600"/> - <char name="eacute" width="600"/> - <char name="ecircumflex" width="600"/> - <char name="edieresis" width="600"/> - <char name="egrave" width="600"/> - <char name="eight" width="600"/> - <char name="ellipsis" width="600"/> - <char name="emdash" width="600"/> - <char name="endash" width="600"/> - <char name="equal" width="600"/> - <char name="eth" width="600"/> - <char name="exclam" width="600"/> - <char name="exclamdown" width="600"/> - <char name="f" width="600"/> - <char name="fi" width="600"/> - <char name="five" width="600"/> - <char name="fl" width="600"/> - <char name="florin" width="600"/> - <char name="format" width="600"/> - <char name="four" width="600"/> - <char name="fraction" width="600"/> - <char name="g" width="600"/> - <char name="gcaron" width="600"/> - <char name="germandbls" width="600"/> - <char name="grave" width="600"/> - <char name="graybox" width="600"/> - <char name="greater" width="600"/> - <char name="guillemotleft" width="600"/> - <char name="guillemotright" width="600"/> - <char name="guilsinglleft" width="600"/> - <char name="guilsinglright" width="600"/> - <char name="h" width="600"/> - <char name="hungarumlaut" width="600"/> - <char name="hyphen" width="600"/> - <char name="i" width="600"/> - <char name="iacute" width="600"/> - <char name="icircumflex" width="600"/> - <char name="idieresis" width="600"/> - <char name="igrave" width="600"/> - <char name="ij" width="600"/> - <char name="indent" width="600"/> - <char name="j" width="600"/> - <char name="k" width="600"/> - <char name="l" width="600"/> - <char name="largebullet" width="600"/> - <char name="left" width="600"/> - <char name="less" width="600"/> - <char name="lira" width="600"/> - <char name="ll" width="600"/> - <char name="logicalnot" width="600"/> - <char name="lslash" width="600"/> - <char name="m" width="600"/> - <char name="macron" width="600"/> - <char name="merge" width="600"/> - <char name="minus" width="600"/> - <char name="mu" width="600"/> - <char name="multiply" width="600"/> - <char name="n" width="600"/> - <char name="nine" width="600"/> - <char name="notegraphic" width="600"/> - <char name="ntilde" width="600"/> - <char name="numbersign" width="600"/> - <char name="o" width="600"/> - <char name="oacute" width="600"/> - <char name="ocircumflex" width="600"/> - <char name="odieresis" width="600"/> - <char name="oe" width="600"/> - <char name="ogonek" width="600"/> - <char name="ograve" width="600"/> - <char name="one" width="600"/> - <char name="onehalf" width="600"/> - <char name="onequarter" width="600"/> - <char name="onesuperior" width="600"/> - <char name="ordfeminine" width="600"/> - <char name="ordmasculine" width="600"/> - <char name="oslash" width="600"/> - <char name="otilde" width="600"/> - <char name="overscore" width="600"/> - <char name="p" width="600"/> - <char name="paragraph" width="600"/> - <char name="parenleft" width="600"/> - <char name="parenright" width="600"/> - <char name="percent" width="600"/> - <char name="period" width="600"/> - <char name="periodcentered" width="600"/> - <char name="perthousand" width="600"/> - <char name="plus" width="600"/> - <char name="plusminus" width="600"/> - <char name="prescription" width="600"/> - <char name="q" width="600"/> - <char name="question" width="600"/> - <char name="questiondown" width="600"/> - <char name="quotedbl" width="600"/> - <char name="quotedblbase" width="600"/> - <char name="quotedblleft" width="600"/> - <char name="quotedblright" width="600"/> - <char name="quoteleft" width="600"/> - <char name="quoteright" width="600"/> - <char name="quotesinglbase" width="600"/> - <char name="quotesingle" width="600"/> - <char name="r" width="600"/> - <char name="registered" width="600"/> - <char name="return" width="600"/> - <char name="ring" width="600"/> - <char name="s" width="600"/> - <char name="scaron" width="600"/> - <char name="scedilla" width="600"/> - <char name="section" width="600"/> - <char name="semicolon" width="600"/> - <char name="seven" width="600"/> - <char name="six" width="600"/> - <char name="slash" width="600"/> - <char name="space" width="600"/> + <char-metrics> + <char name="A" width="600" llx="3" lly="0" urx="607" ury="562"/> + <char name="AE" width="600" llx="3" lly="0" urx="655" ury="562"/> + <char name="Aacute" width="600" llx="3" lly="0" urx="660" ury="805"/> + <char name="Acircumflex" width="600" llx="3" lly="0" urx="607" ury="787"/> + <char name="Adieresis" width="600" llx="3" lly="0" urx="607" ury="753"/> + <char name="Agrave" width="600" llx="3" lly="0" urx="607" ury="805"/> + <char name="Aring" width="600" llx="3" lly="0" urx="607" ury="750"/> + <char name="Atilde" width="600" llx="3" lly="0" urx="655" ury="729"/> + <char name="B" width="600" llx="43" lly="0" urx="616" ury="562"/> + <char name="C" width="600" llx="93" lly="-18" urx="655" ury="580"/> + <char name="Ccedilla" width="600" llx="93" lly="-151" urx="658" ury="580"/> + <char name="D" width="600" llx="43" lly="0" urx="645" ury="562"/> + <char name="E" width="600" llx="53" lly="0" urx="660" ury="562"/> + <char name="Eacute" width="600" llx="53" lly="0" urx="670" ury="805"/> + <char name="Ecircumflex" width="600" llx="53" lly="0" urx="660" ury="787"/> + <char name="Edieresis" width="600" llx="53" lly="0" urx="660" ury="753"/> + <char name="Egrave" width="600" llx="53" lly="0" urx="660" ury="805"/> + <char name="Eth" width="600" llx="43" lly="0" urx="645" ury="562"/> + <char name="Euro" width="600" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="600" llx="53" lly="0" urx="660" ury="562"/> + <char name="G" width="600" llx="83" lly="-18" urx="645" ury="580"/> + <char name="H" width="600" llx="32" lly="0" urx="687" ury="562"/> + <char name="I" width="600" llx="96" lly="0" urx="623" ury="562"/> + <char name="Iacute" width="600" llx="96" lly="0" urx="640" ury="805"/> + <char name="Icircumflex" width="600" llx="96" lly="0" urx="623" ury="787"/> + <char name="Idieresis" width="600" llx="96" lly="0" urx="623" ury="753"/> + <char name="Igrave" width="600" llx="96" lly="0" urx="623" ury="805"/> + <char name="J" width="600" llx="52" lly="-18" urx="685" ury="562"/> + <char name="K" width="600" llx="38" lly="0" urx="671" ury="562"/> + <char name="L" width="600" llx="47" lly="0" urx="607" ury="562"/> + <char name="Lslash" width="600" llx="47" lly="0" urx="607" ury="562"/> + <char name="M" width="600" llx="4" lly="0" urx="715" ury="562"/> + <char name="N" width="600" llx="7" lly="-13" urx="712" ury="562"/> + <char name="Ntilde" width="600" llx="7" lly="-13" urx="712" ury="729"/> + <char name="O" width="600" llx="94" lly="-18" urx="625" ury="580"/> + <char name="OE" width="600" llx="59" lly="0" urx="672" ury="562"/> + <char name="Oacute" width="600" llx="94" lly="-18" urx="640" ury="805"/> + <char name="Ocircumflex" width="600" llx="94" lly="-18" urx="625" ury="787"/> + <char name="Odieresis" width="600" llx="94" lly="-18" urx="625" ury="753"/> + <char name="Ograve" width="600" llx="94" lly="-18" urx="625" ury="805"/> + <char name="Oslash" width="600" llx="94" lly="-80" urx="625" ury="629"/> + <char name="Otilde" width="600" llx="94" lly="-18" urx="655" ury="729"/> + <char name="P" width="600" llx="79" lly="0" urx="644" ury="562"/> + <char name="Q" width="600" llx="95" lly="-138" urx="625" ury="580"/> + <char name="R" width="600" llx="38" lly="0" urx="598" ury="562"/> + <char name="S" width="600" llx="76" lly="-20" urx="650" ury="580"/> + <char name="Scaron" width="600" llx="76" lly="-20" urx="672" ury="802"/> + <char name="Scedilla" width="600" llx="76" lly="-151" urx="650" ury="580"/> + <char name="T" width="600" llx="108" lly="0" urx="665" ury="562"/> + <char name="Thorn" width="600" llx="79" lly="0" urx="606" ury="562"/> + <char name="U" width="600" llx="125" lly="-18" urx="702" ury="562"/> + <char name="Uacute" width="600" llx="125" lly="-18" urx="702" ury="805"/> + <char name="Ucircumflex" width="600" llx="125" lly="-18" urx="702" ury="787"/> + <char name="Udieresis" width="600" llx="125" lly="-18" urx="702" ury="753"/> + <char name="Ugrave" width="600" llx="125" lly="-18" urx="702" ury="805"/> + <char name="V" width="600" llx="105" lly="-13" urx="723" ury="562"/> + <char name="W" width="600" llx="106" lly="-13" urx="722" ury="562"/> + <char name="X" width="600" llx="23" lly="0" urx="675" ury="562"/> + <char name="Y" width="600" llx="133" lly="0" urx="695" ury="562"/> + <char name="Yacute" width="600" llx="133" lly="0" urx="695" ury="805"/> + <char name="Ydieresis" width="600" llx="133" lly="0" urx="695" ury="753"/> + <char name="Z" width="600" llx="86" lly="0" urx="610" ury="562"/> + <char name="Zcaron" width="600" llx="86" lly="0" urx="642" ury="802"/> + <char name="a" width="600" llx="76" lly="-15" urx="569" ury="441"/> + <char name="aacute" width="600" llx="76" lly="-15" urx="612" ury="672"/> + <char name="acircumflex" width="600" llx="76" lly="-15" urx="581" ury="654"/> + <char name="acute" width="600" llx="348" lly="497" urx="612" ury="672"/> + <char name="adieresis" width="600" llx="76" lly="-15" urx="575" ury="620"/> + <char name="ae" width="600" llx="41" lly="-15" urx="626" ury="441"/> + <char name="agrave" width="600" llx="76" lly="-15" urx="569" ury="672"/> + <char name="ampersand" width="600" llx="87" lly="-15" urx="580" ury="543"/> + <char name="aring" width="600" llx="76" lly="-15" urx="569" ury="627"/> + <char name="asciicircum" width="600" llx="175" lly="354" urx="587" ury="622"/> + <char name="asciitilde" width="600" llx="116" lly="197" urx="600" ury="320"/> + <char name="asterisk" width="600" llx="212" lly="257" urx="580" ury="607"/> + <char name="at" width="600" llx="127" lly="-15" urx="582" ury="622"/> + <char name="atilde" width="600" llx="76" lly="-15" urx="629" ury="606"/> + <char name="b" width="600" llx="29" lly="-15" urx="625" ury="629"/> + <char name="backslash" width="600" llx="249" lly="-80" urx="468" ury="629"/> + <char name="bar" width="600" llx="222" lly="-250" urx="485" ury="750"/> + <char name="braceleft" width="600" llx="233" lly="-108" urx="569" ury="622"/> + <char name="braceright" width="600" llx="140" lly="-108" urx="477" ury="622"/> + <char name="bracketleft" width="600" llx="246" lly="-108" urx="574" ury="622"/> + <char name="bracketright" width="600" llx="135" lly="-108" urx="463" ury="622"/> + <char name="breve" width="600" llx="279" lly="501" urx="576" ury="609"/> + <char name="brokenbar" width="600" llx="238" lly="-175" urx="469" ury="675"/> + <char name="bullet" width="600" llx="224" lly="130" urx="485" ury="383"/> + <char name="c" width="600" llx="106" lly="-15" urx="608" ury="441"/> + <char name="caron" width="600" llx="262" lly="492" urx="614" ury="669"/> + <char name="ccedilla" width="600" llx="106" lly="-151" urx="614" ury="441"/> + <char name="cedilla" width="600" llx="197" lly="-151" urx="344" ury="10"/> + <char name="cent" width="600" llx="151" lly="-49" urx="588" ury="614"/> + <char name="circumflex" width="600" llx="229" lly="477" urx="581" ury="654"/> + <char name="colon" width="600" llx="238" lly="-15" urx="441" ury="385"/> + <char name="comma" width="600" llx="157" lly="-112" urx="370" ury="122"/> + <char name="copyright" width="600" llx="53" lly="-18" urx="667" ury="580"/> + <char name="currency" width="600" llx="94" lly="58" urx="628" ury="506"/> + <char name="d" width="600" llx="85" lly="-15" urx="640" ury="629"/> + <char name="dagger" width="600" llx="217" lly="-78" urx="546" ury="580"/> + <char name="daggerdbl" width="600" llx="163" lly="-78" urx="546" ury="580"/> + <char name="degree" width="600" llx="214" lly="269" urx="576" ury="622"/> + <char name="dieresis" width="600" llx="272" lly="537" urx="579" ury="640"/> + <char name="divide" width="600" llx="136" lly="48" urx="573" ury="467"/> + <char name="dollar" width="600" llx="108" lly="-126" urx="596" ury="662"/> + <char name="dotaccent" width="600" llx="373" lly="537" urx="478" ury="640"/> + <char name="dotlessi" width="600" llx="95" lly="0" urx="515" ury="426"/> + <char name="e" width="600" llx="106" lly="-15" urx="598" ury="441"/> + <char name="eacute" width="600" llx="106" lly="-15" urx="612" ury="672"/> + <char name="ecircumflex" width="600" llx="106" lly="-15" urx="598" ury="654"/> + <char name="edieresis" width="600" llx="106" lly="-15" urx="598" ury="620"/> + <char name="egrave" width="600" llx="106" lly="-15" urx="598" ury="672"/> + <char name="eight" width="600" llx="132" lly="-15" urx="588" ury="622"/> + <char name="ellipsis" width="600" llx="46" lly="-15" urx="575" ury="111"/> + <char name="emdash" width="600" llx="49" lly="231" urx="661" ury="285"/> + <char name="endash" width="600" llx="124" lly="231" urx="586" ury="285"/> + <char name="equal" width="600" llx="109" lly="138" urx="600" ury="376"/> + <char name="eth" width="600" llx="102" lly="-15" urx="639" ury="629"/> + <char name="exclam" width="600" llx="243" lly="-15" urx="464" ury="572"/> + <char name="exclamdown" width="600" llx="225" lly="-157" urx="445" ury="430"/> + <char name="f" width="600" llx="114" lly="0" urx="662" ury="629"/> + <char name="fi" width="600" llx="3" lly="0" urx="619" ury="629"/> + <char name="five" width="600" llx="99" lly="-15" urx="589" ury="607"/> + <char name="fl" width="600" llx="3" lly="0" urx="619" ury="629"/> + <char name="florin" width="600" llx="-26" lly="-143" urx="671" ury="622"/> + <char name="four" width="600" llx="108" lly="0" urx="541" ury="622"/> + <char name="fraction" width="600" llx="84" lly="-57" urx="646" ury="665"/> + <char name="g" width="600" llx="61" lly="-157" urx="657" ury="441"/> + <char name="germandbls" width="600" llx="48" lly="-15" urx="617" ury="629"/> + <char name="grave" width="600" llx="294" lly="497" urx="484" ury="672"/> + <char name="greater" width="600" llx="85" lly="42" urx="599" ury="472"/> + <char name="guillemotleft" width="600" llx="92" lly="70" urx="652" ury="446"/> + <char name="guillemotright" width="600" llx="58" lly="70" urx="618" ury="446"/> + <char name="guilsinglleft" width="600" llx="204" lly="70" urx="540" ury="446"/> + <char name="guilsinglright" width="600" llx="170" lly="70" urx="506" ury="446"/> + <char name="h" width="600" llx="33" lly="0" urx="592" ury="629"/> + <char name="hungarumlaut" width="600" llx="239" lly="497" urx="683" ury="672"/> + <char name="hyphen" width="600" llx="152" lly="231" urx="558" ury="285"/> + <char name="i" width="600" llx="95" lly="0" urx="515" ury="657"/> + <char name="iacute" width="600" llx="95" lly="0" urx="612" ury="672"/> + <char name="icircumflex" width="600" llx="95" lly="0" urx="551" ury="654"/> + <char name="idieresis" width="600" llx="95" lly="0" urx="545" ury="620"/> + <char name="igrave" width="600" llx="95" lly="0" urx="515" ury="672"/> + <char name="j" width="600" llx="52" lly="-157" urx="550" ury="657"/> + <char name="k" width="600" llx="58" lly="0" urx="633" ury="629"/> + <char name="l" width="600" llx="95" lly="0" urx="515" ury="629"/> + <char name="less" width="600" llx="96" lly="42" urx="610" ury="472"/> + <char name="logicalnot" width="600" llx="155" lly="108" urx="591" ury="369"/> + <char name="lslash" width="600" llx="95" lly="0" urx="587" ury="629"/> + <char name="m" width="600" llx="-5" lly="0" urx="615" ury="441"/> + <char name="macron" width="600" llx="232" lly="525" urx="600" ury="565"/> + <char name="minus" width="600" llx="129" lly="232" urx="580" ury="283"/> + <char name="mu" width="600" llx="72" lly="-157" urx="572" ury="426"/> + <char name="multiply" width="600" llx="103" lly="43" urx="607" ury="470"/> + <char name="n" width="600" llx="26" lly="0" urx="585" ury="441"/> + <char name="nine" width="600" llx="93" lly="-15" urx="574" ury="622"/> + <char name="ntilde" width="600" llx="26" lly="0" urx="629" ury="606"/> + <char name="numbersign" width="600" llx="133" lly="-32" urx="596" ury="639"/> + <char name="o" width="600" llx="102" lly="-15" urx="588" ury="441"/> + <char name="oacute" width="600" llx="102" lly="-15" urx="612" ury="672"/> + <char name="ocircumflex" width="600" llx="102" lly="-15" urx="588" ury="654"/> + <char name="odieresis" width="600" llx="102" lly="-15" urx="588" ury="620"/> + <char name="oe" width="600" llx="54" lly="-15" urx="615" ury="441"/> + <char name="ogonek" width="600" llx="189" lly="-172" urx="377" ury="4"/> + <char name="ograve" width="600" llx="102" lly="-15" urx="588" ury="672"/> + <char name="one" width="600" llx="98" lly="0" urx="515" ury="622"/> + <char name="onehalf" width="600" llx="65" lly="-57" urx="669" ury="665"/> + <char name="onequarter" width="600" llx="65" lly="-57" urx="674" ury="665"/> + <char name="onesuperior" width="600" llx="231" lly="249" urx="491" ury="622"/> + <char name="ordfeminine" width="600" llx="209" lly="249" urx="512" ury="580"/> + <char name="ordmasculine" width="600" llx="210" lly="249" urx="535" ury="580"/> + <char name="oslash" width="600" llx="102" lly="-80" urx="588" ury="506"/> + <char name="otilde" width="600" llx="102" lly="-15" urx="629" ury="606"/> + <char name="p" width="600" llx="-24" lly="-157" urx="605" ury="441"/> + <char name="paragraph" width="600" llx="100" lly="-78" urx="630" ury="562"/> + <char name="parenleft" width="600" llx="313" lly="-108" urx="572" ury="622"/> + <char name="parenright" width="600" llx="137" lly="-108" urx="396" ury="622"/> + <char name="percent" width="600" llx="134" lly="-15" urx="599" ury="622"/> + <char name="period" width="600" llx="238" lly="-15" urx="382" ury="109"/> + <char name="periodcentered" width="600" llx="275" lly="189" urx="434" ury="327"/> + <char name="perthousand" width="600" llx="59" lly="-15" urx="627" ury="622"/> + <char name="plus" width="600" llx="129" lly="44" urx="580" ury="470"/> + <char name="plusminus" width="600" llx="96" lly="44" urx="594" ury="558"/> + <char name="q" width="600" llx="85" lly="-157" urx="682" ury="441"/> + <char name="question" width="600" llx="222" lly="-15" urx="583" ury="572"/> + <char name="questiondown" width="600" llx="105" lly="-157" urx="466" ury="430"/> + <char name="quotedbl" width="600" llx="273" lly="328" urx="532" ury="562"/> + <char name="quotedblbase" width="600" llx="115" lly="-134" urx="478" ury="100"/> + <char name="quotedblleft" width="600" llx="262" lly="328" urx="541" ury="562"/> + <char name="quotedblright" width="600" llx="213" lly="328" urx="576" ury="562"/> + <char name="quoteleft" width="600" llx="343" lly="328" urx="457" ury="562"/> + <char name="quoteright" width="600" llx="283" lly="328" urx="495" ury="562"/> + <char name="quotesinglbase" width="600" llx="185" lly="-134" urx="397" ury="100"/> + <char name="quotesingle" width="600" llx="345" lly="328" urx="460" ury="562"/> + <char name="r" width="600" llx="60" lly="0" urx="636" ury="441"/> + <char name="registered" width="600" llx="53" lly="-18" urx="667" ury="580"/> + <char name="ring" width="600" llx="332" lly="463" urx="500" ury="627"/> + <char name="s" width="600" llx="78" lly="-15" urx="584" ury="441"/> + <char name="scaron" width="600" llx="78" lly="-15" urx="614" ury="669"/> + <char name="scedilla" width="600" llx="78" lly="-151" urx="584" ury="441"/> + <char name="section" width="600" llx="104" lly="-78" urx="590" ury="580"/> + <char name="semicolon" width="600" llx="157" lly="-112" urx="441" ury="385"/> + <char name="seven" width="600" llx="182" lly="0" urx="612" ury="607"/> + <char name="six" width="600" llx="155" lly="-15" urx="629" ury="622"/> + <char name="slash" width="600" llx="112" lly="-80" urx="604" ury="629"/> + <char name="space" width="600" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="600"/> - <char name="square" width="600"/> - <char name="sterling" width="600"/> - <char name="stop" width="600"/> - <char name="t" width="600"/> - <char name="tab" width="600"/> - <char name="thorn" width="600"/> - <char name="three" width="600"/> - <char name="threequarters" width="600"/> - <char name="threesuperior" width="600"/> - <char name="tilde" width="600"/> - <char name="trademark" width="600"/> - <char name="two" width="600"/> - <char name="twosuperior" width="600"/> - <char name="u" width="600"/> - <char name="uacute" width="600"/> - <char name="ucircumflex" width="600"/> - <char name="udieresis" width="600"/> - <char name="ugrave" width="600"/> - <char name="underscore" width="600"/> - <char name="up" width="600"/> - <char name="v" width="600"/> - <char name="w" width="600"/> - <char name="x" width="600"/> - <char name="y" width="600"/> - <char name="yacute" width="600"/> - <char name="ydieresis" width="600"/> - <char name="yen" width="600"/> - <char name="z" width="600"/> - <char name="zcaron" width="600"/> - <char name="zero" width="600"/> - </widths> -</font-metrics>
\ No newline at end of file + <char name="sterling" width="600" llx="124" lly="-21" urx="621" ury="611"/> + <char name="t" width="600" llx="167" lly="-15" urx="561" ury="561"/> + <char name="thorn" width="600" llx="-24" lly="-157" urx="605" ury="629"/> + <char name="three" width="600" llx="82" lly="-15" urx="538" ury="622"/> + <char name="threequarters" width="600" llx="73" lly="-56" urx="659" ury="666"/> + <char name="threesuperior" width="600" llx="213" lly="240" urx="501" ury="622"/> + <char name="tilde" width="600" llx="212" lly="489" urx="629" ury="606"/> + <char name="trademark" width="600" llx="75" lly="263" urx="742" ury="562"/> + <char name="two" width="600" llx="70" lly="0" urx="568" ury="622"/> + <char name="twosuperior" width="600" llx="230" lly="249" urx="535" ury="622"/> + <char name="u" width="600" llx="101" lly="-15" urx="572" ury="426"/> + <char name="uacute" width="600" llx="101" lly="-15" urx="602" ury="672"/> + <char name="ucircumflex" width="600" llx="101" lly="-15" urx="572" ury="654"/> + <char name="udieresis" width="600" llx="101" lly="-15" urx="575" ury="620"/> + <char name="ugrave" width="600" llx="101" lly="-15" urx="572" ury="672"/> + <char name="underscore" width="600" llx="-27" lly="-125" urx="584" ury="-75"/> + <char name="v" width="600" llx="90" lly="-10" urx="681" ury="426"/> + <char name="w" width="600" llx="76" lly="-10" urx="695" ury="426"/> + <char name="x" width="600" llx="20" lly="0" urx="655" ury="426"/> + <char name="y" width="600" llx="-4" lly="-157" urx="683" ury="426"/> + <char name="yacute" width="600" llx="-4" lly="-157" urx="683" ury="672"/> + <char name="ydieresis" width="600" llx="-4" lly="-157" urx="683" ury="620"/> + <char name="yen" width="600" llx="120" lly="0" urx="693" ury="562"/> + <char name="z" width="600" llx="99" lly="0" urx="593" ury="426"/> + <char name="zcaron" width="600" llx="99" lly="0" urx="624" ury="669"/> + <char name="zero" width="600" llx="154" lly="-15" urx="575" ury="622"/> + </char-metrics> +</font-metrics> diff --git a/src/codegen/fonts/Helvetica.xml b/src/codegen/fonts/Helvetica.xml index 38ae23055..b6e11a72b 100644 --- a/src/codegen/fonts/Helvetica.xml +++ b/src/codegen/fonts/Helvetica.xml @@ -22,245 +22,246 @@ <family-name>Helvetica</family-name> <class-name>Helvetica</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>718</cap-height> <x-height>523</x-height> <ascender>718</ascender> <descender>-207</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="667"/> - <char name="AE" width="1000"/> - <char name="Aacute" width="667"/> - <char name="Acircumflex" width="667"/> - <char name="Adieresis" width="667"/> - <char name="Agrave" width="667"/> - <char name="Aring" width="667"/> - <char name="Atilde" width="667"/> - <char name="B" width="667"/> - <char name="C" width="722"/> - <char name="Ccedilla" width="722"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="556"/> - <char name="F" width="611"/> - <char name="G" width="778"/> - <char name="H" width="722"/> - <char name="I" width="278"/> - <char name="Iacute" width="278"/> - <char name="Icircumflex" width="278"/> - <char name="Idieresis" width="278"/> - <char name="Igrave" width="278"/> - <char name="J" width="500"/> - <char name="K" width="667"/> - <char name="L" width="556"/> - <char name="Lslash" width="556"/> - <char name="M" width="833"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="778"/> - <char name="OE" width="1000"/> - <char name="Oacute" width="778"/> - <char name="Ocircumflex" width="778"/> - <char name="Odieresis" width="778"/> - <char name="Ograve" width="778"/> - <char name="Oslash" width="778"/> - <char name="Otilde" width="778"/> - <char name="P" width="667"/> - <char name="Q" width="778"/> - <char name="R" width="722"/> - <char name="S" width="667"/> - <char name="Scaron" width="667"/> - <char name="T" width="611"/> - <char name="Thorn" width="667"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="667"/> - <char name="W" width="944"/> - <char name="X" width="667"/> - <char name="Y" width="667"/> - <char name="Yacute" width="667"/> - <char name="Ydieresis" width="667"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="556"/> - <char name="aacute" width="556"/> - <char name="acircumflex" width="556"/> - <char name="acute" width="333"/> - <char name="adieresis" width="556"/> - <char name="ae" width="889"/> - <char name="agrave" width="556"/> - <char name="ampersand" width="667"/> - <char name="aring" width="556"/> - <char name="asciicircum" width="469"/> - <char name="asciitilde" width="584"/> - <char name="asterisk" width="389"/> - <char name="at" width="1015"/> - <char name="atilde" width="556"/> - <char name="b" width="556"/> - <char name="backslash" width="278"/> - <char name="bar" width="260"/> - <char name="braceleft" width="334"/> - <char name="braceright" width="334"/> - <char name="bracketleft" width="278"/> - <char name="bracketright" width="278"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="260"/> - <char name="bullet" width="350"/> - <char name="c" width="500"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="500"/> - <char name="cedilla" width="333"/> - <char name="cent" width="556"/> - <char name="circumflex" width="333"/> - <char name="colon" width="278"/> - <char name="comma" width="278"/> - <char name="copyright" width="737"/> - <char name="currency" width="556"/> - <char name="d" width="556"/> - <char name="dagger" width="556"/> - <char name="daggerdbl" width="556"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="584"/> - <char name="dollar" width="556"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="556"/> - <char name="eacute" width="556"/> - <char name="ecircumflex" width="556"/> - <char name="edieresis" width="556"/> - <char name="egrave" width="556"/> - <char name="eight" width="556"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="556"/> - <char name="equal" width="584"/> - <char name="eth" width="556"/> - <char name="exclam" width="278"/> - <char name="exclamdown" width="333"/> - <char name="f" width="278"/> - <char name="fi" width="500"/> - <char name="five" width="556"/> - <char name="fl" width="500"/> - <char name="florin" width="556"/> - <char name="four" width="556"/> - <char name="fraction" width="167"/> - <char name="g" width="556"/> - <char name="germandbls" width="611"/> - <char name="grave" width="333"/> - <char name="greater" width="584"/> - <char name="guillemotleft" width="556"/> - <char name="guillemotright" width="556"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="556"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="222"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="222"/> - <char name="k" width="500"/> - <char name="l" width="222"/> - <char name="less" width="584"/> - <char name="logicalnot" width="584"/> - <char name="lslash" width="222"/> - <char name="m" width="833"/> - <char name="macron" width="333"/> - <char name="minus" width="324"/> - <char name="mu" width="556"/> - <char name="multiply" width="584"/> - <char name="n" width="556"/> - <char name="nine" width="556"/> - <char name="ntilde" width="556"/> - <char name="numbersign" width="556"/> - <char name="o" width="556"/> - <char name="oacute" width="556"/> - <char name="ocircumflex" width="556"/> - <char name="odieresis" width="556"/> - <char name="oe" width="944"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="556"/> - <char name="one" width="556"/> - <char name="onehalf" width="834"/> - <char name="onequarter" width="834"/> - <char name="onesuperior" width="333"/> - <char name="ordfeminine" width="370"/> - <char name="ordmasculine" width="365"/> - <char name="oslash" width="611"/> - <char name="otilde" width="556"/> - <char name="p" width="556"/> - <char name="paragraph" width="537"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="889"/> - <char name="period" width="278"/> - <char name="periodcentered" width="278"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="584"/> - <char name="plusminus" width="584"/> - <char name="q" width="556"/> - <char name="question" width="556"/> - <char name="questiondown" width="611"/> - <char name="quotedbl" width="355"/> - <char name="quotedblbase" width="333"/> - <char name="quotedblleft" width="333"/> - <char name="quotedblright" width="333"/> - <char name="quoteleft" width="222"/> - <char name="quoteright" width="222"/> - <char name="quotesinglbase" width="222"/> - <char name="quotesingle" width="191"/> - <char name="r" width="333"/> - <char name="registered" width="737"/> - <char name="ring" width="333"/> - <char name="s" width="500"/> - <char name="scaron" width="500"/> - <char name="section" width="556"/> - <char name="semicolon" width="278"/> - <char name="seven" width="556"/> - <char name="six" width="556"/> - <char name="slash" width="278"/> - <char name="space" width="278"/> + <char-metrics> + <char name="A" width="667" llx="14" lly="0" urx="654" ury="718"/> + <char name="AE" width="1000" llx="8" lly="0" urx="951" ury="718"/> + <char name="Aacute" width="667" llx="14" lly="0" urx="654" ury="929"/> + <char name="Acircumflex" width="667" llx="14" lly="0" urx="654" ury="929"/> + <char name="Adieresis" width="667" llx="14" lly="0" urx="654" ury="901"/> + <char name="Agrave" width="667" llx="14" lly="0" urx="654" ury="929"/> + <char name="Aring" width="667" llx="14" lly="0" urx="654" ury="931"/> + <char name="Atilde" width="667" llx="14" lly="0" urx="654" ury="917"/> + <char name="B" width="667" llx="74" lly="0" urx="627" ury="718"/> + <char name="C" width="722" llx="44" lly="-19" urx="681" ury="737"/> + <char name="Ccedilla" width="722" llx="44" lly="-225" urx="681" ury="737"/> + <char name="D" width="722" llx="81" lly="0" urx="674" ury="718"/> + <char name="E" width="667" llx="86" lly="0" urx="616" ury="718"/> + <char name="Eacute" width="667" llx="86" lly="0" urx="616" ury="929"/> + <char name="Ecircumflex" width="667" llx="86" lly="0" urx="616" ury="929"/> + <char name="Edieresis" width="667" llx="86" lly="0" urx="616" ury="901"/> + <char name="Egrave" width="667" llx="86" lly="0" urx="616" ury="929"/> + <char name="Eth" width="722" llx="0" lly="0" urx="674" ury="718"/> + <char name="Euro" width="556" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="86" lly="0" urx="583" ury="718"/> + <char name="G" width="778" llx="48" lly="-19" urx="704" ury="737"/> + <char name="H" width="722" llx="77" lly="0" urx="646" ury="718"/> + <char name="I" width="278" llx="91" lly="0" urx="188" ury="718"/> + <char name="Iacute" width="278" llx="91" lly="0" urx="292" ury="929"/> + <char name="Icircumflex" width="278" llx="-6" lly="0" urx="285" ury="929"/> + <char name="Idieresis" width="278" llx="13" lly="0" urx="266" ury="901"/> + <char name="Igrave" width="278" llx="-13" lly="0" urx="188" ury="929"/> + <char name="J" width="500" llx="17" lly="-19" urx="428" ury="718"/> + <char name="K" width="667" llx="76" lly="0" urx="663" ury="718"/> + <char name="L" width="556" llx="76" lly="0" urx="537" ury="718"/> + <char name="Lslash" width="556" llx="-20" lly="0" urx="537" ury="718"/> + <char name="M" width="833" llx="73" lly="0" urx="761" ury="718"/> + <char name="N" width="722" llx="76" lly="0" urx="646" ury="718"/> + <char name="Ntilde" width="722" llx="76" lly="0" urx="646" ury="917"/> + <char name="O" width="778" llx="39" lly="-19" urx="739" ury="737"/> + <char name="OE" width="1000" llx="36" lly="-19" urx="965" ury="737"/> + <char name="Oacute" width="778" llx="39" lly="-19" urx="739" ury="929"/> + <char name="Ocircumflex" width="778" llx="39" lly="-19" urx="739" ury="929"/> + <char name="Odieresis" width="778" llx="39" lly="-19" urx="739" ury="901"/> + <char name="Ograve" width="778" llx="39" lly="-19" urx="739" ury="929"/> + <char name="Oslash" width="778" llx="39" lly="-19" urx="740" ury="737"/> + <char name="Otilde" width="778" llx="39" lly="-19" urx="739" ury="917"/> + <char name="P" width="667" llx="86" lly="0" urx="622" ury="718"/> + <char name="Q" width="778" llx="39" lly="-56" urx="739" ury="737"/> + <char name="R" width="722" llx="88" lly="0" urx="684" ury="718"/> + <char name="S" width="667" llx="49" lly="-19" urx="620" ury="737"/> + <char name="Scaron" width="667" llx="49" lly="-19" urx="620" ury="929"/> + <char name="T" width="611" llx="14" lly="0" urx="597" ury="718"/> + <char name="Thorn" width="667" llx="86" lly="0" urx="622" ury="718"/> + <char name="U" width="722" llx="79" lly="-19" urx="644" ury="718"/> + <char name="Uacute" width="722" llx="79" lly="-19" urx="644" ury="929"/> + <char name="Ucircumflex" width="722" llx="79" lly="-19" urx="644" ury="929"/> + <char name="Udieresis" width="722" llx="79" lly="-19" urx="644" ury="901"/> + <char name="Ugrave" width="722" llx="79" lly="-19" urx="644" ury="929"/> + <char name="V" width="667" llx="20" lly="0" urx="647" ury="718"/> + <char name="W" width="944" llx="16" lly="0" urx="928" ury="718"/> + <char name="X" width="667" llx="19" lly="0" urx="648" ury="718"/> + <char name="Y" width="667" llx="14" lly="0" urx="653" ury="718"/> + <char name="Yacute" width="667" llx="14" lly="0" urx="653" ury="929"/> + <char name="Ydieresis" width="667" llx="14" lly="0" urx="653" ury="901"/> + <char name="Z" width="611" llx="23" lly="0" urx="588" ury="718"/> + <char name="Zcaron" width="611" llx="23" lly="0" urx="588" ury="929"/> + <char name="a" width="556" llx="36" lly="-15" urx="530" ury="538"/> + <char name="aacute" width="556" llx="36" lly="-15" urx="530" ury="734"/> + <char name="acircumflex" width="556" llx="36" lly="-15" urx="530" ury="734"/> + <char name="acute" width="333" llx="122" lly="593" urx="319" ury="734"/> + <char name="adieresis" width="556" llx="36" lly="-15" urx="530" ury="706"/> + <char name="ae" width="889" llx="36" lly="-15" urx="847" ury="538"/> + <char name="agrave" width="556" llx="36" lly="-15" urx="530" ury="734"/> + <char name="ampersand" width="667" llx="44" lly="-15" urx="645" ury="718"/> + <char name="aring" width="556" llx="36" lly="-15" urx="530" ury="756"/> + <char name="asciicircum" width="469" llx="-14" lly="264" urx="483" ury="688"/> + <char name="asciitilde" width="584" llx="61" lly="180" urx="523" ury="326"/> + <char name="asterisk" width="389" llx="39" lly="431" urx="349" ury="718"/> + <char name="at" width="1015" llx="147" lly="-19" urx="868" ury="737"/> + <char name="atilde" width="556" llx="36" lly="-15" urx="530" ury="722"/> + <char name="b" width="556" llx="58" lly="-15" urx="517" ury="718"/> + <char name="backslash" width="278" llx="-17" lly="-19" urx="295" ury="737"/> + <char name="bar" width="260" llx="94" lly="-225" urx="167" ury="775"/> + <char name="braceleft" width="334" llx="42" lly="-196" urx="292" ury="722"/> + <char name="braceright" width="334" llx="42" lly="-196" urx="292" ury="722"/> + <char name="bracketleft" width="278" llx="63" lly="-196" urx="250" ury="722"/> + <char name="bracketright" width="278" llx="28" lly="-196" urx="215" ury="722"/> + <char name="breve" width="333" llx="13" lly="595" urx="321" ury="731"/> + <char name="brokenbar" width="260" llx="94" lly="-150" urx="167" ury="700"/> + <char name="bullet" width="350" llx="18" lly="202" urx="333" ury="517"/> + <char name="c" width="500" llx="30" lly="-15" urx="477" ury="538"/> + <char name="caron" width="333" llx="21" lly="593" urx="312" ury="734"/> + <char name="ccedilla" width="500" llx="30" lly="-225" urx="477" ury="538"/> + <char name="cedilla" width="333" llx="45" lly="-225" urx="259" ury="0"/> + <char name="cent" width="556" llx="51" lly="-115" urx="513" ury="623"/> + <char name="circumflex" width="333" llx="21" lly="593" urx="312" ury="734"/> + <char name="colon" width="278" llx="87" lly="0" urx="191" ury="516"/> + <char name="comma" width="278" llx="87" lly="-147" urx="191" ury="106"/> + <char name="copyright" width="737" llx="-14" lly="-19" urx="752" ury="737"/> + <char name="currency" width="556" llx="28" lly="99" urx="528" ury="603"/> + <char name="d" width="556" llx="35" lly="-15" urx="499" ury="718"/> + <char name="dagger" width="556" llx="43" lly="-159" urx="514" ury="718"/> + <char name="daggerdbl" width="556" llx="43" lly="-159" urx="514" ury="718"/> + <char name="degree" width="400" llx="54" lly="411" urx="346" ury="703"/> + <char name="dieresis" width="333" llx="40" lly="604" urx="293" ury="706"/> + <char name="divide" width="584" llx="39" lly="-19" urx="545" ury="524"/> + <char name="dollar" width="556" llx="32" lly="-115" urx="520" ury="775"/> + <char name="dotaccent" width="333" llx="121" lly="604" urx="212" ury="706"/> + <char name="dotlessi" width="278" llx="95" lly="0" urx="183" ury="523"/> + <char name="e" width="556" llx="40" lly="-15" urx="516" ury="538"/> + <char name="eacute" width="556" llx="40" lly="-15" urx="516" ury="734"/> + <char name="ecircumflex" width="556" llx="40" lly="-15" urx="516" ury="734"/> + <char name="edieresis" width="556" llx="40" lly="-15" urx="516" ury="706"/> + <char name="egrave" width="556" llx="40" lly="-15" urx="516" ury="734"/> + <char name="eight" width="556" llx="38" lly="-19" urx="517" ury="703"/> + <char name="ellipsis" width="1000" llx="115" lly="0" urx="885" ury="106"/> + <char name="emdash" width="1000" llx="0" lly="240" urx="1000" ury="313"/> + <char name="endash" width="556" llx="0" lly="240" urx="556" ury="313"/> + <char name="equal" width="584" llx="39" lly="115" urx="545" ury="390"/> + <char name="eth" width="556" llx="35" lly="-15" urx="522" ury="737"/> + <char name="exclam" width="278" llx="90" lly="0" urx="187" ury="718"/> + <char name="exclamdown" width="333" llx="118" lly="-195" urx="215" ury="523"/> + <char name="f" width="278" llx="14" lly="0" urx="262" ury="728"/> + <char name="fi" width="500" llx="14" lly="0" urx="434" ury="728"/> + <char name="five" width="556" llx="32" lly="-19" urx="514" ury="688"/> + <char name="fl" width="500" llx="14" lly="0" urx="432" ury="728"/> + <char name="florin" width="556" llx="-11" lly="-207" urx="501" ury="737"/> + <char name="four" width="556" llx="25" lly="0" urx="523" ury="703"/> + <char name="fraction" width="167" llx="-166" lly="-19" urx="333" ury="703"/> + <char name="g" width="556" llx="40" lly="-220" urx="499" ury="538"/> + <char name="germandbls" width="611" llx="67" lly="-15" urx="571" ury="728"/> + <char name="grave" width="333" llx="14" lly="593" urx="211" ury="734"/> + <char name="greater" width="584" llx="48" lly="11" urx="536" ury="495"/> + <char name="guillemotleft" width="556" llx="97" lly="108" urx="459" ury="446"/> + <char name="guillemotright" width="556" llx="97" lly="108" urx="459" ury="446"/> + <char name="guilsinglleft" width="333" llx="88" lly="108" urx="245" ury="446"/> + <char name="guilsinglright" width="333" llx="88" lly="108" urx="245" ury="446"/> + <char name="h" width="556" llx="65" lly="0" urx="491" ury="718"/> + <char name="hungarumlaut" width="333" llx="31" lly="593" urx="409" ury="734"/> + <char name="hyphen" width="333" llx="44" lly="232" urx="289" ury="322"/> + <char name="i" width="222" llx="67" lly="0" urx="155" ury="718"/> + <char name="iacute" width="278" llx="95" lly="0" urx="292" ury="734"/> + <char name="icircumflex" width="278" llx="-6" lly="0" urx="285" ury="734"/> + <char name="idieresis" width="278" llx="13" lly="0" urx="266" ury="706"/> + <char name="igrave" width="278" llx="-13" lly="0" urx="184" ury="734"/> + <char name="j" width="222" llx="-16" lly="-210" urx="155" ury="718"/> + <char name="k" width="500" llx="67" lly="0" urx="501" ury="718"/> + <char name="l" width="222" llx="67" lly="0" urx="155" ury="718"/> + <char name="less" width="584" llx="48" lly="11" urx="536" ury="495"/> + <char name="logicalnot" width="584" llx="39" lly="108" urx="545" ury="390"/> + <char name="lslash" width="222" llx="-20" lly="0" urx="242" ury="718"/> + <char name="m" width="833" llx="65" lly="0" urx="769" ury="538"/> + <char name="macron" width="333" llx="10" lly="627" urx="323" ury="684"/> + <char name="minus" width="324" llx="39" lly="216" urx="545" ury="289"/> + <char name="mu" width="556" llx="68" lly="-207" urx="489" ury="523"/> + <char name="multiply" width="584" llx="39" lly="0" urx="545" ury="506"/> + <char name="n" width="556" llx="65" lly="0" urx="491" ury="538"/> + <char name="nine" width="556" llx="42" lly="-19" urx="514" ury="703"/> + <char name="ntilde" width="556" llx="65" lly="0" urx="491" ury="722"/> + <char name="numbersign" width="556" llx="28" lly="0" urx="529" ury="688"/> + <char name="o" width="556" llx="35" lly="-14" urx="521" ury="538"/> + <char name="oacute" width="556" llx="35" lly="-14" urx="521" ury="734"/> + <char name="ocircumflex" width="556" llx="35" lly="-14" urx="521" ury="734"/> + <char name="odieresis" width="556" llx="35" lly="-14" urx="521" ury="706"/> + <char name="oe" width="944" llx="35" lly="-15" urx="902" ury="538"/> + <char name="ogonek" width="333" llx="73" lly="-225" urx="287" ury="0"/> + <char name="ograve" width="556" llx="35" lly="-14" urx="521" ury="734"/> + <char name="one" width="556" llx="101" lly="0" urx="359" ury="703"/> + <char name="onehalf" width="834" llx="43" lly="-19" urx="773" ury="703"/> + <char name="onequarter" width="834" llx="73" lly="-19" urx="756" ury="703"/> + <char name="onesuperior" width="333" llx="43" lly="281" urx="222" ury="703"/> + <char name="ordfeminine" width="370" llx="24" lly="405" urx="346" ury="737"/> + <char name="ordmasculine" width="365" llx="25" lly="405" urx="341" ury="737"/> + <char name="oslash" width="611" llx="28" lly="-22" urx="537" ury="545"/> + <char name="otilde" width="556" llx="35" lly="-14" urx="521" ury="722"/> + <char name="p" width="556" llx="58" lly="-207" urx="517" ury="538"/> + <char name="paragraph" width="537" llx="18" lly="-173" urx="497" ury="718"/> + <char name="parenleft" width="333" llx="68" lly="-207" urx="299" ury="733"/> + <char name="parenright" width="333" llx="34" lly="-207" urx="265" ury="733"/> + <char name="percent" width="889" llx="39" lly="-19" urx="850" ury="703"/> + <char name="period" width="278" llx="87" lly="0" urx="191" ury="106"/> + <char name="periodcentered" width="278" llx="77" lly="190" urx="202" ury="315"/> + <char name="perthousand" width="1000" llx="7" lly="-19" urx="994" ury="703"/> + <char name="plus" width="584" llx="39" lly="0" urx="545" ury="505"/> + <char name="plusminus" width="584" llx="39" lly="0" urx="545" ury="506"/> + <char name="q" width="556" llx="35" lly="-207" urx="494" ury="538"/> + <char name="question" width="556" llx="56" lly="0" urx="492" ury="727"/> + <char name="questiondown" width="611" llx="91" lly="-201" urx="527" ury="525"/> + <char name="quotedbl" width="355" llx="70" lly="463" urx="285" ury="718"/> + <char name="quotedblbase" width="333" llx="26" lly="-149" urx="295" ury="106"/> + <char name="quotedblleft" width="333" llx="38" lly="470" urx="307" ury="725"/> + <char name="quotedblright" width="333" llx="26" lly="463" urx="295" ury="718"/> + <char name="quoteleft" width="222" llx="65" lly="470" urx="169" ury="725"/> + <char name="quoteright" width="222" llx="53" lly="463" urx="157" ury="718"/> + <char name="quotesinglbase" width="222" llx="53" lly="-149" urx="157" ury="106"/> + <char name="quotesingle" width="191" llx="59" lly="463" urx="132" ury="718"/> + <char name="r" width="333" llx="77" lly="0" urx="332" ury="538"/> + <char name="registered" width="737" llx="-14" lly="-19" urx="752" ury="737"/> + <char name="ring" width="333" llx="75" lly="572" urx="259" ury="756"/> + <char name="s" width="500" llx="32" lly="-15" urx="464" ury="538"/> + <char name="scaron" width="500" llx="32" lly="-15" urx="464" ury="734"/> + <char name="section" width="556" llx="43" lly="-191" urx="512" ury="737"/> + <char name="semicolon" width="278" llx="87" lly="-147" urx="191" ury="516"/> + <char name="seven" width="556" llx="37" lly="0" urx="523" ury="688"/> + <char name="six" width="556" llx="38" lly="-19" urx="518" ury="703"/> + <char name="slash" width="278" llx="-17" lly="-19" urx="295" ury="737"/> + <char name="space" width="278" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="278"/> - <char name="sterling" width="556"/> - <char name="t" width="278"/> - <char name="thorn" width="556"/> - <char name="three" width="556"/> - <char name="threequarters" width="834"/> - <char name="threesuperior" width="333"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="556"/> - <char name="twosuperior" width="333"/> - <char name="u" width="556"/> - <char name="uacute" width="556"/> - <char name="ucircumflex" width="556"/> - <char name="udieresis" width="556"/> - <char name="ugrave" width="556"/> - <char name="underscore" width="556"/> - <char name="v" width="500"/> - <char name="w" width="722"/> - <char name="x" width="500"/> - <char name="y" width="500"/> - <char name="yacute" width="500"/> - <char name="ydieresis" width="500"/> - <char name="yen" width="556"/> - <char name="z" width="500"/> - <char name="zcaron" width="500"/> - <char name="zero" width="556"/> - </widths> + <char name="sterling" width="556" llx="33" lly="-16" urx="539" ury="718"/> + <char name="t" width="278" llx="14" lly="-7" urx="257" ury="669"/> + <char name="thorn" width="556" llx="58" lly="-207" urx="517" ury="718"/> + <char name="three" width="556" llx="34" lly="-19" urx="522" ury="703"/> + <char name="threequarters" width="834" llx="45" lly="-19" urx="810" ury="703"/> + <char name="threesuperior" width="333" llx="5" lly="270" urx="325" ury="703"/> + <char name="tilde" width="333" llx="-4" lly="606" urx="337" ury="722"/> + <char name="trademark" width="1000" llx="46" lly="306" urx="903" ury="718"/> + <char name="two" width="556" llx="26" lly="0" urx="507" ury="703"/> + <char name="twosuperior" width="333" llx="4" lly="281" urx="323" ury="703"/> + <char name="u" width="556" llx="68" lly="-15" urx="489" ury="523"/> + <char name="uacute" width="556" llx="68" lly="-15" urx="489" ury="734"/> + <char name="ucircumflex" width="556" llx="68" lly="-15" urx="489" ury="734"/> + <char name="udieresis" width="556" llx="68" lly="-15" urx="489" ury="706"/> + <char name="ugrave" width="556" llx="68" lly="-15" urx="489" ury="734"/> + <char name="underscore" width="556" llx="0" lly="-125" urx="556" ury="-75"/> + <char name="v" width="500" llx="8" lly="0" urx="492" ury="523"/> + <char name="w" width="722" llx="14" lly="0" urx="709" ury="523"/> + <char name="x" width="500" llx="11" lly="0" urx="490" ury="523"/> + <char name="y" width="500" llx="11" lly="-214" urx="489" ury="523"/> + <char name="yacute" width="500" llx="11" lly="-214" urx="489" ury="734"/> + <char name="ydieresis" width="500" llx="11" lly="-214" urx="489" ury="706"/> + <char name="yen" width="556" llx="3" lly="0" urx="553" ury="688"/> + <char name="z" width="500" llx="31" lly="0" urx="469" ury="523"/> + <char name="zcaron" width="500" llx="31" lly="0" urx="469" ury="734"/> + <char name="zero" width="556" llx="37" lly="-19" urx="519" ury="703"/> + </char-metrics> <kerning kpx1="107"> <pair kern="-20" kpx2="111"/> <pair kern="-20" kpx2="101"/> diff --git a/src/codegen/fonts/HelveticaBold.xml b/src/codegen/fonts/HelveticaBold.xml index 2620a128e..4efd01f22 100644 --- a/src/codegen/fonts/HelveticaBold.xml +++ b/src/codegen/fonts/HelveticaBold.xml @@ -22,245 +22,246 @@ <family-name>Helvetica</family-name> <class-name>HelveticaBold</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>718</cap-height> <x-height>532</x-height> <ascender>718</ascender> <descender>-207</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="722"/> - <char name="AE" width="1000"/> - <char name="Aacute" width="722"/> - <char name="Acircumflex" width="722"/> - <char name="Adieresis" width="722"/> - <char name="Agrave" width="722"/> - <char name="Aring" width="722"/> - <char name="Atilde" width="722"/> - <char name="B" width="722"/> - <char name="C" width="722"/> - <char name="Ccedilla" width="722"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="556"/> - <char name="F" width="611"/> - <char name="G" width="778"/> - <char name="H" width="722"/> - <char name="I" width="278"/> - <char name="Iacute" width="278"/> - <char name="Icircumflex" width="278"/> - <char name="Idieresis" width="278"/> - <char name="Igrave" width="278"/> - <char name="J" width="556"/> - <char name="K" width="722"/> - <char name="L" width="611"/> - <char name="Lslash" width="611"/> - <char name="M" width="833"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="778"/> - <char name="OE" width="1000"/> - <char name="Oacute" width="778"/> - <char name="Ocircumflex" width="778"/> - <char name="Odieresis" width="778"/> - <char name="Ograve" width="778"/> - <char name="Oslash" width="778"/> - <char name="Otilde" width="778"/> - <char name="P" width="667"/> - <char name="Q" width="778"/> - <char name="R" width="722"/> - <char name="S" width="667"/> - <char name="Scaron" width="667"/> - <char name="T" width="611"/> - <char name="Thorn" width="667"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="667"/> - <char name="W" width="944"/> - <char name="X" width="667"/> - <char name="Y" width="667"/> - <char name="Yacute" width="667"/> - <char name="Ydieresis" width="667"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="556"/> - <char name="aacute" width="556"/> - <char name="acircumflex" width="556"/> - <char name="acute" width="333"/> - <char name="adieresis" width="556"/> - <char name="ae" width="889"/> - <char name="agrave" width="556"/> - <char name="ampersand" width="722"/> - <char name="aring" width="556"/> - <char name="asciicircum" width="584"/> - <char name="asciitilde" width="584"/> - <char name="asterisk" width="389"/> - <char name="at" width="975"/> - <char name="atilde" width="556"/> - <char name="b" width="611"/> - <char name="backslash" width="278"/> - <char name="bar" width="280"/> - <char name="braceleft" width="389"/> - <char name="braceright" width="389"/> - <char name="bracketleft" width="333"/> - <char name="bracketright" width="333"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="280"/> - <char name="bullet" width="350"/> - <char name="c" width="556"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="556"/> - <char name="cedilla" width="333"/> - <char name="cent" width="556"/> - <char name="circumflex" width="333"/> - <char name="colon" width="333"/> - <char name="comma" width="278"/> - <char name="copyright" width="737"/> - <char name="currency" width="556"/> - <char name="d" width="611"/> - <char name="dagger" width="556"/> - <char name="daggerdbl" width="556"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="584"/> - <char name="dollar" width="556"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="556"/> - <char name="eacute" width="556"/> - <char name="ecircumflex" width="556"/> - <char name="edieresis" width="556"/> - <char name="egrave" width="556"/> - <char name="eight" width="556"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="556"/> - <char name="equal" width="584"/> - <char name="eth" width="611"/> - <char name="exclam" width="333"/> - <char name="exclamdown" width="333"/> - <char name="f" width="333"/> - <char name="fi" width="611"/> - <char name="five" width="556"/> - <char name="fl" width="611"/> - <char name="florin" width="556"/> - <char name="four" width="556"/> - <char name="fraction" width="167"/> - <char name="g" width="611"/> - <char name="germandbls" width="611"/> - <char name="grave" width="333"/> - <char name="greater" width="584"/> - <char name="guillemotleft" width="556"/> - <char name="guillemotright" width="556"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="611"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="278"/> - <char name="k" width="556"/> - <char name="l" width="278"/> - <char name="less" width="584"/> - <char name="logicalnot" width="584"/> - <char name="lslash" width="278"/> - <char name="m" width="889"/> - <char name="macron" width="333"/> - <char name="minus" width="324"/> - <char name="mu" width="611"/> - <char name="multiply" width="584"/> - <char name="n" width="611"/> - <char name="nine" width="556"/> - <char name="ntilde" width="611"/> - <char name="numbersign" width="556"/> - <char name="o" width="611"/> - <char name="oacute" width="611"/> - <char name="ocircumflex" width="611"/> - <char name="odieresis" width="611"/> - <char name="oe" width="944"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="611"/> - <char name="one" width="556"/> - <char name="onehalf" width="834"/> - <char name="onequarter" width="834"/> - <char name="onesuperior" width="333"/> - <char name="ordfeminine" width="370"/> - <char name="ordmasculine" width="365"/> - <char name="oslash" width="611"/> - <char name="otilde" width="611"/> - <char name="p" width="611"/> - <char name="paragraph" width="556"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="889"/> - <char name="period" width="278"/> - <char name="periodcentered" width="278"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="584"/> - <char name="plusminus" width="584"/> - <char name="q" width="611"/> - <char name="question" width="611"/> - <char name="questiondown" width="611"/> - <char name="quotedbl" width="474"/> - <char name="quotedblbase" width="500"/> - <char name="quotedblleft" width="500"/> - <char name="quotedblright" width="500"/> - <char name="quoteleft" width="278"/> - <char name="quoteright" width="278"/> - <char name="quotesinglbase" width="278"/> - <char name="quotesingle" width="238"/> - <char name="r" width="389"/> - <char name="registered" width="737"/> - <char name="ring" width="333"/> - <char name="s" width="556"/> - <char name="scaron" width="556"/> - <char name="section" width="556"/> - <char name="semicolon" width="333"/> - <char name="seven" width="556"/> - <char name="six" width="556"/> - <char name="slash" width="278"/> - <char name="space" width="278"/> + <char-metrics> + <char name="A" width="722" llx="20" lly="0" urx="702" ury="718"/> + <char name="AE" width="1000" llx="5" lly="0" urx="954" ury="718"/> + <char name="Aacute" width="722" llx="20" lly="0" urx="702" ury="936"/> + <char name="Acircumflex" width="722" llx="20" lly="0" urx="702" ury="936"/> + <char name="Adieresis" width="722" llx="20" lly="0" urx="702" ury="915"/> + <char name="Agrave" width="722" llx="20" lly="0" urx="702" ury="936"/> + <char name="Aring" width="722" llx="20" lly="0" urx="702" ury="962"/> + <char name="Atilde" width="722" llx="20" lly="0" urx="702" ury="923"/> + <char name="B" width="722" llx="76" lly="0" urx="669" ury="718"/> + <char name="C" width="722" llx="44" lly="-19" urx="684" ury="737"/> + <char name="Ccedilla" width="722" llx="44" lly="-228" urx="684" ury="737"/> + <char name="D" width="722" llx="76" lly="0" urx="685" ury="718"/> + <char name="E" width="667" llx="76" lly="0" urx="621" ury="718"/> + <char name="Eacute" width="667" llx="76" lly="0" urx="621" ury="936"/> + <char name="Ecircumflex" width="667" llx="76" lly="0" urx="621" ury="936"/> + <char name="Edieresis" width="667" llx="76" lly="0" urx="621" ury="915"/> + <char name="Egrave" width="667" llx="76" lly="0" urx="621" ury="936"/> + <char name="Eth" width="722" llx="-5" lly="0" urx="685" ury="718"/> + <char name="Euro" width="556" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="76" lly="0" urx="587" ury="718"/> + <char name="G" width="778" llx="44" lly="-19" urx="713" ury="737"/> + <char name="H" width="722" llx="71" lly="0" urx="651" ury="718"/> + <char name="I" width="278" llx="64" lly="0" urx="214" ury="718"/> + <char name="Iacute" width="278" llx="64" lly="0" urx="329" ury="936"/> + <char name="Icircumflex" width="278" llx="-37" lly="0" urx="316" ury="936"/> + <char name="Idieresis" width="278" llx="-21" lly="0" urx="300" ury="915"/> + <char name="Igrave" width="278" llx="-50" lly="0" urx="214" ury="936"/> + <char name="J" width="556" llx="22" lly="-18" urx="484" ury="718"/> + <char name="K" width="722" llx="87" lly="0" urx="722" ury="718"/> + <char name="L" width="611" llx="76" lly="0" urx="583" ury="718"/> + <char name="Lslash" width="611" llx="-20" lly="0" urx="583" ury="718"/> + <char name="M" width="833" llx="69" lly="0" urx="765" ury="718"/> + <char name="N" width="722" llx="69" lly="0" urx="654" ury="718"/> + <char name="Ntilde" width="722" llx="69" lly="0" urx="654" ury="923"/> + <char name="O" width="778" llx="44" lly="-19" urx="734" ury="737"/> + <char name="OE" width="1000" llx="37" lly="-19" urx="961" ury="737"/> + <char name="Oacute" width="778" llx="44" lly="-19" urx="734" ury="936"/> + <char name="Ocircumflex" width="778" llx="44" lly="-19" urx="734" ury="936"/> + <char name="Odieresis" width="778" llx="44" lly="-19" urx="734" ury="915"/> + <char name="Ograve" width="778" llx="44" lly="-19" urx="734" ury="936"/> + <char name="Oslash" width="778" llx="33" lly="-27" urx="744" ury="745"/> + <char name="Otilde" width="778" llx="44" lly="-19" urx="734" ury="923"/> + <char name="P" width="667" llx="76" lly="0" urx="627" ury="718"/> + <char name="Q" width="778" llx="44" lly="-52" urx="737" ury="737"/> + <char name="R" width="722" llx="76" lly="0" urx="677" ury="718"/> + <char name="S" width="667" llx="39" lly="-19" urx="629" ury="737"/> + <char name="Scaron" width="667" llx="39" lly="-19" urx="629" ury="936"/> + <char name="T" width="611" llx="14" lly="0" urx="598" ury="718"/> + <char name="Thorn" width="667" llx="76" lly="0" urx="627" ury="718"/> + <char name="U" width="722" llx="72" lly="-19" urx="651" ury="718"/> + <char name="Uacute" width="722" llx="72" lly="-19" urx="651" ury="936"/> + <char name="Ucircumflex" width="722" llx="72" lly="-19" urx="651" ury="936"/> + <char name="Udieresis" width="722" llx="72" lly="-19" urx="651" ury="915"/> + <char name="Ugrave" width="722" llx="72" lly="-19" urx="651" ury="936"/> + <char name="V" width="667" llx="19" lly="0" urx="648" ury="718"/> + <char name="W" width="944" llx="16" lly="0" urx="929" ury="718"/> + <char name="X" width="667" llx="14" lly="0" urx="653" ury="718"/> + <char name="Y" width="667" llx="15" lly="0" urx="653" ury="718"/> + <char name="Yacute" width="667" llx="15" lly="0" urx="653" ury="936"/> + <char name="Ydieresis" width="667" llx="15" lly="0" urx="653" ury="915"/> + <char name="Z" width="611" llx="25" lly="0" urx="586" ury="718"/> + <char name="Zcaron" width="611" llx="25" lly="0" urx="586" ury="936"/> + <char name="a" width="556" llx="29" lly="-14" urx="527" ury="546"/> + <char name="aacute" width="556" llx="29" lly="-14" urx="527" ury="750"/> + <char name="acircumflex" width="556" llx="29" lly="-14" urx="527" ury="750"/> + <char name="acute" width="333" llx="108" lly="604" urx="356" ury="750"/> + <char name="adieresis" width="556" llx="29" lly="-14" urx="527" ury="729"/> + <char name="ae" width="889" llx="29" lly="-14" urx="858" ury="546"/> + <char name="agrave" width="556" llx="29" lly="-14" urx="527" ury="750"/> + <char name="ampersand" width="722" llx="54" lly="-19" urx="701" ury="718"/> + <char name="aring" width="556" llx="29" lly="-14" urx="527" ury="776"/> + <char name="asciicircum" width="584" llx="62" lly="323" urx="522" ury="698"/> + <char name="asciitilde" width="584" llx="61" lly="163" urx="523" ury="343"/> + <char name="asterisk" width="389" llx="27" lly="387" urx="362" ury="718"/> + <char name="at" width="975" llx="118" lly="-19" urx="856" ury="737"/> + <char name="atilde" width="556" llx="29" lly="-14" urx="527" ury="737"/> + <char name="b" width="611" llx="61" lly="-14" urx="578" ury="718"/> + <char name="backslash" width="278" llx="-33" lly="-19" urx="311" ury="737"/> + <char name="bar" width="280" llx="84" lly="-225" urx="196" ury="775"/> + <char name="braceleft" width="389" llx="48" lly="-196" urx="365" ury="722"/> + <char name="braceright" width="389" llx="24" lly="-196" urx="341" ury="722"/> + <char name="bracketleft" width="333" llx="63" lly="-196" urx="309" ury="722"/> + <char name="bracketright" width="333" llx="24" lly="-196" urx="270" ury="722"/> + <char name="breve" width="333" llx="-2" lly="604" urx="335" ury="750"/> + <char name="brokenbar" width="280" llx="84" lly="-150" urx="196" ury="700"/> + <char name="bullet" width="350" llx="10" lly="194" urx="340" ury="524"/> + <char name="c" width="556" llx="34" lly="-14" urx="524" ury="546"/> + <char name="caron" width="333" llx="-10" lly="604" urx="343" ury="750"/> + <char name="ccedilla" width="556" llx="34" lly="-228" urx="524" ury="546"/> + <char name="cedilla" width="333" llx="6" lly="-228" urx="245" ury="0"/> + <char name="cent" width="556" llx="34" lly="-118" urx="524" ury="628"/> + <char name="circumflex" width="333" llx="-10" lly="604" urx="343" ury="750"/> + <char name="colon" width="333" llx="92" lly="0" urx="242" ury="512"/> + <char name="comma" width="278" llx="64" lly="-168" urx="214" ury="146"/> + <char name="copyright" width="737" llx="-11" lly="-19" urx="749" ury="737"/> + <char name="currency" width="556" llx="-3" lly="76" urx="559" ury="636"/> + <char name="d" width="611" llx="34" lly="-14" urx="551" ury="718"/> + <char name="dagger" width="556" llx="36" lly="-171" urx="520" ury="718"/> + <char name="daggerdbl" width="556" llx="36" lly="-171" urx="520" ury="718"/> + <char name="degree" width="400" llx="57" lly="426" urx="343" ury="712"/> + <char name="dieresis" width="333" llx="6" lly="614" urx="327" ury="729"/> + <char name="divide" width="584" llx="40" lly="-42" urx="544" ury="548"/> + <char name="dollar" width="556" llx="30" lly="-115" urx="523" ury="775"/> + <char name="dotaccent" width="333" llx="104" lly="614" urx="230" ury="729"/> + <char name="dotlessi" width="278" llx="69" lly="0" urx="209" ury="532"/> + <char name="e" width="556" llx="23" lly="-14" urx="528" ury="546"/> + <char name="eacute" width="556" llx="23" lly="-14" urx="528" ury="750"/> + <char name="ecircumflex" width="556" llx="23" lly="-14" urx="528" ury="750"/> + <char name="edieresis" width="556" llx="23" lly="-14" urx="528" ury="729"/> + <char name="egrave" width="556" llx="23" lly="-14" urx="528" ury="750"/> + <char name="eight" width="556" llx="32" lly="-19" urx="524" ury="710"/> + <char name="ellipsis" width="1000" llx="92" lly="0" urx="908" ury="146"/> + <char name="emdash" width="1000" llx="0" lly="227" urx="1000" ury="333"/> + <char name="endash" width="556" llx="0" lly="227" urx="556" ury="333"/> + <char name="equal" width="584" llx="40" lly="87" urx="544" ury="419"/> + <char name="eth" width="611" llx="34" lly="-14" urx="578" ury="737"/> + <char name="exclam" width="333" llx="90" lly="0" urx="244" ury="718"/> + <char name="exclamdown" width="333" llx="90" lly="-186" urx="244" ury="532"/> + <char name="f" width="333" llx="10" lly="0" urx="318" ury="727"/> + <char name="fi" width="611" llx="10" lly="0" urx="542" ury="727"/> + <char name="five" width="556" llx="27" lly="-19" urx="516" ury="698"/> + <char name="fl" width="611" llx="10" lly="0" urx="542" ury="727"/> + <char name="florin" width="556" llx="-10" lly="-210" urx="516" ury="737"/> + <char name="four" width="556" llx="27" lly="0" urx="526" ury="710"/> + <char name="fraction" width="167" llx="-170" lly="-19" urx="336" ury="710"/> + <char name="g" width="611" llx="40" lly="-217" urx="553" ury="546"/> + <char name="germandbls" width="611" llx="69" lly="-14" urx="579" ury="731"/> + <char name="grave" width="333" llx="-23" lly="604" urx="225" ury="750"/> + <char name="greater" width="584" llx="38" lly="-8" urx="546" ury="514"/> + <char name="guillemotleft" width="556" llx="88" lly="76" urx="468" ury="484"/> + <char name="guillemotright" width="556" llx="88" lly="76" urx="468" ury="484"/> + <char name="guilsinglleft" width="333" llx="83" lly="76" urx="250" ury="484"/> + <char name="guilsinglright" width="333" llx="83" lly="76" urx="250" ury="484"/> + <char name="h" width="611" llx="65" lly="0" urx="546" ury="718"/> + <char name="hungarumlaut" width="333" llx="9" lly="604" urx="486" ury="750"/> + <char name="hyphen" width="333" llx="27" lly="215" urx="306" ury="345"/> + <char name="i" width="278" llx="69" lly="0" urx="209" ury="725"/> + <char name="iacute" width="278" llx="69" lly="0" urx="329" ury="750"/> + <char name="icircumflex" width="278" llx="-37" lly="0" urx="316" ury="750"/> + <char name="idieresis" width="278" llx="-21" lly="0" urx="300" ury="729"/> + <char name="igrave" width="278" llx="-50" lly="0" urx="209" ury="750"/> + <char name="j" width="278" llx="3" lly="-214" urx="209" ury="725"/> + <char name="k" width="556" llx="69" lly="0" urx="562" ury="718"/> + <char name="l" width="278" llx="69" lly="0" urx="209" ury="718"/> + <char name="less" width="584" llx="38" lly="-8" urx="546" ury="514"/> + <char name="logicalnot" width="584" llx="40" lly="108" urx="544" ury="419"/> + <char name="lslash" width="278" llx="-18" lly="0" urx="296" ury="718"/> + <char name="m" width="889" llx="64" lly="0" urx="826" ury="546"/> + <char name="macron" width="333" llx="-6" lly="604" urx="339" ury="678"/> + <char name="minus" width="324" llx="40" lly="197" urx="544" ury="309"/> + <char name="mu" width="611" llx="66" lly="-207" urx="545" ury="532"/> + <char name="multiply" width="584" llx="40" lly="1" urx="545" ury="505"/> + <char name="n" width="611" llx="65" lly="0" urx="546" ury="546"/> + <char name="nine" width="556" llx="30" lly="-19" urx="522" ury="710"/> + <char name="ntilde" width="611" llx="65" lly="0" urx="546" ury="737"/> + <char name="numbersign" width="556" llx="18" lly="0" urx="538" ury="698"/> + <char name="o" width="611" llx="34" lly="-14" urx="578" ury="546"/> + <char name="oacute" width="611" llx="34" lly="-14" urx="578" ury="750"/> + <char name="ocircumflex" width="611" llx="34" lly="-14" urx="578" ury="750"/> + <char name="odieresis" width="611" llx="34" lly="-14" urx="578" ury="729"/> + <char name="oe" width="944" llx="34" lly="-14" urx="912" ury="546"/> + <char name="ogonek" width="333" llx="71" lly="-228" urx="304" ury="0"/> + <char name="ograve" width="611" llx="34" lly="-14" urx="578" ury="750"/> + <char name="one" width="556" llx="69" lly="0" urx="378" ury="710"/> + <char name="onehalf" width="834" llx="26" lly="-19" urx="794" ury="710"/> + <char name="onequarter" width="834" llx="26" lly="-19" urx="766" ury="710"/> + <char name="onesuperior" width="333" llx="26" lly="283" urx="237" ury="710"/> + <char name="ordfeminine" width="370" llx="22" lly="401" urx="347" ury="737"/> + <char name="ordmasculine" width="365" llx="6" lly="401" urx="360" ury="737"/> + <char name="oslash" width="611" llx="22" lly="-29" urx="589" ury="560"/> + <char name="otilde" width="611" llx="34" lly="-14" urx="578" ury="737"/> + <char name="p" width="611" llx="62" lly="-207" urx="578" ury="546"/> + <char name="paragraph" width="556" llx="-8" lly="-191" urx="539" ury="700"/> + <char name="parenleft" width="333" llx="35" lly="-208" urx="314" ury="734"/> + <char name="parenright" width="333" llx="19" lly="-208" urx="298" ury="734"/> + <char name="percent" width="889" llx="28" lly="-19" urx="861" ury="710"/> + <char name="period" width="278" llx="64" lly="0" urx="214" ury="146"/> + <char name="periodcentered" width="278" llx="58" lly="172" urx="220" ury="334"/> + <char name="perthousand" width="1000" llx="-3" lly="-19" urx="1003" ury="710"/> + <char name="plus" width="584" llx="40" lly="0" urx="544" ury="506"/> + <char name="plusminus" width="584" llx="40" lly="0" urx="544" ury="506"/> + <char name="q" width="611" llx="34" lly="-207" urx="552" ury="546"/> + <char name="question" width="611" llx="60" lly="0" urx="556" ury="727"/> + <char name="questiondown" width="611" llx="55" lly="-195" urx="551" ury="532"/> + <char name="quotedbl" width="474" llx="98" lly="447" urx="376" ury="718"/> + <char name="quotedblbase" width="500" llx="64" lly="-146" urx="436" ury="127"/> + <char name="quotedblleft" width="500" llx="64" lly="454" urx="436" ury="727"/> + <char name="quotedblright" width="500" llx="64" lly="445" urx="436" ury="718"/> + <char name="quoteleft" width="278" llx="69" lly="454" urx="209" ury="727"/> + <char name="quoteright" width="278" llx="69" lly="445" urx="209" ury="718"/> + <char name="quotesinglbase" width="278" llx="69" lly="-146" urx="209" ury="127"/> + <char name="quotesingle" width="238" llx="70" lly="447" urx="168" ury="718"/> + <char name="r" width="389" llx="64" lly="0" urx="373" ury="546"/> + <char name="registered" width="737" llx="-11" lly="-19" urx="748" ury="737"/> + <char name="ring" width="333" llx="59" lly="568" urx="275" ury="776"/> + <char name="s" width="556" llx="30" lly="-14" urx="519" ury="546"/> + <char name="scaron" width="556" llx="30" lly="-14" urx="519" ury="750"/> + <char name="section" width="556" llx="34" lly="-184" urx="522" ury="727"/> + <char name="semicolon" width="333" llx="92" lly="-168" urx="242" ury="512"/> + <char name="seven" width="556" llx="25" lly="0" urx="528" ury="698"/> + <char name="six" width="556" llx="31" lly="-19" urx="520" ury="710"/> + <char name="slash" width="278" llx="-33" lly="-19" urx="311" ury="737"/> + <char name="space" width="278" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="278"/> - <char name="sterling" width="556"/> - <char name="t" width="333"/> - <char name="thorn" width="611"/> - <char name="three" width="556"/> - <char name="threequarters" width="834"/> - <char name="threesuperior" width="333"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="556"/> - <char name="twosuperior" width="333"/> - <char name="u" width="611"/> - <char name="uacute" width="611"/> - <char name="ucircumflex" width="611"/> - <char name="udieresis" width="611"/> - <char name="ugrave" width="611"/> - <char name="underscore" width="556"/> - <char name="v" width="556"/> - <char name="w" width="778"/> - <char name="x" width="556"/> - <char name="y" width="556"/> - <char name="yacute" width="556"/> - <char name="ydieresis" width="556"/> - <char name="yen" width="556"/> - <char name="z" width="500"/> - <char name="zcaron" width="500"/> - <char name="zero" width="556"/> - </widths> + <char name="sterling" width="556" llx="28" lly="-16" urx="541" ury="718"/> + <char name="t" width="333" llx="10" lly="-6" urx="309" ury="676"/> + <char name="thorn" width="611" llx="62" lly="-208" urx="578" ury="718"/> + <char name="three" width="556" llx="27" lly="-19" urx="516" ury="710"/> + <char name="threequarters" width="834" llx="16" lly="-19" urx="799" ury="710"/> + <char name="threesuperior" width="333" llx="8" lly="271" urx="326" ury="710"/> + <char name="tilde" width="333" llx="-17" lly="610" urx="350" ury="737"/> + <char name="trademark" width="1000" llx="44" lly="306" urx="956" ury="718"/> + <char name="two" width="556" llx="26" lly="0" urx="511" ury="710"/> + <char name="twosuperior" width="333" llx="9" lly="283" urx="324" ury="710"/> + <char name="u" width="611" llx="66" lly="-14" urx="545" ury="532"/> + <char name="uacute" width="611" llx="66" lly="-14" urx="545" ury="750"/> + <char name="ucircumflex" width="611" llx="66" lly="-14" urx="545" ury="750"/> + <char name="udieresis" width="611" llx="66" lly="-14" urx="545" ury="729"/> + <char name="ugrave" width="611" llx="66" lly="-14" urx="545" ury="750"/> + <char name="underscore" width="556" llx="0" lly="-125" urx="556" ury="-75"/> + <char name="v" width="556" llx="13" lly="0" urx="543" ury="532"/> + <char name="w" width="778" llx="10" lly="0" urx="769" ury="532"/> + <char name="x" width="556" llx="15" lly="0" urx="541" ury="532"/> + <char name="y" width="556" llx="10" lly="-214" urx="539" ury="532"/> + <char name="yacute" width="556" llx="10" lly="-214" urx="539" ury="750"/> + <char name="ydieresis" width="556" llx="10" lly="-214" urx="539" ury="729"/> + <char name="yen" width="556" llx="-9" lly="0" urx="565" ury="698"/> + <char name="z" width="500" llx="20" lly="0" urx="480" ury="532"/> + <char name="zcaron" width="500" llx="20" lly="0" urx="480" ury="750"/> + <char name="zero" width="556" llx="32" lly="-19" urx="524" ury="710"/> + </char-metrics> <kerning kpx1="107"> <pair kern="-15" kpx2="111"/> </kerning> diff --git a/src/codegen/fonts/HelveticaBoldOblique.xml b/src/codegen/fonts/HelveticaBoldOblique.xml index c11e0ba18..e1d0fd294 100644 --- a/src/codegen/fonts/HelveticaBoldOblique.xml +++ b/src/codegen/fonts/HelveticaBoldOblique.xml @@ -22,245 +22,246 @@ <family-name>Helvetica</family-name> <class-name>HelveticaBoldOblique</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>718</cap-height> <x-height>532</x-height> <ascender>718</ascender> <descender>-207</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="722"/> - <char name="AE" width="1000"/> - <char name="Aacute" width="722"/> - <char name="Acircumflex" width="722"/> - <char name="Adieresis" width="722"/> - <char name="Agrave" width="722"/> - <char name="Aring" width="722"/> - <char name="Atilde" width="722"/> - <char name="B" width="722"/> - <char name="C" width="722"/> - <char name="Ccedilla" width="722"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="556"/> - <char name="F" width="611"/> - <char name="G" width="778"/> - <char name="H" width="722"/> - <char name="I" width="278"/> - <char name="Iacute" width="278"/> - <char name="Icircumflex" width="278"/> - <char name="Idieresis" width="278"/> - <char name="Igrave" width="278"/> - <char name="J" width="556"/> - <char name="K" width="722"/> - <char name="L" width="611"/> - <char name="Lslash" width="611"/> - <char name="M" width="833"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="778"/> - <char name="OE" width="1000"/> - <char name="Oacute" width="778"/> - <char name="Ocircumflex" width="778"/> - <char name="Odieresis" width="778"/> - <char name="Ograve" width="778"/> - <char name="Oslash" width="778"/> - <char name="Otilde" width="778"/> - <char name="P" width="667"/> - <char name="Q" width="778"/> - <char name="R" width="722"/> - <char name="S" width="667"/> - <char name="Scaron" width="667"/> - <char name="T" width="611"/> - <char name="Thorn" width="667"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="667"/> - <char name="W" width="944"/> - <char name="X" width="667"/> - <char name="Y" width="667"/> - <char name="Yacute" width="667"/> - <char name="Ydieresis" width="667"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="556"/> - <char name="aacute" width="556"/> - <char name="acircumflex" width="556"/> - <char name="acute" width="333"/> - <char name="adieresis" width="556"/> - <char name="ae" width="889"/> - <char name="agrave" width="556"/> - <char name="ampersand" width="722"/> - <char name="aring" width="556"/> - <char name="asciicircum" width="584"/> - <char name="asciitilde" width="584"/> - <char name="asterisk" width="389"/> - <char name="at" width="975"/> - <char name="atilde" width="556"/> - <char name="b" width="611"/> - <char name="backslash" width="278"/> - <char name="bar" width="280"/> - <char name="braceleft" width="389"/> - <char name="braceright" width="389"/> - <char name="bracketleft" width="333"/> - <char name="bracketright" width="333"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="280"/> - <char name="bullet" width="350"/> - <char name="c" width="556"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="556"/> - <char name="cedilla" width="333"/> - <char name="cent" width="556"/> - <char name="circumflex" width="333"/> - <char name="colon" width="333"/> - <char name="comma" width="278"/> - <char name="copyright" width="737"/> - <char name="currency" width="556"/> - <char name="d" width="611"/> - <char name="dagger" width="556"/> - <char name="daggerdbl" width="556"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="584"/> - <char name="dollar" width="556"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="556"/> - <char name="eacute" width="556"/> - <char name="ecircumflex" width="556"/> - <char name="edieresis" width="556"/> - <char name="egrave" width="556"/> - <char name="eight" width="556"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="556"/> - <char name="equal" width="584"/> - <char name="eth" width="611"/> - <char name="exclam" width="333"/> - <char name="exclamdown" width="333"/> - <char name="f" width="333"/> - <char name="fi" width="611"/> - <char name="five" width="556"/> - <char name="fl" width="611"/> - <char name="florin" width="556"/> - <char name="four" width="556"/> - <char name="fraction" width="167"/> - <char name="g" width="611"/> - <char name="germandbls" width="611"/> - <char name="grave" width="333"/> - <char name="greater" width="584"/> - <char name="guillemotleft" width="556"/> - <char name="guillemotright" width="556"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="611"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="278"/> - <char name="k" width="556"/> - <char name="l" width="278"/> - <char name="less" width="584"/> - <char name="logicalnot" width="584"/> - <char name="lslash" width="278"/> - <char name="m" width="889"/> - <char name="macron" width="333"/> - <char name="minus" width="324"/> - <char name="mu" width="611"/> - <char name="multiply" width="584"/> - <char name="n" width="611"/> - <char name="nine" width="556"/> - <char name="ntilde" width="611"/> - <char name="numbersign" width="556"/> - <char name="o" width="611"/> - <char name="oacute" width="611"/> - <char name="ocircumflex" width="611"/> - <char name="odieresis" width="611"/> - <char name="oe" width="944"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="611"/> - <char name="one" width="556"/> - <char name="onehalf" width="834"/> - <char name="onequarter" width="834"/> - <char name="onesuperior" width="333"/> - <char name="ordfeminine" width="370"/> - <char name="ordmasculine" width="365"/> - <char name="oslash" width="611"/> - <char name="otilde" width="611"/> - <char name="p" width="611"/> - <char name="paragraph" width="556"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="889"/> - <char name="period" width="278"/> - <char name="periodcentered" width="278"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="584"/> - <char name="plusminus" width="584"/> - <char name="q" width="611"/> - <char name="question" width="611"/> - <char name="questiondown" width="611"/> - <char name="quotedbl" width="474"/> - <char name="quotedblbase" width="500"/> - <char name="quotedblleft" width="500"/> - <char name="quotedblright" width="500"/> - <char name="quoteleft" width="278"/> - <char name="quoteright" width="278"/> - <char name="quotesinglbase" width="278"/> - <char name="quotesingle" width="238"/> - <char name="r" width="389"/> - <char name="registered" width="737"/> - <char name="ring" width="333"/> - <char name="s" width="556"/> - <char name="scaron" width="556"/> - <char name="section" width="556"/> - <char name="semicolon" width="333"/> - <char name="seven" width="556"/> - <char name="six" width="556"/> - <char name="slash" width="278"/> - <char name="space" width="278"/> + <char-metrics> + <char name="A" width="722" llx="20" lly="0" urx="702" ury="718"/> + <char name="AE" width="1000" llx="5" lly="0" urx="1100" ury="718"/> + <char name="Aacute" width="722" llx="20" lly="0" urx="750" ury="936"/> + <char name="Acircumflex" width="722" llx="20" lly="0" urx="706" ury="936"/> + <char name="Adieresis" width="722" llx="20" lly="0" urx="716" ury="915"/> + <char name="Agrave" width="722" llx="20" lly="0" urx="702" ury="936"/> + <char name="Aring" width="722" llx="20" lly="0" urx="702" ury="962"/> + <char name="Atilde" width="722" llx="20" lly="0" urx="741" ury="923"/> + <char name="B" width="722" llx="76" lly="0" urx="764" ury="718"/> + <char name="C" width="722" llx="107" lly="-19" urx="789" ury="737"/> + <char name="Ccedilla" width="722" llx="107" lly="-228" urx="789" ury="737"/> + <char name="D" width="722" llx="76" lly="0" urx="777" ury="718"/> + <char name="E" width="667" llx="76" lly="0" urx="757" ury="718"/> + <char name="Eacute" width="667" llx="76" lly="0" urx="757" ury="936"/> + <char name="Ecircumflex" width="667" llx="76" lly="0" urx="757" ury="936"/> + <char name="Edieresis" width="667" llx="76" lly="0" urx="757" ury="915"/> + <char name="Egrave" width="667" llx="76" lly="0" urx="757" ury="936"/> + <char name="Eth" width="722" llx="62" lly="0" urx="777" ury="718"/> + <char name="Euro" width="556" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="76" lly="0" urx="740" ury="718"/> + <char name="G" width="778" llx="108" lly="-19" urx="817" ury="737"/> + <char name="H" width="722" llx="71" lly="0" urx="804" ury="718"/> + <char name="I" width="278" llx="64" lly="0" urx="367" ury="718"/> + <char name="Iacute" width="278" llx="64" lly="0" urx="528" ury="936"/> + <char name="Icircumflex" width="278" llx="64" lly="0" urx="484" ury="936"/> + <char name="Idieresis" width="278" llx="64" lly="0" urx="494" ury="915"/> + <char name="Igrave" width="278" llx="64" lly="0" urx="367" ury="936"/> + <char name="J" width="556" llx="60" lly="-18" urx="637" ury="718"/> + <char name="K" width="722" llx="87" lly="0" urx="858" ury="718"/> + <char name="L" width="611" llx="76" lly="0" urx="611" ury="718"/> + <char name="Lslash" width="611" llx="34" lly="0" urx="611" ury="718"/> + <char name="M" width="833" llx="69" lly="0" urx="918" ury="718"/> + <char name="N" width="722" llx="69" lly="0" urx="807" ury="718"/> + <char name="Ntilde" width="722" llx="69" lly="0" urx="807" ury="923"/> + <char name="O" width="778" llx="107" lly="-19" urx="823" ury="737"/> + <char name="OE" width="1000" llx="99" lly="-19" urx="1114" ury="737"/> + <char name="Oacute" width="778" llx="107" lly="-19" urx="823" ury="936"/> + <char name="Ocircumflex" width="778" llx="107" lly="-19" urx="823" ury="936"/> + <char name="Odieresis" width="778" llx="107" lly="-19" urx="823" ury="915"/> + <char name="Ograve" width="778" llx="107" lly="-19" urx="823" ury="936"/> + <char name="Oslash" width="778" llx="35" lly="-27" urx="894" ury="745"/> + <char name="Otilde" width="778" llx="107" lly="-19" urx="823" ury="923"/> + <char name="P" width="667" llx="76" lly="0" urx="738" ury="718"/> + <char name="Q" width="778" llx="107" lly="-52" urx="823" ury="737"/> + <char name="R" width="722" llx="76" lly="0" urx="778" ury="718"/> + <char name="S" width="667" llx="81" lly="-19" urx="718" ury="737"/> + <char name="Scaron" width="667" llx="81" lly="-19" urx="718" ury="936"/> + <char name="T" width="611" llx="140" lly="0" urx="751" ury="718"/> + <char name="Thorn" width="667" llx="76" lly="0" urx="716" ury="718"/> + <char name="U" width="722" llx="116" lly="-19" urx="804" ury="718"/> + <char name="Uacute" width="722" llx="116" lly="-19" urx="804" ury="936"/> + <char name="Ucircumflex" width="722" llx="116" lly="-19" urx="804" ury="936"/> + <char name="Udieresis" width="722" llx="116" lly="-19" urx="804" ury="915"/> + <char name="Ugrave" width="722" llx="116" lly="-19" urx="804" ury="936"/> + <char name="V" width="667" llx="172" lly="0" urx="801" ury="718"/> + <char name="W" width="944" llx="169" lly="0" urx="1082" ury="718"/> + <char name="X" width="667" llx="14" lly="0" urx="791" ury="718"/> + <char name="Y" width="667" llx="168" lly="0" urx="806" ury="718"/> + <char name="Yacute" width="667" llx="168" lly="0" urx="806" ury="936"/> + <char name="Ydieresis" width="667" llx="168" lly="0" urx="806" ury="915"/> + <char name="Z" width="611" llx="25" lly="0" urx="737" ury="718"/> + <char name="Zcaron" width="611" llx="25" lly="0" urx="737" ury="936"/> + <char name="a" width="556" llx="55" lly="-14" urx="583" ury="546"/> + <char name="aacute" width="556" llx="55" lly="-14" urx="627" ury="750"/> + <char name="acircumflex" width="556" llx="55" lly="-14" urx="583" ury="750"/> + <char name="acute" width="333" llx="236" lly="604" urx="515" ury="750"/> + <char name="adieresis" width="556" llx="55" lly="-14" urx="594" ury="729"/> + <char name="ae" width="889" llx="56" lly="-14" urx="923" ury="546"/> + <char name="agrave" width="556" llx="55" lly="-14" urx="583" ury="750"/> + <char name="ampersand" width="722" llx="89" lly="-19" urx="732" ury="718"/> + <char name="aring" width="556" llx="55" lly="-14" urx="583" ury="776"/> + <char name="asciicircum" width="584" llx="131" lly="323" urx="591" ury="698"/> + <char name="asciitilde" width="584" llx="115" lly="163" urx="577" ury="343"/> + <char name="asterisk" width="389" llx="146" lly="387" urx="481" ury="718"/> + <char name="at" width="975" llx="186" lly="-19" urx="954" ury="737"/> + <char name="atilde" width="556" llx="55" lly="-14" urx="619" ury="737"/> + <char name="b" width="611" llx="61" lly="-14" urx="645" ury="718"/> + <char name="backslash" width="278" llx="124" lly="-19" urx="307" ury="737"/> + <char name="bar" width="280" llx="36" lly="-225" urx="361" ury="775"/> + <char name="braceleft" width="389" llx="94" lly="-196" urx="518" ury="722"/> + <char name="braceright" width="389" llx="-18" lly="-196" urx="407" ury="722"/> + <char name="bracketleft" width="333" llx="21" lly="-196" urx="462" ury="722"/> + <char name="bracketright" width="333" llx="-18" lly="-196" urx="423" ury="722"/> + <char name="breve" width="333" llx="156" lly="604" urx="494" ury="750"/> + <char name="brokenbar" width="280" llx="52" lly="-150" urx="345" ury="700"/> + <char name="bullet" width="350" llx="83" lly="194" urx="420" ury="524"/> + <char name="c" width="556" llx="79" lly="-14" urx="599" ury="546"/> + <char name="caron" width="333" llx="149" lly="604" urx="502" ury="750"/> + <char name="ccedilla" width="556" llx="79" lly="-228" urx="599" ury="546"/> + <char name="cedilla" width="333" llx="-37" lly="-228" urx="220" ury="0"/> + <char name="cent" width="556" llx="79" lly="-118" urx="599" ury="628"/> + <char name="circumflex" width="333" llx="118" lly="604" urx="471" ury="750"/> + <char name="colon" width="333" llx="92" lly="0" urx="351" ury="512"/> + <char name="comma" width="278" llx="28" lly="-168" urx="245" ury="146"/> + <char name="copyright" width="737" llx="56" lly="-19" urx="835" ury="737"/> + <char name="currency" width="556" llx="27" lly="76" urx="680" ury="636"/> + <char name="d" width="611" llx="82" lly="-14" urx="704" ury="718"/> + <char name="dagger" width="556" llx="118" lly="-171" urx="626" ury="718"/> + <char name="daggerdbl" width="556" llx="46" lly="-171" urx="628" ury="718"/> + <char name="degree" width="400" llx="175" lly="426" urx="467" ury="712"/> + <char name="dieresis" width="333" llx="137" lly="614" urx="482" ury="729"/> + <char name="divide" width="584" llx="82" lly="-42" urx="610" ury="548"/> + <char name="dollar" width="556" llx="67" lly="-115" urx="622" ury="775"/> + <char name="dotaccent" width="333" llx="235" lly="614" urx="385" ury="729"/> + <char name="dotlessi" width="278" llx="69" lly="0" urx="322" ury="532"/> + <char name="e" width="556" llx="70" lly="-14" urx="593" ury="546"/> + <char name="eacute" width="556" llx="70" lly="-14" urx="627" ury="750"/> + <char name="ecircumflex" width="556" llx="70" lly="-14" urx="593" ury="750"/> + <char name="edieresis" width="556" llx="70" lly="-14" urx="594" ury="729"/> + <char name="egrave" width="556" llx="70" lly="-14" urx="593" ury="750"/> + <char name="eight" width="556" llx="69" lly="-19" urx="616" ury="710"/> + <char name="ellipsis" width="1000" llx="92" lly="0" urx="939" ury="146"/> + <char name="emdash" width="1000" llx="48" lly="227" urx="1071" ury="333"/> + <char name="endash" width="556" llx="48" lly="227" urx="627" ury="333"/> + <char name="equal" width="584" llx="58" lly="87" urx="633" ury="419"/> + <char name="eth" width="611" llx="82" lly="-14" urx="670" ury="737"/> + <char name="exclam" width="333" llx="94" lly="0" urx="397" ury="718"/> + <char name="exclamdown" width="333" llx="50" lly="-186" urx="353" ury="532"/> + <char name="f" width="333" llx="87" lly="0" urx="469" ury="727"/> + <char name="fi" width="611" llx="87" lly="0" urx="696" ury="727"/> + <char name="five" width="556" llx="64" lly="-19" urx="636" ury="698"/> + <char name="fl" width="611" llx="87" lly="0" urx="695" ury="727"/> + <char name="florin" width="556" llx="-50" lly="-210" urx="669" ury="737"/> + <char name="four" width="556" llx="60" lly="0" urx="598" ury="710"/> + <char name="fraction" width="167" llx="-174" lly="-19" urx="487" ury="710"/> + <char name="g" width="611" llx="38" lly="-217" urx="666" ury="546"/> + <char name="germandbls" width="611" llx="69" lly="-14" urx="657" ury="731"/> + <char name="grave" width="333" llx="136" lly="604" urx="353" ury="750"/> + <char name="greater" width="584" llx="36" lly="-8" urx="609" ury="514"/> + <char name="guillemotleft" width="556" llx="135" lly="76" urx="571" ury="484"/> + <char name="guillemotright" width="556" llx="104" lly="76" urx="540" ury="484"/> + <char name="guilsinglleft" width="333" llx="130" lly="76" urx="353" ury="484"/> + <char name="guilsinglright" width="333" llx="99" lly="76" urx="322" ury="484"/> + <char name="h" width="611" llx="65" lly="0" urx="629" ury="718"/> + <char name="hungarumlaut" width="333" llx="137" lly="604" urx="645" ury="750"/> + <char name="hyphen" width="333" llx="73" lly="215" urx="379" ury="345"/> + <char name="i" width="278" llx="69" lly="0" urx="363" ury="725"/> + <char name="iacute" width="278" llx="69" lly="0" urx="488" ury="750"/> + <char name="icircumflex" width="278" llx="69" lly="0" urx="444" ury="750"/> + <char name="idieresis" width="278" llx="69" lly="0" urx="455" ury="729"/> + <char name="igrave" width="278" llx="69" lly="0" urx="326" ury="750"/> + <char name="j" width="278" llx="-42" lly="-214" urx="363" ury="725"/> + <char name="k" width="556" llx="69" lly="0" urx="670" ury="718"/> + <char name="l" width="278" llx="69" lly="0" urx="362" ury="718"/> + <char name="less" width="584" llx="82" lly="-8" urx="655" ury="514"/> + <char name="logicalnot" width="584" llx="105" lly="108" urx="633" ury="419"/> + <char name="lslash" width="278" llx="40" lly="0" urx="407" ury="718"/> + <char name="m" width="889" llx="64" lly="0" urx="909" ury="546"/> + <char name="macron" width="333" llx="122" lly="604" urx="483" ury="678"/> + <char name="minus" width="324" llx="82" lly="197" urx="610" ury="309"/> + <char name="mu" width="611" llx="22" lly="-207" urx="658" ury="532"/> + <char name="multiply" width="584" llx="57" lly="1" urx="635" ury="505"/> + <char name="n" width="611" llx="65" lly="0" urx="629" ury="546"/> + <char name="nine" width="556" llx="78" lly="-19" urx="615" ury="710"/> + <char name="ntilde" width="611" llx="65" lly="0" urx="646" ury="737"/> + <char name="numbersign" width="556" llx="60" lly="0" urx="644" ury="698"/> + <char name="o" width="611" llx="82" lly="-14" urx="643" ury="546"/> + <char name="oacute" width="611" llx="82" lly="-14" urx="654" ury="750"/> + <char name="ocircumflex" width="611" llx="82" lly="-14" urx="643" ury="750"/> + <char name="odieresis" width="611" llx="82" lly="-14" urx="643" ury="729"/> + <char name="oe" width="944" llx="82" lly="-14" urx="977" ury="546"/> + <char name="ogonek" width="333" llx="41" lly="-228" urx="264" ury="0"/> + <char name="ograve" width="611" llx="82" lly="-14" urx="643" ury="750"/> + <char name="one" width="556" llx="173" lly="0" urx="529" ury="710"/> + <char name="onehalf" width="834" llx="132" lly="-19" urx="858" ury="710"/> + <char name="onequarter" width="834" llx="132" lly="-19" urx="806" ury="710"/> + <char name="onesuperior" width="333" llx="148" lly="283" urx="388" ury="710"/> + <char name="ordfeminine" width="370" llx="125" lly="401" urx="465" ury="737"/> + <char name="ordmasculine" width="365" llx="123" lly="401" urx="485" ury="737"/> + <char name="oslash" width="611" llx="22" lly="-29" urx="701" ury="560"/> + <char name="otilde" width="611" llx="82" lly="-14" urx="646" ury="737"/> + <char name="p" width="611" llx="18" lly="-207" urx="645" ury="546"/> + <char name="paragraph" width="556" llx="98" lly="-191" urx="688" ury="700"/> + <char name="parenleft" width="333" llx="76" lly="-208" urx="470" ury="734"/> + <char name="parenright" width="333" llx="-25" lly="-208" urx="369" ury="734"/> + <char name="percent" width="889" llx="136" lly="-19" urx="901" ury="710"/> + <char name="period" width="278" llx="64" lly="0" urx="245" ury="146"/> + <char name="periodcentered" width="278" llx="110" lly="172" urx="276" ury="334"/> + <char name="perthousand" width="1000" llx="76" lly="-19" urx="1038" ury="710"/> + <char name="plus" width="584" llx="82" lly="0" urx="610" ury="506"/> + <char name="plusminus" width="584" llx="40" lly="0" urx="625" ury="506"/> + <char name="q" width="611" llx="80" lly="-207" urx="665" ury="546"/> + <char name="question" width="611" llx="165" lly="0" urx="671" ury="727"/> + <char name="questiondown" width="611" llx="53" lly="-195" urx="559" ury="532"/> + <char name="quotedbl" width="474" llx="193" lly="447" urx="529" ury="718"/> + <char name="quotedblbase" width="500" llx="36" lly="-146" urx="463" ury="127"/> + <char name="quotedblleft" width="500" llx="160" lly="454" urx="588" ury="727"/> + <char name="quotedblright" width="500" llx="162" lly="445" urx="589" ury="718"/> + <char name="quoteleft" width="278" llx="165" lly="454" urx="361" ury="727"/> + <char name="quoteright" width="278" llx="167" lly="445" urx="362" ury="718"/> + <char name="quotesinglbase" width="278" llx="41" lly="-146" urx="236" ury="127"/> + <char name="quotesingle" width="238" llx="165" lly="447" urx="321" ury="718"/> + <char name="r" width="389" llx="64" lly="0" urx="489" ury="546"/> + <char name="registered" width="737" llx="55" lly="-19" urx="834" ury="737"/> + <char name="ring" width="333" llx="200" lly="568" urx="420" ury="776"/> + <char name="s" width="556" llx="63" lly="-14" urx="584" ury="546"/> + <char name="scaron" width="556" llx="63" lly="-14" urx="614" ury="750"/> + <char name="section" width="556" llx="61" lly="-184" urx="598" ury="727"/> + <char name="semicolon" width="333" llx="56" lly="-168" urx="351" ury="512"/> + <char name="seven" width="556" llx="125" lly="0" urx="676" ury="698"/> + <char name="six" width="556" llx="85" lly="-19" urx="619" ury="710"/> + <char name="slash" width="278" llx="-37" lly="-19" urx="468" ury="737"/> + <char name="space" width="278" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="278"/> - <char name="sterling" width="556"/> - <char name="t" width="333"/> - <char name="thorn" width="611"/> - <char name="three" width="556"/> - <char name="threequarters" width="834"/> - <char name="threesuperior" width="333"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="556"/> - <char name="twosuperior" width="333"/> - <char name="u" width="611"/> - <char name="uacute" width="611"/> - <char name="ucircumflex" width="611"/> - <char name="udieresis" width="611"/> - <char name="ugrave" width="611"/> - <char name="underscore" width="556"/> - <char name="v" width="556"/> - <char name="w" width="778"/> - <char name="x" width="556"/> - <char name="y" width="556"/> - <char name="yacute" width="556"/> - <char name="ydieresis" width="556"/> - <char name="yen" width="556"/> - <char name="z" width="500"/> - <char name="zcaron" width="500"/> - <char name="zero" width="556"/> - </widths> + <char name="sterling" width="556" llx="50" lly="-16" urx="635" ury="718"/> + <char name="t" width="333" llx="100" lly="-6" urx="422" ury="676"/> + <char name="thorn" width="611" llx="18" lly="-208" urx="645" ury="718"/> + <char name="three" width="556" llx="65" lly="-19" urx="608" ury="710"/> + <char name="threequarters" width="834" llx="99" lly="-19" urx="839" ury="710"/> + <char name="threesuperior" width="333" llx="91" lly="271" urx="441" ury="710"/> + <char name="tilde" width="333" llx="113" lly="610" urx="507" ury="737"/> + <char name="trademark" width="1000" llx="179" lly="306" urx="1109" ury="718"/> + <char name="two" width="556" llx="26" lly="0" urx="619" ury="710"/> + <char name="twosuperior" width="333" llx="69" lly="283" urx="449" ury="710"/> + <char name="u" width="611" llx="98" lly="-14" urx="658" ury="532"/> + <char name="uacute" width="611" llx="98" lly="-14" urx="658" ury="750"/> + <char name="ucircumflex" width="611" llx="98" lly="-14" urx="658" ury="750"/> + <char name="udieresis" width="611" llx="98" lly="-14" urx="658" ury="729"/> + <char name="ugrave" width="611" llx="98" lly="-14" urx="658" ury="750"/> + <char name="underscore" width="556" llx="-27" lly="-125" urx="540" ury="-75"/> + <char name="v" width="556" llx="126" lly="0" urx="656" ury="532"/> + <char name="w" width="778" llx="123" lly="0" urx="882" ury="532"/> + <char name="x" width="556" llx="15" lly="0" urx="648" ury="532"/> + <char name="y" width="556" llx="42" lly="-214" urx="652" ury="532"/> + <char name="yacute" width="556" llx="42" lly="-214" urx="652" ury="750"/> + <char name="ydieresis" width="556" llx="42" lly="-214" urx="652" ury="729"/> + <char name="yen" width="556" llx="60" lly="0" urx="713" ury="698"/> + <char name="z" width="500" llx="20" lly="0" urx="583" ury="532"/> + <char name="zcaron" width="500" llx="20" lly="0" urx="586" ury="750"/> + <char name="zero" width="556" llx="86" lly="-19" urx="617" ury="710"/> + </char-metrics> <kerning kpx1="107"> <pair kern="-15" kpx2="111"/> </kerning> diff --git a/src/codegen/fonts/HelveticaOblique.xml b/src/codegen/fonts/HelveticaOblique.xml index 7f651a5d9..efa1165f2 100644 --- a/src/codegen/fonts/HelveticaOblique.xml +++ b/src/codegen/fonts/HelveticaOblique.xml @@ -22,245 +22,246 @@ <family-name>Helvetica</family-name> <class-name>HelveticaOblique</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>718</cap-height> <x-height>523</x-height> <ascender>718</ascender> <descender>-207</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="667"/> - <char name="AE" width="1000"/> - <char name="Aacute" width="667"/> - <char name="Acircumflex" width="667"/> - <char name="Adieresis" width="667"/> - <char name="Agrave" width="667"/> - <char name="Aring" width="667"/> - <char name="Atilde" width="667"/> - <char name="B" width="667"/> - <char name="C" width="722"/> - <char name="Ccedilla" width="722"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="556"/> - <char name="F" width="611"/> - <char name="G" width="778"/> - <char name="H" width="722"/> - <char name="I" width="278"/> - <char name="Iacute" width="278"/> - <char name="Icircumflex" width="278"/> - <char name="Idieresis" width="278"/> - <char name="Igrave" width="278"/> - <char name="J" width="500"/> - <char name="K" width="667"/> - <char name="L" width="556"/> - <char name="Lslash" width="556"/> - <char name="M" width="833"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="778"/> - <char name="OE" width="1000"/> - <char name="Oacute" width="778"/> - <char name="Ocircumflex" width="778"/> - <char name="Odieresis" width="778"/> - <char name="Ograve" width="778"/> - <char name="Oslash" width="778"/> - <char name="Otilde" width="778"/> - <char name="P" width="667"/> - <char name="Q" width="778"/> - <char name="R" width="722"/> - <char name="S" width="667"/> - <char name="Scaron" width="667"/> - <char name="T" width="611"/> - <char name="Thorn" width="667"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="667"/> - <char name="W" width="944"/> - <char name="X" width="667"/> - <char name="Y" width="667"/> - <char name="Yacute" width="667"/> - <char name="Ydieresis" width="667"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="556"/> - <char name="aacute" width="556"/> - <char name="acircumflex" width="556"/> - <char name="acute" width="333"/> - <char name="adieresis" width="556"/> - <char name="ae" width="889"/> - <char name="agrave" width="556"/> - <char name="ampersand" width="667"/> - <char name="aring" width="556"/> - <char name="asciicircum" width="469"/> - <char name="asciitilde" width="584"/> - <char name="asterisk" width="389"/> - <char name="at" width="1015"/> - <char name="atilde" width="556"/> - <char name="b" width="556"/> - <char name="backslash" width="278"/> - <char name="bar" width="260"/> - <char name="braceleft" width="334"/> - <char name="braceright" width="334"/> - <char name="bracketleft" width="278"/> - <char name="bracketright" width="278"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="260"/> - <char name="bullet" width="350"/> - <char name="c" width="500"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="500"/> - <char name="cedilla" width="333"/> - <char name="cent" width="556"/> - <char name="circumflex" width="333"/> - <char name="colon" width="278"/> - <char name="comma" width="278"/> - <char name="copyright" width="737"/> - <char name="currency" width="556"/> - <char name="d" width="556"/> - <char name="dagger" width="556"/> - <char name="daggerdbl" width="556"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="584"/> - <char name="dollar" width="556"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="556"/> - <char name="eacute" width="556"/> - <char name="ecircumflex" width="556"/> - <char name="edieresis" width="556"/> - <char name="egrave" width="556"/> - <char name="eight" width="556"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="556"/> - <char name="equal" width="584"/> - <char name="eth" width="556"/> - <char name="exclam" width="278"/> - <char name="exclamdown" width="333"/> - <char name="f" width="278"/> - <char name="fi" width="500"/> - <char name="five" width="556"/> - <char name="fl" width="500"/> - <char name="florin" width="556"/> - <char name="four" width="556"/> - <char name="fraction" width="167"/> - <char name="g" width="556"/> - <char name="germandbls" width="611"/> - <char name="grave" width="333"/> - <char name="greater" width="584"/> - <char name="guillemotleft" width="556"/> - <char name="guillemotright" width="556"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="556"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="222"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="222"/> - <char name="k" width="500"/> - <char name="l" width="222"/> - <char name="less" width="584"/> - <char name="logicalnot" width="584"/> - <char name="lslash" width="222"/> - <char name="m" width="833"/> - <char name="macron" width="333"/> - <char name="minus" width="584"/> - <char name="mu" width="556"/> - <char name="multiply" width="584"/> - <char name="n" width="556"/> - <char name="nine" width="556"/> - <char name="ntilde" width="556"/> - <char name="numbersign" width="556"/> - <char name="o" width="556"/> - <char name="oacute" width="556"/> - <char name="ocircumflex" width="556"/> - <char name="odieresis" width="556"/> - <char name="oe" width="944"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="556"/> - <char name="one" width="556"/> - <char name="onehalf" width="834"/> - <char name="onequarter" width="834"/> - <char name="onesuperior" width="333"/> - <char name="ordfeminine" width="370"/> - <char name="ordmasculine" width="365"/> - <char name="oslash" width="611"/> - <char name="otilde" width="556"/> - <char name="p" width="556"/> - <char name="paragraph" width="537"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="889"/> - <char name="period" width="278"/> - <char name="periodcentered" width="278"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="584"/> - <char name="plusminus" width="584"/> - <char name="q" width="556"/> - <char name="question" width="556"/> - <char name="questiondown" width="611"/> - <char name="quotedbl" width="355"/> - <char name="quotedblbase" width="333"/> - <char name="quotedblleft" width="333"/> - <char name="quotedblright" width="333"/> - <char name="quoteleft" width="222"/> - <char name="quoteright" width="222"/> - <char name="quotesinglbase" width="222"/> - <char name="quotesingle" width="191"/> - <char name="r" width="333"/> - <char name="registered" width="737"/> - <char name="ring" width="333"/> - <char name="s" width="500"/> - <char name="scaron" width="500"/> - <char name="section" width="556"/> - <char name="semicolon" width="278"/> - <char name="seven" width="556"/> - <char name="six" width="556"/> - <char name="slash" width="278"/> - <char name="space" width="278"/> + <char-metrics> + <char name="A" width="667" llx="14" lly="0" urx="654" ury="718"/> + <char name="AE" width="1000" llx="8" lly="0" urx="1097" ury="718"/> + <char name="Aacute" width="667" llx="14" lly="0" urx="683" ury="929"/> + <char name="Acircumflex" width="667" llx="14" lly="0" urx="654" ury="929"/> + <char name="Adieresis" width="667" llx="14" lly="0" urx="654" ury="901"/> + <char name="Agrave" width="667" llx="14" lly="0" urx="654" ury="929"/> + <char name="Aring" width="667" llx="14" lly="0" urx="654" ury="931"/> + <char name="Atilde" width="667" llx="14" lly="0" urx="699" ury="917"/> + <char name="B" width="667" llx="74" lly="0" urx="712" ury="718"/> + <char name="C" width="722" llx="108" lly="-19" urx="782" ury="737"/> + <char name="Ccedilla" width="722" llx="108" lly="-225" urx="782" ury="737"/> + <char name="D" width="722" llx="81" lly="0" urx="764" ury="718"/> + <char name="E" width="667" llx="86" lly="0" urx="762" ury="718"/> + <char name="Eacute" width="667" llx="86" lly="0" urx="762" ury="929"/> + <char name="Ecircumflex" width="667" llx="86" lly="0" urx="762" ury="929"/> + <char name="Edieresis" width="667" llx="86" lly="0" urx="762" ury="901"/> + <char name="Egrave" width="667" llx="86" lly="0" urx="762" ury="929"/> + <char name="Eth" width="722" llx="69" lly="0" urx="764" ury="718"/> + <char name="Euro" width="556" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="86" lly="0" urx="736" ury="718"/> + <char name="G" width="778" llx="111" lly="-19" urx="799" ury="737"/> + <char name="H" width="722" llx="77" lly="0" urx="799" ury="718"/> + <char name="I" width="278" llx="91" lly="0" urx="341" ury="718"/> + <char name="Iacute" width="278" llx="91" lly="0" urx="489" ury="929"/> + <char name="Icircumflex" width="278" llx="91" lly="0" urx="452" ury="929"/> + <char name="Idieresis" width="278" llx="91" lly="0" urx="458" ury="901"/> + <char name="Igrave" width="278" llx="91" lly="0" urx="351" ury="929"/> + <char name="J" width="500" llx="47" lly="-19" urx="581" ury="718"/> + <char name="K" width="667" llx="76" lly="0" urx="808" ury="718"/> + <char name="L" width="556" llx="76" lly="0" urx="555" ury="718"/> + <char name="Lslash" width="556" llx="41" lly="0" urx="555" ury="718"/> + <char name="M" width="833" llx="73" lly="0" urx="914" ury="718"/> + <char name="N" width="722" llx="76" lly="0" urx="799" ury="718"/> + <char name="Ntilde" width="722" llx="76" lly="0" urx="799" ury="917"/> + <char name="O" width="778" llx="105" lly="-19" urx="826" ury="737"/> + <char name="OE" width="1000" llx="98" lly="-19" urx="1116" ury="737"/> + <char name="Oacute" width="778" llx="105" lly="-19" urx="826" ury="929"/> + <char name="Ocircumflex" width="778" llx="105" lly="-19" urx="826" ury="929"/> + <char name="Odieresis" width="778" llx="105" lly="-19" urx="826" ury="901"/> + <char name="Ograve" width="778" llx="105" lly="-19" urx="826" ury="929"/> + <char name="Oslash" width="778" llx="43" lly="-19" urx="890" ury="737"/> + <char name="Otilde" width="778" llx="105" lly="-19" urx="826" ury="917"/> + <char name="P" width="667" llx="86" lly="0" urx="737" ury="718"/> + <char name="Q" width="778" llx="105" lly="-56" urx="826" ury="737"/> + <char name="R" width="722" llx="88" lly="0" urx="773" ury="718"/> + <char name="S" width="667" llx="90" lly="-19" urx="713" ury="737"/> + <char name="Scaron" width="667" llx="90" lly="-19" urx="713" ury="929"/> + <char name="T" width="611" llx="148" lly="0" urx="750" ury="718"/> + <char name="Thorn" width="667" llx="86" lly="0" urx="712" ury="718"/> + <char name="U" width="722" llx="123" lly="-19" urx="797" ury="718"/> + <char name="Uacute" width="722" llx="123" lly="-19" urx="797" ury="929"/> + <char name="Ucircumflex" width="722" llx="123" lly="-19" urx="797" ury="929"/> + <char name="Udieresis" width="722" llx="123" lly="-19" urx="797" ury="901"/> + <char name="Ugrave" width="722" llx="123" lly="-19" urx="797" ury="929"/> + <char name="V" width="667" llx="173" lly="0" urx="800" ury="718"/> + <char name="W" width="944" llx="169" lly="0" urx="1081" ury="718"/> + <char name="X" width="667" llx="19" lly="0" urx="790" ury="718"/> + <char name="Y" width="667" llx="167" lly="0" urx="806" ury="718"/> + <char name="Yacute" width="667" llx="167" lly="0" urx="806" ury="929"/> + <char name="Ydieresis" width="667" llx="167" lly="0" urx="806" ury="901"/> + <char name="Z" width="611" llx="23" lly="0" urx="741" ury="718"/> + <char name="Zcaron" width="611" llx="23" lly="0" urx="741" ury="929"/> + <char name="a" width="556" llx="61" lly="-15" urx="559" ury="538"/> + <char name="aacute" width="556" llx="61" lly="-15" urx="587" ury="734"/> + <char name="acircumflex" width="556" llx="61" lly="-15" urx="559" ury="734"/> + <char name="acute" width="333" llx="248" lly="593" urx="475" ury="734"/> + <char name="adieresis" width="556" llx="61" lly="-15" urx="559" ury="706"/> + <char name="ae" width="889" llx="61" lly="-15" urx="909" ury="538"/> + <char name="agrave" width="556" llx="61" lly="-15" urx="559" ury="734"/> + <char name="ampersand" width="667" llx="77" lly="-15" urx="647" ury="718"/> + <char name="aring" width="556" llx="61" lly="-15" urx="559" ury="756"/> + <char name="asciicircum" width="469" llx="42" lly="264" urx="539" ury="688"/> + <char name="asciitilde" width="584" llx="111" lly="180" urx="580" ury="326"/> + <char name="asterisk" width="389" llx="165" lly="431" urx="475" ury="718"/> + <char name="at" width="1015" llx="215" lly="-19" urx="965" ury="737"/> + <char name="atilde" width="556" llx="61" lly="-15" urx="592" ury="722"/> + <char name="b" width="556" llx="58" lly="-15" urx="584" ury="718"/> + <char name="backslash" width="278" llx="140" lly="-19" urx="291" ury="737"/> + <char name="bar" width="260" llx="46" lly="-225" urx="332" ury="775"/> + <char name="braceleft" width="334" llx="92" lly="-196" urx="445" ury="722"/> + <char name="braceright" width="334" llx="0" lly="-196" urx="354" ury="722"/> + <char name="bracketleft" width="278" llx="21" lly="-196" urx="403" ury="722"/> + <char name="bracketright" width="278" llx="-14" lly="-196" urx="368" ury="722"/> + <char name="breve" width="333" llx="167" lly="595" urx="476" ury="731"/> + <char name="brokenbar" width="260" llx="62" lly="-150" urx="316" ury="700"/> + <char name="bullet" width="350" llx="91" lly="202" urx="413" ury="517"/> + <char name="c" width="500" llx="74" lly="-15" urx="553" ury="538"/> + <char name="caron" width="333" llx="177" lly="593" urx="468" ury="734"/> + <char name="ccedilla" width="500" llx="74" lly="-225" urx="553" ury="538"/> + <char name="cedilla" width="333" llx="2" lly="-225" urx="232" ury="0"/> + <char name="cent" width="556" llx="95" lly="-115" urx="584" ury="623"/> + <char name="circumflex" width="333" llx="147" lly="593" urx="438" ury="734"/> + <char name="colon" width="278" llx="87" lly="0" urx="301" ury="516"/> + <char name="comma" width="278" llx="56" lly="-147" urx="214" ury="106"/> + <char name="copyright" width="737" llx="54" lly="-19" urx="837" ury="737"/> + <char name="currency" width="556" llx="60" lly="99" urx="646" ury="603"/> + <char name="d" width="556" llx="84" lly="-15" urx="652" ury="718"/> + <char name="dagger" width="556" llx="135" lly="-159" urx="622" ury="718"/> + <char name="daggerdbl" width="556" llx="52" lly="-159" urx="623" ury="718"/> + <char name="degree" width="400" llx="169" lly="411" urx="468" ury="703"/> + <char name="dieresis" width="333" llx="168" lly="604" urx="443" ury="706"/> + <char name="divide" width="584" llx="85" lly="-19" urx="606" ury="524"/> + <char name="dollar" width="556" llx="69" lly="-115" urx="617" ury="775"/> + <char name="dotaccent" width="333" llx="249" lly="604" urx="362" ury="706"/> + <char name="dotlessi" width="278" llx="95" lly="0" urx="294" ury="523"/> + <char name="e" width="556" llx="84" lly="-15" urx="578" ury="538"/> + <char name="eacute" width="556" llx="84" lly="-15" urx="587" ury="734"/> + <char name="ecircumflex" width="556" llx="84" lly="-15" urx="578" ury="734"/> + <char name="edieresis" width="556" llx="84" lly="-15" urx="578" ury="706"/> + <char name="egrave" width="556" llx="84" lly="-15" urx="578" ury="734"/> + <char name="eight" width="556" llx="74" lly="-19" urx="607" ury="703"/> + <char name="ellipsis" width="1000" llx="115" lly="0" urx="908" ury="106"/> + <char name="emdash" width="1000" llx="51" lly="240" urx="1067" ury="313"/> + <char name="endash" width="556" llx="51" lly="240" urx="623" ury="313"/> + <char name="equal" width="584" llx="63" lly="115" urx="628" ury="390"/> + <char name="eth" width="556" llx="81" lly="-15" urx="617" ury="737"/> + <char name="exclam" width="278" llx="90" lly="0" urx="340" ury="718"/> + <char name="exclamdown" width="333" llx="77" lly="-195" urx="326" ury="523"/> + <char name="f" width="278" llx="86" lly="0" urx="416" ury="728"/> + <char name="fi" width="500" llx="86" lly="0" urx="587" ury="728"/> + <char name="five" width="556" llx="68" lly="-19" urx="621" ury="688"/> + <char name="fl" width="500" llx="86" lly="0" urx="585" ury="728"/> + <char name="florin" width="556" llx="-52" lly="-207" urx="654" ury="737"/> + <char name="four" width="556" llx="61" lly="0" urx="576" ury="703"/> + <char name="fraction" width="167" llx="-170" lly="-19" urx="482" ury="703"/> + <char name="g" width="556" llx="42" lly="-220" urx="610" ury="538"/> + <char name="germandbls" width="611" llx="67" lly="-15" urx="658" ury="728"/> + <char name="grave" width="333" llx="170" lly="593" urx="337" ury="734"/> + <char name="greater" width="584" llx="50" lly="11" urx="597" ury="495"/> + <char name="guillemotleft" width="556" llx="146" lly="108" urx="554" ury="446"/> + <char name="guillemotright" width="556" llx="120" lly="108" urx="528" ury="446"/> + <char name="guilsinglleft" width="333" llx="137" lly="108" urx="340" ury="446"/> + <char name="guilsinglright" width="333" llx="111" lly="108" urx="314" ury="446"/> + <char name="h" width="556" llx="65" lly="0" urx="573" ury="718"/> + <char name="hungarumlaut" width="333" llx="157" lly="593" urx="565" ury="734"/> + <char name="hyphen" width="333" llx="93" lly="232" urx="357" ury="322"/> + <char name="i" width="222" llx="67" lly="0" urx="308" ury="718"/> + <char name="iacute" width="278" llx="95" lly="0" urx="448" ury="734"/> + <char name="icircumflex" width="278" llx="95" lly="0" urx="411" ury="734"/> + <char name="idieresis" width="278" llx="95" lly="0" urx="416" ury="706"/> + <char name="igrave" width="278" llx="95" lly="0" urx="310" ury="734"/> + <char name="j" width="222" llx="-60" lly="-210" urx="308" ury="718"/> + <char name="k" width="500" llx="67" lly="0" urx="600" ury="718"/> + <char name="l" width="222" llx="67" lly="0" urx="308" ury="718"/> + <char name="less" width="584" llx="94" lly="11" urx="641" ury="495"/> + <char name="logicalnot" width="584" llx="106" lly="108" urx="628" ury="390"/> + <char name="lslash" width="222" llx="41" lly="0" urx="347" ury="718"/> + <char name="m" width="833" llx="65" lly="0" urx="852" ury="538"/> + <char name="macron" width="333" llx="143" lly="627" urx="468" ury="684"/> + <char name="minus" width="584" llx="85" lly="216" urx="606" ury="289"/> + <char name="mu" width="556" llx="24" lly="-207" urx="600" ury="523"/> + <char name="multiply" width="584" llx="50" lly="0" urx="642" ury="506"/> + <char name="n" width="556" llx="65" lly="0" urx="573" ury="538"/> + <char name="nine" width="556" llx="82" lly="-19" urx="609" ury="703"/> + <char name="ntilde" width="556" llx="65" lly="0" urx="592" ury="722"/> + <char name="numbersign" width="556" llx="73" lly="0" urx="631" ury="688"/> + <char name="o" width="556" llx="83" lly="-14" urx="585" ury="538"/> + <char name="oacute" width="556" llx="83" lly="-14" urx="587" ury="734"/> + <char name="ocircumflex" width="556" llx="83" lly="-14" urx="585" ury="734"/> + <char name="odieresis" width="556" llx="83" lly="-14" urx="585" ury="706"/> + <char name="oe" width="944" llx="83" lly="-15" urx="964" ury="538"/> + <char name="ogonek" width="333" llx="43" lly="-225" urx="249" ury="0"/> + <char name="ograve" width="556" llx="83" lly="-14" urx="585" ury="734"/> + <char name="one" width="556" llx="207" lly="0" urx="508" ury="703"/> + <char name="onehalf" width="834" llx="114" lly="-19" urx="839" ury="703"/> + <char name="onequarter" width="834" llx="150" lly="-19" urx="802" ury="703"/> + <char name="onesuperior" width="333" llx="166" lly="281" urx="371" ury="703"/> + <char name="ordfeminine" width="370" llx="127" lly="405" urx="449" ury="737"/> + <char name="ordmasculine" width="365" llx="141" lly="405" urx="468" ury="737"/> + <char name="oslash" width="611" llx="29" lly="-22" urx="647" ury="545"/> + <char name="otilde" width="556" llx="83" lly="-14" urx="602" ury="722"/> + <char name="p" width="556" llx="14" lly="-207" urx="584" ury="538"/> + <char name="paragraph" width="537" llx="126" lly="-173" urx="650" ury="718"/> + <char name="parenleft" width="333" llx="108" lly="-207" urx="454" ury="733"/> + <char name="parenright" width="333" llx="-9" lly="-207" urx="337" ury="733"/> + <char name="percent" width="889" llx="147" lly="-19" urx="889" ury="703"/> + <char name="period" width="278" llx="87" lly="0" urx="214" ury="106"/> + <char name="periodcentered" width="278" llx="129" lly="190" urx="257" ury="315"/> + <char name="perthousand" width="1000" llx="88" lly="-19" urx="1029" ury="703"/> + <char name="plus" width="584" llx="85" lly="0" urx="606" ury="505"/> + <char name="plusminus" width="584" llx="39" lly="0" urx="618" ury="506"/> + <char name="q" width="556" llx="84" lly="-207" urx="605" ury="538"/> + <char name="question" width="556" llx="161" lly="0" urx="610" ury="727"/> + <char name="questiondown" width="611" llx="85" lly="-201" urx="534" ury="525"/> + <char name="quotedbl" width="355" llx="168" lly="463" urx="438" ury="718"/> + <char name="quotedblbase" width="333" llx="-6" lly="-149" urx="318" ury="106"/> + <char name="quotedblleft" width="333" llx="138" lly="470" urx="461" ury="725"/> + <char name="quotedblright" width="333" llx="124" lly="463" urx="448" ury="718"/> + <char name="quoteleft" width="222" llx="165" lly="470" urx="323" ury="725"/> + <char name="quoteright" width="222" llx="151" lly="463" urx="310" ury="718"/> + <char name="quotesinglbase" width="222" llx="21" lly="-149" urx="180" ury="106"/> + <char name="quotesingle" width="191" llx="157" lly="463" urx="285" ury="718"/> + <char name="r" width="333" llx="77" lly="0" urx="446" ury="538"/> + <char name="registered" width="737" llx="54" lly="-19" urx="837" ury="737"/> + <char name="ring" width="333" llx="214" lly="572" urx="402" ury="756"/> + <char name="s" width="500" llx="63" lly="-15" urx="529" ury="538"/> + <char name="scaron" width="500" llx="63" lly="-15" urx="552" ury="734"/> + <char name="section" width="556" llx="76" lly="-191" urx="584" ury="737"/> + <char name="semicolon" width="278" llx="56" lly="-147" urx="301" ury="516"/> + <char name="seven" width="556" llx="137" lly="0" urx="669" ury="688"/> + <char name="six" width="556" llx="91" lly="-19" urx="615" ury="703"/> + <char name="slash" width="278" llx="-21" lly="-19" urx="452" ury="737"/> + <char name="space" width="278" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="278"/> - <char name="sterling" width="556"/> - <char name="t" width="278"/> - <char name="thorn" width="556"/> - <char name="three" width="556"/> - <char name="threequarters" width="834"/> - <char name="threesuperior" width="333"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="556"/> - <char name="twosuperior" width="333"/> - <char name="u" width="556"/> - <char name="uacute" width="556"/> - <char name="ucircumflex" width="556"/> - <char name="udieresis" width="556"/> - <char name="ugrave" width="556"/> - <char name="underscore" width="556"/> - <char name="v" width="500"/> - <char name="w" width="722"/> - <char name="x" width="500"/> - <char name="y" width="500"/> - <char name="yacute" width="500"/> - <char name="ydieresis" width="500"/> - <char name="yen" width="556"/> - <char name="z" width="500"/> - <char name="zcaron" width="500"/> - <char name="zero" width="556"/> - </widths> + <char name="sterling" width="556" llx="49" lly="-16" urx="634" ury="718"/> + <char name="t" width="278" llx="102" lly="-7" urx="368" ury="669"/> + <char name="thorn" width="556" llx="14" lly="-207" urx="584" ury="718"/> + <char name="three" width="556" llx="75" lly="-19" urx="610" ury="703"/> + <char name="threequarters" width="834" llx="130" lly="-19" urx="861" ury="703"/> + <char name="threesuperior" width="333" llx="90" lly="270" urx="436" ury="703"/> + <char name="tilde" width="333" llx="125" lly="606" urx="490" ury="722"/> + <char name="trademark" width="1000" llx="186" lly="306" urx="1056" ury="718"/> + <char name="two" width="556" llx="26" lly="0" urx="617" ury="703"/> + <char name="twosuperior" width="333" llx="64" lly="281" urx="449" ury="703"/> + <char name="u" width="556" llx="94" lly="-15" urx="600" ury="523"/> + <char name="uacute" width="556" llx="94" lly="-15" urx="600" ury="734"/> + <char name="ucircumflex" width="556" llx="94" lly="-15" urx="600" ury="734"/> + <char name="udieresis" width="556" llx="94" lly="-15" urx="600" ury="706"/> + <char name="ugrave" width="556" llx="94" lly="-15" urx="600" ury="734"/> + <char name="underscore" width="556" llx="-27" lly="-125" urx="540" ury="-75"/> + <char name="v" width="500" llx="119" lly="0" urx="603" ury="523"/> + <char name="w" width="722" llx="125" lly="0" urx="820" ury="523"/> + <char name="x" width="500" llx="11" lly="0" urx="594" ury="523"/> + <char name="y" width="500" llx="15" lly="-214" urx="600" ury="523"/> + <char name="yacute" width="500" llx="15" lly="-214" urx="600" ury="734"/> + <char name="ydieresis" width="500" llx="15" lly="-214" urx="600" ury="706"/> + <char name="yen" width="556" llx="81" lly="0" urx="699" ury="688"/> + <char name="z" width="500" llx="31" lly="0" urx="571" ury="523"/> + <char name="zcaron" width="500" llx="31" lly="0" urx="571" ury="734"/> + <char name="zero" width="556" llx="93" lly="-19" urx="608" ury="703"/> + </char-metrics> <kerning kpx1="107"> <pair kern="-20" kpx2="111"/> <pair kern="-20" kpx2="101"/> @@ -602,4 +603,4 @@ <pair kern="-30" kpx2="118"/> <pair kern="-15" kpx2="44"/> </kerning> -</font-metrics>
\ No newline at end of file +</font-metrics> diff --git a/src/codegen/fonts/Symbol.xml b/src/codegen/fonts/Symbol.xml index c0dce043a..7493b7e7f 100644 --- a/src/codegen/fonts/Symbol.xml +++ b/src/codegen/fonts/Symbol.xml @@ -21,203 +21,204 @@ <family-name>Symbol</family-name> <class-name>Symbol</class-name> <encoding>SymbolEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>1010</cap-height> <x-height>520</x-height> <ascender>1010</ascender> <descender>-293</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="space" width="250"/> - <char name="exclam" width="333"/> - <char name="universal" width="713"/> - <char name="numbersign" width="500"/> - <char name="existential" width="549"/> - <char name="percent" width="833"/> - <char name="ampersand" width="778"/> - <char name="suchthat" width="439"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="asteriskmath" width="500"/> - <char name="plus" width="549"/> - <char name="comma" width="250"/> - <char name="minus" width="549"/> - <char name="period" width="250"/> - <char name="slash" width="278"/> - <char name="zero" width="500"/> - <char name="one" width="500"/> - <char name="two" width="500"/> - <char name="three" width="500"/> - <char name="four" width="500"/> - <char name="five" width="500"/> - <char name="six" width="500"/> - <char name="seven" width="500"/> - <char name="eight" width="500"/> - <char name="nine" width="500"/> - <char name="colon" width="278"/> - <char name="semicolon" width="278"/> - <char name="less" width="549"/> - <char name="equal" width="549"/> - <char name="greater" width="549"/> - <char name="question" width="444"/> - <char name="congruent" width="549"/> - <char name="Alpha" width="722"/> - <char name="Beta" width="667"/> - <char name="Chi" width="722"/> - <char name="Delta" width="612"/> - <char name="Epsilon" width="611"/> - <char name="Phi" width="763"/> - <char name="Gamma" width="603"/> - <char name="Eta" width="722"/> - <char name="Iota" width="333"/> - <char name="theta1" width="631"/> - <char name="Kappa" width="722"/> - <char name="Lambda" width="686"/> - <char name="Mu" width="889"/> - <char name="Nu" width="722"/> - <char name="Omicron" width="722"/> - <char name="Pi" width="768"/> - <char name="Theta" width="741"/> - <char name="Rho" width="556"/> - <char name="Sigma" width="592"/> - <char name="Tau" width="611"/> - <char name="Upsilon" width="690"/> - <char name="sigma1" width="439"/> - <char name="Omega" width="768"/> - <char name="Xi" width="645"/> - <char name="Psi" width="795"/> - <char name="Zeta" width="611"/> - <char name="bracketleft" width="333"/> - <char name="therefore" width="863"/> - <char name="bracketright" width="333"/> - <char name="perpendicular" width="658"/> - <char name="underscore" width="500"/> - <char name="radicalex" width="500"/> - <char name="alpha" width="631"/> - <char name="beta" width="549"/> - <char name="chi" width="549"/> - <char name="delta" width="494"/> - <char name="epsilon" width="439"/> - <char name="phi" width="521"/> - <char name="gamma" width="411"/> - <char name="eta" width="603"/> - <char name="iota" width="329"/> - <char name="phi1" width="603"/> - <char name="kappa" width="549"/> - <char name="lambda" width="549"/> - <char name="m" width="576"/> - <char name="mu" width="576"/> - <char name="nu" width="521"/> - <char name="omicron" width="549"/> - <char name="pi" width="549"/> - <char name="theta" width="521"/> - <char name="rho" width="549"/> - <char name="sigma" width="603"/> - <char name="tau" width="439"/> - <char name="upsilon" width="576"/> - <char name="omega1" width="713"/> - <char name="omega" width="686"/> - <char name="xi" width="493"/> - <char name="psi" width="686"/> - <char name="zeta" width="494"/> - <char name="braceleft" width="480"/> - <char name="bar" width="200"/> - <char name="braceright" width="480"/> - <char name="similar" width="549"/> - <char name="Euro" width="750"/> - <char name="Upsilon1" width="620"/> - <char name="minute" width="247"/> - <char name="lessequal" width="549"/> - <char name="fraction" width="167"/> - <char name="infinity" width="713"/> - <char name="florin" width="500"/> - <char name="club" width="753"/> - <char name="diamond" width="753"/> - <char name="heart" width="753"/> - <char name="spade" width="753"/> - <char name="arrowboth" width="1042"/> - <char name="arrowleft" width="987"/> - <char name="arrowup" width="603"/> - <char name="arrowright" width="987"/> - <char name="arrowdown" width="603"/> - <char name="degree" width="400"/> - <char name="plusminus" width="549"/> - <char name="second" width="411"/> - <char name="greaterequal" width="549"/> - <char name="multiply" width="549"/> - <char name="proportional" width="713"/> - <char name="partialdiff" width="494"/> - <char name="bullet" width="460"/> - <char name="divide" width="549"/> - <char name="notequal" width="549"/> - <char name="equivalence" width="549"/> - <char name="approxequal" width="549"/> - <char name="ellipsis" width="1000"/> - <char name="arrowvertex" width="603"/> - <char name="arrowhorizex" width="1000"/> - <char name="carriagereturn" width="658"/> - <char name="aleph" width="823"/> - <char name="Ifraktur" width="686"/> - <char name="Rfraktur" width="795"/> - <char name="weierstrass" width="987"/> - <char name="circlemultiply" width="768"/> - <char name="circleplus" width="768"/> - <char name="emptyset" width="823"/> - <char name="intersection" width="768"/> - <char name="union" width="768"/> - <char name="propersuperset" width="713"/> - <char name="reflexsuperset" width="713"/> - <char name="notsubset" width="713"/> - <char name="propersubset" width="713"/> - <char name="reflexsubset" width="713"/> - <char name="element" width="713"/> - <char name="notelement" width="713"/> - <char name="angle" width="768"/> - <char name="gradient" width="713"/> - <char name="registerserif" width="790"/> - <char name="copyrightserif" width="790"/> - <char name="trademarkserif" width="890"/> - <char name="product" width="823"/> - <char name="radical" width="549"/> - <char name="dotmath" width="250"/> - <char name="logicalnot" width="713"/> - <char name="logicaland" width="603"/> - <char name="logicalor" width="603"/> - <char name="arrowdblboth" width="1042"/> - <char name="arrowdblleft" width="987"/> - <char name="arrowdblup" width="603"/> - <char name="arrowdblright" width="987"/> - <char name="arrowdbldown" width="603"/> - <char name="lozenge" width="494"/> - <char name="angleleft" width="329"/> - <char name="registersans" width="790"/> - <char name="copyrightsans" width="790"/> - <char name="trademarksans" width="786"/> - <char name="summation" width="713"/> - <char name="parenlefttp" width="384"/> - <char name="parenleftex" width="384"/> - <char name="parenleftbt" width="384"/> - <char name="bracketlefttp" width="384"/> - <char name="bracketleftex" width="384"/> - <char name="bracketleftbt" width="384"/> - <char name="bracelefttp" width="494"/> - <char name="braceleftmid" width="494"/> - <char name="braceleftbt" width="494"/> - <char name="braceex" width="494"/> - <char name="angleright" width="329"/> - <char name="integral" width="274"/> - <char name="integraltp" width="686"/> - <char name="integralex" width="686"/> - <char name="integralbt" width="686"/> - <char name="parenrighttp" width="384"/> - <char name="parenrightex" width="384"/> - <char name="parenrightbt" width="384"/> - <char name="bracketrighttp" width="384"/> - <char name="bracketrightex" width="384"/> - <char name="bracketrightbt" width="384"/> - <char name="bracerighttp" width="494"/> - <char name="bracerightmid" width="494"/> - <char name="bracerightbt" width="494"/> - <char name="apple" width="790"/> - </widths> + <char-metrics> + <char name="space" width="250" llx="0" lly="0" urx="0" ury="0"/> + <char name="exclam" width="333" llx="128" lly="-17" urx="240" ury="672"/> + <char name="universal" width="713" llx="31" lly="0" urx="681" ury="705"/> + <char name="numbersign" width="500" llx="20" lly="-16" urx="481" ury="673"/> + <char name="existential" width="549" llx="25" lly="0" urx="478" ury="707"/> + <char name="percent" width="833" llx="63" lly="-36" urx="771" ury="655"/> + <char name="ampersand" width="778" llx="41" lly="-18" urx="750" ury="661"/> + <char name="suchthat" width="439" llx="48" lly="-17" urx="414" ury="500"/> + <char name="parenleft" width="333" llx="53" lly="-191" urx="300" ury="673"/> + <char name="parenright" width="333" llx="30" lly="-191" urx="277" ury="673"/> + <char name="asteriskmath" width="500" llx="65" lly="134" urx="427" ury="551"/> + <char name="plus" width="549" llx="10" lly="0" urx="539" ury="533"/> + <char name="comma" width="250" llx="56" lly="-152" urx="194" ury="104"/> + <char name="minus" width="549" llx="11" lly="233" urx="535" ury="288"/> + <char name="period" width="250" llx="69" lly="-17" urx="181" ury="95"/> + <char name="slash" width="278" llx="0" lly="-18" urx="254" ury="646"/> + <char name="zero" width="500" llx="24" lly="-14" urx="476" ury="685"/> + <char name="one" width="500" llx="117" lly="0" urx="390" ury="673"/> + <char name="two" width="500" llx="25" lly="0" urx="475" ury="685"/> + <char name="three" width="500" llx="43" lly="-14" urx="435" ury="685"/> + <char name="four" width="500" llx="15" lly="0" urx="469" ury="685"/> + <char name="five" width="500" llx="32" lly="-14" urx="445" ury="690"/> + <char name="six" width="500" llx="34" lly="-14" urx="468" ury="685"/> + <char name="seven" width="500" llx="24" lly="-16" urx="448" ury="673"/> + <char name="eight" width="500" llx="56" lly="-14" urx="445" ury="685"/> + <char name="nine" width="500" llx="30" lly="-18" urx="459" ury="685"/> + <char name="colon" width="278" llx="81" lly="-17" urx="193" ury="460"/> + <char name="semicolon" width="278" llx="83" lly="-152" urx="221" ury="460"/> + <char name="less" width="549" llx="26" lly="0" urx="523" ury="522"/> + <char name="equal" width="549" llx="11" lly="141" urx="537" ury="390"/> + <char name="greater" width="549" llx="26" lly="0" urx="523" ury="522"/> + <char name="question" width="444" llx="70" lly="-17" urx="412" ury="686"/> + <char name="congruent" width="549" llx="11" lly="0" urx="537" ury="475"/> + <char name="Alpha" width="722" llx="4" lly="0" urx="684" ury="673"/> + <char name="Beta" width="667" llx="29" lly="0" urx="592" ury="673"/> + <char name="Chi" width="722" llx="-9" lly="0" urx="704" ury="673"/> + <char name="Delta" width="612" llx="6" lly="0" urx="608" ury="688"/> + <char name="Epsilon" width="611" llx="32" lly="0" urx="617" ury="673"/> + <char name="Phi" width="763" llx="26" lly="0" urx="741" ury="673"/> + <char name="Gamma" width="603" llx="24" lly="0" urx="609" ury="673"/> + <char name="Eta" width="722" llx="39" lly="0" urx="729" ury="673"/> + <char name="Iota" width="333" llx="32" lly="0" urx="316" ury="673"/> + <char name="theta1" width="631" llx="18" lly="-18" urx="623" ury="689"/> + <char name="Kappa" width="722" llx="35" lly="0" urx="722" ury="673"/> + <char name="Lambda" width="686" llx="6" lly="0" urx="680" ury="688"/> + <char name="Mu" width="889" llx="28" lly="0" urx="887" ury="673"/> + <char name="Nu" width="722" llx="29" lly="-8" urx="720" ury="673"/> + <char name="Omicron" width="722" llx="41" lly="-17" urx="715" ury="685"/> + <char name="Pi" width="768" llx="25" lly="0" urx="745" ury="673"/> + <char name="Theta" width="741" llx="41" lly="-17" urx="715" ury="685"/> + <char name="Rho" width="556" llx="28" lly="0" urx="563" ury="673"/> + <char name="Sigma" width="592" llx="5" lly="0" urx="589" ury="673"/> + <char name="Tau" width="611" llx="33" lly="0" urx="607" ury="673"/> + <char name="Upsilon" width="690" llx="-8" lly="0" urx="694" ury="673"/> + <char name="sigma1" width="439" llx="40" lly="-233" urx="436" ury="500"/> + <char name="Omega" width="768" llx="34" lly="0" urx="736" ury="688"/> + <char name="Xi" width="645" llx="40" lly="0" urx="599" ury="673"/> + <char name="Psi" width="795" llx="15" lly="0" urx="781" ury="684"/> + <char name="Zeta" width="611" llx="44" lly="0" urx="636" ury="673"/> + <char name="bracketleft" width="333" llx="86" lly="-155" urx="299" ury="674"/> + <char name="therefore" width="863" llx="163" lly="0" urx="701" ury="487"/> + <char name="bracketright" width="333" llx="33" lly="-155" urx="246" ury="674"/> + <char name="perpendicular" width="658" llx="15" lly="0" urx="652" ury="674"/> + <char name="underscore" width="500" llx="-2" lly="-125" urx="502" ury="-75"/> + <char name="radicalex" width="500" llx="480" lly="881" urx="1090" ury="917"/> + <char name="alpha" width="631" llx="41" lly="-18" urx="622" ury="500"/> + <char name="beta" width="549" llx="61" lly="-223" urx="515" ury="741"/> + <char name="chi" width="549" llx="12" lly="-231" urx="522" ury="499"/> + <char name="delta" width="494" llx="40" lly="-19" urx="481" ury="740"/> + <char name="epsilon" width="439" llx="22" lly="-19" urx="427" ury="502"/> + <char name="phi" width="521" llx="28" lly="-224" urx="492" ury="673"/> + <char name="gamma" width="411" llx="5" lly="-225" urx="484" ury="499"/> + <char name="eta" width="603" llx="0" lly="-202" urx="527" ury="514"/> + <char name="iota" width="329" llx="0" lly="-17" urx="301" ury="503"/> + <char name="phi1" width="603" llx="36" lly="-224" urx="587" ury="499"/> + <char name="kappa" width="549" llx="33" lly="0" urx="558" ury="501"/> + <char name="lambda" width="549" llx="24" lly="-17" urx="548" ury="739"/> + <char name="mu" width="576" llx="33" lly="-223" urx="567" ury="500"/> + <char name="nu" width="521" llx="-9" lly="-16" urx="475" ury="507"/> + <char name="omicron" width="549" llx="35" lly="-19" urx="501" ury="499"/> + <char name="pi" width="549" llx="10" lly="-19" urx="530" ury="487"/> + <char name="theta" width="521" llx="43" lly="-17" urx="485" ury="690"/> + <char name="rho" width="549" llx="50" lly="-230" urx="490" ury="499"/> + <char name="sigma" width="603" llx="30" lly="-21" urx="588" ury="500"/> + <char name="tau" width="439" llx="10" lly="-19" urx="418" ury="500"/> + <char name="upsilon" width="576" llx="7" lly="-18" urx="535" ury="507"/> + <char name="omega1" width="713" llx="12" lly="-18" urx="671" ury="583"/> + <char name="omega" width="686" llx="42" lly="-17" urx="684" ury="500"/> + <char name="xi" width="493" llx="27" lly="-224" urx="469" ury="766"/> + <char name="psi" width="686" llx="12" lly="-228" urx="701" ury="500"/> + <char name="zeta" width="494" llx="60" lly="-225" urx="467" ury="756"/> + <char name="braceleft" width="480" llx="58" lly="-183" urx="397" ury="673"/> + <char name="bar" width="200" llx="65" lly="-293" urx="135" ury="707"/> + <char name="braceright" width="480" llx="79" lly="-183" urx="418" ury="673"/> + <char name="similar" width="549" llx="17" lly="203" urx="529" ury="307"/> + <char name="Euro" width="750" llx="20" lly="-12" urx="714" ury="685"/> + <char name="Upsilon1" width="620" llx="-2" lly="0" urx="610" ury="685"/> + <char name="minute" width="247" llx="27" lly="459" urx="228" ury="735"/> + <char name="lessequal" width="549" llx="29" lly="0" urx="526" ury="639"/> + <char name="fraction" width="167" llx="-180" lly="-12" urx="340" ury="677"/> + <char name="infinity" width="713" llx="26" lly="124" urx="688" ury="404"/> + <char name="florin" width="500" llx="2" lly="-193" urx="494" ury="686"/> + <char name="club" width="753" llx="86" lly="-26" urx="660" ury="533"/> + <char name="diamond" width="753" llx="142" lly="-36" urx="600" ury="550"/> + <char name="heart" width="753" llx="117" lly="-33" urx="631" ury="532"/> + <char name="spade" width="753" llx="113" lly="-36" urx="629" ury="548"/> + <char name="arrowboth" width="1042" llx="24" lly="-15" urx="1024" ury="511"/> + <char name="arrowleft" width="987" llx="32" lly="-15" urx="942" ury="511"/> + <char name="arrowup" width="603" llx="45" lly="0" urx="571" ury="910"/> + <char name="arrowright" width="987" llx="49" lly="-15" urx="959" ury="511"/> + <char name="arrowdown" width="603" llx="45" lly="-22" urx="571" ury="888"/> + <char name="degree" width="400" llx="50" lly="385" urx="350" ury="685"/> + <char name="plusminus" width="549" llx="10" lly="0" urx="539" ury="645"/> + <char name="second" width="411" llx="20" lly="459" urx="413" ury="737"/> + <char name="greaterequal" width="549" llx="29" lly="0" urx="526" ury="639"/> + <char name="multiply" width="549" llx="17" lly="8" urx="533" ury="524"/> + <char name="proportional" width="713" llx="27" lly="123" urx="639" ury="404"/> + <char name="partialdiff" width="494" llx="26" lly="-20" urx="462" ury="746"/> + <char name="bullet" width="460" llx="50" lly="113" urx="410" ury="473"/> + <char name="divide" width="549" llx="10" lly="71" urx="536" ury="456"/> + <char name="notequal" width="549" llx="15" lly="-25" urx="540" ury="549"/> + <char name="equivalence" width="549" llx="14" lly="82" urx="538" ury="443"/> + <char name="approxequal" width="549" llx="14" lly="135" urx="527" ury="394"/> + <char name="ellipsis" width="1000" llx="111" lly="-17" urx="889" ury="95"/> + <char name="arrowvertex" width="603" llx="280" lly="-120" urx="336" ury="1010"/> + <char name="arrowhorizex" width="1000" llx="-60" lly="220" urx="1050" ury="276"/> + <char name="carriagereturn" width="658" llx="15" lly="-16" urx="602" ury="629"/> + <char name="aleph" width="823" llx="175" lly="-18" urx="661" ury="658"/> + <char name="Ifraktur" width="686" llx="10" lly="-53" urx="578" ury="740"/> + <char name="Rfraktur" width="795" llx="26" lly="-15" urx="759" ury="734"/> + <char name="weierstrass" width="987" llx="159" lly="-211" urx="870" ury="573"/> + <char name="circlemultiply" width="768" llx="43" lly="-17" urx="733" ury="673"/> + <char name="circleplus" width="768" llx="43" lly="-15" urx="733" ury="675"/> + <char name="emptyset" width="823" llx="39" lly="-24" urx="781" ury="719"/> + <char name="intersection" width="768" llx="40" lly="0" urx="732" ury="509"/> + <char name="union" width="768" llx="40" lly="-17" urx="732" ury="492"/> + <char name="propersuperset" width="713" llx="20" lly="0" urx="673" ury="470"/> + <char name="reflexsuperset" width="713" llx="20" lly="-125" urx="673" ury="470"/> + <char name="notsubset" width="713" llx="36" lly="-70" urx="690" ury="540"/> + <char name="propersubset" width="713" llx="37" lly="0" urx="690" ury="470"/> + <char name="reflexsubset" width="713" llx="37" lly="-125" urx="690" ury="470"/> + <char name="element" width="713" llx="45" lly="0" urx="505" ury="468"/> + <char name="notelement" width="713" llx="45" lly="-58" urx="505" ury="555"/> + <char name="angle" width="768" llx="26" lly="0" urx="738" ury="673"/> + <char name="gradient" width="713" llx="36" lly="-19" urx="681" ury="718"/> + <char name="registerserif" width="790" llx="50" lly="-17" urx="740" ury="673"/> + <char name="copyrightserif" width="790" llx="51" lly="-15" urx="741" ury="675"/> + <char name="trademarkserif" width="890" llx="18" lly="293" urx="855" ury="673"/> + <char name="product" width="823" llx="25" lly="-101" urx="803" ury="751"/> + <char name="radical" width="549" llx="10" lly="-38" urx="515" ury="917"/> + <char name="dotmath" width="250" llx="69" lly="210" urx="169" ury="310"/> + <char name="logicalnot" width="713" llx="15" lly="0" urx="680" ury="288"/> + <char name="logicaland" width="603" llx="23" lly="0" urx="583" ury="454"/> + <char name="logicalor" width="603" llx="30" lly="0" urx="578" ury="477"/> + <char name="arrowdblboth" width="1042" llx="27" lly="-20" urx="1023" ury="510"/> + <char name="arrowdblleft" width="987" llx="30" lly="-15" urx="939" ury="513"/> + <char name="arrowdblup" width="603" llx="39" lly="2" urx="567" ury="911"/> + <char name="arrowdblright" width="987" llx="45" lly="-20" urx="954" ury="508"/> + <char name="arrowdbldown" width="603" llx="44" lly="-19" urx="572" ury="890"/> + <char name="lozenge" width="494" llx="18" lly="0" urx="466" ury="745"/> + <char name="angleleft" width="329" llx="25" lly="-198" urx="306" ury="746"/> + <char name="registersans" width="790" llx="50" lly="-20" urx="740" ury="670"/> + <char name="copyrightsans" width="790" llx="49" lly="-15" urx="739" ury="675"/> + <char name="trademarksans" width="786" llx="5" lly="293" urx="725" ury="673"/> + <char name="summation" width="713" llx="14" lly="-108" urx="695" ury="752"/> + <char name="parenlefttp" width="384" llx="24" lly="-293" urx="436" ury="926"/> + <char name="parenleftex" width="384" llx="24" lly="-85" urx="108" ury="925"/> + <char name="parenleftbt" width="384" llx="24" lly="-293" urx="436" ury="926"/> + <char name="bracketlefttp" width="384" llx="0" lly="-80" urx="349" ury="926"/> + <char name="bracketleftex" width="384" llx="0" lly="-79" urx="77" ury="925"/> + <char name="bracketleftbt" width="384" llx="0" lly="-80" urx="349" ury="926"/> + <char name="bracelefttp" width="494" llx="209" lly="-85" urx="445" ury="925"/> + <char name="braceleftmid" width="494" llx="20" lly="-85" urx="284" ury="935"/> + <char name="braceleftbt" width="494" llx="209" lly="-75" urx="445" ury="935"/> + <char name="braceex" width="494" llx="209" lly="-85" urx="284" ury="935"/> + <char name="angleright" width="329" llx="21" lly="-198" urx="302" ury="746"/> + <char name="integral" width="274" llx="2" lly="-107" urx="291" ury="916"/> + <char name="integraltp" width="686" llx="308" lly="-88" urx="675" ury="920"/> + <char name="integralex" width="686" llx="308" lly="-88" urx="378" ury="975"/> + <char name="integralbt" width="686" llx="11" lly="-87" urx="378" ury="921"/> + <char name="parenrighttp" width="384" llx="54" lly="-293" urx="466" ury="926"/> + <char name="parenrightex" width="384" llx="382" lly="-85" urx="466" ury="925"/> + <char name="parenrightbt" width="384" llx="54" lly="-293" urx="466" ury="926"/> + <char name="bracketrighttp" width="384" llx="22" lly="-80" urx="371" ury="926"/> + <char name="bracketrightex" width="384" llx="294" lly="-79" urx="371" ury="925"/> + <char name="bracketrightbt" width="384" llx="22" lly="-80" urx="371" ury="926"/> + <char name="bracerighttp" width="494" llx="48" lly="-85" urx="284" ury="925"/> + <char name="bracerightmid" width="494" llx="209" lly="-85" urx="473" ury="935"/> + <char name="bracerightbt" width="494" llx="48" lly="-75" urx="284" ury="935"/> + <char name="apple" width="790" llx="56" lly="-3" urx="733" ury="808"/> + </char-metrics> </font-metrics> diff --git a/src/codegen/fonts/TimesBold.xml b/src/codegen/fonts/TimesBold.xml index 20d50fdd8..ef5d6bcc0 100644 --- a/src/codegen/fonts/TimesBold.xml +++ b/src/codegen/fonts/TimesBold.xml @@ -22,245 +22,246 @@ <family-name>Times</family-name> <class-name>TimesBold</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>676</cap-height> <x-height>461</x-height> <ascender>676</ascender> <descender>-205</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="722"/> - <char name="AE" width="1000"/> - <char name="Aacute" width="722"/> - <char name="Acircumflex" width="722"/> - <char name="Adieresis" width="722"/> - <char name="Agrave" width="722"/> - <char name="Aring" width="722"/> - <char name="Atilde" width="722"/> - <char name="B" width="667"/> - <char name="C" width="722"/> - <char name="Ccedilla" width="722"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="500"/> - <char name="F" width="611"/> - <char name="G" width="778"/> - <char name="H" width="778"/> - <char name="I" width="389"/> - <char name="Iacute" width="389"/> - <char name="Icircumflex" width="389"/> - <char name="Idieresis" width="389"/> - <char name="Igrave" width="389"/> - <char name="J" width="500"/> - <char name="K" width="778"/> - <char name="L" width="667"/> - <char name="Lslash" width="667"/> - <char name="M" width="944"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="778"/> - <char name="OE" width="1000"/> - <char name="Oacute" width="778"/> - <char name="Ocircumflex" width="778"/> - <char name="Odieresis" width="778"/> - <char name="Ograve" width="778"/> - <char name="Oslash" width="778"/> - <char name="Otilde" width="778"/> - <char name="P" width="611"/> - <char name="Q" width="778"/> - <char name="R" width="722"/> - <char name="S" width="556"/> - <char name="Scaron" width="556"/> - <char name="T" width="667"/> - <char name="Thorn" width="611"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="722"/> - <char name="W" width="1000"/> - <char name="X" width="722"/> - <char name="Y" width="722"/> - <char name="Yacute" width="722"/> - <char name="Ydieresis" width="722"/> - <char name="Z" width="667"/> - <char name="Zcaron" width="667"/> - <char name="a" width="500"/> - <char name="aacute" width="500"/> - <char name="acircumflex" width="500"/> - <char name="acute" width="333"/> - <char name="adieresis" width="500"/> - <char name="ae" width="722"/> - <char name="agrave" width="500"/> - <char name="ampersand" width="833"/> - <char name="aring" width="500"/> - <char name="asciicircum" width="581"/> - <char name="asciitilde" width="520"/> - <char name="asterisk" width="500"/> - <char name="at" width="930"/> - <char name="atilde" width="500"/> - <char name="b" width="556"/> - <char name="backslash" width="278"/> - <char name="bar" width="220"/> - <char name="braceleft" width="394"/> - <char name="braceright" width="394"/> - <char name="bracketleft" width="333"/> - <char name="bracketright" width="333"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="220"/> - <char name="bullet" width="350"/> - <char name="c" width="444"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="444"/> - <char name="cedilla" width="333"/> - <char name="cent" width="500"/> - <char name="circumflex" width="333"/> - <char name="colon" width="333"/> - <char name="comma" width="250"/> - <char name="copyright" width="747"/> - <char name="currency" width="500"/> - <char name="d" width="556"/> - <char name="dagger" width="500"/> - <char name="daggerdbl" width="500"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="570"/> - <char name="dollar" width="500"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="444"/> - <char name="eacute" width="444"/> - <char name="ecircumflex" width="444"/> - <char name="edieresis" width="444"/> - <char name="egrave" width="444"/> - <char name="eight" width="500"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="500"/> - <char name="equal" width="570"/> - <char name="eth" width="500"/> - <char name="exclam" width="333"/> - <char name="exclamdown" width="333"/> - <char name="f" width="333"/> - <char name="fi" width="556"/> - <char name="five" width="500"/> - <char name="fl" width="556"/> - <char name="florin" width="500"/> - <char name="four" width="500"/> - <char name="fraction" width="167"/> - <char name="g" width="500"/> - <char name="germandbls" width="556"/> - <char name="grave" width="333"/> - <char name="greater" width="570"/> - <char name="guillemotleft" width="500"/> - <char name="guillemotright" width="500"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="556"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="333"/> - <char name="k" width="556"/> - <char name="l" width="278"/> - <char name="less" width="570"/> - <char name="logicalnot" width="570"/> - <char name="lslash" width="278"/> - <char name="m" width="833"/> - <char name="macron" width="333"/> - <char name="minus" width="324"/> - <char name="mu" width="556"/> - <char name="multiply" width="570"/> - <char name="n" width="556"/> - <char name="nine" width="500"/> - <char name="ntilde" width="556"/> - <char name="numbersign" width="500"/> - <char name="o" width="500"/> - <char name="oacute" width="500"/> - <char name="ocircumflex" width="500"/> - <char name="odieresis" width="500"/> - <char name="oe" width="722"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="500"/> - <char name="one" width="500"/> - <char name="onehalf" width="750"/> - <char name="onequarter" width="750"/> - <char name="onesuperior" width="300"/> - <char name="ordfeminine" width="300"/> - <char name="ordmasculine" width="330"/> - <char name="oslash" width="500"/> - <char name="otilde" width="500"/> - <char name="p" width="556"/> - <char name="paragraph" width="540"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="1000"/> - <char name="period" width="250"/> - <char name="periodcentered" width="250"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="570"/> - <char name="plusminus" width="570"/> - <char name="q" width="556"/> - <char name="question" width="500"/> - <char name="questiondown" width="500"/> - <char name="quotedbl" width="555"/> - <char name="quotedblbase" width="500"/> - <char name="quotedblleft" width="500"/> - <char name="quotedblright" width="500"/> - <char name="quoteleft" width="333"/> - <char name="quoteright" width="333"/> - <char name="quotesinglbase" width="333"/> - <char name="quotesingle" width="278"/> - <char name="r" width="444"/> - <char name="registered" width="747"/> - <char name="ring" width="333"/> - <char name="s" width="389"/> - <char name="scaron" width="389"/> - <char name="section" width="500"/> - <char name="semicolon" width="333"/> - <char name="seven" width="500"/> - <char name="six" width="500"/> - <char name="slash" width="278"/> - <char name="space" width="250"/> + <char-metrics> + <char name="A" width="722" llx="9" lly="0" urx="689" ury="690"/> + <char name="AE" width="1000" llx="4" lly="0" urx="951" ury="676"/> + <char name="Aacute" width="722" llx="9" lly="0" urx="689" ury="923"/> + <char name="Acircumflex" width="722" llx="9" lly="0" urx="689" ury="914"/> + <char name="Adieresis" width="722" llx="9" lly="0" urx="689" ury="877"/> + <char name="Agrave" width="722" llx="9" lly="0" urx="689" ury="923"/> + <char name="Aring" width="722" llx="9" lly="0" urx="689" ury="935"/> + <char name="Atilde" width="722" llx="9" lly="0" urx="689" ury="884"/> + <char name="B" width="667" llx="16" lly="0" urx="619" ury="676"/> + <char name="C" width="722" llx="49" lly="-19" urx="687" ury="691"/> + <char name="Ccedilla" width="722" llx="49" lly="-218" urx="687" ury="691"/> + <char name="D" width="722" llx="14" lly="0" urx="690" ury="676"/> + <char name="E" width="667" llx="16" lly="0" urx="641" ury="676"/> + <char name="Eacute" width="667" llx="16" lly="0" urx="641" ury="923"/> + <char name="Ecircumflex" width="667" llx="16" lly="0" urx="641" ury="914"/> + <char name="Edieresis" width="667" llx="16" lly="0" urx="641" ury="877"/> + <char name="Egrave" width="667" llx="16" lly="0" urx="641" ury="923"/> + <char name="Eth" width="722" llx="6" lly="0" urx="690" ury="676"/> + <char name="Euro" width="500" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="16" lly="0" urx="583" ury="676"/> + <char name="G" width="778" llx="37" lly="-19" urx="755" ury="691"/> + <char name="H" width="778" llx="21" lly="0" urx="759" ury="676"/> + <char name="I" width="389" llx="20" lly="0" urx="370" ury="676"/> + <char name="Iacute" width="389" llx="20" lly="0" urx="370" ury="923"/> + <char name="Icircumflex" width="389" llx="20" lly="0" urx="370" ury="914"/> + <char name="Idieresis" width="389" llx="20" lly="0" urx="370" ury="877"/> + <char name="Igrave" width="389" llx="20" lly="0" urx="370" ury="923"/> + <char name="J" width="500" llx="3" lly="-96" urx="479" ury="676"/> + <char name="K" width="778" llx="30" lly="0" urx="769" ury="676"/> + <char name="L" width="667" llx="19" lly="0" urx="638" ury="676"/> + <char name="Lslash" width="667" llx="19" lly="0" urx="638" ury="676"/> + <char name="M" width="944" llx="14" lly="0" urx="921" ury="676"/> + <char name="N" width="722" llx="16" lly="-18" urx="701" ury="676"/> + <char name="Ntilde" width="722" llx="16" lly="-18" urx="701" ury="884"/> + <char name="O" width="778" llx="35" lly="-19" urx="743" ury="691"/> + <char name="OE" width="1000" llx="22" lly="-5" urx="981" ury="684"/> + <char name="Oacute" width="778" llx="35" lly="-19" urx="743" ury="923"/> + <char name="Ocircumflex" width="778" llx="35" lly="-19" urx="743" ury="914"/> + <char name="Odieresis" width="778" llx="35" lly="-19" urx="743" ury="877"/> + <char name="Ograve" width="778" llx="35" lly="-19" urx="743" ury="923"/> + <char name="Oslash" width="778" llx="35" lly="-74" urx="743" ury="737"/> + <char name="Otilde" width="778" llx="35" lly="-19" urx="743" ury="884"/> + <char name="P" width="611" llx="16" lly="0" urx="600" ury="676"/> + <char name="Q" width="778" llx="35" lly="-176" urx="743" ury="691"/> + <char name="R" width="722" llx="26" lly="0" urx="715" ury="676"/> + <char name="S" width="556" llx="35" lly="-19" urx="513" ury="692"/> + <char name="Scaron" width="556" llx="35" lly="-19" urx="513" ury="914"/> + <char name="T" width="667" llx="31" lly="0" urx="636" ury="676"/> + <char name="Thorn" width="611" llx="16" lly="0" urx="600" ury="676"/> + <char name="U" width="722" llx="16" lly="-19" urx="701" ury="676"/> + <char name="Uacute" width="722" llx="16" lly="-19" urx="701" ury="923"/> + <char name="Ucircumflex" width="722" llx="16" lly="-19" urx="701" ury="914"/> + <char name="Udieresis" width="722" llx="16" lly="-19" urx="701" ury="877"/> + <char name="Ugrave" width="722" llx="16" lly="-19" urx="701" ury="923"/> + <char name="V" width="722" llx="16" lly="-18" urx="701" ury="676"/> + <char name="W" width="1000" llx="19" lly="-15" urx="981" ury="676"/> + <char name="X" width="722" llx="16" lly="0" urx="699" ury="676"/> + <char name="Y" width="722" llx="15" lly="0" urx="699" ury="676"/> + <char name="Yacute" width="722" llx="15" lly="0" urx="699" ury="923"/> + <char name="Ydieresis" width="722" llx="15" lly="0" urx="699" ury="877"/> + <char name="Z" width="667" llx="28" lly="0" urx="634" ury="676"/> + <char name="Zcaron" width="667" llx="28" lly="0" urx="634" ury="914"/> + <char name="a" width="500" llx="25" lly="-14" urx="488" ury="473"/> + <char name="aacute" width="500" llx="25" lly="-14" urx="488" ury="713"/> + <char name="acircumflex" width="500" llx="25" lly="-14" urx="488" ury="704"/> + <char name="acute" width="333" llx="86" lly="528" urx="324" ury="713"/> + <char name="adieresis" width="500" llx="25" lly="-14" urx="488" ury="667"/> + <char name="ae" width="722" llx="33" lly="-14" urx="693" ury="473"/> + <char name="agrave" width="500" llx="25" lly="-14" urx="488" ury="713"/> + <char name="ampersand" width="833" llx="62" lly="-16" urx="787" ury="691"/> + <char name="aring" width="500" llx="25" lly="-14" urx="488" ury="740"/> + <char name="asciicircum" width="581" llx="73" lly="311" urx="509" ury="676"/> + <char name="asciitilde" width="520" llx="29" lly="173" urx="491" ury="333"/> + <char name="asterisk" width="500" llx="56" lly="255" urx="447" ury="691"/> + <char name="at" width="930" llx="108" lly="-19" urx="822" ury="691"/> + <char name="atilde" width="500" llx="25" lly="-14" urx="488" ury="674"/> + <char name="b" width="556" llx="17" lly="-14" urx="521" ury="676"/> + <char name="backslash" width="278" llx="-25" lly="-19" urx="303" ury="691"/> + <char name="bar" width="220" llx="66" lly="-218" urx="154" ury="782"/> + <char name="braceleft" width="394" llx="22" lly="-175" urx="340" ury="698"/> + <char name="braceright" width="394" llx="54" lly="-175" urx="372" ury="698"/> + <char name="bracketleft" width="333" llx="67" lly="-149" urx="301" ury="678"/> + <char name="bracketright" width="333" llx="32" lly="-149" urx="266" ury="678"/> + <char name="breve" width="333" llx="15" lly="528" urx="318" ury="691"/> + <char name="brokenbar" width="220" llx="66" lly="-143" urx="154" ury="707"/> + <char name="bullet" width="350" llx="35" lly="198" urx="315" ury="478"/> + <char name="c" width="444" llx="25" lly="-14" urx="430" ury="473"/> + <char name="caron" width="333" llx="-2" lly="528" urx="335" ury="704"/> + <char name="ccedilla" width="444" llx="25" lly="-218" urx="430" ury="473"/> + <char name="cedilla" width="333" llx="68" lly="-218" urx="294" ury="0"/> + <char name="cent" width="500" llx="53" lly="-140" urx="458" ury="588"/> + <char name="circumflex" width="333" llx="-2" lly="528" urx="335" ury="704"/> + <char name="colon" width="333" llx="82" lly="-13" urx="251" ury="472"/> + <char name="comma" width="250" llx="39" lly="-180" urx="223" ury="155"/> + <char name="copyright" width="747" llx="26" lly="-19" urx="721" ury="691"/> + <char name="currency" width="500" llx="-26" lly="61" urx="526" ury="613"/> + <char name="d" width="556" llx="25" lly="-14" urx="534" ury="676"/> + <char name="dagger" width="500" llx="47" lly="-134" urx="453" ury="691"/> + <char name="daggerdbl" width="500" llx="45" lly="-132" urx="456" ury="691"/> + <char name="degree" width="400" llx="57" lly="402" urx="343" ury="688"/> + <char name="dieresis" width="333" llx="-2" lly="537" urx="335" ury="667"/> + <char name="divide" width="570" llx="33" lly="-31" urx="537" ury="537"/> + <char name="dollar" width="500" llx="29" lly="-99" urx="472" ury="750"/> + <char name="dotaccent" width="333" llx="103" lly="536" urx="258" ury="691"/> + <char name="dotlessi" width="278" llx="16" lly="0" urx="255" ury="461"/> + <char name="e" width="444" llx="25" lly="-14" urx="426" ury="473"/> + <char name="eacute" width="444" llx="25" lly="-14" urx="426" ury="713"/> + <char name="ecircumflex" width="444" llx="25" lly="-14" urx="426" ury="704"/> + <char name="edieresis" width="444" llx="25" lly="-14" urx="426" ury="667"/> + <char name="egrave" width="444" llx="25" lly="-14" urx="426" ury="713"/> + <char name="eight" width="500" llx="28" lly="-13" urx="472" ury="688"/> + <char name="ellipsis" width="1000" llx="82" lly="-13" urx="917" ury="156"/> + <char name="emdash" width="1000" llx="0" lly="181" urx="1000" ury="271"/> + <char name="endash" width="500" llx="0" lly="181" urx="500" ury="271"/> + <char name="equal" width="570" llx="33" lly="107" urx="537" ury="399"/> + <char name="eth" width="500" llx="25" lly="-14" urx="476" ury="691"/> + <char name="exclam" width="333" llx="81" lly="-13" urx="251" ury="691"/> + <char name="exclamdown" width="333" llx="82" lly="-203" urx="252" ury="501"/> + <char name="f" width="333" llx="14" lly="0" urx="389" ury="691"/> + <char name="fi" width="556" llx="14" lly="0" urx="536" ury="691"/> + <char name="five" width="500" llx="22" lly="-8" urx="470" ury="676"/> + <char name="fl" width="556" llx="14" lly="0" urx="536" ury="691"/> + <char name="florin" width="500" llx="0" lly="-155" urx="498" ury="706"/> + <char name="four" width="500" llx="19" lly="0" urx="475" ury="688"/> + <char name="fraction" width="167" llx="-168" lly="-12" urx="329" ury="688"/> + <char name="g" width="500" llx="28" lly="-206" urx="483" ury="473"/> + <char name="germandbls" width="556" llx="19" lly="-12" urx="517" ury="691"/> + <char name="grave" width="333" llx="8" lly="528" urx="246" ury="713"/> + <char name="greater" width="570" llx="31" lly="-8" urx="539" ury="514"/> + <char name="guillemotleft" width="500" llx="23" lly="36" urx="473" ury="415"/> + <char name="guillemotright" width="500" llx="27" lly="36" urx="477" ury="415"/> + <char name="guilsinglleft" width="333" llx="51" lly="36" urx="305" ury="415"/> + <char name="guilsinglright" width="333" llx="28" lly="36" urx="282" ury="415"/> + <char name="h" width="556" llx="16" lly="0" urx="534" ury="676"/> + <char name="hungarumlaut" width="333" llx="-13" lly="528" urx="425" ury="713"/> + <char name="hyphen" width="333" llx="44" lly="171" urx="287" ury="287"/> + <char name="i" width="278" llx="16" lly="0" urx="255" ury="691"/> + <char name="iacute" width="278" llx="16" lly="0" urx="289" ury="713"/> + <char name="icircumflex" width="278" llx="-37" lly="0" urx="300" ury="704"/> + <char name="idieresis" width="278" llx="-37" lly="0" urx="300" ury="667"/> + <char name="igrave" width="278" llx="-27" lly="0" urx="255" ury="713"/> + <char name="j" width="333" llx="-57" lly="-203" urx="263" ury="691"/> + <char name="k" width="556" llx="22" lly="0" urx="543" ury="676"/> + <char name="l" width="278" llx="16" lly="0" urx="255" ury="676"/> + <char name="less" width="570" llx="31" lly="-8" urx="539" ury="514"/> + <char name="logicalnot" width="570" llx="33" lly="108" urx="537" ury="399"/> + <char name="lslash" width="278" llx="-22" lly="0" urx="303" ury="676"/> + <char name="m" width="833" llx="16" lly="0" urx="814" ury="473"/> + <char name="macron" width="333" llx="1" lly="565" urx="331" ury="637"/> + <char name="minus" width="324" llx="33" lly="209" urx="537" ury="297"/> + <char name="mu" width="556" llx="33" lly="-206" urx="536" ury="461"/> + <char name="multiply" width="570" llx="48" lly="16" urx="522" ury="490"/> + <char name="n" width="556" llx="21" lly="0" urx="539" ury="473"/> + <char name="nine" width="500" llx="26" lly="-13" urx="473" ury="688"/> + <char name="ntilde" width="556" llx="21" lly="0" urx="539" ury="674"/> + <char name="numbersign" width="500" llx="4" lly="0" urx="496" ury="700"/> + <char name="o" width="500" llx="25" lly="-14" urx="476" ury="473"/> + <char name="oacute" width="500" llx="25" lly="-14" urx="476" ury="713"/> + <char name="ocircumflex" width="500" llx="25" lly="-14" urx="476" ury="704"/> + <char name="odieresis" width="500" llx="25" lly="-14" urx="476" ury="667"/> + <char name="oe" width="722" llx="22" lly="-14" urx="696" ury="473"/> + <char name="ogonek" width="333" llx="90" lly="-193" urx="319" ury="24"/> + <char name="ograve" width="500" llx="25" lly="-14" urx="476" ury="713"/> + <char name="one" width="500" llx="65" lly="0" urx="442" ury="688"/> + <char name="onehalf" width="750" llx="-7" lly="-12" urx="775" ury="688"/> + <char name="onequarter" width="750" llx="28" lly="-12" urx="743" ury="688"/> + <char name="onesuperior" width="300" llx="28" lly="275" urx="273" ury="688"/> + <char name="ordfeminine" width="300" llx="-1" lly="397" urx="301" ury="688"/> + <char name="ordmasculine" width="330" llx="18" lly="397" urx="312" ury="688"/> + <char name="oslash" width="500" llx="25" lly="-92" urx="476" ury="549"/> + <char name="otilde" width="500" llx="25" lly="-14" urx="476" ury="674"/> + <char name="p" width="556" llx="19" lly="-205" urx="524" ury="473"/> + <char name="paragraph" width="540" llx="0" lly="-186" urx="519" ury="676"/> + <char name="parenleft" width="333" llx="46" lly="-168" urx="306" ury="694"/> + <char name="parenright" width="333" llx="27" lly="-168" urx="287" ury="694"/> + <char name="percent" width="1000" llx="124" lly="-14" urx="877" ury="692"/> + <char name="period" width="250" llx="41" lly="-13" urx="210" ury="156"/> + <char name="periodcentered" width="250" llx="41" lly="248" urx="210" ury="417"/> + <char name="perthousand" width="1000" llx="7" lly="-29" urx="995" ury="706"/> + <char name="plus" width="570" llx="33" lly="0" urx="537" ury="506"/> + <char name="plusminus" width="570" llx="33" lly="0" urx="537" ury="506"/> + <char name="q" width="556" llx="34" lly="-205" urx="536" ury="473"/> + <char name="question" width="500" llx="57" lly="-13" urx="445" ury="689"/> + <char name="questiondown" width="500" llx="55" lly="-201" urx="443" ury="501"/> + <char name="quotedbl" width="555" llx="83" lly="404" urx="472" ury="691"/> + <char name="quotedblbase" width="500" llx="14" lly="-180" urx="468" ury="155"/> + <char name="quotedblleft" width="500" llx="32" lly="356" urx="486" ury="691"/> + <char name="quotedblright" width="500" llx="14" lly="356" urx="468" ury="691"/> + <char name="quoteleft" width="333" llx="70" lly="356" urx="254" ury="691"/> + <char name="quoteright" width="333" llx="79" lly="356" urx="263" ury="691"/> + <char name="quotesinglbase" width="333" llx="79" lly="-180" urx="263" ury="155"/> + <char name="quotesingle" width="278" llx="75" lly="404" urx="204" ury="691"/> + <char name="r" width="444" llx="29" lly="0" urx="434" ury="473"/> + <char name="registered" width="747" llx="26" lly="-19" urx="721" ury="691"/> + <char name="ring" width="333" llx="60" lly="527" urx="273" ury="740"/> + <char name="s" width="389" llx="25" lly="-14" urx="361" ury="473"/> + <char name="scaron" width="389" llx="25" lly="-14" urx="363" ury="704"/> + <char name="section" width="500" llx="57" lly="-132" urx="443" ury="691"/> + <char name="semicolon" width="333" llx="82" lly="-180" urx="266" ury="472"/> + <char name="seven" width="500" llx="17" lly="0" urx="477" ury="676"/> + <char name="six" width="500" llx="28" lly="-13" urx="475" ury="688"/> + <char name="slash" width="278" llx="-24" lly="-19" urx="302" ury="691"/> + <char name="space" width="250" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="250"/> - <char name="sterling" width="500"/> - <char name="t" width="333"/> - <char name="thorn" width="556"/> - <char name="three" width="500"/> - <char name="threequarters" width="750"/> - <char name="threesuperior" width="300"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="500"/> - <char name="twosuperior" width="300"/> - <char name="u" width="556"/> - <char name="uacute" width="556"/> - <char name="ucircumflex" width="556"/> - <char name="udieresis" width="556"/> - <char name="ugrave" width="556"/> - <char name="underscore" width="500"/> - <char name="v" width="500"/> - <char name="w" width="722"/> - <char name="x" width="500"/> - <char name="y" width="500"/> - <char name="yacute" width="500"/> - <char name="ydieresis" width="500"/> - <char name="yen" width="500"/> - <char name="z" width="444"/> - <char name="zcaron" width="444"/> - <char name="zero" width="500"/> - </widths> + <char name="sterling" width="500" llx="21" lly="-14" urx="477" ury="684"/> + <char name="t" width="333" llx="20" lly="-12" urx="332" ury="630"/> + <char name="thorn" width="556" llx="19" lly="-205" urx="524" ury="676"/> + <char name="three" width="500" llx="16" lly="-14" urx="468" ury="688"/> + <char name="threequarters" width="750" llx="23" lly="-12" urx="733" ury="688"/> + <char name="threesuperior" width="300" llx="3" lly="268" urx="297" ury="688"/> + <char name="tilde" width="333" llx="-16" lly="547" urx="349" ury="674"/> + <char name="trademark" width="1000" llx="24" lly="271" urx="977" ury="676"/> + <char name="two" width="500" llx="17" lly="0" urx="478" ury="688"/> + <char name="twosuperior" width="300" llx="0" lly="275" urx="300" ury="688"/> + <char name="u" width="556" llx="16" lly="-14" urx="537" ury="461"/> + <char name="uacute" width="556" llx="16" lly="-14" urx="537" ury="713"/> + <char name="ucircumflex" width="556" llx="16" lly="-14" urx="537" ury="704"/> + <char name="udieresis" width="556" llx="16" lly="-14" urx="537" ury="667"/> + <char name="ugrave" width="556" llx="16" lly="-14" urx="537" ury="713"/> + <char name="underscore" width="500" llx="0" lly="-125" urx="500" ury="-75"/> + <char name="v" width="500" llx="21" lly="-14" urx="485" ury="461"/> + <char name="w" width="722" llx="23" lly="-14" urx="707" ury="461"/> + <char name="x" width="500" llx="12" lly="0" urx="484" ury="461"/> + <char name="y" width="500" llx="16" lly="-205" urx="480" ury="461"/> + <char name="yacute" width="500" llx="16" lly="-205" urx="480" ury="713"/> + <char name="ydieresis" width="500" llx="16" lly="-205" urx="480" ury="667"/> + <char name="yen" width="500" llx="-64" lly="0" urx="547" ury="676"/> + <char name="z" width="444" llx="21" lly="0" urx="420" ury="461"/> + <char name="zcaron" width="444" llx="21" lly="0" urx="420" ury="704"/> + <char name="zero" width="500" llx="24" lly="-13" urx="476" ury="688"/> + </char-metrics> <kerning kpx1="79"> <pair kern="-40" kpx2="65"/> <pair kern="-50" kpx2="87"/> diff --git a/src/codegen/fonts/TimesBoldItalic.xml b/src/codegen/fonts/TimesBoldItalic.xml index d1b70872a..ec67369f2 100644 --- a/src/codegen/fonts/TimesBoldItalic.xml +++ b/src/codegen/fonts/TimesBoldItalic.xml @@ -22,245 +22,246 @@ <family-name>Times</family-name> <class-name>TimesBoldItalic</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>669</cap-height> <x-height>462</x-height> <ascender>699</ascender> <descender>-205</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="667"/> - <char name="AE" width="944"/> - <char name="Aacute" width="667"/> - <char name="Acircumflex" width="667"/> - <char name="Adieresis" width="667"/> - <char name="Agrave" width="667"/> - <char name="Aring" width="667"/> - <char name="Atilde" width="667"/> - <char name="B" width="667"/> - <char name="C" width="667"/> - <char name="Ccedilla" width="667"/> - <char name="D" width="722"/> - <char name="E" width="667"/> - <char name="Eacute" width="667"/> - <char name="Ecircumflex" width="667"/> - <char name="Edieresis" width="667"/> - <char name="Egrave" width="667"/> - <char name="Eth" width="722"/> - <char name="Euro" width="500"/> - <char name="F" width="667"/> - <char name="G" width="722"/> - <char name="H" width="778"/> - <char name="I" width="389"/> - <char name="Iacute" width="389"/> - <char name="Icircumflex" width="389"/> - <char name="Idieresis" width="389"/> - <char name="Igrave" width="389"/> - <char name="J" width="500"/> - <char name="K" width="667"/> - <char name="L" width="611"/> - <char name="Lslash" width="611"/> - <char name="M" width="889"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="722"/> - <char name="OE" width="944"/> - <char name="Oacute" width="722"/> - <char name="Ocircumflex" width="722"/> - <char name="Odieresis" width="722"/> - <char name="Ograve" width="722"/> - <char name="Oslash" width="722"/> - <char name="Otilde" width="722"/> - <char name="P" width="611"/> - <char name="Q" width="722"/> - <char name="R" width="667"/> - <char name="S" width="556"/> - <char name="Scaron" width="556"/> - <char name="T" width="611"/> - <char name="Thorn" width="611"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="667"/> - <char name="W" width="889"/> - <char name="X" width="667"/> - <char name="Y" width="611"/> - <char name="Yacute" width="611"/> - <char name="Ydieresis" width="611"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="500"/> - <char name="aacute" width="500"/> - <char name="acircumflex" width="500"/> - <char name="acute" width="333"/> - <char name="adieresis" width="500"/> - <char name="ae" width="722"/> - <char name="agrave" width="500"/> - <char name="ampersand" width="778"/> - <char name="aring" width="500"/> - <char name="asciicircum" width="570"/> - <char name="asciitilde" width="570"/> - <char name="asterisk" width="500"/> - <char name="at" width="832"/> - <char name="atilde" width="500"/> - <char name="b" width="500"/> - <char name="backslash" width="278"/> - <char name="bar" width="220"/> - <char name="braceleft" width="348"/> - <char name="braceright" width="348"/> - <char name="bracketleft" width="333"/> - <char name="bracketright" width="333"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="220"/> - <char name="bullet" width="350"/> - <char name="c" width="444"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="444"/> - <char name="cedilla" width="333"/> - <char name="cent" width="500"/> - <char name="circumflex" width="333"/> - <char name="colon" width="333"/> - <char name="comma" width="250"/> - <char name="copyright" width="747"/> - <char name="currency" width="500"/> - <char name="d" width="500"/> - <char name="dagger" width="500"/> - <char name="daggerdbl" width="500"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="570"/> - <char name="dollar" width="500"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="444"/> - <char name="eacute" width="444"/> - <char name="ecircumflex" width="444"/> - <char name="edieresis" width="444"/> - <char name="egrave" width="444"/> - <char name="eight" width="500"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="500"/> - <char name="equal" width="570"/> - <char name="eth" width="500"/> - <char name="exclam" width="389"/> - <char name="exclamdown" width="389"/> - <char name="f" width="333"/> - <char name="fi" width="556"/> - <char name="five" width="500"/> - <char name="fl" width="556"/> - <char name="florin" width="500"/> - <char name="four" width="500"/> - <char name="fraction" width="167"/> - <char name="g" width="500"/> - <char name="germandbls" width="500"/> - <char name="grave" width="333"/> - <char name="greater" width="570"/> - <char name="guillemotleft" width="500"/> - <char name="guillemotright" width="500"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="556"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="278"/> - <char name="k" width="500"/> - <char name="l" width="278"/> - <char name="less" width="570"/> - <char name="logicalnot" width="606"/> - <char name="lslash" width="278"/> - <char name="m" width="778"/> - <char name="macron" width="333"/> - <char name="minus" width="330"/> - <char name="mu" width="576"/> - <char name="multiply" width="570"/> - <char name="n" width="556"/> - <char name="nine" width="500"/> - <char name="ntilde" width="556"/> - <char name="numbersign" width="500"/> - <char name="o" width="500"/> - <char name="oacute" width="500"/> - <char name="ocircumflex" width="500"/> - <char name="odieresis" width="500"/> - <char name="oe" width="722"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="500"/> - <char name="one" width="500"/> - <char name="onehalf" width="750"/> - <char name="onequarter" width="750"/> - <char name="onesuperior" width="300"/> - <char name="ordfeminine" width="266"/> - <char name="ordmasculine" width="300"/> - <char name="oslash" width="500"/> - <char name="otilde" width="500"/> - <char name="p" width="500"/> - <char name="paragraph" width="500"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="833"/> - <char name="period" width="250"/> - <char name="periodcentered" width="250"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="570"/> - <char name="plusminus" width="570"/> - <char name="q" width="500"/> - <char name="question" width="500"/> - <char name="questiondown" width="500"/> - <char name="quotedbl" width="555"/> - <char name="quotedblbase" width="500"/> - <char name="quotedblleft" width="500"/> - <char name="quotedblright" width="500"/> - <char name="quoteleft" width="333"/> - <char name="quoteright" width="333"/> - <char name="quotesinglbase" width="333"/> - <char name="quotesingle" width="278"/> - <char name="r" width="389"/> - <char name="registered" width="747"/> - <char name="ring" width="333"/> - <char name="s" width="389"/> - <char name="scaron" width="389"/> - <char name="section" width="500"/> - <char name="semicolon" width="333"/> - <char name="seven" width="500"/> - <char name="six" width="500"/> - <char name="slash" width="278"/> - <char name="space" width="250"/> + <char-metrics> + <char name="A" width="667" llx="-67" lly="0" urx="593" ury="683"/> + <char name="AE" width="944" llx="-64" lly="0" urx="918" ury="669"/> + <char name="Aacute" width="667" llx="-67" lly="0" urx="593" ury="904"/> + <char name="Acircumflex" width="667" llx="-67" lly="0" urx="593" ury="897"/> + <char name="Adieresis" width="667" llx="-67" lly="0" urx="593" ury="862"/> + <char name="Agrave" width="667" llx="-67" lly="0" urx="593" ury="904"/> + <char name="Aring" width="667" llx="-67" lly="0" urx="593" ury="921"/> + <char name="Atilde" width="667" llx="-67" lly="0" urx="593" ury="862"/> + <char name="B" width="667" llx="-24" lly="0" urx="624" ury="669"/> + <char name="C" width="667" llx="32" lly="-18" urx="677" ury="685"/> + <char name="Ccedilla" width="667" llx="32" lly="-218" urx="677" ury="685"/> + <char name="D" width="722" llx="-46" lly="0" urx="685" ury="669"/> + <char name="E" width="667" llx="-27" lly="0" urx="653" ury="669"/> + <char name="Eacute" width="667" llx="-27" lly="0" urx="653" ury="904"/> + <char name="Ecircumflex" width="667" llx="-27" lly="0" urx="653" ury="897"/> + <char name="Edieresis" width="667" llx="-27" lly="0" urx="653" ury="862"/> + <char name="Egrave" width="667" llx="-27" lly="0" urx="653" ury="904"/> + <char name="Eth" width="722" llx="-31" lly="0" urx="700" ury="669"/> + <char name="Euro" width="500" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="667" llx="-13" lly="0" urx="660" ury="669"/> + <char name="G" width="722" llx="21" lly="-18" urx="706" ury="685"/> + <char name="H" width="778" llx="-24" lly="0" urx="799" ury="669"/> + <char name="I" width="389" llx="-32" lly="0" urx="406" ury="669"/> + <char name="Iacute" width="389" llx="-32" lly="0" urx="432" ury="904"/> + <char name="Icircumflex" width="389" llx="-32" lly="0" urx="450" ury="897"/> + <char name="Idieresis" width="389" llx="-32" lly="0" urx="450" ury="862"/> + <char name="Igrave" width="389" llx="-32" lly="0" urx="406" ury="904"/> + <char name="J" width="500" llx="-46" lly="-99" urx="524" ury="669"/> + <char name="K" width="667" llx="-21" lly="0" urx="702" ury="669"/> + <char name="L" width="611" llx="-22" lly="0" urx="590" ury="669"/> + <char name="Lslash" width="611" llx="-22" lly="0" urx="590" ury="669"/> + <char name="M" width="889" llx="-29" lly="-12" urx="917" ury="669"/> + <char name="N" width="722" llx="-27" lly="-15" urx="748" ury="669"/> + <char name="Ntilde" width="722" llx="-27" lly="-15" urx="748" ury="862"/> + <char name="O" width="722" llx="27" lly="-18" urx="691" ury="685"/> + <char name="OE" width="944" llx="23" lly="-8" urx="946" ury="677"/> + <char name="Oacute" width="722" llx="27" lly="-18" urx="691" ury="904"/> + <char name="Ocircumflex" width="722" llx="27" lly="-18" urx="691" ury="897"/> + <char name="Odieresis" width="722" llx="27" lly="-18" urx="691" ury="862"/> + <char name="Ograve" width="722" llx="27" lly="-18" urx="691" ury="904"/> + <char name="Oslash" width="722" llx="27" lly="-125" urx="691" ury="764"/> + <char name="Otilde" width="722" llx="27" lly="-18" urx="691" ury="862"/> + <char name="P" width="611" llx="-27" lly="0" urx="613" ury="669"/> + <char name="Q" width="722" llx="27" lly="-208" urx="691" ury="685"/> + <char name="R" width="667" llx="-29" lly="0" urx="623" ury="669"/> + <char name="S" width="556" llx="2" lly="-18" urx="526" ury="685"/> + <char name="Scaron" width="556" llx="2" lly="-18" urx="553" ury="897"/> + <char name="T" width="611" llx="50" lly="0" urx="650" ury="669"/> + <char name="Thorn" width="611" llx="-27" lly="0" urx="573" ury="669"/> + <char name="U" width="722" llx="67" lly="-18" urx="744" ury="669"/> + <char name="Uacute" width="722" llx="67" lly="-18" urx="744" ury="904"/> + <char name="Ucircumflex" width="722" llx="67" lly="-18" urx="744" ury="897"/> + <char name="Udieresis" width="722" llx="67" lly="-18" urx="744" ury="862"/> + <char name="Ugrave" width="722" llx="67" lly="-18" urx="744" ury="904"/> + <char name="V" width="667" llx="65" lly="-18" urx="715" ury="669"/> + <char name="W" width="889" llx="65" lly="-18" urx="940" ury="669"/> + <char name="X" width="667" llx="-24" lly="0" urx="694" ury="669"/> + <char name="Y" width="611" llx="73" lly="0" urx="659" ury="669"/> + <char name="Yacute" width="611" llx="73" lly="0" urx="659" ury="904"/> + <char name="Ydieresis" width="611" llx="73" lly="0" urx="659" ury="862"/> + <char name="Z" width="611" llx="-11" lly="0" urx="590" ury="669"/> + <char name="Zcaron" width="611" llx="-11" lly="0" urx="590" ury="897"/> + <char name="a" width="500" llx="-21" lly="-14" urx="455" ury="462"/> + <char name="aacute" width="500" llx="-21" lly="-14" urx="463" ury="697"/> + <char name="acircumflex" width="500" llx="-21" lly="-14" urx="455" ury="690"/> + <char name="acute" width="333" llx="139" lly="516" urx="379" ury="697"/> + <char name="adieresis" width="500" llx="-21" lly="-14" urx="476" ury="655"/> + <char name="ae" width="722" llx="-5" lly="-13" urx="673" ury="462"/> + <char name="agrave" width="500" llx="-21" lly="-14" urx="455" ury="697"/> + <char name="ampersand" width="778" llx="5" lly="-19" urx="699" ury="682"/> + <char name="aring" width="500" llx="-21" lly="-14" urx="455" ury="729"/> + <char name="asciicircum" width="570" llx="67" lly="304" urx="503" ury="669"/> + <char name="asciitilde" width="570" llx="54" lly="173" urx="516" ury="333"/> + <char name="asterisk" width="500" llx="65" lly="249" urx="456" ury="685"/> + <char name="at" width="832" llx="63" lly="-18" urx="770" ury="685"/> + <char name="atilde" width="500" llx="-21" lly="-14" urx="491" ury="655"/> + <char name="b" width="500" llx="-14" lly="-13" urx="444" ury="699"/> + <char name="backslash" width="278" llx="-1" lly="-18" urx="279" ury="685"/> + <char name="bar" width="220" llx="66" lly="-218" urx="154" ury="782"/> + <char name="braceleft" width="348" llx="5" lly="-187" urx="436" ury="686"/> + <char name="braceright" width="348" llx="-129" lly="-187" urx="302" ury="686"/> + <char name="bracketleft" width="333" llx="-37" lly="-159" urx="362" ury="674"/> + <char name="bracketright" width="333" llx="-56" lly="-157" urx="343" ury="674"/> + <char name="breve" width="333" llx="71" lly="516" urx="387" ury="678"/> + <char name="brokenbar" width="220" llx="66" lly="-143" urx="154" ury="707"/> + <char name="bullet" width="350" llx="0" lly="175" urx="350" ury="525"/> + <char name="c" width="444" llx="-5" lly="-13" urx="392" ury="462"/> + <char name="caron" width="333" llx="79" lly="516" urx="411" ury="690"/> + <char name="ccedilla" width="444" llx="-5" lly="-218" urx="392" ury="462"/> + <char name="cedilla" width="333" llx="-80" lly="-218" urx="156" ury="5"/> + <char name="cent" width="500" llx="42" lly="-143" urx="439" ury="576"/> + <char name="circumflex" width="333" llx="40" lly="516" urx="367" ury="690"/> + <char name="colon" width="333" llx="23" lly="-13" urx="264" ury="459"/> + <char name="comma" width="250" llx="-60" lly="-182" urx="144" ury="134"/> + <char name="copyright" width="747" llx="30" lly="-18" urx="718" ury="685"/> + <char name="currency" width="500" llx="-26" lly="34" urx="526" ury="586"/> + <char name="d" width="500" llx="-21" lly="-13" urx="517" ury="699"/> + <char name="dagger" width="500" llx="91" lly="-145" urx="494" ury="685"/> + <char name="daggerdbl" width="500" llx="10" lly="-139" urx="493" ury="685"/> + <char name="degree" width="400" llx="83" lly="397" urx="369" ury="683"/> + <char name="dieresis" width="333" llx="55" lly="550" urx="402" ury="684"/> + <char name="divide" width="570" llx="33" lly="-29" urx="537" ury="535"/> + <char name="dollar" width="500" llx="-20" lly="-100" urx="497" ury="733"/> + <char name="dotaccent" width="333" llx="163" lly="550" urx="298" ury="684"/> + <char name="dotlessi" width="278" llx="2" lly="-9" urx="238" ury="462"/> + <char name="e" width="444" llx="5" lly="-13" urx="398" ury="462"/> + <char name="eacute" width="444" llx="5" lly="-13" urx="435" ury="697"/> + <char name="ecircumflex" width="444" llx="5" lly="-13" urx="423" ury="690"/> + <char name="edieresis" width="444" llx="5" lly="-13" urx="448" ury="655"/> + <char name="egrave" width="444" llx="5" lly="-13" urx="398" ury="697"/> + <char name="eight" width="500" llx="3" lly="-13" urx="476" ury="683"/> + <char name="ellipsis" width="1000" llx="40" lly="-13" urx="852" ury="135"/> + <char name="emdash" width="1000" llx="-40" lly="178" urx="977" ury="269"/> + <char name="endash" width="500" llx="-40" lly="178" urx="477" ury="269"/> + <char name="equal" width="570" llx="33" lly="107" urx="537" ury="399"/> + <char name="eth" width="500" llx="-3" lly="-13" urx="454" ury="699"/> + <char name="exclam" width="389" llx="67" lly="-13" urx="370" ury="684"/> + <char name="exclamdown" width="389" llx="19" lly="-205" urx="322" ury="492"/> + <char name="f" width="333" llx="-169" lly="-205" urx="446" ury="698"/> + <char name="fi" width="556" llx="-188" lly="-205" urx="514" ury="703"/> + <char name="five" width="500" llx="-11" lly="-13" urx="487" ury="669"/> + <char name="fl" width="556" llx="-186" lly="-205" urx="553" ury="704"/> + <char name="florin" width="500" llx="-87" lly="-156" urx="537" ury="707"/> + <char name="four" width="500" llx="-15" lly="0" urx="503" ury="683"/> + <char name="fraction" width="167" llx="-169" lly="-14" urx="324" ury="683"/> + <char name="g" width="500" llx="-52" lly="-203" urx="478" ury="462"/> + <char name="germandbls" width="500" llx="-200" lly="-200" urx="473" ury="705"/> + <char name="grave" width="333" llx="85" lly="516" urx="297" ury="697"/> + <char name="greater" width="570" llx="31" lly="-8" urx="539" ury="514"/> + <char name="guillemotleft" width="500" llx="12" lly="32" urx="468" ury="415"/> + <char name="guillemotright" width="500" llx="12" lly="32" urx="468" ury="415"/> + <char name="guilsinglleft" width="333" llx="32" lly="32" urx="303" ury="415"/> + <char name="guilsinglright" width="333" llx="10" lly="32" urx="281" ury="415"/> + <char name="h" width="556" llx="-13" lly="-9" urx="498" ury="699"/> + <char name="hungarumlaut" width="333" llx="69" lly="516" urx="498" ury="697"/> + <char name="hyphen" width="333" llx="2" lly="166" urx="271" ury="282"/> + <char name="i" width="278" llx="2" lly="-9" urx="263" ury="684"/> + <char name="iacute" width="278" llx="2" lly="-9" urx="352" ury="697"/> + <char name="icircumflex" width="278" llx="-3" lly="-9" urx="324" ury="690"/> + <char name="idieresis" width="278" llx="2" lly="-9" urx="364" ury="655"/> + <char name="igrave" width="278" llx="2" lly="-9" urx="259" ury="697"/> + <char name="j" width="278" llx="-189" lly="-207" urx="279" ury="684"/> + <char name="k" width="500" llx="-23" lly="-8" urx="483" ury="699"/> + <char name="l" width="278" llx="2" lly="-9" urx="290" ury="699"/> + <char name="less" width="570" llx="31" lly="-8" urx="539" ury="514"/> + <char name="logicalnot" width="606" llx="51" lly="108" urx="555" ury="399"/> + <char name="lslash" width="278" llx="-7" lly="-9" urx="307" ury="699"/> + <char name="m" width="778" llx="-14" lly="-9" urx="722" ury="462"/> + <char name="macron" width="333" llx="51" lly="553" urx="393" ury="623"/> + <char name="minus" width="330" llx="51" lly="209" urx="555" ury="297"/> + <char name="mu" width="576" llx="-60" lly="-207" urx="516" ury="449"/> + <char name="multiply" width="570" llx="48" lly="16" urx="522" ury="490"/> + <char name="n" width="556" llx="-6" lly="-9" urx="493" ury="462"/> + <char name="nine" width="500" llx="-12" lly="-10" urx="475" ury="683"/> + <char name="ntilde" width="556" llx="-6" lly="-9" urx="504" ury="655"/> + <char name="numbersign" width="500" llx="-33" lly="0" urx="533" ury="700"/> + <char name="o" width="500" llx="-3" lly="-13" urx="441" ury="462"/> + <char name="oacute" width="500" llx="-3" lly="-13" urx="463" ury="697"/> + <char name="ocircumflex" width="500" llx="-3" lly="-13" urx="451" ury="690"/> + <char name="odieresis" width="500" llx="-3" lly="-13" urx="471" ury="655"/> + <char name="oe" width="722" llx="6" lly="-13" urx="674" ury="462"/> + <char name="ogonek" width="333" llx="15" lly="-183" urx="244" ury="34"/> + <char name="ograve" width="500" llx="-3" lly="-13" urx="441" ury="697"/> + <char name="one" width="500" llx="5" lly="0" urx="419" ury="683"/> + <char name="onehalf" width="750" llx="-9" lly="-14" urx="723" ury="683"/> + <char name="onequarter" width="750" llx="7" lly="-14" urx="721" ury="683"/> + <char name="onesuperior" width="300" llx="30" lly="274" urx="301" ury="683"/> + <char name="ordfeminine" width="266" llx="16" lly="399" urx="330" ury="685"/> + <char name="ordmasculine" width="300" llx="56" lly="400" urx="347" ury="685"/> + <char name="oslash" width="500" llx="-3" lly="-119" urx="441" ury="560"/> + <char name="otilde" width="500" llx="-3" lly="-13" urx="491" ury="655"/> + <char name="p" width="500" llx="-120" lly="-205" urx="446" ury="462"/> + <char name="paragraph" width="500" llx="-57" lly="-193" urx="562" ury="669"/> + <char name="parenleft" width="333" llx="28" lly="-179" urx="344" ury="685"/> + <char name="parenright" width="333" llx="-44" lly="-179" urx="271" ury="685"/> + <char name="percent" width="833" llx="39" lly="-10" urx="793" ury="692"/> + <char name="period" width="250" llx="-9" lly="-13" urx="139" ury="135"/> + <char name="periodcentered" width="250" llx="51" lly="257" urx="199" ury="405"/> + <char name="perthousand" width="1000" llx="7" lly="-29" urx="996" ury="706"/> + <char name="plus" width="570" llx="33" lly="0" urx="537" ury="506"/> + <char name="plusminus" width="570" llx="33" lly="0" urx="537" ury="506"/> + <char name="q" width="500" llx="1" lly="-205" urx="471" ury="462"/> + <char name="question" width="500" llx="79" lly="-13" urx="470" ury="684"/> + <char name="questiondown" width="500" llx="30" lly="-205" urx="421" ury="492"/> + <char name="quotedbl" width="555" llx="136" lly="398" urx="536" ury="685"/> + <char name="quotedblbase" width="500" llx="-57" lly="-182" urx="403" ury="134"/> + <char name="quotedblleft" width="500" llx="53" lly="369" urx="513" ury="685"/> + <char name="quotedblright" width="500" llx="53" lly="369" urx="513" ury="685"/> + <char name="quoteleft" width="333" llx="128" lly="369" urx="332" ury="685"/> + <char name="quoteright" width="333" llx="98" lly="369" urx="302" ury="685"/> + <char name="quotesinglbase" width="333" llx="-5" lly="-182" urx="199" ury="134"/> + <char name="quotesingle" width="278" llx="128" lly="398" urx="268" ury="685"/> + <char name="r" width="389" llx="-21" lly="0" urx="389" ury="462"/> + <char name="registered" width="747" llx="30" lly="-18" urx="718" ury="685"/> + <char name="ring" width="333" llx="127" lly="516" urx="340" ury="729"/> + <char name="s" width="389" llx="-19" lly="-13" urx="333" ury="462"/> + <char name="scaron" width="389" llx="-19" lly="-13" urx="424" ury="690"/> + <char name="section" width="500" llx="36" lly="-143" urx="459" ury="685"/> + <char name="semicolon" width="333" llx="-25" lly="-183" urx="264" ury="459"/> + <char name="seven" width="500" llx="52" lly="0" urx="525" ury="669"/> + <char name="six" width="500" llx="23" lly="-15" urx="509" ury="679"/> + <char name="slash" width="278" llx="-64" lly="-18" urx="342" ury="685"/> + <char name="space" width="250" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="250"/> - <char name="sterling" width="500"/> - <char name="t" width="278"/> - <char name="thorn" width="500"/> - <char name="three" width="500"/> - <char name="threequarters" width="750"/> - <char name="threesuperior" width="300"/> - <char name="tilde" width="333"/> - <char name="trademark" width="1000"/> - <char name="two" width="500"/> - <char name="twosuperior" width="300"/> - <char name="u" width="556"/> - <char name="uacute" width="556"/> - <char name="ucircumflex" width="556"/> - <char name="udieresis" width="556"/> - <char name="ugrave" width="556"/> - <char name="underscore" width="500"/> - <char name="v" width="444"/> - <char name="w" width="667"/> - <char name="x" width="500"/> - <char name="y" width="444"/> - <char name="yacute" width="444"/> - <char name="ydieresis" width="444"/> - <char name="yen" width="500"/> - <char name="z" width="389"/> - <char name="zcaron" width="389"/> - <char name="zero" width="500"/> - </widths> + <char name="sterling" width="500" llx="-32" lly="-12" urx="510" ury="683"/> + <char name="t" width="278" llx="-11" lly="-9" urx="281" ury="594"/> + <char name="thorn" width="500" llx="-120" lly="-205" urx="446" ury="699"/> + <char name="three" width="500" llx="-15" lly="-13" urx="450" ury="683"/> + <char name="threequarters" width="750" llx="7" lly="-14" urx="726" ury="683"/> + <char name="threesuperior" width="300" llx="17" lly="265" urx="321" ury="683"/> + <char name="tilde" width="333" llx="48" lly="536" urx="407" ury="655"/> + <char name="trademark" width="1000" llx="32" lly="263" urx="968" ury="669"/> + <char name="two" width="500" llx="-27" lly="0" urx="446" ury="683"/> + <char name="twosuperior" width="300" llx="2" lly="274" urx="313" ury="683"/> + <char name="u" width="556" llx="15" lly="-9" urx="492" ury="462"/> + <char name="uacute" width="556" llx="15" lly="-9" urx="492" ury="697"/> + <char name="ucircumflex" width="556" llx="15" lly="-9" urx="492" ury="690"/> + <char name="udieresis" width="556" llx="15" lly="-9" urx="499" ury="655"/> + <char name="ugrave" width="556" llx="15" lly="-9" urx="492" ury="697"/> + <char name="underscore" width="500" llx="0" lly="-125" urx="500" ury="-75"/> + <char name="v" width="444" llx="16" lly="-13" urx="401" ury="462"/> + <char name="w" width="667" llx="16" lly="-13" urx="614" ury="462"/> + <char name="x" width="500" llx="-46" lly="-13" urx="469" ury="462"/> + <char name="y" width="444" llx="-94" lly="-205" urx="392" ury="462"/> + <char name="yacute" width="444" llx="-94" lly="-205" urx="435" ury="697"/> + <char name="ydieresis" width="444" llx="-94" lly="-205" urx="443" ury="655"/> + <char name="yen" width="500" llx="33" lly="0" urx="628" ury="669"/> + <char name="z" width="389" llx="-43" lly="-78" urx="368" ury="449"/> + <char name="zcaron" width="389" llx="-43" lly="-78" urx="424" ury="690"/> + <char name="zero" width="500" llx="17" lly="-14" urx="477" ury="683"/> + </char-metrics> <kerning kpx1="79"> <pair kern="-40" kpx2="65"/> <pair kern="-50" kpx2="87"/> diff --git a/src/codegen/fonts/TimesItalic.xml b/src/codegen/fonts/TimesItalic.xml index 514aaa6dd..607f4d701 100644 --- a/src/codegen/fonts/TimesItalic.xml +++ b/src/codegen/fonts/TimesItalic.xml @@ -22,245 +22,246 @@ <family-name>Times</family-name> <class-name>TimesItalic</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>653</cap-height> <x-height>441</x-height> <ascender>683</ascender> <descender>-205</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="611"/> - <char name="AE" width="889"/> - <char name="Aacute" width="611"/> - <char name="Acircumflex" width="611"/> - <char name="Adieresis" width="611"/> - <char name="Agrave" width="611"/> - <char name="Aring" width="611"/> - <char name="Atilde" width="611"/> - <char name="B" width="611"/> - <char name="C" width="667"/> - <char name="Ccedilla" width="667"/> - <char name="D" width="722"/> - <char name="E" width="611"/> - <char name="Eacute" width="611"/> - <char name="Ecircumflex" width="611"/> - <char name="Edieresis" width="611"/> - <char name="Egrave" width="611"/> - <char name="Eth" width="722"/> - <char name="Euro" width="500"/> - <char name="F" width="611"/> - <char name="G" width="722"/> - <char name="H" width="722"/> - <char name="I" width="333"/> - <char name="Iacute" width="333"/> - <char name="Icircumflex" width="333"/> - <char name="Idieresis" width="333"/> - <char name="Igrave" width="333"/> - <char name="J" width="444"/> - <char name="K" width="667"/> - <char name="L" width="556"/> - <char name="Lslash" width="556"/> - <char name="M" width="833"/> - <char name="N" width="667"/> - <char name="Ntilde" width="667"/> - <char name="O" width="722"/> - <char name="OE" width="944"/> - <char name="Oacute" width="722"/> - <char name="Ocircumflex" width="722"/> - <char name="Odieresis" width="722"/> - <char name="Ograve" width="722"/> - <char name="Oslash" width="722"/> - <char name="Otilde" width="722"/> - <char name="P" width="611"/> - <char name="Q" width="722"/> - <char name="R" width="611"/> - <char name="S" width="500"/> - <char name="Scaron" width="500"/> - <char name="T" width="556"/> - <char name="Thorn" width="611"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="611"/> - <char name="W" width="833"/> - <char name="X" width="611"/> - <char name="Y" width="556"/> - <char name="Yacute" width="556"/> - <char name="Ydieresis" width="556"/> - <char name="Z" width="556"/> - <char name="Zcaron" width="556"/> - <char name="a" width="500"/> - <char name="aacute" width="500"/> - <char name="acircumflex" width="500"/> - <char name="acute" width="333"/> - <char name="adieresis" width="500"/> - <char name="ae" width="667"/> - <char name="agrave" width="500"/> - <char name="ampersand" width="778"/> - <char name="aring" width="500"/> - <char name="asciicircum" width="422"/> - <char name="asciitilde" width="541"/> - <char name="asterisk" width="500"/> - <char name="at" width="920"/> - <char name="atilde" width="500"/> - <char name="b" width="500"/> - <char name="backslash" width="278"/> - <char name="bar" width="275"/> - <char name="braceleft" width="400"/> - <char name="braceright" width="400"/> - <char name="bracketleft" width="389"/> - <char name="bracketright" width="389"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="275"/> - <char name="bullet" width="350"/> - <char name="c" width="444"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="444"/> - <char name="cedilla" width="333"/> - <char name="cent" width="500"/> - <char name="circumflex" width="333"/> - <char name="colon" width="333"/> - <char name="comma" width="250"/> - <char name="copyright" width="760"/> - <char name="currency" width="500"/> - <char name="d" width="500"/> - <char name="dagger" width="500"/> - <char name="daggerdbl" width="500"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="675"/> - <char name="dollar" width="500"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="444"/> - <char name="eacute" width="444"/> - <char name="ecircumflex" width="444"/> - <char name="edieresis" width="444"/> - <char name="egrave" width="444"/> - <char name="eight" width="500"/> - <char name="ellipsis" width="889"/> - <char name="emdash" width="889"/> - <char name="endash" width="500"/> - <char name="equal" width="675"/> - <char name="eth" width="500"/> - <char name="exclam" width="333"/> - <char name="exclamdown" width="389"/> - <char name="f" width="278"/> - <char name="fi" width="500"/> - <char name="five" width="500"/> - <char name="fl" width="500"/> - <char name="florin" width="500"/> - <char name="four" width="500"/> - <char name="fraction" width="167"/> - <char name="g" width="500"/> - <char name="germandbls" width="500"/> - <char name="grave" width="333"/> - <char name="greater" width="675"/> - <char name="guillemotleft" width="500"/> - <char name="guillemotright" width="500"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="500"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="278"/> - <char name="k" width="444"/> - <char name="l" width="278"/> - <char name="less" width="675"/> - <char name="logicalnot" width="675"/> - <char name="lslash" width="278"/> - <char name="m" width="722"/> - <char name="macron" width="333"/> - <char name="minus" width="675"/> - <char name="mu" width="500"/> - <char name="multiply" width="675"/> - <char name="n" width="500"/> - <char name="nine" width="500"/> - <char name="ntilde" width="500"/> - <char name="numbersign" width="500"/> - <char name="o" width="500"/> - <char name="oacute" width="500"/> - <char name="ocircumflex" width="500"/> - <char name="odieresis" width="500"/> - <char name="oe" width="667"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="500"/> - <char name="one" width="500"/> - <char name="onehalf" width="750"/> - <char name="onequarter" width="750"/> - <char name="onesuperior" width="300"/> - <char name="ordfeminine" width="276"/> - <char name="ordmasculine" width="310"/> - <char name="oslash" width="500"/> - <char name="otilde" width="500"/> - <char name="p" width="500"/> - <char name="paragraph" width="523"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="833"/> - <char name="period" width="250"/> - <char name="periodcentered" width="250"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="675"/> - <char name="plusminus" width="675"/> - <char name="q" width="500"/> - <char name="question" width="500"/> - <char name="questiondown" width="500"/> - <char name="quotedbl" width="420"/> - <char name="quotedblbase" width="556"/> - <char name="quotedblleft" width="556"/> - <char name="quotedblright" width="556"/> - <char name="quoteleft" width="333"/> - <char name="quoteright" width="333"/> - <char name="quotesinglbase" width="333"/> - <char name="quotesingle" width="214"/> - <char name="r" width="389"/> - <char name="registered" width="760"/> - <char name="ring" width="333"/> - <char name="s" width="389"/> - <char name="scaron" width="389"/> - <char name="section" width="500"/> - <char name="semicolon" width="333"/> - <char name="seven" width="500"/> - <char name="six" width="500"/> - <char name="slash" width="278"/> - <char name="space" width="250"/> + <char-metrics> + <char name="A" width="611" llx="-51" lly="0" urx="564" ury="668"/> + <char name="AE" width="889" llx="-27" lly="0" urx="911" ury="653"/> + <char name="Aacute" width="611" llx="-51" lly="0" urx="564" ury="876"/> + <char name="Acircumflex" width="611" llx="-51" lly="0" urx="564" ury="873"/> + <char name="Adieresis" width="611" llx="-51" lly="0" urx="564" ury="818"/> + <char name="Agrave" width="611" llx="-51" lly="0" urx="564" ury="876"/> + <char name="Aring" width="611" llx="-51" lly="0" urx="564" ury="883"/> + <char name="Atilde" width="611" llx="-51" lly="0" urx="566" ury="836"/> + <char name="B" width="611" llx="-8" lly="0" urx="588" ury="653"/> + <char name="C" width="667" llx="66" lly="-18" urx="689" ury="666"/> + <char name="Ccedilla" width="667" llx="66" lly="-217" urx="689" ury="666"/> + <char name="D" width="722" llx="-8" lly="0" urx="700" ury="653"/> + <char name="E" width="611" llx="-1" lly="0" urx="634" ury="653"/> + <char name="Eacute" width="611" llx="-1" lly="0" urx="634" ury="876"/> + <char name="Ecircumflex" width="611" llx="-1" lly="0" urx="634" ury="873"/> + <char name="Edieresis" width="611" llx="-1" lly="0" urx="634" ury="818"/> + <char name="Egrave" width="611" llx="-1" lly="0" urx="634" ury="876"/> + <char name="Eth" width="722" llx="-8" lly="0" urx="700" ury="653"/> + <char name="Euro" width="500" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="611" llx="8" lly="0" urx="645" ury="653"/> + <char name="G" width="722" llx="52" lly="-18" urx="722" ury="666"/> + <char name="H" width="722" llx="-8" lly="0" urx="767" ury="653"/> + <char name="I" width="333" llx="-8" lly="0" urx="384" ury="653"/> + <char name="Iacute" width="333" llx="-8" lly="0" urx="433" ury="876"/> + <char name="Icircumflex" width="333" llx="-8" lly="0" urx="425" ury="873"/> + <char name="Idieresis" width="333" llx="-8" lly="0" urx="435" ury="818"/> + <char name="Igrave" width="333" llx="-8" lly="0" urx="384" ury="876"/> + <char name="J" width="444" llx="-6" lly="-18" urx="491" ury="653"/> + <char name="K" width="667" llx="7" lly="0" urx="722" ury="653"/> + <char name="L" width="556" llx="-8" lly="0" urx="559" ury="653"/> + <char name="Lslash" width="556" llx="-8" lly="0" urx="559" ury="653"/> + <char name="M" width="833" llx="-18" lly="0" urx="873" ury="653"/> + <char name="N" width="667" llx="-20" lly="-15" urx="727" ury="653"/> + <char name="Ntilde" width="667" llx="-20" lly="-15" urx="727" ury="836"/> + <char name="O" width="722" llx="60" lly="-18" urx="699" ury="666"/> + <char name="OE" width="944" llx="49" lly="-8" urx="964" ury="666"/> + <char name="Oacute" width="722" llx="60" lly="-18" urx="699" ury="876"/> + <char name="Ocircumflex" width="722" llx="60" lly="-18" urx="699" ury="873"/> + <char name="Odieresis" width="722" llx="60" lly="-18" urx="699" ury="818"/> + <char name="Ograve" width="722" llx="60" lly="-18" urx="699" ury="876"/> + <char name="Oslash" width="722" llx="60" lly="-105" urx="699" ury="722"/> + <char name="Otilde" width="722" llx="60" lly="-18" urx="699" ury="836"/> + <char name="P" width="611" llx="0" lly="0" urx="605" ury="653"/> + <char name="Q" width="722" llx="59" lly="-182" urx="699" ury="666"/> + <char name="R" width="611" llx="-13" lly="0" urx="588" ury="653"/> + <char name="S" width="500" llx="17" lly="-18" urx="508" ury="667"/> + <char name="Scaron" width="500" llx="17" lly="-18" urx="520" ury="873"/> + <char name="T" width="556" llx="59" lly="0" urx="633" ury="653"/> + <char name="Thorn" width="611" llx="0" lly="0" urx="569" ury="653"/> + <char name="U" width="722" llx="102" lly="-18" urx="765" ury="653"/> + <char name="Uacute" width="722" llx="102" lly="-18" urx="765" ury="876"/> + <char name="Ucircumflex" width="722" llx="102" lly="-18" urx="765" ury="873"/> + <char name="Udieresis" width="722" llx="102" lly="-18" urx="765" ury="818"/> + <char name="Ugrave" width="722" llx="102" lly="-18" urx="765" ury="876"/> + <char name="V" width="611" llx="76" lly="-18" urx="688" ury="653"/> + <char name="W" width="833" llx="71" lly="-18" urx="906" ury="653"/> + <char name="X" width="611" llx="-29" lly="0" urx="655" ury="653"/> + <char name="Y" width="556" llx="78" lly="0" urx="633" ury="653"/> + <char name="Yacute" width="556" llx="78" lly="0" urx="633" ury="876"/> + <char name="Ydieresis" width="556" llx="78" lly="0" urx="633" ury="818"/> + <char name="Z" width="556" llx="-6" lly="0" urx="606" ury="653"/> + <char name="Zcaron" width="556" llx="-6" lly="0" urx="606" ury="873"/> + <char name="a" width="500" llx="17" lly="-11" urx="476" ury="441"/> + <char name="aacute" width="500" llx="17" lly="-11" urx="487" ury="664"/> + <char name="acircumflex" width="500" llx="17" lly="-11" urx="476" ury="661"/> + <char name="acute" width="333" llx="180" lly="494" urx="403" ury="664"/> + <char name="adieresis" width="500" llx="17" lly="-11" urx="489" ury="606"/> + <char name="ae" width="667" llx="23" lly="-11" urx="640" ury="441"/> + <char name="agrave" width="500" llx="17" lly="-11" urx="476" ury="664"/> + <char name="ampersand" width="778" llx="76" lly="-18" urx="723" ury="666"/> + <char name="aring" width="500" llx="17" lly="-11" urx="476" ury="691"/> + <char name="asciicircum" width="422" llx="0" lly="301" urx="422" ury="666"/> + <char name="asciitilde" width="541" llx="40" lly="183" urx="502" ury="323"/> + <char name="asterisk" width="500" llx="128" lly="255" urx="492" ury="666"/> + <char name="at" width="920" llx="118" lly="-18" urx="806" ury="666"/> + <char name="atilde" width="500" llx="17" lly="-11" urx="511" ury="624"/> + <char name="b" width="500" llx="23" lly="-11" urx="473" ury="683"/> + <char name="backslash" width="278" llx="-41" lly="-18" urx="319" ury="666"/> + <char name="bar" width="275" llx="105" lly="-217" urx="171" ury="783"/> + <char name="braceleft" width="400" llx="51" lly="-177" urx="407" ury="687"/> + <char name="braceright" width="400" llx="-7" lly="-177" urx="349" ury="687"/> + <char name="bracketleft" width="389" llx="21" lly="-153" urx="391" ury="663"/> + <char name="bracketright" width="389" llx="12" lly="-153" urx="382" ury="663"/> + <char name="breve" width="333" llx="117" lly="492" urx="418" ury="650"/> + <char name="brokenbar" width="275" llx="105" lly="-142" urx="171" ury="708"/> + <char name="bullet" width="350" llx="40" lly="191" urx="310" ury="461"/> + <char name="c" width="444" llx="30" lly="-11" urx="425" ury="441"/> + <char name="caron" width="333" llx="121" lly="492" urx="426" ury="661"/> + <char name="ccedilla" width="444" llx="30" lly="-217" urx="425" ury="441"/> + <char name="cedilla" width="333" llx="-30" lly="-217" urx="182" ury="0"/> + <char name="cent" width="500" llx="77" lly="-143" urx="472" ury="560"/> + <char name="circumflex" width="333" llx="91" lly="492" urx="385" ury="661"/> + <char name="colon" width="333" llx="50" lly="-11" urx="261" ury="441"/> + <char name="comma" width="250" llx="-4" lly="-129" urx="135" ury="101"/> + <char name="copyright" width="760" llx="41" lly="-18" urx="719" ury="666"/> + <char name="currency" width="500" llx="-22" lly="53" urx="522" ury="597"/> + <char name="d" width="500" llx="15" lly="-13" urx="527" ury="683"/> + <char name="dagger" width="500" llx="101" lly="-159" urx="488" ury="666"/> + <char name="daggerdbl" width="500" llx="22" lly="-143" urx="491" ury="666"/> + <char name="degree" width="400" llx="101" lly="390" urx="387" ury="676"/> + <char name="dieresis" width="333" llx="107" lly="548" urx="405" ury="646"/> + <char name="divide" width="675" llx="86" lly="-11" urx="590" ury="517"/> + <char name="dollar" width="500" llx="31" lly="-89" urx="497" ury="731"/> + <char name="dotaccent" width="333" llx="207" lly="548" urx="305" ury="646"/> + <char name="dotlessi" width="278" llx="49" lly="-11" urx="235" ury="441"/> + <char name="e" width="444" llx="31" lly="-11" urx="412" ury="441"/> + <char name="eacute" width="444" llx="31" lly="-11" urx="459" ury="664"/> + <char name="ecircumflex" width="444" llx="31" lly="-11" urx="441" ury="661"/> + <char name="edieresis" width="444" llx="31" lly="-11" urx="451" ury="606"/> + <char name="egrave" width="444" llx="31" lly="-11" urx="412" ury="664"/> + <char name="eight" width="500" llx="30" lly="-7" urx="493" ury="676"/> + <char name="ellipsis" width="889" llx="57" lly="-11" urx="762" ury="100"/> + <char name="emdash" width="889" llx="-6" lly="197" urx="894" ury="243"/> + <char name="endash" width="500" llx="-6" lly="197" urx="505" ury="243"/> + <char name="equal" width="675" llx="86" lly="120" urx="590" ury="386"/> + <char name="eth" width="500" llx="27" lly="-11" urx="482" ury="683"/> + <char name="exclam" width="333" llx="39" lly="-11" urx="302" ury="667"/> + <char name="exclamdown" width="389" llx="59" lly="-205" urx="322" ury="473"/> + <char name="f" width="278" llx="-147" lly="-207" urx="424" ury="678"/> + <char name="fi" width="500" llx="-141" lly="-207" urx="481" ury="681"/> + <char name="five" width="500" llx="15" lly="-7" urx="491" ury="666"/> + <char name="fl" width="500" llx="-141" lly="-204" urx="518" ury="682"/> + <char name="florin" width="500" llx="25" lly="-182" urx="507" ury="682"/> + <char name="four" width="500" llx="1" lly="0" urx="479" ury="676"/> + <char name="fraction" width="167" llx="-169" lly="-10" urx="337" ury="676"/> + <char name="g" width="500" llx="8" lly="-206" urx="472" ury="441"/> + <char name="germandbls" width="500" llx="-168" lly="-207" urx="493" ury="679"/> + <char name="grave" width="333" llx="121" lly="492" urx="311" ury="664"/> + <char name="greater" width="675" llx="84" lly="-8" urx="592" ury="514"/> + <char name="guillemotleft" width="500" llx="53" lly="37" urx="445" ury="403"/> + <char name="guillemotright" width="500" llx="55" lly="37" urx="447" ury="403"/> + <char name="guilsinglleft" width="333" llx="51" lly="37" urx="281" ury="403"/> + <char name="guilsinglright" width="333" llx="52" lly="37" urx="282" ury="403"/> + <char name="h" width="500" llx="19" lly="-9" urx="478" ury="683"/> + <char name="hungarumlaut" width="333" llx="93" lly="494" urx="486" ury="664"/> + <char name="hyphen" width="333" llx="49" lly="192" urx="282" ury="255"/> + <char name="i" width="278" llx="49" lly="-11" urx="264" ury="654"/> + <char name="iacute" width="278" llx="49" lly="-11" urx="355" ury="664"/> + <char name="icircumflex" width="278" llx="33" lly="-11" urx="327" ury="661"/> + <char name="idieresis" width="278" llx="49" lly="-11" urx="352" ury="606"/> + <char name="igrave" width="278" llx="49" lly="-11" urx="284" ury="664"/> + <char name="j" width="278" llx="-124" lly="-207" urx="276" ury="654"/> + <char name="k" width="444" llx="14" lly="-11" urx="461" ury="683"/> + <char name="l" width="278" llx="41" lly="-11" urx="279" ury="683"/> + <char name="less" width="675" llx="84" lly="-8" urx="592" ury="514"/> + <char name="logicalnot" width="675" llx="86" lly="108" urx="590" ury="386"/> + <char name="lslash" width="278" llx="41" lly="-11" urx="312" ury="683"/> + <char name="m" width="722" llx="12" lly="-9" urx="704" ury="441"/> + <char name="macron" width="333" llx="99" lly="532" urx="411" ury="583"/> + <char name="minus" width="675" llx="86" lly="220" urx="590" ury="286"/> + <char name="mu" width="500" llx="-30" lly="-209" urx="497" ury="428"/> + <char name="multiply" width="675" llx="93" lly="8" urx="582" ury="497"/> + <char name="n" width="500" llx="14" lly="-9" urx="474" ury="441"/> + <char name="nine" width="500" llx="23" lly="-17" urx="492" ury="676"/> + <char name="ntilde" width="500" llx="14" lly="-9" urx="476" ury="624"/> + <char name="numbersign" width="500" llx="2" lly="0" urx="540" ury="676"/> + <char name="o" width="500" llx="27" lly="-11" urx="468" ury="441"/> + <char name="oacute" width="500" llx="27" lly="-11" urx="487" ury="664"/> + <char name="ocircumflex" width="500" llx="27" lly="-11" urx="468" ury="661"/> + <char name="odieresis" width="500" llx="27" lly="-11" urx="489" ury="606"/> + <char name="oe" width="667" llx="20" lly="-12" urx="646" ury="441"/> + <char name="ogonek" width="333" llx="20" lly="-169" urx="203" ury="40"/> + <char name="ograve" width="500" llx="27" lly="-11" urx="468" ury="664"/> + <char name="one" width="500" llx="49" lly="0" urx="409" ury="676"/> + <char name="onehalf" width="750" llx="34" lly="-10" urx="749" ury="676"/> + <char name="onequarter" width="750" llx="33" lly="-10" urx="736" ury="676"/> + <char name="onesuperior" width="300" llx="43" lly="271" urx="284" ury="676"/> + <char name="ordfeminine" width="276" llx="42" lly="406" urx="352" ury="676"/> + <char name="ordmasculine" width="310" llx="67" lly="406" urx="362" ury="676"/> + <char name="oslash" width="500" llx="28" lly="-135" urx="469" ury="554"/> + <char name="otilde" width="500" llx="27" lly="-11" urx="496" ury="624"/> + <char name="p" width="500" llx="-75" lly="-205" urx="469" ury="441"/> + <char name="paragraph" width="523" llx="55" lly="-123" urx="616" ury="653"/> + <char name="parenleft" width="333" llx="42" lly="-181" urx="315" ury="669"/> + <char name="parenright" width="333" llx="16" lly="-180" urx="289" ury="669"/> + <char name="percent" width="833" llx="79" lly="-13" urx="790" ury="676"/> + <char name="period" width="250" llx="27" lly="-11" urx="138" ury="100"/> + <char name="periodcentered" width="250" llx="70" lly="199" urx="181" ury="310"/> + <char name="perthousand" width="1000" llx="25" lly="-19" urx="1010" ury="706"/> + <char name="plus" width="675" llx="86" lly="0" urx="590" ury="506"/> + <char name="plusminus" width="675" llx="86" lly="0" urx="590" ury="506"/> + <char name="q" width="500" llx="25" lly="-209" urx="483" ury="441"/> + <char name="question" width="500" llx="132" lly="-12" urx="472" ury="664"/> + <char name="questiondown" width="500" llx="28" lly="-205" urx="368" ury="471"/> + <char name="quotedbl" width="420" llx="144" lly="421" urx="432" ury="666"/> + <char name="quotedblbase" width="556" llx="57" lly="-129" urx="405" ury="101"/> + <char name="quotedblleft" width="556" llx="166" lly="436" urx="514" ury="666"/> + <char name="quotedblright" width="556" llx="151" lly="436" urx="499" ury="666"/> + <char name="quoteleft" width="333" llx="171" lly="436" urx="310" ury="666"/> + <char name="quoteright" width="333" llx="151" lly="436" urx="290" ury="666"/> + <char name="quotesinglbase" width="333" llx="44" lly="-129" urx="183" ury="101"/> + <char name="quotesingle" width="214" llx="132" lly="421" urx="241" ury="666"/> + <char name="r" width="389" llx="45" lly="0" urx="412" ury="441"/> + <char name="registered" width="760" llx="41" lly="-18" urx="719" ury="666"/> + <char name="ring" width="333" llx="155" lly="492" urx="355" ury="691"/> + <char name="s" width="389" llx="16" lly="-13" urx="366" ury="442"/> + <char name="scaron" width="389" llx="16" lly="-13" urx="454" ury="661"/> + <char name="section" width="500" llx="53" lly="-162" urx="461" ury="666"/> + <char name="semicolon" width="333" llx="27" lly="-129" urx="261" ury="441"/> + <char name="seven" width="500" llx="75" lly="-8" urx="537" ury="666"/> + <char name="six" width="500" llx="30" lly="-7" urx="521" ury="686"/> + <char name="slash" width="278" llx="-65" lly="-18" urx="386" ury="666"/> + <char name="space" width="250" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="250"/> - <char name="sterling" width="500"/> - <char name="t" width="278"/> - <char name="thorn" width="500"/> - <char name="three" width="500"/> - <char name="threequarters" width="750"/> - <char name="threesuperior" width="300"/> - <char name="tilde" width="333"/> - <char name="trademark" width="980"/> - <char name="two" width="500"/> - <char name="twosuperior" width="300"/> - <char name="u" width="500"/> - <char name="uacute" width="500"/> - <char name="ucircumflex" width="500"/> - <char name="udieresis" width="500"/> - <char name="ugrave" width="500"/> - <char name="underscore" width="500"/> - <char name="v" width="444"/> - <char name="w" width="667"/> - <char name="x" width="444"/> - <char name="y" width="444"/> - <char name="yacute" width="444"/> - <char name="ydieresis" width="444"/> - <char name="yen" width="500"/> - <char name="z" width="389"/> - <char name="zcaron" width="389"/> - <char name="zero" width="500"/> - </widths> + <char name="sterling" width="500" llx="10" lly="-6" urx="517" ury="670"/> + <char name="t" width="278" llx="37" lly="-11" urx="296" ury="546"/> + <char name="thorn" width="500" llx="-75" lly="-205" urx="469" ury="683"/> + <char name="three" width="500" llx="15" lly="-7" urx="465" ury="676"/> + <char name="threequarters" width="750" llx="23" lly="-10" urx="736" ury="676"/> + <char name="threesuperior" width="300" llx="43" lly="268" urx="339" ury="676"/> + <char name="tilde" width="333" llx="100" lly="517" urx="427" ury="624"/> + <char name="trademark" width="980" llx="30" lly="247" urx="957" ury="653"/> + <char name="two" width="500" llx="12" lly="0" urx="452" ury="676"/> + <char name="twosuperior" width="300" llx="33" lly="271" urx="324" ury="676"/> + <char name="u" width="500" llx="42" lly="-11" urx="475" ury="441"/> + <char name="uacute" width="500" llx="42" lly="-11" urx="477" ury="664"/> + <char name="ucircumflex" width="500" llx="42" lly="-11" urx="475" ury="661"/> + <char name="udieresis" width="500" llx="42" lly="-11" urx="479" ury="606"/> + <char name="ugrave" width="500" llx="42" lly="-11" urx="475" ury="664"/> + <char name="underscore" width="500" llx="0" lly="-125" urx="500" ury="-75"/> + <char name="v" width="444" llx="21" lly="-18" urx="426" ury="441"/> + <char name="w" width="667" llx="16" lly="-18" urx="648" ury="441"/> + <char name="x" width="444" llx="-27" lly="-11" urx="447" ury="441"/> + <char name="y" width="444" llx="-24" lly="-206" urx="426" ury="441"/> + <char name="yacute" width="444" llx="-24" lly="-206" urx="459" ury="664"/> + <char name="ydieresis" width="444" llx="-24" lly="-206" urx="441" ury="606"/> + <char name="yen" width="500" llx="27" lly="0" urx="603" ury="653"/> + <char name="z" width="389" llx="-2" lly="-81" urx="380" ury="428"/> + <char name="zcaron" width="389" llx="-2" lly="-81" urx="434" ury="661"/> + <char name="zero" width="500" llx="32" lly="-7" urx="497" ury="676"/> + </char-metrics> <kerning kpx1="79"> <pair kern="-55" kpx2="65"/> <pair kern="-50" kpx2="87"/> @@ -641,4 +642,4 @@ <pair kern="0" kpx2="121"/> <pair kern="-40" kpx2="118"/> </kerning> -</font-metrics>
\ No newline at end of file +</font-metrics> diff --git a/src/codegen/fonts/TimesRoman.xml b/src/codegen/fonts/TimesRoman.xml index 9ddadfddd..9e16b6a3b 100644 --- a/src/codegen/fonts/TimesRoman.xml +++ b/src/codegen/fonts/TimesRoman.xml @@ -22,245 +22,246 @@ <family-name>Times</family-name> <class-name>TimesRoman</class-name> <encoding>StandardEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>662</cap-height> <x-height>450</x-height> <ascender>683</ascender> <descender>-217</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="A" width="722"/> - <char name="AE" width="889"/> - <char name="Aacute" width="722"/> - <char name="Acircumflex" width="722"/> - <char name="Adieresis" width="722"/> - <char name="Agrave" width="722"/> - <char name="Aring" width="722"/> - <char name="Atilde" width="722"/> - <char name="B" width="667"/> - <char name="C" width="667"/> - <char name="Ccedilla" width="667"/> - <char name="D" width="722"/> - <char name="E" width="611"/> - <char name="Eacute" width="611"/> - <char name="Ecircumflex" width="611"/> - <char name="Edieresis" width="611"/> - <char name="Egrave" width="611"/> - <char name="Eth" width="722"/> - <char name="Euro" width="500"/> - <char name="F" width="556"/> - <char name="G" width="722"/> - <char name="H" width="722"/> - <char name="I" width="333"/> - <char name="Iacute" width="333"/> - <char name="Icircumflex" width="333"/> - <char name="Idieresis" width="333"/> - <char name="Igrave" width="333"/> - <char name="J" width="389"/> - <char name="K" width="722"/> - <char name="L" width="611"/> - <char name="Lslash" width="611"/> - <char name="M" width="889"/> - <char name="N" width="722"/> - <char name="Ntilde" width="722"/> - <char name="O" width="722"/> - <char name="OE" width="889"/> - <char name="Oacute" width="722"/> - <char name="Ocircumflex" width="722"/> - <char name="Odieresis" width="722"/> - <char name="Ograve" width="722"/> - <char name="Oslash" width="722"/> - <char name="Otilde" width="722"/> - <char name="P" width="556"/> - <char name="Q" width="722"/> - <char name="R" width="667"/> - <char name="S" width="556"/> - <char name="Scaron" width="556"/> - <char name="T" width="611"/> - <char name="Thorn" width="556"/> - <char name="U" width="722"/> - <char name="Uacute" width="722"/> - <char name="Ucircumflex" width="722"/> - <char name="Udieresis" width="722"/> - <char name="Ugrave" width="722"/> - <char name="V" width="722"/> - <char name="W" width="944"/> - <char name="X" width="722"/> - <char name="Y" width="722"/> - <char name="Yacute" width="722"/> - <char name="Ydieresis" width="722"/> - <char name="Z" width="611"/> - <char name="Zcaron" width="611"/> - <char name="a" width="444"/> - <char name="aacute" width="444"/> - <char name="acircumflex" width="444"/> - <char name="acute" width="333"/> - <char name="adieresis" width="444"/> - <char name="ae" width="667"/> - <char name="agrave" width="444"/> - <char name="ampersand" width="778"/> - <char name="aring" width="444"/> - <char name="asciicircum" width="469"/> - <char name="asciitilde" width="541"/> - <char name="asterisk" width="500"/> - <char name="at" width="921"/> - <char name="atilde" width="444"/> - <char name="b" width="500"/> - <char name="backslash" width="278"/> - <char name="bar" width="200"/> - <char name="braceleft" width="480"/> - <char name="braceright" width="480"/> - <char name="bracketleft" width="333"/> - <char name="bracketright" width="333"/> - <char name="breve" width="333"/> - <char name="brokenbar" width="200"/> - <char name="bullet" width="350"/> - <char name="c" width="444"/> - <char name="caron" width="333"/> - <char name="ccedilla" width="444"/> - <char name="cedilla" width="333"/> - <char name="cent" width="500"/> - <char name="circumflex" width="333"/> - <char name="colon" width="278"/> - <char name="comma" width="250"/> - <char name="copyright" width="760"/> - <char name="currency" width="500"/> - <char name="d" width="500"/> - <char name="dagger" width="500"/> - <char name="daggerdbl" width="500"/> - <char name="degree" width="400"/> - <char name="dieresis" width="333"/> - <char name="divide" width="564"/> - <char name="dollar" width="500"/> - <char name="dotaccent" width="333"/> - <char name="dotlessi" width="278"/> - <char name="e" width="444"/> - <char name="eacute" width="444"/> - <char name="ecircumflex" width="444"/> - <char name="edieresis" width="444"/> - <char name="egrave" width="444"/> - <char name="eight" width="500"/> - <char name="ellipsis" width="1000"/> - <char name="emdash" width="1000"/> - <char name="endash" width="500"/> - <char name="equal" width="564"/> - <char name="eth" width="500"/> - <char name="exclam" width="333"/> - <char name="exclamdown" width="333"/> - <char name="f" width="333"/> - <char name="fi" width="556"/> - <char name="five" width="500"/> - <char name="fl" width="556"/> - <char name="florin" width="500"/> - <char name="four" width="500"/> - <char name="fraction" width="167"/> - <char name="g" width="500"/> - <char name="germandbls" width="500"/> - <char name="grave" width="333"/> - <char name="greater" width="564"/> - <char name="guillemotleft" width="500"/> - <char name="guillemotright" width="500"/> - <char name="guilsinglleft" width="333"/> - <char name="guilsinglright" width="333"/> - <char name="h" width="500"/> - <char name="hungarumlaut" width="333"/> - <char name="hyphen" width="333"/> - <char name="i" width="278"/> - <char name="iacute" width="278"/> - <char name="icircumflex" width="278"/> - <char name="idieresis" width="278"/> - <char name="igrave" width="278"/> - <char name="j" width="278"/> - <char name="k" width="500"/> - <char name="l" width="278"/> - <char name="less" width="564"/> - <char name="logicalnot" width="564"/> - <char name="lslash" width="278"/> - <char name="m" width="778"/> - <char name="macron" width="333"/> - <char name="minus" width="324"/> - <char name="mu" width="500"/> - <char name="multiply" width="564"/> - <char name="n" width="500"/> - <char name="nine" width="500"/> - <char name="ntilde" width="500"/> - <char name="numbersign" width="500"/> - <char name="o" width="500"/> - <char name="oacute" width="500"/> - <char name="ocircumflex" width="500"/> - <char name="odieresis" width="500"/> - <char name="oe" width="722"/> - <char name="ogonek" width="333"/> - <char name="ograve" width="500"/> - <char name="one" width="500"/> - <char name="onehalf" width="750"/> - <char name="onequarter" width="750"/> - <char name="onesuperior" width="300"/> - <char name="ordfeminine" width="276"/> - <char name="ordmasculine" width="310"/> - <char name="oslash" width="500"/> - <char name="otilde" width="500"/> - <char name="p" width="500"/> - <char name="paragraph" width="453"/> - <char name="parenleft" width="333"/> - <char name="parenright" width="333"/> - <char name="percent" width="833"/> - <char name="period" width="250"/> - <char name="periodcentered" width="250"/> - <char name="perthousand" width="1000"/> - <char name="plus" width="564"/> - <char name="plusminus" width="564"/> - <char name="q" width="500"/> - <char name="question" width="444"/> - <char name="questiondown" width="444"/> - <char name="quotedbl" width="408"/> - <char name="quotedblbase" width="444"/> - <char name="quotedblleft" width="444"/> - <char name="quotedblright" width="444"/> - <char name="quoteleft" width="333"/> - <char name="quoteright" width="333"/> - <char name="quotesinglbase" width="333"/> - <char name="quotesingle" width="180"/> - <char name="r" width="333"/> - <char name="registered" width="760"/> - <char name="ring" width="333"/> - <char name="s" width="389"/> - <char name="scaron" width="389"/> - <char name="section" width="500"/> - <char name="semicolon" width="278"/> - <char name="seven" width="500"/> - <char name="six" width="500"/> - <char name="slash" width="278"/> - <char name="space" width="250"/> + <char-metrics> + <char name="A" width="722" llx="15" lly="0" urx="706" ury="674"/> + <char name="AE" width="889" llx="0" lly="0" urx="863" ury="662"/> + <char name="Aacute" width="722" llx="15" lly="0" urx="706" ury="890"/> + <char name="Acircumflex" width="722" llx="15" lly="0" urx="706" ury="886"/> + <char name="Adieresis" width="722" llx="15" lly="0" urx="706" ury="835"/> + <char name="Agrave" width="722" llx="15" lly="0" urx="706" ury="890"/> + <char name="Aring" width="722" llx="15" lly="0" urx="706" ury="898"/> + <char name="Atilde" width="722" llx="15" lly="0" urx="706" ury="850"/> + <char name="B" width="667" llx="17" lly="0" urx="593" ury="662"/> + <char name="C" width="667" llx="28" lly="-14" urx="633" ury="676"/> + <char name="Ccedilla" width="667" llx="28" lly="-215" urx="633" ury="676"/> + <char name="D" width="722" llx="16" lly="0" urx="685" ury="662"/> + <char name="E" width="611" llx="12" lly="0" urx="597" ury="662"/> + <char name="Eacute" width="611" llx="12" lly="0" urx="597" ury="890"/> + <char name="Ecircumflex" width="611" llx="12" lly="0" urx="597" ury="886"/> + <char name="Edieresis" width="611" llx="12" lly="0" urx="597" ury="835"/> + <char name="Egrave" width="611" llx="12" lly="0" urx="597" ury="890"/> + <char name="Eth" width="722" llx="16" lly="0" urx="685" ury="662"/> + <char name="Euro" width="500" llx="0" lly="0" urx="0" ury="0"/> + <char name="F" width="556" llx="12" lly="0" urx="546" ury="662"/> + <char name="G" width="722" llx="32" lly="-14" urx="709" ury="676"/> + <char name="H" width="722" llx="19" lly="0" urx="702" ury="662"/> + <char name="I" width="333" llx="18" lly="0" urx="315" ury="662"/> + <char name="Iacute" width="333" llx="18" lly="0" urx="317" ury="890"/> + <char name="Icircumflex" width="333" llx="11" lly="0" urx="322" ury="886"/> + <char name="Idieresis" width="333" llx="18" lly="0" urx="315" ury="835"/> + <char name="Igrave" width="333" llx="18" lly="0" urx="315" ury="890"/> + <char name="J" width="389" llx="10" lly="-14" urx="370" ury="662"/> + <char name="K" width="722" llx="34" lly="0" urx="723" ury="662"/> + <char name="L" width="611" llx="12" lly="0" urx="598" ury="662"/> + <char name="Lslash" width="611" llx="12" lly="0" urx="598" ury="662"/> + <char name="M" width="889" llx="12" lly="0" urx="863" ury="662"/> + <char name="N" width="722" llx="12" lly="-11" urx="707" ury="662"/> + <char name="Ntilde" width="722" llx="12" lly="-11" urx="707" ury="850"/> + <char name="O" width="722" llx="34" lly="-14" urx="688" ury="676"/> + <char name="OE" width="889" llx="30" lly="-6" urx="885" ury="668"/> + <char name="Oacute" width="722" llx="34" lly="-14" urx="688" ury="890"/> + <char name="Ocircumflex" width="722" llx="34" lly="-14" urx="688" ury="886"/> + <char name="Odieresis" width="722" llx="34" lly="-14" urx="688" ury="835"/> + <char name="Ograve" width="722" llx="34" lly="-14" urx="688" ury="890"/> + <char name="Oslash" width="722" llx="34" lly="-80" urx="688" ury="734"/> + <char name="Otilde" width="722" llx="34" lly="-14" urx="688" ury="850"/> + <char name="P" width="556" llx="16" lly="0" urx="542" ury="662"/> + <char name="Q" width="722" llx="34" lly="-178" urx="701" ury="676"/> + <char name="R" width="667" llx="17" lly="0" urx="659" ury="662"/> + <char name="S" width="556" llx="42" lly="-14" urx="491" ury="676"/> + <char name="Scaron" width="556" llx="42" lly="-14" urx="491" ury="886"/> + <char name="T" width="611" llx="17" lly="0" urx="593" ury="662"/> + <char name="Thorn" width="556" llx="16" lly="0" urx="542" ury="662"/> + <char name="U" width="722" llx="14" lly="-14" urx="705" ury="662"/> + <char name="Uacute" width="722" llx="14" lly="-14" urx="705" ury="890"/> + <char name="Ucircumflex" width="722" llx="14" lly="-14" urx="705" ury="886"/> + <char name="Udieresis" width="722" llx="14" lly="-14" urx="705" ury="835"/> + <char name="Ugrave" width="722" llx="14" lly="-14" urx="705" ury="890"/> + <char name="V" width="722" llx="16" lly="-11" urx="697" ury="662"/> + <char name="W" width="944" llx="5" lly="-11" urx="932" ury="662"/> + <char name="X" width="722" llx="10" lly="0" urx="704" ury="662"/> + <char name="Y" width="722" llx="22" lly="0" urx="703" ury="662"/> + <char name="Yacute" width="722" llx="22" lly="0" urx="703" ury="890"/> + <char name="Ydieresis" width="722" llx="22" lly="0" urx="703" ury="835"/> + <char name="Z" width="611" llx="9" lly="0" urx="597" ury="662"/> + <char name="Zcaron" width="611" llx="9" lly="0" urx="597" ury="886"/> + <char name="a" width="444" llx="37" lly="-10" urx="442" ury="460"/> + <char name="aacute" width="444" llx="37" lly="-10" urx="442" ury="678"/> + <char name="acircumflex" width="444" llx="37" lly="-10" urx="442" ury="674"/> + <char name="acute" width="333" llx="93" lly="507" urx="317" ury="678"/> + <char name="adieresis" width="444" llx="37" lly="-10" urx="442" ury="623"/> + <char name="ae" width="667" llx="38" lly="-10" urx="632" ury="460"/> + <char name="agrave" width="444" llx="37" lly="-10" urx="442" ury="678"/> + <char name="ampersand" width="778" llx="42" lly="-13" urx="750" ury="676"/> + <char name="aring" width="444" llx="37" lly="-10" urx="442" ury="711"/> + <char name="asciicircum" width="469" llx="24" lly="297" urx="446" ury="662"/> + <char name="asciitilde" width="541" llx="40" lly="183" urx="502" ury="323"/> + <char name="asterisk" width="500" llx="69" lly="265" urx="432" ury="676"/> + <char name="at" width="921" llx="116" lly="-14" urx="809" ury="676"/> + <char name="atilde" width="444" llx="37" lly="-10" urx="442" ury="638"/> + <char name="b" width="500" llx="3" lly="-10" urx="468" ury="683"/> + <char name="backslash" width="278" llx="-9" lly="-14" urx="287" ury="676"/> + <char name="bar" width="200" llx="67" lly="-218" urx="133" ury="782"/> + <char name="braceleft" width="480" llx="100" lly="-181" urx="350" ury="680"/> + <char name="braceright" width="480" llx="130" lly="-181" urx="380" ury="680"/> + <char name="bracketleft" width="333" llx="88" lly="-156" urx="299" ury="662"/> + <char name="bracketright" width="333" llx="34" lly="-156" urx="245" ury="662"/> + <char name="breve" width="333" llx="26" lly="507" urx="307" ury="664"/> + <char name="brokenbar" width="200" llx="67" lly="-143" urx="133" ury="707"/> + <char name="bullet" width="350" llx="40" lly="196" urx="310" ury="466"/> + <char name="c" width="444" llx="25" lly="-10" urx="412" ury="460"/> + <char name="caron" width="333" llx="11" lly="507" urx="322" ury="674"/> + <char name="ccedilla" width="444" llx="25" lly="-215" urx="412" ury="460"/> + <char name="cedilla" width="333" llx="52" lly="-215" urx="261" ury="0"/> + <char name="cent" width="500" llx="53" lly="-138" urx="448" ury="579"/> + <char name="circumflex" width="333" llx="11" lly="507" urx="322" ury="674"/> + <char name="colon" width="278" llx="81" lly="-11" urx="192" ury="459"/> + <char name="comma" width="250" llx="56" lly="-141" urx="195" ury="102"/> + <char name="copyright" width="760" llx="38" lly="-14" urx="722" ury="676"/> + <char name="currency" width="500" llx="-22" lly="58" urx="522" ury="602"/> + <char name="d" width="500" llx="27" lly="-10" urx="491" ury="683"/> + <char name="dagger" width="500" llx="59" lly="-149" urx="442" ury="676"/> + <char name="daggerdbl" width="500" llx="58" lly="-153" urx="442" ury="676"/> + <char name="degree" width="400" llx="57" lly="390" urx="343" ury="676"/> + <char name="dieresis" width="333" llx="18" lly="581" urx="315" ury="681"/> + <char name="divide" width="564" llx="30" lly="-10" urx="534" ury="516"/> + <char name="dollar" width="500" llx="44" lly="-87" urx="457" ury="727"/> + <char name="dotaccent" width="333" llx="118" lly="581" urx="216" ury="681"/> + <char name="dotlessi" width="278" llx="16" lly="0" urx="253" ury="460"/> + <char name="e" width="444" llx="25" lly="-10" urx="424" ury="460"/> + <char name="eacute" width="444" llx="25" lly="-10" urx="424" ury="678"/> + <char name="ecircumflex" width="444" llx="25" lly="-10" urx="424" ury="674"/> + <char name="edieresis" width="444" llx="25" lly="-10" urx="424" ury="623"/> + <char name="egrave" width="444" llx="25" lly="-10" urx="424" ury="678"/> + <char name="eight" width="500" llx="56" lly="-14" urx="445" ury="676"/> + <char name="ellipsis" width="1000" llx="111" lly="-11" urx="888" ury="100"/> + <char name="emdash" width="1000" llx="0" lly="201" urx="1000" ury="250"/> + <char name="endash" width="500" llx="0" lly="201" urx="500" ury="250"/> + <char name="equal" width="564" llx="30" lly="120" urx="534" ury="386"/> + <char name="eth" width="500" llx="29" lly="-10" urx="471" ury="686"/> + <char name="exclam" width="333" llx="130" lly="-9" urx="238" ury="676"/> + <char name="exclamdown" width="333" llx="97" lly="-218" urx="205" ury="467"/> + <char name="f" width="333" llx="20" lly="0" urx="383" ury="683"/> + <char name="fi" width="556" llx="31" lly="0" urx="521" ury="683"/> + <char name="five" width="500" llx="32" lly="-14" urx="438" ury="688"/> + <char name="fl" width="556" llx="32" lly="0" urx="521" ury="683"/> + <char name="florin" width="500" llx="7" lly="-189" urx="490" ury="676"/> + <char name="four" width="500" llx="12" lly="0" urx="472" ury="676"/> + <char name="fraction" width="167" llx="-168" lly="-14" urx="331" ury="676"/> + <char name="g" width="500" llx="28" lly="-218" urx="470" ury="460"/> + <char name="germandbls" width="500" llx="12" lly="-9" urx="468" ury="683"/> + <char name="grave" width="333" llx="19" lly="507" urx="242" ury="678"/> + <char name="greater" width="564" llx="28" lly="-8" urx="536" ury="514"/> + <char name="guillemotleft" width="500" llx="42" lly="33" urx="456" ury="416"/> + <char name="guillemotright" width="500" llx="44" lly="33" urx="458" ury="416"/> + <char name="guilsinglleft" width="333" llx="63" lly="33" urx="285" ury="416"/> + <char name="guilsinglright" width="333" llx="48" lly="33" urx="270" ury="416"/> + <char name="h" width="500" llx="9" lly="0" urx="487" ury="683"/> + <char name="hungarumlaut" width="333" llx="-3" lly="507" urx="377" ury="678"/> + <char name="hyphen" width="333" llx="39" lly="194" urx="285" ury="257"/> + <char name="i" width="278" llx="16" lly="0" urx="253" ury="683"/> + <char name="iacute" width="278" llx="16" lly="0" urx="290" ury="678"/> + <char name="icircumflex" width="278" llx="-16" lly="0" urx="295" ury="674"/> + <char name="idieresis" width="278" llx="-9" lly="0" urx="288" ury="623"/> + <char name="igrave" width="278" llx="-8" lly="0" urx="253" ury="678"/> + <char name="j" width="278" llx="-70" lly="-218" urx="194" ury="683"/> + <char name="k" width="500" llx="7" lly="0" urx="505" ury="683"/> + <char name="l" width="278" llx="19" lly="0" urx="257" ury="683"/> + <char name="less" width="564" llx="28" lly="-8" urx="536" ury="514"/> + <char name="logicalnot" width="564" llx="30" lly="108" urx="534" ury="386"/> + <char name="lslash" width="278" llx="19" lly="0" urx="259" ury="683"/> + <char name="m" width="778" llx="16" lly="0" urx="775" ury="460"/> + <char name="macron" width="333" llx="11" lly="547" urx="322" ury="601"/> + <char name="minus" width="324" llx="30" lly="220" urx="534" ury="286"/> + <char name="mu" width="500" llx="36" lly="-218" urx="512" ury="450"/> + <char name="multiply" width="564" llx="38" lly="8" urx="527" ury="497"/> + <char name="n" width="500" llx="16" lly="0" urx="485" ury="460"/> + <char name="nine" width="500" llx="30" lly="-22" urx="459" ury="676"/> + <char name="ntilde" width="500" llx="16" lly="0" urx="485" ury="638"/> + <char name="numbersign" width="500" llx="5" lly="0" urx="496" ury="662"/> + <char name="o" width="500" llx="29" lly="-10" urx="470" ury="460"/> + <char name="oacute" width="500" llx="29" lly="-10" urx="470" ury="678"/> + <char name="ocircumflex" width="500" llx="29" lly="-10" urx="470" ury="674"/> + <char name="odieresis" width="500" llx="29" lly="-10" urx="470" ury="623"/> + <char name="oe" width="722" llx="30" lly="-10" urx="690" ury="460"/> + <char name="ogonek" width="333" llx="62" lly="-165" urx="243" ury="0"/> + <char name="ograve" width="500" llx="29" lly="-10" urx="470" ury="678"/> + <char name="one" width="500" llx="111" lly="0" urx="394" ury="676"/> + <char name="onehalf" width="750" llx="31" lly="-14" urx="746" ury="676"/> + <char name="onequarter" width="750" llx="37" lly="-14" urx="718" ury="676"/> + <char name="onesuperior" width="300" llx="57" lly="270" urx="248" ury="676"/> + <char name="ordfeminine" width="276" llx="4" lly="394" urx="270" ury="676"/> + <char name="ordmasculine" width="310" llx="6" lly="394" urx="304" ury="676"/> + <char name="oslash" width="500" llx="29" lly="-112" urx="470" ury="551"/> + <char name="otilde" width="500" llx="29" lly="-10" urx="470" ury="638"/> + <char name="p" width="500" llx="5" lly="-217" urx="470" ury="460"/> + <char name="paragraph" width="453" llx="-22" lly="-154" urx="450" ury="662"/> + <char name="parenleft" width="333" llx="48" lly="-177" urx="304" ury="676"/> + <char name="parenright" width="333" llx="29" lly="-177" urx="285" ury="676"/> + <char name="percent" width="833" llx="61" lly="-13" urx="772" ury="676"/> + <char name="period" width="250" llx="70" lly="-11" urx="181" ury="100"/> + <char name="periodcentered" width="250" llx="70" lly="199" urx="181" ury="310"/> + <char name="perthousand" width="1000" llx="7" lly="-19" urx="994" ury="706"/> + <char name="plus" width="564" llx="30" lly="0" urx="534" ury="506"/> + <char name="plusminus" width="564" llx="30" lly="0" urx="534" ury="506"/> + <char name="q" width="500" llx="24" lly="-217" urx="488" ury="460"/> + <char name="question" width="444" llx="68" lly="-8" urx="414" ury="676"/> + <char name="questiondown" width="444" llx="30" lly="-218" urx="376" ury="466"/> + <char name="quotedbl" width="408" llx="77" lly="431" urx="331" ury="676"/> + <char name="quotedblbase" width="444" llx="45" lly="-141" urx="416" ury="102"/> + <char name="quotedblleft" width="444" llx="43" lly="433" urx="414" ury="676"/> + <char name="quotedblright" width="444" llx="30" lly="433" urx="401" ury="676"/> + <char name="quoteleft" width="333" llx="115" lly="433" urx="254" ury="676"/> + <char name="quoteright" width="333" llx="79" lly="433" urx="218" ury="676"/> + <char name="quotesinglbase" width="333" llx="79" lly="-141" urx="218" ury="102"/> + <char name="quotesingle" width="180" llx="48" lly="431" urx="133" ury="676"/> + <char name="r" width="333" llx="5" lly="0" urx="335" ury="460"/> + <char name="registered" width="760" llx="38" lly="-14" urx="722" ury="676"/> + <char name="ring" width="333" llx="67" lly="512" urx="266" ury="711"/> + <char name="s" width="389" llx="51" lly="-10" urx="348" ury="460"/> + <char name="scaron" width="389" llx="39" lly="-10" urx="350" ury="674"/> + <char name="section" width="500" llx="70" lly="-148" urx="426" ury="676"/> + <char name="semicolon" width="278" llx="80" lly="-141" urx="219" ury="459"/> + <char name="seven" width="500" llx="20" lly="-8" urx="449" ury="662"/> + <char name="six" width="500" llx="34" lly="-14" urx="468" ury="684"/> + <char name="slash" width="278" llx="-9" lly="-14" urx="287" ury="676"/> + <char name="space" width="250" llx="0" lly="0" urx="0" ury="0"/> <!-- JKT: the following has been manually added --> - <char name="nbsp" width="250"/> - <char name="sterling" width="500"/> - <char name="t" width="278"/> - <char name="thorn" width="500"/> - <char name="three" width="500"/> - <char name="threequarters" width="750"/> - <char name="threesuperior" width="300"/> - <char name="tilde" width="333"/> - <char name="trademark" width="980"/> - <char name="two" width="500"/> - <char name="twosuperior" width="300"/> - <char name="u" width="500"/> - <char name="uacute" width="500"/> - <char name="ucircumflex" width="500"/> - <char name="udieresis" width="500"/> - <char name="ugrave" width="500"/> - <char name="underscore" width="500"/> - <char name="v" width="500"/> - <char name="w" width="722"/> - <char name="x" width="500"/> - <char name="y" width="500"/> - <char name="yacute" width="500"/> - <char name="ydieresis" width="500"/> - <char name="yen" width="500"/> - <char name="z" width="444"/> - <char name="zcaron" width="444"/> - <char name="zero" width="500"/> - </widths> + <char name="sterling" width="500" llx="12" lly="-8" urx="490" ury="676"/> + <char name="t" width="278" llx="13" lly="-10" urx="279" ury="579"/> + <char name="thorn" width="500" llx="5" lly="-217" urx="470" ury="683"/> + <char name="three" width="500" llx="43" lly="-14" urx="431" ury="676"/> + <char name="threequarters" width="750" llx="15" lly="-14" urx="718" ury="676"/> + <char name="threesuperior" width="300" llx="15" lly="262" urx="291" ury="676"/> + <char name="tilde" width="333" llx="1" lly="532" urx="331" ury="638"/> + <char name="trademark" width="980" llx="30" lly="256" urx="957" ury="662"/> + <char name="two" width="500" llx="30" lly="0" urx="475" ury="676"/> + <char name="twosuperior" width="300" llx="1" lly="270" urx="296" ury="676"/> + <char name="u" width="500" llx="9" lly="-10" urx="479" ury="450"/> + <char name="uacute" width="500" llx="9" lly="-10" urx="479" ury="678"/> + <char name="ucircumflex" width="500" llx="9" lly="-10" urx="479" ury="674"/> + <char name="udieresis" width="500" llx="9" lly="-10" urx="479" ury="623"/> + <char name="ugrave" width="500" llx="9" lly="-10" urx="479" ury="678"/> + <char name="underscore" width="500" llx="0" lly="-125" urx="500" ury="-75"/> + <char name="v" width="500" llx="19" lly="-14" urx="477" ury="450"/> + <char name="w" width="722" llx="21" lly="-14" urx="694" ury="450"/> + <char name="x" width="500" llx="17" lly="0" urx="479" ury="450"/> + <char name="y" width="500" llx="14" lly="-218" urx="475" ury="450"/> + <char name="yacute" width="500" llx="14" lly="-218" urx="475" ury="678"/> + <char name="ydieresis" width="500" llx="14" lly="-218" urx="475" ury="623"/> + <char name="yen" width="500" llx="-53" lly="0" urx="512" ury="662"/> + <char name="z" width="444" llx="27" lly="0" urx="418" ury="450"/> + <char name="zcaron" width="444" llx="27" lly="0" urx="418" ury="674"/> + <char name="zero" width="500" llx="24" lly="-14" urx="476" ury="676"/> + </char-metrics> <kerning kpx1="79"> <pair kern="-35" kpx2="65"/> <pair kern="-35" kpx2="87"/> diff --git a/src/codegen/fonts/ZapfDingbats.xml b/src/codegen/fonts/ZapfDingbats.xml index f6ed76d25..bd72901dc 100644 --- a/src/codegen/fonts/ZapfDingbats.xml +++ b/src/codegen/fonts/ZapfDingbats.xml @@ -21,214 +21,216 @@ <family-name>ZapfDingbats</family-name> <class-name>ZapfDingbats</class-name> <encoding>ZapfDingbatsEncoding</encoding> + <underline-position>-100</underline-position> + <underline-thickness>50</underline-thickness> <cap-height>820</cap-height> <x-height>426</x-height> <ascender>820</ascender> <descender>-143</descender> <first-char>32</first-char> <last-char>255</last-char> - <widths> - <char name="space" width="278"/> - <char name="a1" width="974"/> - <char name="a2" width="961"/> - <char name="a202" width="974"/> - <char name="a3" width="980"/> - <char name="a4" width="719"/> - <char name="a5" width="789"/> - <char name="a119" width="790"/> - <char name="a118" width="791"/> - <char name="a117" width="690"/> - <char name="a11" width="960"/> - <char name="a12" width="939"/> - <char name="a13" width="549"/> - <char name="a14" width="855"/> - <char name="a15" width="911"/> - <char name="a16" width="933"/> - <char name="a105" width="911"/> - <char name="a17" width="945"/> - <char name="a18" width="974"/> - <char name="a19" width="755"/> - <char name="a20" width="846"/> - <char name="a21" width="762"/> - <char name="a22" width="761"/> - <char name="a23" width="571"/> - <char name="a24" width="677"/> - <char name="a25" width="763"/> - <char name="a26" width="760"/> - <char name="a27" width="759"/> - <char name="a28" width="754"/> - <char name="a6" width="494"/> - <char name="a7" width="552"/> - <char name="a8" width="537"/> - <char name="a9" width="577"/> - <char name="a10" width="692"/> - <char name="a29" width="786"/> - <char name="a30" width="788"/> - <char name="a31" width="788"/> - <char name="a32" width="790"/> - <char name="a33" width="793"/> - <char name="a34" width="794"/> - <char name="a35" width="816"/> - <char name="a36" width="823"/> - <char name="a37" width="789"/> - <char name="a38" width="841"/> - <char name="a39" width="823"/> - <char name="a40" width="833"/> - <char name="a41" width="816"/> - <char name="a42" width="831"/> - <char name="a43" width="923"/> - <char name="a44" width="744"/> - <char name="a45" width="723"/> - <char name="a46" width="749"/> - <char name="a47" width="790"/> - <char name="a48" width="792"/> - <char name="a49" width="695"/> - <char name="a50" width="776"/> - <char name="a51" width="768"/> - <char name="a52" width="792"/> - <char name="a53" width="759"/> - <char name="a54" width="707"/> - <char name="a55" width="708"/> - <char name="a56" width="682"/> - <char name="a57" width="701"/> - <char name="a58" width="826"/> - <char name="a59" width="815"/> - <char name="a60" width="789"/> - <char name="a61" width="789"/> - <char name="a62" width="707"/> - <char name="a63" width="687"/> - <char name="a64" width="696"/> - <char name="a65" width="689"/> - <char name="a66" width="786"/> - <char name="a67" width="787"/> - <char name="a68" width="713"/> - <char name="a69" width="791"/> - <char name="a70" width="785"/> - <char name="a71" width="791"/> - <char name="a72" width="873"/> - <char name="a73" width="761"/> - <char name="a74" width="762"/> - <char name="a203" width="762"/> - <char name="a75" width="759"/> - <char name="a204" width="759"/> - <char name="a76" width="892"/> - <char name="a77" width="892"/> - <char name="a78" width="788"/> - <char name="a79" width="784"/> - <char name="a81" width="438"/> - <char name="a82" width="138"/> - <char name="a83" width="277"/> - <char name="a84" width="415"/> - <char name="a97" width="392"/> - <char name="a98" width="392"/> - <char name="a99" width="668"/> - <char name="a100" width="668"/> - <char name="a101" width="732"/> - <char name="a102" width="544"/> - <char name="a103" width="544"/> - <char name="a104" width="910"/> - <char name="a106" width="667"/> - <char name="a107" width="760"/> - <char name="a108" width="760"/> - <char name="a112" width="776"/> - <char name="a111" width="595"/> - <char name="a110" width="694"/> - <char name="a109" width="626"/> - <char name="a120" width="788"/> - <char name="a121" width="788"/> - <char name="a122" width="788"/> - <char name="a123" width="788"/> - <char name="a124" width="788"/> - <char name="a125" width="788"/> - <char name="a126" width="788"/> - <char name="a127" width="788"/> - <char name="a128" width="788"/> - <char name="a129" width="788"/> - <char name="a130" width="788"/> - <char name="a131" width="788"/> - <char name="a132" width="788"/> - <char name="a133" width="788"/> - <char name="a134" width="788"/> - <char name="a135" width="788"/> - <char name="a136" width="788"/> - <char name="a137" width="788"/> - <char name="a138" width="788"/> - <char name="a139" width="788"/> - <char name="a140" width="788"/> - <char name="a141" width="788"/> - <char name="a142" width="788"/> - <char name="a143" width="788"/> - <char name="a144" width="788"/> - <char name="a145" width="788"/> - <char name="a146" width="788"/> - <char name="a147" width="788"/> - <char name="a148" width="788"/> - <char name="a149" width="788"/> - <char name="a150" width="788"/> - <char name="a151" width="788"/> - <char name="a152" width="788"/> - <char name="a153" width="788"/> - <char name="a154" width="788"/> - <char name="a155" width="788"/> - <char name="a156" width="788"/> - <char name="a157" width="788"/> - <char name="a158" width="788"/> - <char name="a159" width="788"/> - <char name="a160" width="894"/> - <char name="a161" width="838"/> - <char name="a163" width="1016"/> - <char name="a164" width="458"/> - <char name="a196" width="748"/> - <char name="a165" width="924"/> - <char name="a192" width="748"/> - <char name="a166" width="918"/> - <char name="a167" width="927"/> - <char name="a168" width="928"/> - <char name="a169" width="928"/> - <char name="a170" width="834"/> - <char name="a171" width="873"/> - <char name="a172" width="828"/> - <char name="a173" width="924"/> - <char name="a162" width="924"/> - <char name="a174" width="917"/> - <char name="a175" width="930"/> - <char name="a176" width="931"/> - <char name="a177" width="463"/> - <char name="a178" width="883"/> - <char name="a179" width="836"/> - <char name="a193" width="836"/> - <char name="a180" width="867"/> - <char name="a199" width="867"/> - <char name="a181" width="696"/> - <char name="a200" width="696"/> - <char name="a182" width="874"/> - <char name="a201" width="874"/> - <char name="a183" width="760"/> - <char name="a184" width="946"/> - <char name="a197" width="771"/> - <char name="a185" width="865"/> - <char name="a194" width="771"/> - <char name="a198" width="888"/> - <char name="a186" width="967"/> - <char name="a195" width="888"/> - <char name="a187" width="831"/> - <char name="a188" width="873"/> - <char name="a189" width="927"/> - <char name="a190" width="970"/> - <char name="a191" width="918"/> - <char name="a86" width="410"/> - <char name="a85" width="509"/> - <char name="a95" width="334"/> - <char name="a205" width="509"/> - <char name="a89" width="390"/> - <char name="a87" width="234"/> - <char name="a91" width="276"/> - <char name="a90" width="390"/> - <char name="a206" width="410"/> - <char name="a94" width="317"/> - <char name="a93" width="317"/> - <char name="a92" width="276"/> - <char name="a96" width="334"/> - <char name="a88" width="234"/> - </widths> -</font-metrics>
\ No newline at end of file + <char-metrics> + <char name="space" width="278" llx="0" lly="0" urx="0" ury="0"/> + <char name="a1" width="974" llx="35" lly="72" urx="939" ury="621"/> + <char name="a2" width="961" llx="35" lly="81" urx="927" ury="611"/> + <char name="a202" width="974" llx="35" lly="72" urx="939" ury="621"/> + <char name="a3" width="980" llx="35" lly="0" urx="945" ury="692"/> + <char name="a4" width="719" llx="34" lly="139" urx="685" ury="566"/> + <char name="a5" width="789" llx="35" lly="-14" urx="755" ury="705"/> + <char name="a119" width="790" llx="35" lly="-14" urx="755" ury="705"/> + <char name="a118" width="791" llx="35" lly="-13" urx="761" ury="705"/> + <char name="a117" width="690" llx="34" lly="138" urx="655" ury="553"/> + <char name="a11" width="960" llx="35" lly="123" urx="925" ury="568"/> + <char name="a12" width="939" llx="35" lly="134" urx="904" ury="559"/> + <char name="a13" width="549" llx="29" lly="-11" urx="516" ury="705"/> + <char name="a14" width="855" llx="34" lly="59" urx="820" ury="632"/> + <char name="a15" width="911" llx="35" lly="50" urx="876" ury="642"/> + <char name="a16" width="933" llx="35" lly="139" urx="899" ury="550"/> + <char name="a105" width="911" llx="35" lly="50" urx="876" ury="642"/> + <char name="a17" width="945" llx="35" lly="139" urx="909" ury="553"/> + <char name="a18" width="974" llx="35" lly="104" urx="938" ury="587"/> + <char name="a19" width="755" llx="34" lly="-13" urx="721" ury="705"/> + <char name="a20" width="846" llx="36" lly="-14" urx="811" ury="705"/> + <char name="a21" width="762" llx="35" lly="0" urx="727" ury="692"/> + <char name="a22" width="761" llx="35" lly="0" urx="727" ury="692"/> + <char name="a23" width="571" llx="-1" lly="-68" urx="571" ury="661"/> + <char name="a24" width="677" llx="36" lly="-13" urx="642" ury="705"/> + <char name="a25" width="763" llx="35" lly="0" urx="728" ury="692"/> + <char name="a26" width="760" llx="35" lly="0" urx="726" ury="692"/> + <char name="a27" width="759" llx="35" lly="0" urx="725" ury="692"/> + <char name="a28" width="754" llx="35" lly="0" urx="720" ury="692"/> + <char name="a6" width="494" llx="35" lly="0" urx="460" ury="692"/> + <char name="a7" width="552" llx="35" lly="0" urx="517" ury="692"/> + <char name="a8" width="537" llx="35" lly="0" urx="503" ury="692"/> + <char name="a9" width="577" llx="35" lly="96" urx="542" ury="596"/> + <char name="a10" width="692" llx="35" lly="-14" urx="657" ury="705"/> + <char name="a29" width="786" llx="35" lly="-14" urx="751" ury="705"/> + <char name="a30" width="788" llx="35" lly="-14" urx="752" ury="705"/> + <char name="a31" width="788" llx="35" lly="-14" urx="753" ury="705"/> + <char name="a32" width="790" llx="35" lly="-14" urx="756" ury="705"/> + <char name="a33" width="793" llx="35" lly="-13" urx="759" ury="705"/> + <char name="a34" width="794" llx="35" lly="-13" urx="759" ury="705"/> + <char name="a35" width="816" llx="35" lly="-14" urx="782" ury="705"/> + <char name="a36" width="823" llx="35" lly="-14" urx="787" ury="705"/> + <char name="a37" width="789" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a38" width="841" llx="35" lly="-14" urx="807" ury="705"/> + <char name="a39" width="823" llx="35" lly="-14" urx="789" ury="705"/> + <char name="a40" width="833" llx="35" lly="-14" urx="798" ury="705"/> + <char name="a41" width="816" llx="35" lly="-13" urx="782" ury="705"/> + <char name="a42" width="831" llx="35" lly="-14" urx="796" ury="705"/> + <char name="a43" width="923" llx="35" lly="-14" urx="888" ury="705"/> + <char name="a44" width="744" llx="35" lly="0" urx="710" ury="692"/> + <char name="a45" width="723" llx="35" lly="0" urx="688" ury="692"/> + <char name="a46" width="749" llx="35" lly="0" urx="714" ury="692"/> + <char name="a47" width="790" llx="34" lly="-14" urx="756" ury="705"/> + <char name="a48" width="792" llx="35" lly="-14" urx="758" ury="705"/> + <char name="a49" width="695" llx="35" lly="-14" urx="661" ury="706"/> + <char name="a50" width="776" llx="35" lly="-6" urx="741" ury="699"/> + <char name="a51" width="768" llx="35" lly="-7" urx="734" ury="699"/> + <char name="a52" width="792" llx="35" lly="-14" urx="757" ury="705"/> + <char name="a53" width="759" llx="35" lly="0" urx="725" ury="692"/> + <char name="a54" width="707" llx="35" lly="-13" urx="672" ury="704"/> + <char name="a55" width="708" llx="35" lly="-14" urx="672" ury="705"/> + <char name="a56" width="682" llx="35" lly="-14" urx="647" ury="705"/> + <char name="a57" width="701" llx="35" lly="-14" urx="666" ury="705"/> + <char name="a58" width="826" llx="35" lly="-14" urx="791" ury="705"/> + <char name="a59" width="815" llx="35" lly="-14" urx="780" ury="705"/> + <char name="a60" width="789" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a61" width="789" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a62" width="707" llx="34" lly="-14" urx="673" ury="705"/> + <char name="a63" width="687" llx="36" lly="0" urx="651" ury="692"/> + <char name="a64" width="696" llx="35" lly="0" urx="661" ury="691"/> + <char name="a65" width="689" llx="35" lly="0" urx="655" ury="692"/> + <char name="a66" width="786" llx="34" lly="-14" urx="751" ury="705"/> + <char name="a67" width="787" llx="35" lly="-14" urx="752" ury="705"/> + <char name="a68" width="713" llx="35" lly="-14" urx="678" ury="705"/> + <char name="a69" width="791" llx="35" lly="-14" urx="756" ury="705"/> + <char name="a70" width="785" llx="36" lly="-14" urx="751" ury="705"/> + <char name="a71" width="791" llx="35" lly="-14" urx="757" ury="705"/> + <char name="a72" width="873" llx="35" lly="-14" urx="838" ury="705"/> + <char name="a73" width="761" llx="35" lly="0" urx="726" ury="692"/> + <char name="a74" width="762" llx="35" lly="0" urx="727" ury="692"/> + <char name="a203" width="762" llx="35" lly="0" urx="727" ury="692"/> + <char name="a75" width="759" llx="35" lly="0" urx="725" ury="692"/> + <char name="a204" width="759" llx="35" lly="0" urx="725" ury="692"/> + <char name="a76" width="892" llx="35" lly="0" urx="858" ury="705"/> + <char name="a77" width="892" llx="35" lly="-14" urx="858" ury="692"/> + <char name="a78" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a79" width="784" llx="35" lly="-14" urx="749" ury="705"/> + <char name="a81" width="438" llx="35" lly="-14" urx="403" ury="705"/> + <char name="a82" width="138" llx="35" lly="0" urx="104" ury="692"/> + <char name="a83" width="277" llx="35" lly="0" urx="242" ury="692"/> + <char name="a84" width="415" llx="35" lly="0" urx="380" ury="692"/> + <char name="a97" width="392" llx="35" lly="263" urx="357" ury="705"/> + <char name="a98" width="392" llx="34" lly="263" urx="357" ury="705"/> + <char name="a99" width="668" llx="35" lly="263" urx="633" ury="705"/> + <char name="a100" width="668" llx="36" lly="263" urx="634" ury="705"/> + <char name="a101" width="732" llx="35" lly="-143" urx="697" ury="806"/> + <char name="a102" width="544" llx="56" lly="-14" urx="488" ury="706"/> + <char name="a103" width="544" llx="34" lly="-14" urx="508" ury="705"/> + <char name="a104" width="910" llx="35" lly="40" urx="875" ury="651"/> + <char name="a106" width="667" llx="35" lly="-14" urx="633" ury="705"/> + <char name="a107" width="760" llx="35" lly="-14" urx="726" ury="705"/> + <char name="a108" width="760" llx="0" lly="121" urx="758" ury="569"/> + <char name="a112" width="776" llx="35" lly="0" urx="741" ury="705"/> + <char name="a111" width="595" llx="34" lly="-14" urx="560" ury="705"/> + <char name="a110" width="694" llx="35" lly="-14" urx="659" ury="705"/> + <char name="a109" width="626" llx="34" lly="0" urx="591" ury="705"/> + <char name="a120" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a121" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a122" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a123" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a124" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a125" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a126" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a127" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a128" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a129" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a130" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a131" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a132" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a133" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a134" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a135" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a136" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a137" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a138" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a139" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a140" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a141" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a142" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a143" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a144" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a145" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a146" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a147" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a148" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a149" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a150" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a151" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a152" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a153" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a154" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a155" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a156" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a157" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a158" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a159" width="788" llx="35" lly="-14" urx="754" ury="705"/> + <char name="a160" width="894" llx="35" lly="58" urx="860" ury="634"/> + <char name="a161" width="838" llx="35" lly="152" urx="803" ury="540"/> + <char name="a163" width="1016" llx="34" lly="152" urx="981" ury="540"/> + <char name="a164" width="458" llx="35" lly="-127" urx="422" ury="820"/> + <char name="a196" width="748" llx="35" lly="94" urx="698" ury="597"/> + <char name="a165" width="924" llx="35" lly="140" urx="890" ury="552"/> + <char name="a192" width="748" llx="35" lly="94" urx="698" ury="597"/> + <char name="a166" width="918" llx="35" lly="166" urx="884" ury="526"/> + <char name="a167" width="927" llx="35" lly="32" urx="892" ury="660"/> + <char name="a168" width="928" llx="35" lly="129" urx="891" ury="562"/> + <char name="a169" width="928" llx="35" lly="128" urx="893" ury="563"/> + <char name="a170" width="834" llx="35" lly="155" urx="799" ury="537"/> + <char name="a171" width="873" llx="35" lly="93" urx="838" ury="599"/> + <char name="a172" width="828" llx="35" lly="104" urx="791" ury="588"/> + <char name="a173" width="924" llx="35" lly="98" urx="889" ury="594"/> + <char name="a162" width="924" llx="35" lly="98" urx="889" ury="594"/> + <char name="a174" width="917" llx="35" lly="0" urx="882" ury="692"/> + <char name="a175" width="930" llx="35" lly="84" urx="896" ury="608"/> + <char name="a176" width="931" llx="35" lly="84" urx="896" ury="608"/> + <char name="a177" width="463" llx="35" lly="-99" urx="429" ury="791"/> + <char name="a178" width="883" llx="35" lly="71" urx="848" ury="623"/> + <char name="a179" width="836" llx="35" lly="44" urx="802" ury="648"/> + <char name="a193" width="836" llx="35" lly="44" urx="802" ury="648"/> + <char name="a180" width="867" llx="35" lly="101" urx="832" ury="591"/> + <char name="a199" width="867" llx="35" lly="101" urx="832" ury="591"/> + <char name="a181" width="696" llx="35" lly="44" urx="661" ury="648"/> + <char name="a200" width="696" llx="35" lly="44" urx="661" ury="648"/> + <char name="a182" width="874" llx="35" lly="77" urx="840" ury="619"/> + <char name="a201" width="874" llx="35" lly="73" urx="840" ury="615"/> + <char name="a183" width="760" llx="35" lly="0" urx="725" ury="692"/> + <char name="a184" width="946" llx="35" lly="160" urx="911" ury="533"/> + <char name="a197" width="771" llx="34" lly="37" urx="736" ury="655"/> + <char name="a185" width="865" llx="35" lly="207" urx="830" ury="481"/> + <char name="a194" width="771" llx="34" lly="37" urx="736" ury="655"/> + <char name="a198" width="888" llx="34" lly="-19" urx="853" ury="712"/> + <char name="a186" width="967" llx="35" lly="124" urx="932" ury="568"/> + <char name="a195" width="888" llx="34" lly="-19" urx="853" ury="712"/> + <char name="a187" width="831" llx="35" lly="113" urx="796" ury="579"/> + <char name="a188" width="873" llx="36" lly="118" urx="838" ury="578"/> + <char name="a189" width="927" llx="35" lly="150" urx="891" ury="542"/> + <char name="a190" width="970" llx="35" lly="76" urx="931" ury="616"/> + <char name="a191" width="918" llx="34" lly="99" urx="884" ury="593"/> + <char name="a86" width="410" llx="35" lly="0" urx="375" ury="692"/> + <char name="a85" width="509" llx="35" lly="0" urx="475" ury="692"/> + <char name="a95" width="334" llx="35" lly="0" urx="299" ury="692"/> + <char name="a205" width="509" llx="35" lly="0" urx="475" ury="692"/> + <char name="a89" width="390" llx="35" lly="-14" urx="356" ury="705"/> + <char name="a87" width="234" llx="35" lly="-14" urx="199" ury="705"/> + <char name="a91" width="276" llx="35" lly="0" urx="242" ury="692"/> + <char name="a90" width="390" llx="35" lly="-14" urx="355" ury="705"/> + <char name="a206" width="410" llx="35" lly="0" urx="375" ury="692"/> + <char name="a94" width="317" llx="35" lly="0" urx="283" ury="692"/> + <char name="a93" width="317" llx="35" lly="0" urx="283" ury="692"/> + <char name="a92" width="276" llx="35" lly="0" urx="242" ury="692"/> + <char name="a96" width="334" llx="35" lly="0" urx="299" ury="692"/> + <char name="a88" width="234" llx="35" lly="-14" urx="199" ury="705"/> + </char-metrics> +</font-metrics> diff --git a/src/codegen/fonts/font-file.xsl b/src/codegen/fonts/font-file.xsl index 85b968808..8723ed960 100644 --- a/src/codegen/fonts/font-file.xsl +++ b/src/codegen/fonts/font-file.xsl @@ -35,6 +35,7 @@ <xsl:template match="font-metrics"> package org.apache.fop.fonts.base14; +import java.awt.Rectangle; <xsl:if test="count(kerning) > 0"> import java.util.Map; </xsl:if> @@ -42,12 +43,14 @@ import java.util.Set; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CodePointMapping; -import org.apache.fop.fonts.Typeface;; +import org.apache.fop.fonts.Typeface; public class <xsl:value-of select="class-name"/> extends Base14Font { private final static String fontName = "<xsl:value-of select="font-name"/>"; private final static String fullName = "<xsl:value-of select="full-name"/>"; private final static Set familyNames; + private final static int underlinePosition = <xsl:value-of select="underline-position"/>; + private final static int underlineThickness = <xsl:value-of select="underline-thickness"/>; private final static String encoding = "<xsl:value-of select="$encoding"/>"; private final static int capHeight = <xsl:value-of select="cap-height"/>; private final static int xHeight = <xsl:value-of select="x-height"/>; @@ -56,6 +59,7 @@ public class <xsl:value-of select="class-name"/> extends Base14Font { private final static int firstChar = <xsl:value-of select="first-char"/>; private final static int lastChar = <xsl:value-of select="last-char"/>; private final static int[] width; + private final static Rectangle[] boundingBoxes; private final CodePointMapping mapping = CodePointMapping.getMapping("<xsl:value-of select="$encoding"/>"); <xsl:if test="count(kerning) > 0"> @@ -66,7 +70,8 @@ public class <xsl:value-of select="class-name"/> extends Base14Font { static { width = new int[256]; - <xsl:apply-templates select="widths"/> + boundingBoxes = new Rectangle[256]; + <xsl:apply-templates select="char-metrics"/> <xsl:if test="count(kerning) > 0"> kerning = new java.util.HashMap(); Integer first, second; @@ -125,6 +130,14 @@ public class <xsl:value-of select="class-name"/> extends Base14Font { return size * xHeight; } + public int getUnderlinePosition(int size) { + return size * underlinePosition; + } + + public int getUnderlineThickness(int size) { + return size * underlineThickness; + } + public int getFirstChar() { return firstChar; } @@ -137,6 +150,11 @@ public class <xsl:value-of select="class-name"/> extends Base14Font { return size * width[i]; } + public Rectangle getBoundingBox(int glyphIndex, int size) { + Rectangle bbox = boundingBoxes[glyphIndex]; + return new Rectangle(bbox.x * size, bbox.y * size, bbox.width * size, bbox.height * size); + } + public int[] getWidths() { int[] arr = new int[getLastChar() - getFirstChar() + 1]; System.arraycopy(width, getFirstChar(), arr, 0, getLastChar() - getFirstChar() + 1); @@ -182,7 +200,9 @@ public class <xsl:value-of select="class-name"/> extends Base14Font { } </xsl:template> - <xsl:template match="widths/char"><xsl:variable name="char-name" select="@name"/><xsl:variable name="char-num" select="$glyphs[@name = $char-name]/@codepoint"/><xsl:if test="$char-num!=''"> width[0x<xsl:value-of select="$char-num"/>] = <xsl:value-of select="@width"/>;</xsl:if></xsl:template> + <xsl:template match="char-metrics/char"> + <xsl:variable name="char-name" select="@name"/><xsl:variable name="char-num" select="$glyphs[@name = $char-name]/@codepoint"/><xsl:if test="$char-num!=''"> width[0x<xsl:value-of select="$char-num"/>] = <xsl:value-of select="@width"/>; + boundingBoxes[0x<xsl:value-of select="$char-num"/>] = new Rectangle(<xsl:value-of select="@llx"/>,<xsl:value-of select="@lly"/>,<xsl:value-of select="@urx - @llx"/>,<xsl:value-of select="@ury - @lly"/>);</xsl:if></xsl:template> <xsl:template match="kerning"> first = new Integer(<xsl:value-of select="@kpx1"/>); diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.java b/src/java/org/apache/fop/afp/AFPEventProducer.java index 01d5c4ad7..1b43400c5 100644 --- a/src/java/org/apache/fop/afp/AFPEventProducer.java +++ b/src/java/org/apache/fop/afp/AFPEventProducer.java @@ -122,4 +122,12 @@ public interface AFPEventProducer extends EventProducer { * @event.severity WARN */ void charactersetMissingMetrics(Object source, char character, String charSet); + + /** + * Double-byte fonts are not currently supported in SVG. + * @param source the event source + * @param fontFamily name of DB font + * @event.severity WARN + */ + void invalidDBFontInSVG(Object source, String fontFamily); } diff --git a/src/java/org/apache/fop/afp/fonts/AFPFont.java b/src/java/org/apache/fop/afp/fonts/AFPFont.java index 06f484f37..99e15a46b 100644 --- a/src/java/org/apache/fop/afp/fonts/AFPFont.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFont.java @@ -19,6 +19,7 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -34,6 +35,8 @@ import org.apache.fop.fonts.Typeface; */ public abstract class AFPFont extends Typeface { + private static final double STRIKEOUT_POSITION_FACTOR = 0.45; + /** The font name */ protected final String name; @@ -117,7 +120,34 @@ public abstract class AFPFont extends Typeface { */ protected static final char toUnicodeCodepoint(int character) { //AFP fonts use Unicode directly as their mapped code points, so we can simply cast to char - return (char)character; + return (char) character; + } + + /** {@inheritDoc} */ + public int getUnderlineThickness(int size) { + // This is the FOCA recommendation in the absence of the Underline Thickness parameter + return getBoundingBox('-', size).height; + } + + /** {@inheritDoc} */ + public int getStrikeoutPosition(int size) { + //TODO This conflicts with the FOCA recommendation of 0 in the absence of the Throughscore Position + // parameter + return (int) (STRIKEOUT_POSITION_FACTOR * getCapHeight(size)); + } + + /** {@inheritDoc} */ + public int getStrikeoutThickness(int size) { + // This is the FOCA recommendation in the absence of the Throughscore Thickness parameter + return getBoundingBox('-', size).height; + } + + /** {@inheritDoc} */ + public abstract Rectangle getBoundingBox(int glyphIndex, int size); + + /** {@inheritDoc} */ + public int[] getWidths() { + throw new UnsupportedOperationException(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java b/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java index 7b57a2b8c..edbdf5e95 100644 --- a/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java @@ -71,22 +71,6 @@ public abstract class AbstractOutlineFont extends AFPFont { } /** - * Get the first character in this font. - * @return the first character in this font - */ - public int getFirstChar() { - return charSet.getFirstChar(); - } - - /** - * Get the last character in this font. - * @return the last character in this font - */ - public int getLastChar() { - return charSet.getLastChar(); - } - - /** * The ascender is the part of a lowercase letter that extends above the * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also * used to denote the part of the letter extending above the x-height. @@ -98,6 +82,17 @@ public abstract class AbstractOutlineFont extends AFPFont { return charSet.getAscender() * size; } + /** {@inheritDoc} */ + public int getUnderlinePosition(int size) { + return charSet.getUnderscorePosition() * size; + } + + @Override + public int getUnderlineThickness(int size) { + int underscoreWidth = charSet.getUnderscoreWidth(); + return underscoreWidth == 0 ? super.getUnderlineThickness(size) : underscoreWidth * size; + } + /** * Obtains the height of capital letters for the specified point size. * @@ -130,40 +125,7 @@ public abstract class AbstractOutlineFont extends AFPFont { return charSet.getXHeight() * size; } - /** - * Obtain the width of the character for the specified point size. - * @param character the character - * @param size the font size (in mpt) - * @return the width of the character for the specified point size - */ - public int getWidth(int character, int size) { - return charSet.getWidth(toUnicodeCodepoint(character)) * size; - } - /** - * Get the getWidth (in 1/1000ths of a point size) of all characters in this - * character set. - * - * @param size the font size (in mpt) - * @return the widths of all characters - */ - public int[] getWidths(int size) { - int[] widths = charSet.getWidths(); - for (int i = 0; i < widths.length; i++) { - widths[i] = widths[i] * size; - } - return widths; - } - - /** - * Get the getWidth (in 1/1000ths of a point size) of all characters in this - * character set. - * - * @return the widths of all characters - */ - public int[] getWidths() { - return getWidths(1000); - } /** {@inheritDoc} */ public boolean hasChar(char c) { diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index e0c3b9c9a..3df8ba4c4 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -19,10 +19,9 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; import java.io.UnsupportedEncodingException; import java.nio.charset.CharacterCodingException; -import java.util.HashMap; -import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -63,6 +62,8 @@ public class CharacterSet { private static final int MAX_NAME_LEN = 8; + /** The current orientation (currently only 0 is supported by FOP) */ + public static final int SUPPORTED_ORIENTATION = 0; /** The code page to which the character set relates */ protected final String codePage; @@ -79,11 +80,8 @@ public class CharacterSet { /** The path to the installed fonts */ private final AFPResourceAccessor accessor; - /** The current orientation (currently only 0 is supported by FOP) */ - private final String currentOrientation = "0"; - /** The collection of objects for each orientation */ - private final Map<String, CharacterSetOrientation> characterSetOrientations; + private CharacterSetOrientation characterSetOrientation; /** The nominal vertical size (in millipoints) for bitmap fonts. 0 for outline fonts. */ private int nominalVerticalSize; @@ -116,8 +114,6 @@ public class CharacterSet { this.encoding = encoding; this.encoder = charsetType.getEncoder(encoding); this.accessor = accessor; - - this.characterSetOrientations = new HashMap<String, CharacterSetOrientation>(4); } // right pad short names with space @@ -131,7 +127,9 @@ public class CharacterSet { * @param cso the metrics for the orientation */ public void addCharacterSetOrientation(CharacterSetOrientation cso) { - characterSetOrientations.put(String.valueOf(cso.getOrientation()), cso); + if (cso.getOrientation() == SUPPORTED_ORIENTATION) { + characterSetOrientation = cso; + } } /** @@ -165,11 +163,24 @@ public class CharacterSet { * @return the ascender value in millipoints */ public int getAscender() { - return getCharacterSetOrientation().getAscender(); } /** + * TODO + */ + public int getUnderscoreWidth() { + return getCharacterSetOrientation().getUnderscoreWidth(); + } + + /** + * TODO + */ + public int getUnderscorePosition() { + return getCharacterSetOrientation().getUnderscorePosition(); + } + + /** * Cap height is the average height of the uppercase characters in * a font. This value is specified by the designer of a font and is * usually the height of the uppercase M. @@ -177,7 +188,6 @@ public class CharacterSet { * @return the cap height value in millipoints */ public int getCapHeight() { - return getCharacterSetOrientation().getCapHeight(); } @@ -194,24 +204,6 @@ public class CharacterSet { } /** - * Returns the first character in the character set - * - * @return the first character in the character set (Unicode codepoint) - */ - public char getFirstChar() { - return getCharacterSetOrientation().getFirstChar(); - } - - /** - * Returns the last character in the character set - * - * @return the last character in the character set (Unicode codepoint) - */ - public char getLastChar() { - return getCharacterSetOrientation().getLastChar(); - } - - /** * Returns the resource accessor to load the font resources with. * @return the resource accessor to load the font resources with */ @@ -220,16 +212,6 @@ public class CharacterSet { } /** - * Get the width (in 1/1000ths of a point size) of all characters - * - * @return the widths of all characters - */ - public int[] getWidths() { - - return getCharacterSetOrientation().getWidths(); - } - - /** * XHeight refers to the height of the lower case letters above the baseline. * * @return the typical height of characters @@ -246,11 +228,13 @@ public class CharacterSet { * @param character the Unicode character from which the width will be calculated * @return the width of the character */ - public int getWidth(char character) { - return getCharacterSetOrientation().getWidth(character); + public int getWidth(char character, int size) { + return getCharacterSetOrientation().getWidth(character, size); } - + public Rectangle getCharacterBox(char character, int size) { + return getCharacterSetOrientation().getCharacterBox(character, size); + } /** * Returns the AFP character set identifier @@ -309,9 +293,7 @@ public class CharacterSet { * @return characterSetOrentation The current orientation metrics. */ private CharacterSetOrientation getCharacterSetOrientation() { - CharacterSetOrientation c - = characterSetOrientations.get(currentOrientation); - return c; + return characterSetOrientation; } /** diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java index 2565942b5..a3b2ab8ec 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java @@ -19,6 +19,7 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; @@ -292,16 +293,14 @@ public abstract class CharacterSetBuilder { metricNormalizationFactor = 1000.0d * 72000.0d / fontDescriptor.getNominalFontSizeInMillipoints() / dpi; } - + ValueNormalizer normalizer = new ValueNormalizer(metricNormalizationFactor); //process D3AC89 Font Position - processFontPosition(structuredFieldReader, characterSetOrientations, - metricNormalizationFactor); - + processFontPosition(structuredFieldReader, characterSetOrientations, normalizer); //process D38C89 Font Index (per orientation) for (int i = 0; i < characterSetOrientations.length; i++) { - processFontIndex(structuredFieldReader, - characterSetOrientations[i], codePage, metricNormalizationFactor); - characterSet.addCharacterSetOrientation(characterSetOrientations[i]); + CharacterSetOrientation characterSetOrientation = characterSetOrientations[i]; + processFontIndex(structuredFieldReader, characterSetOrientation, codePage, normalizer); + characterSet.addCharacterSetOrientation(characterSetOrientation); } } else { throw new IOException("Missing D3AE89 Font Control structured field."); @@ -314,6 +313,19 @@ public abstract class CharacterSetBuilder { return characterSet; } + private static class ValueNormalizer { + + private final double factor; + + public ValueNormalizer(double factor) { + this.factor = factor; + } + + public int normalize(int value) { + return (int) Math.round(value * factor); + } + } + /** * Load the code page information from the appropriate file. The file name * to load is determined by the code page name and the file extension 'CDP'. @@ -475,7 +487,7 @@ public abstract class CharacterSetBuilder { * @throws IOException if an I/O exception of some sort has occurred. */ private void processFontPosition(StructuredFieldReader structuredFieldReader, - CharacterSetOrientation[] characterSetOrientations, double metricNormalizationFactor) + CharacterSetOrientation[] characterSetOrientations, ValueNormalizer normalizer) throws IOException { byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF); @@ -493,48 +505,34 @@ public abstract class CharacterSetBuilder { if (position == 9) { CharacterSetOrientation characterSetOrientation = characterSetOrientations[characterSetOrientationIndex]; - int xHeight = getSBIN(fpData, 2); int capHeight = getSBIN(fpData, 4); int ascHeight = getSBIN(fpData, 6); int dscHeight = getSBIN(fpData, 8); - dscHeight = dscHeight * -1; - - characterSetOrientation.setXHeight( - (int)Math.round(xHeight * metricNormalizationFactor)); - characterSetOrientation.setCapHeight( - (int)Math.round(capHeight * metricNormalizationFactor)); - characterSetOrientation.setAscender( - (int)Math.round(ascHeight * metricNormalizationFactor)); - characterSetOrientation.setDescender( - (int)Math.round(dscHeight * metricNormalizationFactor)); + int underscoreWidth = getUBIN(fpData, 17); + int underscorePosition = getSBIN(fpData, 20); + characterSetOrientation.setXHeight(normalizer.normalize(xHeight)); + characterSetOrientation.setCapHeight(normalizer.normalize(capHeight)); + characterSetOrientation.setAscender(normalizer.normalize(ascHeight)); + characterSetOrientation.setDescender(normalizer.normalize(dscHeight)); + characterSetOrientation.setUnderscoreWidth(normalizer.normalize(underscoreWidth)); + characterSetOrientation.setUnderscorePosition(normalizer.normalize(underscorePosition)); } } else if (position == 22) { position = 0; characterSetOrientationIndex++; fpData[position] = data[index]; } - position++; } } - /** - * Process the font index details for the character set orientation. - * - * @param structuredFieldReader the structured field reader - * @param cso the CharacterSetOrientation object to populate - * @param codepage the map of code pages - * @param metricNormalizationFactor factor to apply to the metrics to get normalized - * font metric values - * @throws IOException if an I/O exception of some sort has occurred. - */ - private void processFontIndex(StructuredFieldReader structuredFieldReader, - CharacterSetOrientation cso, Map<String, String> codepage, - double metricNormalizationFactor) - throws IOException { + + private void processFontIndex(StructuredFieldReader structuredFieldReader, CharacterSetOrientation cso, + Map<String, String> codepage, ValueNormalizer normalizer) + throws IOException { byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF); @@ -543,8 +541,6 @@ public abstract class CharacterSetBuilder { byte[] gcgid = new byte[8]; byte[] fiData = new byte[20]; - char lowest = 255; - char highest = 0; String firstABCMismatch = null; // Read data, ignoring bytes 0 - 2 @@ -569,13 +565,15 @@ public abstract class CharacterSetBuilder { char cidx = idx.charAt(0); int width = getUBIN(fiData, 0); + int ascendHt = getSBIN(fiData, 2); + int descendDp = getSBIN(fiData, 4); int a = getSBIN(fiData, 10); int b = getUBIN(fiData, 12); int c = getSBIN(fiData, 14); int abc = a + b + c; int diff = Math.abs(abc - width); if (diff != 0 && width != 0) { - double diffPercent = 100 * diff / (double)width; + double diffPercent = 100 * diff / (double) width; if (diffPercent > 2) { if (LOG.isTraceEnabled()) { LOG.trace(gcgiString + ": " @@ -587,27 +585,16 @@ public abstract class CharacterSetBuilder { } } } - - if (cidx < lowest) { - lowest = cidx; - } - - if (cidx > highest) { - highest = cidx; - } - - int normalizedWidth = (int)Math.round(width * metricNormalizationFactor); - - cso.setWidth(cidx, normalizedWidth); - + int normalizedWidth = normalizer.normalize(width); + int x0 = normalizer.normalize(a); + int y0 = normalizer.normalize(-descendDp); + int dx = normalizer.normalize(b); + int dy = normalizer.normalize(ascendHt + descendDp); + cso.setCharacterMetrics(cidx, normalizedWidth, new Rectangle(x0, y0, dx, dy)); } - } } - cso.setFirstChar(lowest); - cso.setLastChar(highest); - if (LOG.isDebugEnabled() && firstABCMismatch != null) { //Debug level because it usually is no problem. LOG.debug("Font has metrics inconsitencies where A+B+C doesn't equal the" diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java index a730525d2..5fe524536 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java @@ -19,7 +19,7 @@ package org.apache.fop.afp.fonts; -import java.util.Arrays; +import java.awt.Rectangle; /** * The IBM Font Object Content Architecture (FOCA) supports presentation @@ -60,23 +60,13 @@ public class CharacterSetOrientation { /** * The character widths in the character set (indexed using Unicode codepoints) */ - private int[] charsWidths; + private IntegerKeyStore<CharacterMetrics> characterMetrics; /** * The height of lowercase letters */ private int xHeight; - /** - * The first character (Unicode codepoint) - */ - private char firstChar; - - /** - * The last character (Unicode codepoint) - */ - private char lastChar; - /** The character set orientation */ private final int orientation; /** space increment */ @@ -86,6 +76,10 @@ public class CharacterSetOrientation { /** Nominal Character Increment */ private final int nomCharIncrement; + private int underscoreWidth; + + private int underscorePosition; + /** * Constructor for the CharacterSetOrientation, the orientation is * expressed as the degrees rotation (i.e 0, 90, 180, 270) @@ -97,8 +91,7 @@ public class CharacterSetOrientation { this.spaceIncrement = spaceIncrement; this.emSpaceIncrement = emSpaceIncrement; this.nomCharIncrement = nomCharIncrement; - charsWidths = new int[256]; - Arrays.fill(charsWidths, -1); + this.characterMetrics = new IntegerKeyStore<CharacterMetrics>(); } /** @@ -138,19 +131,17 @@ public class CharacterSetOrientation { } /** - * The first character in the character set - * @return the first character (Unicode codepoint) + * TODO */ - public char getFirstChar() { - return firstChar; + public int getUnderscoreWidth() { + return underscoreWidth; } /** - * The last character in the character set - * @return the last character (Unicode codepoint) + * TODO */ - public char getLastChar() { - return lastChar; + public int getUnderscorePosition() { + return underscorePosition; } /** @@ -162,17 +153,6 @@ public class CharacterSetOrientation { } /** - * Get the width (in 1/1000ths of a point size) of all characters - * in this character set. - * @return the widths of all characters - */ - public int[] getWidths() { - int[] arr = new int[(getLastChar() - getFirstChar()) + 1]; - System.arraycopy(charsWidths, getFirstChar(), arr, 0, (getLastChar() - getFirstChar()) + 1); - return arr; - } - - /** * XHeight refers to the height of the lower case letters above * the baseline. * @return heightX the typical height of characters @@ -187,13 +167,38 @@ public class CharacterSetOrientation { * @param character the Unicode character to evaluate * @return the widths of the character */ - public int getWidth(char character) { - if (character >= charsWidths.length) { - throw new IllegalArgumentException("Invalid character: " - + character + " (" + Integer.toString(character) - + "), maximum is " + (charsWidths.length - 1)); + public int getWidth(char character, int size) { + CharacterMetrics cm = getCharacterMetrics(character); + return cm == null ? -1 : size * cm.width; + } + + private CharacterMetrics getCharacterMetrics(char character) { + return characterMetrics.get((int) character); + } + + /** + * Get the character box (rectangle with dimensions in 1/1000ths of a point size) of the character + * identified by the parameter passed. + * @param character the Unicode character to evaluate + * @return the character box + */ + public Rectangle getCharacterBox(char character, int size) { + CharacterMetrics cm = getCharacterMetrics(character); + return scale(cm == null ? getFallbackCharacterBox() : cm.characterBox, size); + } + + private static Rectangle scale(Rectangle rectangle, int size) { + if (rectangle == null) { + return null; + } else { + return new Rectangle((int) (size * rectangle.getX()), (int) (size * rectangle.getY()), + (int) (size * rectangle.getWidth()), (int) (size * rectangle.getHeight())); } - return charsWidths[character]; + } + + private Rectangle getFallbackCharacterBox() { + // TODO replace with something sensible + return new Rectangle(0, 0, 0, 0); } /** @@ -233,19 +238,19 @@ public class CharacterSetOrientation { } /** - * The first character in the character set - * @param firstChar the first character + * TODO + * @param underscoreWidth the underscore width value in millipoints */ - public void setFirstChar(char firstChar) { - this.firstChar = firstChar; + public void setUnderscoreWidth(int underscoreWidth) { + this.underscoreWidth = underscoreWidth; } /** - * The last character in the character set - * @param lastChar the last character + * TODO + * @param underscorePosition the underscore position value in millipoints */ - public void setLastChar(char lastChar) { - this.lastChar = lastChar; + public void setUnderscorePosition(int underscorePosition) { + this.underscorePosition = underscorePosition; } /** @@ -254,17 +259,8 @@ public class CharacterSetOrientation { * @param character the Unicode character for which the width is being set * @param width the widths of the character */ - public void setWidth(char character, int width) { - if (character >= charsWidths.length) { - // Increase the size of the array if necessary - // TODO Can we remove firstChar? surely firstChar==0 at this stage? - int[] arr = new int[(character - firstChar) + 1]; - System.arraycopy(charsWidths, 0, arr, 0, charsWidths.length); - Arrays.fill(arr, charsWidths.length, character - firstChar, -1); - charsWidths = arr; - } - charsWidths[character] = width; - + public void setCharacterMetrics(char character, int width, Rectangle characterBox) { + characterMetrics.put((int) character, new CharacterMetrics(width, characterBox)); } /** @@ -299,4 +295,16 @@ public class CharacterSetOrientation { public int getNominalCharIncrement() { return this.nomCharIncrement; } + + private static class CharacterMetrics { + + public final int width; + + public final Rectangle characterBox; + + public CharacterMetrics(int width, Rectangle characterBox) { + this.width = width; + this.characterBox = characterBox; + } + } } diff --git a/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java b/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java index 78da6ea82..5b9bf6101 100644 --- a/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java +++ b/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java @@ -19,6 +19,7 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; import java.lang.Character.UnicodeBlock; import java.util.HashSet; import java.util.Set; @@ -68,7 +69,7 @@ public class DoubleByteFont extends AbstractOutlineFont { public int getWidth(int character, int size) { int charWidth; try { - charWidth = charSet.getWidth(toUnicodeCodepoint(character)); + charWidth = charSet.getWidth(toUnicodeCodepoint(character), size); } catch (IllegalArgumentException e) { if (!charsProcessed.contains(character)) { charsProcessed.add(character); @@ -80,9 +81,9 @@ public class DoubleByteFont extends AbstractOutlineFont { } if (charWidth == -1) { - charWidth = getDefaultCharacterWidth(character); + charWidth = getDefaultCharacterWidth(character) * size; } - return charWidth * size; + return charWidth; } private int getDefaultCharacterWidth(int character) { @@ -94,6 +95,33 @@ public class DoubleByteFont extends AbstractOutlineFont { } } + @Override + public Rectangle getBoundingBox(int character, int size) { + Rectangle characterBox = getBoundingBoxOrNull(character, size); + if (characterBox == null) { + characterBox = getDefaultCharacterBox(character, size); + } + return characterBox; + } + + private Rectangle getBoundingBoxOrNull(int character, int size) { + Rectangle characterBox = null; + try { + characterBox = charSet.getCharacterBox(toUnicodeCodepoint(character), size); + } catch (IllegalArgumentException e) { + if (!charsProcessed.contains(character)) { + charsProcessed.add(character); + getAFPEventProducer().charactersetMissingMetrics(this, (char) character, + charSet.getName().trim()); + } + } + return characterBox; + } + + private Rectangle getDefaultCharacterBox(int character, int size) { + return getBoundingBoxOrNull('-', size); + } + private int inferCharWidth(int character) { //Is this character an ideograph? diff --git a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java index 7c2b68506..b729a8995 100644 --- a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java @@ -19,6 +19,8 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; + import org.apache.fop.afp.AFPEventProducer; import org.apache.fop.afp.util.AFPResourceAccessor; import org.apache.fop.fonts.Typeface; @@ -84,45 +86,31 @@ public class FopCharacterSet extends CharacterSet { } /** - * The first character in the character set - * @return the first character + * XHeight refers to the height of the lower case letters above the baseline. + * @return the typical height of characters */ - public char getFirstChar() { - return 0; + public int getXHeight() { + return charSet.getXHeight(1); } - /** - * The last character in the character set - * @return the last character - */ - public char getLastChar() { - return 0; + @Override + public int getWidth(char character, int size) { + return charSet.getWidth(character, size); } - /** - * Get the width (in 1/1000ths of a point size) of all characters - * @return the widths of all characters - */ - public int[] getWidths() { - return charSet.getWidths(); - } + @Override + public Rectangle getCharacterBox(char character, int size) { + return charSet.getBoundingBox(character, size); + }; - /** - * XHeight refers to the height of the lower case letters above the baseline. - * @return the typical height of characters - */ - public int getXHeight() { - return charSet.getXHeight(1); + @Override + public int getUnderscoreWidth() { + return charSet.getUnderlineThickness(1); } - /** - * Get the width (in 1/1000ths of a point size) of the character - * identified by the parameter passed. - * @param character the character from which the width will be calculated - * @return the width of the character - */ - public int getWidth(char character) { - return charSet.getWidth(character, 1); + @Override + public int getUnderscorePosition() { + return charSet.getUnderlinePosition(1); } /** diff --git a/src/java/org/apache/fop/afp/fonts/IntegerKeyStore.java b/src/java/org/apache/fop/afp/fonts/IntegerKeyStore.java new file mode 100644 index 000000000..7e73b5b9f --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/IntegerKeyStore.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.afp.fonts; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * A simple compact data structure to model a sparse array + */ +class IntegerKeyStore<T> { + + private static final int RANGE_BIT_SIZE = 8; + + private static final int RANGE_SIZE = 1 << RANGE_BIT_SIZE; + + private final Map<Integer, ArrayList<T>> arrays = new HashMap<Integer, ArrayList<T>>(); + + /** + * + * @param index a positive integer + * @param value value to store + */ + public void put(Integer index, T value) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + int rangeKey = index >> RANGE_BIT_SIZE; + int rangeIndex = index % RANGE_SIZE; + ArrayList<T> range = arrays.get(rangeKey); + if (range == null) { + range = new ArrayList<T>(Collections.<T>nCopies(RANGE_SIZE, null)); + arrays.put(rangeKey, range); + } + range.set(rangeIndex, value); + } + + /** + * + * @param index a positive integer + * @return value the value associated with the index or null + */ + public T get(Integer index) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + int rangeKey = index >> RANGE_BIT_SIZE; + int rangeIndex = index % RANGE_SIZE; + ArrayList<T> range = arrays.get(rangeKey); + return range == null ? null : range.get(rangeIndex); + } +} diff --git a/src/java/org/apache/fop/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java index e9cdf5ba4..fc2332ce9 100644 --- a/src/java/org/apache/fop/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java @@ -19,6 +19,8 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; + import org.apache.fop.afp.AFPEventProducer; /** @@ -38,4 +40,18 @@ public class OutlineFont extends AbstractOutlineFont { super(name, embeddable, charSet, eventProducer); } + /** + * Obtain the width of the character for the specified point size. + * @param character the character + * @param size the font size (in mpt) + * @return the width of the character for the specified point size + */ + public int getWidth(int character, int size) { + return charSet.getWidth(toUnicodeCodepoint(character), size); + } + + @Override + public Rectangle getBoundingBox(int character, int size) { + return charSet.getCharacterBox(toUnicodeCodepoint(character), size); + } } diff --git a/src/java/org/apache/fop/afp/fonts/RasterFont.java b/src/java/org/apache/fop/afp/fonts/RasterFont.java index 5c4c38dc5..1fd30e0ba 100644 --- a/src/java/org/apache/fop/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/afp/fonts/RasterFont.java @@ -19,8 +19,8 @@ package org.apache.fop.afp.fonts; +import java.awt.Rectangle; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; @@ -135,46 +135,21 @@ public class RasterFont extends AFPFont { } - /** - * Get the first character in this font. - * @return the first character in this font. - */ - public int getFirstChar() { - Iterator<CharacterSet> it = charSets.values().iterator(); - if (it.hasNext()) { - CharacterSet csm = it.next(); - return csm.getFirstChar(); - } else { - String msg = "getFirstChar() - No character set found for font:" + getFontName(); - LOG.error(msg); - throw new FontRuntimeException(msg); - } - } - - /** - * Get the last character in this font. - * @return the last character in this font. - */ - public int getLastChar() { - - Iterator<CharacterSet> it = charSets.values().iterator(); - if (it.hasNext()) { - CharacterSet csm = it.next(); - return csm.getLastChar(); + private int metricsToAbsoluteSize(CharacterSet cs, int value, int givenSize) { + int nominalVerticalSize = cs.getNominalVerticalSize(); + if (nominalVerticalSize != 0) { + return value * nominalVerticalSize; } else { - String msg = "getLastChar() - No character set found for font:" + getFontName(); - LOG.error(msg); - throw new FontRuntimeException(msg); + return value * givenSize; } - } - private int metricsToAbsoluteSize(CharacterSet cs, int value, int givenSize) { + private int metricsToAbsoluteSize(CharacterSet cs, double value, int givenSize) { int nominalVerticalSize = cs.getNominalVerticalSize(); if (nominalVerticalSize != 0) { - return value * nominalVerticalSize; + return (int) (value * nominalVerticalSize); } else { - return value * givenSize; + return (int) (value * givenSize); } } @@ -191,6 +166,20 @@ public class RasterFont extends AFPFont { return metricsToAbsoluteSize(cs, cs.getAscender(), size); } + /** {@inheritDoc} */ + public int getUnderlinePosition(int size) { + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.getUnderscorePosition(), size); + } + + @Override + public int getUnderlineThickness(int size) { + CharacterSet cs = getCharacterSet(size); + int underscoreWidth = cs.getUnderscoreWidth(); + return underscoreWidth == 0 ? super.getUnderlineThickness(size) + : metricsToAbsoluteSize(cs, underscoreWidth, size); + } + /** * Obtains the height of capital letters for the specified point size. * @@ -234,33 +223,20 @@ public class RasterFont extends AFPFont { */ public int getWidth(int character, int size) { CharacterSet cs = getCharacterSet(size); - return metricsToAbsoluteSize(cs, cs.getWidth(toUnicodeCodepoint(character)), size); + return metricsToAbsoluteSize(cs, cs.getWidth(toUnicodeCodepoint(character), 1), size); } /** - * Get the getWidth (in 1/1000ths of a point size) of all characters in this - * character set. - * - * @param size the font size (in mpt) - * @return the widths of all characters + * TODO */ - public int[] getWidths(int size) { + public Rectangle getBoundingBox(int character, int size) { CharacterSet cs = getCharacterSet(size); - int[] widths = cs.getWidths(); - for (int i = 0, c = widths.length; i < c; i++) { - widths[i] = metricsToAbsoluteSize(cs, widths[i], size); - } - return widths; - } - - /** - * Get the getWidth (in 1/1000ths of a point size) of all characters in this - * character set. - * - * @return the widths of all characters - */ - public int[] getWidths() { - return getWidths(1000); + Rectangle characterBox = cs.getCharacterBox(toUnicodeCodepoint(character), 1); + int x = metricsToAbsoluteSize(cs, characterBox.getX(), size); + int y = metricsToAbsoluteSize(cs, characterBox.getY(), size); + int w = metricsToAbsoluteSize(cs, characterBox.getWidth(), size); + int h = metricsToAbsoluteSize(cs, characterBox.getHeight(), size); + return new Rectangle(x, y, w, h); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java index 77ad7e806..d41adf867 100644 --- a/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java +++ b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java @@ -67,7 +67,11 @@ public class GraphicsCharacterString extends AbstractGraphicsCoord { /** {@inheritDoc} */ public int getDataLength() { - return super.getDataLength() + str.length(); + try { + return super.getDataLength() + getStringAsBytes().length; + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java index 2c6668454..5c13b9d92 100644 --- a/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java +++ b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java @@ -25,13 +25,17 @@ import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.DocumentLoader; import org.apache.batik.bridge.UserAgent; import org.apache.batik.gvt.TextPainter; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; +import org.apache.batik.gvt.font.FontFamilyResolver; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.events.EventBroadcaster; import org.apache.fop.fonts.FontInfo; import org.apache.fop.svg.AbstractFOPBridgeContext; +import org.apache.fop.svg.font.AggregatingFontFamilyResolver; /** * An AFP specific implementation of a Batik BridgeContext @@ -40,6 +44,8 @@ public class AFPBridgeContext extends AbstractFOPBridgeContext { private final AFPGraphics2D g2d; + private final EventBroadcaster eventBroadCaster; + /** * Constructs a new bridge context. * @@ -54,47 +60,35 @@ public class AFPBridgeContext extends AbstractFOPBridgeContext { */ public AFPBridgeContext(UserAgent userAgent, FontInfo fontInfo, ImageManager imageManager, ImageSessionContext imageSessionContext, - AffineTransform linkTransform, AFPGraphics2D g2d) { + AffineTransform linkTransform, AFPGraphics2D g2d, EventBroadcaster eventBroadCaster) { super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform); this.g2d = g2d; + this.eventBroadCaster = eventBroadCaster; } - /** - * Constructs a new bridge context. - * @param userAgent the user agent - * @param documentLoader the Document Loader to use for referenced documents. - * @param fontInfo the font list for the text painter, may be null - * in which case text is painted as shapes - * @param imageManager an image manager - * @param imageSessionContext an image session context - * @param linkTransform AffineTransform to properly place links, - * may be null - * @param g2d an AFPGraphics 2D implementation - */ - public AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader, + private AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader, FontInfo fontInfo, ImageManager imageManager, ImageSessionContext imageSessionContext, - AffineTransform linkTransform, AFPGraphics2D g2d) { - super(userAgent, documentLoader, fontInfo, imageManager, - imageSessionContext, linkTransform); + AffineTransform linkTransform, AFPGraphics2D g2d, EventBroadcaster eventBroadCaster) { + super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform); this.g2d = g2d; + this.eventBroadCaster = eventBroadCaster; } /** {@inheritDoc} */ @Override public void registerSVGBridges() { super.registerSVGBridges(); - if (fontInfo != null) { AFPTextHandler textHandler = new AFPTextHandler(fontInfo, g2d.getResourceManager()); g2d.setCustomTextHandler(textHandler); - - TextPainter textPainter = new AFPTextPainter(textHandler); - setTextPainter(textPainter); - + //TODO + FontFamilyResolver fontFamilyResolver = new AggregatingFontFamilyResolver( + new AFPFontFamilyResolver(fontInfo, eventBroadCaster), DefaultFontFamilyResolver.SINGLETON); + TextPainter textPainter = new AFPTextPainter(textHandler, fontFamilyResolver); + setTextPainter(new AFPTextPainter(textHandler, fontFamilyResolver)); putBridge(new AFPTextElementBridge(textPainter)); } - putBridge(new AFPImageElementBridge()); } @@ -105,7 +99,7 @@ public class AFPBridgeContext extends AbstractFOPBridgeContext { fontInfo, getImageManager(), getImageSessionContext(), - linkTransform, g2d); + linkTransform, g2d, eventBroadCaster); } } diff --git a/src/java/org/apache/fop/afp/svg/AFPFontFamilyResolver.java b/src/java/org/apache/fop/afp/svg/AFPFontFamilyResolver.java new file mode 100644 index 000000000..27026f4f3 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPFontFamilyResolver.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.afp.svg; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.fop.afp.AFPEventProducer; +import org.apache.fop.afp.fonts.DoubleByteFont; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.Typeface; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; +import org.apache.fop.svg.font.FOPGVTFontFamily; +import org.apache.fop.svg.font.FilteringFontFamilyResolver; + +public class AFPFontFamilyResolver extends FilteringFontFamilyResolver { + + private final FontInfo fontInfo; + + private final AFPEventProducer eventProducer; + + + public AFPFontFamilyResolver(FontInfo fontInfo, EventBroadcaster eventBroadCaster) { + super(new FOPFontFamilyResolverImpl(fontInfo)); + this.fontInfo = fontInfo; + this.eventProducer = AFPEventProducer.Provider.get(eventBroadCaster); + } + + @Override + public FOPGVTFontFamily resolve(String familyName) { + FOPGVTFontFamily fopGVTFontFamily = super.resolve(familyName); + // TODO why don't DB fonts work with GOCA?!? + if (fopGVTFontFamily != null && fopGVTFontFamily.deriveFont(1, new HashMap()) + .getFont().getFontMetrics() instanceof DoubleByteFont) { + notifyDBFontRejection(fopGVTFontFamily.getFamilyName()); + fopGVTFontFamily = null; + } + return fopGVTFontFamily; + } + + @Override + public FOPGVTFontFamily getFamilyThatCanDisplay(char c) { + Map<String, Typeface> fonts = fontInfo.getFonts(); + for (Typeface font : fonts.values()) { + // TODO why don't DB fonts work with GOCA?!? + if (font.hasChar(c) && !(font instanceof DoubleByteFont)) { + String fontFamily = font.getFamilyNames().iterator().next(); + if (font instanceof DoubleByteFont) { + notifyDBFontRejection(font.getFontName()); + } else { + return new FOPGVTFontFamily(fontInfo, fontFamily, + new FontTriplet(fontFamily, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + } + + } + } + return null; + } + + private void notifyDBFontRejection(String fontFamily) { + eventProducer.invalidDBFontInSVG(this, fontFamily); + } + +} diff --git a/src/java/org/apache/fop/afp/svg/AFPTextHandler.java b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java index 2bb4cb60e..3e987648e 100644 --- a/src/java/org/apache/fop/afp/svg/AFPTextHandler.java +++ b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java @@ -135,27 +135,18 @@ public class AFPTextHandler extends FOPTextHandlerAdapter { if (log.isDebugEnabled()) { log.debug(" with overriding font: " + internalFontName + ", " + fontSize); } - } else { - java.awt.Font awtFont = g2d.getFont(); - Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont); - if (log.isDebugEnabled()) { - log.debug(" with font: " + fopFont); - } - internalFontName = fopFont.getFontName(); - fontSize = fopFont.getFontSize(); + fontSize = (int) Math.round(g2d.convertToAbsoluteLength(fontSize)); + fontReference = registerPageFont(pageFonts, internalFontName, fontSize); + // TODO: re-think above registerPageFont code... + AFPFont afpFont = (AFPFont) fontInfo.getFonts().get(internalFontName); + final CharacterSet charSet = afpFont.getCharacterSet(fontSize); + // Work-around for InfoPrint's AFP which loses character set state + // over Graphics Data + // boundaries. + graphicsObj.setCharacterSet(fontReference); + // add the character string + graphicsObj.addString(str, Math.round(x), Math.round(y), charSet); } - fontSize = (int)Math.round( - g2d.convertToAbsoluteLength(fontSize)); - fontReference = registerPageFont(pageFonts, internalFontName, fontSize); - // TODO: re-think above registerPageFont code... - AFPFont afpFont = (AFPFont) fontInfo.getFonts().get(internalFontName); - final CharacterSet charSet = afpFont.getCharacterSet(fontSize); - // Work-around for InfoPrint's AFP which loses character set state - // over Graphics Data - // boundaries. - graphicsObj.setCharacterSet(fontReference); - // add the character string - graphicsObj.addString(str, Math.round(x), Math.round(y), charSet); } else { //Inside Batik's SVG filter operations, you won't get an AFPGraphics2D g.drawString(str, x, y); diff --git a/src/java/org/apache/fop/afp/svg/AFPTextPainter.java b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java index 3815c9eae..996ae8691 100644 --- a/src/java/org/apache/fop/afp/svg/AFPTextPainter.java +++ b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java @@ -21,6 +21,9 @@ package org.apache.fop.afp.svg; import java.awt.Graphics2D; +import org.apache.batik.gvt.font.FontFamilyResolver; +import org.apache.batik.gvt.renderer.StrokingTextPainter; + import org.apache.fop.afp.AFPGraphics2D; import org.apache.fop.svg.AbstractFOPTextPainter; import org.apache.fop.svg.FOPTextHandler; @@ -39,8 +42,8 @@ public class AFPTextPainter extends AbstractFOPTextPainter { * Create a new text painter with the given font information. * @param nativeTextHandler the NativeTextHandler instance used for text painting */ - public AFPTextPainter(FOPTextHandler nativeTextHandler) { - super(nativeTextHandler); + public AFPTextPainter(FOPTextHandler nativeTextHandler, FontFamilyResolver fopFontFamilyResolver) { + super(nativeTextHandler, new FOPStrokingTextPainter(fopFontFamilyResolver)); } /** {@inheritDoc} */ @@ -48,4 +51,18 @@ public class AFPTextPainter extends AbstractFOPTextPainter { return g2d instanceof AFPGraphics2D; } + private static class FOPStrokingTextPainter extends StrokingTextPainter { + + private final FontFamilyResolver fopFontFontFamily; + + FOPStrokingTextPainter(FontFamilyResolver fopFontFontFamily) { + this.fopFontFontFamily = fopFontFontFamily; + } + + @Override + protected FontFamilyResolver getFontFamilyResolver() { + return fopFontFontFamily; + } + } + } diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 2fc998c63..0b7dde212 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -21,7 +21,6 @@ package org.apache.fop.fo; import java.awt.Color; import java.nio.CharBuffer; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Stack; @@ -38,12 +37,13 @@ import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.fonts.TextFragment; import org.apache.fop.util.CharUtilities; /** * A text node (PCDATA) in the formatting object tree. */ -public class FOText extends FONode implements CharSequence { +public class FOText extends FONode implements CharSequence, TextFragment { /** the <code>CharBuffer</code> containing the text */ private CharBuffer charBuffer; @@ -93,9 +93,6 @@ public class FOText extends FONode implements CharSequence { /* bidi levels */ private int[] bidiLevels; - /* advanced script processing state */ - private Map/*<MapRange,String>*/ mappings; - private static final int IS_WORD_CHAR_FALSE = 0; private static final int IS_WORD_CHAR_TRUE = 1; private static final int IS_WORD_CHAR_MAYBE = 2; @@ -804,93 +801,6 @@ public class FOText extends FONode implements CharSequence { } } - /** - * Add characters mapped by script substitution processing. - * @param start index in character buffer - * @param end index in character buffer - * @param mappedChars sequence of character codes denoting substituted characters - */ - public void addMapping(int start, int end, CharSequence mappedChars) { - if (mappings == null) { - mappings = new java.util.HashMap(); - } - mappings.put(new MapRange(start, end), mappedChars.toString()); - } - - /** - * Determine if characters over specific interval have a mapping. - * @param start index in character buffer - * @param end index in character buffer - * @return true if a mapping exist such that the mapping's interval is coincident to - * [start,end) - */ - public boolean hasMapping(int start, int end) { - return (mappings != null) && (mappings.containsKey(new MapRange(start, end))); - } - - /** - * Obtain mapping of characters over specific interval. - * @param start index in character buffer - * @param end index in character buffer - * @return a string of characters representing the mapping over the interval - * [start,end) - */ - public String getMapping(int start, int end) { - if (mappings != null) { - return (String) mappings.get(new MapRange(start, end)); - } else { - return null; - } - } - - /** - * Obtain length of mapping of characters over specific interval. - * @param start index in character buffer - * @param end index in character buffer - * @return the length of the mapping (if present) or zero - */ - public int getMappingLength(int start, int end) { - if (mappings != null) { - return ((String) mappings.get(new MapRange(start, end))) .length(); - } else { - return 0; - } - } - - /** - * Obtain bidirectional levels of mapping of characters over specific interval. - * @param start index in character buffer - * @param end index in character buffer - * @return a (possibly empty) array of bidi levels or null - * in case no bidi levels have been assigned - */ - public int[] getMappingBidiLevels(int start, int end) { - if (hasMapping(start, end)) { - int nc = end - start; - int nm = getMappingLength(start, end); - int[] la = getBidiLevels(start, end); - if (la == null) { - return null; - } else if (nm == nc) { // mapping is same length as mapped range - return la; - } else if (nm > nc) { // mapping is longer than mapped range - int[] ma = new int [ nm ]; - System.arraycopy(la, 0, ma, 0, la.length); - for (int i = la.length, - n = ma.length, l = (i > 0) ? la [ i - 1 ] : 0; i < n; i++) { - ma [ i ] = l; - } - return ma; - } else { // mapping is shorter than mapped range - int[] ma = new int [ nm ]; - System.arraycopy(la, 0, ma, 0, ma.length); - return ma; - } - } else { - return getBidiLevels(start, end); - } - } - @Override protected Stack collectDelimitedTextRanges(Stack ranges, DelimitedTextRange currentRange) { if (currentRange != null) { diff --git a/src/java/org/apache/fop/fonts/Base14Font.java b/src/java/org/apache/fop/fonts/Base14Font.java index 9b2e95bc7..fdefd0cdd 100644 --- a/src/java/org/apache/fop/fonts/Base14Font.java +++ b/src/java/org/apache/fop/fonts/Base14Font.java @@ -25,4 +25,15 @@ package org.apache.fop.fonts; */ public abstract class Base14Font extends Typeface { + /** Thickness for underline and strikeout. */ + private static final int LINE_THICKNESS = 50; + + public int getStrikeoutPosition(int size) { + return getXHeight(size) / 2; + } + + public int getStrikeoutThickness(int size) { + return size * LINE_THICKNESS; + } + } diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index dc398263e..26212ea56 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; + import org.apache.fop.apps.io.InternalResourceResolver; //Java diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 70961a55c..96b70feea 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -37,6 +37,9 @@ import org.apache.fop.apps.io.InternalResourceResolver; public abstract class CustomFont extends Typeface implements FontDescriptor, MutableFont { + /** Fallback thickness for underline and strikeout when not provided by the font. */ + private static final int DEFAULT_LINE_THICKNESS = 50; + private String fontName; private String fullName; private Set<String> familyNames; @@ -60,6 +63,14 @@ public abstract class CustomFont extends Typeface private int firstChar; private int lastChar = 255; + private int underlinePosition; + + private int underlineThickness; + + private int strikeoutPosition; + + private int strikeoutThickness; + private Map<Integer, Map<Integer, Integer>> kerning; private boolean useKerning = true; @@ -507,4 +518,40 @@ public abstract class CustomFont extends Typeface return copy; } + public int getUnderlinePosition(int size) { + return (underlinePosition == 0) + ? getDescender(size) / 2 + : size * underlinePosition; + } + + public void setUnderlinePosition(int underlinePosition) { + this.underlinePosition = underlinePosition; + } + + public int getUnderlineThickness(int size) { + return size * ((underlineThickness == 0) ? DEFAULT_LINE_THICKNESS : underlineThickness); + } + + public void setUnderlineThickness(int underlineThickness) { + this.underlineThickness = underlineThickness; + } + + public int getStrikeoutPosition(int size) { + return (strikeoutPosition == 0) + ? getXHeight(size) / 2 + : size * strikeoutPosition; + } + + public void setStrikeoutPosition(int strikeoutPosition) { + this.strikeoutPosition = strikeoutPosition; + } + + public int getStrikeoutThickness(int size) { + return (strikeoutThickness == 0) ? getUnderlineThickness(size) : size * strikeoutThickness; + } + + public void setStrikeoutThickness(int strikeoutThickness) { + this.strikeoutThickness = strikeoutThickness; + } + } diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 472567eec..720531205 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -30,6 +30,7 @@ import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + /** * The FontInfo holds font information for the layout and rendering of a fo document. * This stores the list of available fonts that are setup by @@ -135,12 +136,10 @@ public class FontInfo { if (oldName != null) { int oldPriority = tripletPriorities.get(triplet).intValue(); if (oldPriority < newPriority) { - logDuplicateFont(triplet, false, oldName, oldPriority, - internalFontKey, newPriority); + logDuplicateFont(triplet, false, oldName, oldPriority, internalFontKey, newPriority); return; } else { - logDuplicateFont(triplet, true, oldName, oldPriority, - internalFontKey, newPriority); + logDuplicateFont(triplet, true, oldName, oldPriority, internalFontKey, newPriority); } } this.triplets.put(triplet, internalFontKey); @@ -157,9 +156,8 @@ public class FontInfo { * @param newKey the new internal font name * @param newPriority the priority of the duplicate font mapping */ - private void logDuplicateFont(FontTriplet triplet, boolean replacing, - String oldKey, int oldPriority, - String newKey, int newPriority) { + private void logDuplicateFont(FontTriplet triplet, boolean replacing, String oldKey, int oldPriority, + String newKey, int newPriority) { if (log.isDebugEnabled()) { log.debug(triplet + (replacing ? ": Replacing " : ": Not replacing ") @@ -198,8 +196,7 @@ public class FontInfo { * default font if not found * @return internal font triplet key */ - private FontTriplet fontLookup(String family, String style, - int weight, boolean substitutable) { + private FontTriplet fontLookup(String family, String style, int weight, boolean substitutable) { if (log.isTraceEnabled()) { log.trace("Font lookup: " + family + " " + style + " " + weight + (substitutable ? " substitutable" : "")); @@ -302,8 +299,7 @@ public class FontInfo { * @return the requested Font instance */ public Font getFontInstance(FontTriplet triplet, int fontSize) { - Map<Integer, Font> sizes - = getFontInstanceCache().get(triplet); + Map<Integer, Font> sizes = getFontInstanceCache().get(triplet); if (sizes == null) { sizes = new HashMap<Integer, Font>(); getFontInstanceCache().put(triplet, sizes); @@ -379,13 +375,11 @@ public class FontInfo { * @param weight font weight * @return the font triplet of the font chosen */ - public FontTriplet fontLookup(String family, String style, - int weight) { + public FontTriplet fontLookup(String family, String style, int weight) { return fontLookup(family, style, weight, true); } - private List<FontTriplet> fontLookup(String[] families, String style, - int weight, boolean substitutable) { + private List<FontTriplet> fontLookup(String[] families, String style, int weight, boolean substitutable) { List<FontTriplet> matchingTriplets = new ArrayList<FontTriplet>(); FontTriplet triplet = null; for (int i = 0; i < families.length; i++) { @@ -410,8 +404,7 @@ public class FontInfo { * @return the set of font triplets of all supported and chosen font-families * in the specified style and weight. */ - public FontTriplet[] fontLookup(String[] families, String style, - int weight) { + public FontTriplet[] fontLookup(String[] families, String style, int weight) { if (families.length == 0) { throw new IllegalArgumentException("Specify at least one font family"); } @@ -434,8 +427,8 @@ public class FontInfo { sb.append(families[i]); } throw new IllegalStateException( - "fontLookup must return an array with at least one " - + "FontTriplet on the last call. Lookup: " + sb.toString()); + "fontLookup must return an array with at least one " + + "FontTriplet on the last call. Lookup: " + sb.toString()); } FontTriplet[] fontTriplets = new FontTriplet[matchedTriplets.size()]; @@ -469,8 +462,7 @@ public class FontInfo { * @param weight font weight * @return internal key */ - public FontTriplet findAdjustWeight(String family, String style, - int weight) { + public FontTriplet findAdjustWeight(String family, String style, int weight) { FontTriplet key = null; String f = null; int newWeight = weight; @@ -542,8 +534,7 @@ public class FontInfo { * @param weight font weight * @return internal key */ - public static FontTriplet createFontKey(String family, String style, - int weight) { + public static FontTriplet createFontKey(String family, String style, int weight) { return new FontTriplet(family, style, weight); } diff --git a/src/java/org/apache/fop/fonts/FontMetrics.java b/src/java/org/apache/fop/fonts/FontMetrics.java index ff32d7305..159d321f7 100644 --- a/src/java/org/apache/fop/fonts/FontMetrics.java +++ b/src/java/org/apache/fop/fonts/FontMetrics.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; +import java.awt.Rectangle; import java.util.Map; import java.util.Set; @@ -120,6 +121,15 @@ public interface FontMetrics { int[] getWidths(); /** + * Returns the bounding box of the glyph at the given index, for the given font size. + * + * @param glyphIndex glyph index + * @param size font size + * @return the scaled bounding box scaled in 1/1000ths of the given size + */ + Rectangle getBoundingBox(int glyphIndex, int size); + + /** * Indicates if the font has kering information. * @return True, if kerning is available. */ @@ -131,4 +141,38 @@ public interface FontMetrics { */ Map<Integer, Map<Integer, Integer>> getKerningInfo(); + /** + * Returns the distance from the baseline to the center of the underline (negative + * value indicates below baseline). + * + * @param size font size + * @return the position in 1/1000ths of the font size + */ + int getUnderlinePosition(int size); + + /** + * Returns the thickness of the underline. + * + * @param size font size + * @return the thickness in 1/1000ths of the font size + */ + int getUnderlineThickness(int size); + + /** + * Returns the distance from the baseline to the center of the strikeout line + * (negative value indicates below baseline). + * + * @param size font size + * @return the position in 1/1000ths of the font size + */ + int getStrikeoutPosition(int size); + + /** + * Returns the thickness of the strikeout line. + * + * @param size font size + * @return the thickness in 1/1000ths of the font size + */ + int getStrikeoutThickness(int size); + } diff --git a/src/java/org/apache/fop/fonts/GlyphMapping.java b/src/java/org/apache/fop/fonts/GlyphMapping.java new file mode 100644 index 000000000..a8a82085e --- /dev/null +++ b/src/java/org/apache/fop/fonts/GlyphMapping.java @@ -0,0 +1,327 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fonts; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.util.CharScript; +import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.CharUtilities; + +/** + * Stores the mapping of a text fragment to glyphs, along with various information. + */ +public class GlyphMapping { + + private static final Log LOG = LogFactory.getLog(GlyphMapping.class); + /** Inclusive. */ + public final int startIndex; + /** Exclusive. */ + public final int endIndex; + private int wordCharLength; + public final int wordSpaceCount; + public int letterSpaceCount; + public MinOptMax areaIPD; + public final boolean isHyphenated; + public final boolean isSpace; + public boolean breakOppAfter; + public final Font font; + public final int level; + public final int[][] gposAdjustments; + public final String mapping; + + public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount, + MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, + Font font, int level, int[][] gposAdjustments) { + this(startIndex, endIndex, wordSpaceCount, letterSpaceCount, areaIPD, isHyphenated, + isSpace, breakOppAfter, font, level, gposAdjustments, null); + } + + public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount, + MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, + Font font, int level, int[][] gposAdjustments, String mapping) { + assert startIndex <= endIndex; + this.startIndex = startIndex; + this.endIndex = endIndex; + this.wordCharLength = -1; + this.wordSpaceCount = wordSpaceCount; + this.letterSpaceCount = letterSpaceCount; + this.areaIPD = areaIPD; + this.isHyphenated = isHyphenated; + this.isSpace = isSpace; + this.breakOppAfter = breakOppAfter; + this.font = font; + this.level = level; + this.gposAdjustments = gposAdjustments; + this.mapping = mapping; + } + + public static GlyphMapping doGlyphMapping(TextFragment text, int startIndex, int endIndex, + Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray, + char precedingChar, char breakOpportunityChar, final boolean endsWithHyphen, int level) { + GlyphMapping mapping; + if (font.performsSubstitution() || font.performsPositioning()) { + mapping = processWordMapping(text, startIndex, endIndex, font, + breakOpportunityChar, endsWithHyphen, level); + } else { + mapping = processWordNoMapping(text, startIndex, endIndex, font, + letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, + level); + } + return mapping; + } + + private static GlyphMapping processWordMapping(TextFragment text, int startIndex, + int endIndex, final Font font, final char breakOpportunityChar, + final boolean endsWithHyphen, int level) { + int e = endIndex; // end index of word in FOText character buffer + int nLS = 0; // # of letter spaces + String script = text.getScript(); + String language = text.getLanguage(); + + if (LOG.isDebugEnabled()) { + LOG.debug("PW: [" + startIndex + "," + endIndex + "]: {" + + " +M" + + ", level = " + level + + " }"); + } + + // 1. extract unmapped character sequence + CharSequence ics = text.subSequence(startIndex, e); + + // 2. if script is not specified (by FO property) or it is specified as 'auto', + // then compute dominant script + if ((script == null) || "auto".equals(script)) { + script = CharScript.scriptTagFromCode(CharScript.dominantScript(ics)); + } + if ((language == null) || "none".equals(language)) { + language = "dflt"; + } + + // 3. perform mapping of chars to glyphs ... to glyphs ... to chars + CharSequence mcs = font.performSubstitution(ics, script, language); + + // 4. compute glyph position adjustments on (substituted) characters + int[][] gpa; + if (font.performsPositioning()) { + // handle GPOS adjustments + gpa = font.performPositioning(mcs, script, language); + } else if (font.hasKerning()) { + // handle standard (non-GPOS) kerning adjustments + gpa = getKerningAdjustments(mcs, font); + } else { + gpa = null; + } + + // 5. reorder combining marks so that they precede (within the mapped char sequence) the + // base to which they are applied; N.B. position adjustments (gpa) are reordered in place + mcs = font.reorderCombiningMarks(mcs, gpa, script, language); + + // 6. compute word ipd based on final position adjustments + MinOptMax ipd = MinOptMax.ZERO; + for (int i = 0, n = mcs.length(); i < n; i++) { + int c = mcs.charAt(i); + // TODO !BMP + int w = font.getCharWidth(c); + if (w < 0) { + w = 0; + } + if (gpa != null) { + w += gpa[i][GlyphPositioningTable.Value.IDX_X_ADVANCE]; + } + ipd = ipd.plus(w); + } + + // [TBD] - handle letter spacing + + return new GlyphMapping(startIndex, e, 0, nLS, ipd, endsWithHyphen, false, + breakOpportunityChar != 0, font, level, gpa, + CharUtilities.isSameSequence(mcs, ics) ? null : mcs.toString()); + } + + /** + * Given a mapped character sequence MCS, obtain glyph position adjustments from the + * font's kerning data. + * + * @param mcs mapped character sequence + * @param font applicable font + * @return glyph position adjustments (or null if no kerning) + */ + private static int[][] getKerningAdjustments(CharSequence mcs, final Font font) { + int nc = mcs.length(); + // extract kerning array + int[] ka = new int[nc]; // kerning array + for (int i = 0, n = nc, cPrev = -1; i < n; i++) { + int c = mcs.charAt(i); + // TODO !BMP + if (cPrev >= 0) { + ka[i] = font.getKernValue(cPrev, c); + } + cPrev = c; + } + // was there a non-zero kerning? + boolean hasKerning = false; + for (int i = 0, n = nc; i < n; i++) { + if (ka[i] != 0) { + hasKerning = true; + break; + } + } + // if non-zero kerning, then create and return glyph position adjustment array + if (hasKerning) { + int[][] gpa = new int[nc][4]; + for (int i = 0, n = nc; i < n; i++) { + if (i > 0) { + gpa [i - 1][GlyphPositioningTable.Value.IDX_X_ADVANCE] = ka[i]; + } + } + return gpa; + } else { + return null; + } + } + + private static GlyphMapping processWordNoMapping(TextFragment text, int startIndex, int endIndex, + final Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray, + char precedingChar, final char breakOpportunityChar, final boolean endsWithHyphen, int level) { + boolean kerning = font.hasKerning(); + MinOptMax wordIPD = MinOptMax.ZERO; + + if (LOG.isDebugEnabled()) { + LOG.debug("PW: [" + startIndex + "," + endIndex + "]: {" + + " -M" + + ", level = " + level + + " }"); + } + + for (int i = startIndex; i < endIndex; i++) { + char currentChar = text.charAt(i); + + // character width + int charWidth = font.getCharWidth(currentChar); + wordIPD = wordIPD.plus(charWidth); + + // kerning + if (kerning) { + int kern = 0; + if (i > startIndex) { + char previousChar = text.charAt(i - 1); + kern = font.getKernValue(previousChar, currentChar); + } else if (precedingChar != 0) { + kern = font.getKernValue(precedingChar, currentChar); + } + if (kern != 0) { + addToLetterAdjust(letterSpaceAdjustArray, i, kern); + wordIPD = wordIPD.plus(kern); + } + } + } + if (kerning + && (breakOpportunityChar != 0) + && !isSpace(breakOpportunityChar) + && endIndex > 0 + && endsWithHyphen) { + int kern = font.getKernValue(text.charAt(endIndex - 1), breakOpportunityChar); + if (kern != 0) { + addToLetterAdjust(letterSpaceAdjustArray, endIndex, kern); + // TODO: add kern to wordIPD? + } + } + // shy+chars at start of word: wordLength == 0 && breakOpportunity + // shy only characters in word: wordLength == 0 && !breakOpportunity + int wordLength = endIndex - startIndex; + int letterSpaces = 0; + if (wordLength != 0) { + letterSpaces = wordLength - 1; + // if there is a break opportunity and the next one (break character) + // is not a space, it could be used as a line end; + // add one more letter space, in case other text follows + if ((breakOpportunityChar != 0) && !isSpace(breakOpportunityChar)) { + letterSpaces++; + } + } + assert letterSpaces >= 0; + wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces)); + + // create and return the AreaInfo object + return new GlyphMapping(startIndex, endIndex, 0, + letterSpaces, wordIPD, + endsWithHyphen, + false, breakOpportunityChar != 0, font, level, null); + } + + private static void addToLetterAdjust(MinOptMax[] letterSpaceAdjustArray, int index, int width) { + if (letterSpaceAdjustArray[index] == null) { + letterSpaceAdjustArray[index] = MinOptMax.getInstance(width); + } else { + letterSpaceAdjustArray[index] = letterSpaceAdjustArray[index].plus(width); + } + } + + /** + * Indicates whether a character is a space in terms of this layout manager. + * + * @param ch the character + * @return true if it's a space + */ + public static boolean isSpace(final char ch) { + return ch == CharUtilities.SPACE + || CharUtilities.isNonBreakableSpace(ch) + || CharUtilities.isFixedWidthSpace(ch); + } + + /** + * Obtain number of 'characters' contained in word. If word is mapped, then this + * number may be less than or greater than the original length (breakIndex - + * startIndex). We compute and memoize thius length upon first invocation of this + * method. + */ + public int getWordLength() { + if (wordCharLength == -1) { + if (mapping != null) { + wordCharLength = mapping.length(); + } else { + assert endIndex >= startIndex; + wordCharLength = endIndex - startIndex; + } + } + return wordCharLength; + } + + public void addToAreaIPD(MinOptMax idp) { + areaIPD = areaIPD.plus(idp); + } + + public String toString() { + return super.toString() + "{" + + "interval = [" + startIndex + "," + endIndex + "]" + + ", isSpace = " + isSpace + + ", level = " + level + + ", areaIPD = " + areaIPD + + ", letterSpaceCount = " + letterSpaceCount + + ", wordSpaceCount = " + wordSpaceCount + + ", isHyphenated = " + isHyphenated + + ", font = " + font + + "}"; + } + +} diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index 49b2e0457..1877a895e 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -18,6 +18,7 @@ /* $Id$ */ package org.apache.fop.fonts; +import java.awt.Rectangle; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -250,6 +251,26 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable, return realFont.getXHeight(size); } + public int getUnderlinePosition(int size) { + load(true); + return realFont.getUnderlinePosition(size); + } + + public int getUnderlineThickness(int size) { + load(true); + return realFont.getUnderlineThickness(size); + } + + public int getStrikeoutPosition(int size) { + load(true); + return realFont.getStrikeoutPosition(size); + } + + public int getStrikeoutThickness(int size) { + load(true); + return realFont.getStrikeoutThickness(size); + } + /** * {@inheritDoc} */ @@ -268,6 +289,11 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable, return realFont.getWidths(); } + public Rectangle getBoundingBox(int glyphIndex, int size) { + load(true); + return realFont.getBoundingBox(glyphIndex, size); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index 83f6491f3..1d1186dcb 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; +import java.awt.Rectangle; import java.nio.CharBuffer; import java.nio.IntBuffer; import java.util.BitSet; @@ -67,6 +68,9 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl private int firstUnmapped; private int lastUnmapped; + /** Contains the character bounding boxes for all characters in the font */ + protected Rectangle[] boundingBoxes; + /** * Default constructor */ @@ -170,6 +174,12 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl return arr; } + public Rectangle getBoundingBox(int glyphIndex, int size) { + int index = isEmbeddable() ? cidSet.getOriginalGlyphIndex(glyphIndex) : glyphIndex; + Rectangle bbox = boundingBoxes[index]; + return new Rectangle(bbox.x * size, bbox.y * size, bbox.width * size, bbox.height * size); + } + /** * Returns the glyph index for a Unicode character. The method returns 0 if there's no * such glyph in the character map. @@ -366,6 +376,14 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl } /** + * Sets the bounding boxes array. + * @param boundingBoxes array of bounding boxes. + */ + public void setBBoxArray(Rectangle[] boundingBoxes) { + this.boundingBoxes = boundingBoxes; + } + + /** * Returns a Map of used Glyphs. * @return Map Map of used Glyphs */ diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index cd11c7849..d412609d5 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; +import java.awt.Rectangle; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -47,6 +48,8 @@ public class SingleByteFont extends CustomFont { private int[] width = null; + private Rectangle[] boundingBoxes; + private Map<Character, UnencodedCharacter> unencodedCharacters; private List<SimpleSingleByteEncoding> additionalEncodings; private Map<Character, Character> alternativeCodes; @@ -111,6 +114,24 @@ public class SingleByteFont extends CustomFont { return arr; } + public Rectangle getBoundingBox(int glyphIndex, int size) { + Rectangle bbox = null; + if (glyphIndex < 256) { + int idx = glyphIndex - getFirstChar(); + if (idx >= 0 && idx < boundingBoxes.length) { + bbox = boundingBoxes[idx]; + } + } else if (this.additionalEncodings != null) { + int encodingIndex = (glyphIndex / 256) - 1; + SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex); + int codePoint = glyphIndex % 256; + NamedCharacter nc = encoding.getCharacterForIndex(codePoint); + UnencodedCharacter uc = this.unencodedCharacters.get(Character.valueOf(nc.getSingleUnicodeValue())); + bbox = uc.getBBox(); + } + return bbox == null ? null : new Rectangle(bbox.x * size, bbox.y * size, bbox.width * size, bbox.height * size); + } + /** * Lookup a character using its alternative names. If found, cache it so we * can speed up lookups. @@ -292,17 +313,24 @@ public class SingleByteFont extends CustomFont { this.width[index - getFirstChar()] = w; } + public void setBoundingBox(int index, Rectangle bbox) { + if (this.boundingBoxes == null) { + this.boundingBoxes = new Rectangle[getLastChar() - getFirstChar() + 1]; + } + this.boundingBoxes[index - getFirstChar()] = bbox; + } + /** * Adds an unencoded character (one that is not supported by the primary encoding). * @param ch the named character * @param width the width of the character */ - public void addUnencodedCharacter(NamedCharacter ch, int width) { + public void addUnencodedCharacter(NamedCharacter ch, int width, Rectangle bbox) { if (this.unencodedCharacters == null) { this.unencodedCharacters = new HashMap<Character, UnencodedCharacter>(); } if (ch.hasSingleUnicodeValue()) { - UnencodedCharacter uc = new UnencodedCharacter(ch, width); + UnencodedCharacter uc = new UnencodedCharacter(ch, width, bbox); this.unencodedCharacters.put(Character.valueOf(ch.getSingleUnicodeValue()), uc); } else { //Cannot deal with unicode sequences, so ignore this character @@ -381,10 +409,12 @@ public class SingleByteFont extends CustomFont { private final NamedCharacter character; private final int width; + private final Rectangle bbox; - public UnencodedCharacter(NamedCharacter character, int width) { + public UnencodedCharacter(NamedCharacter character, int width, Rectangle bbox) { this.character = character; this.width = width; + this.bbox = bbox; } public NamedCharacter getCharacter() { @@ -395,6 +425,10 @@ public class SingleByteFont extends CustomFont { return this.width; } + public Rectangle getBBox() { + return bbox; + } + /** {@inheritDoc} */ @Override public String toString() { diff --git a/src/java/org/apache/fop/fonts/TextFragment.java b/src/java/org/apache/fop/fonts/TextFragment.java new file mode 100644 index 000000000..ad72db8e0 --- /dev/null +++ b/src/java/org/apache/fop/fonts/TextFragment.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fonts; + +public interface TextFragment { + + String getScript(); + + String getLanguage(); + + char charAt(int index); + + CharSequence subSequence(int startIndex, int endIndex); +} diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 2e78ef7f0..62686bbd4 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts.truetype; +import java.awt.Rectangle; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -199,6 +200,8 @@ public class TTFFile { private int os2CapHeight = 0; private int underlinePosition = 0; private int underlineThickness = 0; + private int strikeoutPosition; + private int strikeoutThickness; private int xHeight = 0; private int os2xHeight = 0; //Effective ascender/descender @@ -976,10 +979,22 @@ public class TTFFile { for (int i = 0; i < wx.length; i++) { wx[i] = convertTTFUnit2PDFUnit(mtxTab[i].getWx()); } - return wx; } + public Rectangle[] getBoundingBoxes() { + Rectangle[] boundingBoxes = new Rectangle[mtxTab.length]; + for (int i = 0; i < boundingBoxes.length; i++) { + int[] boundingBox = mtxTab[i].getBoundingBox(); + boundingBoxes[i] = new Rectangle( + convertTTFUnit2PDFUnit(boundingBox[0]), + convertTTFUnit2PDFUnit(boundingBox[1]), + convertTTFUnit2PDFUnit(boundingBox[2] - boundingBox[0]), + convertTTFUnit2PDFUnit(boundingBox[3] - boundingBox[1])); + } + return boundingBoxes; + } + /** * Returns an array (xMin, yMin, xMax, yMax) for a glyph. * @@ -1020,6 +1035,22 @@ public class TTFFile { return ansiKerningTab; } + public int getUnderlinePosition() { + return convertTTFUnit2PDFUnit(underlinePosition); + } + + public int getUnderlineThickness() { + return convertTTFUnit2PDFUnit(underlineThickness); + } + + public int getStrikeoutPosition() { + return convertTTFUnit2PDFUnit(strikeoutPosition); + } + + public int getStrikeoutThickness() { + return convertTTFUnit2PDFUnit(strikeoutThickness); + } + /** * Indicates if the font may be embedded. * @return boolean True if it may be embedded @@ -1301,7 +1332,10 @@ public class TTFFile { } else { isEmbeddable = true; } - fontFile.skip(11 * 2); + fontFile.skip(8 * 2); + strikeoutThickness = fontFile.readTTFShort(); + strikeoutPosition = fontFile.readTTFShort(); + fontFile.skip(2); fontFile.skip(10); //panose array fontFile.skip(4 * 4); //unicode ranges fontFile.skip(4); diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index b7adbd4c9..98f81ab3e 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts.truetype; +import java.awt.Rectangle; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -144,6 +145,10 @@ public class TTFFontLoader extends FontLoader { 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())); @@ -152,15 +157,15 @@ public class TTFFontLoader extends FontLoader { returnFont.setEmbeddingMode(this.embeddingMode); if (isCid) { multiFont.setCIDType(CIDFontType.CIDTYPE2); - int[] wx = ttf.getWidths(); - multiFont.setWidthArray(wx); + multiFont.setWidthArray(ttf.getWidths()); + multiFont.setBBoxArray(ttf.getBoundingBoxes()); } else { singleFont.setFontType(FontType.TRUETYPE); singleFont.setEncoding(ttf.getCharSetName()); returnFont.setFirstChar(ttf.getFirstChar()); returnFont.setLastChar(ttf.getLastChar()); singleFont.setTrueTypePostScriptVersion(ttf.getPostScriptVersion()); - copyWidthsSingleByte(ttf); + copyGlyphMetricsSingleByte(ttf); } returnFont.setCMap(getCMap(ttf)); @@ -186,12 +191,15 @@ public class TTFFontLoader extends FontLoader { return ttf.getCMaps().toArray(array); } - private void copyWidthsSingleByte(TTFFile ttf) { + private void copyGlyphMetricsSingleByte(TTFFile ttf) { int[] wx = ttf.getWidths(); + Rectangle[] bboxes = ttf.getBoundingBoxes(); for (int i = singleFont.getFirstChar(); i <= singleFont.getLastChar(); i++) { singleFont.setWidth(i, ttf.getCharWidth(i)); + int[] bbox = ttf.getBBox(i); + singleFont.setBoundingBox(i, + new Rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1])); } - for (CMapSegment segment : ttf.getCMaps()) { if (segment.getUnicodeStart() < 0xFFFE) { for (char u = (char)segment.getUnicodeStart(); u <= segment.getUnicodeEnd(); u++) { @@ -205,7 +213,7 @@ public class TTFFontLoader extends FontLoader { if (glyphName.length() > 0) { String unicode = Character.toString(u); NamedCharacter nc = new NamedCharacter(glyphName, unicode); - singleFont.addUnencodedCharacter(nc, wx[glyphIndex]); + singleFont.addUnencodedCharacter(nc, wx[glyphIndex], bboxes[glyphIndex]); } } } diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java index 4906f2c31..8d9f4238b 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -19,7 +19,7 @@ package org.apache.fop.fonts.type1; -import java.awt.geom.RectangularShape; +import java.awt.Rectangle; import org.apache.fop.fonts.NamedCharacter; @@ -33,7 +33,7 @@ public class AFMCharMetrics { private NamedCharacter character; private double widthX; private double widthY; - private RectangularShape bBox; + private Rectangle bBox; /** * Returns the character code. @@ -137,7 +137,7 @@ public class AFMCharMetrics { * Returns the character's bounding box. * @return the bounding box (or null if it isn't available) */ - public RectangularShape getBBox() { + public Rectangle getBBox() { return bBox; } @@ -145,7 +145,7 @@ public class AFMCharMetrics { * Sets the character's bounding box. * @param box the bounding box */ - public void setBBox(RectangularShape box) { + public void setBBox(Rectangle box) { bBox = box; } diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 853e23eb5..7922ff6fd 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -203,12 +203,16 @@ public class Type1FontLoader extends FontLoader { for (AFMCharMetrics metrics : charMetrics) { String charName = metrics.getCharName(); if (charName != null && !glyphNames.contains(charName)) { - singleFont.addUnencodedCharacter(metrics.getCharacter(), - (int)Math.round(metrics.getWidthX())); + addUnencodedCharacter(singleFont, metrics); } } } + private static void addUnencodedCharacter(SingleByteFont font, AFMCharMetrics metrics) { + font.addUnencodedCharacter(metrics.getCharacter(), + (int) Math.round(metrics.getWidthX()), metrics.getBBox()); + } + /** * Adds characters not encoded in the font's primary encoding. This method is used when * the primary encoding is built based on the character codes in the AFM rather than @@ -220,8 +224,7 @@ public class Type1FontLoader extends FontLoader { for (int i = 0, c = afm.getCharCount(); i < c; i++) { AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i); if (!metrics.hasCharCode() && metrics.getCharacter() != null) { - singleFont.addUnencodedCharacter(metrics.getCharacter(), - (int)Math.round(metrics.getWidthX())); + addUnencodedCharacter(singleFont, metrics); } } } @@ -267,7 +270,10 @@ public class Type1FontLoader extends FontLoader { } else { returnFont.setStemV(80); // Arbitrary value } - returnFont.setItalicAngle((int) afm.getWritingDirectionMetrics(0).getItalicAngle()); + AFMWritingDirectionMetrics metrics = afm.getWritingDirectionMetrics(0); + returnFont.setItalicAngle((int) metrics.getItalicAngle()); + returnFont.setUnderlinePosition(metrics.getUnderlinePosition().intValue()); + returnFont.setUnderlineThickness(metrics.getUnderlineThickness().intValue()); } else { returnFont.setFontBBox(pfm.getFontBBox()); returnFont.setStemV(pfm.getStemV()); @@ -369,6 +375,7 @@ public class Type1FontLoader extends FontLoader { for (AFMCharMetrics chm : afm.getCharMetrics()) { if (chm.hasCharCode()) { singleFont.setWidth(chm.getCharCode(), (int) Math.round(chm.getWidthX())); + singleFont.setBoundingBox(chm.getCharCode(), chm.getBBox()); } } if (useKerning) { diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 79592efd1..ec187b8d0 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -33,6 +33,7 @@ import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; import org.apache.xmlgraphics.image.GraphicsConstants; import org.apache.xmlgraphics.image.loader.Image; @@ -123,10 +124,8 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { * @return the newly created user agent */ protected SimpleSVGUserAgent createBatikUserAgent(float pxToMillimeter) { - return new SimpleSVGUserAgent( - pxToMillimeter, - new AffineTransform()) { - + return new SimpleSVGUserAgent(pxToMillimeter, new AffineTransform(), + DefaultFontFamilyResolver.SINGLETON) { /** {@inheritDoc} */ public void displayMessage(String message) { //TODO Refine and pipe through to caller diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index 3aa340a4a..58daadc52 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -38,6 +38,7 @@ import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGOMDocument; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; import org.apache.xmlgraphics.image.loader.ImageContext; import org.apache.xmlgraphics.image.loader.ImageInfo; @@ -162,7 +163,7 @@ public class PreloaderSVG extends AbstractImagePreloader { Element e = doc.getRootElement(); float pxUnitToMillimeter = UnitConv.IN2MM / context.getSourceResolution(); UserAgent userAg = new SimpleSVGUserAgent(pxUnitToMillimeter, - new AffineTransform()) { + new AffineTransform(), DefaultFontFamilyResolver.SINGLETON) { /** {@inheritDoc} */ public void displayMessage(String message) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 53f51cd32..625b43ee5 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -30,12 +30,11 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; -import org.apache.fop.complexscripts.util.CharScript; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontSelector; +import org.apache.fop.fonts.GlyphMapping; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -65,91 +64,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final int SOFT_HYPHEN_PENALTY = 1; /** - * Store information about each potential text area. - * Index of character which ends the area, IPD of area, including - * any word-space and letter-space. - * Number of word-spaces? - */ - private class AreaInfo { - - private final int startIndex; - private final int breakIndex; - private int wordCharLength; - private final int wordSpaceCount; - private int letterSpaceCount; - private MinOptMax areaIPD; - private final boolean isHyphenated; - private final boolean isSpace; - private boolean breakOppAfter; - private final Font font; - private final int level; - private final int[][] gposAdjustments; - - AreaInfo( - int startIndex, int breakIndex, int wordSpaceCount, int letterSpaceCount, - MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, - Font font, int level, int[][] gposAdjustments) { - assert startIndex <= breakIndex; - this.startIndex = startIndex; - this.breakIndex = breakIndex; - this.wordCharLength = -1; - this.wordSpaceCount = wordSpaceCount; - this.letterSpaceCount = letterSpaceCount; - this.areaIPD = areaIPD; - this.isHyphenated = isHyphenated; - this.isSpace = isSpace; - this.breakOppAfter = breakOppAfter; - this.font = font; - this.level = level; - this.gposAdjustments = gposAdjustments; - } - - /** - * Obtain number of 'characters' contained in word. If word - * is mapped, then this number may be less than or greater than the - * original length (breakIndex - startIndex). We compute and - * memoize thius length upon first invocation of this method. - */ - private int getWordLength() { - if (wordCharLength == -1) { - if (foText.hasMapping(startIndex, breakIndex)) { - wordCharLength = foText.getMapping(startIndex, breakIndex).length(); - } else { - assert breakIndex >= startIndex; - wordCharLength = breakIndex - startIndex; - } - } - return wordCharLength; - } - - private void addToAreaIPD(MinOptMax idp) { - areaIPD = areaIPD.plus(idp); - } - - public String toString() { - return super.toString() + "{" - + "interval = [" + startIndex + "," + breakIndex + "]" - + ", isSpace = " + isSpace - + ", level = " + level - + ", areaIPD = " + areaIPD - + ", letterSpaceCount = " + letterSpaceCount - + ", wordSpaceCount = " + wordSpaceCount - + ", isHyphenated = " + isHyphenated - + ", font = " + font - + "}"; - } - } - - /** * this class stores information about changes in vecAreaInfo which are not yet applied */ private final class PendingChange { - private final AreaInfo areaInfo; + private final GlyphMapping mapping; private final int index; - private PendingChange(final AreaInfo areaInfo, final int index) { - this.areaInfo = areaInfo; + private PendingChange(final GlyphMapping mapping, final int index) { + this.mapping = mapping; this.index = index; } } @@ -160,7 +83,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final Log LOG = LogFactory.getLog(TextLayoutManager.class); // Hold all possible breaks for the text in this LM's FO. - private final List areaInfos; + private final List<GlyphMapping> mappings; /** Non-space characters on which we can end a line. */ private static final String BREAK_CHARS = "-/"; @@ -216,7 +139,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public TextLayoutManager(FOText node) { foText = node; letterSpaceAdjustArray = new MinOptMax[node.length() + 1]; - areaInfos = new ArrayList(); + mappings = new ArrayList<GlyphMapping>(); } private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { @@ -274,61 +197,61 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public void addAreas(final PositionIterator posIter, final LayoutContext context) { // Add word areas - AreaInfo areaInfo; + GlyphMapping mapping; int wordSpaceCount = 0; int letterSpaceCount = 0; - int firstAreaInfoIndex = -1; - int lastAreaInfoIndex = 0; + int firstMappingIndex = -1; + int lastMappingIndex = 0; MinOptMax realWidth = MinOptMax.ZERO; /* On first area created, add any leading space. * Calculate word-space stretch value. */ - AreaInfo lastAreaInfo = null; + GlyphMapping lastMapping = null; while (posIter.hasNext()) { final LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { continue; //Ignore elements without Positions } if (tbpNext.getLeafPos() != -1) { - areaInfo = (AreaInfo) areaInfos.get(tbpNext.getLeafPos()); - if (lastAreaInfo == null - || (areaInfo.font != lastAreaInfo.font) - || (areaInfo.level != lastAreaInfo.level)) { - if (lastAreaInfo != null) { - addAreaInfoAreas(lastAreaInfo, wordSpaceCount, - letterSpaceCount, firstAreaInfoIndex, - lastAreaInfoIndex, realWidth, context); + mapping = mappings.get(tbpNext.getLeafPos()); + if (lastMapping == null + || (mapping.font != lastMapping.font) + || (mapping.level != lastMapping.level)) { + if (lastMapping != null) { + addMappingAreas(lastMapping, wordSpaceCount, + letterSpaceCount, firstMappingIndex, + lastMappingIndex, realWidth, context); } - firstAreaInfoIndex = tbpNext.getLeafPos(); + firstMappingIndex = tbpNext.getLeafPos(); wordSpaceCount = 0; letterSpaceCount = 0; realWidth = MinOptMax.ZERO; } - wordSpaceCount += areaInfo.wordSpaceCount; - letterSpaceCount += areaInfo.letterSpaceCount; - realWidth = realWidth.plus(areaInfo.areaIPD); - lastAreaInfoIndex = tbpNext.getLeafPos(); - lastAreaInfo = areaInfo; + wordSpaceCount += mapping.wordSpaceCount; + letterSpaceCount += mapping.letterSpaceCount; + realWidth = realWidth.plus(mapping.areaIPD); + lastMappingIndex = tbpNext.getLeafPos(); + lastMapping = mapping; } } - if (lastAreaInfo != null) { - addAreaInfoAreas(lastAreaInfo, wordSpaceCount, letterSpaceCount, firstAreaInfoIndex, - lastAreaInfoIndex, realWidth, context); + if (lastMapping != null) { + addMappingAreas(lastMapping, wordSpaceCount, letterSpaceCount, firstMappingIndex, + lastMappingIndex, realWidth, context); } } - private void addAreaInfoAreas(AreaInfo areaInfo, int wordSpaceCount, int letterSpaceCount, - int firstAreaInfoIndex, int lastAreaInfoIndex, + private void addMappingAreas(GlyphMapping mapping, int wordSpaceCount, int letterSpaceCount, + int firstMappingIndex, int lastMappingIndex, MinOptMax realWidth, LayoutContext context) { // TODO: These two statements (if, for) were like this before my recent - // changes. However, it seems as if they should use the AreaInfo from - // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last areaInfo. + // changes. However, it seems as if they should use the GlyphMapping from + // firstMappingIndex.. lastMappingIndex rather than just the last mapping. // This needs to be checked. - int textLength = areaInfo.getWordLength(); - if (areaInfo.letterSpaceCount == textLength && !areaInfo.isHyphenated + int textLength = mapping.getWordLength(); + if (mapping.letterSpaceCount == textLength && !mapping.isHyphenated && context.isLastArea()) { // the line ends at a character like "/" or "-"; // remove the letter space after the last character @@ -336,7 +259,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { letterSpaceCount--; } - for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + for (int i = mapping.startIndex; i < mapping.endIndex; i++) { MinOptMax letterSpaceAdjustment = letterSpaceAdjustArray[i + 1]; if (letterSpaceAdjustment != null && letterSpaceAdjustment.isElastic()) { letterSpaceCount++; @@ -344,7 +267,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } // add hyphenation character if the last word is hyphenated - if (context.isLastArea() && areaInfo.isHyphenated) { + if (context.isLastArea() && mapping.isHyphenated) { realWidth = realWidth.plus(hyphIPD); } @@ -385,8 +308,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { totalAdjust = difference; } - TextArea textArea = new TextAreaBuilder(realWidth, totalAdjust, context, firstAreaInfoIndex, - lastAreaInfoIndex, context.isLastArea(), areaInfo.font).build(); + TextArea textArea = new TextAreaBuilder(realWidth, totalAdjust, context, firstMappingIndex, + lastMappingIndex, context.isLastArea(), mapping.font).build(); // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -417,15 +340,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final MinOptMax width; // content ipd private final int adjust; // content ipd adjustment private final LayoutContext context; // layout context - private final int firstIndex; // index of first AreaInfo - private final int lastIndex; // index of last AreaInfo + private final int firstIndex; // index of first GlyphMapping + private final int lastIndex; // index of last GlyphMapping private final boolean isLastArea; // true if last inline area in line area private final Font font; // applicable font // other, non-constructor state private TextArea textArea; // text area being constructed private int blockProgressionDimension; // calculated bpd - private AreaInfo areaInfo; // current area info when iterating over words + private GlyphMapping mapping; // current mapping when iterating over words private StringBuffer wordChars; // current word's character buffer private int[] letterSpaceAdjust; // current word's letter space adjustments private int letterSpaceAdjustIndex; // last written letter space adjustment index @@ -442,8 +365,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @param width the MinOptMax width of the content * @param adjust the total ipd adjustment with respect to the optimal width * @param context the layout context - * @param firstIndex the index of the first AreaInfo used for the TextArea - * @param lastIndex the index of the last AreaInfo used for the TextArea + * @param firstIndex the index of the first GlyphMapping used for the TextArea + * @param lastIndex the index of the last GlyphMapping used for the TextArea * @param isLastArea is this TextArea the last in a line? * @param font Font to be used in this particular TextArea */ @@ -516,30 +439,30 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Sets the text of the TextArea, split into words and spaces. */ private void setText() { - int areaInfoIndex = -1; + int mappingIndex = -1; int wordCharLength = 0; for (int wordIndex = firstIndex; wordIndex <= lastIndex; wordIndex++) { - areaInfo = getAreaInfo(wordIndex); - if (areaInfo.isSpace) { + mapping = getGlyphMapping(wordIndex); + if (mapping.isSpace) { addSpaces(); } else { - // areaInfo stores information about a word fragment - if (areaInfoIndex == -1) { + // mapping stores information about a word fragment + if (mappingIndex == -1) { // here starts a new word - areaInfoIndex = wordIndex; + mappingIndex = wordIndex; wordCharLength = 0; } - wordCharLength += areaInfo.getWordLength(); + wordCharLength += mapping.getWordLength(); if (isWordEnd(wordIndex)) { - addWord(areaInfoIndex, wordIndex, wordCharLength); - areaInfoIndex = -1; + addWord(mappingIndex, wordIndex, wordCharLength); + mappingIndex = -1; } } } } - private boolean isWordEnd(int areaInfoIndex) { - return areaInfoIndex == lastIndex || getAreaInfo(areaInfoIndex + 1).isSpace; + private boolean isWordEnd(int mappingIndex) { + return mappingIndex == lastIndex || getGlyphMapping(mappingIndex + 1).isSpace; } /** @@ -564,10 +487,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // iterate over word's fragments, adding word chars (with bidi // levels), letter space adjustments, and glyph position adjustments for (int i = startIndex; i <= endIndex; i++) { - AreaInfo wordAreaInfo = getAreaInfo(i); - addWordChars(wordAreaInfo); - addLetterAdjust(wordAreaInfo); - if (addGlyphPositionAdjustments(wordAreaInfo)) { + GlyphMapping wordMapping = getGlyphMapping(i); + addWordChars(wordMapping); + addLetterAdjust(wordMapping); + if (addGlyphPositionAdjustments(wordMapping)) { gposAdjusted = true; } } @@ -617,7 +540,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } private boolean isHyphenated(int endIndex) { - return isLastArea && endIndex == lastIndex && areaInfo.isHyphenated; + return isLastArea && endIndex == lastIndex && mapping.isHyphenated; } private void addHyphenationChar() { @@ -632,21 +555,54 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * (1) concatenate (possibly mapped) word characters to word character buffer; * (2) concatenante (possibly mapped) word bidi levels to levels buffer; * (3) update word's IPD with optimal IPD of fragment. - * @param wordAreaInfo fragment info + * @param wordMapping fragment info */ - private void addWordChars(AreaInfo wordAreaInfo) { - int s = wordAreaInfo.startIndex; - int e = wordAreaInfo.breakIndex; - if (foText.hasMapping(s, e)) { - wordChars.append(foText.getMapping(s, e)); - addWordLevels(foText.getMappingBidiLevels(s, e)); + private void addWordChars(GlyphMapping wordMapping) { + int s = wordMapping.startIndex; + int e = wordMapping.endIndex; + if (wordMapping.mapping != null) { + wordChars.append(wordMapping.mapping); + addWordLevels(getMappingBidiLevels(wordMapping)); } else { for (int i = s; i < e; i++) { wordChars.append(foText.charAt(i)); } addWordLevels(foText.getBidiLevels(s, e)); } - wordIPD += wordAreaInfo.areaIPD.getOpt(); + wordIPD += wordMapping.areaIPD.getOpt(); + } + + /** + * Obtain bidirectional levels of mapping of characters over specific interval. + * @param start index in character buffer + * @param end index in character buffer + * @return a (possibly empty) array of bidi levels or null + * in case no bidi levels have been assigned + */ + private int[] getMappingBidiLevels(GlyphMapping mapping) { + if (mapping.mapping != null) { + int nc = mapping.endIndex - mapping.startIndex; + int nm = mapping.mapping.length(); + int[] la = foText.getBidiLevels(mapping.startIndex, mapping.endIndex); + if (la == null) { + return null; + } else if (nm == nc) { // mapping is same length as mapped range + return la; + } else if (nm > nc) { // mapping is longer than mapped range + int[] ma = new int[nm]; + System.arraycopy(la, 0, ma, 0, la.length); + for (int i = la.length, n = ma.length, l = (i > 0) ? la[i - 1] : 0; i < n; i++) { + ma[i] = l; + } + return ma; + } else { // mapping is shorter than mapped range + int[] ma = new int[nm]; + System.arraycopy(la, 0, ma, 0, ma.length); + return ma; + } + } else { + return foText.getBidiLevels(mapping.startIndex, mapping.endIndex); + } } /** @@ -672,16 +628,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** * Given a word area info associated with a word fragment, * concatenate letter space adjustments for each (possibly mapped) character. - * @param wordAreaInfo fragment info + * @param wordMapping fragment info */ - private void addLetterAdjust(AreaInfo wordAreaInfo) { - int letterSpaceCount = wordAreaInfo.letterSpaceCount; - int wordLength = wordAreaInfo.getWordLength(); + private void addLetterAdjust(GlyphMapping wordMapping) { + int letterSpaceCount = wordMapping.letterSpaceCount; + int wordLength = wordMapping.getWordLength(); int taAdjust = textArea.getTextLetterSpaceAdjust(); for (int i = 0, n = wordLength; i < n; i++) { int j = letterSpaceAdjustIndex + i; if (j > 0) { - int k = wordAreaInfo.startIndex + i; + int k = wordMapping.startIndex + i; MinOptMax adj = (k < letterSpaceAdjustArray.length) ? letterSpaceAdjustArray [ k ] : null; letterSpaceAdjust [ j ] = (adj == null) ? 0 : adj.getOpt(); @@ -697,14 +653,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** * Given a word area info associated with a word fragment, * concatenate glyph position adjustments for each (possibly mapped) character. - * @param wordAreaInfo fragment info + * @param wordMapping fragment info * @return true if an adjustment was non-zero */ - private boolean addGlyphPositionAdjustments(AreaInfo wordAreaInfo) { + private boolean addGlyphPositionAdjustments(GlyphMapping wordMapping) { boolean adjusted = false; - int[][] gpa = wordAreaInfo.gposAdjustments; + int[][] gpa = wordMapping.gposAdjustments; int numAdjusts = (gpa != null) ? gpa.length : 0; - int wordLength = wordAreaInfo.getWordLength(); + int wordLength = wordMapping.getWordLength(); if (numAdjusts > 0) { int need = gposAdjustmentsIndex + numAdjusts; if (need <= gposAdjustments.length) { @@ -733,7 +689,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** - * The <code>AreaInfo</code> stores information about spaces. + * The <code>GlyphMapping</code> stores information about spaces. * <p/> * Add the spaces - except zero-width spaces - to the TextArea. */ @@ -743,16 +699,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // divide the area info's allocated IPD evenly among the // non-zero-width space characters int numZeroWidthSpaces = 0; - for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + for (int i = mapping.startIndex; i < mapping.endIndex; i++) { char spaceChar = foText.charAt(i); if (CharUtilities.isZeroWidthSpace(spaceChar)) { numZeroWidthSpaces++; } } - int numSpaces = areaInfo.breakIndex - areaInfo.startIndex - numZeroWidthSpaces; - int spaceIPD = areaInfo.areaIPD.getOpt() / ((numSpaces > 0) ? numSpaces : 1); + int numSpaces = mapping.endIndex - mapping.startIndex - numZeroWidthSpaces; + int spaceIPD = mapping.areaIPD.getOpt() / ((numSpaces > 0) ? numSpaces : 1); // add space area children, one for each non-zero-width space character - for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + for (int i = mapping.startIndex; i < mapping.endIndex; i++) { char spaceChar = foText.charAt(i); int level = foText.bidiLevelAt(i); if (!CharUtilities.isZeroWidthSpace(spaceChar)) { @@ -766,39 +722,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } - private void addAreaInfo(AreaInfo ai) { - addAreaInfo(areaInfos.size(), ai); + private void addGlyphMapping(GlyphMapping mapping) { + addGlyphMapping(mappings.size(), mapping); } - private void addAreaInfo(int index, AreaInfo ai) { - areaInfos.add(index, ai); + private void addGlyphMapping(int index, GlyphMapping mapping) { + mappings.add(index, mapping); } - private void removeAreaInfo(int index) { - areaInfos.remove(index); + private void removeGlyphMapping(int index) { + mappings.remove(index); } - private AreaInfo getAreaInfo(int index) { - return (AreaInfo) areaInfos.get(index); - } - - private void addToLetterAdjust(int index, int width) { - if (letterSpaceAdjustArray[index] == null) { - letterSpaceAdjustArray[index] = MinOptMax.getInstance(width); - } else { - letterSpaceAdjustArray[index] = letterSpaceAdjustArray[index].plus(width); - } - } - - /** - * Indicates whether a character is a space in terms of this layout manager. - * @param ch the character - * @return true if it's a space - */ - private static boolean isSpace(final char ch) { - return ch == CharUtilities.SPACE - || CharUtilities.isNonBreakableSpace(ch) - || CharUtilities.isFixedWidthSpace(ch); + private GlyphMapping getGlyphMapping(int index) { + return mappings.get(index); } /** {@inheritDoc} */ @@ -810,8 +747,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final List returnList = new LinkedList(); KnuthSequence sequence = new InlineKnuthSequence(); - AreaInfo areaInfo = null; - AreaInfo prevAreaInfo = null; + GlyphMapping mapping = null; + GlyphMapping prevMapping = null; returnList.add(sequence); if (LOG.isDebugEnabled()) { @@ -857,24 +794,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } if (inWord) { if (breakOpportunity - || TextLayoutManager.isSpace(ch) + || GlyphMapping.isSpace(ch) || CharUtilities.isExplicitBreak(ch) || ((prevLevel != -1) && (level != prevLevel))) { // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN - prevAreaInfo = processWord(alignment, sequence, prevAreaInfo, ch, + prevMapping = processWord(alignment, sequence, prevMapping, ch, breakOpportunity, true, prevLevel); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { - prevAreaInfo = processWhitespace(alignment, sequence, + prevMapping = processWhitespace(alignment, sequence, breakOpportunity, prevLevel); } } else { - if (areaInfo != null) { - prevAreaInfo = areaInfo; - processLeftoverAreaInfo(alignment, sequence, areaInfo, + if (mapping != null) { + prevMapping = mapping; + processLeftoverGlyphMapping(alignment, sequence, mapping, ch == CharUtilities.SPACE || breakOpportunity); - areaInfo = null; + mapping = null; } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { sequence = processLinebreak(returnList, sequence); @@ -888,15 +825,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.foText, this); font.mapChar(ch); // preserved space or non-breaking space: - // create the AreaInfo object - areaInfo = new AreaInfo(nextStart, nextStart + 1, 1, 0, wordSpaceIPD, false, true, + // create the GlyphMapping object + mapping = new GlyphMapping(nextStart, nextStart + 1, 1, 0, wordSpaceIPD, false, true, breakOpportunity, spaceFont, level, null); thisStart = nextStart + 1; } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { - // create the AreaInfo object + // create the GlyphMapping object Font font = FontSelector.selectFontForCharacterInText(ch, foText, this); MinOptMax ipd = MinOptMax.getInstance(font.getCharWidth(ch)); - areaInfo = new AreaInfo(nextStart, nextStart + 1, 0, 0, ipd, false, true, + mapping = new GlyphMapping(nextStart, nextStart + 1, 0, 0, ipd, false, true, breakOpportunity, font, level, null); thisStart = nextStart + 1; } else if (CharUtilities.isExplicitBreak(ch)) { @@ -904,7 +841,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { thisStart = nextStart + 1; } - inWord = !TextLayoutManager.isSpace(ch) && !CharUtilities.isExplicitBreak(ch); + inWord = !GlyphMapping.isSpace(ch) && !CharUtilities.isExplicitBreak(ch); inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; prevLevel = level; @@ -913,11 +850,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // Process any last elements if (inWord) { - processWord(alignment, sequence, prevAreaInfo, ch, false, false, prevLevel); + processWord(alignment, sequence, prevMapping, ch, false, false, prevLevel); } else if (inWhitespace) { processWhitespace(alignment, sequence, !keepTogether, prevLevel); - } else if (areaInfo != null) { - processLeftoverAreaInfo(alignment, sequence, areaInfo, + } else if (mapping != null) { + processLeftoverGlyphMapping(alignment, sequence, mapping, ch == CharUtilities.ZERO_WIDTH_SPACE); } else if (CharUtilities.isExplicitBreak(ch)) { this.processLinebreak(returnList, sequence); @@ -948,15 +885,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return sequence; } - private void processLeftoverAreaInfo(int alignment, - KnuthSequence sequence, AreaInfo areaInfo, - boolean breakOpportunityAfter) { - addAreaInfo(areaInfo); - areaInfo.breakOppAfter = breakOpportunityAfter; - addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); + private void processLeftoverGlyphMapping(int alignment, KnuthSequence sequence, + GlyphMapping mapping, boolean breakOpportunityAfter) { + addGlyphMapping(mapping); + mapping.breakOppAfter = breakOpportunityAfter; + addElementsForASpace(sequence, alignment, mapping, mappings.size() - 1); } - private AreaInfo processWhitespace(final int alignment, + private GlyphMapping processWhitespace(final int alignment, final KnuthSequence sequence, final boolean breakOpportunity, int level) { if (LOG.isDebugEnabled()) { @@ -964,209 +900,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } // End of whitespace - // create the AreaInfo object + // create the GlyphMapping object assert nextStart >= thisStart; - AreaInfo areaInfo = new AreaInfo( - thisStart, nextStart, nextStart - thisStart, 0, + GlyphMapping mapping = new GlyphMapping( + thisStart, nextStart, nextStart - thisStart, 0, wordSpaceIPD.mult(nextStart - thisStart), false, true, breakOpportunity, spaceFont, level, null); - addAreaInfo(areaInfo); + addGlyphMapping(mapping); // create the elements - addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); + addElementsForASpace(sequence, alignment, mapping, mappings.size() - 1); thisStart = nextStart; - return areaInfo; - } - - private AreaInfo processWordMapping( - int lastIndex, final Font font, AreaInfo prevAreaInfo, final char breakOpportunityChar, - final boolean endsWithHyphen, int level) { - int s = this.thisStart; // start index of word in FOText character buffer - int e = lastIndex; // end index of word in FOText character buffer - int nLS = 0; // # of letter spaces - String script = foText.getScript(); - String language = foText.getLanguage(); - - if (LOG.isDebugEnabled()) { - LOG.debug("PW: [" + thisStart + "," + lastIndex + "]: {" - + " +M" - + ", level = " + level - + " }"); - } - - // 1. extract unmapped character sequence - CharSequence ics = foText.subSequence(s, e); - - // 2. if script is not specified (by FO property) or it is specified as 'auto', - // then compute dominant script - if ((script == null) || "auto".equals(script)) { - script = CharScript.scriptTagFromCode(CharScript.dominantScript(ics)); - } - if ((language == null) || "none".equals(language)) { - language = "dflt"; - } - - // 3. perform mapping of chars to glyphs ... to glyphs ... to chars - CharSequence mcs = font.performSubstitution(ics, script, language); - - // 4. compute glyph position adjustments on (substituted) characters - int[][] gpa; - if (font.performsPositioning()) { - // handle GPOS adjustments - gpa = font.performPositioning(mcs, script, language); - } else if (font.hasKerning()) { - // handle standard (non-GPOS) kerning adjustments - gpa = getKerningAdjustments(mcs, font); - } else { - gpa = null; - } - - // 5. reorder combining marks so that they precede (within the mapped char sequence) the - // base to which they are applied; N.B. position adjustments (gpa) are reordered in place - mcs = font.reorderCombiningMarks(mcs, gpa, script, language); - - // 6. if mapped sequence differs from input sequence, then memoize mapped sequence - if (!CharUtilities.isSameSequence(mcs, ics)) { - foText.addMapping(s, e, mcs); - } - - // 7. compute word ipd based on final position adjustments - MinOptMax ipd = MinOptMax.ZERO; - for (int i = 0, n = mcs.length(); i < n; i++) { - int c = mcs.charAt(i); - // TODO !BMP - int w = font.getCharWidth(c); - if (w < 0) { - w = 0; - } - if (gpa != null) { - w += gpa [ i ] [ GlyphPositioningTable.Value.IDX_X_ADVANCE ]; - } - ipd = ipd.plus(w); - } - - // [TBD] - handle letter spacing - - return new AreaInfo( - s, e, 0, nLS, ipd, endsWithHyphen, false, - breakOpportunityChar != 0, font, level, gpa); - } - - /** - * Given a mapped character sequence MCS, obtain glyph position adjustments - * from the font's kerning data. - * @param mcs mapped character sequence - * @param font applicable font - * @return glyph position adjustments (or null if no kerning) - */ - private int[][] getKerningAdjustments(CharSequence mcs, final Font font) { - int nc = mcs.length(); - // extract kerning array - int[] ka = new int [ nc ]; // kerning array - for (int i = 0, n = nc, cPrev = -1; i < n; i++) { - int c = mcs.charAt(i); - // TODO !BMP - if (cPrev >= 0) { - ka[i] = font.getKernValue(cPrev, c); - } - cPrev = c; - } - // was there a non-zero kerning? - boolean hasKerning = false; - for (int i = 0, n = nc; i < n; i++) { - if (ka[i] != 0) { - hasKerning = true; - break; - } - } - // if non-zero kerning, then create and return glyph position adjustment array - if (hasKerning) { - int[][] gpa = new int [ nc ] [ 4 ]; - for (int i = 0, n = nc; i < n; i++) { - if (i > 0) { - gpa [ i - 1 ] [ GlyphPositioningTable.Value.IDX_X_ADVANCE ] = ka [ i ]; - } - } - return gpa; - } else { - return null; - } + return mapping; } - private AreaInfo processWordNoMapping(int lastIndex, final Font font, AreaInfo prevAreaInfo, - final char breakOpportunityChar, final boolean endsWithHyphen, int level) { - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = MinOptMax.ZERO; - - if (LOG.isDebugEnabled()) { - LOG.debug("PW: [" + thisStart + "," + lastIndex + "]: {" - + " -M" - + ", level = " + level - + " }"); - } - - for (int i = thisStart; i < lastIndex; i++) { - char currentChar = foText.charAt(i); - - //character width - int charWidth = font.getCharWidth(currentChar); - wordIPD = wordIPD.plus(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > thisStart) { - char previousChar = foText.charAt(i - 1); - kern = font.getKernValue(previousChar, currentChar); - } else if (prevAreaInfo != null - && !prevAreaInfo.isSpace && prevAreaInfo.breakIndex > 0) { - char previousChar = foText.charAt(prevAreaInfo.breakIndex - 1); - kern = font.getKernValue(previousChar, currentChar); - } - if (kern != 0) { - addToLetterAdjust(i, kern); - wordIPD = wordIPD.plus(kern); - } - } - } - if (kerning - && (breakOpportunityChar != 0) - && !TextLayoutManager.isSpace(breakOpportunityChar) - && lastIndex > 0 - && endsWithHyphen) { - int kern = font.getKernValue(foText.charAt(lastIndex - 1), breakOpportunityChar); - if (kern != 0) { - addToLetterAdjust(lastIndex, kern); - //TODO: add kern to wordIPD? - } - } - // shy+chars at start of word: wordLength == 0 && breakOpportunity - // shy only characters in word: wordLength == 0 && !breakOpportunity - int wordLength = lastIndex - thisStart; - int letterSpaces = 0; - if (wordLength != 0) { - letterSpaces = wordLength - 1; - // if there is a break opportunity and the next one (break character) - // is not a space, it could be used as a line end; - // add one more letter space, in case other text follows - if ((breakOpportunityChar != 0) && !TextLayoutManager.isSpace(breakOpportunityChar)) { - letterSpaces++; - } - } - assert letterSpaces >= 0; - wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces)); - - // create and return the AreaInfo object - return new AreaInfo(thisStart, lastIndex, 0, - letterSpaces, wordIPD, - endsWithHyphen, - false, breakOpportunityChar != 0, font, level, null); - } - - private AreaInfo processWord(final int alignment, final KnuthSequence sequence, - AreaInfo prevAreaInfo, final char ch, final boolean breakOpportunity, + private GlyphMapping processWord(final int alignment, final KnuthSequence sequence, + GlyphMapping prevMapping, final char ch, final boolean breakOpportunity, final boolean checkEndsWithHyphen, int level) { //Word boundary found, process widths and kerning @@ -1178,23 +929,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; Font font = FontSelector.selectFontForCharactersInText( foText, thisStart, lastIndex, foText, this); - AreaInfo areaInfo; - if (font.performsSubstitution() || font.performsPositioning()) { - areaInfo = processWordMapping( - lastIndex, font, prevAreaInfo, breakOpportunity ? ch : 0, endsWithHyphen, level); - } else { - areaInfo = processWordNoMapping( - lastIndex, font, prevAreaInfo, breakOpportunity ? ch : 0, endsWithHyphen, level); - } - prevAreaInfo = areaInfo; - addAreaInfo(areaInfo); + char breakOpportunityChar = breakOpportunity ? ch : 0; + char precedingChar = prevMapping != null && !prevMapping.isSpace + && prevMapping.endIndex > 0 ? foText.charAt(prevMapping.endIndex - 1) : 0; + GlyphMapping mapping = GlyphMapping.doGlyphMapping(foText, thisStart, lastIndex, font, + letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, level); + prevMapping = mapping; + addGlyphMapping(mapping); tempStart = nextStart; //add the elements - addElementsForAWordFragment(sequence, alignment, areaInfo, areaInfos.size() - 1); + addElementsForAWordFragment(sequence, alignment, mapping, mappings.size() - 1); thisStart = nextStart; - return prevAreaInfo; + return prevMapping; } /** {@inheritDoc} */ @@ -1214,9 +962,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int index = leafPos.getLeafPos(); //element could refer to '-1' position, for non-collapsed spaces (?) if (index > -1) { - AreaInfo areaInfo = getAreaInfo(index); - areaInfo.letterSpaceCount++; - areaInfo.addToAreaIPD(letterSpaceIPD); + GlyphMapping mapping = getGlyphMapping(index); + mapping.letterSpaceCount++; + mapping.addToAreaIPD(letterSpaceIPD); if (TextLayoutManager.BREAK_CHARS.indexOf(foText.charAt(tempStart - 1)) >= 0) { // the last character could be used as a line break // append new elements to oldList @@ -1227,13 +975,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (letterSpaceIPD.isStiff()) { // constant letter space: replace the box // give it the unwrapped position of the replaced element - oldListIterator.set(new KnuthInlineBox(areaInfo.areaIPD.getOpt(), + oldListIterator.set(new KnuthInlineBox(mapping.areaIPD.getOpt(), alignmentContext, pos, false)); } else { // adjustable letter space: replace the glue oldListIterator.next(); // this would return the penalty element oldListIterator.next(); // this would return the glue element - oldListIterator.set(new KnuthGlue(letterSpaceIPD.mult(areaInfo.letterSpaceCount), + oldListIterator.set(new KnuthGlue(letterSpaceIPD.mult(mapping.letterSpaceCount), auxiliaryPosition, true)); } } @@ -1242,26 +990,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void hyphenate(Position pos, HyphContext hyphContext) { - AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos() + changeOffset); - int startIndex = areaInfo.startIndex; + GlyphMapping mapping = getGlyphMapping(((LeafPosition) pos).getLeafPos() + changeOffset); + int startIndex = mapping.startIndex; int stopIndex; boolean nothingChanged = true; - Font font = areaInfo.font; + Font font = mapping.font; - while (startIndex < areaInfo.breakIndex) { + while (startIndex < mapping.endIndex) { MinOptMax newIPD = MinOptMax.ZERO; boolean hyphenFollows; stopIndex = startIndex + hyphContext.getNextHyphPoint(); - if (hyphContext.hasMoreHyphPoints() && stopIndex <= areaInfo.breakIndex) { + if (hyphContext.hasMoreHyphPoints() && stopIndex <= mapping.endIndex) { // stopIndex is the index of the first character // after a hyphenation point hyphenFollows = true; } else { // there are no more hyphenation points, - // or the next one is after areaInfo.breakIndex + // or the next one is after mapping.breakIndex hyphenFollows = false; - stopIndex = areaInfo.breakIndex; + stopIndex = mapping.endIndex; } hyphContext.updateOffset(stopIndex - startIndex); @@ -1286,18 +1034,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // add letter spaces boolean isWordEnd - = (stopIndex == areaInfo.breakIndex) - && (areaInfo.letterSpaceCount < areaInfo.getWordLength()); + = (stopIndex == mapping.endIndex) + && (mapping.letterSpaceCount < mapping.getWordLength()); int letterSpaceCount = isWordEnd ? stopIndex - startIndex - 1 : stopIndex - startIndex; assert letterSpaceCount >= 0; newIPD = newIPD.plus(letterSpaceIPD.mult(letterSpaceCount)); - if (!(nothingChanged && stopIndex == areaInfo.breakIndex && !hyphenFollows)) { - // the new AreaInfo object is not equal to the old one + if (!(nothingChanged && stopIndex == mapping.endIndex && !hyphenFollows)) { + // the new GlyphMapping object is not equal to the old one changeList.add( new PendingChange( - new AreaInfo(startIndex, stopIndex, 0, + new GlyphMapping(startIndex, stopIndex, 0, letterSpaceCount, newIPD, hyphenFollows, false, false, font, -1, null), ((LeafPosition) pos).getLeafPos() + changeOffset)); @@ -1324,7 +1072,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return false; } - // Find the first and last positions in oldList that point to an AreaInfo + // Find the first and last positions in oldList that point to a GlyphMapping // (i.e. getLeafPos() != -1) LeafPosition startPos = null; LeafPosition endPos = null; @@ -1349,8 +1097,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { returnedIndices[0] = (startPos != null ? startPos.getLeafPos() : -1) + changeOffset; returnedIndices[1] = (endPos != null ? endPos.getLeafPos() : -1) + changeOffset; - int areaInfosAdded = 0; - int areaInfosRemoved = 0; + int mappingsAdded = 0; + int mappingsRemoved = 0; if (!changeList.isEmpty()) { int oldIndex = -1; @@ -1360,24 +1108,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); if (currChange.index == oldIndex) { - areaInfosAdded++; - changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; + mappingsAdded++; + changeIndex = currChange.index + mappingsAdded - mappingsRemoved; } else { - areaInfosRemoved++; - areaInfosAdded++; + mappingsRemoved++; + mappingsAdded++; oldIndex = currChange.index; - changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; - removeAreaInfo(changeIndex); + changeIndex = currChange.index + mappingsAdded - mappingsRemoved; + removeGlyphMapping(changeIndex); } - addAreaInfo(changeIndex, currChange.areaInfo); + addGlyphMapping(changeIndex, currChange.mapping); } changeList.clear(); } // increase the end index for getChangedKnuthElements() - returnedIndices[1] += (areaInfosAdded - areaInfosRemoved); + returnedIndices[1] += (mappingsAdded - mappingsRemoved); // increase offset to use for subsequent paragraphs - changeOffset += (areaInfosAdded - areaInfosRemoved); + changeOffset += (mappingsAdded - mappingsRemoved); return hasChanged; } @@ -1391,16 +1139,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final LinkedList returnList = new LinkedList(); for (; returnedIndices[0] <= returnedIndices[1]; returnedIndices[0]++) { - AreaInfo areaInfo = getAreaInfo(returnedIndices[0]); - if (areaInfo.wordSpaceCount == 0) { - // areaInfo refers either to a word or a word fragment - addElementsForAWordFragment(returnList, alignment, areaInfo, returnedIndices[0]); + GlyphMapping mapping = getGlyphMapping(returnedIndices[0]); + if (mapping.wordSpaceCount == 0) { + // mapping refers either to a word or a word fragment + addElementsForAWordFragment(returnList, alignment, mapping, returnedIndices[0]); } else { - // areaInfo refers to a space - addElementsForASpace(returnList, alignment, areaInfo, returnedIndices[0]); + // mapping refers to a space + addElementsForASpace(returnList, alignment, mapping, returnedIndices[0]); } } - setFinished(returnedIndices[0] == areaInfos.size() - 1); + setFinished(returnedIndices[0] == mappings.size() - 1); //ElementListObserver.observe(returnList, "text-changed", null); return returnList; } @@ -1409,9 +1157,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public String getWordChars(Position pos) { int leafValue = ((LeafPosition) pos).getLeafPos() + changeOffset; if (leafValue != -1) { - AreaInfo areaInfo = getAreaInfo(leafValue); - StringBuffer buffer = new StringBuffer(areaInfo.getWordLength()); - for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + GlyphMapping mapping = getGlyphMapping(leafValue); + StringBuffer buffer = new StringBuffer(mapping.getWordLength()); + for (int i = mapping.startIndex; i < mapping.endIndex; i++) { buffer.append(foText.charAt(i)); } return buffer.toString(); @@ -1420,41 +1168,39 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private void addElementsForASpace(List baseList, int alignment, AreaInfo areaInfo, + private void addElementsForASpace(List baseList, int alignment, GlyphMapping mapping, int leafValue) { LeafPosition mainPosition = new LeafPosition(this, leafValue); - if (!areaInfo.breakOppAfter) { + if (!mapping.breakOppAfter) { // a non-breaking space if (alignment == Constants.EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line baseList.add(makeAuxiliaryZeroWidthBox()); baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(areaInfo.areaIPD, mainPosition, false)); + baseList.add(new KnuthGlue(mapping.areaIPD, mainPosition, false)); } else { // the space does not need to stretch or shrink, and must be // preserved when starting a line - baseList.add(new KnuthInlineBox(areaInfo.areaIPD.getOpt(), null, mainPosition, + baseList.add(new KnuthInlineBox(mapping.areaIPD.getOpt(), null, mainPosition, true)); } } else { - if (foText.charAt(areaInfo.startIndex) != CharUtilities.SPACE + if (foText.charAt(mapping.startIndex) != CharUtilities.SPACE || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - baseList - .addAll(getElementsForBreakingSpace(alignment, areaInfo, auxiliaryPosition, 0, - mainPosition, areaInfo.areaIPD.getOpt(), true)); + baseList.addAll(getElementsForBreakingSpace(alignment, mapping, auxiliaryPosition, 0, + mainPosition, mapping.areaIPD.getOpt(), true)); } else { // a (possible block) of breaking spaces - baseList - .addAll(getElementsForBreakingSpace(alignment, areaInfo, mainPosition, - areaInfo.areaIPD.getOpt(), auxiliaryPosition, 0, false)); + baseList.addAll(getElementsForBreakingSpace(alignment, mapping, mainPosition, + mapping.areaIPD.getOpt(), auxiliaryPosition, 0, false)); } } } - private List getElementsForBreakingSpace(int alignment, AreaInfo areaInfo, Position pos2, + private List getElementsForBreakingSpace(int alignment, GlyphMapping mapping, Position pos2, int p2WidthOffset, Position pos3, int p3WidthOffset, boolean skipZeroCheck) { List elements = new ArrayList(); @@ -1504,7 +1250,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { elements.add(g); elements.add(makeZeroWidthPenalty(0)); g = new KnuthGlue( - areaInfo.areaIPD.getOpt(), + mapping.areaIPD.getOpt(), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false); elements.add(g); } @@ -1513,25 +1259,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { case EN_JUSTIFY: // justified text: // the stretch and shrink depends on the space width - elements.addAll(getElementsForJustifiedText(areaInfo, pos2, p2WidthOffset, pos3, - p3WidthOffset, skipZeroCheck, areaInfo.areaIPD.getShrink())); + elements.addAll(getElementsForJustifiedText(mapping, pos2, p2WidthOffset, pos3, + p3WidthOffset, skipZeroCheck, mapping.areaIPD.getShrink())); break; default: // last line justified, the other lines unjustified: // use only the space stretch - elements.addAll(getElementsForJustifiedText(areaInfo, pos2, p2WidthOffset, pos3, + elements.addAll(getElementsForJustifiedText(mapping, pos2, p2WidthOffset, pos3, p3WidthOffset, skipZeroCheck, 0)); } return elements; } - private List getElementsForJustifiedText( - AreaInfo areaInfo, Position pos2, int p2WidthOffset, - Position pos3, int p3WidthOffset, boolean skipZeroCheck, - int shrinkability) { + private List getElementsForJustifiedText(GlyphMapping mapping, Position pos2, int p2WidthOffset, + Position pos3, int p3WidthOffset, boolean skipZeroCheck, + int shrinkability) { - int stretchability = areaInfo.areaIPD.getStretch(); + int stretchability = mapping.areaIPD.getStretch(); List elements = new ArrayList(); if (skipZeroCheck || lineStartBAP != 0 || lineEndBAP != 0) { @@ -1543,34 +1288,34 @@ public class TextLayoutManager extends LeafNodeLayoutManager { elements.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); elements.add(new KnuthGlue(lineStartBAP + p3WidthOffset, 0, 0, pos3, false)); } else { - elements.add(new KnuthGlue(areaInfo.areaIPD.getOpt(), stretchability, shrinkability, + elements.add(new KnuthGlue(mapping.areaIPD.getOpt(), stretchability, shrinkability, pos2, false)); } return elements; } - private void addElementsForAWordFragment(List baseList, int alignment, AreaInfo areaInfo, + private void addElementsForAWordFragment(List baseList, int alignment, GlyphMapping mapping, int leafValue) { LeafPosition mainPosition = new LeafPosition(this, leafValue); // if the last character of the word fragment is '-' or '/', // the fragment could end a line; in this case, it loses one // of its letter spaces; - boolean suppressibleLetterSpace = areaInfo.breakOppAfter && !areaInfo.isHyphenated; + boolean suppressibleLetterSpace = mapping.breakOppAfter && !mapping.isHyphenated; if (letterSpaceIPD.isStiff()) { // constant letter spacing baseList.add(new KnuthInlineBox(suppressibleLetterSpace - ? areaInfo.areaIPD.getOpt() - letterSpaceIPD.getOpt() - : areaInfo.areaIPD.getOpt(), + ? mapping.areaIPD.getOpt() - letterSpaceIPD.getOpt() + : mapping.areaIPD.getOpt(), alignmentContext, notifyPos(mainPosition), false)); } else { // adjustable letter spacing int unsuppressibleLetterSpaces = suppressibleLetterSpace - ? areaInfo.letterSpaceCount - 1 - : areaInfo.letterSpaceCount; - baseList.add(new KnuthInlineBox(areaInfo.areaIPD.getOpt() - - areaInfo.letterSpaceCount * letterSpaceIPD.getOpt(), + ? mapping.letterSpaceCount - 1 + : mapping.letterSpaceCount; + baseList.add(new KnuthInlineBox(mapping.areaIPD.getOpt() + - mapping.letterSpaceCount * letterSpaceIPD.getOpt(), alignmentContext, notifyPos(mainPosition), false)); baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(letterSpaceIPD.mult(unsuppressibleLetterSpaces), @@ -1580,19 +1325,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break - if (areaInfo.isHyphenated) { + if (mapping.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (areaInfo.breakIndex < foText.length()) { + if (mapping.endIndex < foText.length()) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = letterSpaceAdjustArray[areaInfo.breakIndex]; + widthIfNoBreakOccurs = letterSpaceAdjustArray[mapping.endIndex]; } - //if (areaInfo.breakIndex) + //if (mapping.breakIndex) // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens addElementsForAHyphen(baseList, alignment, hyphIPD, widthIfNoBreakOccurs, - areaInfo.breakOppAfter && areaInfo.isHyphenated); + mapping.breakOppAfter && mapping.isHyphenated); } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index 392eb875e..983a5ad90 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -31,6 +31,7 @@ import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.dom.AbstractDocument; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; @@ -122,7 +123,8 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC //Prepare FOUserAgent userAgent = rendererContext.getUserAgent(); - SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AffineTransform()); + SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, DefaultFontFamilyResolver.SINGLETON, + new AffineTransform()); //Create Batik BridgeContext final BridgeContext bridgeContext = new BridgeContext(svgUserAgent); diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 4549a26af..ccb4cc678 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -29,6 +29,7 @@ import org.w3c.dom.Document; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; @@ -43,6 +44,7 @@ import org.apache.fop.afp.AFPResourceInfo; import org.apache.fop.afp.AFPResourceManager; import org.apache.fop.afp.AFPUnitConverter; import org.apache.fop.afp.svg.AFPBridgeContext; +import org.apache.fop.afp.svg.AFPFontFamilyResolver; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontInfo; import org.apache.fop.image.loader.batik.BatikUtil; @@ -53,6 +55,7 @@ import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.svg.font.AggregatingFontFamilyResolver; /** * AFP XML handler for SVG. Uses Apache Batik for SVG processing. @@ -196,15 +199,13 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { */ public static BridgeContext createBridgeContext(FOUserAgent userAgent, AFPGraphics2D g2d) { ImageManager imageManager = userAgent.getImageManager(); - - SVGUserAgent svgUserAgent - = new SVGUserAgent(userAgent, new AffineTransform()); - - ImageSessionContext imageSessionContext = userAgent.getImageSessionContext(); - FontInfo fontInfo = g2d.getFontInfo(); + SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AggregatingFontFamilyResolver( + new AFPFontFamilyResolver(fontInfo, userAgent.getEventBroadcaster()), DefaultFontFamilyResolver.SINGLETON), + new AffineTransform()); + ImageSessionContext imageSessionContext = userAgent.getImageSessionContext(); return new AFPBridgeContext(svgUserAgent, fontInfo, imageManager, imageSessionContext, - new AffineTransform(), g2d); + new AffineTransform(), g2d, userAgent.getEventBroadcaster()); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 2f8865b14..5e9372a75 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -21,6 +21,7 @@ package org.apache.fop.render.java2d; import java.awt.Font; import java.awt.FontFormatException; +import java.awt.Rectangle; import java.io.IOException; import java.io.InputStream; import java.util.Map; @@ -183,11 +184,31 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp return typeface.getWidths(); } + public Rectangle getBoundingBox(int glyphIndex, int size) { + return typeface.getBoundingBox(glyphIndex, size); + } + /** {@inheritDoc} */ public final int getXHeight(final int size) { return typeface.getXHeight(size); } + public int getUnderlinePosition(int size) { + return typeface.getUnderlinePosition(size); + } + + public int getUnderlineThickness(int size) { + return typeface.getUnderlineThickness(size); + } + + public int getStrikeoutPosition(int size) { + return typeface.getStrikeoutPosition(size); + } + + public int getStrikeoutThickness(int size) { + return typeface.getStrikeoutThickness(size); + } + /** {@inheritDoc} */ public final boolean hasKerningInfo() { return typeface.hasKerningInfo(); diff --git a/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java index fc4af3574..5e681e9e2 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java +++ b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java @@ -223,6 +223,26 @@ public class Java2DFontMetrics { return xHeight * 1000; } + public int getUnderlinePosition(String family, int style, int size) { + setFont(family, style, size); + return -Math.round(lineMetrics.getUnderlineOffset()); + } + + public int getUnderlineThickness(String family, int style, int size) { + setFont(family, style, size); + return Math.round(lineMetrics.getUnderlineThickness()); + } + + public int getStrikeoutPosition(String family, int style, int size) { + setFont(family, style, size); + return -Math.round(lineMetrics.getStrikethroughOffset()); + } + + public int getStrikeoutThickness(String family, int style, int size) { + setFont(family, style, size); + return Math.round(lineMetrics.getStrikethroughThickness()); + } + /** * Returns width (in 1/1000ths of point size) of character at * code point i diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java index 110581f27..f3128c600 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java +++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java @@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.font.DefaultFontFamilyResolver; import org.apache.fop.image.loader.batik.BatikUtil; import org.apache.fop.render.AbstractGenericSVGHandler; @@ -128,8 +129,8 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler int x = info.currentXPosition; int y = info.currentYPosition; - - SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), DefaultFontFamilyResolver.SINGLETON, + new AffineTransform()); BridgeContext ctx = new BridgeContext(ua); diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java index 06c975b86..f922e3f05 100644 --- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -20,6 +20,7 @@ package org.apache.fop.render.java2d; // Java +import java.awt.Rectangle; import java.util.Map; import java.util.Set; @@ -133,6 +134,22 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp return java2DFontMetrics.getXHeight(family, style, size); } + public int getUnderlinePosition(int size) { + return java2DFontMetrics.getUnderlinePosition(family, style, size); + } + + public int getUnderlineThickness(int size) { + return java2DFontMetrics.getUnderlineThickness(family, style, size); + } + + public int getStrikeoutPosition(int size) { + return java2DFontMetrics.getStrikeoutPosition(family, style, size); + } + + public int getStrikeoutThickness(int size) { + return java2DFontMetrics.getStrikeoutThickness(family, style, size); + } + /** * {@inheritDoc} */ @@ -148,6 +165,10 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp return java2DFontMetrics.getWidths(family, style, Java2DFontMetrics.FONT_SIZE); } + public Rectangle getBoundingBox(int glyphIndex, int size) { + throw new UnsupportedOperationException("Not implemented"); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java index 45d8dff2d..3b7084a65 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java @@ -52,6 +52,7 @@ import org.apache.fop.svg.PDFBridgeContext; import org.apache.fop.svg.PDFGraphics2D; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; /** * Image Handler implementation which handles SVG images. @@ -76,7 +77,8 @@ public class PDFImageHandlerSVG implements ImageHandler { } final float uaResolution = userAgent.getSourceResolution(); - SVGUserAgent ua = new SVGUserAgent(userAgent, new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(userAgent, new FOPFontFamilyResolverImpl(pdfContext.getFontInfo()), + new AffineTransform()); GVTBuilder builder = new GVTBuilder(); diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index 1d464cae6..96886910e 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -40,6 +40,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.FontInfo; import org.apache.fop.svg.AbstractFOPTranscoder; import org.apache.fop.svg.PDFDocumentGraphics2DConfigurator; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; /** * <p>This class enables to transcode an input to a PostScript document.</p> @@ -115,6 +116,8 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { this.fontInfo = PDFDocumentGraphics2DConfigurator.createFontInfo( getEffectiveConfiguration(), useComplexScriptFeatures); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); + ((FOPTranscoderUserAgent) userAgent).setFontFamilyResolver( + new FOPFontFamilyResolverImpl(fontInfo)); } catch (FOPException fe) { throw new TranscoderException(fe); } diff --git a/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java b/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java index 3ade34522..bd8e97063 100644 --- a/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java +++ b/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java @@ -41,6 +41,7 @@ import org.apache.fop.render.ImageHandler; import org.apache.fop.render.RenderingContext; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; /** * Image handler implementation which handles SVG images for PostScript output. @@ -62,8 +63,8 @@ public class PSImageHandlerSVG implements ImageHandler { boolean strokeText = false; //TODO Configure text stroking - SVGUserAgent ua - = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), + new FOPFontFamilyResolverImpl(psContext.getFontInfo()), new AffineTransform()); PSGraphics2D graphics = new PSGraphics2D(strokeText, gen); graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index e30f6391b..dfbaf60b7 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -249,8 +249,7 @@ public class PSSVGHandler extends AbstractGenericSVGHandler strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText); } - SVGUserAgent ua - = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), null /* TODO */, new AffineTransform()); PSGraphics2D graphics = new PSGraphics2D(strokeText, gen); graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java index eb2188026..44b7b08a3 100644 --- a/src/java/org/apache/fop/render/ps/PSTextPainter.java +++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java @@ -19,25 +19,21 @@ package org.apache.fop.render.ps; -import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; +import java.awt.geom.Point2D.Double; import java.io.IOException; -import java.text.AttributedCharacterIterator; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; -import org.apache.batik.gvt.font.GVTGlyphVector; import org.apache.batik.gvt.text.TextPaintInfo; -import org.apache.batik.gvt.text.TextSpanLayout; import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; @@ -48,7 +44,6 @@ import org.apache.fop.fonts.FontMetrics; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.svg.NativeTextPainter; -import org.apache.fop.util.CharUtilities; import org.apache.fop.util.HexEncoder; /** @@ -62,10 +57,20 @@ import org.apache.fop.util.HexEncoder; */ public class PSTextPainter extends NativeTextPainter { - private static final boolean DEBUG = false; - private FontResourceCache fontResources; + private PSGraphics2D ps; + + private PSGenerator gen; + + private TextUtil textUtil; + + private boolean flushCurrentRun; + + private PSTextRun psRun; + + private Double relPos; + private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); /** @@ -82,165 +87,26 @@ public class PSTextPainter extends NativeTextPainter { return g2d instanceof PSGraphics2D; } - /** {@inheritDoc} */ - protected void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException { - AttributedCharacterIterator runaci = textRun.getACI(); - runaci.first(); - - TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO); - if (tpi == null || !tpi.visible) { - return; - } - if ((tpi != null) && (tpi.composite != null)) { - g2d.setComposite(tpi.composite); - } - - //------------------------------------ - TextSpanLayout layout = textRun.getLayout(); - logTextRun(runaci, layout); - CharSequence chars = collectCharacters(runaci); - runaci.first(); //Reset ACI - - final PSGraphics2D ps = (PSGraphics2D)g2d; - final PSGenerator gen = ps.getPSGenerator(); + @Override + protected void preparePainting(Graphics2D g2d) { + ps = (PSGraphics2D) g2d; + gen = ps.getPSGenerator(); ps.preparePainting(); + } - if (DEBUG) { - log.debug("Text: " + chars); - gen.commentln("%Text: " + chars); - } - - GeneralPath debugShapes = null; - if (DEBUG) { - debugShapes = new GeneralPath(); - } - - TextUtil textUtil = new TextUtil(gen); - textUtil.setupFonts(runaci); - if (!textUtil.hasFonts()) { - //Draw using Java2D when no native fonts are available - textRun.getLayout().draw(g2d); - return; - } - + @Override + protected void saveGraphicsState() throws IOException { gen.saveGraphicsState(); - gen.concatMatrix(g2d.getTransform()); - Shape imclip = g2d.getClip(); - clip(ps, imclip); - - gen.writeln("BT"); //beginTextObject() - - AffineTransform localTransform = new AffineTransform(); - Point2D prevPos = null; - GVTGlyphVector gv = layout.getGlyphVector(); - PSTextRun psRun = new PSTextRun(); //Used to split a text run into smaller runs - for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) { - char ch = chars.charAt(index); - boolean visibleChar = gv.isGlyphVisible(index) - || (CharUtilities.isAnySpace(ch) && !CharUtilities.isZeroWidthSpace(ch)); - logCharacter(ch, layout, index, visibleChar); - if (!visibleChar) { - continue; - } - Point2D glyphPos = gv.getGlyphPosition(index); - - AffineTransform glyphTransform = gv.getGlyphTransform(index); - if (log.isTraceEnabled()) { - log.trace("pos " + glyphPos + ", transform " + glyphTransform); - } - if (DEBUG) { - Shape sh = gv.getGlyphLogicalBounds(index); - if (sh == null) { - sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2); - } - debugShapes.append(sh, false); - } - - //Exact position of the glyph - localTransform.setToIdentity(); - localTransform.translate(glyphPos.getX(), glyphPos.getY()); - if (glyphTransform != null) { - localTransform.concatenate(glyphTransform); - } - localTransform.scale(1, -1); - - boolean flushCurrentRun = false; - //Try to optimize by combining characters using the same font and on the same line. - if (glyphTransform != null) { - //Happens for text-on-a-path - flushCurrentRun = true; - } - if (psRun.getRunLength() >= 128) { - //Don't let a run get too long - flushCurrentRun = true; - } - - //Note the position of the glyph relative to the previous one - Point2D relPos; - if (prevPos == null) { - relPos = new Point2D.Double(0, 0); - } else { - relPos = new Point2D.Double( - glyphPos.getX() - prevPos.getX(), - glyphPos.getY() - prevPos.getY()); - } - if (psRun.vertChanges == 0 - && psRun.getHorizRunLength() > 2 - && relPos.getY() != 0) { - //new line - flushCurrentRun = true; - } - - //Select the actual character to paint - char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch); - - //Select (sub)font for character - Font f = textUtil.selectFontForChar(paintChar); - char mapped = f.mapChar(ch); - boolean fontChanging = textUtil.isFontChanging(f, mapped); - if (fontChanging) { - flushCurrentRun = true; - } - - if (flushCurrentRun) { - //Paint the current run and reset for the next run - psRun.paint(ps, textUtil, tpi); - psRun.reset(); - } - - //Track current run - psRun.addCharacter(paintChar, relPos); - psRun.noteStartingTransformation(localTransform); - - //Change font if necessary - if (fontChanging) { - textUtil.setCurrentFont(f, mapped); - } + } - //Update last position - prevPos = glyphPos; - } - psRun.paint(ps, textUtil, tpi); - gen.writeln("ET"); //endTextObject() + @Override + protected void restoreGraphicsState() throws IOException { gen.restoreGraphicsState(); - - if (DEBUG) { - //Paint debug shapes - g2d.setStroke(new BasicStroke(0)); - g2d.setColor(Color.LIGHT_GRAY); - g2d.draw(debugShapes); - } } - private void applyColor(Paint paint, final PSGenerator gen) throws IOException { - if (paint == null) { - return; - } else if (paint instanceof Color) { - Color col = (Color)paint; - gen.useColor(col); - } else { - log.warn("Paint not supported: " + paint.toString()); - } + @Override + protected void setInitialTransform(AffineTransform transform) throws IOException { + gen.concatMatrix(transform); } private PSFontResource getResourceForFont(Font f, String postfix) { @@ -248,7 +114,8 @@ public class PSTextPainter extends NativeTextPainter { return this.fontResources.getFontResourceForFontKey(key); } - private void clip(PSGraphics2D ps, Shape shape) throws IOException { + @Override + protected void clip(Shape shape) throws IOException { if (shape == null) { return; } @@ -258,17 +125,76 @@ public class PSTextPainter extends NativeTextPainter { ps.getPSGenerator().writeln("clip"); } + @Override + protected void beginTextObject() throws IOException { + gen.writeln("BT"); + textUtil = new TextUtil(); + psRun = new PSTextRun(); //Used to split a text run into smaller runs + } + + @Override + protected void endTextObject() throws IOException { + psRun.paint(ps, textUtil, tpi); + gen.writeln("ET"); + } + + @Override + protected void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition) { + flushCurrentRun = false; + //Try to optimize by combining characters using the same font and on the same line. + if (reposition) { + //Happens for text-on-a-path + flushCurrentRun = true; + } + if (psRun.getRunLength() >= 128) { + //Don't let a run get too long + flushCurrentRun = true; + } + + //Note the position of the glyph relative to the previous one + if (prevPos == null) { + relPos = new Point2D.Double(0, 0); + } else { + relPos = new Point2D.Double( + glyphPos.getX() - prevPos.getX(), + glyphPos.getY() - prevPos.getY()); + } + if (psRun.vertChanges == 0 + && psRun.getHorizRunLength() > 2 + && relPos.getY() != 0) { + //new line + flushCurrentRun = true; + } + } + + @Override + protected void writeGlyph(char glyph, AffineTransform localTransform) throws IOException { + boolean fontChanging = textUtil.isFontChanging(font, glyph); + if (fontChanging) { + flushCurrentRun = true; + } + + if (flushCurrentRun) { + //Paint the current run and reset for the next run + psRun.paint(ps, textUtil, tpi); + psRun.reset(); + } + + //Track current run + psRun.addGlyph(glyph, relPos); + psRun.noteStartingTransformation(localTransform); + + //Change font if necessary + if (fontChanging) { + textUtil.setCurrentFont(font, glyph); + } + } + private class TextUtil { - private PSGenerator gen; - private Font[] fonts; private Font currentFont; private int currentEncoding = -1; - public TextUtil(PSGenerator gen) { - this.gen = gen; - } - public boolean isMultiByte(Font f) { FontMetrics metrics = f.getFontMetrics(); boolean multiByte = metrics instanceof MultiByteFont || metrics instanceof LazyFont @@ -276,15 +202,6 @@ public class PSTextPainter extends NativeTextPainter { return multiByte; } - public Font selectFontForChar(char ch) { - for (int i = 0, c = fonts.length; i < c; i++) { - if (fonts[i].hasChar(ch)) { - return fonts[i]; - } - } - return fonts[0]; //TODO Maybe fall back to painting with shapes - } - public void writeTextMatrix(AffineTransform transform) throws IOException { double[] matrix = new double[6]; transform.getMatrix(matrix); @@ -335,27 +252,19 @@ public class PSTextPainter extends NativeTextPainter { setCurrentFont(font, encoding); } - public void setupFonts(AttributedCharacterIterator runaci) { - this.fonts = findFonts(runaci); - } - - public boolean hasFonts() { - return (fonts != null) && (fonts.length > 0); - } - } private class PSTextRun { private AffineTransform textTransform; - private List relativePositions = new java.util.LinkedList(); - private StringBuffer currentChars = new StringBuffer(); + private List<Point2D> relativePositions = new LinkedList<Point2D>(); + private StringBuffer currentGlyphs = new StringBuffer(); private int horizChanges = 0; private int vertChanges = 0; public void reset() { textTransform = null; - currentChars.setLength(0); + currentGlyphs.setLength(0); horizChanges = 0; vertChanges = 0; relativePositions.clear(); @@ -369,9 +278,9 @@ public class PSTextPainter extends NativeTextPainter { return 0; } - public void addCharacter(char paintChar, Point2D relPos) { + public void addGlyph(char glyph, Point2D relPos) { addRelativePosition(relPos); - currentChars.append(paintChar); + currentGlyphs.append(glyph); } private void addRelativePosition(Point2D relPos) { @@ -393,7 +302,7 @@ public class PSTextPainter extends NativeTextPainter { } public int getRunLength() { - return currentChars.length(); + return currentGlyphs.length(); } private boolean isXShow() { @@ -407,9 +316,6 @@ public class PSTextPainter extends NativeTextPainter { public void paint(PSGraphics2D g2d, TextUtil textUtil, TextPaintInfo tpi) throws IOException { if (getRunLength() > 0) { - if (log.isDebugEnabled()) { - log.debug("Text run: " + currentChars); - } textUtil.writeTextMatrix(this.textTransform); if (isXShow()) { log.debug("Horizontal text: xshow"); @@ -431,25 +337,20 @@ public class PSTextPainter extends NativeTextPainter { private void paintXYShow(PSGraphics2D g2d, TextUtil textUtil, Paint paint, boolean x, boolean y) throws IOException { - PSGenerator gen = textUtil.gen; - char firstChar = this.currentChars.charAt(0); - //Font only has to be setup up before the first character - Font f = textUtil.selectFontForChar(firstChar); - char mapped = f.mapChar(firstChar); - textUtil.selectFont(f, mapped); - textUtil.setCurrentFont(f, mapped); - applyColor(paint, gen); - - boolean multiByte = textUtil.isMultiByte(f); + char glyph = currentGlyphs.charAt(0); + textUtil.selectFont(font, glyph); + textUtil.setCurrentFont(font, glyph); + applyColor(paint); + + boolean multiByte = textUtil.isMultiByte(font); StringBuffer sb = new StringBuffer(); sb.append(multiByte ? '<' : '('); - for (int i = 0, c = this.currentChars.length(); i < c; i++) { - char ch = this.currentChars.charAt(i); - mapped = f.mapChar(ch); + for (int i = 0, c = this.currentGlyphs.length(); i < c; i++) { + glyph = this.currentGlyphs.charAt(i); if (multiByte) { - sb.append(HexEncoder.encode(mapped)); + sb.append(HexEncoder.encode(glyph)); } else { - char codepoint = (char) (mapped % 256); + char codepoint = (char) (glyph % 256); PSGenerator.escapeChar(codepoint, sb); } } @@ -457,9 +358,9 @@ public class PSTextPainter extends NativeTextPainter { if (x || y) { sb.append("\n["); int idx = 0; - Iterator iter = this.relativePositions.iterator(); + Iterator<Point2D> iter = this.relativePositions.iterator(); while (iter.hasNext()) { - Point2D pt = (Point2D)iter.next(); + Point2D pt = iter.next(); if (idx > 0) { if (x) { sb.append(format(gen, pt.getX())); @@ -500,6 +401,17 @@ public class PSTextPainter extends NativeTextPainter { gen.writeln(sb.toString()); } + private void applyColor(Paint paint) throws IOException { + if (paint == null) { + return; + } else if (paint instanceof Color) { + Color col = (Color) paint; + gen.useColor(col); + } else { + log.warn("Paint not supported: " + paint.toString()); + } + } + private String format(PSGenerator gen, double coord) { if (Math.abs(coord) < 0.00001) { return "0"; @@ -510,30 +422,21 @@ public class PSTextPainter extends NativeTextPainter { private void paintStrokedGlyphs(PSGraphics2D g2d, TextUtil textUtil, Paint strokePaint, Stroke stroke) throws IOException { - PSGenerator gen = textUtil.gen; - - applyColor(strokePaint, gen); + applyColor(strokePaint); PSGraphics2D.applyStroke(stroke, gen); - Font f = null; - Iterator iter = this.relativePositions.iterator(); + Iterator<Point2D> iter = this.relativePositions.iterator(); iter.next(); Point2D pos = new Point2D.Double(0, 0); gen.writeln("0 0 M"); - for (int i = 0, c = this.currentChars.length(); i < c; i++) { - char ch = this.currentChars.charAt(0); + for (int i = 0, c = this.currentGlyphs.length(); i < c; i++) { + char mapped = this.currentGlyphs.charAt(i); if (i == 0) { - //Font only has to be setup up before the first character - f = textUtil.selectFontForChar(ch); - } - char mapped = f.mapChar(ch); - if (i == 0) { - textUtil.selectFont(f, mapped); - textUtil.setCurrentFont(f, mapped); + textUtil.selectFont(font, mapped); + textUtil.setCurrentFont(font, mapped); } //add glyph outlines to current path - mapped = f.mapChar(this.currentChars.charAt(i)); - FontMetrics metrics = f.getFontMetrics(); + FontMetrics metrics = font.getFontMetrics(); boolean multiByte = metrics instanceof MultiByteFont || metrics instanceof LazyFont && ((LazyFont) metrics).getRealFont() instanceof MultiByteFont; @@ -542,14 +445,14 @@ public class PSTextPainter extends NativeTextPainter { gen.write(HexEncoder.encode(mapped)); gen.write(">"); } else { - char codepoint = (char)(mapped % 256); + char codepoint = (char) (mapped % 256); gen.write("(" + codepoint + ")"); } gen.writeln(" false charpath"); if (iter.hasNext()) { //Position for the next character - Point2D pt = (Point2D)iter.next(); + Point2D pt = iter.next(); pos.setLocation(pos.getX() + pt.getX(), pos.getY() - pt.getY()); gen.writeln(gen.formatDouble5(pos.getX()) + " " + gen.formatDouble5(pos.getY()) + " M"); diff --git a/src/java/org/apache/fop/svg/ACIUtils.java b/src/java/org/apache/fop/svg/ACIUtils.java index f54a026e1..deba98f21 100644 --- a/src/java/org/apache/fop/svg/ACIUtils.java +++ b/src/java/org/apache/fop/svg/ACIUtils.java @@ -38,7 +38,8 @@ import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.svg.font.FOPGVTFont; +import org.apache.fop.svg.font.FOPGVTFontFamily; /** * Utilities for java.text.AttributedCharacterIterator. @@ -64,57 +65,43 @@ public final class ACIUtils { @SuppressWarnings("unchecked") List<GVTFontFamily> gvtFonts = (List<GVTFontFamily>) aci.getAttribute( GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); - Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE); - Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT); - Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE); - - String style = toStyle(posture); - int weight = toCSSWeight(taWeight); - int fsize = (int)(fontSize.floatValue() * 1000); + String style = toStyle((Float) aci.getAttribute(TextAttribute.POSTURE)); + int weight = toCSSWeight((Float) aci.getAttribute(TextAttribute.WEIGHT)); + float fontSize = ((Float) aci.getAttribute(TextAttribute.SIZE)).floatValue(); String firstFontFamily = null; - //GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES //or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set - /* The following code section is not available until Batik 1.7 is released. */ - GVTFont gvtFont = (GVTFont)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.GVT_FONT); + GVTFont gvtFont = (GVTFont) aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT); if (gvtFont != null) { String gvtFontFamily = gvtFont.getFamilyName(); - if (fontInfo.hasFont(gvtFontFamily, style, weight)) { - FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, style, - weight); - Font f = fontInfo.getFontInstance(triplet, fsize); + if (gvtFont instanceof FOPGVTFont) { + Font font = ((FOPGVTFont) gvtFont).getFont(); if (LOG.isDebugEnabled()) { LOG.debug("Found a font that matches the GVT font: " + gvtFontFamily + ", " + weight + ", " + style - + " -> " + f); + + " -> " + font); } - fonts.add(f); + fonts.add(font); } firstFontFamily = gvtFontFamily; } if (gvtFonts != null) { boolean haveInstanceOfSVGFontFamily = false; - for (GVTFontFamily fam : gvtFonts) { - if (fam instanceof SVGFontFamily) { + for (GVTFontFamily fontFamily : gvtFonts) { + if (fontFamily instanceof SVGFontFamily) { haveInstanceOfSVGFontFamily = true; - } - String fontFamily = fam.getFamilyName(); - if (fontInfo.hasFont(fontFamily, style, weight)) { - FontTriplet triplet = fontInfo.fontLookup(fontFamily, style, - weight); - Font f = fontInfo.getFontInstance(triplet, fsize); + } else if (fontFamily instanceof FOPGVTFontFamily) { + Font font = ((FOPGVTFontFamily) fontFamily).deriveFont(fontSize, aci).getFont(); if (LOG.isDebugEnabled()) { LOG.debug("Found a font that matches the GVT font family: " - + fontFamily + ", " + weight + ", " + style - + " -> " + f); + + fontFamily.getFamilyName() + ", " + weight + ", " + style + " -> " + font); } - fonts.add(f); + fonts.add(font); } if (firstFontFamily == null) { - firstFontFamily = fontFamily; + firstFontFamily = fontFamily.getFamilyName(); } } // SVG fonts are embedded fonts in the SVG document and are rarely used; however if they @@ -126,25 +113,10 @@ public final class ACIUtils { return null; // Let Batik paint this text! } } - if (fonts.isEmpty()) { - if (firstFontFamily == null) { - //This will probably never happen. Just to be on the safe side. - firstFontFamily = "any"; - } - //lookup with fallback possibility (incl. substitution notification) - FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight); - Font f = fontInfo.getFontInstance(triplet, fsize); - if (LOG.isDebugEnabled()) { - LOG.debug("Falling back to adjustable font lookup up for: " - + firstFontFamily + ", " + weight + ", " + style - + " -> " + f); - } - fonts.add(f); - } - return fonts.toArray(new Font[fonts.size()]); + return fonts.isEmpty() ? null : fonts.toArray(new Font[fonts.size()]); } - private static int toCSSWeight(Float weight) { + public static int toCSSWeight(Float weight) { if (weight == null) { return 400; } else if (weight <= TextAttribute.WEIGHT_EXTRA_LIGHT.floatValue()) { @@ -170,7 +142,7 @@ public final class ACIUtils { } } - private static String toStyle(Float posture) { + public static String toStyle(Float posture) { return ((posture != null) && (posture.floatValue() > 0.0)) ? Font.STYLE_ITALIC : Font.STYLE_NORMAL; diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java index 3e16799f4..7df127d3a 100644 --- a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java +++ b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java @@ -23,20 +23,15 @@ import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; -import java.awt.font.TextAttribute; -import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.text.AttributedCharacterIterator; import java.text.CharacterIterator; -import java.util.Iterator; -import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.batik.dom.svg.SVGOMTextElement; import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.TextPainter; import org.apache.batik.gvt.renderer.StrokingTextPainter; @@ -66,15 +61,15 @@ public abstract class AbstractFOPTextPainter implements TextPainter { * Use the stroking text painter to get the bounds and shape. * Also used as a fallback to draw the string with strokes. */ - protected static final TextPainter - PROXY_PAINTER = StrokingTextPainter.getInstance(); + private final TextPainter proxyTextPainter; /** * Create a new PS text painter with the given font information. * @param nativeTextHandler the NativeTextHandler instance used for text painting */ - public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler) { + public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler, TextPainter proxyTextPainter) { this.nativeTextHandler = nativeTextHandler; + this.proxyTextPainter = proxyTextPainter; } /** @@ -85,19 +80,10 @@ public abstract class AbstractFOPTextPainter implements TextPainter { * @param g2d the Graphics2D to use */ public void paint(TextNode node, Graphics2D g2d) { - Point2D loc = node.getLocation(); - if (!isSupportedGraphics2D(g2d) || hasUnsupportedAttributes(node)) { - if (log.isDebugEnabled()) { - log.debug("painting text node " + node - + " by stroking due to unsupported attributes or an incompatible Graphics2D"); - } - PROXY_PAINTER.paint(node, g2d); - } else { - if (log.isDebugEnabled()) { - log.debug("painting text node " + node + " normally."); - } - paintTextRuns(node.getTextRuns(), g2d, loc); + if (isSupportedGraphics2D(g2d)) { + new TextRunPainter().paintTextRuns(node.getTextRuns(), g2d, node.getLocation()); } + proxyTextPainter.paint(node, g2d); } /** @@ -109,190 +95,99 @@ public abstract class AbstractFOPTextPainter implements TextPainter { */ protected abstract boolean isSupportedGraphics2D(Graphics2D g2d); - private boolean hasUnsupportedAttributes(TextNode node) { - Iterator iter = node.getTextRuns().iterator(); - while (iter.hasNext()) { - StrokingTextPainter.TextRun - run = (StrokingTextPainter.TextRun)iter.next(); - AttributedCharacterIterator aci = run.getACI(); - boolean hasUnsupported = hasUnsupportedAttributes(aci); - if (hasUnsupported) { - return true; - } - } - return false; - } - - private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) { - boolean hasUnsupported = false; - - Font font = getFont(aci); - String text = getText(aci); - if (hasUnsupportedGlyphs(text, font)) { - log.trace("-> Unsupported glyphs found"); - hasUnsupported = true; - } + private class TextRunPainter { - TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); - if ((tpi != null) - && ((tpi.strokeStroke != null && tpi.strokePaint != null) - || (tpi.strikethroughStroke != null) - || (tpi.underlineStroke != null) - || (tpi.overlineStroke != null))) { - log.trace("-> under/overlines etc. found"); - hasUnsupported = true; - } + private Point2D currentLocation; - //Alpha is not supported - Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND); - if (foreground instanceof Color) { - Color col = (Color)foreground; - if (col.getAlpha() != 255) { - log.trace("-> transparency found"); - hasUnsupported = true; + public void paintTextRuns(Iterable<StrokingTextPainter.TextRun> textRuns, Graphics2D g2d, + Point2D nodeLocation) { + currentLocation = new Point2D.Double(nodeLocation.getX(), nodeLocation.getY()); + for (StrokingTextPainter.TextRun run : textRuns) { + paintTextRun(run, g2d); } } - Object letSpace = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING); - if (letSpace != null) { - log.trace("-> letter spacing found"); - hasUnsupported = true; - } - - Object wordSpace = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING); - if (wordSpace != null) { - log.trace("-> word spacing found"); - hasUnsupported = true; - } - - Object lengthAdjust = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST); - if (lengthAdjust != null) { - log.trace("-> length adjustments found"); - hasUnsupported = true; - } - - Object writeMod = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE); - if (writeMod != null - && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals( - writeMod)) { - log.trace("-> Unsupported writing modes found"); - hasUnsupported = true; - } - - Object vertOr = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION); - if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals( - vertOr)) { - log.trace("-> vertical orientation found"); - hasUnsupported = true; - } - - Object rcDel = aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); - //Batik 1.6 returns null here which makes it impossible to determine whether this can - //be painted or not, i.e. fall back to stroking. :-( - if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) { - log.trace("-> spans found"); - hasUnsupported = true; //Filter spans - } - - if (hasUnsupported) { - log.trace("Unsupported attributes found in ACI, using StrokingTextPainter"); - } - return hasUnsupported; - } - - /** - * Paint a list of text runs on the Graphics2D at a given location. - * @param textRuns the list of text runs - * @param g2d the Graphics2D to paint to - * @param loc the current location of the "cursor" - */ - protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) { - Point2D currentloc = loc; - Iterator i = textRuns.iterator(); - while (i.hasNext()) { - StrokingTextPainter.TextRun - run = (StrokingTextPainter.TextRun)i.next(); - currentloc = paintTextRun(run, g2d, currentloc); - } - } - - /** - * Paint a single text run on the Graphics2D at a given location. - * @param run the text run to paint - * @param g2d the Graphics2D to paint to - * @param loc the current location of the "cursor" - * @return the new location of the "cursor" after painting the text run - */ - protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) { - AttributedCharacterIterator aci = run.getACI(); - aci.first(); - - updateLocationFromACI(aci, loc); - AffineTransform at = g2d.getTransform(); - loc = at.transform(loc, null); - - // font - Font font = getFont(aci); - if (font != null) { - nativeTextHandler.setOverrideFont(font); - } - - // color - TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); - if (tpi == null) { - return loc; - } - Paint foreground = tpi.fillPaint; - if (foreground instanceof Color) { - Color col = (Color)foreground; - g2d.setColor(col); - } - g2d.setPaint(foreground); - - // text anchor - TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE); - - // text - String txt = getText(aci); - float advance = getStringWidth(txt, font); - float tx = 0; - if (anchor != null) { - switch (anchor.getType()) { - case TextNode.Anchor.ANCHOR_MIDDLE: - tx = -advance / 2; - break; - case TextNode.Anchor.ANCHOR_END: - tx = -advance; - break; - default: //nop + private void paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d) { + AttributedCharacterIterator aci = run.getACI(); + aci.first(); + updateLocationFromACI(aci, currentLocation); + // font + Font font = getFont(aci); + if (font != null) { + nativeTextHandler.setOverrideFont(font); } - } - - // draw string - double x = loc.getX(); - double y = loc.getY(); - try { + // color + TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); + if (tpi == null) { + return; + } + Paint foreground = tpi.fillPaint; + if (foreground instanceof Color) { + Color col = (Color) foreground; + g2d.setColor(col); + } + g2d.setPaint(foreground); + // text anchor + TextNode.Anchor anchor = (TextNode.Anchor) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE); + // text + String txt = getText(aci); + double advance = font == null ? run.getLayout().getAdvance2D().getX() : getStringWidth(txt, font); + double tx = 0; + if (anchor != null) { + switch (anchor.getType()) { + case TextNode.Anchor.ANCHOR_MIDDLE: + tx = -advance / 2; + break; + case TextNode.Anchor.ANCHOR_END: + tx = -advance; + break; + default: //nop + } + } + // draw string + Point2D outputLocation = g2d.getTransform().transform(currentLocation, null); + double x = outputLocation.getX(); + double y = outputLocation.getY(); try { - nativeTextHandler.drawString(g2d, txt, (float)x + tx, (float)y); - } catch (IOException ioe) { - if (g2d instanceof AFPGraphics2D) { - ((AFPGraphics2D)g2d).handleIOException(ioe); + try { + //TODO draw underline and overline if set + nativeTextHandler.drawString(g2d, txt, (float) (x + tx), (float) y); + //TODO draw strikethrough if set + } catch (IOException ioe) { + if (g2d instanceof AFPGraphics2D) { + ((AFPGraphics2D) g2d).handleIOException(ioe); + } } + } finally { + nativeTextHandler.setOverrideFont(null); + } + currentLocation.setLocation(currentLocation.getX() + advance, currentLocation.getY()); + } + private void updateLocationFromACI(AttributedCharacterIterator aci, Point2D loc) { + //Adjust position of span + Float xpos = (Float) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.X); + Float ypos = (Float) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.Y); + Float dxpos = (Float) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.DX); + Float dypos = (Float) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.DY); + if (xpos != null) { + loc.setLocation(xpos.doubleValue(), loc.getY()); + } + if (ypos != null) { + loc.setLocation(loc.getX(), ypos.doubleValue()); + } + if (dxpos != null) { + loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY()); + } + if (dypos != null) { + loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue()); } - } finally { - nativeTextHandler.setOverrideFont(null); } - loc.setLocation(loc.getX() + advance, loc.getY()); - return loc; } /** @@ -305,36 +200,9 @@ public abstract class AbstractFOPTextPainter implements TextPainter { for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) { sb.append(c); } - aci.first(); return sb.toString(); } - private void updateLocationFromACI( - AttributedCharacterIterator aci, - Point2D loc) { - //Adjust position of span - Float xpos = (Float)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.X); - Float ypos = (Float)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.Y); - Float dxpos = (Float)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.DX); - Float dypos = (Float)aci.getAttribute( - GVTAttributedCharacterIterator.TextAttribute.DY); - if (xpos != null) { - loc.setLocation(xpos.doubleValue(), loc.getY()); - } - if (ypos != null) { - loc.setLocation(loc.getX(), ypos.doubleValue()); - } - if (dxpos != null) { - loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY()); - } - if (dypos != null) { - loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue()); - } - } - private Font getFont(AttributedCharacterIterator aci) { Font[] fonts = ACIUtils.findFontsForBatikACI(aci, nativeTextHandler.getFontInfo()); return fonts == null ? null : fonts[0]; @@ -360,21 +228,6 @@ public abstract class AbstractFOPTextPainter implements TextPainter { return wordWidth / 1000f; } - private boolean hasUnsupportedGlyphs(String str, Font font) { - if (font == null) { - return true; - } - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) { - if (!font.hasChar(c)) { - return true; - } - } - } - return false; - } - /** * Get the outline shape of the text characters. * This uses the StrokingTextPainter to get the outline @@ -384,7 +237,7 @@ public abstract class AbstractFOPTextPainter implements TextPainter { * @return the outline shape of the text characters */ public Shape getOutline(TextNode node) { - return PROXY_PAINTER.getOutline(node); + return proxyTextPainter.getOutline(node); } /** @@ -399,7 +252,7 @@ public abstract class AbstractFOPTextPainter implements TextPainter { /* (todo) getBounds2D() is too slow * because it uses the StrokingTextPainter. We should implement this * method ourselves. */ - return PROXY_PAINTER.getBounds2D(node); + return proxyTextPainter.getBounds2D(node); } /** @@ -411,7 +264,7 @@ public abstract class AbstractFOPTextPainter implements TextPainter { * @return the bounds of the text */ public Rectangle2D getGeometryBounds(TextNode node) { - return PROXY_PAINTER.getGeometryBounds(node); + return proxyTextPainter.getGeometryBounds(node); } // Methods that have no purpose for PS diff --git a/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java b/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java index e04bf0d35..9b1606953 100644 --- a/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java +++ b/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java @@ -36,9 +36,9 @@ import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.impl.SimpleLog; -import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.util.DocumentFactory; +import org.apache.batik.gvt.font.FontFamilyResolver; import org.apache.batik.transcoder.ErrorHandler; import org.apache.batik.transcoder.SVGAbstractTranscoder; import org.apache.batik.transcoder.TranscoderException; @@ -56,6 +56,8 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; import org.apache.xmlgraphics.util.UnitConv; +import org.apache.fop.svg.font.FOPFontFamilyResolver; + /** * This is the common base class of all of FOP's transcoders. */ @@ -86,11 +88,6 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem /** The value to turn off text stroking. */ public static final Boolean VALUE_FORMAT_OFF = Boolean.FALSE; - /** - * The user agent dedicated to this Transcoder. - */ - protected UserAgent userAgent = createUserAgent(); - private Log logger; private EntityResolver resolver; private Configuration cfg = null; @@ -113,7 +110,7 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem * this method if you need non-default behaviour. * @return UserAgent the newly created user agent */ - protected UserAgent createUserAgent() { + protected FOPTranscoderUserAgent createUserAgent() { return new FOPTranscoderUserAgent(); } @@ -331,6 +328,8 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem */ protected class FOPTranscoderUserAgent extends SVGAbstractTranscoderUserAgent { + private FOPFontFamilyResolver fontFamilyResolver; + /** * Displays the specified error message using the {@link ErrorHandler}. * @param message the message to display @@ -386,6 +385,15 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem return "print"; } + public void setFontFamilyResolver(FOPFontFamilyResolver resolver) { + fontFamilyResolver = resolver; + } + + @Override + public FontFamilyResolver getFontFamilyResolver() { + return fontFamilyResolver; + } + } } diff --git a/src/java/org/apache/fop/svg/NativeTextPainter.java b/src/java/org/apache/fop/svg/NativeTextPainter.java index 4513e0101..200f6558b 100644 --- a/src/java/org/apache/fop/svg/NativeTextPainter.java +++ b/src/java/org/apache/fop/svg/NativeTextPainter.java @@ -19,7 +19,14 @@ package org.apache.fop.svg; +import java.awt.BasicStroke; +import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; import java.io.IOException; import java.text.AttributedCharacterIterator; import java.util.List; @@ -27,11 +34,17 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.batik.bridge.SVGGVTFont; +import org.apache.batik.gvt.font.FontFamilyResolver; +import org.apache.batik.gvt.font.GVTGlyphVector; import org.apache.batik.gvt.renderer.StrokingTextPainter; +import org.apache.batik.gvt.text.TextPaintInfo; import org.apache.batik.gvt.text.TextSpanLayout; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; +import org.apache.fop.svg.font.FOPGVTFont; import org.apache.fop.util.CharUtilities; /** @@ -41,17 +54,26 @@ import org.apache.fop.util.CharUtilities; public abstract class NativeTextPainter extends StrokingTextPainter { /** the logger for this class */ - protected Log log = LogFactory.getLog(NativeTextPainter.class); + protected static final Log log = LogFactory.getLog(NativeTextPainter.class); + + private static final boolean DEBUG = false; /** the font collection */ protected final FontInfo fontInfo; + protected final FontFamilyResolver fontFamilyResolver; + + protected Font font; + + protected TextPaintInfo tpi; + /** * Creates a new instance. * @param fontInfo the font collection */ public NativeTextPainter(FontInfo fontInfo) { this.fontInfo = fontInfo; + this.fontFamilyResolver = new FOPFontFamilyResolverImpl(fontInfo); } /** @@ -68,11 +90,93 @@ public abstract class NativeTextPainter extends StrokingTextPainter { * @param g2d the target Graphics2D instance * @throws IOException if an I/O error occurs while rendering the text */ - protected abstract void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException; + protected final void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException { + AttributedCharacterIterator runaci = textRun.getACI(); + runaci.first(); + + tpi = (TextPaintInfo) runaci.getAttribute(PAINT_INFO); + if (tpi == null || !tpi.visible) { + return; + } + if (tpi.composite != null) { + g2d.setComposite(tpi.composite); + } + + //------------------------------------ + TextSpanLayout layout = textRun.getLayout(); + logTextRun(runaci, layout); + runaci.first(); //Reset ACI + + GeneralPath debugShapes = null; + if (DEBUG) { + debugShapes = new GeneralPath(); + } + + preparePainting(g2d); + + GVTGlyphVector gv = layout.getGlyphVector(); + if (!(gv.getFont() instanceof FOPGVTFont)) { + assert gv.getFont() == null || gv.getFont() instanceof SVGGVTFont; + //Draw using Java2D when no native fonts are available + textRun.getLayout().draw(g2d); + return; + } + font = ((FOPGVTFont) gv.getFont()).getFont(); + + saveGraphicsState(); + setInitialTransform(g2d.getTransform()); + clip(g2d.getClip()); + beginTextObject(); + + AffineTransform localTransform = new AffineTransform(); + Point2D prevPos = null; + AffineTransform prevGlyphTransform = null; + for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) { + if (!gv.isGlyphVisible(index)) { + continue; + } + Point2D glyphPos = gv.getGlyphPosition(index); + + AffineTransform glyphTransform = gv.getGlyphTransform(index); + if (log.isTraceEnabled()) { + log.trace("pos " + glyphPos + ", transform " + glyphTransform); + } + if (DEBUG) { + Shape sh = gv.getGlyphLogicalBounds(index); + if (sh == null) { + sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2); + } + debugShapes.append(sh, false); + } + + //Exact position of the glyph + localTransform.setToIdentity(); + localTransform.translate(glyphPos.getX(), glyphPos.getY()); + if (glyphTransform != null) { + localTransform.concatenate(glyphTransform); + } + localTransform.scale(1, -1); + + positionGlyph(prevPos, glyphPos, glyphTransform != null || prevGlyphTransform != null); + char glyph = (char) gv.getGlyphCode(index); + //Update last position + prevPos = glyphPos; + prevGlyphTransform = glyphTransform; + + writeGlyph(glyph, localTransform); + } + endTextObject(); + restoreGraphicsState(); + if (DEBUG) { + //Paint debug shapes + g2d.setStroke(new BasicStroke(0)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.draw(debugShapes); + } + } - /** {@inheritDoc} */ @Override - protected void paintTextRuns(List textRuns, Graphics2D g2d) { + protected void paintTextRuns(@SuppressWarnings("rawtypes") List textRuns, Graphics2D g2d) { if (log.isTraceEnabled()) { log.trace("paintTextRuns: count = " + textRuns.size()); } @@ -81,7 +185,7 @@ public abstract class NativeTextPainter extends StrokingTextPainter { return; } for (int i = 0; i < textRuns.size(); i++) { - TextRun textRun = (TextRun)textRuns.get(i); + TextRun textRun = (TextRun) textRuns.get(i); try { paintTextRun(textRun, g2d); } catch (IOException ioe) { @@ -92,16 +196,6 @@ public abstract class NativeTextPainter extends StrokingTextPainter { } /** - * Finds an array of suitable fonts for a given AttributedCharacterIterator. - * @param aci the character iterator - * @return the array of fonts - */ - protected Font[] findFonts(AttributedCharacterIterator aci) { - Font[] fonts = ACIUtils.findFontsForBatikACI(aci, fontInfo); - return fonts; - } - - /** * Collects all characters from an {@link AttributedCharacterIterator}. * @param runaci the character iterator * @return the characters @@ -115,6 +209,25 @@ public abstract class NativeTextPainter extends StrokingTextPainter { return chars; } + protected abstract void preparePainting(Graphics2D g2d); + + protected abstract void saveGraphicsState() throws IOException; + + protected abstract void restoreGraphicsState() throws IOException; + + protected abstract void setInitialTransform(AffineTransform transform) throws IOException; + + protected abstract void clip(Shape clip) throws IOException; + + protected abstract void beginTextObject() throws IOException; + + protected abstract void endTextObject() throws IOException; + + protected abstract void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition); + + protected abstract void writeGlyph(char glyph, AffineTransform transform) throws IOException; + + /** * @param runaci an attributed character iterator * @param layout a text span layout @@ -155,5 +268,9 @@ public abstract class NativeTextPainter extends StrokingTextPainter { } } + @Override + protected FontFamilyResolver getFontFamilyResolver() { + return this.fontFamilyResolver; + } } diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java index ef376663f..c5fa9f04e 100644 --- a/src/java/org/apache/fop/svg/PDFTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFTextPainter.java @@ -19,25 +19,17 @@ package org.apache.fop.svg; -import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; -import java.text.AttributedCharacterIterator; -import org.apache.batik.gvt.font.GVTGlyphVector; import org.apache.batik.gvt.text.TextPaintInfo; -import org.apache.batik.gvt.text.TextSpanLayout; -import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.util.CharUtilities; /** * Renders the attributed character iterator of a {@link org.apache.batik.gvt.TextNode}. @@ -51,11 +43,19 @@ import org.apache.fop.util.CharUtilities; */ class PDFTextPainter extends NativeTextPainter { - private static final boolean DEBUG = false; + private PDFGraphics2D pdf; + + private PDFTextUtil textUtil; + + private double prevVisibleGlyphWidth; + + private boolean repositionNextGlyph; /** * Create a new PDF text painter with the given font information. + * * @param fi the font info + * @param fontFamilyResolver the Font Family Resolver */ public PDFTextPainter(FontInfo fi) { super(fi); @@ -67,29 +67,29 @@ class PDFTextPainter extends NativeTextPainter { return g2d instanceof PDFGraphics2D; } - /** {@inheritDoc} */ @Override - protected void paintTextRun(TextRun textRun, Graphics2D g2d) { - AttributedCharacterIterator runaci = textRun.getACI(); - runaci.first(); + protected void preparePainting(Graphics2D g2d) { + pdf = (PDFGraphics2D) g2d; + } - TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO); - if (tpi == null || !tpi.visible) { - return; - } - if ((tpi != null) && (tpi.composite != null)) { - g2d.setComposite(tpi.composite); - } + @Override + protected void saveGraphicsState() { + pdf.saveGraphicsState(); + } - //------------------------------------ - TextSpanLayout layout = textRun.getLayout(); - logTextRun(runaci, layout); - CharSequence chars = collectCharacters(runaci); - runaci.first(); //Reset ACI + @Override + protected void restoreGraphicsState() { + pdf.restoreGraphicsState(); + } - final PDFGraphics2D pdf = (PDFGraphics2D)g2d; + @Override + protected void setInitialTransform(AffineTransform transform) { + createTextUtil(); + textUtil.concatMatrix(transform); + } - PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) { + private void createTextUtil() { + textUtil = new PDFTextUtil(pdf.fontInfo) { protected void write(String code) { pdf.currentStream.write(code); } @@ -97,142 +97,39 @@ class PDFTextPainter extends NativeTextPainter { pdf.currentStream.append(code); } }; + } - if (DEBUG) { - log.debug("Text: " + chars); - pdf.currentStream.write("%Text: " + chars + "\n"); - } - - GeneralPath debugShapes = null; - if (DEBUG) { - debugShapes = new GeneralPath(); - } - - Font[] fonts = findFonts(runaci); - if (fonts == null || fonts.length == 0) { - //Draw using Java2D when no native fonts are available - textRun.getLayout().draw(g2d); - return; - } - - pdf.saveGraphicsState(); - textUtil.concatMatrix(g2d.getTransform()); - Shape imclip = g2d.getClip(); - pdf.writeClip(imclip); - - applyColorAndPaint(tpi, pdf); + @Override + protected void clip(Shape clip) { + pdf.writeClip(clip); + } + @Override + protected void beginTextObject() { + applyColorAndPaint(tpi); textUtil.beginTextObject(); - textUtil.setFonts(fonts); - boolean stroke = (tpi.strokePaint != null) - && (tpi.strokeStroke != null); + boolean stroke = (tpi.strokePaint != null) && (tpi.strokeStroke != null); textUtil.setTextRenderingMode(tpi.fillPaint != null, stroke, false); + } - AffineTransform localTransform = new AffineTransform(); - Point2D prevPos = null; - double prevVisibleCharWidth = 0.0; - GVTGlyphVector gv = layout.getGlyphVector(); - for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) { - char ch = chars.charAt(index); - boolean visibleChar = gv.isGlyphVisible(index) - || (CharUtilities.isAnySpace(ch) && !CharUtilities.isZeroWidthSpace(ch)); - logCharacter(ch, layout, index, visibleChar); - if (!visibleChar) { - continue; - } - Point2D glyphPos = gv.getGlyphPosition(index); - - AffineTransform glyphTransform = gv.getGlyphTransform(index); - //TODO Glyph transforms could be refined so not every char has to be painted - //with its own TJ command (stretch/squeeze case could be optimized) - if (log.isTraceEnabled()) { - log.trace("pos " + glyphPos + ", transform " + glyphTransform); - } - if (DEBUG) { - Shape sh = gv.getGlyphLogicalBounds(index); - if (sh == null) { - sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2); - } - debugShapes.append(sh, false); - } - - //Exact position of the glyph - localTransform.setToIdentity(); - localTransform.translate(glyphPos.getX(), glyphPos.getY()); - if (glyphTransform != null) { - localTransform.concatenate(glyphTransform); - } - localTransform.scale(1, -1); - - boolean yPosChanged = (prevPos == null - || prevPos.getY() != glyphPos.getY() - || glyphTransform != null); - if (yPosChanged) { - if (index > 0) { - textUtil.writeTJ(); - textUtil.writeTextMatrix(localTransform); - } - } else { - double xdiff = glyphPos.getX() - prevPos.getX(); - //Width of previous character - Font font = textUtil.getCurrentFont(); - double cw = prevVisibleCharWidth; - double effxdiff = (1000 * xdiff) - cw; - if (effxdiff != 0) { - double adjust = (-effxdiff / font.getFontSize()); - textUtil.adjustGlyphTJ(adjust * 1000); - } - if (log.isTraceEnabled()) { - log.trace("==> x diff: " + xdiff + ", " + effxdiff - + ", charWidth: " + cw); - } - } - Font f = textUtil.selectFontForChar(ch); - char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch); - char mappedChar = f.mapChar(paintChar); - boolean encodingChanging = false; // used for single byte - if (!textUtil.isMultiByteFont(f.getFontName())) { - int encoding = mappedChar / 256; - mappedChar = (char) (mappedChar % 256); - if (textUtil.getCurrentEncoding() != encoding) { - textUtil.setCurrentEncoding(encoding); - encodingChanging = true; - } - } - if (f != textUtil.getCurrentFont() || encodingChanging) { - textUtil.writeTJ(); - textUtil.setCurrentFont(f); - textUtil.writeTf(f); - textUtil.writeTextMatrix(localTransform); - } - textUtil.writeTJMappedChar(mappedChar); - - //Update last position - prevPos = glyphPos; - prevVisibleCharWidth = textUtil.getCurrentFont().getCharWidth(chars.charAt(index)); - } + @Override + protected void endTextObject() { textUtil.writeTJ(); textUtil.endTextObject(); - pdf.restoreGraphicsState(); - if (DEBUG) { - g2d.setStroke(new BasicStroke(0)); - g2d.setColor(Color.LIGHT_GRAY); - g2d.draw(debugShapes); - } } - private void applyColorAndPaint(TextPaintInfo tpi, PDFGraphics2D pdf) { + private void applyColorAndPaint(TextPaintInfo tpi) { Paint fillPaint = tpi.fillPaint; Paint strokePaint = tpi.strokePaint; Stroke stroke = tpi.strokeStroke; int fillAlpha = PDFGraphics2D.OPAQUE; if (fillPaint instanceof Color) { - Color col = (Color)fillPaint; + Color col = (Color) fillPaint; pdf.applyColor(col, true); fillAlpha = col.getAlpha(); } if (strokePaint instanceof Color) { - Color col = (Color)strokePaint; + Color col = (Color) strokePaint; pdf.applyColor(col, false); } pdf.applyPaint(fillPaint, true); @@ -243,4 +140,46 @@ class PDFTextPainter extends NativeTextPainter { pdf.applyAlpha(fillAlpha, PDFGraphics2D.OPAQUE); } + @Override + protected void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition) { + // TODO Glyph transforms could be refined so not every char has to be painted + // with its own TJ command (stretch/squeeze case could be optimized) + repositionNextGlyph = (prevPos == null + || prevPos.getY() != glyphPos.getY() + || reposition); + if (!repositionNextGlyph) { + double xdiff = glyphPos.getX() - prevPos.getX(); + //Width of previous character + double cw = prevVisibleGlyphWidth; + double effxdiff = (1000 * xdiff) - cw; + if (effxdiff != 0) { + double adjust = (-effxdiff / font.getFontSize()); + textUtil.adjustGlyphTJ(adjust * 1000); + } + } + } + + @Override + protected void writeGlyph(char glyph, AffineTransform transform) { + prevVisibleGlyphWidth = font.getWidth(glyph); + boolean encodingChanging = false; // used for single byte + if (!textUtil.isMultiByteFont(font.getFontName())) { + int encoding = glyph / 256; + glyph = (char) (glyph % 256); + if (textUtil.getCurrentEncoding() != encoding) { + textUtil.setCurrentEncoding(encoding); + encodingChanging = true; + } + } + if (repositionNextGlyph || encodingChanging) { + textUtil.writeTJ(); + if (font != textUtil.getCurrentFont() || encodingChanging) { + textUtil.setCurrentFont(font); + textUtil.writeTf(font); + } + textUtil.writeTextMatrix(transform); + } + textUtil.writeTJMappedChar(glyph); + } + } diff --git a/src/java/org/apache/fop/svg/PDFTextUtil.java b/src/java/org/apache/fop/svg/PDFTextUtil.java index 8325dce1f..d525ecefc 100644 --- a/src/java/org/apache/fop/svg/PDFTextUtil.java +++ b/src/java/org/apache/fop/svg/PDFTextUtil.java @@ -30,7 +30,6 @@ import org.apache.fop.fonts.Typeface; public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil { private FontInfo fontInfo; - private Font[] fonts; private Font font; private int encoding; @@ -50,23 +49,6 @@ public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil { } /** - * Sets the current fonts for the text object. For every character, the suitable font will - * be selected. - * @param fonts the new fonts - */ - public void setFonts(Font[] fonts) { - this.fonts = fonts; - } - - /** - * Sets the current font for the text object. - * @param font the new font - */ - public void setFont(Font font) { - setFonts(new Font[] {font}); - } - - /** * Returns the current font in use. * @return the current font or null if no font is currently active. */ @@ -123,27 +105,4 @@ public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil { } } - /** - * Selects a font from the font list suitable to display the given character. - * @param ch the character - * @return the recommended Font to use - */ - public Font selectFontForChar(char ch) { - for (int i = 0, c = fonts.length; i < c; i++) { - if (fonts[i].hasChar(ch)) { - return fonts[i]; - } - } - return fonts[0]; //TODO Maybe fall back to painting with shapes - } - - /** - * Writes a char to the "TJ-Buffer". - * @param ch the unmapped character - */ - public void writeTJChar(char ch) { - char mappedChar = font.mapChar(ch); - writeTJMappedChar(mappedChar); - } - } diff --git a/src/java/org/apache/fop/svg/PDFTranscoder.java b/src/java/org/apache/fop/svg/PDFTranscoder.java index 9f0345657..1a3f154cb 100644 --- a/src/java/org/apache/fop/svg/PDFTranscoder.java +++ b/src/java/org/apache/fop/svg/PDFTranscoder.java @@ -31,7 +31,6 @@ import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; -import org.apache.batik.bridge.UserAgent; import org.apache.batik.ext.awt.RenderingHintsKeyExt; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; @@ -39,6 +38,7 @@ import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.fop.Version; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; /** * <p>This class enables to transcode an input to a PDF document.</p> @@ -88,7 +88,7 @@ public class PDFTranscoder extends AbstractFOPTranscoder { /** * {@inheritDoc} */ - protected UserAgent createUserAgent() { + protected FOPTranscoderUserAgent createUserAgent() { return new AbstractFOPTranscoder.FOPTranscoderUserAgent() { // The PDF stuff wants everything at 72dpi public float getPixelUnitToMillimeter() { @@ -131,6 +131,8 @@ public class PDFTranscoder extends AbstractFOPTranscoder { } else { graphics.setupDefaultFontInfo(); } + ((FOPTranscoderUserAgent) userAgent).setFontFamilyResolver( + new FOPFontFamilyResolverImpl(graphics.getFontInfo())); } catch (Exception e) { throw new TranscoderException( "Error while setting up PDFDocumentGraphics2D", e); diff --git a/src/java/org/apache/fop/svg/SVGUserAgent.java b/src/java/org/apache/fop/svg/SVGUserAgent.java index d43552289..a265b4fef 100644 --- a/src/java/org/apache/fop/svg/SVGUserAgent.java +++ b/src/java/org/apache/fop/svg/SVGUserAgent.java @@ -21,6 +21,8 @@ package org.apache.fop.svg; import java.awt.geom.AffineTransform; +import org.apache.batik.gvt.font.FontFamilyResolver; + import org.apache.fop.apps.FOUserAgent; /** @@ -34,10 +36,11 @@ public class SVGUserAgent extends SimpleSVGUserAgent { /** * Creates a new SVGUserAgent. * @param foUserAgent the FO user agent to associate with this SVG user agent + * @param fontFamilyResolver the font family resolver * @param at the current transform */ - public SVGUserAgent(FOUserAgent foUserAgent, AffineTransform at) { - super(foUserAgent.getSourcePixelUnitToMillimeter(), at); + public SVGUserAgent(FOUserAgent foUserAgent, FontFamilyResolver fontFamilyResolver, AffineTransform at) { + super(foUserAgent.getSourcePixelUnitToMillimeter(), at, fontFamilyResolver); this.eventProducer = SVGEventProducer.Provider.get(foUserAgent.getEventBroadcaster()); } @@ -45,8 +48,8 @@ public class SVGUserAgent extends SimpleSVGUserAgent { * Creates a new SVGUserAgent. * @param foUserAgent the FO user agent to associate with this SVG user agent */ - public SVGUserAgent(FOUserAgent foUserAgent) { - this(foUserAgent, new AffineTransform()); + public SVGUserAgent(FOUserAgent foUserAgent, FontFamilyResolver fontFamilyResolver) { + this(foUserAgent, fontFamilyResolver, new AffineTransform()); } /** diff --git a/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java b/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java index 2b27945a4..42a18b17c 100644 --- a/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java +++ b/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java @@ -26,6 +26,7 @@ import java.awt.geom.Dimension2D; import javax.xml.parsers.SAXParserFactory; import org.apache.batik.bridge.UserAgentAdapter; +import org.apache.batik.gvt.font.FontFamilyResolver; /** * A simple SVG user agent. @@ -35,14 +36,18 @@ import org.apache.batik.bridge.UserAgentAdapter; public class SimpleSVGUserAgent extends UserAgentAdapter { private AffineTransform currentTransform = null; + private float pixelUnitToMillimeter = 0.0f; + private final FontFamilyResolver fontFamilyResolver; + /** * Creates a new user agent. * @param pixelUnitToMM the pixel to millimeter conversion factor currently in effect * @param at the current transform */ - public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at) { + public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at, FontFamilyResolver fontFamilyResolver) { + this.fontFamilyResolver = fontFamilyResolver; pixelUnitToMillimeter = pixelUnitToMM; currentTransform = at; } @@ -122,5 +127,10 @@ public class SimpleSVGUserAgent extends UserAgentAdapter { return new Dimension(100, 100); } + @Override + public FontFamilyResolver getFontFamilyResolver() { + return fontFamilyResolver; + } + } diff --git a/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java b/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java new file mode 100644 index 000000000..313a6a74b --- /dev/null +++ b/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java @@ -0,0 +1,70 @@ +/* + * 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.svg.font; + +import java.util.Arrays; +import java.util.List; + +import org.apache.batik.gvt.font.FontFamilyResolver; +import org.apache.batik.gvt.font.GVTFontFamily; + +public class AggregatingFontFamilyResolver implements FontFamilyResolver { + + private final List<FontFamilyResolver> resolvers; + + public AggregatingFontFamilyResolver(FontFamilyResolver... resolvers) { + this.resolvers = Arrays.<FontFamilyResolver>asList(resolvers); + } + + public String lookup(String familyName) { + for (FontFamilyResolver resolver : resolvers) { + String lookup = resolver.lookup(familyName); + if (lookup != null) { + return lookup; + } + } + return null; + } + + public GVTFontFamily resolve(String familyName) { + for (FontFamilyResolver resolver : resolvers) { + GVTFontFamily family = resolver.resolve(familyName); + if (family != null) { + return family; + } + } + return null; + } + + public GVTFontFamily getDefault() { + return resolve("any"); + } + + public GVTFontFamily getFamilyThatCanDisplay(char c) { + for (FontFamilyResolver resolver : resolvers) { + GVTFontFamily family = resolver.getFamilyThatCanDisplay(c); + if (family != null) { + return family; + } + } + return null; + } + +} diff --git a/src/java/org/apache/fop/svg/font/FOPFontFamilyResolver.java b/src/java/org/apache/fop/svg/font/FOPFontFamilyResolver.java new file mode 100644 index 000000000..7af5f0b4f --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FOPFontFamilyResolver.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.svg.font; + +import org.apache.batik.gvt.font.FontFamilyResolver; + +public interface FOPFontFamilyResolver extends FontFamilyResolver { + + FOPGVTFontFamily resolve(String familyName); + + FOPGVTFontFamily getDefault(); + + FOPGVTFontFamily getFamilyThatCanDisplay(char c); +} diff --git a/src/java/org/apache/fop/svg/font/FOPFontFamilyResolverImpl.java b/src/java/org/apache/fop/svg/font/FOPFontFamilyResolverImpl.java new file mode 100644 index 000000000..a9a631691 --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FOPFontFamilyResolverImpl.java @@ -0,0 +1,67 @@ +/* + * 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.svg.font; + +import java.util.Map; + +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.Typeface; + +public class FOPFontFamilyResolverImpl implements FOPFontFamilyResolver { + + private final FontInfo fontInfo; + + public FOPFontFamilyResolverImpl(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + public String lookup(String familyName) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public FOPGVTFontFamily resolve(String familyName) { + FOPGVTFontFamily gvtFontFamily = null; + FontTriplet triplet = fontInfo.fontLookup(familyName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + if (fontInfo.hasFont(familyName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)) { + gvtFontFamily = new FOPGVTFontFamily(fontInfo, familyName, triplet); + } + return gvtFontFamily; + } + + public FOPGVTFontFamily getDefault() { + return resolve("any"); + } + + public FOPGVTFontFamily getFamilyThatCanDisplay(char c) { + Map<String, Typeface> fonts = fontInfo.getFonts(); + for (Typeface font : fonts.values()) { + if (font.hasChar(c)) { + String fontFamily = font.getFamilyNames().iterator().next(); + return new FOPGVTFontFamily(fontInfo, fontFamily, + new FontTriplet(fontFamily, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + } + } + return null; + } + +} diff --git a/src/java/org/apache/fop/svg/font/FOPGVTFont.java b/src/java/org/apache/fop/svg/font/FOPGVTFont.java new file mode 100644 index 000000000..c55e2fa8b --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FOPGVTFont.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.svg.font; + +import java.awt.font.FontRenderContext; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; + +import org.apache.batik.gvt.font.GVTFont; +import org.apache.batik.gvt.font.GVTFontFamily; +import org.apache.batik.gvt.font.GVTGlyphVector; +import org.apache.batik.gvt.font.GVTLineMetrics; + +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontMetrics; + +public class FOPGVTFont implements GVTFont { + + private final Font font; + + private final GVTFontFamily fontFamily; + + public FOPGVTFont(Font font, GVTFontFamily fontFamily) { + this.font = font; + this.fontFamily = fontFamily; + } + + public Font getFont() { + return font; + } + + public boolean canDisplay(char c) { + return font.hasChar(c); + } + + public int canDisplayUpTo(char[] text, int start, int limit) { + for (int i = start; i < limit; i++) { + if (!canDisplay(text[i])) { + return i; + } + } + return -1; + } + + + public int canDisplayUpTo(CharacterIterator iter, int start, int limit) { + for (char c = iter.setIndex(start); iter.getIndex() < limit; c = iter.next()) { + if (!canDisplay(c)) { + return iter.getIndex(); + } + } + return -1; + } + + public int canDisplayUpTo(String str) { + for (int i = 0; i < str.length(); i++) { + if (!canDisplay(str.charAt(i))) { + return i; + } + } + return -1; + } + + public GVTGlyphVector createGlyphVector(FontRenderContext frc, char[] chars) { + return createGlyphVector(frc, new String(chars)); + } + + public GVTGlyphVector createGlyphVector(FontRenderContext frc, CharacterIterator ci) { + // TODO Batik does manual glyph shaping for Arabic. Replace with complex scripts implementation + return new FOPGVTGlyphVector(this, ci, frc); + } + + public GVTGlyphVector createGlyphVector(FontRenderContext frc, + int[] glyphCodes, + CharacterIterator ci) { + throw new UnsupportedOperationException("Not implemented"); + } + + public GVTGlyphVector createGlyphVector(FontRenderContext frc, String str) { + StringCharacterIterator sci = new StringCharacterIterator(str); + return createGlyphVector(frc, sci); + } + + public FOPGVTFont deriveFont(float size) { + throw new UnsupportedOperationException("Not implemented"); + } + + public String getFamilyName() { + return fontFamily.getFamilyName(); + } + + public GVTLineMetrics getLineMetrics(char[] chars, int beginIndex, int limit, FontRenderContext frc) { + return getLineMetrics(limit - beginIndex); + } + + GVTLineMetrics getLineMetrics(int numChars) { + numChars = numChars < 0 ? 0 : numChars; + FontMetrics metrics = font.getFontMetrics(); + int size = font.getFontSize(); + return new GVTLineMetrics( + metrics.getCapHeight(size) / 1000000f, + java.awt.Font.ROMAN_BASELINE, // Not actually used by Batik + null, // Not actually used by Batik + -metrics.getDescender(size) / 1000000f, + 0, // Not actually used by Batik + 0, // Not actually used by Batik + numChars, + -metrics.getStrikeoutPosition(size) / 1000000f, + metrics.getStrikeoutThickness(size) / 1000000f, + -metrics.getUnderlinePosition(size) / 1000000f, + metrics.getUnderlineThickness(size) / 1000000f, + -metrics.getCapHeight(size) / 1000000f, // Because this is what Batik does in GVTLineMetrics + metrics.getUnderlineThickness(size) / 1000000f); + } + + public GVTLineMetrics getLineMetrics(CharacterIterator ci, int beginIndex, int limit, + FontRenderContext frc) { + return getLineMetrics(limit - beginIndex); + } + + public GVTLineMetrics getLineMetrics(String str, FontRenderContext frc) { + return getLineMetrics(str.length()); + } + + public GVTLineMetrics getLineMetrics(String str, int beginIndex, int limit, FontRenderContext frc) { + return getLineMetrics(limit - beginIndex); + } + + public float getSize() { + return font.getFontSize() / 1000f; + } + + public float getVKern(int glyphCode1, int glyphCode2) { + return 0; + } + + public float getHKern(int glyphCode1, int glyphCode2) { + // TODO Cannot be implemented until getKernValue takes glyph indices instead of character codes + return 0; + } + +} diff --git a/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java b/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java new file mode 100644 index 000000000..036b560a0 --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.svg.font; + +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +import org.apache.batik.gvt.font.GVTFontFace; +import org.apache.batik.gvt.font.GVTFontFamily; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.svg.ACIUtils; + +public class FOPGVTFontFamily implements GVTFontFamily { + + private final FontInfo fontInfo; + + private final FontTriplet fontTriplet; + + private final String familyName; + + public FOPGVTFontFamily(FontInfo fontInfo, String familyName, FontTriplet triplet) { + this.fontInfo = fontInfo; + this.fontTriplet = triplet; + this.familyName = familyName; + } + + public String getFamilyName() { + return familyName; + } + + public GVTFontFace getFontFace() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public FOPGVTFont deriveFont(float size, AttributedCharacterIterator aci) { + return deriveFont(size, aci.getAttributes()); + } + + public FOPGVTFont deriveFont(float size, @SuppressWarnings("rawtypes") Map attrs) { + Float fontWeight = (Float) attrs.get(TextAttribute.WEIGHT); + int weight = fontWeight == null ? fontTriplet.getWeight() : ACIUtils.toCSSWeight(fontWeight); + Float fontStyle = (Float) attrs.get(TextAttribute.POSTURE); + String style = fontStyle == null ? fontTriplet.getStyle() : ACIUtils.toStyle(fontStyle); + FontTriplet triplet = fontInfo.fontLookup(fontTriplet.getName(), style, weight); + return new FOPGVTFont(fontInfo.getFontInstance(triplet, (int) (size * 1000)), this); + } + + public boolean isComplex() { + return false; + } + +} diff --git a/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java b/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java new file mode 100644 index 000000000..3567bb508 --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java @@ -0,0 +1,339 @@ +/* + * 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.svg.font; + +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphJustificationInfo; +import java.awt.font.GlyphMetrics; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.text.AttributedCharacterIterator; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Arrays; + +import org.apache.batik.gvt.font.GVTFont; +import org.apache.batik.gvt.font.GVTGlyphMetrics; +import org.apache.batik.gvt.font.GVTGlyphVector; +import org.apache.batik.gvt.font.GVTLineMetrics; + +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontMetrics; +import org.apache.fop.fonts.GlyphMapping; +import org.apache.fop.fonts.TextFragment; +import org.apache.fop.traits.MinOptMax; + +class FOPGVTGlyphVector implements GVTGlyphVector { + + private final CharacterIterator charIter; + + private final FOPGVTFont font; + + private final int fontSize; + + private final FontMetrics fontMetrics; + + private final FontRenderContext frc; + + private int[] glyphs; + + private float[] positions; + + private Rectangle2D[] boundingBoxes; + + private GeneralPath outline; + + private AffineTransform[] glyphTransforms; + + private boolean[] glyphVisibilities; + + private Rectangle2D logicalBounds; + + FOPGVTGlyphVector(FOPGVTFont font, final CharacterIterator iter, FontRenderContext frc) { + this.charIter = iter; + this.font = font; + Font f = font.getFont(); + this.fontSize = f.getFontSize(); + this.fontMetrics = f.getFontMetrics(); + this.frc = frc; + } + + public void performDefaultLayout() { + Font f = font.getFont(); + TextFragment text = new SVGTextFragment(charIter); + MinOptMax letterSpaceIPD = MinOptMax.ZERO; + MinOptMax[] letterSpaceAdjustments = new MinOptMax[charIter.getEndIndex() - charIter.getBeginIndex()]; + GlyphMapping mapping = GlyphMapping.doGlyphMapping(text, charIter.getBeginIndex(), charIter.getEndIndex(), + f, letterSpaceIPD, letterSpaceAdjustments, '\0', '\0', false, 0 /* TODO */); + glyphs = buildGlyphs(f, mapping.mapping != null ? new StringCharacterIterator(mapping.mapping) : charIter); + buildGlyphPositions(mapping, letterSpaceAdjustments); + this.glyphVisibilities = new boolean[this.glyphs.length]; + Arrays.fill(glyphVisibilities, true); + this.glyphTransforms = new AffineTransform[this.glyphs.length]; + } + + private static class SVGTextFragment implements TextFragment { + + private final CharacterIterator charIter; + + SVGTextFragment(CharacterIterator charIter) { + this.charIter = charIter; + } + + public CharSequence subSequence(int startIndex, int endIndex) { + StringBuilder sb = new StringBuilder(); + for (char c = charIter.first(); c != CharacterIterator.DONE; c = charIter.next()) { + sb.append(c); + } + return sb.toString(); + } + + public String getScript() { + return "DFLT"; // TODO pass on script value from SVG + } + + public String getLanguage() { + return "dflt"; // TODO pass on language value from SVG + } + + public char charAt(int index) { + return charIter.setIndex(index - charIter.getBeginIndex()); + } + } + + private int[] buildGlyphs(Font font, final CharacterIterator charIter) { + int[] glyphs = new int[charIter.getEndIndex() - charIter.getBeginIndex()]; + int index = 0; + for (char c = charIter.first(); c != CharacterIterator.DONE; c = charIter.next()) { + glyphs[index] = font.mapChar(c); + index++; + } + return glyphs; + } + + private void buildGlyphPositions(GlyphMapping ai, MinOptMax[] letterSpaceAdjustments) { + positions = new float[2 * glyphs.length + 2]; + if (ai.gposAdjustments != null) { + assert ai.gposAdjustments.length == glyphs.length; + for (int glyphIndex = 0; glyphIndex < glyphs.length; glyphIndex++) { + int n = 2 * glyphIndex; + if (ai.gposAdjustments[glyphIndex] != null) { + for (int p = 0; p < 4; p++) { + positions[n + p] += ai.gposAdjustments[glyphIndex][p] / 1000f; + } + } + positions[n + 2] += positions[n] + getGlyphWidth(glyphIndex); + } + } else { + for (int i = 0, n = 2; i < glyphs.length; i++, n += 2) { + int kern = i < glyphs.length - 1 && letterSpaceAdjustments[i + 1] != null + ? letterSpaceAdjustments[i + 1].getOpt() + : 0; + positions[n] = positions[n - 2] + getGlyphWidth(i) + kern / 1000f; + positions[n + 1] = 0; + } + } + } + + private float getGlyphWidth(int index) { + return fontMetrics.getWidth(glyphs[index], fontSize) / 1000000f; + } + + public GVTFont getFont() { + return font; + } + + public FontRenderContext getFontRenderContext() { + return frc; + } + + public int getGlyphCode(int glyphIndex) { + return glyphs[glyphIndex]; + } + + public int[] getGlyphCodes(int beginGlyphIndex, int numEntries, + int[] codeReturn) { + if (codeReturn == null) { + codeReturn = new int[numEntries]; + } + System.arraycopy(glyphs, beginGlyphIndex, codeReturn, 0, numEntries); + return codeReturn; + } + + public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public Shape getGlyphLogicalBounds(int glyphIndex) { + GVTGlyphMetrics metrics = getGlyphMetrics(glyphIndex); + Point2D pos = getGlyphPosition(glyphIndex); + GVTLineMetrics fontMetrics = font.getLineMetrics(0); + Rectangle2D bounds = new Rectangle2D.Float(0, -fontMetrics.getDescent(), metrics.getHorizontalAdvance(), + fontMetrics.getAscent() + fontMetrics.getDescent()); + AffineTransform t = AffineTransform.getTranslateInstance(pos.getX(), pos.getY()); + AffineTransform transf = getGlyphTransform(glyphIndex); + if (transf != null) { + t.concatenate(transf); + } + t.scale(1, -1); // Translate from glyph coordinate system to user + return t.createTransformedShape(bounds); + } + + public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) { + Rectangle2D bbox = getBoundingBoxes()[glyphIndex]; + return new GVTGlyphMetrics(positions[2 * (glyphIndex + 1)] - positions[2 * glyphIndex], + (fontMetrics.getAscender(fontSize) - fontMetrics.getDescender(fontSize)) / 1000000f, + bbox, GlyphMetrics.STANDARD); + } + + public Shape getGlyphOutline(int glyphIndex) { + Shape glyphBox = getBoundingBoxes()[glyphIndex]; + AffineTransform tr = AffineTransform.getTranslateInstance(positions[glyphIndex * 2], + positions[glyphIndex * 2 + 1]); + AffineTransform glyphTransform = getGlyphTransform(glyphIndex); + if (glyphTransform != null) { + tr.concatenate(glyphTransform); + } + return tr.createTransformedShape(glyphBox); + } + + public Rectangle2D getGlyphCellBounds(int glyphIndex) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public Point2D getGlyphPosition(int glyphIndex) { + int positionIndex = glyphIndex * 2; + return new Point2D.Float(positions[positionIndex], positions[positionIndex + 1]); + } + + public float[] getGlyphPositions(int beginGlyphIndex, int numEntries, float[] positionReturn) { + if (positionReturn == null) { + positionReturn = new float[numEntries * 2]; + } + System.arraycopy(positions, beginGlyphIndex * 2, positionReturn, 0, numEntries * 2); + return positionReturn; + } + + public AffineTransform getGlyphTransform(int glyphIndex) { + return glyphTransforms[glyphIndex]; + } + + public Shape getGlyphVisualBounds(int glyphIndex) { + Rectangle2D bbox = getBoundingBoxes()[glyphIndex]; + Point2D pos = getGlyphPosition(glyphIndex); + AffineTransform t = AffineTransform.getTranslateInstance(pos.getX(), pos.getY()); + AffineTransform transf = getGlyphTransform(glyphIndex); + if (transf != null) { + t.concatenate(transf); + } + return t.createTransformedShape(bbox); + } + + public Rectangle2D getLogicalBounds() { + if (logicalBounds == null) { + GeneralPath logicalBoundsPath = new GeneralPath(); + for (int i = 0; i < getNumGlyphs(); i++) { + Shape glyphLogicalBounds = getGlyphLogicalBounds(i); + logicalBoundsPath.append(glyphLogicalBounds, false); + } + logicalBounds = logicalBoundsPath.getBounds2D(); + } + return logicalBounds; + } + + public int getNumGlyphs() { + return glyphs.length; + } + + public Shape getOutline() { + if (outline == null) { + outline = new GeneralPath(); + for (int i = 0; i < glyphs.length; i++) { + outline.append(getGlyphOutline(i), false); + } + } + return outline; + } + + public Shape getOutline(float x, float y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public Rectangle2D getGeometricBounds() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + public Rectangle2D getBounds2D(AttributedCharacterIterator aci) { + return getOutline().getBounds2D(); + } + + public void setGlyphPosition(int glyphIndex, Point2D newPos) { + int idx = glyphIndex * 2; + positions[idx] = (float) newPos.getX(); + positions[idx + 1] = (float) newPos.getY(); + } + + public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { + glyphTransforms[glyphIndex] = newTX; + } + + public void setGlyphVisible(int glyphIndex, boolean visible) { + glyphVisibilities[glyphIndex] = visible; + } + + public boolean isGlyphVisible(int glyphIndex) { + return glyphVisibilities[glyphIndex]; + } + + public int getCharacterCount(int startGlyphIndex, int endGlyphIndex) { + // TODO Not that simple if complex scripts are involved + return endGlyphIndex - startGlyphIndex + 1; + } + + public void draw(Graphics2D graphics2d, AttributedCharacterIterator aci) { + // NOP + } + + private Rectangle2D[] getBoundingBoxes() { + if (boundingBoxes == null) { + buildBoundingBoxes(); + } + return boundingBoxes; + } + + private void buildBoundingBoxes() { + boundingBoxes = new Rectangle2D[glyphs.length]; + for (int i = 0; i < glyphs.length; i++) { + Rectangle bbox = fontMetrics.getBoundingBox(glyphs[i], fontSize); + boundingBoxes[i] = new Rectangle2D.Float(bbox.x / 1000000f, -(bbox.y + bbox.height) / 1000000f, + bbox.width / 1000000f, bbox.height / 1000000f); + } + } + +} diff --git a/src/java/org/apache/fop/svg/font/FilteringFontFamilyResolver.java b/src/java/org/apache/fop/svg/font/FilteringFontFamilyResolver.java new file mode 100644 index 000000000..319d6b2b8 --- /dev/null +++ b/src/java/org/apache/fop/svg/font/FilteringFontFamilyResolver.java @@ -0,0 +1,47 @@ +/* + * 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.svg.font; + + +public class FilteringFontFamilyResolver implements FOPFontFamilyResolver { + + private final FOPFontFamilyResolver delegate; + + public FilteringFontFamilyResolver(FOPFontFamilyResolver delegate) { + this.delegate = delegate; + } + + public String lookup(String familyName) { + return delegate.lookup(familyName); + } + + public FOPGVTFontFamily resolve(String familyName) { + return delegate.resolve(familyName); + } + + public FOPGVTFontFamily getDefault() { + return delegate.getDefault(); + } + + public FOPGVTFontFamily getFamilyThatCanDisplay(char c) { + return delegate.getFamilyThatCanDisplay(c); + } + +} diff --git a/test/java/org/apache/fop/afp/fonts/IntegerKeyStoreTestCase.java b/test/java/org/apache/fop/afp/fonts/IntegerKeyStoreTestCase.java new file mode 100644 index 000000000..96c0618a7 --- /dev/null +++ b/test/java/org/apache/fop/afp/fonts/IntegerKeyStoreTestCase.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.afp.fonts; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +public class IntegerKeyStoreTestCase { + + @Test + public void getAndPut() { + IntegerKeyStore<Integer> sut = new IntegerKeyStore<Integer>(); + assertNull(sut.get(0)); + sut.put(0, 0); + assertEquals(Integer.valueOf(0), sut.get(0)); + sut.put(0, 1); + assertEquals(Integer.valueOf(1), sut.get(0)); + sut.put(0, null); + assertNull(sut.get(0)); + try { + sut.put(-1, 0); + fail("Negative index"); + } catch (IndexOutOfBoundsException e) { + // As expected + } + } + +} diff --git a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java index 20212b002..4c89d00da 100644 --- a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java +++ b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java @@ -24,11 +24,11 @@ import java.io.File; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + import org.apache.fop.apps.io.InternalResourceResolver; import org.apache.fop.apps.io.ResourceResolverFactory; -import static org.junit.Assert.assertEquals; - /** * */ @@ -58,4 +58,17 @@ public class DejaVuLGCSerifTestCase { public void testFontName() { assertEquals("DejaVuLGCSerif", font.getFontName()); } + + @Test + public void testUnderline() { + assertEquals(-840, font.getUnderlinePosition(10)); + assertEquals(430, font.getUnderlineThickness(10)); + } + + @Test + public void testStrikeout() { + assertEquals(2340, font.getStrikeoutPosition(10)); + assertEquals(490, font.getStrikeoutThickness(10)); + } + } diff --git a/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java b/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java index 509ee56f4..b4271ba60 100644 --- a/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java +++ b/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java @@ -52,13 +52,4 @@ public class FontEventProcessingTestCase { MimeConstants.MIME_PDF); } - @Test - public void testSVGFontStrokedAsShapes() throws Exception { - // svg-fonts.fo embeds two fonts; one that is present in the system and the other is not; the - // missing font is stroked as shapes while the fonts that exists is stroked as text - InputStream inStream = getClass().getResourceAsStream("svg-fonts.fo"); - eventsTests.doTest(inStream, null, FontEventProducer.class.getName() + ".svgTextStrokedAsShapes", - MimeConstants.MIME_PDF); - } - } diff --git a/test/java/org/apache/fop/fonts/svg-fonts.fo b/test/java/org/apache/fop/fonts/svg-fonts.fo deleted file mode 100644 index 0c5f3f599..000000000 --- a/test/java/org/apache/fop/fonts/svg-fonts.fo +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> - <fo:layout-master-set> - <fo:simple-page-master master-name="page"> - <fo:region-body /> - </fo:simple-page-master> - </fo:layout-master-set> - <fo:page-sequence master-reference="page"> - <fo:flow flow-name="xsl-region-body"> - <fo:block> - <fo:instream-foreign-object> - <svg:svg width="250" height="50"> - <svg:font horiz-adv-x="1000"> - <svg:font-face font-family="Missing" units-per-em="1000" underline-position="-100" - underline-thickness="50" /> - <svg:glyph unicode="A" horiz-adv-x="686" d="M162,186l362,0l78,-186l84,0l-308,708l-70,0l-308,-708l84,0M343,624l153,-372l-307,0z" /> - <svg:glyph unicode="C" horiz-adv-x="704" d="M620,154C567,72 491,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C492,660 571,613 599,567l63,47C600,693 505,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C534,-18 632,39 679,112z" /> - <svg:glyph unicode="F" horiz-adv-x="556" d="M168,335l330,0l0,66l-330,0l0,241l355,0l0,66l-427,0l0,-708l72,0z" /> - <svg:glyph unicode="G" horiz-adv-x="778" d="M673,631C610,694 529,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C503,-18 606,7 685,54l0,347l-241,0l0,-66l169,0l0,-237C560,68 490,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C504,660 571,629 619,578z" /> - </svg:font> - <svg:font horiz-adv-x="1000"> - <!-- this is not Helvetica but it is here to increase coverage and show the code takes expected path --> - <svg:font-face font-family="Helvetica" units-per-em="1000" underline-position="-100" - underline-thickness="50" /> - <svg:glyph unicode="A" horiz-adv-x="686" d="M162,186l362,0l78,-186l84,0l-308,708l-70,0l-308,-708l84,0M343,624l153,-372l-307,0z" /> - <svg:glyph unicode="C" horiz-adv-x="704" d="M620,154C567,72 491,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C492,660 571,613 599,567l63,47C600,693 505,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C534,-18 632,39 679,112z" /> - <svg:glyph unicode="F" horiz-adv-x="556" d="M168,335l330,0l0,66l-330,0l0,241l355,0l0,66l-427,0l0,-708l72,0z" /> - <svg:glyph unicode="G" horiz-adv-x="778" d="M673,631C610,694 529,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C503,-18 606,7 685,54l0,347l-241,0l0,-66l169,0l0,-237C560,68 490,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C504,660 571,629 619,578z" /> - </svg:font> - <svg:text x="20" y="20" font-family="Missing" font-size="12">ACFG</svg:text> - <svg:text x="20" y="40" font-family="Helvetica" font-size="12">ACFG</svg:text> - </svg:svg> - </fo:instream-foreign-object> - </fo:block> - </fo:flow> - </fo:page-sequence> -</fo:root> diff --git a/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java index e04347032..2d583dd3e 100644 --- a/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java +++ b/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java @@ -26,12 +26,12 @@ import java.util.Map; import org.junit.Test; -import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; + /** * Class for testing org.apache.fop.fonts.truetype.TTFFile */ @@ -426,6 +426,24 @@ public class TTFFileTestCase { assertEquals(true, droidmonoTTFFile.isEmbeddable()); } + /** Underline position and thickness. */ + @Test + public void testUnderline() { + assertEquals(-63, dejavuTTFFile.getUnderlinePosition()); + assertEquals(43, dejavuTTFFile.getUnderlineThickness()); + assertEquals(-75, droidmonoTTFFile.getUnderlinePosition()); + assertEquals(49, droidmonoTTFFile.getUnderlineThickness()); + } + + /** Strikeout position and thickness. */ + @Test + public void testStrikeout() { + assertEquals(258, dejavuTTFFile.getStrikeoutPosition()); + assertEquals(49, dejavuTTFFile.getStrikeoutThickness()); + assertEquals(243, droidmonoTTFFile.getStrikeoutPosition()); + assertEquals(49, droidmonoTTFFile.getStrikeoutThickness()); + } + /** * Test readFont() - Add implementation if necessary. */ diff --git a/test/java/org/apache/fop/fonts/type1/AFMParserTestCase.java b/test/java/org/apache/fop/fonts/type1/AFMParserTestCase.java index 93443a0d9..31a613567 100644 --- a/test/java/org/apache/fop/fonts/type1/AFMParserTestCase.java +++ b/test/java/org/apache/fop/fonts/type1/AFMParserTestCase.java @@ -19,9 +19,6 @@ package org.apache.fop.fonts.type1; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - import java.awt.Rectangle; import java.io.IOException; import java.io.InputStream; @@ -29,6 +26,9 @@ import java.util.List; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + /** * Test case for {@link AFMParser}. */ @@ -128,4 +128,13 @@ public class AFMParserTestCase { private boolean objectEquals(Object o1, Object o2) { return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2)); } + + @Test + public void testUnderlinePositionAndThickness() throws IOException { + AFMFile afm = sut.parse(getClass().getResourceAsStream("underline.afm"), null); + AFMWritingDirectionMetrics metrics = afm.getWritingDirectionMetrics(0); + assertEquals(-96, metrics.getUnderlinePosition()); + assertEquals(58, metrics.getUnderlineThickness()); + } + } diff --git a/test/java/org/apache/fop/fonts/type1/underline.afm b/test/java/org/apache/fop/fonts/type1/underline.afm new file mode 100644 index 000000000..8137b41eb --- /dev/null +++ b/test/java/org/apache/fop/fonts/type1/underline.afm @@ -0,0 +1,4 @@ +StartFontMetrics 2.0 +UnderlinePosition -96 +UnderlineThickness 58 +EndFontMetrics diff --git a/test/java/org/apache/fop/svg/NativeTextPainterTest.java b/test/java/org/apache/fop/svg/NativeTextPainterTest.java new file mode 100644 index 000000000..1c2c3b582 --- /dev/null +++ b/test/java/org/apache/fop/svg/NativeTextPainterTest.java @@ -0,0 +1,78 @@ +/* + * 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.svg; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.io.File; +import java.io.IOException; + +import org.w3c.dom.Document; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.dom.svg.SAXSVGDocumentFactory; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.TextPainter; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.base14.Base14FontCollection; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; + +abstract class NativeTextPainterTest { + + protected final void runTest(String testcase, OperatorValidator validator) throws Exception { + FontInfo fontInfo = createFontInfo(); + BridgeContext bridgeContext = createBridgeContext(fontInfo); + GraphicsNode svg = loadSVG(bridgeContext, testcase); + Graphics2D g2d = createGraphics2D(fontInfo, validator); + svg.paint(g2d); + validator.end(); + } + + private FontInfo createFontInfo() { + FontInfo fontInfo = new FontInfo(); + new Base14FontCollection(true).setup(0, fontInfo); + return fontInfo; + } + + private BridgeContext createBridgeContext(FontInfo fontInfo) { + FOUserAgent userAgent = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); + SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new FOPFontFamilyResolverImpl(fontInfo), + new AffineTransform()); + BridgeContext bridgeContext = new BridgeContext(svgUserAgent); + bridgeContext.setTextPainter(createTextPainter(fontInfo)); + return bridgeContext; + } + + protected abstract TextPainter createTextPainter(FontInfo fontInfo); + + private GraphicsNode loadSVG(BridgeContext bridgeContext, String resourceName) throws IOException { + SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(null); + Document svg = factory.createDocument(null, getClass().getResourceAsStream(resourceName)); + GVTBuilder builder = new GVTBuilder(); + return builder.build(bridgeContext, svg); + } + + protected abstract Graphics2D createGraphics2D(FontInfo fontInfo, OperatorValidator validator); + +} diff --git a/test/java/org/apache/fop/svg/OperatorValidator.java b/test/java/org/apache/fop/svg/OperatorValidator.java new file mode 100644 index 000000000..959adc9a1 --- /dev/null +++ b/test/java/org/apache/fop/svg/OperatorValidator.java @@ -0,0 +1,108 @@ +/* + * 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.svg; + +import java.util.LinkedList; +import java.util.Queue; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +class OperatorValidator { + + private static interface Match { + + boolean match(String line); + } + + private static class MatchSequence implements OperatorValidator.Match { + + private final Queue<OperatorValidator.Match> expectedMatches = new LinkedList<OperatorValidator.Match>(); + + private OperatorValidator.Match currentMatch; + + private static final OperatorValidator.Match FINAL_MATCH = new Match() { + + public boolean match(String line) { + return false; + } + }; + + public boolean isExhausted() { + return currentMatch == FINAL_MATCH; + } + + public void addMatch(OperatorValidator.Match match) { + if (currentMatch == null) { + currentMatch = match; + } else { + expectedMatches.add(match); + } + } + + public boolean match(String line) { + boolean match = currentMatch.match(line); + if (match) { + if(expectedMatches.isEmpty()) { + currentMatch = FINAL_MATCH; + } else { + currentMatch = expectedMatches.remove(); + } + } + return match; + } + } + + private static class OperatorMatch implements OperatorValidator.Match { + + final String operator; + + final String line; + + OperatorMatch(String operator, String line) { + this.operator = operator; + this.line = line; + } + + public boolean match(String line) { + if (line.contains(operator)) { + assertEquals(this.line, line); + return true; + } + return false; + } + } + + private final OperatorValidator.MatchSequence matchSequence = new MatchSequence(); + + public OperatorValidator addOperatorMatch(String operator, String expectedLine) { + matchSequence.addMatch(new OperatorMatch(operator, expectedLine)); + return this; + } + + public void check(String line) { + matchSequence.match(line); + } + + public void end() { + assertTrue("Expected operators remain", matchSequence.isExhausted()); + } + +}
\ No newline at end of file diff --git a/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java b/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java new file mode 100644 index 000000000..52f18bb5e --- /dev/null +++ b/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.svg; + +import java.awt.Graphics2D; +import java.io.StringWriter; + +import org.junit.Test; + +import org.apache.batik.gvt.TextPainter; + +import org.apache.xmlgraphics.java2d.GraphicContext; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; + +public class PDFTextPainterTestCase extends NativeTextPainterTest { + + private static class OperatorCheckingPDFGraphics2D extends PDFGraphics2D { + + OperatorCheckingPDFGraphics2D(FontInfo fontInfo, final OperatorValidator validator) { + super(false, fontInfo, new PDFDocument("test"), null, null, null, 0); + this.currentStream = new StringWriter() { + + @Override + public void write(String str) { + validator.check(str); + } + + }; + } + } + + @Override + protected TextPainter createTextPainter(FontInfo fontInfo) { + return new PDFTextPainter(fontInfo); + } + + @Override + protected Graphics2D createGraphics2D(FontInfo fontInfo, OperatorValidator validator) { + PDFGraphics2D g2d = new OperatorCheckingPDFGraphics2D(fontInfo, validator); + g2d.setGraphicContext(new GraphicContext()); + return g2d; + } + + @Test + public void testRotatedGlyph() throws Exception { + runTest("rotated-glyph.svg", new OperatorValidator() + .addOperatorMatch("Tm", "1 0 0 -1 40 110 Tm ") + .addOperatorMatch("TJ", "[(A)] TJ\n") + .addOperatorMatch("Tm", "0.70710677 0.7071068 0.7071068 -0.70710677 106.69999695 110 Tm ") + .addOperatorMatch("TJ", "[(B)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 173.3999939 110 Tm ") + .addOperatorMatch("TJ", "[(C)] TJ\n")); + } + + @Test + public void testDxDy() throws Exception { + runTest("dx-dy.svg", new OperatorValidator() + .addOperatorMatch("Tm", "1 0 0 -1 55 35 Tm ") + .addOperatorMatch("TJ", "[(ABCDE)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 55 75 Tm ") + .addOperatorMatch("TJ", "[(A)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 69 85 Tm ") + .addOperatorMatch("TJ", "[(B)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 109 80 Tm ") + .addOperatorMatch("TJ", "[(C)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 91 65 Tm ") + .addOperatorMatch("TJ", "[(D)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 127 75 Tm ") + .addOperatorMatch("TJ", "[(E)] TJ\n")); + } + + @Test + public void testSpacing() throws Exception { + runTest("spacing.svg", new OperatorValidator() + .addOperatorMatch("Tm", "1 0 0 -1 0 0 Tm ") + .addOperatorMatch("TJ", "[(V) 80 (A) 70 (V)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 0 0 Tm ") + .addOperatorMatch("TJ", "[(V) 80 (A) 70 (V)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 0 0 Tm ") + .addOperatorMatch("TJ", "[(V) -20 (A) -30 (V)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 0 0 Tm ") + .addOperatorMatch("TJ", "[(ab) -111 ( ) -389 (cd)] TJ\n")); + } + + @Test + public void testGlyphOrientation() throws Exception { + runTest("glyph-orientation.svg", new OperatorValidator() + .addOperatorMatch("Tm", "0 1 1 0 738.5 0 Tm ") + .addOperatorMatch("TJ", "[(A)] TJ\n") + .addOperatorMatch("Tm", "0 1 1 0 738.5 667 Tm ") + .addOperatorMatch("TJ", "[(B)] TJ\n") + .addOperatorMatch("Tm", "0 1 1 0 738.5 1334 Tm ") + .addOperatorMatch("TJ", "[(C)] TJ\n") + .addOperatorMatch("Tm", "0 1 1 0 738.5 2056 Tm ") + .addOperatorMatch("TJ", "[(D)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 2149 718 Tm ") + .addOperatorMatch("TJ", "[(E)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 2165.5 1643 Tm ") + .addOperatorMatch("TJ", "[(F)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 2124 2568 Tm ") + .addOperatorMatch("TJ", "[(G)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 2138.5 3493 Tm ") + .addOperatorMatch("TJ", "[(H)] TJ\n") + .addOperatorMatch("Tm", "0 -1 -1 0 718 5000 Tm ") + .addOperatorMatch("TJ", "[(I)] TJ\n") + .addOperatorMatch("Tm", "0 -1 -1 0 1643 5000 Tm ") + .addOperatorMatch("TJ", "[(J)] TJ\n") + .addOperatorMatch("Tm", "0 -1 -1 0 2568 5000 Tm ") + .addOperatorMatch("TJ", "[(K)] TJ\n") + .addOperatorMatch("Tm", "0 -1 -1 0 3493 5000 Tm ") + .addOperatorMatch("TJ", "[(L)] TJ\n")); + } + + @Test + public void testBaselineShift() throws Exception { + runTest("baseline-shift.svg", new OperatorValidator() + .addOperatorMatch("Tm", "1 0 0 -1 0 0 Tm ") + .addOperatorMatch("TJ", "[(AB)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 1334 -462.5 Tm ") + .addOperatorMatch("TJ", "[(CD)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 2778 0 Tm ") + .addOperatorMatch("TJ", "[(EF)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 4056 462.5 Tm ") + .addOperatorMatch("TJ", "[(GH)] TJ\n") + .addOperatorMatch("Tm", "1 0 0 -1 5556 0 Tm ") + .addOperatorMatch("TJ", "[(IJ)] TJ\n")); + } + +} diff --git a/test/java/org/apache/fop/svg/PSTextPainterTestCase.java b/test/java/org/apache/fop/svg/PSTextPainterTestCase.java new file mode 100644 index 000000000..2d5de7455 --- /dev/null +++ b/test/java/org/apache/fop/svg/PSTextPainterTestCase.java @@ -0,0 +1,77 @@ +/* + * 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.svg; + +import java.awt.Graphics2D; +import java.io.IOException; + +import org.junit.Test; + +import org.apache.commons.io.output.NullOutputStream; + +import org.apache.batik.gvt.TextPainter; + +import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.render.ps.PSTextPainter; + +public class PSTextPainterTestCase extends NativeTextPainterTest { + + private static class OperatorCheckingPSGraphics2D extends PSGraphics2D { + + OperatorCheckingPSGraphics2D(FontInfo fontInfo, final OperatorValidator validator) { + super(false, new PSGenerator(new NullOutputStream()) { + + @Override + public void writeln(String cmd) throws IOException { + validator.check(cmd); + } + + }); + } + } + + @Override + protected TextPainter createTextPainter(FontInfo fontInfo) { + return new PSTextPainter(fontInfo); + } + + @Override + protected Graphics2D createGraphics2D(FontInfo fontInfo, OperatorValidator validator) { + PSGraphics2D g2d = new OperatorCheckingPSGraphics2D(fontInfo, validator); + g2d.setGraphicContext(new GraphicContext()); + return g2d; + } + + @Test + public void testRotatedGlyph() throws Exception { + runTest("rotated-glyph.svg", new OperatorValidator() + .addOperatorMatch("Tm", "1 0 0 -1 40 110 Tm") + .addOperatorMatch("xshow", "(A)\n[0] xshow") + .addOperatorMatch("Tm", "0.70711 0.70711 0.70711 -0.70711 106.7 110 Tm") + .addOperatorMatch("xshow", "(B)\n[0] xshow") + .addOperatorMatch("Tm", "1 0 0 -1 173.39999 110 Tm") + .addOperatorMatch("xshow", "(C)\n[0] xshow")); + } + +} diff --git a/test/java/org/apache/fop/svg/baseline-shift.svg b/test/java/org/apache/fop/svg/baseline-shift.svg new file mode 100644 index 000000000..0f375b9af --- /dev/null +++ b/test/java/org/apache/fop/svg/baseline-shift.svg @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<svg width="150" height="60" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="100%" height="100%" fill="none" stroke="black" stroke-width="2"/> +<g transform="translate(10, 40) scale(20) scale(0.001)"> +<text font-family="sans-serif" font-size="1000"> +AB<tspan baseline-shift="super">CD</tspan>EF<tspan baseline-shift="sub">GH</tspan>IJ +</text> +</g> +</svg> diff --git a/test/java/org/apache/fop/svg/dx-dy.svg b/test/java/org/apache/fop/svg/dx-dy.svg new file mode 100644 index 000000000..cfdc2de01 --- /dev/null +++ b/test/java/org/apache/fop/svg/dx-dy.svg @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="100%" height="100%" stroke="black" stroke-width="2" fill="none"/> +<g font-family="monospace" font-size="30"> + <text x="55" y="35">ABCDE</text> + <text x="55" y="75" dx="0 -4 22 -36 18" dy="0 10 -5 -15 10">ABCDE</text> +</g> +</svg> diff --git a/test/java/org/apache/fop/svg/font/BasicGlyphVectorTestCase.java b/test/java/org/apache/fop/svg/font/BasicGlyphVectorTestCase.java new file mode 100644 index 000000000..c6f062a84 --- /dev/null +++ b/test/java/org/apache/fop/svg/font/BasicGlyphVectorTestCase.java @@ -0,0 +1,193 @@ +/* + * 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.svg.font; + +import java.awt.Rectangle; +import java.awt.font.GlyphMetrics; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.batik.gvt.font.GVTGlyphMetrics; +import org.apache.batik.gvt.font.GVTLineMetrics; + +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontMetrics; + +/** + * Tests all the methods of {@link FOPGVTGlyphVector} with a mocked font. + */ +public class BasicGlyphVectorTestCase extends FOPGVTGlyphVectorTest { + + private final int fontSize = 10000; + + @Before + public void createGlyphVector() { + FontMetrics metrics = mockFontMetrics(); + Font font = mockFont(metrics); + FOPGVTFont gvtFont = mockGVTFont(font); + CharacterIterator it = new StringCharacterIterator("ABC"); + glyphVector = new FOPGVTGlyphVector(gvtFont, it, null); + glyphVector.performDefaultLayout(); + } + + private FontMetrics mockFontMetrics() { + FontMetrics metrics = mock(FontMetrics.class); + when(metrics.getAscender(eq(fontSize))).thenReturn(8000000); + when(metrics.getDescender(eq(fontSize))).thenReturn(-4000000); + when(metrics.getWidth(eq(1), eq(fontSize))).thenReturn(10000000); + when(metrics.getBoundingBox(eq(1), eq(fontSize))).thenReturn( + new Rectangle(-1000000, -2000000, 3000000, 4000000)); + when(metrics.getWidth(eq(2), eq(fontSize))).thenReturn(11000000); + when(metrics.getBoundingBox(eq(2), eq(fontSize))).thenReturn( + new Rectangle(-5000000, -6000000, 7000000, 9000000)); + when(metrics.getWidth(eq(3), eq(fontSize))).thenReturn(12000000); + when(metrics.getBoundingBox(eq(3), eq(fontSize))).thenReturn( + new Rectangle(-9000000, -10000000, 11000000, 14000000)); + return metrics; + } + + private Font mockFont(FontMetrics metrics) { + Font font = mock(Font.class); + when(font.getFontMetrics()).thenReturn(metrics); + when(font.getFontSize()).thenReturn(fontSize); + when(font.mapChar(eq('A'))).thenReturn((char) 1); + when(font.mapChar(eq('B'))).thenReturn((char) 2); + when(font.mapChar(eq('C'))).thenReturn((char) 3); + return font; + } + + private FOPGVTFont mockGVTFont(Font font) { + FOPGVTFont gvtFont = mock(FOPGVTFont.class); + when(gvtFont.getFont()).thenReturn(font); + when(gvtFont.getLineMetrics(anyInt())).thenReturn( + new GVTLineMetrics(8, 0, null, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + return gvtFont; + } + + @Test + public void getGlyphCodeReturnsGlyphIndex() { + assertEquals(1, glyphVector.getGlyphCode(0)); + assertEquals(2, glyphVector.getGlyphCode(1)); + assertEquals(3, glyphVector.getGlyphCode(2)); + } + + @Test + public void testGetGlyphCodes() { + assertArrayEquals(new int[] {1, 2, 3}, glyphVector.getGlyphCodes(0, 3, null)); + assertArrayEquals(new int[] {2, 3}, glyphVector.getGlyphCodes(1, 2, null)); + } + + @Test + public void testGetGlyphMetrics() { + assertGlyphMetricsEqual(new GVTGlyphMetrics(10, 12, new Rectangle(-1, -2, 3, 4), GlyphMetrics.STANDARD), + glyphVector.getGlyphMetrics(0)); + assertGlyphMetricsEqual(new GVTGlyphMetrics(11, 12, new Rectangle(-5, -3, 7, 9), GlyphMetrics.STANDARD), + glyphVector.getGlyphMetrics(1)); + assertGlyphMetricsEqual(new GVTGlyphMetrics(12, 12, new Rectangle(-9, -4, 11, 14), GlyphMetrics.STANDARD), + glyphVector.getGlyphMetrics(2)); + } + + private void assertGlyphMetricsEqual(GVTGlyphMetrics expected, GVTGlyphMetrics actual) { + assertEquals(expected.getHorizontalAdvance(), actual.getHorizontalAdvance(), 0); + assertEquals(expected.getVerticalAdvance(), actual.getVerticalAdvance(), 0); + assertEquals(expected.getBounds2D(), actual.getBounds2D()); + assertEquals(expected.getLSB(), actual.getLSB(), 0); + assertEquals(expected.getRSB(), actual.getRSB(), 0); + assertEquals(expected.getType(), actual.getType()); + assertEquals(expected.isCombining(), actual.isCombining()); + assertEquals(expected.isComponent(), actual.isComponent()); + assertEquals(expected.isLigature(), actual.isLigature()); + assertEquals(expected.isStandard(), actual.isStandard()); + assertEquals(expected.isWhitespace(), actual.isWhitespace()); + } + + @Test + public void testGetGlyphPosition() { + assertEquals(new Point2D.Float(0, 0), glyphVector.getGlyphPosition(0)); + assertEquals(new Point2D.Float(10, 0), glyphVector.getGlyphPosition(1)); + assertEquals(new Point2D.Float(21, 0), glyphVector.getGlyphPosition(2)); + assertEquals(new Point2D.Float(33, 0), glyphVector.getGlyphPosition(3)); + } + + @Test + public void testGetGlyphPositions() { + float[] expectedPositions = new float[] {0, 0, 10, 0, 21, 0, 33, 0}; + assertArrayEquals(expectedPositions, glyphVector.getGlyphPositions(0, 4, null), 0); + assertArrayEquals(expectedPositions, glyphVector.getGlyphPositions(0, 4, new float[8]), 0); + } + + @Test + public void testGetGlyphOutline() { + assertEquals(new Rectangle(-1, -2, 3, 4), glyphVector.getGlyphOutline(0).getBounds()); + assertEquals(new Rectangle(5, -3, 7, 9), glyphVector.getGlyphOutline(1).getBounds()); + assertEquals(new Rectangle(12, -4, 11, 14), glyphVector.getGlyphOutline(2).getBounds()); + } + + @Test + public void testGetOutline() { + assertEquals(new Rectangle(-1, -4, 24, 14), glyphVector.getOutline().getBounds()); + } + + @Test + public void testGetLogicalBounds() { + assertEquals(new Rectangle(0, -8, 33, 12), glyphVector.getLogicalBounds()); + } + + @Test + public void testGetLogicalBoundsRotated() { + for (int i = 0; i < 3; i++) { + glyphVector.setGlyphTransform(i, new AffineTransform(0.7, 0.7, -0.7, 0.7, 0, 0)); + } + assertEquals(new Rectangle2D.Float(-2.8f, -5.6f, 37.8f, 16.8f), glyphVector.getLogicalBounds()); + } + + @Test + public void testGetBounds() { + assertEquals(new Rectangle(-1, -4, 24, 14), glyphVector.getBounds2D(null)); + } + + @Test + public void testGetGlyphVisualBounds() { + assertEquals(new Rectangle(-1, -2, 3, 4), glyphVector.getGlyphVisualBounds(0).getBounds()); + assertEquals(new Rectangle(5, -3, 7, 9), glyphVector.getGlyphVisualBounds(1).getBounds()); + assertEquals(new Rectangle(12, -4, 11, 14), glyphVector.getGlyphVisualBounds(2).getBounds()); + } + + @Test + public void testGetGlyphLogicalBounds() { + assertEquals(new Rectangle(0, -8, 10, 12), glyphVector.getGlyphLogicalBounds(0).getBounds()); + assertEquals(new Rectangle(10, -8, 11, 12), glyphVector.getGlyphLogicalBounds(1).getBounds()); + assertEquals(new Rectangle(21, -8, 12, 12), glyphVector.getGlyphLogicalBounds(2).getBounds()); + } + +} diff --git a/test/java/org/apache/fop/svg/font/FOPFontFamilyResolverTestCase.java b/test/java/org/apache/fop/svg/font/FOPFontFamilyResolverTestCase.java new file mode 100644 index 000000000..2f5668cbc --- /dev/null +++ b/test/java/org/apache/fop/svg/font/FOPFontFamilyResolverTestCase.java @@ -0,0 +1,127 @@ +/* + * 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.svg.font; + +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Collections; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import org.apache.batik.gvt.font.GVTFontFamily; +import org.apache.batik.gvt.font.GVTLineMetrics; + +import org.apache.fop.fonts.FontInfo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class FOPFontFamilyResolverTestCase { + + private static FontInfo fontInfo; + + private FOPFontFamilyResolver resolver; + + @BeforeClass + public static void setUpFontInfo() { + fontInfo = new FontInfoBuilder() + .useDejaVuLGCSerif() + .useDroidSansMono() + .build(); + } + + @Before + public void createFontFamilyResolver() { + resolver = new FOPFontFamilyResolverImpl(fontInfo); + } + + @Test + public void testResolve() { + assertNull(resolver.resolve("Unavailable")); + assertNotNull(resolver.resolve(FontInfoBuilder.DEJAVU_LGC_SERIF)); + } + + @Test + public void testGetFamilyThatCanDisplay() { + GVTFontFamily family = resolver.getFamilyThatCanDisplay('\u0180'); + assertEquals(FontInfoBuilder.DEJAVU_LGC_SERIF, family.getFamilyName()); + family = resolver.getFamilyThatCanDisplay('\u02F3'); + assertEquals(FontInfoBuilder.DROID_SANS_MONO, family.getFamilyName()); + family = resolver.getFamilyThatCanDisplay('\u02DF'); + assertNull(family); + } + + @Test + public void testDeriveFont() { + FOPGVTFontFamily family = (FOPGVTFontFamily) resolver.resolve(FontInfoBuilder.DEJAVU_LGC_SERIF); + FOPGVTFont font = family.deriveFont(10, Collections.emptyMap()); + assertEquals(10, font.getSize(), 0); + assertTrue(font.canDisplay('\u01F6')); + assertFalse(font.canDisplay('\u01F7')); + } + + @Test + @Ignore("FOP metrics don't match AWT, but not sure who is right and who is wrong") + public void testLineMetrics() throws FontFormatException, IOException { + FOPGVTFontFamily family = (FOPGVTFontFamily) resolver.resolve(FontInfoBuilder.DEJAVU_LGC_SERIF); + FOPGVTFont font = family.deriveFont(10, Collections.emptyMap()); + GVTLineMetrics fopMetrics = font.getLineMetrics("", null); + LineMetrics awtMetrics = getAWTLineMetrics(); + printDifference("Ascent", awtMetrics.getAscent(), fopMetrics.getAscent()); + printDifference("Descent", awtMetrics.getDescent(), fopMetrics.getDescent()); + printDifference("Height", awtMetrics.getHeight(), fopMetrics.getHeight()); + printDifference("Leading", awtMetrics.getLeading(), fopMetrics.getLeading()); + printDifference("StrikethroughOffset", awtMetrics.getStrikethroughOffset(), + fopMetrics.getStrikethroughOffset()); + printDifference("StrikethroughThickness", awtMetrics.getStrikethroughThickness(), + fopMetrics.getStrikethroughThickness()); + printDifference("UnderlineOffset", awtMetrics.getUnderlineOffset(), + fopMetrics.getUnderlineOffset()); + printDifference("UnderlineThickness", awtMetrics.getUnderlineThickness(), + fopMetrics.getUnderlineThickness()); + } + + private LineMetrics getAWTLineMetrics() throws FontFormatException, IOException { + File fontFile = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf"); + java.awt.Font awtFont = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, fontFile).deriveFont(10f); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + BufferedImage dummyImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB); + FontRenderContext frc = ge.createGraphics(dummyImage).getFontRenderContext(); + LineMetrics awtMetrics = awtFont.getLineMetrics("ABC", frc); + return awtMetrics; + } + + private void printDifference(String value, float awt, float fop) { + System.out.println(String.format("%22s AWT: %10f FOP: %10f Difference: %.2f%%", value, awt, fop, + (fop - awt) / awt * 100)); + } + +} diff --git a/test/java/org/apache/fop/svg/font/FOPGVTFontTestCase.java b/test/java/org/apache/fop/svg/font/FOPGVTFontTestCase.java new file mode 100644 index 000000000..c7af068ce --- /dev/null +++ b/test/java/org/apache/fop/svg/font/FOPGVTFontTestCase.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.svg.font; + +import java.text.StringCharacterIterator; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.fop.fonts.Font; +import org.apache.fop.svg.font.FOPGVTFont; + +public class FOPGVTFontTestCase { + + private FOPGVTFont font; + + @Before + public void createFont() { + Font f = mock(Font.class); + when(f.hasChar(eq((char) 0))).thenReturn(false); + when(f.hasChar(eq((char) 1))).thenReturn(true); + font = new FOPGVTFont(f, null); + } + + @Test + public void testCanDisplayUpTo() { + char[] text = new char[] {1, 1, 1}; + testCanDisplayUpToVariants(text, -1, 0, 3); + testCanDisplayUpToVariants(text, -1, 1, 3); + text = new char[] {1, 1, 0, 1}; + testCanDisplayUpToVariants(text, 2, 0, 4); + testCanDisplayUpToVariants(text, 2, 1, 4); + testCanDisplayUpToVariants(text, 2, 2, 4); + testCanDisplayUpToVariants(text, -1, 3, 4); + testCanDisplayUpToVariants(text, -1, 1, 2); + } + + @Test + public void testCanDisplayUpToString() { + assertEquals(-1, font.canDisplayUpTo(new String(new char[] {1, 1, 1}))); + assertEquals(0, font.canDisplayUpTo(new String(new char[] {0, 1, 1}))); + assertEquals(1, font.canDisplayUpTo(new String(new char[] {1, 0, 1}))); + assertEquals(2, font.canDisplayUpTo(new String(new char[] {1, 1, 0}))); + } + + private void testCanDisplayUpToVariants(char[] text, int expected, int start, int limit) { + assertEquals(expected, font.canDisplayUpTo(text, start, limit)); + assertEquals(expected, font.canDisplayUpTo(new StringCharacterIterator(new String(text)), start, limit)); + } +} diff --git a/test/java/org/apache/fop/svg/font/FOPGVTGlyphVectorTest.java b/test/java/org/apache/fop/svg/font/FOPGVTGlyphVectorTest.java new file mode 100644 index 000000000..0995ab4df --- /dev/null +++ b/test/java/org/apache/fop/svg/font/FOPGVTGlyphVectorTest.java @@ -0,0 +1,27 @@ +/* + * 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.svg.font; + + +public abstract class FOPGVTGlyphVectorTest { + + protected FOPGVTGlyphVector glyphVector; + +} diff --git a/test/java/org/apache/fop/svg/font/FontInfoBuilder.java b/test/java/org/apache/fop/svg/font/FontInfoBuilder.java new file mode 100644 index 000000000..f7a5825bd --- /dev/null +++ b/test/java/org/apache/fop/svg/font/FontInfoBuilder.java @@ -0,0 +1,102 @@ +/* + * 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.svg.font; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.fop.apps.io.InternalResourceResolver; +import org.apache.fop.apps.io.ResourceResolverFactory; +import org.apache.fop.fonts.EmbeddingMode; +import org.apache.fop.fonts.EncodingMode; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontMetrics; +import org.apache.fop.fonts.truetype.TTFFontLoader; + +class FontInfoBuilder { + + public static final String DEJAVU_LGC_SERIF = "DejaVu LGC Serif"; + + public static final String DROID_SANS_MONO = "Droid Sans Mono"; + + private static final boolean USE_ADVANCED_BY_DEFAULT = true; + + private FontInfo fontInfo; + + private int fontKey; + + public FontInfoBuilder() { + reset(); + } + + private void reset() { + fontInfo = new FontInfo(); + fontKey = 1; + } + + public FontInfoBuilder useDejaVuLGCSerif() { + return useDejaVuLGCSerif(USE_ADVANCED_BY_DEFAULT); + } + + public FontInfoBuilder useDejaVuLGCSerif(boolean useAdvanced) { + try { + return useFont(DEJAVU_LGC_SERIF, "DejaVuLGCSerif.ttf", useAdvanced); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public FontInfoBuilder useDroidSansMono() { + return useDroidSansMono(USE_ADVANCED_BY_DEFAULT); + } + + public FontInfoBuilder useDroidSansMono(boolean useAdvanced) { + try { + return useFont(DROID_SANS_MONO, "DroidSansMono.ttf", useAdvanced); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private FontInfoBuilder useFont(String fontName, String filename, boolean useAdvanced) + throws IOException, URISyntaxException { + URI baseURI = new File("test/resources/fonts/ttf").toURI(); + InternalResourceResolver resolver = ResourceResolverFactory.createDefaultInternalResourceResolver(baseURI); + TTFFontLoader fontLoader = new TTFFontLoader(new URI(filename), null, true, + EmbeddingMode.AUTO, EncodingMode.AUTO, true, useAdvanced, resolver); + FontMetrics font = fontLoader.getFont(); + registerFont(font, "F" + fontKey++, fontName); + return this; + } + + private void registerFont(FontMetrics font, String key, String familyName) { + fontInfo.addMetrics(key, font); + fontInfo.addFontProperties(key, familyName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + } + + public FontInfo build() { + FontInfo fontInfo = this.fontInfo; + reset(); + return fontInfo; + } +} diff --git a/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java b/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java new file mode 100644 index 000000000..34cba604a --- /dev/null +++ b/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java @@ -0,0 +1,91 @@ +/* + * 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.svg.font; + +import java.util.Collections; + +import org.junit.Test; + +import org.apache.fop.fonts.FontInfo; + +import static org.junit.Assert.assertEquals; + +/** + * Specifically tests glyph positioning from a real font. + */ +public class GlyphLayoutTestCase extends FOPGVTGlyphVectorTest { + + /** + * Glyph positioning using the legacy kern table. + */ + @Test + public void testBasicGlyphPositioning() throws Exception { + testGlyphLayout(false); + } + + /** + * Glyph positioning using GPOS sub-tables. + */ + @Test + public void testAdvancedGlyphPositioning() throws Exception { + testGlyphLayout(true); + } + + private void testGlyphLayout(boolean useAdvanced) { + FOPGVTFont font = loadFont(useAdvanced); + glyphVector = (FOPGVTGlyphVector) font.createGlyphVector(null, "L\u201DP,V.F,A\u2019LT."); + glyphVector.performDefaultLayout(); + // Values in font units (unitsPerEm = 2048), glyph width - kern + int[] widths = { + /* L */ 1360 - 491, + /* " */ 1047, + /* P */ 1378 - 415, + /* , */ 651, + /* V */ 1479 - 358, + /* . */ 651, + /* F */ 1421 - 319, + /* , */ 651, + /* A */ 1479 - 301, + /* ' */ 651, + /* L */ 1360 - 167, + /* T */ 1366 - 301, + /* . */ 651}; + checkGlyphPositions(13, widths); + } + + private FOPGVTFont loadFont(boolean useAdvanced) { + FontInfo fontInfo = new FontInfoBuilder().useDejaVuLGCSerif(useAdvanced).build(); + FOPFontFamilyResolver resolver = new FOPFontFamilyResolverImpl(fontInfo); + FOPGVTFontFamily family = resolver.resolve(FontInfoBuilder.DEJAVU_LGC_SERIF); + return family.deriveFont(1000, Collections.emptyMap()); + } + + private void checkGlyphPositions(int expectedGlyphCount, int[] widths) { + assertEquals(expectedGlyphCount, glyphVector.getNumGlyphs()); + float[] positions = new float[2 * (widths.length + 1)]; + for (int i = 0, n = 2; i < widths.length; i++, n += 2) { + positions[n] = positions[n - 2] + widths[i] / 2.048f; + } + for (int i = 0; i <= widths.length; i++) { + assertEquals(positions[2 * i], glyphVector.getGlyphPosition(i).getX(), 3); + } + } + +} diff --git a/test/java/org/apache/fop/svg/glyph-orientation.svg b/test/java/org/apache/fop/svg/glyph-orientation.svg new file mode 100644 index 000000000..4900a3b02 --- /dev/null +++ b/test/java/org/apache/fop/svg/glyph-orientation.svg @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<svg width="100" height="140" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="100%" height="100%" fill="none" stroke="black" stroke-width="2"/> +<g transform="translate(10) scale(20) scale(0.001) translate(0, 1000)" + font-family="sans-serif" font-size="1000"> + <text x="1000" writing-mode="tb">ABCD</text> + <text x="2500" writing-mode="tb" glyph-orientation-vertical="0">EFGH</text> + <text x="0" y="5000" glyph-orientation-horizontal="270">IJKL</text> +</g> +</svg> diff --git a/test/java/org/apache/fop/svg/rotated-glyph.svg b/test/java/org/apache/fop/svg/rotated-glyph.svg new file mode 100644 index 000000000..8b942905e --- /dev/null +++ b/test/java/org/apache/fop/svg/rotated-glyph.svg @@ -0,0 +1,5 @@ +<?xml version="1.0"?> +<svg width="300" height="150" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="100%" height="100%" fill="none" stroke="black" stroke-width="2"/> +<text font-family="Helvetica" font-size="100" x="40" y="110" rotate="0 45 0">ABC</text> +</svg> diff --git a/test/java/org/apache/fop/svg/spacing.svg b/test/java/org/apache/fop/svg/spacing.svg new file mode 100644 index 000000000..943ab1d04 --- /dev/null +++ b/test/java/org/apache/fop/svg/spacing.svg @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<svg width="150" height="200" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="100%" height="100%" stroke="black" stroke-width="2" fill="none"/> +<g transform="translate(10) scale(40) scale(0.001) translate(0, 1000)" + font-family="sans-serif" font-size="1000"> + <g transform=""> + <text>VAV</text> + <line x1="667" y1="-818" x2="667" y2="100" stroke-width="10" stroke="blue"/> + </g> + <g transform="translate(0, 1000)"> + <text kerning="0">VAV</text> + <line x1="667" y1="-818" x2="667" y2="100" stroke-width="10" stroke="blue"/> + </g> + <g transform="translate(0, 2000)"> + <text letter-spacing="100">VAV</text> + </g> + <g transform="translate(0, 3000)"> + <text word-spacing="500">ab cd</text> + </g> +</g> +</svg> |