diff options
author | (no author) <(no author)@unknown> | 2002-07-05 16:44:10 +0000 |
---|---|---|
committer | (no author) <(no author)@unknown> | 2002-07-05 16:44:10 +0000 |
commit | 46e7dde597ddd52ae304fdf83b3b68c32afa3286 (patch) | |
tree | 46a778f3b6f8f04424767a199467c9caf216cd5c /src | |
parent | bea520e06587303175f812eeaedc315d3417e393 (diff) | |
download | xmlgraphics-fop-fop-0_20_4.tar.gz xmlgraphics-fop-fop-0_20_4.zip |
This commit was manufactured by cvs2svn to create tag 'fop-0_20_4'.fop-0_20_4
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/tags/fop-0_20_4@194977 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
182 files changed, 7924 insertions, 3584 deletions
diff --git a/src/codegen/Courier-Bold.xml b/src/codegen/Courier-Bold.xml index 53c0a6f20..7f748fda3 100644 --- a/src/codegen/Courier-Bold.xml +++ b/src/codegen/Courier-Bold.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Courier-Bold</font-name> <class-name>CourierBold</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>562</cap-height> <x-height>439</x-height> <ascender>626</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Courier-BoldOblique.xml b/src/codegen/Courier-BoldOblique.xml index 5dac9ae2f..bc996d4db 100644 --- a/src/codegen/Courier-BoldOblique.xml +++ b/src/codegen/Courier-BoldOblique.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Courier-BoldOblique</font-name> <class-name>CourierBoldOblique</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>562</cap-height> <x-height>439</x-height> <ascender>626</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Courier-Oblique.xml b/src/codegen/Courier-Oblique.xml index 701ec8534..5bb2d1f9a 100644 --- a/src/codegen/Courier-Oblique.xml +++ b/src/codegen/Courier-Oblique.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Courier-Oblique</font-name> <class-name>CourierOblique</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>562</cap-height> <x-height>426</x-height> <ascender>629</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Courier.xml b/src/codegen/Courier.xml index 8ec2e8492..1382b78e1 100644 --- a/src/codegen/Courier.xml +++ b/src/codegen/Courier.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Courier</font-name> <class-name>Courier</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>562</cap-height> <x-height>426</x-height> <ascender>629</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Helvetica-Bold.xml b/src/codegen/Helvetica-Bold.xml index 8e46115db..6322a8964 100644 --- a/src/codegen/Helvetica-Bold.xml +++ b/src/codegen/Helvetica-Bold.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Helvetica-Bold</font-name> <class-name>HelveticaBold</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>718</cap-height> <x-height>532</x-height> <ascender>718</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Helvetica-BoldOblique.xml b/src/codegen/Helvetica-BoldOblique.xml index 777d3564a..ab8c4ce2f 100644 --- a/src/codegen/Helvetica-BoldOblique.xml +++ b/src/codegen/Helvetica-BoldOblique.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Helvetica-BoldOblique</font-name> <class-name>HelveticaBoldOblique</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>718</cap-height> <x-height>532</x-height> <ascender>718</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Helvetica-Oblique.xml b/src/codegen/Helvetica-Oblique.xml index f002086e6..2d3c5ed4e 100644 --- a/src/codegen/Helvetica-Oblique.xml +++ b/src/codegen/Helvetica-Oblique.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Helvetica-Oblique</font-name> <class-name>HelveticaOblique</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>718</cap-height> <x-height>523</x-height> <ascender>718</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Helvetica.xml b/src/codegen/Helvetica.xml index a188996f1..fbbff254f 100644 --- a/src/codegen/Helvetica.xml +++ b/src/codegen/Helvetica.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Helvetica</font-name> <class-name>Helvetica</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>718</cap-height> <x-height>523</x-height> <ascender>718</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Symbol.xml b/src/codegen/Symbol.xml index 8dcb507ef..0776bee01 100644 --- a/src/codegen/Symbol.xml +++ b/src/codegen/Symbol.xml @@ -1,7 +1,7 @@ <font-metrics> <font-name>Symbol</font-name> <class-name>Symbol</class-name> - <encoding>StandardEncoding</encoding> + <encoding>SymbolEncoding</encoding> <cap-height>1010</cap-height> <x-height>520</x-height> <ascender>1010</ascender> diff --git a/src/codegen/Times-Bold.xml b/src/codegen/Times-Bold.xml index fdb7dccfa..519e074e8 100644 --- a/src/codegen/Times-Bold.xml +++ b/src/codegen/Times-Bold.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Times-Bold</font-name> <class-name>TimesBold</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>676</cap-height> <x-height>461</x-height> <ascender>676</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Times-BoldItalic.xml b/src/codegen/Times-BoldItalic.xml index 4bf4e579b..073c6838c 100644 --- a/src/codegen/Times-BoldItalic.xml +++ b/src/codegen/Times-BoldItalic.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Times-BoldItalic</font-name> <class-name>TimesBoldItalic</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>669</cap-height> <x-height>462</x-height> <ascender>699</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Times-Italic.xml b/src/codegen/Times-Italic.xml index 83ab11330..53bdda82c 100644 --- a/src/codegen/Times-Italic.xml +++ b/src/codegen/Times-Italic.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Times-Italic</font-name> <class-name>TimesItalic</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>653</cap-height> <x-height>441</x-height> <ascender>683</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/Times-Roman.xml b/src/codegen/Times-Roman.xml index d22f89e5f..af5b6a59d 100644 --- a/src/codegen/Times-Roman.xml +++ b/src/codegen/Times-Roman.xml @@ -2,7 +2,7 @@ <font-metrics> <font-name>Times-Roman</font-name> <class-name>TimesRoman</class-name> - <encoding>WinAnsiEncoding</encoding> + <encoding>StandardEncoding</encoding> <cap-height>662</cap-height> <x-height>450</x-height> <ascender>683</ascender> @@ -28,6 +28,7 @@ <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"/> diff --git a/src/codegen/ZapfDingbats.xml b/src/codegen/ZapfDingbats.xml index 4e0511937..25b61871c 100644 --- a/src/codegen/ZapfDingbats.xml +++ b/src/codegen/ZapfDingbats.xml @@ -1,7 +1,7 @@ <font-metrics> <font-name>ZapfDingbats</font-name> <class-name>ZapfDingbats</class-name> - <encoding>StandardEncoding</encoding> + <encoding>ZapfDingbatsEncoding</encoding> <cap-height>820</cap-height> <x-height>426</x-height> <ascender>820</ascender> diff --git a/src/codegen/code-point-mapping.xsl b/src/codegen/code-point-mapping.xsl index a3e235cbc..ab4f26da9 100644 --- a/src/codegen/code-point-mapping.xsl +++ b/src/codegen/code-point-mapping.xsl @@ -1,24 +1,101 @@ <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:lxslt="http://xml.apache.org/xslt" - xmlns:redirect="org.apache.xalan.xslt.extensions.Redirect" - extension-element-prefixes="redirect"> -<xsl:output method="text" /> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output method="text"/> + <xsl:variable name='glyphlists' + select="document('glyphlist.xml')/glyphlist-set"/> -<xsl:template match="font-mappings"> -<!-- <redirect:write file="org/apache/fop/render/pdf/CodePointMapping.java"> --> + <xsl:template match="encoding-set"> package org.apache.fop.render.pdf; +import java.util.Hashtable; public class CodePointMapping { - public static char[] map; + private char[] latin1Map; + private char[] characters; + private char[] codepoints; + private CodePointMapping(int [] table) { + int nonLatin1 = 0; + latin1Map = new char[256]; + for(int i = 0; i < table.length; i += 2) { + if(table[i+1] < 256) + latin1Map[table[i+1]] = (char) table[i]; + else + ++nonLatin1; + } + characters = new char[nonLatin1]; + codepoints = new char[nonLatin1]; + int top = 0; + for(int i = 0; i < table.length; i += 2) { + char c = (char) table[i+1]; + if(c >= 256) { + ++top; + for(int j = top - 1; j >= 0; --j) { + if(j > 0 && characters[j-1] >= c) { + characters[j] = characters[j-1]; + codepoints[j] = codepoints[j-1]; + } else { + characters[j] = c; + codepoints[j] = (char) table[i]; + break; + } + } + } + } + } + public final char mapChar(char c) { + if(c < 256) { + return latin1Map[c]; + } else { + int bot = 0, top = characters.length - 1; + while(top >= bot) { + int mid = (bot + top) / 2; + char mc = characters[mid]; + + if(c == mc) + return codepoints[mid]; + else if(c < mc) + top = mid - 1; + else + bot = mid + 1; + } + return 0; + } + } - static { - map = new char[65536]; -<xsl:for-each select="map[@unicode!='-1' and @win-ansi!='-1']"> map[<xsl:value-of select="@unicode"/>] = <xsl:value-of select="@win-ansi"/>; -</xsl:for-each> + private static Hashtable mappings; + static { + mappings = new Hashtable(); + } + public static CodePointMapping getMapping(String encoding) { + CodePointMapping mapping = (CodePointMapping) mappings.get(encoding); + if(mapping != null) { + return mapping; + } <xsl:apply-templates mode="get"/> + else { + return null; } + } +<xsl:apply-templates mode="table"/> } -<!-- </redirect:write>--> -</xsl:template> -</xsl:stylesheet> + </xsl:template> + + <xsl:template match="encoding" mode="get"> + else if(encoding.equals("<xsl:value-of select="@id"/>")) { + mapping = new CodePointMapping(enc<xsl:value-of select="@id"/>); + mappings.put("<xsl:value-of select="@id"/>", mapping); + return mapping; + } + </xsl:template> + <xsl:template match="encoding" mode="table"> + <xsl:variable name="glyphlist-name" select="@glyphlist"/> + <xsl:variable name="glyphlist" + select="$glyphlists/glyphlist[@id=$glyphlist-name]"/> + private static final int[] enc<xsl:value-of select="@id"/> + = {<xsl:for-each select="glyph"> + <xsl:variable name="codepoint" select="@codepoint"/> + <xsl:variable name="name" select="@name"/><xsl:for-each select="$glyphlist/glyph[@name=$name]"> + 0x<xsl:value-of select="$codepoint"/>, 0x<xsl:value-of select="@codepoint"/>, // <xsl:value-of select="$name"/> +</xsl:for-each></xsl:for-each> + }; + </xsl:template> +</xsl:stylesheet> diff --git a/src/codegen/encodings.xml b/src/codegen/encodings.xml new file mode 100644 index 000000000..2566d2e74 --- /dev/null +++ b/src/codegen/encodings.xml @@ -0,0 +1,1633 @@ +<?xml version='1.0'?> +<!DOCTYPE encoding-set [ + <!ELEMENT encoding-set (encoding+)> + <!ELEMENT encoding (glyph+)> + <!ATTLIST encoding id ID #REQUIRED glyphlist CDATA "AGL"> + <!ELEMENT glyph EMPTY> + <!ATTLIST glyph codepoint CDATA #REQUIRED name CDATA #REQUIRED> +]> +<encoding-set> + <encoding id='StandardEncoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quoteright'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='hyphen'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='quoteleft'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7a' name='z'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='a1' name='exclamdown'/> + <glyph codepoint='a2' name='cent'/> + <glyph codepoint='a3' name='sterling'/> + <glyph codepoint='a4' name='fraction'/> + <glyph codepoint='a5' name='yen'/> + <glyph codepoint='a6' name='florin'/> + <glyph codepoint='a7' name='section'/> + <glyph codepoint='a8' name='currency'/> + <glyph codepoint='a9' name='quotesingle'/> + <glyph codepoint='aa' name='quotedblleft'/> + <glyph codepoint='ab' name='guillemotleft'/> + <glyph codepoint='ac' name='guilsinglleft'/> + <glyph codepoint='ad' name='guilsinglright'/> + <glyph codepoint='ae' name='fi'/> + <glyph codepoint='af' name='fl'/> + <glyph codepoint='b1' name='endash'/> + <glyph codepoint='b2' name='dagger'/> + <glyph codepoint='b3' name='daggerdbl'/> + <glyph codepoint='b4' name='periodcentered'/> + <glyph codepoint='b6' name='paragraph'/> + <glyph codepoint='b7' name='bullet'/> + <glyph codepoint='b8' name='quotesinglbase'/> + <glyph codepoint='b9' name='quotedblbase'/> + <glyph codepoint='ba' name='quotedblright'/> + <glyph codepoint='bb' name='guillemotright'/> + <glyph codepoint='bc' name='ellipsis'/> + <glyph codepoint='bd' name='perthousand'/> + <glyph codepoint='bf' name='questiondown'/> + <glyph codepoint='c1' name='grave'/> + <glyph codepoint='c2' name='acute'/> + <glyph codepoint='c3' name='circumflex'/> + <glyph codepoint='c4' name='tilde'/> + <glyph codepoint='c5' name='macron'/> + <glyph codepoint='c6' name='breve'/> + <glyph codepoint='c7' name='dotaccent'/> + <glyph codepoint='c8' name='dieresis'/> + <glyph codepoint='ca' name='ring'/> + <glyph codepoint='cb' name='cedilla'/> + <glyph codepoint='cd' name='hungarumlaut'/> + <glyph codepoint='ce' name='ogonek'/> + <glyph codepoint='cf' name='caron'/> + <glyph codepoint='d0' name='emdash'/> + <glyph codepoint='e1' name='AE'/> + <glyph codepoint='e3' name='ordfeminine'/> + <glyph codepoint='e8' name='Lslash'/> + <glyph codepoint='e9' name='Oslash'/> + <glyph codepoint='ea' name='OE'/> + <glyph codepoint='eb' name='ordmasculine'/> + <glyph codepoint='f1' name='ae'/> + <glyph codepoint='f5' name='dotlessi'/> + <glyph codepoint='f8' name='lslash'/> + <glyph codepoint='f9' name='oslash'/> + <glyph codepoint='fa' name='oe'/> + <glyph codepoint='fb' name='germandbls'/> + </encoding> + <encoding id='ISOLatin1Encoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quoteright'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='minus'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='quoteleft'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7a' name='z'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='90' name='dotlessi'/> + <glyph codepoint='91' name='grave'/> + <glyph codepoint='93' name='circumflex'/> + <glyph codepoint='94' name='tilde'/> + <glyph codepoint='96' name='breve'/> + <glyph codepoint='97' name='dotaccent'/> + <glyph codepoint='9a' name='ring'/> + <glyph codepoint='9d' name='hungarumlaut'/> + <glyph codepoint='9e' name='ogonek'/> + <glyph codepoint='9f' name='caron'/> + <glyph codepoint='a1' name='exclamdown'/> + <glyph codepoint='a2' name='cent'/> + <glyph codepoint='a3' name='sterling'/> + <glyph codepoint='a4' name='currency'/> + <glyph codepoint='a5' name='yen'/> + <glyph codepoint='a6' name='brokenbar'/> + <glyph codepoint='a7' name='section'/> + <glyph codepoint='a8' name='dieresis'/> + <glyph codepoint='a9' name='copyright'/> + <glyph codepoint='aa' name='ordfeminine'/> + <glyph codepoint='ab' name='guillemotleft'/> + <glyph codepoint='ac' name='logicalnot'/> + <glyph codepoint='ad' name='hyphen'/> + <glyph codepoint='ae' name='registered'/> + <glyph codepoint='af' name='macron'/> + <glyph codepoint='b0' name='degree'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b2' name='twosuperior'/> + <glyph codepoint='b3' name='threesuperior'/> + <glyph codepoint='b4' name='acute'/> + <glyph codepoint='b5' name='mu'/> + <glyph codepoint='b6' name='paragraph'/> + <glyph codepoint='b7' name='periodcentered'/> + <glyph codepoint='b8' name='cedilla'/> + <glyph codepoint='b9' name='onesuperior'/> + <glyph codepoint='ba' name='ordmasculine'/> + <glyph codepoint='bb' name='guillemotright'/> + <glyph codepoint='bc' name='onequarter'/> + <glyph codepoint='bd' name='onehalf'/> + <glyph codepoint='be' name='threequarters'/> + <glyph codepoint='bf' name='questiondown'/> + <glyph codepoint='c0' name='Agrave'/> + <glyph codepoint='c1' name='Aacute'/> + <glyph codepoint='c2' name='Acircumflex'/> + <glyph codepoint='c3' name='Atilde'/> + <glyph codepoint='c4' name='Adieresis'/> + <glyph codepoint='c5' name='Aring'/> + <glyph codepoint='c6' name='AE'/> + <glyph codepoint='c7' name='Ccedilla'/> + <glyph codepoint='c8' name='Egrave'/> + <glyph codepoint='c9' name='Eacute'/> + <glyph codepoint='ca' name='Ecircumflex'/> + <glyph codepoint='cb' name='Edieresis'/> + <glyph codepoint='cc' name='Igrave'/> + <glyph codepoint='cd' name='Iacute'/> + <glyph codepoint='ce' name='Icircumflex'/> + <glyph codepoint='cf' name='Idieresis'/> + <glyph codepoint='d0' name='Eth'/> + <glyph codepoint='d1' name='Ntilde'/> + <glyph codepoint='d2' name='Ograve'/> + <glyph codepoint='d3' name='Oacute'/> + <glyph codepoint='d4' name='Ocircumflex'/> + <glyph codepoint='d5' name='Otilde'/> + <glyph codepoint='d6' name='Odieresis'/> + <glyph codepoint='d7' name='multiply'/> + <glyph codepoint='d8' name='Oslash'/> + <glyph codepoint='d9' name='Ugrave'/> + <glyph codepoint='da' name='Uacute'/> + <glyph codepoint='db' name='Ucircumflex'/> + <glyph codepoint='dc' name='Udieresis'/> + <glyph codepoint='dd' name='Yacute'/> + <glyph codepoint='de' name='Thorn'/> + <glyph codepoint='df' name='germandbls'/> + <glyph codepoint='e0' name='agrave'/> + <glyph codepoint='e1' name='aacute'/> + <glyph codepoint='e2' name='acircumflex'/> + <glyph codepoint='e3' name='atilde'/> + <glyph codepoint='e4' name='adieresis'/> + <glyph codepoint='e5' name='aring'/> + <glyph codepoint='e6' name='ae'/> + <glyph codepoint='e7' name='ccedilla'/> + <glyph codepoint='e8' name='egrave'/> + <glyph codepoint='e9' name='eacute'/> + <glyph codepoint='ea' name='ecircumflex'/> + <glyph codepoint='eb' name='edieresis'/> + <glyph codepoint='ec' name='igrave'/> + <glyph codepoint='ed' name='iacute'/> + <glyph codepoint='ee' name='icircumflex'/> + <glyph codepoint='ef' name='idieresis'/> + <glyph codepoint='f0' name='eth'/> + <glyph codepoint='f1' name='ntilde'/> + <glyph codepoint='f2' name='ograve'/> + <glyph codepoint='f3' name='oacute'/> + <glyph codepoint='f4' name='ocircumflex'/> + <glyph codepoint='f5' name='otilde'/> + <glyph codepoint='f6' name='odieresis'/> + <glyph codepoint='f7' name='divide'/> + <glyph codepoint='f8' name='oslash'/> + <glyph codepoint='f9' name='ugrave'/> + <glyph codepoint='fa' name='uacute'/> + <glyph codepoint='fb' name='ucircumflex'/> + <glyph codepoint='fc' name='udieresis'/> + <glyph codepoint='fd' name='yacute'/> + <glyph codepoint='fe' name='thorn'/> + <glyph codepoint='ff' name='ydieresis'/> + </encoding> + <encoding id='CEEncoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quotesingle'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='hyphen'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='grave'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7a' name='z'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='82' name='quotesinglbase'/> + <glyph codepoint='84' name='quotedblbase'/> + <glyph codepoint='85' name='ellipsis'/> + <glyph codepoint='86' name='dagger'/> + <glyph codepoint='87' name='daggerdbl'/> + <glyph codepoint='89' name='perthousand'/> + <glyph codepoint='8a' name='Scaron'/> + <glyph codepoint='8b' name='guilsinglleft'/> + <glyph codepoint='8c' name='Sacute'/> + <glyph codepoint='8d' name='Tcaron'/> + <glyph codepoint='8e' name='Zcaron'/> + <glyph codepoint='8f' name='Zacute'/> + <glyph codepoint='91' name='quoteleft'/> + <glyph codepoint='92' name='quoteright'/> + <glyph codepoint='93' name='quotedblleft'/> + <glyph codepoint='94' name='quotedblright'/> + <glyph codepoint='95' name='bullet'/> + <glyph codepoint='96' name='endash'/> + <glyph codepoint='97' name='emdash'/> + <glyph codepoint='99' name='trademark'/> + <glyph codepoint='9a' name='scaron'/> + <glyph codepoint='9b' name='guilsinglright'/> + <glyph codepoint='9c' name='sacute'/> + <glyph codepoint='9d' name='tcaron'/> + <glyph codepoint='9e' name='zcaron'/> + <glyph codepoint='9f' name='zacute'/> + <glyph codepoint='a1' name='caron'/> + <glyph codepoint='a2' name='breve'/> + <glyph codepoint='a3' name='Lslash'/> + <glyph codepoint='a4' name='currency'/> + <glyph codepoint='a5' name='Aogonek'/> + <glyph codepoint='a6' name='brokenbar'/> + <glyph codepoint='a7' name='section'/> + <glyph codepoint='a8' name='dieresis'/> + <glyph codepoint='a9' name='copyright'/> + <glyph codepoint='aa' name='Scommaaccent'/> + <glyph codepoint='ab' name='guillemotleft'/> + <glyph codepoint='ac' name='logicalnot'/> + <glyph codepoint='ae' name='registered'/> + <glyph codepoint='af' name='Zdotaccent'/> + <glyph codepoint='b0' name='degree'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b2' name='ogonek'/> + <glyph codepoint='b3' name='lslash'/> + <glyph codepoint='b4' name='acute'/> + <glyph codepoint='b5' name='mu'/> + <glyph codepoint='b6' name='paragraph'/> + <glyph codepoint='b7' name='periodcentered'/> + <glyph codepoint='b8' name='cedilla'/> + <glyph codepoint='b9' name='aogonek'/> + <glyph codepoint='ba' name='scommaaccent'/> + <glyph codepoint='bb' name='guillemotright'/> + <glyph codepoint='bc' name='Lcaron'/> + <glyph codepoint='bd' name='hungarumlaut'/> + <glyph codepoint='be' name='lcaron'/> + <glyph codepoint='bf' name='zdotaccent'/> + <glyph codepoint='c0' name='Racute'/> + <glyph codepoint='c1' name='Aacute'/> + <glyph codepoint='c2' name='Acircumflex'/> + <glyph codepoint='c3' name='Abreve'/> + <glyph codepoint='c4' name='Adieresis'/> + <glyph codepoint='c5' name='Lacute'/> + <glyph codepoint='c6' name='Cacute'/> + <glyph codepoint='c7' name='Ccedilla'/> + <glyph codepoint='c8' name='Ccaron'/> + <glyph codepoint='c9' name='Eacute'/> + <glyph codepoint='ca' name='Eogonek'/> + <glyph codepoint='cb' name='Edieresis'/> + <glyph codepoint='cc' name='Ecaron'/> + <glyph codepoint='cd' name='Iacute'/> + <glyph codepoint='ce' name='Icircumflex'/> + <glyph codepoint='cf' name='Dcaron'/> + <glyph codepoint='d0' name='Dcroat'/> + <glyph codepoint='d1' name='Nacute'/> + <glyph codepoint='d2' name='Ncaron'/> + <glyph codepoint='d3' name='Oacute'/> + <glyph codepoint='d4' name='Ocircumflex'/> + <glyph codepoint='d5' name='Ohungarumlaut'/> + <glyph codepoint='d6' name='Odieresis'/> + <glyph codepoint='d7' name='multiply'/> + <glyph codepoint='d8' name='Rcaron'/> + <glyph codepoint='d9' name='Uring'/> + <glyph codepoint='da' name='Uacute'/> + <glyph codepoint='db' name='Uhungarumlaut'/> + <glyph codepoint='dc' name='Udieresis'/> + <glyph codepoint='dd' name='Yacute'/> + <glyph codepoint='de' name='Tcommaaccent'/> + <glyph codepoint='df' name='germandbls'/> + <glyph codepoint='e0' name='racute'/> + <glyph codepoint='e1' name='aacute'/> + <glyph codepoint='e2' name='acircumflex'/> + <glyph codepoint='e3' name='abreve'/> + <glyph codepoint='e4' name='adieresis'/> + <glyph codepoint='e5' name='lacute'/> + <glyph codepoint='e6' name='cacute'/> + <glyph codepoint='e7' name='ccedilla'/> + <glyph codepoint='e8' name='ccaron'/> + <glyph codepoint='e9' name='eacute'/> + <glyph codepoint='ea' name='eogonek'/> + <glyph codepoint='eb' name='edieresis'/> + <glyph codepoint='ec' name='ecaron'/> + <glyph codepoint='ed' name='iacute'/> + <glyph codepoint='ee' name='icircumflex'/> + <glyph codepoint='ef' name='dcaron'/> + <glyph codepoint='f0' name='dcroat'/> + <glyph codepoint='f1' name='nacute'/> + <glyph codepoint='f2' name='ncaron'/> + <glyph codepoint='f3' name='oacute'/> + <glyph codepoint='f4' name='ocircumflex'/> + <glyph codepoint='f5' name='ohungarumlaut'/> + <glyph codepoint='f6' name='odieresis'/> + <glyph codepoint='f7' name='divide'/> + <glyph codepoint='f8' name='rcaron'/> + <glyph codepoint='f9' name='uring'/> + <glyph codepoint='fa' name='uacute'/> + <glyph codepoint='fb' name='uhungarumlaut'/> + <glyph codepoint='fc' name='udieresis'/> + <glyph codepoint='fd' name='yacute'/> + <glyph codepoint='fe' name='tcommaaccent'/> + <glyph codepoint='ff' name='dotaccent'/> + </encoding> + <encoding id='MacRomanEncoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quotesingle'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='hyphen'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='grave'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='80' name='Adieresis'/> + <glyph codepoint='81' name='Aring'/> + <glyph codepoint='82' name='Ccedilla'/> + <glyph codepoint='83' name='Eacute'/> + <glyph codepoint='84' name='Ntilde'/> + <glyph codepoint='85' name='Odieresis'/> + <glyph codepoint='86' name='Udieresis'/> + <glyph codepoint='87' name='aacute'/> + <glyph codepoint='88' name='agrave'/> + <glyph codepoint='89' name='acircumflex'/> + <glyph codepoint='8a' name='adieresis'/> + <glyph codepoint='8b' name='atilde'/> + <glyph codepoint='8c' name='aring'/> + <glyph codepoint='8d' name='ccedilla'/> + <glyph codepoint='8e' name='eacute'/> + <glyph codepoint='8f' name='egrave'/> + <glyph codepoint='90' name='ecircumflex'/> + <glyph codepoint='91' name='edieresis'/> + <glyph codepoint='92' name='iacute'/> + <glyph codepoint='93' name='igrave'/> + <glyph codepoint='94' name='icircumflex'/> + <glyph codepoint='95' name='idieresis'/> + <glyph codepoint='96' name='ntilde'/> + <glyph codepoint='97' name='oacute'/> + <glyph codepoint='98' name='ograve'/> + <glyph codepoint='99' name='ocircumflex'/> + <glyph codepoint='9a' name='odieresis'/> + <glyph codepoint='9b' name='otilde'/> + <glyph codepoint='9c' name='uacute'/> + <glyph codepoint='9d' name='ugrave'/> + <glyph codepoint='9e' name='ucircumflex'/> + <glyph codepoint='9f' name='udieresis'/> + <glyph codepoint='a0' name='dagger'/> + <glyph codepoint='a1' name='degree'/> + <glyph codepoint='a2' name='cent'/> + <glyph codepoint='a3' name='sterling'/> + <glyph codepoint='a4' name='section'/> + <glyph codepoint='a5' name='bullet'/> + <glyph codepoint='a6' name='paragraph'/> + <glyph codepoint='a7' name='germandbls'/> + <glyph codepoint='a8' name='registered'/> + <glyph codepoint='a9' name='copyright'/> + <glyph codepoint='aa' name='trademark'/> + <glyph codepoint='ab' name='acute'/> + <glyph codepoint='ac' name='dieresis'/> + <glyph codepoint='ae' name='AE'/> + <glyph codepoint='af' name='Oslash'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b5' name='mu'/> + <glyph codepoint='bb' name='ordfeminine'/> + <glyph codepoint='bc' name='ordmasculine'/> + <glyph codepoint='be' name='ae'/> + <glyph codepoint='bf' name='oslash'/> + <glyph codepoint='c0' name='questiondown'/> + <glyph codepoint='c1' name='exclamdown'/> + <glyph codepoint='c2' name='logicalnot'/> + <glyph codepoint='c4' name='florin'/> + <glyph codepoint='c7' name='guillemotleft'/> + <glyph codepoint='c8' name='guillemotright'/> + <glyph codepoint='c9' name='ellipsis'/> + <glyph codepoint='cb' name='Agrave'/> + <glyph codepoint='cc' name='Atilde'/> + <glyph codepoint='cd' name='Otilde'/> + <glyph codepoint='ce' name='OE'/> + <glyph codepoint='cf' name='oe'/> + <glyph codepoint='d0' name='endash'/> + <glyph codepoint='d1' name='emdash'/> + <glyph codepoint='d2' name='quotedblleft'/> + <glyph codepoint='d3' name='quotedblright'/> + <glyph codepoint='d4' name='quoteleft'/> + <glyph codepoint='d5' name='quoteright'/> + <glyph codepoint='d6' name='divide'/> + <glyph codepoint='d9' name='Ydieresis'/> + <glyph codepoint='da' name='fraction'/> + <glyph codepoint='db' name='currency'/> + <glyph codepoint='dc' name='guilsinglleft'/> + <glyph codepoint='dd' name='guilsinglright'/> + <glyph codepoint='de' name='fi'/> + <glyph codepoint='df' name='fl'/> + <glyph codepoint='e0' name='daggerdbl'/> + <glyph codepoint='e1' name='periodcentered'/> + <glyph codepoint='e2' name='quotesinglbase'/> + <glyph codepoint='e3' name='quotedblbase'/> + <glyph codepoint='e4' name='perthousand'/> + <glyph codepoint='e5' name='Acircumflex'/> + <glyph codepoint='e6' name='Ecircumflex'/> + <glyph codepoint='e7' name='Aacute'/> + <glyph codepoint='e8' name='Edieresis'/> + <glyph codepoint='e9' name='Egrave'/> + <glyph codepoint='ea' name='Iacute'/> + <glyph codepoint='eb' name='Icircumflex'/> + <glyph codepoint='ec' name='Idieresis'/> + <glyph codepoint='ed' name='Igrave'/> + <glyph codepoint='ee' name='Oacute'/> + <glyph codepoint='ef' name='Ocircumflex'/> + <glyph codepoint='f1' name='Ograve'/> + <glyph codepoint='f2' name='Uacute'/> + <glyph codepoint='f3' name='Ucircumflex'/> + <glyph codepoint='f4' name='Ugrave'/> + <glyph codepoint='f5' name='dotlessi'/> + <glyph codepoint='f6' name='circumflex'/> + <glyph codepoint='f7' name='tilde'/> + <glyph codepoint='f8' name='macron'/> + <glyph codepoint='f9' name='breve'/> + <glyph codepoint='fa' name='dotaccent'/> + <glyph codepoint='fb' name='ring'/> + <glyph codepoint='fc' name='cedilla'/> + <glyph codepoint='fd' name='hungarumlaut'/> + <glyph codepoint='fe' name='ogonek'/> + <glyph codepoint='ff' name='caron'/> + <glyph codepoint='d8' name='ydieresis'/> + <glyph codepoint='b4' name='yen'/> + <glyph codepoint='7a' name='z'/> + </encoding> + <encoding id='WinAnsiEncoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quotesingle'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='hyphen'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='grave'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7a' name='z'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='80' name='Euro'/> + <glyph codepoint='82' name='quotesinglbase'/> + <glyph codepoint='83' name='florin'/> + <glyph codepoint='84' name='quotedblbase'/> + <glyph codepoint='85' name='ellipsis'/> + <glyph codepoint='86' name='dagger'/> + <glyph codepoint='87' name='daggerdbl'/> + <glyph codepoint='88' name='circumflex'/> + <glyph codepoint='89' name='perthousand'/> + <glyph codepoint='8a' name='Scaron'/> + <glyph codepoint='8b' name='guilsinglleft'/> + <glyph codepoint='8c' name='OE'/> + <glyph codepoint='8e' name='Zcaron'/> + <glyph codepoint='91' name='quoteleft'/> + <glyph codepoint='92' name='quoteright'/> + <glyph codepoint='93' name='quotedblleft'/> + <glyph codepoint='94' name='quotedblright'/> + <glyph codepoint='95' name='bullet'/> + <glyph codepoint='96' name='endash'/> + <glyph codepoint='97' name='emdash'/> + <glyph codepoint='98' name='tilde'/> + <glyph codepoint='99' name='trademark'/> + <glyph codepoint='9a' name='scaron'/> + <glyph codepoint='9b' name='guilsinglright'/> + <glyph codepoint='9c' name='oe'/> + <glyph codepoint='9e' name='zcaron'/> + <glyph codepoint='9f' name='Ydieresis'/> + <glyph codepoint='a1' name='exclamdown'/> + <glyph codepoint='a2' name='cent'/> + <glyph codepoint='a3' name='sterling'/> + <glyph codepoint='a4' name='currency'/> + <glyph codepoint='a5' name='yen'/> + <glyph codepoint='a6' name='brokenbar'/> + <glyph codepoint='a7' name='section'/> + <glyph codepoint='a8' name='dieresis'/> + <glyph codepoint='a9' name='copyright'/> + <glyph codepoint='aa' name='ordfeminine'/> + <glyph codepoint='ab' name='guillemotleft'/> + <glyph codepoint='ac' name='logicalnot'/> + <glyph codepoint='ae' name='registered'/> + <glyph codepoint='af' name='macron'/> + <glyph codepoint='b0' name='degree'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b2' name='twosuperior'/> + <glyph codepoint='b3' name='threesuperior'/> + <glyph codepoint='b4' name='acute'/> + <glyph codepoint='b5' name='mu'/> + <glyph codepoint='b6' name='paragraph'/> + <glyph codepoint='b7' name='periodcentered'/> + <glyph codepoint='b8' name='cedilla'/> + <glyph codepoint='b9' name='onesuperior'/> + <glyph codepoint='ba' name='ordmasculine'/> + <glyph codepoint='bb' name='guillemotright'/> + <glyph codepoint='bc' name='onequarter'/> + <glyph codepoint='bd' name='onehalf'/> + <glyph codepoint='be' name='threequarters'/> + <glyph codepoint='bf' name='questiondown'/> + <glyph codepoint='c0' name='Agrave'/> + <glyph codepoint='c1' name='Aacute'/> + <glyph codepoint='c2' name='Acircumflex'/> + <glyph codepoint='c3' name='Atilde'/> + <glyph codepoint='c4' name='Adieresis'/> + <glyph codepoint='c5' name='Aring'/> + <glyph codepoint='c6' name='AE'/> + <glyph codepoint='c7' name='Ccedilla'/> + <glyph codepoint='c8' name='Egrave'/> + <glyph codepoint='c9' name='Eacute'/> + <glyph codepoint='ca' name='Ecircumflex'/> + <glyph codepoint='cb' name='Edieresis'/> + <glyph codepoint='cc' name='Igrave'/> + <glyph codepoint='cd' name='Iacute'/> + <glyph codepoint='ce' name='Icircumflex'/> + <glyph codepoint='cf' name='Idieresis'/> + <glyph codepoint='d0' name='Eth'/> + <glyph codepoint='d1' name='Ntilde'/> + <glyph codepoint='d2' name='Ograve'/> + <glyph codepoint='d3' name='Oacute'/> + <glyph codepoint='d4' name='Ocircumflex'/> + <glyph codepoint='d5' name='Otilde'/> + <glyph codepoint='d6' name='Odieresis'/> + <glyph codepoint='d7' name='multiply'/> + <glyph codepoint='d8' name='Oslash'/> + <glyph codepoint='d9' name='Ugrave'/> + <glyph codepoint='da' name='Uacute'/> + <glyph codepoint='db' name='Ucircumflex'/> + <glyph codepoint='dc' name='Udieresis'/> + <glyph codepoint='dd' name='Yacute'/> + <glyph codepoint='de' name='Thorn'/> + <glyph codepoint='df' name='germandbls'/> + <glyph codepoint='e0' name='agrave'/> + <glyph codepoint='e1' name='aacute'/> + <glyph codepoint='e2' name='acircumflex'/> + <glyph codepoint='e3' name='atilde'/> + <glyph codepoint='e4' name='adieresis'/> + <glyph codepoint='e5' name='aring'/> + <glyph codepoint='e6' name='ae'/> + <glyph codepoint='e7' name='ccedilla'/> + <glyph codepoint='e8' name='egrave'/> + <glyph codepoint='e9' name='eacute'/> + <glyph codepoint='ea' name='ecircumflex'/> + <glyph codepoint='eb' name='edieresis'/> + <glyph codepoint='ec' name='igrave'/> + <glyph codepoint='ed' name='iacute'/> + <glyph codepoint='ee' name='icircumflex'/> + <glyph codepoint='ef' name='idieresis'/> + <glyph codepoint='f0' name='eth'/> + <glyph codepoint='f1' name='ntilde'/> + <glyph codepoint='f2' name='ograve'/> + <glyph codepoint='f3' name='oacute'/> + <glyph codepoint='f4' name='ocircumflex'/> + <glyph codepoint='f5' name='otilde'/> + <glyph codepoint='f6' name='odieresis'/> + <glyph codepoint='f7' name='divide'/> + <glyph codepoint='f8' name='oslash'/> + <glyph codepoint='f9' name='ugrave'/> + <glyph codepoint='fa' name='uacute'/> + <glyph codepoint='fb' name='ucircumflex'/> + <glyph codepoint='fc' name='udieresis'/> + <glyph codepoint='fd' name='yacute'/> + <glyph codepoint='fe' name='thorn'/> + <glyph codepoint='ff' name='ydieresis'/> + </encoding> + <encoding id='PDFDocEncoding' glyphlist='AGL'> + <glyph codepoint='18' name='breve'/> + <glyph codepoint='19' name='caron'/> + <glyph codepoint='1a' name='circumflex'/> + <glyph codepoint='1b' name='dotaccent'/> + <glyph codepoint='1c' name='hungarumlaut'/> + <glyph codepoint='1d' name='ogonek'/> + <glyph codepoint='1e' name='ring'/> + <glyph codepoint='1f' name='tilde'/> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='quotedbl'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='dollar'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='quotesingle'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asterisk'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='hyphen'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='at'/> + <glyph codepoint='41' name='A'/> + <glyph codepoint='42' name='B'/> + <glyph codepoint='43' name='C'/> + <glyph codepoint='44' name='D'/> + <glyph codepoint='45' name='E'/> + <glyph codepoint='46' name='F'/> + <glyph codepoint='47' name='G'/> + <glyph codepoint='48' name='H'/> + <glyph codepoint='49' name='I'/> + <glyph codepoint='4a' name='J'/> + <glyph codepoint='4b' name='K'/> + <glyph codepoint='4c' name='L'/> + <glyph codepoint='4d' name='M'/> + <glyph codepoint='4e' name='N'/> + <glyph codepoint='4f' name='O'/> + <glyph codepoint='50' name='P'/> + <glyph codepoint='51' name='Q'/> + <glyph codepoint='52' name='R'/> + <glyph codepoint='53' name='S'/> + <glyph codepoint='54' name='T'/> + <glyph codepoint='55' name='U'/> + <glyph codepoint='56' name='V'/> + <glyph codepoint='57' name='W'/> + <glyph codepoint='58' name='X'/> + <glyph codepoint='59' name='Y'/> + <glyph codepoint='5a' name='Z'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='backslash'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='asciicircum'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='grave'/> + <glyph codepoint='61' name='a'/> + <glyph codepoint='62' name='b'/> + <glyph codepoint='63' name='c'/> + <glyph codepoint='64' name='d'/> + <glyph codepoint='65' name='e'/> + <glyph codepoint='66' name='f'/> + <glyph codepoint='67' name='g'/> + <glyph codepoint='68' name='h'/> + <glyph codepoint='69' name='i'/> + <glyph codepoint='6a' name='j'/> + <glyph codepoint='6b' name='k'/> + <glyph codepoint='6c' name='l'/> + <glyph codepoint='6d' name='m'/> + <glyph codepoint='6e' name='n'/> + <glyph codepoint='6f' name='o'/> + <glyph codepoint='70' name='p'/> + <glyph codepoint='71' name='q'/> + <glyph codepoint='72' name='r'/> + <glyph codepoint='73' name='s'/> + <glyph codepoint='74' name='t'/> + <glyph codepoint='75' name='u'/> + <glyph codepoint='76' name='v'/> + <glyph codepoint='77' name='w'/> + <glyph codepoint='78' name='x'/> + <glyph codepoint='79' name='y'/> + <glyph codepoint='7a' name='z'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='asciitilde'/> + <glyph codepoint='80' name='bullet'/> + <glyph codepoint='81' name='dagger'/> + <glyph codepoint='82' name='daggerdbl'/> + <glyph codepoint='83' name='ellipsis'/> + <glyph codepoint='84' name='emdash'/> + <glyph codepoint='85' name='endash'/> + <glyph codepoint='86' name='florin'/> + <glyph codepoint='87' name='fraction'/> + <glyph codepoint='88' name='guilsinglleft'/> + <glyph codepoint='89' name='guilsinglright'/> + <glyph codepoint='8a' name='minus'/> + <glyph codepoint='8b' name='perthousand'/> + <glyph codepoint='8c' name='quotedblbase'/> + <glyph codepoint='8d' name='quotedblleft'/> + <glyph codepoint='8e' name='quotedblright'/> + <glyph codepoint='8f' name='quoteleft'/> + <glyph codepoint='90' name='quoteright'/> + <glyph codepoint='91' name='quotesinglbase'/> + <glyph codepoint='92' name='trademark'/> + <glyph codepoint='93' name='fi'/> + <glyph codepoint='94' name='fl'/> + <glyph codepoint='95' name='Lslash'/> + <glyph codepoint='96' name='OE'/> + <glyph codepoint='97' name='Scaron'/> + <glyph codepoint='98' name='Ydieresis'/> + <glyph codepoint='99' name='Zcaron'/> + <glyph codepoint='9a' name='dotlessi'/> + <glyph codepoint='9b' name='lslash'/> + <glyph codepoint='9c' name='oe'/> + <glyph codepoint='9d' name='scaron'/> + <glyph codepoint='9e' name='zcaron'/> + <glyph codepoint='a0' name='Euro'/> + <glyph codepoint='a1' name='exclamdown'/> + <glyph codepoint='a2' name='cent'/> + <glyph codepoint='a3' name='sterling'/> + <glyph codepoint='a4' name='currency'/> + <glyph codepoint='a5' name='yen'/> + <glyph codepoint='a6' name='brokenbar'/> + <glyph codepoint='a7' name='section'/> + <glyph codepoint='a8' name='dieresis'/> + <glyph codepoint='a9' name='copyright'/> + <glyph codepoint='aa' name='ordfeminine'/> + <glyph codepoint='ab' name='guillemotleft'/> + <glyph codepoint='ac' name='logicalnot'/> + <glyph codepoint='ae' name='registered'/> + <glyph codepoint='af' name='macron'/> + <glyph codepoint='b0' name='degree'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b2' name='twosuperior'/> + <glyph codepoint='b3' name='threesuperior'/> + <glyph codepoint='b4' name='acute'/> + <glyph codepoint='b5' name='mu'/> + <glyph codepoint='b6' name='paragraph'/> + <glyph codepoint='b7' name='periodcentered'/> + <glyph codepoint='b8' name='cedilla'/> + <glyph codepoint='b9' name='onesuperior'/> + <glyph codepoint='ba' name='ordmasculine'/> + <glyph codepoint='bb' name='guillemotright'/> + <glyph codepoint='bc' name='onequarter'/> + <glyph codepoint='bd' name='onehalf'/> + <glyph codepoint='be' name='threequarters'/> + <glyph codepoint='bf' name='questiondown'/> + <glyph codepoint='c0' name='Agrave'/> + <glyph codepoint='c1' name='Aacute'/> + <glyph codepoint='c2' name='Acircumflex'/> + <glyph codepoint='c3' name='Atilde'/> + <glyph codepoint='c4' name='Adieresis'/> + <glyph codepoint='c5' name='Aring'/> + <glyph codepoint='c6' name='AE'/> + <glyph codepoint='c7' name='Ccedilla'/> + <glyph codepoint='c8' name='Egrave'/> + <glyph codepoint='c9' name='Eacute'/> + <glyph codepoint='ca' name='Ecircumflex'/> + <glyph codepoint='cb' name='Edieresis'/> + <glyph codepoint='cc' name='Igrave'/> + <glyph codepoint='cd' name='Iacute'/> + <glyph codepoint='ce' name='Icircumflex'/> + <glyph codepoint='cf' name='Idieresis'/> + <glyph codepoint='d0' name='Eth'/> + <glyph codepoint='d1' name='Ntilde'/> + <glyph codepoint='d2' name='Ograve'/> + <glyph codepoint='d3' name='Oacute'/> + <glyph codepoint='d4' name='Ocircumflex'/> + <glyph codepoint='d5' name='Otilde'/> + <glyph codepoint='d6' name='Odieresis'/> + <glyph codepoint='d7' name='multiply'/> + <glyph codepoint='d8' name='Oslash'/> + <glyph codepoint='d9' name='Ugrave'/> + <glyph codepoint='da' name='Uacute'/> + <glyph codepoint='db' name='Ucircumflex'/> + <glyph codepoint='dc' name='Udieresis'/> + <glyph codepoint='dd' name='Yacute'/> + <glyph codepoint='de' name='Thorn'/> + <glyph codepoint='df' name='germandbls'/> + <glyph codepoint='e0' name='agrave'/> + <glyph codepoint='e1' name='aacute'/> + <glyph codepoint='e2' name='acircumflex'/> + <glyph codepoint='e3' name='atilde'/> + <glyph codepoint='e4' name='adieresis'/> + <glyph codepoint='e5' name='aring'/> + <glyph codepoint='e6' name='ae'/> + <glyph codepoint='e7' name='ccedilla'/> + <glyph codepoint='e8' name='egrave'/> + <glyph codepoint='e9' name='eacute'/> + <glyph codepoint='ea' name='ecircumflex'/> + <glyph codepoint='eb' name='edieresis'/> + <glyph codepoint='ec' name='igrave'/> + <glyph codepoint='ed' name='iacute'/> + <glyph codepoint='ee' name='icircumflex'/> + <glyph codepoint='ef' name='idieresis'/> + <glyph codepoint='f0' name='eth'/> + <glyph codepoint='f1' name='ntilde'/> + <glyph codepoint='f2' name='ograve'/> + <glyph codepoint='f3' name='oacute'/> + <glyph codepoint='f4' name='ocircumflex'/> + <glyph codepoint='f5' name='otilde'/> + <glyph codepoint='f6' name='odieresis'/> + <glyph codepoint='f7' name='divide'/> + <glyph codepoint='f8' name='oslash'/> + <glyph codepoint='f9' name='ugrave'/> + <glyph codepoint='fa' name='uacute'/> + <glyph codepoint='fb' name='ucircumflex'/> + <glyph codepoint='fc' name='udieresis'/> + <glyph codepoint='fd' name='yacute'/> + <glyph codepoint='fe' name='thorn'/> + <glyph codepoint='ff' name='ydieresis'/> + </encoding> + <encoding id='SymbolEncoding' glyphlist='AGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='exclam'/> + <glyph codepoint='22' name='universal'/> + <glyph codepoint='23' name='numbersign'/> + <glyph codepoint='24' name='existential'/> + <glyph codepoint='25' name='percent'/> + <glyph codepoint='26' name='ampersand'/> + <glyph codepoint='27' name='suchthat'/> + <glyph codepoint='28' name='parenleft'/> + <glyph codepoint='29' name='parenright'/> + <glyph codepoint='2a' name='asteriskmath'/> + <glyph codepoint='2b' name='plus'/> + <glyph codepoint='2c' name='comma'/> + <glyph codepoint='2d' name='minus'/> + <glyph codepoint='2e' name='period'/> + <glyph codepoint='2f' name='slash'/> + <glyph codepoint='30' name='zero'/> + <glyph codepoint='31' name='one'/> + <glyph codepoint='32' name='two'/> + <glyph codepoint='33' name='three'/> + <glyph codepoint='34' name='four'/> + <glyph codepoint='35' name='five'/> + <glyph codepoint='36' name='six'/> + <glyph codepoint='37' name='seven'/> + <glyph codepoint='38' name='eight'/> + <glyph codepoint='39' name='nine'/> + <glyph codepoint='3a' name='colon'/> + <glyph codepoint='3b' name='semicolon'/> + <glyph codepoint='3c' name='less'/> + <glyph codepoint='3d' name='equal'/> + <glyph codepoint='3e' name='greater'/> + <glyph codepoint='3f' name='question'/> + <glyph codepoint='40' name='congruent'/> + <glyph codepoint='41' name='Alpha'/> + <glyph codepoint='42' name='Beta'/> + <glyph codepoint='43' name='Chi'/> + <glyph codepoint='44' name='Delta'/> + <glyph codepoint='45' name='Epsilon'/> + <glyph codepoint='46' name='Phi'/> + <glyph codepoint='47' name='Gamma'/> + <glyph codepoint='48' name='Eta'/> + <glyph codepoint='49' name='Iota'/> + <glyph codepoint='4a' name='theta1'/> + <glyph codepoint='4b' name='Kappa'/> + <glyph codepoint='4c' name='Lambda'/> + <glyph codepoint='4d' name='Mu'/> + <glyph codepoint='4e' name='Nu'/> + <glyph codepoint='4f' name='Omicron'/> + <glyph codepoint='50' name='Pi'/> + <glyph codepoint='51' name='Theta'/> + <glyph codepoint='52' name='Rho'/> + <glyph codepoint='53' name='Sigma'/> + <glyph codepoint='54' name='Tau'/> + <glyph codepoint='55' name='Upsilon'/> + <glyph codepoint='56' name='sigma1'/> + <glyph codepoint='57' name='Omega'/> + <glyph codepoint='58' name='Xi'/> + <glyph codepoint='59' name='Psi'/> + <glyph codepoint='5a' name='Zeta'/> + <glyph codepoint='5b' name='bracketleft'/> + <glyph codepoint='5c' name='therefore'/> + <glyph codepoint='5d' name='bracketright'/> + <glyph codepoint='5e' name='perpendicular'/> + <glyph codepoint='5f' name='underscore'/> + <glyph codepoint='60' name='radicalex'/> + <glyph codepoint='61' name='alpha'/> + <glyph codepoint='62' name='beta'/> + <glyph codepoint='63' name='chi'/> + <glyph codepoint='64' name='delta'/> + <glyph codepoint='65' name='epsilon'/> + <glyph codepoint='66' name='phi'/> + <glyph codepoint='67' name='gamma'/> + <glyph codepoint='68' name='eta'/> + <glyph codepoint='69' name='iota'/> + <glyph codepoint='6a' name='phi1'/> + <glyph codepoint='6b' name='kappa'/> + <glyph codepoint='6c' name='lambda'/> + <glyph codepoint='6d' name='mu'/> + <glyph codepoint='6e' name='nu'/> + <glyph codepoint='6f' name='omicron'/> + <glyph codepoint='70' name='pi'/> + <glyph codepoint='71' name='theta'/> + <glyph codepoint='72' name='rho'/> + <glyph codepoint='73' name='sigma'/> + <glyph codepoint='74' name='tau'/> + <glyph codepoint='75' name='upsilon'/> + <glyph codepoint='76' name='omega1'/> + <glyph codepoint='77' name='omega'/> + <glyph codepoint='78' name='xi'/> + <glyph codepoint='79' name='psi'/> + <glyph codepoint='7a' name='zeta'/> + <glyph codepoint='7b' name='braceleft'/> + <glyph codepoint='7c' name='bar'/> + <glyph codepoint='7d' name='braceright'/> + <glyph codepoint='7e' name='similar'/> + <glyph codepoint='a0' name='Euro'/> + <glyph codepoint='a1' name='Upsilon1'/> + <glyph codepoint='a2' name='minute'/> + <glyph codepoint='a3' name='lessequal'/> + <glyph codepoint='a4' name='fraction'/> + <glyph codepoint='a5' name='infinity'/> + <glyph codepoint='a6' name='florin'/> + <glyph codepoint='a7' name='club'/> + <glyph codepoint='a8' name='diamond'/> + <glyph codepoint='a9' name='heart'/> + <glyph codepoint='aa' name='spade'/> + <glyph codepoint='ab' name='arrowboth'/> + <glyph codepoint='ac' name='arrowleft'/> + <glyph codepoint='ad' name='arrowup'/> + <glyph codepoint='ae' name='arrowright'/> + <glyph codepoint='af' name='arrowdown'/> + <glyph codepoint='b0' name='degree'/> + <glyph codepoint='b1' name='plusminus'/> + <glyph codepoint='b2' name='second'/> + <glyph codepoint='b3' name='greaterequal'/> + <glyph codepoint='b4' name='multiply'/> + <glyph codepoint='b5' name='proportional'/> + <glyph codepoint='b6' name='partialdiff'/> + <glyph codepoint='b7' name='bullet'/> + <glyph codepoint='b8' name='divide'/> + <glyph codepoint='b9' name='notequal'/> + <glyph codepoint='ba' name='equivalence'/> + <glyph codepoint='bb' name='approxequal'/> + <glyph codepoint='bc' name='ellipsis'/> + <glyph codepoint='bd' name='arrowvertex'/> + <glyph codepoint='be' name='arrowhorizex'/> + <glyph codepoint='bf' name='carriagereturn'/> + <glyph codepoint='c0' name='aleph'/> + <glyph codepoint='c1' name='Ifraktur'/> + <glyph codepoint='c2' name='Rfraktur'/> + <glyph codepoint='c3' name='weierstrass'/> + <glyph codepoint='c4' name='circlemultiply'/> + <glyph codepoint='c5' name='circleplus'/> + <glyph codepoint='c6' name='emptyset'/> + <glyph codepoint='c7' name='intersection'/> + <glyph codepoint='c8' name='union'/> + <glyph codepoint='c9' name='propersuperset'/> + <glyph codepoint='ca' name='reflexsuperset'/> + <glyph codepoint='cb' name='notsubset'/> + <glyph codepoint='cc' name='propersubset'/> + <glyph codepoint='cd' name='reflexsubset'/> + <glyph codepoint='ce' name='element'/> + <glyph codepoint='cf' name='notelement'/> + <glyph codepoint='d0' name='angle'/> + <glyph codepoint='d1' name='gradient'/> + <glyph codepoint='d2' name='registerserif'/> + <glyph codepoint='d3' name='copyrightserif'/> + <glyph codepoint='d4' name='trademarkserif'/> + <glyph codepoint='d5' name='product'/> + <glyph codepoint='d6' name='radical'/> + <glyph codepoint='d7' name='dotmath'/> + <glyph codepoint='d8' name='logicalnot'/> + <glyph codepoint='d9' name='logicaland'/> + <glyph codepoint='da' name='logicalor'/> + <glyph codepoint='db' name='arrowdblboth'/> + <glyph codepoint='dc' name='arrowdblleft'/> + <glyph codepoint='dd' name='arrowdblup'/> + <glyph codepoint='de' name='arrowdblright'/> + <glyph codepoint='df' name='arrowdbldown'/> + <glyph codepoint='e0' name='lozenge'/> + <glyph codepoint='e1' name='angleleft'/> + <glyph codepoint='e2' name='registersans'/> + <glyph codepoint='e3' name='copyrightsans'/> + <glyph codepoint='e4' name='trademarksans'/> + <glyph codepoint='e5' name='summation'/> + <glyph codepoint='e6' name='parenlefttp'/> + <glyph codepoint='e7' name='parenleftex'/> + <glyph codepoint='e8' name='parenleftbt'/> + <glyph codepoint='e9' name='bracketlefttp'/> + <glyph codepoint='ea' name='bracketleftex'/> + <glyph codepoint='eb' name='bracketleftbt'/> + <glyph codepoint='ec' name='bracelefttp'/> + <glyph codepoint='ed' name='braceleftmid'/> + <glyph codepoint='ee' name='braceleftbt'/> + <glyph codepoint='ef' name='braceex'/> + <glyph codepoint='f1' name='angleright'/> + <glyph codepoint='f2' name='integral'/> + <glyph codepoint='f3' name='integraltp'/> + <glyph codepoint='f4' name='integralex'/> + <glyph codepoint='f5' name='integralbt'/> + <glyph codepoint='f6' name='parenrighttp'/> + <glyph codepoint='f7' name='parenrightex'/> + <glyph codepoint='f8' name='parenrightbt'/> + <glyph codepoint='f9' name='bracketrighttp'/> + <glyph codepoint='fa' name='bracketrightex'/> + <glyph codepoint='fb' name='bracketrightbt'/> + <glyph codepoint='fc' name='bracerighttp'/> + <glyph codepoint='fd' name='bracerightmid'/> + <glyph codepoint='fe' name='bracerightbt'/> + </encoding> + <encoding id='ZapfDingbatsEncoding' glyphlist='ZGL'> + <glyph codepoint='20' name='space'/> + <glyph codepoint='21' name='a1'/> + <glyph codepoint='22' name='a2'/> + <glyph codepoint='23' name='a202'/> + <glyph codepoint='24' name='a3'/> + <glyph codepoint='25' name='a4'/> + <glyph codepoint='26' name='a5'/> + <glyph codepoint='27' name='a119'/> + <glyph codepoint='28' name='a118'/> + <glyph codepoint='29' name='a117'/> + <glyph codepoint='2A' name='a11'/> + <glyph codepoint='2B' name='a12'/> + <glyph codepoint='2C' name='a13'/> + <glyph codepoint='2D' name='a14'/> + <glyph codepoint='2E' name='a15'/> + <glyph codepoint='2F' name='a16'/> + <glyph codepoint='30' name='a105'/> + <glyph codepoint='31' name='a17'/> + <glyph codepoint='32' name='a18'/> + <glyph codepoint='33' name='a19'/> + <glyph codepoint='34' name='a20'/> + <glyph codepoint='35' name='a21'/> + <glyph codepoint='36' name='a22'/> + <glyph codepoint='37' name='a23'/> + <glyph codepoint='38' name='a24'/> + <glyph codepoint='39' name='a25'/> + <glyph codepoint='3A' name='a26'/> + <glyph codepoint='3B' name='a27'/> + <glyph codepoint='3C' name='a28'/> + <glyph codepoint='3D' name='a6'/> + <glyph codepoint='3E' name='a7'/> + <glyph codepoint='3F' name='a8'/> + <glyph codepoint='40' name='a9'/> + <glyph codepoint='41' name='a10'/> + <glyph codepoint='42' name='a29'/> + <glyph codepoint='43' name='a30'/> + <glyph codepoint='44' name='a31'/> + <glyph codepoint='45' name='a32'/> + <glyph codepoint='46' name='a33'/> + <glyph codepoint='47' name='a34'/> + <glyph codepoint='48' name='a35'/> + <glyph codepoint='49' name='a36'/> + <glyph codepoint='4A' name='a37'/> + <glyph codepoint='4B' name='a38'/> + <glyph codepoint='4C' name='a39'/> + <glyph codepoint='4D' name='a40'/> + <glyph codepoint='4E' name='a41'/> + <glyph codepoint='4F' name='a42'/> + <glyph codepoint='50' name='a43'/> + <glyph codepoint='51' name='a44'/> + <glyph codepoint='52' name='a45'/> + <glyph codepoint='53' name='a46'/> + <glyph codepoint='54' name='a47'/> + <glyph codepoint='55' name='a48'/> + <glyph codepoint='56' name='a49'/> + <glyph codepoint='57' name='a50'/> + <glyph codepoint='58' name='a51'/> + <glyph codepoint='59' name='a52'/> + <glyph codepoint='5A' name='a53'/> + <glyph codepoint='5B' name='a54'/> + <glyph codepoint='5C' name='a55'/> + <glyph codepoint='5D' name='a56'/> + <glyph codepoint='5E' name='a57'/> + <glyph codepoint='5F' name='a58'/> + <glyph codepoint='60' name='a59'/> + <glyph codepoint='61' name='a60'/> + <glyph codepoint='62' name='a61'/> + <glyph codepoint='63' name='a62'/> + <glyph codepoint='64' name='a63'/> + <glyph codepoint='65' name='a64'/> + <glyph codepoint='66' name='a65'/> + <glyph codepoint='67' name='a66'/> + <glyph codepoint='68' name='a67'/> + <glyph codepoint='69' name='a68'/> + <glyph codepoint='6A' name='a69'/> + <glyph codepoint='6B' name='a70'/> + <glyph codepoint='6C' name='a71'/> + <glyph codepoint='6D' name='a72'/> + <glyph codepoint='6E' name='a73'/> + <glyph codepoint='6F' name='a74'/> + <glyph codepoint='70' name='a203'/> + <glyph codepoint='71' name='a75'/> + <glyph codepoint='72' name='a204'/> + <glyph codepoint='73' name='a76'/> + <glyph codepoint='74' name='a77'/> + <glyph codepoint='75' name='a78'/> + <glyph codepoint='76' name='a79'/> + <glyph codepoint='77' name='a81'/> + <glyph codepoint='78' name='a82'/> + <glyph codepoint='79' name='a83'/> + <glyph codepoint='7A' name='a84'/> + <glyph codepoint='7B' name='a97'/> + <glyph codepoint='7C' name='a98'/> + <glyph codepoint='7D' name='a99'/> + <glyph codepoint='7E' name='a100'/> + <glyph codepoint='80' name='a89'/> + <glyph codepoint='81' name='a90'/> + <glyph codepoint='82' name='a93'/> + <glyph codepoint='83' name='a94'/> + <glyph codepoint='84' name='a91'/> + <glyph codepoint='85' name='a92'/> + <glyph codepoint='86' name='a205'/> + <glyph codepoint='87' name='a85'/> + <glyph codepoint='88' name='a206'/> + <glyph codepoint='89' name='a86'/> + <glyph codepoint='8A' name='a87'/> + <glyph codepoint='8B' name='a88'/> + <glyph codepoint='8C' name='a95'/> + <glyph codepoint='8D' name='a96'/> + <glyph codepoint='A1' name='a101'/> + <glyph codepoint='A2' name='a102'/> + <glyph codepoint='A3' name='a103'/> + <glyph codepoint='A4' name='a104'/> + <glyph codepoint='A5' name='a106'/> + <glyph codepoint='A6' name='a107'/> + <glyph codepoint='A7' name='a108'/> + <glyph codepoint='A8' name='a112'/> + <glyph codepoint='A9' name='a111'/> + <glyph codepoint='AA' name='a110'/> + <glyph codepoint='AB' name='a109'/> + <glyph codepoint='AC' name='a120'/> + <glyph codepoint='AD' name='a121'/> + <glyph codepoint='AE' name='a122'/> + <glyph codepoint='AF' name='a123'/> + <glyph codepoint='B0' name='a124'/> + <glyph codepoint='B1' name='a125'/> + <glyph codepoint='B2' name='a126'/> + <glyph codepoint='B3' name='a127'/> + <glyph codepoint='B4' name='a128'/> + <glyph codepoint='B5' name='a129'/> + <glyph codepoint='B6' name='a130'/> + <glyph codepoint='B7' name='a131'/> + <glyph codepoint='B8' name='a132'/> + <glyph codepoint='B9' name='a133'/> + <glyph codepoint='BA' name='a134'/> + <glyph codepoint='BB' name='a135'/> + <glyph codepoint='BC' name='a136'/> + <glyph codepoint='BD' name='a137'/> + <glyph codepoint='BE' name='a138'/> + <glyph codepoint='BF' name='a139'/> + <glyph codepoint='C0' name='a140'/> + <glyph codepoint='C1' name='a141'/> + <glyph codepoint='C2' name='a142'/> + <glyph codepoint='C3' name='a143'/> + <glyph codepoint='C4' name='a144'/> + <glyph codepoint='C5' name='a145'/> + <glyph codepoint='C6' name='a146'/> + <glyph codepoint='C7' name='a147'/> + <glyph codepoint='C8' name='a148'/> + <glyph codepoint='C9' name='a149'/> + <glyph codepoint='CA' name='a150'/> + <glyph codepoint='CB' name='a151'/> + <glyph codepoint='CC' name='a152'/> + <glyph codepoint='CD' name='a153'/> + <glyph codepoint='CE' name='a154'/> + <glyph codepoint='CF' name='a155'/> + <glyph codepoint='D0' name='a156'/> + <glyph codepoint='D1' name='a157'/> + <glyph codepoint='D2' name='a158'/> + <glyph codepoint='D3' name='a159'/> + <glyph codepoint='D4' name='a160'/> + <glyph codepoint='D5' name='a161'/> + <glyph codepoint='D6' name='a163'/> + <glyph codepoint='D7' name='a164'/> + <glyph codepoint='D8' name='a196'/> + <glyph codepoint='D9' name='a165'/> + <glyph codepoint='DA' name='a192'/> + <glyph codepoint='DB' name='a166'/> + <glyph codepoint='DC' name='a167'/> + <glyph codepoint='DD' name='a168'/> + <glyph codepoint='DE' name='a169'/> + <glyph codepoint='DF' name='a170'/> + <glyph codepoint='E0' name='a171'/> + <glyph codepoint='E1' name='a172'/> + <glyph codepoint='E2' name='a173'/> + <glyph codepoint='E3' name='a162'/> + <glyph codepoint='E4' name='a174'/> + <glyph codepoint='E5' name='a175'/> + <glyph codepoint='E6' name='a176'/> + <glyph codepoint='E7' name='a177'/> + <glyph codepoint='E8' name='a178'/> + <glyph codepoint='E9' name='a179'/> + <glyph codepoint='EA' name='a193'/> + <glyph codepoint='EB' name='a180'/> + <glyph codepoint='EC' name='a199'/> + <glyph codepoint='ED' name='a181'/> + <glyph codepoint='EE' name='a200'/> + <glyph codepoint='EF' name='a182'/> + <glyph codepoint='F1' name='a201'/> + <glyph codepoint='F2' name='a183'/> + <glyph codepoint='F3' name='a184'/> + <glyph codepoint='F4' name='a197'/> + <glyph codepoint='F5' name='a185'/> + <glyph codepoint='F6' name='a194'/> + <glyph codepoint='F7' name='a198'/> + <glyph codepoint='F8' name='a186'/> + <glyph codepoint='F9' name='a195'/> + <glyph codepoint='FA' name='a187'/> + <glyph codepoint='FB' name='a188'/> + <glyph codepoint='FC' name='a189'/> + <glyph codepoint='FD' name='a190'/> + <glyph codepoint='FE' name='a191'/> + </encoding> +</encoding-set> diff --git a/src/codegen/font-file.xsl b/src/codegen/font-file.xsl index 96a6f8583..7167c5b54 100644 --- a/src/codegen/font-file.xsl +++ b/src/codegen/font-file.xsl @@ -1,33 +1,30 @@ -<!-- -This files writes the class files for the fonts (Courier.java, Helvetica.java etc.). -It uses the information in the font description files (Courier.xml, Helvetica.xml) to this -In these font description files each character is referenced by its adobe name: - <char name="A" width="667"/> -To resolve this name and to find the code for this character it looks up the adobe name in the -file charlist.xml and extracts the WinAnsi code. ---> - +<!-- This file writes the class files for the fonts (Courier.java, + Helvetica.java etc.). It uses the information in the font + description files (Courier.xml, Helvetica.xml) to do this. In these + font description files each character is referenced by its adobe + glyph name: + <char name="A" width="667"/> + To resolve this name and to find the code for this character it looks + up the adobe name in the file encodings.xml and extracts the appropriate + code. --> <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:lxslt="http://xml.apache.org/xslt" - xmlns:redirect="org.apache.xalan.xslt.extensions.Redirect" - extension-element-prefixes="redirect"> -<xsl:output method="text" /> - + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> -<!-- Note: this key is used with charlist.xml in a for-each. --> -<xsl:key name="adobe-char-map" match="map" use="@adobe-name"/> + <xsl:output method="text"/> + + <xsl:param name="encoding" select="/font-metrics/encoding"/> + <xsl:variable name="native-encoding" select="/font-metrics/encoding"/> + <xsl:variable name="glyphs" select="document('encodings.xml')/encoding-set/encoding[@id=$encoding]/glyph"/> -<xsl:template match="font-metrics"> -<xsl:variable name="class-name" select="class-name"/> -<!--<redirect:write select="concat('org/apache/fop/render/pdf/fonts/', $class-name, '.java')">--> + <xsl:template match="font-metrics"> package org.apache.fop.render.pdf.fonts; import org.apache.fop.render.pdf.Font; +import org.apache.fop.render.pdf.CodePointMapping; public class <xsl:value-of select="class-name"/> extends Font { private final static String fontName = "<xsl:value-of select="font-name"/>"; - private final static String encoding = "<xsl:value-of select="encoding"/>"; + private final static String encoding = <xsl:choose><xsl:when test="$encoding != $native-encoding">"<xsl:value-of select="$encoding"/>"</xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>; private final static int capHeight = <xsl:value-of select="cap-height"/>; private final static int xHeight = <xsl:value-of select="x-height"/>; private final static int ascender = <xsl:value-of select="ascender"/>; @@ -35,13 +32,12 @@ public class <xsl:value-of select="class-name"/> extends Font { 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 CodePointMapping mapping + = CodePointMapping.getMapping("<xsl:value-of select="$encoding"/>"); static { width = new int[256]; -<xsl:for-each select="widths/char"><xsl:variable name="char-name" select="@name"/><xsl:variable name="char-width" select="@width"/> -<xsl:for-each select="document('charlist.xml')"><xsl:variable name="char-num" select="key('adobe-char-map',$char-name)/@win-ansi"/> -<xsl:if test="$char-num!='-1'"> width[<xsl:value-of select="$char-num"/>] = <xsl:value-of select="$char-width"/>; -</xsl:if></xsl:for-each></xsl:for-each> + <xsl:apply-templates select="widths"/> } public String encoding() { @@ -86,8 +82,18 @@ public class <xsl:value-of select="class-name"/> extends Font { for( int i = 0; i < arr.length; i++) arr[i] *= size; return arr; } + + public char mapChar(char c) { + char d = mapping.mapChar(c); + if(d != 0) + return d; + else + return '#'; + } + } -<!--</redirect:write>--> -</xsl:template> + </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:stylesheet> diff --git a/src/codegen/foproperties.xml b/src/codegen/foproperties.xml index ce2a7503c..f8abe1c69 100644 --- a/src/codegen/foproperties.xml +++ b/src/codegen/foproperties.xml @@ -1,212 +1,212 @@ <?xml version="1.0" standalone="yes" ?> <property-list family="FO"> <generic-property-list> - <property type="generic"> - <name>generic-color</name> - <class-name>GenericColor</class-name> - <datatype>ColorType</datatype> - <extfile href="colorkw.xml"/> + <property type="generic"> + <name>generic-color</name> + <class-name>GenericColor</class-name> + <datatype>ColorType</datatype> + <extfile href="colorkw.xml"/> <!-- - <datatype-conversion from-type="String" varname="strval"> - new ColorType(strval)</datatype-conversion> + <datatype-conversion from-type="String" varname="strval"> + new ColorType(strval)</datatype-conversion> --> - </property> - <property type="generic"> - <name>generic-boolean</name> - <class-name>GenericBoolean</class-name> - <datatype>Enum</datatype> - <enumeration> - <value const="TRUE">true</value> - <value const="FALSE">false</value> - </enumeration> - </property> - <property type="generic"> - <name>generic-keep</name> - <class-name>GenericKeep</class-name> - <datatype>Keep</datatype> <!-- CompoundDatatype --> - <compound> - <subproperty set-by-shorthand="true"> - <name>within-page</name> - <datatype>Number</datatype> - <default>auto</default> - <enumeration> - <value const="AUTO">auto</value> - <value const="ALWAYS">always</value> - </enumeration> - </subproperty> - <subproperty set-by-shorthand="true"> - <name>within-line</name> - <datatype>Number</datatype> - <default>auto</default> - <enumeration> - <value const="AUTO">auto</value> - <value const="ALWAYS">always</value> - </enumeration> - </subproperty> - <subproperty set-by-shorthand="true"> - <name>within-column</name> - <datatype>Number</datatype> - <default>auto</default> - <enumeration> - <value const="AUTO">auto</value> - <value const="ALWAYS">always</value> - </enumeration> - </subproperty> - </compound> - </property> - <property type="generic"> - <name>conditional-length-template</name> - <class-name>GenericCondLength</class-name> - <datatype>CondLength</datatype> - <compound> - <subproperty set-by-shorthand="true"> - <name>length</name> - <datatype>Length</datatype> - </subproperty> - <subproperty> - <name>conditionality</name> - <datatype>Enum</datatype> - <enumeration> - <value const="DISCARD">discard</value> - <value const="RETAIN">retain</value> - </enumeration> - </subproperty> - </compound> - </property> - <property type="generic"> - <name>padding-template</name> - <class-name>GenericCondPadding</class-name> - <use-generic>GenericCondLength</use-generic> - <inherited>false</inherited> - <default subproperty="length">0pt</default> - </property> - <property type="generic"> - <name>padding-template</name> - <class-name>GenericPadding</class-name> - <datatype>Length</datatype> - <inherited>false</inherited> - <default>0pt</default> + </property> + <property type="generic"> + <name>generic-boolean</name> + <class-name>GenericBoolean</class-name> + <datatype>Enum</datatype> + <enumeration> + <value const="TRUE">true</value> + <value const="FALSE">false</value> + </enumeration> + </property> + <property type="generic"> + <name>generic-keep</name> + <class-name>GenericKeep</class-name> + <datatype>Keep</datatype> <!-- CompoundDatatype --> + <compound> + <subproperty set-by-shorthand="true"> + <name>within-page</name> + <datatype>Number</datatype> + <default>auto</default> + <enumeration> + <value const="AUTO">auto</value> + <value const="ALWAYS">always</value> + </enumeration> + </subproperty> + <subproperty set-by-shorthand="true"> + <name>within-line</name> + <datatype>Number</datatype> + <default>auto</default> + <enumeration> + <value const="AUTO">auto</value> + <value const="ALWAYS">always</value> + </enumeration> + </subproperty> + <subproperty set-by-shorthand="true"> + <name>within-column</name> + <datatype>Number</datatype> + <default>auto</default> + <enumeration> + <value const="AUTO">auto</value> + <value const="ALWAYS">always</value> + </enumeration> + </subproperty> + </compound> + </property> + <property type="generic"> + <name>conditional-length-template</name> + <class-name>GenericCondLength</class-name> + <datatype>CondLength</datatype> + <compound> + <subproperty set-by-shorthand="true"> + <name>length</name> + <datatype>Length</datatype> + </subproperty> + <subproperty> + <name>conditionality</name> + <datatype>Enum</datatype> + <enumeration> + <value const="DISCARD">discard</value> + <value const="RETAIN">retain</value> + </enumeration> + </subproperty> + </compound> + </property> + <property type="generic"> + <name>padding-template</name> + <class-name>GenericCondPadding</class-name> + <use-generic>GenericCondLength</use-generic> + <inherited>false</inherited> + <default subproperty="length">0pt</default> + </property> + <property type="generic"> + <name>padding-template</name> + <class-name>GenericPadding</class-name> + <datatype>Length</datatype> + <inherited>false</inherited> + <default>0pt</default> <shorthand>padding</shorthand> - </property> + </property> <!-- Before, After, Start, End border width props --> <!-- CondLength, but adds keyword values both to the "shorthand" setting - and to the length component. So we redefine the components here, - rather than doing a "use-generic" on GenericCondLength. + and to the length component. So we redefine the components here, + rather than doing a "use-generic" on GenericCondLength. --> - <property type="generic"> - <name>border-cond-width-template</name> - <class-name>GenericCondBorderWidth</class-name> - <keyword-equiv match="thin">0.5pt</keyword-equiv> - <keyword-equiv match="medium">1pt</keyword-equiv> - <keyword-equiv match="thick">2pt</keyword-equiv> - <inherited>false</inherited> - <datatype>CondLength</datatype> - <compound> - <subproperty set-by-shorthand="true"> - <name>length</name> - <datatype>Length</datatype> - <keyword-equiv match="thin">0.5pt</keyword-equiv> - <keyword-equiv match="medium">1pt</keyword-equiv> - <keyword-equiv match="thick">2pt</keyword-equiv> - <default>medium</default> - </subproperty> - <subproperty> - <datatype>Enum</datatype> - <name>conditionality</name> - <enumeration> - <value const="DISCARD">discard</value> - <value const="RETAIN">retain</value> - </enumeration> - </subproperty> - </compound> - </property> + <property type="generic"> + <name>border-cond-width-template</name> + <class-name>GenericCondBorderWidth</class-name> + <keyword-equiv match="thin">0.5pt</keyword-equiv> + <keyword-equiv match="medium">1pt</keyword-equiv> + <keyword-equiv match="thick">2pt</keyword-equiv> + <inherited>false</inherited> + <datatype>CondLength</datatype> + <compound> + <subproperty set-by-shorthand="true"> + <name>length</name> + <datatype>Length</datatype> + <keyword-equiv match="thin">0.5pt</keyword-equiv> + <keyword-equiv match="medium">1pt</keyword-equiv> + <keyword-equiv match="thick">2pt</keyword-equiv> + <default>medium</default> + </subproperty> + <subproperty> + <datatype>Enum</datatype> + <name>conditionality</name> + <enumeration> + <value const="DISCARD">discard</value> + <value const="RETAIN">retain</value> + </enumeration> + </subproperty> + </compound> + </property> <!-- Left, Right, Top, Bottom borderwidth props --> - <property type="generic"> - <name>border-width-template</name> - <class-name>GenericBorderWidth</class-name> - <datatype>Length</datatype> - <keyword-equiv match="thin">0.5pt</keyword-equiv> - <keyword-equiv match="medium">1pt</keyword-equiv> - <keyword-equiv match="thick">2pt</keyword-equiv> - <inherited>false</inherited> - <default>0pt</default> - <shorthand>border-width</shorthand> - </property> - <property type="generic"> - <name>border-style-template</name> - <class-name>GenericBorderStyle</class-name> - <inherited>false</inherited> - <datatype>Enum</datatype> - <enumeration> - <value const="NONE">none</value> - <value const="HIDDEN">hidden</value> - <value const="DOTTED">dotted</value> - <value const="DASHED">dashed</value> - <value const="SOLID">solid</value> - <value const="DOUBLE">double</value> - <value const="GROOVE">groove</value> - <value const="RIDGE">ridge</value> - <value const="INSET">inset</value> - <value const="OUTSET">outset</value> - </enumeration> - <default>none</default> - <shorthand>border-style</shorthand> - </property> - <property type="generic"> - <name>break-template</name> - <class-name>GenericBreak</class-name> - <inherited>false</inherited> - <datatype>Enum</datatype> - <enumeration> - <value const="AUTO">auto</value> - <value const="COLUMN">column</value> - <value const="PAGE">page</value> - <value const="EVEN_PAGE">even-page</value> - <value const="ODD_PAGE">odd-page</value> - </enumeration> - <default>auto</default> - </property> - <property type="generic"> - <name>generic-space</name> - <class-name>GenericSpace</class-name> - <inherited>false</inherited> - <datatype>Space</datatype> - <compound> - <subproperty set-by-shorthand="true"> - <name>minimum</name> - <datatype>Length</datatype> - <default>0pt</default> - </subproperty> - <subproperty set-by-shorthand="true"> - <name>optimum</name> - <datatype>Length</datatype> - <default>0pt</default> - </subproperty> - <subproperty set-by-shorthand="true"> - <name>maximum</name> - <datatype>Length</datatype> - <default>0pt</default> - </subproperty> - <subproperty> - <name>precedence</name> - <datatype>Number</datatype> - <enumeration> - <value const="FORCE">force</value> - </enumeration> - <default>0</default> - </subproperty> - <subproperty> - <name>conditionality</name> - <datatype>Enum</datatype> - <enumeration> - <value const="DISCARD">discard</value> - <value const="RETAIN">retain</value> - </enumeration> - <default>discard</default> - </subproperty> - </compound> - </property> + <property type="generic"> + <name>border-width-template</name> + <class-name>GenericBorderWidth</class-name> + <datatype>Length</datatype> + <keyword-equiv match="thin">0.5pt</keyword-equiv> + <keyword-equiv match="medium">1pt</keyword-equiv> + <keyword-equiv match="thick">2pt</keyword-equiv> + <inherited>false</inherited> + <default>0pt</default> + <shorthand>border-width</shorthand> + </property> + <property type="generic"> + <name>border-style-template</name> + <class-name>GenericBorderStyle</class-name> + <inherited>false</inherited> + <datatype>Enum</datatype> + <enumeration> + <value const="NONE">none</value> + <value const="HIDDEN">hidden</value> + <value const="DOTTED">dotted</value> + <value const="DASHED">dashed</value> + <value const="SOLID">solid</value> + <value const="DOUBLE">double</value> + <value const="GROOVE">groove</value> + <value const="RIDGE">ridge</value> + <value const="INSET">inset</value> + <value const="OUTSET">outset</value> + </enumeration> + <default>none</default> + <shorthand>border-style</shorthand> + </property> + <property type="generic"> + <name>break-template</name> + <class-name>GenericBreak</class-name> + <inherited>false</inherited> + <datatype>Enum</datatype> + <enumeration> + <value const="AUTO">auto</value> + <value const="COLUMN">column</value> + <value const="PAGE">page</value> + <value const="EVEN_PAGE">even-page</value> + <value const="ODD_PAGE">odd-page</value> + </enumeration> + <default>auto</default> + </property> + <property type="generic"> + <name>generic-space</name> + <class-name>GenericSpace</class-name> + <inherited>false</inherited> + <datatype>Space</datatype> + <compound> + <subproperty set-by-shorthand="true"> + <name>minimum</name> + <datatype>Length</datatype> + <default>0pt</default> + </subproperty> + <subproperty set-by-shorthand="true"> + <name>optimum</name> + <datatype>Length</datatype> + <default>0pt</default> + </subproperty> + <subproperty set-by-shorthand="true"> + <name>maximum</name> + <datatype>Length</datatype> + <default>0pt</default> + </subproperty> + <subproperty> + <name>precedence</name> + <datatype>Number</datatype> + <enumeration> + <value const="FORCE">force</value> + </enumeration> + <default>0</default> + </subproperty> + <subproperty> + <name>conditionality</name> + <datatype>Enum</datatype> + <enumeration> + <value const="DISCARD">discard</value> + <value const="RETAIN">retain</value> + </enumeration> + <default>discard</default> + </subproperty> + </compound> + </property> <!-- Common Accessibility Properties --> @@ -397,13 +397,20 @@ <property> <name>background-image</name> <inherited>false</inherited> - <datatype>ToBeImplemented</datatype> + <datatype>String</datatype> <default>none</default> </property> <property> <name>background-repeat</name> <inherited>false</inherited> - <datatype>ToBeImplemented</datatype> + <datatype>Enum</datatype> + <enumeration> + <value const="REPEAT">repeat</value> + <value const="REPEAT_X">repeat-x</value> + <value const="REPEAT_Y">repeat-y</value> + <value const="NO_REPEAT">no-repeat</value> + <value const="INHERIT">inherit</value> + </enumeration> <default>repeat</default> </property> <property> @@ -822,24 +829,28 @@ <inherited>false</inherited> <datatype>Length</datatype> <default>0pt</default> + <shorthand>margin</shorthand> </property> <property> <name>margin-bottom</name> <inherited>false</inherited> <datatype>Length</datatype> <default>0pt</default> + <shorthand>margin</shorthand> </property> <property> <name>margin-left</name> <inherited>false</inherited> <datatype>Length</datatype> <default>0pt</default> + <shorthand>margin</shorthand> </property> <property> <name>margin-right</name> <inherited>false</inherited> <datatype>Length</datatype> <default>0pt</default> + <shorthand>margin</shorthand> </property> <property> <name>space-before</name> @@ -1148,7 +1159,7 @@ <default>treat-as-space</default> </property> <property> - <name>space-treatment</name> + <name>white-space-treatment</name> <inherited>true</inherited> <datatype>ToBeImplemented</datatype> <default>preserve</default> @@ -1220,8 +1231,8 @@ <property> <name>letter-spacing</name> <inherited>true</inherited> - <datatype>ToBeImplemented</datatype> - <default>normal</default> + <datatype>Length</datatype> + <default>0pt</default> </property> <property> <name>suppress-at-line-break</name> @@ -1691,6 +1702,12 @@ <default></default> </property> <property> + <name>master-reference</name> + <inherited>false</inherited> + <datatype>String</datatype> + <default></default> + </property> + <property> <name>maximum-repeats</name> <inherited>false</inherited> <datatype>String</datatype> @@ -2077,8 +2094,8 @@ <property> <name>margin</name> <inherited>false</inherited> - <datatype>ToBeImplemented</datatype> - <default></default> + <datatype>List</datatype> + <datatype-parser>MarginShorthandParser</datatype-parser> </property> <property> <name>padding</name> diff --git a/src/codegen/glyphlist.xml b/src/codegen/glyphlist.xml new file mode 100644 index 000000000..b5dc36f19 --- /dev/null +++ b/src/codegen/glyphlist.xml @@ -0,0 +1,1276 @@ +<?xml version='1.0'?> +<!DOCTYPE glyphlist-set [ + <!ELEMENT glyphlist-set (glyphlist+)> + <!ELEMENT glyphlist (glyph+)> + <!ATTLIST glyphlist id ID #REQUIRED> + <!ELEMENT glyph EMPTY> + <!ATTLIST glyph codepoint CDATA #REQUIRED name CDATA #REQUIRED> +]> +<glyphlist-set> + + <!-- This encodes the Adobe Glyph List, version 1.2 (22 Oct 1998), + located at http://partners.adobe.com/asn/developer/type/glyphlist.txt + --> + <glyphlist id='AGL'> + <glyph codepoint='0041' name='A'/> + <glyph codepoint='00C6' name='AE'/> + <glyph codepoint='01FC' name='AEacute'/> + <glyph codepoint='F7E6' name='AEsmall'/> + <glyph codepoint='00C1' name='Aacute'/> + <glyph codepoint='F7E1' name='Aacutesmall'/> + <glyph codepoint='0102' name='Abreve'/> + <glyph codepoint='00C2' name='Acircumflex'/> + <glyph codepoint='F7E2' name='Acircumflexsmall'/> + <glyph codepoint='F6C9' name='Acute'/> + <glyph codepoint='F7B4' name='Acutesmall'/> + <glyph codepoint='00C4' name='Adieresis'/> + <glyph codepoint='F7E4' name='Adieresissmall'/> + <glyph codepoint='00C0' name='Agrave'/> + <glyph codepoint='F7E0' name='Agravesmall'/> + <glyph codepoint='0391' name='Alpha'/> + <glyph codepoint='0386' name='Alphatonos'/> + <glyph codepoint='0100' name='Amacron'/> + <glyph codepoint='0104' name='Aogonek'/> + <glyph codepoint='00C5' name='Aring'/> + <glyph codepoint='01FA' name='Aringacute'/> + <glyph codepoint='F7E5' name='Aringsmall'/> + <glyph codepoint='F761' name='Asmall'/> + <glyph codepoint='00C3' name='Atilde'/> + <glyph codepoint='F7E3' name='Atildesmall'/> + <glyph codepoint='0042' name='B'/> + <glyph codepoint='0392' name='Beta'/> + <glyph codepoint='F6F4' name='Brevesmall'/> + <glyph codepoint='F762' name='Bsmall'/> + <glyph codepoint='0043' name='C'/> + <glyph codepoint='0106' name='Cacute'/> + <glyph codepoint='F6CA' name='Caron'/> + <glyph codepoint='F6F5' name='Caronsmall'/> + <glyph codepoint='010C' name='Ccaron'/> + <glyph codepoint='00C7' name='Ccedilla'/> + <glyph codepoint='F7E7' name='Ccedillasmall'/> + <glyph codepoint='0108' name='Ccircumflex'/> + <glyph codepoint='010A' name='Cdotaccent'/> + <glyph codepoint='F7B8' name='Cedillasmall'/> + <glyph codepoint='03A7' name='Chi'/> + <glyph codepoint='F6F6' name='Circumflexsmall'/> + <glyph codepoint='F763' name='Csmall'/> + <glyph codepoint='0044' name='D'/> + <glyph codepoint='010E' name='Dcaron'/> + <glyph codepoint='0110' name='Dcroat'/> + <glyph codepoint='2206' name='Delta'/> + <glyph codepoint='0394' name='Delta'/> + <glyph codepoint='F6CB' name='Dieresis'/> + <glyph codepoint='F6CC' name='DieresisAcute'/> + <glyph codepoint='F6CD' name='DieresisGrave'/> + <glyph codepoint='F7A8' name='Dieresissmall'/> + <glyph codepoint='F6F7' name='Dotaccentsmall'/> + <glyph codepoint='F764' name='Dsmall'/> + <glyph codepoint='0045' name='E'/> + <glyph codepoint='00C9' name='Eacute'/> + <glyph codepoint='F7E9' name='Eacutesmall'/> + <glyph codepoint='0114' name='Ebreve'/> + <glyph codepoint='011A' name='Ecaron'/> + <glyph codepoint='00CA' name='Ecircumflex'/> + <glyph codepoint='F7EA' name='Ecircumflexsmall'/> + <glyph codepoint='00CB' name='Edieresis'/> + <glyph codepoint='F7EB' name='Edieresissmall'/> + <glyph codepoint='0116' name='Edotaccent'/> + <glyph codepoint='00C8' name='Egrave'/> + <glyph codepoint='F7E8' name='Egravesmall'/> + <glyph codepoint='0112' name='Emacron'/> + <glyph codepoint='014A' name='Eng'/> + <glyph codepoint='0118' name='Eogonek'/> + <glyph codepoint='0395' name='Epsilon'/> + <glyph codepoint='0388' name='Epsilontonos'/> + <glyph codepoint='F765' name='Esmall'/> + <glyph codepoint='0397' name='Eta'/> + <glyph codepoint='0389' name='Etatonos'/> + <glyph codepoint='00D0' name='Eth'/> + <glyph codepoint='F7F0' name='Ethsmall'/> + <glyph codepoint='20AC' name='Euro'/> + <glyph codepoint='0046' name='F'/> + <glyph codepoint='F766' name='Fsmall'/> + <glyph codepoint='0047' name='G'/> + <glyph codepoint='0393' name='Gamma'/> + <glyph codepoint='011E' name='Gbreve'/> + <glyph codepoint='01E6' name='Gcaron'/> + <glyph codepoint='011C' name='Gcircumflex'/> + <glyph codepoint='0122' name='Gcommaaccent'/> + <glyph codepoint='0120' name='Gdotaccent'/> + <glyph codepoint='F6CE' name='Grave'/> + <glyph codepoint='F760' name='Gravesmall'/> + <glyph codepoint='F767' name='Gsmall'/> + <glyph codepoint='0048' name='H'/> + <glyph codepoint='25CF' name='H18533'/> + <glyph codepoint='25AA' name='H18543'/> + <glyph codepoint='25AB' name='H18551'/> + <glyph codepoint='25A1' name='H22073'/> + <glyph codepoint='0126' name='Hbar'/> + <glyph codepoint='0124' name='Hcircumflex'/> + <glyph codepoint='F768' name='Hsmall'/> + <glyph codepoint='F6CF' name='Hungarumlaut'/> + <glyph codepoint='F6F8' name='Hungarumlautsmall'/> + <glyph codepoint='0049' name='I'/> + <glyph codepoint='0132' name='IJ'/> + <glyph codepoint='00CD' name='Iacute'/> + <glyph codepoint='F7ED' name='Iacutesmall'/> + <glyph codepoint='012C' name='Ibreve'/> + <glyph codepoint='00CE' name='Icircumflex'/> + <glyph codepoint='F7EE' name='Icircumflexsmall'/> + <glyph codepoint='00CF' name='Idieresis'/> + <glyph codepoint='F7EF' name='Idieresissmall'/> + <glyph codepoint='0130' name='Idotaccent'/> + <glyph codepoint='2111' name='Ifraktur'/> + <glyph codepoint='00CC' name='Igrave'/> + <glyph codepoint='F7EC' name='Igravesmall'/> + <glyph codepoint='012A' name='Imacron'/> + <glyph codepoint='012E' name='Iogonek'/> + <glyph codepoint='0399' name='Iota'/> + <glyph codepoint='03AA' name='Iotadieresis'/> + <glyph codepoint='038A' name='Iotatonos'/> + <glyph codepoint='F769' name='Ismall'/> + <glyph codepoint='0128' name='Itilde'/> + <glyph codepoint='004A' name='J'/> + <glyph codepoint='0134' name='Jcircumflex'/> + <glyph codepoint='F76A' name='Jsmall'/> + <glyph codepoint='004B' name='K'/> + <glyph codepoint='039A' name='Kappa'/> + <glyph codepoint='0136' name='Kcommaaccent'/> + <glyph codepoint='F76B' name='Ksmall'/> + <glyph codepoint='004C' name='L'/> + <glyph codepoint='F6BF' name='LL'/> + <glyph codepoint='0139' name='Lacute'/> + <glyph codepoint='039B' name='Lambda'/> + <glyph codepoint='013D' name='Lcaron'/> + <glyph codepoint='013B' name='Lcommaaccent'/> + <glyph codepoint='013F' name='Ldot'/> + <glyph codepoint='0141' name='Lslash'/> + <glyph codepoint='F6F9' name='Lslashsmall'/> + <glyph codepoint='F76C' name='Lsmall'/> + <glyph codepoint='004D' name='M'/> + <glyph codepoint='F6D0' name='Macron'/> + <glyph codepoint='F7AF' name='Macronsmall'/> + <glyph codepoint='F76D' name='Msmall'/> + <glyph codepoint='039C' name='Mu'/> + <glyph codepoint='004E' name='N'/> + <glyph codepoint='0143' name='Nacute'/> + <glyph codepoint='0147' name='Ncaron'/> + <glyph codepoint='0145' name='Ncommaaccent'/> + <glyph codepoint='F76E' name='Nsmall'/> + <glyph codepoint='00D1' name='Ntilde'/> + <glyph codepoint='F7F1' name='Ntildesmall'/> + <glyph codepoint='039D' name='Nu'/> + <glyph codepoint='004F' name='O'/> + <glyph codepoint='0152' name='OE'/> + <glyph codepoint='F6FA' name='OEsmall'/> + <glyph codepoint='00D3' name='Oacute'/> + <glyph codepoint='F7F3' name='Oacutesmall'/> + <glyph codepoint='014E' name='Obreve'/> + <glyph codepoint='00D4' name='Ocircumflex'/> + <glyph codepoint='F7F4' name='Ocircumflexsmall'/> + <glyph codepoint='00D6' name='Odieresis'/> + <glyph codepoint='F7F6' name='Odieresissmall'/> + <glyph codepoint='F6FB' name='Ogoneksmall'/> + <glyph codepoint='00D2' name='Ograve'/> + <glyph codepoint='F7F2' name='Ogravesmall'/> + <glyph codepoint='01A0' name='Ohorn'/> + <glyph codepoint='0150' name='Ohungarumlaut'/> + <glyph codepoint='014C' name='Omacron'/> + <glyph codepoint='2126' name='Omega'/> + <glyph codepoint='03A9' name='Omega'/> + <glyph codepoint='038F' name='Omegatonos'/> + <glyph codepoint='039F' name='Omicron'/> + <glyph codepoint='038C' name='Omicrontonos'/> + <glyph codepoint='00D8' name='Oslash'/> + <glyph codepoint='01FE' name='Oslashacute'/> + <glyph codepoint='F7F8' name='Oslashsmall'/> + <glyph codepoint='F76F' name='Osmall'/> + <glyph codepoint='00D5' name='Otilde'/> + <glyph codepoint='F7F5' name='Otildesmall'/> + <glyph codepoint='0050' name='P'/> + <glyph codepoint='03A6' name='Phi'/> + <glyph codepoint='03A0' name='Pi'/> + <glyph codepoint='03A8' name='Psi'/> + <glyph codepoint='F770' name='Psmall'/> + <glyph codepoint='0051' name='Q'/> + <glyph codepoint='F771' name='Qsmall'/> + <glyph codepoint='0052' name='R'/> + <glyph codepoint='0154' name='Racute'/> + <glyph codepoint='0158' name='Rcaron'/> + <glyph codepoint='0156' name='Rcommaaccent'/> + <glyph codepoint='211C' name='Rfraktur'/> + <glyph codepoint='03A1' name='Rho'/> + <glyph codepoint='F6FC' name='Ringsmall'/> + <glyph codepoint='F772' name='Rsmall'/> + <glyph codepoint='0053' name='S'/> + <glyph codepoint='250C' name='SF010000'/> + <glyph codepoint='2514' name='SF020000'/> + <glyph codepoint='2510' name='SF030000'/> + <glyph codepoint='2518' name='SF040000'/> + <glyph codepoint='253C' name='SF050000'/> + <glyph codepoint='252C' name='SF060000'/> + <glyph codepoint='2534' name='SF070000'/> + <glyph codepoint='251C' name='SF080000'/> + <glyph codepoint='2524' name='SF090000'/> + <glyph codepoint='2500' name='SF100000'/> + <glyph codepoint='2502' name='SF110000'/> + <glyph codepoint='2561' name='SF190000'/> + <glyph codepoint='2562' name='SF200000'/> + <glyph codepoint='2556' name='SF210000'/> + <glyph codepoint='2555' name='SF220000'/> + <glyph codepoint='2563' name='SF230000'/> + <glyph codepoint='2551' name='SF240000'/> + <glyph codepoint='2557' name='SF250000'/> + <glyph codepoint='255D' name='SF260000'/> + <glyph codepoint='255C' name='SF270000'/> + <glyph codepoint='255B' name='SF280000'/> + <glyph codepoint='255E' name='SF360000'/> + <glyph codepoint='255F' name='SF370000'/> + <glyph codepoint='255A' name='SF380000'/> + <glyph codepoint='2554' name='SF390000'/> + <glyph codepoint='2569' name='SF400000'/> + <glyph codepoint='2566' name='SF410000'/> + <glyph codepoint='2560' name='SF420000'/> + <glyph codepoint='2550' name='SF430000'/> + <glyph codepoint='256C' name='SF440000'/> + <glyph codepoint='2567' name='SF450000'/> + <glyph codepoint='2568' name='SF460000'/> + <glyph codepoint='2564' name='SF470000'/> + <glyph codepoint='2565' name='SF480000'/> + <glyph codepoint='2559' name='SF490000'/> + <glyph codepoint='2558' name='SF500000'/> + <glyph codepoint='2552' name='SF510000'/> + <glyph codepoint='2553' name='SF520000'/> + <glyph codepoint='256B' name='SF530000'/> + <glyph codepoint='256A' name='SF540000'/> + <glyph codepoint='015A' name='Sacute'/> + <glyph codepoint='0160' name='Scaron'/> + <glyph codepoint='F6FD' name='Scaronsmall'/> + <glyph codepoint='015E' name='Scedilla'/> + <glyph codepoint='F6C1' name='Scedilla'/> + <glyph codepoint='015C' name='Scircumflex'/> + <glyph codepoint='0218' name='Scommaaccent'/> + <glyph codepoint='03A3' name='Sigma'/> + <glyph codepoint='F773' name='Ssmall'/> + <glyph codepoint='0054' name='T'/> + <glyph codepoint='03A4' name='Tau'/> + <glyph codepoint='0166' name='Tbar'/> + <glyph codepoint='0164' name='Tcaron'/> + <glyph codepoint='0162' name='Tcommaaccent'/> + <glyph codepoint='021A' name='Tcommaaccent'/> + <glyph codepoint='0398' name='Theta'/> + <glyph codepoint='00DE' name='Thorn'/> + <glyph codepoint='F7FE' name='Thornsmall'/> + <glyph codepoint='F6FE' name='Tildesmall'/> + <glyph codepoint='F774' name='Tsmall'/> + <glyph codepoint='0055' name='U'/> + <glyph codepoint='00DA' name='Uacute'/> + <glyph codepoint='F7FA' name='Uacutesmall'/> + <glyph codepoint='016C' name='Ubreve'/> + <glyph codepoint='00DB' name='Ucircumflex'/> + <glyph codepoint='F7FB' name='Ucircumflexsmall'/> + <glyph codepoint='00DC' name='Udieresis'/> + <glyph codepoint='F7FC' name='Udieresissmall'/> + <glyph codepoint='00D9' name='Ugrave'/> + <glyph codepoint='F7F9' name='Ugravesmall'/> + <glyph codepoint='01AF' name='Uhorn'/> + <glyph codepoint='0170' name='Uhungarumlaut'/> + <glyph codepoint='016A' name='Umacron'/> + <glyph codepoint='0172' name='Uogonek'/> + <glyph codepoint='03A5' name='Upsilon'/> + <glyph codepoint='03D2' name='Upsilon1'/> + <glyph codepoint='03AB' name='Upsilondieresis'/> + <glyph codepoint='038E' name='Upsilontonos'/> + <glyph codepoint='016E' name='Uring'/> + <glyph codepoint='F775' name='Usmall'/> + <glyph codepoint='0168' name='Utilde'/> + <glyph codepoint='0056' name='V'/> + <glyph codepoint='F776' name='Vsmall'/> + <glyph codepoint='0057' name='W'/> + <glyph codepoint='1E82' name='Wacute'/> + <glyph codepoint='0174' name='Wcircumflex'/> + <glyph codepoint='1E84' name='Wdieresis'/> + <glyph codepoint='1E80' name='Wgrave'/> + <glyph codepoint='F777' name='Wsmall'/> + <glyph codepoint='0058' name='X'/> + <glyph codepoint='039E' name='Xi'/> + <glyph codepoint='F778' name='Xsmall'/> + <glyph codepoint='0059' name='Y'/> + <glyph codepoint='00DD' name='Yacute'/> + <glyph codepoint='F7FD' name='Yacutesmall'/> + <glyph codepoint='0176' name='Ycircumflex'/> + <glyph codepoint='0178' name='Ydieresis'/> + <glyph codepoint='F7FF' name='Ydieresissmall'/> + <glyph codepoint='1EF2' name='Ygrave'/> + <glyph codepoint='F779' name='Ysmall'/> + <glyph codepoint='005A' name='Z'/> + <glyph codepoint='0179' name='Zacute'/> + <glyph codepoint='017D' name='Zcaron'/> + <glyph codepoint='F6FF' name='Zcaronsmall'/> + <glyph codepoint='017B' name='Zdotaccent'/> + <glyph codepoint='0396' name='Zeta'/> + <glyph codepoint='F77A' name='Zsmall'/> + <glyph codepoint='0061' name='a'/> + <glyph codepoint='00E1' name='aacute'/> + <glyph codepoint='0103' name='abreve'/> + <glyph codepoint='00E2' name='acircumflex'/> + <glyph codepoint='00B4' name='acute'/> + <glyph codepoint='0301' name='acutecomb'/> + <glyph codepoint='00E4' name='adieresis'/> + <glyph codepoint='00E6' name='ae'/> + <glyph codepoint='01FD' name='aeacute'/> + <glyph codepoint='2015' name='afii00208'/> + <glyph codepoint='0410' name='afii10017'/> + <glyph codepoint='0411' name='afii10018'/> + <glyph codepoint='0412' name='afii10019'/> + <glyph codepoint='0413' name='afii10020'/> + <glyph codepoint='0414' name='afii10021'/> + <glyph codepoint='0415' name='afii10022'/> + <glyph codepoint='0401' name='afii10023'/> + <glyph codepoint='0416' name='afii10024'/> + <glyph codepoint='0417' name='afii10025'/> + <glyph codepoint='0418' name='afii10026'/> + <glyph codepoint='0419' name='afii10027'/> + <glyph codepoint='041A' name='afii10028'/> + <glyph codepoint='041B' name='afii10029'/> + <glyph codepoint='041C' name='afii10030'/> + <glyph codepoint='041D' name='afii10031'/> + <glyph codepoint='041E' name='afii10032'/> + <glyph codepoint='041F' name='afii10033'/> + <glyph codepoint='0420' name='afii10034'/> + <glyph codepoint='0421' name='afii10035'/> + <glyph codepoint='0422' name='afii10036'/> + <glyph codepoint='0423' name='afii10037'/> + <glyph codepoint='0424' name='afii10038'/> + <glyph codepoint='0425' name='afii10039'/> + <glyph codepoint='0426' name='afii10040'/> + <glyph codepoint='0427' name='afii10041'/> + <glyph codepoint='0428' name='afii10042'/> + <glyph codepoint='0429' name='afii10043'/> + <glyph codepoint='042A' name='afii10044'/> + <glyph codepoint='042B' name='afii10045'/> + <glyph codepoint='042C' name='afii10046'/> + <glyph codepoint='042D' name='afii10047'/> + <glyph codepoint='042E' name='afii10048'/> + <glyph codepoint='042F' name='afii10049'/> + <glyph codepoint='0490' name='afii10050'/> + <glyph codepoint='0402' name='afii10051'/> + <glyph codepoint='0403' name='afii10052'/> + <glyph codepoint='0404' name='afii10053'/> + <glyph codepoint='0405' name='afii10054'/> + <glyph codepoint='0406' name='afii10055'/> + <glyph codepoint='0407' name='afii10056'/> + <glyph codepoint='0408' name='afii10057'/> + <glyph codepoint='0409' name='afii10058'/> + <glyph codepoint='040A' name='afii10059'/> + <glyph codepoint='040B' name='afii10060'/> + <glyph codepoint='040C' name='afii10061'/> + <glyph codepoint='040E' name='afii10062'/> + <glyph codepoint='F6C4' name='afii10063'/> + <glyph codepoint='F6C5' name='afii10064'/> + <glyph codepoint='0430' name='afii10065'/> + <glyph codepoint='0431' name='afii10066'/> + <glyph codepoint='0432' name='afii10067'/> + <glyph codepoint='0433' name='afii10068'/> + <glyph codepoint='0434' name='afii10069'/> + <glyph codepoint='0435' name='afii10070'/> + <glyph codepoint='0451' name='afii10071'/> + <glyph codepoint='0436' name='afii10072'/> + <glyph codepoint='0437' name='afii10073'/> + <glyph codepoint='0438' name='afii10074'/> + <glyph codepoint='0439' name='afii10075'/> + <glyph codepoint='043A' name='afii10076'/> + <glyph codepoint='043B' name='afii10077'/> + <glyph codepoint='043C' name='afii10078'/> + <glyph codepoint='043D' name='afii10079'/> + <glyph codepoint='043E' name='afii10080'/> + <glyph codepoint='043F' name='afii10081'/> + <glyph codepoint='0440' name='afii10082'/> + <glyph codepoint='0441' name='afii10083'/> + <glyph codepoint='0442' name='afii10084'/> + <glyph codepoint='0443' name='afii10085'/> + <glyph codepoint='0444' name='afii10086'/> + <glyph codepoint='0445' name='afii10087'/> + <glyph codepoint='0446' name='afii10088'/> + <glyph codepoint='0447' name='afii10089'/> + <glyph codepoint='0448' name='afii10090'/> + <glyph codepoint='0449' name='afii10091'/> + <glyph codepoint='044A' name='afii10092'/> + <glyph codepoint='044B' name='afii10093'/> + <glyph codepoint='044C' name='afii10094'/> + <glyph codepoint='044D' name='afii10095'/> + <glyph codepoint='044E' name='afii10096'/> + <glyph codepoint='044F' name='afii10097'/> + <glyph codepoint='0491' name='afii10098'/> + <glyph codepoint='0452' name='afii10099'/> + <glyph codepoint='0453' name='afii10100'/> + <glyph codepoint='0454' name='afii10101'/> + <glyph codepoint='0455' name='afii10102'/> + <glyph codepoint='0456' name='afii10103'/> + <glyph codepoint='0457' name='afii10104'/> + <glyph codepoint='0458' name='afii10105'/> + <glyph codepoint='0459' name='afii10106'/> + <glyph codepoint='045A' name='afii10107'/> + <glyph codepoint='045B' name='afii10108'/> + <glyph codepoint='045C' name='afii10109'/> + <glyph codepoint='045E' name='afii10110'/> + <glyph codepoint='040F' name='afii10145'/> + <glyph codepoint='0462' name='afii10146'/> + <glyph codepoint='0472' name='afii10147'/> + <glyph codepoint='0474' name='afii10148'/> + <glyph codepoint='F6C6' name='afii10192'/> + <glyph codepoint='045F' name='afii10193'/> + <glyph codepoint='0463' name='afii10194'/> + <glyph codepoint='0473' name='afii10195'/> + <glyph codepoint='0475' name='afii10196'/> + <glyph codepoint='F6C7' name='afii10831'/> + <glyph codepoint='F6C8' name='afii10832'/> + <glyph codepoint='04D9' name='afii10846'/> + <glyph codepoint='200E' name='afii299'/> + <glyph codepoint='200F' name='afii300'/> + <glyph codepoint='200D' name='afii301'/> + <glyph codepoint='066A' name='afii57381'/> + <glyph codepoint='060C' name='afii57388'/> + <glyph codepoint='0660' name='afii57392'/> + <glyph codepoint='0661' name='afii57393'/> + <glyph codepoint='0662' name='afii57394'/> + <glyph codepoint='0663' name='afii57395'/> + <glyph codepoint='0664' name='afii57396'/> + <glyph codepoint='0665' name='afii57397'/> + <glyph codepoint='0666' name='afii57398'/> + <glyph codepoint='0667' name='afii57399'/> + <glyph codepoint='0668' name='afii57400'/> + <glyph codepoint='0669' name='afii57401'/> + <glyph codepoint='061B' name='afii57403'/> + <glyph codepoint='061F' name='afii57407'/> + <glyph codepoint='0621' name='afii57409'/> + <glyph codepoint='0622' name='afii57410'/> + <glyph codepoint='0623' name='afii57411'/> + <glyph codepoint='0624' name='afii57412'/> + <glyph codepoint='0625' name='afii57413'/> + <glyph codepoint='0626' name='afii57414'/> + <glyph codepoint='0627' name='afii57415'/> + <glyph codepoint='0628' name='afii57416'/> + <glyph codepoint='0629' name='afii57417'/> + <glyph codepoint='062A' name='afii57418'/> + <glyph codepoint='062B' name='afii57419'/> + <glyph codepoint='062C' name='afii57420'/> + <glyph codepoint='062D' name='afii57421'/> + <glyph codepoint='062E' name='afii57422'/> + <glyph codepoint='062F' name='afii57423'/> + <glyph codepoint='0630' name='afii57424'/> + <glyph codepoint='0631' name='afii57425'/> + <glyph codepoint='0632' name='afii57426'/> + <glyph codepoint='0633' name='afii57427'/> + <glyph codepoint='0634' name='afii57428'/> + <glyph codepoint='0635' name='afii57429'/> + <glyph codepoint='0636' name='afii57430'/> + <glyph codepoint='0637' name='afii57431'/> + <glyph codepoint='0638' name='afii57432'/> + <glyph codepoint='0639' name='afii57433'/> + <glyph codepoint='063A' name='afii57434'/> + <glyph codepoint='0640' name='afii57440'/> + <glyph codepoint='0641' name='afii57441'/> + <glyph codepoint='0642' name='afii57442'/> + <glyph codepoint='0643' name='afii57443'/> + <glyph codepoint='0644' name='afii57444'/> + <glyph codepoint='0645' name='afii57445'/> + <glyph codepoint='0646' name='afii57446'/> + <glyph codepoint='0648' name='afii57448'/> + <glyph codepoint='0649' name='afii57449'/> + <glyph codepoint='064A' name='afii57450'/> + <glyph codepoint='064B' name='afii57451'/> + <glyph codepoint='064C' name='afii57452'/> + <glyph codepoint='064D' name='afii57453'/> + <glyph codepoint='064E' name='afii57454'/> + <glyph codepoint='064F' name='afii57455'/> + <glyph codepoint='0650' name='afii57456'/> + <glyph codepoint='0651' name='afii57457'/> + <glyph codepoint='0652' name='afii57458'/> + <glyph codepoint='0647' name='afii57470'/> + <glyph codepoint='06A4' name='afii57505'/> + <glyph codepoint='067E' name='afii57506'/> + <glyph codepoint='0686' name='afii57507'/> + <glyph codepoint='0698' name='afii57508'/> + <glyph codepoint='06AF' name='afii57509'/> + <glyph codepoint='0679' name='afii57511'/> + <glyph codepoint='0688' name='afii57512'/> + <glyph codepoint='0691' name='afii57513'/> + <glyph codepoint='06BA' name='afii57514'/> + <glyph codepoint='06D2' name='afii57519'/> + <glyph codepoint='06D5' name='afii57534'/> + <glyph codepoint='20AA' name='afii57636'/> + <glyph codepoint='05BE' name='afii57645'/> + <glyph codepoint='05C3' name='afii57658'/> + <glyph codepoint='05D0' name='afii57664'/> + <glyph codepoint='05D1' name='afii57665'/> + <glyph codepoint='05D2' name='afii57666'/> + <glyph codepoint='05D3' name='afii57667'/> + <glyph codepoint='05D4' name='afii57668'/> + <glyph codepoint='05D5' name='afii57669'/> + <glyph codepoint='05D6' name='afii57670'/> + <glyph codepoint='05D7' name='afii57671'/> + <glyph codepoint='05D8' name='afii57672'/> + <glyph codepoint='05D9' name='afii57673'/> + <glyph codepoint='05DA' name='afii57674'/> + <glyph codepoint='05DB' name='afii57675'/> + <glyph codepoint='05DC' name='afii57676'/> + <glyph codepoint='05DD' name='afii57677'/> + <glyph codepoint='05DE' name='afii57678'/> + <glyph codepoint='05DF' name='afii57679'/> + <glyph codepoint='05E0' name='afii57680'/> + <glyph codepoint='05E1' name='afii57681'/> + <glyph codepoint='05E2' name='afii57682'/> + <glyph codepoint='05E3' name='afii57683'/> + <glyph codepoint='05E4' name='afii57684'/> + <glyph codepoint='05E5' name='afii57685'/> + <glyph codepoint='05E6' name='afii57686'/> + <glyph codepoint='05E7' name='afii57687'/> + <glyph codepoint='05E8' name='afii57688'/> + <glyph codepoint='05E9' name='afii57689'/> + <glyph codepoint='05EA' name='afii57690'/> + <glyph codepoint='FB2A' name='afii57694'/> + <glyph codepoint='FB2B' name='afii57695'/> + <glyph codepoint='FB4B' name='afii57700'/> + <glyph codepoint='FB1F' name='afii57705'/> + <glyph codepoint='05F0' name='afii57716'/> + <glyph codepoint='05F1' name='afii57717'/> + <glyph codepoint='05F2' name='afii57718'/> + <glyph codepoint='FB35' name='afii57723'/> + <glyph codepoint='05B4' name='afii57793'/> + <glyph codepoint='05B5' name='afii57794'/> + <glyph codepoint='05B6' name='afii57795'/> + <glyph codepoint='05BB' name='afii57796'/> + <glyph codepoint='05B8' name='afii57797'/> + <glyph codepoint='05B7' name='afii57798'/> + <glyph codepoint='05B0' name='afii57799'/> + <glyph codepoint='05B2' name='afii57800'/> + <glyph codepoint='05B1' name='afii57801'/> + <glyph codepoint='05B3' name='afii57802'/> + <glyph codepoint='05C2' name='afii57803'/> + <glyph codepoint='05C1' name='afii57804'/> + <glyph codepoint='05B9' name='afii57806'/> + <glyph codepoint='05BC' name='afii57807'/> + <glyph codepoint='05BD' name='afii57839'/> + <glyph codepoint='05BF' name='afii57841'/> + <glyph codepoint='05C0' name='afii57842'/> + <glyph codepoint='02BC' name='afii57929'/> + <glyph codepoint='2105' name='afii61248'/> + <glyph codepoint='2113' name='afii61289'/> + <glyph codepoint='2116' name='afii61352'/> + <glyph codepoint='202C' name='afii61573'/> + <glyph codepoint='202D' name='afii61574'/> + <glyph codepoint='202E' name='afii61575'/> + <glyph codepoint='200C' name='afii61664'/> + <glyph codepoint='066D' name='afii63167'/> + <glyph codepoint='02BD' name='afii64937'/> + <glyph codepoint='00E0' name='agrave'/> + <glyph codepoint='2135' name='aleph'/> + <glyph codepoint='03B1' name='alpha'/> + <glyph codepoint='03AC' name='alphatonos'/> + <glyph codepoint='0101' name='amacron'/> + <glyph codepoint='0026' name='ampersand'/> + <glyph codepoint='F726' name='ampersandsmall'/> + <glyph codepoint='2220' name='angle'/> + <glyph codepoint='2329' name='angleleft'/> + <glyph codepoint='232A' name='angleright'/> + <glyph codepoint='0387' name='anoteleia'/> + <glyph codepoint='0105' name='aogonek'/> + <glyph codepoint='2248' name='approxequal'/> + <glyph codepoint='00E5' name='aring'/> + <glyph codepoint='01FB' name='aringacute'/> + <glyph codepoint='2194' name='arrowboth'/> + <glyph codepoint='21D4' name='arrowdblboth'/> + <glyph codepoint='21D3' name='arrowdbldown'/> + <glyph codepoint='21D0' name='arrowdblleft'/> + <glyph codepoint='21D2' name='arrowdblright'/> + <glyph codepoint='21D1' name='arrowdblup'/> + <glyph codepoint='2193' name='arrowdown'/> + <glyph codepoint='F8E7' name='arrowhorizex'/> + <glyph codepoint='2190' name='arrowleft'/> + <glyph codepoint='2192' name='arrowright'/> + <glyph codepoint='2191' name='arrowup'/> + <glyph codepoint='2195' name='arrowupdn'/> + <glyph codepoint='21A8' name='arrowupdnbse'/> + <glyph codepoint='F8E6' name='arrowvertex'/> + <glyph codepoint='005E' name='asciicircum'/> + <glyph codepoint='007E' name='asciitilde'/> + <glyph codepoint='002A' name='asterisk'/> + <glyph codepoint='2217' name='asteriskmath'/> + <glyph codepoint='F6E9' name='asuperior'/> + <glyph codepoint='0040' name='at'/> + <glyph codepoint='00E3' name='atilde'/> + <glyph codepoint='0062' name='b'/> + <glyph codepoint='005C' name='backslash'/> + <glyph codepoint='007C' name='bar'/> + <glyph codepoint='03B2' name='beta'/> + <glyph codepoint='2588' name='block'/> + <glyph codepoint='F8F4' name='braceex'/> + <glyph codepoint='007B' name='braceleft'/> + <glyph codepoint='F8F3' name='braceleftbt'/> + <glyph codepoint='F8F2' name='braceleftmid'/> + <glyph codepoint='F8F1' name='bracelefttp'/> + <glyph codepoint='007D' name='braceright'/> + <glyph codepoint='F8FE' name='bracerightbt'/> + <glyph codepoint='F8FD' name='bracerightmid'/> + <glyph codepoint='F8FC' name='bracerighttp'/> + <glyph codepoint='005B' name='bracketleft'/> + <glyph codepoint='F8F0' name='bracketleftbt'/> + <glyph codepoint='F8EF' name='bracketleftex'/> + <glyph codepoint='F8EE' name='bracketlefttp'/> + <glyph codepoint='005D' name='bracketright'/> + <glyph codepoint='F8FB' name='bracketrightbt'/> + <glyph codepoint='F8FA' name='bracketrightex'/> + <glyph codepoint='F8F9' name='bracketrighttp'/> + <glyph codepoint='02D8' name='breve'/> + <glyph codepoint='00A6' name='brokenbar'/> + <glyph codepoint='F6EA' name='bsuperior'/> + <glyph codepoint='2022' name='bullet'/> + <glyph codepoint='0063' name='c'/> + <glyph codepoint='0107' name='cacute'/> + <glyph codepoint='02C7' name='caron'/> + <glyph codepoint='21B5' name='carriagereturn'/> + <glyph codepoint='010D' name='ccaron'/> + <glyph codepoint='00E7' name='ccedilla'/> + <glyph codepoint='0109' name='ccircumflex'/> + <glyph codepoint='010B' name='cdotaccent'/> + <glyph codepoint='00B8' name='cedilla'/> + <glyph codepoint='00A2' name='cent'/> + <glyph codepoint='F6DF' name='centinferior'/> + <glyph codepoint='F7A2' name='centoldstyle'/> + <glyph codepoint='F6E0' name='centsuperior'/> + <glyph codepoint='03C7' name='chi'/> + <glyph codepoint='25CB' name='circle'/> + <glyph codepoint='2297' name='circlemultiply'/> + <glyph codepoint='2295' name='circleplus'/> + <glyph codepoint='02C6' name='circumflex'/> + <glyph codepoint='2663' name='club'/> + <glyph codepoint='003A' name='colon'/> + <glyph codepoint='20A1' name='colonmonetary'/> + <glyph codepoint='002C' name='comma'/> + <glyph codepoint='F6C3' name='commaaccent'/> + <glyph codepoint='F6E1' name='commainferior'/> + <glyph codepoint='F6E2' name='commasuperior'/> + <glyph codepoint='2245' name='congruent'/> + <glyph codepoint='00A9' name='copyright'/> + <glyph codepoint='F8E9' name='copyrightsans'/> + <glyph codepoint='F6D9' name='copyrightserif'/> + <glyph codepoint='00A4' name='currency'/> + <glyph codepoint='F6D1' name='cyrBreve'/> + <glyph codepoint='F6D2' name='cyrFlex'/> + <glyph codepoint='F6D4' name='cyrbreve'/> + <glyph codepoint='F6D5' name='cyrflex'/> + <glyph codepoint='0064' name='d'/> + <glyph codepoint='2020' name='dagger'/> + <glyph codepoint='2021' name='daggerdbl'/> + <glyph codepoint='F6D3' name='dblGrave'/> + <glyph codepoint='F6D6' name='dblgrave'/> + <glyph codepoint='010F' name='dcaron'/> + <glyph codepoint='0111' name='dcroat'/> + <glyph codepoint='00B0' name='degree'/> + <glyph codepoint='03B4' name='delta'/> + <glyph codepoint='2666' name='diamond'/> + <glyph codepoint='00A8' name='dieresis'/> + <glyph codepoint='F6D7' name='dieresisacute'/> + <glyph codepoint='F6D8' name='dieresisgrave'/> + <glyph codepoint='0385' name='dieresistonos'/> + <glyph codepoint='00F7' name='divide'/> + <glyph codepoint='2593' name='dkshade'/> + <glyph codepoint='2584' name='dnblock'/> + <glyph codepoint='0024' name='dollar'/> + <glyph codepoint='F6E3' name='dollarinferior'/> + <glyph codepoint='F724' name='dollaroldstyle'/> + <glyph codepoint='F6E4' name='dollarsuperior'/> + <glyph codepoint='20AB' name='dong'/> + <glyph codepoint='02D9' name='dotaccent'/> + <glyph codepoint='0323' name='dotbelowcomb'/> + <glyph codepoint='0131' name='dotlessi'/> + <glyph codepoint='F6BE' name='dotlessj'/> + <glyph codepoint='22C5' name='dotmath'/> + <glyph codepoint='F6EB' name='dsuperior'/> + <glyph codepoint='0065' name='e'/> + <glyph codepoint='00E9' name='eacute'/> + <glyph codepoint='0115' name='ebreve'/> + <glyph codepoint='011B' name='ecaron'/> + <glyph codepoint='00EA' name='ecircumflex'/> + <glyph codepoint='00EB' name='edieresis'/> + <glyph codepoint='0117' name='edotaccent'/> + <glyph codepoint='00E8' name='egrave'/> + <glyph codepoint='0038' name='eight'/> + <glyph codepoint='2088' name='eightinferior'/> + <glyph codepoint='F738' name='eightoldstyle'/> + <glyph codepoint='2078' name='eightsuperior'/> + <glyph codepoint='2208' name='element'/> + <glyph codepoint='2026' name='ellipsis'/> + <glyph codepoint='0113' name='emacron'/> + <glyph codepoint='2014' name='emdash'/> + <glyph codepoint='2205' name='emptyset'/> + <glyph codepoint='2013' name='endash'/> + <glyph codepoint='014B' name='eng'/> + <glyph codepoint='0119' name='eogonek'/> + <glyph codepoint='03B5' name='epsilon'/> + <glyph codepoint='03AD' name='epsilontonos'/> + <glyph codepoint='003D' name='equal'/> + <glyph codepoint='2261' name='equivalence'/> + <glyph codepoint='212E' name='estimated'/> + <glyph codepoint='F6EC' name='esuperior'/> + <glyph codepoint='03B7' name='eta'/> + <glyph codepoint='03AE' name='etatonos'/> + <glyph codepoint='00F0' name='eth'/> + <glyph codepoint='0021' name='exclam'/> + <glyph codepoint='203C' name='exclamdbl'/> + <glyph codepoint='00A1' name='exclamdown'/> + <glyph codepoint='F7A1' name='exclamdownsmall'/> + <glyph codepoint='F721' name='exclamsmall'/> + <glyph codepoint='2203' name='existential'/> + <glyph codepoint='0066' name='f'/> + <glyph codepoint='2640' name='female'/> + <glyph codepoint='FB00' name='ff'/> + <glyph codepoint='FB03' name='ffi'/> + <glyph codepoint='FB04' name='ffl'/> + <glyph codepoint='FB01' name='fi'/> + <glyph codepoint='2012' name='figuredash'/> + <glyph codepoint='25A0' name='filledbox'/> + <glyph codepoint='25AC' name='filledrect'/> + <glyph codepoint='0035' name='five'/> + <glyph codepoint='215D' name='fiveeighths'/> + <glyph codepoint='2085' name='fiveinferior'/> + <glyph codepoint='F735' name='fiveoldstyle'/> + <glyph codepoint='2075' name='fivesuperior'/> + <glyph codepoint='FB02' name='fl'/> + <glyph codepoint='0192' name='florin'/> + <glyph codepoint='0034' name='four'/> + <glyph codepoint='2084' name='fourinferior'/> + <glyph codepoint='F734' name='fouroldstyle'/> + <glyph codepoint='2074' name='foursuperior'/> + <glyph codepoint='2044' name='fraction'/> + <glyph codepoint='2215' name='fraction'/> + <glyph codepoint='20A3' name='franc'/> + <glyph codepoint='0067' name='g'/> + <glyph codepoint='03B3' name='gamma'/> + <glyph codepoint='011F' name='gbreve'/> + <glyph codepoint='01E7' name='gcaron'/> + <glyph codepoint='011D' name='gcircumflex'/> + <glyph codepoint='0123' name='gcommaaccent'/> + <glyph codepoint='0121' name='gdotaccent'/> + <glyph codepoint='00DF' name='germandbls'/> + <glyph codepoint='2207' name='gradient'/> + <glyph codepoint='0060' name='grave'/> + <glyph codepoint='0300' name='gravecomb'/> + <glyph codepoint='003E' name='greater'/> + <glyph codepoint='2265' name='greaterequal'/> + <glyph codepoint='00AB' name='guillemotleft'/> + <glyph codepoint='00BB' name='guillemotright'/> + <glyph codepoint='2039' name='guilsinglleft'/> + <glyph codepoint='203A' name='guilsinglright'/> + <glyph codepoint='0068' name='h'/> + <glyph codepoint='0127' name='hbar'/> + <glyph codepoint='0125' name='hcircumflex'/> + <glyph codepoint='2665' name='heart'/> + <glyph codepoint='0309' name='hookabovecomb'/> + <glyph codepoint='2302' name='house'/> + <glyph codepoint='02DD' name='hungarumlaut'/> + <glyph codepoint='002D' name='hyphen'/> + <glyph codepoint='00AD' name='hyphen'/> + <glyph codepoint='F6E5' name='hypheninferior'/> + <glyph codepoint='F6E6' name='hyphensuperior'/> + <glyph codepoint='0069' name='i'/> + <glyph codepoint='00ED' name='iacute'/> + <glyph codepoint='012D' name='ibreve'/> + <glyph codepoint='00EE' name='icircumflex'/> + <glyph codepoint='00EF' name='idieresis'/> + <glyph codepoint='00EC' name='igrave'/> + <glyph codepoint='0133' name='ij'/> + <glyph codepoint='012B' name='imacron'/> + <glyph codepoint='221E' name='infinity'/> + <glyph codepoint='222B' name='integral'/> + <glyph codepoint='2321' name='integralbt'/> + <glyph codepoint='F8F5' name='integralex'/> + <glyph codepoint='2320' name='integraltp'/> + <glyph codepoint='2229' name='intersection'/> + <glyph codepoint='25D8' name='invbullet'/> + <glyph codepoint='25D9' name='invcircle'/> + <glyph codepoint='263B' name='invsmileface'/> + <glyph codepoint='012F' name='iogonek'/> + <glyph codepoint='03B9' name='iota'/> + <glyph codepoint='03CA' name='iotadieresis'/> + <glyph codepoint='0390' name='iotadieresistonos'/> + <glyph codepoint='03AF' name='iotatonos'/> + <glyph codepoint='F6ED' name='isuperior'/> + <glyph codepoint='0129' name='itilde'/> + <glyph codepoint='006A' name='j'/> + <glyph codepoint='0135' name='jcircumflex'/> + <glyph codepoint='006B' name='k'/> + <glyph codepoint='03BA' name='kappa'/> + <glyph codepoint='0137' name='kcommaaccent'/> + <glyph codepoint='0138' name='kgreenlandic'/> + <glyph codepoint='006C' name='l'/> + <glyph codepoint='013A' name='lacute'/> + <glyph codepoint='03BB' name='lambda'/> + <glyph codepoint='013E' name='lcaron'/> + <glyph codepoint='013C' name='lcommaaccent'/> + <glyph codepoint='0140' name='ldot'/> + <glyph codepoint='003C' name='less'/> + <glyph codepoint='2264' name='lessequal'/> + <glyph codepoint='258C' name='lfblock'/> + <glyph codepoint='20A4' name='lira'/> + <glyph codepoint='F6C0' name='ll'/> + <glyph codepoint='2227' name='logicaland'/> + <glyph codepoint='00AC' name='logicalnot'/> + <glyph codepoint='2228' name='logicalor'/> + <glyph codepoint='017F' name='longs'/> + <glyph codepoint='25CA' name='lozenge'/> + <glyph codepoint='0142' name='lslash'/> + <glyph codepoint='F6EE' name='lsuperior'/> + <glyph codepoint='2591' name='ltshade'/> + <glyph codepoint='006D' name='m'/> + <glyph codepoint='00AF' name='macron'/> + <glyph codepoint='02C9' name='macron'/> + <glyph codepoint='2642' name='male'/> + <glyph codepoint='2212' name='minus'/> + <glyph codepoint='2032' name='minute'/> + <glyph codepoint='F6EF' name='msuperior'/> + <glyph codepoint='00B5' name='mu'/> + <glyph codepoint='03BC' name='mu'/> + <glyph codepoint='00D7' name='multiply'/> + <glyph codepoint='266A' name='musicalnote'/> + <glyph codepoint='266B' name='musicalnotedbl'/> + <glyph codepoint='006E' name='n'/> + <glyph codepoint='0144' name='nacute'/> + <glyph codepoint='0149' name='napostrophe'/> + <glyph codepoint='0148' name='ncaron'/> + <glyph codepoint='0146' name='ncommaaccent'/> + <glyph codepoint='0039' name='nine'/> + <glyph codepoint='2089' name='nineinferior'/> + <glyph codepoint='F739' name='nineoldstyle'/> + <glyph codepoint='2079' name='ninesuperior'/> + <glyph codepoint='2209' name='notelement'/> + <glyph codepoint='2260' name='notequal'/> + <glyph codepoint='2284' name='notsubset'/> + <glyph codepoint='207F' name='nsuperior'/> + <glyph codepoint='00F1' name='ntilde'/> + <glyph codepoint='03BD' name='nu'/> + <glyph codepoint='0023' name='numbersign'/> + <glyph codepoint='006F' name='o'/> + <glyph codepoint='00F3' name='oacute'/> + <glyph codepoint='014F' name='obreve'/> + <glyph codepoint='00F4' name='ocircumflex'/> + <glyph codepoint='00F6' name='odieresis'/> + <glyph codepoint='0153' name='oe'/> + <glyph codepoint='02DB' name='ogonek'/> + <glyph codepoint='00F2' name='ograve'/> + <glyph codepoint='01A1' name='ohorn'/> + <glyph codepoint='0151' name='ohungarumlaut'/> + <glyph codepoint='014D' name='omacron'/> + <glyph codepoint='03C9' name='omega'/> + <glyph codepoint='03D6' name='omega1'/> + <glyph codepoint='03CE' name='omegatonos'/> + <glyph codepoint='03BF' name='omicron'/> + <glyph codepoint='03CC' name='omicrontonos'/> + <glyph codepoint='0031' name='one'/> + <glyph codepoint='2024' name='onedotenleader'/> + <glyph codepoint='215B' name='oneeighth'/> + <glyph codepoint='F6DC' name='onefitted'/> + <glyph codepoint='00BD' name='onehalf'/> + <glyph codepoint='2081' name='oneinferior'/> + <glyph codepoint='F731' name='oneoldstyle'/> + <glyph codepoint='00BC' name='onequarter'/> + <glyph codepoint='00B9' name='onesuperior'/> + <glyph codepoint='2153' name='onethird'/> + <glyph codepoint='25E6' name='openbullet'/> + <glyph codepoint='00AA' name='ordfeminine'/> + <glyph codepoint='00BA' name='ordmasculine'/> + <glyph codepoint='221F' name='orthogonal'/> + <glyph codepoint='00F8' name='oslash'/> + <glyph codepoint='01FF' name='oslashacute'/> + <glyph codepoint='F6F0' name='osuperior'/> + <glyph codepoint='00F5' name='otilde'/> + <glyph codepoint='0070' name='p'/> + <glyph codepoint='00B6' name='paragraph'/> + <glyph codepoint='0028' name='parenleft'/> + <glyph codepoint='F8ED' name='parenleftbt'/> + <glyph codepoint='F8EC' name='parenleftex'/> + <glyph codepoint='208D' name='parenleftinferior'/> + <glyph codepoint='207D' name='parenleftsuperior'/> + <glyph codepoint='F8EB' name='parenlefttp'/> + <glyph codepoint='0029' name='parenright'/> + <glyph codepoint='F8F8' name='parenrightbt'/> + <glyph codepoint='F8F7' name='parenrightex'/> + <glyph codepoint='208E' name='parenrightinferior'/> + <glyph codepoint='207E' name='parenrightsuperior'/> + <glyph codepoint='F8F6' name='parenrighttp'/> + <glyph codepoint='2202' name='partialdiff'/> + <glyph codepoint='0025' name='percent'/> + <glyph codepoint='002E' name='period'/> + <glyph codepoint='00B7' name='periodcentered'/> + <glyph codepoint='2219' name='periodcentered'/> + <glyph codepoint='F6E7' name='periodinferior'/> + <glyph codepoint='F6E8' name='periodsuperior'/> + <glyph codepoint='22A5' name='perpendicular'/> + <glyph codepoint='2030' name='perthousand'/> + <glyph codepoint='20A7' name='peseta'/> + <glyph codepoint='03C6' name='phi'/> + <glyph codepoint='03D5' name='phi1'/> + <glyph codepoint='03C0' name='pi'/> + <glyph codepoint='002B' name='plus'/> + <glyph codepoint='00B1' name='plusminus'/> + <glyph codepoint='211E' name='prescription'/> + <glyph codepoint='220F' name='product'/> + <glyph codepoint='2282' name='propersubset'/> + <glyph codepoint='2283' name='propersuperset'/> + <glyph codepoint='221D' name='proportional'/> + <glyph codepoint='03C8' name='psi'/> + <glyph codepoint='0071' name='q'/> + <glyph codepoint='003F' name='question'/> + <glyph codepoint='00BF' name='questiondown'/> + <glyph codepoint='F7BF' name='questiondownsmall'/> + <glyph codepoint='F73F' name='questionsmall'/> + <glyph codepoint='0022' name='quotedbl'/> + <glyph codepoint='201E' name='quotedblbase'/> + <glyph codepoint='201C' name='quotedblleft'/> + <glyph codepoint='201D' name='quotedblright'/> + <glyph codepoint='2018' name='quoteleft'/> + <glyph codepoint='201B' name='quotereversed'/> + <glyph codepoint='2019' name='quoteright'/> + <glyph codepoint='201A' name='quotesinglbase'/> + <glyph codepoint='0027' name='quotesingle'/> + <glyph codepoint='0072' name='r'/> + <glyph codepoint='0155' name='racute'/> + <glyph codepoint='221A' name='radical'/> + <glyph codepoint='F8E5' name='radicalex'/> + <glyph codepoint='0159' name='rcaron'/> + <glyph codepoint='0157' name='rcommaaccent'/> + <glyph codepoint='2286' name='reflexsubset'/> + <glyph codepoint='2287' name='reflexsuperset'/> + <glyph codepoint='00AE' name='registered'/> + <glyph codepoint='F8E8' name='registersans'/> + <glyph codepoint='F6DA' name='registerserif'/> + <glyph codepoint='2310' name='revlogicalnot'/> + <glyph codepoint='03C1' name='rho'/> + <glyph codepoint='02DA' name='ring'/> + <glyph codepoint='F6F1' name='rsuperior'/> + <glyph codepoint='2590' name='rtblock'/> + <glyph codepoint='F6DD' name='rupiah'/> + <glyph codepoint='0073' name='s'/> + <glyph codepoint='015B' name='sacute'/> + <glyph codepoint='0161' name='scaron'/> + <glyph codepoint='015F' name='scedilla'/> + <glyph codepoint='F6C2' name='scedilla'/> + <glyph codepoint='015D' name='scircumflex'/> + <glyph codepoint='0219' name='scommaaccent'/> + <glyph codepoint='2033' name='second'/> + <glyph codepoint='00A7' name='section'/> + <glyph codepoint='003B' name='semicolon'/> + <glyph codepoint='0037' name='seven'/> + <glyph codepoint='215E' name='seveneighths'/> + <glyph codepoint='2087' name='seveninferior'/> + <glyph codepoint='F737' name='sevenoldstyle'/> + <glyph codepoint='2077' name='sevensuperior'/> + <glyph codepoint='2592' name='shade'/> + <glyph codepoint='03C3' name='sigma'/> + <glyph codepoint='03C2' name='sigma1'/> + <glyph codepoint='223C' name='similar'/> + <glyph codepoint='0036' name='six'/> + <glyph codepoint='2086' name='sixinferior'/> + <glyph codepoint='F736' name='sixoldstyle'/> + <glyph codepoint='2076' name='sixsuperior'/> + <glyph codepoint='002F' name='slash'/> + <glyph codepoint='263A' name='smileface'/> + <glyph codepoint='0020' name='space'/> + <glyph codepoint='00A0' name='space'/> + <glyph codepoint='2660' name='spade'/> + <glyph codepoint='F6F2' name='ssuperior'/> + <glyph codepoint='00A3' name='sterling'/> + <glyph codepoint='220B' name='suchthat'/> + <glyph codepoint='2211' name='summation'/> + <glyph codepoint='263C' name='sun'/> + <glyph codepoint='0074' name='t'/> + <glyph codepoint='03C4' name='tau'/> + <glyph codepoint='0167' name='tbar'/> + <glyph codepoint='0165' name='tcaron'/> + <glyph codepoint='0163' name='tcommaaccent'/> + <glyph codepoint='021B' name='tcommaaccent'/> + <glyph codepoint='2234' name='therefore'/> + <glyph codepoint='03B8' name='theta'/> + <glyph codepoint='03D1' name='theta1'/> + <glyph codepoint='00FE' name='thorn'/> + <glyph codepoint='0033' name='three'/> + <glyph codepoint='215C' name='threeeighths'/> + <glyph codepoint='2083' name='threeinferior'/> + <glyph codepoint='F733' name='threeoldstyle'/> + <glyph codepoint='00BE' name='threequarters'/> + <glyph codepoint='F6DE' name='threequartersemdash'/> + <glyph codepoint='00B3' name='threesuperior'/> + <glyph codepoint='02DC' name='tilde'/> + <glyph codepoint='0303' name='tildecomb'/> + <glyph codepoint='0384' name='tonos'/> + <glyph codepoint='2122' name='trademark'/> + <glyph codepoint='F8EA' name='trademarksans'/> + <glyph codepoint='F6DB' name='trademarkserif'/> + <glyph codepoint='25BC' name='triagdn'/> + <glyph codepoint='25C4' name='triaglf'/> + <glyph codepoint='25BA' name='triagrt'/> + <glyph codepoint='25B2' name='triagup'/> + <glyph codepoint='F6F3' name='tsuperior'/> + <glyph codepoint='0032' name='two'/> + <glyph codepoint='2025' name='twodotenleader'/> + <glyph codepoint='2082' name='twoinferior'/> + <glyph codepoint='F732' name='twooldstyle'/> + <glyph codepoint='00B2' name='twosuperior'/> + <glyph codepoint='2154' name='twothirds'/> + <glyph codepoint='0075' name='u'/> + <glyph codepoint='00FA' name='uacute'/> + <glyph codepoint='016D' name='ubreve'/> + <glyph codepoint='00FB' name='ucircumflex'/> + <glyph codepoint='00FC' name='udieresis'/> + <glyph codepoint='00F9' name='ugrave'/> + <glyph codepoint='01B0' name='uhorn'/> + <glyph codepoint='0171' name='uhungarumlaut'/> + <glyph codepoint='016B' name='umacron'/> + <glyph codepoint='005F' name='underscore'/> + <glyph codepoint='2017' name='underscoredbl'/> + <glyph codepoint='222A' name='union'/> + <glyph codepoint='2200' name='universal'/> + <glyph codepoint='0173' name='uogonek'/> + <glyph codepoint='2580' name='upblock'/> + <glyph codepoint='03C5' name='upsilon'/> + <glyph codepoint='03CB' name='upsilondieresis'/> + <glyph codepoint='03B0' name='upsilondieresistonos'/> + <glyph codepoint='03CD' name='upsilontonos'/> + <glyph codepoint='016F' name='uring'/> + <glyph codepoint='0169' name='utilde'/> + <glyph codepoint='0076' name='v'/> + <glyph codepoint='0077' name='w'/> + <glyph codepoint='1E83' name='wacute'/> + <glyph codepoint='0175' name='wcircumflex'/> + <glyph codepoint='1E85' name='wdieresis'/> + <glyph codepoint='2118' name='weierstrass'/> + <glyph codepoint='1E81' name='wgrave'/> + <glyph codepoint='0078' name='x'/> + <glyph codepoint='03BE' name='xi'/> + <glyph codepoint='0079' name='y'/> + <glyph codepoint='00FD' name='yacute'/> + <glyph codepoint='0177' name='ycircumflex'/> + <glyph codepoint='00FF' name='ydieresis'/> + <glyph codepoint='00A5' name='yen'/> + <glyph codepoint='1EF3' name='ygrave'/> + <glyph codepoint='007A' name='z'/> + <glyph codepoint='017A' name='zacute'/> + <glyph codepoint='017E' name='zcaron'/> + <glyph codepoint='017C' name='zdotaccent'/> + <glyph codepoint='0030' name='zero'/> + <glyph codepoint='2080' name='zeroinferior'/> + <glyph codepoint='F730' name='zerooldstyle'/> + <glyph codepoint='2070' name='zerosuperior'/> + <glyph codepoint='03B6' name='zeta'/> + </glyphlist> + + <!-- This encodes the Zapf Dingbats Glyph List, version 1.0 (17 July 1997) + located at http://partners.adobe.com/asn/developer/type/zapfdingbats.txt + --> + <glyphlist id='ZGL'> + <glyph codepoint='0020' name='space'/> + <glyph codepoint='00A0' name='space'/> + <glyph codepoint='2701' name='a1'/> + <glyph codepoint='2702' name='a2'/> + <glyph codepoint='2703' name='a202'/> + <glyph codepoint='2704' name='a3'/> + <glyph codepoint='260E' name='a4'/> + <glyph codepoint='2706' name='a5'/> + <glyph codepoint='2707' name='a119'/> + <glyph codepoint='2708' name='a118'/> + <glyph codepoint='2709' name='a117'/> + <glyph codepoint='261B' name='a11'/> + <glyph codepoint='261E' name='a12'/> + <glyph codepoint='270C' name='a13'/> + <glyph codepoint='270D' name='a14'/> + <glyph codepoint='270E' name='a15'/> + <glyph codepoint='270F' name='a16'/> + <glyph codepoint='2710' name='a105'/> + <glyph codepoint='2711' name='a17'/> + <glyph codepoint='2712' name='a18'/> + <glyph codepoint='2713' name='a19'/> + <glyph codepoint='2714' name='a20'/> + <glyph codepoint='2715' name='a21'/> + <glyph codepoint='2716' name='a22'/> + <glyph codepoint='2717' name='a23'/> + <glyph codepoint='2718' name='a24'/> + <glyph codepoint='2719' name='a25'/> + <glyph codepoint='271A' name='a26'/> + <glyph codepoint='271B' name='a27'/> + <glyph codepoint='271C' name='a28'/> + <glyph codepoint='271D' name='a6'/> + <glyph codepoint='271E' name='a7'/> + <glyph codepoint='271F' name='a8'/> + <glyph codepoint='2720' name='a9'/> + <glyph codepoint='2721' name='a10'/> + <glyph codepoint='2722' name='a29'/> + <glyph codepoint='2723' name='a30'/> + <glyph codepoint='2724' name='a31'/> + <glyph codepoint='2725' name='a32'/> + <glyph codepoint='2726' name='a33'/> + <glyph codepoint='2727' name='a34'/> + <glyph codepoint='2605' name='a35'/> + <glyph codepoint='2729' name='a36'/> + <glyph codepoint='272A' name='a37'/> + <glyph codepoint='272B' name='a38'/> + <glyph codepoint='272C' name='a39'/> + <glyph codepoint='272D' name='a40'/> + <glyph codepoint='272E' name='a41'/> + <glyph codepoint='272F' name='a42'/> + <glyph codepoint='2730' name='a43'/> + <glyph codepoint='2731' name='a44'/> + <glyph codepoint='2732' name='a45'/> + <glyph codepoint='2733' name='a46'/> + <glyph codepoint='2734' name='a47'/> + <glyph codepoint='2735' name='a48'/> + <glyph codepoint='2736' name='a49'/> + <glyph codepoint='2737' name='a50'/> + <glyph codepoint='2738' name='a51'/> + <glyph codepoint='2739' name='a52'/> + <glyph codepoint='273A' name='a53'/> + <glyph codepoint='273B' name='a54'/> + <glyph codepoint='273C' name='a55'/> + <glyph codepoint='273D' name='a56'/> + <glyph codepoint='273E' name='a57'/> + <glyph codepoint='273F' name='a58'/> + <glyph codepoint='2740' name='a59'/> + <glyph codepoint='2741' name='a60'/> + <glyph codepoint='2742' name='a61'/> + <glyph codepoint='2743' name='a62'/> + <glyph codepoint='2744' name='a63'/> + <glyph codepoint='2745' name='a64'/> + <glyph codepoint='2746' name='a65'/> + <glyph codepoint='2747' name='a66'/> + <glyph codepoint='2748' name='a67'/> + <glyph codepoint='2749' name='a68'/> + <glyph codepoint='274A' name='a69'/> + <glyph codepoint='274B' name='a70'/> + <glyph codepoint='25CF' name='a71'/> + <glyph codepoint='274D' name='a72'/> + <glyph codepoint='25A0' name='a73'/> + <glyph codepoint='274F' name='a74'/> + <glyph codepoint='2750' name='a203'/> + <glyph codepoint='2751' name='a75'/> + <glyph codepoint='2752' name='a204'/> + <glyph codepoint='25B2' name='a76'/> + <glyph codepoint='25BC' name='a77'/> + <glyph codepoint='25C6' name='a78'/> + <glyph codepoint='2756' name='a79'/> + <glyph codepoint='25D7' name='a81'/> + <glyph codepoint='2758' name='a82'/> + <glyph codepoint='2759' name='a83'/> + <glyph codepoint='275A' name='a84'/> + <glyph codepoint='275B' name='a97'/> + <glyph codepoint='275C' name='a98'/> + <glyph codepoint='275D' name='a99'/> + <glyph codepoint='275E' name='a100'/> + <glyph codepoint='F8D7' name='a89'/> + <glyph codepoint='F8D8' name='a90'/> + <glyph codepoint='F8D9' name='a93'/> + <glyph codepoint='F8DA' name='a94'/> + <glyph codepoint='F8DB' name='a91'/> + <glyph codepoint='F8DC' name='a92'/> + <glyph codepoint='F8DD' name='a205'/> + <glyph codepoint='F8DE' name='a85'/> + <glyph codepoint='F8DF' name='a206'/> + <glyph codepoint='F8E0' name='a86'/> + <glyph codepoint='F8E1' name='a87'/> + <glyph codepoint='F8E2' name='a88'/> + <glyph codepoint='F8E3' name='a95'/> + <glyph codepoint='F8E4' name='a96'/> + <glyph codepoint='2761' name='a101'/> + <glyph codepoint='2762' name='a102'/> + <glyph codepoint='2763' name='a103'/> + <glyph codepoint='2764' name='a104'/> + <glyph codepoint='2765' name='a106'/> + <glyph codepoint='2766' name='a107'/> + <glyph codepoint='2767' name='a108'/> + <glyph codepoint='2663' name='a112'/> + <glyph codepoint='2666' name='a111'/> + <glyph codepoint='2665' name='a110'/> + <glyph codepoint='2660' name='a109'/> + <glyph codepoint='2460' name='a120'/> + <glyph codepoint='2461' name='a121'/> + <glyph codepoint='2462' name='a122'/> + <glyph codepoint='2463' name='a123'/> + <glyph codepoint='2464' name='a124'/> + <glyph codepoint='2465' name='a125'/> + <glyph codepoint='2466' name='a126'/> + <glyph codepoint='2467' name='a127'/> + <glyph codepoint='2468' name='a128'/> + <glyph codepoint='2469' name='a129'/> + <glyph codepoint='2776' name='a130'/> + <glyph codepoint='2777' name='a131'/> + <glyph codepoint='2778' name='a132'/> + <glyph codepoint='2779' name='a133'/> + <glyph codepoint='277A' name='a134'/> + <glyph codepoint='277B' name='a135'/> + <glyph codepoint='277C' name='a136'/> + <glyph codepoint='277D' name='a137'/> + <glyph codepoint='277E' name='a138'/> + <glyph codepoint='277F' name='a139'/> + <glyph codepoint='2780' name='a140'/> + <glyph codepoint='2781' name='a141'/> + <glyph codepoint='2782' name='a142'/> + <glyph codepoint='2783' name='a143'/> + <glyph codepoint='2784' name='a144'/> + <glyph codepoint='2785' name='a145'/> + <glyph codepoint='2786' name='a146'/> + <glyph codepoint='2787' name='a147'/> + <glyph codepoint='2788' name='a148'/> + <glyph codepoint='2789' name='a149'/> + <glyph codepoint='278A' name='a150'/> + <glyph codepoint='278B' name='a151'/> + <glyph codepoint='278C' name='a152'/> + <glyph codepoint='278D' name='a153'/> + <glyph codepoint='278E' name='a154'/> + <glyph codepoint='278F' name='a155'/> + <glyph codepoint='2790' name='a156'/> + <glyph codepoint='2791' name='a157'/> + <glyph codepoint='2792' name='a158'/> + <glyph codepoint='2793' name='a159'/> + <glyph codepoint='2794' name='a160'/> + <glyph codepoint='2192' name='a161'/> + <glyph codepoint='2194' name='a163'/> + <glyph codepoint='2195' name='a164'/> + <glyph codepoint='2798' name='a196'/> + <glyph codepoint='2799' name='a165'/> + <glyph codepoint='279A' name='a192'/> + <glyph codepoint='279B' name='a166'/> + <glyph codepoint='279C' name='a167'/> + <glyph codepoint='279D' name='a168'/> + <glyph codepoint='279E' name='a169'/> + <glyph codepoint='279F' name='a170'/> + <glyph codepoint='27A0' name='a171'/> + <glyph codepoint='27A1' name='a172'/> + <glyph codepoint='27A2' name='a173'/> + <glyph codepoint='27A3' name='a162'/> + <glyph codepoint='27A4' name='a174'/> + <glyph codepoint='27A5' name='a175'/> + <glyph codepoint='27A6' name='a176'/> + <glyph codepoint='27A7' name='a177'/> + <glyph codepoint='27A8' name='a178'/> + <glyph codepoint='27A9' name='a179'/> + <glyph codepoint='27AA' name='a193'/> + <glyph codepoint='27AB' name='a180'/> + <glyph codepoint='27AC' name='a199'/> + <glyph codepoint='27AD' name='a181'/> + <glyph codepoint='27AE' name='a200'/> + <glyph codepoint='27AF' name='a182'/> + <glyph codepoint='27B1' name='a201'/> + <glyph codepoint='27B2' name='a183'/> + <glyph codepoint='27B3' name='a184'/> + <glyph codepoint='27B4' name='a197'/> + <glyph codepoint='27B5' name='a185'/> + <glyph codepoint='27B6' name='a194'/> + <glyph codepoint='27B7' name='a198'/> + <glyph codepoint='27B8' name='a186'/> + <glyph codepoint='27B9' name='a195'/> + <glyph codepoint='27BA' name='a187'/> + <glyph codepoint='27BB' name='a188'/> + <glyph codepoint='27BC' name='a189'/> + <glyph codepoint='27BD' name='a190'/> + <glyph codepoint='27BE' name='a191'/> + </glyphlist> +</glyphlist-set> diff --git a/src/org/apache/fop/apps/AWTStarter.java b/src/org/apache/fop/apps/AWTStarter.java index 27749d9f8..9ee4f91e2 100644 --- a/src/org/apache/fop/apps/AWTStarter.java +++ b/src/org/apache/fop/apps/AWTStarter.java @@ -15,6 +15,8 @@ package org.apache.fop.apps; */ import org.apache.fop.viewer.*; import org.apache.fop.render.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import javax.swing.UIManager; @@ -49,6 +51,8 @@ public class AWTStarter extends CommandLineStarter { PreviewDialog frame; AWTRenderer renderer; + protected Driver driver; + protected XMLReader parser; public static String TRANSLATION_PATH = "/org/apache/fop/viewer/resources/"; @@ -60,7 +64,7 @@ public class AWTStarter extends CommandLineStarter { init(); } - private void init() { + private void init() throws FOPException { try { UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel()); } catch (Exception e) { @@ -88,29 +92,24 @@ public class AWTStarter extends CommandLineStarter { frame = createPreviewDialog(renderer, resource); renderer.setProgressListener(frame); renderer.setComponent(frame); - } - - - public void run() throws FOPException { - Driver driver = new Driver(); + driver = new Driver(); driver.setLogger(log); if (errorDump) { driver.setErrorDump(true); } - + driver.setRenderer(renderer); // init parser frame.progress(resource.getString("Init parser") + " ..."); - XMLReader parser = inputHandler.getParser(); - + parser = inputHandler.getParser(); if (parser == null) { throw new FOPException("Unable to create SAX parser"); } + } - setParserFeatures(parser); + public void run() throws FOPException { + driver.reset(); try { - driver.setRenderer(renderer); - // build FO tree: time frame.progress(resource.getString("Build FO tree") + " ..."); driver.render(parser, inputHandler.getInputSource()); @@ -119,6 +118,7 @@ public class AWTStarter extends CommandLineStarter { frame.showPage(); } catch (Exception e) { + frame.reportException(e); if (e instanceof FOPException) { throw (FOPException)e; } @@ -129,8 +129,13 @@ public class AWTStarter extends CommandLineStarter { protected PreviewDialog createPreviewDialog(AWTRenderer renderer, Translator res) { - PreviewDialog frame = new PreviewDialog(renderer, res); + PreviewDialog frame = new PreviewDialog(this, renderer, res); frame.validate(); + frame.addWindowListener(new WindowAdapter() { + public void windowClosed(WindowEvent we) { + System.exit(0); + } + }); // center window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); @@ -152,6 +157,15 @@ public class AWTStarter extends CommandLineStarter { try { URL url = getClass().getResource(path); + + /* The following code was added by Alex Alishevskikh [alex@openmechanics.net] + to fix for crashes on machines with unsupported user languages */ + if (url == null) { + // if the given resource file not found, the english resource uses as default + path = path.substring(0, path.lastIndexOf(".")) + ".en"; + url = getClass().getResource(path); + } + in = url.openStream(); } catch (Exception ex) { log.error("Can't find URL to: <" + path + "> " diff --git a/src/org/apache/fop/apps/CommandLineOptions.java b/src/org/apache/fop/apps/CommandLineOptions.java index 44737ef62..116da7f24 100644 --- a/src/org/apache/fop/apps/CommandLineOptions.java +++ b/src/org/apache/fop/apps/CommandLineOptions.java @@ -15,11 +15,11 @@ import java.io.FileNotFoundException; // FOP import org.apache.fop.configuration.Configuration; import org.apache.fop.apps.FOPException; +import org.apache.fop.messaging.MessageHandler; -import org.apache.log.*; -import org.apache.log.format.*; -import org.apache.log.output.io.*; -import org.apache.log.output.*; +// Avalon +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; import java.io.*; @@ -58,24 +58,24 @@ public class CommandLineOptions { private static final int AREA_OUTPUT = 9; /* use debug mode */ - Boolean errorDump = new Boolean(false); + Boolean errorDump = Boolean.FALSE; /* show configuration information */ - Boolean dumpConfiguration = new Boolean(false); + Boolean dumpConfiguration = Boolean.FALSE; /* suppress any progress information */ - Boolean quiet = new Boolean(false); + Boolean quiet = Boolean.FALSE; /* for area tree XML output, only down to block area level */ - Boolean suppressLowLevelAreas = new Boolean(false); - /* name of user configuration file */ + Boolean suppressLowLevelAreas = Boolean.FALSE; + /* user configuration file */ File userConfigFile = null; - /* name of input fo file */ + /* input fo file */ File fofile = null; - /* name of xsltfile (xslt transformation as input) */ + /* xsltfile (xslt transformation as input) */ File xsltfile = null; - /* name of xml file (xslt transformation as input) */ + /* xml file (xslt transformation as input) */ File xmlfile = null; - /* name of output file */ + /* output file */ File outfile = null; - /* name of buffer file */ + /* buffer file */ File bufferFile = null; /* input mode */ int inputmode = NOT_SET; @@ -93,24 +93,7 @@ public class CommandLineOptions { public CommandLineOptions(String[] args) throws FOPException, FileNotFoundException { - Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); - PatternFormatter formatter = new PatternFormatter( - "[%{priority}]: %{message}\n%{throwable}" ); - - LogTarget target = null; - boolean doConsoleLogging = true; - if (doConsoleLogging) { - target = new StreamTarget(System.out, formatter); - } else { - try { - File f = new File("fop.log"); - target = new FileTarget(f, false, formatter); - } catch (IOException e) {} - } - - hierarchy.setDefaultLogTarget(target); - log = hierarchy.getLoggerFor("fop"); - log.setPriority(Priority.INFO); + setLogger(new ConsoleLogger(ConsoleLogger.LEVEL_INFO)); boolean optionsParsed = true; rendererOptions = new java.util.Hashtable(); @@ -140,14 +123,14 @@ public class CommandLineOptions { private boolean parseOptions(String args[]) throws FOPException { for (int i = 0; i < args.length; i++) { if (args[i].equals("-d") || args[i].equals("--full-error-dump")) { - errorDump = new Boolean(true); - log.setPriority(Priority.DEBUG); + errorDump = Boolean.TRUE; + setLogger(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG)); } else if (args[i].equals("-x") || args[i].equals("--dump-config")) { - dumpConfiguration = new Boolean(true); + dumpConfiguration = Boolean.TRUE; } else if (args[i].equals("-q") || args[i].equals("--quiet")) { - quiet = new Boolean(true); - log.setPriority(Priority.ERROR); + quiet = Boolean.TRUE; + setLogger(new ConsoleLogger(ConsoleLogger.LEVEL_ERROR)); } else if (args[i].equals("-c")) { if ((i + 1 == args.length) || (args[i + 1].charAt(0) == '-')) { @@ -165,7 +148,7 @@ public class CommandLineOptions { i++; } } else if (args[i].equals("-s")) { - suppressLowLevelAreas = new Boolean(true); + suppressLowLevelAreas = Boolean.TRUE; } else if (args[i].equals("-fo")) { inputmode = FO_INPUT; if ((i + 1 == args.length) @@ -365,6 +348,11 @@ public class CommandLineOptions { } } // end checkSettings + private void setLogger(Logger newLogger) { + this.log = newLogger; + MessageHandler.setScreenLogger(newLogger); + } + /** * returns the chosen renderer, throws FOPException */ diff --git a/src/org/apache/fop/apps/CommandLineStarter.java b/src/org/apache/fop/apps/CommandLineStarter.java index c7d463290..775b02397 100644 --- a/src/org/apache/fop/apps/CommandLineStarter.java +++ b/src/org/apache/fop/apps/CommandLineStarter.java @@ -13,8 +13,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -import org.apache.log.*; - // Java import java.io.*; import java.net.URL; @@ -53,7 +51,6 @@ public class CommandLineStarter extends Starter { log.info(version); XMLReader parser = inputHandler.getParser(); - setParserFeatures(parser); Driver driver = new Driver(); driver.setLogger(log); @@ -63,20 +60,28 @@ public class CommandLineStarter extends Starter { driver.setErrorDump(true); } + FileOutputStream output=null; try { + output=new FileOutputStream(commandLineOptions.getOutputFile()); driver.setRenderer(commandLineOptions.getRenderer()); - driver.setOutputStream( new FileOutputStream( - commandLineOptions.getOutputFile())); + driver.setOutputStream(output); driver.getRenderer().setOptions( commandLineOptions.getRendererOptions()); driver.render(parser, inputHandler.getInputSource()); - System.exit(0); } catch (Exception e) { if (e instanceof FOPException) { throw (FOPException) e; } throw new FOPException(e); } + finally { + if (output!=null) { + try { + output.close(); + } + catch(Exception e) {} + } + } } } diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java index 203d062e1..8d2b0aaa0 100644 --- a/src/org/apache/fop/apps/Driver.java +++ b/src/org/apache/fop/apps/Driver.java @@ -21,11 +21,9 @@ import org.apache.fop.render.pdf.PDFRenderer; import org.apache.fop.system.BufferManager; -import org.apache.log.*; -import org.apache.log.format.*; -import org.apache.log.output.io.*; -import org.apache.log.output.*; -import org.apache.avalon.framework.logger.Loggable; +// Avalon +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; // DOM import org.w3c.dom.Document; @@ -89,7 +87,7 @@ import java.util.*; * driver.render(parser, fileInputSource(args[0])); * </PRE> */ -public class Driver implements Loggable { +public class Driver { /** * Render to PDF. OutputStream must be set @@ -179,15 +177,13 @@ public class Driver implements Loggable { private Logger log; public static final String getParserClassName() { - String parserClassName = null; try { - parserClassName = System.getProperty("org.xml.sax.parser"); - } catch (SecurityException se) {} - - if (parserClassName == null) { - parserClassName = "org.apache.xerces.parsers.SAXParser"; + return javax.xml.parsers.SAXParserFactory.newInstance().newSAXParser().getXMLReader().getClass().getName(); + } catch (javax.xml.parsers.ParserConfigurationException e) { + return null; + } catch (org.xml.sax.SAXException e) { + return null; } - return parserClassName; } /** @@ -213,18 +209,10 @@ public class Driver implements Loggable { private Logger getLogger() { if(log == null) { - Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); - PatternFormatter formatter = new PatternFormatter( - "[%{priority}]: %{message}\n%{throwable}" ); - - LogTarget target = null; - target = new StreamTarget(System.out, formatter); + log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO); + log.error("Logger not set"); + } - hierarchy.setDefaultLogTarget(target); - log = hierarchy.getLoggerFor("fop"); - log.setPriority(Priority.INFO); - log.error("Logger not set"); - } return log; } @@ -241,6 +229,19 @@ public class Driver implements Loggable { _treeBuilder.reset(); } + /** + * Returns the results of the last rendering process. Information includes + * the total number of pages generated and the number of pages per + * page-sequence. + */ + public FormattingResults getResults() { + try { + return _treeBuilder.getStreamRenderer().getResults(); + } catch (NullPointerException e) { + return null; + } + } + public boolean hasData() { return (_treeBuilder.hasData()); } @@ -483,19 +484,9 @@ public class Driver implements Loggable { */ public synchronized void render(Document document) throws FOPException { - - try { - DocumentInputSource source = new DocumentInputSource(document); - DocumentReader reader = new DocumentReader(); - reader.setContentHandler(getContentHandler()); - reader.parse(source); - } catch (SAXException e) { - throw new FOPException(e); - } - catch (IOException e) { - throw new FOPException(e); - } - + DocumentInputSource source = new DocumentInputSource(document); + DocumentReader reader = new DocumentReader(); + render(reader, source); } /** diff --git a/src/org/apache/fop/apps/Fop.java b/src/org/apache/fop/apps/Fop.java index 8cd8d71e7..94d40a857 100644 --- a/src/org/apache/fop/apps/Fop.java +++ b/src/org/apache/fop/apps/Fop.java @@ -19,14 +19,26 @@ public class Fop { starter.run(); } catch (FOPException e) { MessageHandler.errorln("" + e.getMessage()); - if (options != null && options.isDebugMode().booleanValue()) { + if (options != null) { + if (options.isDebugMode().booleanValue()) { e.printStackTrace(); + } + if (options.outfile != null) { + options.outfile.delete(); + } } + System.exit(2); } catch (java.io.FileNotFoundException e) { MessageHandler.errorln("" + e.getMessage()); - if (options != null && options.isDebugMode().booleanValue()) { + if (options != null) { + if (options.isDebugMode().booleanValue()) { e.printStackTrace(); + } + if (options.outfile != null) { + options.outfile.delete(); + } } + System.exit(1); } } diff --git a/src/org/apache/fop/apps/FormattingResults.java b/src/org/apache/fop/apps/FormattingResults.java new file mode 100644 index 000000000..546a5233e --- /dev/null +++ b/src/org/apache/fop/apps/FormattingResults.java @@ -0,0 +1,73 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.apps; + +import java.util.List; + +import org.apache.fop.fo.pagination.PageSequence; + +/** + * Class for reporting back formatting results to the calling application. + * + * @author Jeremias Maerki + */ +public class FormattingResults { + + private int pageCount = 0; + private List pageSequences = null; + + /** + * Constructor for the FormattingResults object + */ + public FormattingResults() { + } + + /** + * Gets the number of pages rendered + * + * @return The number of pages overall + */ + public int getPageCount() { + return this.pageCount; + } + + /** + * Gets the results for the individual page-sequences. + * + * @return A List with PageSequenceResults objects + */ + public List getPageSequences() { + return this.pageSequences; + } + + /** + * Resets this object + */ + public void reset() { + this.pageCount = 0; + if (this.pageSequences != null) { + this.pageSequences.clear(); + } + } + + /** + * Description of the Method + * + * @param pageSequence Description of Parameter + */ + public void haveFormattedPageSequence(PageSequence pageSequence) { + this.pageCount += pageSequence.getPageCount(); + if (this.pageSequences == null) { + this.pageSequences = new java.util.ArrayList(); + } + this.pageSequences.add( + new PageSequenceResults(pageSequence.getProperty("id").getString(), + pageSequence.getPageCount())); + } +} + diff --git a/src/org/apache/fop/apps/InputHandler.java b/src/org/apache/fop/apps/InputHandler.java index c2899ddbe..48c90b055 100644 --- a/src/org/apache/fop/apps/InputHandler.java +++ b/src/org/apache/fop/apps/InputHandler.java @@ -14,6 +14,7 @@ import org.xml.sax.XMLReader; // Java import java.net.URL; import java.io.File; +import javax.xml.parsers.*; // FOP import org.apache.fop.messaging.MessageHandler; @@ -53,27 +54,21 @@ abstract public class InputHandler { } /** - * creates a SAX parser, using the value of org.xml.sax.parser - * defaulting to org.apache.xerces.parsers.SAXParser + * creates a SAX parser * * @return the created SAX parser */ protected static XMLReader createParser() throws FOPException { - String parserClassName = Driver.getParserClassName(); - MessageHandler.logln("using SAX parser " + parserClassName); - try { - return (XMLReader)Class.forName(parserClassName).newInstance(); - } catch (ClassNotFoundException e) { - throw new FOPException(e); - } catch (InstantiationException e) { - throw new FOPException("Could not instantiate " - + parserClassName, e); - } catch (IllegalAccessException e) { - throw new FOPException("Could not access " + parserClassName, e); - } catch (ClassCastException e) { - throw new FOPException(parserClassName + " is not a SAX driver", - e); + SAXParserFactory spf = javax.xml.parsers.SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + XMLReader xmlReader = spf.newSAXParser().getXMLReader(); + MessageHandler.logln("Using " + xmlReader.getClass().getName() + " as SAX2 Parser"); + return xmlReader; + } catch (javax.xml.parsers.ParserConfigurationException e) { + throw new FOPException(e); + } catch (org.xml.sax.SAXException e) { + throw new FOPException( e); } } diff --git a/src/org/apache/fop/apps/PDFOutputHandler.java b/src/org/apache/fop/apps/PDFOutputHandler.java deleted file mode 100644 index d7b16043d..000000000 --- a/src/org/apache/fop/apps/PDFOutputHandler.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.apps; - -import org.xml.sax.*; -import com.jclark.xsl.sax.*; -import java.io.*; - -// FOP -import org.apache.fop.fo.XTFOTreeBuilder; -import org.apache.fop.fo.XTElementMapping; -import org.apache.fop.layout.AreaTree; -import org.apache.fop.layout.FontInfo; -import org.apache.fop.render.Renderer; -import org.apache.fop.messaging.MessageHandler; - -// //////////////////////////////////////////////////////////////////////////////////// - -/** - * A DocumentHandler that writes a PDF representation to an OutputStream. - * - * Use with James Clark's XT. Just put FOP on your class path and add - * <xsl:output method="fop:org.apache.fop.apps.PDFOutputHandler" - * xmlns:fop="http://www.jclark.com/xt/java"/> - * to your stylesheet. Now XT will automatically call FOP. - * - */ -public class PDFOutputHandler extends XTFOTreeBuilder - implements OutputDocumentHandler { - - /** - * the area tree that is the result of formatting the FO tree - */ - protected AreaTree areaTree; - - /** - * the renderer to use to output the area tree - */ - protected Renderer renderer; - - /** - * the PrintWriter to use to output the results of the renderer - */ - protected PrintWriter writer; - - /** - * the stream to use to output the results of the renderer - */ - protected OutputStream stream; - - private boolean keepOpen; - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - */ - public PDFOutputHandler() {} - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - */ - public PDFOutputHandler(OutputStream out) { - this(); - this.stream = out; - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - */ - public DocumentHandler init(Destination dest, - AttributeList atts) throws IOException { - this.stream = dest.getOutputStream("application/pdf", null); - this.keepOpen = dest.keepOpen(); - - String version = org.apache.fop.apps.Version.getVersion(); - setRenderer("org.apache.fop.render.pdf.PDFRenderer", version); - addElementMapping("org.apache.fop.fo.StandardElementMapping"); - addElementMapping("org.apache.fop.svg.SVGElementMapping"); - return this; - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * set the class name of the Renderer to use as well as the - * producer string for those renderers that can make use of it - */ - public void setRenderer(String rendererClassName, String producer) { - this.renderer = createRenderer(rendererClassName); - this.renderer.setProducer(producer); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * SAX passthrough, finish rendering the document - */ - public void endDocument() throws SAXException { - super.endDocument(); - - try { - doFormat(); - doRender(); - } catch (IOException io) { - throw new SAXException(io); - } catch (FOPException fop) { - throw new SAXException(fop); - } - writer.flush(); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * format the formatting object tree into an area tree - */ - public void doFormat() throws FOPException { - FontInfo fontInfo = new FontInfo(); - this.renderer.setupFontInfo(fontInfo); - -// this.areaTree = new AreaTree(); - this.areaTree.setFontInfo(fontInfo); - - format(areaTree); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * render the area tree to the output form - */ - public void doRender() throws IOException, FOPException { - //this.renderer.render(areaTree, this.stream); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * add the given element mapping. - * - * an element mapping maps element names to Java classes - */ - public void addElementMapping(XTElementMapping mapping) { - mapping.addToBuilder(this); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * add the element mapping with the given class name - */ - public void addElementMapping(String mappingClassName) { - createElementMapping(mappingClassName).addToBuilder(this); - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * protected method used by addElementMapping(String) to - * instantiate element mapping class - */ - protected XTElementMapping createElementMapping(String mappingClassName) { - MessageHandler.logln("using element mapping " + mappingClassName); - - try { - return (XTElementMapping)Class.forName(mappingClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + mappingClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + mappingClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + mappingClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(mappingClassName - + " is not an element mapping"); - } - return null; - } - - // //////////////////////////////////////////////////////////////////////////////////// - - /** - * protected method used by setRenderer(String, String) to - * instantiate the Renderer class - */ - protected Renderer createRenderer(String rendererClassName) { - MessageHandler.logln("using renderer " + rendererClassName); - - try { - return (Renderer)Class.forName(rendererClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + rendererClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + rendererClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + rendererClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(rendererClassName + " is not a renderer"); - } - return null; - } - -} - diff --git a/src/org/apache/fop/apps/PageSequenceResults.java b/src/org/apache/fop/apps/PageSequenceResults.java new file mode 100644 index 000000000..eee11a08d --- /dev/null +++ b/src/org/apache/fop/apps/PageSequenceResults.java @@ -0,0 +1,50 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.apps; + +/** + * Class for reporting back formatting results to the calling application. This + * particular class is used to report the results of a single page-sequence. + * + * @author Jeremias Maerki + */ +public class PageSequenceResults { + + private String id; + private int pageCount; + + /** + * Constructor for the PageSequenceResults object + * + * @param id ID of the page-sequence, if available + * @param pageCount The number of resulting pages + */ + public PageSequenceResults(String id, int pageCount) { + this.id = id; + this.pageCount = pageCount; + } + + /** + * Gets the ID of the page-sequence if one was specified. + * + * @return The ID + */ + public String getID() { + return this.id; + } + + /** + * Gets the number of pages that resulted by processing the page-sequence. + * + * @return The number of pages generated + */ + public int getPageCount() { + return this.pageCount; + } +} + diff --git a/src/org/apache/fop/apps/PrintStarter.java b/src/org/apache/fop/apps/PrintStarter.java index f3c039f64..96408e5d1 100644 --- a/src/org/apache/fop/apps/PrintStarter.java +++ b/src/org/apache/fop/apps/PrintStarter.java @@ -64,8 +64,6 @@ public class PrintStarter extends CommandLineStarter { XMLReader parser = inputHandler.getParser(); - setParserFeatures(parser); - PrinterJob pj = PrinterJob.getPrinterJob(); if(System.getProperty("dialog") != null) if(!pj.printDialog()) diff --git a/src/org/apache/fop/apps/Starter.java b/src/org/apache/fop/apps/Starter.java index 90d63c59b..393395a11 100644 --- a/src/org/apache/fop/apps/Starter.java +++ b/src/org/apache/fop/apps/Starter.java @@ -7,7 +7,8 @@ package org.apache.fop.apps; -import org.apache.log.*; +// Avalon +import org.apache.avalon.framework.logger.Logger; // SAX import org.xml.sax.XMLReader; @@ -32,8 +33,8 @@ public abstract class Starter { options = new Options(); } - public void setLogger(Logger logger) { - log = logger; + public void setLogger(Logger handler) { + log = handler; } public void setInputHandler(InputHandler inputHandler) { @@ -42,15 +43,4 @@ public abstract class Starter { abstract public void run() throws FOPException; - // setting the parser features - public void setParserFeatures(XMLReader parser) throws FOPException { - try { - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", - true); - } catch (SAXException e) { - throw new FOPException("Error in setting up parser feature namespace-prefixes\n" - + "You need a parser which supports SAX version 2", e); - } - } - } diff --git a/src/org/apache/fop/apps/StreamRenderer.java b/src/org/apache/fop/apps/StreamRenderer.java index cb3da8744..3c3f7c4f7 100644 --- a/src/org/apache/fop/apps/StreamRenderer.java +++ b/src/org/apache/fop/apps/StreamRenderer.java @@ -1,3 +1,9 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ package org.apache.fop.apps; import java.io.OutputStream; @@ -15,7 +21,7 @@ import org.apache.fop.datatypes.IDReferences; import org.apache.fop.extensions.ExtensionObj; import org.apache.fop.fo.pagination.PageSequence; -import org.apache.log.Logger; +import org.apache.avalon.framework.logger.Logger; /** This class acts as a bridge between the XML:FO parser @@ -23,7 +29,7 @@ import org.apache.log.Logger; PageSequences up until all the IDs required by them are satisfied, at which time it will render the pages.<P> - + StreamRenderer is created by Driver and called from FOTreeBuilder when a PageSequence is created, and AreaTree when a Page is formatted.<P> @@ -66,6 +72,11 @@ public class StreamRenderer { private Renderer renderer; /** + * The formatting results to be handed back to the caller. + */ + private FormattingResults results = new FormattingResults(); + + /** The FontInfo for this renderer. */ private FontInfo fontInfo = new FontInfo(); @@ -102,6 +113,10 @@ public class StreamRenderer { return idReferences; } + public FormattingResults getResults() { + return this.results; + } + public void addExtension(ExtensionObj ext) { extensions.addElement(ext); } @@ -119,6 +134,8 @@ public class StreamRenderer { try { renderer.setupFontInfo(fontInfo); renderer.startRenderer(outputStream); + } catch (FOPException fe) { + throw new SAXException(fe); } catch (IOException e) { throw new SAXException(e); } @@ -158,8 +175,10 @@ public class StreamRenderer { long timeUsed = System.currentTimeMillis() - startTime; log.debug("Total time used: " + timeUsed + "ms"); - log.debug("Pages rendererd: " + pageCount); - log.debug("Avg render time: " + (timeUsed / pageCount) + "ms/page"); + log.debug("Pages rendered: " + pageCount); + if (pageCount != 0) { + log.debug("Avg render time: " + (timeUsed / pageCount) + "ms/page"); + } } /** @@ -192,6 +211,8 @@ public class StreamRenderer { } catch (FOPException e) { throw new SAXException(e); } + this.results.haveFormattedPageSequence(pageSequence); + log.debug("Last page-sequence produced "+pageSequence.getPageCount()+" pages."); } public synchronized void queuePage(Page page) @@ -296,7 +317,7 @@ public class StreamRenderer { return true; } } - + public Page getNextPage(Page current, boolean isWithinPageSequence, boolean isFirstCall) { Page nextPage = null; diff --git a/src/org/apache/fop/apps/XTDriver.java b/src/org/apache/fop/apps/XTDriver.java deleted file mode 100644 index 1551760fa..000000000 --- a/src/org/apache/fop/apps/XTDriver.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.apps; - -// FOP -import org.apache.fop.fo.XTFOTreeBuilder; -import org.apache.fop.fo.ElementMapping; -import org.apache.fop.layout.AreaTree; -import org.apache.fop.layout.FontInfo; -import org.apache.fop.render.Renderer; -import org.apache.fop.messaging.MessageHandler; - -// DOM -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Attr; - -// SAX -import org.xml.sax.DocumentHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Parser; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -// Java -import java.io.*; - -/** - * <P>Primary class that drives overall FOP process. - * - * <P>Once this class is instantiated, methods are called to set the - * Renderer to use, the (possibly multiple) ElementMapping(s) to - * use and the PrintWriter to use to output the results of the - * rendering (where applicable). In the case of the Renderer and - * ElementMapping(s), the Driver may be supplied either with the - * object itself, or the name of the class, in which case Driver will - * instantiate the class itself. The advantage of the latter is it - * enables runtime determination of Renderer and ElementMapping(s). - * - * <P>Once the Driver is set up, the buildFOTree method - * is called. Depending on whether DOM or SAX is being used, the - * invocation of the method is either buildFOTree(Document) or - * buildFOTree(Parser, InputSource) respectively. - * - * <P>A third possibility may be used to build the FO Tree, namely - * calling getDocumentHandler() and firing the SAX events yourself. - * - * <P>Once the FO Tree is built, the format() and render() methods may be - * called in that order. - * - * <P>Here is an example use of Driver from CommandLine.java: - * - * <PRE> - * Driver driver = new Driver(); - * driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", version); - * driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - * driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - * driver.setWriter(new PrintWriter(new FileWriter(args[1]))); - * driver.buildFOTree(parser, fileInputSource(args[0])); - * driver.format(); - * driver.render(); - * </PRE> - */ -public class XTDriver { - - /** - * the FO tree builder - */ - protected XTFOTreeBuilder treeBuilder; - - /** - * the area tree that is the result of formatting the FO tree - */ - protected AreaTree areaTree; - - /** - * the renderer to use to output the area tree - */ - protected Renderer renderer; - - /** - * the PrintWriter to use to output the results of the renderer - */ - protected PrintWriter writer; - - /** - * the stream to use to output the results of the renderer - */ - protected OutputStream stream; - - /** - * create a new Driver - */ - public XTDriver() { - this.treeBuilder = new XTFOTreeBuilder(); - } - - /** - * set the Renderer to use - */ - public void setRenderer(Renderer renderer) { - this.renderer = renderer; - } - - /** - * set the class name of the Renderer to use as well as the - * producer string for those renderers that can make use of it - */ - public void setRenderer(String rendererClassName, String producer) { - this.renderer = createRenderer(rendererClassName); - this.renderer.setProducer(producer); - } - - /** - * protected method used by setRenderer(String, String) to - * instantiate the Renderer class - */ - protected Renderer createRenderer(String rendererClassName) { - MessageHandler.logln("using renderer " + rendererClassName); - - try { - return (Renderer)Class.forName(rendererClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + rendererClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + rendererClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + rendererClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(rendererClassName + " is not a renderer"); - } - return null; - } - - /** - * add the given element mapping. - * - * an element mapping maps element names to Java classes - */ - public void addElementMapping(ElementMapping mapping) { - mapping.addToBuilder(this.treeBuilder); - } - - /** - * add the element mapping with the given class name - */ - public void addElementMapping(String mappingClassName) { - createElementMapping(mappingClassName).addToBuilder(this.treeBuilder); - } - - /** - * protected method used by addElementMapping(String) to - * instantiate element mapping class - */ - protected ElementMapping createElementMapping(String mappingClassName) { - MessageHandler.logln("using element mapping " + mappingClassName); - - try { - return (ElementMapping)Class.forName(mappingClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + mappingClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + mappingClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + mappingClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(mappingClassName - + " is not an element mapping"); - } - return null; - } - - /** - * return the tree builder (a SAX DocumentHandler). - * - * used in situations where SAX is used but not via a FOP-invoked - * SAX parser. A good example is an XSLT engine that fires SAX - * events but isn't a SAX Parser itself. - */ - public DocumentHandler getDocumentHandler() { - return this.treeBuilder; - } - - /** - * build the formatting object tree using the given SAX Parser and - * SAX InputSource - */ - public void buildFOTree(Parser parser, - InputSource source) throws FOPException { - - parser.setDocumentHandler(this.treeBuilder); - try { - parser.parse(source); - } catch (SAXException e) { - if (e.getException() instanceof FOPException) - throw (FOPException)e.getException(); - else - throw new FOPException(e.getMessage()); - } catch (IOException e) { - throw new FOPException(e.getMessage()); - } - } - - /** - * build the formatting object tree using the given DOM Document - */ - public void buildFOTree(Document document) throws FOPException { - - /* most of this code is modified from John Cowan's */ - - Node currentNode; - AttributesImpl currentAtts; - - /* temporary array for making Strings into character arrays */ - char[] array = null; - - currentAtts = new AttributesImpl(); - - /* start at the document element */ - currentNode = document; - - try { - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.startDocument(); - break; - case Node.CDATA_SECTION_NODE: - case Node.TEXT_NODE: - String data = currentNode.getNodeValue(); - int datalen = data.length(); - if (array == null || array.length < datalen) { - /* - * if the array isn't big enough, make a new - * one - */ - array = new char[datalen]; - } - data.getChars(0, datalen, array, 0); - this.treeBuilder.characters(array, 0, datalen); - break; - case Node.PROCESSING_INSTRUCTION_NODE: - this.treeBuilder.processingInstruction(currentNode.getNodeName(), - currentNode.getNodeValue()); - break; - case Node.ELEMENT_NODE: - NamedNodeMap map = currentNode.getAttributes(); - currentAtts.clear(); - for (int i = map.getLength() - 1; i >= 0; i--) { - Attr att = (Attr)map.item(i); - currentAtts.addAttribute("", att.getName(), "", - "CDATA", att.getValue()); - } - this.treeBuilder.startElement("", - currentNode.getNodeName(), - "", currentAtts); - break; - } - - Node nextNode = currentNode.getFirstChild(); - if (nextNode != null) { - currentNode = nextNode; - continue; - } - - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.endDocument(); - break; - case Node.ELEMENT_NODE: - this.treeBuilder.endElement("", - currentNode.getNodeName(), - ""); - break; - } - - nextNode = currentNode.getNextSibling(); - if (nextNode != null) { - currentNode = nextNode; - break; - } - - currentNode = currentNode.getParentNode(); - } - } - } catch (SAXException e) { - throw new FOPException(e.getMessage()); - } - } - - /** - * set the PrintWriter to use to output the result of the Renderer - * (if applicable) - */ - public void setWriter(PrintWriter writer) { - this.writer = writer; - } - - /** - * set the OutputStream to use to output the result of the Renderer - * (if applicable) - */ - public void setOutputStream(OutputStream stream) { - this.stream = stream; - } - - /** - * format the formatting object tree into an area tree - */ - public void format() throws FOPException { - FontInfo fontInfo = new FontInfo(); - this.renderer.setupFontInfo(fontInfo); - - //this.areaTree = new AreaTree(); - this.areaTree.setFontInfo(fontInfo); - - this.treeBuilder.format(areaTree); - } - - /** - * render the area tree to the output form - */ - public void render() throws IOException, FOPException { - //this.renderer.render(areaTree, this.stream); - } - -} diff --git a/src/org/apache/fop/configuration/ConfigurationReader.java b/src/org/apache/fop/configuration/ConfigurationReader.java index 3f982407f..a6771ef7a 100644 --- a/src/org/apache/fop/configuration/ConfigurationReader.java +++ b/src/org/apache/fop/configuration/ConfigurationReader.java @@ -11,9 +11,12 @@ package org.apache.fop.configuration; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.XMLReader; import org.xml.sax.SAXException; -import java.io.IOException; import org.xml.sax.InputSource; +// java +import java.io.IOException; +import javax.xml.parsers.*; + // fop import org.apache.fop.apps.Driver; import org.apache.fop.messaging.MessageHandler; @@ -61,14 +64,6 @@ public class ConfigurationReader { public void start() throws FOPException { XMLReader parser = createParser(); - // setting the parser features - try { - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", - false); - } catch (SAXException e) { - throw new FOPException("You need a parser which supports SAX version 2", - e); - } ConfigurationParser configurationParser = new ConfigurationParser(); parser.setContentHandler(configurationParser); @@ -86,30 +81,21 @@ public class ConfigurationReader { } /** - * creates a SAX parser, using the value of org.xml.sax.parser - * defaulting to org.apache.xerces.parsers.SAXParser + * creates a SAX parser * * @return the created SAX parser */ public static XMLReader createParser() throws FOPException { - String parserClassName = Driver.getParserClassName(); - if (errorDump) { - MessageHandler.logln("configuration reader using SAX parser " - + parserClassName); - } - try { - return (XMLReader)Class.forName(parserClassName).newInstance(); - } catch (ClassNotFoundException e) { - throw new FOPException("Could not find " + parserClassName, e); - } catch (InstantiationException e) { - throw new FOPException("Could not instantiate " - + parserClassName, e); - } catch (IllegalAccessException e) { - throw new FOPException("Could not access " + parserClassName, e); - } catch (ClassCastException e) { - throw new FOPException(parserClassName + " is not a SAX driver", - e); + SAXParserFactory spf = javax.xml.parsers.SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + XMLReader xmlReader = spf.newSAXParser().getXMLReader(); + MessageHandler.logln("Using " + xmlReader.getClass().getName() + " as SAX2 Parser"); + return xmlReader; + } catch (javax.xml.parsers.ParserConfigurationException e) { + throw new FOPException(e); + } catch (org.xml.sax.SAXException e) { + throw new FOPException( e); } } diff --git a/src/org/apache/fop/configuration/FontInfo.java b/src/org/apache/fop/configuration/FontInfo.java index e552e0cd4..95e70f417 100644 --- a/src/org/apache/fop/configuration/FontInfo.java +++ b/src/org/apache/fop/configuration/FontInfo.java @@ -8,16 +8,25 @@ package org.apache.fop.configuration; +// Java +import java.io.File; +import java.net.URL; +import java.net.MalformedURLException; import java.util.Vector; +// Fop +import org.apache.fop.apps.FOPException; + /** * FontInfo contains meta information on fonts (where is the metrics file etc.) */ public class FontInfo { + private String metricsFile, embedFile, name; private boolean kerning; private Vector fontTriplets; + private String baseDir; public FontInfo(String name, String metricsFile, boolean kerning, Vector fontTriplets, String embedFile) { @@ -28,12 +37,38 @@ public class FontInfo { this.fontTriplets = fontTriplets; } - public String getMetricsFile() { - return metricsFile; + /** + * @return the (absolute) file name of the metrics file + */ + public String getMetricsFile() throws FOPException { + // check if it's a URL and convert it to a filename + try { + metricsFile = new URL(metricsFile).getFile(); + } catch (MalformedURLException mue) {} + + // check if filename is absolute + if ((new File(metricsFile).isAbsolute())) { + return metricsFile; + } else { + return getBaseDir() + metricsFile; + } } - public String getEmbedFile() { - return embedFile; + /** + * @return the (absolute) file name of the font + */ + public String getEmbedFile() throws FOPException { + // check if it's a URL and convert it to a filename + try { + embedFile = new URL(embedFile).getFile(); + } catch (MalformedURLException mue) {} + + // check if filename is absolute + if ((new File(embedFile).isAbsolute())) { + return embedFile; + } else { + return getBaseDir() + embedFile; + } } public boolean getKerning() { @@ -44,5 +79,27 @@ public class FontInfo { return fontTriplets; } + /** + * @return BaseDir (path) + */ + private String getBaseDir() throws FOPException { + baseDir = Configuration.getStringValue("baseDir"); + URL baseURL = null; + try { + baseURL = new URL(baseDir); + } catch (MalformedURLException mue) { + // if the href contains only a path then file is assumed + try { + baseURL = new URL("file:" + baseDir); + } catch (MalformedURLException mue2) { + throw new FOPException("Error with baseDir: " + + mue2.getMessage()); + } + } + baseDir = baseURL.getFile(); + return baseDir; + } + + } diff --git a/src/org/apache/fop/datatypes/ColorSpace.java b/src/org/apache/fop/datatypes/ColorSpace.java index 9b289369f..01fcf221a 100644 --- a/src/org/apache/fop/datatypes/ColorSpace.java +++ b/src/org/apache/fop/datatypes/ColorSpace.java @@ -8,6 +8,10 @@ package org.apache.fop.datatypes; public class ColorSpace { + private boolean hasICCProfile; + private byte[] iccProfile; + private int numComponents; + // Ok... so I had some grand purpose for this, but I can't recall. // I'm just writing it @@ -18,21 +22,55 @@ public class ColorSpace { public static int DEVICE_RGB = 2; public static int DEVICE_CMYK = 3; + // Are there any others? protected int currentColorSpace = -1; public ColorSpace(int theColorSpace) { this.currentColorSpace = theColorSpace; + hasICCProfile = false; + numComponents = calculateNumComponents(); + } + + private int calculateNumComponents() { + if (currentColorSpace == DEVICE_GRAY) + return 1; + else if (currentColorSpace == DEVICE_RGB) + return 3; + else if (currentColorSpace == DEVICE_CMYK) + return 4; + else + return 0; + } + public void setColorSpace(int theColorSpace) { + this.currentColorSpace = theColorSpace; + numComponents = calculateNumComponents(); + } + + public boolean hasICCProfile() { + return hasICCProfile; + } + + public byte[] getICCProfile() { + if (hasICCProfile) + return iccProfile; + else + return new byte[0]; + } + + public void setICCProfile(byte[] iccProfile) { + this.iccProfile = iccProfile; + hasICCProfile = true; } public int getColorSpace() { return (this.currentColorSpace); } - public void setColorSpace(int theColorSpace) { - this.currentColorSpace = theColorSpace; + public int getNumComponents() { + return numComponents; } public String getColorSpacePDFString() { // this is for PDF Output. Does anyone else need a string representation? diff --git a/src/org/apache/fop/datatypes/LinearCombinationLength.java b/src/org/apache/fop/datatypes/LinearCombinationLength.java index ad1ce1bd9..88af67190 100644 --- a/src/org/apache/fop/datatypes/LinearCombinationLength.java +++ b/src/org/apache/fop/datatypes/LinearCombinationLength.java @@ -27,7 +27,7 @@ public class LinearCombinationLength extends Length { /** * Return the computed value in millipoints. */ - protected void computeValue() { + public void computeValue() { int result = 0; int numFactors = factors.size(); for (int i = 0; i < numFactors; ++i) { diff --git a/src/org/apache/fop/datatypes/ToBeImplementedProperty.java b/src/org/apache/fop/datatypes/ToBeImplementedProperty.java index f21d08e57..224162dc7 100644 --- a/src/org/apache/fop/datatypes/ToBeImplementedProperty.java +++ b/src/org/apache/fop/datatypes/ToBeImplementedProperty.java @@ -8,8 +8,7 @@ package org.apache.fop.datatypes; import org.apache.fop.fo.*; - -import org.apache.log.*; +import org.apache.fop.messaging.MessageHandler; public class ToBeImplementedProperty extends Property { @@ -31,9 +30,8 @@ public class ToBeImplementedProperty extends Property { } public ToBeImplementedProperty(String propName) { - Logger log = Hierarchy.getDefaultHierarchy().getLoggerFor("fop"); - log.warn("property - \"" + propName - + "\" is not implemented yet."); + MessageHandler.errorln("property - \"" + propName + + "\" is not implemented yet."); } } diff --git a/src/org/apache/fop/extensions/ExtensionElementMapping.java b/src/org/apache/fop/extensions/ExtensionElementMapping.java index c6c8ae402..8f33af6b9 100644 --- a/src/org/apache/fop/extensions/ExtensionElementMapping.java +++ b/src/org/apache/fop/extensions/ExtensionElementMapping.java @@ -21,12 +21,16 @@ public class ExtensionElementMapping implements ElementMapping { private static HashMap foObjs = null; - public synchronized void addToBuilder(TreeBuilder builder) { + private static synchronized void setupExt() { if(foObjs == null) { foObjs = new HashMap(); foObjs.put("outline", Outline.maker()); foObjs.put("label", Label.maker()); } + } + + public void addToBuilder(TreeBuilder builder) { + setupExt(); builder.addMapping(URI, foObjs); diff --git a/src/org/apache/fop/fo/FONode.java b/src/org/apache/fop/fo/FONode.java index af4791a40..291d2df35 100644 --- a/src/org/apache/fop/fo/FONode.java +++ b/src/org/apache/fop/fo/FONode.java @@ -16,7 +16,8 @@ import org.apache.fop.layout.LinkSet; import org.apache.fop.system.BufferManager; import org.apache.fop.fo.flow.Marker; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; // Java import java.util.Vector; diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java index bc86aba20..3eb6c3972 100644 --- a/src/org/apache/fop/fo/FOText.java +++ b/src/org/apache/fop/fo/FOText.java @@ -123,9 +123,11 @@ public class FOText extends FONode { int fontVariant = this.parent.properties.get("font-variant").getEnum(); + int letterSpacing = + this.parent.properties.get("letter-spacing").getLength().mvalue(); this.fs = new FontState(area.getFontInfo(), fontFamily, fontStyle, fontWeight, fontSize, - fontVariant); + fontVariant, letterSpacing); ColorType c = this.parent.properties.get("color").getColorType(); this.red = c.red(); diff --git a/src/org/apache/fop/fo/FOTreeBuilder.java b/src/org/apache/fop/fo/FOTreeBuilder.java index 4e4cefafe..29377f436 100644 --- a/src/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/org/apache/fop/fo/FOTreeBuilder.java @@ -16,7 +16,8 @@ import org.apache.fop.system.BufferManager; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.extensions.ExtensionObj; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; // SAX import org.xml.sax.helpers.DefaultHandler; @@ -92,6 +93,10 @@ public class FOTreeBuilder extends DefaultHandler implements TreeBuilder { this.streamRenderer = streamRenderer; } + public StreamRenderer getStreamRenderer() { + return this.streamRenderer; + } + /** * add a mapping from element name to maker. * diff --git a/src/org/apache/fop/fo/FObjMixed.java b/src/org/apache/fop/fo/FObjMixed.java index ddab909cc..66a90f4a9 100644 --- a/src/org/apache/fop/fo/FObjMixed.java +++ b/src/org/apache/fop/fo/FObjMixed.java @@ -8,6 +8,7 @@ package org.apache.fop.fo; import org.apache.fop.layout.Area; +import org.apache.fop.layout.TextState; import org.apache.fop.apps.FOPException; /** @@ -16,6 +17,9 @@ import org.apache.fop.apps.FOPException; */ public class FObjMixed extends FObj { + // Textdecoration + protected TextState ts; + public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { @@ -32,8 +36,21 @@ public class FObjMixed extends FObj { super(parent, propertyList); } + public TextState getTextState() { + return ts; + } + protected void addCharacters(char data[], int start, int length) { - addChild(new FOText(data, start, length, this)); + // addChild(new FOText(data, start, length, this)); + FOText ft = new FOText(data, start, length, this); + ft.setLogger(log); + if (ts != null) { + ft.setUnderlined(ts.getUnderlined()); + ft.setOverlined(ts.getOverlined()); + ft.setLineThrough(ts.getLineThrough()); + } + addChild(ft); + } public Status layout(Area area) throws FOPException { diff --git a/src/org/apache/fop/fo/MarginShorthandParser.java b/src/org/apache/fop/fo/MarginShorthandParser.java new file mode 100644 index 000000000..dd96c777b --- /dev/null +++ b/src/org/apache/fop/fo/MarginShorthandParser.java @@ -0,0 +1,97 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.fo; + +import java.util.Vector; +import java.util.Enumeration; + +public class MarginShorthandParser implements ShorthandParser { + + protected Vector list; // Vector of Property objects + + public MarginShorthandParser(ListProperty listprop) { + this.list = listprop.getList(); + } + + protected Property getElement(int index) { + if (list.size() > index) + return (Property)list.elementAt(index); + else + return null; + } + + protected int count() { + return list.size(); + } + + // Stores 1 to 4 values for margin-top, -right, -bottom or -left + public Property getValueForProperty(String propName, + Property.Maker maker, + PropertyList propertyList) { + Property prop = null; + // Check for keyword "inherit" + if (count() == 1) + { + String sval = ((Property)list.elementAt(0)).getString(); + if (sval != null && sval.equals("inherit")) + { + return propertyList.getFromParent(propName); + } + } + return convertValueForProperty(propName, maker, propertyList); + } + + + protected Property convertValueForProperty(String propName, + Property.Maker maker, + PropertyList propertyList) { + Property prop = null; + int idx = 0; + + switch (count()) + { + case 1: // + idx = 0; + break; + case 2: // 1st value top/bottom, 2nd value left/right + if (propName.equals("margin-top") || + propName.equals("margin-bottom")) + idx = 0; + else + idx = 1; + break; + case 3: // 1st value top, 2nd left/right, 3rd bottom + if (propName == "margin-top") + idx = 0; + else if (propName.equals("margin-bottom")) + idx = 2; + else + idx = 1; + break; + case 4: // top, right, bottom, left + if (propName.equals("margin-top")) + idx = 0; + else if (propName.equals("margin-right")) + idx = 1; + else if (propName.equals("margin-bottom")) + idx = 2; + else if (propName.equals("margin-left")) + idx = 3; + break; + default: + // TODO Error Message: Wrong number of args + return null; + } + + Property p = getElement(idx); + prop = maker.convertShorthandProperty(propertyList, p, null); + return prop; + } + +} + diff --git a/src/org/apache/fop/fo/Property.java b/src/org/apache/fop/fo/Property.java index 7aa9745ac..9406f7625 100644 --- a/src/org/apache/fop/fo/Property.java +++ b/src/org/apache/fop/fo/Property.java @@ -7,15 +7,19 @@ package org.apache.fop.fo; +// FOP import org.apache.fop.datatypes.*; import org.apache.fop.fo.expr.Numeric; import org.apache.fop.fo.expr.PropertyParser; import org.apache.fop.fo.expr.PropertyInfo; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.apps.FOPException; -import java.util.Vector; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; + +// Java +import java.util.Vector; public class Property { diff --git a/src/org/apache/fop/fo/PropertyManager.java b/src/org/apache/fop/fo/PropertyManager.java index dfbabd383..cd6b57d9e 100644 --- a/src/org/apache/fop/fo/PropertyManager.java +++ b/src/org/apache/fop/fo/PropertyManager.java @@ -7,25 +7,32 @@ package org.apache.fop.fo; -import org.apache.fop.layout.FontState; -import org.apache.fop.layout.FontInfo; -import org.apache.fop.layout.BorderAndPadding; -import org.apache.fop.layout.MarginProps; -import org.apache.fop.layout.BackgroundProps; -import org.apache.fop.layout.MarginInlineProps; -import org.apache.fop.layout.AccessibilityProps; -import org.apache.fop.layout.AuralProps; -import org.apache.fop.layout.RelativePositionProps; -import org.apache.fop.layout.AbsolutePositionProps; +import java.net.MalformedURLException; +import java.text.FieldPosition; +import java.text.MessageFormat; + +import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.BreakAfter; import org.apache.fop.fo.properties.BreakBefore; import org.apache.fop.fo.properties.Constants; -import org.apache.fop.layout.HyphenationProps; -import org.apache.fop.apps.FOPException; -import java.text.MessageFormat; -import java.text.FieldPosition; +import org.apache.fop.fo.properties.TextDecoration; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.FopImageFactory; +import org.apache.fop.image.FopImageException; +import org.apache.fop.layout.AbsolutePositionProps; +import org.apache.fop.layout.AccessibilityProps; import org.apache.fop.layout.Area; +import org.apache.fop.layout.AuralProps; +import org.apache.fop.layout.BackgroundProps; +import org.apache.fop.layout.BorderAndPadding; import org.apache.fop.layout.ColumnArea; +import org.apache.fop.layout.FontInfo; +import org.apache.fop.layout.FontState; +import org.apache.fop.layout.HyphenationProps; +import org.apache.fop.layout.MarginInlineProps; +import org.apache.fop.layout.MarginProps; +import org.apache.fop.layout.RelativePositionProps; +import org.apache.fop.layout.TextState; public class PropertyManager { @@ -33,6 +40,7 @@ public class PropertyManager { private FontState fontState = null; private BorderAndPadding borderAndPadding = null; private HyphenationProps hyphProps = null; + private BackgroundProps bgProps = null; private String[] saLeft; private String[] saRight; @@ -210,8 +218,45 @@ public class PropertyManager { } public BackgroundProps getBackgroundProps() { - BackgroundProps bp = new BackgroundProps(); - return bp; + if (bgProps == null) { + this.bgProps = new BackgroundProps(); + // bgProps.backAttachment = this.properties.get("background-attachment").getEnum(); + bgProps.backColor = + this.properties.get("background-color").getColorType(); + + String src = this.properties.get("background-image").getString(); + if (src.equalsIgnoreCase("none")) { + bgProps.backImage = null; + } + else if (src.equalsIgnoreCase("inherit")) { + // XXX: implement this + bgProps.backImage = null; + } + else { + try { + bgProps.backImage = FopImageFactory.Make(src); + } + catch (MalformedURLException urlex) { + bgProps.backImage = null; + // XXX: use a logger instead + System.out.println("Error creating background image: " + + urlex.getMessage()); + } + catch (FopImageException imgex) { + bgProps.backImage = null; + // XXX: use a logger instead + System.out.println("Error creating background image: " + + imgex.getMessage()); + } + } + + bgProps.backRepeat = this.properties.get("background-repeat").getEnum(); + + + // bgProps.backPosHorizontal = this.properties.get("background-position-horizontal").getLength(); + // bgProps.backPosVertical = this.properties.get("background-position-vertical").getLength(); + } + return bgProps; } public MarginInlineProps getMarginInlineProps() { @@ -247,4 +292,55 @@ public class PropertyManager { AbsolutePositionProps props = new AbsolutePositionProps(); return props; } + + public TextState getTextDecoration(FObj parent) throws FOPException { + + // TextState from parent Block/Inline + TextState tsp = null; + boolean found = false; + + do { + String fname = parent.getName(); + if (fname.equals("fo:flow") || fname.equals("fo:static-content")) { + found = true; + } else if (fname.equals("fo:block") || fname.equals("fo:inline")) { + FObjMixed fom = (FObjMixed) parent; + tsp = fom.getTextState(); + found = true; + } + parent = parent.getParent(); + } while (!found); + + TextState ts = new TextState(); + + if (tsp != null) { + ts.setUnderlined(tsp.getUnderlined()); + ts.setOverlined(tsp.getOverlined()); + ts.setLineThrough(tsp.getLineThrough()); + } + + int textDecoration = this.properties.get("text-decoration").getEnum(); + + if (textDecoration == TextDecoration.UNDERLINE) { + ts.setUnderlined(true); + } + if (textDecoration == TextDecoration.OVERLINE) { + ts.setOverlined(true); + } + if (textDecoration == TextDecoration.LINE_THROUGH) { + ts.setLineThrough(true); + } + if (textDecoration == TextDecoration.NO_UNDERLINE) { + ts.setUnderlined(false); + } + if (textDecoration == TextDecoration.NO_OVERLINE) { + ts.setOverlined(false); + } + if (textDecoration == TextDecoration.NO_LINE_THROUGH) { + ts.setLineThrough(false); + } + + return ts; + } + } diff --git a/src/org/apache/fop/fo/StandardElementMapping.java b/src/org/apache/fop/fo/StandardElementMapping.java index 5938bf0fd..784604062 100644 --- a/src/org/apache/fop/fo/StandardElementMapping.java +++ b/src/org/apache/fop/fo/StandardElementMapping.java @@ -18,7 +18,7 @@ import org.apache.fop.fo.pagination.*; public class StandardElementMapping implements ElementMapping { private static HashMap foObjs = null; - public synchronized void addToBuilder(TreeBuilder builder) { + private static synchronized void setupFO() { if(foObjs == null) { foObjs = new HashMap(); @@ -107,7 +107,10 @@ public class StandardElementMapping implements ElementMapping { foObjs.put("marker", Marker.maker()); foObjs.put("retrieve-marker", RetrieveMarker.maker()); } + } + public void addToBuilder(TreeBuilder builder) { + setupFO(); String uri = "http://www.w3.org/1999/XSL/Format"; builder.addMapping(uri, foObjs); @@ -119,7 +122,6 @@ public class StandardElementMapping implements ElementMapping { builder.addElementPropertyList(uri, elem, FOPropertyMapping.getElementMapping(elem)); } - } - } + diff --git a/src/org/apache/fop/fo/XTElementMapping.java b/src/org/apache/fop/fo/XTElementMapping.java deleted file mode 100644 index 0cfb25930..000000000 --- a/src/org/apache/fop/fo/XTElementMapping.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.fo; - -public interface XTElementMapping { - - public void addToBuilder(XTFOTreeBuilder builder); -} diff --git a/src/org/apache/fop/fo/XTFOTreeBuilder.java b/src/org/apache/fop/fo/XTFOTreeBuilder.java deleted file mode 100644 index a827b3a15..000000000 --- a/src/org/apache/fop/fo/XTFOTreeBuilder.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.fo; - -// FOP -import org.apache.fop.layout.AreaTree; -import org.apache.fop.messaging.MessageHandler; -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.pagination.Root; - -// SAX -import org.xml.sax.SAXException; -import org.xml.sax.Attributes; -import org.xml.sax.helpers.AttributesImpl; -import org.xml.sax.DocumentHandler; -import org.xml.sax.AttributeList; - -// Java -import java.util.Hashtable; -import java.util.Stack; -import java.io.IOException; - -/** - * SAX Handler that builds the formatting object tree. - */ -// public class XTFOTreeBuilder extends HandlerBase { -public class XTFOTreeBuilder extends FOTreeBuilder - implements DocumentHandler { - - // namespace implementation ideas pinched from John Cowan - protected static class NSMap { - String prefix; - String uri; - int level; - - NSMap(String prefix, String uri, int level) { - this.prefix = prefix; - this.uri = uri; - this.level = level; - } - - } - - protected int level = 0; - protected String m_uri = null; - protected String m_localPart = null; - protected Stack namespaceStack = new Stack(); - - { - namespaceStack.push(new NSMap("xml", - "http://www.w3.org/XML/1998/namespace", - -1)); - namespaceStack.push(new NSMap("", "", -1)); - } - - protected String findURI(String prefix) { - for (int i = namespaceStack.size() - 1; i >= 0; i--) { - NSMap nsMap = (NSMap)(namespaceStack.elementAt(i)); - if (prefix.equals(nsMap.prefix)) - return nsMap.uri; - } - return null; - } - - protected String mapName(String name) throws SAXException { - - int colon = name.indexOf(':'); - String prefix = ""; - m_localPart = name; - if (colon != -1) { - prefix = name.substring(0, colon); - m_localPart = name.substring(colon + 1); - } - m_uri = findURI(prefix); - if (m_uri == null) { - if (prefix.equals("")) { - return name; - } else { - throw new SAXException(new FOPException("Unknown namespace prefix " - + prefix)); - } - } - return m_uri + "^" + m_localPart; - } - - /** - * SAX1 Handler for the end of an element - */ - public void endElement(String rawName) throws SAXException { - mapName(rawName); - super.endElement(m_uri, m_localPart, rawName); - level--; - while (((NSMap)namespaceStack.peek()).level > level) { - namespaceStack.pop(); - } - } - - /** - * SAX1 Handler for the start of an element - */ - public void startElement(String rawName, - AttributeList attlist) throws SAXException { - - // SAX2 version of AttributeList - AttributesImpl newAttrs = new AttributesImpl(); - - level++; - int length = attlist.getLength(); - for (int i = 0; i < length; i++) { - String att = attlist.getName(i); - if (att.equals("xmlns")) { - namespaceStack.push(new NSMap("", attlist.getValue(i), - level)); - } else if (att.startsWith("xmlns:")) { - String value = attlist.getValue(i); - namespaceStack.push(new NSMap(att.substring(6), value, - level)); - } else { - mapName(att); - newAttrs.addAttribute(m_uri, m_localPart, att, - attlist.getType(i), - attlist.getValue(i)); - } - - } - - mapName(rawName); - super.startElement(m_uri, m_localPart, rawName, newAttrs); - } - -} diff --git a/src/org/apache/fop/fo/expr/LabelEndFunction.java b/src/org/apache/fop/fo/expr/LabelEndFunction.java index 46ec29160..3bd11051d 100644 --- a/src/org/apache/fop/fo/expr/LabelEndFunction.java +++ b/src/org/apache/fop/fo/expr/LabelEndFunction.java @@ -47,6 +47,9 @@ public class LabelEndFunction extends FunctionBase { labelEnd.addTerm(-1.0, distance); labelEnd.addTerm(-1.0, startIndent); labelEnd.addTerm(1.0, separation); + + // make sure value gets calculated + labelEnd.computeValue(); return new LengthProperty(labelEnd); } diff --git a/src/org/apache/fop/fo/expr/PropertyParser.java b/src/org/apache/fop/fo/expr/PropertyParser.java index f41cfc43a..669ee6d8d 100644 --- a/src/org/apache/fop/fo/expr/PropertyParser.java +++ b/src/org/apache/fop/fo/expr/PropertyParser.java @@ -53,7 +53,7 @@ public class PropertyParser extends PropertyTokenizer { /** * * NOT YET IMPLEMENTED!!! - * functionTable.put("icc-color", new ICCcolorFunction()); + * functionTable.put("rgb-icc", new RgbICCFunction()); * functionTable.put("system-color", new SystemColorFunction()); * functionTable.put("system-font", new SystemFontFunction()); * diff --git a/src/org/apache/fop/fo/flow/Block.java b/src/org/apache/fop/fo/flow/Block.java index 1b6c812fa..85a1ca0cd 100644 --- a/src/org/apache/fop/fo/flow/Block.java +++ b/src/org/apache/fop/fo/flow/Block.java @@ -53,7 +53,6 @@ public class Block extends FObjMixed { int spaceAfter; int textIndent; int keepWithNext; - ColorType backgroundColor; int blockWidows; int blockOrphans; @@ -66,10 +65,13 @@ public class Block extends FObjMixed { // this may be helpful on other FOs too boolean anythingLaidOut = false; - public Block(FObj parent, PropertyList propertyList) { + public Block(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); this.name = "fo:block"; this.span = this.properties.get("span").getEnum(); + ts = propMgr.getTextDecoration(parent); } public Status layout(Area area) throws FOPException { @@ -123,7 +125,7 @@ public class Block extends FObjMixed { // this.properties.get("line-height-shift-adjustment"); // this.properties.get("line-stacking-strategy"); // this.properties.get("orphans"); - // this.properties.get("space-treatment"); + // this.properties.get("white-space-treatment"); // this.properties.get("span"); // this.properties.get("text-align"); // this.properties.get("text-align-last"); @@ -151,8 +153,6 @@ public class Block extends FObjMixed { this.properties.get("text-indent").getLength().mvalue(); this.keepWithNext = this.properties.get("keep-with-next").getEnum(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); this.blockWidows = this.properties.get("widows").getNumber().intValue(); @@ -242,7 +242,7 @@ public class Block extends FObjMixed { blockArea.setParent(area); // BasicLink needs it blockArea.setPage(area.getPage()); - blockArea.setBackgroundColor(backgroundColor); + blockArea.setBackground(propMgr.getBackgroundProps()); blockArea.setBorderAndPadding(propMgr.getBorderAndPadding()); blockArea.setHyphenation(propMgr.getHyphenationProps()); blockArea.start(); diff --git a/src/org/apache/fop/fo/flow/BlockContainer.java b/src/org/apache/fop/fo/flow/BlockContainer.java index 563fbbfcc..1f165d3c8 100644 --- a/src/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/org/apache/fop/fo/flow/BlockContainer.java @@ -21,7 +21,6 @@ import java.util.Enumeration; public class BlockContainer extends FObj { - ColorType backgroundColor; int position; int top; @@ -87,9 +86,6 @@ public class BlockContainer extends FObj { this.marker = 0; - this.backgroundColor = - this.properties.get("background-color").getColorType(); - this.position = this.properties.get("position").getEnum(); this.top = this.properties.get("top").getLength().mvalue(); this.bottom = this.properties.get("bottom").getLength().mvalue(); @@ -119,7 +115,7 @@ public class BlockContainer extends FObj { position); areaContainer.setPage(area.getPage()); - areaContainer.setBackgroundColor(backgroundColor); + areaContainer.setBackground(propMgr.getBackgroundProps()); areaContainer.setBorderAndPadding(propMgr.getBorderAndPadding()); areaContainer.start(); diff --git a/src/org/apache/fop/fo/flow/Inline.java b/src/org/apache/fop/fo/flow/Inline.java index 69987b4e7..d21c815b4 100644 --- a/src/org/apache/fop/fo/flow/Inline.java +++ b/src/org/apache/fop/fo/flow/Inline.java @@ -30,12 +30,6 @@ public class Inline extends FObjMixed { return new Inline.Maker(); } - // Textdecoration - protected boolean underlined = false; - protected boolean overlined = false; - protected boolean lineThrough = false; - - public Inline(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); @@ -79,27 +73,17 @@ public class Inline extends FObjMixed { // this.properties.get("visibility"); // this.properties.get("z-index"); - int textDecoration = this.properties.get("text-decoration").getEnum(); - - if (textDecoration == TextDecoration.UNDERLINE) { - this.underlined = true; - } + // Text Decoration Properties + ts = propMgr.getTextDecoration(parent); - if (textDecoration == TextDecoration.OVERLINE) { - this.overlined = true; - } - - if (textDecoration == TextDecoration.LINE_THROUGH) { - this.lineThrough = true; - } } protected void addCharacters(char data[], int start, int length) { FOText ft = new FOText(data, start, length, this); ft.setLogger(log); - ft.setUnderlined(underlined); - ft.setOverlined(overlined); - ft.setLineThrough(lineThrough); + ft.setUnderlined(ts.getUnderlined()); + ft.setOverlined(ts.getOverlined()); + ft.setLineThrough(ts.getLineThrough()); children.addElement(ft); } diff --git a/src/org/apache/fop/fo/flow/ListBlock.java b/src/org/apache/fop/fo/flow/ListBlock.java index 935ba9ccb..e414b6bb5 100644 --- a/src/org/apache/fop/fo/flow/ListBlock.java +++ b/src/org/apache/fop/fo/flow/ListBlock.java @@ -43,7 +43,6 @@ public class ListBlock extends FObj { int spaceBefore; int spaceAfter; int spaceBetweenListRows = 0; - ColorType backgroundColor; public ListBlock(FObj parent, PropertyList propertyList) { super(parent, propertyList); @@ -91,8 +90,6 @@ public class ListBlock extends FObj { this.spaceAfter = this.properties.get("space-after.optimum").getLength().mvalue(); this.spaceBetweenListRows = 0; // not used at present - this.backgroundColor = - this.properties.get("background-color").getColorType(); this.marker = 0; @@ -133,7 +130,7 @@ public class ListBlock extends FObj { blockArea.setPage(area.getPage()); - blockArea.setBackgroundColor(backgroundColor); + blockArea.setBackground(propMgr.getBackgroundProps()); blockArea.start(); blockArea.setAbsoluteHeight(area.getAbsoluteHeight()); diff --git a/src/org/apache/fop/fo/flow/RetrieveMarker.java b/src/org/apache/fop/fo/flow/RetrieveMarker.java index 67e9f5047..7e2817f7b 100644 --- a/src/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/org/apache/fop/fo/flow/RetrieveMarker.java @@ -72,7 +72,7 @@ public class RetrieveMarker extends FObjMixed { } } - Status status = new Status(Status.AREA_FULL_NONE); + Status status = new Status(Status.OK); if (null != bestMarker) { // System.out.println("Laying out marker '" + bestMarker + "' in area '" + area + "'"); // the 'markers' referred to in this method are internal; they have diff --git a/src/org/apache/fop/fo/flow/RowSpanMgr.java b/src/org/apache/fop/fo/flow/RowSpanMgr.java index 363963b62..c98b054cc 100644 --- a/src/org/apache/fop/fo/flow/RowSpanMgr.java +++ b/src/org/apache/fop/fo/flow/RowSpanMgr.java @@ -52,6 +52,8 @@ public class RowSpanMgr { private SpanInfo spanInfo[]; + private boolean ignoreKeeps = false; + public RowSpanMgr(int numCols) { this.spanInfo = new SpanInfo[numCols]; } @@ -125,4 +127,22 @@ public class RowSpanMgr { return false; } + /** + * helper method to prevent infinite loops if + * keeps or spans are not fitting on a page + * @param <code>true</code> if keeps and spans should be ignored + */ + public void setIgnoreKeeps(boolean ignoreKeeps) { + this.ignoreKeeps = ignoreKeeps; + } + + /** + * helper method (i.e. hack ;-) to prevent infinite loops if + * keeps or spans are not fitting on a page + * @return true if keeps or spans should be ignored + */ + public boolean ignoreKeeps() { + return ignoreKeeps; + } + } diff --git a/src/org/apache/fop/fo/flow/Table.java b/src/org/apache/fop/fo/flow/Table.java index 6ebd4b711..c2a0c4479 100644 --- a/src/org/apache/fop/fo/flow/Table.java +++ b/src/org/apache/fop/fo/flow/Table.java @@ -37,7 +37,6 @@ public class Table extends FObj { int breakAfter; int spaceBefore; int spaceAfter; - ColorType backgroundColor; LengthRange ipd; int height; String id; @@ -113,8 +112,6 @@ public class Table extends FObj { this.properties.get("space-before.optimum").getLength().mvalue(); this.spaceAfter = this.properties.get("space-after.optimum").getLength().mvalue(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); this.ipd = this.properties.get("inline-progression-dimension"). getLengthRange(); @@ -173,7 +170,7 @@ public class Table extends FObj { areaContainer.foCreator = this; // G Seshadri areaContainer.setPage(area.getPage()); - areaContainer.setBackgroundColor(backgroundColor); + areaContainer.setBackground(propMgr.getBackgroundProps()); areaContainer.setBorderAndPadding(propMgr.getBorderAndPadding()); areaContainer.start(); diff --git a/src/org/apache/fop/fo/flow/TableBody.java b/src/org/apache/fop/fo/flow/TableBody.java index 7ca06d172..10dba40c8 100644 --- a/src/org/apache/fop/fo/flow/TableBody.java +++ b/src/org/apache/fop/fo/flow/TableBody.java @@ -34,7 +34,6 @@ public class TableBody extends FObj { int spaceBefore; int spaceAfter; - ColorType backgroundColor; String id; Vector columns; @@ -89,8 +88,6 @@ public class TableBody extends FObj { this.properties.get("space-before.optimum").getLength().mvalue(); this.spaceAfter = this.properties.get("space-after.optimum").getLength().mvalue(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); this.id = this.properties.get("id").getString(); area.getIDReferences().createID(id); @@ -136,7 +133,7 @@ public class TableBody extends FObj { area.spaceLeft(), Position.RELATIVE); areaContainer.foCreator = this; // G Seshadri areaContainer.setPage(area.getPage()); - areaContainer.setBackgroundColor(backgroundColor); + areaContainer.setBackground(propMgr.getBackgroundProps()); areaContainer.setBorderAndPadding(propMgr.getBorderAndPadding()); areaContainer.start(); @@ -186,8 +183,9 @@ public class TableBody extends FObj { } return status; } - if (keepWith.size() - > 0) { // && status.getCode() == Status.AREA_FULL_NONE + if ((keepWith.size() > 0) + && (!rowSpanMgr.ignoreKeeps())) { + // && status.getCode() == Status.AREA_FULL_NONE // FIXME!!! Handle rows spans!!! row.removeLayout(areaContainer); for (Enumeration e = keepWith.elements(); @@ -198,6 +196,10 @@ public class TableBody extends FObj { } if (i == 0) { resetMarker(); + + // Fix for infinite loop bug if keeps are too big for page + rowSpanMgr.setIgnoreKeeps(true); + return new Status(Status.AREA_FULL_NONE); } } @@ -212,6 +214,10 @@ public class TableBody extends FObj { area.increaseHeight(areaContainer.getHeight()); area.setAbsoluteHeight(areaContainer.getAbsoluteHeight()); } + + // Fix for infinite loop bug if spanned rows are too big for page + rowSpanMgr.setIgnoreKeeps(true); + return status; } else if (status.getCode() == Status.KEEP_WITH_NEXT || rowSpanMgr.hasUnfinishedSpans()) { diff --git a/src/org/apache/fop/fo/flow/TableCell.java b/src/org/apache/fop/fo/flow/TableCell.java index 4c5fe1c1d..ba728190f 100644 --- a/src/org/apache/fop/fo/flow/TableCell.java +++ b/src/org/apache/fop/fo/flow/TableCell.java @@ -30,7 +30,6 @@ public class TableCell extends FObj { // int spaceBefore; // int spaceAfter; - ColorType backgroundColor; String id; int numColumnsSpanned; @@ -173,9 +172,6 @@ public class TableCell extends FObj { numRowsSpanned = 1; } - this.backgroundColor = - this.properties.get("background-color").getColorType(); - this.id = this.properties.get("id").getString(); bSepBorders = (this.properties.get("border-collapse").getEnum() @@ -247,7 +243,7 @@ public class TableCell extends FObj { System.err.println("Can't clone BorderAndPadding: " + e) ; cellArea.setBorderAndPadding(propMgr.getBorderAndPadding()); } - cellArea.setBackgroundColor(this.backgroundColor); + cellArea.setBackground(propMgr.getBackgroundProps()); cellArea.start(); cellArea.setAbsoluteHeight(area.getAbsoluteHeight()); // ??? diff --git a/src/org/apache/fop/fo/flow/TableColumn.java b/src/org/apache/fop/fo/flow/TableColumn.java index 44684ae33..11e2a5e3d 100644 --- a/src/org/apache/fop/fo/flow/TableColumn.java +++ b/src/org/apache/fop/fo/flow/TableColumn.java @@ -16,8 +16,6 @@ import org.apache.fop.datatypes.*; public class TableColumn extends FObj { - ColorType backgroundColor; - Length columnWidthPropVal; int columnWidth; int columnOffset; @@ -88,9 +86,6 @@ public class TableColumn extends FObj { this.numColumnsRepeated = this.properties.get("number-columns-repeated").getNumber().intValue(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); - this.columnWidthPropVal = this.properties.get("column-width").getLength(); // This won't include resolved table-units or % values yet. @@ -121,7 +116,7 @@ public class TableColumn extends FObj { areaContainer.foCreator = this; // G Seshadri areaContainer.setPage(area.getPage()); areaContainer.setBorderAndPadding(propMgr.getBorderAndPadding()); - areaContainer.setBackgroundColor(this.backgroundColor); + areaContainer.setBackground(propMgr.getBackgroundProps()); areaContainer.setHeight(area.getHeight()); area.addChild(areaContainer); } diff --git a/src/org/apache/fop/fo/flow/TableRow.java b/src/org/apache/fop/fo/flow/TableRow.java index d06e04784..83762c8b9 100644 --- a/src/org/apache/fop/fo/flow/TableRow.java +++ b/src/org/apache/fop/fo/flow/TableRow.java @@ -35,7 +35,6 @@ public class TableRow extends FObj { boolean setup = false; int breakAfter; - ColorType backgroundColor; String id; KeepValue keepWithNext; @@ -214,8 +213,6 @@ public class TableRow extends FObj { this.breakAfter = this.properties.get("break-after").getEnum(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); this.keepTogether = getKeepValue("keep-together.within-column"); this.keepWithNext = getKeepValue("keep-with-next.within-column"); @@ -286,7 +283,7 @@ public class TableRow extends FObj { areaContainer.foCreator = this; // G Seshadri areaContainer.setPage(area.getPage()); - areaContainer.setBackgroundColor(backgroundColor); + areaContainer.setBackground(propMgr.getBackgroundProps()); areaContainer.start(); areaContainer.setAbsoluteHeight(area.getAbsoluteHeight()); diff --git a/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java b/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java index 2e3a81431..fba2c52c0 100644 --- a/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java @@ -38,8 +38,8 @@ public class ConditionalPageMasterReference extends FObj { super(parent, propertyList); this.name = getElementName(); - if (getProperty("master-name") != null) { - setMasterName(getProperty("master-name").getString()); + if (getProperty("master-reference") != null) { + setMasterName(getProperty("master-reference").getString()); } validateParent(parent); @@ -56,7 +56,7 @@ public class ConditionalPageMasterReference extends FObj { } /** - * Returns the "master-name" attribute of this page master reference + * Returns the "master-reference" attribute of this page master reference */ public String getMasterName() { return masterName; @@ -148,7 +148,7 @@ public class ConditionalPageMasterReference extends FObj { if (getMasterName() == null) { log.warn("single-page-master-reference" - + "does not have a master-name and so is being ignored"); + + "does not have a master-reference and so is being ignored"); } else { this.repeatablePageMasterAlternatives.addConditionalPageMasterReference(this); } diff --git a/src/org/apache/fop/fo/pagination/PageMasterReference.java b/src/org/apache/fop/fo/pagination/PageMasterReference.java index 05300a065..0af756abf 100644 --- a/src/org/apache/fop/fo/pagination/PageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/PageMasterReference.java @@ -13,7 +13,7 @@ import org.apache.fop.apps.FOPException; /** * Base PageMasterReference class. Provides implementation for handling the - * master-name attribute and containment within a PageSequenceMaster + * master-reference attribute and containment within a PageSequenceMaster */ public abstract class PageMasterReference extends FObj implements SubSequenceSpecifier { @@ -25,8 +25,8 @@ public abstract class PageMasterReference extends FObj throws FOPException { super(parent, propertyList); this.name = getElementName(); - if (getProperty("master-name") != null) { - setMasterName(getProperty("master-name").getString()); + if (getProperty("master-reference") != null) { + setMasterName(getProperty("master-reference").getString()); } validateParent(parent); @@ -37,7 +37,7 @@ public abstract class PageMasterReference extends FObj } /** - * Returns the "master-name" attribute of this page master reference + * Returns the "master-reference" attribute of this page master reference */ public String getMasterName() { return _masterName; @@ -72,7 +72,7 @@ public abstract class PageMasterReference extends FObj if (getMasterName() == null) { log.warn("" + getElementName() - + " does not have a master-name and so is being ignored"); + + " does not have a master-reference and so is being ignored"); } else { _pageSequenceMaster.addSubsequenceSpecifier(this); } diff --git a/src/org/apache/fop/fo/pagination/PageNumberGenerator.java b/src/org/apache/fop/fo/pagination/PageNumberGenerator.java index 8c3e6c257..facb47f48 100644 --- a/src/org/apache/fop/fo/pagination/PageNumberGenerator.java +++ b/src/org/apache/fop/fo/pagination/PageNumberGenerator.java @@ -7,9 +7,11 @@ package org.apache.fop.fo.pagination; +// FOP import org.apache.fop.fo.properties.*; -import org.apache.log.*; +// Avalon +import org.apache.avalon.framework.logger.Logger; // Java import java.util.*; diff --git a/src/org/apache/fop/fo/pagination/PageSequence.java b/src/org/apache/fop/fo/pagination/PageSequence.java index 290f19454..36b3752a2 100644 --- a/src/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/org/apache/fop/fo/pagination/PageSequence.java @@ -82,7 +82,9 @@ public class PageSequence extends FObj { private Hashtable _flowMap; /** - * the "master-name" attribute + * the "master-reference" attribute, + * which specifies the name of the page-sequence-master or + * page-master to be used to create pages in the sequence */ private String masterName; @@ -176,7 +178,7 @@ public class PageSequence extends FObj { } } - masterName = this.properties.get("master-name").getString(); + masterName = this.properties.get("master-reference").getString(); // get the 'format' properties this.pageNumberGenerator = @@ -527,7 +529,7 @@ public class PageSequence extends FObj { SimplePageMaster simpleMaster = this.layoutMasterSet.getSimplePageMaster(pageSequenceName); if (simpleMaster == null) { - throw new FOPException("'master-name' for 'fo:page-sequence'" + throw new FOPException("'master-reference' for 'fo:page-sequence'" + "matches no 'simple-page-master' or 'page-sequence-master'"); } currentPageMasterName = pageSequenceName; @@ -611,7 +613,11 @@ public class PageSequence extends FObj { } public int getCurrentPageNumber() { - return currentPageNumber; + return currentPageNumber; + } + + public int getPageCount() { + return this.pageCount; } private void forcePage(AreaTree areaTree, int firstAvailPageNumber) { diff --git a/src/org/apache/fop/fo/pagination/RegionAfter.java b/src/org/apache/fop/fo/pagination/RegionAfter.java index 39fe22d1a..e88988707 100644 --- a/src/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/org/apache/fop/fo/pagination/RegionAfter.java @@ -57,10 +57,12 @@ public class RegionAfter extends Region { // this.properties.get("reference-orientation"); // this.properties.get("writing-mode"); - return new RegionArea(allocationRectangleXPosition, - allocationRectangleYPosition - - allocationRectangleHeight + extent, - allocationRectangleWidth, extent); + RegionArea area = new RegionArea(allocationRectangleXPosition, + allocationRectangleYPosition + - allocationRectangleHeight + extent, + allocationRectangleWidth, extent); + area.setBackground(bProps); + return area; } diff --git a/src/org/apache/fop/fo/pagination/RegionBefore.java b/src/org/apache/fop/fo/pagination/RegionBefore.java index e2bcdcf5e..75140d1ca 100644 --- a/src/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/org/apache/fop/fo/pagination/RegionBefore.java @@ -58,9 +58,11 @@ public class RegionBefore extends Region { // this.properties.get("reference-orientation"); // this.properties.get("writing-mode"); - return new RegionArea(allocationRectangleXPosition, - allocationRectangleYPosition, - allocationRectangleWidth, extent); + RegionArea area = new RegionArea(allocationRectangleXPosition, + allocationRectangleYPosition, + allocationRectangleWidth, extent); + area.setBackground(bProps); + return area; } diff --git a/src/org/apache/fop/fo/pagination/RegionBody.java b/src/org/apache/fop/fo/pagination/RegionBody.java index 9c4d46078..6f5200390 100644 --- a/src/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/org/apache/fop/fo/pagination/RegionBody.java @@ -11,7 +11,6 @@ package org.apache.fop.fo.pagination; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.Overflow; -import org.apache.fop.datatypes.ColorType; import org.apache.fop.apps.FOPException; import org.apache.fop.layout.RegionArea; import org.apache.fop.layout.BodyRegionArea; @@ -36,8 +35,6 @@ public class RegionBody extends Region { public static final String REGION_CLASS = "body"; - ColorType backgroundColor; - protected RegionBody(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); @@ -61,9 +58,6 @@ public class RegionBody extends Region { // this.properties.get("reference-orientation"); // this.properties.get("writing-mode"); - this.backgroundColor = - this.properties.get("background-color").getColorType(); - BodyRegionArea body = new BodyRegionArea(allocationRectangleXPosition + mProps.marginLeft, allocationRectangleYPosition @@ -75,6 +69,8 @@ public class RegionBody extends Region { - mProps.marginTop - mProps.marginBottom); + body.setBackground(propMgr.getBackgroundProps()); + int overflow = this.properties.get("overflow").getEnum(); String columnCountAsString = this.properties.get("column-count").getString(); @@ -98,8 +94,6 @@ public class RegionBody extends Region { this.properties.get("column-gap").getLength().mvalue(); body.setColumnGap(columnGap); - body.setBackgroundColor(backgroundColor); - return body; } diff --git a/src/org/apache/fop/fo/pagination/RegionEnd.java b/src/org/apache/fop/fo/pagination/RegionEnd.java index 0712af5c0..edff866fa 100644 --- a/src/org/apache/fop/fo/pagination/RegionEnd.java +++ b/src/org/apache/fop/fo/pagination/RegionEnd.java @@ -55,9 +55,12 @@ public class RegionEnd extends Region { } if (afterPrecedence) startH -= afterHeight; - return new RegionArea(allocationRectangleXPosition - + allocationRectangleWidth - extent, startY, - extent, startH); + RegionArea area = new RegionArea(allocationRectangleXPosition + + allocationRectangleWidth - extent, + startY, extent, startH); + area.setBackground(propMgr.getBackgroundProps()); + return area; + } RegionArea makeRegionArea(int allocationRectangleXPosition, diff --git a/src/org/apache/fop/fo/pagination/RegionStart.java b/src/org/apache/fop/fo/pagination/RegionStart.java index 0388340ec..6892669d5 100644 --- a/src/org/apache/fop/fo/pagination/RegionStart.java +++ b/src/org/apache/fop/fo/pagination/RegionStart.java @@ -55,8 +55,10 @@ public class RegionStart extends Region { } if (afterPrecedence) startH -= afterHeight; - return new RegionArea(allocationRectangleXPosition, startY, extent, - startH); + RegionArea area = new RegionArea(allocationRectangleXPosition, + startY, extent, startH); + area.setBackground(propMgr.getBackgroundProps()); + return area; } RegionArea makeRegionArea(int allocationRectangleXPosition, diff --git a/src/org/apache/fop/fonts/TTFFile.java b/src/org/apache/fop/fonts/TTFFile.java index d48a1948e..b587da1a3 100644 --- a/src/org/apache/fop/fonts/TTFFile.java +++ b/src/org/apache/fop/fonts/TTFFile.java @@ -224,31 +224,23 @@ public class TTFFile { // Also add winAnsiWidth - if (false) { - int d = j; - if (j > 127) - d = (int)org.apache.fop.render.pdf.CodePointMapping.map[j]; - if (d < ansiWidth.length) - ansiWidth[d] = mtx_tab[glyphIdx].wx; - } else { - Vector v = - (Vector)ansiIndex.get(new Integer(j)); - if (v != null) { - for (Enumeration e = v.elements(); - e.hasMoreElements(); ) { - Integer aIdx = - (Integer)e.nextElement(); - ansiWidth[aIdx.intValue()] = - mtx_tab[glyphIdx].wx; - /* - * System.out.println("Added width "+ - * mtx_tab[glyphIdx].wx + - * " uni: " + j + - * " ansi: " + aIdx.intValue()); - */ - } - } - } + Vector v = + (Vector)ansiIndex.get(new Integer(j)); + if (v != null) { + for (Enumeration e = v.elements(); + e.hasMoreElements(); ) { + Integer aIdx = + (Integer)e.nextElement(); + ansiWidth[aIdx.intValue()] = + mtx_tab[glyphIdx].wx; + /* + * System.out.println("Added width "+ + * mtx_tab[glyphIdx].wx + + * " uni: " + j + + * " ansi: " + aIdx.intValue()); + */ + } + } /* * System.out.println("Idx: "+ * glyphIdx + @@ -281,26 +273,17 @@ public class TTFFile { // Also add winAnsiWidth - if (false) { - int d = j; - if (j > 127) - d = (int)org.apache.fop.render.pdf.CodePointMapping.map[j]; - - if (d < ansiWidth.length) - ansiWidth[d] = mtx_tab[glyphIdx].wx; - } else { - Vector v = - (Vector)ansiIndex.get(new Integer(j)); - if (v != null) { - for (Enumeration e = v.elements(); - e.hasMoreElements(); ) { - Integer aIdx = - (Integer)e.nextElement(); - ansiWidth[aIdx.intValue()] = - mtx_tab[glyphIdx].wx; - } - } - } + Vector v = + (Vector)ansiIndex.get(new Integer(j)); + if (v != null) { + for (Enumeration e = v.elements(); + e.hasMoreElements(); ) { + Integer aIdx = + (Integer)e.nextElement(); + ansiWidth[aIdx.intValue()] = + mtx_tab[glyphIdx].wx; + } + } /* * System.out.println("IIdx: "+ @@ -669,7 +652,7 @@ public class TTFFile { mtx_tab[i] = new TTFMtxEntry(); for (int i = 0; i < nhmtx; i++) { mtx_tab[i].wx = in.readTTFUShort(); - mtx_tab[i].lsb = in.readTTFUShort(); + mtx_tab[i].lsb = in.readTTFShort(); /* * System.out.println(" width["+i+"] = "+ * get_ttf_funit(mtx_tab[i].wx)+";"); @@ -681,7 +664,7 @@ public class TTFFile { int lastWidth = mtx_tab[nhmtx - 1].wx; for (int i = nhmtx; i < mtx_size; i++) { mtx_tab[i].wx = lastWidth; - mtx_tab[i].lsb = in.readTTFUShort(); + mtx_tab[i].lsb = in.readTTFShort(); } } } diff --git a/src/org/apache/fop/fonts/apps/PFMReader.java b/src/org/apache/fop/fonts/apps/PFMReader.java index 4dba53e94..8a7148e9c 100644 --- a/src/org/apache/fop/fonts/apps/PFMReader.java +++ b/src/org/apache/fop/fonts/apps/PFMReader.java @@ -4,14 +4,10 @@ * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ - package org.apache.fop.fonts.apps; import java.io.*; import org.w3c.dom.*; -import org.apache.xerces.dom.*; -import org.apache.xml.serialize.*; -import org.apache.xalan.xslt.*; import org.apache.fop.fonts.*; import java.util.Hashtable; import java.util.Vector; @@ -197,13 +193,19 @@ public class PFMReader { System.out.println(); try { - OutputFormat format = new OutputFormat(doc); // Serialize DOM - FileWriter out = new FileWriter(target); // Writer will be a String + javax.xml.transform.TransformerFactory.newInstance() + .newTransformer().transform( + new javax.xml.transform.dom.DOMSource(doc), + new javax.xml.transform.stream.StreamResult(new File(target))); +/* + OutputFormat format = new OutputFormat(doc); // Serialize DOM + FileWriter out = new FileWriter(target); // Writer will be a String XMLSerializer serial = new XMLSerializer(out, format); serial.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); out.close(); +*/ } catch (Exception e) { e.printStackTrace(); } @@ -220,7 +222,15 @@ public class PFMReader { System.out.println("Creating xml font file..."); System.out.println(); - Document doc = new DocumentImpl(); +// Document doc = new DocumentImpl(); + Document doc; + try { + doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + } + catch (javax.xml.parsers.ParserConfigurationException e) { + System.out.println("Can't create DOM implementation "+e.getMessage()); + return null; + } Element root = doc.createElement("font-metrics"); doc.appendChild(root); root.setAttribute("type", "TYPE1"); diff --git a/src/org/apache/fop/fonts/apps/TTFReader.java b/src/org/apache/fop/fonts/apps/TTFReader.java index 5a7c47919..584f74c88 100644 --- a/src/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/org/apache/fop/fonts/apps/TTFReader.java @@ -8,9 +8,6 @@ package org.apache.fop.fonts.apps; import java.io.*; import org.w3c.dom.*; -import org.apache.xerces.dom.*; -import org.apache.xml.serialize.*; -import org.apache.xalan.xslt.*; import org.apache.fop.fonts.*; import java.util.Hashtable; import java.util.Vector; @@ -198,13 +195,19 @@ public class TTFReader { System.out.println(); try { - OutputFormat format = new OutputFormat(doc); // Serialize DOM + javax.xml.transform.TransformerFactory.newInstance() + .newTransformer().transform( + new javax.xml.transform.dom.DOMSource(doc), + new javax.xml.transform.stream.StreamResult(new File(target))); + +/* OutputFormat format = new OutputFormat(doc); // Serialize DOM FileWriter out = new FileWriter(target); // Writer will be a String XMLSerializer serial = new XMLSerializer(out, format); serial.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); out.close(); +*/ } catch (Exception e) { e.printStackTrace(); } @@ -222,7 +225,15 @@ public class TTFReader { System.out.println("Creating xml font file..."); System.out.println(); - Document doc = new DocumentImpl(); +// Document doc = new DocumentImpl(); + Document doc; + try { + doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + } + catch (javax.xml.parsers.ParserConfigurationException e) { + System.out.println("Can't create DOM implementation "+e.getMessage()); + return null; + } Element root = doc.createElement("font-metrics"); doc.appendChild(root); if (isCid) diff --git a/src/org/apache/fop/image/AbstractFopImage.java b/src/org/apache/fop/image/AbstractFopImage.java index 4669758c7..e37516287 100644 --- a/src/org/apache/fop/image/AbstractFopImage.java +++ b/src/org/apache/fop/image/AbstractFopImage.java @@ -27,6 +27,11 @@ import org.apache.fop.image.analyser.ImageReader; public abstract class AbstractFopImage implements FopImage { /** + * Photoshop generated cmykl jpeg's are inverted. + */ + protected boolean m_invertImage = false; + + /** * Image width (in pixel). */ protected int m_width = 0; @@ -136,6 +141,13 @@ public abstract class AbstractFopImage implements FopImage { abstract protected void loadImage() throws FopImageException; /** + * If true, image data are inverted + */ + public boolean invertImage() { + return m_invertImage; + } + + /** * Return the image URL. * @return the image URL (as String) */ diff --git a/src/org/apache/fop/image/EPSImage.java b/src/org/apache/fop/image/EPSImage.java new file mode 100644 index 000000000..125652b22 --- /dev/null +++ b/src/org/apache/fop/image/EPSImage.java @@ -0,0 +1,94 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.image; + +// Java +import java.net.URL; +import java.net.URLConnection; +import java.io.InputStream; +import java.io.IOException; + +// FOP +import org.apache.fop.apps.Driver; +import org.apache.fop.messaging.*; +import org.apache.fop.datatypes.ColorSpace; +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.image.analyser.ImageReader; +import org.apache.fop.image.analyser.EPSReader; + +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + + +/** + * @see AbstractFopImage + * @see FopImage + */ +public class EPSImage extends AbstractFopImage { + private String docName; + private int[] bbox; + + private byte[] epsImage = null; + private EPSReader epsReader = null; + + /** + * Initialize docName and bounding box + */ + private void init(URL href) { + bbox = new int[4]; + bbox[0] = 0; + bbox[1] = 0; + bbox[2] = 0; + bbox[3] = 0; + + docName = href.toString(); + } + + /** + * Return the name of the eps + */ + public String getDocName() { + return docName; + } + + /** + * Return the bounding box + */ + public int[] getBBox() { + return bbox; + } + + public EPSImage(URL href) throws FopImageException { + super(href); + init(href); + } + + public EPSImage(URL href, + ImageReader imgReader) throws FopImageException { + super(href, imgReader); + init(href); + if (imgReader instanceof EPSReader) { + EPSReader eimgReader = (EPSReader)imgReader; + epsReader = eimgReader; + epsImage = eimgReader.getEpsFile(); + m_bitmaps = epsImage; + bbox = eimgReader.getBBox(); + } + } + + protected void loadImage() throws FopImageException { + // Image is loaded in reader + } + + public byte[] getEPSImage() throws FopImageException { + if (epsImage == null) + MessageHandler.errorln("ERROR LOADING EXTERNAL EPS"); + return epsImage; + } + +} diff --git a/src/org/apache/fop/image/FopImage.java b/src/org/apache/fop/image/FopImage.java index 2cbcc45c5..a6628b5ef 100644 --- a/src/org/apache/fop/image/FopImage.java +++ b/src/org/apache/fop/image/FopImage.java @@ -25,7 +25,9 @@ public interface FopImage { // Methods throw exception because they can retrieve data // when needed. - // Ressource location + public boolean invertImage(); + + // Resource location public String getURL(); // image size diff --git a/src/org/apache/fop/image/FopImageConsumer.java b/src/org/apache/fop/image/FopImageConsumer.java index 696f1bdd1..972db183d 100644 --- a/src/org/apache/fop/image/FopImageConsumer.java +++ b/src/org/apache/fop/image/FopImageConsumer.java @@ -57,7 +57,8 @@ public class FopImageConsumer implements ImageConsumer { */ synchronized (this.imageStatus) { // Need to stop status if image done - if (this.imageStatus.intValue() != ImageConsumer.STATICIMAGEDONE) + if (imageStatus.intValue() != ImageConsumer.STATICIMAGEDONE + && imageStatus.intValue() != ImageConsumer.SINGLEFRAMEDONE) this.imageStatus = new Integer(status); } } @@ -96,7 +97,8 @@ public class FopImageConsumer implements ImageConsumer { if (this.imageStatus.intValue() == ImageConsumer.IMAGEERROR) throw new Exception("Image error"); - if (this.imageStatus.intValue() == ImageConsumer.STATICIMAGEDONE) + if (imageStatus.intValue() == ImageConsumer.STATICIMAGEDONE + || imageStatus.intValue() == ImageConsumer.SINGLEFRAMEDONE) return true; return false; diff --git a/src/org/apache/fop/image/FopImageFactory.java b/src/org/apache/fop/image/FopImageFactory.java index 4e1ea97e6..305bc35d1 100644 --- a/src/org/apache/fop/image/FopImageFactory.java +++ b/src/org/apache/fop/image/FopImageFactory.java @@ -58,6 +58,12 @@ public class FopImageFactory { href = href.substring(1, href.length() - 1); } } + + // check if already created + FopImage imageObject = (FopImage)m_urlMap.get(href); + if (imageObject != null) + return imageObject; + try { // try url as complete first, this can cause // a problem with relative uri's if there is an @@ -77,11 +83,13 @@ public class FopImageFactory { // maybe relative URL context_url = null; String base = Configuration.getStringValue("baseDir"); + if(base == null) { throw new FopImageException("Error with image URL: " + e.getMessage() + " and no base directory is specified"); } + try { absoluteURL = new URL(Configuration.getStringValue("baseDir") + absoluteURL.getFile()); @@ -92,11 +100,6 @@ public class FopImageFactory { } } - // check if already created - FopImage imageObject = (FopImage)m_urlMap.get(absoluteURL.toString()); - if (imageObject != null) - return imageObject; - // If not, check image type ImageReader imgReader = null; try { @@ -138,6 +141,8 @@ public class FopImageFactory { } else if ("image/tga".equals(imgMimeType)) { imgClassName = "org.apache.fop.image.JimiImage"; // imgClassName = "org.apache.fop.image.JAIImage"; + } else if ("image/eps".equals(imgMimeType)) { + imgClassName = "org.apache.fop.image.EPSImage"; } else if ("image/tiff".equals(imgMimeType)) { imgClassName = "org.apache.fop.image.JimiImage"; // imgClassName = "org.apache.fop.image.JAIImage"; @@ -188,7 +193,7 @@ public class FopImageFactory { + "class " + imageClass.getName() + " doesn't implement org.apache.fop.image.FopImage interface"); } - m_urlMap.put(absoluteURL.toString(), imageInstance); + m_urlMap.put(href, imageInstance); return (FopImage)imageInstance; } diff --git a/src/org/apache/fop/image/JpegImage.java b/src/org/apache/fop/image/JpegImage.java index e725b79f5..0e439a8a8 100644 --- a/src/org/apache/fop/image/JpegImage.java +++ b/src/org/apache/fop/image/JpegImage.java @@ -28,6 +28,10 @@ import org.apache.fop.image.analyser.ImageReader; * @see FopImage */ public class JpegImage extends AbstractFopImage { + boolean hasAPPEMarker = false; + boolean found_icc_profile = false; + boolean found_dimensions = false; + public JpegImage(URL href) throws FopImageException { super(href); } @@ -39,8 +43,9 @@ public class JpegImage extends AbstractFopImage { protected void loadImage() throws FopImageException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ByteArrayOutputStream iccStream = new ByteArrayOutputStream(); InputStream inStream; - + this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_UNKNOWN); byte[] readBuf = new byte[4096]; int bytes_read; int index = 0; @@ -85,39 +90,94 @@ public class JpegImage extends AbstractFopImage { this.m_bitmaps[index + 8]); if (this.m_bitmaps[index + 9] == 1) { - this.m_colorSpace = new ColorSpace( - ColorSpace.DEVICE_GRAY); + this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_GRAY); } else if (this.m_bitmaps[index + 9] == 3) { - this.m_colorSpace = - new ColorSpace(ColorSpace.DEVICE_RGB); - } else { + this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_RGB); + } else if (this.m_bitmaps[index + 9] == 4) { + this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_CMYK); + } + + found_dimensions = true; + if (found_icc_profile) { cont = false; - throw new FopImageException( - "\n2 Error while loading image " + - this.m_href.toString() + - " : JpegImage - Invalid JPEG Header (bad color space " + - this.m_bitmaps[index + 9] + ")."); + break; + } + index += calcBytes(this.m_bitmaps[index + 2], + this.m_bitmaps[index + 3]) + 2; + + } else if (uByte(this.m_bitmaps[index+1]) == 226 && + this.m_bitmaps.length > (index+60)) { + // Check if ICC profile + byte[] icc_string = new byte[11]; + System.arraycopy(this.m_bitmaps, index+4, icc_string, 0, 11); + + /* + byte[] acsp = new byte[4]; + System.arraycopy(this.m_bitmaps, index+18+36, acsp, 0, 4); + boolean first_chunk = false; + if ("acsp".equals(new String(acsp))) { + System.out.println("1st icc chunk"); + first_chunk = true; } + */ + if ("ICC_PROFILE".equals(new String(icc_string))){ + int chunkSize = calcBytes(this.m_bitmaps[index + 2], + this.m_bitmaps[index + 3]) + 2; - cont = false; - break; + if (iccStream.size() == 0) + iccStream.write(this.m_bitmaps, index+18, chunkSize - 20); + else + iccStream.write(this.m_bitmaps, index+16, chunkSize - 18); // eller 18.. + + } - } else { // if (uByte(this.m_bitmaps[index + 1]) == headers[headerIndex]) { + index += calcBytes(this.m_bitmaps[index + 2], + this.m_bitmaps[index + 3]) + 2; + // Check for Adobe APPE Marker + } else if ((uByte(this.m_bitmaps[index]) == 0xff && + uByte(this.m_bitmaps[index+1]) == 0xee && + uByte(this.m_bitmaps[index+2]) == 0 && + uByte(this.m_bitmaps[index+3]) == 14 && + "Adobe".equals(new String(this.m_bitmaps, index+4, 5)))) { + // The reason for reading the APPE marker is that photoshop + // generates cmyk jpeg's with inverted values. The correct thing + // to do would be to interpret the values in the marker, but for now + // only assume that if APPE marker is present and colorspace is CMYK, + // the image is inverted. + hasAPPEMarker = true; + + index += calcBytes(this.m_bitmaps[index + 2], + this.m_bitmaps[index + 3]) + 2; + } else { index += calcBytes(this.m_bitmaps[index + 2], this.m_bitmaps[index + 3]) + 2; } + } else { cont = false; + /* throw new FopImageException( "\n2 Error while loading image " + this.m_href.toString() + " : JpegImage - Invalid JPEG Header (bad header byte)."); + */ } } } else { throw new FopImageException( "\n1 Error while loading image " + this.m_href.toString() + " : JpegImage - Invalid JPEG Header."); } + if (iccStream.size() > 0) { + byte[] align = new byte[((iccStream.size()) % 8) + 8]; + try {iccStream.write(align);} catch (Exception e) { + throw new FopImageException( "\n1 Error while loading image " + + this.m_href.toString() + " : " + e.getMessage()); + } + this.m_colorSpace.setICCProfile(iccStream.toByteArray()); + } + + if (hasAPPEMarker && this.m_colorSpace.getColorSpace() == ColorSpace.DEVICE_CMYK) + this.m_invertImage = true; } private int calcBytes(byte bOne, byte bTwo) { diff --git a/src/org/apache/fop/image/SVGImage.java b/src/org/apache/fop/image/SVGImage.java index 34f4a625a..50c094991 100644 --- a/src/org/apache/fop/image/SVGImage.java +++ b/src/org/apache/fop/image/SVGImage.java @@ -40,14 +40,12 @@ public class SVGImage extends AbstractFopImage { } /** - * creates a SAX parser, using the value of org.xml.sax.parser - * defaulting to org.apache.xerces.parsers.SAXParser + * get Parser Class name * - * @return the created SAX parser + * @return the SAX parser name */ public static String getParserName() { - String parserClassName = Driver.getParserClassName(); - return parserClassName; + return org.apache.fop.apps.Driver.getParserClassName(); } protected void loadImage() throws FopImageException { diff --git a/src/org/apache/fop/image/analyser/EPSReader.java b/src/org/apache/fop/image/analyser/EPSReader.java new file mode 100644 index 000000000..4ceb52c1d --- /dev/null +++ b/src/org/apache/fop/image/analyser/EPSReader.java @@ -0,0 +1,227 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.image.analyser; + +// Java +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + + +// FOP +import org.apache.fop.messaging.*; +import org.apache.fop.image.SVGImage; + +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + + +/** + * ImageReader object for SVG document image type. + */ +public class EPSReader extends AbstractImageReader { + private long[] bbox; + private boolean isAscii; // True if plain ascii eps file + + // offsets if not ascii + long psStart = 0; + long psLength = 0; + long wmfStart = 0; + long wmfLength = 0; + long tiffStart = 0; + long tiffLength = 0; + + /** raw eps file */ + private byte[] rawEps; + /** eps part */ + private byte[] epsFile; + private byte[] preview = null; + + private long getLong(byte[] buf, int idx) { + int b1 = buf[idx] & 0xff; + int b2 = buf[idx+1] & 0xff; + int b3 = buf[idx+2] & 0xff; + int b4 = buf[idx+3] & 0xff; + + //return (long)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4); + return (long)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); + } + + public boolean verifySignature(String uri, BufferedInputStream fis) + throws IOException { + boolean isEPS = false; + this.imageStream = fis; + fis.mark(32); + byte[] header = new byte[30]; + fis.read(header, 0, 30); + fis.reset(); + + // Check if binary header + //if (getLong(header, 0) == 0xC5D0D3C6) { + if (getLong(header, 0) == 0xC6D3D0C5) { + isAscii = false; + isEPS = true; + + psStart = getLong(header, 4); + psLength = getLong(header, 8); + wmfStart = getLong(header, 12); + wmfLength = getLong(header, 16); + tiffStart = getLong(header, 20); + tiffLength = getLong(header, 24); + + } else { + // Check if plain ascii + byte[] epsh = "%!PS".getBytes(); + if (epsh[0] == header[0] && + epsh[1] == header[1] && + epsh[2] == header[2] && + epsh[3] == header[3]) { + isAscii = true; + isEPS = true; + } + } + + if (isEPS) { + readEPSImage(fis); + bbox = readBBox(); + + if (bbox != null) { + width = (int)(bbox[2]-bbox[0]); + height = (int)(bbox[3]-bbox[1]); + } else { + // Ain't eps if no BoundingBox + isEPS = false; + } + } + + return isEPS; + } + + /** read the eps file and extract eps part */ + private void readEPSImage(BufferedInputStream fis) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] file; + byte[] readBuf = new byte[20480]; + int bytes_read; + int index = 0; + boolean cont = true; + + + try { + while ((bytes_read = fis.read(readBuf)) != -1) { + baos.write(readBuf, 0, bytes_read); + } + } catch (java.io.IOException ex) { + throw new IOException("Error while loading EPS image " + ex.getMessage()); + } + + file = baos.toByteArray(); + + if (isAscii) { + rawEps = null; + epsFile = new byte[file.length]; + System.arraycopy(file, 0, epsFile, 0, epsFile.length); + } else { + rawEps = new byte[file.length]; + epsFile = new byte[(int)psLength]; + System.arraycopy(file, 0, rawEps, 0, rawEps.length); + System.arraycopy(rawEps, (int)psStart, epsFile, 0, (int)psLength); + } + } + + public byte[] getEpsFile() { + return epsFile; + } + + /* Get embedded preview or null */ + public byte[] getPreview() { + InputStream is = null; + if (preview == null) { + if (tiffLength > 0) { + preview = new byte[(int)tiffLength]; + System.arraycopy(rawEps, (int)tiffStart, preview, 0, (int)tiffLength); + } + } + return preview; + } + + /** Extract bounding box from eps part + */ + private long[] readBBox() { + long[] mbbox = null; + int idx = 0; + byte[] bbxName = "%%BoundingBox: ".getBytes(); + boolean found = false; + + while (!found && (epsFile.length > (idx + bbxName.length))) { + boolean sfound = true; + int i = idx; + for (i = idx; sfound && (i-idx) < bbxName.length; i++) { + if (bbxName[i - idx] != epsFile[i]) + sfound = false; + } + if (sfound) { + found = true; + idx = i; + } else { + idx++; + } + } + + if (!found) + return mbbox; + + + mbbox = new long[4]; + idx += readLongString(mbbox, 0, idx); + idx += readLongString(mbbox, 1, idx); + idx += readLongString(mbbox, 2, idx); + idx += readLongString(mbbox, 3, idx); + + return mbbox; + } + + private int readLongString(long[] mbbox, int i, int idx) { + while (idx < epsFile.length && + (epsFile[idx] == 32)) + idx++; + + int nidx = idx; + + while (nidx < epsFile.length && + ((epsFile[nidx] >= 48 && epsFile[nidx] <= 57) || + (epsFile[nidx] == 45))) + nidx++; + + byte[] num = new byte[nidx - idx]; + System.arraycopy(epsFile, idx, num, 0, nidx-idx); + String ns = new String(num); + mbbox[i] = Long.parseLong(ns); + + return (1+nidx - idx); + } + + public String getMimeType() { + return "image/eps"; + } + + /** + * Return the BoundingBox + */ + public int[] getBBox() { + int[] bbox = new int[4]; + bbox[0] = (int)this.bbox[0]; + bbox[1] = (int)this.bbox[1]; + bbox[2] = (int)this.bbox[2]; + bbox[3] = (int)this.bbox[3]; + return bbox; + } +} + diff --git a/src/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/org/apache/fop/image/analyser/ImageReaderFactory.java index e9b5ce3f0..f2c2160b7 100644 --- a/src/org/apache/fop/image/analyser/ImageReaderFactory.java +++ b/src/org/apache/fop/image/analyser/ImageReaderFactory.java @@ -42,6 +42,7 @@ public class ImageReaderFactory { formats.addElement(new GIFReader()); formats.addElement(new PNGReader()); formats.addElement(new TIFFReader()); + formats.addElement(new EPSReader()); formats.addElement(new SVGReader()); // diff --git a/src/org/apache/fop/image/analyser/SVGReader.java b/src/org/apache/fop/image/analyser/SVGReader.java index 1178bf903..d00a8d1ce 100644 --- a/src/org/apache/fop/image/analyser/SVGReader.java +++ b/src/org/apache/fop/image/analyser/SVGReader.java @@ -108,7 +108,7 @@ public class SVGReader extends AbstractImageReader { } } - protected class MUserAgent implements UserAgent { + protected class MUserAgent extends UserAgentAdapter { AffineTransform currentTransform = null; /** @@ -148,6 +148,11 @@ public class SVGReader extends AbstractImageReader { return 0.35277777777777777778f; // 72 dpi // return 0.26458333333333333333333333333333f; // 96dpi } + public float getPixelUnitToMillimeter() { + // this is set to 72dpi as the values in fo are 72dpi + return 0.35277777777777777778f; // 72 dpi + // return 0.26458333333333333333333333333333f; // 96dpi + } /** * Returns the language settings. @@ -157,9 +162,12 @@ public class SVGReader extends AbstractImageReader { } public String getMedia() { - return ""; + return "print"; } +public boolean isXMLParserValidating() { +return true; +} /** * Returns the user stylesheet uri. @@ -176,21 +184,6 @@ public class SVGReader extends AbstractImageReader { return org.apache.fop.apps.Driver.getParserClassName(); } - /** - * Opens a link in a new component. - * @param doc The current document. - * @param uri The document URI. - */ - public void openLink(SVGAElement elt) { - } - - public Point getClientAreaLocationOnScreen() { - return new Point(0, 0); - } - - public void setSVGCursor(java.awt.Cursor cursor) {} - - public AffineTransform getTransform() { return currentTransform; } @@ -199,22 +192,6 @@ public class SVGReader extends AbstractImageReader { return new Dimension(100, 100); } - public EventDispatcher getEventDispatcher() { - return null; - } - - public boolean supportExtension(String str) { - return false; - } - - public boolean hasFeature(String str) { - return false; - } - - public void registerExtension(BridgeExtension be) {} - - public void handleElement(Element elt, Object data) {} - } } diff --git a/src/org/apache/fop/layout/Area.java b/src/org/apache/fop/layout/Area.java index 4ac0c935d..f4188e28f 100644 --- a/src/org/apache/fop/layout/Area.java +++ b/src/org/apache/fop/layout/Area.java @@ -48,7 +48,7 @@ abstract public class Area extends Box { /* the page this area is on */ protected Page page; - protected ColorType backgroundColor; + protected BackgroundProps background; private IDReferences idReferences; @@ -206,8 +206,8 @@ abstract public class Area extends Box { return this.page; } - public ColorType getBackgroundColor() { - return this.backgroundColor; + public BackgroundProps getBackground() { + return this.background; } // Must handle conditionality here, depending on isLast/isFirst @@ -291,8 +291,8 @@ abstract public class Area extends Box { this.page = page; } - public void setBackgroundColor(ColorType bgColor) { - this.backgroundColor = bgColor; + public void setBackground(BackgroundProps bg) { + this.background = bg; } public void setBorderAndPadding(BorderAndPadding bp) { diff --git a/src/org/apache/fop/layout/BackgroundProps.java b/src/org/apache/fop/layout/BackgroundProps.java index 6c2d47cda..5ce281061 100644 --- a/src/org/apache/fop/layout/BackgroundProps.java +++ b/src/org/apache/fop/layout/BackgroundProps.java @@ -7,9 +7,9 @@ package org.apache.fop.layout; +import org.apache.fop.datatypes.ColorType; import org.apache.fop.datatypes.Length; - -import java.awt.Color; +import org.apache.fop.image.FopImage; /** * Store all hyphenation related properties on an FO. @@ -17,8 +17,8 @@ import java.awt.Color; */ public class BackgroundProps { public int backAttachment; - public Color backColor; - public String backImage; + public ColorType backColor; + public FopImage backImage; // null if no image public int backRepeat; public Length backPosHorizontal; public Length backPosVertical; diff --git a/src/org/apache/fop/layout/BodyRegionArea.java b/src/org/apache/fop/layout/BodyRegionArea.java index 98d46a873..2447edad3 100644 --- a/src/org/apache/fop/layout/BodyRegionArea.java +++ b/src/org/apache/fop/layout/BodyRegionArea.java @@ -25,9 +25,12 @@ public class BodyRegionArea extends RegionArea { } public BodyAreaContainer makeBodyAreaContainer() { - return new BodyAreaContainer(null, xPosition, yPosition, width, - height, Position.ABSOLUTE, columnCount, - columnGap); + BodyAreaContainer area = + new BodyAreaContainer(null, xPosition, yPosition, width, + height, Position.ABSOLUTE, columnCount, + columnGap); + area.setBackground(getBackground()); + return area; } public void setColumnCount(int columnCount) { diff --git a/src/org/apache/fop/layout/FontInfo.java b/src/org/apache/fop/layout/FontInfo.java index 4e8258fb1..2fd4100d1 100644 --- a/src/org/apache/fop/layout/FontInfo.java +++ b/src/org/apache/fop/layout/FontInfo.java @@ -73,6 +73,10 @@ public class FontInfo { return this.triplets.get(key) != null; } + public boolean hasFont(String key) { + return this.triplets.get(key) != null; + } + /** * Creates a key from the given strings */ diff --git a/src/org/apache/fop/layout/FontState.java b/src/org/apache/fop/layout/FontState.java index 498db1000..b8a746067 100644 --- a/src/org/apache/fop/layout/FontState.java +++ b/src/org/apache/fop/layout/FontState.java @@ -8,9 +8,11 @@ package org.apache.fop.layout; import java.util.Hashtable; +import java.util.StringTokenizer; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.FontVariant; +import org.apache.fop.render.pdf.CodePointMapping; public class FontState { @@ -23,6 +25,7 @@ public class FontState { private int _fontVariant; private FontMetric _metric; + private int _letterSpacing; private static Hashtable EMPTY_HASHTABLE = new Hashtable(); @@ -35,15 +38,74 @@ public class FontState { _fontStyle = fontStyle; _fontWeight = fontWeight; _fontSize = fontSize; - _fontName = fontInfo.fontLookup(fontFamily, fontStyle, fontWeight); + String _fontKey = FontInfo.createFontKey(_fontFamily, _fontStyle, _fontWeight); + //Quick check-out for simple font family + if (!fontInfo.hasFont(_fontKey)) { + //Tokenizes font-family list + StringTokenizer st = new StringTokenizer(_fontFamily, ","); + while (st.hasMoreTokens()) { + String token = st.nextToken().trim(); + //Checks for quoted font family name + if (token.charAt(0) == '"' || token.charAt(0) == '\'') + token = token.substring(1, token.length()-1); + else { + //In a nonquoted font family name any sequence of whitespace + //inside should be converted to a single space + StringBuffer sb = new StringBuffer(); + boolean spaced = false; + for (int i=0; i<token.length(); i++) { + char c = token.charAt(i); + if (!isWhitespace(c)) { + sb.append(c); + spaced = false; + } + else if (!spaced) { + sb.append(c); + spaced = true; + } + } + token = sb.toString(); + } + //Checks found font family name for existence + _fontKey = FontInfo.createFontKey(token, _fontStyle, _fontWeight); + if (fontInfo.hasFont(_fontKey)) { + _fontFamily = token; + break; + } + } + } + _fontName = fontInfo.fontLookup(_fontKey); _metric = fontInfo.getMetricsFor(_fontName); _fontVariant = fontVariant; + _letterSpacing = 0; + } + + public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, + String fontWeight, int fontSize, + int fontVariant, int letterSpacing) throws FOPException { + this(fontInfo, fontFamily, fontStyle, fontWeight, fontSize, + fontVariant); + _letterSpacing = letterSpacing; + } + + private static boolean isWhitespace(char ch) { + return (ch <= 0x0020) && + (((((1L << 0x0009) | + (1L << 0x000A) | + (1L << 0x000C) | + (1L << 0x000D) | + (1L << 0x0020)) >> ch) & 1L) != 0); } public int getAscender() { return _metric.getAscender(_fontSize) / 1000; } + public int getLetterSpacing() { + return _letterSpacing; + } + + public int getCapHeight() { return _metric.getCapHeight(_fontSize) / 1000; } @@ -95,7 +157,7 @@ public class FontState { public int width(int charnum) { // returns width of given character number in millipoints - return (_metric.width(charnum, _fontSize) / 1000); + return _letterSpacing + (_metric.width(charnum, _fontSize) / 1000); } /** @@ -106,17 +168,17 @@ public class FontState { if (_metric instanceof org.apache.fop.render.pdf.Font) { return ((org.apache.fop.render.pdf.Font)_metric).mapChar(c); + } else if (_metric instanceof org.apache.fop.render.awt.FontMetricsMapper) { + return c; } // Use default CodePointMapping - if (c > 127) { - char d = org.apache.fop.render.pdf.CodePointMapping.map[c]; - if (d != 0) { - c = d; - } else { - c = '#'; - } - } + char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c); + if (d != 0) { + c = d; + } else { + c = '#'; + } return c; } diff --git a/src/org/apache/fop/layout/LineArea.java b/src/org/apache/fop/layout/LineArea.java index 6c1c68429..41544b8a4 100644 --- a/src/org/apache/fop/layout/LineArea.java +++ b/src/org/apache/fop/layout/LineArea.java @@ -71,6 +71,7 @@ public class LineArea extends Area { protected static final int NOTHING = 0; protected static final int WHITESPACE = 1; protected static final int TEXT = 2; + protected static final int MULTIBYTECHAR = 3; /* the character type of the previous character */ protected int prev = NOTHING; @@ -210,6 +211,7 @@ public class LineArea extends Area { System.arraycopy(odata, 0, dataCopy, 0, odata.length); boolean isText = false; + boolean isMultiByteChar = false; /* iterate over each character */ for (int i = start; i < end; i++) { @@ -220,6 +222,7 @@ public class LineArea extends Area { || (c == '\u2028'))) { charWidth = getCharWidth(c); isText = true; + isMultiByteChar = (c > 127); // Add support for zero-width spaces if (charWidth <= 0 && c != '\u200B' && c != '\uFEFF') charWidth = whitespaceWidth; @@ -230,6 +233,7 @@ public class LineArea extends Area { charWidth = getCharWidth(c); isText = false; + isMultiByteChar = false; if (prev == WHITESPACE) { @@ -268,7 +272,7 @@ public class LineArea extends Area { return i + 1; } - } else if (prev == TEXT) { + } else if (prev == TEXT || prev == MULTIBYTECHAR ) { // if current is WHITESPACE and previous TEXT // the current word made it, so @@ -339,7 +343,7 @@ public class LineArea extends Area { spaceWidth = getCharWidth(c); /* - * here is the place for space-treatment value 'ignore': + * here is the place for white-space-treatment value 'ignore': * if (this.spaceTreatment == * SpaceTreatment.IGNORE) { * // do nothing @@ -388,6 +392,7 @@ public class LineArea extends Area { if (isText) { // current is TEXT + int curr = isMultiByteChar ? MULTIBYTECHAR : TEXT; if (prev == WHITESPACE) { // if current is TEXT and previous WHITESPACE @@ -401,15 +406,74 @@ public class LineArea extends Area { return i; } } - prev = TEXT; + prev = curr; wordStart = i; wordLength = 1; - } else if (prev == TEXT) { - wordLength++; - wordWidth += charWidth; + } else if (prev == TEXT || prev == MULTIBYTECHAR ) { + if ( prev == TEXT && curr == TEXT || ! canBreakMidWord()) { + wordLength++; + wordWidth += charWidth; + } else { + +// if (spaceWidth > 0) { // for text-align="justify" + InlineSpace is = new InlineSpace(spaceWidth); + if (prevUlState) { + is.setUnderlined(textState.getUnderlined()); + } + if (prevOlState) { + is.setOverlined(textState.getOverlined()); + } + if (prevLTState) { + is.setLineThrough(textState.getLineThrough()); + } + addChild(is); + finalWidth += spaceWidth; + spaceWidth = 0; +// } + + // add any pending areas + + Enumeration e = pendingAreas.elements(); + while (e.hasMoreElements()) { + Box box = (Box)e.nextElement(); + if (box instanceof InlineArea) { + if (ls != null) { + Rectangle lr = + new Rectangle(finalWidth, 0, + ((InlineArea)box).getContentWidth(), + fontState.getFontSize()); + ls.addRect(lr, this, (InlineArea)box); + } + } + addChild(box); + } + + finalWidth += pendingWidth; + + // reset pending areas array + pendingWidth = 0; + pendingAreas = new Vector(); + + // add the current word + + if (wordLength > 0) { + // The word might contain nonbreaking + // spaces. Split the word and add InlineSpace + // as necessary. All spaces inside the word + // Have a fixed width. + addSpacedWord(new String(data, wordStart, wordLength), + ls, finalWidth, 0, textState, false); + finalWidth += wordWidth; + } + spaceWidth = 0; + wordStart = i; + wordLength = 1; + wordWidth = charWidth; + } + prev = curr; } else { // nothing previous - prev = TEXT; + prev = curr; wordStart = i; wordLength = 1; wordWidth = charWidth; @@ -419,7 +483,7 @@ public class LineArea extends Area { > this.getContentWidth()) { // BREAK MID WORD - if (canBreakMidWord()) { +/* if (canBreakMidWord()) { addSpacedWord(new String(data, wordStart, wordLength - 1), ls, finalWidth + spaceWidth @@ -429,7 +493,7 @@ public class LineArea extends Area { wordWidth = 0; return i; } - +*/ if (this.wrapOption == WrapOption.WRAP) { if (hyphProps.hyphenate == Hyphenate.TRUE) { @@ -476,7 +540,7 @@ public class LineArea extends Area { } } // end of iteration over text - if (prev == TEXT) { + if (prev == TEXT || prev == MULTIBYTECHAR) { if (spaceWidth > 0) { InlineSpace pis = new InlineSpace(spaceWidth); @@ -529,8 +593,7 @@ public class LineArea extends Area { int whitespaceWidth = currentFontState.width(currentFontState.mapChar(whitespaceIndex)); - int remainingWidth = this.getContentWidth() - - this.getCurrentXPosition(); + int remainingWidth = this.getRemainingWidth(); /** * checks whether leaderLenghtOptimum fits into rest of line; @@ -948,14 +1011,15 @@ public class LineArea extends Area { // we will only handle hard hyphens and slashes if (getWordWidth(wordToHyphenate) < remainingWidth) { inwordPunctuation = - characters[wordStart + wordToHyphenate.length()]; + characters[wordStart + remainingString.length() + + wordToHyphenate.length()]; if (inwordPunctuation == '-' || inwordPunctuation == '/') { preString = new StringBuffer(wordToHyphenate); preString = preString.append(inwordPunctuation); wordToHyphenate = getHyphenationWord(characters, - wordStart + wordToHyphenate.length() - + 1); + wordStart + remainingString.length() + + wordToHyphenate.length() + 1); remainingWidth -= (getWordWidth(wordToHyphenate) + this.currentFontState.width(currentFontState.mapChar(inwordPunctuation))); @@ -1030,7 +1094,7 @@ public class LineArea extends Area { } public int getRemainingWidth() { - return this.getContentWidth() - this.getCurrentXPosition(); + return this.getContentWidth() + startIndent - this.getCurrentXPosition(); } public void setLinkSet(LinkSet ls) {} @@ -1053,8 +1117,7 @@ public class LineArea extends Area { */ public int addCharacter(char data, LinkSet ls, boolean ul) { WordArea ia = null; - int remainingWidth = this.getContentWidth() - - this.getCurrentXPosition(); + int remainingWidth = this.getRemainingWidth(); int width = this.currentFontState.width(currentFontState.mapChar(data)); // if it doesn't fit, return @@ -1172,51 +1235,53 @@ public class LineArea extends Area { * versions of space that might not exists in the font. */ private int getCharWidth(char c) { - int width = currentFontState.width(currentFontState.mapChar(c)); - if (width <= 0) { - // Estimate the width of spaces not represented in - // the font - int em = currentFontState.width(currentFontState.mapChar('m')); - int en = currentFontState.width(currentFontState.mapChar('n')); - if (em <= 0) - em = 500 * currentFontState.getFontSize(); - if (en <= 0) - en = em - 10; - - if (c == ' ') - width = em; - if (c == '\u2000') - width = en; - if (c == '\u2001') - width = em; - if (c == '\u2002') - width = em / 2; - if (c == '\u2003') - width = currentFontState.getFontSize(); - if (c == '\u2004') - width = em / 3; - if (c == '\u2005') - width = em / 4; - if (c == '\u2006') - width = em / 6; - if (c == '\u2007') - width = getCharWidth(' '); - if (c == '\u2008') - width = getCharWidth('.'); - if (c == '\u2009') - width = em / 5; - if (c == '\u200A') - width = 5; - if (c == '\u200B') - width = 100; - if (c == '\u00A0') - width = getCharWidth(' '); - if (c == '\u202F') - width = getCharWidth(' ') / 2; - if (c == '\u3000') - width = getCharWidth(' ') * 2; - if ((c == '\n') || (c == '\r') || (c == '\t')) - width = getCharWidth(' '); + int width; + + if ((c == '\n') || (c == '\r') || (c == '\t') || (c == '\u00A0')) { + width = getCharWidth(' '); + } else { + width = currentFontState.width(currentFontState.mapChar(c)); + if (width <= 0) { + // Estimate the width of spaces not represented in + // the font + int em = currentFontState.width(currentFontState.mapChar('m')); + int en = currentFontState.width(currentFontState.mapChar('n')); + if (em <= 0) + em = 500 * currentFontState.getFontSize(); + if (en <= 0) + en = em - 10; + + if (c == ' ') + width = em; + if (c == '\u2000') + width = en; + if (c == '\u2001') + width = em; + if (c == '\u2002') + width = em / 2; + if (c == '\u2003') + width = currentFontState.getFontSize(); + if (c == '\u2004') + width = em / 3; + if (c == '\u2005') + width = em / 4; + if (c == '\u2006') + width = em / 6; + if (c == '\u2007') + width = getCharWidth(' '); + if (c == '\u2008') + width = getCharWidth('.'); + if (c == '\u2009') + width = em / 5; + if (c == '\u200A') + width = 5; + if (c == '\u200B') + width = 100; + if (c == '\u202F') + width = getCharWidth(' ') / 2; + if (c == '\u3000') + width = getCharWidth(' ') * 2; + } } return width; diff --git a/src/org/apache/fop/layout/RegionArea.java b/src/org/apache/fop/layout/RegionArea.java index 7e7465448..23bd824fa 100644 --- a/src/org/apache/fop/layout/RegionArea.java +++ b/src/org/apache/fop/layout/RegionArea.java @@ -17,7 +17,7 @@ public class RegionArea { protected int width; protected int height; - protected ColorType backgroundColor; + protected BackgroundProps background; public RegionArea(int xPosition, int yPosition, int width, int height) { this.xPosition = xPosition; @@ -27,16 +27,19 @@ public class RegionArea { } public AreaContainer makeAreaContainer() { - return new AreaContainer(null, xPosition, yPosition, width, height, - Position.ABSOLUTE); + AreaContainer area = + new AreaContainer(null, xPosition, yPosition, width, height, + Position.ABSOLUTE); + area.setBackground(getBackground()); + return area; } - public ColorType getBackgroundColor() { - return this.backgroundColor; + public BackgroundProps getBackground() { + return this.background; } - public void setBackgroundColor(ColorType bgColor) { - this.backgroundColor = bgColor; + public void setBackground(BackgroundProps bg) { + this.background = bg; } public int getHeight() { diff --git a/src/org/apache/fop/messaging/MessageHandler.java b/src/org/apache/fop/messaging/MessageHandler.java index b9229f897..c6eecfd6c 100644 --- a/src/org/apache/fop/messaging/MessageHandler.java +++ b/src/org/apache/fop/messaging/MessageHandler.java @@ -7,11 +7,12 @@ package org.apache.fop.messaging; +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; + import java.io.*; import java.util.*; -import org.apache.log.*; - /** * The class MessageHandler contains the static methods log and error which * should be used for any end user information instead of System.out.print() or @@ -47,6 +48,7 @@ public class MessageHandler { public static final int EVENT = 2; public static final int NONE = 3; // this should always be the last method + private static Logger logger = null; private static String logfileName = "fop.log"; private static PrintWriter writer; private static int outputMethod = SCREEN; @@ -80,47 +82,47 @@ public class MessageHandler { } } - // temp workaround - private static Logger logger = null; - /** * informs the user of the message * @param message the message for the user */ public static void log(String message) { - if (!quiet) { - if(logger == null) { - logger = Hierarchy.getDefaultHierarchy().getLoggerFor("fop"); - } - setMessage(message); - switch (outputMethod) { - case SCREEN: - logger.debug(getMessage()); - break; - case FILE: - if (fileOpened) { - writer.print(getMessage()); - writer.flush(); - } else { - openFile(); - writer.print(getMessage()); - writer.flush(); - } - break; - case EVENT: - setMessage(message); - Enumeration enum = listeners.elements(); - while (enum.hasMoreElements()) { - ((MessageListener)enum.nextElement()).processMessage(new MessageEvent(getMessage())); - } - break; - case NONE: - // do nothing - break; - default: - logger.debug(message); - } - } + if (quiet) + return; + + if (logger == null) { + logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO); + logger.warn("Screen logger not set."); + } + + setMessage(message); + switch (outputMethod) { + case SCREEN: + logger.debug(getMessage()); + break; + case FILE: + if (fileOpened) { + writer.print(getMessage()); + writer.flush(); + } else { + openFile(); + writer.print(getMessage()); + writer.flush(); + } + break; + case EVENT: + setMessage(message); + Enumeration enum = listeners.elements(); + while (enum.hasMoreElements()) { + ((MessageListener)enum.nextElement()).processMessage(new MessageEvent(getMessage())); + } + break; + case NONE: + // do nothing + break; + default: + logger.debug(message); + } } /** @@ -137,9 +139,11 @@ public class MessageHandler { */ public static void error(String errorMessage) { - if(logger == null) { - logger = Hierarchy.getDefaultHierarchy().getLoggerFor("fop"); - } + if (logger == null) { + logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO); + logger.warn("Screen logger not set."); + } + setMessage(errorMessage); switch (outputMethod) { case SCREEN: @@ -197,6 +201,16 @@ public class MessageHandler { } /** + * Sets the Logger used for the screen output method. + * @param newLogger a logger for screen output. This may not be null. + */ + public static void setScreenLogger(Logger newLogger) { + if (newLogger == null) + throw new NullPointerException(); + logger = newLogger; + } + + /** * sets the output method * @param method the output method to use, allowed values are<br> * MessageHandler.SCREEN, MessageHandler.FILE, MessageHandler.EVENT diff --git a/src/org/apache/fop/mif/MIFDocument.java b/src/org/apache/fop/mif/MIFDocument.java index ea4a16277..6a584aee3 100644 --- a/src/org/apache/fop/mif/MIFDocument.java +++ b/src/org/apache/fop/mif/MIFDocument.java @@ -47,6 +47,55 @@ public class MIFDocument { // a table private ID curIDCounter = new ID(); + public final static String MIFEncode(String val) { + int len = val.length(); + StringBuffer buf = new StringBuffer(len * 2); + char c; + + for(int i = 0; i < len; i++) { + c = val.charAt(i); + switch(c) { + case '\u00e0': buf.append("\\x88 "); break; + case '\u00e8': buf.append("\\x8f "); break; + case '\u00ec': buf.append("\\x93 "); break; + case '\u00f2': buf.append("\\x98 "); break; + case '\u00f9': buf.append("\\x9d "); break; + case '\u00c0': buf.append("\\xcb "); break; + case '\u00c8': buf.append("\\xe9 "); break; + case '\u00cc': buf.append("\\xed "); break; + case '\u00d2': buf.append("\\xf1 "); break; + case '\u00d9': buf.append("\\xf4 "); break; + + case '\u00e1': buf.append("\\x87 "); break; + case '\u00e9': buf.append("\\x8e "); break; + case '\u00ed': buf.append("\\x92 "); break; + case '\u00f3': buf.append("\\x97 "); break; + case '\u00fa': buf.append("\\x9c "); break; + case '\u00c1': buf.append("\\xe7 "); break; + case '\u00c9': buf.append("\\x83 "); break; + case '\u00cd': buf.append("\\xea "); break; + case '\u00d3': buf.append("\\xee "); break; + case '\u00da': buf.append("\\xf2 "); break; + + case '\u00f1': buf.append("\\x96 "); break; + case '\u00d1': buf.append("\\x84 "); break; + + case '\u00e7': buf.append("\\x8d "); break; + case '\u00c7': buf.append("\\x82 "); break; + + case '`': buf.append("\\xd4 "); break; + case '\'': buf.append("\\xd5 "); break; + case '\u00b4': buf.append("\\xab "); break; + case '\u00aa': buf.append("\\xbb "); break; + case '\u00ba': buf.append("\\xbc "); break; + + case '>': buf.append("\\>"); break; + default: buf.append(c); + } + } + return buf.toString(); + } + class ID { private int idCounter = 1; @@ -299,6 +348,12 @@ public class MIFDocument { public TextRect curTextRect() { + //temporary fix for NoSuchElementException + if (textRects.isEmpty()) { + TextRect textRect = new TextRect(1); + this.textRects.addElement(textRect); + } + return (TextRect)textRects.lastElement(); } @@ -505,7 +560,7 @@ public class MIFDocument { mif = "\n<Char HardReturn>"; } else { - mif = "\n\t<String `" + elem + "'>"; + mif = "\n\t<String `" + MIFEncode((String)elem) + "'>"; } stream.write(mif.getBytes()); diff --git a/src/org/apache/fop/pdf/ASCII85Filter.java b/src/org/apache/fop/pdf/ASCII85Filter.java index 40706e968..7c8e43cb8 100644 --- a/src/org/apache/fop/pdf/ASCII85Filter.java +++ b/src/org/apache/fop/pdf/ASCII85Filter.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; public class ASCII85Filter extends PDFFilter { private static final char ASCII85_ZERO = 'z'; @@ -87,13 +88,15 @@ public class ASCII85Filter extends PDFFilter { } // finally write the two character end of data marker - buffer.write(ASCII85_EOD.getBytes(), 0, - ASCII85_EOD.getBytes().length); - - + byte[] eod; + try { + eod = ASCII85_EOD.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + eod = ASCII85_EOD.getBytes(); + } + buffer.write(eod, 0, eod.length); byte[] result = buffer.toByteArray(); - // assert that we have the correct outgoing length /* * int in = (data.length % 4); diff --git a/src/org/apache/fop/pdf/ASCIIHexFilter.java b/src/org/apache/fop/pdf/ASCIIHexFilter.java index 775a7fcb4..d7c93674e 100644 --- a/src/org/apache/fop/pdf/ASCIIHexFilter.java +++ b/src/org/apache/fop/pdf/ASCIIHexFilter.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; public class ASCIIHexFilter extends PDFFilter { private static final String ASCIIHEX_EOD = ">"; @@ -32,8 +33,11 @@ public class ASCIIHexFilter extends PDFFilter { } buffer.append(ASCIIHEX_EOD); - return buffer.toString().getBytes(); - + try { + return buffer.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return buffer.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFAnnotList.java b/src/org/apache/fop/pdf/PDFAnnotList.java index 1a23d85d5..3c509073b 100644 --- a/src/org/apache/fop/pdf/PDFAnnotList.java +++ b/src/org/apache/fop/pdf/PDFAnnotList.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; // Java +import java.io.UnsupportedEncodingException; import java.util.Vector; /** @@ -71,7 +72,12 @@ public class PDFAnnotList extends PDFObject { + "\n"); } p = p.append("]\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } /* diff --git a/src/org/apache/fop/pdf/PDFArray.java b/src/org/apache/fop/pdf/PDFArray.java index 243c19f09..ad0240248 100644 --- a/src/org/apache/fop/pdf/PDFArray.java +++ b/src/org/apache/fop/pdf/PDFArray.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +//Java +import java.io.UnsupportedEncodingException; + /** * class representing an array object */ @@ -42,7 +45,12 @@ public class PDFArray extends PDFObject { p.append(values[i]); } p.append("]\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFCIDFont.java b/src/org/apache/fop/pdf/PDFCIDFont.java index 5323996bb..b97bf97d3 100644 --- a/src/org/apache/fop/pdf/PDFCIDFont.java +++ b/src/org/apache/fop/pdf/PDFCIDFont.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + // based on work by Takayuki Takeuchi /** @@ -147,7 +150,11 @@ public class PDFCIDFont extends PDFObject { * @return the PDF */ public byte[] toPDF() { - return toPDFString().getBytes(); + try { + return toPDFString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return toPDFString().getBytes(); + } } public String toPDFString() { diff --git a/src/org/apache/fop/pdf/PDFCIDSystemInfo.java b/src/org/apache/fop/pdf/PDFCIDSystemInfo.java index 7104fd9d7..dc538c01f 100644 --- a/src/org/apache/fop/pdf/PDFCIDSystemInfo.java +++ b/src/org/apache/fop/pdf/PDFCIDSystemInfo.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + // based on work by Takayuki Takeuchi /** @@ -36,7 +39,11 @@ public class PDFCIDSystemInfo extends PDFObject { * @return the PDF */ public byte[] toPDF() { - return toPDFString().getBytes(); + try { + return toPDFString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return toPDFString().getBytes(); + } } public String toPDFString() { diff --git a/src/org/apache/fop/pdf/PDFDocument.java b/src/org/apache/fop/pdf/PDFDocument.java index cdf039b9f..13cc5fdea 100644 --- a/src/org/apache/fop/pdf/PDFDocument.java +++ b/src/org/apache/fop/pdf/PDFDocument.java @@ -27,6 +27,7 @@ import org.apache.fop.layout.FontDescriptor; // Java import java.io.IOException; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.util.Vector; import java.util.Hashtable; import java.util.Enumeration; @@ -155,8 +156,13 @@ public class PDFDocument { protected Vector pendingLinks = null; /** + * Encoding of the PDF + */ + public static final String ENCODING = "ISO-8859-1"; + + /** * creates an empty PDF document <p> - * + * * The constructor creates a /Root and /Pages object to * track the document but does not write these objects until * the trailer is written. Note that the object ID of the @@ -761,6 +767,12 @@ public class PDFDocument { } + public PDFICCStream makePDFICCStream() { + PDFICCStream iccStream = new PDFICCStream(++this.objectcount); + this.objects.add(iccStream); + return iccStream; + } + /** * make a Type1 /Font object * @@ -918,8 +930,7 @@ public class PDFDocument { if (xObject != null) return xObject.getXNumber(); // else, create a new one - xObject = new PDFXObject(++this.objectcount, ++this.xObjectCount, - img); + xObject = new PDFXObject(++this.objectcount, ++this.xObjectCount, img, this); this.objects.addElement(xObject); this.xObjects.addElement(xObject); this.xObjectsMap.put(url, xObject); @@ -1033,8 +1044,8 @@ public class PDFDocument { //next line by lmckenzi@ca.ibm.com //solves when IDNode made before IDReferences.createID called //idReferences.createNewId(destination); - - idReferences.createUnvalidatedID(destination); + + idReferences.createUnvalidatedID(destination); idReferences.addToIdValidationList(destination); goToReference = idReferences.createInternalLinkGoTo(destination, ++this.objectcount); @@ -1213,7 +1224,12 @@ public class PDFDocument { throws IOException { this.position=0; - byte[] pdf = ("%PDF-" + this.pdfVersion + "\n").getBytes(); + byte[] pdf; + try { + pdf = ("%PDF-" + this.pdfVersion + "\n").getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdf = ("%PDF-" + this.pdfVersion + "\n").getBytes(); + } stream.write(pdf); this.position += pdf.length; @@ -1260,7 +1276,13 @@ public class PDFDocument { "%%EOF\n"; /* write the trailer */ - stream.write(pdf.getBytes()); + byte[] trailer; + try { + trailer = pdf.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + trailer = pdf.getBytes(); + } + stream.write(trailer); } /** @@ -1292,7 +1314,12 @@ public class PDFDocument { } /* write the xref table and return the character length */ - byte[] pdfBytes = pdf.toString().getBytes(); + byte[] pdfBytes; + try { + pdfBytes = pdf.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdfBytes = pdf.toString().getBytes(); + } stream.write(pdfBytes); return pdfBytes.length; } diff --git a/src/org/apache/fop/pdf/PDFEncoding.java b/src/org/apache/fop/pdf/PDFEncoding.java index 68151bdfd..933896960 100644 --- a/src/org/apache/fop/pdf/PDFEncoding.java +++ b/src/org/apache/fop/pdf/PDFEncoding.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; // Java +import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; @@ -106,7 +107,12 @@ public class PDFEncoding extends PDFObject { p.append(" ]"); } p.append(" >>\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } /* diff --git a/src/org/apache/fop/pdf/PDFFileSpec.java b/src/org/apache/fop/pdf/PDFFileSpec.java index d7c5338d0..3ea5a38b9 100644 --- a/src/org/apache/fop/pdf/PDFFileSpec.java +++ b/src/org/apache/fop/pdf/PDFFileSpec.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a /FileSpec object. * @@ -41,7 +44,12 @@ public class PDFFileSpec extends PDFObject { String p = new String(this.number + " " + this.generation + " obj\n<<\n/Type /FileSpec\n" + "/F (" + this.filename + ")\n" + ">>\nendobj\n"); - return p.getBytes(); + + try { + return p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.getBytes(); + } } /* diff --git a/src/org/apache/fop/pdf/PDFFont.java b/src/org/apache/fop/pdf/PDFFont.java index 3d1c2ec05..360f7e2f8 100644 --- a/src/org/apache/fop/pdf/PDFFont.java +++ b/src/org/apache/fop/pdf/PDFFont.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a /Font object. * @@ -218,7 +221,12 @@ public class PDFFont extends PDFObject { } fillInPDF(p); p.append(" >>\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } /** diff --git a/src/org/apache/fop/pdf/PDFFontDescriptor.java b/src/org/apache/fop/pdf/PDFFontDescriptor.java index 203879b35..c99de0581 100644 --- a/src/org/apache/fop/pdf/PDFFontDescriptor.java +++ b/src/org/apache/fop/pdf/PDFFontDescriptor.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a font descriptor. * @@ -162,7 +165,12 @@ public class PDFFontDescriptor extends PDFObject { // CID optional field fillInPDF(p); p.append("\n >>\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } /** diff --git a/src/org/apache/fop/pdf/PDFFunction.java b/src/org/apache/fop/pdf/PDFFunction.java index 185addc9e..b17320f47 100644 --- a/src/org/apache/fop/pdf/PDFFunction.java +++ b/src/org/apache/fop/pdf/PDFFunction.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; // Java... import java.util.Vector; +import java.io.UnsupportedEncodingException; /** * class representing a PDF Function. @@ -663,8 +664,11 @@ public class PDFFunction extends PDFObject { } - return (p.toString().getBytes()); - + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFGoTo.java b/src/org/apache/fop/pdf/PDFGoTo.java index f8dd65a8e..8bcb5a0b7 100644 --- a/src/org/apache/fop/pdf/PDFGoTo.java +++ b/src/org/apache/fop/pdf/PDFGoTo.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a /GoTo object. * @@ -91,7 +94,12 @@ public class PDFGoTo extends PDFAction { String p = new String(this.number + " " + this.generation + " obj\n<<\n/S /GoTo\n" + destination + ">>\nendobj\n"); - return p.getBytes(); + + try { + return p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.getBytes(); + } } /* diff --git a/src/org/apache/fop/pdf/PDFGoToRemote.java b/src/org/apache/fop/pdf/PDFGoToRemote.java index aa8ef5afa..c23862602 100644 --- a/src/org/apache/fop/pdf/PDFGoToRemote.java +++ b/src/org/apache/fop/pdf/PDFGoToRemote.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a /GoToR object. */ @@ -51,7 +54,12 @@ public class PDFGoToRemote extends PDFAction { + pdfFileSpec.referencePDF() + "\n" + "/D [ 0 /XYZ null null null ]" + " \n>>\nendobj\n"); - return p.getBytes(); + + try { + return p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.getBytes(); + } } diff --git a/src/org/apache/fop/pdf/PDFICCStream.java b/src/org/apache/fop/pdf/PDFICCStream.java new file mode 100644 index 000000000..9462eb8dc --- /dev/null +++ b/src/org/apache/fop/pdf/PDFICCStream.java @@ -0,0 +1,72 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.pdf; + +// Java +import java.io.UnsupportedEncodingException; +// Fop +import org.apache.fop.datatypes.ColorSpace; + +public class PDFICCStream extends PDFStream { + private int origLength; + private int len1, len3; + private byte[] originalData = null; + + private ColorSpace cs; + + public void setColorSpace(ColorSpace cs) throws java.io.IOException { + this.cs = cs; + setData(cs.getICCProfile()); + } + + public PDFICCStream(int num) { + super(num); + cs = null; + } + + public PDFICCStream(int num, ColorSpace cs) throws java.io.IOException { + super(num); + setColorSpace(cs); + } + + // overload the base object method so we don't have to copy + // byte arrays around so much + protected int output(java.io.OutputStream stream) + throws java.io.IOException { + int length = 0; + String filterEntry = applyFilters(); + StringBuffer pb = new StringBuffer(); + pb.append(this.number).append(" ").append(this.generation).append(" obj\n<< "); + pb.append("/N ").append(cs.getNumComponents()).append(" "); + + if (cs.getColorSpace() > 0) + pb.append("/Alternate /").append(cs.getColorSpacePDFString()).append(" "); + + pb.append("/Length ").append((_data.size() + 1)).append(" ").append(filterEntry); + pb.append(" >>\n"); + byte[] p; + try { + p = pb.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = pb.toString().getBytes(); + } + stream.write(p); + length += p.length; + length += outputStreamData(stream); + try { + p = "endobj\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "endobj\n".getBytes(); + } + stream.write(p); + length += p.length; + return length; + } + + +} diff --git a/src/org/apache/fop/pdf/PDFInfo.java b/src/org/apache/fop/pdf/PDFInfo.java index a8215fcea..8e346d80a 100644 --- a/src/org/apache/fop/pdf/PDFInfo.java +++ b/src/org/apache/fop/pdf/PDFInfo.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; // Java import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.io.PrintWriter; /** @@ -48,7 +49,11 @@ public class PDFInfo extends PDFObject { String p = this.number + " " + this.generation + " obj\n<< /Type /Info\n/Producer (" + this.producer + ") >>\nendobj\n"; - return p.getBytes(); + try { + return p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFLink.java b/src/org/apache/fop/pdf/PDFLink.java index 6af94f1d8..f839a9a0a 100644 --- a/src/org/apache/fop/pdf/PDFLink.java +++ b/src/org/apache/fop/pdf/PDFLink.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; // Java import java.awt.Rectangle; +import java.io.UnsupportedEncodingException; /** * class representing an /Annot object of /Subtype /Link @@ -56,7 +57,12 @@ public class PDFLink extends PDFObject { + (brx / 1000f) + " " + (bry / 1000f) + " ]\n" + "/C [ " + this.color + " ]\n" + "/Border [ 0 0 0 ]\n" + "/A " + this.action.getAction() + "\n" + "/H /I\n>>\nendobj\n"; - return p.getBytes(); + + try { + return p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.getBytes(); + } } /* diff --git a/src/org/apache/fop/pdf/PDFOutline.java b/src/org/apache/fop/pdf/PDFOutline.java index 48e281b81..1d280fedb 100644 --- a/src/org/apache/fop/pdf/PDFOutline.java +++ b/src/org/apache/fop/pdf/PDFOutline.java @@ -7,6 +7,8 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; import java.util.Vector; @@ -142,8 +144,12 @@ public class PDFOutline extends PDFObject { } result.append(">> endobj\n"); - return result.toString().getBytes(); + try { + return result.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return result.toString().getBytes(); + } } /** diff --git a/src/org/apache/fop/pdf/PDFPage.java b/src/org/apache/fop/pdf/PDFPage.java index 8fce26098..19e3ab135 100644 --- a/src/org/apache/fop/pdf/PDFPage.java +++ b/src/org/apache/fop/pdf/PDFPage.java @@ -7,6 +7,8 @@ package org.apache.fop.pdf; +import java.io.UnsupportedEncodingException; + /** * class representing a /Page object. * @@ -129,7 +131,11 @@ public class PDFPage extends PDFObject { sb = sb.append(">>\nendobj\n"); - return sb.toString().getBytes(); + try { + return sb.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return sb.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFPages.java b/src/org/apache/fop/pdf/PDFPages.java index 4035fc2eb..9274fdda6 100644 --- a/src/org/apache/fop/pdf/PDFPages.java +++ b/src/org/apache/fop/pdf/PDFPages.java @@ -9,8 +9,10 @@ package org.apache.fop.pdf; // Java import java.io.PrintWriter; -import org.apache.fop.messaging.MessageHandler; +import java.io.UnsupportedEncodingException; import java.util.Vector; +// Fop +import org.apache.fop.messaging.MessageHandler; /** * class representing a /Pages object. @@ -88,7 +90,12 @@ public class PDFPages extends PDFObject { p = p.append(kids.elementAt(i) + " "); } p = p.append("] >>\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFPattern.java b/src/org/apache/fop/pdf/PDFPattern.java index 3fa15d59b..cc1c5dbcf 100644 --- a/src/org/apache/fop/pdf/PDFPattern.java +++ b/src/org/apache/fop/pdf/PDFPattern.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; // Java... +import java.io.UnsupportedEncodingException; import java.util.Vector; // FOP... @@ -288,10 +289,11 @@ public class PDFPattern extends PDFPathPaint { p.append("endobj\n"); - - - return (p.toString().getBytes()); - + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFRectangle.java b/src/org/apache/fop/pdf/PDFRectangle.java index 2dc04fb74..b89e9a451 100644 --- a/src/org/apache/fop/pdf/PDFRectangle.java +++ b/src/org/apache/fop/pdf/PDFRectangle.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + /** * class representing a rectangle * @@ -67,7 +70,11 @@ public class PDFRectangle { * @return the PDF */ public byte[] toPDF() { - return toPDFString().getBytes(); + try { + return toPDFString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return toPDFString().getBytes(); + } } public String toPDFString() { diff --git a/src/org/apache/fop/pdf/PDFResources.java b/src/org/apache/fop/pdf/PDFResources.java index d51b716e4..45602cb22 100644 --- a/src/org/apache/fop/pdf/PDFResources.java +++ b/src/org/apache/fop/pdf/PDFResources.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; // Java import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Vector; import java.util.Hashtable; @@ -138,7 +139,11 @@ public class PDFResources extends PDFObject { p = p.append(">> \nendobj\n"); - return p.toString().getBytes(); + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFRoot.java b/src/org/apache/fop/pdf/PDFRoot.java index 8741bd519..edd6bdda3 100644 --- a/src/org/apache/fop/pdf/PDFRoot.java +++ b/src/org/apache/fop/pdf/PDFRoot.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; // Java import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.io.PrintWriter; /** @@ -96,7 +97,12 @@ public class PDFRoot extends PDFObject { } p.append(" >>\nendobj\n"); - return p.toString().getBytes(); + + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFShading.java b/src/org/apache/fop/pdf/PDFShading.java index a1a1a9be0..8d5b1f208 100644 --- a/src/org/apache/fop/pdf/PDFShading.java +++ b/src/org/apache/fop/pdf/PDFShading.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; // Java... +import java.io.UnsupportedEncodingException; import java.util.Vector; // FOP @@ -505,7 +506,11 @@ public class PDFShading extends PDFObject { p.append(">> \nendobj\n"); - return (p.toString().getBytes()); + try { + return p.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return p.toString().getBytes(); + } } } diff --git a/src/org/apache/fop/pdf/PDFStream.java b/src/org/apache/fop/pdf/PDFStream.java index 01b87b9d6..56d1e3af5 100644 --- a/src/org/apache/fop/pdf/PDFStream.java +++ b/src/org/apache/fop/pdf/PDFStream.java @@ -7,11 +7,14 @@ package org.apache.fop.pdf; +// Java import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.Vector; import java.util.Enumeration; +// Fop import org.apache.fop.configuration.Configuration; import org.apache.fop.messaging.MessageHandler; @@ -53,7 +56,11 @@ public class PDFStream extends PDFObject { */ public void add(String s) { try { - _data.write(s.getBytes()); + try { + _data.write(s.getBytes(PDFDocument.ENCODING)); + } catch (UnsupportedEncodingException ue) { + _data.write(s.getBytes()); + } } catch (IOException ex) { ex.printStackTrace(); } @@ -133,19 +140,35 @@ public class PDFStream extends PDFObject { if (r < 16) { _data.write('0'); } - _data.write(Integer.toHexString(r).getBytes()); + try { + _data.write(Integer.toHexString(r).getBytes(PDFDocument.ENCODING)); + } catch (UnsupportedEncodingException ue) { + _data.write(Integer.toHexString(r).getBytes()); + } if (g < 16) { _data.write('0'); } - _data.write(Integer.toHexString(g).getBytes()); + try { + _data.write(Integer.toHexString(g).getBytes(PDFDocument.ENCODING)); + } catch (UnsupportedEncodingException ue) { + _data.write(Integer.toHexString(g).getBytes()); + } if (b < 16) { _data.write('0'); } - _data.write(Integer.toHexString(b).getBytes()); + try { + _data.write(Integer.toHexString(b).getBytes(PDFDocument.ENCODING)); + } catch (UnsupportedEncodingException ue) { + _data.write(Integer.toHexString(b).getBytes()); + } _data.write(' '); } } - _data.write(">\n".getBytes()); + try { + _data.write(">\n".getBytes(PDFDocument.ENCODING)); + } catch (UnsupportedEncodingException ue) { + _data.write(">\n".getBytes()); + } } catch (IOException ex) { ex.printStackTrace(); } @@ -195,14 +218,23 @@ public class PDFStream extends PDFObject { protected int output(OutputStream stream) throws IOException { int length = 0; String filterEntry = applyFilters(); - byte[] p = (this.number + " " + this.generation + " obj\n<< /Length " + String s = this.number + " " + this.generation + " obj\n<< /Length " + (_data.size() + 1) + " " + filterEntry - + " >>\n").getBytes(); - + + " >>\n"; + byte[] p; + try { + p = s.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = s.getBytes(); + } stream.write(p); length += p.length; length += outputStreamData(stream); - p = "endobj\n".getBytes(); + try { + p = "endobj\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "endobj\n".getBytes(); + } stream.write(p); length += p.length; return length; @@ -214,12 +246,21 @@ public class PDFStream extends PDFObject { */ protected int outputStreamData(OutputStream stream) throws IOException { int length = 0; - byte[] p = "stream\n".getBytes(); + byte[] p; + try { + p = "stream\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "stream\n".getBytes(); + } stream.write(p); length += p.length; _data.writeTo(stream); length += _data.size(); - p = "\nendstream\n".getBytes(); + try { + p = "\nendstream\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "\nendstream\n".getBytes(); + } stream.write(p); length += p.length; return length; diff --git a/src/org/apache/fop/pdf/PDFT1Stream.java b/src/org/apache/fop/pdf/PDFT1Stream.java index 8de99f260..5588a0c01 100644 --- a/src/org/apache/fop/pdf/PDFT1Stream.java +++ b/src/org/apache/fop/pdf/PDFT1Stream.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + public class PDFT1Stream extends PDFStream { private int origLength; private int len1, len3; @@ -41,7 +44,12 @@ public class PDFT1Stream extends PDFStream { // Get the first binary number and search backwards for "eexec" len1 = 30; - byte[] eexec = (new String("currentfile eexec")).getBytes(); + byte[] eexec; + try { + eexec = "currentfile eexec".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + eexec = "currentfile eexec".getBytes(); + } // System.out.println("Length1="+len1); while (!byteCmp(originalData, len1 - eexec.length, eexec)) len1++; @@ -50,7 +58,13 @@ public class PDFT1Stream extends PDFStream { // Length3 is length of the last portion of the file len3 = 0; - byte[] cltom = (new String("cleartomark")).getBytes(); + byte[] cltom; + try { + cltom = "cleartomark".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + cltom = "cleartomark".getBytes(); + } + len3 -= cltom.length; while (!byteCmp(originalData, origLength + len3, cltom)) { len3--; @@ -60,9 +74,24 @@ public class PDFT1Stream extends PDFStream { len3++; // Eat 512 zeroes int numZeroes = 0; - byte[] ws1 = "\n".getBytes(); - byte[] ws2 = "\r".getBytes(); - byte[] ws3 = "0".getBytes(); + byte[] ws1; + try { + ws1 = "\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + ws1 = "\n".getBytes(); + } + byte[] ws2; + try { + ws2 = "\r".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + ws2 = "\r".getBytes(); + } + byte[] ws3; + try { + ws3 = "0".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + ws3 = "0".getBytes(); + } while ((originalData[origLength - len3] == ws1[0] || originalData[origLength - len3] == ws2[0] || originalData[origLength - len3] == ws3[0]) && numZeroes < 512) { len3++; @@ -85,15 +114,25 @@ public class PDFT1Stream extends PDFStream { + (origLength - len3 - len1) + " /Length3 " + len3 + " >>\n"); - byte[] p = preData.getBytes(); + byte[] p; + try { + p = preData.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = preData.getBytes(); + } + stream.write(p); length += p.length; length += outputStreamData(stream); - p = "endobj\n".getBytes(); + try { + p = "endobj\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "endobj\n".getBytes(); + } stream.write(p); length += p.length; - System.out.println("Embedded Type1 font"); + //System.out.println("Embedded Type1 font"); return length; } diff --git a/src/org/apache/fop/pdf/PDFTTFStream.java b/src/org/apache/fop/pdf/PDFTTFStream.java index f56e5f587..a6e894349 100644 --- a/src/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/org/apache/fop/pdf/PDFTTFStream.java @@ -7,6 +7,9 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; + public class PDFTTFStream extends PDFStream { private int origLength; @@ -27,12 +30,22 @@ public class PDFTTFStream extends PDFStream { + " " + "/Length1 " + origLength + " >>\n"); - byte[] p = preData.getBytes(); + byte[] p; + try { + p = preData.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = preData.getBytes(); + } + stream.write(p); length += p.length; length += outputStreamData(stream); - p = "endobj\n".getBytes(); + try { + p = "endobj\n".getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + p = "endobj\n".getBytes(); + } stream.write(p); length += p.length; return length; @@ -40,7 +53,7 @@ public class PDFTTFStream extends PDFStream { public void setData(byte[] data, int size) throws java.io.IOException { _data.reset(); - System.out.println("Writing " + size + " bytes of font data"); + //System.out.println("Writing " + size + " bytes of font data"); _data.write(data, 0, size); } diff --git a/src/org/apache/fop/pdf/PDFWArray.java b/src/org/apache/fop/pdf/PDFWArray.java index a391f45f3..da86f7d48 100644 --- a/src/org/apache/fop/pdf/PDFWArray.java +++ b/src/org/apache/fop/pdf/PDFWArray.java @@ -7,6 +7,8 @@ package org.apache.fop.pdf; +// Java +import java.io.UnsupportedEncodingException; import java.util.Vector; /** @@ -63,7 +65,11 @@ public class PDFWArray { } public byte[] toPDF() { - return toPDFString().getBytes(); + try { + return toPDFString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + return toPDFString().getBytes(); + } } public String toPDFString() { diff --git a/src/org/apache/fop/pdf/PDFXObject.java b/src/org/apache/fop/pdf/PDFXObject.java index 8d670a574..db2ec8cb4 100644 --- a/src/org/apache/fop/pdf/PDFXObject.java +++ b/src/org/apache/fop/pdf/PDFXObject.java @@ -12,12 +12,17 @@ package org.apache.fop.pdf; // Java import java.io.IOException; -import org.apache.fop.messaging.MessageHandler; +import java.io.UnsupportedEncodingException; import java.io.OutputStream; // FOP import org.apache.fop.datatypes.ColorSpace; +import org.apache.fop.messaging.MessageHandler; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFICCStream; import org.apache.fop.image.FopImage; +import org.apache.fop.image.EPSImage; +import org.apache.fop.image.JpegImage; import org.apache.fop.image.FopImageException; /** @@ -28,21 +33,44 @@ import org.apache.fop.image.FopImageException; * the dictionary just provides information like the stream length */ public class PDFXObject extends PDFObject { + private boolean isPS; + private PDFDocument pdfDoc; + private PDFICCStream pdfICCStream; FopImage fopimage; int Xnum; - /** * create an Xobject with the given number and name and load the * image in the object */ public PDFXObject(int number, int Xnumber, FopImage img) { + this(number, Xnumber, img, null); + } + + public PDFXObject(int number, int Xnumber, FopImage img, PDFDocument pdfdoc) { super(number); + isPS = false; this.Xnum = Xnumber; if (img == null) MessageHandler.errorln("FISH"); fopimage = img; + this.pdfDoc = pdfdoc; + pdfICCStream = null; + try { + if (fopimage instanceof JpegImage) { + fopimage.getBitmaps(); + JpegImage jpegimage = (JpegImage)fopimage; + if (jpegimage.getColorSpace().hasICCProfile()) { + pdfICCStream = pdfDoc.makePDFICCStream(); + pdfICCStream.setColorSpace(jpegimage.getColorSpace()); + pdfICCStream.addDefaultFilters(); + } + } + } catch (Exception e) { + MessageHandler.errorln("Error while reading image " + fopimage.getURL() + + ": " + e.getMessage()); + } } /** @@ -58,58 +86,169 @@ public class PDFXObject extends PDFObject { protected int output(OutputStream stream) throws IOException { int length = 0; int i = 0; - int x, y; try { - // delegate the stream work to PDFStream - PDFStream imgStream = new PDFStream(0); + if (fopimage instanceof EPSImage) { + isPS = true; + EPSImage epsImage = (EPSImage)fopimage; + int[] bbox = epsImage.getBBox(); + int bboxw = bbox[2] - bbox[0]; + int bboxh = bbox[3] - bbox[1]; - imgStream.setData(fopimage.getBitmaps()); + // delegate the stream work to PDFStream + PDFStream imgStream = new PDFStream(0); - /* - * Added by Eric Dalquist - * If the DCT filter hasn't been added to the object we add it here - */ - if (fopimage.getPDFFilter() != null) { - imgStream.addFilter(fopimage.getPDFFilter()); - } + StringBuffer preamble = new StringBuffer(); + preamble.append("%%BeginDocument: " + epsImage.getDocName() + "\n"); + + preamble.append("userdict begin % Push userdict on dict stack\n"); + preamble.append("/PreEPS_state save def\n"); + preamble.append("/dict_stack countdictstack def\n"); + preamble.append("/ops_count count 1 sub def\n"); + preamble.append("/showpage {} def\n"); + + + preamble.append((double)(1f/(double)bboxw) + " " + (double)(1f/(double)bboxh) + " scale\n"); + preamble.append(-bbox[0] + " " + (-bbox[1]) + " translate\n"); + preamble.append(bbox[0] + " " + bbox[1] + " " + bboxw + " " + bboxh + " rectclip\n"); + preamble.append("newpath\n"); + + StringBuffer post = new StringBuffer(); + post.append("%%EndDocument\n"); + post.append("count ops_count sub {pop} repeat\n"); + post.append("countdictstack dict_stack sub {end} repeat\n"); + post.append("PreEPS_state restore\n"); + post.append("end % userdict\n"); + + byte[] preBytes; + try { + preBytes = preamble.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + preBytes = preamble.toString().getBytes(); + } + byte[] postBytes; + try { + postBytes = post.toString().getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + postBytes = post.toString().getBytes(); + } + byte[] imgData = new byte[preBytes.length + postBytes.length + fopimage.getBitmaps().length]; + + System.arraycopy (preBytes, 0, imgData, 0, preBytes.length); + System.arraycopy (fopimage.getBitmaps(), 0, imgData, preBytes.length, fopimage.getBitmaps().length); + System.arraycopy (postBytes, 0, imgData, preBytes.length + fopimage.getBitmaps().length, postBytes.length); + + + imgStream.setData(imgData); + //imgStream.addFilter(new FlateFilter()); + imgStream.addDefaultFilters(); + + String dictEntries = imgStream.applyFilters(); + + String p = this.number + " " + this.generation + " obj\n"; + p = p + "<</Type /XObject\n"; + p = p + "/Subtype /PS\n"; + p = p + "/Length " + imgStream.getDataLength(); + + // don't know if it's the good place (other objects can have references to it) + fopimage.close(); + p = p + dictEntries; + p = p + ">>\n"; + + // push the pdf dictionary on the writer + byte[] pdfBytes; + try { + pdfBytes = p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdfBytes = p.getBytes(); + } + stream.write(pdfBytes); + length += pdfBytes.length; + // push all the image data on the writer and takes care of length for trailer + length += imgStream.outputStreamData(stream); + + try { + pdfBytes = ("endobj\n").getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdfBytes = ("endobj\n").getBytes(); + } + stream.write(pdfBytes); + length += pdfBytes.length; + + } else { + + // delegate the stream work to PDFStream + PDFStream imgStream = new PDFStream(0); + + imgStream.setData(fopimage.getBitmaps()); + + /* + * Added by Eric Dalquist + * If the DCT filter hasn't been added to the object we add it here + */ + if (fopimage.getPDFFilter() != null) { + imgStream.addFilter(fopimage.getPDFFilter()); + } + + imgStream.addDefaultFilters(); + + String dictEntries = imgStream.applyFilters(); + + String p = this.number + " " + this.generation + " obj\n"; + p = p + "<</Type /XObject\n"; + p = p + "/Subtype /Image\n"; + p = p + "/Name /Im" + Xnum + "\n"; + p = p + "/Length " + imgStream.getDataLength() + "\n"; + p = p + "/Width " + fopimage.getWidth() + "\n"; + p = p + "/Height " + fopimage.getHeight() + "\n"; + p = p + "/BitsPerComponent " + fopimage.getBitsPerPixel() + "\n"; + + if (pdfICCStream != null ) { + p = p + "/ColorSpace [/ICCBased " + pdfICCStream.referencePDF() + "]\n"; + } else { + ColorSpace cs = fopimage.getColorSpace(); + p = p + "/ColorSpace /" + cs.getColorSpacePDFString() + "\n"; + } + + /* PhotoShop generates CMYK values that's inverse, + */ + if (fopimage.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK && + fopimage.invertImage()) { + p = p + "/Decode [ 1.0 0.0 1.0 0.0 1.0 0.0 1.1 0.0 ]\n"; + } + + if (fopimage.isTransparent()) { + PDFColor transp = fopimage.getTransparentColor(); + p = p + "/Mask [" + transp.red255() + " " + transp.red255() + + " " + transp.green255() + " " + transp.green255() + " " + + transp.blue255() + " " + transp.blue255() + "]\n"; + } + p = p + dictEntries; + p = p + ">>\n"; + + // don't know if it's the good place (other objects can have references to it) + fopimage.close(); + + // push the pdf dictionary on the writer + byte[] pdfBytes; + try { + pdfBytes = p.getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdfBytes = p.getBytes(); + } + stream.write(pdfBytes); + length += pdfBytes.length; + // push all the image data on the writer and takes care of length for trailer + length += imgStream.outputStreamData(stream); - imgStream.addDefaultFilters(); - - String dictEntries = imgStream.applyFilters(); - - String p = this.number + " " + this.generation + " obj\n"; - p = p + "<</Type /XObject\n"; - p = p + "/Subtype /Image\n"; - p = p + "/Name /Im" + Xnum + "\n"; - p = p + "/Length " + imgStream.getDataLength() + "\n"; - p = p + "/Width " + fopimage.getWidth() + "\n"; - p = p + "/Height " + fopimage.getHeight() + "\n"; - p = p + "/BitsPerComponent " + fopimage.getBitsPerPixel() + "\n"; - ColorSpace cs = fopimage.getColorSpace(); - p = p + "/ColorSpace /" + cs.getColorSpacePDFString() + "\n"; - if (fopimage.isTransparent()) { - PDFColor transp = fopimage.getTransparentColor(); - p = p + "/Mask [" + transp.red255() + " " + transp.red255() - + " " + transp.green255() + " " + transp.green255() + " " - + transp.blue255() + " " + transp.blue255() + "]\n"; + try { + pdfBytes = ("endobj\n").getBytes(PDFDocument.ENCODING); + } catch (UnsupportedEncodingException ue) { + pdfBytes = ("endobj\n").getBytes(); + } + stream.write(pdfBytes); + length += pdfBytes.length; } - p = p + dictEntries; - p = p + ">>\n"; - - // don't know if it's the good place (other objects can have references to it) - fopimage.close(); - - // push the pdf dictionary on the writer - byte[] pdfBytes = p.getBytes(); - stream.write(pdfBytes); - length += pdfBytes.length; - // push all the image data on the writer and takes care of length for trailer - length += imgStream.outputStreamData(stream); - - pdfBytes = ("endobj\n").getBytes(); - stream.write(pdfBytes); - length += pdfBytes.length; } catch (FopImageException imgex) { MessageHandler.errorln("Error in XObject : " + imgex.getMessage()); diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java index 0c203753f..5d5a45c8e 100644 --- a/src/org/apache/fop/render/AbstractRenderer.java +++ b/src/org/apache/fop/render/AbstractRenderer.java @@ -8,9 +8,9 @@ package org.apache.fop.render; // FOP -import org.apache.fop.pdf.PDFPathPaint; -import org.apache.fop.pdf.PDFColor; import org.apache.fop.image.ImageArea; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.FopImageException; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; @@ -18,7 +18,8 @@ import org.apache.fop.layout.inline.*; import org.apache.fop.datatypes.*; import org.apache.fop.render.pdf.FontSetup; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; // Java import java.io.IOException; @@ -63,6 +64,129 @@ public abstract class AbstractRenderer implements Renderer { protected abstract void doFrame(Area area); /** + * Renders an area's background. + * @param x the x position of the left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + */ + protected void doBackground(Area area, int x, int y, int w, int h) { + if (h == 0 || w == 0) + return; + + BackgroundProps props = area.getBackground(); + if (props == null) + return; + + if (props.backColor.alpha() == 0) { + this.addFilledRect(x, y, w, -h, props.backColor); + } + + // XXX: I'm ignoring area rotation here 8( + // is this taken care of for me elsewhere in the codebase? + if (props.backImage != null) { + int imgW; + int imgH; + try { + // XXX: do correct unit conversion here + imgW = props.backImage.getWidth() * 1000; + imgH = props.backImage.getHeight() * 1000; + } + catch (FopImageException fie) { + log.error("Error obtaining bg image width and height", fie); + return; + } + + int dx = x; + int dy = y; + int endX = x + w; + int endY = y - h; + int clipW = w % imgW; + int clipH = h % imgH; + + boolean repeatX = true; + boolean repeatY = true; + switch (props.backRepeat) { + case BackgroundRepeat.REPEAT: + break; + + case BackgroundRepeat.REPEAT_X: + repeatY = false; + break; + + case BackgroundRepeat.REPEAT_Y: + repeatX = false; + break; + + case BackgroundRepeat.NO_REPEAT: + repeatX = false; + repeatY = false; + break; + + case BackgroundRepeat.INHERIT: + // XXX: what to do here? + break; + + default: + log.error("Ignoring invalid background-repeat property"); + } + + FontState fs = area.getFontState(); + + while (dy > endY) { // looping through rows + while (dx < endX) { // looping through cols + if (dx + imgW <= endX) { + // no x clipping + if (dy - imgH >= endY) { + // no x clipping, no y clipping + drawImageScaled(dx, dy, imgW, imgH, + props.backImage, fs); + } + else { + // no x clipping, y clipping + drawImageClipped(dx, dy, + 0, 0, imgW, clipH, + props.backImage, fs); + } + } + else { + // x clipping + if (dy - imgH >= endY) { + // x clipping, no y clipping + drawImageClipped(dx, dy, + 0, 0, clipW, imgH, + props.backImage, fs); + } + + else { + // x clipping, y clipping + drawImageClipped(dx, dy, + 0, 0, clipW, clipH, + props.backImage, fs); + } + } + + if (repeatX) { + dx += imgW; + } + else { + break; + } + } // end looping through cols + + dx = x; + + if (repeatY) { + dy -= imgH; + } + else { + break; + } + } // end looping through rows + } + } + + /** * Add a filled rectangle to the current stream * This default implementation calls addRect * using the same color for fill and border. @@ -76,6 +200,95 @@ public abstract class AbstractRenderer implements Renderer { protected abstract void addFilledRect(int x, int y, int w, int h, ColorType col); + /** + * Renders an image, rendered at the image's intrinsic size. + * This by default calls drawImageScaled() with the image's + * intrinsic width and height, but implementations may + * override this method if it can provide a more efficient solution. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImage(int x, int y, FopImage image, FontState fs) { + int w; + int h; + try { + // XXX: convert these units correctly + w = image.getWidth() * 1000; + h = image.getHeight() * 1000; + } + catch (FopImageException e) { + log.error("Failed to obtain the image width and height", e); + return; + } + drawImageScaled(x, y, w, h, image, fs); + } + + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected abstract void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs); + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected abstract void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs); + + /** + * Render an image area. + * + * @param area the image area to render + */ + public void renderImageArea(ImageArea area) { + // adapted from contribution by BoBoGi + int x = this.currentXPosition + area.getXOffset(); + int y = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + + this.currentYPosition -= h; + + FopImage img = area.getImage(); + + if (img == null) { + log.error("Error while loading image : area.getImage() is null"); + } + else { + drawImageScaled(x, y, w, h, img, area.getFontState()); + } + + this.currentXPosition += w; + } + public void renderBodyAreaContainer(BodyAreaContainer area) { int saveY = this.currentYPosition; int saveX = this.currentAreaContainerXPosition; @@ -90,18 +303,19 @@ public abstract class AbstractRenderer implements Renderer { } this.currentXPosition = this.currentAreaContainerXPosition; - int w, h; int rx = this.currentAreaContainerXPosition; - w = area.getContentWidth(); - h = area.getContentHeight(); int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); - - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - addFilledRect(rx, ry, w, -h, bg); - } + // XXX: (mjg@recaldesign.com) I had to use getAllocationWidth() + // and getMaxHeight() as the content width and height are + // always 0. Is this supposed to be the case? + // IMHO, the bg should cover the entire area anyway, not + // just the parts with content, which makes this correct. + // Probably want to check this for the other region + // areas as well. + int w = area.getAllocationWidth(); + int h = area.getMaxHeight(); + + doBackground(area, rx, ry, w, h); // floats & footnotes stuff renderAreaContainer(area.getBeforeFloatReferenceArea()); diff --git a/src/org/apache/fop/render/PrintRenderer.java b/src/org/apache/fop/render/PrintRenderer.java index e6f4c6101..f19220700 100644 --- a/src/org/apache/fop/render/PrintRenderer.java +++ b/src/org/apache/fop/render/PrintRenderer.java @@ -13,13 +13,13 @@ package org.apache.fop.render; // FOP import org.apache.fop.pdf.PDFPathPaint; import org.apache.fop.pdf.PDFColor; -import org.apache.fop.image.ImageArea; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; import org.apache.fop.datatypes.*; import org.apache.fop.render.pdf.FontSetup; +import org.apache.fop.apps.FOPException; import org.apache.fop.svg.SVGArea; @@ -191,18 +191,13 @@ public abstract class PrintRenderer extends AbstractRenderer { rx += ((BlockArea)area).getStartIndent(); h = area.getContentHeight(); int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); rx = rx - area.getPaddingLeft(); ry = ry + area.getPaddingTop(); w = w + area.getPaddingLeft() + area.getPaddingRight(); h = h + area.getPaddingTop() + area.getPaddingBottom(); - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - this.addFilledRect(rx, ry, w, -h, new PDFColor(bg)); - } + doBackground(area, rx, ry, w, h); // rx = rx - area.getBorderLeftWidth(); // ry = ry + area.getBorderTopWidth(); @@ -260,13 +255,6 @@ public abstract class PrintRenderer extends AbstractRenderer { } /** - * render image area - * - * @param area the image area to render - */ - public abstract void renderImageArea(ImageArea area); - - /** * render a foreign object area */ public abstract void renderForeignObjectArea(ForeignObjectArea area); @@ -332,6 +320,8 @@ public abstract class PrintRenderer extends AbstractRenderer { prevUnderlineXEndPos + space.getSize(), prevUnderlineYEndPos, prevUnderlineSize, prevUnderlineColor); + // save position for a following InlineSpace + prevUnderlineXEndPos = prevUnderlineXEndPos + space.getSize(); } } if (space.getOverlined()) { @@ -340,6 +330,7 @@ public abstract class PrintRenderer extends AbstractRenderer { prevOverlineXEndPos + space.getSize(), prevOverlineYEndPos, prevOverlineSize, prevOverlineColor); + prevOverlineXEndPos = prevOverlineXEndPos + space.getSize(); } } if (space.getLineThrough()) { @@ -348,6 +339,7 @@ public abstract class PrintRenderer extends AbstractRenderer { prevLineThroughXEndPos + space.getSize(), prevLineThroughYEndPos, prevLineThroughSize, prevLineThroughColor); + prevLineThroughXEndPos = prevLineThroughXEndPos + space.getSize(); } } } @@ -414,7 +406,7 @@ public abstract class PrintRenderer extends AbstractRenderer { * * @param fontInfo font info to set up */ - public void setupFontInfo(FontInfo fontInfo) { + public void setupFontInfo(FontInfo fontInfo) throws FOPException { this.fontInfo = fontInfo; FontSetup.setup(fontInfo); } diff --git a/src/org/apache/fop/render/Renderer.java b/src/org/apache/fop/render/Renderer.java index 36d4364fa..d8641f13e 100644 --- a/src/org/apache/fop/render/Renderer.java +++ b/src/org/apache/fop/render/Renderer.java @@ -13,7 +13,8 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; // Java import java.io.OutputStream; @@ -35,7 +36,7 @@ public interface Renderer { /** * set up the given FontInfo */ - public void setupFontInfo(FontInfo fontInfo); + public void setupFontInfo(FontInfo fontInfo) throws FOPException; /** * set up renderer options diff --git a/src/org/apache/fop/render/awt/AWTFontMetrics.java b/src/org/apache/fop/render/awt/AWTFontMetrics.java index 33a79fe8b..ee4ea7ab1 100644 --- a/src/org/apache/fop/render/awt/AWTFontMetrics.java +++ b/src/org/apache/fop/render/awt/AWTFontMetrics.java @@ -16,6 +16,7 @@ import org.apache.fop.layout.FontState; // Java import java.util.Enumeration; import java.util.Hashtable; +import java.io.FileInputStream; import java.awt.Component; import java.awt.Font; import java.awt.Graphics; @@ -94,6 +95,16 @@ public class AWTFontMetrics { Graphics2D graphics; /** + * Embed Font List. + */ + private Hashtable embedFontList = null; + + /** + * Physical Font Cash. + */ + private Hashtable fontCash = null; + + /** * Constructs a new Font-metrics. * @param parent an temp graphics object - this is needed so * that we can get an instance of @@ -210,7 +221,7 @@ public class AWTFontMetrics { int s = (int)(size / 1000f); if (f1 == null) { - f1 = new Font(family, style, s); + f1 = createFont(family, style, s); fmt = graphics.getFontMetrics(f1); changed = true; } else { @@ -219,7 +230,7 @@ public class AWTFontMetrics { if (family.equals(this.family)) { f1 = f1.deriveFont(style, (float)s); } else - f1 = new Font(family, style, s); + f1 = createFont(family, style, s); fmt = graphics.getFontMetrics(f1); changed = true; } @@ -237,6 +248,58 @@ public class AWTFontMetrics { return changed; } + /** + * set embed font. + * @param family font-family name + * @param style font style + * @param fontPath path to phsical font + */ + public void setEmbedFont(String family,int style,String fontPath) { + if (embedFontList == null) + embedFontList = new Hashtable(); + embedFontList.put(family+style,fontPath); + } + + /** + * create Font to draw. + * @param family font-family name + * @param style font style + * @param size font size + */ + public java.awt.Font createFont(String family, int style, int size) { + String fontPath = null; + if (embedFontList != null) + fontPath = (String)embedFontList.get(family+style); + if (fontPath == null) + return new Font(family, style, size); + // lazy instanciation for fontCash. + if (fontCash == null) + fontCash = new Hashtable(); + Font cashedFont = (Font)fontCash.get(fontPath); + if (cashedFont == null) { + // Create specified TrueType Font. + FileInputStream fontStream = null; + try { + MessageHandler.logln("create embedFont "+fontPath); + fontStream = new FileInputStream(fontPath); + // createFont methods supports higer than JDK1.3 + // Currently supports only TrueType font. + cashedFont = Font.createFont(Font.TRUETYPE_FONT,fontStream); + } catch(Throwable th) { + MessageHandler.error("Failed to create embedFont "+ + fontPath + " : " + th.toString()); + // if failed create font, use system "Dialog" logical font + // name for each Locale. + cashedFont = new Font("Dialog", style, size); + } finally { + if (fontStream != null) + try { fontStream.close(); } catch(Exception ex) {} + } + fontCash.put(fontPath,cashedFont); + } + Font font = cashedFont.deriveFont(style, (float)size); + return font; + } /** * Returns a java.awt.Font instance for the desired diff --git a/src/org/apache/fop/render/awt/AWTRenderer.java b/src/org/apache/fop/render/awt/AWTRenderer.java index 98118ed36..8e849511e 100644 --- a/src/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/org/apache/fop/render/awt/AWTRenderer.java @@ -79,7 +79,7 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable * object that is contained withing the Image Object. */ private BufferedImage pageImage = null; - private Graphics2D graphics = null; + protected Graphics2D graphics = null; /** * The current (internal) font name @@ -99,6 +99,13 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable protected float currentBlue = 0; /** + * Used to make the last font and color available to + * renderInlineSpace() to render text decorations. + */ + protected java.awt.Font lastFont = null; + protected Color lastColor = null; + + /** * The parent component, used to set up the font. * This is needed as FontSetup needs a live AWT component * in order to generate valid font measures. @@ -271,10 +278,14 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable int starty = pageHeight - ((y + 500) / 1000); int endx = (x + w + 500) / 1000; int endy = pageHeight - ((y + h + 500) / 1000); - if (drawAsOutline) + if (drawAsOutline) { graphics.drawRect(startx, starty, endx - startx, endy - starty); - else + } else { + //don't round down to zero + if (w != 0 && endx == startx) endx++; + if (h != 0 && endy == starty) endy++; graphics.fillRect(startx, starty, endx - startx, endy - starty); + } } protected void addFilledRect(int x, int y, int w, int h, @@ -408,19 +419,13 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable h = area.getContentHeight(); int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); rx = rx - area.getPaddingLeft(); ry = ry + area.getPaddingTop(); w = w + area.getPaddingLeft() + area.getPaddingRight(); h = h + area.getPaddingTop() + area.getPaddingBottom(); - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - this.addRect(rx, ry, w, -h, bg.red(), bg.green(), bg.blue(), - bg.red(), bg.green(), bg.blue()); - } + doBackground(area, rx, ry, w, h); rx = rx - area.getBorderLeftWidth(); ry = ry + area.getBorderTopWidth(); @@ -470,7 +475,8 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable a.getAllocationWidth(), a.getHeight()); } - public void setupFontInfo(FontInfo fontInfo) { + public void setupFontInfo(FontInfo fontInfo) + throws FOPException { // create a temp Image to test font metrics on BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); @@ -482,6 +488,45 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable this.currentYPosition -= d; } + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } // correct integer roundoff (aml/rlc) @@ -560,13 +605,13 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable this.currentXPosition += area.getContentWidth(); } + public void renderWordArea(WordArea area) { char ch; StringBuffer pdf = new StringBuffer(); - String name = area.getFontState().getFontName(); + String fontname = area.getFontState().getFontName(); int size = area.getFontState().getFontSize(); - boolean underlined = area.getUnderlined(); float red = area.getRed(); float green = area.getGreen(); @@ -575,15 +620,15 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable FontMetricsMapper mapper; try { mapper = - (FontMetricsMapper)area.getFontState().getFontInfo().getMetricsFor(name); + (FontMetricsMapper)area.getFontState().getFontInfo().getMetricsFor(fontname); } catch (FOPException iox) { mapper = new FontMetricsMapper("MonoSpaced", java.awt.Font.PLAIN, graphics); } - if ((!name.equals(this.currentFontName)) + if ((!fontname.equals(this.currentFontName)) || (size != this.currentFontSize)) { - this.currentFontName = name; + this.currentFontName = fontname; this.currentFontSize = size; } @@ -598,7 +643,7 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable int bl = this.currentYPosition; - String s; // = area.getText(); + String s; if (area.getPageNumberID() != null) { // this text is a page number, so resolve it s = idReferences.getPageNumber(area.getPageNumberID()); @@ -623,29 +668,106 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable } graphics.setColor(saveColor); - AttributedString ats = new AttributedString(s); - ats.addAttribute(TextAttribute.FONT, f); - if (underlined) { - ats.addAttribute(TextAttribute.UNDERLINE, - TextAttribute.UNDERLINE_ON); - } - AttributedCharacterIterator iter = ats.getIterator(); + // Ralph LaChance (May 16, 2002) + // AttributedString mechanism removed because of + // rendering bug in both jdk 1.3.0_x and 1.4. + // see bug parade 4650042 and others + // + graphics.setFont(f); + + // correct starting location for integer roundoff + int newx = (int)(rx + 500) / 1000; + int newy = (int)(pageHeight - (bl + 500) / 1000); + + // draw text, corrected for integer roundoff + graphics.drawString(s, newx, newy); - // correct integer roundoff - // graphics.drawString(iter, rx / 1000f, - // (int)(pageHeight - bl / 1000f)); + FontMetrics fm = graphics.getFontMetrics(f); + int tdwidth = (int)fm.getStringBounds(s, graphics).getWidth(); - graphics.drawString(iter, (rx + 500) / 1000, - (int)(pageHeight - (bl + 500) / 1000)); + // text decorations + renderTextDecoration(rx, bl, tdwidth, f, " ", + area.getUnderlined(), + area.getOverlined(), + area.getLineThrough()); + // remember last font and color for possible inline spaces + // (especially for text decorations) + this.lastFont = graphics.getFont(); + this.lastColor = graphics.getColor(); + + graphics.setFont(oldFont); graphics.setColor(oldColor); + this.currentXPosition += area.getContentWidth(); } + public void renderInlineSpace(InlineSpace space) { + if (space.getUnderlined() || space.getOverlined() || space.getLineThrough()) { + int rx = this.currentXPosition; + int bl = this.currentYPosition; + + java.awt.Font oldFont = graphics.getFont(); + if (this.lastFont != null) { + graphics.setFont(this.lastFont); + } + Color oldColor = graphics.getColor(); + if (this.lastColor != null) { + graphics.setColor(this.lastColor); + } + + int width = (int)(space.getSize() + 500) / 1000; + renderTextDecoration(rx, bl, width, graphics.getFont(), " ", + space.getUnderlined(), + space.getOverlined(), + space.getLineThrough()); + + graphics.setFont(oldFont); + graphics.setColor(oldColor); + } + this.currentXPosition += space.getSize(); } + + protected void renderTextDecoration(int x, int bl, int width, + java.awt.Font font, String text, + boolean underline, + boolean overline, + boolean linethrough) { + if (!(underline || overline || linethrough)) return; + int newx = (int)(x + 500) / 1000; + int newy = (int)(pageHeight - (bl + 500) / 1000); + + // text decorations + FontMetrics fm = graphics.getFontMetrics(font); + LineMetrics lm = fm.getLineMetrics(text, graphics); + + int ulthick = (int)lm.getUnderlineThickness(); + if (ulthick < 1) + ulthick = 1; // don't allow it to disappear + if (underline) { + // nothing in awt specifies underline location, + // descent/2 seems to match my word processor + int deltay = fm.getDescent() / 2; + graphics.fillRect(newx, newy + deltay, width, ulthick); + } + if (overline) { + // todo: maybe improve positioning of overline + int deltay = -(int)(lm.getAscent() * 0.8); + graphics.fillRect(newx, newy + deltay, width, ulthick); + } + if (linethrough) { + int ltthick = (int)lm.getStrikethroughThickness(); + if (ltthick < 1) + ltthick = 1; // don't allow it to disappear + int deltay = (int)lm.getStrikethroughOffset(); + graphics.fillRect(newx, newy + deltay, width, ltthick); + } + } + + /** * render leader area into AWT * diff --git a/src/org/apache/fop/render/awt/FontMetricsMapper.java b/src/org/apache/fop/render/awt/FontMetricsMapper.java index 2991e85a0..a8499a4d1 100644 --- a/src/org/apache/fop/render/awt/FontMetricsMapper.java +++ b/src/org/apache/fop/render/awt/FontMetricsMapper.java @@ -70,6 +70,14 @@ public class FontMetricsMapper implements org.apache.fop.layout.FontMetric { } /** + * Create Original Font. + * @param fontPath path to truetype font + */ + public void setEmbedFont(String fontPath) { + metric.setEmbedFont(family,style,fontPath); + } + + /** * Determines the font ascent of the Font described by this * FontMetrics object * @return ascent in milliponts diff --git a/src/org/apache/fop/render/awt/FontSetup.java b/src/org/apache/fop/render/awt/FontSetup.java index 90e33f8f6..1b988869c 100644 --- a/src/org/apache/fop/render/awt/FontSetup.java +++ b/src/org/apache/fop/render/awt/FontSetup.java @@ -11,12 +11,17 @@ package org.apache.fop.render.awt; import org.apache.fop.messaging.MessageHandler; import org.apache.fop.layout.FontInfo; import org.apache.fop.layout.FontDescriptor; +import org.apache.fop.configuration.Configuration; +import org.apache.fop.configuration.FontTriplet; +import org.apache.fop.apps.FOPException; + // Java import java.util.Enumeration; import java.util.Hashtable; import java.awt.Font; import java.awt.Graphics2D; +import java.util.Vector; /** * sets up the AWT fonts. It is similar to @@ -26,6 +31,14 @@ import java.awt.Graphics2D; */ public class FontSetup { + /** Regular */ + private static int normal = java.awt.Font.PLAIN; + /** Bold */ + private static int bold = java.awt.Font.BOLD; + /** Italic */ + private static int italic = java.awt.Font.ITALIC; + /** BoldItalic */ + private static int bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; /** * sets up the font info object. @@ -37,9 +50,10 @@ public class FontSetup { * @param parent needed, since a live AWT component is needed * to get a valid java.awt.FontMetrics object */ - public static void setup(FontInfo fontInfo, Graphics2D graphics) { + public static void setup(FontInfo fontInfo, Graphics2D graphics) + throws FOPException { + FontMetricsMapper metric; - int normal, bold, bolditalic, italic; MessageHandler.logln("setting up fonts"); @@ -49,10 +63,6 @@ public class FontSetup { * SansSerif - bold, normal, italic, bold-italic * MonoSpaced - bold, normal, italic, bold-italic */ - normal = java.awt.Font.PLAIN; - bold = java.awt.Font.BOLD; - italic = java.awt.Font.ITALIC; - bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; metric = new FontMetricsMapper("SansSerif", normal, graphics); // --> goes to F1 @@ -172,8 +182,78 @@ public class FontSetup { fontInfo.addFontProperties("F8", "Times Roman", "italic", "bold"); fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", "normal", "normal"); + + /* Add configured fonts */ + addConfiguredFonts(fontInfo, 15, graphics); + } + + /** + * Add fonts from configuration file starting with + * internalnames F<num> + */ + public static void addConfiguredFonts( + FontInfo fontInfo, int num, Graphics2D graphics) + throws FOPException { + FontMetricsMapper metric; + String internalName = null; + + Vector fontInfos = Configuration.getFonts(); + if (fontInfos == null) + return; + + for (Enumeration e = fontInfos.elements(); e.hasMoreElements(); ) { + org.apache.fop.configuration.FontInfo configFontInfo = + (org.apache.fop.configuration.FontInfo)e.nextElement(); + + try { + String metricsFile = configFontInfo.getMetricsFile(); + if (metricsFile != null) { + internalName = "F" + num; + num++; + + Vector triplets = configFontInfo.getFontTriplets(); + for (Enumeration t = triplets.elements(); + t.hasMoreElements(); ) { + FontTriplet triplet = (FontTriplet)t.nextElement(); + boolean embed = configFontInfo.getEmbedFile() != null; + // if embed font is not specified, use system "Dialog" + // logical font name for each Locale. + String family = embed ? triplet.getName() : "Dialog"; + metric = new FontMetricsMapper(family, + getFontMetrics(triplet), + graphics); + if (embed) + metric.setEmbedFont(configFontInfo.getEmbedFile()); + fontInfo.addMetrics(internalName, metric); + fontInfo.addFontProperties(internalName, + triplet.getName(), + triplet.getStyle(), + triplet.getWeight()); + } + } + } catch (Exception ex) { + MessageHandler.error("Failed to read font metrics file " + + configFontInfo.getMetricsFile() + + " : " + ex.getMessage()); + } + } } + /** + * Return configured font metrics value. + */ + private static int getFontMetrics(FontTriplet triplet) { + boolean isBold = ("bold".equalsIgnoreCase(triplet.getWeight())); + boolean isItalic = ("italic".equalsIgnoreCase(triplet.getStyle())); + if (isBold && isItalic) { + return bolditalic; + } else if (isBold) { + return bold; + } else if (isItalic) { + return italic; + } + return normal; + } } diff --git a/src/org/apache/fop/render/mif/MIFRenderer.java b/src/org/apache/fop/render/mif/MIFRenderer.java index 3d4a990d1..da3bee13c 100644 --- a/src/org/apache/fop/render/mif/MIFRenderer.java +++ b/src/org/apache/fop/render/mif/MIFRenderer.java @@ -12,8 +12,6 @@ package org.apache.fop.render.mif; // FOP import org.apache.fop.render.Renderer; import org.apache.fop.render.AbstractRenderer; -import org.apache.fop.image.ImageArea; -import org.apache.fop.image.FopImage; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.fo.*; @@ -166,22 +164,13 @@ public class MIFRenderer extends AbstractRenderer { h = area.getContentHeight(); int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); rx = rx - area.getPaddingLeft(); ry = ry + area.getPaddingTop(); w = w + area.getPaddingLeft() + area.getPaddingRight(); h = h + area.getPaddingTop() + area.getPaddingBottom(); - /* - * // I'm not sure I should have to check for bg being null - * // but I do - * if ((bg != null) && (bg.alpha() == 0)) { - * this.addRect(rx, ry, w, -h, - * new PDFColor(bg), - * new PDFColor(bg)); - * } - */ + doBackground(area, rx, ry, w, h); rx = rx - area.getBorderLeftWidth(); ry = ry + area.getBorderTopWidth(); @@ -251,6 +240,46 @@ public class MIFRenderer extends AbstractRenderer { } /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** * render the given image area */ public void renderImageArea(ImageArea area) { diff --git a/src/org/apache/fop/render/pcl/PCLRenderer.java b/src/org/apache/fop/render/pcl/PCLRenderer.java index a11ee2bcb..ba25deff7 100755 --- a/src/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/org/apache/fop/render/pcl/PCLRenderer.java @@ -9,8 +9,6 @@ package org.apache.fop.render.pcl; // FOP import org.apache.fop.render.PrintRenderer; -import org.apache.fop.image.ImageArea; -import org.apache.fop.image.FopImage; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.datatypes.*; @@ -246,6 +244,46 @@ public class PCLRenderer extends PrintRenderer { currentStream.add("\033*v0O"); } + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } + boolean printBMP(FopImage img, int x, int y, int w, int h) throws FopImageException { // Print the passed image file in PCL. diff --git a/src/org/apache/fop/render/pdf/Font.java b/src/org/apache/fop/render/pdf/Font.java index d0142ef87..aceaf219e 100644 --- a/src/org/apache/fop/render/pdf/Font.java +++ b/src/org/apache/fop/render/pdf/Font.java @@ -33,21 +33,9 @@ public abstract class Font implements FontMetric { } /** - * Provide a default mapping + * map a Unicode character to a code point in the font */ - public char mapChar(char c) { - // Use default CodePointMapping - if (c > 127) { - char d = org.apache.fop.render.pdf.CodePointMapping.map[c]; - if (d != 0) { - c = d; - } else { - c = '#'; - } - } - return c; - } - + public abstract char mapChar(char c); } diff --git a/src/org/apache/fop/render/pdf/FontSetup.java b/src/org/apache/fop/render/pdf/FontSetup.java index 00a415230..a767ad10d 100644 --- a/src/org/apache/fop/render/pdf/FontSetup.java +++ b/src/org/apache/fop/render/pdf/FontSetup.java @@ -16,6 +16,7 @@ import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFResources; import org.apache.fop.configuration.Configuration; import org.apache.fop.configuration.FontTriplet; +import org.apache.fop.apps.FOPException; // Java import java.util.Enumeration; @@ -38,7 +39,7 @@ public class FontSetup { * * @param fontInfo the font info object to set up */ - public static void setup(FontInfo fontInfo) { + public static void setup(FontInfo fontInfo) throws FOPException { MessageHandler.logln("setting up fonts"); fontInfo.addMetrics("F1", new Helvetica()); @@ -138,7 +139,8 @@ public class FontSetup { * Add fonts from configuration file starting with * internalnames F<num> */ - public static void addConfiguredFonts(FontInfo fontInfo, int num) { + public static void addConfiguredFonts(FontInfo fontInfo, int num) + throws FOPException { String internalName = null; FontReader reader = null; diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index ec9da0725..44e62f89b 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -4,13 +4,12 @@ * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ - package org.apache.fop.render.pdf; // FOP import org.apache.fop.render.PrintRenderer; -import org.apache.fop.image.ImageArea; import org.apache.fop.image.FopImage; +import org.apache.fop.image.FopImageException; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.inline.*; @@ -49,16 +48,17 @@ import java.awt.RenderingHints; import java.awt.Dimension; /** - * Renderer that renders areas to PDF + * <p> + * + * Renderer that renders areas to PDF.</p> <p> * - * Modified by Mark Lillywhite, mark-fop@inomial.com to use the - * new Renderer interface. The PDF renderer is by far the trickiest - * renderer and the best supported by FOP. It also required some - * reworking in the way that Pages, Catalogs and the Root object - * were written to the stream. The output document should now still - * be a 100% compatible PDF document, but hte order of the document - * writing is significantly different. See also the changes - * to PDFPage, PDFPages and PDFRoot. + * Modified by Mark Lillywhite, mark-fop@inomial.com to use the new Renderer + * interface. The PDF renderer is by far the trickiest renderer and the best + * supported by FOP. It also required some reworking in the way that Pages, + * Catalogs and the Root object were written to the stream. The output document + * should now still be a 100% compatible PDF document, but the order of the + * document writing is significantly different. See also the changes to + * PDFPage, PDFPages and PDFRoot.</p> */ public class PDFRenderer extends PrintRenderer { @@ -89,25 +89,27 @@ public class PDFRenderer extends PrintRenderer { PDFColor currentColor; + float currentLetterSpacing = Float.NaN; + /** * true if a TJ command is left to be written */ boolean textOpen = false; /** - * the previous Y coordinate of the last word written. - * Used to decide if we can draw the next word on the same line. + * the previous Y coordinate of the last word written. Used to decide if we + * can draw the next word on the same line. */ int prevWordY = 0; /** - * the previous X coordinate of the last word written. - * used to calculate how much space between two words + * the previous X coordinate of the last word written. used to calculate + * how much space between two words */ int prevWordX = 0; /** - * The width of the previous word. Used to calculate space between + * The width of the previous word. Used to calculate space between */ int prevWordWidth = 0; @@ -132,6 +134,8 @@ public class PDFRenderer extends PrintRenderer { /** * set up renderer options + * + * @param options Options for the renderer */ public void setOptions(Hashtable options) { this.options = options; @@ -140,19 +144,31 @@ public class PDFRenderer extends PrintRenderer { /** * set the PDF document's producer * - * @param producer string indicating application producing PDF + * @param producer string indicating application producing PDF */ public void setProducer(String producer) { this.pdfDoc.setProducer(producer); } + /** + * Starts the renderer + * + * @param stream OutputStream to be written to + * @exception IOException In case of an IO problem + */ public void startRenderer(OutputStream stream) - throws IOException { + throws IOException { pdfDoc.outputHeader(stream); } + /** + * Called when the renderer has finished its work + * + * @param stream OutputStream to be written to + * @exception IOException In cas of an IO problem + */ public void stopRenderer(OutputStream stream) - throws IOException { + throws IOException { renderRootExtensions(extensions); FontSetup.addToResources(this.pdfDoc, fontInfo); pdfDoc.outputTrailer(stream); @@ -171,142 +187,217 @@ public class PDFRenderer extends PrintRenderer { /** * add a line to the current stream * - * @param x1 the start x location in millipoints - * @param y1 the start y location in millipoints - * @param x2 the end x location in millipoints - * @param y2 the end y location in millipoints - * @param th the thickness in millipoints - * @param r the red component - * @param g the green component - * @param b the blue component + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param stroke the stroke color/gradient */ protected void addLine(int x1, int y1, int x2, int y2, int th, - PDFPathPaint stroke) { + PDFPathPaint stroke) { closeText(); currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) - + (x1 / 1000f) + " " + (y1 / 1000f) + " m " - + (x2 / 1000f) + " " + (y2 / 1000f) + " l " - + (th / 1000f) + " w S\n" + "Q\nBT\n"); + + (x1 / 1000f) + " " + (y1 / 1000f) + " m " + + (x2 / 1000f) + " " + (y2 / 1000f) + " l " + + (th / 1000f) + " w S\n" + "Q\nBT\n"); } /** * add a line to the current stream * - * @param x1 the start x location in millipoints - * @param y1 the start y location in millipoints - * @param x2 the end x location in millipoints - * @param y2 the end y location in millipoints - * @param th the thickness in millipoints - * @param rs the rule style - * @param r the red component - * @param g the green component - * @param b the blue component + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param rs the rule style + * @param stroke the stroke color/gradient */ protected void addLine(int x1, int y1, int x2, int y2, int th, int rs, - PDFPathPaint stroke) { + PDFPathPaint stroke) { closeText(); currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) - + setRuleStylePattern(rs) + (x1 / 1000f) + " " - + (y1 / 1000f) + " m " + (x2 / 1000f) + " " - + (y2 / 1000f) + " l " + (th / 1000f) + " w S\n" - + "Q\nBT\n"); + + setRuleStylePattern(rs) + (x1 / 1000f) + " " + + (y1 / 1000f) + " m " + (x2 / 1000f) + " " + + (y2 / 1000f) + " l " + (th / 1000f) + " w S\n" + + "Q\nBT\n"); } /** * add a rectangle to the current stream * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param stroke the stroke color/gradient + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param stroke the stroke color/gradient */ protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke) { closeText(); currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) - + (x / 1000f) + " " + (y / 1000f) + " " - + (w / 1000f) + " " + (h / 1000f) + " re s\n" - + "Q\nBT\n"); + + (x / 1000f) + " " + (y / 1000f) + " " + + (w / 1000f) + " " + (h / 1000f) + " re s\n" + + "Q\nBT\n"); } /** * add a filled rectangle to the current stream * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param fill the fill color/gradient - * @param stroke the stroke color/gradient + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param fill the fill color/gradient + * @param stroke the stroke color/gradient */ protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke, - PDFPathPaint fill) { + PDFPathPaint fill) { closeText(); currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) - + stroke.getColorSpaceOut(false) + (x / 1000f) - + " " + (y / 1000f) + " " + (w / 1000f) + " " - + (h / 1000f) + " re b\n" + "Q\nBT\n"); + + stroke.getColorSpaceOut(false) + (x / 1000f) + + " " + (y / 1000f) + " " + (w / 1000f) + " " + + (h / 1000f) + " re b\n" + "Q\nBT\n"); } /** * add a filled rectangle to the current stream * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param fill the fill color/gradient + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param fill the fill color/gradient */ protected void addFilledRect(int x, int y, int w, int h, - PDFPathPaint fill) { + PDFPathPaint fill) { closeText(); currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) - + (x / 1000f) + " " + (y / 1000f) + " " - + (w / 1000f) + " " + (h / 1000f) + " re f\n" - + "Q\nBT\n"); + + (x / 1000f) + " " + (y / 1000f) + " " + + (w / 1000f) + " " + (h / 1000f) + " re f\n" + + "Q\nBT\n"); } /** - * render image area to PDF + * Renders an image, scaling it to the given width and height. If the + * scaled width and height is the same intrinsic size of the image, the + * image is not scaled. * - * @param area the image area to render + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text in non-bitmapped + * images. */ - public void renderImageArea(ImageArea area) { - // adapted from contribution by BoBoGi - int x = this.currentXPosition + area.getXOffset(); - int y = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - - this.currentYPosition -= h; - - FopImage img = area.getImage(); - if (img instanceof SVGImage) { + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + if (image instanceof SVGImage) { try { closeText(); - SVGDocument svg = ((SVGImage)img).getSVGDocument(); + SVGDocument svg = ((SVGImage) image).getSVGDocument(); currentStream.add("ET\nq\n"); - renderSVGDocument(svg, (int)x, (int)y, area.getFontState()); + renderSVGDocument(svg, x, y, fs); currentStream.add("Q\nBT\n"); } catch (FopImageException e) {} } else { - int xObjectNum = this.pdfDoc.addImage(img); + int xObjectNum = this.pdfDoc.addImage(image); closeText(); + currentStream.add("ET\nq\n" + (((float) w) / 1000f) + " 0 0 " + + (((float) h) / 1000f) + " " + + (((float) x) / 1000f) + " " + + (((float) y - h) / 1000f) + " cm\n" + "/Im" + + xObjectNum + " Do\nQ\nBT\n"); + } + } - currentStream.add("ET\nq\n" + (((float)w) / 1000f) + " 0 0 " - + (((float)h) / 1000f) + " " - + (((float)x) / 1000f) + " " - + (((float)(y - h)) / 1000f) + " cm\n" + "/Im" - + xObjectNum + " Do\nQ\nBT\n"); + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fs the font state to use when rendering text in non-bitmapped + * images. + * @param image the image to be painted + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + + float cx1 = ((float) x) / 1000f; + float cy1 = ((float) y - clipH) / 1000f; + + float cx2 = ((float) x + clipW) / 1000f; + float cy2 = ((float) y) / 1000f; + + int imgX = x - clipX; + int imgY = y - clipY; + + int imgW; + int imgH; + try { + // XXX: do correct unit conversion here.. + imgW = image.getWidth() * 1000; + imgH = image.getHeight() * 1000; + } catch (FopImageException fie) { + log.error("Error obtaining image width and height", fie); + return; + } + + if (image instanceof SVGImage) { + try { + closeText(); + + SVGDocument svg = ((SVGImage) image).getSVGDocument(); + currentStream.add("ET\nq\n" + + // clipping + cx1 + " " + cy1 + " m\n" + + cx2 + " " + cy1 + " l\n" + + cx2 + " " + cy2 + " l\n" + + cx1 + " " + cy2 + " l\n" + + "W\n" + + "n\n"); + renderSVGDocument(svg, imgX, imgY, fs); + currentStream.add("Q\nBT\n"); + } catch (FopImageException e) {} + + } else { + int xObjectNum = this.pdfDoc.addImage(image); + closeText(); + currentStream.add("ET\nq\n" + + // clipping + cx1 + " " + cy1 + " m\n" + + cx2 + " " + cy1 + " l\n" + + cx2 + " " + cy2 + " l\n" + + cx1 + " " + cy2 + " l\n" + + "W\n" + + "n\n" + + // image matrix + (((float) imgW) / 1000f) + " 0 0 " + + (((float) imgH) / 1000f) + " " + + (((float) imgX) / 1000f) + " " + + (((float) imgY - imgH) / 1000f) + " cm\n" + + "s\n" + + // the image itself + "/Im" + xObjectNum + " Do\nQ\nBT\n"); } - this.currentXPosition += area.getContentWidth(); } /** * render a foreign object area + * + * @param area the foreign object area to be rendered */ public void renderForeignObjectArea(ForeignObjectArea area) { // if necessary need to scale and align the content @@ -373,7 +464,7 @@ public class PDFRenderer extends PrintRenderer { /** * render SVG area to PDF * - * @param area the SVG area to render + * @param area the SVG area to render */ public void renderSVGArea(SVGArea area) { // place at the current instream offset @@ -382,20 +473,30 @@ public class PDFRenderer extends PrintRenderer { renderSVGDocument(area.getSVGDocument(), x, y, area.getFontState()); } + /** + * render SVG document to PDF + * + * @param doc the document to render + * @param x the x offset + * @param y the y offset + * @param fs the fontstate to use + */ protected void renderSVGDocument(Document doc, int x, int y, - FontState fs) { - float sx = 1, sy = -1; - int xOffset = x, yOffset = y; + FontState fs) { + float sx = 1; + float sy = -1; + int xOffset = x; + int yOffset = y; org.apache.fop.svg.SVGUserAgent userAgent - = new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); + = new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); userAgent.setLogger(log); GVTBuilder builder = new GVTBuilder(); BridgeContext ctx = new BridgeContext(userAgent); TextPainter textPainter = null; Boolean bl = - org.apache.fop.configuration.Configuration.getBooleanValue("strokeSVGText"); + org.apache.fop.configuration.Configuration.getBooleanValue("strokeSVGText"); if (bl == null || bl.booleanValue()) { textPainter = new StrokingTextPainter(); } else { @@ -404,21 +505,21 @@ public class PDFRenderer extends PrintRenderer { ctx.setTextPainter(textPainter); PDFAElementBridge aBridge = new PDFAElementBridge(); - aBridge.setCurrentTransform(new AffineTransform(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f)); + aBridge.setCurrentTransform(new AffineTransform(sx, 0, 0, + sy, xOffset / 1000f, yOffset / 1000f)); ctx.putBridge(aBridge); - GraphicsNode root; try { root = builder.build(ctx, doc); } catch (Exception e) { log.error("svg graphic could not be built: " - + e.getMessage(), e); + + e.getMessage(), e); return; } // get the 'width' and 'height' attributes of the SVG document - float w = (float)ctx.getDocumentSize().getWidth() * 1000f; - float h = (float)ctx.getDocumentSize().getHeight() * 1000f; + float w = (float) ctx.getDocumentSize().getWidth() * 1000f; + float h = (float) ctx.getDocumentSize().getHeight() * 1000f; ctx = null; builder = null; @@ -432,7 +533,7 @@ public class PDFRenderer extends PrintRenderer { currentStream.add(x / 1000f + " " + y / 1000f + " m\n"); currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n"); currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f - + " l\n"); + + " l\n"); currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n"); currentStream.add("h\n"); currentStream.add("W\n"); @@ -442,34 +543,36 @@ public class PDFRenderer extends PrintRenderer { // and positive is down and to the right. (0,0) is where the // viewBox puts it. currentStream.add(sx + " 0 0 " + sy + " " + xOffset / 1000f + " " - + yOffset / 1000f + " cm\n"); + + yOffset / 1000f + " cm\n"); - SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); - AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, w / 1000f, h / 1000f); - if(!at.isIdentity()) { + SVGSVGElement svg = ((SVGDocument) doc).getRootElement(); + AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, + w / 1000f, h / 1000f); + if (!at.isIdentity()) { double[] vals = new double[6]; at.getMatrix(vals); currentStream.add(PDFNumber.doubleOut(vals[0]) + " " - + PDFNumber.doubleOut(vals[1]) + " " - + PDFNumber.doubleOut(vals[2]) + " " - + PDFNumber.doubleOut(vals[3]) + " " - + PDFNumber.doubleOut(vals[4]) + " " - + PDFNumber.doubleOut(vals[5]) + " cm\n"); + + PDFNumber.doubleOut(vals[1]) + " " + + PDFNumber.doubleOut(vals[2]) + " " + + PDFNumber.doubleOut(vals[3]) + " " + + PDFNumber.doubleOut(vals[4]) + " " + + PDFNumber.doubleOut(vals[5]) + " cm\n"); } PDFGraphics2D graphics = new PDFGraphics2D(true, fs, pdfDoc, - currentFontName, - currentFontSize, - currentXPosition, - currentYPosition); - graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); + currentFontName, + currentFontSize, + currentXPosition, + currentYPosition); + graphics.setGraphicContext( + new org.apache.batik.ext.awt.g2d.GraphicContext()); try { root.paint(graphics); currentStream.add(graphics.getString()); } catch (Exception e) { log.error("svg graphic could not be rendered: " - + e.getMessage(), e); + + e.getMessage(), e); } currentAnnotList = graphics.getAnnotList(); @@ -480,7 +583,7 @@ public class PDFRenderer extends PrintRenderer { /** * render inline area to PDF * - * @param area inline area to render + * @param area inline area to render */ public void renderWordArea(WordArea area) { synchronized (_wordAreaPDF) { @@ -491,7 +594,7 @@ public class PDFRenderer extends PrintRenderer { boolean kerningAvailable = false; kerning = area.getFontState().getKerning(); - if (kerning != null &&!kerning.isEmpty()) { + if (kerning != null && !kerning.isEmpty()) { kerningAvailable = true; } @@ -500,13 +603,13 @@ public class PDFRenderer extends PrintRenderer { // This assumes that *all* CIDFonts use a /ToUnicode mapping boolean useMultiByte = false; - Font f = - (Font)area.getFontState().getFontInfo().getFonts().get(name); - if (f instanceof LazyFont){ - if(((LazyFont) f).getRealFont() instanceof CIDFont){ + Font f = (Font) area.getFontState(). + getFontInfo().getFonts().get(name); + if (f instanceof LazyFont) { + if (((LazyFont) f).getRealFont() instanceof CIDFont) { useMultiByte = true; } - }else if (f instanceof CIDFont){ + } else if (f instanceof CIDFont) { useMultiByte = true; } // String startText = useMultiByte ? "<FEFF" : "("; @@ -519,53 +622,59 @@ public class PDFRenderer extends PrintRenderer { this.currentFontName = name; this.currentFontSize = size; - pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n"); + pdf = pdf.append("/" + name + " " + ((float)size / 1000) + " Tf\n"); + } + + //Do letter spacing (must be outside of [..] TJ) + float letterspacing = + ((float) area.getFontState().getLetterSpacing()) / 1000; + if (letterspacing != this.currentLetterSpacing) { + this.currentLetterSpacing = letterspacing; + closeText(); + pdf.append(letterspacing).append(" Tc\n"); } PDFColor areaColor = null; if (this.currentFill instanceof PDFColor) { - areaColor = (PDFColor)this.currentFill; + areaColor = (PDFColor) this.currentFill; } - if (areaColor == null || areaColor.red() != (double)area.getRed() - || areaColor.green() != (double)area.getGreen() - || areaColor.blue() != (double)area.getBlue()) { - - areaColor = new PDFColor((double)area.getRed(), - (double)area.getGreen(), - (double)area.getBlue()); + if (areaColor == null || areaColor.red() != (double) area.getRed() + || areaColor.green() != (double) area.getGreen() + || areaColor.blue() != (double) area.getBlue()) { + areaColor = new PDFColor((double) area.getRed(), + (double) area.getGreen(), + (double) area.getBlue()); closeText(); this.currentFill = areaColor; pdf.append(this.currentFill.getColorSpaceOut(true)); } - int rx = this.currentXPosition; int bl = this.currentYPosition; addWordLines(area, rx, bl, size, areaColor); - if (!textOpen || bl != prevWordY) { closeText(); pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f) - + " Tm [" + startText); + + " Tm [" + startText); prevWordY = bl; textOpen = true; } else { // express the space between words in thousandths of an em int space = prevWordX - rx + prevWordWidth; - float emDiff = (float)space / (float)currentFontSize * 1000f; + float emDiff = (float) space / (float) currentFontSize * 1000f; // this prevents a problem in Acrobat Reader where large // numbers cause text to disappear or default to a limit if (emDiff < -33000) { closeText(); pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f) - + " Tm [" + startText); + + " Tm [" + startText); textOpen = true; } else { pdf.append(Float.toString(emDiff)); @@ -576,10 +685,9 @@ public class PDFRenderer extends PrintRenderer { prevWordWidth = area.getContentWidth(); prevWordX = rx; - String s; if (area.getPageNumberID() - != null) { // this text is a page number, so resolve it + != null) {// this text is a page number, so resolve it s = idReferences.getPageNumber(area.getPageNumberID()); if (s == null) { s = ""; @@ -596,7 +704,7 @@ public class PDFRenderer extends PrintRenderer { if (!useMultiByte) { if (ch > 127) { pdf.append("\\"); - pdf.append(Integer.toOctalString((int)ch)); + pdf.append(Integer.toOctalString((int) ch)); } else { switch (ch) { @@ -613,11 +721,10 @@ public class PDFRenderer extends PrintRenderer { } if (kerningAvailable && (i + 1) < l) { - addKerning(pdf, (new Integer((int)ch)), - (new Integer((int)area.getFontState().mapChar(s.charAt(i + 1)))), - kerning, startText, endText); + addKerning(pdf, (new Integer((int) ch)), + (new Integer((int) area.getFontState().mapChar(s.charAt(i + 1)))), + kerning, startText, endText); } - } pdf.append(endText); @@ -630,6 +737,9 @@ public class PDFRenderer extends PrintRenderer { /** * Convert a char to a multibyte hex representation + * + * @param c character to be converted + * @return the string representation of the character */ private String getUnicodeString(char c) { @@ -637,33 +747,31 @@ public class PDFRenderer extends PrintRenderer { byte[] uniBytes = null; try { - char[] a = { - c - }; + char[] a = {c}; uniBytes = new String(a).getBytes("UnicodeBigUnmarked"); } catch (Exception e) { // This should never fail + throw new org.apache.avalon.framework.CascadingRuntimeException("Incompatible VM", e); } - for (int i = 0; i < uniBytes.length; i++) { - int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) - : (int)uniBytes[i]; + int b = (uniBytes[i] < 0) ? (int) (256 + uniBytes[i]) + : (int) uniBytes[i]; String hexString = Integer.toHexString(b); - if (hexString.length() == 1) + if (hexString.length() == 1) { buf = buf.append("0" + hexString); - else + } else { buf = buf.append(hexString); + } } return buf.toString(); - } /** - * Checks to see if we have some text rendering commands open - * still and writes out the TJ command to the stream if we do + * Checks to see if we have some text rendering commands open still and + * writes out the TJ command to the stream if we do */ private void closeText() { if (textOpen) { @@ -675,20 +783,30 @@ public class PDFRenderer extends PrintRenderer { } private void addKerning(StringBuffer buf, Integer ch1, Integer ch2, - Hashtable kerning, String startText, - String endText) { - Hashtable kernPair = (Hashtable)kerning.get(ch1); + Hashtable kerning, String startText, + String endText) { + Hashtable kernPair = (Hashtable) kerning.get(ch1); if (kernPair != null) { - Integer width = (Integer)kernPair.get(ch2); + Integer width = (Integer) kernPair.get(ch2); if (width != null) { - buf.append(endText).append(-(width.intValue())).append(' ').append(startText); + buf.append(endText).append(-(width.intValue())). + append(' ').append(startText); } } } + + /** + * render page to PDF + * + * @param page the page render + * @param outputStream the target OutputStream + * @exception FOPException in case of an internal problem + * @exception IOException in case of an IO problem + */ public void render(Page page, OutputStream outputStream) - throws FOPException, IOException { + throws FOPException, IOException { // log.debug("rendering single page to PDF"); this.idReferences = page.getIDReferences(); this.pdfResources = this.pdfDoc.getResources(); @@ -696,7 +814,7 @@ public class PDFRenderer extends PrintRenderer { this.renderPage(page); Vector exts = page.getExtensions(); - if(exts != null) { + if (exts != null) { extensions = exts; } @@ -707,11 +825,14 @@ public class PDFRenderer extends PrintRenderer { /** * render page into PDF * - * @param page page to render + * @param page page to render */ public void renderPage(Page page) { BodyAreaContainer body; - AreaContainer before, after, start, end; + AreaContainer before; + AreaContainer after; + AreaContainer start; + AreaContainer end; currentStream = this.pdfDoc.makeStream(); body = page.getBody(); @@ -749,27 +870,28 @@ public class PDFRenderer extends PrintRenderer { currentStream.add("ET\n"); currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream, - Math.round(w / 1000), - Math.round(h / 1000), page); + Math.round(w / 1000), + Math.round(h / 1000), page); if (page.hasLinks() || currentAnnotList != null) { - if(currentAnnotList == null) { + if (currentAnnotList == null) { currentAnnotList = this.pdfDoc.makeAnnotList(); } currentPage.setAnnotList(currentAnnotList); Enumeration e = page.getLinkSets().elements(); while (e.hasMoreElements()) { - LinkSet linkSet = (LinkSet)e.nextElement(); + LinkSet linkSet = (LinkSet) e.nextElement(); linkSet.align(); String dest = linkSet.getDest(); int linkType = linkSet.getLinkType(); Enumeration f = linkSet.getRects().elements(); while (f.hasMoreElements()) { - LinkedRectangle lrect = (LinkedRectangle)f.nextElement(); - currentAnnotList.addLink(this.pdfDoc.makeLink(lrect.getRectangle(), - dest, linkType)); + LinkedRectangle lrect = (LinkedRectangle) f.nextElement(); + currentAnnotList.addLink( + this.pdfDoc.makeLink(lrect.getRectangle(), + dest, linkType)); } } currentAnnotList = null; @@ -784,6 +906,9 @@ public class PDFRenderer extends PrintRenderer { /** * defines a string containing dashArray and dashPhase for the rule style + * + * @param style the rule style + * @return PDF code to setup the rule style */ private String setRuleStylePattern(int style) { String rs = ""; @@ -806,13 +931,18 @@ public class PDFRenderer extends PrintRenderer { return rs; } + /** + * render root extensions such as outlines + * + * @param exts the list of root extensions to process + */ protected void renderRootExtensions(Vector exts) { if (exts != null) { Enumeration e = exts.elements(); while (e.hasMoreElements()) { - ExtensionObj ext = (ExtensionObj)e.nextElement(); + ExtensionObj ext = (ExtensionObj) e.nextElement(); if (ext instanceof Outline) { - renderOutline((Outline)ext); + renderOutline((Outline) ext); } } } @@ -824,19 +954,19 @@ public class PDFRenderer extends PrintRenderer { Outline parent = outline.getParentOutline(); if (parent == null) { pdfOutline = - this.pdfDoc.makeOutline(outlineRoot, - outline.getLabel().toString(), - outline.getInternalDestination()); + this.pdfDoc.makeOutline(outlineRoot, + outline.getLabel().toString(), + outline.getInternalDestination()); } else { PDFOutline pdfParentOutline = - (PDFOutline)parent.getRendererObject(); + (PDFOutline) parent.getRendererObject(); if (pdfParentOutline == null) { log.error("pdfParentOutline is null"); } else { pdfOutline = - this.pdfDoc.makeOutline(pdfParentOutline, - outline.getLabel().toString(), - outline.getInternalDestination()); + this.pdfDoc.makeOutline(pdfParentOutline, + outline.getLabel().toString(), + outline.getInternalDestination()); } } @@ -846,7 +976,7 @@ public class PDFRenderer extends PrintRenderer { Vector v = outline.getOutlines(); Enumeration e = v.elements(); while (e.hasMoreElements()) { - renderOutline((Outline)e.nextElement()); + renderOutline((Outline) e.nextElement()); } } diff --git a/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java b/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java index e780594f0..1654882c2 100644 --- a/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java +++ b/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java @@ -8,6 +8,7 @@ package org.apache.fop.render.pdf.fonts; import org.apache.fop.render.pdf.Font; +import org.apache.fop.render.pdf.CodePointMapping; import org.apache.fop.layout.FontDescriptor; import org.apache.fop.fonts.Glyphs; import org.apache.fop.pdf.PDFStream; @@ -24,6 +25,8 @@ import java.util.Hashtable; public class SingleByteFont extends Font implements FontDescriptor { public String fontName = null; public String encoding = "WinAnsiEncoding"; + private final CodePointMapping mapping + = CodePointMapping.getMapping("WinAnsiEncoding"); public int capHeight = 0; public int xHeight = 0; @@ -237,5 +240,13 @@ public class SingleByteFont extends Font implements FontDescriptor { return arr; } + public char mapChar(char c) { + char d = mapping.mapChar(c); + if(d != 0) + return d; + else + return '#'; + } + } diff --git a/src/org/apache/fop/render/ps/ASCII85EncodeFilter.java b/src/org/apache/fop/render/ps/ASCII85EncodeFilter.java deleted file mode 100644 index 887598868..000000000 --- a/src/org/apache/fop/render/ps/ASCII85EncodeFilter.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.render.ps; - -import java.io.*; - -public class ASCII85EncodeFilter implements Filter { - - private static final char ASCII85_ZERO = 'z'; - private static final char ASCII85_START = '!'; - private static final char ASCII85_EOL = '\n'; - private static final String ASCII85_EOD = "~>"; - private static final String ENCODING = "US-ASCII"; - - private static final long base85_4 = 85; - private static final long base85_3 = base85_4 * base85_4; - private static final long base85_2 = base85_3 * base85_4; - private static final long base85_1 = base85_2 * base85_4; - - protected ASCII85EncodeFilter() {} - - public long write(OutputStream out, byte[] buf, int len, - long bw) throws IOException { - // Assumption: len<80 - int line = (int)(bw % 80) + len; - if (line >= 80) { - int first = len - (line - 80); - out.write(buf, 0, first); - out.write(ASCII85_EOL); - out.write(buf, first, len - first); - } else { - out.write(buf, 0, len); - } - return bw + len; - } - - public void doFilter(InputStream in, - OutputStream out) throws IOException { - int total = 0; - int diff = 0; - long bw = 0; - - // first encode the majority of the data - // each 4 byte group becomes a 5 byte group - byte[] data = new byte[4]; - int bytes_read; - while ((bytes_read = in.read(data)) == data.length) { - long val = ((data[0] << 24) - & 0xff000000L) // note: must have the L at the - + ((data[1] << 16) & 0xff0000L) // end, otherwise you get into - + ((data[2] << 8) & 0xff00L) // weird signed value problems - + (data[3] & 0xffL); // cause we're using a full 32 bits - byte[] conv = convertWord(val); - - bw = write(out, conv, conv.length, bw); - } - - // now take care of the trailing few bytes. - // with n leftover bytes, we append 0 bytes to make a full group of 4 - // then convert like normal (except not applying the special zero rule) - // and write out the first n+1 bytes from the result - if ((bytes_read < data.length) && (bytes_read >= 0)) { - int n = data.length - bytes_read; - byte[] lastdata = new byte[4]; - int i = 0; - for (int j = 0; j < 4; j++) { - if (j < n) { - lastdata[j] = data[i++]; - } else { - lastdata[j] = 0; - } - } - - long val = ((lastdata[0] << 24) & 0xff000000L) - + ((lastdata[1] << 16) & 0xff0000L) - + ((lastdata[2] << 8) & 0xff00L) - + (lastdata[3] & 0xffL); - - byte[] conv; - // special rule for handling zeros at the end - if (val != 0) { - conv = convertWord(val); - } else { - conv = new byte[5]; - for (int j = 0; j < 5; j++) { - conv[j] = (byte)'!'; - } - } - // assert n+1 <= 5 - bw = write(out, conv, n + 1, bw); - // System.out.println("ASCII85 end of data was "+n+" bytes long"); - - } - // finally write the two character end of data marker - byte[] EOD = ASCII85_EOD.getBytes(); - bw = write(out, EOD, EOD.length, bw); - } - - /** - * This converts a 32 bit value (4 bytes) into 5 bytes using base 85. - * each byte in the result starts with zero at the '!' character so - * the resulting base85 number fits into printable ascii chars - * - * @param word the 32 bit unsigned (hence the long datatype) word - * @return 5 bytes (or a single byte of the 'z' character for word - * values of 0) - */ - private byte[] convertWord(long word) { - word = word & 0xffffffff; - if (word < 0) { - word = -word; - } - - if (word == 0) { - byte[] result = { - (byte)ASCII85_ZERO - }; - return result; - } else { - byte c1 = (byte)((word / base85_1) & 0xFF); - byte c2 = (byte)(((word - (c1 * base85_1)) / base85_2) & 0xFF); - byte c3 = - (byte)(((word - (c1 * base85_1) - (c2 * base85_2)) / base85_3) - & 0xFF); - byte c4 = - (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3)) / base85_4) - & 0xFF); - byte c5 = - (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3) - (c4 * base85_4))) - & 0xFF); - - byte[] ret = { - (byte)(c1 + ASCII85_START), (byte)(c2 + ASCII85_START), - (byte)(c3 + ASCII85_START), (byte)(c4 + ASCII85_START), - (byte)(c5 + ASCII85_START) - }; - - for (int i = 0; i < ret.length; i++) { - if (ret[i] < 33 || ret[i] > 117) { - System.out.println("Illegal char value " - + new Integer(ret[i])); - } - } - return ret; - } - } - - - public static InputStream filter(InputStream in) throws IOException { - ASCII85EncodeFilter myfilter = new ASCII85EncodeFilter(); - return FilterThread.filter(in, myfilter); - } - -} diff --git a/src/org/apache/fop/render/ps/ASCII85OutputStream.java b/src/org/apache/fop/render/ps/ASCII85OutputStream.java new file mode 100644 index 000000000..80adf8dab --- /dev/null +++ b/src/org/apache/fop/render/ps/ASCII85OutputStream.java @@ -0,0 +1,201 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ +package org.apache.fop.render.ps; + +import java.io.OutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; + +/** + * This class applies a ASCII85 encoding to the stream. + * + * @author <a href="mailto:jeremias.maerki@outline.ch">Jeremias Maerki</a> + * @version $Id$ + */ +public class ASCII85OutputStream extends FilterOutputStream + implements Finalizable { + + private static final int ZERO = 0x7A; //"z" + private static final byte[] ZERO_ARRAY = {(byte)ZERO}; + private static final int START = 0x21; //"!" + private static final int EOL = 0x0A; //"\n" + private static final byte[] EOD = {0x7E, 0x3E}; //"~>" + + private static final long base85_4 = 85; + private static final long base85_3 = base85_4 * base85_4; + private static final long base85_2 = base85_3 * base85_4; + private static final long base85_1 = base85_2 * base85_4; + + private static final boolean DEBUG = false; + + private int pos = 0; + private long buffer = 0; + private int posinline = 0; + private int bw = 0; + + + public ASCII85OutputStream(OutputStream out) { + super(out); + } + + + public void write(int b) throws IOException { + if (pos == 0) { + buffer += (b << 24) & 0xff000000L; + } else if (pos == 1) { + buffer += (b << 16) & 0xff0000L; + } else if (pos == 2) { + buffer += (b << 8) & 0xff00L; + } else { + buffer += b & 0xffL; + } + pos++; + + if (pos > 3) { + checkedWrite(convertWord(buffer)); + buffer = 0; + pos = 0; + } + } + + + private void checkedWrite(int b) throws IOException { + if (posinline == 80) { + out.write(EOL); bw++; + posinline = 0; + } + checkedWrite(b); + posinline++; + bw++; + } + + + private void checkedWrite(byte[] buf) throws IOException { + checkedWrite(buf, buf.length); + } + + + private void checkedWrite(byte[] buf , int len) throws IOException { + if (posinline + len > 80) { + int firstpart = len - (posinline + len - 80); + if (firstpart > 0) out.write(buf, 0, firstpart); + out.write(EOL); bw++; + int rest = len - firstpart; + if (rest > 0) out.write(buf, firstpart, rest); + posinline = rest; + } else { + out.write(buf, 0, len); + posinline += len; + } + bw += len; + } + + + /** + * This converts a 32 bit value (4 bytes) into 5 bytes using base 85. + * each byte in the result starts with zero at the '!' character so + * the resulting base85 number fits into printable ascii chars + * + * @param word the 32 bit unsigned (hence the long datatype) word + * @return 5 bytes (or a single byte of the 'z' character for word + * values of 0) + */ + private byte[] convertWord(long word) { + word = word & 0xffffffff; + + if (word == 0) { + return ZERO_ARRAY; + } else { + if (word < 0) { + word = -word; + } + byte c1 = (byte)((word / base85_1) & 0xFF); + byte c2 = (byte)(((word - (c1 * base85_1)) / base85_2) & 0xFF); + byte c3 = + (byte)(((word - (c1 * base85_1) - (c2 * base85_2)) / base85_3) + & 0xFF); + byte c4 = + (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3)) / base85_4) + & 0xFF); + byte c5 = + (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3) - (c4 * base85_4))) + & 0xFF); + + byte[] ret = { + (byte)(c1 + START), (byte)(c2 + START), + (byte)(c3 + START), (byte)(c4 + START), + (byte)(c5 + START) + }; + + if (DEBUG) { + for (int i = 0; i < ret.length; i++) { + if (ret[i] < 33 || ret[i] > 117) { + System.out.println("Illegal char value " + + new Integer(ret[i])); + } + } + } + return ret; + } + } + + + public void finalizeStream() throws IOException { + // now take care of the trailing few bytes. + // with n leftover bytes, we append 0 bytes to make a full group of 4 + // then convert like normal (except not applying the special zero rule) + // and write out the first n+1 bytes from the result + if (pos > 0) { + int rest = pos; + /* + byte[] lastdata = new byte[4]; + int i = 0; + for (int j = 0; j < 4; j++) { + if (j < rest) { + lastdata[j] = data[i++]; + } else { + lastdata[j] = 0; + } + } + + long val = ((lastdata[0] << 24) & 0xff000000L) + + ((lastdata[1] << 16) & 0xff0000L) + + ((lastdata[2] << 8) & 0xff00L) + + (lastdata[3] & 0xffL); + */ + + byte[] conv; + // special rule for handling zeros at the end + if (buffer != 0) { + conv = convertWord(buffer); + } else { + conv = new byte[5]; + for (int j = 0; j < 5; j++) { + conv[j] = (byte)'!'; + } + } + // assert rest+1 <= 5 + checkedWrite(conv, rest + 1); + } + // finally write the two character end of data marker + checkedWrite(EOD); + + flush(); + if (out instanceof Finalizable) { + ((Finalizable)out).finalizeStream(); + } + } + + + public void close() throws IOException { + finalizeStream(); + super.close(); + } + +} + + diff --git a/src/org/apache/fop/render/ps/ASCIIHexEncodeFilter.java b/src/org/apache/fop/render/ps/ASCIIHexEncodeFilter.java deleted file mode 100644 index 8a8c2d837..000000000 --- a/src/org/apache/fop/render/ps/ASCIIHexEncodeFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.render.ps; - -import java.io.*; - -public class ASCIIHexEncodeFilter implements Filter { - - private static final char ASCIIHEX_EOL = '\n'; - private static final String ASCIIHEX_EOD = ">"; - private static final String ENCODING = "US-ASCII"; - - protected ASCIIHexEncodeFilter() {} - - public long write(OutputStream out, byte[] buf, int len, - long bw) throws IOException { - boolean last = false; - int pos = 0; - int rest = len; - while (rest > 0) { - int restofline = 80 - (int)((bw + pos) % 80); - if (rest < restofline) { - // last line - restofline = rest; - last = true; - } - if (restofline > 0) { - out.write(buf, pos, restofline); - pos += restofline; - if (!last) - out.write(ASCIIHEX_EOL); - } - rest = len - pos; - } - return bw + len; - } - - public void doFilter(InputStream in, - OutputStream out) throws IOException { - long bw = 0; - byte[] buf = new byte[2048]; - int bytes_read; - StringBuffer sb = new StringBuffer(2048 * 2); - while ((bytes_read = in.read(buf)) != -1) { - sb.setLength(0); - for (int i = 0; i < bytes_read; i++) { - int val = (int)(buf[i] & 0xFF); - if (val < 16) - sb.append("0"); - sb.append(Integer.toHexString(val)); - } - bw = write(out, sb.toString().getBytes(ENCODING), bytes_read * 2, - bw); - } - byte[] eod = ASCIIHEX_EOD.getBytes(ENCODING); - bw = write(out, eod, eod.length, bw); - } - - public static InputStream filter(InputStream in) throws IOException { - ASCIIHexEncodeFilter myfilter = new ASCIIHexEncodeFilter(); - return FilterThread.filter(in, myfilter); - } - -} diff --git a/src/org/apache/fop/render/ps/ASCIIHexOutputStream.java b/src/org/apache/fop/render/ps/ASCIIHexOutputStream.java new file mode 100644 index 000000000..af37a73b4 --- /dev/null +++ b/src/org/apache/fop/render/ps/ASCIIHexOutputStream.java @@ -0,0 +1,81 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ +package org.apache.fop.render.ps; + +import java.io.OutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; + +/** + * This class applies a ASCII Hex encoding to the stream. + * + * @author <a href="mailto:jeremias.maerki@outline.ch">Jeremias Maerki</a> + * @version $Id$ + */ +public class ASCIIHexOutputStream extends FilterOutputStream { + + private static final int EOL = 0x0A; //"\n" + private static final int EOD = 0x3E; //">" + private static final int ZERO = 0x30; //"0" + private static final int NINE = 0x39; //"9" + private static final int A = 0x41; //"A" + private static final int ADIFF = A - NINE -1; + + private int posinline = 0; + + + public ASCIIHexOutputStream(OutputStream out) { + super(out); + } + + + public void write(int b) throws IOException { + b &= 0xFF; + + int digit1 = ((b & 0xF0) >> 4) + ZERO; + if (digit1 > NINE) digit1 += ADIFF; + out.write(digit1); + + int digit2 = (b & 0x0F) + ZERO; + if (digit2 > NINE) digit2 += ADIFF; + out.write(digit2); + + posinline++; + checkLineWrap(); + } + + + private void checkLineWrap() throws IOException { + //Maximum line length is 80 characters + if (posinline >= 40) { + out.write(EOL); + posinline = 0; + } + } + + + public void finalizeStream() throws IOException { + checkLineWrap(); + //Write closing character ">" + super.write(EOD); + + flush(); + if (out instanceof Finalizable) { + ((Finalizable)out).finalizeStream(); + } + } + + + public void close() throws IOException { + finalizeStream(); + super.close(); + } + + +} + + diff --git a/src/org/apache/fop/render/ps/Filter.java b/src/org/apache/fop/render/ps/Filter.java deleted file mode 100644 index 3d6f0034c..000000000 --- a/src/org/apache/fop/render/ps/Filter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.render.ps; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public interface Filter { - - public void doFilter(InputStream in, OutputStream out) throws IOException; -} - diff --git a/src/org/apache/fop/render/ps/FilterThread.java b/src/org/apache/fop/render/ps/FilterThread.java deleted file mode 100644 index b690c3225..000000000 --- a/src/org/apache/fop/render/ps/FilterThread.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.render.ps; - -import java.io.*; - -public class FilterThread extends Thread { - - private Filter filter; - private InputStream in; - private OutputStream out; - - private FilterThread(Filter filter, InputStream in, OutputStream out) { - this.filter = filter; - this.in = in; - this.out = out; - } - - public void run() { - try { - try { - this.filter.doFilter(in, out); - this.out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - finally { - this.filter = null; - this.in = null; - this.out = null; - } - } - - public static InputStream filter(InputStream in, - Filter filter) throws IOException { - PipedInputStream pin = new PipedInputStream(); - PipedOutputStream pout = new PipedOutputStream(pin); - FilterThread thread = new FilterThread(filter, in, pout); - thread.start(); - return pin; - } - -} diff --git a/src/org/apache/fop/render/ps/Finalizable.java b/src/org/apache/fop/render/ps/Finalizable.java new file mode 100644 index 000000000..d7c77d668 --- /dev/null +++ b/src/org/apache/fop/render/ps/Finalizable.java @@ -0,0 +1,30 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ +package org.apache.fop.render.ps; + +/** + * This interface is used for special FilteredOutputStream classes that won't + * be closed (since this causes the target OutputStream to be closed, too) but + * where flush() is not enough, for example because a final marker has to be + * written to the target stream. + * + * @author <a href="mailto:jeremias.maerki@outline.ch">Jeremias Maerki</a> + * @version $Id$ + */ +public interface Finalizable { + + /** + * This method can be called instead of close() on a subclass of + * FilteredOutputStream when a final marker has to be written to the target + * stream, but close() cannot be called. + * + * @exception java.io.IOException In case of an IO problem + */ + public void finalizeStream() + throws java.io.IOException; + +} diff --git a/src/org/apache/fop/render/ps/FlateEncodeFilter.java b/src/org/apache/fop/render/ps/FlateEncodeFilter.java deleted file mode 100644 index bde626713..000000000 --- a/src/org/apache/fop/render/ps/FlateEncodeFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.render.ps; - -import java.io.*; -import java.util.zip.DeflaterOutputStream; - -public class FlateEncodeFilter implements Filter { - - protected FlateEncodeFilter() {} - - private long copyStream(InputStream in, OutputStream out, - int bufferSize) throws IOException { - long bytes_total = 0; - byte[] buf = new byte[bufferSize]; - int bytes_read; - while ((bytes_read = in.read(buf)) != -1) { - bytes_total += bytes_read; - out.write(buf, 0, bytes_read); - } - return bytes_total; - } - - public void doFilter(InputStream in, - OutputStream out) throws IOException { - DeflaterOutputStream dout = new DeflaterOutputStream(out); - copyStream(in, dout, 2048); - // dout.flush(); - dout.close(); - } - - public static InputStream filter(InputStream in) throws IOException { - FlateEncodeFilter myfilter = new FlateEncodeFilter(); - return FilterThread.filter(in, myfilter); - } - -} diff --git a/src/org/apache/fop/render/ps/FlateEncodeOutputStream.java b/src/org/apache/fop/render/ps/FlateEncodeOutputStream.java new file mode 100644 index 000000000..e6d96b8e9 --- /dev/null +++ b/src/org/apache/fop/render/ps/FlateEncodeOutputStream.java @@ -0,0 +1,39 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ +package org.apache.fop.render.ps; + +import java.io.OutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; + +/** + * This class applies a FlateEncode filter to the stream. It is basically the + * normal DeflaterOutputStream except now conformi + * + * @author <a href="mailto:jeremias.maerki@outline.ch">Jeremias Maerki</a> + * @version $Id$ + */ +public class FlateEncodeOutputStream extends java.util.zip.DeflaterOutputStream + implements Finalizable { + + + public FlateEncodeOutputStream(OutputStream out) { + super(out); + } + + + public void finalizeStream() throws IOException { + finish(); + flush(); + if (out instanceof Finalizable) { + ((Finalizable)out).finalizeStream(); + } + } + +} + + diff --git a/src/org/apache/fop/render/ps/PSGraphics2D.java b/src/org/apache/fop/render/ps/PSGraphics2D.java index 67859e351..d2fe4d3b2 100644 --- a/src/org/apache/fop/render/ps/PSGraphics2D.java +++ b/src/org/apache/fop/render/ps/PSGraphics2D.java @@ -245,6 +245,9 @@ public class PSGraphics2D extends AbstractGraphics2D { this.m_bitmaps = result; this.m_mask = mask; } + public boolean invertImage() { +return false; +} public String getURL() { return "" + m_bitmaps; diff --git a/src/org/apache/fop/render/ps/PSRenderer.java b/src/org/apache/fop/render/ps/PSRenderer.java index d380f54ef..4d0da9bdc 100644 --- a/src/org/apache/fop/render/ps/PSRenderer.java +++ b/src/org/apache/fop/render/ps/PSRenderer.java @@ -1,6 +1,6 @@ /* * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ @@ -14,12 +14,14 @@ import org.apache.fop.render.Renderer; import org.apache.fop.image.ImageArea; import org.apache.fop.image.FopImage; import org.apache.fop.image.FopImageException; +import org.apache.fop.image.JpegImage; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; import org.apache.fop.datatypes.*; import org.apache.fop.fo.properties.*; import org.apache.fop.render.pdf.Font; import org.apache.fop.image.*; +import org.apache.fop.apps.FOPException; import org.apache.batik.bridge.*; import org.apache.batik.swing.svg.*; @@ -29,8 +31,6 @@ import org.apache.batik.gvt.renderer.*; import org.apache.batik.gvt.filter.*; import org.apache.batik.gvt.event.*; -import org.apache.log.Logger; - // SVG import org.w3c.dom.svg.SVGSVGElement; import org.w3c.dom.svg.SVGDocument; @@ -51,29 +51,42 @@ import java.awt.Point; import java.awt.RenderingHints; import java.awt.Dimension; +/* +PostScript renderer + +Remarks: +- If anyone modifies this renderer please make sure to also follow the DSC to + make it simpler to programmatically modify the generated Postscript files + (ex. extract pages etc.). +- The filters in use are hardcoded at the moment. +- Modified by Mark Lillywhite mark-fop@inomial.com, to use the new + Renderer interface. This PostScript renderer appears to be the + most efficient at producing output. + +TODO-List: +- Character size/spacing +- SVG Transcoder for Batik +- configuration +- move to PrintRenderer +- maybe improve filters (I'm not very proud of them) +- add a RunLengthEncode filter (useful for Level 2 Postscript) +- Improve DocumentProcessColors stuff (probably needs to be configurable, then maybe + add a color to grayscale conversion for bitmaps to make output smaller (See + PCLRenderer) +- enhanced font support and font embedding +- support different character encodings +- try to implement image transparency +- Add PPD support +- fix border painting (see table.fo) + +*/ + /** * Renderer that renders to PostScript. * <br> * This class currently generates PostScript Level 2 code. The only exception - * is the FlateEncode filter which is a Level 3 feature. The filters in use - * are hardcoded at the moment. - * <br> - * This class follows the Document Structuring Conventions (DSC) version 3.0 - * (If I did everything right). If anyone modifies this renderer please make - * sure to also follow the DSC to make it simpler to programmatically modify - * the generated Postscript files (ex. extract pages etc.). - * <br> - * TODO: Character size/spacing, SVG Transcoder for Batik, configuration, move - * to PrintRenderer, maybe improve filters (I'm not very proud of them), add a - * RunLengthEncode filter (useful for Level 2 Postscript), Improve - * DocumentProcessColors stuff (probably needs to be configurable, then maybe - * add a color to grayscale conversion for bitmaps to make output smaller (See - * PCLRenderer), font embedding, support different character encodings, try to - * implement image transparency, positioning of images is wrong etc. <P> - * - * Modified by Mark Lillywhite mark-fop@inomial.com, to use the new - * Renderer interface. This PostScript renderer appears to be the - * most efficient at producing output. + * is the FlateEncode filter which is a Level 3 feature. The PostScript code + * generated follows the Document Structuring Conventions (DSC) version 3.0. * * @author Jeremias Mrki */ @@ -85,6 +98,7 @@ public class PSRenderer extends AbstractRenderer { protected String producer; int imagecount = 0; // DEBUG + int pagecount = 0; private boolean enableComments = true; @@ -147,20 +161,25 @@ public class PSRenderer extends AbstractRenderer { write(comment); } - protected void writeFontDict(FontInfo fontInfo) { - write("%%BeginResource: procset FOPFonts"); - write("%%Title: Font setup (shortcuts) for this file"); - write("/FOPFonts 100 dict dup begin"); + protected void writeProcs() { + write("%%BeginResource: procset FOPprocs"); + write("%%Title: Utility procedures"); + write("/FOPprocs 20 dict dup begin"); write("/bd{bind def}bind def"); write("/ld{load def}bd"); write("/M/moveto ld"); write("/RM/rmoveto ld"); write("/t/show ld"); + write("/A/ashow ld"); + write("/cp/closepath ld"); + write("/re {4 2 roll M"); //define rectangle + write("1 index 0 rlineto"); + write("0 exch rlineto"); + write("neg 0 rlineto"); + write("cp } bd"); write("/ux 0.0 def"); write("/uy 0.0 def"); - // write("/cf /Helvetica def"); - // write("/cs 12000 def"); // <font> <size> F write("/F {"); @@ -210,9 +229,14 @@ public class PSRenderer extends AbstractRenderer { write(" Tt setlinewidth stroke"); write(" grestore"); write("} bd"); + write("end def"); + write("%%EndResource"); + } - - + protected void writeFontDict(FontInfo fontInfo) { + write("%%BeginResource: procset FOPFonts"); + write("%%Title: Font setup (shortcuts) for this file"); + write("/FOPFonts 100 dict dup begin"); // write("/gfF1{/Helvetica findfont} bd"); // write("/gfF3{/Helvetica-Bold findfont} bd"); Hashtable fonts = fontInfo.getFonts(); @@ -224,6 +248,8 @@ public class PSRenderer extends AbstractRenderer { } write("end def"); write("%%EndResource"); + + //Rewrite font encodings enum = fonts.keys(); while (enum.hasMoreElements()) { String key = (String)enum.nextElement(); @@ -247,7 +273,8 @@ public class PSRenderer extends AbstractRenderer { * * @param fontInfo the font info object to set up */ - public void setupFontInfo(FontInfo fontInfo) { + public void setupFontInfo(FontInfo fontInfo) + throws FOPException { /* use PDF's font setup to get PDF metrics */ org.apache.fop.render.pdf.FontSetup.setup(fontInfo); this.fontInfo = fontInfo; @@ -255,13 +282,21 @@ public class PSRenderer extends AbstractRenderer { protected void addFilledRect(int x, int y, int w, int h, ColorType col) { + // XXX: cater for braindead, legacy -ve heights + if (h < 0) { + h = -h; + } + write("newpath"); + write(x + " " + y + " " + w + " " + -h + " re"); + /* write(x + " " + y + " M"); write(w + " 0 rlineto"); write("0 " + (-h) + " rlineto"); write((-w) + " 0 rlineto"); write("0 " + h + " rlineto"); write("closepath"); + */ useColor(col); write("fill"); } @@ -282,7 +317,17 @@ public class PSRenderer extends AbstractRenderer { */ public void renderForeignObjectArea(ForeignObjectArea area) { // if necessary need to scale and align the content + this.currentXPosition = this.currentXPosition + area.getXOffset(); + int plOffset = 0; + Area parent = area.getParent(); + if (parent instanceof LineArea) { + plOffset = ((LineArea)parent).getPlacementOffset(); + } + this.currentYPosition += plOffset; area.getObject().render(this); + this.currentXPosition += area.getEffectiveWidth(); + this.currentYPosition -= plOffset; + movetoCurrPosition(); } /** @@ -293,8 +338,20 @@ public class PSRenderer extends AbstractRenderer { public void renderSVGArea(SVGArea area) { int x = this.currentXPosition; int y = this.currentYPosition; - Document doc = area.getSVGDocument(); + renderSVGDocument(area.getSVGDocument(), x, y, area.getFontState()); + } + + /** + * render SVG document to PostScript + * + * @param doc the document to render + * @param x the x offset + * @param y the y offset + * @param fs the fontstate to use + */ + protected void renderSVGDocument(Document doc, int x, int y, + FontState fs) { org.apache.fop.svg.SVGUserAgent userAgent = new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); userAgent.setLogger(log); @@ -303,16 +360,19 @@ public class PSRenderer extends AbstractRenderer { BridgeContext ctx = new BridgeContext(userAgent); GraphicsNode root; - try { + try { root = builder.build(ctx, doc); - } catch (Exception e) { + } catch (Exception e) { log.error("svg graphic could not be built: " - + e.getMessage(), e); + + e.getMessage(), e); return; } // get the 'width' and 'height' attributes of the SVG document float w = (float)ctx.getDocumentSize().getWidth() * 1000f; float h = (float)ctx.getDocumentSize().getHeight() * 1000f; + + //log.debug("drawing SVG image: "+x+"/"+y+" "+w+"/"+h); + ctx = null; builder = null; @@ -336,7 +396,7 @@ public class PSRenderer extends AbstractRenderer { write(xOffset + " " + yOffset + " translate"); write(sx + " " + sy + " scale"); - PSGraphics2D graphics = new PSGraphics2D(false, area.getFontState(), + PSGraphics2D graphics = new PSGraphics2D(false, fs, this, currentFontName, currentFontSize, currentXPosition, @@ -352,7 +412,98 @@ public class PSRenderer extends AbstractRenderer { write("grestore"); comment("% --- SVG Area end"); - movetoCurrPosition(); + } + + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + //log.debug("drawing scaled image: "+x+"/"+y+" "+w+"/"+h); + if (image instanceof SVGImage) { + try { + renderSVGDocument(((SVGImage)image).getSVGDocument(), x, y, fs); + } catch (FopImageException e) { + log.error("Error rendering SVG image", e); + } + } else if (image instanceof EPSImage) { + renderEPS(image, x, y, w, h); + } else { + renderBitmap(image, x, y, w, h); + } + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + //log.debug("drawing clipped image: "+x+"/"+y+" "+clipX+"/"+clipY+" "+clipW+"/"+clipH); + write("gsave"); + write(clipX + " " + clipY + " " + clipW + " " + clipH + " re"); + write("clippath"); + + try { + int w = image.getWidth() * 1000; + int h = image.getHeight() * 1000; + + drawImageScaled(x, y, w, h, image, fs); + } catch (FopImageException e) { + log.error("Error getting image extents", e); + } + write("grestore"); + } + + public void renderEPS(FopImage img, int x, int y, int w, int h) { + try { + EPSImage eimg = (EPSImage)img; + int[] bbox = eimg.getBBox(); + int bboxw = bbox[2] - bbox[0]; + int bboxh = bbox[3] - bbox[1]; + + + write("%%BeginDocument: " + eimg.getDocName()); + write("BeginEPSF"); + + write(x + " " + (y - h) + " translate"); + write("0.0 rotate"); + write((long)(w/bboxw) + " " + (long)(h/bboxh) + " scale"); + write(-bbox[0] + " " + (-bbox[1]) + " translate"); + write(bbox[0] + " " + bbox[1] + " " + bboxw + " " + bboxh + " rectclip"); + write("newpath"); + out.writeByteArr(img.getBitmaps()); + write("%%EndDocument"); + write("EndEPSF"); + write(""); + } catch (Exception e) { + e.printStackTrace(); + log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" + + e.getMessage() + ")", e); + } } public void renderBitmap(FopImage img, int x, int y, int w, int h) { @@ -362,7 +513,11 @@ public class PSRenderer extends AbstractRenderer { byte[] imgmap = img.getBitmaps(); write("gsave"); - write("/DeviceRGB setcolorspace"); + if (img.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK) + write("/DeviceCMYK setcolorspace"); + else + write("/DeviceRGB setcolorspace"); + write(x + " " + (y - h) + " translate"); write(w + " " + h + " scale"); write("<<"); @@ -370,7 +525,12 @@ public class PSRenderer extends AbstractRenderer { write(" /Width " + img.getWidth()); write(" /Height " + img.getHeight()); write(" /BitsPerComponent 8"); - if (iscolor) { + if (img.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK) { + if (img.invertImage()) + write(" /Decode [1 0 1 0 1 0 1 0]"); + else + write(" /Decode [0 1 0 1 0 1 0 1]"); + } else if (iscolor) { write(" /Decode [0 1 0 1 0 1]"); } else { write(" /Decode [0 1]"); @@ -378,7 +538,11 @@ public class PSRenderer extends AbstractRenderer { // Setup scanning for left-to-right and top-to-bottom write(" /ImageMatrix [" + img.getWidth() + " 0 0 -" + img.getHeight() + " 0 " + img.getHeight() + "]"); - write(" /DataSource currentfile /ASCII85Decode filter /FlateDecode filter"); + + if (img instanceof JpegImage) + write(" /DataSource currentfile /ASCII85Decode filter /DCTDecode filter"); + else + write(" /DataSource currentfile /ASCII85Decode filter /FlateDecode filter"); // write(" /DataSource currentfile /ASCIIHexDecode filter /FlateDecode filter"); // write(" /DataSource currentfile /ASCII85Decode filter /RunLengthDecode filter"); // write(" /DataSource currentfile /ASCIIHexDecode filter /RunLengthDecode filter"); @@ -405,14 +569,13 @@ public class PSRenderer extends AbstractRenderer { */ try { // imgmap[0] = 1; - InputStream bain = new ByteArrayInputStream(imgmap); - InputStream in; - in = bain; - in = FlateEncodeFilter.filter(in); - // in = RunLengthEncodeFilter.filter(in); - // in = ASCIIHexEncodeFilter.filter(in); - in = ASCII85EncodeFilter.filter(in); - copyStream(in, this.out); + OutputStream out = this.out; + out = new ASCII85OutputStream(out); + if (!(img instanceof JpegImage)) { + out = new FlateEncodeOutputStream(out); + } + out.write(imgmap); + ((Finalizable)out).finalizeStream(); } catch (IOException e) { if (!ioTrouble) e.printStackTrace(); @@ -428,13 +591,48 @@ public class PSRenderer extends AbstractRenderer { } /** + * Render an image area. + * + * @param area the image area to render + */ + public void renderImageArea(ImageArea area) { + // adapted from contribution by BoBoGi + int x = this.currentXPosition + area.getXOffset(); + int ploffset = 0; + if (area.getParent() instanceof LineArea) { + ploffset = ((LineArea)area.getParent()).getPlacementOffset(); + } + int y = this.currentYPosition + ploffset; + int w = area.getContentWidth(); + int h = area.getHeight(); + + //this.currentYPosition -= h; + this.currentXPosition += w; + + FopImage img = area.getImage(); + + if (img == null) { + log.error("Error while loading image: area.getImage() is null"); + } else { + drawImageScaled(x, y, w, h, img, area.getFontState()); + } + movetoCurrPosition(); + } + + + /** * render an image area to PostScript * * @param area the area to render */ + /* public void renderImageArea(ImageArea area) { - int x = this.currentAreaContainerXPosition + area.getXOffset(); - int y = this.currentYPosition; + int x = this.currentXPosition + area.getXOffset(); + int ploffset = 0; + if (area.getParent() instanceof LineArea) { + ploffset = ((LineArea)area.getParent()).getPlacementOffset(); + } + int y = this.currentYPosition + ploffset; int w = area.getContentWidth(); int h = area.getHeight(); this.currentYPosition -= area.getHeight(); @@ -443,30 +641,15 @@ public class PSRenderer extends AbstractRenderer { // if (imagecount!=4) return; comment("% --- ImageArea"); - if (area.getImage() instanceof SVGImage) {} - else { + if (area.getImage() instanceof SVGImage) { + renderSVGDocument(((SVGImage)area.getImage()).getSVGDocument(), x, y, area.getFontState()); + } else if (area.getImage() instanceof EPSImage) { + renderEPS(area.getImage(), x, y, w, h); + } else { renderBitmap(area.getImage(), x, y, w, h); } comment("% --- ImageArea end"); - } - - private long copyStream(InputStream in, OutputStream out, - int bufferSize) throws IOException { - long bytes_total = 0; - byte[] buf = new byte[bufferSize]; - int bytes_read; - while ((bytes_read = in.read(buf)) != -1) { - bytes_total += bytes_read; - out.write(buf, 0, bytes_read); - } - return bytes_total; - } - - - private long copyStream(InputStream in, - OutputStream out) throws IOException { - return copyStream(in, out, 4096); - } + }*/ /** * render an inline area to PostScript @@ -474,6 +657,7 @@ public class PSRenderer extends AbstractRenderer { * @param area the area to render */ public void renderWordArea(WordArea area) { + movetoCurrPosition(); FontState fs = area.getFontState(); String fontWeight = fs.getFontWeight(); StringBuffer sb = new StringBuffer(); @@ -488,7 +672,7 @@ public class PSRenderer extends AbstractRenderer { s = area.getText(); } int l = s.length(); - + for (int i = 0; i < l; i++) { char ch = s.charAt(i); char mch = fs.mapChar(ch); @@ -502,6 +686,18 @@ public class PSRenderer extends AbstractRenderer { sb = sb.append(mch); } } + + String psString = null; + if (area.getFontState().getLetterSpacing() > 0) { + //float f = area.getFontState().getLetterSpacing() * 1000 / this.currentFontSize; + float f = area.getFontState().getLetterSpacing(); + psString = (new StringBuffer().append(f).append(" 0.0 (").append(sb). + append(") A")).toString(); + } else { + psString = (new StringBuffer("(").append(sb).append(") t")).toString(); + } + + // System.out.println("["+s+"] --> ["+sb.toString()+"]"); // comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString()); @@ -510,7 +706,7 @@ public class PSRenderer extends AbstractRenderer { if (area.getUnderlined() || area.getLineThrough() || area.getOverlined()) write("ULS"); - write("(" + sb.toString() + ") t"); + write(psString); if (area.getUnderlined()) write("ULE"); if (area.getLineThrough()) @@ -535,17 +731,23 @@ public class PSRenderer extends AbstractRenderer { */ public void renderInlineSpace(InlineSpace space) { // write("% --- InlineSpace size="+space.getSize()); - this.currentXPosition += space.getSize(); if (space.getUnderlined() || space.getLineThrough() - || space.getOverlined()) + || space.getOverlined()) { + //start textdeko + movetoCurrPosition(); write("ULS"); - write(space.getSize() + " 0 RM"); - if (space.getUnderlined()) - write("ULE"); - if (space.getLineThrough()) - write("SOE"); - if (space.getOverlined()) - write("OLE"); + + write(space.getSize() + " 0 RM"); + + //end textdeko + if (space.getUnderlined()) + write("ULE"); + if (space.getLineThrough()) + write("SOE"); + if (space.getOverlined()) + write("OLE"); + } + this.currentXPosition += space.getSize(); } /** @@ -567,14 +769,14 @@ public class PSRenderer extends AbstractRenderer { movetoCurrPosition(); String fontWeight = area.getFontState().getFontWeight(); - // comment("% --- LineArea begin font-weight="+fontWeight); + //comment("% --- LineArea begin font-weight="+fontWeight); Enumeration e = area.getChildren().elements(); while (e.hasMoreElements()) { Box b = (Box)e.nextElement(); this.currentYPosition = ry - area.getPlacementOffset(); b.render(this); } - // comment("% --- LineArea end"); + //comment("% --- LineArea end"); this.currentYPosition = ry - h; this.currentXPosition = rx; @@ -586,12 +788,17 @@ public class PSRenderer extends AbstractRenderer { * @param page the page to render */ public void renderPage(Page page) { + this.pagecount++; this.idReferences = page.getIDReferences(); BodyAreaContainer body; AreaContainer before, after; write("%%Page: " + page.getNumber() + " " + page.getNumber()); + write("%%PageBoundingBox: 0 0 " + + Math.round(page.getWidth() / 1000f) + " " + + Math.round(page.getHeight() / 1000f)); write("%%BeginPageSetup"); + write("FOPprocs begin"); write("FOPFonts begin"); write("0.001 0.001 scale"); write("%%EndPageSetup"); @@ -607,7 +814,7 @@ public class PSRenderer extends AbstractRenderer { } write("showpage"); write("%%PageTrailer"); - write("%%EndPage"); + write("%%EndPage"); //This is non-standard, but used by Adobe. } /** @@ -736,22 +943,7 @@ public class PSRenderer extends AbstractRenderer { w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); - // Create a textrect with these dimensions. - // The y co-ordinate is measured +ve downwards so subtract page-height - - ColorType bg = area.getBackgroundColor(); - if ((bg != null) && (bg.alpha() == 0)) { - write("newpath"); - write(rx + " " + ry + " M"); - write(w + " 0 rlineto"); - write("0 " + (-h) + " rlineto"); - write((-w) + " 0 rlineto"); - write("0 " + h + " rlineto"); - write("closepath"); - useColor(bg); - write("fill"); - } - + doBackground(area, rx, ry, w, h); if (area.getBorderTopWidth() != 0) { write("newpath"); @@ -812,9 +1004,14 @@ public class PSRenderer extends AbstractRenderer { throws IOException { log.debug("rendering areas to PostScript"); + this.pagecount = 0; this.out = new PSStream(outputStream); write("%!PS-Adobe-3.0"); + if (this.producer == null) { + this.producer = org.apache.fop.apps.Version.getVersion(); + } write("%%Creator: "+this.producer); + write("%%Pages: (atend)"); write("%%DocumentProcessColors: Black"); write("%%DocumentSuppliedResources: procset FOPFonts"); write("%%EndComments"); @@ -823,9 +1020,38 @@ public class PSRenderer extends AbstractRenderer { write("%%BeginProlog"); write("%%EndProlog"); write("%%BeginSetup"); + writeProcs(); writeFontDict(fontInfo); + + /* Write proc for including EPS */ + write("%%BeginResource: procset EPSprocs"); + write("%%Title: EPS encapsulation procs"); + + write("/BeginEPSF { %def"); + write("/b4_Inc_state save def % Save state for cleanup"); + write("/dict_count countdictstack def % Count objects on dict stack"); + write("/op_count count 1 sub def % Count objects on operand stack"); + write("userdict begin % Push userdict on dict stack"); + write("/showpage { } def % Redefine showpage, { } = null proc"); + write("0 setgray 0 setlinecap % Prepare graphics state"); + write("1 setlinewidth 0 setlinejoin"); + write("10 setmiterlimit [ ] 0 setdash newpath"); + write("/languagelevel where % If level not equal to 1 then"); + write("{pop languagelevel % set strokeadjust and"); + write("1 ne % overprint to their defaults."); + write("{false setstrokeadjust false setoverprint"); + write("} if"); + write("} if"); + write("} bind def"); + + write("/EndEPSF { %def"); + write("count op_count sub {pop} repeat % Clean up stacks"); + write("countdictstack dict_count sub {end} repeat"); + write("b4_Inc_state restore"); + write("} bind def"); + write("%%EndResource"); + write("%%EndSetup"); - write("FOPFonts begin"); } /** @@ -835,6 +1061,7 @@ public class PSRenderer extends AbstractRenderer { public void stopRenderer(OutputStream outputStream) throws IOException { write("%%Trailer"); + write("%%Pages: "+this.pagecount); write("%%EOF"); this.out.flush(); log.debug("written out PostScript"); diff --git a/src/org/apache/fop/render/ps/PSStream.java b/src/org/apache/fop/render/ps/PSStream.java index 9b03c11fd..f752b7148 100644 --- a/src/org/apache/fop/render/ps/PSStream.java +++ b/src/org/apache/fop/render/ps/PSStream.java @@ -22,4 +22,8 @@ public class PSStream extends FilterOutputStream { write('\n'); } + public void writeByteArr(byte[] cmd) throws IOException { + write(cmd); + write('\n'); + } } diff --git a/src/org/apache/fop/render/svg/SVGRenderer.java b/src/org/apache/fop/render/svg/SVGRenderer.java index 23b16c9be..0c05bb3e9 100644 --- a/src/org/apache/fop/render/svg/SVGRenderer.java +++ b/src/org/apache/fop/render/svg/SVGRenderer.java @@ -9,28 +9,21 @@ package org.apache.fop.render.svg; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; -import org.apache.fop.datatypes.*; +import org.apache.fop.datatypes.IDReferences; +import org.apache.fop.datatypes.ColorType; import org.apache.fop.image.*; -import org.apache.fop.svg.*; -import org.apache.fop.render.pdf.*; -import org.apache.fop.render.awt.*; -import org.apache.fop.viewer.*; -import org.apache.fop.apps.*; +import org.apache.fop.svg.SVGArea; import org.apache.fop.svg.SVGUtilities; +import org.apache.fop.apps.FOPException; -import org.w3c.dom.*; -import org.w3c.dom.svg.*; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.svg.SVGSVGElement; +import org.w3c.dom.svg.SVGDocument; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.DOMImplementation; -import org.apache.batik.bridge.*; -import org.apache.batik.swing.svg.*; -import org.apache.batik.swing.gvt.*; -import org.apache.batik.gvt.*; -import org.apache.batik.gvt.renderer.*; -import org.apache.batik.gvt.filter.*; -import org.apache.batik.gvt.event.*; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGOMElement; import org.apache.batik.dom.util.XMLSupport; @@ -39,27 +32,20 @@ import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.TranscoderException; -import java.awt.*; +import java.awt.Color; import java.awt.Image; -import java.awt.image.*; -import java.awt.geom.*; -import java.awt.font.*; -import java.util.*; +import java.awt.image.BufferedImage; +import java.awt.geom.Rectangle2D; +import java.util.Hashtable; import java.net.URL; import java.net.MalformedURLException; -import java.io.*; -import java.beans.*; -import javax.swing.*; -import java.awt.print.*; -import java.awt.image.BufferedImage; -import java.text.*; +import java.io.OutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import javax.swing.ImageIcon; import org.apache.fop.render.AbstractRenderer; -import org.apache.batik.util.SVGConstants; -import org.apache.batik.svggen.SVGGraphics2D; -import org.apache.batik.dom.svg.ExtensibleSVGDOMImplementation; - public class SVGRenderer extends AbstractRenderer { static final String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; Document svgDocument; @@ -307,19 +293,13 @@ public class SVGRenderer extends AbstractRenderer { h = area.getContentHeight(); int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); rx = rx - area.getPaddingLeft(); ry = ry + area.getPaddingTop(); w = w + area.getPaddingLeft() + area.getPaddingRight(); h = h + area.getPaddingTop() + area.getPaddingBottom(); - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - this.addRect(rx, ry, w, h, bg.red(), bg.green(), bg.blue(), - bg.red(), bg.green(), bg.blue()); - } + doBackground(area, rx, ry, w, h); rx = rx - area.getBorderLeftWidth(); ry = ry + area.getBorderTopWidth(); @@ -365,7 +345,7 @@ public class SVGRenderer extends AbstractRenderer { a.getAllocationWidth(), a.getHeight()); } - public void setupFontInfo(FontInfo fontInfo) { + public void setupFontInfo(FontInfo fontInfo) throws FOPException { // create a temp Image to test font metrics on BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); @@ -377,6 +357,46 @@ public class SVGRenderer extends AbstractRenderer { this.currentYPosition -= d; } + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } + public void renderImageArea(ImageArea area) { int x = currentXPosition + area.getXOffset(); diff --git a/src/org/apache/fop/render/txt/TXTRenderer.java b/src/org/apache/fop/render/txt/TXTRenderer.java index d8f6b0d5a..6a03ab07a 100755 --- a/src/org/apache/fop/render/txt/TXTRenderer.java +++ b/src/org/apache/fop/render/txt/TXTRenderer.java @@ -13,6 +13,8 @@ import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.pcl.*; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.FopImageException; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; import org.apache.fop.datatypes.*; @@ -43,7 +45,7 @@ public class TXTRenderer extends PrintRenderer { /** * the current stream to add Text commands to */ - PCLStream currentStream; + TXTStream currentStream; private int pageHeight = 7920; @@ -734,6 +736,45 @@ public class TXTRenderer extends PrintRenderer { PDFColor fc, PDFColor sc, float sw, boolean close) {} + /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } boolean printBMP(FopImage img, int x, int y, int w, int h) throws FopImageException { @@ -1677,7 +1718,7 @@ public class TXTRenderer extends PrintRenderer { public void startRenderer(OutputStream outputStream) throws IOException { log.info("rendering areas to TEXT"); - currentStream = new PCLStream(outputStream); + currentStream = new TXTStream(outputStream); firstPage=true; } diff --git a/src/org/apache/fop/render/txt/TXTStream.java b/src/org/apache/fop/render/txt/TXTStream.java new file mode 100644 index 000000000..9b2704271 --- /dev/null +++ b/src/org/apache/fop/render/txt/TXTStream.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.render.txt; + +import java.io.*; + +public class TXTStream { + OutputStream out = null; + boolean doOutput = true; + + public TXTStream(OutputStream os) { + out = os; + } + + public void add(String str) { + if (!doOutput) + return; + + try { + byte buff[] = str.getBytes("UTF-8"); + out.write(buff); + } catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + + public void setDoOutput(boolean doout) { + doOutput = doout; + } + +} diff --git a/src/org/apache/fop/render/xml/XMLRenderer.java b/src/org/apache/fop/render/xml/XMLRenderer.java index 456be9a1f..bd4a4c109 100644 --- a/src/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/org/apache/fop/render/xml/XMLRenderer.java @@ -11,13 +11,16 @@ package org.apache.fop.render.xml; import org.apache.fop.svg.*; import org.apache.fop.render.Renderer; import org.apache.fop.render.AbstractRenderer; +import org.apache.fop.image.FopImage; import org.apache.fop.image.ImageArea; import org.apache.fop.layout.*; import org.apache.fop.layout.inline.*; import org.apache.fop.pdf.*; import org.apache.fop.fo.properties.LeaderPattern; +import org.apache.fop.apps.FOPException; -import org.apache.log.Logger; +// Avalon +import org.apache.avalon.framework.logger.Logger; // Java import java.io.IOException; @@ -147,13 +150,53 @@ public class XMLRenderer implements Renderer { * * @param fontInfo the font info object to set up */ - public void setupFontInfo(FontInfo fontInfo) { + public void setupFontInfo(FontInfo fontInfo) throws FOPException { /* use PDF's font setup to get PDF metrics */ org.apache.fop.render.pdf.FontSetup.setup(fontInfo); } /** + * Renders an image, scaling it to the given width and height. + * If the scaled width and height is the same intrinsic size + * of the image, the image is not scaled. + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param image the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageScaled(int x, int y, int w, int h, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** + * Renders an image, clipping it as specified. + * + * @param x the x position of left edge in millipoints. + * @param y the y position of top edge in millipoints. + * @param clipX the left edge of the clip in millipoints + * @param clipY the top edge of the clip in millipoints + * @param clipW the clip width in millipoints + * @param clipH the clip height in millipoints + * @param fill the image to be rendered + * @param fs the font state to use when rendering text + * in non-bitmapped images. + */ + protected void drawImageClipped(int x, int y, + int clipX, int clipY, + int clipW, int clipH, + FopImage image, + FontState fs) { + // XXX: implement this + } + + /** * render an area container to XML * * @param area the area container to render diff --git a/src/org/apache/fop/svg/PDFAElementBridge.java b/src/org/apache/fop/svg/PDFAElementBridge.java index dfc79bf74..c441dc46e 100644 --- a/src/org/apache/fop/svg/PDFAElementBridge.java +++ b/src/org/apache/fop/svg/PDFAElementBridge.java @@ -12,7 +12,6 @@ import java.awt.geom.AffineTransform; import org.apache.batik.bridge.*; -import org.apache.batik.css.HiddenChildElementSupport; import org.apache.batik.gvt.CompositeGraphicsNode; import org.apache.batik.gvt.GraphicsNode; diff --git a/src/org/apache/fop/svg/PDFANode.java b/src/org/apache/fop/svg/PDFANode.java index 3fd4be391..a4e28a88e 100644 --- a/src/org/apache/fop/svg/PDFANode.java +++ b/src/org/apache/fop/svg/PDFANode.java @@ -58,6 +58,7 @@ public class PDFANode extends CompositeGraphicsNode { int type = org.apache.fop.layout.LinkSet.EXTERNAL; Shape outline = getOutline(); if(destination.startsWith("#svgView(viewBox(")) { + type = org.apache.fop.layout.LinkSet.INTERNAL; String nums = destination.substring(18, destination.length() - 2); float x = 0; float y = 0; diff --git a/src/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/org/apache/fop/svg/PDFDocumentGraphics2D.java index d0b63a3de..f145dc476 100644 --- a/src/org/apache/fop/svg/PDFDocumentGraphics2D.java +++ b/src/org/apache/fop/svg/PDFDocumentGraphics2D.java @@ -56,7 +56,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { * @param height the height of the document */ public PDFDocumentGraphics2D(boolean textAsShapes, OutputStream stream, - int width, int height) { + int width, int height) throws FOPException { super(textAsShapes); if (!textAsShapes) { diff --git a/src/org/apache/fop/svg/PDFGraphics2D.java b/src/org/apache/fop/svg/PDFGraphics2D.java index 7fc44b294..69acebab5 100644 --- a/src/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/org/apache/fop/svg/PDFGraphics2D.java @@ -15,6 +15,7 @@ import org.apache.fop.image.*; import org.apache.fop.datatypes.ColorSpace; import org.apache.fop.render.pdf.CIDFont; import org.apache.fop.render.pdf.fonts.LazyFont; +import org.apache.fop.apps.FOPException; import org.apache.batik.ext.awt.g2d.*; import org.apache.batik.ext.awt.image.GraphicsUtil; @@ -31,6 +32,7 @@ import java.awt.image.renderable.*; import java.io.*; import java.util.Map; +import java.util.HashMap; import java.util.Vector; import java.util.Hashtable; @@ -93,6 +95,20 @@ public class PDFGraphics2D extends AbstractGraphics2D { PDFColor currentColour = new PDFColor(0, 0, 0); /** + * A registry of images that have already been drawn. They are mapped to + * a structure with the PDF xObjectNum, width and height. This + * prevents multiple copies from being stored, which can greatly + * reduce the size of a PDF graphic that uses the same image over and over + * (e.g. graphic bullets, map icons, etc.). + */ + private HashMap imageInfos = new HashMap(); + private static class ImageInfo { + public int width; + public int height; + public int xObjectNum; + } + + /** * Create a new PDFGraphics2D with the given pdf document info. * This is used to create a Graphics object for use inside an already * existing document. @@ -158,7 +174,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { rect.y = rect.y * 1000; rect.height = -rect.height * 1000; rect.width = rect.width * 1000; - if(linkType == LinkSet.EXTERNAL) { + if(linkType != LinkSet.EXTERNAL) { String pdfdest = "/XYZ " + dest; currentAnnotList.addLink(pdfDoc.makeLinkCurrentPage(rect, pdfdest)); } else { @@ -219,91 +235,105 @@ public class PDFGraphics2D extends AbstractGraphics2D { ImageObserver observer) { // System.err.println("drawImage:x, y"); - final int width = img.getWidth(observer); - final int height = img.getHeight(observer); - if (width == -1 || height == -1) { - return false; - } - - Dimension size = new Dimension(width * 3, height * 3); - BufferedImage buf = buildBufferedImage(size); - - java.awt.Graphics2D g = buf.createGraphics(); - g.setComposite(AlphaComposite.SrcOver); - g.setBackground(new Color(1, 1, 1, 0)); - g.setPaint(new Color(1, 1, 1, 0)); - g.fillRect(0, 0, width * 3, height * 3); - g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); - - if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) { - return false; - } - g.dispose(); - - final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3]; - final byte[] mask = new byte[buf.getWidth() * buf.getHeight()]; - - Raster raster = buf.getData(); - DataBuffer bd = raster.getDataBuffer(); - - int count = 0; - int maskpos = 0; - int[] iarray; - int i, j, val, alpha, add, mult; - switch (bd.getDataType()) { - case DataBuffer.TYPE_INT: - int[][] idata = ((DataBufferInt)bd).getBankData(); - for (i = 0; i < idata.length; i++) { - iarray = idata[i]; - for (j = 0; j < iarray.length; j++) { - val = iarray[j]; - alpha = val >>> 24; - // mask[maskpos++] = (byte)((idata[i][j] >> 24) & 0xFF); - if (alpha != 255) { - // System.out.println("Alpha: " + alpha); - // Composite with opaque white... - add = (255 - alpha); - mult = (alpha << 16) / 255; - result[count++] = - (byte)(add - + ((((val >> 16) & 0xFF) * mult) >> 16)); - result[count++] = - (byte)(add - + ((((val >> 8) & 0xFF) * mult) >> 16)); - result[count++] = (byte)(add - + ((((val) & 0xFF) * mult) - >> 16)); - } else { - result[count++] = (byte)((val >> 16) & 0xFF); - result[count++] = (byte)((val >> 8) & 0xFF); - result[count++] = (byte)((val) & 0xFF); + // first we look to see if we've already added this image to + // the pdf document. If so, we just reuse the reference; + // otherwise we have to build a FopImage and add it to the pdf + // document + ImageInfo imageInfo = (ImageInfo)imageInfos.get(img); + if (imageInfo == null) { + // OK, have to build and add a PDF image + imageInfo = new ImageInfo(); + imageInfo.width = img.getWidth(observer); + imageInfo.height = img.getHeight(observer); + + if (imageInfo.width == -1 || imageInfo.height == -1) { + return false; + } + + Dimension size = new Dimension(imageInfo.width * 3, imageInfo.height * 3); + BufferedImage buf = buildBufferedImage(size); + + java.awt.Graphics2D g = buf.createGraphics(); + g.setComposite(AlphaComposite.SrcOver); + g.setBackground(new Color(1, 1, 1, 0)); + g.setPaint(new Color(1, 1, 1, 0)); + g.fillRect(0, 0, imageInfo.width * 3, imageInfo.height * 3); + g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); + + if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) { + return false; + } + g.dispose(); + + final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3]; + final byte[] mask = new byte[buf.getWidth() * buf.getHeight()]; + + Raster raster = buf.getData(); + DataBuffer bd = raster.getDataBuffer(); + + int count = 0; + int maskpos = 0; + int[] iarray; + int i, j, val, alpha, add, mult; + switch (bd.getDataType()) { + case DataBuffer.TYPE_INT: + int[][] idata = ((DataBufferInt)bd).getBankData(); + for (i = 0; i < idata.length; i++) { + iarray = idata[i]; + for (j = 0; j < iarray.length; j++) { + val = iarray[j]; + alpha = val >>> 24; + // mask[maskpos++] = (byte)((idata[i][j] >> 24) & 0xFF); + if (alpha != 255) { + // System.out.println("Alpha: " + alpha); + // Composite with opaque white... + add = (255 - alpha); + mult = (alpha << 16) / 255; + result[count++] = + (byte)(add + + ((((val >> 16) & 0xFF) * mult) >> 16)); + result[count++] = + (byte)(add + + ((((val >> 8) & 0xFF) * mult) >> 16)); + result[count++] = (byte)(add + + ((((val) & 0xFF) * mult) + >> 16)); + } else { + result[count++] = (byte)((val >> 16) & 0xFF); + result[count++] = (byte)((val >> 8) & 0xFF); + result[count++] = (byte)((val) & 0xFF); + } } } + break; + default: + // error + break; + } + + try { + FopImage fopimg = new TempImage("TempImage:" + img.toString(), buf.getWidth(), buf.getHeight(), result, mask); + imageInfo.xObjectNum = this.pdfDoc.addImage(fopimg); + imageInfos.put(img, imageInfo); + } catch (Exception e) { + e.printStackTrace(); } - break; - default: - // error - break; } - try { - FopImage fopimg = new TempImage(buf.getWidth(), buf.getHeight(), result, mask); - int xObjectNum = this.pdfDoc.addImage(fopimg); - AffineTransform at = getTransform(); - double[] matrix = new double[6]; - at.getMatrix(matrix); - currentStream.write("q\n"); - Shape imclip = getClip(); - writeClip(imclip); - currentStream.write("" + matrix[0] + " " + matrix[1] + " " - + matrix[2] + " " + matrix[3] + " " - + matrix[4] + " " + matrix[5] + " cm\n"); - currentStream.write("" + width + " 0 0 " + (-height) + " " + x - + " " + (y + height) + " cm\n" + "/Im" - + xObjectNum + " Do\nQ\n"); - } catch (Exception e) { - e.printStackTrace(); - } + // now do any transformation required and add the actual image + // placement instance + AffineTransform at = getTransform(); + double[] matrix = new double[6]; + at.getMatrix(matrix); + currentStream.write("q\n"); + Shape imclip = getClip(); + writeClip(imclip); + currentStream.write("" + matrix[0] + " " + matrix[1] + " " + + matrix[2] + " " + matrix[3] + " " + + matrix[4] + " " + matrix[5] + " cm\n"); + currentStream.write("" + imageInfo.width + " 0 0 " + (-imageInfo.height) + " " + x + + " " + (y + imageInfo.height) + " cm\n" + "/Im" + + imageInfo.xObjectNum + " Do\nQ\n"); return true; } @@ -321,9 +351,11 @@ public class PDFGraphics2D extends AbstractGraphics2D { byte[] m_bitmaps; byte[] m_mask; PDFColor transparent = new PDFColor(255, 255, 255); + String url; - TempImage(int width, int height, byte[] result, + TempImage(String url, int width, int height, byte[] result, byte[] mask) throws FopImageException { + this.url = url; this.m_height = height; this.m_width = width; this.m_bitsPerPixel = 8; @@ -334,8 +366,12 @@ public class PDFGraphics2D extends AbstractGraphics2D { this.m_mask = mask; } + public boolean invertImage() { + return false; + } + public String getURL() { - return "" + m_bitmaps; + return url; } // image size @@ -511,7 +547,17 @@ public class PDFGraphics2D extends AbstractGraphics2D { applyPaint(getPaint(), false); applyStroke(getStroke()); - PathIterator iter = s.getPathIterator(getTransform()); + AffineTransform trans = getTransform(); + double[] tranvals = new double[6]; + trans.getMatrix(tranvals); + currentStream.write(PDFNumber.doubleOut(tranvals[0]) + " " + + PDFNumber.doubleOut(tranvals[1]) + " " + + PDFNumber.doubleOut(tranvals[2]) + " " + + PDFNumber.doubleOut(tranvals[3]) + " " + + PDFNumber.doubleOut(tranvals[4]) + " " + + PDFNumber.doubleOut(tranvals[5]) + " cm\n"); + + PathIterator iter = s.getPathIterator(new AffineTransform()); while (!iter.isDone()) { double vals[] = new double[6]; int type = iter.currentSegment(vals); @@ -1240,6 +1286,11 @@ System.out.println("getting getNormalizingTransform"); return new PDFGraphicsDevice(this); } + // needed for compiling under jdk1.4 + //public java.awt.image.VolatileImage createCompatibleVolatileImage(int width, int height) { + // return null; + //} + } /** diff --git a/src/org/apache/fop/svg/PDFImageElementBridge.java b/src/org/apache/fop/svg/PDFImageElementBridge.java index 7bfb7a1fb..3d0e30f38 100644 --- a/src/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/org/apache/fop/svg/PDFImageElementBridge.java @@ -12,7 +12,6 @@ import java.awt.geom.AffineTransform; import org.apache.batik.bridge.*; -import org.apache.batik.css.HiddenChildElementSupport; import org.apache.batik.gvt.CompositeGraphicsNode; import org.apache.batik.gvt.GraphicsNode; diff --git a/src/org/apache/fop/svg/PDFTranscoder.java b/src/org/apache/fop/svg/PDFTranscoder.java index 21f5b5641..271dd2600 100644 --- a/src/org/apache/fop/svg/PDFTranscoder.java +++ b/src/org/apache/fop/svg/PDFTranscoder.java @@ -32,6 +32,8 @@ import java.net.URL; import java.util.HashSet; import java.util.Set; +import org.apache.fop.apps.FOPException; + import org.apache.batik.transcoder.*; import org.apache.batik.bridge.BridgeContext; @@ -40,7 +42,6 @@ import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.UserAgent; import org.apache.batik.bridge.ViewBox; -import org.apache.batik.dom.svg.DefaultSVGContext; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGOMDocument; @@ -95,9 +96,6 @@ import org.w3c.dom.svg.SVGAElement; import org.w3c.dom.svg.SVGDocument; import org.w3c.dom.svg.SVGSVGElement; -// <!> FIXME : Those import clauses will change with new design -import org.apache.batik.gvt.renderer.StaticRendererFactory; - /** * This class enables to transcode an input to a pdf document. * @@ -155,7 +153,8 @@ public class PDFTranscoder extends XMLAbstractTranscoder { * @exception TranscoderException if an error occured while transcoding */ protected void transcode(Document document, String uri, - TranscoderOutput output) throws TranscoderException { + TranscoderOutput output) + throws TranscoderException { if (!(document instanceof SVGOMDocument)) { throw new TranscoderException(Messages.formatMessage("notsvg", @@ -165,9 +164,6 @@ public class PDFTranscoder extends XMLAbstractTranscoder { SVGSVGElement root = svgDoc.getRootElement(); // initialize the SVG document with the appropriate context String parserClassname = (String)hints.get(KEY_XML_PARSER_CLASSNAME); - DefaultSVGContext svgCtx = new DefaultSVGContext(); - svgCtx.setPixelToMM(userAgent.getPixelToMM()); - ((SVGOMDocument)document).setSVGContext(svgCtx); boolean stroke = true; if (hints.containsKey(KEY_STROKE_TEXT)) { @@ -176,7 +172,6 @@ public class PDFTranscoder extends XMLAbstractTranscoder { // build the GVT tree GVTBuilder builder = new GVTBuilder(); - ImageRendererFactory rendFactory = new StaticRendererFactory(); BridgeContext ctx = new BridgeContext(userAgent); TextPainter textPainter = null; textPainter = new StrokingTextPainter(); @@ -267,8 +262,13 @@ public class PDFTranscoder extends XMLAbstractTranscoder { int w = (int)width; int h = (int)height; - PDFDocumentGraphics2D graphics = new PDFDocumentGraphics2D(stroke, + PDFDocumentGraphics2D graphics; + try { + graphics = new PDFDocumentGraphics2D(stroke, output.getOutputStream(), w, h); + } catch (FOPException ex) { + throw new TranscoderException(ex); + } graphics.setSVGDimension(docWidth, docHeight); currentTransform.setTransform(1, 0, 0, -1, 0, height); if (!stroke) { @@ -311,7 +311,11 @@ public class PDFTranscoder extends XMLAbstractTranscoder { /** * A user agent implementation for <tt>ImageTranscoder</tt>. */ - protected class ImageTranscoderUserAgent implements UserAgent { + protected class ImageTranscoderUserAgent extends UserAgentAdapter { + + public boolean isXMLParserValidating() { + return true; + } /** * Returns the default size of this user agent (400x400). @@ -379,10 +383,9 @@ public class PDFTranscoder extends XMLAbstractTranscoder { } public String getMedia() { - return ""; + return "print"; } - /** * Returns the user stylesheet specified in the * <tt>TranscodingHints</tt> or null if any. @@ -402,68 +405,6 @@ public class PDFTranscoder extends XMLAbstractTranscoder { } } - /** - * Unsupported operation. - */ - public EventDispatcher getEventDispatcher() { - return null; - } - - /** - * Unsupported operation. - */ - public void openLink(SVGAElement elt) {} - - /** - * Unsupported operation. - */ - public void setSVGCursor(Cursor cursor) {} - - /** - * Unsupported operation. - */ - public void runThread(Thread t) {} - - /** - * Unsupported operation. - */ - public AffineTransform getTransform() { - return null; - } - - /** - * Unsupported operation. - */ - public Point getClientAreaLocationOnScreen() { - return new Point(); - } - - /** - * Tells whether the given feature is supported by this - * user agent. - */ - public boolean hasFeature(String s) { - return FEATURES.contains(s); - } - - /** - * Tells whether the given extension is supported by this - * user agent. - */ - public boolean supportExtension(String s) { - return false; - } - - public void registerExtension(BridgeExtension be) {} - - public void handleElement(Element elt, Object data) {} - } - protected final static Set FEATURES = new HashSet(); - static { - FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_FEATURE); - FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_LANG_FEATURE); - FEATURES.add(SVGConstants.SVG_ORG_W3C_SVG_STATIC_FEATURE); - } } diff --git a/src/org/apache/fop/svg/SVGElement.java b/src/org/apache/fop/svg/SVGElement.java index 3d098e32c..b77298646 100644 --- a/src/org/apache/fop/svg/SVGElement.java +++ b/src/org/apache/fop/svg/SVGElement.java @@ -37,6 +37,7 @@ import java.net.URL; import java.util.List; import java.util.ArrayList; import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; /** * class representing svg:svg pseudo flow object. @@ -107,37 +108,43 @@ public class SVGElement extends SVGObj { final Element svgRoot = element; /* create an SVG area */ /* if width and height are zero, get the bounds of the content. */ - DefaultSVGContext dc = new DefaultSVGContext() { + final ForeignObjectArea foa = (ForeignObjectArea)area; + SVGContext dc = new SVGContext() { public float getPixelToMM() { // 72 dpi return 0.35277777777777777778f; } - public float getViewportWidth(Element e) throws IllegalStateException { - if(e == svgRoot) { - ForeignObjectArea foa = (ForeignObjectArea)area; - if(!foa.isContentWidthAuto()) { - return foa.getContentWidth(); - } - } - return super.getViewportWidth(e); + public float getPixelUnitToMillimeter() { + // 72 dpi + return 0.35277777777777777778f; + } + + public Rectangle2D getBBox() { + return new Rectangle2D.Double(0, 0, foa.getContentWidth(), foa.getContentHeight()); } - public float getViewportHeight(Element e) throws IllegalStateException { - if(e == svgRoot) { - ForeignObjectArea foa = (ForeignObjectArea)area; - if(!foa.isContentHeightAuto()) { - return foa.getContentHeight(); - } - } - return super.getViewportHeight(e); + public AffineTransform getCTM() { + return new AffineTransform(); } - public List getDefaultFontFamilyValue() { - return FONT_FAMILY; + public AffineTransform getGlobalTransform() { + return new AffineTransform(); + } + + public float getViewportWidth() { + return (float)foa.getContentWidth(); + } + + public float getViewportHeight() { + return (float)foa.getContentHeight(); + } + + public float getFontSize(){ + return fs.getFontSize() / 1000f; } }; - ((SVGOMDocument)doc).setSVGContext(dc); + ((SVGOMElement)svgRoot).setSVGContext(dc); try { String baseDir = Configuration.getStringValue("baseDir"); @@ -184,11 +191,12 @@ public class SVGElement extends SVGObj { svg.end(); /* add the SVG area to the containing area */ - ForeignObjectArea foa = (ForeignObjectArea)area; foa.setObject(svg); foa.setIntrinsicWidth(svg.getWidth()); foa.setIntrinsicHeight(svg.getHeight()); + ((SVGOMElement)svgRoot).setSVGContext(null); + /* return status */ return new Status(Status.OK); } @@ -203,14 +211,4 @@ public class SVGElement extends SVGObj { buildTopLevel(doc, element); } - public final static List FONT_FAMILY; - static { - FONT_FAMILY = new ArrayList(); - FONT_FAMILY.add("Helvetica"); - FONT_FAMILY.add("Times"); - FONT_FAMILY.add("Courier"); - FONT_FAMILY.add("sans-serif"); - FONT_FAMILY.add("serif"); - } - } diff --git a/src/org/apache/fop/svg/SVGElementMapping.java b/src/org/apache/fop/svg/SVGElementMapping.java index 012cd9b89..cabf3667f 100644 --- a/src/org/apache/fop/svg/SVGElementMapping.java +++ b/src/org/apache/fop/svg/SVGElementMapping.java @@ -22,7 +22,7 @@ public class SVGElementMapping implements ElementMapping { private static HashMap foObjs = null; - public synchronized void addToBuilder(TreeBuilder builder) { + private static synchronized void setupSVG() { if(foObjs == null) { // this sets the parser that will be used @@ -84,11 +84,14 @@ public class SVGElementMapping implements ElementMapping { foObjs.put("feMerge", SVGObj.maker("feMerge")); foObjs.put("feMergeNode", SVGObj.maker("feMergeNode")); } + } + public void addToBuilder(TreeBuilder builder) { + setupSVG(); String uri = "http://www.w3.org/2000/svg"; builder.addMapping(uri, foObjs); builder.addPropertyListBuilder(uri, new DirectPropertyListBuilder()); } - } + diff --git a/src/org/apache/fop/svg/SVGUserAgent.java b/src/org/apache/fop/svg/SVGUserAgent.java index 52873f18a..24fe7766b 100644 --- a/src/org/apache/fop/svg/SVGUserAgent.java +++ b/src/org/apache/fop/svg/SVGUserAgent.java @@ -7,8 +7,6 @@ package org.apache.fop.svg; -import org.apache.log.Logger; - import org.apache.batik.bridge.*; import org.apache.batik.swing.svg.*; import org.apache.batik.swing.gvt.*; @@ -17,6 +15,8 @@ import org.apache.batik.gvt.renderer.*; import org.apache.batik.gvt.filter.*; import org.apache.batik.gvt.event.*; +import org.apache.avalon.framework.logger.Logger; + import org.w3c.dom.*; import org.w3c.dom.svg.*; import org.w3c.dom.css.*; @@ -34,7 +34,7 @@ import java.awt.Point; import java.awt.RenderingHints; import java.awt.Dimension; -public class SVGUserAgent implements UserAgent { +public class SVGUserAgent extends UserAgentAdapter { AffineTransform currentTransform = null; Logger log; @@ -80,6 +80,12 @@ public class SVGUserAgent implements UserAgent { // return 0.26458333333333333333333333333333f; // 96dpi } + public float getPixelUnitToMillimeter() { + // this is set to 72dpi as the values in fo are 72dpi + return 0.35277777777777777778f; // 72 dpi + // return 0.26458333333333333333333333333333f; // 96dpi + } + /** * Returns the language settings. */ @@ -88,7 +94,7 @@ public class SVGUserAgent implements UserAgent { } public String getMedia() { - return ""; + return "print"; } /** @@ -106,21 +112,6 @@ public class SVGUserAgent implements UserAgent { return org.apache.fop.apps.Driver.getParserClassName(); } - /** - * Opens a link in a new component. - * @param doc The current document. - * @param uri The document URI. - */ - public void openLink(SVGAElement elt) { - } - - - public Point getClientAreaLocationOnScreen() { - return new Point(0, 0); - } - - public void setSVGCursor(java.awt.Cursor cursor) {} - public AffineTransform getTransform() { return currentTransform; } @@ -129,22 +120,9 @@ public class SVGUserAgent implements UserAgent { return new Dimension(100, 100); } - public EventDispatcher getEventDispatcher() { - return null; - } - - public boolean supportExtension(String str) { - return false; + public boolean isXMLParserValidating() { + return true; } - public boolean hasFeature(String str) { - return false; - } - - public void registerExtension(BridgeExtension be) {} - - public void handleElement(Element elt, Object data) {} - - } diff --git a/src/org/apache/fop/tools/TestConverter.java b/src/org/apache/fop/tools/TestConverter.java index b972198ff..f230474ca 100644 --- a/src/org/apache/fop/tools/TestConverter.java +++ b/src/org/apache/fop/tools/TestConverter.java @@ -9,11 +9,10 @@ package org.apache.fop.tools; import org.apache.fop.apps.*; import org.apache.fop.configuration.*; +import org.apache.fop.messaging.MessageHandler; -import org.apache.log.*; -import org.apache.log.format.*; -import org.apache.log.output.io.*; -import org.apache.log.output.*; +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; import java.io.*; import java.util.*; @@ -88,16 +87,8 @@ public class TestConverter { } private void setupLogging() { - Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); - PatternFormatter formatter = new PatternFormatter( - "[%{priority}]: %{message}\n%{throwable}" ); - - LogTarget target = null; - target = new StreamTarget(System.out, formatter); - - hierarchy.setDefaultLogTarget(target); - log = hierarchy.getLoggerFor("test"); - log.setPriority(Priority.ERROR); + log = new ConsoleLogger(ConsoleLogger.LEVEL_ERROR); + MessageHandler.setScreenLogger(log); } public void setOutputPDF(boolean pdf) { diff --git a/src/org/apache/fop/tools/anttasks/CompileXMLFiles.java b/src/org/apache/fop/tools/anttasks/CompileXMLFiles.java deleted file mode 100644 index 15568d03f..000000000 --- a/src/org/apache/fop/tools/anttasks/CompileXMLFiles.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.tools.anttasks; - -/** - * This class is an extension of Ant, a script utility from - * jakarta.apache.org. - * It takes a couple of xml files conforming to the xml-site dtd and - * writes them all into one xml file, deleting any reference to - * the proprietary protocol sbk. The configFile determines what files - * are read in what sequence. - */ -// Ant -import org.apache.tools.ant.Task; -import org.apache.tools.ant.BuildException; - - -// SAX -import org.xml.sax.Parser; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.Locator; -import org.xml.sax.AttributeList; - -// Java -import java.io.*; -import java.util.*; -import java.net.URL; - -public class CompileXMLFiles extends Task - implements org.xml.sax.EntityResolver, org.xml.sax.DTDHandler, - org.xml.sax.DocumentHandler, org.xml.sax.ErrorHandler { - private String configFile, outFile; - private String[] filenameList; - private String filenames; - private Vector files = new Vector(); - - // sets name of configuration file, which must - // be an xml file conforming to the book.dtd used by xml-site - public void setConfigFile(String configFile) { - this.configFile = configFile; - } - - public void setOutFile(String outFile) { - this.outFile = outFile; - } - - - // main method of this task - public void execute() throws BuildException { - boolean errors = false; - - if (!(new File(configFile).exists())) { - errors = true; - System.err.println("Task CompileXMLFiles - ERROR: config file " - + configFile + " is missing."); - } - - Parser parser = createParser(); - - if (parser == null) { - System.err.println("Task CompileXMLFiles - ERROR: Unable to create SAX parser"); - errors = true; - } - parser.setDocumentHandler(this); - try { - parser.parse(CompileXMLFiles.fileInputSource(configFile)); - } catch (SAXException e) { - System.out.println(e); - } catch (IOException ioe) { - System.out.println(ioe); - } - } // end: execute() - - - /* the following methods belong to the sax parser and implement the Document Handler */ - public InputSource resolveEntity(String publicId, - String systemId) throws SAXException { - return null; - } - - public void notationDecl(String name, String publicId, String systemId) { - // no op - } - - public void unparsedEntityDecl(String name, String publicId, - String systemId, String notationName) { - // no op - } - - public void setDocumentLocator(Locator locator) { - // no op - } - - public void startDocument() throws SAXException { - // no op - } - - /* - * After the cnfiguration file has been parsed all files which - * have been collected in the ArrayList files are concatinated - * and written to a new (temporary) file - */ - public void endDocument() throws SAXException { - String line, filename; - BufferedReader in; - Enumeration iterator = files.elements(); - try { - BufferedWriter out = - new BufferedWriter(new FileWriter("compileXMLFiles-tmp.xml")); - out.write("<?xml version=\"1.0\"?>\n" - + "<!DOCTYPE documentation [\n" - + "<!ENTITY nbsp \" \">\n" + "]>\n<documentation>"); - while (iterator.hasMoreElements()) { - filename = (String)iterator.nextElement(); - in = new BufferedReader(new FileReader(filename)); - while ((line = in.readLine()) != null) { - // kill the lines pointing to the sbk protocol and the xml declaration - if (line.indexOf("<!DOCTYPE ") != -1 - || line.indexOf("<?xml ") != -1) { - line = ""; - } - out.write(line + "\n"); - } - out.flush(); - } - out.write("\n</documentation>"); - out.close(); - } catch (Exception e) { - System.out.println(e); - } - - } - - public void startElement(String name, - AttributeList atts) throws SAXException { - String id, label, source; - if (name.equals("document") || name.equals("entry")) { - source = atts.getValue("source"); - files.addElement(source); - } - } - - public void endElement(String name) throws SAXException { - // no op - } - - public void characters(char ch[], int start, - int length) throws SAXException { - // no op - } - - public void ignorableWhitespace(char ch[], int start, - int length) throws SAXException { - // no op - } - - public void processingInstruction(String target, - String data) throws SAXException { - // no op - } - - public void warning(SAXParseException e) throws SAXException { - // no op - } - - public void error(SAXParseException e) throws SAXException { - // no op - } - - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - - /* ------------------------ */ - - /** - * creates a SAX parser, using the value of org.xml.sax.parser - * defaulting to org.apache.xerces.parsers.SAXParser - * - * @return the created SAX parser - */ - static Parser createParser() { - String parserClassName = System.getProperty("org.xml.sax.parser"); - if (parserClassName == null) { - parserClassName = "org.apache.xerces.parsers.SAXParser"; - } - System.err.println("using SAX parser " + parserClassName); - - try { - return (Parser)Class.forName(parserClassName).newInstance(); - } catch (ClassNotFoundException e) { - System.err.println("Could not find " + parserClassName); - } catch (InstantiationException e) { - System.err.println("Could not instantiate " + parserClassName); - } catch (IllegalAccessException e) { - System.err.println("Could not access " + parserClassName); - } catch (ClassCastException e) { - System.err.println(parserClassName + " is not a SAX driver"); - } - return null; - } - - /** - * create an InputSource from a file name - * - * @param filename the name of the file - * @return the InputSource created - */ - protected static InputSource fileInputSource(String filename) { - - /* this code adapted from James Clark's in XT */ - File file = new File(filename); - String path = file.getAbsolutePath(); - String fSep = System.getProperty("file.separator"); - if (fSep != null && fSep.length() == 1) - path = path.replace(fSep.charAt(0), '/'); - if (path.length() > 0 && path.charAt(0) != '/') - path = '/' + path; - try { - return new InputSource(new URL("file", null, path).toString()); - } catch (java.net.MalformedURLException e) { - throw new Error("unexpected MalformedURLException"); - } - } - -} - diff --git a/src/org/apache/fop/tools/anttasks/Fop.java b/src/org/apache/fop/tools/anttasks/Fop.java index 95fc36927..b9284b943 100644 --- a/src/org/apache/fop/tools/anttasks/Fop.java +++ b/src/org/apache/fop/tools/anttasks/Fop.java @@ -11,11 +11,6 @@ package org.apache.fop.tools.anttasks; import org.apache.tools.ant.*; import org.apache.tools.ant.types.FileSet; -import org.apache.log.*; -import org.apache.log.format.*; -import org.apache.log.output.io.*; -import org.apache.log.output.*; - // SAX import org.xml.sax.XMLReader; import org.xml.sax.InputSource; @@ -36,6 +31,10 @@ import org.apache.fop.apps.Driver; import org.apache.fop.apps.FOPException; import org.apache.fop.configuration.Configuration; +// Avalon +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; + /** * Wrapper for Fop which allows it to be accessed from within an Ant task. * Accepts the inputs: @@ -195,25 +194,8 @@ class FOPTaskStarter extends Starter { FOPTaskStarter(Fop task) throws FOPException { this.task = task; - Hierarchy hierarchy = new Hierarchy(); - // PatternFormatter formatter = new PatternFormatter( - // "[%{priority}] %{category}: %{message}\n%{throwable}" ); - PatternFormatter formatter = new PatternFormatter("%{message}\n%{throwable}"); - - LogTarget target = null; - boolean doConsoleLogging = true; - if (doConsoleLogging) { - target = new StreamTarget(System.out, formatter); - } else { - try { - File f = new File("fop.log"); - target = new FileTarget(f, false, formatter); - } catch (IOException e) {} - } - - hierarchy.setDefaultLogTarget(target); - log = hierarchy.getLoggerFor("fop"); - log.setPriority(Priority.INFO); + log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO); + MessageHandler.setScreenLogger(log); } private int determineRenderer(String format) { @@ -287,7 +269,7 @@ class FOPTaskStarter extends Starter { toExternalForm()); } } catch (Exception e) { - task.log("Error setting base directory", Project.MSG_DEBUG); + log.error("Error setting base directory",e); } task.log("Using base directory: " + @@ -351,7 +333,6 @@ class FOPTaskStarter extends Starter { int renderer) throws FOPException { InputHandler inputHandler = new FOInputHandler(foFile); XMLReader parser = inputHandler.getParser(); - setParserFeatures(parser); FileOutputStream out = null; try { @@ -367,6 +348,11 @@ class FOPTaskStarter extends Starter { Driver driver = new Driver(inputHandler.getInputSource(), out); driver.setLogger(log); driver.setRenderer(renderer); + if (renderer == Driver.RENDER_XML) { + Hashtable rendererOptions = new Hashtable(); + rendererOptions.put("fineDetail", new Boolean(true)); + driver.getRenderer().setOptions(rendererOptions); + } driver.setXMLReader(parser); driver.run(); out.close(); diff --git a/src/org/apache/fop/tools/anttasks/Manifest.java b/src/org/apache/fop/tools/anttasks/Manifest.java deleted file mode 100644 index 3c7820348..000000000 --- a/src/org/apache/fop/tools/anttasks/Manifest.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.tools.anttasks; - -import org.apache.tools.ant.Task; -import org.apache.tools.ant.BuildException; - -import java.io.*; -import java.text.SimpleDateFormat; -import java.net.InetAddress; -import java.util.Date; -import java.util.Properties; - - - -/** - * Creates a manifest file for packing into a jar. - * <P> - * Attributes are as follows: - * <dl> - * <dt>file</dt> <dd>the manifest file to write out to (required)</dd> - * <dt>overwrite</dt> <dd>if set to yes or true, overwrite the given - * manifest file. Default is no</dd> - * <dt>version</dt> <dd>manifest version. Defaults to "1.0"</dd> - * <dt>spectitle</dt> <dd>the specification title</dd> - * <dt>specversion</dt> <dd>the specification version</dd> - * <dt>specvendor</dt> <dd>the specification vendor</dd> - * <dt>impltitle</dt> <dd>the implementation title</dd> - * <dt>implversion</dt> <dd>the implementation version.</dd> - * <dt>implvendor</dt> <dd>the implementation vendor</dd> - * <dt>mainclass</dt> <dd>the class to run when java -jar is invoked</dd> - * <dt>classpath</dt> <dd>the classpath to use when java -jar is invoked</dd> - * <dt>createdby</dt> <dd>the string to set the Created-By field to</dd> - * <dt>buildid</dt> <dd>A build identifier. Defaults to a build identifier - * containing <tt>date + " ("+username+"@"+hostname+" ["+os+" "+version+" "+arch+"]</tt> </dd> - * </dl> - * - * @author Kelly A. Campbell - */ - -public class Manifest extends Task { - public static final String MANIFEST_VERSION = "Manifest-Version: "; - public static final String CREATED_BY = "Created-By: "; - public static final String REQUIRED_VERSION = "Required-Version: "; - - public static final String SPECIFICATION_TITLE = "Specification-Title: "; - public static final String SPECIFICATION_VERSION = - "Specification-Version: "; - public static final String SPECIFICATION_VENDOR = - "Specification-Vendor: "; - public static final String IMPL_TITLE = "Implementation-Title: "; - public static final String IMPL_VERSION = "Implementation-Version: "; - public static final String IMPL_VENDOR = "Implementation-Vendor: "; - public static final String BUILD_ID = "Build-ID: "; - public static final String MAIN_CLASS = "Main-Class: "; - public static final String CLASS_PATH = "Class-Path: "; - - - private String _manifestVersion = "1.0"; - private String _spectitle; - private String _specvers; - private String _specvend; - private String _impltitle; - private String _implvers; - private String _implvend; - private String _mainclass; - private String _classpath; - private String _createdby; - private String _buildid; - - private String _manifestFilename; - private Boolean _overwrite = Boolean.FALSE; - - public void setFile(String s) { - _manifestFilename = s; - } - - public void setOverwrite(Boolean b) { - _overwrite = b; - } - - public void setSpectitle(String s) { - _spectitle = s; - } - - public void setSpecversion(String s) { - _specvers = s; - } - - public void setSpecvendor(String s) { - _specvend = s; - } - - public void setImpltitle(String s) { - _impltitle = s; - } - - public void setImplversion(String s) { - _implvers = s; - } - - public void setImplvendor(String s) { - _implvend = s; - } - - public void setMainclass(String s) { - _mainclass = s; - } - - public void setClasspath(String s) { - _classpath = s; - } - - public void setCreatedby(String s) { - _createdby = s; - } - - public void setBuildid(String s) { - _buildid = s; - } - - /** - * Main task method which runs this task and creates the manifest file. - * @exception BuildException if one of the required attributes isn't set - */ - public void execute() throws BuildException { - // System.out.println("Executing manifest task"); - - PrintWriter out; - try { - if (_manifestFilename != null) { - // open the file for writing - File f = new File(_manifestFilename); - if (f.exists()) { - if (_overwrite.booleanValue()) { - f.delete(); - } else { - throw new BuildException("Will not overwrite existing file: " - + _manifestFilename - + ". Use overwrite='yes' if you wish to overwrite the file."); - } - } - System.out.println("creating " + f); - - // jdk1.2 -- f.createNewFile(); - out = new PrintWriter(new FileOutputStream(f)); - - } else { - throw new BuildException("Manifest task requires a 'file' attribute"); - } - } catch (IOException ex) { - throw new BuildException(ex); - } - - // setup the implementation versionn (buildID) - if (_buildid == null || _buildid.trim().equals("")) { - _buildid = createBuildID(); - } - if (_createdby == null || _createdby.trim().equals("")) { - _createdby = getCreator(); - } - - print(out, MANIFEST_VERSION, _manifestVersion); - print(out, CREATED_BY, _createdby); - - print(out, SPECIFICATION_TITLE, _spectitle); - print(out, SPECIFICATION_VERSION, _specvers); - print(out, SPECIFICATION_VENDOR, _specvend); - print(out, IMPL_TITLE, _impltitle); - print(out, IMPL_VERSION, _implvers); - print(out, IMPL_VENDOR, _implvend); - print(out, BUILD_ID, _buildid); - print(out, MAIN_CLASS, _mainclass); - print(out, CLASS_PATH, _classpath); - - out.flush(); - out.close(); - - } - - protected void print(PrintWriter out, String header, String value) { - if (value != null &&!value.trim().equals("")) { - out.println(header + value); - // System.out.println("manifest: "+header+value); - } - } - - private static String createBuildID() { - Date d = new Date(); - SimpleDateFormat f = new SimpleDateFormat("yyyyMMdd-HHmmss-z"); - String date = f.format(d); - String hostname, username, os, version, arch; - try { - hostname = InetAddress.getLocalHost().getHostName(); - } catch (Exception ex) { - hostname = "unknown"; - } - username = System.getProperty("user.name"); - os = System.getProperty("os.name"); - version = System.getProperty("os.version"); - arch = System.getProperty("os.arch"); - String buildid = date + " (" + username + "@" + hostname + " [" + os - + " " + version + " " + arch + "])"; - return buildid; - - } - - private static String getCreator() { - try { - Properties props = new Properties(); - InputStream in = - org.apache.tools.ant.Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); - if (in != null) { - props.load(in); - in.close(); - - return "Ant " + props.getProperty("VERSION"); - } else { - return null; - } - } catch (IOException ex) { - return null; - } - } - -} diff --git a/src/org/apache/fop/tools/anttasks/Xslt.java b/src/org/apache/fop/tools/anttasks/Xslt.java deleted file mode 100644 index ed660fa20..000000000 --- a/src/org/apache/fop/tools/anttasks/Xslt.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.tools.anttasks; - -import org.apache.tools.ant.Task; -import java.net.*; -import java.io.*; -import java.util.*; -import org.w3c.dom.*; -import org.xml.sax.SAXException; - - - -/** - * Task to call the XSLT processor Xalan (part of xml.apache.org), which converts xml files - * from a source to an output using a stylesheet file - * - * <p> - * This task can take the following arguments: - * <ul> - * <li>infile - * <li>xsltfile - * <li>outfile - * <li>mergefile - * <li>smart - * <li>dependent - * </ul> - * <p> - * Of these arguments, <b>infile, outfile</b> and <b>xsltfile</b> are required. - * <p>smart defaults to 'no'. The other allowed value is 'yes'. If smart is set to 'yes' - * <P> - * xalan is only called if either the outfile is older than the infile or the stylesheet - * or the outfile doesn't exist. - * <P> - * <p>dependent defaults to 'none'. Other possible values: a comma delimited list of file names - * which date is checked against the output file. This way you can name files which, if - * they have been modified, initiate a restart of the xslt process, like external entities etc. - * <p> - * The mergefile parameter causes this task to merge the contents of the specified file into the infile at the end. This is used for the font character mapping generation because the keys() xslt function doesn't work on an external document. - * - * @author Fotis Jannidis <a href="mailto:fotis@jannidis.de">fotis@jannidis.de</a> - * @author Kelly A. Campbell <a href="mailto:camk@camk.net">camk@camk.net</a> - */ - - -public class Xslt extends Task { - private String infile, outfile, xsltfile, mergefile; - private String smart = - "no"; // defaults to do conversion everytime task is called - private String dependent = "none"; // defaults to no dependencies - private boolean startXslt = false; - - /** - * When true, we use the trax api's from xalan2, otherwise - * just the xalan1 native interfaces - */ - private boolean useTrax = false; - - - /** - * Sets the input file - * - */ - public void setInfile(String infile) { - this.infile = infile; - } - - public void setMergefile(String mergefile) { - this.mergefile = mergefile; - } - - /** - * Sets the stylesheet file - * - */ - public void setXsltfile(String xsltfile) { - this.xsltfile = xsltfile; - } - - /** - * Sets the output file - * - */ - public void setOutfile(String outfile) { - this.outfile = outfile; - } - - /** - * Sets the value for smart - * - * @param option valid values: - * <ul> - * <li>yes: check whether output file is older than input or stylesheet - * <li>no: (default) do conversion everytime task is called - * </ul> - */ - public void setSmart(String smart) { - this.smart = smart; - } - - /** - * Sets the value for dependent - * - * @param option valid values: - * <ul> - * <li>none: (default) - * <li>comma delimited list of files whose existence and date is checked - * against the output file - * </ul> - */ - public void setDependent(String dependent) { - this.dependent = dependent; - } - - - /** - * Builds a document from the given file, merging the mergefile onto the end of the root node - */ - private org.w3c.dom.Document buildDocument(String xmlFile) - throws IOException, SAXException { - try { - - javax.xml.parsers.DocumentBuilder docBuilder = - javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document doc = docBuilder.parse(new FileInputStream(xmlFile)); - - if (mergefile != null &&!mergefile.equals("")) { - - File mergefileF = new File(mergefile); - - Document mergedoc = - docBuilder.parse(new FileInputStream(mergefileF)); - Node mergenode = doc.importNode(mergedoc.getDocumentElement(), - true); - doc.getDocumentElement().appendChild(mergenode); - } - - return doc; - } catch (javax.xml.parsers.ParserConfigurationException e) { - System.out.println("Task xslt - SAX ERROR:\n " - + e.getMessage()); - } - return null; - } - - - /** - * Calls Xalan and does the transformation - * - */ - private void transform() { - try { - org.w3c.dom.Document source = null; - if (mergefile != null && !mergefile.equals("")) { - source = buildDocument(infile); - } - // Perform the transformation. - System.out.println("============================"); - System.out.println("xslt \nin: " + infile + "\nstyle: " - + xsltfile + "\nout: " + outfile); - System.out.println("============================"); - if (source != null) { - org.apache.fop.tools.xslt.XSLTransform.transform(source, - xsltfile, outfile); - } - else { - // Read the xml file directly - org.apache.fop.tools.xslt.XSLTransform.transform(infile, - xsltfile, outfile); - } - - - } catch (org.xml.sax.SAXException saxerror) { - System.out.println("Task xslt - SAX ERROR:\n " + saxerror); - } catch (MalformedURLException urlerror) { - System.out.println("Task xslt - URL ERROR:\n " + urlerror); - } catch (IOException ioerror) { - System.out.println("Task xslt - IO ERROR:\n " + ioerror); - } catch (Exception ex) { - ex.printStackTrace(); - } - - } // end transform - - - /** - * Checks for existence of output file and compares - * dates with input and stylesheet file - */ - private boolean smartCheck(File outfileF, long outfileLastModified, - File infileF, File xsltfileF) { - - if (outfileF.exists()) { - // checks whether output file is older than input file or xslt stylesheet file - if ((outfileLastModified < infileF.lastModified()) - | (outfileLastModified < xsltfileF.lastModified())) { - return true; - } - } else { - // if output file does not exist, start xslt process - return true; - } - return false; - } // end smartCheck - - /** - * Checks for existence and date of dependent files - * This could be folded together with smartCheck by using - * a general routine but it wouldn't be as fast as now - */ - private boolean dependenciesCheck(File outfileF, - long outfileLastModified) { - String dependentFileName; - File dependentFile; - StringTokenizer tokens = new StringTokenizer(dependent, ","); - while (tokens.hasMoreTokens()) { - dependentFileName = (String)tokens.nextToken(); - dependentFile = new File(dependentFileName); - // check: does dependent file exist - if (dependentFile.exists()) { - // check dates - if ((outfileLastModified < dependentFile.lastModified())) { - return true; - } - } else { - System.err.println("Task xslt - ERROR in attribute 'dependent':\n file " - + dependentFileName + " does not exist."); - } - } - return false; - } // end dependenciesCheck - - /** - * Main method, which is called by ant. - * Checks for the value of smart and calls startTransform accordingly - */ - public void execute() throws org.apache.tools.ant.BuildException { - - File outfileF = new File(outfile); - File infileF = new File(infile); - File xsltfileF = new File(xsltfile); - long outfileLastModified = outfileF.lastModified(); - boolean startFileExist = true; - - // checks whether input and stylesheet exist. - // this could be left to the parser, but this solution does make problems if smart is set to yes - if (!infileF.exists()) { - System.err.println("Task xslt - ERROR:\n Input file " - + infile + " does not exist!"); - startFileExist = false; - } else if (!xsltfileF.exists()) { - System.err.println("Task xslt - ERROR:\n Stylesheet file " - + xsltfile + " does not exist!"); - startFileExist = false; - } - - // checks attribute 'smart' - if (smart.equals("no")) { - startXslt = true; - // if attribute smart = 'yes' - } else if (smart.equals("yes")) { - startXslt = smartCheck(outfileF, outfileLastModified, infileF, - xsltfileF); - // checks dependent files against output file, makes only sense if smartCheck returns false - if (!dependent.equals("none") & (startXslt == false)) { - startXslt = dependenciesCheck(outfileF, outfileLastModified); - } - // returns error message, if smart has another value as 'yes' or 'no' - } else { - System.err.println("Task xslt - ERROR: Allowed values for the attribute smart are 'yes' or 'no'"); - } - if (startFileExist & startXslt) { - transform(); - } - } // end execute - - // quick access for debugging - // usage XSLT infile xsltfile outfile (smart is 'yes') - /* - * public static void main (String args[]) { - * Xslt xslt = new Xslt(); - * xslt.setInfile(args[0]); - * xslt.setXsltfile(args[1]); - * xslt.setOutfile(args[2]); - * xslt.setSmart("yes"); - * xslt.setDependent("test1,test2"); - * xslt.execute(); - * } - */ - - - - -} diff --git a/src/org/apache/fop/tools/xslt/XSLTransform.java b/src/org/apache/fop/tools/xslt/XSLTransform.java index c764af22e..7d129bf62 100644 --- a/src/org/apache/fop/tools/xslt/XSLTransform.java +++ b/src/org/apache/fop/tools/xslt/XSLTransform.java @@ -8,26 +8,34 @@ package org.apache.fop.tools.xslt; import java.io.*; -import java.lang.reflect.*; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.dom.DOMResult; +//import java.lang.reflect.*; public class XSLTransform { public static void transform(String xmlSource, String xslURL, String outputFile) throws Exception { - Class[] argTypes = { +/* Class[] argTypes = { String.class, String.class, String.class }; Object[] params = { xmlSource, xslURL, outputFile }; - transform(params, argTypes); + transform(params, argTypes);*/ + TransformerFactory.newInstance().newTransformer( + new StreamSource(xslURL)).transform( + new StreamSource(xmlSource),new StreamResult(new File(outputFile))); } public static void transform(org.w3c.dom.Document xmlSource, String xslURL, String outputFile) throws Exception { - Class[] argTypes = { +/* Class[] argTypes = { org.w3c.dom.Document.class, String.class, String.class }; @@ -35,25 +43,31 @@ public class XSLTransform { xmlSource, xslURL, outputFile }; transform(params, argTypes); - +*/ + TransformerFactory.newInstance().newTransformer( + new StreamSource(xslURL)).transform( + new DOMSource(xmlSource),new StreamResult(new File(outputFile))); } public static void transform(String xmlSource, String xslURL, Writer outputWriter) throws Exception { - Class[] argTypes = { +/* Class[] argTypes = { String.class, String.class, Writer.class }; Object[] params = { xmlSource, xslURL, outputWriter }; transform(params, argTypes); - +*/ + TransformerFactory.newInstance().newTransformer( + new StreamSource(xslURL)).transform( + new StreamSource(xmlSource),new StreamResult(outputWriter)); } public static void transform(org.w3c.dom.Document xmlSource, InputStream xsl, org.w3c.dom.Document outputDoc) throws Exception { - Class[] argTypes = { +/* Class[] argTypes = { org.w3c.dom.Document.class, InputStream.class, org.w3c.dom.Document.class }; @@ -61,10 +75,13 @@ public class XSLTransform { xmlSource, xsl, outputDoc }; transform(params, argTypes); - +*/ + TransformerFactory.newInstance().newTransformer( + new StreamSource(xsl)).transform( + new DOMSource(xmlSource),new DOMResult(outputDoc)); } - +/* private static void transform(Object[] args, Class[] argTypes) throws Exception { Class transformer = getTransformClass(); @@ -132,5 +149,5 @@ public class XSLTransform { } return null; } - +*/ } diff --git a/src/org/apache/fop/tools/xslt/Xalan1Transform.java b/src/org/apache/fop/tools/xslt/Xalan1Transform.java deleted file mode 100644 index 40fdbd9a7..000000000 --- a/src/org/apache/fop/tools/xslt/Xalan1Transform.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.tools.xslt; - -import org.apache.xalan.xslt.*; - -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.Hashtable; -import org.w3c.dom.Document; - -/** - * Handles xslt tranformations via Xalan1 (non-trax) - */ - -public class Xalan1Transform { - - /** - * Cache of compiled stylesheets (filename, StylesheetRoot) - */ - private static Hashtable _stylesheetCache = new Hashtable(); - - public static StylesheetRoot getStylesheet(String xsltFilename, boolean cache) - throws org.xml.sax.SAXException { - if (cache && _stylesheetCache.containsKey(xsltFilename)) { - return (StylesheetRoot)_stylesheetCache.get(xsltFilename); - } - - // Use XSLTProcessor to instantiate an XSLTProcessor. - XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); - - XSLTInputSource xslSheet = new XSLTInputSource(xsltFilename); - - // Perform the transformation. - StylesheetRoot compiledSheet = processor.processStylesheet(xslSheet); - if (cache) { - _stylesheetCache.put(xsltFilename, compiledSheet); - } - return compiledSheet; - } - - public static void transform(String xmlSource, String xslURL, - String outputFile) throws java.io.IOException, - java.net.MalformedURLException, - org.xml.sax.SAXException { - try { - javax.xml.parsers.DocumentBuilder docBuilder = - javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document doc = docBuilder.parse(new FileInputStream(xmlSource)); - transform(doc, xslURL, outputFile); - } catch (javax.xml.parsers.ParserConfigurationException ex) { - throw new org.xml.sax.SAXException(ex); - } - - } - - public static void transform(Document xmlSource, String xslURL, - String outputFile) throws java.io.IOException, - java.net.MalformedURLException, - org.xml.sax.SAXException { - - XSLTResultTarget xmlResult = new XSLTResultTarget(outputFile); - - StylesheetRoot stylesheet = getStylesheet(xslURL, true); - - // Perform the transformation. - stylesheet.process(XSLTProcessorFactory.getProcessor(), xmlSource, - xmlResult); - } - - public static void transform(String xmlSource, String xslURL, - java.io.Writer outputFile) throws java.io.IOException, - java.net.MalformedURLException, - org.xml.sax.SAXException { - - XSLTInputSource source = new XSLTInputSource(xmlSource); - XSLTResultTarget xmlResult = new XSLTResultTarget(outputFile); - - StylesheetRoot stylesheet = getStylesheet(xslURL, true); - - // Perform the transformation. - stylesheet.process(XSLTProcessorFactory.getProcessor(), source, - xmlResult); - } - - public static void transform(Document xmlSource, InputStream xsl, - Document outputDoc) throws java.io.IOException, - java.net.MalformedURLException, - org.xml.sax.SAXException { - - XSLTInputSource source = new XSLTInputSource(xmlSource); - XSLTInputSource xslSheet = new XSLTInputSource(xsl); - XSLTResultTarget xmlResult = new XSLTResultTarget(outputDoc); - - - // Perform the transformation. - XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); - - processor.process(source, xslSheet, xmlResult); - } - -} diff --git a/src/org/apache/fop/viewer/Images/reload.gif b/src/org/apache/fop/viewer/Images/reload.gif Binary files differnew file mode 100644 index 000000000..405718c1b --- /dev/null +++ b/src/org/apache/fop/viewer/Images/reload.gif diff --git a/src/org/apache/fop/viewer/LoadableProperties.java b/src/org/apache/fop/viewer/LoadableProperties.java index 6e00e00bf..4b28907a7 100644 --- a/src/org/apache/fop/viewer/LoadableProperties.java +++ b/src/org/apache/fop/viewer/LoadableProperties.java @@ -33,7 +33,7 @@ public class LoadableProperties extends Hashtable { public void load(InputStream inStream) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(inStream, - "8859_1")); + "UTF-8")); String aKey; String aValue; diff --git a/src/org/apache/fop/viewer/PreviewDialog.java b/src/org/apache/fop/viewer/PreviewDialog.java index 29ba72a8f..4370435db 100644 --- a/src/org/apache/fop/viewer/PreviewDialog.java +++ b/src/org/apache/fop/viewer/PreviewDialog.java @@ -33,6 +33,8 @@ import javax.swing.*; import org.apache.fop.layout.*; import org.apache.fop.render.awt.*; import org.apache.fop.messaging.*; +import org.apache.fop.apps.AWTStarter; +import org.apache.fop.apps.FOPException; /** * Frame and User Interface for Preview @@ -46,6 +48,7 @@ public class PreviewDialog extends JFrame implements ProgressListener, protected int pageCount = 0; protected AWTRenderer renderer; + protected AWTStarter starter; protected IconToolBar toolBar = new IconToolBar(); @@ -54,6 +57,8 @@ public class PreviewDialog extends JFrame implements ProgressListener, protected Command previousPageAction; protected Command nextPageAction; protected Command lastPageAction; + protected Command reloadAction; + protected Reloader reloader; protected JLabel zoomLabel = new JLabel(); // {public float getAlignmentY() { return 0.0f; }}; @@ -74,6 +79,18 @@ public class PreviewDialog extends JFrame implements ProgressListener, protected JLabel infoStatus = new JLabel(); protected JLabel previewImageLabel = new JLabel(); + /** + * Create a new PreviewDialog that uses the given starter, renderer and translator. + * + * @param aStarter the to use starter + * @param aRenderer the to use renderer + * @param aRes the to use translator + */ + public PreviewDialog(AWTStarter aStarter, AWTRenderer aRenderer, Translator aRes) { + this(aRenderer, aRes); + starter = aStarter; + } + /** * Create a new PreviewDialog that uses the given renderer and translator. * @@ -116,6 +133,12 @@ public class PreviewDialog extends JFrame implements ProgressListener, } }; + reloadAction = new Command(res.getString("Reload"), "reload") { + public void doit() { + reload(null); + } + + }; setDefaultCloseOperation(DISPOSE_ON_CLOSE); this.setSize(new Dimension(379, 476)); @@ -150,6 +173,7 @@ public class PreviewDialog extends JFrame implements ProgressListener, this.getContentPane().add(toolBar, BorderLayout.NORTH); toolBar.add(printAction); + toolBar.add(reloadAction); toolBar.addSeparator(); toolBar.add(firstPageAction); toolBar.add(previousPageAction); @@ -221,6 +245,12 @@ public class PreviewDialog extends JFrame implements ProgressListener, } }); + menu.add(new Command(res.getString("Reload")) { + public void doit() { + reload(null); + } + + }); menu.addSeparator(); menu.add(new Command(res.getString("Exit")) { public void doit() { @@ -385,6 +415,35 @@ public class PreviewDialog extends JFrame implements ProgressListener, } /** + * Reloads and reformats document. + */ + private synchronized void reload(ActionEvent e) { + if (reloader == null || !reloader.isAlive()) { + reloader = new Reloader(); + reloader.start(); + } + } + + /** + * This class is used to reload document in + * a thread safe way. + */ + private class Reloader extends Thread { + public void run() { + previewImageLabel.setIcon(null); + statisticsStatus.setText(""); + //Cleans up renderer + while (renderer.getPageCount() != 0) + renderer.removePage(0); + try { + starter.run(); + } catch (FOPException e) { + e.printStackTrace(); + } + } + } + + /** * Shows a page by number. */ private void goToPage(ActionEvent e) { @@ -626,9 +685,15 @@ public class PreviewDialog extends JFrame implements ProgressListener, } } - - public void dispose() { - System.exit(0); + public void reportException(Exception e) { + String msg = res.getString("An exception has occured"); + progress(msg); + JOptionPane.showMessageDialog( + getContentPane(), + "<html><b>" + msg + ":</b><br>" + + e.getClass().getName() + "<br>" + e.getMessage() + "</html>", res.getString("Fatal error"), + JOptionPane.ERROR_MESSAGE + ); } } // class PreviewDialog diff --git a/src/org/apache/fop/viewer/resources/messages.cs b/src/org/apache/fop/viewer/resources/messages.cs new file mode 100644 index 000000000..a7fd487e4 --- /dev/null +++ b/src/org/apache/fop/viewer/resources/messages.cs @@ -0,0 +1,80 @@ +############################################################################### +# +# This file contains the czech messages. +# +# NOTICE: When defining a new message it has to be created in message files for each language. +# +# +# +# +# DEFINING A MESSAGE +# ================== +# +# A message has a uinique CHARACTER ID. It is placed on the left hand side of the equation. +# For each message there are additional switches: +# - iconType (see below) +# - buttonType (see below) +# - messageText may contain placeholders for parameters. + +# A placeholder pattern is a "&&&" . See Examplemessage "No_Records_found". +# +# A messsage definition is placed within a single row, its switches are seperated by a colon ":". +# +# Format: +# ======= +# <MESSAGE_ID>=<iconType>:<buttonType>:<message text> +# +# +# Allowed values for: +# =================== +# iconType: +# INFO +# WARNING +# ERROR +# QUESTION +# +# buttonType: +# STYLE_Y ("yes" Button) +# STYLE_Y_N ("yes" and "no" Buttons) +# STYLE_Y_N_C ("yes", "no" and "cancel" Buttons) +# +# +# Example with a parameter array: +# ================================ +# Message definition: +# No_Records_found=WARNING:STYLE_Y:The Table &&& has no records. Expected at least &&&. Continue? +# Aufruf: +# answer = UserMessage.show("No_Records_found", new String[] {"Employee", "" + minNumber}, aShowFrame); +# if (answer == UserMessage.NO) +# return; +# +# Example with an Exception: +# ============================= +# Message definition: +# UNEXPECTED_EXCEPTION=ERROR:STYLE_Y:Wow! An exception! +# +# Aufruf: +# try { +# String str = null; +# int index = str.indexOf("abc"); +# } catch (Exception ex) { +# UserMessage.show("UNEXPECTED_EXCEPTION", ex); +# } +# +# +# +# +################################################################################################# + + +# Titles +Info=Informace +Warning=Varování +Question=Dotaz +Error=Chyba + +# Messages +TRANSLATION_SOURCE_NOT_FOUND=WARNING:STYLE_Y:Soubor &&& s překladem nebyl nalezen. +UNKNOWN_EXCEPTION=ERROR:STYLE_Y:Neznámá chyba. +UNHANDLED_EXCEPTION=ERROR:STYLE_Y:Vnitřní chyba. + diff --git a/src/org/apache/fop/viewer/resources/messages.de b/src/org/apache/fop/viewer/resources/messages.de index 8db0001a8..9cf0ecd5e 100644 --- a/src/org/apache/fop/viewer/resources/messages.de +++ b/src/org/apache/fop/viewer/resources/messages.de @@ -2,7 +2,7 @@ # # In dieser Datei werden im Abschnitt "Messages" Meldungen auf deutsch # definiert. -# Zu beachten: Beim Definieren einer neuen neuen Meldung, diese soweit mglich +# Zu beachten: Beim Definieren einer neuen neuen Meldung, diese soweit möglich # in allen Sprachen anlegen. # # @@ -14,9 +14,9 @@ # Zu jeder Meldung wird angegeben: # - iconType (Typen siehe unten) # - buttonType (Typen siehe unten) -# - Meldungstext mit evtl. Platzhaltern fr Parameter. +# - Meldungstext mit evtl. Platzhaltern für Parameter. # -# Ein Parameterplatzhalter ist ein dreifaches kaumnisches "und". Siehe Beispielmeldung +# Ein Parameterplatzhalter ist ein dreifaches kaumänisches "und". Siehe Beispielmeldung # "No_Records_found". # # Die Angaben erfolgen in einer Zeile, jeweils durch einen Doppelpunkt getrennt. @@ -24,7 +24,7 @@ # Format: # <MESSAGE_ID>=<iconType>:<buttonType>:<Meldungstext> # -# Zulssige Werte fr: +# Zulässige Werte für: # iconType: # INFO # WARNING @@ -40,7 +40,7 @@ # Beispiel mit einem String-Array: # ================================ # Messagedefinition: -# No_Records_found=WARNING:STYLE_Y:Die Tabelle &&& enthlt keinen Eintrag. Erwartet mind. &&&. Weitermachen? +# No_Records_found=WARNING:STYLE_Y:Die Tabelle &&& enthält keinen Eintrag. Erwartet mind. &&&. Weitermachen? # Aufruf: # answer = UserMessage.show("No_Records_found", new String[] {"Mitarbeiter", "" + minNumber}, aShowFrame); # if (answer == UserMessage.NO) @@ -72,7 +72,7 @@ Question=Frage Error=Fehler # Messages -TRANSLATION_SOURCE_NOT_FOUND=WARNING:STYLE_Y:Die bersetzungsdatei &&& ist nicht gefunden. +TRANSLATION_SOURCE_NOT_FOUND=WARNING:STYLE_Y:Die Übersetzungsdatei &&& ist nicht gefunden. UNKNOWN_EXCEPTION=ERROR:STYLE_Y:Unbekannter Fehler UNHANDLED_EXCEPTION=ERROR:STYLE_Y:Interner Fehler diff --git a/src/org/apache/fop/viewer/resources/messages.ja b/src/org/apache/fop/viewer/resources/messages.ja new file mode 100644 index 000000000..f87aabfbc --- /dev/null +++ b/src/org/apache/fop/viewer/resources/messages.ja @@ -0,0 +1,80 @@ +############################################################################### +# +# This file contains the Japanese messages. +# +# NOTICE: When defining a new message it has to be created in message files for each language. +# +# +# +# +# DEFINING A MESSAGE +# ================== +# +# A message has a uinique CHARACTER ID. It is placed on the left hand side of the equation. +# For each message there are additional switches: +# - iconType (see below) +# - buttonType (see below) +# - messageText may contain placeholders for parameters. + +# A placeholder pattern is a "&&&" . See Examplemessage "No_Records_found". +# +# A messsage definition is placed within a single row, its switches are seperated by a colon ":". +# +# Format: +# ======= +# <MESSAGE_ID>=<iconType>:<buttonType>:<message text> +# +# +# Allowed values for: +# =================== +# iconType: +# INFO +# WARNING +# ERROR +# QUESTION +# +# buttonType: +# STYLE_Y ("yes" Button) +# STYLE_Y_N ("yes" and "no" Buttons) +# STYLE_Y_N_C ("yes", "no" and "cancel" Buttons) +# +# +# Example with a parameter array: +# ================================ +# Message definition: +# No_Records_found=WARNING:STYLE_Y:The Table &&& has no records. Expected at least &&&. Continue? +# Aufruf: +# answer = UserMessage.show("No_Records_found", new String[] {"Employee", "" + minNumber}, aShowFrame); +# if (answer == UserMessage.NO) +# return; +# +# Example with an Exception: +# ============================= +# Message definition: +# UNEXPECTED_EXCEPTION=ERROR:STYLE_Y:Wow! An exception! +# +# Aufruf: +# try { +# String str = null; +# int index = str.indexOf("abc"); +# } catch (Exception ex) { +# UserMessage.show("UNEXPECTED_EXCEPTION", ex); +# } +# +# +# +# +################################################################################################# + + +# Titles +Info=情報 +Warning=警告 +Question=質問 +Error=エラー + +# Messages +TRANSLATION_SOURCE_NOT_FOUND=WARNING:STYLE_Y:指定されたファイルが &&& 見つかりません。 +UNKNOWN_EXCEPTION=ERROR:STYLE_Y:不明なエラー +UNHANDLED_EXCEPTION=ERROR:STYLE_Y:内部エラー + diff --git a/src/org/apache/fop/viewer/resources/messages.ru b/src/org/apache/fop/viewer/resources/messages.ru new file mode 100644 index 000000000..9afa6462e --- /dev/null +++ b/src/org/apache/fop/viewer/resources/messages.ru @@ -0,0 +1,80 @@ +############################################################################### +# +# This file contains the russian messages. +# +# NOTICE: When defining a new message it has to be created in message files for each language. +# +# +# +# +# DEFINING A MESSAGE +# ================== +# +# A message has a uinique CHARACTER ID. It is placed on the left hand side of the equation. +# For each message there are additional switches: +# - iconType (see below) +# - buttonType (see below) +# - messageText may contain placeholders for parameters. + +# A placeholder pattern is a "&&&" . See Examplemessage "No_Records_found". +# +# A messsage definition is placed within a single row, its switches are seperated by a colon ":". +# +# Format: +# ======= +# <MESSAGE_ID>=<iconType>:<buttonType>:<message text> +# +# +# Allowed values for: +# =================== +# iconType: +# INFO +# WARNING +# ERROR +# QUESTION +# +# buttonType: +# STYLE_Y ("yes" Button) +# STYLE_Y_N ("yes" and "no" Buttons) +# STYLE_Y_N_C ("yes", "no" and "cancel" Buttons) +# +# +# Example with a parameter array: +# ================================ +# Message definition: +# No_Records_found=WARNING:STYLE_Y:The Table &&& has no records. Expected at least &&&. Continue? +# Aufruf: +# answer = UserMessage.show("No_Records_found", new String[] {"Employee", "" + minNumber}, aShowFrame); +# if (answer == UserMessage.NO) +# return; +# +# Example with an Exception: +# ============================= +# Message definition: +# UNEXPECTED_EXCEPTION=ERROR:STYLE_Y:Wow! An exception! +# +# Aufruf: +# try { +# String str = null; +# int index = str.indexOf("abc"); +# } catch (Exception ex) { +# UserMessage.show("UNEXPECTED_EXCEPTION", ex); +# } +# +# +# +# +################################################################################################# + + +# Titles +Info=Информация +Warning=Предупреждение +Question=Вопрос +Error=Ошибка + +# Messages +TRANSLATION_SOURCE_NOT_FOUND=WARNING:STYLE_Y:Файл трансляции &&& не найден. +UNKNOWN_EXCEPTION=ERROR:STYLE_Y:Неизвестная ошибка. +UNHANDLED_EXCEPTION=ERROR:STYLE_Y:Внутренняя ошибка. + diff --git a/src/org/apache/fop/viewer/resources/resources.cs b/src/org/apache/fop/viewer/resources/resources.cs new file mode 100644 index 000000000..8d507407a --- /dev/null +++ b/src/org/apache/fop/viewer/resources/resources.cs @@ -0,0 +1,17 @@ +File=Soubor +Print=Tisk +Exit=Konec +View=Zobrazit +First page=První strana +Previous page=Předchozí strana +Next page=Další strana +Last page=Poslední strana +Zoom=Lupa +Default zoom=Standardní lupa +Help=Nápověda +Index=Rejstřík +Introduction=Představení +About=O aplikaci +Page=Strana + + diff --git a/src/org/apache/fop/viewer/resources/resources.de b/src/org/apache/fop/viewer/resources/resources.de index 400a326ba..baf49a930 100644 --- a/src/org/apache/fop/viewer/resources/resources.de +++ b/src/org/apache/fop/viewer/resources/resources.de @@ -6,7 +6,7 @@ View=Anzeige Previous page=Vorherige Seite -Next page=Nchste Seite +Next page=Nächste Seite Last page=Letzte Seite @@ -16,7 +16,7 @@ Default zoom=Standardzoom Introduction=Einleitung -About=ber +About=Über Show=Anzeigen @@ -40,6 +40,6 @@ Layout FO tree=Formatiere FO-Baum Render=Gebe aus -Close=Schlieen +Close=Schließen Go to Page=Gehe zur Seite diff --git a/src/org/apache/fop/viewer/resources/resources.en b/src/org/apache/fop/viewer/resources/resources.en index acf0ef669..189902eee 100644 --- a/src/org/apache/fop/viewer/resources/resources.en +++ b/src/org/apache/fop/viewer/resources/resources.en @@ -1,4 +1,4 @@ -# Diese Datei ist nur dafr da, da die Warnung -# "bersetzungsdatei nicht gefunden" nicht hochkommt. -# Die Suchschlssel fr die zu bersetzenden Begriffe sind -# englisch. Daher wre eine bersetzung redundant. +# Diese Datei ist nur dafür da, daß die Warnung +# "Übersetzungsdatei nicht gefunden" nicht hochkommt. +# Die Suchschlüssel für die zu übersetzenden Begriffe sind +# englisch. Daher wäre eine Übersetzung redundant. diff --git a/src/org/apache/fop/viewer/resources/resources.fi b/src/org/apache/fop/viewer/resources/resources.fi index 97219031d..b8f6bfb72 100644 --- a/src/org/apache/fop/viewer/resources/resources.fi +++ b/src/org/apache/fop/viewer/resources/resources.fi @@ -1,14 +1,14 @@ File=Tiedosto Print=Tulosta Exit=Poistu -View=Nyt -First page=Ensimminen sivu +View=Näytä +First page=Ensimmäinen sivu Previous page=Edellinen sivu Next page=Seuraava sivu Last page=Viimeinen sivu Default zoom=Normaali zoom Help=Ohje -Index=Sisllys +Index=Sisällys Introduction=Esittely About=Tietoja Page=Sivu diff --git a/src/org/apache/fop/viewer/resources/resources.fr b/src/org/apache/fop/viewer/resources/resources.fr index 5287dcbb9..a568c2b5a 100644 --- a/src/org/apache/fop/viewer/resources/resources.fr +++ b/src/org/apache/fop/viewer/resources/resources.fr @@ -2,12 +2,12 @@ File=Fichier Print=Imprimer Exit=Quitter View=Affichage -First page=Premire page -Previous page=Page prcdente +First page=Première page +Previous page=Page précédente Next page=Page suivante -Last page=Dernire page +Last page=Dernière page Help=Aide -Default zoom=Zoom par dfaut +Default zoom=Zoom par défaut Introduction=Introduction About=A propos diff --git a/src/org/apache/fop/viewer/resources/resources.ja b/src/org/apache/fop/viewer/resources/resources.ja new file mode 100644 index 000000000..1f9fc94ed --- /dev/null +++ b/src/org/apache/fop/viewer/resources/resources.ja @@ -0,0 +1,26 @@ +File=ファイル +Print=印刷 +Exit=終了 +View=表示 +First page=開始ページ +Previous page=前ページ +Next page=次ページ +Last page=最終ページ +Go to Page=ページ指定 +Zoom=ズーム +Default zoom=デフォルトのズーム +Help=ヘルプ +Index=索引 +Introduction=紹介 +About=バージョン情報 + +Page=ページ +of=/ + +Init parser=XMLパーサ初期化中 +Init mappings=マッピング初期化中 +Build FO tree=FOツリー構築中 +Layout FO tree=FOツリーレイアウト中 +Render=レンダリング中 +Show=完了 +Close=閉じる diff --git a/src/org/apache/fop/viewer/resources/resources.pl b/src/org/apache/fop/viewer/resources/resources.pl index 9b727e151..73d7f408a 100644 --- a/src/org/apache/fop/viewer/resources/resources.pl +++ b/src/org/apache/fop/viewer/resources/resources.pl @@ -1,16 +1,16 @@ File=Plik Print=Drukuj -Exit=Zakocz +Exit=Zakoñcz View=Widok First page=Pierwsza strona Previous page=Poprzednia strona -Next page=Nastpna strona +Next page=Nastêpna strona Last page=Ostatnia strona -Zoom=Powikszenie -Default zoom=Domylne powiekszenie +Zoom=Powiêkszenie +Default zoom=Domy¶lne powiekszenie Help=Pomoc Index=Indeks -Introduction=Wstp +Introduction=Wstêp About=O programie Page=Strona diff --git a/src/org/apache/fop/viewer/resources/resources.ru b/src/org/apache/fop/viewer/resources/resources.ru index 84309253e..44ab75cbe 100644 --- a/src/org/apache/fop/viewer/resources/resources.ru +++ b/src/org/apache/fop/viewer/resources/resources.ru @@ -1,38 +1,38 @@ -File= +File=Файл -Exit= +Exit=Выход -View= +View=Вид -First page= +First page=Первая страница -Previous page= +Previous page=Предыдущая страница -Next page= +Next page=Следующая страница -Last page= +Last page=Последняя страница -Go to Page= +Go to Page=Перейти к странице -Help= +Help=Помощь -Default zoom= +Default zoom=Стандартный размер -Introduction= +Introduction=Введение -About= +About=О продукте -Show= +Show=Просмотр -Preview= +Preview=Просмотр -Print= +Print=Печать -Page= +Page=Страница -of= +of=из -Zoom= +Zoom=Размер -Close= +Close=Закрыть |