summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.xml7
-rw-r--r--findbugs-exclude.xml30
-rw-r--r--lib/batik-all-1.7.jarbin3318083 -> 0 bytes
-rw-r--r--lib/batik-all-trunk-patch1041.jarbin0 -> 3313165 bytes
-rw-r--r--src/codegen/fonts/Courier.xml501
-rw-r--r--src/codegen/fonts/CourierBold.xml501
-rw-r--r--src/codegen/fonts/CourierBoldOblique.xml499
-rw-r--r--src/codegen/fonts/CourierOblique.xml501
-rw-r--r--src/codegen/fonts/Helvetica.xml465
-rw-r--r--src/codegen/fonts/HelveticaBold.xml465
-rw-r--r--src/codegen/fonts/HelveticaBoldOblique.xml465
-rw-r--r--src/codegen/fonts/HelveticaOblique.xml467
-rw-r--r--src/codegen/fonts/Symbol.xml387
-rw-r--r--src/codegen/fonts/TimesBold.xml465
-rw-r--r--src/codegen/fonts/TimesBoldItalic.xml465
-rw-r--r--src/codegen/fonts/TimesItalic.xml467
-rw-r--r--src/codegen/fonts/TimesRoman.xml465
-rw-r--r--src/codegen/fonts/ZapfDingbats.xml412
-rw-r--r--src/codegen/fonts/font-file.xsl26
-rw-r--r--src/java/org/apache/fop/afp/AFPEventProducer.java8
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFont.java32
-rw-r--r--src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java60
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSet.java72
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java95
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java124
-rw-r--r--src/java/org/apache/fop/afp/fonts/DoubleByteFont.java34
-rw-r--r--src/java/org/apache/fop/afp/fonts/FopCharacterSet.java50
-rw-r--r--src/java/org/apache/fop/afp/fonts/IntegerKeyStore.java71
-rw-r--r--src/java/org/apache/fop/afp/fonts/OutlineFont.java16
-rw-r--r--src/java/org/apache/fop/afp/fonts/RasterFont.java88
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java6
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPBridgeContext.java42
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPFontFamilyResolver.java84
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPTextHandler.java31
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPTextPainter.java21
-rw-r--r--src/java/org/apache/fop/fo/FOText.java94
-rw-r--r--src/java/org/apache/fop/fonts/Base14Font.java11
-rw-r--r--src/java/org/apache/fop/fonts/CIDFont.java1
-rw-r--r--src/java/org/apache/fop/fonts/CustomFont.java47
-rw-r--r--src/java/org/apache/fop/fonts/FontInfo.java37
-rw-r--r--src/java/org/apache/fop/fonts/FontMetrics.java44
-rw-r--r--src/java/org/apache/fop/fonts/GlyphMapping.java327
-rw-r--r--src/java/org/apache/fop/fonts/LazyFont.java26
-rw-r--r--src/java/org/apache/fop/fonts/MultiByteFont.java18
-rw-r--r--src/java/org/apache/fop/fonts/SingleByteFont.java40
-rw-r--r--src/java/org/apache/fop/fonts/TextFragment.java31
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFFile.java38
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java20
-rw-r--r--src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java8
-rw-r--r--src/java/org/apache/fop/fonts/type1/Type1FontLoader.java17
-rw-r--r--src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java7
-rw-r--r--src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java3
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java719
-rw-r--r--src/java/org/apache/fop/render/AbstractGenericSVGHandler.java4
-rw-r--r--src/java/org/apache/fop/render/afp/AFPSVGHandler.java15
-rw-r--r--src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java21
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java20
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java5
-rw-r--r--src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java21
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java4
-rw-r--r--src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java3
-rw-r--r--src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java5
-rw-r--r--src/java/org/apache/fop/render/ps/PSSVGHandler.java3
-rw-r--r--src/java/org/apache/fop/render/ps/PSTextPainter.java361
-rw-r--r--src/java/org/apache/fop/svg/ACIUtils.java68
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPTextPainter.java331
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPTranscoder.java22
-rw-r--r--src/java/org/apache/fop/svg/NativeTextPainter.java147
-rw-r--r--src/java/org/apache/fop/svg/PDFTextPainter.java229
-rw-r--r--src/java/org/apache/fop/svg/PDFTextUtil.java41
-rw-r--r--src/java/org/apache/fop/svg/PDFTranscoder.java6
-rw-r--r--src/java/org/apache/fop/svg/SVGUserAgent.java11
-rw-r--r--src/java/org/apache/fop/svg/SimpleSVGUserAgent.java12
-rw-r--r--src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java70
-rw-r--r--src/java/org/apache/fop/svg/font/FOPFontFamilyResolver.java31
-rw-r--r--src/java/org/apache/fop/svg/font/FOPFontFamilyResolverImpl.java67
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTFont.java159
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java73
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java339
-rw-r--r--src/java/org/apache/fop/svg/font/FilteringFontFamilyResolver.java47
-rw-r--r--test/java/org/apache/fop/afp/fonts/IntegerKeyStoreTestCase.java48
-rw-r--r--test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java17
-rw-r--r--test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java9
-rw-r--r--test/java/org/apache/fop/fonts/svg-fonts.fo37
-rw-r--r--test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java22
-rw-r--r--test/java/org/apache/fop/fonts/type1/AFMParserTestCase.java15
-rw-r--r--test/java/org/apache/fop/fonts/type1/underline.afm4
-rw-r--r--test/java/org/apache/fop/svg/NativeTextPainterTest.java78
-rw-r--r--test/java/org/apache/fop/svg/OperatorValidator.java108
-rw-r--r--test/java/org/apache/fop/svg/PDFTextPainterTestCase.java149
-rw-r--r--test/java/org/apache/fop/svg/PSTextPainterTestCase.java77
-rw-r--r--test/java/org/apache/fop/svg/baseline-shift.svg9
-rw-r--r--test/java/org/apache/fop/svg/dx-dy.svg8
-rw-r--r--test/java/org/apache/fop/svg/font/BasicGlyphVectorTestCase.java193
-rw-r--r--test/java/org/apache/fop/svg/font/FOPFontFamilyResolverTestCase.java127
-rw-r--r--test/java/org/apache/fop/svg/font/FOPGVTFontTestCase.java72
-rw-r--r--test/java/org/apache/fop/svg/font/FOPGVTGlyphVectorTest.java27
-rw-r--r--test/java/org/apache/fop/svg/font/FontInfoBuilder.java102
-rw-r--r--test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java91
-rw-r--r--test/java/org/apache/fop/svg/glyph-orientation.svg10
-rw-r--r--test/java/org/apache/fop/svg/rotated-glyph.svg5
-rw-r--r--test/java/org/apache/fop/svg/spacing.svg21
102 files changed, 7165 insertions, 5089 deletions
diff --git a/build.xml b/build.xml
index fee1ef03c..e1770ec55 100644
--- a/build.xml
+++ b/build.xml
@@ -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="&lt;init&gt;"/>
+ <Bug pattern="EI_EXPOSE_REP2"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.fonts.MultiByteFont"/>
+ <Method name="setBBoxArray"/>
+ <Bug pattern="EI_EXPOSE_REP2"/>
+ </Match>
+ <Match>
<Class name="org.apache.fop.fonts.truetype.TTFFile$1"/>
<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
deleted file mode 100644
index 589328581..000000000
--- a/lib/batik-all-1.7.jar
+++ /dev/null
Binary files differ
diff --git a/lib/batik-all-trunk-patch1041.jar b/lib/batik-all-trunk-patch1041.jar
new file mode 100644
index 000000000..cf69a308d
--- /dev/null
+++ b/lib/batik-all-trunk-patch1041.jar
Binary files differ
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) &gt; 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) &gt; 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) &gt; 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>