From 10070e8383ff94f3f256e346b8c4a2a493533cfb Mon Sep 17 00:00:00 2001 From: Dirk-Willem van Gulik Date: Mon, 8 Nov 1999 19:12:49 +0000 Subject: [PATCH] Initial revision git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193213 13f79535-47bb-0310-9956-ffa450edef68 --- Makefile | 106 +++++ Makefile.rules | 24 + src/codegen/Courier-Bold.xml | 274 +++++++++++ src/codegen/Courier-BoldOblique.xml | 274 +++++++++++ src/codegen/Courier-Oblique.xml | 274 +++++++++++ src/codegen/Courier.xml | 274 +++++++++++ src/codegen/Helvetica-Bold.xml | 242 ++++++++++ src/codegen/Helvetica-BoldOblique.xml | 242 ++++++++++ src/codegen/Helvetica-Oblique.xml | 242 ++++++++++ src/codegen/Helvetica.xml | 242 ++++++++++ src/codegen/Times-Bold.xml | 242 ++++++++++ src/codegen/Times-BoldItalic.xml | 242 ++++++++++ src/codegen/Times-Italic.xml | 242 ++++++++++ src/codegen/Times-Roman.xml | 242 ++++++++++ src/codegen/charlist.xml | 272 +++++++++++ src/codegen/code-point-mapping.xsl | 19 + src/codegen/font-file.xsl | 56 +++ src/codegen/properties.xml | 315 +++++++++++++ src/codegen/properties.xsl | 137 ++++++ src/org/Makefile | 20 + src/org/apache/Makefile | 20 + src/org/apache/fop/Makefile | 26 ++ src/org/apache/fop/apps/CommandLine.java | 122 +++++ src/org/apache/fop/apps/Driver.java | 215 +++++++++ src/org/apache/fop/apps/ErrorHandler.java | 4 + src/org/apache/fop/apps/FOPException.java | 16 + src/org/apache/fop/apps/Makefile | 30 ++ src/org/apache/fop/apps/Version.java | 18 + src/org/apache/fop/apps/XTCommandLine.java | 78 ++++ src/org/apache/fop/apps/package.html | 7 + src/org/apache/fop/datatypes/ColorType.java | 136 ++++++ src/org/apache/fop/datatypes/Length.java | 88 ++++ src/org/apache/fop/datatypes/Makefile | 25 + src/org/apache/fop/datatypes/package.html | 6 + src/org/apache/fop/fo/ElementMapping.java | 6 + src/org/apache/fop/fo/FONode.java | 110 +++++ src/org/apache/fop/fo/FOText.java | 80 ++++ src/org/apache/fop/fo/FOTreeBuilder.java | 204 +++++++++ src/org/apache/fop/fo/FObj.java | 57 +++ src/org/apache/fop/fo/FObjMixed.java | 49 ++ src/org/apache/fop/fo/Makefile | 33 ++ src/org/apache/fop/fo/Property.java | 41 ++ src/org/apache/fop/fo/PropertyList.java | 41 ++ .../apache/fop/fo/PropertyListBuilder.java | 120 +++++ .../apache/fop/fo/StandardElementMapping.java | 52 +++ src/org/apache/fop/fo/flow/Block.java | 192 ++++++++ .../apache/fop/fo/flow/DisplayGraphic.java | 132 ++++++ src/org/apache/fop/fo/flow/DisplayRule.java | 88 ++++ .../apache/fop/fo/flow/DisplaySequence.java | 52 +++ src/org/apache/fop/fo/flow/Flow.java | 59 +++ .../apache/fop/fo/flow/InlineSequence.java | 35 ++ src/org/apache/fop/fo/flow/ListBlock.java | 143 ++++++ src/org/apache/fop/fo/flow/ListItem.java | 144 ++++++ src/org/apache/fop/fo/flow/ListItemBody.java | 54 +++ src/org/apache/fop/fo/flow/ListItemLabel.java | 49 ++ src/org/apache/fop/fo/flow/Makefile | 39 ++ src/org/apache/fop/fo/flow/PageNumber.java | 66 +++ src/org/apache/fop/fo/flow/StaticContent.java | 54 +++ src/org/apache/fop/fo/flow/Table.java | 183 ++++++++ src/org/apache/fop/fo/flow/TableBody.java | 137 ++++++ src/org/apache/fop/fo/flow/TableCell.java | 122 +++++ src/org/apache/fop/fo/flow/TableColumn.java | 34 ++ src/org/apache/fop/fo/flow/TableRow.java | 155 +++++++ .../fop/fo/pagination/LayoutMasterSet.java | 50 ++ src/org/apache/fop/fo/pagination/Makefile | 36 ++ .../fop/fo/pagination/PageSequence.java | 138 ++++++ .../apache/fop/fo/pagination/RegionAfter.java | 54 +++ .../fop/fo/pagination/RegionBefore.java | 53 +++ .../apache/fop/fo/pagination/RegionBody.java | 50 ++ src/org/apache/fop/fo/pagination/Root.java | 61 +++ .../fo/pagination/SequenceSpecification.java | 66 +++ .../fop/fo/pagination/SequenceSpecifier.java | 13 + .../SequenceSpecifierAlternating.java | 65 +++ .../SequenceSpecifierRepeating.java | 61 +++ .../pagination/SequenceSpecifierSingle.java | 59 +++ .../fop/fo/pagination/SimplePageMaster.java | 89 ++++ src/org/apache/fop/image/BmpBwImage.java | 108 +++++ src/org/apache/fop/image/BmpColImage.java | 126 ++++++ src/org/apache/fop/image/FopImage.java | 24 + src/org/apache/fop/image/FopImageFactory.java | 47 ++ src/org/apache/fop/image/GifJpegImage.java | 120 +++++ src/org/apache/fop/image/ImageArea.java | 57 +++ src/org/apache/fop/image/Makefile | 28 ++ .../layout/AlternatingPageMasterFactory.java | 41 ++ src/org/apache/fop/layout/Area.java | 103 +++++ src/org/apache/fop/layout/AreaContainer.java | 32 ++ src/org/apache/fop/layout/AreaTree.java | 40 ++ src/org/apache/fop/layout/BlockArea.java | 132 ++++++ src/org/apache/fop/layout/Box.java | 9 + src/org/apache/fop/layout/DisplaySpace.java | 18 + src/org/apache/fop/layout/FontInfo.java | 77 ++++ src/org/apache/fop/layout/FontMetric.java | 17 + src/org/apache/fop/layout/FontState.java | 61 +++ src/org/apache/fop/layout/InlineArea.java | 38 ++ src/org/apache/fop/layout/InlineSpace.java | 23 + src/org/apache/fop/layout/LineArea.java | 401 +++++++++++++++++ src/org/apache/fop/layout/Makefile | 43 ++ src/org/apache/fop/layout/Page.java | 91 ++++ src/org/apache/fop/layout/PageMaster.java | 66 +++ .../apache/fop/layout/PageMasterFactory.java | 20 + src/org/apache/fop/layout/Region.java | 20 + .../layout/RepeatingPageMasterFactory.java | 37 ++ src/org/apache/fop/layout/RuleArea.java | 59 +++ .../fop/layout/SinglePageMasterFactory.java | 34 ++ src/org/apache/fop/layout/Space.java | 4 + src/org/apache/fop/pdf/Makefile | 33 ++ src/org/apache/fop/pdf/PDFDocument.java | 305 +++++++++++++ src/org/apache/fop/pdf/PDFFont.java | 67 +++ src/org/apache/fop/pdf/PDFInfo.java | 44 ++ src/org/apache/fop/pdf/PDFObject.java | 59 +++ src/org/apache/fop/pdf/PDFPage.java | 78 ++++ src/org/apache/fop/pdf/PDFPages.java | 70 +++ src/org/apache/fop/pdf/PDFResources.java | 83 ++++ src/org/apache/fop/pdf/PDFRoot.java | 53 +++ src/org/apache/fop/pdf/PDFStream.java | 77 ++++ src/org/apache/fop/pdf/PDFXObject.java | 100 ++++ src/org/apache/fop/pdf/package.html | 8 + src/org/apache/fop/render/Makefile | 24 + src/org/apache/fop/render/Renderer.java | 58 +++ src/org/apache/fop/render/package.html | 6 + src/org/apache/fop/render/pdf/Font.java | 20 + src/org/apache/fop/render/pdf/FontSetup.java | 167 +++++++ src/org/apache/fop/render/pdf/Makefile | 26 ++ .../apache/fop/render/pdf/PDFRenderer.java | 426 ++++++++++++++++++ src/org/apache/fop/render/pdf/fonts/Makefile | 23 + .../apache/fop/render/pdf/fonts/package.html | 7 + src/org/apache/fop/render/pdf/package.html | 6 + src/org/apache/fop/render/xml/Makefile | 23 + .../apache/fop/render/xml/XMLRenderer.java | 276 ++++++++++++ src/org/apache/fop/render/xml/package.html | 6 + src/org/apache/fop/svg/Graphic.java | 8 + src/org/apache/fop/svg/Line.java | 81 ++++ src/org/apache/fop/svg/LineGraphic.java | 34 ++ src/org/apache/fop/svg/Makefile | 33 ++ src/org/apache/fop/svg/Rect.java | 81 ++++ src/org/apache/fop/svg/RectGraphic.java | 34 ++ src/org/apache/fop/svg/SVG.java | 176 ++++++++ src/org/apache/fop/svg/SVGArea.java | 45 ++ src/org/apache/fop/svg/SVGElementMapping.java | 15 + src/org/apache/fop/svg/SVGLength.java | 77 ++++ src/org/apache/fop/svg/Text.java | 95 ++++ src/org/apache/fop/svg/TextGraphic.java | 29 ++ src/org/apache/fop/svg/package.html | 7 + src/overview.html | 7 + 144 files changed, 12741 insertions(+) create mode 100644 Makefile create mode 100644 Makefile.rules create mode 100644 src/codegen/Courier-Bold.xml create mode 100644 src/codegen/Courier-BoldOblique.xml create mode 100644 src/codegen/Courier-Oblique.xml create mode 100644 src/codegen/Courier.xml create mode 100644 src/codegen/Helvetica-Bold.xml create mode 100644 src/codegen/Helvetica-BoldOblique.xml create mode 100644 src/codegen/Helvetica-Oblique.xml create mode 100644 src/codegen/Helvetica.xml create mode 100644 src/codegen/Times-Bold.xml create mode 100644 src/codegen/Times-BoldItalic.xml create mode 100644 src/codegen/Times-Italic.xml create mode 100644 src/codegen/Times-Roman.xml create mode 100644 src/codegen/charlist.xml create mode 100644 src/codegen/code-point-mapping.xsl create mode 100644 src/codegen/font-file.xsl create mode 100644 src/codegen/properties.xml create mode 100644 src/codegen/properties.xsl create mode 100644 src/org/Makefile create mode 100644 src/org/apache/Makefile create mode 100644 src/org/apache/fop/Makefile create mode 100644 src/org/apache/fop/apps/CommandLine.java create mode 100644 src/org/apache/fop/apps/Driver.java create mode 100644 src/org/apache/fop/apps/ErrorHandler.java create mode 100644 src/org/apache/fop/apps/FOPException.java create mode 100644 src/org/apache/fop/apps/Makefile create mode 100644 src/org/apache/fop/apps/Version.java create mode 100644 src/org/apache/fop/apps/XTCommandLine.java create mode 100644 src/org/apache/fop/apps/package.html create mode 100644 src/org/apache/fop/datatypes/ColorType.java create mode 100644 src/org/apache/fop/datatypes/Length.java create mode 100644 src/org/apache/fop/datatypes/Makefile create mode 100644 src/org/apache/fop/datatypes/package.html create mode 100644 src/org/apache/fop/fo/ElementMapping.java create mode 100644 src/org/apache/fop/fo/FONode.java create mode 100644 src/org/apache/fop/fo/FOText.java create mode 100644 src/org/apache/fop/fo/FOTreeBuilder.java create mode 100644 src/org/apache/fop/fo/FObj.java create mode 100644 src/org/apache/fop/fo/FObjMixed.java create mode 100644 src/org/apache/fop/fo/Makefile create mode 100644 src/org/apache/fop/fo/Property.java create mode 100644 src/org/apache/fop/fo/PropertyList.java create mode 100644 src/org/apache/fop/fo/PropertyListBuilder.java create mode 100644 src/org/apache/fop/fo/StandardElementMapping.java create mode 100644 src/org/apache/fop/fo/flow/Block.java create mode 100644 src/org/apache/fop/fo/flow/DisplayGraphic.java create mode 100644 src/org/apache/fop/fo/flow/DisplayRule.java create mode 100644 src/org/apache/fop/fo/flow/DisplaySequence.java create mode 100644 src/org/apache/fop/fo/flow/Flow.java create mode 100644 src/org/apache/fop/fo/flow/InlineSequence.java create mode 100644 src/org/apache/fop/fo/flow/ListBlock.java create mode 100644 src/org/apache/fop/fo/flow/ListItem.java create mode 100644 src/org/apache/fop/fo/flow/ListItemBody.java create mode 100644 src/org/apache/fop/fo/flow/ListItemLabel.java create mode 100644 src/org/apache/fop/fo/flow/Makefile create mode 100644 src/org/apache/fop/fo/flow/PageNumber.java create mode 100644 src/org/apache/fop/fo/flow/StaticContent.java create mode 100644 src/org/apache/fop/fo/flow/Table.java create mode 100644 src/org/apache/fop/fo/flow/TableBody.java create mode 100644 src/org/apache/fop/fo/flow/TableCell.java create mode 100644 src/org/apache/fop/fo/flow/TableColumn.java create mode 100644 src/org/apache/fop/fo/flow/TableRow.java create mode 100644 src/org/apache/fop/fo/pagination/LayoutMasterSet.java create mode 100644 src/org/apache/fop/fo/pagination/Makefile create mode 100644 src/org/apache/fop/fo/pagination/PageSequence.java create mode 100644 src/org/apache/fop/fo/pagination/RegionAfter.java create mode 100644 src/org/apache/fop/fo/pagination/RegionBefore.java create mode 100644 src/org/apache/fop/fo/pagination/RegionBody.java create mode 100644 src/org/apache/fop/fo/pagination/Root.java create mode 100644 src/org/apache/fop/fo/pagination/SequenceSpecification.java create mode 100644 src/org/apache/fop/fo/pagination/SequenceSpecifier.java create mode 100644 src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java create mode 100644 src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java create mode 100644 src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java create mode 100644 src/org/apache/fop/fo/pagination/SimplePageMaster.java create mode 100644 src/org/apache/fop/image/BmpBwImage.java create mode 100644 src/org/apache/fop/image/BmpColImage.java create mode 100644 src/org/apache/fop/image/FopImage.java create mode 100644 src/org/apache/fop/image/FopImageFactory.java create mode 100644 src/org/apache/fop/image/GifJpegImage.java create mode 100644 src/org/apache/fop/image/ImageArea.java create mode 100644 src/org/apache/fop/image/Makefile create mode 100644 src/org/apache/fop/layout/AlternatingPageMasterFactory.java create mode 100644 src/org/apache/fop/layout/Area.java create mode 100644 src/org/apache/fop/layout/AreaContainer.java create mode 100644 src/org/apache/fop/layout/AreaTree.java create mode 100644 src/org/apache/fop/layout/BlockArea.java create mode 100644 src/org/apache/fop/layout/Box.java create mode 100644 src/org/apache/fop/layout/DisplaySpace.java create mode 100644 src/org/apache/fop/layout/FontInfo.java create mode 100644 src/org/apache/fop/layout/FontMetric.java create mode 100644 src/org/apache/fop/layout/FontState.java create mode 100644 src/org/apache/fop/layout/InlineArea.java create mode 100644 src/org/apache/fop/layout/InlineSpace.java create mode 100644 src/org/apache/fop/layout/LineArea.java create mode 100644 src/org/apache/fop/layout/Makefile create mode 100644 src/org/apache/fop/layout/Page.java create mode 100644 src/org/apache/fop/layout/PageMaster.java create mode 100644 src/org/apache/fop/layout/PageMasterFactory.java create mode 100644 src/org/apache/fop/layout/Region.java create mode 100644 src/org/apache/fop/layout/RepeatingPageMasterFactory.java create mode 100644 src/org/apache/fop/layout/RuleArea.java create mode 100644 src/org/apache/fop/layout/SinglePageMasterFactory.java create mode 100644 src/org/apache/fop/layout/Space.java create mode 100644 src/org/apache/fop/pdf/Makefile create mode 100644 src/org/apache/fop/pdf/PDFDocument.java create mode 100644 src/org/apache/fop/pdf/PDFFont.java create mode 100644 src/org/apache/fop/pdf/PDFInfo.java create mode 100644 src/org/apache/fop/pdf/PDFObject.java create mode 100644 src/org/apache/fop/pdf/PDFPage.java create mode 100644 src/org/apache/fop/pdf/PDFPages.java create mode 100644 src/org/apache/fop/pdf/PDFResources.java create mode 100644 src/org/apache/fop/pdf/PDFRoot.java create mode 100644 src/org/apache/fop/pdf/PDFStream.java create mode 100644 src/org/apache/fop/pdf/PDFXObject.java create mode 100644 src/org/apache/fop/pdf/package.html create mode 100644 src/org/apache/fop/render/Makefile create mode 100644 src/org/apache/fop/render/Renderer.java create mode 100644 src/org/apache/fop/render/package.html create mode 100644 src/org/apache/fop/render/pdf/Font.java create mode 100644 src/org/apache/fop/render/pdf/FontSetup.java create mode 100644 src/org/apache/fop/render/pdf/Makefile create mode 100644 src/org/apache/fop/render/pdf/PDFRenderer.java create mode 100644 src/org/apache/fop/render/pdf/fonts/Makefile create mode 100644 src/org/apache/fop/render/pdf/fonts/package.html create mode 100644 src/org/apache/fop/render/pdf/package.html create mode 100644 src/org/apache/fop/render/xml/Makefile create mode 100644 src/org/apache/fop/render/xml/XMLRenderer.java create mode 100644 src/org/apache/fop/render/xml/package.html create mode 100644 src/org/apache/fop/svg/Graphic.java create mode 100644 src/org/apache/fop/svg/Line.java create mode 100644 src/org/apache/fop/svg/LineGraphic.java create mode 100644 src/org/apache/fop/svg/Makefile create mode 100644 src/org/apache/fop/svg/Rect.java create mode 100644 src/org/apache/fop/svg/RectGraphic.java create mode 100644 src/org/apache/fop/svg/SVG.java create mode 100644 src/org/apache/fop/svg/SVGArea.java create mode 100644 src/org/apache/fop/svg/SVGElementMapping.java create mode 100644 src/org/apache/fop/svg/SVGLength.java create mode 100644 src/org/apache/fop/svg/Text.java create mode 100644 src/org/apache/fop/svg/TextGraphic.java create mode 100644 src/org/apache/fop/svg/package.html create mode 100644 src/overview.html diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..2f4056071 --- /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 index 000000000..0eb223b63 --- /dev/null +++ b/Makefile.rules @@ -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 index 000000000..a2ded8d53 --- /dev/null +++ b/src/codegen/Courier-Bold.xml @@ -0,0 +1,274 @@ + + + Courier-Bold + CourierBold + WinAnsiEncoding + 562 + 439 + 626 + -142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Courier-BoldOblique.xml b/src/codegen/Courier-BoldOblique.xml new file mode 100644 index 000000000..58a419ec5 --- /dev/null +++ b/src/codegen/Courier-BoldOblique.xml @@ -0,0 +1,274 @@ + + + Courier-BoldOblique + CourierBoldOblique + WinAnsiEncoding + 562 + 439 + 626 + -142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/codegen/Courier-Oblique.xml b/src/codegen/Courier-Oblique.xml new file mode 100644 index 000000000..f43986004 --- /dev/null +++ b/src/codegen/Courier-Oblique.xml @@ -0,0 +1,274 @@ + + + Courier-Oblique + CourierOblique + WinAnsiEncoding + 562 + 426 + 629 + -157 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Courier.xml b/src/codegen/Courier.xml new file mode 100644 index 000000000..80f1bfc6e --- /dev/null +++ b/src/codegen/Courier.xml @@ -0,0 +1,274 @@ + + + Courier + Courier + WinAnsiEncoding + 562 + 426 + 629 + -157 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Helvetica-Bold.xml b/src/codegen/Helvetica-Bold.xml new file mode 100644 index 000000000..6c9b6f4b9 --- /dev/null +++ b/src/codegen/Helvetica-Bold.xml @@ -0,0 +1,242 @@ + + + Helvetica-Bold + HelveticaBold + WinAnsiEncoding + 718 + 532 + 718 + -207 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Helvetica-BoldOblique.xml b/src/codegen/Helvetica-BoldOblique.xml new file mode 100644 index 000000000..d07b5de49 --- /dev/null +++ b/src/codegen/Helvetica-BoldOblique.xml @@ -0,0 +1,242 @@ + + + Helvetica-BoldOblique + HelveticaBoldOblique + WinAnsiEncoding + 718 + 532 + 718 + -207 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Helvetica-Oblique.xml b/src/codegen/Helvetica-Oblique.xml new file mode 100644 index 000000000..00339df1d --- /dev/null +++ b/src/codegen/Helvetica-Oblique.xml @@ -0,0 +1,242 @@ + + + Helvetica-Oblique + HelveticaOblique + WinAnsiEncoding + 718 + 523 + 718 + -207 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Helvetica.xml b/src/codegen/Helvetica.xml new file mode 100644 index 000000000..b5221bfb9 --- /dev/null +++ b/src/codegen/Helvetica.xml @@ -0,0 +1,242 @@ + + + Helvetica + Helvetica + WinAnsiEncoding + 718 + 523 + 718 + -207 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Times-Bold.xml b/src/codegen/Times-Bold.xml new file mode 100644 index 000000000..f446d298d --- /dev/null +++ b/src/codegen/Times-Bold.xml @@ -0,0 +1,242 @@ + + + Times-Bold + TimesBold + WinAnsiEncoding + 676 + 461 + 676 + -205 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Times-BoldItalic.xml b/src/codegen/Times-BoldItalic.xml new file mode 100644 index 000000000..b79b83179 --- /dev/null +++ b/src/codegen/Times-BoldItalic.xml @@ -0,0 +1,242 @@ + + + Times-BoldItalic + TimesBoldItalic + WinAnsiEncoding + 669 + 462 + 699 + -205 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Times-Italic.xml b/src/codegen/Times-Italic.xml new file mode 100644 index 000000000..5b0242e5e --- /dev/null +++ b/src/codegen/Times-Italic.xml @@ -0,0 +1,242 @@ + + + Times-Italic + TimesItalic + WinAnsiEncoding + 653 + 441 + 683 + -205 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/Times-Roman.xml b/src/codegen/Times-Roman.xml new file mode 100644 index 000000000..ae5c16151 --- /dev/null +++ b/src/codegen/Times-Roman.xml @@ -0,0 +1,242 @@ + + + Times-Roman + TimesRoman + WinAnsiEncoding + 662 + 450 + 683 + -217 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/codegen/charlist.xml b/src/codegen/charlist.xml new file mode 100644 index 000000000..30fc1fa01 --- /dev/null +++ b/src/codegen/charlist.xml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 index 000000000..e65ea9895 --- /dev/null +++ b/src/codegen/code-point-mapping.xsl @@ -0,0 +1,19 @@ + + + diff --git a/src/codegen/font-file.xsl b/src/codegen/font-file.xsl new file mode 100644 index 000000000..0a52f7563 --- /dev/null +++ b/src/codegen/font-file.xsl @@ -0,0 +1,56 @@ + + + diff --git a/src/codegen/properties.xml b/src/codegen/properties.xml new file mode 100644 index 000000000..cfeb6aac2 --- /dev/null +++ b/src/codegen/properties.xml @@ -0,0 +1,315 @@ + + + font-size + FontSize + true + Length + 12pt + + + start-indent + StartIndent + true + Length + 0pt + + + font-style + FontStyle + true + String + normal + + + flow-name + FlowName + false + String + + + + page-master-first + PageMasterFirst + false + String + + + + page-master-odd + PageMasterOdd + false + String + + + + extent + Extent + true + Length + 0pt + + + font-weight + FontWeight + true + String + normal + + + margin-left + MarginLeft + false + Length + 0pt + + + font-family + FontFamily + true + String + sans-serif + + + page-master-even + PageMasterEven + false + String + + + + margin-top + MarginTop + false + Length + 0pt + + + page-master-name + PageMasterName + false + String + + + + end-indent + EndIndent + true + Length + 0pt + + + color + Color + true + ColorType + black + + + margin-bottom + MarginBottom + false + Length + 0pt + + + page-height + PageHeight + false + Length + 11in + + + space-before.optimum + SpaceBeforeOptimum + false + Length + 0pt + + + provisional-label-separation + ProvisionalLabelSeparation + true + Length + 6pt + + + id + ID + false + String + + + + margin-right + MarginRight + false + Length + 0pt + + + rule-thickness + RuleThickness + false + Length + 1pt + + + page-width + PageWidth + false + Length + 8in + + + page-master-repeating + PageMasterRepeating + false + String + + + + provisional-distance-between-starts + ProvisionalDistanceBetweenStarts + true + Length + 24pt + + + line-height + LineHeight + true + Length + 12pt + + + space-after.optimum + SpaceAfterOptimum + false + Length + 0pt + + + text-align + TextAlign + true + + + centered + end + start + justified + + + start + + + white-space-treatment + WhiteSpaceTreatment + true + + + preserve + collapse + ignore + + + collapse + + + break-after + BreakAfter + false + + + auto + column + page + even-page + odd-page + + + auto + + + break-before + BreakBefore + false + + + auto + column + page + even-page + odd-page + + + auto + + + wrap-option + WrapOption + true + + + wrap + no-wrap + + + wrap + + + text-align-last + TextAlignLast + true + + + centered + end + start + justified + + + start + + START + END + START + CENTERED + + + + line-height + LineHeight + true + Length + normal + + + 1.2,propertyList.get("font-size") + d,propertyList.get("font-size") + value + + + + text-indent + TextIndent + false + Length + 0pt + + + href + HRef + false + String + + + + column-width + ColumnWidth + false + Length + 0pt + + + diff --git a/src/codegen/properties.xsl b/src/codegen/properties.xsl new file mode 100644 index 000000000..97289b912 --- /dev/null +++ b/src/codegen/properties.xsl @@ -0,0 +1,137 @@ + + + + + diff --git a/src/org/Makefile b/src/org/Makefile new file mode 100644 index 000000000..fa3129b6c --- /dev/null +++ b/src/org/Makefile @@ -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 index 000000000..10781e4b0 --- /dev/null +++ b/src/org/apache/Makefile @@ -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 index 000000000..173fad8d4 --- /dev/null +++ b/src/org/apache/fop/Makefile @@ -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 index 000000000..0786ba7aa --- /dev/null +++ b/src/org/apache/fop/apps/CommandLine.java @@ -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 index 000000000..fc0ba13fd --- /dev/null +++ b/src/org/apache/fop/apps/Driver.java @@ -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 index 000000000..c2aaa277d --- /dev/null +++ b/src/org/apache/fop/apps/ErrorHandler.java @@ -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 index 000000000..1bbbf051f --- /dev/null +++ b/src/org/apache/fop/apps/FOPException.java @@ -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 index 000000000..f1cd6126a --- /dev/null +++ b/src/org/apache/fop/apps/Makefile @@ -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 index 000000000..bcc2c26e0 --- /dev/null +++ b/src/org/apache/fop/apps/Version.java @@ -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 index 000000000..bd273c45c --- /dev/null +++ b/src/org/apache/fop/apps/XTCommandLine.java @@ -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 index 000000000..1832867a5 --- /dev/null +++ b/src/org/apache/fop/apps/package.html @@ -0,0 +1,7 @@ + +org.apache.xml.fop.apps Package + +

Application classes used for running FOP both on the command line and +embedded in other applications.

+ + \ 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 index 000000000..43c691d50 --- /dev/null +++ b/src/org/apache/fop/datatypes/ColorType.java @@ -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 index 000000000..1b67dfd97 --- /dev/null +++ b/src/org/apache/fop/datatypes/Length.java @@ -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 index 000000000..87a779187 --- /dev/null +++ b/src/org/apache/fop/datatypes/Makefile @@ -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 index 000000000..04f65b164 --- /dev/null +++ b/src/org/apache/fop/datatypes/package.html @@ -0,0 +1,6 @@ + +org.apache.xml.fop.datatypes Package + +

XSL Datatypes

+ + \ 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 index 000000000..04fc3a0eb --- /dev/null +++ b/src/org/apache/fop/fo/ElementMapping.java @@ -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 index 000000000..ede968d78 --- /dev/null +++ b/src/org/apache/fop/fo/FONode.java @@ -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 index 000000000..f61995a88 --- /dev/null +++ b/src/org/apache/fop/fo/FOText.java @@ -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 index 000000000..d4a1f5d09 --- /dev/null +++ b/src/org/apache/fop/fo/FOTreeBuilder.java @@ -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 index 000000000..a94cbcad6 --- /dev/null +++ b/src/org/apache/fop/fo/FObj.java @@ -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 index 000000000..177e940b1 --- /dev/null +++ b/src/org/apache/fop/fo/FObjMixed.java @@ -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 index 000000000..da4211088 --- /dev/null +++ b/src/org/apache/fop/fo/Makefile @@ -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 index 000000000..420bee8cb --- /dev/null +++ b/src/org/apache/fop/fo/Property.java @@ -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 index 000000000..e3a6092b7 --- /dev/null +++ b/src/org/apache/fop/fo/PropertyList.java @@ -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 index 000000000..7c12763d6 --- /dev/null +++ b/src/org/apache/fop/fo/PropertyListBuilder.java @@ -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 index 000000000..396b01aeb --- /dev/null +++ b/src/org/apache/fop/fo/StandardElementMapping.java @@ -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 index 000000000..61e28108a --- /dev/null +++ b/src/org/apache/fop/fo/flow/Block.java @@ -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 index 000000000..90f4508e5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplayGraphic.java @@ -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 index 000000000..83784816e --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplayRule.java @@ -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 index 000000000..c50b6bc6a --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplaySequence.java @@ -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 index 000000000..b9b66a1b8 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Flow.java @@ -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 index 000000000..33efc6b31 --- /dev/null +++ b/src/org/apache/fop/fo/flow/InlineSequence.java @@ -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 index 000000000..6810825d5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListBlock.java @@ -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 index 000000000..f69cf45da --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItem.java @@ -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 index 000000000..c348355f5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItemBody.java @@ -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 index 000000000..fe7c0513a --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItemLabel.java @@ -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 index 000000000..72876ca68 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Makefile @@ -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 index 000000000..3a3f59813 --- /dev/null +++ b/src/org/apache/fop/fo/flow/PageNumber.java @@ -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 index 000000000..5dc6971e1 --- /dev/null +++ b/src/org/apache/fop/fo/flow/StaticContent.java @@ -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 index 000000000..f838a7947 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Table.java @@ -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 index 000000000..9ff6a842c --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableBody.java @@ -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 index 000000000..f2df8328c --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableCell.java @@ -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 index 000000000..6888bbef9 --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableColumn.java @@ -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 index 000000000..4f2f27a6a --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableRow.java @@ -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 index 000000000..5e4d01dba --- /dev/null +++ b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java @@ -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 index 000000000..ca1a2a346 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/Makefile @@ -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 index 000000000..eaae6366d --- /dev/null +++ b/src/org/apache/fop/fo/pagination/PageSequence.java @@ -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 index 000000000..afac8fd1a --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionAfter.java @@ -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 index 000000000..79994d00f --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionBefore.java @@ -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 index 000000000..dfeaa880a --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionBody.java @@ -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 index 000000000..ecfb42ba3 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/Root.java @@ -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 index 000000000..abea78aa0 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecification.java @@ -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 index 000000000..eef8433c5 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifier.java @@ -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 index 000000000..f81bd1224 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java @@ -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 index 000000000..1a5185137 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java @@ -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 index 000000000..bb46eff2f --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java @@ -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 index 000000000..7f0a38841 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -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 index 000000000..a56084135 --- /dev/null +++ b/src/org/apache/fop/image/BmpBwImage.java @@ -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 index 000000000..95287d340 --- /dev/null +++ b/src/org/apache/fop/image/BmpColImage.java @@ -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>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 index 000000000..cbac46735 --- /dev/null +++ b/src/org/apache/fop/image/ImageArea.java @@ -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 index 000000000..9cd51e2cd --- /dev/null +++ b/src/org/apache/fop/image/Makefile @@ -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 index 000000000..3406154cd --- /dev/null +++ b/src/org/apache/fop/layout/AlternatingPageMasterFactory.java @@ -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 index 000000000..cc9ba21b9 --- /dev/null +++ b/src/org/apache/fop/layout/Area.java @@ -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 index 000000000..ff4de0d10 --- /dev/null +++ b/src/org/apache/fop/layout/AreaContainer.java @@ -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 index 000000000..47d28ab9a --- /dev/null +++ b/src/org/apache/fop/layout/AreaTree.java @@ -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 index 000000000..cdc8d6abc --- /dev/null +++ b/src/org/apache/fop/layout/BlockArea.java @@ -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 index 000000000..f5c5afeaf --- /dev/null +++ b/src/org/apache/fop/layout/Box.java @@ -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 index 000000000..f721a0c2c --- /dev/null +++ b/src/org/apache/fop/layout/DisplaySpace.java @@ -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 index 000000000..7deb34d4d --- /dev/null +++ b/src/org/apache/fop/layout/FontInfo.java @@ -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 index 000000000..8f157960c --- /dev/null +++ b/src/org/apache/fop/layout/FontMetric.java @@ -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 index 000000000..dea5014de --- /dev/null +++ b/src/org/apache/fop/layout/FontState.java @@ -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 index 000000000..740d3fee2 --- /dev/null +++ b/src/org/apache/fop/layout/InlineArea.java @@ -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 index 000000000..d33f2e459 --- /dev/null +++ b/src/org/apache/fop/layout/InlineSpace.java @@ -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 index 000000000..8286c1f5a --- /dev/null +++ b/src/org/apache/fop/layout/LineArea.java @@ -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 index 000000000..3139558d1 --- /dev/null +++ b/src/org/apache/fop/layout/Makefile @@ -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 index 000000000..49b5ca942 --- /dev/null +++ b/src/org/apache/fop/layout/Page.java @@ -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 index 000000000..5a164afce --- /dev/null +++ b/src/org/apache/fop/layout/PageMaster.java @@ -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 index 000000000..9e15c6016 --- /dev/null +++ b/src/org/apache/fop/layout/PageMasterFactory.java @@ -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 index 000000000..aeb9358cc --- /dev/null +++ b/src/org/apache/fop/layout/Region.java @@ -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 index 000000000..06fa48e0f --- /dev/null +++ b/src/org/apache/fop/layout/RepeatingPageMasterFactory.java @@ -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 index 000000000..cfce4873c --- /dev/null +++ b/src/org/apache/fop/layout/RuleArea.java @@ -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 index 000000000..f62d47e30 --- /dev/null +++ b/src/org/apache/fop/layout/SinglePageMasterFactory.java @@ -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 index 000000000..5663cea21 --- /dev/null +++ b/src/org/apache/fop/layout/Space.java @@ -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 index 000000000..111ac16ed --- /dev/null +++ b/src/org/apache/fop/pdf/Makefile @@ -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 index 000000000..58b485d27 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFDocument.java @@ -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 index 000000000..fb57573b9 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFFont.java @@ -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 index 000000000..9f2cc3a65 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFInfo.java @@ -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 index 000000000..059157fdf --- /dev/null +++ b/src/org/apache/fop/pdf/PDFObject.java @@ -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 index 000000000..405f537b9 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFPage.java @@ -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 index 000000000..cac6d1e00 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFPages.java @@ -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 index 000000000..0bbb3aaff --- /dev/null +++ b/src/org/apache/fop/pdf/PDFResources.java @@ -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 index 000000000..9c4b183d7 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFRoot.java @@ -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 index 000000000..14d3ecf23 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFStream.java @@ -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 index 000000000..3a494201d --- /dev/null +++ b/src/org/apache/fop/pdf/PDFXObject.java @@ -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 +org.apache.xml.fop.pdf Package + +

Classes for handling the low-level creation of PDF documents

+

These classes were developed for FOP, but could be used by other +applications wishing to produce PDF.

+ + \ 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 index 000000000..16807e584 --- /dev/null +++ b/src/org/apache/fop/render/Makefile @@ -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 index 000000000..93842dc3f --- /dev/null +++ b/src/org/apache/fop/render/Renderer.java @@ -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 index 000000000..0e31dbd07 --- /dev/null +++ b/src/org/apache/fop/render/package.html @@ -0,0 +1,6 @@ + +org.apache.xml.fop.render Package + +

generic renderer interface

+ + \ 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 index 000000000..8d5d94a0f --- /dev/null +++ b/src/org/apache/fop/render/pdf/Font.java @@ -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 index 000000000..90ca29c5a --- /dev/null +++ b/src/org/apache/fop/render/pdf/FontSetup.java @@ -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 index 000000000..eda522ec4 --- /dev/null +++ b/src/org/apache/fop/render/pdf/Makefile @@ -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 index 000000000..cb6165edd --- /dev/null +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -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 index 000000000..a4658ae4e --- /dev/null +++ b/src/org/apache/fop/render/pdf/fonts/Makefile @@ -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 index 000000000..dbd584a22 --- /dev/null +++ b/src/org/apache/fop/render/pdf/fonts/package.html @@ -0,0 +1,7 @@ + +org.apache.xml.fop.render.pdf.fonts Package + +

PDF font information/metrics

+

Generated entirely from XML files.

+ + \ 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 index 000000000..ec19c7cc2 --- /dev/null +++ b/src/org/apache/fop/render/pdf/package.html @@ -0,0 +1,6 @@ + +org.apache.xml.fop.render.pdf Package + +

classes for rendering to PDF

+ + \ 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 index 000000000..75c36869e --- /dev/null +++ b/src/org/apache/fop/render/xml/Makefile @@ -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 index 000000000..9efc436dd --- /dev/null +++ b/src/org/apache/fop/render/xml/XMLRenderer.java @@ -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("\n\n"); + writeStartTag(""); + Enumeration e = areaTree.getPages().elements(); + while (e.hasMoreElements()) { + this.renderPage((Page) e.nextElement()); + } + writeEndTag(""); + 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"); + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Box b = (Box) e.nextElement(); + b.render(this); + } + writeEndTag(""); + } + + /** + * render a block area to XML + * + * @param area the block area to render + */ + public void renderBlockArea(BlockArea area) { + writeStartTag(""); + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Box b = (Box) e.nextElement(); + b.render(this); + } + writeEndTag(""); + } + + /** + * render a display space to XML + * + * @param space the space to render + */ + public void renderDisplaySpace(DisplaySpace space) { + writeEmptyElementTag(""); + } + + /** + * render an SVG area to XML + * + * @param area the area to render + */ + public void renderSVGArea(SVGArea area) { + writeEmptyElementTag(""); + } + + /** + * render an image area to XML + * + * @param area the area to render + */ + public void renderImageArea(ImageArea area) { + writeEmptyElementTag(""); + } + + /** + * 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("" + sb.toString() + + ""); + } + + /** + * render an inline space to XML + * + * @param space the space to render + */ + public void renderInlineSpace(InlineSpace space) { + writeEmptyElementTag(""); + } + + /** + * render a line area to XML + * + * @param area the area to render + */ + public void renderLineArea(LineArea area) { + String fontWeight = area.getFontState().getFontWeight(); + writeStartTag(""); + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Box b = (Box)e.nextElement(); + b.render(this); + } + writeEndTag(""); + } + + /** + * render a page to XML + * + * @param page the page to render + */ + public void renderPage(Page page) { + AreaContainer body, before, after; + writeStartTag(""); + body = page.getBody(); + before = page.getBefore(); + after = page.getAfter(); + if (before != null) { + renderAreaContainer(before); + } + renderAreaContainer(body); + if (after != null) { + renderAreaContainer(after); + } + writeEndTag(""); + } + + /** + * render a rule area to XML + * + * @param area the area to render + */ + public void renderRuleArea(RuleArea area) { + writeEmptyElementTag(""); + } +} diff --git a/src/org/apache/fop/render/xml/package.html b/src/org/apache/fop/render/xml/package.html new file mode 100644 index 000000000..4459f9e94 --- /dev/null +++ b/src/org/apache/fop/render/xml/package.html @@ -0,0 +1,6 @@ + +org.apache.xml.fop.render.xml Package + +

classes for rendering to XML for debugging

+ + \ 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 index 000000000..48b0c31e9 --- /dev/null +++ b/src/org/apache/fop/svg/Graphic.java @@ -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 index 000000000..93ed5cb51 --- /dev/null +++ b/src/org/apache/fop/svg/Line.java @@ -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 index 000000000..f4d103e22 --- /dev/null +++ b/src/org/apache/fop/svg/LineGraphic.java @@ -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 index 000000000..f2f9f5b73 --- /dev/null +++ b/src/org/apache/fop/svg/Makefile @@ -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 index 000000000..e86657744 --- /dev/null +++ b/src/org/apache/fop/svg/Rect.java @@ -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 index 000000000..e27bd488b --- /dev/null +++ b/src/org/apache/fop/svg/RectGraphic.java @@ -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 index 000000000..2e229e738 --- /dev/null +++ b/src/org/apache/fop/svg/SVG.java @@ -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 index 000000000..7a6ac2815 --- /dev/null +++ b/src/org/apache/fop/svg/SVGArea.java @@ -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 index 000000000..c01041c6b --- /dev/null +++ b/src/org/apache/fop/svg/SVGElementMapping.java @@ -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 index 000000000..252946046 --- /dev/null +++ b/src/org/apache/fop/svg/SVGLength.java @@ -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 index 000000000..d24a10d94 --- /dev/null +++ b/src/org/apache/fop/svg/Text.java @@ -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 index 000000000..e0510f2f1 --- /dev/null +++ b/src/org/apache/fop/svg/TextGraphic.java @@ -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 index 000000000..695f0699c --- /dev/null +++ b/src/org/apache/fop/svg/package.html @@ -0,0 +1,7 @@ + +org.apache.xml.fop.svg Package + +

Classes that add basic SVG support to FOP

+

This includes flow objects, areas and properties.

+ + \ No newline at end of file diff --git a/src/overview.html b/src/overview.html new file mode 100644 index 000000000..693138338 --- /dev/null +++ b/src/overview.html @@ -0,0 +1,7 @@ + +FOP Overview + +

FOP is an XSL formatter and renderer that works with an XSLT transformer to +produce PDF (and eventually other output formats) from XML documents.

+ + \ No newline at end of file -- 2.39.5