]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Initial revision
authorDirk-Willem van Gulik <dirkx@apache.org>
Mon, 8 Nov 1999 19:12:49 +0000 (19:12 +0000)
committerDirk-Willem van Gulik <dirkx@apache.org>
Mon, 8 Nov 1999 19:12:49 +0000 (19:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193213 13f79535-47bb-0310-9956-ffa450edef68

144 files changed:
Makefile [new file with mode: 0644]
Makefile.rules [new file with mode: 0644]
src/codegen/Courier-Bold.xml [new file with mode: 0644]
src/codegen/Courier-BoldOblique.xml [new file with mode: 0644]
src/codegen/Courier-Oblique.xml [new file with mode: 0644]
src/codegen/Courier.xml [new file with mode: 0644]
src/codegen/Helvetica-Bold.xml [new file with mode: 0644]
src/codegen/Helvetica-BoldOblique.xml [new file with mode: 0644]
src/codegen/Helvetica-Oblique.xml [new file with mode: 0644]
src/codegen/Helvetica.xml [new file with mode: 0644]
src/codegen/Times-Bold.xml [new file with mode: 0644]
src/codegen/Times-BoldItalic.xml [new file with mode: 0644]
src/codegen/Times-Italic.xml [new file with mode: 0644]
src/codegen/Times-Roman.xml [new file with mode: 0644]
src/codegen/charlist.xml [new file with mode: 0644]
src/codegen/code-point-mapping.xsl [new file with mode: 0644]
src/codegen/font-file.xsl [new file with mode: 0644]
src/codegen/properties.xml [new file with mode: 0644]
src/codegen/properties.xsl [new file with mode: 0644]
src/org/Makefile [new file with mode: 0644]
src/org/apache/Makefile [new file with mode: 0644]
src/org/apache/fop/Makefile [new file with mode: 0644]
src/org/apache/fop/apps/CommandLine.java [new file with mode: 0644]
src/org/apache/fop/apps/Driver.java [new file with mode: 0644]
src/org/apache/fop/apps/ErrorHandler.java [new file with mode: 0644]
src/org/apache/fop/apps/FOPException.java [new file with mode: 0644]
src/org/apache/fop/apps/Makefile [new file with mode: 0644]
src/org/apache/fop/apps/Version.java [new file with mode: 0644]
src/org/apache/fop/apps/XTCommandLine.java [new file with mode: 0644]
src/org/apache/fop/apps/package.html [new file with mode: 0644]
src/org/apache/fop/datatypes/ColorType.java [new file with mode: 0644]
src/org/apache/fop/datatypes/Length.java [new file with mode: 0644]
src/org/apache/fop/datatypes/Makefile [new file with mode: 0644]
src/org/apache/fop/datatypes/package.html [new file with mode: 0644]
src/org/apache/fop/fo/ElementMapping.java [new file with mode: 0644]
src/org/apache/fop/fo/FONode.java [new file with mode: 0644]
src/org/apache/fop/fo/FOText.java [new file with mode: 0644]
src/org/apache/fop/fo/FOTreeBuilder.java [new file with mode: 0644]
src/org/apache/fop/fo/FObj.java [new file with mode: 0644]
src/org/apache/fop/fo/FObjMixed.java [new file with mode: 0644]
src/org/apache/fop/fo/Makefile [new file with mode: 0644]
src/org/apache/fop/fo/Property.java [new file with mode: 0644]
src/org/apache/fop/fo/PropertyList.java [new file with mode: 0644]
src/org/apache/fop/fo/PropertyListBuilder.java [new file with mode: 0644]
src/org/apache/fop/fo/StandardElementMapping.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/Block.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/DisplayGraphic.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/DisplayRule.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/DisplaySequence.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/Flow.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/InlineSequence.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/ListBlock.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/ListItem.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/ListItemBody.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/ListItemLabel.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/Makefile [new file with mode: 0644]
src/org/apache/fop/fo/flow/PageNumber.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/StaticContent.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/Table.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/TableBody.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/TableCell.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/TableColumn.java [new file with mode: 0644]
src/org/apache/fop/fo/flow/TableRow.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/LayoutMasterSet.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/Makefile [new file with mode: 0644]
src/org/apache/fop/fo/pagination/PageSequence.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/RegionAfter.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/RegionBefore.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/RegionBody.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/Root.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SequenceSpecification.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SequenceSpecifier.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java [new file with mode: 0644]
src/org/apache/fop/fo/pagination/SimplePageMaster.java [new file with mode: 0644]
src/org/apache/fop/image/BmpBwImage.java [new file with mode: 0644]
src/org/apache/fop/image/BmpColImage.java [new file with mode: 0644]
src/org/apache/fop/image/FopImage.java [new file with mode: 0644]
src/org/apache/fop/image/FopImageFactory.java [new file with mode: 0644]
src/org/apache/fop/image/GifJpegImage.java [new file with mode: 0644]
src/org/apache/fop/image/ImageArea.java [new file with mode: 0644]
src/org/apache/fop/image/Makefile [new file with mode: 0644]
src/org/apache/fop/layout/AlternatingPageMasterFactory.java [new file with mode: 0644]
src/org/apache/fop/layout/Area.java [new file with mode: 0644]
src/org/apache/fop/layout/AreaContainer.java [new file with mode: 0644]
src/org/apache/fop/layout/AreaTree.java [new file with mode: 0644]
src/org/apache/fop/layout/BlockArea.java [new file with mode: 0644]
src/org/apache/fop/layout/Box.java [new file with mode: 0644]
src/org/apache/fop/layout/DisplaySpace.java [new file with mode: 0644]
src/org/apache/fop/layout/FontInfo.java [new file with mode: 0644]
src/org/apache/fop/layout/FontMetric.java [new file with mode: 0644]
src/org/apache/fop/layout/FontState.java [new file with mode: 0644]
src/org/apache/fop/layout/InlineArea.java [new file with mode: 0644]
src/org/apache/fop/layout/InlineSpace.java [new file with mode: 0644]
src/org/apache/fop/layout/LineArea.java [new file with mode: 0644]
src/org/apache/fop/layout/Makefile [new file with mode: 0644]
src/org/apache/fop/layout/Page.java [new file with mode: 0644]
src/org/apache/fop/layout/PageMaster.java [new file with mode: 0644]
src/org/apache/fop/layout/PageMasterFactory.java [new file with mode: 0644]
src/org/apache/fop/layout/Region.java [new file with mode: 0644]
src/org/apache/fop/layout/RepeatingPageMasterFactory.java [new file with mode: 0644]
src/org/apache/fop/layout/RuleArea.java [new file with mode: 0644]
src/org/apache/fop/layout/SinglePageMasterFactory.java [new file with mode: 0644]
src/org/apache/fop/layout/Space.java [new file with mode: 0644]
src/org/apache/fop/pdf/Makefile [new file with mode: 0644]
src/org/apache/fop/pdf/PDFDocument.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFFont.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFInfo.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFObject.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFPage.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFPages.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFResources.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFRoot.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFStream.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFXObject.java [new file with mode: 0644]
src/org/apache/fop/pdf/package.html [new file with mode: 0644]
src/org/apache/fop/render/Makefile [new file with mode: 0644]
src/org/apache/fop/render/Renderer.java [new file with mode: 0644]
src/org/apache/fop/render/package.html [new file with mode: 0644]
src/org/apache/fop/render/pdf/Font.java [new file with mode: 0644]
src/org/apache/fop/render/pdf/FontSetup.java [new file with mode: 0644]
src/org/apache/fop/render/pdf/Makefile [new file with mode: 0644]
src/org/apache/fop/render/pdf/PDFRenderer.java [new file with mode: 0644]
src/org/apache/fop/render/pdf/fonts/Makefile [new file with mode: 0644]
src/org/apache/fop/render/pdf/fonts/package.html [new file with mode: 0644]
src/org/apache/fop/render/pdf/package.html [new file with mode: 0644]
src/org/apache/fop/render/xml/Makefile [new file with mode: 0644]
src/org/apache/fop/render/xml/XMLRenderer.java [new file with mode: 0644]
src/org/apache/fop/render/xml/package.html [new file with mode: 0644]
src/org/apache/fop/svg/Graphic.java [new file with mode: 0644]
src/org/apache/fop/svg/Line.java [new file with mode: 0644]
src/org/apache/fop/svg/LineGraphic.java [new file with mode: 0644]
src/org/apache/fop/svg/Makefile [new file with mode: 0644]
src/org/apache/fop/svg/Rect.java [new file with mode: 0644]
src/org/apache/fop/svg/RectGraphic.java [new file with mode: 0644]
src/org/apache/fop/svg/SVG.java [new file with mode: 0644]
src/org/apache/fop/svg/SVGArea.java [new file with mode: 0644]
src/org/apache/fop/svg/SVGElementMapping.java [new file with mode: 0644]
src/org/apache/fop/svg/SVGLength.java [new file with mode: 0644]
src/org/apache/fop/svg/Text.java [new file with mode: 0644]
src/org/apache/fop/svg/TextGraphic.java [new file with mode: 0644]
src/org/apache/fop/svg/package.html [new file with mode: 0644]
src/overview.html [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..2f40560
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,106 @@
+# 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
+
diff --git a/Makefile.rules b/Makefile.rules
new file mode 100644 (file)
index 0000000..0eb223b
--- /dev/null
@@ -0,0 +1,24 @@
+# 
+#
+#
+
+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) $<
diff --git a/src/codegen/Courier-Bold.xml b/src/codegen/Courier-Bold.xml
new file mode 100644 (file)
index 0000000..a2ded8d
--- /dev/null
@@ -0,0 +1,274 @@
+<!-- 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
diff --git a/src/codegen/Courier-BoldOblique.xml b/src/codegen/Courier-BoldOblique.xml
new file mode 100644 (file)
index 0000000..58a419e
--- /dev/null
@@ -0,0 +1,274 @@
+<!-- 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>
diff --git a/src/codegen/Courier-Oblique.xml b/src/codegen/Courier-Oblique.xml
new file mode 100644 (file)
index 0000000..f439860
--- /dev/null
@@ -0,0 +1,274 @@
+<!-- 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
diff --git a/src/codegen/Courier.xml b/src/codegen/Courier.xml
new file mode 100644 (file)
index 0000000..80f1bfc
--- /dev/null
@@ -0,0 +1,274 @@
+<!-- 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
diff --git a/src/codegen/Helvetica-Bold.xml b/src/codegen/Helvetica-Bold.xml
new file mode 100644 (file)
index 0000000..6c9b6f4
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Helvetica-BoldOblique.xml b/src/codegen/Helvetica-BoldOblique.xml
new file mode 100644 (file)
index 0000000..d07b5de
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Helvetica-Oblique.xml b/src/codegen/Helvetica-Oblique.xml
new file mode 100644 (file)
index 0000000..00339df
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Helvetica.xml b/src/codegen/Helvetica.xml
new file mode 100644 (file)
index 0000000..b5221bf
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Times-Bold.xml b/src/codegen/Times-Bold.xml
new file mode 100644 (file)
index 0000000..f446d29
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Times-BoldItalic.xml b/src/codegen/Times-BoldItalic.xml
new file mode 100644 (file)
index 0000000..b79b831
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Times-Italic.xml b/src/codegen/Times-Italic.xml
new file mode 100644 (file)
index 0000000..5b0242e
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/Times-Roman.xml b/src/codegen/Times-Roman.xml
new file mode 100644 (file)
index 0000000..ae5c161
--- /dev/null
@@ -0,0 +1,242 @@
+<!-- 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
diff --git a/src/codegen/charlist.xml b/src/codegen/charlist.xml
new file mode 100644 (file)
index 0000000..30fc1fa
--- /dev/null
@@ -0,0 +1,272 @@
+<!-- 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
diff --git a/src/codegen/code-point-mapping.xsl b/src/codegen/code-point-mapping.xsl
new file mode 100644 (file)
index 0000000..e65ea98
--- /dev/null
@@ -0,0 +1,19 @@
+<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>
diff --git a/src/codegen/font-file.xsl b/src/codegen/font-file.xsl
new file mode 100644 (file)
index 0000000..0a52f75
--- /dev/null
@@ -0,0 +1,56 @@
+<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>
diff --git a/src/codegen/properties.xml b/src/codegen/properties.xml
new file mode 100644 (file)
index 0000000..cfeb6aa
--- /dev/null
@@ -0,0 +1,315 @@
+<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>
+
diff --git a/src/codegen/properties.xsl b/src/codegen/properties.xsl
new file mode 100644 (file)
index 0000000..97289b9
--- /dev/null
@@ -0,0 +1,137 @@
+<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>
diff --git a/src/org/Makefile b/src/org/Makefile
new file mode 100644 (file)
index 0000000..fa3129b
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+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
+
diff --git a/src/org/apache/Makefile b/src/org/apache/Makefile
new file mode 100644 (file)
index 0000000..10781e4
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+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
+
diff --git a/src/org/apache/fop/Makefile b/src/org/apache/fop/Makefile
new file mode 100644 (file)
index 0000000..173fad8
--- /dev/null
@@ -0,0 +1,26 @@
+
+
+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
+
diff --git a/src/org/apache/fop/apps/CommandLine.java b/src/org/apache/fop/apps/CommandLine.java
new file mode 100644 (file)
index 0000000..0786ba7
--- /dev/null
@@ -0,0 +1,122 @@
+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);
+       }
+    }
+}
diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java
new file mode 100644 (file)
index 0000000..fc0ba13
--- /dev/null
@@ -0,0 +1,215 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/apps/ErrorHandler.java b/src/org/apache/fop/apps/ErrorHandler.java
new file mode 100644 (file)
index 0000000..c2aaa27
--- /dev/null
@@ -0,0 +1,4 @@
+package org.apache.xml.fop.apps;
+
+/** not implemented yet */
+public interface ErrorHandler {}
diff --git a/src/org/apache/fop/apps/FOPException.java b/src/org/apache/fop/apps/FOPException.java
new file mode 100644 (file)
index 0000000..1bbbf05
--- /dev/null
@@ -0,0 +1,16 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/apps/Makefile b/src/org/apache/fop/apps/Makefile
new file mode 100644 (file)
index 0000000..f1cd612
--- /dev/null
@@ -0,0 +1,30 @@
+
+
+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
+
diff --git a/src/org/apache/fop/apps/Version.java b/src/org/apache/fop/apps/Version.java
new file mode 100644 (file)
index 0000000..bcc2c26
--- /dev/null
@@ -0,0 +1,18 @@
+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";
+    }
+}
diff --git a/src/org/apache/fop/apps/XTCommandLine.java b/src/org/apache/fop/apps/XTCommandLine.java
new file mode 100644 (file)
index 0000000..bd273c4
--- /dev/null
@@ -0,0 +1,78 @@
+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);
+       }
+    }
+}
diff --git a/src/org/apache/fop/apps/package.html b/src/org/apache/fop/apps/package.html
new file mode 100644 (file)
index 0000000..1832867
--- /dev/null
@@ -0,0 +1,7 @@
+<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
diff --git a/src/org/apache/fop/datatypes/ColorType.java b/src/org/apache/fop/datatypes/ColorType.java
new file mode 100644 (file)
index 0000000..43c691d
--- /dev/null
@@ -0,0 +1,136 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/datatypes/Length.java b/src/org/apache/fop/datatypes/Length.java
new file mode 100644 (file)
index 0000000..1b67dfd
--- /dev/null
@@ -0,0 +1,88 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/datatypes/Makefile b/src/org/apache/fop/datatypes/Makefile
new file mode 100644 (file)
index 0000000..87a7791
--- /dev/null
@@ -0,0 +1,25 @@
+
+
+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
+
diff --git a/src/org/apache/fop/datatypes/package.html b/src/org/apache/fop/datatypes/package.html
new file mode 100644 (file)
index 0000000..04f65b1
--- /dev/null
@@ -0,0 +1,6 @@
+<HTML>
+<TITLE>org.apache.xml.fop.datatypes Package</TITLE>
+<BODY>
+<P>XSL Datatypes</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/org/apache/fop/fo/ElementMapping.java b/src/org/apache/fop/fo/ElementMapping.java
new file mode 100644 (file)
index 0000000..04fc3a0
--- /dev/null
@@ -0,0 +1,6 @@
+package org.apache.xml.fop.fo;
+
+public interface ElementMapping {
+
+    public void addToBuilder(FOTreeBuilder builder);
+}
diff --git a/src/org/apache/fop/fo/FONode.java b/src/org/apache/fop/fo/FONode.java
new file mode 100644 (file)
index 0000000..ede968d
--- /dev/null
@@ -0,0 +1,110 @@
+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;
+}
diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java
new file mode 100644 (file)
index 0000000..f61995a
--- /dev/null
@@ -0,0 +1,80 @@
+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;
+       }
+    }
+}
diff --git a/src/org/apache/fop/fo/FOTreeBuilder.java b/src/org/apache/fop/fo/FOTreeBuilder.java
new file mode 100644 (file)
index 0000000..d4a1f5d
--- /dev/null
@@ -0,0 +1,204 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java
new file mode 100644 (file)
index 0000000..a94cbca
--- /dev/null
@@ -0,0 +1,57 @@
+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
+    }
+}
+
diff --git a/src/org/apache/fop/fo/FObjMixed.java b/src/org/apache/fop/fo/FObjMixed.java
new file mode 100644 (file)
index 0000000..177e940
--- /dev/null
@@ -0,0 +1,49 @@
+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;
+    }
+}
+
diff --git a/src/org/apache/fop/fo/Makefile b/src/org/apache/fop/fo/Makefile
new file mode 100644 (file)
index 0000000..da42110
--- /dev/null
@@ -0,0 +1,33 @@
+
+
+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
+
diff --git a/src/org/apache/fop/fo/Property.java b/src/org/apache/fop/fo/Property.java
new file mode 100644 (file)
index 0000000..420bee8
--- /dev/null
@@ -0,0 +1,41 @@
+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;
+  }
+
+}
diff --git a/src/org/apache/fop/fo/PropertyList.java b/src/org/apache/fop/fo/PropertyList.java
new file mode 100644 (file)
index 0000000..e3a6092
--- /dev/null
@@ -0,0 +1,41 @@
+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;
+  }
+}
diff --git a/src/org/apache/fop/fo/PropertyListBuilder.java b/src/org/apache/fop/fo/PropertyListBuilder.java
new file mode 100644 (file)
index 0000000..7c12763
--- /dev/null
@@ -0,0 +1,120 @@
+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;
+  }
+}
diff --git a/src/org/apache/fop/fo/StandardElementMapping.java b/src/org/apache/fop/fo/StandardElementMapping.java
new file mode 100644 (file)
index 0000000..396b01a
--- /dev/null
@@ -0,0 +1,52 @@
+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());
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/Block.java b/src/org/apache/fop/fo/flow/Block.java
new file mode 100644 (file)
index 0000000..61e2810
--- /dev/null
@@ -0,0 +1,192 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/DisplayGraphic.java b/src/org/apache/fop/fo/flow/DisplayGraphic.java
new file mode 100644 (file)
index 0000000..90f4508
--- /dev/null
@@ -0,0 +1,132 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/DisplayRule.java b/src/org/apache/fop/fo/flow/DisplayRule.java
new file mode 100644 (file)
index 0000000..8378481
--- /dev/null
@@ -0,0 +1,88 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/DisplaySequence.java b/src/org/apache/fop/fo/flow/DisplaySequence.java
new file mode 100644 (file)
index 0000000..c50b6bc
--- /dev/null
@@ -0,0 +1,52 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/Flow.java b/src/org/apache/fop/fo/flow/Flow.java
new file mode 100644 (file)
index 0000000..b9b66a1
--- /dev/null
@@ -0,0 +1,59 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/InlineSequence.java b/src/org/apache/fop/fo/flow/InlineSequence.java
new file mode 100644 (file)
index 0000000..33efc6b
--- /dev/null
@@ -0,0 +1,35 @@
+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"); 
+       }
+    }
+
+}
diff --git a/src/org/apache/fop/fo/flow/ListBlock.java b/src/org/apache/fop/fo/flow/ListBlock.java
new file mode 100644 (file)
index 0000000..6810825
--- /dev/null
@@ -0,0 +1,143 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/ListItem.java b/src/org/apache/fop/fo/flow/ListItem.java
new file mode 100644 (file)
index 0000000..f69cf45
--- /dev/null
@@ -0,0 +1,144 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/ListItemBody.java b/src/org/apache/fop/fo/flow/ListItemBody.java
new file mode 100644 (file)
index 0000000..c348355
--- /dev/null
@@ -0,0 +1,54 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/ListItemLabel.java b/src/org/apache/fop/fo/flow/ListItemLabel.java
new file mode 100644 (file)
index 0000000..fe7c051
--- /dev/null
@@ -0,0 +1,49 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/Makefile b/src/org/apache/fop/fo/flow/Makefile
new file mode 100644 (file)
index 0000000..72876ca
--- /dev/null
@@ -0,0 +1,39 @@
+
+
+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
+
diff --git a/src/org/apache/fop/fo/flow/PageNumber.java b/src/org/apache/fop/fo/flow/PageNumber.java
new file mode 100644 (file)
index 0000000..3a3f598
--- /dev/null
@@ -0,0 +1,66 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/StaticContent.java b/src/org/apache/fop/fo/flow/StaticContent.java
new file mode 100644 (file)
index 0000000..5dc6971
--- /dev/null
@@ -0,0 +1,54 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/Table.java b/src/org/apache/fop/fo/flow/Table.java
new file mode 100644 (file)
index 0000000..f838a79
--- /dev/null
@@ -0,0 +1,183 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/TableBody.java b/src/org/apache/fop/fo/flow/TableBody.java
new file mode 100644 (file)
index 0000000..9ff6a84
--- /dev/null
@@ -0,0 +1,137 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/TableCell.java b/src/org/apache/fop/fo/flow/TableCell.java
new file mode 100644 (file)
index 0000000..f2df832
--- /dev/null
@@ -0,0 +1,122 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/TableColumn.java b/src/org/apache/fop/fo/flow/TableColumn.java
new file mode 100644 (file)
index 0000000..6888bbe
--- /dev/null
@@ -0,0 +1,34 @@
+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
+    }
+}
diff --git a/src/org/apache/fop/fo/flow/TableRow.java b/src/org/apache/fop/fo/flow/TableRow.java
new file mode 100644 (file)
index 0000000..4f2f27a
--- /dev/null
@@ -0,0 +1,155 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java
new file mode 100644 (file)
index 0000000..5e4d01d
--- /dev/null
@@ -0,0 +1,50 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/Makefile b/src/org/apache/fop/fo/pagination/Makefile
new file mode 100644 (file)
index 0000000..ca1a2a3
--- /dev/null
@@ -0,0 +1,36 @@
+
+
+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
+
diff --git a/src/org/apache/fop/fo/pagination/PageSequence.java b/src/org/apache/fop/fo/pagination/PageSequence.java
new file mode 100644 (file)
index 0000000..eaae636
--- /dev/null
@@ -0,0 +1,138 @@
+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"); 
+       }
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/RegionAfter.java b/src/org/apache/fop/fo/pagination/RegionAfter.java
new file mode 100644 (file)
index 0000000..afac8fd
--- /dev/null
@@ -0,0 +1,54 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/RegionBefore.java b/src/org/apache/fop/fo/pagination/RegionBefore.java
new file mode 100644 (file)
index 0000000..79994d0
--- /dev/null
@@ -0,0 +1,53 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/RegionBody.java b/src/org/apache/fop/fo/pagination/RegionBody.java
new file mode 100644 (file)
index 0000000..dfeaa88
--- /dev/null
@@ -0,0 +1,50 @@
+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); 
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/Root.java b/src/org/apache/fop/fo/pagination/Root.java
new file mode 100644 (file)
index 0000000..ecfb42b
--- /dev/null
@@ -0,0 +1,61 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecification.java b/src/org/apache/fop/fo/pagination/SequenceSpecification.java
new file mode 100644 (file)
index 0000000..abea78a
--- /dev/null
@@ -0,0 +1,66 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifier.java b/src/org/apache/fop/fo/pagination/SequenceSpecifier.java
new file mode 100644 (file)
index 0000000..eef8433
--- /dev/null
@@ -0,0 +1,13 @@
+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();
+}
diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java
new file mode 100644 (file)
index 0000000..f81bd12
--- /dev/null
@@ -0,0 +1,65 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java
new file mode 100644 (file)
index 0000000..1a51851
--- /dev/null
@@ -0,0 +1,61 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java
new file mode 100644 (file)
index 0000000..bb46eff
--- /dev/null
@@ -0,0 +1,59 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/org/apache/fop/fo/pagination/SimplePageMaster.java
new file mode 100644 (file)
index 0000000..7f0a388
--- /dev/null
@@ -0,0 +1,89 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/image/BmpBwImage.java b/src/org/apache/fop/image/BmpBwImage.java
new file mode 100644 (file)
index 0000000..a560841
--- /dev/null
@@ -0,0 +1,108 @@
+/* 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;
+    }
+    
+}
diff --git a/src/org/apache/fop/image/BmpColImage.java b/src/org/apache/fop/image/BmpColImage.java
new file mode 100644 (file)
index 0000000..95287d3
--- /dev/null
@@ -0,0 +1,126 @@
+/* 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;
+    }
+
+}
diff --git a/src/org/apache/fop/image/FopImage.java b/src/org/apache/fop/image/FopImage.java
new file mode 100644 (file)
index 0000000..21617b5
--- /dev/null
@@ -0,0 +1,24 @@
+/* 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();
+}
diff --git a/src/org/apache/fop/image/FopImageFactory.java b/src/org/apache/fop/image/FopImageFactory.java
new file mode 100644 (file)
index 0000000..d13041c
--- /dev/null
@@ -0,0 +1,47 @@
+/* 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;
+       
+    }
+} 
diff --git a/src/org/apache/fop/image/GifJpegImage.java b/src/org/apache/fop/image/GifJpegImage.java
new file mode 100644 (file)
index 0000000..1179dd4
--- /dev/null
@@ -0,0 +1,120 @@
+/* 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;}
+  }
+
+
diff --git a/src/org/apache/fop/image/ImageArea.java b/src/org/apache/fop/image/ImageArea.java
new file mode 100644 (file)
index 0000000..cbac467
--- /dev/null
@@ -0,0 +1,57 @@
+/* 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;
+    }
+}
diff --git a/src/org/apache/fop/image/Makefile b/src/org/apache/fop/image/Makefile
new file mode 100644 (file)
index 0000000..9cd51e2
--- /dev/null
@@ -0,0 +1,28 @@
+
+
+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
+
diff --git a/src/org/apache/fop/layout/AlternatingPageMasterFactory.java b/src/org/apache/fop/layout/AlternatingPageMasterFactory.java
new file mode 100644 (file)
index 0000000..3406154
--- /dev/null
@@ -0,0 +1,41 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/layout/Area.java b/src/org/apache/fop/layout/Area.java
new file mode 100644 (file)
index 0000000..cc9ba21
--- /dev/null
@@ -0,0 +1,103 @@
+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() {
+    }
+}
diff --git a/src/org/apache/fop/layout/AreaContainer.java b/src/org/apache/fop/layout/AreaContainer.java
new file mode 100644 (file)
index 0000000..ff4de0d
--- /dev/null
@@ -0,0 +1,32 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/AreaTree.java b/src/org/apache/fop/layout/AreaTree.java
new file mode 100644 (file)
index 0000000..47d28ab
--- /dev/null
@@ -0,0 +1,40 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/BlockArea.java b/src/org/apache/fop/layout/BlockArea.java
new file mode 100644 (file)
index 0000000..cdc8d6a
--- /dev/null
@@ -0,0 +1,132 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/Box.java b/src/org/apache/fop/layout/Box.java
new file mode 100644 (file)
index 0000000..f5c5afe
--- /dev/null
@@ -0,0 +1,9 @@
+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);
+}
diff --git a/src/org/apache/fop/layout/DisplaySpace.java b/src/org/apache/fop/layout/DisplaySpace.java
new file mode 100644 (file)
index 0000000..f721a0c
--- /dev/null
@@ -0,0 +1,18 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/layout/FontInfo.java b/src/org/apache/fop/layout/FontInfo.java
new file mode 100644 (file)
index 0000000..7deb34d
--- /dev/null
@@ -0,0 +1,77 @@
+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));
+  }
+}
diff --git a/src/org/apache/fop/layout/FontMetric.java b/src/org/apache/fop/layout/FontMetric.java
new file mode 100644 (file)
index 0000000..8f15796
--- /dev/null
@@ -0,0 +1,17 @@
+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);
+}
diff --git a/src/org/apache/fop/layout/FontState.java b/src/org/apache/fop/layout/FontState.java
new file mode 100644 (file)
index 0000000..dea5014
--- /dev/null
@@ -0,0 +1,61 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/layout/InlineArea.java b/src/org/apache/fop/layout/InlineArea.java
new file mode 100644 (file)
index 0000000..740d3fe
--- /dev/null
@@ -0,0 +1,38 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/InlineSpace.java b/src/org/apache/fop/layout/InlineSpace.java
new file mode 100644 (file)
index 0000000..d33f2e4
--- /dev/null
@@ -0,0 +1,23 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/layout/LineArea.java b/src/org/apache/fop/layout/LineArea.java
new file mode 100644 (file)
index 0000000..8286c1f
--- /dev/null
@@ -0,0 +1,401 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/Makefile b/src/org/apache/fop/layout/Makefile
new file mode 100644 (file)
index 0000000..3139558
--- /dev/null
@@ -0,0 +1,43 @@
+
+
+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
+
diff --git a/src/org/apache/fop/layout/Page.java b/src/org/apache/fop/layout/Page.java
new file mode 100644 (file)
index 0000000..49b5ca9
--- /dev/null
@@ -0,0 +1,91 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/layout/PageMaster.java b/src/org/apache/fop/layout/PageMaster.java
new file mode 100644 (file)
index 0000000..5a164af
--- /dev/null
@@ -0,0 +1,66 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/PageMasterFactory.java b/src/org/apache/fop/layout/PageMasterFactory.java
new file mode 100644 (file)
index 0000000..9e15c60
--- /dev/null
@@ -0,0 +1,20 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/layout/Region.java b/src/org/apache/fop/layout/Region.java
new file mode 100644 (file)
index 0000000..aeb9358
--- /dev/null
@@ -0,0 +1,20 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/layout/RepeatingPageMasterFactory.java b/src/org/apache/fop/layout/RepeatingPageMasterFactory.java
new file mode 100644 (file)
index 0000000..06fa48e
--- /dev/null
@@ -0,0 +1,37 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/layout/RuleArea.java b/src/org/apache/fop/layout/RuleArea.java
new file mode 100644 (file)
index 0000000..cfce487
--- /dev/null
@@ -0,0 +1,59 @@
+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;
+       }
+}
diff --git a/src/org/apache/fop/layout/SinglePageMasterFactory.java b/src/org/apache/fop/layout/SinglePageMasterFactory.java
new file mode 100644 (file)
index 0000000..f62d47e
--- /dev/null
@@ -0,0 +1,34 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/layout/Space.java b/src/org/apache/fop/layout/Space.java
new file mode 100644 (file)
index 0000000..5663cea
--- /dev/null
@@ -0,0 +1,4 @@
+package org.apache.xml.fop.layout;
+
+abstract public class Space extends Box {
+}
diff --git a/src/org/apache/fop/pdf/Makefile b/src/org/apache/fop/pdf/Makefile
new file mode 100644 (file)
index 0000000..111ac16
--- /dev/null
@@ -0,0 +1,33 @@
+
+
+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
+
diff --git a/src/org/apache/fop/pdf/PDFDocument.java b/src/org/apache/fop/pdf/PDFDocument.java
new file mode 100644 (file)
index 0000000..58b485d
--- /dev/null
@@ -0,0 +1,305 @@
+/* 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();
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFFont.java b/src/org/apache/fop/pdf/PDFFont.java
new file mode 100644 (file)
index 0000000..fb57573
--- /dev/null
@@ -0,0 +1,67 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFInfo.java b/src/org/apache/fop/pdf/PDFInfo.java
new file mode 100644 (file)
index 0000000..9f2cc3a
--- /dev/null
@@ -0,0 +1,44 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFObject.java b/src/org/apache/fop/pdf/PDFObject.java
new file mode 100644 (file)
index 0000000..059157f
--- /dev/null
@@ -0,0 +1,59 @@
+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();
+}
diff --git a/src/org/apache/fop/pdf/PDFPage.java b/src/org/apache/fop/pdf/PDFPage.java
new file mode 100644 (file)
index 0000000..405f537
--- /dev/null
@@ -0,0 +1,78 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFPages.java b/src/org/apache/fop/pdf/PDFPages.java
new file mode 100644 (file)
index 0000000..cac6d1e
--- /dev/null
@@ -0,0 +1,70 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFResources.java b/src/org/apache/fop/pdf/PDFResources.java
new file mode 100644 (file)
index 0000000..0bbb3aa
--- /dev/null
@@ -0,0 +1,83 @@
+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();
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFRoot.java b/src/org/apache/fop/pdf/PDFRoot.java
new file mode 100644 (file)
index 0000000..9c4b183
--- /dev/null
@@ -0,0 +1,53 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFStream.java b/src/org/apache/fop/pdf/PDFStream.java
new file mode 100644 (file)
index 0000000..14d3ecf
--- /dev/null
@@ -0,0 +1,77 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/PDFXObject.java b/src/org/apache/fop/pdf/PDFXObject.java
new file mode 100644 (file)
index 0000000..3a49420
--- /dev/null
@@ -0,0 +1,100 @@
+/* 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;
+    }
+}
diff --git a/src/org/apache/fop/pdf/package.html b/src/org/apache/fop/pdf/package.html
new file mode 100644 (file)
index 0000000..6b4c7f2
--- /dev/null
@@ -0,0 +1,8 @@
+<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
diff --git a/src/org/apache/fop/render/Makefile b/src/org/apache/fop/render/Makefile
new file mode 100644 (file)
index 0000000..16807e5
--- /dev/null
@@ -0,0 +1,24 @@
+
+
+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
+
diff --git a/src/org/apache/fop/render/Renderer.java b/src/org/apache/fop/render/Renderer.java
new file mode 100644 (file)
index 0000000..93842dc
--- /dev/null
@@ -0,0 +1,58 @@
+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);
+}
diff --git a/src/org/apache/fop/render/package.html b/src/org/apache/fop/render/package.html
new file mode 100644 (file)
index 0000000..0e31dbd
--- /dev/null
@@ -0,0 +1,6 @@
+<HTML>
+<TITLE>org.apache.xml.fop.render Package</TITLE>
+<BODY>
+<P>generic renderer interface</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/org/apache/fop/render/pdf/Font.java b/src/org/apache/fop/render/pdf/Font.java
new file mode 100644 (file)
index 0000000..8d5d94a
--- /dev/null
@@ -0,0 +1,20 @@
+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();
+}
diff --git a/src/org/apache/fop/render/pdf/FontSetup.java b/src/org/apache/fop/render/pdf/FontSetup.java
new file mode 100644 (file)
index 0000000..90ca29c
--- /dev/null
@@ -0,0 +1,167 @@
+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()
+                                          )
+                             );
+       }
+    }
+}
diff --git a/src/org/apache/fop/render/pdf/Makefile b/src/org/apache/fop/render/pdf/Makefile
new file mode 100644 (file)
index 0000000..eda522e
--- /dev/null
@@ -0,0 +1,26 @@
+
+
+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
+
diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java
new file mode 100644 (file)
index 0000000..cb6165e
--- /dev/null
@@ -0,0 +1,426 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/render/pdf/fonts/Makefile b/src/org/apache/fop/render/pdf/fonts/Makefile
new file mode 100644 (file)
index 0000000..a4658ae
--- /dev/null
@@ -0,0 +1,23 @@
+
+
+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
+
diff --git a/src/org/apache/fop/render/pdf/fonts/package.html b/src/org/apache/fop/render/pdf/fonts/package.html
new file mode 100644 (file)
index 0000000..dbd584a
--- /dev/null
@@ -0,0 +1,7 @@
+<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
diff --git a/src/org/apache/fop/render/pdf/package.html b/src/org/apache/fop/render/pdf/package.html
new file mode 100644 (file)
index 0000000..ec19c7c
--- /dev/null
@@ -0,0 +1,6 @@
+<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
diff --git a/src/org/apache/fop/render/xml/Makefile b/src/org/apache/fop/render/xml/Makefile
new file mode 100644 (file)
index 0000000..75c3686
--- /dev/null
@@ -0,0 +1,23 @@
+
+
+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
+
diff --git a/src/org/apache/fop/render/xml/XMLRenderer.java b/src/org/apache/fop/render/xml/XMLRenderer.java
new file mode 100644 (file)
index 0000000..9efc436
--- /dev/null
@@ -0,0 +1,276 @@
+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()
+                            + "\"/>");
+    }
+}
diff --git a/src/org/apache/fop/render/xml/package.html b/src/org/apache/fop/render/xml/package.html
new file mode 100644 (file)
index 0000000..4459f9e
--- /dev/null
@@ -0,0 +1,6 @@
+<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
diff --git a/src/org/apache/fop/svg/Graphic.java b/src/org/apache/fop/svg/Graphic.java
new file mode 100644 (file)
index 0000000..48b0c31
--- /dev/null
@@ -0,0 +1,8 @@
+package org.apache.xml.fop.svg;
+
+/**
+ * base class for SVG graphic objects.
+ *
+ * Graphic objects include rectangles, lines and text
+ */
+public abstract class Graphic {}
diff --git a/src/org/apache/fop/svg/Line.java b/src/org/apache/fop/svg/Line.java
new file mode 100644 (file)
index 0000000..93ed5cb
--- /dev/null
@@ -0,0 +1,81 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/LineGraphic.java b/src/org/apache/fop/svg/LineGraphic.java
new file mode 100644 (file)
index 0000000..f4d103e
--- /dev/null
@@ -0,0 +1,34 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/Makefile b/src/org/apache/fop/svg/Makefile
new file mode 100644 (file)
index 0000000..f2f9f5b
--- /dev/null
@@ -0,0 +1,33 @@
+
+
+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
+
diff --git a/src/org/apache/fop/svg/Rect.java b/src/org/apache/fop/svg/Rect.java
new file mode 100644 (file)
index 0000000..e866577
--- /dev/null
@@ -0,0 +1,81 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/RectGraphic.java b/src/org/apache/fop/svg/RectGraphic.java
new file mode 100644 (file)
index 0000000..e27bd48
--- /dev/null
@@ -0,0 +1,34 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/SVG.java b/src/org/apache/fop/svg/SVG.java
new file mode 100644 (file)
index 0000000..2e229e7
--- /dev/null
@@ -0,0 +1,176 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/SVGArea.java b/src/org/apache/fop/svg/SVGArea.java
new file mode 100644 (file)
index 0000000..7a6ac28
--- /dev/null
@@ -0,0 +1,45 @@
+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);
+    }
+}
diff --git a/src/org/apache/fop/svg/SVGElementMapping.java b/src/org/apache/fop/svg/SVGElementMapping.java
new file mode 100644 (file)
index 0000000..c01041c
--- /dev/null
@@ -0,0 +1,15 @@
+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());
+    }
+}
diff --git a/src/org/apache/fop/svg/SVGLength.java b/src/org/apache/fop/svg/SVGLength.java
new file mode 100644 (file)
index 0000000..2529460
--- /dev/null
@@ -0,0 +1,77 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/Text.java b/src/org/apache/fop/svg/Text.java
new file mode 100644 (file)
index 0000000..d24a10d
--- /dev/null
@@ -0,0 +1,95 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/TextGraphic.java b/src/org/apache/fop/svg/TextGraphic.java
new file mode 100644 (file)
index 0000000..e0510f2
--- /dev/null
@@ -0,0 +1,29 @@
+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;
+    }
+}
diff --git a/src/org/apache/fop/svg/package.html b/src/org/apache/fop/svg/package.html
new file mode 100644 (file)
index 0000000..695f069
--- /dev/null
@@ -0,0 +1,7 @@
+<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
diff --git a/src/overview.html b/src/overview.html
new file mode 100644 (file)
index 0000000..6931383
--- /dev/null
@@ -0,0 +1,7 @@
+<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