--- /dev/null
+# makefile for fop
+#
+# use gmake
+#
+BASEDIR=.
+
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=org
+
+CODEGEN=codegen
+
+GENDIR=generated
+
+JARTEMP=jartemp
+
+JARTOC=jartoc
+
+JARFILE=fop.jar
+
+SRCJAR=fopsrc.jar
+
+FONTXMLBASE=Courier.xml \
+ Courier-Oblique.xml \
+ Courier-Bold.xml \
+ Courier-BoldOblique.xml \
+ Helvetica.xml \
+ Helvetica-Oblique.xml \
+ Helvetica-Bold.xml \
+ Helvetica-BoldOblique.xml \
+ Times-Roman.xml \
+ Times-Italic.xml \
+ Times-Bold.xml \
+ Times-BoldItalic.xml
+
+FONTXML=$(FONTXMLBASE:%=$(CODEGEN)/%)
+
+FONTXSL=$(CODEGEN)/font-file.xsl
+
+PROPERTIESXML=$(CODEGEN)/properties.xml
+PROPERTIESXSL=$(CODEGEN)/properties.xsl
+CHARLISTXML =$(CODEGEN)/charlist.xml
+CHARLISTXSL =$(CODEGEN)/code-point-mapping.xsl
+
+all: codegen allsubs
+
+clean: cleansubs
+ rm -f *~
+
+clobber: clean
+ rm -rf $(GENDIR)
+ rm -rf $(JARTEMP) $(JARTOC) $(JARFILE)
+ rm -f $(SRCJAR)
+
+
+
+codegen: $(GENDIR) compilegen
+
+compilegen: properties charlist fonts
+ cd $(GENDIR) && \
+ ($(FIND) . -name \*.java -print > javafiletoc) && \
+ for javafile in `cat javafiletoc` ; do \
+ echo $(JAVAC) $(JAVAC_ARGS) $$javafile ;\
+ $(JAVAC) $(JAVAC_ARGS) $$javafile ;\
+ done
+
+$(GENDIR):
+ mkdir -p $(GENDIR)/org/apache/xml/fop/fo/properties;
+ mkdir -p $(GENDIR)/org/apache/xml/fop/render/pdf/fonts;
+
+properties: $(PROPERTIESXML) $(PROPERTIESXSL)
+ cd $(GENDIR) && $(XT) ../$(PROPERTIESXML) ../$(PROPERTIESXSL)
+
+charlist: $(CHARLISTXML) $(CHARLISTXSL)
+ cd $(GENDIR) && $(XT) ../$(CHARLISTXML) ../$(CHARLISTXSL)
+
+fonts: $(FONTXML) $(FONTXSL)
+ cd $(GENDIR) && for font in $(FONTXML) ; do $(XT) ../$$font ../$(FONTXSL) ; done
+
+dist: all $(JARTEMP) distgen distorg
+ rm -f $(JARFILE)
+ cd $(JARTEMP) && $(JAR) -cf ../$(JARFILE) *
+ rm -rf $(JARTEMP) $(JARTOC)
+
+srcdist: clobber
+ $(JAR) -cf $(SRCJAR) .
+
+$(JARTEMP):
+ mkdir $(JARTEMP)
+
+distgen:
+ cd $(GENDIR) && \
+ rm -f $(JARTOC) && \
+ ($(FIND) . -name \*.class -print > $(JARTOC)) && \
+ ($(TAR) -cf - -T $(JARTOC) | (cd ../$(JARTEMP); $(TAR) -xf - ))
+
+distorg:
+ rm -f $(JARTOC) && \
+ ($(FIND) org -name \*.class -print > $(JARTOC)) && \
+ ($(TAR) -cf - -T $(JARTOC) | (cd $(JARTEMP); $(TAR) -xf - ))
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+#
+#
+#
+
+JAVA = java
+JAVAC = javac
+#JAVAC = jikes
+#JAVAC_ARGS = -g $(BASEDIR)/generated:$(CLASSPATH)
+
+# following class path is for CygWin bash
+JAVAC_ARGS = -g:none -classpath "$(BASEDIR)/generated;$(CLASSPATH)"
+
+FIND=find
+TAR=tar
+JAR=jar
+
+XT=${JAVA} com.jclark.xsl.sax.Driver
+
+TARGETS = all clean clobber
+
+.SUFFIXES: .java .class .xml $(SUFFIXES)
+
+.java.class:
+ $(JAVAC) $(JAVAC_ARGS) $<
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Courier-Bold</font-name>
+ <class-name>CourierBold</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>562</cap-height>
+ <x-height>439</x-height>
+ <ascender>626</ascender>
+ <descender>-142</descender>
+ <widths>
+ <char name="A" width="600"/>
+ <char name="AE" width="600"/>
+ <char name="Aacute" width="600"/>
+ <char name="Acircumflex" width="600"/>
+ <char name="Adieresis" width="600"/>
+ <char name="Agrave" width="600"/>
+ <char name="Aring" width="600"/>
+ <char name="Atilde" width="600"/>
+ <char name="B" width="600"/>
+ <char name="C" width="600"/>
+ <char name="Ccedilla" width="600"/>
+ <char name="D" width="600"/>
+ <char name="E" width="600"/>
+ <char name="Eacute" width="600"/>
+ <char name="Ecircumflex" width="600"/>
+ <char name="Edieresis" width="600"/>
+ <char name="Egrave" width="600"/>
+ <char name="Eth" width="600"/>
+ <char name="F" width="600"/>
+ <char name="G" width="600"/>
+ <char name="Gcaron" width="600"/>
+ <char name="H" width="600"/>
+ <char name="I" width="600"/>
+ <char name="IJ" width="600"/>
+ <char name="Iacute" width="600"/>
+ <char name="Icircumflex" width="600"/>
+ <char name="Idieresis" width="600"/>
+ <char name="Idot" width="600"/>
+ <char name="Igrave" width="600"/>
+ <char name="J" width="600"/>
+ <char name="K" width="600"/>
+ <char name="L" width="600"/>
+ <char name="LL" width="600"/>
+ <char name="Lslash" width="600"/>
+ <char name="M" width="600"/>
+ <char name="N" width="600"/>
+ <char name="Ntilde" width="600"/>
+ <char name="O" width="600"/>
+ <char name="OE" width="600"/>
+ <char name="Oacute" width="600"/>
+ <char name="Ocircumflex" width="600"/>
+ <char name="Odieresis" width="600"/>
+ <char name="Ograve" width="600"/>
+ <char name="Oslash" width="600"/>
+ <char name="Otilde" width="600"/>
+ <char name="P" width="600"/>
+ <char name="Q" width="600"/>
+ <char name="R" width="600"/>
+ <char name="S" width="600"/>
+ <char name="Scaron" width="600"/>
+ <char name="Scedilla" width="600"/>
+ <char name="T" width="600"/>
+ <char name="Thorn" width="600"/>
+ <char name="U" width="600"/>
+ <char name="Uacute" width="600"/>
+ <char name="Ucircumflex" width="600"/>
+ <char name="Udieresis" width="600"/>
+ <char name="Ugrave" width="600"/>
+ <char name="V" width="600"/>
+ <char name="W" width="600"/>
+ <char name="X" width="600"/>
+ <char name="Y" width="600"/>
+ <char name="Yacute" width="600"/>
+ <char name="Ydieresis" width="600"/>
+ <char name="Z" width="600"/>
+ <char name="Zcaron" width="600"/>
+ <char name="a" width="600"/>
+ <char name="aacute" width="600"/>
+ <char name="acircumflex" width="600"/>
+ <char name="acute" width="600"/>
+ <char name="adieresis" width="600"/>
+ <char name="ae" width="600"/>
+ <char name="agrave" width="600"/>
+ <char name="ampersand" width="600"/>
+ <char name="aring" width="600"/>
+ <char name="arrowboth" width="600"/>
+ <char name="arrowdown" width="600"/>
+ <char name="arrowleft" width="600"/>
+ <char name="arrowright" width="600"/>
+ <char name="arrowup" width="600"/>
+ <char name="asciicircum" width="600"/>
+ <char name="asciitilde" width="600"/>
+ <char name="asterisk" width="600"/>
+ <char name="at" width="600"/>
+ <char name="atilde" width="600"/>
+ <char name="b" width="600"/>
+ <char name="backslash" width="600"/>
+ <char name="bar" width="600"/>
+ <char name="braceleft" width="600"/>
+ <char name="braceright" width="600"/>
+ <char name="bracketleft" width="600"/>
+ <char name="bracketright" width="600"/>
+ <char name="breve" width="600"/>
+ <char name="brokenbar" width="600"/>
+ <char name="bullet" width="600"/>
+ <char name="c" width="600"/>
+ <char name="caron" width="600"/>
+ <char name="ccedilla" width="600"/>
+ <char name="cedilla" width="600"/>
+ <char name="cent" width="600"/>
+ <char name="center" width="600"/>
+ <char name="circumflex" width="600"/>
+ <char name="colon" width="600"/>
+ <char name="comma" width="600"/>
+ <char name="copyright" width="600"/>
+ <char name="currency" width="600"/>
+ <char name="d" width="600"/>
+ <char name="dagger" width="600"/>
+ <char name="daggerdbl" width="600"/>
+ <char name="dectab" width="600"/>
+ <char name="degree" width="600"/>
+ <char name="dieresis" width="600"/>
+ <char name="divide" width="600"/>
+ <char name="dollar" width="600"/>
+ <char name="dotaccent" width="600"/>
+ <char name="dotlessi" width="600"/>
+ <char name="down" width="600"/>
+ <char name="e" width="600"/>
+ <char name="eacute" width="600"/>
+ <char name="ecircumflex" width="600"/>
+ <char name="edieresis" width="600"/>
+ <char name="egrave" width="600"/>
+ <char name="eight" width="600"/>
+ <char name="ellipsis" width="600"/>
+ <char name="emdash" width="600"/>
+ <char name="endash" width="600"/>
+ <char name="equal" width="600"/>
+ <char name="eth" width="600"/>
+ <char name="exclam" width="600"/>
+ <char name="exclamdown" width="600"/>
+ <char name="f" width="600"/>
+ <char name="fi" width="600"/>
+ <char name="five" width="600"/>
+ <char name="fl" width="600"/>
+ <char name="florin" width="600"/>
+ <char name="format" width="600"/>
+ <char name="four" width="600"/>
+ <char name="fraction" width="600"/>
+ <char name="g" width="600"/>
+ <char name="gcaron" width="600"/>
+ <char name="germandbls" width="600"/>
+ <char name="grave" width="600"/>
+ <char name="graybox" width="600"/>
+ <char name="greater" width="600"/>
+ <char name="guillemotleft" width="600"/>
+ <char name="guillemotright" width="600"/>
+ <char name="guilsinglleft" width="600"/>
+ <char name="guilsinglright" width="600"/>
+ <char name="h" width="600"/>
+ <char name="hungarumlaut" width="600"/>
+ <char name="hyphen" width="600"/>
+ <char name="i" width="600"/>
+ <char name="iacute" width="600"/>
+ <char name="icircumflex" width="600"/>
+ <char name="idieresis" width="600"/>
+ <char name="igrave" width="600"/>
+ <char name="ij" width="600"/>
+ <char name="indent" width="600"/>
+ <char name="j" width="600"/>
+ <char name="k" width="600"/>
+ <char name="l" width="600"/>
+ <char name="largebullet" width="600"/>
+ <char name="left" width="600"/>
+ <char name="less" width="600"/>
+ <char name="lira" width="600"/>
+ <char name="ll" width="600"/>
+ <char name="logicalnot" width="600"/>
+ <char name="lslash" width="600"/>
+ <char name="m" width="600"/>
+ <char name="macron" width="600"/>
+ <char name="merge" width="600"/>
+ <char name="minus" width="600"/>
+ <char name="mu" width="600"/>
+ <char name="multiply" width="600"/>
+ <char name="n" width="600"/>
+ <char name="nine" width="600"/>
+ <char name="notegraphic" width="600"/>
+ <char name="ntilde" width="600"/>
+ <char name="numbersign" width="600"/>
+ <char name="o" width="600"/>
+ <char name="oacute" width="600"/>
+ <char name="ocircumflex" width="600"/>
+ <char name="odieresis" width="600"/>
+ <char name="oe" width="600"/>
+ <char name="ogonek" width="600"/>
+ <char name="ograve" width="600"/>
+ <char name="one" width="600"/>
+ <char name="onehalf" width="600"/>
+ <char name="onequarter" width="600"/>
+ <char name="onesuperior" width="600"/>
+ <char name="ordfeminine" width="600"/>
+ <char name="ordmasculine" width="600"/>
+ <char name="oslash" width="600"/>
+ <char name="otilde" width="600"/>
+ <char name="overscore" width="600"/>
+ <char name="p" width="600"/>
+ <char name="paragraph" width="600"/>
+ <char name="parenleft" width="600"/>
+ <char name="parenright" width="600"/>
+ <char name="percent" width="600"/>
+ <char name="period" width="600"/>
+ <char name="periodcentered" width="600"/>
+ <char name="perthousand" width="600"/>
+ <char name="plus" width="600"/>
+ <char name="plusminus" width="600"/>
+ <char name="prescription" width="600"/>
+ <char name="q" width="600"/>
+ <char name="question" width="600"/>
+ <char name="questiondown" width="600"/>
+ <char name="quotedbl" width="600"/>
+ <char name="quotedblbase" width="600"/>
+ <char name="quotedblleft" width="600"/>
+ <char name="quotedblright" width="600"/>
+ <char name="quoteleft" width="600"/>
+ <char name="quoteright" width="600"/>
+ <char name="quotesinglbase" width="600"/>
+ <char name="quotesingle" width="600"/>
+ <char name="r" width="600"/>
+ <char name="registered" width="600"/>
+ <char name="return" width="600"/>
+ <char name="ring" width="600"/>
+ <char name="s" width="600"/>
+ <char name="scaron" width="600"/>
+ <char name="scedilla" width="600"/>
+ <char name="section" width="600"/>
+ <char name="semicolon" width="600"/>
+ <char name="seven" width="600"/>
+ <char name="six" width="600"/>
+ <char name="slash" width="600"/>
+ <char name="space" width="600"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="600"/>
+ <char name="square" width="600"/>
+ <char name="sterling" width="600"/>
+ <char name="stop" width="600"/>
+ <char name="t" width="600"/>
+ <char name="tab" width="600"/>
+ <char name="thorn" width="600"/>
+ <char name="three" width="600"/>
+ <char name="threequarters" width="600"/>
+ <char name="threesuperior" width="600"/>
+ <char name="tilde" width="600"/>
+ <char name="trademark" width="600"/>
+ <char name="two" width="600"/>
+ <char name="twosuperior" width="600"/>
+ <char name="u" width="600"/>
+ <char name="uacute" width="600"/>
+ <char name="ucircumflex" width="600"/>
+ <char name="udieresis" width="600"/>
+ <char name="ugrave" width="600"/>
+ <char name="underscore" width="600"/>
+ <char name="up" width="600"/>
+ <char name="v" width="600"/>
+ <char name="w" width="600"/>
+ <char name="x" width="600"/>
+ <char name="y" width="600"/>
+ <char name="yacute" width="600"/>
+ <char name="ydieresis" width="600"/>
+ <char name="yen" width="600"/>
+ <char name="z" width="600"/>
+ <char name="zcaron" width="600"/>
+ <char name="zero" width="600"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Courier-BoldOblique</font-name>
+ <class-name>CourierBoldOblique</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>562</cap-height>
+ <x-height>439</x-height>
+ <ascender>626</ascender>
+ <descender>-142</descender>
+ <widths>
+ <char name="A" width="600"/>
+ <char name="AE" width="600"/>
+ <char name="Aacute" width="600"/>
+ <char name="Acircumflex" width="600"/>
+ <char name="Adieresis" width="600"/>
+ <char name="Agrave" width="600"/>
+ <char name="Aring" width="600"/>
+ <char name="Atilde" width="600"/>
+ <char name="B" width="600"/>
+ <char name="C" width="600"/>
+ <char name="Ccedilla" width="600"/>
+ <char name="D" width="600"/>
+ <char name="E" width="600"/>
+ <char name="Eacute" width="600"/>
+ <char name="Ecircumflex" width="600"/>
+ <char name="Edieresis" width="600"/>
+ <char name="Egrave" width="600"/>
+ <char name="Eth" width="600"/>
+ <char name="F" width="600"/>
+ <char name="G" width="600"/>
+ <char name="Gcaron" width="600"/>
+ <char name="H" width="600"/>
+ <char name="I" width="600"/>
+ <char name="IJ" width="600"/>
+ <char name="Iacute" width="600"/>
+ <char name="Icircumflex" width="600"/>
+ <char name="Idieresis" width="600"/>
+ <char name="Idot" width="600"/>
+ <char name="Igrave" width="600"/>
+ <char name="J" width="600"/>
+ <char name="K" width="600"/>
+ <char name="L" width="600"/>
+ <char name="LL" width="600"/>
+ <char name="Lslash" width="600"/>
+ <char name="M" width="600"/>
+ <char name="N" width="600"/>
+ <char name="Ntilde" width="600"/>
+ <char name="O" width="600"/>
+ <char name="OE" width="600"/>
+ <char name="Oacute" width="600"/>
+ <char name="Ocircumflex" width="600"/>
+ <char name="Odieresis" width="600"/>
+ <char name="Ograve" width="600"/>
+ <char name="Oslash" width="600"/>
+ <char name="Otilde" width="600"/>
+ <char name="P" width="600"/>
+ <char name="Q" width="600"/>
+ <char name="R" width="600"/>
+ <char name="S" width="600"/>
+ <char name="Scaron" width="600"/>
+ <char name="Scedilla" width="600"/>
+ <char name="T" width="600"/>
+ <char name="Thorn" width="600"/>
+ <char name="U" width="600"/>
+ <char name="Uacute" width="600"/>
+ <char name="Ucircumflex" width="600"/>
+ <char name="Udieresis" width="600"/>
+ <char name="Ugrave" width="600"/>
+ <char name="V" width="600"/>
+ <char name="W" width="600"/>
+ <char name="X" width="600"/>
+ <char name="Y" width="600"/>
+ <char name="Yacute" width="600"/>
+ <char name="Ydieresis" width="600"/>
+ <char name="Z" width="600"/>
+ <char name="Zcaron" width="600"/>
+ <char name="a" width="600"/>
+ <char name="aacute" width="600"/>
+ <char name="acircumflex" width="600"/>
+ <char name="acute" width="600"/>
+ <char name="adieresis" width="600"/>
+ <char name="ae" width="600"/>
+ <char name="agrave" width="600"/>
+ <char name="ampersand" width="600"/>
+ <char name="aring" width="600"/>
+ <char name="arrowboth" width="600"/>
+ <char name="arrowdown" width="600"/>
+ <char name="arrowleft" width="600"/>
+ <char name="arrowright" width="600"/>
+ <char name="arrowup" width="600"/>
+ <char name="asciicircum" width="600"/>
+ <char name="asciitilde" width="600"/>
+ <char name="asterisk" width="600"/>
+ <char name="at" width="600"/>
+ <char name="atilde" width="600"/>
+ <char name="b" width="600"/>
+ <char name="backslash" width="600"/>
+ <char name="bar" width="600"/>
+ <char name="braceleft" width="600"/>
+ <char name="braceright" width="600"/>
+ <char name="bracketleft" width="600"/>
+ <char name="bracketright" width="600"/>
+ <char name="breve" width="600"/>
+ <char name="brokenbar" width="600"/>
+ <char name="bullet" width="600"/>
+ <char name="c" width="600"/>
+ <char name="caron" width="600"/>
+ <char name="ccedilla" width="600"/>
+ <char name="cedilla" width="600"/>
+ <char name="cent" width="600"/>
+ <char name="center" width="600"/>
+ <char name="circumflex" width="600"/>
+ <char name="colon" width="600"/>
+ <char name="comma" width="600"/>
+ <char name="copyright" width="600"/>
+ <char name="currency" width="600"/>
+ <char name="d" width="600"/>
+ <char name="dagger" width="600"/>
+ <char name="daggerdbl" width="600"/>
+ <char name="dectab" width="600"/>
+ <char name="degree" width="600"/>
+ <char name="dieresis" width="600"/>
+ <char name="divide" width="600"/>
+ <char name="dollar" width="600"/>
+ <char name="dotaccent" width="600"/>
+ <char name="dotlessi" width="600"/>
+ <char name="down" width="600"/>
+ <char name="e" width="600"/>
+ <char name="eacute" width="600"/>
+ <char name="ecircumflex" width="600"/>
+ <char name="edieresis" width="600"/>
+ <char name="egrave" width="600"/>
+ <char name="eight" width="600"/>
+ <char name="ellipsis" width="600"/>
+ <char name="emdash" width="600"/>
+ <char name="endash" width="600"/>
+ <char name="equal" width="600"/>
+ <char name="eth" width="600"/>
+ <char name="exclam" width="600"/>
+ <char name="exclamdown" width="600"/>
+ <char name="f" width="600"/>
+ <char name="fi" width="600"/>
+ <char name="five" width="600"/>
+ <char name="fl" width="600"/>
+ <char name="florin" width="600"/>
+ <char name="format" width="600"/>
+ <char name="four" width="600"/>
+ <char name="fraction" width="600"/>
+ <char name="g" width="600"/>
+ <char name="gcaron" width="600"/>
+ <char name="germandbls" width="600"/>
+ <char name="grave" width="600"/>
+ <char name="graybox" width="600"/>
+ <char name="greater" width="600"/>
+ <char name="guillemotleft" width="600"/>
+ <char name="guillemotright" width="600"/>
+ <char name="guilsinglleft" width="600"/>
+ <char name="guilsinglright" width="600"/>
+ <char name="h" width="600"/>
+ <char name="hungarumlaut" width="600"/>
+ <char name="hyphen" width="600"/>
+ <char name="i" width="600"/>
+ <char name="iacute" width="600"/>
+ <char name="icircumflex" width="600"/>
+ <char name="idieresis" width="600"/>
+ <char name="igrave" width="600"/>
+ <char name="ij" width="600"/>
+ <char name="indent" width="600"/>
+ <char name="j" width="600"/>
+ <char name="k" width="600"/>
+ <char name="l" width="600"/>
+ <char name="largebullet" width="600"/>
+ <char name="left" width="600"/>
+ <char name="less" width="600"/>
+ <char name="lira" width="600"/>
+ <char name="ll" width="600"/>
+ <char name="logicalnot" width="600"/>
+ <char name="lslash" width="600"/>
+ <char name="m" width="600"/>
+ <char name="macron" width="600"/>
+ <char name="merge" width="600"/>
+ <char name="minus" width="600"/>
+ <char name="mu" width="600"/>
+ <char name="multiply" width="600"/>
+ <char name="n" width="600"/>
+ <char name="nine" width="600"/>
+ <char name="notegraphic" width="600"/>
+ <char name="ntilde" width="600"/>
+ <char name="numbersign" width="600"/>
+ <char name="o" width="600"/>
+ <char name="oacute" width="600"/>
+ <char name="ocircumflex" width="600"/>
+ <char name="odieresis" width="600"/>
+ <char name="oe" width="600"/>
+ <char name="ogonek" width="600"/>
+ <char name="ograve" width="600"/>
+ <char name="one" width="600"/>
+ <char name="onehalf" width="600"/>
+ <char name="onequarter" width="600"/>
+ <char name="onesuperior" width="600"/>
+ <char name="ordfeminine" width="600"/>
+ <char name="ordmasculine" width="600"/>
+ <char name="oslash" width="600"/>
+ <char name="otilde" width="600"/>
+ <char name="overscore" width="600"/>
+ <char name="p" width="600"/>
+ <char name="paragraph" width="600"/>
+ <char name="parenleft" width="600"/>
+ <char name="parenright" width="600"/>
+ <char name="percent" width="600"/>
+ <char name="period" width="600"/>
+ <char name="periodcentered" width="600"/>
+ <char name="perthousand" width="600"/>
+ <char name="plus" width="600"/>
+ <char name="plusminus" width="600"/>
+ <char name="prescription" width="600"/>
+ <char name="q" width="600"/>
+ <char name="question" width="600"/>
+ <char name="questiondown" width="600"/>
+ <char name="quotedbl" width="600"/>
+ <char name="quotedblbase" width="600"/>
+ <char name="quotedblleft" width="600"/>
+ <char name="quotedblright" width="600"/>
+ <char name="quoteleft" width="600"/>
+ <char name="quoteright" width="600"/>
+ <char name="quotesinglbase" width="600"/>
+ <char name="quotesingle" width="600"/>
+ <char name="r" width="600"/>
+ <char name="registered" width="600"/>
+ <char name="return" width="600"/>
+ <char name="ring" width="600"/>
+ <char name="s" width="600"/>
+ <char name="scaron" width="600"/>
+ <char name="scedilla" width="600"/>
+ <char name="section" width="600"/>
+ <char name="semicolon" width="600"/>
+ <char name="seven" width="600"/>
+ <char name="six" width="600"/>
+ <char name="slash" width="600"/>
+ <char name="space" width="600"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="600"/>
+ <char name="square" width="600"/>
+ <char name="sterling" width="600"/>
+ <char name="stop" width="600"/>
+ <char name="t" width="600"/>
+ <char name="tab" width="600"/>
+ <char name="thorn" width="600"/>
+ <char name="three" width="600"/>
+ <char name="threequarters" width="600"/>
+ <char name="threesuperior" width="600"/>
+ <char name="tilde" width="600"/>
+ <char name="trademark" width="600"/>
+ <char name="two" width="600"/>
+ <char name="twosuperior" width="600"/>
+ <char name="u" width="600"/>
+ <char name="uacute" width="600"/>
+ <char name="ucircumflex" width="600"/>
+ <char name="udieresis" width="600"/>
+ <char name="ugrave" width="600"/>
+ <char name="underscore" width="600"/>
+ <char name="up" width="600"/>
+ <char name="v" width="600"/>
+ <char name="w" width="600"/>
+ <char name="x" width="600"/>
+ <char name="y" width="600"/>
+ <char name="yacute" width="600"/>
+ <char name="ydieresis" width="600"/>
+ <char name="yen" width="600"/>
+ <char name="z" width="600"/>
+ <char name="zcaron" width="600"/>
+ <char name="zero" width="600"/>
+ </widths>
+</font-metrics>
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Courier-Oblique</font-name>
+ <class-name>CourierOblique</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>562</cap-height>
+ <x-height>426</x-height>
+ <ascender>629</ascender>
+ <descender>-157</descender>
+ <widths>
+ <char name="A" width="600"/>
+ <char name="AE" width="600"/>
+ <char name="Aacute" width="600"/>
+ <char name="Acircumflex" width="600"/>
+ <char name="Adieresis" width="600"/>
+ <char name="Agrave" width="600"/>
+ <char name="Aring" width="600"/>
+ <char name="Atilde" width="600"/>
+ <char name="B" width="600"/>
+ <char name="C" width="600"/>
+ <char name="Ccedilla" width="600"/>
+ <char name="D" width="600"/>
+ <char name="E" width="600"/>
+ <char name="Eacute" width="600"/>
+ <char name="Ecircumflex" width="600"/>
+ <char name="Edieresis" width="600"/>
+ <char name="Egrave" width="600"/>
+ <char name="Eth" width="600"/>
+ <char name="F" width="600"/>
+ <char name="G" width="600"/>
+ <char name="Gcaron" width="600"/>
+ <char name="H" width="600"/>
+ <char name="I" width="600"/>
+ <char name="IJ" width="600"/>
+ <char name="Iacute" width="600"/>
+ <char name="Icircumflex" width="600"/>
+ <char name="Idieresis" width="600"/>
+ <char name="Idot" width="600"/>
+ <char name="Igrave" width="600"/>
+ <char name="J" width="600"/>
+ <char name="K" width="600"/>
+ <char name="L" width="600"/>
+ <char name="LL" width="600"/>
+ <char name="Lslash" width="600"/>
+ <char name="M" width="600"/>
+ <char name="N" width="600"/>
+ <char name="Ntilde" width="600"/>
+ <char name="O" width="600"/>
+ <char name="OE" width="600"/>
+ <char name="Oacute" width="600"/>
+ <char name="Ocircumflex" width="600"/>
+ <char name="Odieresis" width="600"/>
+ <char name="Ograve" width="600"/>
+ <char name="Oslash" width="600"/>
+ <char name="Otilde" width="600"/>
+ <char name="P" width="600"/>
+ <char name="Q" width="600"/>
+ <char name="R" width="600"/>
+ <char name="S" width="600"/>
+ <char name="Scaron" width="600"/>
+ <char name="Scedilla" width="600"/>
+ <char name="T" width="600"/>
+ <char name="Thorn" width="600"/>
+ <char name="U" width="600"/>
+ <char name="Uacute" width="600"/>
+ <char name="Ucircumflex" width="600"/>
+ <char name="Udieresis" width="600"/>
+ <char name="Ugrave" width="600"/>
+ <char name="V" width="600"/>
+ <char name="W" width="600"/>
+ <char name="X" width="600"/>
+ <char name="Y" width="600"/>
+ <char name="Yacute" width="600"/>
+ <char name="Ydieresis" width="600"/>
+ <char name="Z" width="600"/>
+ <char name="Zcaron" width="600"/>
+ <char name="a" width="600"/>
+ <char name="aacute" width="600"/>
+ <char name="acircumflex" width="600"/>
+ <char name="acute" width="600"/>
+ <char name="adieresis" width="600"/>
+ <char name="ae" width="600"/>
+ <char name="agrave" width="600"/>
+ <char name="ampersand" width="600"/>
+ <char name="aring" width="600"/>
+ <char name="arrowboth" width="600"/>
+ <char name="arrowdown" width="600"/>
+ <char name="arrowleft" width="600"/>
+ <char name="arrowright" width="600"/>
+ <char name="arrowup" width="600"/>
+ <char name="asciicircum" width="600"/>
+ <char name="asciitilde" width="600"/>
+ <char name="asterisk" width="600"/>
+ <char name="at" width="600"/>
+ <char name="atilde" width="600"/>
+ <char name="b" width="600"/>
+ <char name="backslash" width="600"/>
+ <char name="bar" width="600"/>
+ <char name="braceleft" width="600"/>
+ <char name="braceright" width="600"/>
+ <char name="bracketleft" width="600"/>
+ <char name="bracketright" width="600"/>
+ <char name="breve" width="600"/>
+ <char name="brokenbar" width="600"/>
+ <char name="bullet" width="600"/>
+ <char name="c" width="600"/>
+ <char name="caron" width="600"/>
+ <char name="ccedilla" width="600"/>
+ <char name="cedilla" width="600"/>
+ <char name="cent" width="600"/>
+ <char name="center" width="600"/>
+ <char name="circumflex" width="600"/>
+ <char name="colon" width="600"/>
+ <char name="comma" width="600"/>
+ <char name="copyright" width="600"/>
+ <char name="currency" width="600"/>
+ <char name="d" width="600"/>
+ <char name="dagger" width="600"/>
+ <char name="daggerdbl" width="600"/>
+ <char name="dectab" width="600"/>
+ <char name="degree" width="600"/>
+ <char name="dieresis" width="600"/>
+ <char name="divide" width="600"/>
+ <char name="dollar" width="600"/>
+ <char name="dotaccent" width="600"/>
+ <char name="dotlessi" width="600"/>
+ <char name="down" width="600"/>
+ <char name="e" width="600"/>
+ <char name="eacute" width="600"/>
+ <char name="ecircumflex" width="600"/>
+ <char name="edieresis" width="600"/>
+ <char name="egrave" width="600"/>
+ <char name="eight" width="600"/>
+ <char name="ellipsis" width="600"/>
+ <char name="emdash" width="600"/>
+ <char name="endash" width="600"/>
+ <char name="equal" width="600"/>
+ <char name="eth" width="600"/>
+ <char name="exclam" width="600"/>
+ <char name="exclamdown" width="600"/>
+ <char name="f" width="600"/>
+ <char name="fi" width="600"/>
+ <char name="five" width="600"/>
+ <char name="fl" width="600"/>
+ <char name="florin" width="600"/>
+ <char name="format" width="600"/>
+ <char name="four" width="600"/>
+ <char name="fraction" width="600"/>
+ <char name="g" width="600"/>
+ <char name="gcaron" width="600"/>
+ <char name="germandbls" width="600"/>
+ <char name="grave" width="600"/>
+ <char name="graybox" width="600"/>
+ <char name="greater" width="600"/>
+ <char name="guillemotleft" width="600"/>
+ <char name="guillemotright" width="600"/>
+ <char name="guilsinglleft" width="600"/>
+ <char name="guilsinglright" width="600"/>
+ <char name="h" width="600"/>
+ <char name="hungarumlaut" width="600"/>
+ <char name="hyphen" width="600"/>
+ <char name="i" width="600"/>
+ <char name="iacute" width="600"/>
+ <char name="icircumflex" width="600"/>
+ <char name="idieresis" width="600"/>
+ <char name="igrave" width="600"/>
+ <char name="ij" width="600"/>
+ <char name="indent" width="600"/>
+ <char name="j" width="600"/>
+ <char name="k" width="600"/>
+ <char name="l" width="600"/>
+ <char name="largebullet" width="600"/>
+ <char name="left" width="600"/>
+ <char name="less" width="600"/>
+ <char name="lira" width="600"/>
+ <char name="ll" width="600"/>
+ <char name="logicalnot" width="600"/>
+ <char name="lslash" width="600"/>
+ <char name="m" width="600"/>
+ <char name="macron" width="600"/>
+ <char name="merge" width="600"/>
+ <char name="minus" width="600"/>
+ <char name="mu" width="600"/>
+ <char name="multiply" width="600"/>
+ <char name="n" width="600"/>
+ <char name="nine" width="600"/>
+ <char name="notegraphic" width="600"/>
+ <char name="ntilde" width="600"/>
+ <char name="numbersign" width="600"/>
+ <char name="o" width="600"/>
+ <char name="oacute" width="600"/>
+ <char name="ocircumflex" width="600"/>
+ <char name="odieresis" width="600"/>
+ <char name="oe" width="600"/>
+ <char name="ogonek" width="600"/>
+ <char name="ograve" width="600"/>
+ <char name="one" width="600"/>
+ <char name="onehalf" width="600"/>
+ <char name="onequarter" width="600"/>
+ <char name="onesuperior" width="600"/>
+ <char name="ordfeminine" width="600"/>
+ <char name="ordmasculine" width="600"/>
+ <char name="oslash" width="600"/>
+ <char name="otilde" width="600"/>
+ <char name="overscore" width="600"/>
+ <char name="p" width="600"/>
+ <char name="paragraph" width="600"/>
+ <char name="parenleft" width="600"/>
+ <char name="parenright" width="600"/>
+ <char name="percent" width="600"/>
+ <char name="period" width="600"/>
+ <char name="periodcentered" width="600"/>
+ <char name="perthousand" width="600"/>
+ <char name="plus" width="600"/>
+ <char name="plusminus" width="600"/>
+ <char name="prescription" width="600"/>
+ <char name="q" width="600"/>
+ <char name="question" width="600"/>
+ <char name="questiondown" width="600"/>
+ <char name="quotedbl" width="600"/>
+ <char name="quotedblbase" width="600"/>
+ <char name="quotedblleft" width="600"/>
+ <char name="quotedblright" width="600"/>
+ <char name="quoteleft" width="600"/>
+ <char name="quoteright" width="600"/>
+ <char name="quotesinglbase" width="600"/>
+ <char name="quotesingle" width="600"/>
+ <char name="r" width="600"/>
+ <char name="registered" width="600"/>
+ <char name="return" width="600"/>
+ <char name="ring" width="600"/>
+ <char name="s" width="600"/>
+ <char name="scaron" width="600"/>
+ <char name="scedilla" width="600"/>
+ <char name="section" width="600"/>
+ <char name="semicolon" width="600"/>
+ <char name="seven" width="600"/>
+ <char name="six" width="600"/>
+ <char name="slash" width="600"/>
+ <char name="space" width="600"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="600"/>
+ <char name="square" width="600"/>
+ <char name="sterling" width="600"/>
+ <char name="stop" width="600"/>
+ <char name="t" width="600"/>
+ <char name="tab" width="600"/>
+ <char name="thorn" width="600"/>
+ <char name="three" width="600"/>
+ <char name="threequarters" width="600"/>
+ <char name="threesuperior" width="600"/>
+ <char name="tilde" width="600"/>
+ <char name="trademark" width="600"/>
+ <char name="two" width="600"/>
+ <char name="twosuperior" width="600"/>
+ <char name="u" width="600"/>
+ <char name="uacute" width="600"/>
+ <char name="ucircumflex" width="600"/>
+ <char name="udieresis" width="600"/>
+ <char name="ugrave" width="600"/>
+ <char name="underscore" width="600"/>
+ <char name="up" width="600"/>
+ <char name="v" width="600"/>
+ <char name="w" width="600"/>
+ <char name="x" width="600"/>
+ <char name="y" width="600"/>
+ <char name="yacute" width="600"/>
+ <char name="ydieresis" width="600"/>
+ <char name="yen" width="600"/>
+ <char name="z" width="600"/>
+ <char name="zcaron" width="600"/>
+ <char name="zero" width="600"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Courier</font-name>
+ <class-name>Courier</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>562</cap-height>
+ <x-height>426</x-height>
+ <ascender>629</ascender>
+ <descender>-157</descender>
+ <widths>
+ <char name="A" width="600"/>
+ <char name="AE" width="600"/>
+ <char name="Aacute" width="600"/>
+ <char name="Acircumflex" width="600"/>
+ <char name="Adieresis" width="600"/>
+ <char name="Agrave" width="600"/>
+ <char name="Aring" width="600"/>
+ <char name="Atilde" width="600"/>
+ <char name="B" width="600"/>
+ <char name="C" width="600"/>
+ <char name="Ccedilla" width="600"/>
+ <char name="D" width="600"/>
+ <char name="E" width="600"/>
+ <char name="Eacute" width="600"/>
+ <char name="Ecircumflex" width="600"/>
+ <char name="Edieresis" width="600"/>
+ <char name="Egrave" width="600"/>
+ <char name="Eth" width="600"/>
+ <char name="F" width="600"/>
+ <char name="G" width="600"/>
+ <char name="Gcaron" width="600"/>
+ <char name="H" width="600"/>
+ <char name="I" width="600"/>
+ <char name="IJ" width="600"/>
+ <char name="Iacute" width="600"/>
+ <char name="Icircumflex" width="600"/>
+ <char name="Idieresis" width="600"/>
+ <char name="Idot" width="600"/>
+ <char name="Igrave" width="600"/>
+ <char name="J" width="600"/>
+ <char name="K" width="600"/>
+ <char name="L" width="600"/>
+ <char name="LL" width="600"/>
+ <char name="Lslash" width="600"/>
+ <char name="M" width="600"/>
+ <char name="N" width="600"/>
+ <char name="Ntilde" width="600"/>
+ <char name="O" width="600"/>
+ <char name="OE" width="600"/>
+ <char name="Oacute" width="600"/>
+ <char name="Ocircumflex" width="600"/>
+ <char name="Odieresis" width="600"/>
+ <char name="Ograve" width="600"/>
+ <char name="Oslash" width="600"/>
+ <char name="Otilde" width="600"/>
+ <char name="P" width="600"/>
+ <char name="Q" width="600"/>
+ <char name="R" width="600"/>
+ <char name="S" width="600"/>
+ <char name="Scaron" width="600"/>
+ <char name="Scedilla" width="600"/>
+ <char name="T" width="600"/>
+ <char name="Thorn" width="600"/>
+ <char name="U" width="600"/>
+ <char name="Uacute" width="600"/>
+ <char name="Ucircumflex" width="600"/>
+ <char name="Udieresis" width="600"/>
+ <char name="Ugrave" width="600"/>
+ <char name="V" width="600"/>
+ <char name="W" width="600"/>
+ <char name="X" width="600"/>
+ <char name="Y" width="600"/>
+ <char name="Yacute" width="600"/>
+ <char name="Ydieresis" width="600"/>
+ <char name="Z" width="600"/>
+ <char name="Zcaron" width="600"/>
+ <char name="a" width="600"/>
+ <char name="aacute" width="600"/>
+ <char name="acircumflex" width="600"/>
+ <char name="acute" width="600"/>
+ <char name="adieresis" width="600"/>
+ <char name="ae" width="600"/>
+ <char name="agrave" width="600"/>
+ <char name="ampersand" width="600"/>
+ <char name="aring" width="600"/>
+ <char name="arrowboth" width="600"/>
+ <char name="arrowdown" width="600"/>
+ <char name="arrowleft" width="600"/>
+ <char name="arrowright" width="600"/>
+ <char name="arrowup" width="600"/>
+ <char name="asciicircum" width="600"/>
+ <char name="asciitilde" width="600"/>
+ <char name="asterisk" width="600"/>
+ <char name="at" width="600"/>
+ <char name="atilde" width="600"/>
+ <char name="b" width="600"/>
+ <char name="backslash" width="600"/>
+ <char name="bar" width="600"/>
+ <char name="braceleft" width="600"/>
+ <char name="braceright" width="600"/>
+ <char name="bracketleft" width="600"/>
+ <char name="bracketright" width="600"/>
+ <char name="breve" width="600"/>
+ <char name="brokenbar" width="600"/>
+ <char name="bullet" width="600"/>
+ <char name="c" width="600"/>
+ <char name="caron" width="600"/>
+ <char name="ccedilla" width="600"/>
+ <char name="cedilla" width="600"/>
+ <char name="cent" width="600"/>
+ <char name="center" width="600"/>
+ <char name="circumflex" width="600"/>
+ <char name="colon" width="600"/>
+ <char name="comma" width="600"/>
+ <char name="copyright" width="600"/>
+ <char name="currency" width="600"/>
+ <char name="d" width="600"/>
+ <char name="dagger" width="600"/>
+ <char name="daggerdbl" width="600"/>
+ <char name="dectab" width="600"/>
+ <char name="degree" width="600"/>
+ <char name="dieresis" width="600"/>
+ <char name="divide" width="600"/>
+ <char name="dollar" width="600"/>
+ <char name="dotaccent" width="600"/>
+ <char name="dotlessi" width="600"/>
+ <char name="down" width="600"/>
+ <char name="e" width="600"/>
+ <char name="eacute" width="600"/>
+ <char name="ecircumflex" width="600"/>
+ <char name="edieresis" width="600"/>
+ <char name="egrave" width="600"/>
+ <char name="eight" width="600"/>
+ <char name="ellipsis" width="600"/>
+ <char name="emdash" width="600"/>
+ <char name="endash" width="600"/>
+ <char name="equal" width="600"/>
+ <char name="eth" width="600"/>
+ <char name="exclam" width="600"/>
+ <char name="exclamdown" width="600"/>
+ <char name="f" width="600"/>
+ <char name="fi" width="600"/>
+ <char name="five" width="600"/>
+ <char name="fl" width="600"/>
+ <char name="florin" width="600"/>
+ <char name="format" width="600"/>
+ <char name="four" width="600"/>
+ <char name="fraction" width="600"/>
+ <char name="g" width="600"/>
+ <char name="gcaron" width="600"/>
+ <char name="germandbls" width="600"/>
+ <char name="grave" width="600"/>
+ <char name="graybox" width="600"/>
+ <char name="greater" width="600"/>
+ <char name="guillemotleft" width="600"/>
+ <char name="guillemotright" width="600"/>
+ <char name="guilsinglleft" width="600"/>
+ <char name="guilsinglright" width="600"/>
+ <char name="h" width="600"/>
+ <char name="hungarumlaut" width="600"/>
+ <char name="hyphen" width="600"/>
+ <char name="i" width="600"/>
+ <char name="iacute" width="600"/>
+ <char name="icircumflex" width="600"/>
+ <char name="idieresis" width="600"/>
+ <char name="igrave" width="600"/>
+ <char name="ij" width="600"/>
+ <char name="indent" width="600"/>
+ <char name="j" width="600"/>
+ <char name="k" width="600"/>
+ <char name="l" width="600"/>
+ <char name="largebullet" width="600"/>
+ <char name="left" width="600"/>
+ <char name="less" width="600"/>
+ <char name="lira" width="600"/>
+ <char name="ll" width="600"/>
+ <char name="logicalnot" width="600"/>
+ <char name="lslash" width="600"/>
+ <char name="m" width="600"/>
+ <char name="macron" width="600"/>
+ <char name="merge" width="600"/>
+ <char name="minus" width="600"/>
+ <char name="mu" width="600"/>
+ <char name="multiply" width="600"/>
+ <char name="n" width="600"/>
+ <char name="nine" width="600"/>
+ <char name="notegraphic" width="600"/>
+ <char name="ntilde" width="600"/>
+ <char name="numbersign" width="600"/>
+ <char name="o" width="600"/>
+ <char name="oacute" width="600"/>
+ <char name="ocircumflex" width="600"/>
+ <char name="odieresis" width="600"/>
+ <char name="oe" width="600"/>
+ <char name="ogonek" width="600"/>
+ <char name="ograve" width="600"/>
+ <char name="one" width="600"/>
+ <char name="onehalf" width="600"/>
+ <char name="onequarter" width="600"/>
+ <char name="onesuperior" width="600"/>
+ <char name="ordfeminine" width="600"/>
+ <char name="ordmasculine" width="600"/>
+ <char name="oslash" width="600"/>
+ <char name="otilde" width="600"/>
+ <char name="overscore" width="600"/>
+ <char name="p" width="600"/>
+ <char name="paragraph" width="600"/>
+ <char name="parenleft" width="600"/>
+ <char name="parenright" width="600"/>
+ <char name="percent" width="600"/>
+ <char name="period" width="600"/>
+ <char name="periodcentered" width="600"/>
+ <char name="perthousand" width="600"/>
+ <char name="plus" width="600"/>
+ <char name="plusminus" width="600"/>
+ <char name="prescription" width="600"/>
+ <char name="q" width="600"/>
+ <char name="question" width="600"/>
+ <char name="questiondown" width="600"/>
+ <char name="quotedbl" width="600"/>
+ <char name="quotedblbase" width="600"/>
+ <char name="quotedblleft" width="600"/>
+ <char name="quotedblright" width="600"/>
+ <char name="quoteleft" width="600"/>
+ <char name="quoteright" width="600"/>
+ <char name="quotesinglbase" width="600"/>
+ <char name="quotesingle" width="600"/>
+ <char name="r" width="600"/>
+ <char name="registered" width="600"/>
+ <char name="return" width="600"/>
+ <char name="ring" width="600"/>
+ <char name="s" width="600"/>
+ <char name="scaron" width="600"/>
+ <char name="scedilla" width="600"/>
+ <char name="section" width="600"/>
+ <char name="semicolon" width="600"/>
+ <char name="seven" width="600"/>
+ <char name="six" width="600"/>
+ <char name="slash" width="600"/>
+ <char name="space" width="600"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="600"/>
+ <char name="square" width="600"/>
+ <char name="sterling" width="600"/>
+ <char name="stop" width="600"/>
+ <char name="t" width="600"/>
+ <char name="tab" width="600"/>
+ <char name="thorn" width="600"/>
+ <char name="three" width="600"/>
+ <char name="threequarters" width="600"/>
+ <char name="threesuperior" width="600"/>
+ <char name="tilde" width="600"/>
+ <char name="trademark" width="600"/>
+ <char name="two" width="600"/>
+ <char name="twosuperior" width="600"/>
+ <char name="u" width="600"/>
+ <char name="uacute" width="600"/>
+ <char name="ucircumflex" width="600"/>
+ <char name="udieresis" width="600"/>
+ <char name="ugrave" width="600"/>
+ <char name="underscore" width="600"/>
+ <char name="up" width="600"/>
+ <char name="v" width="600"/>
+ <char name="w" width="600"/>
+ <char name="x" width="600"/>
+ <char name="y" width="600"/>
+ <char name="yacute" width="600"/>
+ <char name="ydieresis" width="600"/>
+ <char name="yen" width="600"/>
+ <char name="z" width="600"/>
+ <char name="zcaron" width="600"/>
+ <char name="zero" width="600"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Helvetica-Bold</font-name>
+ <class-name>HelveticaBold</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>718</cap-height>
+ <x-height>532</x-height>
+ <ascender>718</ascender>
+ <descender>-207</descender>
+ <widths>
+ <char name="A" width="722"/>
+ <char name="AE" width="1000"/>
+ <char name="Aacute" width="722"/>
+ <char name="Acircumflex" width="722"/>
+ <char name="Adieresis" width="722"/>
+ <char name="Agrave" width="722"/>
+ <char name="Aring" width="722"/>
+ <char name="Atilde" width="722"/>
+ <char name="B" width="722"/>
+ <char name="C" width="722"/>
+ <char name="Ccedilla" width="722"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="778"/>
+ <char name="H" width="722"/>
+ <char name="I" width="278"/>
+ <char name="Iacute" width="278"/>
+ <char name="Icircumflex" width="278"/>
+ <char name="Idieresis" width="278"/>
+ <char name="Igrave" width="278"/>
+ <char name="J" width="556"/>
+ <char name="K" width="722"/>
+ <char name="L" width="611"/>
+ <char name="Lslash" width="611"/>
+ <char name="M" width="833"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="778"/>
+ <char name="OE" width="1000"/>
+ <char name="Oacute" width="778"/>
+ <char name="Ocircumflex" width="778"/>
+ <char name="Odieresis" width="778"/>
+ <char name="Ograve" width="778"/>
+ <char name="Oslash" width="778"/>
+ <char name="Otilde" width="778"/>
+ <char name="P" width="667"/>
+ <char name="Q" width="778"/>
+ <char name="R" width="722"/>
+ <char name="S" width="667"/>
+ <char name="Scaron" width="667"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="667"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="667"/>
+ <char name="W" width="944"/>
+ <char name="X" width="667"/>
+ <char name="Y" width="667"/>
+ <char name="Yacute" width="667"/>
+ <char name="Ydieresis" width="667"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="556"/>
+ <char name="aacute" width="556"/>
+ <char name="acircumflex" width="556"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="556"/>
+ <char name="ae" width="889"/>
+ <char name="agrave" width="556"/>
+ <char name="ampersand" width="722"/>
+ <char name="aring" width="556"/>
+ <char name="asciicircum" width="584"/>
+ <char name="asciitilde" width="584"/>
+ <char name="asterisk" width="389"/>
+ <char name="at" width="975"/>
+ <char name="atilde" width="556"/>
+ <char name="b" width="611"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="280"/>
+ <char name="braceleft" width="389"/>
+ <char name="braceright" width="389"/>
+ <char name="bracketleft" width="333"/>
+ <char name="bracketright" width="333"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="280"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="556"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="556"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="556"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="333"/>
+ <char name="comma" width="278"/>
+ <char name="copyright" width="737"/>
+ <char name="currency" width="556"/>
+ <char name="d" width="611"/>
+ <char name="dagger" width="556"/>
+ <char name="daggerdbl" width="556"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="584"/>
+ <char name="dollar" width="556"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="556"/>
+ <char name="eacute" width="556"/>
+ <char name="ecircumflex" width="556"/>
+ <char name="edieresis" width="556"/>
+ <char name="egrave" width="556"/>
+ <char name="eight" width="556"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="556"/>
+ <char name="equal" width="584"/>
+ <char name="eth" width="611"/>
+ <char name="exclam" width="333"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="333"/>
+ <char name="fi" width="611"/>
+ <char name="five" width="556"/>
+ <char name="fl" width="611"/>
+ <char name="florin" width="556"/>
+ <char name="four" width="556"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="611"/>
+ <char name="germandbls" width="611"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="584"/>
+ <char name="guillemotleft" width="556"/>
+ <char name="guillemotright" width="556"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="611"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="278"/>
+ <char name="k" width="556"/>
+ <char name="l" width="278"/>
+ <char name="less" width="584"/>
+ <char name="logicalnot" width="584"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="889"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="584"/>
+ <char name="mu" width="611"/>
+ <char name="multiply" width="584"/>
+ <char name="n" width="611"/>
+ <char name="nine" width="556"/>
+ <char name="ntilde" width="611"/>
+ <char name="numbersign" width="556"/>
+ <char name="o" width="611"/>
+ <char name="oacute" width="611"/>
+ <char name="ocircumflex" width="611"/>
+ <char name="odieresis" width="611"/>
+ <char name="oe" width="944"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="611"/>
+ <char name="one" width="556"/>
+ <char name="onehalf" width="834"/>
+ <char name="onequarter" width="834"/>
+ <char name="onesuperior" width="333"/>
+ <char name="ordfeminine" width="370"/>
+ <char name="ordmasculine" width="365"/>
+ <char name="oslash" width="611"/>
+ <char name="otilde" width="611"/>
+ <char name="p" width="611"/>
+ <char name="paragraph" width="556"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="889"/>
+ <char name="period" width="278"/>
+ <char name="periodcentered" width="278"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="584"/>
+ <char name="plusminus" width="584"/>
+ <char name="q" width="611"/>
+ <char name="question" width="611"/>
+ <char name="questiondown" width="611"/>
+ <char name="quotedbl" width="474"/>
+ <char name="quotedblbase" width="500"/>
+ <char name="quotedblleft" width="500"/>
+ <char name="quotedblright" width="500"/>
+ <char name="quoteleft" width="278"/>
+ <char name="quoteright" width="278"/>
+ <char name="quotesinglbase" width="278"/>
+ <char name="quotesingle" width="238"/>
+ <char name="r" width="389"/>
+ <char name="registered" width="737"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="556"/>
+ <char name="scaron" width="556"/>
+ <char name="section" width="556"/>
+ <char name="semicolon" width="333"/>
+ <char name="seven" width="556"/>
+ <char name="six" width="556"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="278"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="278"/>
+ <char name="sterling" width="556"/>
+ <char name="t" width="333"/>
+ <char name="thorn" width="611"/>
+ <char name="three" width="556"/>
+ <char name="threequarters" width="834"/>
+ <char name="threesuperior" width="333"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="556"/>
+ <char name="twosuperior" width="333"/>
+ <char name="u" width="611"/>
+ <char name="uacute" width="611"/>
+ <char name="ucircumflex" width="611"/>
+ <char name="udieresis" width="611"/>
+ <char name="ugrave" width="611"/>
+ <char name="underscore" width="556"/>
+ <char name="v" width="556"/>
+ <char name="w" width="778"/>
+ <char name="x" width="556"/>
+ <char name="y" width="556"/>
+ <char name="yacute" width="556"/>
+ <char name="ydieresis" width="556"/>
+ <char name="yen" width="556"/>
+ <char name="z" width="500"/>
+ <char name="zcaron" width="500"/>
+ <char name="zero" width="556"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Helvetica-BoldOblique</font-name>
+ <class-name>HelveticaBoldOblique</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>718</cap-height>
+ <x-height>532</x-height>
+ <ascender>718</ascender>
+ <descender>-207</descender>
+ <widths>
+ <char name="A" width="722"/>
+ <char name="AE" width="1000"/>
+ <char name="Aacute" width="722"/>
+ <char name="Acircumflex" width="722"/>
+ <char name="Adieresis" width="722"/>
+ <char name="Agrave" width="722"/>
+ <char name="Aring" width="722"/>
+ <char name="Atilde" width="722"/>
+ <char name="B" width="722"/>
+ <char name="C" width="722"/>
+ <char name="Ccedilla" width="722"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="778"/>
+ <char name="H" width="722"/>
+ <char name="I" width="278"/>
+ <char name="Iacute" width="278"/>
+ <char name="Icircumflex" width="278"/>
+ <char name="Idieresis" width="278"/>
+ <char name="Igrave" width="278"/>
+ <char name="J" width="556"/>
+ <char name="K" width="722"/>
+ <char name="L" width="611"/>
+ <char name="Lslash" width="611"/>
+ <char name="M" width="833"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="778"/>
+ <char name="OE" width="1000"/>
+ <char name="Oacute" width="778"/>
+ <char name="Ocircumflex" width="778"/>
+ <char name="Odieresis" width="778"/>
+ <char name="Ograve" width="778"/>
+ <char name="Oslash" width="778"/>
+ <char name="Otilde" width="778"/>
+ <char name="P" width="667"/>
+ <char name="Q" width="778"/>
+ <char name="R" width="722"/>
+ <char name="S" width="667"/>
+ <char name="Scaron" width="667"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="667"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="667"/>
+ <char name="W" width="944"/>
+ <char name="X" width="667"/>
+ <char name="Y" width="667"/>
+ <char name="Yacute" width="667"/>
+ <char name="Ydieresis" width="667"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="556"/>
+ <char name="aacute" width="556"/>
+ <char name="acircumflex" width="556"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="556"/>
+ <char name="ae" width="889"/>
+ <char name="agrave" width="556"/>
+ <char name="ampersand" width="722"/>
+ <char name="aring" width="556"/>
+ <char name="asciicircum" width="584"/>
+ <char name="asciitilde" width="584"/>
+ <char name="asterisk" width="389"/>
+ <char name="at" width="975"/>
+ <char name="atilde" width="556"/>
+ <char name="b" width="611"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="280"/>
+ <char name="braceleft" width="389"/>
+ <char name="braceright" width="389"/>
+ <char name="bracketleft" width="333"/>
+ <char name="bracketright" width="333"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="280"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="556"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="556"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="556"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="333"/>
+ <char name="comma" width="278"/>
+ <char name="copyright" width="737"/>
+ <char name="currency" width="556"/>
+ <char name="d" width="611"/>
+ <char name="dagger" width="556"/>
+ <char name="daggerdbl" width="556"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="584"/>
+ <char name="dollar" width="556"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="556"/>
+ <char name="eacute" width="556"/>
+ <char name="ecircumflex" width="556"/>
+ <char name="edieresis" width="556"/>
+ <char name="egrave" width="556"/>
+ <char name="eight" width="556"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="556"/>
+ <char name="equal" width="584"/>
+ <char name="eth" width="611"/>
+ <char name="exclam" width="333"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="333"/>
+ <char name="fi" width="611"/>
+ <char name="five" width="556"/>
+ <char name="fl" width="611"/>
+ <char name="florin" width="556"/>
+ <char name="four" width="556"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="611"/>
+ <char name="germandbls" width="611"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="584"/>
+ <char name="guillemotleft" width="556"/>
+ <char name="guillemotright" width="556"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="611"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="278"/>
+ <char name="k" width="556"/>
+ <char name="l" width="278"/>
+ <char name="less" width="584"/>
+ <char name="logicalnot" width="584"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="889"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="584"/>
+ <char name="mu" width="611"/>
+ <char name="multiply" width="584"/>
+ <char name="n" width="611"/>
+ <char name="nine" width="556"/>
+ <char name="ntilde" width="611"/>
+ <char name="numbersign" width="556"/>
+ <char name="o" width="611"/>
+ <char name="oacute" width="611"/>
+ <char name="ocircumflex" width="611"/>
+ <char name="odieresis" width="611"/>
+ <char name="oe" width="944"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="611"/>
+ <char name="one" width="556"/>
+ <char name="onehalf" width="834"/>
+ <char name="onequarter" width="834"/>
+ <char name="onesuperior" width="333"/>
+ <char name="ordfeminine" width="370"/>
+ <char name="ordmasculine" width="365"/>
+ <char name="oslash" width="611"/>
+ <char name="otilde" width="611"/>
+ <char name="p" width="611"/>
+ <char name="paragraph" width="556"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="889"/>
+ <char name="period" width="278"/>
+ <char name="periodcentered" width="278"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="584"/>
+ <char name="plusminus" width="584"/>
+ <char name="q" width="611"/>
+ <char name="question" width="611"/>
+ <char name="questiondown" width="611"/>
+ <char name="quotedbl" width="474"/>
+ <char name="quotedblbase" width="500"/>
+ <char name="quotedblleft" width="500"/>
+ <char name="quotedblright" width="500"/>
+ <char name="quoteleft" width="278"/>
+ <char name="quoteright" width="278"/>
+ <char name="quotesinglbase" width="278"/>
+ <char name="quotesingle" width="238"/>
+ <char name="r" width="389"/>
+ <char name="registered" width="737"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="556"/>
+ <char name="scaron" width="556"/>
+ <char name="section" width="556"/>
+ <char name="semicolon" width="333"/>
+ <char name="seven" width="556"/>
+ <char name="six" width="556"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="278"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="278"/>
+ <char name="sterling" width="556"/>
+ <char name="t" width="333"/>
+ <char name="thorn" width="611"/>
+ <char name="three" width="556"/>
+ <char name="threequarters" width="834"/>
+ <char name="threesuperior" width="333"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="556"/>
+ <char name="twosuperior" width="333"/>
+ <char name="u" width="611"/>
+ <char name="uacute" width="611"/>
+ <char name="ucircumflex" width="611"/>
+ <char name="udieresis" width="611"/>
+ <char name="ugrave" width="611"/>
+ <char name="underscore" width="556"/>
+ <char name="v" width="556"/>
+ <char name="w" width="778"/>
+ <char name="x" width="556"/>
+ <char name="y" width="556"/>
+ <char name="yacute" width="556"/>
+ <char name="ydieresis" width="556"/>
+ <char name="yen" width="556"/>
+ <char name="z" width="500"/>
+ <char name="zcaron" width="500"/>
+ <char name="zero" width="556"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Helvetica-Oblique</font-name>
+ <class-name>HelveticaOblique</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>718</cap-height>
+ <x-height>523</x-height>
+ <ascender>718</ascender>
+ <descender>-207</descender>
+ <widths>
+ <char name="A" width="667"/>
+ <char name="AE" width="1000"/>
+ <char name="Aacute" width="667"/>
+ <char name="Acircumflex" width="667"/>
+ <char name="Adieresis" width="667"/>
+ <char name="Agrave" width="667"/>
+ <char name="Aring" width="667"/>
+ <char name="Atilde" width="667"/>
+ <char name="B" width="667"/>
+ <char name="C" width="722"/>
+ <char name="Ccedilla" width="722"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="778"/>
+ <char name="H" width="722"/>
+ <char name="I" width="278"/>
+ <char name="Iacute" width="278"/>
+ <char name="Icircumflex" width="278"/>
+ <char name="Idieresis" width="278"/>
+ <char name="Igrave" width="278"/>
+ <char name="J" width="500"/>
+ <char name="K" width="667"/>
+ <char name="L" width="556"/>
+ <char name="Lslash" width="556"/>
+ <char name="M" width="833"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="778"/>
+ <char name="OE" width="1000"/>
+ <char name="Oacute" width="778"/>
+ <char name="Ocircumflex" width="778"/>
+ <char name="Odieresis" width="778"/>
+ <char name="Ograve" width="778"/>
+ <char name="Oslash" width="778"/>
+ <char name="Otilde" width="778"/>
+ <char name="P" width="667"/>
+ <char name="Q" width="778"/>
+ <char name="R" width="722"/>
+ <char name="S" width="667"/>
+ <char name="Scaron" width="667"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="667"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="667"/>
+ <char name="W" width="944"/>
+ <char name="X" width="667"/>
+ <char name="Y" width="667"/>
+ <char name="Yacute" width="667"/>
+ <char name="Ydieresis" width="667"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="556"/>
+ <char name="aacute" width="556"/>
+ <char name="acircumflex" width="556"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="556"/>
+ <char name="ae" width="889"/>
+ <char name="agrave" width="556"/>
+ <char name="ampersand" width="667"/>
+ <char name="aring" width="556"/>
+ <char name="asciicircum" width="469"/>
+ <char name="asciitilde" width="584"/>
+ <char name="asterisk" width="389"/>
+ <char name="at" width="1015"/>
+ <char name="atilde" width="556"/>
+ <char name="b" width="556"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="260"/>
+ <char name="braceleft" width="334"/>
+ <char name="braceright" width="334"/>
+ <char name="bracketleft" width="278"/>
+ <char name="bracketright" width="278"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="260"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="500"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="500"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="556"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="278"/>
+ <char name="comma" width="278"/>
+ <char name="copyright" width="737"/>
+ <char name="currency" width="556"/>
+ <char name="d" width="556"/>
+ <char name="dagger" width="556"/>
+ <char name="daggerdbl" width="556"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="584"/>
+ <char name="dollar" width="556"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="556"/>
+ <char name="eacute" width="556"/>
+ <char name="ecircumflex" width="556"/>
+ <char name="edieresis" width="556"/>
+ <char name="egrave" width="556"/>
+ <char name="eight" width="556"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="556"/>
+ <char name="equal" width="584"/>
+ <char name="eth" width="556"/>
+ <char name="exclam" width="278"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="278"/>
+ <char name="fi" width="500"/>
+ <char name="five" width="556"/>
+ <char name="fl" width="500"/>
+ <char name="florin" width="556"/>
+ <char name="four" width="556"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="556"/>
+ <char name="germandbls" width="611"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="584"/>
+ <char name="guillemotleft" width="556"/>
+ <char name="guillemotright" width="556"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="556"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="222"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="222"/>
+ <char name="k" width="500"/>
+ <char name="l" width="222"/>
+ <char name="less" width="584"/>
+ <char name="logicalnot" width="584"/>
+ <char name="lslash" width="222"/>
+ <char name="m" width="833"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="584"/>
+ <char name="mu" width="556"/>
+ <char name="multiply" width="584"/>
+ <char name="n" width="556"/>
+ <char name="nine" width="556"/>
+ <char name="ntilde" width="556"/>
+ <char name="numbersign" width="556"/>
+ <char name="o" width="556"/>
+ <char name="oacute" width="556"/>
+ <char name="ocircumflex" width="556"/>
+ <char name="odieresis" width="556"/>
+ <char name="oe" width="944"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="556"/>
+ <char name="one" width="556"/>
+ <char name="onehalf" width="834"/>
+ <char name="onequarter" width="834"/>
+ <char name="onesuperior" width="333"/>
+ <char name="ordfeminine" width="370"/>
+ <char name="ordmasculine" width="365"/>
+ <char name="oslash" width="611"/>
+ <char name="otilde" width="556"/>
+ <char name="p" width="556"/>
+ <char name="paragraph" width="537"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="889"/>
+ <char name="period" width="278"/>
+ <char name="periodcentered" width="278"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="584"/>
+ <char name="plusminus" width="584"/>
+ <char name="q" width="556"/>
+ <char name="question" width="556"/>
+ <char name="questiondown" width="611"/>
+ <char name="quotedbl" width="355"/>
+ <char name="quotedblbase" width="333"/>
+ <char name="quotedblleft" width="333"/>
+ <char name="quotedblright" width="333"/>
+ <char name="quoteleft" width="222"/>
+ <char name="quoteright" width="222"/>
+ <char name="quotesinglbase" width="222"/>
+ <char name="quotesingle" width="191"/>
+ <char name="r" width="333"/>
+ <char name="registered" width="737"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="500"/>
+ <char name="scaron" width="500"/>
+ <char name="section" width="556"/>
+ <char name="semicolon" width="278"/>
+ <char name="seven" width="556"/>
+ <char name="six" width="556"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="278"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="278"/>
+ <char name="sterling" width="556"/>
+ <char name="t" width="278"/>
+ <char name="thorn" width="556"/>
+ <char name="three" width="556"/>
+ <char name="threequarters" width="834"/>
+ <char name="threesuperior" width="333"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="556"/>
+ <char name="twosuperior" width="333"/>
+ <char name="u" width="556"/>
+ <char name="uacute" width="556"/>
+ <char name="ucircumflex" width="556"/>
+ <char name="udieresis" width="556"/>
+ <char name="ugrave" width="556"/>
+ <char name="underscore" width="556"/>
+ <char name="v" width="500"/>
+ <char name="w" width="722"/>
+ <char name="x" width="500"/>
+ <char name="y" width="500"/>
+ <char name="yacute" width="500"/>
+ <char name="ydieresis" width="500"/>
+ <char name="yen" width="556"/>
+ <char name="z" width="500"/>
+ <char name="zcaron" width="500"/>
+ <char name="zero" width="556"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Helvetica</font-name>
+ <class-name>Helvetica</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>718</cap-height>
+ <x-height>523</x-height>
+ <ascender>718</ascender>
+ <descender>-207</descender>
+ <widths>
+ <char name="A" width="667"/>
+ <char name="AE" width="1000"/>
+ <char name="Aacute" width="667"/>
+ <char name="Acircumflex" width="667"/>
+ <char name="Adieresis" width="667"/>
+ <char name="Agrave" width="667"/>
+ <char name="Aring" width="667"/>
+ <char name="Atilde" width="667"/>
+ <char name="B" width="667"/>
+ <char name="C" width="722"/>
+ <char name="Ccedilla" width="722"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="778"/>
+ <char name="H" width="722"/>
+ <char name="I" width="278"/>
+ <char name="Iacute" width="278"/>
+ <char name="Icircumflex" width="278"/>
+ <char name="Idieresis" width="278"/>
+ <char name="Igrave" width="278"/>
+ <char name="J" width="500"/>
+ <char name="K" width="667"/>
+ <char name="L" width="556"/>
+ <char name="Lslash" width="556"/>
+ <char name="M" width="833"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="778"/>
+ <char name="OE" width="1000"/>
+ <char name="Oacute" width="778"/>
+ <char name="Ocircumflex" width="778"/>
+ <char name="Odieresis" width="778"/>
+ <char name="Ograve" width="778"/>
+ <char name="Oslash" width="778"/>
+ <char name="Otilde" width="778"/>
+ <char name="P" width="667"/>
+ <char name="Q" width="778"/>
+ <char name="R" width="722"/>
+ <char name="S" width="667"/>
+ <char name="Scaron" width="667"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="667"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="667"/>
+ <char name="W" width="944"/>
+ <char name="X" width="667"/>
+ <char name="Y" width="667"/>
+ <char name="Yacute" width="667"/>
+ <char name="Ydieresis" width="667"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="556"/>
+ <char name="aacute" width="556"/>
+ <char name="acircumflex" width="556"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="556"/>
+ <char name="ae" width="889"/>
+ <char name="agrave" width="556"/>
+ <char name="ampersand" width="667"/>
+ <char name="aring" width="556"/>
+ <char name="asciicircum" width="469"/>
+ <char name="asciitilde" width="584"/>
+ <char name="asterisk" width="389"/>
+ <char name="at" width="1015"/>
+ <char name="atilde" width="556"/>
+ <char name="b" width="556"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="260"/>
+ <char name="braceleft" width="334"/>
+ <char name="braceright" width="334"/>
+ <char name="bracketleft" width="278"/>
+ <char name="bracketright" width="278"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="260"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="500"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="500"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="556"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="278"/>
+ <char name="comma" width="278"/>
+ <char name="copyright" width="737"/>
+ <char name="currency" width="556"/>
+ <char name="d" width="556"/>
+ <char name="dagger" width="556"/>
+ <char name="daggerdbl" width="556"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="584"/>
+ <char name="dollar" width="556"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="556"/>
+ <char name="eacute" width="556"/>
+ <char name="ecircumflex" width="556"/>
+ <char name="edieresis" width="556"/>
+ <char name="egrave" width="556"/>
+ <char name="eight" width="556"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="556"/>
+ <char name="equal" width="584"/>
+ <char name="eth" width="556"/>
+ <char name="exclam" width="278"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="278"/>
+ <char name="fi" width="500"/>
+ <char name="five" width="556"/>
+ <char name="fl" width="500"/>
+ <char name="florin" width="556"/>
+ <char name="four" width="556"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="556"/>
+ <char name="germandbls" width="611"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="584"/>
+ <char name="guillemotleft" width="556"/>
+ <char name="guillemotright" width="556"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="556"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="222"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="222"/>
+ <char name="k" width="500"/>
+ <char name="l" width="222"/>
+ <char name="less" width="584"/>
+ <char name="logicalnot" width="584"/>
+ <char name="lslash" width="222"/>
+ <char name="m" width="833"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="584"/>
+ <char name="mu" width="556"/>
+ <char name="multiply" width="584"/>
+ <char name="n" width="556"/>
+ <char name="nine" width="556"/>
+ <char name="ntilde" width="556"/>
+ <char name="numbersign" width="556"/>
+ <char name="o" width="556"/>
+ <char name="oacute" width="556"/>
+ <char name="ocircumflex" width="556"/>
+ <char name="odieresis" width="556"/>
+ <char name="oe" width="944"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="556"/>
+ <char name="one" width="556"/>
+ <char name="onehalf" width="834"/>
+ <char name="onequarter" width="834"/>
+ <char name="onesuperior" width="333"/>
+ <char name="ordfeminine" width="370"/>
+ <char name="ordmasculine" width="365"/>
+ <char name="oslash" width="611"/>
+ <char name="otilde" width="556"/>
+ <char name="p" width="556"/>
+ <char name="paragraph" width="537"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="889"/>
+ <char name="period" width="278"/>
+ <char name="periodcentered" width="278"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="584"/>
+ <char name="plusminus" width="584"/>
+ <char name="q" width="556"/>
+ <char name="question" width="556"/>
+ <char name="questiondown" width="611"/>
+ <char name="quotedbl" width="355"/>
+ <char name="quotedblbase" width="333"/>
+ <char name="quotedblleft" width="333"/>
+ <char name="quotedblright" width="333"/>
+ <char name="quoteleft" width="222"/>
+ <char name="quoteright" width="222"/>
+ <char name="quotesinglbase" width="222"/>
+ <char name="quotesingle" width="191"/>
+ <char name="r" width="333"/>
+ <char name="registered" width="737"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="500"/>
+ <char name="scaron" width="500"/>
+ <char name="section" width="556"/>
+ <char name="semicolon" width="278"/>
+ <char name="seven" width="556"/>
+ <char name="six" width="556"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="278"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="278"/>
+ <char name="sterling" width="556"/>
+ <char name="t" width="278"/>
+ <char name="thorn" width="556"/>
+ <char name="three" width="556"/>
+ <char name="threequarters" width="834"/>
+ <char name="threesuperior" width="333"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="556"/>
+ <char name="twosuperior" width="333"/>
+ <char name="u" width="556"/>
+ <char name="uacute" width="556"/>
+ <char name="ucircumflex" width="556"/>
+ <char name="udieresis" width="556"/>
+ <char name="ugrave" width="556"/>
+ <char name="underscore" width="556"/>
+ <char name="v" width="500"/>
+ <char name="w" width="722"/>
+ <char name="x" width="500"/>
+ <char name="y" width="500"/>
+ <char name="yacute" width="500"/>
+ <char name="ydieresis" width="500"/>
+ <char name="yen" width="556"/>
+ <char name="z" width="500"/>
+ <char name="zcaron" width="500"/>
+ <char name="zero" width="556"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Times-Bold</font-name>
+ <class-name>TimesBold</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>676</cap-height>
+ <x-height>461</x-height>
+ <ascender>676</ascender>
+ <descender>-205</descender>
+ <widths>
+ <char name="A" width="722"/>
+ <char name="AE" width="1000"/>
+ <char name="Aacute" width="722"/>
+ <char name="Acircumflex" width="722"/>
+ <char name="Adieresis" width="722"/>
+ <char name="Agrave" width="722"/>
+ <char name="Aring" width="722"/>
+ <char name="Atilde" width="722"/>
+ <char name="B" width="667"/>
+ <char name="C" width="722"/>
+ <char name="Ccedilla" width="722"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="778"/>
+ <char name="H" width="778"/>
+ <char name="I" width="389"/>
+ <char name="Iacute" width="389"/>
+ <char name="Icircumflex" width="389"/>
+ <char name="Idieresis" width="389"/>
+ <char name="Igrave" width="389"/>
+ <char name="J" width="500"/>
+ <char name="K" width="778"/>
+ <char name="L" width="667"/>
+ <char name="Lslash" width="667"/>
+ <char name="M" width="944"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="778"/>
+ <char name="OE" width="1000"/>
+ <char name="Oacute" width="778"/>
+ <char name="Ocircumflex" width="778"/>
+ <char name="Odieresis" width="778"/>
+ <char name="Ograve" width="778"/>
+ <char name="Oslash" width="778"/>
+ <char name="Otilde" width="778"/>
+ <char name="P" width="611"/>
+ <char name="Q" width="778"/>
+ <char name="R" width="722"/>
+ <char name="S" width="556"/>
+ <char name="Scaron" width="556"/>
+ <char name="T" width="667"/>
+ <char name="Thorn" width="611"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="722"/>
+ <char name="W" width="1000"/>
+ <char name="X" width="722"/>
+ <char name="Y" width="722"/>
+ <char name="Yacute" width="722"/>
+ <char name="Ydieresis" width="722"/>
+ <char name="Z" width="667"/>
+ <char name="Zcaron" width="667"/>
+ <char name="a" width="500"/>
+ <char name="aacute" width="500"/>
+ <char name="acircumflex" width="500"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="500"/>
+ <char name="ae" width="722"/>
+ <char name="agrave" width="500"/>
+ <char name="ampersand" width="833"/>
+ <char name="aring" width="500"/>
+ <char name="asciicircum" width="581"/>
+ <char name="asciitilde" width="520"/>
+ <char name="asterisk" width="500"/>
+ <char name="at" width="930"/>
+ <char name="atilde" width="500"/>
+ <char name="b" width="556"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="220"/>
+ <char name="braceleft" width="394"/>
+ <char name="braceright" width="394"/>
+ <char name="bracketleft" width="333"/>
+ <char name="bracketright" width="333"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="220"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="444"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="444"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="500"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="333"/>
+ <char name="comma" width="250"/>
+ <char name="copyright" width="747"/>
+ <char name="currency" width="500"/>
+ <char name="d" width="556"/>
+ <char name="dagger" width="500"/>
+ <char name="daggerdbl" width="500"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="570"/>
+ <char name="dollar" width="500"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="444"/>
+ <char name="eacute" width="444"/>
+ <char name="ecircumflex" width="444"/>
+ <char name="edieresis" width="444"/>
+ <char name="egrave" width="444"/>
+ <char name="eight" width="500"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="500"/>
+ <char name="equal" width="570"/>
+ <char name="eth" width="500"/>
+ <char name="exclam" width="333"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="333"/>
+ <char name="fi" width="556"/>
+ <char name="five" width="500"/>
+ <char name="fl" width="556"/>
+ <char name="florin" width="500"/>
+ <char name="four" width="500"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="500"/>
+ <char name="germandbls" width="556"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="570"/>
+ <char name="guillemotleft" width="500"/>
+ <char name="guillemotright" width="500"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="556"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="333"/>
+ <char name="k" width="556"/>
+ <char name="l" width="278"/>
+ <char name="less" width="570"/>
+ <char name="logicalnot" width="570"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="833"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="570"/>
+ <char name="mu" width="556"/>
+ <char name="multiply" width="570"/>
+ <char name="n" width="556"/>
+ <char name="nine" width="500"/>
+ <char name="ntilde" width="556"/>
+ <char name="numbersign" width="500"/>
+ <char name="o" width="500"/>
+ <char name="oacute" width="500"/>
+ <char name="ocircumflex" width="500"/>
+ <char name="odieresis" width="500"/>
+ <char name="oe" width="722"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="500"/>
+ <char name="one" width="500"/>
+ <char name="onehalf" width="750"/>
+ <char name="onequarter" width="750"/>
+ <char name="onesuperior" width="300"/>
+ <char name="ordfeminine" width="300"/>
+ <char name="ordmasculine" width="330"/>
+ <char name="oslash" width="500"/>
+ <char name="otilde" width="500"/>
+ <char name="p" width="556"/>
+ <char name="paragraph" width="540"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="1000"/>
+ <char name="period" width="250"/>
+ <char name="periodcentered" width="250"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="570"/>
+ <char name="plusminus" width="570"/>
+ <char name="q" width="556"/>
+ <char name="question" width="500"/>
+ <char name="questiondown" width="500"/>
+ <char name="quotedbl" width="555"/>
+ <char name="quotedblbase" width="500"/>
+ <char name="quotedblleft" width="500"/>
+ <char name="quotedblright" width="500"/>
+ <char name="quoteleft" width="333"/>
+ <char name="quoteright" width="333"/>
+ <char name="quotesinglbase" width="333"/>
+ <char name="quotesingle" width="278"/>
+ <char name="r" width="444"/>
+ <char name="registered" width="747"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="389"/>
+ <char name="scaron" width="389"/>
+ <char name="section" width="500"/>
+ <char name="semicolon" width="333"/>
+ <char name="seven" width="500"/>
+ <char name="six" width="500"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="250"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="250"/>
+ <char name="sterling" width="500"/>
+ <char name="t" width="333"/>
+ <char name="thorn" width="556"/>
+ <char name="three" width="500"/>
+ <char name="threequarters" width="750"/>
+ <char name="threesuperior" width="300"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="500"/>
+ <char name="twosuperior" width="300"/>
+ <char name="u" width="556"/>
+ <char name="uacute" width="556"/>
+ <char name="ucircumflex" width="556"/>
+ <char name="udieresis" width="556"/>
+ <char name="ugrave" width="556"/>
+ <char name="underscore" width="500"/>
+ <char name="v" width="500"/>
+ <char name="w" width="722"/>
+ <char name="x" width="500"/>
+ <char name="y" width="500"/>
+ <char name="yacute" width="500"/>
+ <char name="ydieresis" width="500"/>
+ <char name="yen" width="500"/>
+ <char name="z" width="444"/>
+ <char name="zcaron" width="444"/>
+ <char name="zero" width="500"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Times-BoldItalic</font-name>
+ <class-name>TimesBoldItalic</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>669</cap-height>
+ <x-height>462</x-height>
+ <ascender>699</ascender>
+ <descender>-205</descender>
+ <widths>
+ <char name="A" width="667"/>
+ <char name="AE" width="944"/>
+ <char name="Aacute" width="667"/>
+ <char name="Acircumflex" width="667"/>
+ <char name="Adieresis" width="667"/>
+ <char name="Agrave" width="667"/>
+ <char name="Aring" width="667"/>
+ <char name="Atilde" width="667"/>
+ <char name="B" width="667"/>
+ <char name="C" width="667"/>
+ <char name="Ccedilla" width="667"/>
+ <char name="D" width="722"/>
+ <char name="E" width="667"/>
+ <char name="Eacute" width="667"/>
+ <char name="Ecircumflex" width="667"/>
+ <char name="Edieresis" width="667"/>
+ <char name="Egrave" width="667"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="667"/>
+ <char name="G" width="722"/>
+ <char name="H" width="778"/>
+ <char name="I" width="389"/>
+ <char name="Iacute" width="389"/>
+ <char name="Icircumflex" width="389"/>
+ <char name="Idieresis" width="389"/>
+ <char name="Igrave" width="389"/>
+ <char name="J" width="500"/>
+ <char name="K" width="667"/>
+ <char name="L" width="611"/>
+ <char name="Lslash" width="611"/>
+ <char name="M" width="889"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="722"/>
+ <char name="OE" width="944"/>
+ <char name="Oacute" width="722"/>
+ <char name="Ocircumflex" width="722"/>
+ <char name="Odieresis" width="722"/>
+ <char name="Ograve" width="722"/>
+ <char name="Oslash" width="722"/>
+ <char name="Otilde" width="722"/>
+ <char name="P" width="611"/>
+ <char name="Q" width="722"/>
+ <char name="R" width="667"/>
+ <char name="S" width="556"/>
+ <char name="Scaron" width="556"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="611"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="667"/>
+ <char name="W" width="889"/>
+ <char name="X" width="667"/>
+ <char name="Y" width="611"/>
+ <char name="Yacute" width="611"/>
+ <char name="Ydieresis" width="611"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="500"/>
+ <char name="aacute" width="500"/>
+ <char name="acircumflex" width="500"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="500"/>
+ <char name="ae" width="722"/>
+ <char name="agrave" width="500"/>
+ <char name="ampersand" width="778"/>
+ <char name="aring" width="500"/>
+ <char name="asciicircum" width="570"/>
+ <char name="asciitilde" width="570"/>
+ <char name="asterisk" width="500"/>
+ <char name="at" width="832"/>
+ <char name="atilde" width="500"/>
+ <char name="b" width="500"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="220"/>
+ <char name="braceleft" width="348"/>
+ <char name="braceright" width="348"/>
+ <char name="bracketleft" width="333"/>
+ <char name="bracketright" width="333"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="220"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="444"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="444"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="500"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="333"/>
+ <char name="comma" width="250"/>
+ <char name="copyright" width="747"/>
+ <char name="currency" width="500"/>
+ <char name="d" width="500"/>
+ <char name="dagger" width="500"/>
+ <char name="daggerdbl" width="500"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="570"/>
+ <char name="dollar" width="500"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="444"/>
+ <char name="eacute" width="444"/>
+ <char name="ecircumflex" width="444"/>
+ <char name="edieresis" width="444"/>
+ <char name="egrave" width="444"/>
+ <char name="eight" width="500"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="500"/>
+ <char name="equal" width="570"/>
+ <char name="eth" width="500"/>
+ <char name="exclam" width="389"/>
+ <char name="exclamdown" width="389"/>
+ <char name="f" width="333"/>
+ <char name="fi" width="556"/>
+ <char name="five" width="500"/>
+ <char name="fl" width="556"/>
+ <char name="florin" width="500"/>
+ <char name="four" width="500"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="500"/>
+ <char name="germandbls" width="500"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="570"/>
+ <char name="guillemotleft" width="500"/>
+ <char name="guillemotright" width="500"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="556"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="278"/>
+ <char name="k" width="500"/>
+ <char name="l" width="278"/>
+ <char name="less" width="570"/>
+ <char name="logicalnot" width="606"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="778"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="606"/>
+ <char name="mu" width="576"/>
+ <char name="multiply" width="570"/>
+ <char name="n" width="556"/>
+ <char name="nine" width="500"/>
+ <char name="ntilde" width="556"/>
+ <char name="numbersign" width="500"/>
+ <char name="o" width="500"/>
+ <char name="oacute" width="500"/>
+ <char name="ocircumflex" width="500"/>
+ <char name="odieresis" width="500"/>
+ <char name="oe" width="722"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="500"/>
+ <char name="one" width="500"/>
+ <char name="onehalf" width="750"/>
+ <char name="onequarter" width="750"/>
+ <char name="onesuperior" width="300"/>
+ <char name="ordfeminine" width="266"/>
+ <char name="ordmasculine" width="300"/>
+ <char name="oslash" width="500"/>
+ <char name="otilde" width="500"/>
+ <char name="p" width="500"/>
+ <char name="paragraph" width="500"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="833"/>
+ <char name="period" width="250"/>
+ <char name="periodcentered" width="250"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="570"/>
+ <char name="plusminus" width="570"/>
+ <char name="q" width="500"/>
+ <char name="question" width="500"/>
+ <char name="questiondown" width="500"/>
+ <char name="quotedbl" width="555"/>
+ <char name="quotedblbase" width="500"/>
+ <char name="quotedblleft" width="500"/>
+ <char name="quotedblright" width="500"/>
+ <char name="quoteleft" width="333"/>
+ <char name="quoteright" width="333"/>
+ <char name="quotesinglbase" width="333"/>
+ <char name="quotesingle" width="278"/>
+ <char name="r" width="389"/>
+ <char name="registered" width="747"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="389"/>
+ <char name="scaron" width="389"/>
+ <char name="section" width="500"/>
+ <char name="semicolon" width="333"/>
+ <char name="seven" width="500"/>
+ <char name="six" width="500"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="250"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="250"/>
+ <char name="sterling" width="500"/>
+ <char name="t" width="278"/>
+ <char name="thorn" width="500"/>
+ <char name="three" width="500"/>
+ <char name="threequarters" width="750"/>
+ <char name="threesuperior" width="300"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="1000"/>
+ <char name="two" width="500"/>
+ <char name="twosuperior" width="300"/>
+ <char name="u" width="556"/>
+ <char name="uacute" width="556"/>
+ <char name="ucircumflex" width="556"/>
+ <char name="udieresis" width="556"/>
+ <char name="ugrave" width="556"/>
+ <char name="underscore" width="500"/>
+ <char name="v" width="444"/>
+ <char name="w" width="667"/>
+ <char name="x" width="500"/>
+ <char name="y" width="444"/>
+ <char name="yacute" width="444"/>
+ <char name="ydieresis" width="444"/>
+ <char name="yen" width="500"/>
+ <char name="z" width="389"/>
+ <char name="zcaron" width="389"/>
+ <char name="zero" width="500"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Times-Italic</font-name>
+ <class-name>TimesItalic</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>653</cap-height>
+ <x-height>441</x-height>
+ <ascender>683</ascender>
+ <descender>-205</descender>
+ <widths>
+ <char name="A" width="611"/>
+ <char name="AE" width="889"/>
+ <char name="Aacute" width="611"/>
+ <char name="Acircumflex" width="611"/>
+ <char name="Adieresis" width="611"/>
+ <char name="Agrave" width="611"/>
+ <char name="Aring" width="611"/>
+ <char name="Atilde" width="611"/>
+ <char name="B" width="611"/>
+ <char name="C" width="667"/>
+ <char name="Ccedilla" width="667"/>
+ <char name="D" width="722"/>
+ <char name="E" width="611"/>
+ <char name="Eacute" width="611"/>
+ <char name="Ecircumflex" width="611"/>
+ <char name="Edieresis" width="611"/>
+ <char name="Egrave" width="611"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="611"/>
+ <char name="G" width="722"/>
+ <char name="H" width="722"/>
+ <char name="I" width="333"/>
+ <char name="Iacute" width="333"/>
+ <char name="Icircumflex" width="333"/>
+ <char name="Idieresis" width="333"/>
+ <char name="Igrave" width="333"/>
+ <char name="J" width="444"/>
+ <char name="K" width="667"/>
+ <char name="L" width="556"/>
+ <char name="Lslash" width="556"/>
+ <char name="M" width="833"/>
+ <char name="N" width="667"/>
+ <char name="Ntilde" width="667"/>
+ <char name="O" width="722"/>
+ <char name="OE" width="944"/>
+ <char name="Oacute" width="722"/>
+ <char name="Ocircumflex" width="722"/>
+ <char name="Odieresis" width="722"/>
+ <char name="Ograve" width="722"/>
+ <char name="Oslash" width="722"/>
+ <char name="Otilde" width="722"/>
+ <char name="P" width="611"/>
+ <char name="Q" width="722"/>
+ <char name="R" width="611"/>
+ <char name="S" width="500"/>
+ <char name="Scaron" width="500"/>
+ <char name="T" width="556"/>
+ <char name="Thorn" width="611"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="611"/>
+ <char name="W" width="833"/>
+ <char name="X" width="611"/>
+ <char name="Y" width="556"/>
+ <char name="Yacute" width="556"/>
+ <char name="Ydieresis" width="556"/>
+ <char name="Z" width="556"/>
+ <char name="Zcaron" width="556"/>
+ <char name="a" width="500"/>
+ <char name="aacute" width="500"/>
+ <char name="acircumflex" width="500"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="500"/>
+ <char name="ae" width="667"/>
+ <char name="agrave" width="500"/>
+ <char name="ampersand" width="778"/>
+ <char name="aring" width="500"/>
+ <char name="asciicircum" width="422"/>
+ <char name="asciitilde" width="541"/>
+ <char name="asterisk" width="500"/>
+ <char name="at" width="920"/>
+ <char name="atilde" width="500"/>
+ <char name="b" width="500"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="275"/>
+ <char name="braceleft" width="400"/>
+ <char name="braceright" width="400"/>
+ <char name="bracketleft" width="389"/>
+ <char name="bracketright" width="389"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="275"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="444"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="444"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="500"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="333"/>
+ <char name="comma" width="250"/>
+ <char name="copyright" width="760"/>
+ <char name="currency" width="500"/>
+ <char name="d" width="500"/>
+ <char name="dagger" width="500"/>
+ <char name="daggerdbl" width="500"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="675"/>
+ <char name="dollar" width="500"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="444"/>
+ <char name="eacute" width="444"/>
+ <char name="ecircumflex" width="444"/>
+ <char name="edieresis" width="444"/>
+ <char name="egrave" width="444"/>
+ <char name="eight" width="500"/>
+ <char name="ellipsis" width="889"/>
+ <char name="emdash" width="889"/>
+ <char name="endash" width="500"/>
+ <char name="equal" width="675"/>
+ <char name="eth" width="500"/>
+ <char name="exclam" width="333"/>
+ <char name="exclamdown" width="389"/>
+ <char name="f" width="278"/>
+ <char name="fi" width="500"/>
+ <char name="five" width="500"/>
+ <char name="fl" width="500"/>
+ <char name="florin" width="500"/>
+ <char name="four" width="500"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="500"/>
+ <char name="germandbls" width="500"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="675"/>
+ <char name="guillemotleft" width="500"/>
+ <char name="guillemotright" width="500"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="500"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="278"/>
+ <char name="k" width="444"/>
+ <char name="l" width="278"/>
+ <char name="less" width="675"/>
+ <char name="logicalnot" width="675"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="722"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="675"/>
+ <char name="mu" width="500"/>
+ <char name="multiply" width="675"/>
+ <char name="n" width="500"/>
+ <char name="nine" width="500"/>
+ <char name="ntilde" width="500"/>
+ <char name="numbersign" width="500"/>
+ <char name="o" width="500"/>
+ <char name="oacute" width="500"/>
+ <char name="ocircumflex" width="500"/>
+ <char name="odieresis" width="500"/>
+ <char name="oe" width="667"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="500"/>
+ <char name="one" width="500"/>
+ <char name="onehalf" width="750"/>
+ <char name="onequarter" width="750"/>
+ <char name="onesuperior" width="300"/>
+ <char name="ordfeminine" width="276"/>
+ <char name="ordmasculine" width="310"/>
+ <char name="oslash" width="500"/>
+ <char name="otilde" width="500"/>
+ <char name="p" width="500"/>
+ <char name="paragraph" width="523"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="833"/>
+ <char name="period" width="250"/>
+ <char name="periodcentered" width="250"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="675"/>
+ <char name="plusminus" width="675"/>
+ <char name="q" width="500"/>
+ <char name="question" width="500"/>
+ <char name="questiondown" width="500"/>
+ <char name="quotedbl" width="420"/>
+ <char name="quotedblbase" width="556"/>
+ <char name="quotedblleft" width="556"/>
+ <char name="quotedblright" width="556"/>
+ <char name="quoteleft" width="333"/>
+ <char name="quoteright" width="333"/>
+ <char name="quotesinglbase" width="333"/>
+ <char name="quotesingle" width="214"/>
+ <char name="r" width="389"/>
+ <char name="registered" width="760"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="389"/>
+ <char name="scaron" width="389"/>
+ <char name="section" width="500"/>
+ <char name="semicolon" width="333"/>
+ <char name="seven" width="500"/>
+ <char name="six" width="500"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="250"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="250"/>
+ <char name="sterling" width="500"/>
+ <char name="t" width="278"/>
+ <char name="thorn" width="500"/>
+ <char name="three" width="500"/>
+ <char name="threequarters" width="750"/>
+ <char name="threesuperior" width="300"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="980"/>
+ <char name="two" width="500"/>
+ <char name="twosuperior" width="300"/>
+ <char name="u" width="500"/>
+ <char name="uacute" width="500"/>
+ <char name="ucircumflex" width="500"/>
+ <char name="udieresis" width="500"/>
+ <char name="ugrave" width="500"/>
+ <char name="underscore" width="500"/>
+ <char name="v" width="444"/>
+ <char name="w" width="667"/>
+ <char name="x" width="444"/>
+ <char name="y" width="444"/>
+ <char name="yacute" width="444"/>
+ <char name="ydieresis" width="444"/>
+ <char name="yen" width="500"/>
+ <char name="z" width="389"/>
+ <char name="zcaron" width="389"/>
+ <char name="zero" width="500"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
+<font-metrics>
+ <font-name>Times-Roman</font-name>
+ <class-name>TimesRoman</class-name>
+ <encoding>WinAnsiEncoding</encoding>
+ <cap-height>662</cap-height>
+ <x-height>450</x-height>
+ <ascender>683</ascender>
+ <descender>-217</descender>
+ <widths>
+ <char name="A" width="722"/>
+ <char name="AE" width="889"/>
+ <char name="Aacute" width="722"/>
+ <char name="Acircumflex" width="722"/>
+ <char name="Adieresis" width="722"/>
+ <char name="Agrave" width="722"/>
+ <char name="Aring" width="722"/>
+ <char name="Atilde" width="722"/>
+ <char name="B" width="667"/>
+ <char name="C" width="667"/>
+ <char name="Ccedilla" width="667"/>
+ <char name="D" width="722"/>
+ <char name="E" width="611"/>
+ <char name="Eacute" width="611"/>
+ <char name="Ecircumflex" width="611"/>
+ <char name="Edieresis" width="611"/>
+ <char name="Egrave" width="611"/>
+ <char name="Eth" width="722"/>
+ <char name="F" width="556"/>
+ <char name="G" width="722"/>
+ <char name="H" width="722"/>
+ <char name="I" width="333"/>
+ <char name="Iacute" width="333"/>
+ <char name="Icircumflex" width="333"/>
+ <char name="Idieresis" width="333"/>
+ <char name="Igrave" width="333"/>
+ <char name="J" width="389"/>
+ <char name="K" width="722"/>
+ <char name="L" width="611"/>
+ <char name="Lslash" width="611"/>
+ <char name="M" width="889"/>
+ <char name="N" width="722"/>
+ <char name="Ntilde" width="722"/>
+ <char name="O" width="722"/>
+ <char name="OE" width="889"/>
+ <char name="Oacute" width="722"/>
+ <char name="Ocircumflex" width="722"/>
+ <char name="Odieresis" width="722"/>
+ <char name="Ograve" width="722"/>
+ <char name="Oslash" width="722"/>
+ <char name="Otilde" width="722"/>
+ <char name="P" width="556"/>
+ <char name="Q" width="722"/>
+ <char name="R" width="667"/>
+ <char name="S" width="556"/>
+ <char name="Scaron" width="556"/>
+ <char name="T" width="611"/>
+ <char name="Thorn" width="556"/>
+ <char name="U" width="722"/>
+ <char name="Uacute" width="722"/>
+ <char name="Ucircumflex" width="722"/>
+ <char name="Udieresis" width="722"/>
+ <char name="Ugrave" width="722"/>
+ <char name="V" width="722"/>
+ <char name="W" width="944"/>
+ <char name="X" width="722"/>
+ <char name="Y" width="722"/>
+ <char name="Yacute" width="722"/>
+ <char name="Ydieresis" width="722"/>
+ <char name="Z" width="611"/>
+ <char name="Zcaron" width="611"/>
+ <char name="a" width="444"/>
+ <char name="aacute" width="444"/>
+ <char name="acircumflex" width="444"/>
+ <char name="acute" width="333"/>
+ <char name="adieresis" width="444"/>
+ <char name="ae" width="667"/>
+ <char name="agrave" width="444"/>
+ <char name="ampersand" width="778"/>
+ <char name="aring" width="444"/>
+ <char name="asciicircum" width="469"/>
+ <char name="asciitilde" width="541"/>
+ <char name="asterisk" width="500"/>
+ <char name="at" width="921"/>
+ <char name="atilde" width="444"/>
+ <char name="b" width="500"/>
+ <char name="backslash" width="278"/>
+ <char name="bar" width="200"/>
+ <char name="braceleft" width="480"/>
+ <char name="braceright" width="480"/>
+ <char name="bracketleft" width="333"/>
+ <char name="bracketright" width="333"/>
+ <char name="breve" width="333"/>
+ <char name="brokenbar" width="200"/>
+ <char name="bullet" width="350"/>
+ <char name="c" width="444"/>
+ <char name="caron" width="333"/>
+ <char name="ccedilla" width="444"/>
+ <char name="cedilla" width="333"/>
+ <char name="cent" width="500"/>
+ <char name="circumflex" width="333"/>
+ <char name="colon" width="278"/>
+ <char name="comma" width="250"/>
+ <char name="copyright" width="760"/>
+ <char name="currency" width="500"/>
+ <char name="d" width="500"/>
+ <char name="dagger" width="500"/>
+ <char name="daggerdbl" width="500"/>
+ <char name="degree" width="400"/>
+ <char name="dieresis" width="333"/>
+ <char name="divide" width="564"/>
+ <char name="dollar" width="500"/>
+ <char name="dotaccent" width="333"/>
+ <char name="dotlessi" width="278"/>
+ <char name="e" width="444"/>
+ <char name="eacute" width="444"/>
+ <char name="ecircumflex" width="444"/>
+ <char name="edieresis" width="444"/>
+ <char name="egrave" width="444"/>
+ <char name="eight" width="500"/>
+ <char name="ellipsis" width="1000"/>
+ <char name="emdash" width="1000"/>
+ <char name="endash" width="500"/>
+ <char name="equal" width="564"/>
+ <char name="eth" width="500"/>
+ <char name="exclam" width="333"/>
+ <char name="exclamdown" width="333"/>
+ <char name="f" width="333"/>
+ <char name="fi" width="556"/>
+ <char name="five" width="500"/>
+ <char name="fl" width="556"/>
+ <char name="florin" width="500"/>
+ <char name="four" width="500"/>
+ <char name="fraction" width="167"/>
+ <char name="g" width="500"/>
+ <char name="germandbls" width="500"/>
+ <char name="grave" width="333"/>
+ <char name="greater" width="564"/>
+ <char name="guillemotleft" width="500"/>
+ <char name="guillemotright" width="500"/>
+ <char name="guilsinglleft" width="333"/>
+ <char name="guilsinglright" width="333"/>
+ <char name="h" width="500"/>
+ <char name="hungarumlaut" width="333"/>
+ <char name="hyphen" width="333"/>
+ <char name="i" width="278"/>
+ <char name="iacute" width="278"/>
+ <char name="icircumflex" width="278"/>
+ <char name="idieresis" width="278"/>
+ <char name="igrave" width="278"/>
+ <char name="j" width="278"/>
+ <char name="k" width="500"/>
+ <char name="l" width="278"/>
+ <char name="less" width="564"/>
+ <char name="logicalnot" width="564"/>
+ <char name="lslash" width="278"/>
+ <char name="m" width="778"/>
+ <char name="macron" width="333"/>
+ <char name="minus" width="564"/>
+ <char name="mu" width="500"/>
+ <char name="multiply" width="564"/>
+ <char name="n" width="500"/>
+ <char name="nine" width="500"/>
+ <char name="ntilde" width="500"/>
+ <char name="numbersign" width="500"/>
+ <char name="o" width="500"/>
+ <char name="oacute" width="500"/>
+ <char name="ocircumflex" width="500"/>
+ <char name="odieresis" width="500"/>
+ <char name="oe" width="722"/>
+ <char name="ogonek" width="333"/>
+ <char name="ograve" width="500"/>
+ <char name="one" width="500"/>
+ <char name="onehalf" width="750"/>
+ <char name="onequarter" width="750"/>
+ <char name="onesuperior" width="300"/>
+ <char name="ordfeminine" width="276"/>
+ <char name="ordmasculine" width="310"/>
+ <char name="oslash" width="500"/>
+ <char name="otilde" width="500"/>
+ <char name="p" width="500"/>
+ <char name="paragraph" width="453"/>
+ <char name="parenleft" width="333"/>
+ <char name="parenright" width="333"/>
+ <char name="percent" width="833"/>
+ <char name="period" width="250"/>
+ <char name="periodcentered" width="250"/>
+ <char name="perthousand" width="1000"/>
+ <char name="plus" width="564"/>
+ <char name="plusminus" width="564"/>
+ <char name="q" width="500"/>
+ <char name="question" width="444"/>
+ <char name="questiondown" width="444"/>
+ <char name="quotedbl" width="408"/>
+ <char name="quotedblbase" width="444"/>
+ <char name="quotedblleft" width="444"/>
+ <char name="quotedblright" width="444"/>
+ <char name="quoteleft" width="333"/>
+ <char name="quoteright" width="333"/>
+ <char name="quotesinglbase" width="333"/>
+ <char name="quotesingle" width="180"/>
+ <char name="r" width="333"/>
+ <char name="registered" width="760"/>
+ <char name="ring" width="333"/>
+ <char name="s" width="389"/>
+ <char name="scaron" width="389"/>
+ <char name="section" width="500"/>
+ <char name="semicolon" width="278"/>
+ <char name="seven" width="500"/>
+ <char name="six" width="500"/>
+ <char name="slash" width="278"/>
+ <char name="space" width="250"/>
+ <!-- JKT: the following has been manually added -->
+ <char name="nbsp" width="250"/>
+ <char name="sterling" width="500"/>
+ <char name="t" width="278"/>
+ <char name="thorn" width="500"/>
+ <char name="three" width="500"/>
+ <char name="threequarters" width="750"/>
+ <char name="threesuperior" width="300"/>
+ <char name="tilde" width="333"/>
+ <char name="trademark" width="980"/>
+ <char name="two" width="500"/>
+ <char name="twosuperior" width="300"/>
+ <char name="u" width="500"/>
+ <char name="uacute" width="500"/>
+ <char name="ucircumflex" width="500"/>
+ <char name="udieresis" width="500"/>
+ <char name="ugrave" width="500"/>
+ <char name="underscore" width="500"/>
+ <char name="v" width="500"/>
+ <char name="w" width="722"/>
+ <char name="x" width="500"/>
+ <char name="y" width="500"/>
+ <char name="yacute" width="500"/>
+ <char name="ydieresis" width="500"/>
+ <char name="yen" width="500"/>
+ <char name="z" width="444"/>
+ <char name="zcaron" width="444"/>
+ <char name="zero" width="500"/>
+ </widths>
+</font-metrics>
\ No newline at end of file
--- /dev/null
+<!-- JKT: these mappings were kindly produced by Fotis Jannidis -->
+<font-mappings>
+ <map adobe-name="A" win-ansi="0x0041" unicode="0x0041"/>
+ <map adobe-name="AE" win-ansi="0x00C6" unicode="0x00C6"/>
+ <map adobe-name="Aacute" win-ansi="0x00C1" unicode="0x00C1"/>
+ <map adobe-name="Acircumflex" win-ansi="0x00C2" unicode="0x00C2"/>
+ <map adobe-name="Adieresis" win-ansi="0x00C4" unicode="0x00C4"/>
+ <map adobe-name="Agrave" win-ansi="0x00C0" unicode="0x00C0"/>
+ <map adobe-name="Aring" win-ansi="0x00C5" unicode="0x00C5"/>
+ <map adobe-name="Atilde" win-ansi="0x00C3" unicode="0x00C3"/>
+ <map adobe-name="B" win-ansi="0x0042" unicode="0x0042"/>
+ <map adobe-name="C" win-ansi="0x0043" unicode="0x0043"/>
+ <map adobe-name="Ccedilla" win-ansi="0x00C7" unicode="0x00C7"/>
+ <map adobe-name="D" win-ansi="0x0044" unicode="0x0044"/>
+ <map adobe-name="E" win-ansi="0x0045" unicode="0x0045"/>
+ <map adobe-name="Eacute" win-ansi="0x00C9" unicode="0x00C9"/>
+ <map adobe-name="Ecircumflex" win-ansi="0x00CA" unicode="0x00CA"/>
+ <map adobe-name="Edieresis" win-ansi="0x00CB" unicode="0x00CB"/>
+ <map adobe-name="Egrave" win-ansi="0x00C8" unicode="0x00C8"/>
+ <map adobe-name="Eth" win-ansi="0x00D0" unicode="0x00D0"/>
+ <map adobe-name="F" win-ansi="0x0046" unicode="0x0046"/>
+ <map adobe-name="G" win-ansi="0x0047" unicode="0x0047"/>
+ <map adobe-name="Gcaron" win-ansi="-1" unicode="0x01E6"/>
+ <map adobe-name="H" win-ansi="0x0048" unicode="0x0048"/>
+ <map adobe-name="I" win-ansi="0x0049" unicode="0x0049"/>
+ <map adobe-name="Iacute" win-ansi="0x00CD" unicode="0x00CD"/>
+ <map adobe-name="Icircumflex" win-ansi="0x00CE" unicode="0x00CE"/>
+ <map adobe-name="Idieresis" win-ansi="0x00CF" unicode="0x00CF"/>
+ <map adobe-name="Idot" win-ansi="-1" unicode="0x0130"/>
+ <map adobe-name="Igrave" win-ansi="0x00CC" unicode="0x00CC"/>
+ <map adobe-name="IJ" win-ansi="-1" unicode="0x0132"/>
+ <map adobe-name="J" win-ansi="0x004A" unicode="0x004A"/>
+ <map adobe-name="K" win-ansi="0x004B" unicode="0x004B"/>
+ <map adobe-name="L" win-ansi="0x004C" unicode="0x004C"/>
+ <map adobe-name="Lslash" win-ansi="-1" unicode="0x0141"/>
+ <map adobe-name="M" win-ansi="0x004D" unicode="0x004D"/>
+ <map adobe-name="N" win-ansi="0x004E" unicode="0x004E"/>
+ <map adobe-name="Ntilde" win-ansi="0x00D1" unicode="0x00D1"/>
+ <map adobe-name="O" win-ansi="0x004F" unicode="0x004F"/>
+ <map adobe-name="OE" win-ansi="0x008C" unicode="0x0152"/>
+ <map adobe-name="Oacute" win-ansi="0x00D3" unicode="0x00D3"/>
+ <map adobe-name="Ocircumflex" win-ansi="0x00D4" unicode="0x00D4"/>
+ <map adobe-name="Odieresis" win-ansi="0x00D6" unicode="0x00D6"/>
+ <map adobe-name="Ograve" win-ansi="0x00D2" unicode="0x00D2"/>
+ <map adobe-name="Oslash" win-ansi="0x00D8" unicode="0x00D8"/>
+ <map adobe-name="Otilde" win-ansi="0x00D5" unicode="0x00D5"/>
+ <map adobe-name="P" win-ansi="0x0050" unicode="0x0050"/>
+ <map adobe-name="Q" win-ansi="0x0051" unicode="0x0051"/>
+ <map adobe-name="R" win-ansi="0x0052" unicode="0x0052"/>
+ <map adobe-name="S" win-ansi="0x0053" unicode="0x0053"/>
+ <map adobe-name="Scaron" win-ansi="0x008A" unicode="0x0160"/>
+ <map adobe-name="Scedilla" win-ansi="-1" unicode="0x015E"/>
+ <map adobe-name="T" win-ansi="0x0054" unicode="0x0054"/>
+ <map adobe-name="Thorn" win-ansi="0x00DE" unicode="0x00DE"/>
+ <map adobe-name="U" win-ansi="0x0055" unicode="0x0055"/>
+ <map adobe-name="Uacute" win-ansi="0x00DA" unicode="0x00DA"/>
+ <map adobe-name="Ucircumflex" win-ansi="0x00DB" unicode="0x00DB"/>
+ <map adobe-name="Udieresis" win-ansi="0x00DC" unicode="0x00DC"/>
+ <map adobe-name="Ugrave" win-ansi="0x00D9" unicode="0x00D9"/>
+ <map adobe-name="V" win-ansi="0x0056" unicode="0x0056"/>
+ <map adobe-name="W" win-ansi="0x0057" unicode="0x0057"/>
+ <map adobe-name="X" win-ansi="0x0058" unicode="0x0058"/>
+ <map adobe-name="Y" win-ansi="0x0059" unicode="0x0059"/>
+ <map adobe-name="Yacute" win-ansi="0x00DD" unicode="0x00DD"/>
+ <map adobe-name="Ydieresis" win-ansi="0x009F" unicode="0x0178"/>
+ <map adobe-name="Z" win-ansi="0x005A" unicode="0x005A"/>
+ <map adobe-name="Zcaron" win-ansi="-1" unicode="0x017D"/>
+ <map adobe-name="a" win-ansi="0x0061" unicode="0x0061"/>
+ <map adobe-name="aacute" win-ansi="0x00E1" unicode="0x00E1"/>
+ <map adobe-name="acircumflex" win-ansi="0x00E2" unicode="0x00E2"/>
+ <map adobe-name="acute" win-ansi="0x00B4" unicode="0x00B4"/>
+ <map adobe-name="adieresis" win-ansi="0x00E4" unicode="0x00E4"/>
+ <map adobe-name="ae" win-ansi="0x00E6" unicode="0x00E6"/>
+ <map adobe-name="agrave" win-ansi="0x00E0" unicode="0x00E0"/>
+ <map adobe-name="ampersand" win-ansi="0x0026" unicode="0x0026"/>
+ <map adobe-name="aring" win-ansi="0x00E5" unicode="0x00E5"/>
+ <map adobe-name="arrowboth" win-ansi="-1" unicode="0x2195"/>
+ <map adobe-name="arrowdown" win-ansi="-1" unicode="0x2193"/>
+ <map adobe-name="arrowleft" win-ansi="-1" unicode="0x2194"/>
+ <map adobe-name="arrowright" win-ansi="-1" unicode="0x2192"/>
+ <map adobe-name="arrowup" win-ansi="-1" unicode="0x2191"/>
+ <map adobe-name="asciicircum" win-ansi="0x005E" unicode="0x005E"/>
+ <map adobe-name="asciitilde" win-ansi="0x007E" unicode="0x007E"/>
+ <map adobe-name="asterisk" win-ansi="0x002A" unicode="0x002A"/>
+ <map adobe-name="at" win-ansi="0x0040" unicode="0x0040"/>
+ <map adobe-name="atilde" win-ansi="0x00E3" unicode="0x00E3"/>
+ <map adobe-name="b" win-ansi="0x0062" unicode="0x0062"/>
+ <map adobe-name="backslash" win-ansi="0x005C" unicode="0x005C"/>
+ <map adobe-name="bar" win-ansi="0x007C" unicode="0x007C"/>
+ <map adobe-name="braceleft" win-ansi="0x007B" unicode="0x007B"/>
+ <map adobe-name="braceright" win-ansi="0x007D" unicode="0x007D"/>
+ <map adobe-name="bracketleft" win-ansi="0x005B" unicode="0x005B"/>
+ <map adobe-name="bracketright" win-ansi="0x005D" unicode="0x005D"/>
+ <map adobe-name="breve" win-ansi="-1" unicode="0x02D8"/>
+ <map adobe-name="brokenbar" win-ansi="0x00A6" unicode="0x00A6"/>
+ <map adobe-name="bullet" win-ansi="0x0095" unicode="0x2022"/>
+ <map adobe-name="c" win-ansi="0x0063" unicode="0x0063"/>
+ <map adobe-name="caron" win-ansi="-1" unicode="0x02C7"/>
+ <map adobe-name="ccedilla" win-ansi="0x00E7" unicode="0x00E7"/>
+ <map adobe-name="cedilla" win-ansi="0x00B8" unicode="0x00B8"/>
+ <map adobe-name="cent" win-ansi="0x00A2" unicode="0x00A2"/>
+ <map adobe-name="circumflex" win-ansi="0x0088" unicode="0x02C6"/>
+ <map adobe-name="colon" win-ansi="0x003A" unicode="0x003A"/>
+ <map adobe-name="comma" win-ansi="0x002C" unicode="0x002C"/>
+ <map adobe-name="copyright" win-ansi="0x00A9" unicode="0x00A9"/>
+ <map adobe-name="currency" win-ansi="0x00A4" unicode="0x00A4"/>
+ <map adobe-name="d" win-ansi="0x0064" unicode="0x0064"/>
+ <map adobe-name="dagger" win-ansi="0x0086" unicode="0x2020"/>
+ <map adobe-name="daggerdbl" win-ansi="0x0087" unicode="0x2021"/>
+ <map adobe-name="degree" win-ansi="0x00B0" unicode="0x00B0"/>
+ <map adobe-name="dieresis" win-ansi="0x00A8" unicode="0x00A8"/>
+ <map adobe-name="divide" win-ansi="0x00F7" unicode="0x00F7"/>
+ <map adobe-name="dollar" win-ansi="0x0024" unicode="0x0024"/>
+ <map adobe-name="dotaccent" win-ansi="-1" unicode="0x02D9"/>
+ <map adobe-name="dotlessi" win-ansi="-1" unicode="0x0269"/>
+ <map adobe-name="e" win-ansi="0x0065" unicode="0x0065"/>
+ <map adobe-name="eacute" win-ansi="0x00E9" unicode="0x00E9"/>
+ <map adobe-name="ecircumflex" win-ansi="0x00EA" unicode="0x00EA"/>
+ <map adobe-name="edieresis" win-ansi="0x00EB" unicode="0x00EB"/>
+ <map adobe-name="egrave" win-ansi="0x00E8" unicode="0x00E8"/>
+ <map adobe-name="eight" win-ansi="0x0038" unicode="0x0038"/>
+ <map adobe-name="ellipsis" win-ansi="0x0085" unicode="0x2026"/>
+ <map adobe-name="emdash" win-ansi="0x0097" unicode="0x2014"/>
+ <map adobe-name="endash" win-ansi="0x0096" unicode="0x2013"/>
+ <map adobe-name="equal" win-ansi="0x003D" unicode="0x003D"/>
+ <map adobe-name="eth" win-ansi="0x00F0" unicode="0x00F0"/>
+ <map adobe-name="exclam" win-ansi="0x0021" unicode="0x0021"/>
+ <map adobe-name="exclamdown" win-ansi="0x00A1" unicode="0x00A1"/>
+ <map adobe-name="f" win-ansi="0x0066" unicode="0x0066"/>
+ <map adobe-name="fi" win-ansi="-1" unicode="-1"/>
+ <map adobe-name="five" win-ansi="0x0035" unicode="0x0035"/>
+ <map adobe-name="fl" win-ansi="-1" unicode="-1"/>
+ <map adobe-name="florin" win-ansi="0x0083" unicode="0x0083"/>
+ <map adobe-name="four" win-ansi="0x0034" unicode="0x0034"/>
+ <map adobe-name="fraction" win-ansi="-1" unicode="0x2044"/>
+ <map adobe-name="g" win-ansi="0x0067" unicode="0x0067"/>
+ <map adobe-name="gcaron" win-ansi="-1" unicode="0x01E7"/>
+ <map adobe-name="germandbls" win-ansi="0x00DF" unicode="0x00DF"/>
+ <map adobe-name="grave" win-ansi="0x0060" unicode="0x0060"/>
+ <map adobe-name="greater" win-ansi="0x003E" unicode="0x003E"/>
+ <map adobe-name="guillemotleft" win-ansi="0x00AB" unicode="0x00AB"/>
+ <map adobe-name="guillemotright" win-ansi="0x00BB" unicode="0x00BB"/>
+ <map adobe-name="guilsinglleft" win-ansi="0x008B" unicode="0x2039"/>
+ <map adobe-name="guilsinglright" win-ansi="0x009B" unicode="0x203A"/>
+ <map adobe-name="h" win-ansi="0x0068" unicode="0x0068"/>
+ <map adobe-name="hungarumlaut" win-ansi="-1" unicode="0x02DD"/>
+ <map adobe-name="hyphen" win-ansi="0x002D" unicode="0x002D"/>
+ <map adobe-name="i" win-ansi="0x0069" unicode="0x0069"/>
+ <map adobe-name="iacute" win-ansi="0x00ED" unicode="0x00ED"/>
+ <map adobe-name="icircumflex" win-ansi="0x00EE" unicode="0x00EE"/>
+ <map adobe-name="idieresis" win-ansi="0x00EF" unicode="0x00EF"/>
+ <map adobe-name="igrave" win-ansi="0x00EC" unicode="0x00EC"/>
+ <map adobe-name="ij" win-ansi="-1" unicode="0x0133"/>
+ <map adobe-name="j" win-ansi="0x006A" unicode="0x006A"/>
+ <map adobe-name="k" win-ansi="0x006B" unicode="0x006B"/>
+ <map adobe-name="l" win-ansi="0x006C" unicode="0x006C"/>
+ <map adobe-name="less" win-ansi="0x003C" unicode="0x003C"/>
+ <map adobe-name="lira" win-ansi="-1" unicode="0x20A4"/>
+ <map adobe-name="logicalnot" win-ansi="0x00AC" unicode="0x00AC"/>
+ <map adobe-name="lslash" win-ansi="-1" unicode="0x0142"/>
+ <map adobe-name="m" win-ansi="0x006D" unicode="0x006D"/>
+ <map adobe-name="macron" win-ansi="0x00AF" unicode="0x00AF"/>
+ <map adobe-name="minus" win-ansi="-1" unicode="0x2212"/>
+ <map adobe-name="mu" win-ansi="0x00B5" unicode="0x00B5"/>
+ <map adobe-name="multiply" win-ansi="0x00D7" unicode="0x00D7"/>
+ <map adobe-name="n" win-ansi="0x006E" unicode="0x006E"/>
+<!-- JKT: the following is not actually an adobe named character -->
+ <map adobe-name="nbsp" win-ansi="0x00A0" unicode="0x00A0"/>
+ <map adobe-name="nine" win-ansi="0x0039" unicode="0x0039"/>
+ <map adobe-name="ntilde" win-ansi="0x00F1" unicode="0x00F1"/>
+ <map adobe-name="numbersign" win-ansi="0x0023" unicode="0x0023"/>
+ <map adobe-name="o" win-ansi="0x006F" unicode="0x006F"/>
+ <map adobe-name="oacute" win-ansi="0x00F3" unicode="0x00F3"/>
+ <map adobe-name="ocircumflex" win-ansi="0x00F4" unicode="0x00F4"/>
+ <map adobe-name="odieresis" win-ansi="0x00F6" unicode="0x00F6"/>
+ <map adobe-name="oe" win-ansi="0x009C" unicode="0x0153"/>
+ <map adobe-name="ogonek" win-ansi="-1" unicode="0x02DB"/>
+ <map adobe-name="ograve" win-ansi="0x00F2" unicode="0x00F2"/>
+ <map adobe-name="one" win-ansi="0x0031" unicode="0x0031"/>
+ <map adobe-name="onehalf" win-ansi="0x00BD" unicode="0x00BD"/>
+ <map adobe-name="onequarter" win-ansi="0x00BC" unicode="0x00BC"/>
+ <map adobe-name="onesuperior" win-ansi="0x00B9" unicode="0x00B9"/>
+ <map adobe-name="ordfeminine" win-ansi="0x00AA" unicode="0x00AA"/>
+ <map adobe-name="ordmasculine" win-ansi="0x00BA" unicode="0x00BA"/>
+ <map adobe-name="oslash" win-ansi="0x00F8" unicode="0x00F8"/>
+ <map adobe-name="otilde" win-ansi="0x00F5" unicode="0x00F5"/>
+ <map adobe-name="p" win-ansi="0x0070" unicode="0x0070"/>
+ <map adobe-name="paragraph" win-ansi="0x00B6" unicode="0x00B6"/>
+ <map adobe-name="parenleft" win-ansi="0x0028" unicode="0x0028"/>
+ <map adobe-name="parenright" win-ansi="0x0029" unicode="0x0029"/>
+ <map adobe-name="percent" win-ansi="0x0025" unicode="0x0025"/>
+ <map adobe-name="period" win-ansi="0x002E" unicode="0x002E"/>
+ <map adobe-name="periodcentered" win-ansi="0x00B7" unicode="0x00B7"/>
+ <map adobe-name="perthousand" win-ansi="0x0089" unicode="0x2030"/>
+ <map adobe-name="plus" win-ansi="0x002B" unicode="0x002B"/>
+ <map adobe-name="plusminus" win-ansi="0x00B1" unicode="0x00B1"/>
+ <map adobe-name="q" win-ansi="0x0071" unicode="0x0071"/>
+ <map adobe-name="question" win-ansi="0x003F" unicode="0x003F"/>
+ <map adobe-name="questiondown" win-ansi="0x00BF" unicode="0x00BF"/>
+ <map adobe-name="quotedbl" win-ansi="0x0022" unicode="0x0022"/>
+ <map adobe-name="quotedblbase" win-ansi="0x0084" unicode="0x201E"/>
+ <map adobe-name="quotedblleft" win-ansi="0x0093" unicode="0x201C"/>
+ <map adobe-name="quotedblright" win-ansi="0x0094" unicode="0x201D"/>
+ <map adobe-name="quoteleft" win-ansi="0x0091" unicode="0x2018"/>
+ <map adobe-name="quoteright" win-ansi="0x0092" unicode="0x2019"/>
+ <map adobe-name="quotesinglbase" win-ansi="0x0082" unicode="0x201A"/>
+ <map adobe-name="quotesingle" win-ansi="0x0027" unicode="0x0027"/>
+ <map adobe-name="r" win-ansi="0x0072" unicode="0x0072"/>
+ <map adobe-name="registered" win-ansi="0x00AE" unicode="0x00AE"/>
+ <map adobe-name="ring" win-ansi="0x00B0" unicode="0x00B0"/>
+ <map adobe-name="s" win-ansi="0x0073" unicode="0x0073"/>
+ <map adobe-name="scaron" win-ansi="0x009A" unicode="0x0161"/>
+ <map adobe-name="scedilla" win-ansi="-1" unicode="0x015F"/>
+ <map adobe-name="section" win-ansi="0x00A7" unicode="0x00A7"/>
+ <map adobe-name="semicolon" win-ansi="0x003B" unicode="0x003B"/>
+ <map adobe-name="seven" win-ansi="0x0037" unicode="0x0037"/>
+ <map adobe-name="six" win-ansi="0x0036" unicode="0x0036"/>
+ <map adobe-name="slash" win-ansi="0x002F" unicode="0x002F"/>
+ <map adobe-name="space" win-ansi="0x0020" unicode="0x0020"/>
+ <map adobe-name="sterling" win-ansi="0x00A3" unicode="0x00A3"/>
+ <map adobe-name="t" win-ansi="0x0074" unicode="0x0074"/>
+ <map adobe-name="thorn" win-ansi="0x00FE" unicode="0x00FE"/>
+ <map adobe-name="three" win-ansi="0x0033" unicode="0x0033"/>
+ <map adobe-name="threequarters" win-ansi="0x00BE" unicode="0x00BE"/>
+ <map adobe-name="threesuperior" win-ansi="0x00B3" unicode="0x00B3"/>
+ <map adobe-name="tilde" win-ansi="0x0098" unicode="0x02DC"/>
+ <map adobe-name="trademark" win-ansi="0x0099" unicode="0x2122"/>
+ <map adobe-name="two" win-ansi="0x0032" unicode="0x0032"/>
+ <map adobe-name="twosuperior" win-ansi="0x00B2" unicode="0x00B2"/>
+ <map adobe-name="u" win-ansi="0x0075" unicode="0x0075"/>
+ <map adobe-name="uacute" win-ansi="0x00FA" unicode="0x00FA"/>
+ <map adobe-name="ucircumflex" win-ansi="0x00FB" unicode="0x00FB"/>
+ <map adobe-name="udieresis" win-ansi="0x00FC" unicode="0x00FC"/>
+ <map adobe-name="ugrave" win-ansi="0x00F9" unicode="0x00F9"/>
+ <map adobe-name="underscore" win-ansi="0x005F" unicode="0x005F"/>
+ <map adobe-name="v" win-ansi="0x0076" unicode="0x0076"/>
+ <map adobe-name="w" win-ansi="0x0077" unicode="0x0077"/>
+ <map adobe-name="x" win-ansi="0x0078" unicode="0x0078"/>
+ <map adobe-name="y" win-ansi="0x0079" unicode="0x0079"/>
+ <map adobe-name="yacute" win-ansi="0x00FD" unicode="0x00FD"/>
+ <map adobe-name="ydieresis" win-ansi="0x00FF" unicode="0x00FF"/>
+ <map adobe-name="yen" win-ansi="0x00A5" unicode="0x00A5"/>
+ <map adobe-name="z" win-ansi="0x007A" unicode="0x007A"/>
+ <map adobe-name="zcaron" win-ansi="-1" unicode="0x017E"/>
+ <map adobe-name="zero" win-ansi="0x0030" unicode="0x0030"/>
+</font-mappings>
+
+<!-- I couldn't find the following characters in the unicode tables -->
+
+<!--
+ <map adobe-name="center" win-ansi="-1" unicode=""/>
+ <map adobe-name="dectab" win-ansi="-1" unicode=""/>
+ <map adobe-name="down" win-ansi="-1" unicode=""/>
+ <map adobe-name="format" win-ansi="-1" unicode=""/>
+ <map adobe-name="graybox" win-ansi="-1" unicode=""/>
+ <map adobe-name="indent" win-ansi="-1" unicode=""/>
+ <map adobe-name="largebullet" win-ansi="-1" unicode=""/>
+ <map adobe-name="left" win-ansi="-1" unicode=""/>
+ <map adobe-name="ll" win-ansi="-1" unicode=""/>
+ <map adobe-name="LL" win-ansi="-1" unicode=""/>
+ <map adobe-name="merge" win-ansi="-1" unicode=""/>
+ <map adobe-name="notegraphic" win-ansi="-1" unicode=""/>
+ <map adobe-name="overscore" win-ansi="-1" unicode=""/>
+ <map adobe-name="prescription" win-ansi="-1" unicode=""/>
+ <map adobe-name="return" win-ansi="-1" unicode=""/>
+ <map adobe-name="square" win-ansi="-1" unicode=""/>
+ <map adobe-name="stop" win-ansi="-1" unicode=""/>
+ <map adobe-name="tab" win-ansi="-1" unicode=""/>
+ <map adobe-name="up" win-ansi="-1" unicode=""/>
+ <map adobe-name="zer" win-ansi="-1" unicode=""/>
+
+-->
\ No newline at end of file
--- /dev/null
+<transform xmlns="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xt="http://www.jclark.com/xt" extension-element-prefixes="xt"
+ version="1.0">
+<template match="font-mappings">
+<xt:document href="org/apache/xml/fop/render/pdf/CodePointMapping.java">
+package org.apache.xml.fop.render.pdf;
+
+public class CodePointMapping {
+ public static char[] map;
+
+ static {
+ map = new char[65536];
+<for-each select="map[@unicode!='-1' and @win-ansi!='-1']"> map[<value-of select="@unicode"/>] = <value-of select="@win-ansi"/>;
+</for-each>
+ }
+}
+</xt:document>
+</template>
+</transform>
--- /dev/null
+<transform xmlns="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xt="http://www.jclark.com/xt" extension-element-prefixes="xt"
+ version="1.0">
+<template match="font-metrics">
+<variable name="class-name" select="class-name"/>
+<xt:document method="text" href="org/apache/xml/fop/render/pdf/fonts/{$class-name}.java">
+package org.apache.xml.fop.render.pdf.fonts;
+
+import org.apache.xml.fop.render.pdf.Font;
+
+public class <value-of select="class-name"/> extends Font {
+ private final static String fontName = "<value-of select="font-name"/>";
+ private final static String encoding = "<value-of select="encoding"/>";
+ private final static int capHeight = <value-of select="cap-height"/>;
+ private final static int xHeight = <value-of select="x-height"/>;
+ private final static int ascender = <value-of select="ascender"/>;
+ private final static int descender = <value-of select="descender"/>;
+ private final static int[] width;
+
+ static {
+ width = new int[256];
+<for-each select="widths/char"><variable name="char-name" select="@name"/><variable name="char-num" select="document('charlist.xml')/font-mappings/map[@adobe-name=$char-name]/@win-ansi"/><if test="$char-num!='-1'"> width[<value-of select="$char-num"/>] = <value-of select="@width"/>;
+</if></for-each>
+ }
+
+ public String encoding() {
+ return encoding;
+ }
+
+ public String fontName() {
+ return fontName;
+ }
+
+ public int getAscender() {
+ return ascender;
+ }
+
+ public int getCapHeight() {
+ return capHeight;
+ }
+
+ public int getDescender() {
+ return descender;
+ }
+
+ public int getXHeight() {
+ return xHeight;
+ }
+
+ public int width(int i) {
+ return width[i];
+ }
+}
+</xt:document>
+</template>
+</transform>
--- /dev/null
+<property-list>
+ <property>
+ <name>font-size</name>
+ <class-name>FontSize</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>12pt</default>
+ </property>
+ <property>
+ <name>start-indent</name>
+ <class-name>StartIndent</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>font-style</name>
+ <class-name>FontStyle</class-name>
+ <inherited>true</inherited>
+ <datatype>String</datatype>
+ <default>normal</default>
+ </property>
+ <property>
+ <name>flow-name</name>
+ <class-name>FlowName</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>page-master-first</name>
+ <class-name>PageMasterFirst</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>page-master-odd</name>
+ <class-name>PageMasterOdd</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>extent</name>
+ <class-name>Extent</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>font-weight</name>
+ <class-name>FontWeight</class-name>
+ <inherited>true</inherited>
+ <datatype>String</datatype>
+ <default>normal</default>
+ </property>
+ <property>
+ <name>margin-left</name>
+ <class-name>MarginLeft</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>font-family</name>
+ <class-name>FontFamily</class-name>
+ <inherited>true</inherited>
+ <datatype>String</datatype>
+ <default>sans-serif</default>
+ </property>
+ <property>
+ <name>page-master-even</name>
+ <class-name>PageMasterEven</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>margin-top</name>
+ <class-name>MarginTop</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>page-master-name</name>
+ <class-name>PageMasterName</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>end-indent</name>
+ <class-name>EndIndent</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>color</name>
+ <class-name>Color</class-name>
+ <inherited>true</inherited>
+ <datatype>ColorType</datatype>
+ <default>black</default>
+ </property>
+ <property>
+ <name>margin-bottom</name>
+ <class-name>MarginBottom</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>page-height</name>
+ <class-name>PageHeight</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>11in</default>
+ </property>
+ <property>
+ <name>space-before.optimum</name>
+ <class-name>SpaceBeforeOptimum</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>provisional-label-separation</name>
+ <class-name>ProvisionalLabelSeparation</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>6pt</default>
+ </property>
+ <property>
+ <name>id</name>
+ <class-name>ID</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>margin-right</name>
+ <class-name>MarginRight</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>rule-thickness</name>
+ <class-name>RuleThickness</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>1pt</default>
+ </property>
+ <property>
+ <name>page-width</name>
+ <class-name>PageWidth</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>8in</default>
+ </property>
+ <property>
+ <name>page-master-repeating</name>
+ <class-name>PageMasterRepeating</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>provisional-distance-between-starts</name>
+ <class-name>ProvisionalDistanceBetweenStarts</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>24pt</default>
+ </property>
+ <property>
+ <name>line-height</name>
+ <class-name>LineHeight</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>12pt</default>
+ </property>
+ <property>
+ <name>space-after.optimum</name>
+ <class-name>SpaceAfterOptimum</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>text-align</name>
+ <class-name>TextAlign</class-name>
+ <inherited>true</inherited>
+ <datatype>
+ <enumeration>
+ <value const="CENTERED">centered</value>
+ <value const="END">end</value>
+ <value const="START">start</value>
+ <value const="JUSTIFIED">justified</value>
+ </enumeration>
+ </datatype>
+ <default>start</default>
+ </property>
+ <property>
+ <name>white-space-treatment</name>
+ <class-name>WhiteSpaceTreatment</class-name>
+ <inherited>true</inherited>
+ <datatype>
+ <enumeration>
+ <value const="PRESERVE">preserve</value>
+ <value const="COLLAPSE">collapse</value>
+ <value const="IGNORE">ignore</value>
+ </enumeration>
+ </datatype>
+ <default>collapse</default>
+ </property>
+ <property>
+ <name>break-after</name>
+ <class-name>BreakAfter</class-name>
+ <inherited>false</inherited>
+ <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>
+ </datatype>
+ <default>auto</default>
+ </property>
+ <property>
+ <name>break-before</name>
+ <class-name>BreakBefore</class-name>
+ <inherited>false</inherited>
+ <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>
+ </datatype>
+ <default>auto</default>
+ </property>
+ <property>
+ <name>wrap-option</name>
+ <class-name>WrapOption</class-name>
+ <inherited>true</inherited>
+ <datatype>
+ <enumeration>
+ <value const="WRAP">wrap</value>
+ <value const="NO_WRAP">no-wrap</value>
+ </enumeration>
+ </datatype>
+ <default>wrap</default>
+ </property>
+ <property>
+ <name>text-align-last</name>
+ <class-name>TextAlignLast</class-name>
+ <inherited>true</inherited>
+ <datatype>
+ <enumeration>
+ <value const="CENTERED">centered</value>
+ <value const="END">end</value>
+ <value const="START">start</value>
+ <value const="JUSTIFIED">justified</value>
+ </enumeration>
+ </datatype>
+ <default>start</default>
+ <derive from="text-align">
+ <if match="TextAlign.JUSTIFIED">START</if>
+ <if match="TextAlign.END">END</if>
+ <if match="TextAlign.START">START</if>
+ <if match="TextAlign.CENTERED">CENTERED</if>
+ </derive>
+ </property>
+ <property>
+ <name>line-height</name>
+ <class-name>LineHeight</class-name>
+ <inherited>true</inherited>
+ <datatype>Length</datatype>
+ <default>normal</default>
+ <make>
+ <to-double/>
+ <if match="normal">1.2,propertyList.get("font-size")</if>
+ <else-if-number>d,propertyList.get("font-size")</else-if-number>
+ <else>value</else>
+ </make>
+ </property>
+ <property>
+ <name>text-indent</name>
+ <class-name>TextIndent</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+ <property>
+ <name>href</name>
+ <class-name>HRef</class-name>
+ <inherited>false</inherited>
+ <datatype>String</datatype>
+ <default></default>
+ </property>
+ <property>
+ <name>column-width</name>
+ <class-name>ColumnWidth</class-name>
+ <inherited>false</inherited>
+ <datatype>Length</datatype>
+ <default>0pt</default>
+ </property>
+</property-list>
+
--- /dev/null
+<transform xmlns="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xt="http://www.jclark.com/xt" element-prefixes="xt"
+ version="1.0">
+<template match="property" priority="-1">
+<variable name="classname" select="class-name"/>
+<xt:document method="text" href="org/apache/xml/fop/fo/properties/{$classname}.java">
+package org.apache.xml.fop.fo.properties;
+
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class <value-of select="class-name"/> extends Property {
+
+ public static class Maker extends Property.Maker {
+ public boolean isInherited() { return <value-of select="inherited"/>; }
+
+ public Property make(PropertyList propertyList, String value) throws FOPException {
+<choose>
+<when test="make">
+ <variable name="datatype" select="datatype"/>
+ <value-of select="$datatype"/> v;
+<if test="make/to-double">
+ double d = toDouble(value);
+</if>
+<for-each select="make/if">
+ if (value.equals("<value-of select="@match"/>")) {
+ v = new <value-of select="$datatype"/>(<value-of select="."/>);
+ }
+</for-each>
+<for-each select="make/else-if-number">
+ else if (!Double.isNaN(d)) {
+ v = new <value-of select="$datatype"/>( <value-of select="."/>);
+ }
+</for-each>
+ else {
+ v = new <value-of select="datatype"/>(<value-of select="make/else"/>);
+ }
+ return new <value-of select="class-name"/>(propertyList, v);
+</when>
+<otherwise>
+ return new <value-of select="class-name"/>(propertyList, new <value-of select="datatype"/>(value));
+</otherwise>
+</choose>
+ }
+
+ public Property make(PropertyList propertyList) throws FOPException {
+ return make(propertyList, "<value-of select="default"/>");
+ }
+ }
+
+ public static Property.Maker maker() {
+ return new <value-of select="class-name"/>.Maker();
+ }
+
+ private <value-of select="datatype"/> value;
+
+ public <value-of select="class-name"/>(PropertyList propertyList, <value-of select="datatype"/> explicitValue) {
+ this.propertyList = propertyList;
+ this.value = explicitValue;
+ }
+
+ public <value-of select="datatype"/> get<value-of select="datatype"/>() {
+ return this.value;
+ }
+
+}
+</xt:document>
+</template>
+
+<template match="property[datatype/enumeration]">
+<variable name="classname" select="class-name"/>
+<xt:document method="text" href="org/apache/xml/fop/fo/properties/{$classname}.java">
+package org.apache.xml.fop.fo.properties;
+
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class <value-of select="class-name"/> extends Property {
+<for-each select="datatype/enumeration/value">
+ public final static int <value-of select="@const"/> = <number/>;</for-each>
+
+ public static class Maker extends Property.Maker {
+ public boolean isInherited() { return <value-of select="inherited"/>; }
+
+ public Property make(PropertyList propertyList, String value) throws FOPException {
+ int v;
+ <for-each select="datatype/enumeration/value">
+ if (value.equals("<value-of select="."/>")) { v = <value-of select="@const"/>; }
+ else</for-each>
+ {
+ System.err.println("WARNING: Unknown value for <value-of select="name"/>: " + value);
+ return make(propertyList, "<value-of select="default"/>");
+ }
+ return new <value-of select="class-name"/>(propertyList, v);
+ }
+
+ public Property make(PropertyList propertyList) throws FOPException {
+ return make(propertyList, "<value-of select="default"/>");
+ }
+ <if test="derive">
+ public Property compute(PropertyList propertyList) {
+ Property computedProperty = null;
+ Property correspondingProperty = propertyList.get("<value-of select="derive/@from"/>");
+ if (correspondingProperty != null) {
+ int correspondingValue = correspondingProperty.getEnum();
+ <for-each select="derive/if">
+ if (correspondingValue == <value-of select="@match"/>)
+ computedProperty = new <value-of select="$classname"/>(propertyList, <value-of select="."/>);
+ else</for-each>
+ ;
+ }
+ return computedProperty;
+ }
+ </if>
+ }
+
+ public static Property.Maker maker() {
+ return new <value-of select="class-name"/>.Maker();
+ }
+
+ private int value;
+
+ public <value-of select="class-name"/>(PropertyList propertyList, int explicitValue) {
+ this.propertyList = propertyList;
+ this.value = explicitValue;
+ }
+
+ public int getEnum() {
+ return this.value;
+ }
+
+}
+</xt:document>
+</template>
+</transform>
--- /dev/null
+
+
+BASEDIR:=..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=apache
+
+all: allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+
+
+BASEDIR:=../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=xml
+
+all: allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+
+
+BASEDIR:=../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=apps \
+ datatypes \
+ fo \
+ image \
+ layout \
+ pdf \
+ render \
+ svg
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.apps;
+
+// SAX
+import org.xml.sax.Parser;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+// Java
+import java.io.FileReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URL;
+
+/**
+ * mainline class.
+ *
+ * Gets input and output filenames from the command line.
+ * Creates a SAX Parser (defaulting to XP).
+ *
+ */
+public class CommandLine {
+
+ /**
+ * creates a SAX parser, using the value of org.xml.sax.parser
+ * defaulting to com.jclark.xml.sax.Driver
+ *
+ * @return the created SAX parser
+ */
+ static Parser createParser() {
+ String parserClassName =
+ System.getProperty("org.xml.sax.parser");
+ if (parserClassName == null) {
+ parserClassName = "com.jclark.xml.sax.Driver";
+ }
+ 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");
+ }
+ }
+
+ /**
+ * mainline method
+ *
+ * first command line argument is input file
+ * second command line argument is output file
+ *
+ * @param command line arguments
+ */
+ public static void main(String[] args) {
+ String version = Version.getVersion();
+ System.err.println(version);
+
+ if (args.length != 2) {
+ System.err.println("usage: java "
+ + "org.apache.xml.fop.apps.CommandLine "
+ + "formatting-object-file pdf-file");
+ System.exit(1);
+ }
+
+ Parser parser = createParser();
+
+ if (parser == null) {
+ System.err.println("ERROR: Unable to create SAX parser");
+ System.exit(1);
+ }
+
+ try {
+ Driver driver = new Driver();
+ driver.setRenderer("org.apache.xml.fop.render.pdf.PDFRenderer", version);
+ driver.addElementMapping("org.apache.xml.fop.fo.StandardElementMapping");
+ driver.addElementMapping("org.apache.xml.fop.svg.SVGElementMapping");
+ driver.setWriter(new PrintWriter(new FileWriter(args[1])));
+ driver.buildFOTree(parser, fileInputSource(args[0]));
+ driver.format();
+ driver.render();
+ } catch (Exception e) {
+ System.err.println("FATAL ERROR: " + e.getMessage());
+ System.exit(1);
+ }
+ }
+}
--- /dev/null
+package org.apache.xml.fop.apps;
+
+// FOP
+import org.apache.xml.fop.fo.FOTreeBuilder;
+import org.apache.xml.fop.fo.ElementMapping;
+import org.apache.xml.fop.layout.AreaTree;
+import org.apache.xml.fop.layout.FontInfo;
+import org.apache.xml.fop.render.Renderer;
+
+// 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.AttributeListImpl;
+
+// Java
+import java.io.PrintWriter;
+import java.io.IOException;
+
+public class Driver {
+
+ protected FOTreeBuilder treeBuilder;
+ protected AreaTree areaTree;
+ protected Renderer renderer;
+ protected PrintWriter writer;
+
+ public Driver() {
+ this.treeBuilder = new FOTreeBuilder();
+ }
+
+ public void setRenderer(Renderer renderer) {
+ this.renderer = renderer;
+ }
+
+ public void setRenderer(String rendererClassName, String producer) {
+ this.renderer = createRenderer(rendererClassName);
+ this.renderer.setProducer(producer);
+ }
+
+ protected Renderer createRenderer(String rendererClassName) {
+ System.err.println("using renderer " + rendererClassName);
+
+ try {
+ return (Renderer)
+ Class.forName(rendererClassName).newInstance();
+ } catch (ClassNotFoundException e) {
+ System.err.println("Could not find " + rendererClassName);
+ } catch (InstantiationException e) {
+ System.err.println("Could not instantiate "
+ + rendererClassName);
+ } catch (IllegalAccessException e) {
+ System.err.println("Could not access " + rendererClassName);
+ } catch (ClassCastException e) {
+ System.err.println(rendererClassName + " is not a renderer");
+ }
+ return null;
+ }
+
+ public void addElementMapping(ElementMapping mapping) {
+ mapping.addToBuilder(this.treeBuilder);
+ }
+
+ public void addElementMapping(String mappingClassName) {
+ createElementMapping(mappingClassName).addToBuilder(this.treeBuilder);
+ }
+
+ protected ElementMapping createElementMapping(String mappingClassName) {
+ System.err.println("using element mapping " + mappingClassName);
+
+ try {
+ return (ElementMapping)
+ Class.forName(mappingClassName).newInstance();
+ } catch (ClassNotFoundException e) {
+ System.err.println("Could not find " + mappingClassName);
+ } catch (InstantiationException e) {
+ System.err.println("Could not instantiate "
+ + mappingClassName);
+ } catch (IllegalAccessException e) {
+ System.err.println("Could not access " + mappingClassName);
+ } catch (ClassCastException e) {
+ System.err.println(mappingClassName + " is not an element mapping");
+ }
+ return null;
+ }
+
+ public DocumentHandler getDocumentHandler() {
+ return this.treeBuilder;
+ }
+
+ 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());
+ }
+ }
+
+ public void buildFOTree(Document document)
+ throws FOPException {
+
+ /* most of this code is modified from John Cowan's */
+
+ Node currentNode;
+ AttributeListImpl currentAtts;
+
+ /* temporary array for making Strings into character arrays */
+ char[] array = null;
+
+ currentAtts = new AttributeListImpl();
+
+ /* 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());
+ }
+ }
+
+ public void setWriter(PrintWriter writer) {
+ this.writer = writer;
+ }
+
+ 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);
+ }
+
+ public void render()
+ throws IOException {
+ this.renderer.render(areaTree, this.writer);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.apps;
+
+/** not implemented yet */
+public interface ErrorHandler {}
--- /dev/null
+package org.apache.xml.fop.apps;
+
+/**
+ * Exception thrown when FOP has a problem
+ */
+public class FOPException extends Exception {
+
+ /**
+ * create a new FOP Exception
+ *
+ * @param message descriptive message
+ */
+ public FOPException(String message) {
+ super(message);
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=CommandLine.java \
+ Driver.java \
+ ErrorHandler.java \
+ FOPException.java \
+ Version.java \
+ XTCommandLine.java
+
+
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.apps;
+
+/**
+ * class representing the version of FOP.
+ *
+ * added at the request of Stefano Mazzocchi for use by Cocoon.
+ */
+public class Version {
+
+ /**
+ * get the version of FOP
+ *
+ * @return the version string
+ */
+ public static String getVersion() {
+ return "FOP 0.12.0pre5";
+ }
+}
--- /dev/null
+package org.apache.xml.fop.apps;
+
+import org.apache.xml.fop.render.pdf.PDFRenderer;
+import org.apache.xml.fop.fo.StandardElementMapping;
+import org.apache.xml.fop.svg.SVGElementMapping;
+
+// James Clark
+import com.jclark.xsl.sax.XSLProcessor;
+import com.jclark.xsl.sax.XSLProcessorImpl;
+
+// SAX
+import org.xml.sax.Parser;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+// Java
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URL;
+
+/**
+ * mainline class for full transformation (via XT) + formatting/rendering.
+ *
+ * gets input, stylesheet and output filenames from the command line
+ * creates an implementation of XSLProcessor, passing it the stylesheet
+ * treats XSLProcessor as SAXParser
+ *
+ */
+public class XTCommandLine extends CommandLine {
+
+ /**
+ * mainline method.
+ *
+ * first command line argument is XML input file
+ * second command line argument is XSL stylesheet file
+ * third command line argument is outputfile
+ */
+ public static void main(String[] args) {
+ String version = Version.getVersion();
+ System.err.println(version);
+
+ if (args.length != 3) {
+ System.err.println("usage: java org.apache.xml.fop.apps.XTCommandLine xml-file xsl-stylesheet pdf-file");
+ System.exit(1);
+ }
+
+ Parser parser = createParser();
+
+ if (parser == null) {
+ System.err.println("ERROR: Unable to create SAX parser");
+ System.exit(1);
+ }
+
+ XSLProcessor xslProcessor = new XSLProcessorImpl();
+ xslProcessor.setParser(parser);
+
+ try {
+ xslProcessor.loadStylesheet(fileInputSource(args[1]));
+
+ Driver driver = new Driver();
+ driver.setRenderer("org.apache.xml.fop.render.pdf.PDFRenderer",
+ version);
+ driver.addElementMapping("org.apache.xml.fop.fo.StandardElementMapping");
+ driver.addElementMapping("org.apache.xml.fop.svg.SVGElementMapping");
+ driver.setWriter(new PrintWriter(new FileWriter(args[2])));
+ driver.buildFOTree(parser, fileInputSource(args[0]));
+ driver.format();
+ driver.render();
+ } catch (Exception e) {
+ System.err.println("FATAL ERROR: " + e.getMessage());
+ System.exit(1);
+ }
+ }
+}
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.apps Package</TITLE>
+<BODY>
+<P>Application classes used for running FOP both on the command line and
+embedded in other applications.</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+package org.apache.xml.fop.datatypes;
+
+/**
+ * a colour quantity in XSL
+ */
+public class ColorType {
+
+ /** the red component */
+ protected float red;
+
+ /** the green component */
+ protected float green;
+
+ /** the blue component */
+ protected float blue;
+
+ /**
+ * set the colour given a particular String specifying either a
+ * colour name or #RGB or #RRGGBB
+ */
+ public ColorType (String value) {
+ if (value.startsWith("#")) {
+ try {
+ if (value.length()==4) {
+ // note: divide by 15 so F = FF = 1 and so on
+ this.red = Integer.parseInt(value.substring(1,2),16)/15f;
+ this.green = Integer.parseInt(value.substring(2,3),16)/15f;
+ this.blue = Integer.parseInt(value.substring(3),16)/15f;
+ } else if (value.length()==7) {
+ // note: divide by 255 so FF = 1
+ this.red = Integer.parseInt(value.substring(1,3),16)/255f;
+ this.green = Integer.parseInt(value.substring(3,5),16)/255f;
+ this.blue = Integer.parseInt(value.substring(5),16)/255f;
+ } else {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 0;
+ System.err.println("ERROR: unknown colour format. Must be #RGB or #RRGGBB");
+ }
+ } catch (Exception e) {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 0;
+ System.err.println("ERROR: unknown colour format. Must be #RGB or #RRGGBB");
+ }
+ } else {
+ if (value.toLowerCase().equals("black")) {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("green")) {
+ this.red = 0;
+ this.green = 0.5f;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("silver")) {
+ this.red = 0.75f;
+ this.green = 0.75f;
+ this.blue = 0.75f;
+ } else if (value.toLowerCase().equals("lime")) {
+ this.red = 0;
+ this.green = 1;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("gray")) {
+ this.red = 0.5f;
+ this.green = 0.5f;
+ this.blue = 0.5f;
+ } else if (value.toLowerCase().equals("olive")) {
+ this.red = 0.5f;
+ this.green = 0.5f;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("white")) {
+ this.red = 1;
+ this.green = 1;
+ this.blue = 1;
+ } else if (value.toLowerCase().equals("yellow")) {
+ this.red = 1;
+ this.green = 1;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("maroon")) {
+ this.red = 0.5f;
+ this.green = 0;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("navy")) {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 0.5f;
+ } else if (value.toLowerCase().equals("red")) {
+ this.red = 1;
+ this.green = 0;
+ this.blue = 0;
+ } else if (value.toLowerCase().equals("blue")) {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 1;
+ } else if (value.toLowerCase().equals("purple")) {
+ this.red = 0.5f;
+ this.green = 0;
+ this.blue = 0.5f;
+ } else if (value.toLowerCase().equals("teal")) {
+ this.red = 0;
+ this.green = 0.5f;
+ this.blue = 0.5f;
+ } else if (value.toLowerCase().equals("fuchsia")) {
+ this.red = 1;
+ this.green = 0;
+ this.blue = 1;
+ } else if (value.toLowerCase().equals("aqua")) {
+ this.red = 0;
+ this.green = 1;
+ this.blue = 1;
+ } else if (value.toLowerCase().equals("orange")) {
+ // for compatibility with passiveTex
+ this.red = 0.7f;
+ this.green = 0.5f;
+ this.blue = 0;
+ } else {
+ this.red = 0;
+ this.green = 0;
+ this.blue = 0;
+ System.err.println("ERROR: unknown colour name: " + value);
+ }
+ }
+ }
+
+ public float blue() {
+ return this.blue;
+ }
+
+ public float green() {
+ return this.green;
+ }
+
+ public float red() {
+ return this.red;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.datatypes;
+
+import org.apache.xml.fop.fo.Property;
+
+/**
+ * a length quantity in XSL
+ */
+public class Length {
+
+ protected int millipoints = 0;
+
+ protected double fontsize = 12;
+
+ /**
+ * set the length given a particular String specifying length and units
+ */
+ public Length (String len) {
+ convert(len);
+ }
+
+ /**
+ * set the length given a particular String specifying length and units,
+ * and the font-size (necessary for an em)
+ */
+ public Length (String len, int fontsize) {
+ this.fontsize = fontsize;
+ convert(len);
+ }
+
+ /**
+ * set the length given a particular multiplier and a length property
+ */
+ public Length (double multiplier, Property property) {
+ this.millipoints = (int)(multiplier * property.getLength().mvalue());
+ }
+
+ protected void convert(String len) {
+ /* convert the given length to a dimensionless integer representing
+ points. */
+
+ int assumed_resolution = 1; // points/pixel
+
+ int l = len.length();
+
+ if (l == 0) {
+ System.err.println("WARNING: empty length");
+ this.millipoints = 0;
+ } else {
+ String unit = len.substring(l-2);
+ double dvalue =
+ Double.valueOf(len.substring(0,(l-2))).doubleValue();
+
+ if (unit.equals("in"))
+ dvalue = dvalue * 72;
+ else if (unit.equals("cm"))
+ dvalue = dvalue * 28.35;
+ else if (unit.equals("mm"))
+ dvalue = dvalue * 2.84;
+ else if (unit.equals("pt"))
+ dvalue = dvalue;
+ else if (unit.equals("pc"))
+ dvalue = dvalue * 12;
+ else if (unit.equals("em"))
+ dvalue = dvalue * fontsize;
+ else if (unit.equals("px"))
+ dvalue = dvalue * assumed_resolution;
+ else {
+ dvalue = 0;
+ System.err.println("ERROR: unknown length units in "
+ + len);
+ }
+
+ this.millipoints = (int) (dvalue * 1000);
+ }
+ }
+
+ /**
+ * return the length in 1/1000ths of a point
+ */
+ public int mvalue() {
+ return millipoints;
+ }
+
+ public String toString() {
+ String s = millipoints + "mpt";
+ return s;
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=ColorType.java \
+ Length.java
+
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.datatypes Package</TITLE>
+<BODY>
+<P>XSL Datatypes</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+package org.apache.xml.fop.fo;
+
+public interface ElementMapping {
+
+ public void addToBuilder(FOTreeBuilder builder);
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+// FOP
+import org.apache.xml.fop.apps.FOPException;
+import org.apache.xml.fop.layout.Area;
+
+// Java
+import java.util.Vector;
+
+/**
+ * base class for nodes in the formatting object tree
+ */
+abstract public class FONode {
+
+ protected FObj parent;
+ protected Vector children = new Vector();
+
+ /** value of marker before layout begins */
+ public final static int START = -1000;
+
+ /** value of marker after break-after */
+ public final static int BREAK_AFTER = -1001;
+
+ /**
+ * where the layout was up to.
+ * for FObjs it is the child number
+ * for FOText it is the character number
+ */
+ protected int marker = START;
+
+ protected boolean isInLabel = false;
+ protected boolean isInListBody = false;
+ protected boolean isInTableCell = false;
+
+ protected int bodyIndent;
+ protected int distanceBetweenStarts;
+ protected int labelSeparation;
+
+ protected int forcedStartOffset = 0;
+ protected int forcedWidth = 0;
+
+ protected FONode(FObj parent) {
+ this.parent = parent;
+ }
+
+ public void setIsInLabel() {
+ this.isInLabel = true;
+ }
+
+ public void setIsInListBody() {
+ this.isInListBody = true;
+ }
+
+ public void setIsInTableCell() {
+ this.isInTableCell = true;
+ }
+
+ public void setDistanceBetweenStarts(int distance) {
+ this.distanceBetweenStarts = distance;
+ }
+
+ public void setLabelSeparation(int separation) {
+ this.labelSeparation = separation;
+ }
+
+ public void setBodyIndent(int indent) {
+ this.bodyIndent = indent;
+ }
+
+ public void forceStartOffset(int offset) {
+ this.forcedStartOffset = offset;
+ }
+
+ public void forceWidth(int width) {
+ this.forcedWidth = width;
+ }
+
+ public void resetMarker() {
+ this.marker = START;
+ int numChildren = this.children.size();
+ for (int i = 0; i < numChildren; i++) {
+ ((FONode) children.elementAt(i)).resetMarker();
+ }
+ }
+
+ protected void addChild(FONode child) {
+ children.addElement(child);
+ }
+
+ public FObj getParent() {
+ return this.parent;
+ }
+
+ /* status */
+ /* layout was fully completed */
+ public final static int OK = 1;
+ /* none of the formatting object could be laid out because the
+ containing area was full (end of page) */
+ public final static int AREA_FULL_NONE = 2;
+ /* some of the formatting object could not be laid out because the
+ containing area was full (end of page) */
+ public final static int AREA_FULL_SOME = 3;
+ /* force page break */
+ public final static int FORCE_PAGE_BREAK = 4;
+ public final static int FORCE_PAGE_BREAK_EVEN = 5;
+ public final static int FORCE_PAGE_BREAK_ODD = 6;
+
+ abstract public int layout(Area area)
+ throws FOPException;
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+// FOP
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * a text node in the formatting object tree
+ */
+public class FOText extends FONode {
+
+ protected char[] ca;
+ protected int start;
+ protected int length;
+
+ FontState fs;
+ float red;
+ float green;
+ float blue;
+ int wrapOption;
+ int whiteSpaceTreatment;
+
+ protected FOText(char[] chars, int s, int e, FObj parent) {
+ super(parent);
+ this.start = 0;
+ this.ca = new char[e - s];
+ for (int i = s; i < e; i++)
+ this.ca[i - s] = chars[i];
+ this.length = e - s;
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (!(area instanceof BlockArea)) {
+ System.err.println("WARNING: text outside block area" + new String(ca, start, length));
+ return OK;
+ }
+ if (this.marker == START) {
+ String fontFamily =
+ this.parent.properties.get("font-family").getString();
+ String fontStyle =
+ this.parent.properties.get("font-style").getString();
+ String fontWeight =
+ this.parent.properties.get("font-weight").getString();
+ int fontSize =
+ this.parent.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily, fontStyle,
+ fontWeight, fontSize);
+
+ ColorType c =
+ this.parent.properties.get("color").getColorType();
+ this.red = c.red();
+ this.green = c.green();
+ this.blue = c.blue();
+
+ this.wrapOption =
+ this.parent.properties.get("wrap-option").getEnum();
+ this.whiteSpaceTreatment =
+ this.parent.properties.get("white-space-treatment").getEnum();
+
+ this.marker = this.start;
+ }
+ int orig_start = this.marker;
+ this.marker = ((BlockArea) area).addText(fs, red, green, blue,
+ wrapOption,
+ whiteSpaceTreatment,
+ ca, this.marker, length);
+ if (this.marker == -1) {
+ return OK;
+ } else if (this.marker != orig_start) {
+ return AREA_FULL_SOME;
+ } else {
+ return AREA_FULL_NONE;
+ }
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+// FOP
+import org.apache.xml.fop.layout.AreaTree;
+import org.apache.xml.fop.apps.FOPException;
+import org.apache.xml.fop.fo.pagination.Root;
+
+// SAX
+import org.xml.sax.HandlerBase;
+import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
+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 FOTreeBuilder extends HandlerBase {
+
+ /**
+ * table mapping element names to the makers of objects
+ * representing formatting objects
+ */
+ protected Hashtable fobjTable = new Hashtable();
+
+ /**
+ * class that builds a property list for each formatting object
+ */
+ protected PropertyListBuilder propertyListBuilder = new
+ PropertyListBuilder();
+
+ /**
+ * current formatting object being handled
+ */
+ protected FObj currentFObj = null;
+
+ /**
+ * the root of the formatting object tree
+ */
+ protected FObj rootFObj = null;
+
+ /**
+ * set of names of formatting objects encountered but unknown
+ */
+ protected Hashtable unknownFOs = new Hashtable();
+
+ // 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 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 = "";
+ String localPart = name;
+ if (colon != -1) {
+ prefix = name.substring(0, colon);
+ localPart = name.substring(colon + 1);
+ }
+ String uri = findURI(prefix);
+ if (uri == null) {
+ if (prefix.equals("")) {
+ return name;
+ } else {
+ throw new SAXException(new FOPException("Unknown namespace prefix " + prefix));
+ }
+ }
+ return uri + "^" + localPart;
+ }
+
+ /**
+ * add a mapping from element name to maker.
+ *
+ * @param namespaceURI namespace URI of formatting object element
+ * @param localName local name of formatting object element
+ * @param maker Maker for class representing formatting object
+ */
+ public void addMapping(String namespaceURI, String localName,
+ FObj.Maker maker) {
+ this.fobjTable.put(namespaceURI + "^" + localName, maker);
+ }
+
+ /** SAX Handler for characters */
+ public void characters(char data[], int start, int length) {
+ currentFObj.addCharacters(data, start, start + length);
+ }
+
+ /** SAX Handler for the end of an element */
+ public void endElement(String name) {
+ currentFObj.end();
+ currentFObj = (FObj) currentFObj.getParent();
+ level--;
+ while (((NSMap) namespaceStack.peek()).level > level) {
+ namespaceStack.pop();
+ }
+ }
+
+ /** SAX Handler for the start of the document */
+ public void startDocument() {
+ System.err.println("building formatting object tree");
+ }
+
+ /** SAX Handler for the start of an element */
+ public void startElement(String name, AttributeList attlist)
+ throws SAXException {
+
+ /* the formatting object started */
+ FObj fobj;
+
+ /* the maker for the formatting object started */
+ FObj.Maker fobjMaker;
+
+ 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));
+ }
+ }
+ String fullName = mapName(name);
+
+ fobjMaker = (FObj.Maker) fobjTable.get(fullName);
+
+ if (fobjMaker == null) {
+ if (!this.unknownFOs.containsKey(fullName)) {
+ this.unknownFOs.put(fullName, "");
+ System.err.println("WARNING: Unknown formatting object "
+ + fullName);
+ }
+ fobjMaker = new FObjMixed.Maker(); // fall back
+ }
+
+ try {
+ fobj =
+ fobjMaker.make(currentFObj,
+ this.propertyListBuilder.makeList(attlist,
+ (currentFObj == null) ? null : currentFObj.properties));
+ } catch (FOPException e) {
+ throw new SAXException(e);
+ }
+
+ if (rootFObj == null) {
+ rootFObj = fobj;
+ if (!fobj.getName().equals("fo:root")) {
+ throw new SAXException(new FOPException("Root element must"
+ + " be root, not "
+ + fobj.getName()));
+ }
+ } else {
+ currentFObj.addChild(fobj);
+ }
+
+ currentFObj = fobj;
+ }
+
+ /**
+ * format this formatting object tree
+ *
+ * @param areaTree the area tree to format into
+ */
+ public void format(AreaTree areaTree)
+ throws FOPException {
+ System.err.println("formatting FOs into areas");
+ ((Root) this.rootFObj).format(areaTree);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+// FOP
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ * base class for representation of formatting objects and their processing
+ */
+public class FObj extends FONode {
+
+ public static class Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new FObj(parent, propertyList);
+ }
+ }
+
+ public static Maker maker() {
+ return new Maker();
+ }
+
+ protected PropertyList properties;
+ protected String name;
+
+ protected FObj(FObj parent, PropertyList propertyList) {
+ super(parent);
+ this.properties = propertyList;
+ this.name = "default FO";
+ }
+
+ protected void addCharacters(char data[], int start, int length) {
+ // ignore
+ }
+
+ public int layout(Area area) throws FOPException {
+ // should always be overridden
+ return OK;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ protected void start() {
+ // do nothing by default
+ }
+
+ protected void end() {
+ // do nothing by default
+ }
+}
+
--- /dev/null
+package org.apache.xml.fop.fo;
+
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * base class for representation of mixed content formatting objects
+ * and their processing
+ */
+public class FObjMixed extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new FObjMixed(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new FObjMixed.Maker();
+ }
+
+ protected FObjMixed(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ }
+
+ protected void addCharacters(char data[], int start, int length) {
+ children.addElement(new FOText(data,start,length,this));
+ }
+
+ public int layout(Area area) throws FOPException {
+
+ if (this.marker == START) {
+ this.marker = 0;
+ }
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FONode fo = (FONode) children.elementAt(i);
+ int status;
+ if ((status = fo.layout(area)) != OK) {
+ this.marker = i;
+ return status;
+ }
+ }
+ return OK;
+ }
+}
+
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=flow \
+ pagination
+
+
+SOURCES=FONode.java \
+ FOText.java \
+ FOTreeBuilder.java \
+ FObj.java \
+ FObjMixed.java \
+ Property.java \
+ PropertyList.java \
+ PropertyListBuilder.java \
+ StandardElementMapping.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.fo;
+
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class Property {
+
+ public static class Maker {
+
+ public boolean isInherited() { return false; }
+
+ public Property make(PropertyList propertyList, String value) throws FOPException {
+ return null;
+ }
+
+ public Property make(PropertyList propertyList) throws FOPException { // default
+ return null;
+ }
+
+ public Property compute(PropertyList propertyList) { // compute
+ return null;
+ }
+ }
+ protected PropertyList propertyList;
+
+ public Length getLength() { return null; }
+ public String getString() { return null; }
+ public ColorType getColorType() { return null; }
+ public int getEnum() { return 0; }
+
+ public static double toDouble(String s) {
+ double d;
+ try {
+ d = Double.valueOf(s).doubleValue();
+ } catch (NumberFormatException e) {
+ d = Double.NaN;
+ }
+ return d;
+ }
+
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+import java.util.Hashtable;
+
+import org.apache.xml.fop.apps.FOPException;
+
+public class PropertyList extends Hashtable {
+ private PropertyListBuilder builder;
+ private PropertyList parentPropertyList = null;
+
+ public PropertyList(PropertyList parentPropertyList) {
+ this.parentPropertyList = parentPropertyList;
+ }
+
+ public Property get(String propertyName) {
+
+ if (builder == null)
+ System.err.println("OH OH, builder has not been set");
+ Property p = (Property)super.get(propertyName);
+
+ if (p == null) { // if not explicit
+ p = this.builder.computeProperty(this,propertyName);
+ if (p == null) { // else inherit
+ if ((this.parentPropertyList != null)&&(this.builder.isInherited(propertyName))) { // check for parent
+ p = this.parentPropertyList.get(propertyName); // retrieve parent's value
+ } else { // default
+ try {
+ p = this.builder.makeProperty(this,propertyName);
+ } catch (FOPException e) {
+ // don't know what to do here
+ }
+ }
+ }
+ }
+ return p;
+ }
+
+ public void setBuilder(PropertyListBuilder builder) {
+ this.builder = builder;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.svg.*;
+
+import org.apache.xml.fop.apps.FOPException;
+
+import org.xml.sax.AttributeList;
+
+import java.util.Hashtable;
+
+public class PropertyListBuilder {
+ private Hashtable propertyTable;
+
+ public PropertyListBuilder() {
+ this.propertyTable = new Hashtable();
+
+ propertyTable.put("end-indent",EndIndent.maker());
+ propertyTable.put("page-master-name",PageMasterName.maker());
+ propertyTable.put("page-master-first",PageMasterFirst.maker());
+ propertyTable.put("page-master-repeating",PageMasterRepeating.maker());
+ propertyTable.put("page-master-odd",PageMasterOdd.maker());
+ propertyTable.put("page-master-even",PageMasterEven.maker());
+ propertyTable.put("margin-top",MarginTop.maker());
+ propertyTable.put("margin-bottom",MarginBottom.maker());
+ propertyTable.put("margin-left",MarginLeft.maker());
+ propertyTable.put("margin-right",MarginRight.maker());
+ propertyTable.put("extent",Extent.maker());
+ propertyTable.put("page-width",PageWidth.maker());
+ propertyTable.put("page-height",PageHeight.maker());
+ propertyTable.put("flow-name",FlowName.maker());
+ propertyTable.put("font-family",FontFamily.maker());
+ propertyTable.put("font-style",FontStyle.maker());
+ propertyTable.put("font-weight",FontWeight.maker());
+ propertyTable.put("font-size",FontSize.maker());
+ propertyTable.put("line-height",LineHeight.maker());
+ propertyTable.put("text-align",TextAlign.maker());
+ propertyTable.put("text-align-last",TextAlignLast.maker());
+ propertyTable.put("space-before.optimum",SpaceBeforeOptimum.maker());
+ propertyTable.put("space-after.optimum",SpaceAfterOptimum.maker());
+ propertyTable.put("start-indent",StartIndent.maker());
+ propertyTable.put("end-indent",EndIndent.maker());
+ propertyTable.put("provisional-distance-between-starts",ProvisionalDistanceBetweenStarts.maker());
+ propertyTable.put("provisional-label-separation",ProvisionalLabelSeparation.maker());
+ propertyTable.put("rule-thickness",RuleThickness.maker());
+ propertyTable.put("color",Color.maker());
+ propertyTable.put("wrap-option",WrapOption.maker());
+ propertyTable.put("white-space-treatment",WhiteSpaceTreatment.maker());
+ propertyTable.put("break-before",BreakBefore.maker());
+ propertyTable.put("break-after",BreakAfter.maker());
+ propertyTable.put("text-indent",TextIndent.maker());
+ propertyTable.put("href",HRef.maker());
+ propertyTable.put("column-width",ColumnWidth.maker());
+ propertyTable.put("height",SVGLength.maker());
+ propertyTable.put("width",SVGLength.maker());
+ propertyTable.put("x",SVGLength.maker());
+ propertyTable.put("y",SVGLength.maker());
+ propertyTable.put("x1",SVGLength.maker());
+ propertyTable.put("x2",SVGLength.maker());
+ propertyTable.put("y1",SVGLength.maker());
+ propertyTable.put("y2",SVGLength.maker());
+ }
+
+ public Property computeProperty(PropertyList propertyList, String propertyName) {
+
+ Property p = null;
+
+ Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName);
+ if (propertyMaker != null) {
+ p = propertyMaker.compute(propertyList);
+ } else {
+ //System.err.println("WARNING: property " + propertyName + " ignored");
+ }
+ return p;
+ }
+
+ public boolean isInherited(String propertyName) {
+ boolean b;
+
+ Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName);
+ if (propertyMaker != null) {
+ b = propertyMaker.isInherited();
+ } else {
+ //System.err.println("WARNING: Unknown property " + propertyName);
+ b = true;
+ }
+ return b;
+ }
+
+ public PropertyList makeList(AttributeList attributes, PropertyList parentPropertyList) throws FOPException {
+
+ PropertyList p = new PropertyList(parentPropertyList);
+ p.setBuilder(this);
+
+ for (int i = 0; i < attributes.getLength(); i++) {
+ String attributeName = attributes.getName(i);
+ Property.Maker propertyMaker = (Property.Maker)propertyTable.get(attributeName);
+ if (propertyMaker != null) {
+ p.put(attributeName,propertyMaker.make(p,attributes.getValue(i)));
+ } else {
+ //System.err.println("WARNING: property " + attributeName + " ignored");
+ }
+ }
+
+ return p;
+ }
+
+ public Property makeProperty(PropertyList propertyList, String propertyName) throws FOPException {
+
+ Property p = null;
+
+ Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName);
+ if (propertyMaker != null) {
+ p = propertyMaker.make(propertyList);
+ } else {
+ //System.err.println("WARNING: property " + propertyName + " ignored");
+ }
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo;
+
+import org.apache.xml.fop.fo.flow.*;
+import org.apache.xml.fop.fo.pagination.*;
+
+public class StandardElementMapping implements ElementMapping {
+
+ public void addToBuilder(FOTreeBuilder builder) {
+
+ String uri = "http://www.w3.org/1999/XSL/Format";
+
+ builder.addMapping(uri, "root", Root.maker());
+ builder.addMapping(uri, "layout-master-set",
+ LayoutMasterSet.maker());
+ builder.addMapping(uri, "simple-page-master",
+ SimplePageMaster.maker());
+ builder.addMapping(uri, "region-body", RegionBody.maker());
+ builder.addMapping(uri, "region-before", RegionBefore.maker());
+ builder.addMapping(uri, "region-after", RegionAfter.maker());
+ builder.addMapping(uri, "page-sequence", PageSequence.maker());
+ builder.addMapping(uri, "sequence-specification",
+ SequenceSpecification.maker());
+ builder.addMapping(uri, "sequence-specifier-single",
+ SequenceSpecifierSingle.maker());
+ builder.addMapping(uri, "sequence-specifier-repeating",
+ SequenceSpecifierRepeating.maker());
+ builder.addMapping(uri, "sequence-specifier-alternating",
+ SequenceSpecifierAlternating.maker());
+ builder.addMapping(uri, "flow", Flow.maker());
+ builder.addMapping(uri, "static-content",
+ StaticContent.maker());
+ builder.addMapping(uri, "block", Block.maker());
+ builder.addMapping(uri, "list-block", ListBlock.maker());
+ builder.addMapping(uri, "list-item", ListItem.maker());
+ builder.addMapping(uri, "list-item-label",
+ ListItemLabel.maker());
+ builder.addMapping(uri, "list-item-body", ListItemBody.maker());
+ builder.addMapping(uri, "page-number", PageNumber.maker());
+ builder.addMapping(uri, "display-sequence",
+ DisplaySequence.maker());
+ builder.addMapping(uri, "inline-sequence",
+ InlineSequence.maker());
+ builder.addMapping(uri, "display-rule", DisplayRule.maker());
+ builder.addMapping(uri, "display-graphic",
+ DisplayGraphic.maker());
+ builder.addMapping(uri, "table", Table.maker());
+ builder.addMapping(uri, "table-column", TableColumn.maker());
+ builder.addMapping(uri, "table-body", TableBody.maker());
+ builder.addMapping(uri, "table-row", TableRow.maker());
+ builder.addMapping(uri, "table-cell", TableCell.maker());
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class Block extends FObjMixed {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Block(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new Block.Maker();
+ }
+
+ FontState fs;
+ int align;
+ int alignLast;
+ int breakBefore;
+ int breakAfter;
+ int lineHeight;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+ int textIndent;
+
+ BlockArea blockArea;
+
+ // this may be helpful on other FOs too
+ boolean anythingLaidOut = false;
+
+ public Block(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:block";
+ }
+
+ public int layout(Area area) throws FOPException {
+ // System.err.print(" b:LAY[" + marker + "] ");
+
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+ this.align = this.properties.get("text-align").getEnum();
+ this.alignLast =
+ this.properties.get("text-align-last").getEnum();
+ this.breakBefore =
+ this.properties.get("break-before").getEnum();
+ this.breakAfter =
+ this.properties.get("break-after").getEnum();
+ this.lineHeight =
+ this.properties.get("line-height").getLength().mvalue();
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ this.textIndent =
+ this.properties.get("text-indent").getLength().mvalue();
+
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+ if (this.isInLabel) {
+ startIndent += bodyIndent;
+ endIndent += (area.getAllocationWidth()
+ - distanceBetweenStarts - startIndent)
+ + labelSeparation;
+ }
+
+ if (this.isInListBody) {
+ startIndent += bodyIndent + distanceBetweenStarts;
+ }
+
+ if (this.isInTableCell) {
+ startIndent += forcedStartOffset;
+ endIndent = area.getAllocationWidth() - startIndent -
+ forcedWidth;
+ }
+
+ this.marker = 0;
+
+ if (breakBefore == BreakBefore.PAGE) {
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakBefore == BreakBefore.ODD_PAGE) {
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakBefore == BreakBefore.EVEN_PAGE) {
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+ }
+
+ if ((spaceBefore != 0) && (this.marker ==0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ if (anythingLaidOut) {
+ this.textIndent = 0;
+ }
+
+ this.blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent,
+ textIndent, align, alignLast, lineHeight);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FONode fo = (FONode) children.elementAt(i);
+ if (this.isInListBody) {
+ fo.setIsInListBody();
+ fo.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ fo.setBodyIndent(this.bodyIndent);
+ }
+ int status;
+ if ((status = fo.layout(blockArea)) != OK) {
+ this.marker = i;
+ if ((i != 0) && (status == AREA_FULL_NONE)) {
+ status = AREA_FULL_SOME;
+ }
+ //blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ anythingLaidOut = true;
+ return status;
+ }
+ anythingLaidOut = true;
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+
+ /* should this be combined into above? */
+ area.increaseHeight(blockArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ if (breakAfter == BreakAfter.PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakAfter == BreakAfter.ODD_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakAfter == BreakAfter.EVEN_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+
+ //System.err.print(" b:OK" + marker + " ");
+ return OK;
+ }
+
+ public int getAreaHeight() {
+ return blockArea.getHeight();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+import org.apache.xml.fop.image.*;
+
+// Java
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class DisplayGraphic extends FObj {
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new DisplayGraphic(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new DisplayGraphic.Maker();
+ }
+
+ FontState fs;
+ int align;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+ String href;
+ int height;
+ int width;
+
+ ImageArea imageArea;
+
+ public DisplayGraphic(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:display-graphic";
+ }
+
+ public int layout(Area area) throws FOPException {
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ // FIXME
+ this.align = this.properties.get("text-align").getEnum();
+
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+
+ this.href = this.properties.get("href").getString();
+ this.width =
+ this.properties.get("width").getLength().mvalue();
+ this.height =
+ this.properties.get("height").getLength().mvalue();
+
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ if (this.isInLabel) {
+ startIndent += bodyIndent;
+ endIndent += (area.getAllocationWidth()
+ - distanceBetweenStarts - startIndent)
+ + labelSeparation;
+ }
+
+ if (this.isInListBody) {
+ startIndent += bodyIndent + distanceBetweenStarts;
+ }
+
+ if (this.isInTableCell) {
+ startIndent += forcedStartOffset;
+ endIndent = area.getAllocationWidth() - startIndent -
+ forcedWidth;
+ }
+
+ this.marker = 0;
+ }
+
+ if ((spaceBefore != 0) && (this.marker == 0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ FopImage img = FopImageFactory.Make(href, 0, 0, width, height);
+
+ this.imageArea = new ImageArea(fs,
+ img,
+ area.getAllocationWidth(),
+ img.getWidth(),
+ img.getHeight(),
+ startIndent, endIndent,
+ align);
+
+ imageArea.start();
+ imageArea.end();
+ area.addChild(imageArea);
+ area.increaseHeight(imageArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.RuleArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+public class DisplayRule extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new DisplayRule(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new DisplayRule.Maker();
+ }
+
+ public DisplayRule(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:display-rule";
+ }
+
+ public int layout(Area area) throws FOPException {
+ // FIXME: doesn't check to see if it will fit
+
+ String fontFamily = this.properties.get("font-family").getString();
+ String fontStyle = this.properties.get("font-style").getString();
+ String fontWeight = this.properties.get("font-weight").getString();
+ int fontSize = this.properties.get("font-size").getLength().mvalue();
+
+ FontState fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ int align = this.properties.get("text-align").getEnum();
+ int startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ int endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ int spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ int spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ int ruleThickness =
+ this.properties.get("rule-thickness").getLength().mvalue();
+ int ruleLength = 0; // not used;
+
+ ColorType c = this.properties.get("color").getColorType();
+ float red = c.red();
+ float green = c.green();
+ float blue = c.blue();
+
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ if (spaceBefore != 0) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ RuleArea ruleArea = new RuleArea(fs,
+ area.getAllocationWidth(),
+ area.spaceLeft(),
+ startIndent, endIndent,
+ align, ruleThickness,
+ ruleLength, red, green,
+ blue);
+ area.addChild(ruleArea);
+ area.increaseHeight(ruleArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class DisplaySequence extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new DisplaySequence(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new DisplaySequence.Maker();
+ }
+
+ public DisplaySequence(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:display-sequence";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == START) {
+ this.marker = 0;
+ }
+ // this is such common code, perhaps it should be in the super class
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FObj fo = (FObj) children.elementAt(i);
+ int status;
+ if ((status = fo.layout(area)) != OK) {
+ /* message from child */
+ if (status > OK) {
+ /* child still successful */
+ this.marker = i+1;
+ } else {
+ /* child unsucessful */
+ this.marker = i;
+ }
+ return status;
+ }
+ }
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.fo.pagination.PageSequence;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+public class Flow extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Flow(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new Flow.Maker();
+ }
+
+ PageSequence pageSequence;
+
+ protected Flow(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:flow";
+
+ if (parent.getName().equals("fo:page-sequence")) {
+ this.pageSequence = (PageSequence) parent;
+ } else {
+ throw new FOPException("flow must be child of "
+ + "page-sequence, not "
+ + parent.getName());
+ }
+ pageSequence.setFlow(this);
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == START) {
+ this.marker = 0;
+ }
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FObj fo = (FObj) children.elementAt(i);
+ int status;
+ if ((status = fo.layout(area)) != OK) {
+ this.marker = i;
+ return status;
+ }
+ }
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class InlineSequence extends FObjMixed {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new InlineSequence(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new InlineSequence.Maker();
+ }
+
+ public InlineSequence(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:inline-sequence";
+
+ if (parent.getName().equals("fo:flow")) {
+ throw new FOPException("inline-sequence can't be directly"
+ + " under flow");
+ }
+ }
+
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class ListBlock extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new ListBlock(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new ListBlock.Maker();
+ }
+
+ FontState fs;
+ int align;
+ int alignLast;
+ int breakBefore;
+ int breakAfter;
+ int lineHeight;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+ int provisionalDistanceBetweenStarts;
+ int provisionalLabelSeparation;
+ int spaceBetweenListRows = 0;
+
+ public ListBlock(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:list-block";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ this.align = this.properties.get("text-align").getEnum();
+ this.alignLast =
+ this.properties.get("text-align-last").getEnum();
+ this.lineHeight =
+ this.properties.get("line-height").getLength().mvalue();
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ this.provisionalDistanceBetweenStarts =
+ this.properties.get("provisional-distance-between-starts").getLength().mvalue();
+ this.provisionalLabelSeparation =
+ this.properties.get("provisional-label-separation").getLength().mvalue();
+ this.spaceBetweenListRows = 0; // not used at present
+
+ this.marker = 0;
+
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ if (spaceBefore != 0) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ if (this.isInListBody) {
+ startIndent += bodyIndent + distanceBetweenStarts;
+ bodyIndent = startIndent;
+ }
+ }
+
+ BlockArea blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, 0,
+ align, alignLast, lineHeight);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ if (!(children.elementAt(i) instanceof ListItem)) {
+ System.err.println("WARNING: This version of FOP requires list-items inside list-blocks");
+ return OK;
+ }
+ ListItem listItem = (ListItem) children.elementAt(i);
+ listItem.setDistanceBetweenStarts(this.provisionalDistanceBetweenStarts);
+ listItem.setLabelSeparation(this.provisionalLabelSeparation);
+ listItem.setBodyIndent(this.bodyIndent);
+ int status;
+ if ((status = listItem.layout(blockArea)) != OK) {
+ /* message from child */
+ if (status > OK) {
+ /* child still successful */
+ this.marker = i+1;
+ } else {
+ /* child unsucessful */
+ this.marker = i;
+ }
+ blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ return status;
+ }
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class ListItem extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new ListItem(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new ListItem.Maker();
+ }
+
+ FontState fs;
+ int align;
+ int alignLast;
+ int breakBefore;
+ int breakAfter;
+ int lineHeight;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+
+ public ListItem(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:list-item";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ this.align = this.properties.get("text-align").getEnum();
+ this.alignLast =
+ this.properties.get("text-align-last").getEnum();
+ this.lineHeight =
+ this.properties.get("line-height").getLength().mvalue();
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+
+ this.marker = 0;
+ }
+
+ /* not sure this is needed given we know area is from list block */
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ if (spaceBefore != 0) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ startIndent += this.bodyIndent;
+
+ BlockArea blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent,
+ 0, align, alignLast, lineHeight);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ if (numChildren != 2) {
+ throw new FOPException("list-item must have exactly two children");
+ }
+ ListItemLabel label = (ListItemLabel) children.elementAt(0);
+ ListItemBody body = (ListItemBody) children.elementAt(1);
+
+ label.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ label.setLabelSeparation(this.labelSeparation);
+ label.setBodyIndent(this.bodyIndent);
+
+ body.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ body.setBodyIndent(this.bodyIndent);
+
+ /* this doesn't actually do anything */
+ body.setLabelSeparation(this.labelSeparation);
+
+ int status;
+
+ // what follows doesn't yet take into account whether the
+ // body failed completely or only got some text in
+
+ if (this.marker == 0) {
+ status = label.layout(blockArea);
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ status = body.layout(blockArea);
+ if (status != OK) {
+ blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ this.marker = 1;
+ return status;
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ /* not sure this is needed given we know area is from list block */
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class ListItemBody extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new ListItemBody(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new ListItemBody.Maker();
+ }
+
+ public ListItemBody(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:list-item-body";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == START) {
+ this.marker = 0;
+ }
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FObj fo = (FObj) children.elementAt(i);
+ fo.setIsInListBody();
+ fo.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ fo.setLabelSeparation(this.labelSeparation);
+ fo.setBodyIndent(this.bodyIndent);
+ int status;
+ if ((status = fo.layout(area)) != OK) {
+ this.marker = i;
+ if ((i == 0) && (status == AREA_FULL_NONE)) {
+ return AREA_FULL_NONE;
+ } else {
+ return AREA_FULL_SOME;
+ }
+ }
+ }
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class ListItemLabel extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new ListItemLabel(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new ListItemLabel.Maker();
+ }
+
+ public ListItemLabel(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:list-item-label";
+ }
+
+ public int layout(Area area) throws FOPException {
+ int numChildren = this.children.size();
+
+ if (numChildren != 1) {
+ throw new FOPException("list-item-label must have exactly one block in this version of FOP");
+ }
+ Block block = (Block) children.elementAt(0);
+
+ block.setIsInLabel();
+ block.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ block.setLabelSeparation(this.labelSeparation);
+ block.setBodyIndent(this.bodyIndent);
+
+ int status;
+ status = block.layout(area);
+ area.addDisplaySpace(-block.getAreaHeight());
+ return status;
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+
+SOURCES=Block.java \
+ DisplayGraphic.java \
+ DisplayRule.java \
+ DisplaySequence.java \
+ Flow.java \
+ InlineSequence.java \
+ ListBlock.java \
+ ListItemBody.java \
+ ListItemLabel.java \
+ PageNumber.java \
+ StaticContent.java \
+ Table.java \
+ TableBody.java \
+ TableCell.java \
+ TableColumn.java \
+ TableRow.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class PageNumber extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new PageNumber(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new PageNumber.Maker();
+ }
+
+ FontState fs;
+ float red;
+ float green;
+ float blue;
+ int wrapOption;
+ int whiteSpaceTreatment;
+
+ public PageNumber(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:page-number";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (!(area instanceof BlockArea)) {
+ System.err.println("WARNING: page-number outside block area");
+ return OK;
+ }
+ if (this.marker == START) {
+ String fontFamily = this.properties.get("font-family").getString();
+ String fontStyle = this.properties.get("font-style").getString();
+ String fontWeight = this.properties.get("font-weight").getString();
+ int fontSize = this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ ColorType c = this.properties.get("color").getColorType();
+ this.red = c.red();
+ this.green = c.green();
+ this.blue = c.blue();
+
+ this.wrapOption = this.properties.get("wrap-option").getEnum();
+ this.whiteSpaceTreatment = this.properties.get("white-space-treatment").getEnum();
+
+ this.marker = 0;
+ }
+ String p = Integer.toString(area.getPage().getNumber());
+ this.marker = ((BlockArea) area).addText(fs, red, green, blue, wrapOption, whiteSpaceTreatment, p.toCharArray(), 0, p.length());
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.fo.pagination.PageSequence;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Enumeration;
+
+public class StaticContent extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new StaticContent(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new StaticContent.Maker();
+ }
+
+ PageSequence pageSequence;
+
+ protected StaticContent(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:static-content";
+
+ if (parent.getName().equals("fo:page-sequence")) {
+ this.pageSequence = (PageSequence) parent;
+ } else {
+ throw new FOPException("static-content must be child of "
+ + "fo:page-sequence, not "
+ + parent.getName());
+ }
+ String flowName = this.properties.get("flow-name").getString();
+
+ pageSequence.setStaticContent(flowName, this);
+ }
+
+ public int layout(Area area) throws FOPException {
+ int numChildren = this.children.size();
+ for (int i = 0; i < numChildren; i++) {
+ FObj fo = (FObj) children.elementAt(i);
+ fo.layout(area);
+ }
+ resetMarker();
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Vector;
+
+public class Table extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Table(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new Table.Maker();
+ }
+
+ FontState fs;
+ int breakBefore;
+ int breakAfter;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+
+ Vector columns = new Vector();
+ int currentColumnNumber = 0;
+
+ BlockArea blockArea;
+
+ public Table(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:table";
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+ this.breakBefore =
+ this.properties.get("break-before").getEnum();
+ this.breakAfter =
+ this.properties.get("break-after").getEnum();
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ if (this.isInListBody) {
+ startIndent += bodyIndent + distanceBetweenStarts;
+ }
+
+ this.marker = 0;
+
+ if (breakBefore == BreakBefore.PAGE) {
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakBefore == BreakBefore.ODD_PAGE) {
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakBefore == BreakBefore.EVEN_PAGE) {
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+ }
+
+ if ((spaceBefore != 0) && (this.marker ==0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ this.blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, 0,
+ 0, 0, 0);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FONode fo = (FONode) children.elementAt(i);
+ if (fo instanceof TableColumn) {
+ TableColumn c = (TableColumn) fo;
+ int num = c.getColumnNumber();
+ if (num == 0) {
+ num = currentColumnNumber + 1;
+ }
+ currentColumnNumber = num;
+ if (num > columns.size()) {
+ columns.setSize(num);
+ }
+ columns.setElementAt(c, num-1);
+ } else if (fo instanceof TableBody) {
+ if (columns.size() == 0) {
+ System.err.println("WARNING: current implementation of tables requires a table-column for each column, indicating column-width");
+ return OK;
+ }
+
+ //if (this.isInListBody) {
+ //fo.setIsInListBody();
+ //fo.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ //fo.setBodyIndent(this.bodyIndent);
+ //}
+
+ ((TableBody) fo).setColumns(columns);
+
+ int status;
+ if ((status = fo.layout(blockArea)) != OK) {
+ this.marker = i;
+ if ((i != 0) && (status == AREA_FULL_NONE)) {
+ status = AREA_FULL_SOME;
+ }
+ //blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ return status;
+ }
+ }
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+
+ /* should this be combined into above? */
+ area.increaseHeight(blockArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ if (breakAfter == BreakAfter.PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakAfter == BreakAfter.ODD_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakAfter == BreakAfter.EVEN_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+
+ return OK;
+ }
+
+ public int getAreaHeight() {
+ return blockArea.getHeight();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Vector;
+
+public class TableBody extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new TableBody(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new TableBody.Maker();
+ }
+
+ FontState fs;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+
+ Vector columns;
+
+ BlockArea blockArea;
+
+ public TableBody(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:table-body";
+ }
+
+ public void setColumns(Vector columns) {
+ this.columns = columns;
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ //if (this.isInListBody) {
+ //startIndent += bodyIndent + distanceBetweenStarts;
+ //}
+
+ this.marker = 0;
+
+ }
+
+ if ((spaceBefore != 0) && (this.marker ==0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ this.blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, 0,
+ 0, 0, 0);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ TableRow row = (TableRow) children.elementAt(i);
+
+ //if (this.isInListBody) {
+ //fo.setIsInListBody();
+ //fo.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ //fo.setBodyIndent(this.bodyIndent);
+ //}
+
+ row.setColumns(columns);
+
+ int status;
+ if ((status = row.layout(blockArea)) != OK) {
+ this.marker = i;
+ if ((i != 0) && (status == AREA_FULL_NONE)) {
+ status = AREA_FULL_SOME;
+ }
+ //blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ return status;
+ }
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+
+ /* should this be combined into above? */
+ area.increaseHeight(blockArea.getHeight());
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ return OK;
+ }
+
+ public int getAreaHeight() {
+ return blockArea.getHeight();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class TableCell extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new TableCell(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new TableCell.Maker();
+ }
+
+ FontState fs;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+
+ protected int startOffset;
+ protected int width;
+ protected int height = 0;
+
+ BlockArea blockArea;
+
+ public TableCell(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:table-cell";
+ }
+
+ public void setStartOffset(int offset) {
+ startOffset = offset;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ //if (this.isInListBody) {
+ //startIndent += bodyIndent + distanceBetweenStarts;
+ //}
+
+ this.marker = 0;
+
+ }
+
+ if ((spaceBefore != 0) && (this.marker ==0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ this.blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, 0,
+ 0, 0, 0);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ for (int i = this.marker; i < numChildren; i++) {
+ FObj fo = (FObj) children.elementAt(i);
+ fo.setIsInTableCell();
+ fo.forceStartOffset(startOffset);
+ fo.forceWidth(width);
+ int status;
+ if ((status = fo.layout(blockArea)) != OK) {
+ this.marker = i;
+ if ((i == 0) && (status == AREA_FULL_NONE)) {
+ return AREA_FULL_NONE;
+ } else {
+ return AREA_FULL_SOME;
+ }
+ }
+ height += blockArea.getHeight();
+
+ }
+ blockArea.end();
+ area.addChild(blockArea);
+
+ return OK;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+public class TableColumn extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new TableColumn(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new TableColumn.Maker();
+ }
+
+ public TableColumn(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:table-column";
+ }
+
+ public int getColumnWidth() {
+ return this.properties.get("column-width").getLength().mvalue();
+ }
+
+ public int getColumnNumber() {
+ return 0; // not implemented yet
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.flow;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Vector;
+
+public class TableRow extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new TableRow(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new TableRow.Maker();
+ }
+
+ FontState fs;
+ int startIndent;
+ int endIndent;
+ int spaceBefore;
+ int spaceAfter;
+
+ int widthOfCellsSoFar = 0;
+ int largestCellHeight = 0;
+
+ Vector columns;
+
+ BlockArea blockArea;
+
+ public TableRow(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "fo:table-row";
+ }
+
+ public void setColumns(Vector columns) {
+ this.columns = columns;
+ }
+
+ public int layout(Area area) throws FOPException {
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ String fontFamily =
+ this.properties.get("font-family").getString();
+ String fontStyle =
+ this.properties.get("font-style").getString();
+ String fontWeight =
+ this.properties.get("font-weight").getString();
+ int fontSize =
+ this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+ this.startIndent =
+ this.properties.get("start-indent").getLength().mvalue();
+ this.endIndent =
+ this.properties.get("end-indent").getLength().mvalue();
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ if (area instanceof BlockArea) {
+ area.end();
+ }
+
+ //if (this.isInListBody) {
+ //startIndent += bodyIndent + distanceBetweenStarts;
+ //}
+
+ this.marker = 0;
+
+ }
+
+ if ((spaceBefore != 0) && (this.marker ==0)) {
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ this.blockArea =
+ new BlockArea(fs, area.getAllocationWidth(),
+ area.spaceLeft(), startIndent, endIndent, 0,
+ 0, 0, 0);
+ blockArea.setPage(area.getPage());
+ blockArea.start();
+
+ int numChildren = this.children.size();
+ if (numChildren != columns.size()) {
+ System.err.println("WARNING: Number of children under table-row not equal to number of table-columns");
+ return OK;
+ }
+
+ for (int i = this.marker; i < numChildren; i++) {
+ TableCell cell = (TableCell) children.elementAt(i);
+
+ //if (this.isInListBody) {
+ //fo.setIsInListBody();
+ //fo.setDistanceBetweenStarts(this.distanceBetweenStarts);
+ //fo.setBodyIndent(this.bodyIndent);
+ //}
+
+ cell.setStartOffset(widthOfCellsSoFar);
+ int width = ((TableColumn) columns.elementAt(i)).getColumnWidth();
+
+ cell.setWidth(width);
+ widthOfCellsSoFar += width;
+
+ int status;
+ if ((status = cell.layout(blockArea)) != OK) {
+ this.marker = i;
+ if ((i != 0) && (status == AREA_FULL_NONE)) {
+ status = AREA_FULL_SOME;
+ }
+ //blockArea.end();
+ area.addChild(blockArea);
+ area.increaseHeight(blockArea.getHeight());
+ return status;
+ }
+
+ int h = cell.getHeight();
+ blockArea.addDisplaySpace(-h);
+ if (h > largestCellHeight) {
+ largestCellHeight = h;
+ }
+
+ }
+
+ blockArea.end();
+ area.addChild(blockArea);
+ area.addDisplaySpace(largestCellHeight);
+ area.increaseHeight(largestCellHeight);
+
+ if (spaceAfter != 0) {
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ if (area instanceof BlockArea) {
+ area.start();
+ }
+
+ return OK;
+ }
+
+ public int getAreaHeight() {
+ return blockArea.getHeight();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Hashtable;
+
+public class LayoutMasterSet extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new LayoutMasterSet(parent,propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new LayoutMasterSet.Maker();
+ }
+
+ private Hashtable layoutMasters;
+ private Root root;
+
+ protected LayoutMasterSet(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:layout-master-set";
+
+ this.layoutMasters = new Hashtable();
+ if (parent.getName().equals("fo:root")) {
+ this.root = (Root)parent;
+ root.setLayoutMasterSet(this);
+ } else {
+ throw
+ new FOPException("fo:layout-master-set must be child of fo:root, not "
+ + parent.getName());
+ }
+ }
+
+ protected void addLayoutMaster(String masterName, SimplePageMaster layoutMaster) {
+ this.layoutMasters.put(masterName, layoutMaster);
+ }
+
+ protected SimplePageMaster getLayoutMaster(String masterName) {
+ return (SimplePageMaster)this.layoutMasters.get(masterName);
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+
+SOURCES=LayoutMasterSet.java \
+ PageSequence.java \
+ RegionAfter.java \
+ RegionBefore.java \
+ RegionBody.java \
+ Root.java \
+ SequenceSpecification.java \
+ SequenceSpecifier.java \
+ SequenceSpecifierAlternating.java \
+ SequenceSpecifierRepeating.java \
+ SequenceSpecifierSingle.java \
+ SimplePageMaster.java
+
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.fo.flow.Flow;
+import org.apache.xml.fop.fo.flow.StaticContent;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.AreaContainer;
+import org.apache.xml.fop.layout.AreaTree;
+import org.apache.xml.fop.layout.Page;
+import org.apache.xml.fop.layout.PageMaster;
+import org.apache.xml.fop.layout.PageMasterFactory;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class PageSequence extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new PageSequence(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new PageSequence.Maker();
+ }
+
+ protected Root root;
+ protected SequenceSpecification sequenceSpecification;
+ protected Flow flow;
+ protected StaticContent staticBefore;
+ protected StaticContent staticAfter;
+ protected LayoutMasterSet layoutMasterSet;
+
+ protected Page currentPage;
+ protected int currentPageNumber = 0;
+
+ protected PageSequence(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:page-sequence";
+
+ if (parent.getName().equals("fo:root")) {
+ this.root = (Root) parent;
+ this.root.addPageSequence(this);
+ } else {
+ throw
+ new FOPException("page-sequence must be child of root, not "
+ + parent.getName());
+ }
+ layoutMasterSet = root.getLayoutMasterSet();
+ }
+
+ protected Page makePage(AreaTree areaTree) throws FOPException {
+ PageMaster pageMaster;
+ // layout this page sequence
+
+ // while there is still stuff in the flow, ask the
+ // sequence-specification for a new page
+
+ if (this.sequenceSpecification == null) {
+ throw new FOPException("page-sequence is missing an"
+ + " sequence-specification");
+ }
+
+ PageMasterFactory pmf =
+ this.sequenceSpecification.getFirstPageMasterFactory();
+
+ pageMaster = pmf.getNextPageMaster();
+
+ while (pageMaster == null) {
+ /* move on to next sequence specifier */
+ pmf = pmf.getNext();
+ if (pmf == null) {
+ throw new FOPException("out of sequence specifiers"
+ + " (FOP will eventually allow this)");
+ }
+ pageMaster = pmf.getNextPageMaster();
+ }
+ return pageMaster.makePage(areaTree);
+ }
+
+ public void format(AreaTree areaTree) throws FOPException {
+ int status = OK;
+
+ do {
+ currentPage = makePage(areaTree);
+ currentPage.setNumber(++this.currentPageNumber);
+ System.err.print(" [" + currentPageNumber);
+ if ((this.staticBefore != null) &&
+ (currentPage.getBefore() != null)) {
+ AreaContainer beforeArea = currentPage.getBefore();
+ this.staticBefore.layout(beforeArea);
+ }
+ if ((this.staticAfter != null) &&
+ (currentPage.getAfter() != null)) {
+ AreaContainer afterArea = currentPage.getAfter();
+ this.staticAfter.layout(afterArea);
+ }
+ if ((status == FORCE_PAGE_BREAK_EVEN) &&
+ ((currentPageNumber % 2) == 1)) {
+ } else if ((status == FORCE_PAGE_BREAK_ODD) &&
+ ((currentPageNumber % 2) == 0)) {
+ } else {
+ AreaContainer bodyArea = currentPage.getBody();
+ status = this.flow.layout(bodyArea);
+ }
+ System.err.print("]");
+ areaTree.addPage(currentPage);
+ } while (status != OK);
+ System.err.println();
+ }
+
+ public void setFlow(Flow flow) {
+ this.flow = flow;
+ }
+
+ protected void setSequenceSpecification(SequenceSpecification sequenceSpecification) {
+ this.sequenceSpecification = sequenceSpecification;
+ sequenceSpecification.setLayoutMasterSet(this.layoutMasterSet);
+ }
+
+ public void setStaticContent(String name, StaticContent staticContent) {
+ if (name.equals("xsl-before")) {
+ this.staticBefore = staticContent;
+ } else if (name.equals("xsl-after")) {
+ this.staticAfter = staticContent;
+ } else {
+ System.err.println("WARNING: this version of FOP only supports "
+ + "static-content in region-before and region-after");
+ }
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Region;
+import org.apache.xml.fop.apps.FOPException;
+
+public class RegionAfter extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList) throws FOPException {
+ return new RegionAfter(parent,propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new RegionAfter.Maker();
+ }
+
+ SimplePageMaster layoutMaster;
+
+ protected RegionAfter(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:region-after";
+
+ if (parent.getName().equals("fo:simple-page-master")) {
+ this.layoutMaster = (SimplePageMaster) parent;
+ this.layoutMaster.setRegionAfter(this);
+ } else {
+ throw new FOPException("region-after must be child "
+ + "of simple-page-master, not "
+ + parent.getName());
+ }
+ }
+
+ Region makeRegion(int allocationRectangleXPosition,
+ int allocationRectangleYPosition,
+ int allocationRectangleWidth,
+ int allocationRectangleHeight) {
+ int marginTop = this.properties.get("margin-top").getLength().mvalue();
+ int marginBottom = this.properties.get("margin-bottom").getLength().mvalue();
+ int marginLeft = this.properties.get("margin-left").getLength().mvalue();
+ int marginRight = this.properties.get("margin-right").getLength().mvalue();
+ int extent = this.properties.get("extent").getLength().mvalue();
+
+ return new Region(allocationRectangleXPosition + marginLeft,
+ allocationRectangleYPosition -
+ allocationRectangleHeight + extent,
+ allocationRectangleWidth - marginLeft -
+ marginRight,extent);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Region;
+import org.apache.xml.fop.apps.FOPException;
+
+public class RegionBefore extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList) throws FOPException {
+ return new RegionBefore(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new RegionBefore.Maker();
+ }
+
+ SimplePageMaster layoutMaster;
+
+ protected RegionBefore(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:region-before";
+
+ if (parent.getName().equals("fo:simple-page-master")) {
+ this.layoutMaster = (SimplePageMaster) parent;
+ this.layoutMaster.setRegionBefore(this);
+ } else {
+ throw new FOPException("region-before must be child of "
+ + "simple-page-master, not "
+ + parent.getName());
+ }
+ }
+
+ Region makeRegion(int allocationRectangleXPosition,
+ int allocationRectangleYPosition,
+ int allocationRectangleWidth,
+ int allocationRectangleHeight) {
+ int marginTop = this.properties.get("margin-top").getLength().mvalue();
+ int marginBottom = this.properties.get("margin-bottom").getLength().mvalue();
+ int marginLeft = this.properties.get("margin-left").getLength().mvalue();
+ int marginRight = this.properties.get("margin-right").getLength().mvalue();
+ int extent = this.properties.get("extent").getLength().mvalue();
+
+ return new Region(allocationRectangleXPosition + marginLeft,
+ allocationRectangleYPosition - marginTop,
+ allocationRectangleWidth - marginLeft -
+ marginRight, extent);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Region;
+import org.apache.xml.fop.apps.FOPException;
+
+public class RegionBody extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList) throws FOPException {
+ return new RegionBody(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new RegionBody.Maker();
+ }
+
+ protected RegionBody(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:region-body";
+
+ if (parent.getName().equals("fo:simple-page-master")) {
+ ((SimplePageMaster) parent).setRegionBody(this);
+ } else {
+ throw new FOPException("region-body must be child of "
+ + "simple-page-master, not "
+ + parent.getName());
+ }
+ }
+
+ Region makeRegion(int allocationRectangleXPosition,
+ int allocationRectangleYPosition,
+ int allocationRectangleWidth,
+ int allocationRectangleHeight) {
+ int marginTop = this.properties.get("margin-top").getLength().mvalue();
+ int marginBottom = this.properties.get("margin-bottom").getLength().mvalue();
+ int marginLeft = this.properties.get("margin-left").getLength().mvalue();
+ int marginRight = this.properties.get("margin-right").getLength().mvalue();
+
+ return new Region(allocationRectangleXPosition + marginLeft,
+ allocationRectangleYPosition - marginTop,
+ allocationRectangleWidth - marginLeft -
+ marginRight, allocationRectangleHeight -
+ marginTop - marginBottom);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.AreaTree;
+import org.apache.xml.fop.apps.FOPException;
+
+// Java
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class Root extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Root(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new Root.Maker();
+ }
+
+ LayoutMasterSet layoutMasterSet;
+ Vector pageSequences;
+
+ protected Root(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:root";
+
+ pageSequences = new Vector();
+ if (parent != null) {
+ throw new FOPException("root must be root element");
+ }
+ }
+
+ public void addPageSequence(PageSequence pageSequence) {
+ this.pageSequences.addElement(pageSequence);
+ }
+
+ public LayoutMasterSet getLayoutMasterSet() {
+ return this.layoutMasterSet;
+ }
+
+ public void format(AreaTree areaTree) throws FOPException {
+ if (layoutMasterSet == null) {
+ throw new FOPException("No layout master set.");
+ }
+ Enumeration e = pageSequences.elements();
+ while (e.hasMoreElements()) {
+ ((PageSequence) e.nextElement()).format(areaTree);
+ }
+ }
+
+ public void setLayoutMasterSet(LayoutMasterSet layoutMasterSet) {
+ this.layoutMasterSet = layoutMasterSet;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.PageMasterFactory;
+import org.apache.xml.fop.apps.FOPException;
+
+public class SequenceSpecification extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SequenceSpecification(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new SequenceSpecification.Maker();
+ }
+
+ private PageSequence pageSequence;
+ private LayoutMasterSet layoutMasterSet;
+ private PageMasterFactory firstPMF;
+ private PageMasterFactory currentPMF;
+
+ protected SequenceSpecification(FObj parent,
+ PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:sequence-specification";
+
+ if (parent.getName().equals("fo:page-sequence")) {
+ this.pageSequence = (PageSequence) parent;
+ this.pageSequence.setSequenceSpecification(this);
+ } else {
+ throw new FOPException("sequence-specification must be child"
+ + " of page-sequence, not "
+ + parent.getName());
+ }
+ this.firstPMF = null;
+ this.currentPMF = null;
+
+}
+
+ protected void addSequenceSpecifier(SequenceSpecifier sequenceSpecifier) {
+ if (this.firstPMF == null) {
+ this.firstPMF = sequenceSpecifier.getPageMasterFactory();
+ } else {
+ this.currentPMF.setNext(sequenceSpecifier.getPageMasterFactory());
+ }
+ this.currentPMF = sequenceSpecifier.getPageMasterFactory();
+ }
+
+ protected PageMasterFactory getFirstPageMasterFactory() {
+ return this.firstPMF;
+ }
+
+ LayoutMasterSet getLayoutMasterSet() {
+ return this.layoutMasterSet;
+ }
+
+ protected void setLayoutMasterSet(LayoutMasterSet layoutMasterSet) {
+ this.layoutMasterSet = layoutMasterSet;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.layout.PageMasterFactory;
+
+abstract public class SequenceSpecifier extends FObj {
+
+ protected SequenceSpecifier(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ }
+
+ public abstract PageMasterFactory getPageMasterFactory();
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.PageMasterFactory;
+import org.apache.xml.fop.layout.AlternatingPageMasterFactory;
+import org.apache.xml.fop.layout.PageMaster;
+import org.apache.xml.fop.apps.FOPException;
+
+public class SequenceSpecifierAlternating extends SequenceSpecifier {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SequenceSpecifierAlternating(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new SequenceSpecifierAlternating.Maker();
+ }
+
+ private SequenceSpecification sequenceSpecification;
+ private LayoutMasterSet layoutMasterSet;
+ private AlternatingPageMasterFactory pageMasterFactory;
+
+ protected SequenceSpecifierAlternating(FObj parent,
+ PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ PageMaster pf, pe, po;
+
+ this.name = "fo:sequence-specifer-alternating";
+
+ if (parent.getName().equals("fo:sequence-specification")) {
+ this.sequenceSpecification = (SequenceSpecification) parent;
+ this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet();
+ } else {
+ throw new FOPException("fo:sequence-specifier-alternating must be "
+ + " child of fo:sequence-specification, not "
+ + parent.getName());
+ }
+
+ String pageMasterFirst = this.properties.get("page-master-first").getString();
+ String pageMasterOdd = this.properties.get("page-master-odd").getString();
+ String pageMasterEven = this.properties.get("page-master-even").getString();
+
+ try {
+ pf = this.layoutMasterSet.getLayoutMaster(pageMasterFirst).getPageMaster();
+ pe = this.layoutMasterSet.getLayoutMaster(pageMasterEven).getPageMaster();
+ po = this.layoutMasterSet.getLayoutMaster(pageMasterOdd).getPageMaster();
+ this.pageMasterFactory = new AlternatingPageMasterFactory(pf,pe,po);
+ } catch (java.lang.NullPointerException e) {
+ throw new FOPException("at least one of the page-master names in"
+ + " sequence-specifier-alternating is not in"
+ + " layout-master-set");
+ }
+ this.sequenceSpecification.addSequenceSpecifier(this);
+ }
+
+ public PageMasterFactory getPageMasterFactory() {
+ return this.pageMasterFactory;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.PageMasterFactory;
+import org.apache.xml.fop.layout.RepeatingPageMasterFactory;
+import org.apache.xml.fop.layout.PageMaster;
+import org.apache.xml.fop.apps.FOPException;
+
+public class SequenceSpecifierRepeating extends SequenceSpecifier {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SequenceSpecifierRepeating(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new SequenceSpecifierRepeating.Maker();
+ }
+
+ private SequenceSpecification sequenceSpecification;
+ private LayoutMasterSet layoutMasterSet;
+ private RepeatingPageMasterFactory pageMasterFactory;
+
+ protected SequenceSpecifierRepeating(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ PageMaster pf, pr;
+
+ this.name = "fo:sequence-specifer-repeating";
+
+ if (parent.getName().equals("fo:sequence-specification")) {
+ this.sequenceSpecification = (SequenceSpecification) parent;
+ this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet();
+ } else {
+ throw new FOPException("sequence-specifier-repeating must be "
+ + "child of fo:sequence-specification, "
+ + "not " + parent.getName());
+ }
+
+ String pageMasterFirst = this.properties.get("page-master-first").getString();
+ String pageMasterRepeating = this.properties.get("page-master-repeating").getString();
+ try {
+ pf = this.layoutMasterSet.getLayoutMaster(pageMasterFirst).getPageMaster();
+ pr = this.layoutMasterSet.getLayoutMaster(pageMasterRepeating).getPageMaster();
+ this.pageMasterFactory = new RepeatingPageMasterFactory(pf, pr);
+ } catch (java.lang.NullPointerException e) {
+ throw new FOPException("at least one of the page-master names in "
+ + "sequence-specifier-repeating is not in "
+ + "layout-master-set");
+ }
+ this.sequenceSpecification.addSequenceSpecifier(this);
+ }
+
+ public PageMasterFactory getPageMasterFactory() {
+ return this.pageMasterFactory;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.PageMasterFactory;
+import org.apache.xml.fop.layout.SinglePageMasterFactory;
+import org.apache.xml.fop.layout.PageMaster;
+import org.apache.xml.fop.apps.FOPException;
+
+public class SequenceSpecifierSingle extends SequenceSpecifier {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SequenceSpecifierSingle(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new SequenceSpecifierSingle.Maker();
+ }
+
+ private SequenceSpecification sequenceSpecification;
+ private LayoutMasterSet layoutMasterSet;
+ private SinglePageMasterFactory pageMasterFactory;
+
+ protected SequenceSpecifierSingle(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:sequence-specifer-single";
+
+ if (parent.getName().equals("fo:sequence-specification")) {
+ this.sequenceSpecification = (SequenceSpecification) parent;
+ this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet();
+ } else {
+ throw new FOPException("sequence-specifier-single must be "
+ + "child of fo:sequence-specification, "
+ + "not " + parent.getName());
+ }
+
+ String pageMasterName = this.properties.get("page-master-name").getString();
+ try {
+ this.pageMasterFactory = new SinglePageMasterFactory(this.layoutMasterSet.getLayoutMaster(pageMasterName).getPageMaster());
+ } catch (java.lang.NullPointerException e) {
+ throw new FOPException("page-master-name " +
+ pageMasterName + " must be in layout-master-set");
+ }
+ this.sequenceSpecification.addSequenceSpecifier(this);
+ }
+
+ public PageMasterFactory getPageMasterFactory() {
+ return this.pageMasterFactory;
+ }
+
+ public String getPageMasterName() {
+ return this.properties.get("page-master-name").getString();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.fo.pagination;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.PageMaster;
+import org.apache.xml.fop.layout.Region;
+import org.apache.xml.fop.apps.FOPException;
+
+public class SimplePageMaster extends FObj {
+
+ public static class Maker extends FObj.Maker {
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SimplePageMaster(parent, propertyList);
+ }
+ }
+
+ public static FObj.Maker maker() {
+ return new SimplePageMaster.Maker();
+ }
+
+ RegionBody regionBody;
+ RegionBefore regionBefore;
+ RegionAfter regionAfter;
+
+ LayoutMasterSet layoutMasterSet;
+ PageMaster pageMaster;
+
+ protected SimplePageMaster(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ super(parent, propertyList);
+ this.name = "fo:simple-page-master";
+
+ if (parent.getName().equals("fo:layout-master-set")) {
+ this.layoutMasterSet = (LayoutMasterSet) parent;
+ String pm = this.properties.get("page-master-name").getString();
+ if (pm == null) {
+ System.err.println("WARNING: simple-page-master does not have "
+ + "a page-master-name and so is being ignored");
+ } else {
+ this.layoutMasterSet.addLayoutMaster(pm, this);
+ }
+ } else {
+ throw new FOPException("fo:simple-page-master must be child "
+ + "of fo:layout-master-set, not "
+ + parent.getName());
+ }
+ }
+
+ protected void end() {
+ int pageWidth = this.properties.get("page-width").getLength().mvalue();
+ int pageHeight = this.properties.get("page-height").getLength().mvalue();
+
+ int marginTop = this.properties.get("margin-top").getLength().mvalue();
+ int marginBottom = this.properties.get("margin-bottom").getLength().mvalue();
+ int marginLeft = this.properties.get("margin-left").getLength().mvalue();
+ int marginRight = this.properties.get("margin-right").getLength().mvalue();
+
+ int contentRectangleXPosition = marginLeft;
+ int contentRectangleYPosition = pageHeight - marginTop;
+ int contentRectangleWidth = pageWidth - marginLeft - marginRight;
+ int contentRectangleHeight = pageHeight - marginTop - marginBottom;
+
+ this.pageMaster = new PageMaster(pageWidth, pageHeight);
+ this.pageMaster.addBody(this.regionBody.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight));
+
+ if (this.regionBefore != null)
+ this.pageMaster.addBefore(this.regionBefore.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight));
+ if (this.regionAfter != null)
+ this.pageMaster.addAfter(this.regionAfter.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight));
+ }
+
+ PageMaster getPageMaster() {
+ return this.pageMaster;
+ }
+
+ protected void setRegionAfter(RegionAfter region) {
+ this.regionAfter = region;
+ }
+
+ protected void setRegionBefore(RegionBefore region) {
+ this.regionBefore = region;
+ }
+
+ protected void setRegionBody(RegionBody region) {
+ this.regionBody = region;
+ }
+}
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+//Title: BoBoGi FOP
+//Version:
+//Copyright: Copyright (c) 1999
+//Author: Sergio Botti
+//Company: Dibe Elsag
+//Description: xml to pdf converter
+
+package org.apache.xml.fop.image;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class BmpBwImage implements FopImage {
+ int X;
+ int Y;
+ int width;
+ int height;
+ int pixelwidth;
+ int pixelheight;
+ String ref;
+ boolean color;
+ int bitperpixel;
+ int[] imagemap;
+ int imagestart;
+ /*
+ Costructor read the header of the bmp file to get the size
+ and the other data
+ SB
+ */
+ public BmpBwImage(String href,int x,int y,int w,int h)
+ {
+ this.ref=href;
+ this.X=x;
+ this.Y=y;
+
+ int wpos=18;
+ int hpos=22; //offset positioning for w and height in bmp files
+ int [] headermap = new int[54];
+ try{
+ FileInputStream file=new FileInputStream(ref);
+ boolean eof=false;
+ int count=0;
+ while ((!eof) && (count<54) ) {
+ int input =file.read();
+ if (input==-1)
+ eof=true;
+ else
+ headermap[count++]=input;
+ }
+ file.close();
+ }catch (IOException e) {System.err.println("Image not found");}
+ // gets h & w from headermap
+ this.pixelwidth = headermap[wpos]+headermap[wpos+1]*256+headermap[wpos+2]*256*256+headermap[wpos+3]*256*256*256;
+ this.pixelheight = headermap[hpos]+headermap[hpos+1]*256+headermap[hpos+2]*256*256+headermap[hpos+3]*256*256*256;
+ if (w==0)
+ this.width=this.pixelwidth*1000;
+ else
+ this.width=w;
+ if (h==0)
+ this.height=this.pixelheight*1000;
+ else
+ this.height=h;
+
+ this.imagestart =headermap[10]+headermap[11]*256+headermap[12]*256*256+headermap[13]*256*256*256;
+ this.bitperpixel=headermap[28];
+ }
+
+ public String gethref() { return this.ref; }
+ public int getWidth() { return this.width; }
+ public int getHeight() { return this.height; }
+ public int getpixelwidth() { return this.pixelwidth; }
+ public int getpixelheight() { return this.pixelheight; }
+ public int getX(){ return this.X; }
+ public int getY(){ return this.Y; }
+
+ public int[] getimagemap(){
+ int input;
+ int[] temp = new int[nextfourdiv(this.pixelwidth)*(this.pixelheight)];
+ try {
+ FileInputStream file = new FileInputStream(this.ref);
+ int count = 0;
+ file.skip((long) this.imagestart);
+ while ((input = file.read()) != -1) {
+ temp[count++] = input;
+ }
+ file.close();
+ } catch (IOException e) {
+ System.err.println("Image not found");
+ }
+ int[] map = new int[this.pixelheight * this.pixelwidth];
+ int k = 0;
+ for (int y = 0; y < this.pixelheight; y++) {
+ for (int x = 0; x < this.pixelwidth; x++)
+ map[k++] = temp[y * nextfourdiv(this.pixelwidth) + x];
+ }
+ return map;
+ }
+
+ public boolean getcolor(){return false;}
+ public int getbitperpixel() {return this.bitperpixel;}
+
+ private int nextfourdiv(int number) {
+ return ((number/4)+1)*4;
+ }
+
+}
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+//Title: BoBoGi FOP
+//Version:
+//Copyright: Copyright (c) 1999
+//Author: Sergio Botti
+//Company: Dibe Elsag
+//Description: xml to pdf converter
+
+package org.apache.xml.fop.image;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class BmpColImage implements FopImage {
+ int X;
+ int Y;
+ int width;
+ int height;
+ int pixelwidth;
+ int pixelheight;
+ String ref;
+ boolean color=true;
+ int bitperpixel;
+ int[] imagemap;
+ int imagestart;
+ /*
+ Costructor read the header of the bmp file to get the size
+ and the other data
+ SB
+ */
+public BmpColImage(String href,int x,int y,int w,int h)
+{
+ this.ref=href;
+ this.X=x;
+ this.Y=y;
+
+ int wpos=18;
+ int hpos=22; //offset positioning for w and height in bmp files
+ int [] headermap = new int[54];
+ try{
+ FileInputStream file=new FileInputStream(ref);
+ boolean eof=false;
+ int count=0;
+ while ((!eof) && (count<54) ) {
+ int input =file.read();
+ if (input==-1)
+ eof=true;
+ else
+ headermap[count++]=input;
+ }
+ file.close();
+ }catch (IOException e) {System.err.println("Image not found");}
+ // gets h & w from headermap
+ this.pixelwidth = headermap[wpos]+headermap[wpos+1]*256+headermap[wpos+2]*256*256+headermap[wpos+3]*256*256*256;
+ this.pixelheight = headermap[hpos]+headermap[hpos+1]*256+headermap[hpos+2]*256*256+headermap[hpos+3]*256*256*256;
+ if (w==0)
+ this.width=this.pixelwidth*1000;
+ else
+ this.width=w;
+ if (h==0)
+ this.height=this.pixelheight*1000;
+ else
+ this.height=h;
+
+ this.imagestart =headermap[10]+headermap[11]*256+headermap[12]*256*256+headermap[13]*256*256*256;
+ this.bitperpixel=headermap[28];
+}
+
+ public String gethref() { return this.ref; }
+ public int getWidth() { return this.width; }
+ public int getHeight() { return this.height; }
+ public int getpixelwidth() { return this.pixelwidth; }
+ public int getpixelheight() { return this.pixelheight; }
+ public int getX(){ return this.X; }
+ public int getY(){ return this.Y; }
+
+ public int[] getimagemap(){
+ int[] temp = new int[nextfourdiv(this.pixelwidth*3)*(this.pixelheight)];
+ try{
+ FileInputStream file=new FileInputStream(this.ref);
+ boolean eof=false;
+ int count=0;
+ file.skip((long)this.imagestart);
+ while (!eof) {
+ int input = file.read();
+ if (input==-1) {
+ eof=true;
+ } else {
+ temp[count++]=input;
+ }
+ }
+ file.close();
+ } catch (IOException e) {
+ System.err.println("Image not found");
+ }
+
+ int[] map =new int[this.pixelheight*this.pixelwidth*3];
+ int k=0;
+
+ for (int y=0;y<this.pixelheight;y++) {
+ for (int x=0;x<(this.pixelwidth);x++) {
+ map[k++]=temp[y*nextfourdiv(this.pixelwidth*3)+x*3+2];
+ map[k++]=temp[y*nextfourdiv(this.pixelwidth*3)+x*3+1];
+ map[k++]=temp[y*nextfourdiv(this.pixelwidth*3)+x*3];
+
+ //map[k++]=temp[y*nextfourdiv(this.pixelwidth*3)+x];
+ }
+ }
+ return map;
+ }
+
+
+ public boolean getcolor(){return true;}
+ public int getbitperpixel() {return this.bitperpixel;}
+
+ //
+ private int nextfourdiv(int number) {
+ int n = number;
+ while((n%4)!=0) {
+ n++;
+ }
+ return n;
+ }
+
+}
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+//Title: BoBoGi FOP
+//Version:
+//Copyright: Copyright (c) 1999
+//Author: Sergio Botti
+//Company: Dibe Elsag
+//Description: Part in xml to pdf converter
+
+
+package org.apache.xml.fop.image;
+
+public interface FopImage {
+ public int getpixelwidth();
+ public int getpixelheight();
+ public int getWidth();
+ public int getHeight();
+ public int getX();
+ public int getY();
+ public String gethref();
+ public int[] getimagemap();
+ public boolean getcolor();
+ public int getbitperpixel();
+}
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+//Title: BoBoGi FOP
+//Version: x
+//Copyright: Copyright (c) 1999
+//Author: Sergio Botti
+//Company: Dibe Elsag
+//Description: xml to pdf converter
+
+
+package org.apache.xml.fop.image;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FopImageFactory {
+
+ public static FopImage Make(String ref,int x,int y, int width, int height) {
+
+
+ int colorpos=28; //offset positioning for w and height in bmp files
+ int [] headermap = new int[54];
+ try{
+ FileInputStream file=new FileInputStream(ref);
+ boolean eof=false;
+ int count=0;
+ while ((!eof) && (count<54) ) {
+ int input =file.read();
+ if (input==-1)
+ eof=true;
+ else
+ headermap[count++]=input;
+ }
+ file.close();
+ } catch (IOException e) {System.err.println("Image not found");}
+ int bpp=headermap[28];
+ if (bpp==8) {
+ return (new BmpBwImage(ref,x,y,width,height));
+ } else if (bpp==24) {
+ return (new BmpColImage(ref,x,y,width,height));
+ }
+ System.err.println("Unsupported bmp format");
+
+ return null;
+
+ }
+}
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+//Title: BoBoGi FOP
+//Version:
+//Copyright: Copyright (c) 1999
+//Author: Sergio Botti
+//Company: Dibe Elsag
+//Description: xml to pdf converter
+
+
+package org.apache.xml.fop.image;
+
+import java.util.Hashtable;
+import java.net.URL;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.awt.image.*;
+import java.awt.Image;
+import java.awt.Toolkit;
+
+public class GifJpegImage implements FopImage {
+ int X;
+ int Y;
+ int width;
+ int height;
+ int pixelwidth;
+ int pixelheight;
+ String ref;
+ boolean color=true;
+ int bitperpixel=8;
+ int[] imagemap;
+ int[] tempmap;
+ /*
+ Costructor read the header of the bmp file to get the size
+ and the other data
+ SB
+ */
+
+public GifJpegImage(String href,int x,int y,int w,int h)
+{
+ this.ref=href;
+ this.X=x;
+ this.Y=y;
+ this.pixelheight=-1;
+ this.pixelwidth=-1;
+ try {
+ URL url = new URL(href);
+ ImageProducer ip = (ImageProducer)url.getContent();
+ FopImageConsumer consumer = new FopImageConsumer();
+ ip.startProduction(consumer);
+ while ((this.pixelheight = consumer.getHeight())==-1) {}
+ while ((this.pixelwidth = consumer.getWidth())==-1) {}
+ this.tempmap = new int[this.pixelwidth*this.pixelheight];
+ //Image img=Toolkit.getDefaultToolkit().getImage("prova.gif");
+ // Image img=Toolkit.getDefaultToolkit().getImage(url);
+ PixelGrabber pg = new PixelGrabber(ip,0,0,this.pixelwidth,this.pixelheight,this.tempmap,0,w);
+ try {
+ pg.grabPixels();
+ }catch (InterruptedException e) {System.err.println("Image grabbing interrupted");}
+ } catch (ClassCastException e) {System.err.println("Image format not supported: " + href);
+ } catch (Exception e) {System.err.println("Error loading image " + href + " : " +e);
+ }
+ if (w==0)
+ this.width=this.pixelwidth*1000;
+ else
+ this.width=w;
+ if (h==0)
+ this.height=this.pixelheight*1000;
+ else
+ this.height=h;
+}
+//
+public static class FopImageConsumer implements ImageConsumer {
+ int width = -1;
+ int height = -1;
+ public void imageComplete(int status) {}
+ public void setColorModel(ColorModel model) {}
+ public void setDimensions(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+ public void setHints(int hintflags) {}
+ public void setPixels(int x, int y, int w, int h,ColorModel model, byte[] pixels,int off, int scansize) {}
+ public void setPixels(int x, int y, int w, int h,ColorModel model, int[] pixels,int off, int scansize) {}
+ public void setProperties(Hashtable props) {}
+ public int getWidth() { return this.width; }
+ public int getHeight() { return this.height; }
+}
+
+//
+ public String gethref() { return this.ref; }
+ public int getWidth() { return this.width; }
+ public int getHeight() { return this.height; }
+ public int getpixelwidth() { return this.pixelwidth; }
+ public int getpixelheight() { return this.pixelheight; }
+ public int getX(){ return this.X; }
+ public int getY(){ return this.Y; }
+
+ public int[] getimagemap(){
+ this.imagemap=new int[this.pixelheight*this.pixelwidth*3];
+ int count=0;
+ int i;
+ for(i=0;i<(this.pixelheight*this.pixelwidth);i++)
+ {
+ int red = ((this.tempmap[i]>>16) & 0xff);
+ int green = ((this.tempmap[i]>> 8) & 0xff);
+ int blue = ((this.tempmap[i] ) & 0xff);
+ this.imagemap[count++]=red;
+ this.imagemap[count++]=green;
+ this.imagemap[count++]=blue;
+ }
+ return imagemap;
+ }
+
+
+ public boolean getcolor(){return true;}
+ public int getbitperpixel() {return this.bitperpixel;}
+ }
+
+
--- /dev/null
+/* modified by JKT to integrate into 0.12.0 */
+
+package org.apache.xml.fop.image;
+
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.render.Renderer;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class ImageArea extends Area {
+
+ protected int xOffset = 0;
+ protected FopImage image;
+
+ public ImageArea(FontState fontState, FopImage img,
+ int AllocationWidth, int width, int height,
+ int startIndent, int endIndent, int align) {
+ super(fontState,width,height);
+ this.currentHeight = height;
+ this.contentRectangleWidth = width;
+ this.image = img;
+
+ switch (align) {
+ case 1:
+ xOffset = startIndent;
+ break;
+ case 2:
+ if (endIndent == 0)
+ endIndent = AllocationWidth;
+ xOffset = (endIndent - width);
+ break;
+ case 3:
+ case 4:
+ if (endIndent == 0)
+ endIndent = AllocationWidth;
+ xOffset = startIndent + ((endIndent - startIndent) - width)/2;
+ break;
+ }
+ }
+
+ public int getXOffset() {
+ return this.xOffset;
+ }
+
+ public FopImage getImage() {
+ return this.image;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderImageArea(this);
+ }
+
+ public int getImageHeight() {
+ return currentHeight;
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=BmpBwImage.java \
+ BmpColImage.java \
+ ImageArea.java \
+ FopImage.java \
+ FopImageFactory.java \
+ GifJpegImage.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.layout;
+
+public class AlternatingPageMasterFactory extends PageMasterFactory {
+
+ private PageMaster pageMasterFirst;
+ private PageMaster pageMasterEven;
+ private PageMaster pageMasterOdd;
+
+ private static final int FIRST = 0;
+ private static final int EVEN = 1;
+ private static final int ODD = 2;
+
+ private int state;
+
+ public AlternatingPageMasterFactory(PageMaster first, PageMaster even, PageMaster odd) {
+ this.pageMasterFirst = first;
+ this.pageMasterEven = even;
+ this.pageMasterOdd = odd;
+ this.state = FIRST;
+ }
+
+ public int getHeight() {
+ return this.pageMasterFirst.getHeight();
+ }
+
+ public PageMaster getNextPageMaster() {
+ PageMaster pm;
+
+ switch (this.state) {
+ case EVEN: pm = this.pageMasterEven; this.state = ODD; break;
+ case ODD: pm = this.pageMasterOdd; this.state = EVEN; break;
+ default: pm = this.pageMasterFirst; this.state = EVEN;
+ }
+
+ return pm;
+ }
+
+ public int getWidth() {
+ return this.pageMasterFirst.getWidth();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+// Java
+import java.util.Vector;
+
+abstract public class Area extends Box {
+
+ /* nominal font size and nominal font family incorporated in
+ fontState */
+ protected FontState fontState;
+
+ protected Vector children = new Vector();
+
+ /* max size in line-progression-direction */
+ protected int maxHeight;
+
+ protected int currentHeight = 0;
+
+ protected int contentRectangleWidth;
+
+ protected int allocationWidth;
+
+ /* the inner-most area container the area is in */
+ protected AreaContainer areaContainer;
+
+ /* the page this area is on */
+ protected Page page;
+
+ public Area (FontState fontState) {
+ this.fontState = fontState;
+ }
+
+ public Area (FontState fontState, int allocationWidth, int maxHeight) {
+ this.fontState = fontState;
+ this.allocationWidth = allocationWidth;
+ this.maxHeight = maxHeight;
+ }
+
+ public void addChild(Box child) {
+ this.children.addElement(child);
+ child.parent = this;
+ }
+
+ public void addChildAtStart(Box child) {
+ this.children.insertElementAt(child,0);
+ child.parent = this;
+ }
+
+ public void addDisplaySpace(int size) {
+ this.addChild(new DisplaySpace(size));
+ this.currentHeight += size;
+ }
+
+ public FontInfo getFontInfo() {
+ return this.page.getFontInfo();
+ }
+
+ public void end() {
+ }
+
+ public int getAllocationWidth() {
+ return this.allocationWidth;
+ }
+
+ public Vector getChildren() {
+ return this.children;
+ }
+
+ public int getContentWidth() {
+ return this.contentRectangleWidth;
+ }
+
+ public FontState getFontState() {
+ return this.fontState;
+ }
+
+ public int getHeight() {
+ return this.currentHeight;
+ }
+
+ public int getMaxHeight() {
+ return this.maxHeight;
+ }
+
+ public Page getPage() {
+ return this.page;
+ }
+
+ public void increaseHeight(int amount) {
+ this.currentHeight += amount;
+ }
+
+ public void setPage(Page page) {
+ this.page = page;
+ }
+
+ public int spaceLeft() {
+ return maxHeight - currentHeight;
+ }
+
+ public void start() {
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+// FOP
+import org.apache.xml.fop.render.Renderer;
+
+// Java
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class AreaContainer extends Area {
+
+ private int xPosition; // should be able to take value 'left' and 'right' too
+ private int yPosition; // should be able to take value 'top' and 'bottom' too
+
+ AreaContainer(int xPosition, int yPosition, int allocationWidth, int maxHeight) {
+ super(null, allocationWidth, maxHeight);
+ this.xPosition = xPosition;
+ this.yPosition = yPosition;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderAreaContainer(this);
+ }
+
+ public int getXPosition() {
+ return xPosition;
+ }
+
+ public int getYPosition() {
+ return yPosition;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+// FOP
+import org.apache.xml.fop.apps.FOPException;
+import org.apache.xml.fop.fo.flow.StaticContent;
+import org.apache.xml.fop.svg.*;
+import org.apache.xml.fop.render.Renderer;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Stack;
+import java.util.Vector;
+
+public class AreaTree {
+
+ /** object containing information on available fonts, including
+ metrics */
+ FontInfo fontInfo;
+
+ /* list of all the pages */
+ Vector pageList = new Vector();
+
+ public void setFontInfo(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ public void addPage(Page page) {
+ this.pageList.addElement(page);
+ }
+
+ public Vector getPages() {
+ return this.pageList;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+// FOP
+import org.apache.xml.fop.render.Renderer;
+
+// Java
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class BlockArea extends Area {
+
+ /* relative to area container */
+ protected int startIndent;
+ protected int endIndent;
+
+ /* first line startIndent modifier */
+ protected int textIndent;
+
+ protected int lineHeight;
+
+ protected int halfLeading;
+
+ /* text-align of all but the last line */
+ protected int align;
+
+ /* text-align of the last line */
+ protected int alignLastLine;
+
+ protected LineArea currentLineArea;
+
+ /* have any line areas been used? */
+ protected boolean hasLines = false;
+
+ public BlockArea(FontState fontState, int allocationWidth,
+ int maxHeight, int startIndent, int endIndent,
+ int textIndent, int align, int alignLastLine,
+ int lineHeight) {
+ super(fontState, allocationWidth, maxHeight);
+
+ this.startIndent = startIndent;
+ this.endIndent = endIndent;
+ this.textIndent = textIndent;
+ this.contentRectangleWidth = allocationWidth - startIndent - endIndent;
+ this.align = align;
+ this.alignLastLine = alignLastLine;
+ this.lineHeight = lineHeight;
+
+ this.halfLeading = (lineHeight - fontState.getFontSize())/2;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderBlockArea(this);
+ }
+
+ public void addLineArea(LineArea la) {
+ if (!la.isEmpty()) {
+ this.addDisplaySpace(this.halfLeading);
+ int size = la.getHeight();
+ this.addChild(la);
+ this.increaseHeight(size);
+ this.addDisplaySpace(this.halfLeading);
+ }
+ }
+
+ public int addText(FontState fontState, float red, float green,
+ float blue, int wrapOption,
+ int whiteSpaceTreatment, char data[],
+ int start, int end) {
+ int ts, te;
+ char[] ca;
+
+ ts = start;
+ te = end;
+ ca = data;
+
+ if (currentHeight + currentLineArea.getHeight() > maxHeight) {
+ return start;
+ }
+
+ this.currentLineArea.changeFont(fontState);
+ this.currentLineArea.changeColor(red, green, blue);
+ this.currentLineArea.changeWrapOption(wrapOption);
+ this.currentLineArea.changeWhiteSpaceTreatment(whiteSpaceTreatment);
+ ts = this.currentLineArea.addText(ca, ts, te);
+ this.hasLines = true;
+
+ while (ts != -1) {
+ this.currentLineArea.align(this.align);
+ this.addLineArea(this.currentLineArea);
+ this.currentLineArea = new
+ LineArea(fontState, lineHeight, halfLeading,
+ allocationWidth, startIndent, endIndent);
+ if (currentHeight + currentLineArea.getHeight() >
+ this.maxHeight) {
+ return ts;
+ }
+ this.currentLineArea.changeFont(fontState);
+ this.currentLineArea.changeColor(red, green, blue);
+ this.currentLineArea.changeWrapOption(wrapOption);
+ this.currentLineArea.changeWhiteSpaceTreatment(whiteSpaceTreatment);
+ ts = this.currentLineArea.addText(ca, ts, te);
+ }
+ return -1;
+ }
+
+ public void end() {
+ if (this.hasLines) {
+ this.currentLineArea.addPending();
+ this.currentLineArea.align(this.alignLastLine);
+ this.addLineArea(this.currentLineArea);
+ }
+ }
+
+ public void start() {
+ currentLineArea = new LineArea(fontState, lineHeight,
+ halfLeading, allocationWidth,
+ startIndent + textIndent,
+ endIndent);
+ }
+
+ public int getEndIndent() {
+ return endIndent;
+ }
+
+ public int getStartIndent() {
+ return startIndent;
+ }
+
+ public int spaceLeft() {
+ return maxHeight - currentHeight;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+abstract public class Box {
+ protected Area parent;
+ protected AreaTree areaTree;
+ abstract public void render(Renderer renderer);
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+public class DisplaySpace extends Space {
+ private int size;
+
+ public DisplaySpace(int size) {
+ this.size = size;
+ }
+ public int getSize() {
+ return size;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderDisplaySpace(this);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import org.apache.xml.fop.apps.FOPException;
+
+public class FontInfo {
+
+ Hashtable triplets; // look up a font-triplet to find a font-name
+ Hashtable fonts; // look up a font-name to get a font (that implements FontMetric at least)
+
+ public FontInfo() {
+ this.triplets = new Hashtable();
+ this.fonts = new Hashtable();
+ }
+
+ public void addFontProperties(String name, String family, String style, String weight) {
+ /* add the given family, style and weight as a lookup for the font
+ with the given name */
+
+ String key = family + "," + style + "," + weight;
+ this.triplets.put(key,name);
+ }
+
+ public void addMetrics(String name, FontMetric metrics) {
+ // add the given metrics as a font with the given name
+
+ this.fonts.put(name,metrics);
+ }
+
+ public String fontLookup(String family, String style, String weight) throws FOPException {
+ // given a family, style and weight, return the font name
+ int i;
+
+ try {
+ i = Integer.parseInt(weight);
+ } catch (NumberFormatException e) {
+ i = 0;
+ }
+
+ if (i > 600)
+ weight = "bold";
+ else if (i > 0)
+ weight = "normal";
+
+ String key = family + "," + style + "," + weight;
+
+ String f = (String)this.triplets.get(key);
+ if (f == null) {
+ f = (String)this.triplets.get("any," + style + "," + weight);
+ if (f == null) {
+ f = (String)this.triplets.get("any,normal,normal");
+ if (f == null) {
+ throw new FOPException("no default font defined by OutputConverter");
+ }
+ System.err.println("WARNING: defaulted font to any,normal,normal");
+ }
+ System.err.println("WARNING: unknown font "+family+" so defaulted font to any");
+ }
+ return f;
+ }
+
+ public Hashtable getFonts() {
+ return this.fonts;
+ }
+
+ public FontMetric getMetricsFor(String fontName) throws FOPException {
+ return (FontMetric)fonts.get(fontName);
+ }
+
+ public FontMetric getMetricsFor(String family, String style, String weight) throws FOPException {
+ // given a family, style and weight, return the metric
+
+ return (FontMetric)fonts.get(fontLookup(family,style,weight));
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+/**
+ * interface for font metric classes
+ */
+public interface FontMetric {
+ int getAscender();
+ int getCapHeight();
+ int getDescender();
+ int getXHeight();
+
+ /**
+ * return width (in 1/1000ths of point size) of character at
+ * code point i
+ */
+ public int width(int i);
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.apps.FOPException;
+
+public class FontState {
+
+ protected FontInfo fontInfo;
+ private String fontName;
+ private int fontSize;
+ private String fontFamily;
+ private String fontStyle;
+ private String fontWeight;
+ private FontMetric metric;
+
+ public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize) throws FOPException {
+ this.fontInfo = fontInfo;
+ this.fontFamily = fontFamily;
+ this.fontStyle = fontStyle;
+ this.fontWeight = fontWeight;
+ this.fontSize = fontSize;
+ this.fontName = fontInfo.fontLookup(fontFamily,fontStyle,fontWeight);
+ this.metric = fontInfo.getMetricsFor(fontName);
+ }
+
+ public int getAscender() {
+ return fontSize * metric.getAscender() / 1000;
+ }
+
+ public int getCapHeight() {
+ return fontSize * metric.getCapHeight() / 1000;
+ }
+
+ public int getDescender() {
+ return fontSize * metric.getDescender() / 1000;
+ }
+
+ public String getFontName() {
+ return this.fontName;
+ }
+
+ public int getFontSize() {
+ return this.fontSize;
+ }
+
+ public String getFontWeight() {
+ return this.fontWeight;
+ }
+
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ public int getXHeight() {
+ return fontSize * metric.getXHeight() / 1000;
+ }
+
+ public int width(int charnum) {
+ // returns width of given character number in millipoints
+ return (fontSize * metric.width(charnum) / 1000);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+public class InlineArea extends Area {
+
+ private String text;
+ private float red, green, blue;
+
+ public InlineArea(FontState fontState, float red, float green, float blue, String text, int width) {
+ super(fontState);
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.text = text;
+ this.contentRectangleWidth = width;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderInlineArea(this);
+ }
+
+ public float getBlue() {
+ return this.blue;
+ }
+
+ public float getGreen() {
+ return this.green;
+ }
+
+ public float getRed() {
+ return this.red;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+public class InlineSpace extends Space {
+ private int size; // in millipoints
+
+ public InlineSpace(int amount) {
+ this.size = amount;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int amount) {
+ this.size = amount;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderInlineSpace(this);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.apache.xml.fop.fo.properties.WrapOption; // for enumerated
+// values
+import org.apache.xml.fop.fo.properties.WhiteSpaceTreatment; // for
+// enumerated values
+import org.apache.xml.fop.fo.properties.TextAlign; // for enumerated
+// values
+import org.apache.xml.fop.fo.properties.TextAlignLast; // for enumerated
+// values
+
+public class LineArea extends Area {
+
+ protected int lineHeight;
+ protected int halfLeading;
+ protected int nominalFontSize;
+ protected int nominalGlyphHeight;
+
+ protected int allocationHeight;
+ protected int startIndent;
+ protected int endIndent;
+
+ private int placementOffset;
+
+ private FontState currentFontState; // not the nominal, which is
+ // in this.fontState
+ private float red, green, blue;
+ private int wrapOption;
+ private int whiteSpaceTreatment;
+
+ /* the width of text that has definitely made it into the line
+ area */
+ protected int finalWidth = 0;
+
+ /* the width of the current word so far */
+ protected int wordWidth = 0;
+
+ /* values that prev (below) may take */
+ protected static final int NOTHING = 0;
+ protected static final int WHITESPACE = 1;
+ protected static final int TEXT = 2;
+
+ /* the character type of the previous character */
+ protected int prev = NOTHING;
+
+ /* the position in data[] of the start of the current word */
+ protected int wordStart;
+
+ /* the length (in characters) of the current word */
+ protected int wordLength = 0;
+
+ /* width of spaces before current word */
+ protected int spaceWidth = 0;
+
+ /* the inline areas that have not yet been added to the line
+ because subsequent characters to come (in a different addText)
+ may be part of the same word */
+ protected Vector pendingAreas = new Vector();
+
+ /* the width of the pendingAreas */
+ protected int pendingWidth = 0;
+
+ public LineArea(FontState fontState, int lineHeight, int
+ halfLeading, int allocationWidth, int startIndent,
+ int endIndent) {
+ super(fontState);
+
+ this.currentFontState = fontState;
+ this.lineHeight = lineHeight;
+ this.nominalFontSize = fontState.getFontSize();
+ this.nominalGlyphHeight = fontState.getAscender() -
+ fontState.getDescender();
+
+ this.placementOffset = fontState.getAscender();
+ this.contentRectangleWidth = allocationWidth - startIndent -
+ endIndent;
+ this.fontState = fontState;
+
+ this.allocationHeight = this.nominalGlyphHeight;
+ this.halfLeading = this.lineHeight - this.allocationHeight;
+
+ this.startIndent = startIndent;
+ this.endIndent = endIndent;
+
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderLineArea(this);
+ }
+
+ public int addText(char data[], int start, int end) {
+ boolean overrun = false;
+
+ wordStart = start;
+ wordLength = 0;
+ wordWidth = 0;
+
+ /* iterate over each character */
+ for (int i = start; i < end; i++) {
+ int charWidth;
+ /* get the character */
+ char c = data[i];
+
+ if (c > 127) {
+ /* this class shouldn't be hard coded */
+ char d =
+ org.apache.xml.fop.render.pdf.CodePointMapping.map[c];
+ if (d != 0) {
+ c = data[i] = d;
+ } else {
+ System.err.print("ch"
+ + (int)c + "?");
+ c = data[i] = '#';
+ }
+ }
+
+ charWidth = currentFontState.width(c);
+
+ if ((c == ' ') ||
+ (c == '\n') ||
+ (c == '\r') ||
+ (c == '\t')) { // whitespace
+
+ if (prev == WHITESPACE) {
+
+ // if current & previous are WHITESPACE
+
+ if (this.whiteSpaceTreatment ==
+ WhiteSpaceTreatment.PRESERVE) {
+ if (c == ' ') {
+ spaceWidth += currentFontState.width(32);
+ } else if (c == '\n') {
+ // force line break
+ return i;
+ } else if (c == '\t') {
+ spaceWidth += 8 * currentFontState.width(32);
+ }
+ } // else ignore it
+
+ } else if (prev == TEXT) {
+
+ // if current is WHITESPACE and previous TEXT
+
+ // the current word made it, so
+
+ // add the space before the current word (if there
+ // was some)
+
+ if (spaceWidth > 0) {
+ addChild(new InlineSpace(spaceWidth));
+ finalWidth += spaceWidth;
+ spaceWidth = 0;
+ }
+
+ // add any pending areas
+
+ Enumeration e = pendingAreas.elements();
+ while (e.hasMoreElements()) {
+ InlineArea inlineArea = (InlineArea) e.nextElement();
+ addChild(inlineArea);
+ }
+ finalWidth += pendingWidth;
+
+ // reset pending areas array
+ pendingWidth = 0;
+ pendingAreas = new Vector();
+
+ // add the current word
+
+ if (wordLength > 0) {
+ addChild(new InlineArea(currentFontState,
+ this.red, this.green,
+ this.blue, new
+ String(data, wordStart,
+ wordLength),
+ wordWidth));
+ finalWidth += wordWidth;
+
+ // reset word width
+ wordWidth = 0;
+ }
+
+ // deal with this new whitespace following the
+ // word we just added
+
+ prev = WHITESPACE;
+
+ if (this.whiteSpaceTreatment ==
+ WhiteSpaceTreatment.IGNORE) {
+ // do nothing
+ } else {
+ spaceWidth = currentFontState.width(32);
+ }
+ if (this.whiteSpaceTreatment ==
+ WhiteSpaceTreatment.PRESERVE) {
+ if (c == '\n') {
+ // force a line break
+ return i;
+ } else if (c == '\t') {
+ spaceWidth = currentFontState.width(32);
+ }
+ }
+
+ } else {
+
+ // if current is WHITESPACE and no previous
+
+ if (this.whiteSpaceTreatment ==
+ WhiteSpaceTreatment.PRESERVE) {
+ prev = WHITESPACE;
+ spaceWidth = currentFontState.width(32);
+ } else {
+ // skip over it
+ start++;
+ }
+ }
+
+ } else { // current is TEXT
+
+ if (prev == WHITESPACE) {
+
+ // if current is TEXT and previous WHITESPACE
+
+ wordWidth = charWidth;
+ if ((finalWidth + spaceWidth + wordWidth) >
+ this.contentRectangleWidth) {
+ if (overrun)
+ System.err.print(">");
+ if (this.wrapOption == WrapOption.WRAP)
+ return i;
+ }
+ prev = TEXT;
+ wordStart = i;
+ wordLength = 1;
+ } else if (prev == TEXT) {
+ wordLength++;
+ wordWidth += charWidth;
+ } else { // nothing previous
+ prev = TEXT;
+ wordStart = i;
+ wordLength = 1;
+ wordWidth = charWidth;
+ }
+
+ if ((finalWidth + spaceWidth + pendingWidth + wordWidth) >
+ this.contentRectangleWidth) {
+
+ // BREAK MID WORD
+ if (wordStart == start) { // if couldn't even fit
+ // first word
+ overrun = true;
+ // if not at start of line, return word start
+ // to try again on a new line
+ if (finalWidth > 0) {
+ return wordStart;
+ }
+ } else if (this.wrapOption == WrapOption.WRAP) {
+ return wordStart;
+ }
+ }
+
+ }
+ } // end of iteration over text
+
+ if (prev == TEXT) {
+ pendingAreas.addElement(new InlineArea(currentFontState, this.red,
+ this.green, this.blue, new
+ String(data, wordStart,
+ wordLength), wordWidth));
+ pendingWidth += wordWidth;
+ wordWidth = 0;
+ }
+
+ if (overrun)
+ System.err.print(">");
+ return -1;
+ }
+
+ public void addPending() {
+ if (spaceWidth > 0) {
+ addChild(new InlineSpace(spaceWidth));
+ finalWidth += spaceWidth;
+ spaceWidth = 0;
+ }
+
+ Enumeration e = pendingAreas.elements();
+ while (e.hasMoreElements()) {
+ InlineArea inlineArea = (InlineArea) e.nextElement();
+ addChild(inlineArea);
+ }
+ finalWidth += pendingWidth;
+
+ // reset pending areas array
+ pendingWidth = 0;
+ pendingAreas = new Vector();
+ }
+
+ public void align(int type) {
+ int padding;
+
+ switch (type) {
+ case TextAlign.START: // left
+ padding = this.contentRectangleWidth - finalWidth;
+ endIndent += padding;
+ break;
+ case TextAlign.END: // right
+ padding = this.contentRectangleWidth - finalWidth;
+ startIndent += padding;
+ break;
+ case TextAlign.CENTERED: // center
+ padding = (this.contentRectangleWidth - finalWidth)/2;
+ startIndent += padding;
+ endIndent += padding;
+ break;
+ case TextAlign.JUSTIFIED: // justify
+ Vector spaceList = new Vector();
+
+ int spaceCount = 0;
+ Enumeration e = children.elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box)e.nextElement();
+ if (b instanceof InlineSpace) {
+ InlineSpace space = (InlineSpace)b;
+ spaceList.addElement(space);
+ spaceCount++;
+ }
+ }
+ if (spaceCount > 0) {
+ padding = (this.contentRectangleWidth - finalWidth) /
+ spaceCount;
+ } else { // no spaces
+ padding = 0;
+ }
+ Enumeration f = spaceList.elements();
+ while (f.hasMoreElements()) {
+ InlineSpace space2 = (InlineSpace)f.nextElement();
+ int i = space2.getSize();
+ space2.setSize(i + padding);
+ }
+ }
+ }
+
+ public void changeColor(float red, float green, float blue) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ }
+
+ public void changeFont(FontState fontState) {
+ this.currentFontState = fontState;
+ }
+
+ public void changeWhiteSpaceTreatment(int whiteSpaceTreatment) {
+ this.whiteSpaceTreatment = whiteSpaceTreatment;
+ }
+
+ public void changeWrapOption(int wrapOption) {
+ this.wrapOption = wrapOption;
+ }
+
+ public int getEndIndent() {
+ return endIndent;
+ }
+
+ public int getHeight() {
+ return this.allocationHeight;
+ }
+
+ public int getPlacementOffset() {
+ return this.placementOffset;
+ }
+
+ public int getStartIndent() {
+ return startIndent;
+ }
+
+ public boolean isEmpty() {
+ return (prev==0);
+ }
+
+ public Vector getPendingAreas() {
+ return pendingAreas;
+ }
+
+ public int getPendingWidth() {
+ return pendingWidth;
+ }
+
+ public void setPendingAreas(Vector areas) {
+ pendingAreas = areas;
+ }
+
+ public void setPendingWidth(int width) {
+ pendingWidth = width;
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=AlternatingPageMasterFactory.java \
+ Area.java \
+ AreaContainer.java \
+ AreaTree.java \
+ BlockArea.java \
+ Box.java \
+ DisplaySpace.java \
+ FontInfo.java \
+ FontMetric.java \
+ FontState.java \
+ InlineArea.java \
+ InlineSpace.java \
+ LineArea.java \
+ Page.java \
+ PageMaster.java \
+ PageMasterFactory.java \
+ Region.java \
+ RepeatingPageMasterFactory.java \
+ RuleArea.java \
+ SinglePageMasterFactory.java \
+ Space.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.layout;
+
+// FOP
+import org.apache.xml.fop.render.Renderer;
+
+// Java
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class Page {
+
+ private int height;
+ private int width;
+
+ private AreaContainer body;
+ private AreaContainer before;
+ private AreaContainer after;
+ private AreaContainer start;
+ private AreaContainer end;
+
+ private AreaTree areaTree;
+
+ protected int pageNumber = 0;
+
+ Page(AreaTree areaTree, int height, int width) {
+ this.areaTree = areaTree;
+ this.height = height;
+ this.width = width;
+ }
+
+ public void setNumber(int number) {
+ this.pageNumber = number;
+ }
+
+ public int getNumber() {
+ return this.pageNumber;
+ }
+
+ void addAfter(AreaContainer area) {
+ this.after = area;
+ area.setPage(this);
+ }
+
+ void addBefore(AreaContainer area) {
+ this.before = area;
+ area.setPage(this);
+ }
+
+ void addBody(AreaContainer area) {
+ this.body = area;
+ area.setPage(this);
+ }
+
+ void addEnd(AreaContainer area) {
+ this.end = area;
+ area.setPage(this);
+ }
+
+ void addStart(AreaContainer area) {
+ this.start = area;
+ area.setPage(this);
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderPage(this);
+ }
+
+ public AreaContainer getAfter() {
+ return this.after;
+ }
+
+ public AreaContainer getBefore() {
+ return this.before;
+ }
+
+ public AreaContainer getBody() {
+ return this.body;
+ }
+
+ public int getHeight() {
+ return this.height;
+ }
+
+ public int getWidth() {
+ return this.width;
+ }
+
+ public FontInfo getFontInfo() {
+ return this.areaTree.getFontInfo();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+public class PageMaster {
+
+ private int width;
+ private int height;
+
+ private Region body;
+ private Region before;
+ private Region after;
+ private Region start;
+ private Region end;
+
+ public PageMaster(int pageWidth, int pageHeight) {
+ this.width = pageWidth;
+ this.height = pageHeight;
+ }
+
+ public void addAfter(Region region) {
+ this.after = region;
+ }
+
+ public void addBefore(Region region) {
+ this.before = region;
+ }
+
+ public void addBody(Region region) {
+ this.body = region;
+ }
+
+ public void addEnd(Region region) {
+ this.end = region;
+ }
+
+ public void addStart(Region region) {
+ this.start = region;
+ }
+
+ public int getHeight() {
+ return this.height;
+ }
+
+ public int getWidth() {
+ return this.width;
+ }
+
+ public Page makePage(AreaTree areaTree) {
+ Page p = new Page(areaTree, this.height, this.width);
+ if (this.body != null) {
+ p.addBody(body.makeAreaContainer());
+ }
+ if (this.before != null) {
+ p.addBefore(before.makeAreaContainer());
+ }
+ if (this.after != null) {
+ p.addAfter(after.makeAreaContainer());
+ }
+ if (this.start != null) {
+ p.addStart(start.makeAreaContainer());
+ }
+ if (this.end != null) {
+ p.addEnd(end.makeAreaContainer());
+ }
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+abstract public class PageMasterFactory {
+
+ private PageMasterFactory next;
+
+ abstract public int getHeight();
+
+ abstract public int getWidth();
+
+ public PageMasterFactory getNext() {
+ return this.next;
+ }
+
+ abstract public PageMaster getNextPageMaster();
+
+ public void setNext(PageMasterFactory pmf) {
+ this.next = pmf;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+public class Region {
+
+ private int xPosition;
+ private int yPosition;
+ private int width;
+ private int height;
+
+ public Region(int xPosition, int yPosition, int width, int height) {
+ this.xPosition = xPosition;
+ this.yPosition = yPosition;
+ this.width = width;
+ this.height = height;
+ }
+
+ public AreaContainer makeAreaContainer() {
+ return new AreaContainer(xPosition, yPosition, width, height);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+public class RepeatingPageMasterFactory extends PageMasterFactory {
+
+ private PageMaster pageMasterFirst;
+ private PageMaster pageMasterRepeating;
+
+ private static final int FIRST = 0;
+ private static final int REST = 1;
+
+ private int state;
+
+ public RepeatingPageMasterFactory(PageMaster first, PageMaster repeating) {
+ this.pageMasterFirst = first;
+ this.pageMasterRepeating = repeating;
+ this.state = FIRST;
+ }
+
+ public int getHeight() {
+ return this.pageMasterFirst.getHeight();
+ }
+
+ public PageMaster getNextPageMaster() {
+ PageMaster pm;
+
+ switch (this.state) {
+ case REST: pm = this.pageMasterRepeating; this.state = REST; break;
+ default: pm = this.pageMasterFirst; this.state = REST;
+ }
+
+ return pm;
+ }
+
+ public int getWidth() {
+ return this.pageMasterFirst.getWidth();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+import org.apache.xml.fop.render.Renderer;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class RuleArea extends Area {
+
+ int align; // text-align
+ int length; // length in millipoints
+ int ruleThickness;
+
+ int startIndent;
+ int endIndent;
+
+ float red, green, blue;
+ public RuleArea(FontState fontState, int allocationWidth, int maxHeight, int startIndent, int endIndent, int align, int ruleThickness, int length, float red, float green, float blue) {
+ super(fontState,allocationWidth,maxHeight);
+
+ this.contentRectangleWidth = allocationWidth - startIndent - endIndent;
+ this.align = align;
+
+ this.startIndent = startIndent;
+ this.endIndent = endIndent;
+ this.ruleThickness = ruleThickness;
+ this.length = length;
+ this.currentHeight = maxHeight;
+
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ }
+
+ public void render(Renderer renderer) {
+ renderer.renderRuleArea(this);
+ }
+ public float getBlue() {
+ return this.blue;
+ }
+ public int getEndIndent() {
+ return endIndent;
+ }
+ public float getGreen() {
+ return this.green;
+ }
+ public int getHeight() {
+ return this.ruleThickness;
+ }
+ public float getRed() {
+ return this.red;
+ }
+ public int getRuleThickness() {
+ return this.ruleThickness;
+ }
+ public int getStartIndent() {
+ return startIndent;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+public class SinglePageMasterFactory extends PageMasterFactory {
+
+ private PageMaster pageMaster;
+
+ private static final int FIRST = 0;
+ private static final int DONE = 1;
+
+ private int state;
+
+ public SinglePageMasterFactory(PageMaster pageMaster) {
+ this.pageMaster = pageMaster;
+ this.state = FIRST;
+ }
+
+ public int getHeight() {
+ return this.pageMaster.getHeight();
+ }
+
+ public PageMaster getNextPageMaster() {
+ PageMaster pm;
+
+ switch (this.state) {
+ case FIRST: pm = this.pageMaster; this.state = DONE; break;
+ default: pm = null;
+ }
+
+ return pm;
+ }
+ public int getWidth() {
+ return this.pageMaster.getWidth();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.layout;
+
+abstract public class Space extends Box {
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=PDFDocument.java \
+ PDFFont.java \
+ PDFInfo.java \
+ PDFObject.java \
+ PDFPage.java \
+ PDFPages.java \
+ PDFResources.java \
+ PDFRoot.java \
+ PDFStream.java \
+ PDFXObject.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+/* image support modified from work of BoBoGi */
+
+package org.apache.xml.fop.pdf;
+
+// images are the one place that FOP classes outside this package get
+// referenced and I'd rather not do it
+import org.apache.xml.fop.image.FopImage;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/**
+ * class representing a PDF document.
+ *
+ * The document is built up by calling various methods and then finally
+ * output to given filehandle using output method.
+ *
+ * A PDF document consists of a series of numbered objects preceded by a
+ * header and followed by an xref table and trailer. The xref table
+ * allows for quick access to objects by listing their character
+ * positions within the document. For this reason the PDF document must
+ * keep track of the character position of each object. The document
+ * also keeps direct track of the /Root, /Info and /Resources objects.
+ */
+public class PDFDocument {
+
+ /** the version of PDF supported */
+ protected static final String pdfVersion = "1.2";
+
+ /** the current character position */
+ protected int position = 0;
+
+ /** the character position of each object */
+ protected Vector location = new Vector();
+
+ /** the counter for object numbering */
+ protected int objectcount = 0;
+
+ /** the objects themselves */
+ protected Vector objects = new Vector();
+
+ /** character position of xref table */
+ protected int xref;
+
+ /** the /Root object */
+ protected PDFRoot root;
+
+ /** the /Info object */
+ protected PDFInfo info;
+
+ /** the /Resources object */
+ protected PDFResources resources;
+
+ protected int xObjectCount = 0;
+ protected Vector xObjects = new Vector();
+
+ /**
+ * creates an empty PDF document
+ */
+ public PDFDocument() {
+
+ /* create the /Root, /Info and /Resources objects */
+ this.root = makeRoot();
+ this.info = makeInfo();
+ this.resources = makeResources();
+ }
+
+ /**
+ * set the producer of the document
+ *
+ * @param producer string indicating application producing the PDF
+ */
+ public void setProducer(String producer) {
+ this.info.setProducer(producer);
+ }
+
+ /**
+ * make /Root object as next object
+ *
+ * @return the created /Root object
+ */
+ protected PDFRoot makeRoot() {
+
+ /* create a PDFRoot with the next object number and add to
+ list of objects */
+ PDFRoot pdfRoot = new PDFRoot(++this.objectcount);
+ this.objects.addElement(pdfRoot);
+
+ /* create a new /Pages object to be root of Pages hierarchy
+ and add to list of objects */
+ PDFPages rootPages = new PDFPages(++this.objectcount);
+ this.objects.addElement(rootPages);
+
+ /* inform the /Root object of the /Pages root */
+ pdfRoot.setRootPages(rootPages);
+ return pdfRoot;
+ }
+
+ /**
+ * make an /Info object
+ *
+ * @param producer string indicating application producing the PDF
+ * @return the created /Info object
+ */
+ protected PDFInfo makeInfo() {
+
+ /* create a PDFInfo with the next object number and add to
+ list of objects */
+ PDFInfo pdfInfo = new PDFInfo(++this.objectcount);
+ this.objects.addElement(pdfInfo);
+ return pdfInfo;
+ }
+
+ /**
+ * make a /Resources object
+ *
+ * @return the created /Resources object
+ */
+ private PDFResources makeResources() {
+
+ /* create a PDFResources with the next object number and add
+ to list of objects */
+ PDFResources pdfResources = new PDFResources(++this.objectcount);
+ this.objects.addElement(pdfResources);
+ return pdfResources;
+ }
+
+ /**
+ * make a Type1 /Font object
+ *
+ * @param fontname internal name to use for this font (eg "F1")
+ * @param basefont name of the base font (eg "Helvetica")
+ * @param encoding character encoding scheme used by the font
+ * @return the created /Font object
+ */
+ public PDFFont makeFont(String fontname, String basefont,
+ String encoding) {
+
+ /* create a PDFFont with the next object number and add to the
+ list of objects */
+ PDFFont font = new PDFFont(++this.objectcount, fontname,
+ basefont, encoding);
+ this.objects.addElement(font);
+ return font;
+ }
+
+ public int addImage(FopImage img) {
+ PDFXObject xObject = new PDFXObject(++this.objectcount,
+ ++this.xObjectCount, img);
+ this.objects.addElement(xObject);
+ this.xObjects.addElement(xObject);
+ return xObjectCount;
+ }
+
+ /**
+ * make a /Page object
+ *
+ * @param resources resources object to use
+ * @param contents stream object with content
+ * @param pagewidth width of the page in points
+ * @param pageheight height of the page in points
+ * @return the created /Page object
+ */
+ public PDFPage makePage(PDFResources resources,
+ PDFStream contents, int pagewidth,
+ int pageheight) {
+
+ /* create a PDFPage with the next object number, the given
+ resources, contents and dimensions */
+ PDFPage page = new PDFPage(++this.objectcount, resources,
+ contents, pagewidth, pageheight);
+
+ /* add it to the list of objects */
+ this.objects.addElement(page);
+
+ /* add the page to the Root */
+ this.root.addPage(page);
+
+ return page;
+ }
+
+ /**
+ * make a stream object
+ *
+ * @return the stream object created
+ */
+ public PDFStream makeStream() {
+
+ /* create a PDFStream with the next object number and add it
+ to the list of objects */
+ PDFStream obj = new PDFStream(++this.objectcount);
+ this.objects.addElement(obj);
+ return obj;
+ }
+
+ /**
+ * get the /Resources object for the document
+ *
+ * @return the /Resources object
+ */
+ public PDFResources getResources() {
+ return this.resources;
+ }
+
+ /**
+ * write the entire document out
+ *
+ * @param writer the PrinterWriter to output the document to
+ */
+ public void output(PrintWriter writer) throws IOException {
+
+ /* output the header and increment the character position by
+ the header's length */
+ this.position += outputHeader(writer);
+
+ this.resources.setXObjects(xObjects);
+
+ /* loop through the object numbers */
+ for (int i=1; i <= this.objectcount; i++) {
+
+ /* add the position of this object to the list of object
+ locations */
+ this.location.addElement(new Integer(this.position));
+
+ /* retrieve the object with the current number */
+ PDFObject object = (PDFObject)this.objects.elementAt(i-1);
+
+ /* output the object and increment the character position
+ by the object's length */
+ this.position += object.output(writer);
+ }
+
+ /* output the xref table and increment the character position
+ by the table's length */
+ this.position += outputXref(writer);
+
+ /* output the trailer and flush the Writer */
+ outputTrailer(writer);
+ writer.flush();
+ }
+
+ /**
+ * write the PDF header
+ *
+ * @param writer the PrintWriter to write the header to
+ * @return the number of characters written
+ */
+ protected int outputHeader(PrintWriter writer) throws IOException {
+ String pdf = "%PDF-" + this.pdfVersion + "\n";
+ writer.write(pdf);
+ return pdf.length();
+ }
+
+ /**
+ * write the trailer
+ *
+ * @param writer the PrintWriter to write the trailer to
+ */
+ protected void outputTrailer(PrintWriter writer) throws IOException {
+
+ /* construct the trailer */
+ String pdf = "trailer\n<<\n/Size " + (this.objectcount+1)
+ + "\n/Root " + this.root.number + " " + this.root.generation
+ + " R\n/Info " + this.info.number + " "
+ + this.info.generation + " R\n>>\nstartxref\n" + this.xref
+ + "\n%%EOF\n";
+
+ /* write the trailer */
+ writer.write(pdf);
+ }
+
+ /**
+ * write the xref table
+ *
+ * @param writer the PrintWriter to write the xref table to
+ * @return the number of characters written
+ */
+ private int outputXref(PrintWriter writer) throws IOException {
+
+ /* remember position of xref table */
+ this.xref = this.position;
+
+ /* construct initial part of xref */
+ StringBuffer pdf = new StringBuffer("xref\n0 " + (this.objectcount+1)
+ + "\n0000000000 65535 f \n");
+
+ /* loop through object numbers */
+ for (int i=1; i < this.objectcount+1; i++) {
+
+ /* contruct xref entry for object */
+ String padding = "0000000000";
+ String x = this.location.elementAt(i-1).toString();
+ String loc = padding.substring(x.length()) + x;
+
+ /* append to xref table */
+ pdf = pdf.append(loc + " 00000 n \n");
+ }
+
+ /* write the xref table and return the character length */
+ writer.write(pdf.toString());
+ return pdf.length();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * class representing a /Font object.
+ *
+ * A small object expressing the base font name and encoding of a
+ * Type 1 font along with an internal name for the font used within
+ * streams of content
+ */
+public class PDFFont extends PDFObject {
+
+ /** the internal name for the font (eg "F1") */
+ protected String fontname;
+
+ /** the base font name (eg "Helvetica") */
+ protected String basefont;
+
+ /** the character encoding scheme used by the font (eg
+ "WinAnsiEncoding") */
+ protected String encoding;
+
+ /**
+ * create the /Font object
+ *
+ * @param the object's number
+ * @param fontname the internal name for the font
+ * @param basefont the base font name
+ * @param encoding the character encoding schema used by the font
+ */
+ public PDFFont(int number, String fontname, String basefont,
+ String encoding) {
+
+ /* generic creation of PDF object */
+ super(number);
+
+ /* set fields using paramaters */
+ this.fontname = fontname;
+ this.basefont = basefont;
+ this.encoding = encoding;
+ }
+
+ /**
+ * get the internal name used for this font
+ *
+ * @return the internal name
+ */
+ public String getName() {
+ return this.fontname;
+ }
+
+ /**
+ * produce the PDF representation for the object
+ *
+ * @return the PDF
+ */
+ public String toPDF() {
+ String p = this.number + " " + this.generation
+ + " obj\n<< /Type /Font\n/Subtype /Type1\n/Name /"
+ + this.fontname + "\n/BaseFont /" + this.basefont
+ + "\n/Encoding /"+ this.encoding + " >>\nendobj\n";
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * class representing an /Info object
+ */
+public class PDFInfo extends PDFObject {
+
+ /** the application producing the PDF */
+ protected String producer;
+
+ /**
+ * create an Info object
+ *
+ * @param number the object's number
+ */
+ public PDFInfo(int number) {
+ super(number);
+ }
+
+ /**
+ * set the producer string
+ *
+ * @param producer the producer string
+ */
+ public void setProducer(String producer) {
+ this.producer = producer;
+ }
+
+ /**
+ * produce the PDF representation of the object
+ *
+ * @return the PDF
+ */
+ public String toPDF() {
+ String p = this.number + " " + this.generation
+ + " obj\n<< /Type /Info\n/Producer (" + this.producer
+ + ") >>\nendobj\n";
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * generic PDF object.
+ *
+ * A PDF Document is essentially a collection of these objects. A PDF
+ * Object has a number and a generation (although the generation will always
+ * be 0 in new documents).
+ */
+public abstract class PDFObject {
+
+ /** the object's number */
+ protected int number;
+
+ /** the object's generation (0 in new documents) */
+ protected int generation = 0;
+
+ /**
+ * create an empty object
+ *
+ * @param number the object's number
+ */
+ public PDFObject(int number) {
+ this.number = number;
+ }
+
+ /**
+ * write the PDF represention of this object
+ *
+ * @param writer the PrintWriter to write the PDF to
+ * @return the number of characters written
+ */
+ protected int output(PrintWriter writer) throws IOException {
+ String pdf = this.toPDF();
+ writer.write(pdf);
+ return pdf.length();
+ }
+
+ /**
+ * the PDF representation of a reference to this object
+ *
+ * @return the reference string
+ */
+ protected String referencePDF() {
+ String p = this.number + " " + this.generation + " R";
+ return p;
+ }
+
+ /**
+ * represent object as PDF
+ *
+ * @return PDF string
+ */
+ abstract String toPDF();
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/**
+ * class representing a /Page object.
+ *
+ * There is one of these for every page in a PDF document. The object
+ * specifies the dimensions of the page and references a /Resources
+ * object, a contents stream and the page's parent in the page
+ * hierarchy.
+ */
+public class PDFPage extends PDFObject {
+
+ /** the page's parent, a /Pages object */
+ protected PDFPages parent;
+
+ /** the page's /Resource object */
+ protected PDFResources resources;
+
+ /** the contents stream */
+ protected PDFStream contents;
+
+ /** the width of the page in points */
+ protected int pagewidth;
+
+ /** the height of the page in points */
+ protected int pageheight;
+
+ /**
+ * create a /Page object
+ *
+ * @param number the object's number
+ * @param resources the /Resources object
+ * @param contents the content stream
+ * @param pagewidth the page's width in points
+ * @param pageheight the page's height in points
+ */
+ public PDFPage(int number, PDFResources resources,
+ PDFStream contents, int pagewidth,
+ int pageheight) {
+
+ /* generic creation of object */
+ super(number);
+
+ /* set fields using parameters */
+ this.resources = resources;
+ this.contents = contents;
+ this.pagewidth = pagewidth;
+ this.pageheight = pageheight;
+ }
+
+ /**
+ * set this page's parent
+ *
+ * @param parent the /Pages object that is this page's parent
+ */
+ public void setParent(PDFPages parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * represent this object as PDF
+ *
+ * @return the PDF string
+ */
+ public String toPDF() {
+ String p = this.number + " " + this.generation
+ + " obj\n<< /Type /Page\n/Parent "
+ + this.parent.referencePDF() + "\n/MediaBox [ 0 0 "
+ + this.pagewidth + " " + this.pageheight + " ]\n/Resources "
+ + this.resources.referencePDF() + "\n/Contents "
+ + this.contents.referencePDF() + " >>\nendobj\n";
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/**
+ * class representing a /Pages object.
+ *
+ * A /Pages object is an ordered collection of pages (/Page objects)
+ * (Actually, /Pages can contain further /Pages as well but this
+ * implementation doesn't allow this)
+ */
+public class PDFPages extends PDFObject {
+
+ /** the /Page objects */
+ protected Vector kids = new Vector();
+
+ /** the number of /Page objects */
+ protected int count = 0;
+
+ // private PDFPages parent;
+
+ /**
+ * create a /Pages object.
+ *
+ * @param number the object's number
+ */
+ public PDFPages(int number) {
+
+ /* generic creation of object */
+ super(number);
+ }
+
+ /**
+ * add a /Page object.
+ *
+ * @param page the PDFPage to add.
+ */
+ public void addPage(PDFPage page) {
+ this.kids.addElement(page);
+ page.setParent(this);
+ }
+
+ /**
+ * get the count of /Page objects
+ *
+ * @return the number of pages
+ */
+ public int getCount() {
+ return this.count;
+ }
+
+ /**
+ * represent the object in PDF
+ *
+ * @return the PDF string
+ */
+ public String toPDF() {
+ StringBuffer p = new StringBuffer(this.number + " "
+ + this.generation
+ + " obj\n<< /Type /Pages\n/Count "
+ + this.getCount() + "\n/Kids [");
+ for (int i = 0; i < kids.size(); i++) {
+ p = p.append(((PDFObject)kids.elementAt(i)).referencePDF() + " ");
+ }
+ p = p.append("] >>\nendobj\n");
+ return p.toString();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Hashtable;
+
+/**
+ * class representing a /Resources object.
+ *
+ * /Resources object contain a list of references to the fonts for the
+ * document
+ */
+public class PDFResources extends PDFObject {
+
+ /** /Font objects keyed by their internal name */
+ protected Hashtable fonts = new Hashtable();
+
+ protected Vector xObjects;
+
+ /**
+ * create a /Resources object.
+ *
+ * @param number the object's number
+ */
+ public PDFResources(int number) {
+
+ /* generic creation of object */
+ super(number);
+ }
+
+ /**
+ * add font object to resources list.
+ *
+ * @param font the PDFFont to add
+ */
+ public void addFont(PDFFont font) {
+ this.fonts.put(font.getName(),font);
+ }
+
+ public void setXObjects(Vector xObjects) {
+ this.xObjects = xObjects;
+ }
+
+ /**
+ * represent the object in PDF
+ *
+ * @return the PDF
+ */
+ public String toPDF() {
+ StringBuffer p = new StringBuffer(this.number + " "
+ + this.generation
+ + " obj\n<< /Font << ");
+
+ /* construct PDF dictionary of font object references */
+ Enumeration fontEnumeration = fonts.keys();
+ while (fontEnumeration.hasMoreElements()) {
+ String fontName = (String) fontEnumeration.nextElement();
+ p = p.append("/" + fontName + " "
+ + ((PDFFont) fonts.get(fontName)).referencePDF()
+ + "\n");
+ }
+
+ p = p.append(">>\n/ProcSet [ /PDF /ImageC /Text ] ");
+
+ if (!this.xObjects.isEmpty()) {
+ p = p.append("/XObject <<");
+ for (int i = 1; i < this.xObjects.size(); i++) {
+ p = p.append("/Im" + i + " " +
+ ((PDFXObject)
+ this.xObjects.elementAt(i -
+ 1)).referencePDF()
+ +
+ " \n");
+ }
+ }
+
+ p = p.append(">>\nendobj\n");
+
+ return p.toString();
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * class representing a Root (/Catalog) object
+ */
+public class PDFRoot extends PDFObject {
+
+ /** the /Pages object that is root of the Pages hierarchy */
+ protected PDFPages rootPages;
+
+ /**
+ * create a Root (/Catalog) object
+ *
+ * @param number the object's number
+ */
+ public PDFRoot(int number) {
+ super(number);
+ }
+
+ /**
+ * add a /Page object to the root /Pages object
+ *
+ * @param page the /Page object to add
+ */
+ public void addPage(PDFPage page) {
+ this.rootPages.addPage(page);
+ }
+
+ /**
+ * set the root /Pages object
+ *
+ * @param pages the /Pages object to set as root
+ */
+ public void setRootPages(PDFPages pages) {
+ this.rootPages = pages;
+ }
+
+ /**
+ * represent the object as PDF
+ *
+ * @return the PDF string
+ */
+ public String toPDF() {
+ String p = this.number + " " + this.generation
+ + " obj\n<< /Type /Catalog\n/Pages "
+ + this.rootPages.referencePDF() + " >>\nendobj\n";
+ return p;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.pdf;
+
+/**
+ * class representing a PDF stream.
+ *
+ * A derivative of the PDF Object, a PDF Stream has not only a dictionary
+ * but a stream of PDF commands. The stream of commands is where the real
+ * work is done, the dictionary just provides information like the stream
+ * length.
+ */
+public class PDFStream extends PDFObject {
+
+ /** the stream of PDF commands */
+ protected StringBuffer data = new StringBuffer();
+
+ /**
+ * create an empty stream object
+ *
+ * @param number the object's number
+ */
+ public PDFStream(int number) {
+ super(number);
+ }
+
+ /**
+ * append data to the stream
+ *
+ * @param s the string of PDF to add
+ */
+ public void add(String s) {
+ this.data = this.data.append(s);
+ }
+
+ /**
+ * append an array of xRGB pixels, ASCII Hex Encoding it first
+ *
+ * @param pixels the area of pixels
+ * @param width the width of the image in pixels
+ * @param height the height of the image in pixels
+ */
+ public void addImageArray(int[] pixels, int width, int height) {
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ int p = pixels[i * width + j];
+ int r = (p >> 16) & 0xFF;
+ int g = (p >> 8) & 0xFF;
+ int b = (p ) & 0xFF;
+ if (r < 16) {
+ this.data = this.data.append(0);
+ }
+ this.data = this.data.append(Integer.toHexString(r));
+ if (g < 16) {
+ this.data = this.data.append(0);
+ }
+ this.data = this.data.append(Integer.toHexString(g));
+ if (b < 16) {
+ this.data = this.data.append(0);
+ }
+ this.data = this.data.append(Integer.toHexString(b));
+ this.data = this.data.append(" ");
+ }
+ }
+ this.data = this.data.append(">\n");
+ }
+
+ /**
+ * represent as PDF.
+ *
+ * @return the PDF string.
+ */
+ public String toPDF() {
+ String p = this.number + " " + this.generation
+ + " obj\n<< /Length " + (this.data.length()+1)
+ + " >>\nstream\n" + this.data + "\nendstream\nendobj\n";
+ return p;
+ }
+}
--- /dev/null
+/* modified by JKT to integrate with 0.12.0 */
+
+package org.apache.xml.fop.pdf;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+// shouldn't have to do this
+import org.apache.xml.fop.image.*;
+
+/**
+ * PDF XObject
+ *
+ * A derivative of the PDF Object, is a PDF Stream that has not only a
+ * dictionary but a stream of image data.
+ * the dictionary just provides information like the stream length
+ */
+public class PDFXObject extends PDFObject {
+
+ FopImage fopimage;
+ int[] map;
+ 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) {
+ super(number);
+ this.Xnum=Xnumber;
+ if (img == null)
+ System.err.println("FISH");
+ this.map = img.getimagemap();
+ fopimage=img;
+ }
+
+ /**
+ * represent as PDF
+ */
+ protected int output(PrintWriter writer) throws IOException {
+ int length=0;
+ int i=0;
+ int x,y;
+ int ncc=(fopimage.getcolor()? 3 : 1);//Number of Color Channels
+ int size=(fopimage.getpixelwidth())*(fopimage.getpixelheight()*ncc);
+ String p;
+ String pdf = this.toPDF();
+ // push the pdf dictionary on the writer
+ writer.write(pdf);
+ length +=pdf.length();
+ p = (size*2+1) + " >>\n";
+ p = p + "stream\n";
+ writer.write(p);
+ length +=p.length();
+ // push all the image data on the writer and takes care of length for trailer
+ for (y=fopimage.getpixelheight()-1;y>=0;y--)
+ {
+ for (x=0;x<fopimage.getpixelwidth()*ncc;x++)
+ {
+ i=y*fopimage.getpixelwidth()*ncc+x;
+ if (this.map[i]<16)
+ {
+ writer.write("0");
+ writer.write(Integer.toHexString(this.map[i]));
+ length++;
+ length++;
+ }else
+ {
+ writer.write(Integer.toHexString(this.map[i]));
+ length++;
+ length++;
+ }
+ }
+ }
+ // close the object
+ p = ">";
+ p += "\nendstream\nendobj\n";
+ writer.write(p);
+ length +=p.length();
+ return length;
+ }
+
+ String toPDF() {
+ 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 + "/Width "+fopimage.getpixelwidth()+"\n";
+ p = p + "/Height "+fopimage.getpixelheight()+"\n";
+ p = p + "/BitsPerComponent 8\n";
+ if (fopimage.getcolor())
+ p = p + "/ColorSpace /DeviceRGB\n";
+ else
+ p = p + "/ColorSpace /DeviceGray\n";
+ p = p + "/Filter /ASCIIHexDecode\n";
+ p = p + "/Length ";
+ return p;
+ }
+}
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.pdf Package</TITLE>
+<BODY>
+<P>Classes for handling the low-level creation of PDF documents</P>
+<P>These classes were developed for FOP, but could be used by other
+applications wishing to produce PDF.</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=pdf \
+ xml
+
+SOURCES=Renderer.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.render;
+
+// FOP
+import org.apache.xml.fop.svg.SVGArea;
+import org.apache.xml.fop.image.ImageArea;
+import org.apache.xml.fop.layout.*;
+
+// Java
+import java.io.PrintWriter;
+import java.io.IOException;
+
+/**
+ * interface implement by all renderers.
+ *
+ * a Renderer implementation takes areas/spaces and produces output in
+ * some format.
+ */
+public interface Renderer {
+
+ /** set up the given FontInfo */
+ public void setupFontInfo(FontInfo fontInfo);
+
+ /** set the producer of the rendering */
+ public void setProducer(String producer);
+
+ /** render the given area tree to the given writer */
+ public void render(AreaTree areaTree, PrintWriter writer) throws IOException;
+
+ /** render the given area container */
+ public void renderAreaContainer(AreaContainer area);
+
+ /** render the given block area */
+ public void renderBlockArea(BlockArea area);
+
+ /** render the given display space */
+ public void renderDisplaySpace(DisplaySpace space);
+
+ /** render the given SVG area */
+ public void renderSVGArea(SVGArea area);
+
+ /** render the given image area */
+ public void renderImageArea(ImageArea area);
+
+ /** render the given inline area */
+ public void renderInlineArea(InlineArea area);
+
+ /** render the given inline space */
+ public void renderInlineSpace(InlineSpace space);
+
+ /** render the given line area */
+ public void renderLineArea(LineArea area);
+
+ /** render the given page */
+ public void renderPage(Page page);
+
+ /** render the given rule area */
+ public void renderRuleArea(RuleArea area);
+}
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.render Package</TITLE>
+<BODY>
+<P>generic renderer interface</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+package org.apache.xml.fop.render.pdf;
+
+// FOP
+import org.apache.xml.fop.layout.FontMetric;
+
+/**
+ * base class for PDF font classes
+ */
+public abstract class Font implements FontMetric {
+
+ /**
+ * get the encoding of the font
+ */
+ public abstract String encoding();
+
+ /**
+ * get the base font name
+ */
+ public abstract String fontName();
+}
--- /dev/null
+package org.apache.xml.fop.render.pdf;
+
+// FOP
+import org.apache.xml.fop.render.pdf.fonts.*;
+import org.apache.xml.fop.layout.FontInfo;
+import org.apache.xml.fop.pdf.PDFDocument;
+import org.apache.xml.fop.pdf.PDFResources;
+
+// Java
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * sets up the PDF fonts.
+ *
+ * Assigns the font (with metrics) to internal names like "F1" and
+ * assigns family-style-weight triplets to the fonts
+ */
+public class FontSetup {
+
+ /**
+ * sets up the font info object.
+ *
+ * adds metrics for basic fonts and useful family-style-weight
+ * triplets for lookup
+ *
+ * @param fontInfo the font info object to set up
+ */
+ public static void setup(FontInfo fontInfo) {
+ System.err.println("setting up fonts");
+
+ fontInfo.addMetrics("F1", new Helvetica());
+ fontInfo.addMetrics("F2", new HelveticaOblique());
+ fontInfo.addMetrics("F3", new HelveticaBold());
+ fontInfo.addMetrics("F4", new HelveticaBoldOblique());
+ fontInfo.addMetrics("F5", new TimesRoman());
+ fontInfo.addMetrics("F6", new TimesItalic());
+ fontInfo.addMetrics("F7", new TimesBold());
+ fontInfo.addMetrics("F8", new TimesBoldItalic());
+ fontInfo.addMetrics("F9", new Courier());
+ fontInfo.addMetrics("F10", new CourierOblique());
+ fontInfo.addMetrics("F11", new CourierBold());
+ fontInfo.addMetrics("F12", new CourierBoldOblique());
+
+ /* any is treated as serif */
+ fontInfo.addFontProperties("F5", "any", "normal", "normal");
+ fontInfo.addFontProperties("F6", "any", "italic", "normal");
+ fontInfo.addFontProperties("F6", "any", "oblique", "normal");
+ fontInfo.addFontProperties("F7", "any", "normal", "bold");
+ fontInfo.addFontProperties("F8", "any", "italic", "bold");
+ fontInfo.addFontProperties("F8", "any", "oblique", "bold");
+
+ fontInfo.addFontProperties("F1", "sans-serif", "normal",
+ "normal");
+ fontInfo.addFontProperties("F2", "sans-serif", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F2", "sans-serif", "italic",
+ "normal");
+ fontInfo.addFontProperties("F3", "sans-serif", "normal",
+ "bold");
+ fontInfo.addFontProperties("F4", "sans-serif", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F4", "sans-serif", "italic",
+ "bold");
+ fontInfo.addFontProperties("F5", "serif", "normal", "normal");
+ fontInfo.addFontProperties("F6", "serif", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F6", "serif", "italic", "normal");
+ fontInfo.addFontProperties("F7", "serif", "normal", "bold");
+ fontInfo.addFontProperties("F8", "serif", "oblique", "bold");
+ fontInfo.addFontProperties("F8", "serif", "italic", "bold");
+ fontInfo.addFontProperties("F9", "monospace", "normal",
+ "normal");
+ fontInfo.addFontProperties("F10", "monospace", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F10", "monospace", "italic",
+ "normal");
+ fontInfo.addFontProperties("F11", "monospace", "normal",
+ "bold");
+ fontInfo.addFontProperties("F12", "monospace", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F12", "monospace", "italic",
+ "bold");
+
+ fontInfo.addFontProperties("F1", "Helvetica", "normal",
+ "normal");
+ fontInfo.addFontProperties("F2", "Helvetica", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F2", "Helvetica", "italic",
+ "normal");
+ fontInfo.addFontProperties("F3", "Helvetica", "normal",
+ "bold");
+ fontInfo.addFontProperties("F4", "Helvetica", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F4", "Helvetica", "italic",
+ "bold");
+ fontInfo.addFontProperties("F5", "Times", "normal", "normal");
+ fontInfo.addFontProperties("F6", "Times", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F6", "Times", "italic", "normal");
+ fontInfo.addFontProperties("F7", "Times", "normal", "bold");
+ fontInfo.addFontProperties("F8", "Times", "oblique", "bold");
+ fontInfo.addFontProperties("F8", "Times", "italic", "bold");
+ fontInfo.addFontProperties("F9", "Courier", "normal",
+ "normal");
+ fontInfo.addFontProperties("F10", "Courier", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F10", "Courier", "italic",
+ "normal");
+ fontInfo.addFontProperties("F11", "Courier", "normal",
+ "bold");
+ fontInfo.addFontProperties("F12", "Courier", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F12", "Courier", "italic",
+ "bold");
+
+ /* for compatibility with PassiveTex */
+ fontInfo.addFontProperties("F5", "Times-Roman", "normal",
+ "normal");
+ fontInfo.addFontProperties("F6", "Times-Roman", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F6", "Times-Roman", "italic",
+ "normal");
+ fontInfo.addFontProperties("F7", "Times-Roman", "normal",
+ "bold");
+ fontInfo.addFontProperties("F8", "Times-Roman", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F8", "Times-Roman", "italic",
+ "bold");
+ fontInfo.addFontProperties("F5", "Times Roman", "normal",
+ "normal");
+ fontInfo.addFontProperties("F6", "Times Roman", "oblique",
+ "normal");
+ fontInfo.addFontProperties("F6", "Times Roman", "italic",
+ "normal");
+ fontInfo.addFontProperties("F7", "Times Roman", "normal",
+ "bold");
+ fontInfo.addFontProperties("F8", "Times Roman", "oblique",
+ "bold");
+ fontInfo.addFontProperties("F8", "Times Roman", "italic",
+ "bold");
+ fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
+ "normal", "normal");
+ }
+
+ /**
+ * add the fonts in the font info to the PDF document
+ *
+ * @param doc PDF document to add fonts to
+ * @param fontInfo font info object to get font information from
+ */
+ public static void addToResources(PDFDocument doc, FontInfo fontInfo) {
+ Hashtable fonts = fontInfo.getFonts();
+ Enumeration e = fonts.keys();
+ PDFResources resources = doc.getResources();
+ while (e.hasMoreElements()) {
+ String f = (String) e.nextElement();
+ resources.addFont(doc.makeFont(f,
+ ((Font)
+ fonts.get(f)).fontName(),
+ ((Font)
+ fonts.get(f)).encoding()
+ )
+ );
+ }
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=fonts
+
+SOURCES= \
+ Font.java \
+ FontSetup.java \
+ PDFRenderer.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.render.pdf;
+
+// FOP
+import org.apache.xml.fop.render.Renderer;
+import org.apache.xml.fop.image.ImageArea;
+import org.apache.xml.fop.image.FopImage;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.svg.*;
+import org.apache.xml.fop.pdf.*;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+
+/**
+ * Renderer that renders areas to PDF
+ */
+public class PDFRenderer implements Renderer {
+
+ /** the PDF Document being created */
+ protected PDFDocument pdfDoc;
+
+ /** the /Resources object of the PDF document being created */
+ protected PDFResources pdfResources;
+
+ /** the current stream to add PDF commands to */
+ PDFStream currentStream;
+
+ /** the current (internal) font name */
+ protected String currentFontName;
+
+ /** the current font size in millipoints */
+ protected int currentFontSize;
+
+ /** the current colour's red component */
+ protected float currentRed = 0;
+
+ /** the current colour's green component */
+ protected float currentGreen = 0;
+
+ /** the current colour's blue component */
+ protected float currentBlue = 0;
+
+ /** the current vertical position in millipoints from bottom */
+ protected int currentYPosition = 0;
+
+ /** the current horizontal position in millipoints from left */
+ protected int currentXPosition = 0;
+
+ /** the horizontal position of the current area container */
+ private int currentAreaContainerXPosition = 0;
+
+ /**
+ * create the PDF renderer
+ */
+ public PDFRenderer() {
+ this.pdfDoc = new PDFDocument();
+ }
+
+ /**
+ * set the PDF document's producer
+ *
+ * @param producer string indicating application producing PDF
+ */
+ public void setProducer(String producer) {
+ this.pdfDoc.setProducer(producer);
+ }
+
+ /**
+ * render the areas into PDF
+ *
+ * @param areaTree the laid-out area tree
+ * @param writer the PrintWriter to write the PDF with
+ */
+ public void render(AreaTree areaTree, PrintWriter writer) throws IOException {
+ System.err.println("rendering areas to PDF");
+ this.pdfResources = this.pdfDoc.getResources();
+ Enumeration e = areaTree.getPages().elements();
+ while (e.hasMoreElements()) {
+ this.renderPage((Page) e.nextElement());
+ }
+ System.err.println("writing out PDF");
+ this.pdfDoc.output(writer);
+ }
+
+ /**
+ * 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
+ */
+ protected void addLine(int x1, int y1, int x2, int y2, int th,
+ float r, float g, float b) {
+ currentStream.add(r + " " + g + " " + b + " RG\n"
+ + (x1/1000f) + " " + (y1/1000f) + " m "
+ + (x2/1000f) + " " + (y2/1000f) + " l "
+ + (th/1000f) + " w S\n"
+ + "0 0 0 RG\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 r the red component
+ * @param g the green component
+ * @param b the blue component
+ */
+ protected void addRect(int x, int y, int w, int h,
+ float r, float g, float b) {
+ currentStream.add(r + " " + g + " " + b + " RG\n"
+ + (x/1000f) + " " + (y/1000f) + " "
+ + (w/1000f) + " " + (h/1000f) + " re S\n"
+ + "0 0 0 RG\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 r the red component of edges
+ * @param g the green component of edges
+ * @param b the blue component of edges
+ * @param fr the red component of the fill
+ * @param fg the green component of the fill
+ * @param fb the blue component of the fill
+ */
+ protected void addRect(int x, int y, int w, int h,
+ float r, float g, float b,
+ float fr, float fg, float fb) {
+ currentStream.add(fr + " " + fg + " " + fb + " rg\n"
+ + r + " " + g + " " + b + " RG\n"
+ + (x/1000f) + " " + (y/1000f) + " "
+ + (w/1000f) + " " + (h/1000f) + " re S\n"
+ + (x/1000f) + " " + (y/1000f) + " "
+ + (w/1000f) + " " + (h/1000f) + " re f\n"
+ + "0 0 0 RG 0 0 0 rg\n");
+ }
+
+ /**
+ * render area container to PDF
+ *
+ * @param area the area container to render
+ */
+ public void renderAreaContainer(AreaContainer area) {
+
+ /* move into position */
+ currentStream.add("1 0 0 1 "
+ + (area.getXPosition()/1000f) + " "
+ + (area.getYPosition()/1000f) + " Tm\n");
+
+ this.currentYPosition = area.getYPosition();
+ this.currentAreaContainerXPosition = area.getXPosition();
+
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ }
+
+ /**
+ * render block area to PDF
+ *
+ * @param area the block area to render
+ */
+ public void renderBlockArea(BlockArea area) {
+ int rx = this.currentAreaContainerXPosition
+ + area.getStartIndent();
+ int ry = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ }
+
+ /**
+ * render display space to PDF
+ *
+ * @param space the display space to render
+ */
+ public void renderDisplaySpace(DisplaySpace space) {
+ int d = space.getSize();
+ this.currentYPosition -= d;
+ }
+
+ /**
+ * render image area to PDF
+ *
+ * @param area the image area to render
+ */
+ public void renderImageArea(ImageArea area) {
+ // adapted from contribution by BoBoGi
+ int x = this.currentAreaContainerXPosition +
+ area.getXOffset();
+ int y = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+
+ this.currentYPosition -= h*1000;
+
+ FopImage img = area.getImage();
+
+ int xObjectNum = this.pdfDoc.addImage(img);
+
+ currentStream.add("ET\nq\n" + (img.getWidth()/1000f) + " 0 0 " +
+ (img.getHeight()/1000f) + " " +
+ ((x + img.getX())/1000f) + " " +
+ (((y - h) - img.getY())/1000f) + " cm\n" +
+ "/Im" + xObjectNum + " Do\nQ\nBT\n");
+ }
+
+ /**
+ * render SVG area to PDF
+ *
+ * @param area the SVG area to render
+ */
+ public void renderSVGArea(SVGArea area) {
+ int x = this.currentAreaContainerXPosition;
+ int y = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+ this.currentYPosition -= h;
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof RectGraphic) {
+ int rx = ((RectGraphic)o).x;
+ int ry = ((RectGraphic)o).y;
+ int rw = ((RectGraphic)o).width;
+ int rh = ((RectGraphic)o).height;
+ addRect(x+rx,y-ry,rw,-rh,0,0,0);
+ } else if (o instanceof LineGraphic) {
+ int x1 = ((LineGraphic)o).x1;
+ int y1 = ((LineGraphic)o).y1;
+ int x2 = ((LineGraphic)o).x2;
+ int y2 = ((LineGraphic)o).y2;
+ addLine(x+x1,y-y1,x+x2,y-y2,0,0,0,0);
+ } else if (o instanceof TextGraphic) {
+ int tx = ((TextGraphic)o).x;
+ int ty = ((TextGraphic)o).y;
+ String s = ((TextGraphic)o).s;
+ currentStream.add("1 0 0 1 "
+ + ((x+tx)/1000f) + " "
+ + ((y-ty)/1000f) + " Tm "
+ + "(" + s + ") Tj\n");
+ }
+ }
+ }
+
+ /**
+ * render inline area to PDF
+ *
+ * @param area inline area to render
+ */
+ public void renderInlineArea(InlineArea area) {
+ char ch;
+ StringBuffer pdf = new StringBuffer();
+
+ String name = area.getFontState().getFontName();
+ int size = area.getFontState().getFontSize();
+
+ float red = area.getRed();
+ float green = area.getGreen();
+ float blue = area.getBlue();
+
+ if ((!name.equals(this.currentFontName))
+ || (size != this.currentFontSize)) {
+ this.currentFontName = name;
+ this.currentFontSize = size;
+ pdf = pdf.append("/" + name + " " + (size/1000) + " Tf\n");
+ }
+
+ if ((red != this.currentRed)
+ || (green != this.currentGreen)
+ || (blue != this.currentBlue)) {
+ this.currentRed = red;
+ this.currentGreen = green;
+ this.currentBlue = blue;
+ pdf = pdf.append(red + " " + green + " " + blue + " rg\n");
+ }
+
+ int rx = this.currentXPosition;
+ int bl = this.currentYPosition;
+
+ pdf = pdf.append("1 0 0 1 "
+ +(rx/1000f) + " " + (bl/1000f)
+ + " Tm (");
+
+ String s = area.getText();
+ int l = s.length();
+
+ for (int i=0; i < l; i++) {
+ ch = s.charAt(i);
+ if (ch > 127) {
+ pdf = pdf.append("\\");
+ pdf = pdf.append(Integer.toOctalString((int)ch));
+ } else {
+ switch (ch) {
+ case '(' : pdf = pdf.append("\\("); break;
+ case ')' : pdf = pdf.append("\\)"); break;
+ case '\\' : pdf = pdf.append("\\\\"); break;
+ default : pdf = pdf.append(ch); break;
+ }
+ }
+ }
+ pdf = pdf.append(") Tj\n");
+
+ currentStream.add(pdf.toString());
+
+ this.currentXPosition += area.getContentWidth();
+ }
+
+ /**
+ * render inline space to PDF
+ *
+ * @param space space to render
+ */
+ public void renderInlineSpace(InlineSpace space) {
+ this.currentXPosition += space.getSize();
+ }
+
+ /**
+ * render line area to PDF
+ *
+ * @param area area to render
+ */
+ public void renderLineArea(LineArea area) {
+ int rx = this.currentAreaContainerXPosition
+ + area.getStartIndent();
+ int ry = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+
+ this.currentYPosition -= area.getPlacementOffset();
+ this.currentXPosition = rx;
+
+ int bl = this.currentYPosition;
+
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+
+ this.currentYPosition = ry-h;
+ }
+
+ /**
+ * render page into PDF
+ *
+ * @param page page to render
+ */
+ public void renderPage(Page page) {
+ AreaContainer body, before, after;
+
+ currentStream = this.pdfDoc.makeStream();
+ body = page.getBody();
+ before = page.getBefore();
+ after = page.getAfter();
+
+ this.currentFontName = "";
+ this.currentFontSize = 0;
+
+ currentStream.add("BT\n");
+ renderAreaContainer(body);
+
+ if (before != null) {
+ renderAreaContainer(before);
+ }
+
+ if (after != null) {
+ renderAreaContainer(after);
+ }
+
+ currentStream.add("ET\n");
+
+ this.pdfDoc.makePage(this.pdfResources, currentStream,
+ page.getWidth()/1000, page.getHeight()/1000);
+ }
+
+ /**
+ * render rule area into PDF
+ *
+ * @param area area to render
+ */
+ public void renderRuleArea(RuleArea area) {
+ int rx = this.currentAreaContainerXPosition
+ + area.getStartIndent();
+ int ry = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+ int th = area.getRuleThickness();
+ float r = area.getRed();
+ float g = area.getGreen();
+ float b = area.getBlue();
+
+ addLine(rx, ry, rx+w, ry, th, r, g, b);
+ }
+
+ /**
+ * set up the font info
+ *
+ * @param fontInfo font info to set up
+ */
+ public void setupFontInfo(FontInfo fontInfo) {
+ FontSetup.setup(fontInfo);
+ FontSetup.addToResources(this.pdfDoc, fontInfo);
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=
+
+CLASSES=
+
+all: allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.render.pdf.fonts Package</TITLE>
+<BODY>
+<P>PDF font information/metrics</P>
+<P>Generated entirely from XML files.</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.render.pdf Package</TITLE>
+<BODY>
+<P>classes for rendering to PDF</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+
+
+BASEDIR:=../../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=XMLRenderer.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.render.xml;
+
+// FOP
+import org.apache.xml.fop.svg.*;
+import org.apache.xml.fop.render.Renderer;
+import org.apache.xml.fop.image.ImageArea;
+import org.apache.xml.fop.layout.*;
+import org.apache.xml.fop.pdf.*;
+
+// Java
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+
+/**
+ * Renderer that renders areas to XML for debugging purposes.
+ */
+public class XMLRenderer implements Renderer {
+
+ /** indentation to use for pretty-printing the XML */
+ protected int indent = 0;
+
+ /** the application producing the XML */
+ protected String producer;
+
+ /** the writer used to output the XML */
+ protected PrintWriter writer;
+
+ /**
+ * set the document's producer
+ *
+ * @param producer string indicating application producing the XML
+ */
+ public void setProducer(String producer) {
+ this.producer = producer;
+ }
+
+ /**
+ * render the areas into XML
+ *
+ * @param areaTree the laid-out area tree
+ * @param writer the PrintWriter to give the XML to
+ */
+ public void render(AreaTree areaTree, PrintWriter writer)
+ throws IOException {
+ System.err.println("rendering areas to XML");
+ this.writer = writer;
+ this.writer.write("<?xml version=\"1.0\"?>\n<!-- produced by "
+ + this.producer + " -->\n");
+ writeStartTag("<AreaTree>");
+ Enumeration e = areaTree.getPages().elements();
+ while (e.hasMoreElements()) {
+ this.renderPage((Page) e.nextElement());
+ }
+ writeEndTag("</AreaTree>");
+ this.writer.flush();
+ System.err.println("written out XML");
+ }
+
+ /**
+ * write out spaces to make indent
+ */
+ protected void writeIndent() {
+ StringBuffer s = new StringBuffer();
+ for (int i= 0; i<this.indent; i++) {
+ s = s.append(" ");
+ }
+ this.writer.write(s.toString());
+ }
+
+ /**
+ * write out an element
+ *
+ * @param element the full text of the element including tags
+ */
+ protected void writeElement(String element) {
+ writeIndent();
+ this.writer.write(element+"\n");
+ }
+
+ /**
+ * write out an empty-element-tag
+ *
+ * @param tag the text of the tag
+ */
+ protected void writeEmptyElementTag(String tag) {
+ writeIndent();
+ this.writer.write(tag + "\n");
+ }
+
+ /**
+ * write out an end tag
+ *
+ * @param tag the text of the tag
+ */
+ protected void writeEndTag(String tag) {
+ this.indent--;
+ writeIndent();
+ this.writer.write(tag + "\n");
+ }
+
+ /**
+ * write out a start tag
+ *
+ * @param tag the text of the tag
+ */
+ protected void writeStartTag(String tag) {
+ writeIndent();
+ this.writer.write(tag + "\n");
+ this.indent++;
+ }
+
+ /**
+ * set up the font info
+ *
+ * @param fontInfo the font info object to set up
+ */
+ public void setupFontInfo(FontInfo fontInfo) {
+
+ /* use PDF's font setup to get PDF metrics */
+ org.apache.xml.fop.render.pdf.FontSetup.setup(fontInfo);
+ }
+
+ /**
+ * render an area container to XML
+ *
+ * @param area the area container to render
+ */
+ public void renderAreaContainer(AreaContainer area) {
+ writeStartTag("<AreaContainer>");
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ writeEndTag("</AreaContainer>");
+ }
+
+ /**
+ * render a block area to XML
+ *
+ * @param area the block area to render
+ */
+ public void renderBlockArea(BlockArea area) {
+ writeStartTag("<BlockArea start-indent=\""
+ + area.getStartIndent()
+ + "\" end-indent=\""
+ + area.getEndIndent() + "\">");
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ writeEndTag("</BlockArea>");
+ }
+
+ /**
+ * render a display space to XML
+ *
+ * @param space the space to render
+ */
+ public void renderDisplaySpace(DisplaySpace space) {
+ writeEmptyElementTag("<DisplaySpace size=\""
+ + space.getSize() +"\"/>");
+ }
+
+ /**
+ * render an SVG area to XML
+ *
+ * @param area the area to render
+ */
+ public void renderSVGArea(SVGArea area) {
+ writeEmptyElementTag("<SVG/>");
+ }
+
+ /**
+ * render an image area to XML
+ *
+ * @param area the area to render
+ */
+ public void renderImageArea(ImageArea area) {
+ writeEmptyElementTag("<ImageArea/>");
+ }
+
+ /**
+ * render an inline area to XML
+ *
+ * @param area the area to render
+ */
+ public void renderInlineArea(InlineArea area) {
+ String fontWeight = area.getFontState().getFontWeight();
+ StringBuffer sb = new StringBuffer();
+ String s = area.getText();
+ int l = s.length();
+ for (int i=0; i < l; i++) {
+ char ch = s.charAt(i);
+ if (ch>127)
+ sb = sb.append("&#"+(int)ch+";");
+ else
+ sb = sb.append(ch);
+ }
+ writeElement("<InlineArea font-weight=\""
+ + fontWeight + "\" red=\""
+ + area.getRed() + "\" green=\""
+ + area.getGreen() + "\" blue = \""
+ + area.getBlue() + " width = \""
+ + area.getContentWidth() + "\">" + sb.toString()
+ + "</InlineArea>");
+ }
+
+ /**
+ * render an inline space to XML
+ *
+ * @param space the space to render
+ */
+ public void renderInlineSpace(InlineSpace space) {
+ writeEmptyElementTag("<InlineSpace size=\""
+ + space.getSize() +"\"/>");
+ }
+
+ /**
+ * render a line area to XML
+ *
+ * @param area the area to render
+ */
+ public void renderLineArea(LineArea area) {
+ String fontWeight = area.getFontState().getFontWeight();
+ writeStartTag("<LineArea font-weight=\""
+ + fontWeight + "\">");
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box)e.nextElement();
+ b.render(this);
+ }
+ writeEndTag("</LineArea>");
+ }
+
+ /**
+ * render a page to XML
+ *
+ * @param page the page to render
+ */
+ public void renderPage(Page page) {
+ AreaContainer body, before, after;
+ writeStartTag("<Page>");
+ body = page.getBody();
+ before = page.getBefore();
+ after = page.getAfter();
+ if (before != null) {
+ renderAreaContainer(before);
+ }
+ renderAreaContainer(body);
+ if (after != null) {
+ renderAreaContainer(after);
+ }
+ writeEndTag("</Page>");
+ }
+
+ /**
+ * render a rule area to XML
+ *
+ * @param area the area to render
+ */
+ public void renderRuleArea(RuleArea area) {
+ writeEmptyElementTag("<Rule start-indent=\""
+ + area.getStartIndent()
+ + "\" end-indent=\""
+ + area.getEndIndent()
+ + "\" rule-thickness=\""
+ + area.getRuleThickness()
+ + "\" red=\"" + area.getRed()
+ + "\" green=\"" + area.getGreen()
+ + "\" blue = \"" + area.getBlue()
+ + "\"/>");
+ }
+}
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.render.xml Package</TITLE>
+<BODY>
+<P>classes for rendering to XML for debugging</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+package org.apache.xml.fop.svg;
+
+/**
+ * base class for SVG graphic objects.
+ *
+ * Graphic objects include rectangles, lines and text
+ */
+public abstract class Graphic {}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * class representing svg:line pseudo flow object.
+ */
+public class Line extends FObj {
+
+ /**
+ * inner class for making Line objects.
+ */
+ public static class Maker extends FObj.Maker {
+
+ /**
+ * make a Line object.
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ *
+ * @return the Line object
+ */
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Line(parent, propertyList);
+ }
+ }
+
+ /**
+ * returns the maker for this object.
+ *
+ * @return the maker for Line objects
+ */
+ public static FObj.Maker maker() {
+ return new Line.Maker();
+ }
+
+ /**
+ * constructs a Line object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ */
+ protected Line(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "svg:line";
+ }
+
+ /**
+ * layout this formatting object.
+ *
+ * @param area the area to layout the object into
+ *
+ * @return the status of the layout
+ */
+ public int layout(Area area) throws FOPException {
+
+ /* retrieve properties */
+ int x1 = this.properties.get("x1").getLength().mvalue();
+ int x2 = this.properties.get("x2").getLength().mvalue();
+ int y1 = this.properties.get("y1").getLength().mvalue();
+ int y2 = this.properties.get("y2").getLength().mvalue();
+
+ /* if the area this is being put into is an SVGArea */
+ if (area instanceof SVGArea) {
+ /* add a line to the SVGArea */
+ ((SVGArea) area).addGraphic(new LineGraphic(x1, y1, x2, y2));
+ } else {
+ /* otherwise generate a warning */
+ System.err.println("WARNING: svg:line outside svg:svg");
+ }
+
+ /* return status */
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+/**
+ * class representing a line in an SVG Area
+ */
+public class LineGraphic extends Graphic {
+
+ /** x-coordinate of start */
+ public int x1;
+
+ /** y-coordinate of start */
+ public int y1;
+
+ /** x-coordinate of end */
+ public int x2;
+
+ /** y-coordinate of end */
+ public int y2;
+
+ /**
+ * construct a line graphic
+ *
+ * @param x1 x-coordinate of start
+ * @param y1 y-coordinate of start
+ * @param x2 x-coordinate of end
+ * @param y2 y-coordinate of end
+ */
+ public LineGraphic(int x1, int y1, int x2, int y2) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+}
--- /dev/null
+
+
+BASEDIR:=../../../../..
+include $(BASEDIR)/Makefile.rules
+
+SUBDIRS=
+
+SOURCES=Graphic.java \
+ Line.java \
+ LineGraphic.java \
+ Rect.java \
+ RectGraphic.java \
+ SVG.java \
+ SVGArea.java \
+ SVGElementMapping.java \
+ SVGLength.java \
+ Text.java \
+ TextGraphic.java
+
+CLASSES=$(SOURCES:.java=.class)
+
+all: $(CLASSES) allsubs
+
+clean: cleanme cleansubs
+
+cleanme:
+ rm -f *.class
+
+$(TARGETS:%=%subs): %subs :
+ for dir in $(SUBDIRS) ; do \
+ (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \
+ done
+
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * class representing svg:rect pseudo flow object.
+ */
+public class Rect extends FObj {
+
+ /**
+ * inner class for making Rect objects.
+ */
+ public static class Maker extends FObj.Maker {
+
+ /**
+ * make a Rect object.
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ *
+ * @return the Rect object
+ */
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Rect(parent, propertyList);
+ }
+ }
+
+ /**
+ * returns the maker for this object.
+ *
+ * @return the maker for Rect objects
+ */
+ public static FObj.Maker maker() {
+ return new Rect.Maker();
+ }
+
+ /**
+ * constructs a Rect object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ */
+ protected Rect(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "svg:rect";
+ }
+
+ /**
+ * layout this formatting object.
+ *
+ * @param area the area to layout the object into
+ *
+ * @return the status of the layout
+ */
+ public int layout(Area area) throws FOPException {
+
+ /* retrieve properties */
+ int width = this.properties.get("width").getLength().mvalue();
+ int height = this.properties.get("height").getLength().mvalue();
+ int x = this.properties.get("x").getLength().mvalue();
+ int y = this.properties.get("y").getLength().mvalue();
+
+ /* if the area this is being put into is an SVGArea */
+ if (area instanceof SVGArea) {
+ /* add a rectangle to the SVGArea */
+ ((SVGArea) area).addGraphic(new RectGraphic(x, y, width, height));
+ } else {
+ /* otherwise generate a warning */
+ System.err.println("WARNING: svg:rect outside svg:svg");
+ }
+
+ /* return status */
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+/**
+ * class representing a rectangle in an SVG Area
+ */
+public class RectGraphic extends Graphic {
+
+ /** x-coordinate of corner */
+ public int x;
+
+ /** y-coordinate of corner */
+ public int y;
+
+ /** width of rectangle */
+ public int width;
+
+ /** height of rectangle */
+ public int height;
+
+ /**
+ * construct a rectangle graphic.
+ *
+ * @param x x-coordinate of corner
+ * @param y y-coordinate of corner
+ * @param width width of rectangle
+ * @param height height of rectangle
+ */
+ public RectGraphic(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.BlockArea;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * class representing svg:svg pseudo flow object.
+ */
+public class SVG extends FObj {
+
+ /**
+ * inner class for making SVG objects.
+ */
+ public static class Maker extends FObj.Maker {
+
+ /**
+ * make an SVG object.
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ *
+ * @return the SVG object
+ */
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new SVG(parent, propertyList);
+ }
+ }
+
+ /**
+ * returns the maker for this object.
+ *
+ * @return the maker for SVG objects
+ */
+ public static FObj.Maker maker() {
+ return new SVG.Maker();
+ }
+
+ FontState fs;
+ int breakBefore;
+ int breakAfter;
+ int width;
+ int height;
+ int spaceBefore;
+ int spaceAfter;
+
+ /**
+ * constructs an SVG object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ */
+ public SVG(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "svg:svg";
+ }
+
+ /**
+ * layout this formatting object.
+ *
+ * @param area the area to layout the object into
+ *
+ * @return the status of the layout
+ */
+ public int layout(Area area) throws FOPException {
+
+ if (this.marker == BREAK_AFTER) {
+ return OK;
+ }
+
+ if (this.marker == START) {
+ /* retrieve properties */
+ String fontFamily = this.properties.get("font-family").getString();
+ String fontStyle = this.properties.get("font-style").getString();
+ String fontWeight = this.properties.get("font-weight").getString();
+ int fontSize = this.properties.get("font-size").getLength().mvalue();
+
+ this.fs = new FontState(area.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, fontSize);
+
+ this.breakBefore = this.properties.get("break-before").getEnum();
+ this.breakAfter = this.properties.get("break-after").getEnum();
+ this.width = this.properties.get("width").getLength().mvalue();
+ this.height = this.properties.get("height").getLength().mvalue();
+
+ this.spaceBefore =
+ this.properties.get("space-before.optimum").getLength().mvalue();
+ this.spaceAfter =
+ this.properties.get("space-after.optimum").getLength().mvalue();
+ /* if the SVG is embedded in a block area */
+ if (area instanceof BlockArea) {
+ /* temporarily end the block area */
+ area.end();
+ }
+
+ this.marker = 0;
+
+ if (breakBefore == BreakBefore.PAGE) {
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakBefore == BreakBefore.ODD_PAGE) {
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakBefore == BreakBefore.EVEN_PAGE) {
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+ }
+
+ /* if there is a space-before */
+ if (spaceBefore != 0) {
+ /* add a display space */
+ area.addDisplaySpace(spaceBefore);
+ }
+
+ /* create an SVG area */
+ SVGArea svgArea = new SVGArea(fs, width, height);
+ svgArea.start();
+
+ /* add the SVG area to the containing area */
+ area.addChild(svgArea);
+
+ /* iterate over the child formatting objects and lay them out
+ into the SVG area */
+ int numChildren = this.children.size();
+ for (int i = 0; i < numChildren; i++) {
+ FONode fo = (FONode) children.elementAt(i);
+ int status;
+ if ((status = fo.layout(svgArea)) != OK) {
+ return status;
+ }
+ }
+
+ /* finish off the SVG area */
+ svgArea.end();
+
+ /* increase the height of the containing area accordingly */
+ area.increaseHeight(svgArea.getHeight());
+
+ /* if there is a space-after */
+ if (spaceAfter != 0) {
+ /* add a display space */
+ area.addDisplaySpace(spaceAfter);
+ }
+
+ /* if the SVG is embedded in a block area */
+ if (area instanceof BlockArea) {
+ /* re-start the block area */
+ area.start();
+ }
+
+ if (breakAfter == BreakAfter.PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK;
+ }
+
+ if (breakAfter == BreakAfter.ODD_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_ODD;
+ }
+
+ if (breakAfter == BreakAfter.EVEN_PAGE) {
+ this.marker = BREAK_AFTER;
+ return FORCE_PAGE_BREAK_EVEN;
+ }
+
+ /* return status */
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.render.Renderer;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.layout.Area;
+
+/**
+ * class representing an SVG area in which the SVG graphics sit
+ */
+public class SVGArea extends Area {
+
+ /**
+ * construct an SVG area
+ *
+ * @param fontState the font state
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ public SVGArea(FontState fontState, int width, int height) {
+ super(fontState, width, height);
+ currentHeight = height;
+ contentRectangleWidth = width;
+ }
+
+ /**
+ * add a graphic.
+ *
+ * Graphics include SVG Rectangles, Lines and Text
+ *
+ * @param graphic the Graphic to add
+ */
+ public void addGraphic(Graphic graphic) {
+ this.children.addElement(graphic);
+ }
+
+ /**
+ * render the SVG.
+ *
+ * @param renderer the Renderer to use
+ */
+ public void render(Renderer renderer) {
+ renderer.renderSVGArea(this);
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+import org.apache.xml.fop.fo.FOTreeBuilder;
+import org.apache.xml.fop.fo.ElementMapping;
+
+public class SVGElementMapping implements ElementMapping {
+
+ public void addToBuilder(FOTreeBuilder builder) {
+ String uri = "http://www.w3.org/Graphics/SVG/SVG-19990812.dtd";
+ builder.addMapping(uri, "svg", SVG.maker());
+ builder.addMapping(uri, "rect", Rect.maker());
+ builder.addMapping(uri, "line", Line.maker());
+ builder.addMapping(uri, "text", Text.maker());
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.datatypes.*;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * a class representing all the length properties in SVG
+ */
+public class SVGLength extends Property {
+
+ /**
+ * inner class for making SVG Length objects.
+ */
+ public static class Maker extends Property.Maker {
+
+ /**
+ * whether this property is inherited or not.
+ *
+ * @return is this inherited?
+ */
+ public boolean isInherited() { return false; }
+
+ /**
+ * make an SVG Length property with the given value.
+ *
+ * @param propertyList the property list this is a member of
+ * @param value the explicit string value of the property
+ */
+ public Property make(PropertyList propertyList, String value)
+ throws FOPException {
+ return new SVGLength(propertyList, new Length(value));
+ }
+
+ /**
+ * make an SVG Length property with the default value.
+ *
+ * @param propertyList the property list the property is a member of
+ */
+ public Property make(PropertyList propertyList) throws FOPException {
+ return make(propertyList, "0pt");
+ }
+ }
+
+ /**
+ * returns the maker for this object.
+ *
+ * @return the maker for SVG Length objects
+ */
+ public static Property.Maker maker() {
+ return new SVGLength.Maker();
+ }
+
+ /** the length as a Length object */
+ protected Length value;
+
+ /**
+ * construct an SVG length (called by the Maker).
+ *
+ * @param propertyList the property list this is a member of
+ * @param explicitValue the explicit value as a Length object
+ */
+ protected SVGLength(PropertyList propertyList, Length explicitValue) {
+ this.propertyList = propertyList;
+ this.value = explicitValue;
+ }
+
+ /**
+ * get the length
+ *
+ * @return the length as a Length object
+ */
+ public Length getLength() {
+ return this.value;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+// FOP
+import org.apache.xml.fop.fo.*;
+import org.apache.xml.fop.fo.properties.*;
+import org.apache.xml.fop.layout.Area;
+import org.apache.xml.fop.layout.FontState;
+import org.apache.xml.fop.apps.FOPException;
+
+/**
+ * class representing svg:text pseudo flow object.
+ */
+public class Text extends FObjMixed {
+
+ /**
+ * inner class for making SVG Text objects.
+ */
+ public static class Maker extends FObj.Maker {
+
+ /**
+ * make an SVG Text object.
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ *
+ * @return the SVG Text object
+ */
+ public FObj make(FObj parent, PropertyList propertyList)
+ throws FOPException {
+ return new Text(parent, propertyList);
+ }
+ }
+
+ /**
+ * returns the maker for this object.
+ *
+ * @return the maker for SVG Text objects
+ */
+ public static FObj.Maker maker() {
+ return new Text.Maker();
+ }
+
+ /**
+ * the string of text to display
+ */
+ protected String text = "";
+
+ /**
+ * constructs an SVG Text object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param propertyList the explicit properties of this object
+ */
+ protected Text(FObj parent, PropertyList propertyList) {
+ super(parent, propertyList);
+ this.name = "svg:text";
+ }
+
+ /**
+ * add characters to the string to display.
+ *
+ * @param data array of characters
+ * @param start start offset in character array
+ * @param length number of characters to add
+ */
+ protected void addCharacters(char data[], int start, int length) {
+ this.text += new String(data, start, length);
+ }
+
+ /**
+ * layout this formatting object.
+ *
+ * @param area the area to layout the object into
+ *
+ * @return the status of the layout
+ */
+ public int layout(Area area) throws FOPException {
+
+ /* retrieve properties */
+ int x = this.properties.get("x").getLength().mvalue();
+ int y = this.properties.get("y").getLength().mvalue();
+
+ /* if the area this is being put into is an SVGArea */
+ if (area instanceof SVGArea) {
+ /* add the text to the SVGArea */
+ ((SVGArea) area).addGraphic(new TextGraphic(x, y, text));
+ } else {
+ /* otherwise generate a warning */
+ System.err.println("WARNING: svg:text outside svg:svg");
+ }
+
+ /* return status */
+ return OK;
+ }
+}
--- /dev/null
+package org.apache.xml.fop.svg;
+
+/**
+ * class representing text in an SVG Area
+ */
+public class TextGraphic extends Graphic {
+
+ /** x-coordinate of text */
+ public int x;
+
+ /** y-coordinate of text */
+ public int y;
+
+ /** the text string itself */
+ public String s;
+
+ /**
+ * construct a text graphic
+ *
+ * @param x x-coordinate of text
+ * @param y y-coordinate of text
+ * @param s the text string
+ */
+ public TextGraphic(int x, int y, String s) {
+ this.x = x;
+ this.y = y;
+ this.s = s;
+ }
+}
--- /dev/null
+<HTML>
+<TITLE>org.apache.xml.fop.svg Package</TITLE>
+<BODY>
+<P>Classes that add basic SVG support to FOP</P>
+<P>This includes flow objects, areas and properties.</P>
+</BODY>
+</HTML>
\ No newline at end of file
--- /dev/null
+<HTML>
+<TITLE>FOP Overview</TITLE>
+<BODY>
+<P>FOP is an XSL formatter and renderer that works with an XSLT transformer to
+produce PDF (and eventually other output formats) from XML documents.</P>
+</BODY>
+</HTML>
\ No newline at end of file