]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
updates to area tree and reading/rendering with xml
authorKeiron Liddle <keiron@apache.org>
Fri, 26 Oct 2001 09:27:00 +0000 (09:27 +0000)
committerKeiron Liddle <keiron@apache.org>
Fri, 26 Oct 2001 09:27:00 +0000 (09:27 +0000)
added user agent, xml handlers
added inline level property

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194521 13f79535-47bb-0310-9956-ffa450edef68

34 files changed:
src/org/apache/fop/apps/XSLTInputHandler.java
src/org/apache/fop/area/Area.java
src/org/apache/fop/area/AreaTree.java
src/org/apache/fop/area/BeforeFloat.java
src/org/apache/fop/area/Block.java
src/org/apache/fop/area/BodyRegion.java
src/org/apache/fop/area/Flow.java
src/org/apache/fop/area/Footnote.java
src/org/apache/fop/area/LineArea.java
src/org/apache/fop/area/LineProperty.java [new file with mode: 0644]
src/org/apache/fop/area/MainReference.java
src/org/apache/fop/area/Page.java
src/org/apache/fop/area/PageViewport.java
src/org/apache/fop/area/Property.java [new file with mode: 0644]
src/org/apache/fop/area/Region.java
src/org/apache/fop/area/RegionViewport.java
src/org/apache/fop/area/Span.java
src/org/apache/fop/area/inline/Container.java
src/org/apache/fop/area/inline/ForeignObject.java
src/org/apache/fop/area/inline/Image.java
src/org/apache/fop/area/inline/InlineArea.java
src/org/apache/fop/area/inline/Leader.java
src/org/apache/fop/area/inline/Viewport.java
src/org/apache/fop/area/inline/Word.java
src/org/apache/fop/fo/FOUserAgent.java
src/org/apache/fop/pdf/PDFDocument.java
src/org/apache/fop/render/AbstractRenderer.java
src/org/apache/fop/render/Renderer.java
src/org/apache/fop/render/RendererContext.java [new file with mode: 0644]
src/org/apache/fop/render/XMLHandler.java [new file with mode: 0644]
src/org/apache/fop/render/pdf/PDFRenderer.java
src/org/apache/fop/render/xml/XMLRenderer.java
src/org/apache/fop/render/xml/XMLXMLHandler.java [new file with mode: 0644]
src/org/apache/fop/tools/AreaTreeBuilder.java

index 2b7e58fee580578021b809dcc52d10d204ca3672..89ba30876a3e8a8edae54ae9ab3afb79d85e91df 100644 (file)
@@ -21,6 +21,10 @@ import java.io.*;
 // FOP
 import org.apache.fop.tools.xslt.XSLTransform;
 
+/*
+add url constructer
+*/
+
 /**
  * XSLTInputHandler basically takes an xmlfile and transforms it with an xsltfile
  * and the resulting xsl:fo document is input for Fop.
index 3d43a5f5b8660bcc98d7fe9394243d31e30ccc37..6a03182756ec91ae30e009dfc6afae075b77d7a6 100644 (file)
@@ -7,10 +7,12 @@
 
 package org.apache.fop.area;
 
+import java.io.Serializable;
+
 /**
- * base object for all areas
+ * Base object for all areas.
  */
-public class Area {
+public class Area implements Serializable {
     // stacking directions
     public static final int LR = 0;
     public static final int RL = 1;
index 6f3157773f0c7ef75661cff6176409330d3e8bc0..b8544878c3a81bb70dd308e4f672dccd6f58a336 100644 (file)
@@ -9,6 +9,24 @@ package org.apache.fop.area;
 
 import java.util.ArrayList;
 
+
+/**
+ * Area tree for formatting objects.
+ *
+ * Concepts:
+ * The area tree is to be as small as possible. With minimal classes
+ * and data to fully represent an area tree for formatting objects.
+ * The area tree needs to be simple to render and follow the spec
+ * closely.
+ * This area tree has the concept of page sequences.
+ * Where ever possible information is discarded or optimised to
+ * keep memory use low. The data is also organised to make it
+ * possible for renderers to minimise their output.
+ * A page can be saved if not fully resolved and once rendered
+ * a page contains only size and id reference information.
+ * The area tree pages are organised in a model that depends on the
+ * type of renderer.
+ */
 public class AreaTree {
     // allows for different models to deal with adding/rendering
     // in different situations
@@ -40,15 +58,6 @@ public class AreaTree {
         public abstract void addPage(PageViewport page);
     }
 
-    // this queues pages and will call the render listener
-    // when the page is ready to be rendered
-    // if the render supports out of order rendering
-    // then a ready page is rendered immediately
-    public static class RenderPagesModel extends AreaTreeModel {
-        public void startPageSequence(Area title) {}
-        public void addPage(PageViewport page) {}
-    }
-
     // this class stores all the pages in the document
     // for interactive agents
     public static class StorePagesModel extends AreaTreeModel {
@@ -89,10 +98,20 @@ public class AreaTree {
             return (PageViewport) sequence.get(count);
         }
     }
-}
 
-abstract class PageRenderListener {
-    public abstract void startPageSequence(Area title);
-    public abstract void preparePage(PageViewport page);
-    public abstract void renderPage(PageViewport page);
+    // this queues pages and will call the render listener
+    // when the page is ready to be rendered
+    // if the render supports out of order rendering
+    // then a ready page is rendered immediately
+    public static class RenderPagesModel extends StorePagesModel {
+        public void startPageSequence(Area title) {}
+        public void addPage(PageViewport page) {}
+    }
+
+    public static abstract class PageRenderListener {
+        public abstract void renderPage(RenderPagesModel model,
+                                        int pageseq, int count);
+    }
+
 }
+
index f313eb5590a47b70f83cd201e7a2a0edb9368a6b..034d467d24196ed7420aa33b24cb62ecea9b37ba 100644 (file)
@@ -21,6 +21,17 @@ public class BeforeFloat extends Area {
 
     ArrayList blocks = null;
 
+    public void addBlock(Block block) {
+        if (blocks == null) {
+            blocks = new ArrayList();
+        }
+        blocks.add(block);
+    }
+
+    public void setSeparator(Block sep) {
+        separator = sep;
+    }
+
     public List getBlocks() {
         return blocks;
     }
index cf070497f74d2b27afb20836640994f90bd9abfc..9a7e3b30c8e9fa238f3a36d77fb1c5a5697885ab 100644 (file)
@@ -7,6 +7,7 @@
 
 package org.apache.fop.area;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import java.awt.geom.Rectangle2D;
@@ -17,7 +18,7 @@ import java.awt.geom.Rectangle2D;
 // or by relative to the parent for floats, tables and lists
 // cacheable object
 // has id information
-public class Block extends Area {
+public class Block extends Area implements Serializable {
     // normally stacked with other blocks
     public static final int STACK = 0;
     // placed relative to the parent area
@@ -79,4 +80,18 @@ public class Block extends Area {
     public int getPositioning() {
         return positioning;
     }
+
+    // store properties in array list, need better solution
+    ArrayList props = null;
+
+    public void addProperty(Property prop) {
+        if (props == null) {
+            props = new ArrayList();
+        }
+        props.add(prop);
+    }
+
+    public List getPropertyList() {
+        return props;
+    }
 }
index 0661ebdd759acf7d8c7aa24a9c141d54e580ed19..e6e886404f25d3e3ec0dc092c08e28829b15d8a0 100644 (file)
@@ -16,6 +16,19 @@ public class BodyRegion extends Region {
         super(BODY);
     }
 
+    public void setBeforeFloat(BeforeFloat bf) {
+        beforeFloat = bf;
+    }
+
+    public void setMainReference(MainReference mr) {
+        mainReference = mr;
+    }
+
+    public void setFootnote(Footnote foot) {
+        footnote = foot;
+    }
+
+
     public BeforeFloat getBeforeFloat() {
         return beforeFloat;
     }
index d054a51d596d60f8b189038f5b0731645c39215d..6cfa09a5301c196e361170a916bb495d321d6ab4 100644 (file)
@@ -18,6 +18,10 @@ public class Flow extends Area {
     int stacking = TB;
     int width;
 
+    public void addBlock(Block block) {
+        blocks.add(block);
+    }
+
     public List getBlocks() {
         return blocks;
     }
index 1baf1502cd5208ccd3e74a17bef93aa31ff7706f..dcd62ecdf4f9bf091c0ee6c05b2ec468ed6eb54b 100644 (file)
@@ -23,6 +23,17 @@ public class Footnote {
 
     ArrayList blocks = null;
 
+    public void setSeparator(Block sep) {
+        separator = sep;
+    }
+
+    public void addBlock(Block block) {
+        if (blocks == null) {
+            blocks = new ArrayList();
+        }
+        blocks.add(block);
+    }
+
     public Block getSeparator() {
         return separator;
     }
index 2e39b51757b4ae87646a11b20d729e5038af7352..8184d332a0f0bd9f8eaa2bd9051837fffb01baa2 100644 (file)
@@ -31,6 +31,14 @@ public class LineArea extends Area {
 
     ArrayList inlineAreas = new ArrayList();
 
+    public void setHeight(int height) {
+        lineHeight = height;
+    }
+
+    public int getHeight() {
+        return lineHeight;
+    }
+
     public void addInlineArea(InlineArea area) {
         inlineAreas.add(area);
     }
@@ -38,11 +46,19 @@ public class LineArea extends Area {
     public List getInlineAreas() {
         return inlineAreas;
     }
+
+    // store properties in array list, need better solution
+    ArrayList props = null;
+
+    public void addProperty(Property prop) {
+        if (props == null) {
+            props = new ArrayList();
+        }
+        props.add(prop);
+    }
+
+    public List getPropertyList() {
+        return props;
+    }
 }
-/*
-class LineProperty {
-    int propType;
-    int[] range;
-    Object data;
-}
-*/
+
diff --git a/src/org/apache/fop/area/LineProperty.java b/src/org/apache/fop/area/LineProperty.java
new file mode 100644 (file)
index 0000000..d5eb3da
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.area;
+
+public class LineProperty extends Property {
+    int[] range;
+}
+
index 4c705637fd6ba0cb79dacc3fe206c2ede34b5ced..b18008b42161cb86f7746a1a9a915c207f673641 100644 (file)
@@ -7,15 +7,20 @@
 
 package org.apache.fop.area;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
 // the area that contains the flow via the span areas
-public class MainReference {
+public class MainReference implements Serializable {
     List spanAreas = new ArrayList();
     int columnGap;
     int width;
 
+    public void addSpan(Span span) {
+        spanAreas.add(span);
+    }
+
     public List getSpans() {
         return spanAreas;
     }
index 059d981504bf11260c208b34cd05620f5e15461c..e8b1bfd62b412eb0ffe1ca28fd633608bd82b55a 100644 (file)
@@ -7,7 +7,9 @@
 
 package org.apache.fop.area;
 
-public class Page {
+import java.io.Serializable;
+
+public class Page implements Serializable {
     // contains before, start, body, end and after regions
     RegionViewport regionBefore = null;
     RegionViewport regionStart = null;
index 29354eda2e116acf2d645c7057f0f2f52fbdf572..18e8ba4ff3df8ff1a2e05bbded6d003ae409fb35 100644 (file)
@@ -8,6 +8,8 @@
 package org.apache.fop.area;
 
 import java.awt.geom.Rectangle2D;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
 import java.util.ArrayList;
 
 // this is the level that creates the page
@@ -15,17 +17,36 @@ import java.util.ArrayList;
 public class PageViewport {
     Page page;
     Rectangle2D viewArea;
+    boolean clip = false;
 
-    public PageViewport(Page p) {
+    public PageViewport(Page p, Rectangle2D bounds) {
         page = p;
+        viewArea = bounds;
     }
 
     // this list is only used when the page is discarded
     // the information is kept for future reference
     ArrayList idReferences = null;
 
+    public void setClip(boolean c) {
+        clip = c;
+    }
+
+    public Rectangle2D getViewArea() {
+        return viewArea;
+    }
+
     // a viewport area for page and reference areas
     public Page getPage() {
         return page;
     }
+
+    public void savePage(ObjectOutputStream out) throws Exception {
+        out.writeObject(page);
+        page = null;
+    }
+
+    public void loadPage(ObjectInputStream in) throws Exception {
+        page = (Page) in.readObject();
+    }
 }
diff --git a/src/org/apache/fop/area/Property.java b/src/org/apache/fop/area/Property.java
new file mode 100644 (file)
index 0000000..3b9a836
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.area;
+
+import java.io.Serializable;
+
+// properties should be serialized by the holder
+public class Property implements Serializable {
+    public static final int ID_LINK = 0;
+    public static final int INTERNAL_LINK = 1; //resolved
+    public static final int EXTERNAL_LINK = 2;
+    public static final int FONT_FAMILY = 3;
+    public static final int FONT_SIZE = 4;
+    public static final int FONT_WEIGHT = 5;
+    public static final int FONT_STYLE = 6;
+    public static final int COLOR = 7;
+    public static final int ID_AREA = 8;
+    public static final int BACKGROUND = 9;
+    public static final int UNDERLINE = 10;
+    public static final int OVERLINE = 11;
+    public static final int LINETHROUGH = 12;
+    public static final int OFFSET = 13;
+    public static final int SHADOW = 14;
+    public int propType;
+    public Object data;
+
+}
+
index d51da6e2d72e283f896230d62c08905531b2dc53..47f2dbfd9aee7280d8fc9a8842a865442c8ac297 100644 (file)
@@ -7,10 +7,11 @@
 
 package org.apache.fop.area;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
-public class Region {
+public class Region implements Serializable {
     public static final int BEFORE = 0;
     public static final int START = 1;
     public static final int BODY = 2;
index 3a90bb95e9cde1f0913e2e92d8feef21142e3875..43b320399b541f85ad0928565619916a05e0768c 100644 (file)
@@ -8,20 +8,48 @@
 package org.apache.fop.area;
 
 import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.io.IOException;
 
-public class RegionViewport {
+public class RegionViewport implements Serializable {
     // this rectangle is relative to the page
     Rectangle2D regionArea;
-    boolean clip;
+    boolean clip = false;
 
     Region region;
 
+    public RegionViewport(Rectangle2D area) {
+        regionArea = area;
+    }
+
     public void setRegion(Region reg) {
         region = reg;
     }
 
+    public Rectangle2D getViewArea() {
+        return regionArea;
+    }
+
     public Region getRegion() {
         return region;
     }
 
+    private void writeObject(java.io.ObjectOutputStream out)
+    throws IOException {
+        out.writeFloat((float) regionArea.getX());
+        out.writeFloat((float) regionArea.getY());
+        out.writeFloat((float) regionArea.getWidth());
+        out.writeFloat((float) regionArea.getHeight());
+        out.writeBoolean(clip);
+        out.writeObject(region);
+    }
+
+    private void readObject(java.io.ObjectInputStream in)
+    throws IOException, ClassNotFoundException {
+        regionArea = new Rectangle2D.Float(in.readFloat(), in.readFloat(),
+                                           in.readFloat(), in.readFloat());
+        clip = in.readBoolean();
+        region = (Region) in.readObject();
+    }
+
 }
index 28dddc7daf1dacd2d3327e66fb3ccefb09ca221a..fc8b45913a766d5d1e380b66d5871bd6db38bd7c 100644 (file)
@@ -12,9 +12,17 @@ import java.util.ArrayList;
 // this is a reference area block area with 0 border and padding
 public class Span extends Area {
     // the list of flow reference areas in this span area
-    ArrayList flowAreas = new ArrayList();
+    ArrayList flowAreas;
     int height;
 
+    public Span(int cols) {
+        flowAreas = new ArrayList(cols);
+    }
+
+    public void addFlow(Flow flow) {
+        flowAreas.add(flow);
+    }
+
     public int getColumnCount() {
         return flowAreas.size();
     }
index 54a9ac493486539f9c5d1801fa61cdc560f2a133..76c987e21f99ef585133c34e83687ba424f7fcc4 100644 (file)
@@ -7,12 +7,14 @@
 
 package org.apache.fop.area.inline;
 
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
 import org.apache.fop.render.Renderer;
 
 import java.util.List;
 import java.util.ArrayList;
 
-public class Container extends InlineArea {
+public class Container extends Area {
     ArrayList blocks = new ArrayList();
 
     // this is an inline area that can have blocks as children
@@ -21,6 +23,10 @@ public class Container extends InlineArea {
         renderer.renderContainer(this);
     }
 
+    public void addBlock(Block block) {
+        blocks.add(block);
+    }
+
     public List getBlocks() {
         return blocks;
     }
index b6757573735946ca89f108aedcfc26deeae3e292..54f35f73c57e75e14dc55887adbac799f84bd630 100644 (file)
@@ -18,4 +18,16 @@ public class ForeignObject extends Area {
     // dom object
     // height, width
 
+    public ForeignObject(Document d, String ns) {
+        doc = d;
+        namespace = ns;
+    }
+
+    public Document getDocument() {
+        return doc;
+    }
+
+    public String getNameSpace() {
+        return namespace;
+    }
 }
index 4cf1b7f7206f77c29ab8fcaaed345cc4ef8bf799..3899997a502eb785156c87b19ad69d43e65ae633 100644 (file)
@@ -10,8 +10,16 @@ package org.apache.fop.area.inline;
 import org.apache.fop.area.Area;
 
 // cacheable object
+// image object, mime type, url
 public class Image extends Area {
+    String url;
 
-    // image object, mime type, url
+    public Image(String u) {
+        url = u;
+    }
+
+    public String getURL() {
+        return url;
+    }
 
 }
index 3c61377dc02fe2a0c1518b43faf089485c391b68..aa229316f99082ef72a47b60f7d0ffe1bcc0bdc5 100644 (file)
@@ -8,8 +8,19 @@
 package org.apache.fop.area.inline;
 
 import org.apache.fop.area.Area;
+import org.apache.fop.area.Property;
 import org.apache.fop.render.Renderer;
 
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Inline Area
+ * This area is for all inline areas that can be placed
+ * in a line area.
+ * Extensions of this class should render themselves with the
+ * requested renderer.
+ */
 public class InlineArea extends Area {
     int width;
     int height;
@@ -17,6 +28,9 @@ public class InlineArea extends Area {
     int verticalPosition;
     // width, height, vertical alignment
 
+    // store properties in array list, need better solution
+    ArrayList props = null;
+
     // inline areas are expected to implement this method
     // to render themselves
     public void render(Renderer renderer) {
@@ -30,4 +44,15 @@ public class InlineArea extends Area {
     public int getWidth() {
         return width;
     }
+
+    public void addProperty(Property prop) {
+        if (props == null) {
+            props = new ArrayList();
+        }
+        props.add(prop);
+    }
+
+    public List getPropertyList() {
+        return props;
+    }
 }
index f31949acb24193168b531068d972a7cda1b82408..2475cac80067070f0905f3fece377ad1ffb96850 100644 (file)
@@ -7,6 +7,8 @@
 
 package org.apache.fop.area.inline;
 
+import org.apache.fop.render.Renderer;
+
 public class Leader extends Stretch {
 
     // pattern, length min opt max
@@ -16,4 +18,37 @@ public class Leader extends Stretch {
     // if space replaced with a space
     // otherwise this is a holder for a line
 
+    public static final int DOTTED = 0;
+    public static final int DASHED = 1;
+    public static final int SOLID = 2;
+    public static final int DOUBLE = 3;
+    public static final int GROOVE = 4;
+    public static final int RIDGE = 5;
+
+    int ruleStyle = SOLID;
+    int ruleThickness = 1000;
+
+    public Leader() {
+
+    }
+
+    public void setRuleStyle(int style) {
+        ruleStyle = style;
+    }
+
+    public void setRuleThickness(int rt) {
+        ruleThickness = rt;
+    }
+
+    public int getRuleStyle() {
+        return ruleStyle;
+    }
+
+    public int getRuleThickness() {
+        return ruleThickness;
+    }
+
+    public void render(Renderer renderer) {
+        renderer.renderLeader(this);
+    }
 }
index a7458c53a8658c1189d0c69675e111dddbd31dfa..5e1ce23d0a8c89ee03a441e699775894750615b9 100644 (file)
@@ -8,15 +8,52 @@
 package org.apache.fop.area.inline;
 
 import org.apache.fop.area.Area;
+import org.apache.fop.render.Renderer;
 
+import java.io.IOException;
 import java.awt.geom.Rectangle2D;
 
 public class Viewport extends InlineArea {
-    // contents could be foreign object or image
+    // contents could be container, foreign object or image
     Area content;
     // an inline-level viewport area for graphic and instream foreign object
     boolean clip = false;
     // position relative to this area
     Rectangle2D contentPosition;
 
+    public Viewport(Area child) {
+        content = child;
+    }
+
+    public Area getContent() {
+        return content;
+    }
+
+    public void render(Renderer renderer) {
+        renderer.renderViewport(this);
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out)
+    throws IOException {
+        out.writeBoolean(contentPosition != null);
+        if (contentPosition != null) {
+            out.writeFloat((float) contentPosition.getX());
+            out.writeFloat((float) contentPosition.getY());
+            out.writeFloat((float) contentPosition.getWidth());
+            out.writeFloat((float) contentPosition.getHeight());
+        }
+        out.writeBoolean(clip);
+        out.writeObject(content);
+    }
+
+    private void readObject(java.io.ObjectInputStream in)
+    throws IOException, ClassNotFoundException {
+        if (in.readBoolean()) {
+            contentPosition = new Rectangle2D.Float(in.readFloat(),
+                                                    in.readFloat(), in.readFloat(), in.readFloat());
+        }
+        clip = in.readBoolean();
+        content = (Area) in.readObject();
+    }
+
 }
index 73c9ec26d87d4d81d27a9877527bb9e587138daa..070af40ff41fdaed890b05d35d7155c50a23afd1 100644 (file)
@@ -7,9 +7,14 @@
 
 package org.apache.fop.area.inline;
 
+import org.apache.fop.render.Renderer;
+
 public class Word extends InlineArea {
 
     // character info: font, char spacing, colour, baseline
     String word;
 
+    public void render(Renderer renderer) {
+        renderer.renderWord(this);
+    }
 }
index b9f74a9f6867ea975f4612ecb494f767e8491e54..05ae93456928b5dbdf42071fd3a560d1622c4693 100644 (file)
@@ -7,13 +7,18 @@
 
 package org.apache.fop.fo;
 
+import org.apache.fop.render.XMLHandler;
+import org.apache.fop.render.RendererContext;
+
 import org.w3c.dom.*;
 
+import java.util.HashMap;
+
 /**
  * The User Agent for fo.
  * This user agent is used by the processing to obtain user configurable
  * options.
- * 
+ *
  * Renderer specific extensions (that do not produce normal areas on
  * the output) will be done like so:
  * The extension will create an area, custom if necessary
@@ -24,14 +29,55 @@ import org.w3c.dom.*;
  * These areas may contain resolveable areas that will be processed
  * with other resolveable areas
  */
-public interface FOUserAgent {
-public void renderXML(RendererContext ctx, Document doc, String namespace);
+public class FOUserAgent {
+    HashMap defaults = new HashMap();
+    HashMap handlers = new HashMap();
 
-}
+    /**
+     * Set the default xml handler for the given mime type.
+     */
+    public void setDefaultXMLHandler(String mime, XMLHandler handler) {
+        defaults.put(mime, handler);
+    }
 
-class RendererContext {
-String getMimeType() {
-return null;
-}
+    /**
+     * Add an xml handler for the given mime type and xml namespace.
+     */
+    public void addXMLHandler(String mime, String ns, XMLHandler handler) {
+        HashMap mh = (HashMap) handlers.get(mime);
+        if (mh == null) {
+            mh = new HashMap();
+            handlers.put(mime, mh);
+        }
+        mh.put(ns, handler);
+    }
+
+    /** 
+     * Render the xml document with the given xml namespace.
+     * The Render Context is by the handle to render into the current
+     * rendering target.
+     */
+    public void renderXML(RendererContext ctx, Document doc,
+                          String namespace) {
+        String mime = ctx.getMimeType();
+        HashMap mh = (HashMap) handlers.get(mime);
+        XMLHandler handler = null;
+        if (mh != null) {
+            handler = (XMLHandler) mh.get(namespace);
+        }
+        if (handler == null) {
+            handler = (XMLHandler) defaults.get(mime);
+        }
+        if (handler != null) {
+            try {
+                handler.handleXML(ctx, doc, namespace);
+            } catch (Throwable t) {
+                // could not handle document
+                //t.printStackTrace();
+            }
+        } else {
+            // no handler found for document
+        }
+    }
 }
 
index cdf039b9f1d08b01743a1f343474031fed189ae2..09dcfd2776dcda84f2e82c46d5f51f6ab03eb869 100644 (file)
@@ -937,7 +937,7 @@ public class PDFDocument {
      * @return the created /Page object
      */
     public PDFPage makePage(PDFResources resources, PDFStream contents,
-                            int pagewidth, int pageheight, Page currentPage) {
+                            int pagewidth, int pageheight) {
 
         /*
          * create a PDFPage with the next object number, the given
@@ -959,7 +959,7 @@ public class PDFDocument {
             }
             pendingLinks = null;
         }
-
+/*
         if (currentPage != null) {
             Enumeration enum = currentPage.getIDList().elements();
             while (enum.hasMoreElements()) {
@@ -968,7 +968,7 @@ public class PDFDocument {
                         page.referencePDF());
             }
         }
-
+*/
         /* add it to the list of objects */
         this.objects.addElement(page);
 
index 8d99f67677f729066ad38df8bc6eb48384168b9a..a76a32f5e202153e5434a99eb53afec629c5bb2b 100644 (file)
@@ -28,7 +28,8 @@ import java.util.List;
  * Abstract base class for all renderers.
  * The Abstract renderer does all the top level processing
  * of the area tree and adds some abstract methods to handle
- * viewports.
+ * viewports. This keeps track of the current block and inline
+ * position.
  */
 public abstract class AbstractRenderer implements Renderer {
     protected Logger log;
@@ -48,7 +49,7 @@ public abstract class AbstractRenderer implements Renderer {
     }
 
     public void setUserAgent(FOUserAgent agent) {
-userAgent = agent;
+        userAgent = agent;
     }
 
     public void setOptions(HashMap opt) {
@@ -64,7 +65,7 @@ userAgent = agent;
     FOPException {
 
         Page p = page.getPage();
-renderPageAreas(p);
+        renderPageAreas(p);
     }
 
     protected void renderPageAreas(Page page) {
@@ -85,13 +86,13 @@ renderPageAreas(p);
     // the region may clip the area and it establishes
     // a position from where the region is placed
     protected void renderRegionViewport(RegionViewport port) {
-        if(port != null) {
-        Region region = port.getRegion();
-        if (region.getRegionClass() == Region.BODY) {
-            renderBodyRegion((BodyRegion) region);
-        } else {
-            renderRegion(region);
-        }
+        if (port != null) {
+            Region region = port.getRegion();
+            if (region.getRegionClass() == Region.BODY) {
+                renderBodyRegion((BodyRegion) region);
+            } else {
+                renderRegion(region);
+            }
         }
     }
 
@@ -104,17 +105,17 @@ renderPageAreas(p);
 
     protected void renderBodyRegion(BodyRegion region) {
         BeforeFloat bf = region.getBeforeFloat();
-if(bf != null) {
-        renderBeforeFloat(bf);
-}
+        if (bf != null) {
+            renderBeforeFloat(bf);
+        }
         MainReference mr = region.getMainReference();
-if(mr != null) {
-        renderMainReference(mr);
-}
+        if (mr != null) {
+            renderMainReference(mr);
+        }
         Footnote foot = region.getFootnote();
-if(foot != null) {
-        renderFootnote(foot);
-}
+        if (foot != null) {
+            renderFootnote(foot);
+        }
     }
 
     protected void renderBeforeFloat(BeforeFloat bf) {
@@ -180,6 +181,8 @@ if(foot != null) {
             if (children == null) {
                 // simply move position
             } else {
+                // a line area is rendered from the top left position
+                // of the line, each inline object is offset from there
                 for (int count = 0; count < children.size(); count++) {
                     LineArea line = (LineArea) children.get(count);
                     renderLineArea(line);
@@ -201,9 +204,26 @@ if(foot != null) {
 
     }
 
+    public void renderViewport(Viewport viewport) {
+        Area content = viewport.getContent();
+        if (content instanceof Image) {
+            renderImage((Image) content);
+        } else if (content instanceof Container) {
+            renderContainer((Container) content);
+        } else if (content instanceof ForeignObject) {
+            renderForeignObject((ForeignObject) content);
+        }
+    }
+
+    public void renderImage(Image image) {
+    }
+
     public void renderContainer(Container cont) {
         List blocks = cont.getBlocks();
         renderBlocks(blocks);
+    }
+
+    public void renderForeignObject(ForeignObject fo) {
 
     }
 
@@ -219,6 +239,14 @@ if(foot != null) {
         currentBlockIPPosition += space.getWidth();
     }
 
+    public void renderLeader(Leader area) {
+        currentBlockIPPosition += area.getWidth();
+    }
+
+    public void renderWord(Word word) {
+        currentBlockIPPosition += word.getWidth();
+    }
+
     protected void renderBlocks(List blocks) {
         for (int count = 0; count < blocks.size(); count++) {
             Block block = (Block) blocks.get(count);
index 6568e07db1ec7f3dbb7d795486ea5e4b6dd07f9f..fe4af30f6700856d159aeb9eac64368bf56064d4 100644 (file)
@@ -32,11 +32,9 @@ import java.util.HashMap;
  */
 public interface Renderer {
 
-    public void startRenderer(OutputStream outputStream)
-    throws IOException;
+    public void startRenderer(OutputStream outputStream) throws IOException;
 
-    public void stopRenderer()
-    throws IOException;
+    public void stopRenderer() throws IOException;
 
     /**
      * Set the logger
@@ -65,25 +63,19 @@ public interface Renderer {
 
     public void startPageSequence(Title seqTitle);
 
-    public void renderPage(PageViewport page)
-    throws IOException, FOPException;
+    public void renderPage(PageViewport page) throws IOException, FOPException;
 
+    public void renderViewport(Viewport viewport);
 
     public void renderContainer(Container cont);
-/*
-    public void renderInlineViewport(org.apache.fop.area.inline.Viewport view);
 
     public void renderWord(Word area);
-*/
-    public void renderCharacter(org.apache.fop.area.inline.Character ch);
 
-    public void renderInlineSpace(Space space);
-/*
-    public void renderForeignObject(ForeignObject area);
+    public void renderCharacter(
+              org.apache.fop.area.inline.Character ch);
 
-    public void renderImage(Image area);
+    public void renderInlineSpace(Space space);
 
     public void renderLeader(Leader area);
-*/
 }
 
diff --git a/src/org/apache/fop/render/RendererContext.java b/src/org/apache/fop/render/RendererContext.java
new file mode 100644 (file)
index 0000000..1fa2a16
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render;
+
+import java.util.HashMap;
+
+/**
+ * The Render Context for external handlers.
+ * This provides a rendering context so that external handlers
+ * can get information to be able to render to the render target.
+ */
+public class RendererContext {
+    String mime;
+    HashMap props = new HashMap();
+
+    public RendererContext(String m) {
+        mime = m;
+    }
+
+    public String getMimeType() {
+        return mime;
+    }
+
+    public void setProperty(String name, Object val) {
+        props.put(name, val);
+    }
+
+    public Object getProperty(String prop) {
+        return props.get(prop);
+    }
+
+}
+
diff --git a/src/org/apache/fop/render/XMLHandler.java b/src/org/apache/fop/render/XMLHandler.java
new file mode 100644 (file)
index 0000000..f734efc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.render;
+
+import org.apache.log.Logger;
+
+import org.w3c.dom.Document;
+
+/**
+ */
+public interface XMLHandler {
+
+    /**
+     * Handle an external xml document inside a Foreign Object Area
+     * This may throw an exception if for some reason it cannot be handled.
+     * The caller is expected to deal with this exception.
+     */
+    public void handleXML(RendererContext context, Document doc,
+                          String ns) throws Exception;
+}
+
index 581e4514c7269bbcd4ee153cb76b25266b484120..3a7d3fbef10334e32e6be7a66c9cac1c834cfbaf 100644 (file)
@@ -29,6 +29,24 @@ import org.w3c.dom.Document;
 import java.io.IOException;
 import java.io.OutputStream;
 
+import java.awt.geom.Rectangle2D;
+
+/*
+TODO:
+
+viewport clipping
+word rendering and optimistion
+pdf state optimistation
+line and border
+leader
+background pattern
+user agent xml (svg) rendering
+orientation
+writing mode
+text decoration
+
+ */
+
 /**
  * Renderer that renders areas to PDF
  *
@@ -40,6 +58,10 @@ public class PDFRenderer extends PrintRenderer {
      */
     protected PDFDocument pdfDoc;
 
+    protected String producer;
+
+    protected OutputStream ostream;
+
     /**
      * the /Resources object of the PDF document being created
      */
@@ -80,7 +102,7 @@ public class PDFRenderer extends PrintRenderer {
     int prevWordX = 0;
 
     /**
-     * The  width of the previous word. Used to calculate space between
+     * The width of the previous word. Used to calculate space between
      */
     int prevWordWidth = 0;
 
@@ -93,7 +115,6 @@ public class PDFRenderer extends PrintRenderer {
      * create the PDF renderer
      */
     public PDFRenderer() {
-        this.pdfDoc = new PDFDocument();
     }
 
     /**
@@ -101,23 +122,50 @@ public class PDFRenderer extends PrintRenderer {
      *
      * @param producer string indicating application producing PDF
      */
-    public void setProducer(String producer) {
-        this.pdfDoc.setProducer(producer);
+    public void setProducer(String prod) {
+        producer = prod;
     }
 
-    public void startRenderer(OutputStream stream)
-    throws IOException {
+    public void startRenderer(OutputStream stream) throws IOException {
+        ostream = stream;
+        this.pdfDoc = new PDFDocument();
+        this.pdfDoc.setProducer(producer);
         pdfDoc.outputHeader(stream);
     }
 
-    public void stopRenderer()
-    throws IOException {
+    public void stopRenderer() throws IOException {
+        FontSetup.addToResources(this.pdfDoc, fontInfo);
+        pdfDoc.outputTrailer(ostream);
+
+        this.pdfDoc = null;
+        ostream = null;
     }
 
-    public void renderPage(PageViewport page) throws IOException, FOPException {
+    /**
+     * This method creates a pdf stream for the current page
+     * uses it as the contents of a new page. The page is wriiten
+     * immediately to the output stream.
+     */
+    public void renderPage(PageViewport page) throws IOException,
+    FOPException {
+
+        this.pdfResources = this.pdfDoc.getResources();
+
+        currentStream = this.pdfDoc.makeStream();
+        currentStream.add("BT\n");
 
         Page p = page.getPage();
-renderPageAreas(p);
+        renderPageAreas(p);
+
+        currentStream.add("ET\n");
+
+        Rectangle2D bounds = page.getViewArea();
+        double w = bounds.getWidth();
+        double h = bounds.getHeight();
+        currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
+                                           (int) Math.round(w / 1000), (int) Math.round(h / 1000));
+
+        this.pdfDoc.output(ostream);
 
     }
 
index 10b15127e244a293d07e25799789f205fc4a20a7..33fa2ed9a8d91a341de5cf73613d417f42095ff4 100644 (file)
@@ -11,11 +11,14 @@ package org.apache.fop.render.xml;
 import org.apache.fop.svg.*;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.XMLHandler;
 import org.apache.fop.image.ImageArea;
 import org.apache.fop.area.*;
 import org.apache.fop.area.inline.*;
 import org.apache.fop.pdf.*;
 import org.apache.fop.fo.properties.LeaderPattern;
+import org.apache.fop.fo.FOUserAgent;
 import org.apache.fop.layout.FontInfo;
 import org.apache.fop.apps.FOPException;
 
@@ -28,12 +31,18 @@ import java.io.OutputStream;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
+import java.awt.geom.Rectangle2D;
+
+import org.w3c.dom.Document;
 
 /**
  * Renderer that renders areas to XML for debugging purposes.
  */
 public class XMLRenderer extends AbstractRenderer {
-boolean startedSequence = false;
+    public static final String mimeType = "text/xml";
+
+    boolean startedSequence = false;
+    RendererContext context;
 
     public void setProducer(String producer) {
     }
@@ -58,7 +67,18 @@ boolean startedSequence = false;
      */
     private boolean consistentOutput = false;
 
-    public XMLRenderer() {}
+    public XMLRenderer() {
+        context = new RendererContext(mimeType);
+    }
+
+    public void setUserAgent(FOUserAgent agent) {
+        super.setUserAgent(agent);
+        //userAgent.addExtensionHandler();
+        XMLHandler handler = new XMLXMLHandler();
+        userAgent.setDefaultXMLHandler(mimeType, handler);
+        String svg = "http://www.w3.org/2000/svg";
+        userAgent.addXMLHandler(mimeType, svg, handler);
+    }
 
     /**
      * write out spaces to make indent
@@ -125,11 +145,11 @@ boolean startedSequence = false;
     }
 
     private boolean isCoarseXml() {
-        return ((Boolean)options.get("fineDetail")).booleanValue();
+        return ((Boolean) options.get("fineDetail")).booleanValue();
     }
 
     /**
-    */
+     */
     public void startRenderer(OutputStream outputStream)
     throws IOException {
         log.debug("rendering areas to XML");
@@ -140,110 +160,254 @@ boolean startedSequence = false;
     }
 
     /**
-    */
-    public void stopRenderer()
-    throws IOException {
+     */
+    public void stopRenderer() throws IOException {
         writeEndTag("</pageSequence>");
         writeEndTag("</areaTree>");
         this.writer.flush();
         log.debug("written out XML");
     }
 
-    public void renderPage(PageViewport page)
-    throws IOException, FOPException {
-        writeStartTag("<pageViewport>");
+    public void renderPage(PageViewport page) throws IOException,
+    FOPException {
+        writeStartTag("<pageViewport bounds=\"" +
+                      createString(page.getViewArea()) + "\">");
         writeStartTag("<page>");
-super.renderPage(page);
+        super.renderPage(page);
         writeEndTag("</page>");
         writeEndTag("</pageViewport>");
     }
 
+    private String createString(Rectangle2D rect) {
+        return "" + (int) rect.getX() + " " + (int) rect.getY() + " " +
+               (int) rect.getWidth() + " " + (int) rect.getHeight();
+    }
+
     public void startPageSequence(Title seqTitle) {
-if(startedSequence) {
-        writeEndTag("</pageSequence>");
-}
-startedSequence = true;
+        if (startedSequence) {
+            writeEndTag("</pageSequence>");
+        }
+        startedSequence = true;
         writeStartTag("<pageSequence>");
-if(seqTitle != null) {
-        writeStartTag("<title>");
-        List children = seqTitle.getInlineAreas();
+        if (seqTitle != null) {
+            writeStartTag("<title>");
+            List children = seqTitle.getInlineAreas();
 
-        for (int count = 0; count < children.size(); count++) {
-            InlineArea inline = (InlineArea) children.get(count);
-            inline.render(this);
-        }
+            for (int count = 0; count < children.size(); count++) {
+                InlineArea inline = (InlineArea) children.get(count);
+                inline.render(this);
+            }
 
-        writeEndTag("</title>");
-}
+            writeEndTag("</title>");
+        }
     }
 
     protected void renderRegionViewport(RegionViewport port) {
-        if(port != null) {
-        writeStartTag("<regionViewport>");
-        Region region = port.getRegion();
-        if (region.getRegionClass() == Region.BEFORE) {
-        writeStartTag("<regionBefore>");
-            renderRegion(region);
-        writeEndTag("</regionBefore>");
-        } else if (region.getRegionClass() == Region.START) {
-        writeStartTag("<regionStart>");
-            renderRegion(region);
-        writeEndTag("</regionStart>");
-        } else if (region.getRegionClass() == Region.BODY) {
-        writeStartTag("<regionBody>");
-            renderBodyRegion((BodyRegion)region);
-        writeEndTag("</regionBody>");
-        } else if (region.getRegionClass() == Region.END) {
-        writeStartTag("<regionEnd>");
-            renderRegion(region);
-        writeEndTag("</regionEnd>");
-        } else if (region.getRegionClass() == Region.AFTER) {
-        writeStartTag("<regionAfter>");
-            renderRegion(region);
-        writeEndTag("</regionAfter>");
+        if (port != null) {
+            writeStartTag("<regionViewport rect=\"" +
+                          createString(port.getViewArea()) + "\">");
+            Region region = port.getRegion();
+            if (region.getRegionClass() == Region.BEFORE) {
+                writeStartTag("<regionBefore>");
+                renderRegion(region);
+                writeEndTag("</regionBefore>");
+            } else if (region.getRegionClass() == Region.START) {
+                writeStartTag("<regionStart>");
+                renderRegion(region);
+                writeEndTag("</regionStart>");
+            } else if (region.getRegionClass() == Region.BODY) {
+                writeStartTag("<regionBody>");
+                renderBodyRegion((BodyRegion) region);
+                writeEndTag("</regionBody>");
+            } else if (region.getRegionClass() == Region.END) {
+                writeStartTag("<regionEnd>");
+                renderRegion(region);
+                writeEndTag("</regionEnd>");
+            } else if (region.getRegionClass() == Region.AFTER) {
+                writeStartTag("<regionAfter>");
+                renderRegion(region);
+                writeEndTag("</regionAfter>");
+            }
+            writeEndTag("</regionViewport>");
         }
-        writeEndTag("</regionViewport>");
-}
-
-
-}
+    }
 
     protected void renderBeforeFloat(BeforeFloat bf) {
         writeStartTag("<beforeFloat>");
-super.renderBeforeFloat(bf);
+        super.renderBeforeFloat(bf);
         writeEndTag("</beforeFloat>");
-}
+    }
 
     protected void renderFootnote(Footnote footnote) {
         writeStartTag("<footnote>");
-super.renderFootnote(footnote);
+        super.renderFootnote(footnote);
         writeEndTag("</footnote>");
-}
+    }
 
     protected void renderMainReference(MainReference mr) {
-        writeStartTag("<mainReference>");
-super.renderMainReference(mr);
+        writeStartTag("<mainReference columnGap=\"" +
+                      mr.getColumnGap() + "\" width=\"" + mr.getWidth() + "\">");
+
+        Span span = null;
+        List spans = mr.getSpans();
+        for (int count = 0; count < spans.size(); count++) {
+            span = (Span) spans.get(count);
+            writeStartTag("<span>");
+            for (int c = 0; c < span.getColumnCount(); c++) {
+                Flow flow = (Flow) span.getFlow(c);
+
+                renderFlow(flow);
+            }
+            writeEndTag("</span>");
+        }
         writeEndTag("</mainReference>");
-}
+    }
+
+    // the normal flow reference area contains stacked blocks
+    protected void renderFlow(Flow flow) {
+        writeStartTag("<flow>");
+        super.renderFlow(flow);
+        writeEndTag("</flow>");
+    }
 
     protected void renderBlock(Block block) {
-        writeStartTag("<block>");
-super.renderBlock(block);
+        String prop = "";
+        List list = block.getPropertyList();
+        if (list != null) {
+            prop = " props=\"" + getPropString(list) + "\"";
+        }
+        writeStartTag("<block" + prop + ">");
+        super.renderBlock(block);
         writeEndTag("</block>");
     }
 
     protected void renderLineArea(LineArea line) {
-        writeStartTag("<lineArea>");
-super.renderLineArea(line);
+        String prop = "";
+        List list = line.getPropertyList();
+        if (list != null) {
+            prop = " props=\"" + getPropString(list) + "\"";
+        }
+        writeStartTag("<lineArea height=\"" + line.getHeight() + "\"" +
+                      prop + ">");
+        super.renderLineArea(line);
         writeEndTag("</lineArea>");
     }
 
-    public void renderCharacter(org.apache.fop.area.inline.Character ch) {    
-writeElement("<char>" + ch.getChar() + "</char>");
-    }    
+    public void renderViewport(Viewport viewport) {
+        writeStartTag("<viewport>");
+        super.renderViewport(viewport);
+        writeEndTag("</viewport>");
+    }
+
+    public void renderImage(Image image) {
+        writeElement("<image url=\"" + image.getURL() + "\"/>");
+    }
+
+    public void renderContainer(Container cont) {
+        writeStartTag("<container>");
+
+        super.renderContainer(cont);
+        writeEndTag("</container>");
+    }
+
+    public void renderForeignObject(ForeignObject fo) {
+        writeStartTag("<foreignObject>");
+        Document doc = fo.getDocument();
+        String ns = fo.getNameSpace();
+        context.setProperty(XMLXMLHandler.WRITER, writer);
+        userAgent.renderXML(context, doc, ns);
+        writeEndTag("</foreignObject>");
+    }
+
+    public void renderCharacter(org.apache.fop.area.inline.Character ch) {
+        String prop = "";
+        List list = ch.getPropertyList();
+        if (list != null) {
+            prop = " props=\"" + getPropString(list) + "\"";
+        }
+        writeElement("<char" + prop + ">" + ch.getChar() + "</char>");
+    }
 
     public void renderInlineSpace(Space space) {
-writeElement("<space width=\"" + space.getWidth() + "\"/>");
+        writeElement("<space width=\"" + space.getWidth() + "\"/>");
     }
 
+    public void renderLeader(Leader area) {
+        String style = "solid";
+        switch (area.getRuleStyle()) {
+            case Leader.DOTTED:
+                style = "dotted";
+                break;
+            case Leader.DASHED:
+                style = "dashed";
+                break;
+            case Leader.SOLID:
+                break;
+            case Leader.DOUBLE:
+                style = "double";
+                break;
+            case Leader.GROOVE:
+                style = "groove";
+                break;
+            case Leader.RIDGE:
+                style = "ridge";
+                break;
+        }
+        writeElement("<leader ruleStyle=\"" + style +
+                     "\" ruleThickness=\"" + area.getRuleThickness() + "\"/>");
+        super.renderLeader(area);
+    }
+
+    protected String getPropString(List list) {
+        String str = "";
+        for (int count = 0; count < list.size(); count++) {
+            Property prop = (Property) list.get(count);
+            switch (prop.propType) {
+                case Property.INTERNAL_LINK:
+                    str += "internal-link:" + prop.data;
+                    break;
+                case Property.EXTERNAL_LINK:
+                    str += "external-link:" + prop.data;
+                    break;
+                case Property.FONT_FAMILY:
+                    str += "font-family:" + prop.data;
+                    break;
+                case Property.FONT_SIZE:
+                    str += "font-size:" + prop.data;
+                    break;
+                case Property.FONT_WEIGHT:
+                    str += "font-weight:" + prop.data;
+                    break;
+                case Property.FONT_STYLE:
+                    str += "font-style:" + prop.data;
+                    break;
+                case Property.COLOR:
+                    str += "color:" + prop.data;
+                    break;
+                case Property.BACKGROUND:
+                    str += "background:" + prop.data;
+                    break;
+                case Property.UNDERLINE:
+                    str += "underline:" + prop.data;
+                    break;
+                case Property.OVERLINE:
+                    str += "overline:" + prop.data;
+                    break;
+                case Property.LINETHROUGH:
+                    str += "linethrough:" + prop.data;
+                    break;
+                case Property.OFFSET:
+                    str += "offset:" + prop.data;
+                    break;
+                case Property.SHADOW:
+                    str += "shadow:" + prop.data;
+                    break;
+                default:
+                    break;
+            }
+            str += ";";
+        }
+        return str;
+    }
 }
+
diff --git a/src/org/apache/fop/render/xml/XMLXMLHandler.java b/src/org/apache/fop/render/xml/XMLXMLHandler.java
new file mode 100644 (file)
index 0000000..c117450
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.render.xml;
+
+import org.apache.fop.fo.FOUserAgent;
+import org.apache.fop.render.XMLHandler;
+import org.apache.fop.render.RendererContext;
+
+import org.apache.log.Logger;
+
+import org.apache.batik.dom.util.DOMUtilities;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Attr;
+
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ */
+public class XMLXMLHandler implements XMLHandler {
+public static final String WRITER = "writer";
+
+    public XMLXMLHandler() {
+    }
+
+    public void handleXML(RendererContext context, Document doc,
+                          String ns) throws Exception {
+        Writer writer = (Writer) context.getProperty(WRITER);
+
+        String svg = "http://www.w3.org/2000/svg";
+        // actually both do the same thing but one requires
+        // batik
+        if (svg.equals(ns)) {
+            DOMUtilities.writeDocument(doc, writer);
+        } else {
+            writeDocument(doc, writer);
+        }
+        writer.write("\n");
+    }
+
+    /**
+     * Writes the given document using the given writer.
+     */
+    public static void writeDocument(Document doc,
+                                     Writer w) throws IOException {
+        for (Node n = doc.getFirstChild(); n != null;
+                n = n.getNextSibling()) {
+            writeNode(n, w);
+        }
+    }
+
+    /**
+     * Writes a node using the given writer.
+     */
+    public static void writeNode(Node n, Writer w) throws IOException {
+        switch (n.getNodeType()) {
+            case Node.ELEMENT_NODE:
+                w.write("<");
+                w.write(n.getNodeName());
+
+                if (n.hasAttributes()) {
+                    NamedNodeMap attr = n.getAttributes();
+                    int len = attr.getLength();
+                    for (int i = 0; i < len; i++) {
+                        Attr a = (Attr) attr.item(i);
+                        w.write(" ");
+                        w.write(a.getNodeName());
+                        w.write("=\"");
+                        w.write(contentToString(a.getNodeValue()));
+                        w.write("\"");
+                    }
+                }
+
+                Node c = n.getFirstChild();
+                if (c != null) {
+                    w.write(">");
+                    for (; c != null; c = c.getNextSibling()) {
+                        writeNode(c, w);
+                    }
+                    w.write("</");
+                    w.write(n.getNodeName());
+                    w.write(">");
+                } else {
+                    w.write("/>");
+                }
+                break;
+            case Node.TEXT_NODE:
+                w.write(contentToString(n.getNodeValue()));
+                break;
+            case Node.CDATA_SECTION_NODE:
+                w.write("<![CDATA[");
+                w.write(n.getNodeValue());
+                w.write("]]>");
+                break;
+            case Node.ENTITY_REFERENCE_NODE:
+                w.write("&");
+                w.write(n.getNodeName());
+                w.write(";");
+                break;
+            case Node.PROCESSING_INSTRUCTION_NODE:
+                w.write("<?");
+                w.write(n.getNodeName());
+                w.write(n.getNodeValue());
+                w.write("?>");
+                break;
+            case Node.COMMENT_NODE:
+                w.write("<!--");
+                w.write(n.getNodeValue());
+                w.write("-->");
+                break;
+            case Node.DOCUMENT_TYPE_NODE:
+                break;
+            default:
+                throw new Error("Internal error (" + n.getNodeType() + ")");
+        }
+    }
+
+    /**
+     * Returns the given content value transformed to replace invalid
+     * characters with entities.
+     */
+    public static String contentToString(String s) {
+        StringBuffer result = new StringBuffer();
+
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+
+            switch (c) {
+                case '<':
+                    result.append("&lt;");
+                    break;
+                case '>':
+                    result.append("&gt;");
+                    break;
+                case '&':
+                    result.append("&amp;");
+                    break;
+                case '"':
+                    result.append("&quot;");
+                    break;
+                case '\'':
+                    result.append("&apos;");
+                    break;
+                default:
+                    result.append(c);
+            }
+        }
+
+        return result.toString();
+    }
+
+}
+
index 70698e630b7998721d1f90566e51544cce15e8c5..e77713da85a6e2ec7cce5002350c5228c0606eda 100644 (file)
@@ -16,6 +16,8 @@ import org.apache.fop.render.*;
 import org.apache.fop.render.pdf.*;
 import org.apache.fop.render.svg.*;
 import org.apache.fop.render.xml.*;
+import org.apache.fop.layout.FontInfo;
+import org.apache.fop.fo.FOUserAgent;
 
 import org.apache.log.*;
 import org.apache.log.format.*;
@@ -25,8 +27,14 @@ import org.apache.log.output.*;
 import java.io.*;
 import java.util.*;
 
+import java.awt.geom.Rectangle2D;
+import java.util.StringTokenizer;
+
 import org.w3c.dom.*;
 
+import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.dom.util.DOMUtilities;
+
 /**
  * Area tree tester.
  * The purpose of this class is to create and render an area tree
@@ -38,14 +46,15 @@ import org.w3c.dom.*;
  */
 public class AreaTreeBuilder {
     private Logger log;
-    String baseName = "temp";
+    //String baseName = "temp";
 
     /**
      */
     public static void main(String[] args) {
         AreaTreeBuilder atb = new AreaTreeBuilder();
 
-        atb.runTests();
+        atb.runTests(args[0], args[1], args[2]);
+        System.exit(0);
     }
 
     public AreaTreeBuilder() {
@@ -67,35 +76,46 @@ public class AreaTreeBuilder {
     /**
      *
      */
-    protected void runTests() {
+    protected void runTests(String in, String type, String out) {
         log.debug("Starting tests");
-        runTest();
+        runTest(in, type, out);
         log.debug("Finished");
     }
 
     /**
      */
-    protected void runTest() {
+    protected void runTest(String in, String type, String out) {
+        Renderer rend = null;
+        if ("xml".equals(type)) {
+            rend = new XMLRenderer();
+        } else if ("pdf".equals(type)) {
+            rend = new PDFRenderer();
+        } else if ("svg".equals(type)) {
+            rend = new SVGRenderer();
+        }
+        FontInfo fi = new FontInfo();
+        rend.setupFontInfo(fi);
+        rend.setUserAgent(new FOUserAgent());
+
         AreaTree.StorePagesModel sm = AreaTree.createStorePagesModel();
-        TreeLoader tl = new TreeLoader();
+        TreeLoader tl = new TreeLoader(fi);
         tl.setTreeModel(sm);
         try {
             InputStream is =
-              new BufferedInputStream(new FileInputStream("doc.xml"));
+              new BufferedInputStream(new FileInputStream(in));
             tl.buildAreaTree(is);
-            renderAreaTree(sm);
+            renderAreaTree(sm, rend, out);
         } catch (IOException e) {
             log.error("error reading file" + e.getMessage(), e);
         }
     }
 
-    protected void renderAreaTree(AreaTree.StorePagesModel sm) {
+    protected void renderAreaTree(AreaTree.StorePagesModel sm,
+                                  Renderer rend, String out) {
         try {
-            OutputStream os = new BufferedOutputStream(
-                                new FileOutputStream(baseName + ".xml"));
+            OutputStream os =
+              new BufferedOutputStream(new FileOutputStream(out));
 
-            Renderer rend = new XMLRenderer();
-            //Renderer rend = new PDFRenderer();
             rend.setLogger(log);
             rend.startRenderer(os);
 
@@ -109,6 +129,19 @@ public class AreaTreeBuilder {
                 while (c < pagec) {
                     PageViewport page = sm.getPage(count, c);
                     c++;
+                    ObjectOutputStream tempstream = new ObjectOutputStream(
+                                                      new BufferedOutputStream(
+                                                        new FileOutputStream("temp.ser")));
+                    page.savePage(tempstream);
+                    tempstream.close();
+                    File temp = new File("temp.ser");
+                    log.debug("page serialized to: " + temp.length());
+                    temp = null;
+                    ObjectInputStream in = new ObjectInputStream(
+                                             new BufferedInputStream(
+                                               new FileInputStream("temp.ser")));
+                    page.loadPage(in);
+                    in.close();
                     rend.renderPage(page);
                 }
                 count++;
@@ -129,8 +162,10 @@ public class AreaTreeBuilder {
 class TreeLoader {
     AreaTree areaTree;
     AreaTree.AreaTreeModel model;
-    TreeLoader() {
+    FontInfo fontInfo;
 
+    TreeLoader(FontInfo fi) {
+        fontInfo = fi;
     }
 
     public void setTreeModel(AreaTree.AreaTreeModel mo) {
@@ -163,7 +198,6 @@ class TreeLoader {
                 readPageSequence((Element) obj);
             }
         }
-
     }
 
     public void readPageSequence(Element root) {
@@ -202,14 +236,14 @@ class TreeLoader {
     }
 
     public PageViewport readPageViewport(Element root) {
-        String bounds = root.getAttribute("bounds");
+        Rectangle2D bounds = getRectangle(root, "bounds");
         PageViewport viewport = null;
         NodeList childs = root.getChildNodes();
         for (int i = 0; i < childs.getLength(); i++) {
             Node obj = childs.item(i);
             if (obj.getNodeName().equals("page")) {
                 Page page = readPage((Element) obj);
-                viewport = new PageViewport(page);
+                viewport = new PageViewport(page, bounds);
             }
         }
         return viewport;
@@ -228,8 +262,32 @@ class TreeLoader {
         return page;
     }
 
+    Rectangle2D getRectangle(Element root, String attr) {
+        String rect = root.getAttribute(attr);
+        StringTokenizer st = new StringTokenizer(rect, " ");
+        int x = 0, y = 0, w = 0, h = 0;
+        if (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            x = Integer.parseInt(tok);
+        }
+        if (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            y = Integer.parseInt(tok);
+        }
+        if (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            w = Integer.parseInt(tok);
+        }
+        if (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            h = Integer.parseInt(tok);
+        }
+        Rectangle2D r2d = new Rectangle2D.Float(x, y, w, h);
+        return r2d;
+    }
+
     public RegionViewport readRegionViewport(Page page, Element root) {
-        RegionViewport reg = new RegionViewport();
+        RegionViewport reg = new RegionViewport(getRectangle(root, "rect"));
         NodeList childs = root.getChildNodes();
         for (int i = 0; i < childs.getLength(); i++) {
             Node obj = childs.item(i);
@@ -257,18 +315,100 @@ class TreeLoader {
     public Region readRegion(Element root, int type) {
         Region reg;
         if (type == Region.BODY) {
-            reg = new BodyRegion();
+            BodyRegion br = new BodyRegion();
+            NodeList childs = root.getChildNodes();
+            for (int i = 0; i < childs.getLength(); i++) {
+                Node obj = childs.item(i);
+                if (obj.getNodeName().equals("beforeFloat")) {
+                    BeforeFloat bf = readBeforeFloat((Element) obj);
+                    br.setBeforeFloat(bf);
+                } else if (obj.getNodeName().equals("mainReference")) {
+                    MainReference mr = readMainReference((Element) obj);
+                    br.setMainReference(mr);
+                } else if (obj.getNodeName().equals("footnote")) {
+                    Footnote foot = readFootnote((Element) obj);
+                    br.setFootnote(foot);
+                }
+            }
+            reg = br;
         } else {
             reg = new Region(type);
+            List blocks = getBlocks(root);
+            for (int i = 0; i < blocks.size(); i++) {
+                Block obj = (Block) blocks.get(i);
+                reg.addBlock(obj);
+            }
         }
+        return reg;
+    }
+
+    public BeforeFloat readBeforeFloat(Element root) {
+        BeforeFloat bf = new BeforeFloat();
         List blocks = getBlocks(root);
         for (int i = 0; i < blocks.size(); i++) {
             Block obj = (Block) blocks.get(i);
-            reg.addBlock(obj);
+            bf.addBlock(obj);
         }
-        return reg;
+        return bf;
     }
 
+    public MainReference readMainReference(Element root) {
+        MainReference mr = new MainReference();
+        List spans = getSpans(root);
+        for (int i = 0; i < spans.size(); i++) {
+            Span obj = (Span) spans.get(i);
+            mr.addSpan(obj);
+        }
+        return mr;
+    }
+
+    List getSpans(Element root) {
+        ArrayList list = new ArrayList();
+        NodeList childs = root.getChildNodes();
+        for (int i = 0; i < childs.getLength(); i++) {
+            Node obj = childs.item(i);
+            if (obj.getNodeName().equals("span")) {
+                List flows = getFlows((Element) obj);
+                Span span = new Span(flows.size());
+                for (int j = 0; j < flows.size(); j++) {
+                    Flow flow = (Flow) flows.get(j);
+                    span.addFlow(flow);
+                }
+                list.add(span);
+            }
+        }
+        return list;
+    }
+
+    List getFlows(Element root) {
+        ArrayList list = new ArrayList();
+        NodeList childs = root.getChildNodes();
+        for (int i = 0; i < childs.getLength(); i++) {
+            Node obj = childs.item(i);
+            if (obj.getNodeName().equals("flow")) {
+                Flow flow = new Flow();
+                List blocks = getBlocks((Element) obj);
+                for (int j = 0; j < blocks.size(); j++) {
+                    Block block = (Block) blocks.get(j);
+                    flow.addBlock(block);
+                }
+                list.add(flow);
+            }
+        }
+        return list;
+    }
+
+    public Footnote readFootnote(Element root) {
+        Footnote foot = new Footnote();
+        List blocks = getBlocks(root);
+        for (int i = 0; i < blocks.size(); i++) {
+            Block obj = (Block) blocks.get(i);
+            foot.addBlock(obj);
+        }
+        return foot;
+    }
+
+
     List getBlocks(Element root) {
         ArrayList list = new ArrayList();
         NodeList childs = root.getChildNodes();
@@ -276,6 +416,10 @@ class TreeLoader {
             Node obj = childs.item(i);
             if (obj.getNodeName().equals("block")) {
                 Block block = new Block();
+                List props = getProperties((Element) obj);
+                for (int count = 0; count < props.size(); count++) {
+                    block.addProperty((Property) props.get(count));
+                }
                 addBlockChildren(block, (Element) obj);
                 list.add(block);
             }
@@ -301,11 +445,19 @@ class TreeLoader {
                     // error
                 }
                 LineArea line = new LineArea();
-                List inlines = getInlineAreas((Element)obj);
-        for (int j = 0; j < inlines.size(); j++) {
-            InlineArea inline = (InlineArea) inlines.get(j);
-            line.addInlineArea(inline);
-        }
+                List props = getProperties((Element) obj);
+                for (int count = 0; count < props.size(); count++) {
+                    line.addProperty((Property) props.get(count));
+                }
+                String height = ((Element) obj).getAttribute("height");
+                int h = Integer.parseInt(height);
+                line.setHeight(h);
+
+                List inlines = getInlineAreas((Element) obj);
+                for (int j = 0; j < inlines.size(); j++) {
+                    InlineArea inline = (InlineArea) inlines.get(j);
+                    line.addInlineArea(inline);
+                }
 
                 block.addLineArea(line);
                 type = 2;
@@ -322,6 +474,7 @@ class TreeLoader {
             if (obj.getNodeName().equals("char")) {
                 Character ch =
                   new Character(getString((Element) obj).charAt(0));
+                addProperties((Element) obj, ch);
                 list.add(ch);
             } else if (obj.getNodeName().equals("space")) {
                 Space space = new Space();
@@ -329,15 +482,223 @@ class TreeLoader {
                 int w = Integer.parseInt(width);
                 space.setWidth(w);
                 list.add(space);
-            } else if (obj.getNodeName().equals("container")) {
             } else if (obj.getNodeName().equals("viewport")) {
+                Viewport viewport = getViewport((Element) obj);
+                if (viewport != null) {
+                    list.add(viewport);
+                }
             } else if (obj.getNodeName().equals("leader")) {
+                Leader leader = getLeader((Element) obj);
+                if (leader != null) {
+                    list.add(leader);
+                }
+            } else if (obj.getNodeName().equals("word")) {
+                Word word = getWord((Element) obj);
+                if (word != null) {
+                    list.add(word);
+                }
             } else {
             }
         }
         return list;
     }
 
+    Viewport getViewport(Element root) {
+        Area child = null;
+        NodeList childs = root.getChildNodes();
+        for (int i = 0; i < childs.getLength(); i++) {
+            Node obj = childs.item(i);
+            if (obj.getNodeName().equals("container")) {
+                child = getContainer((Element) obj);
+            } else if (obj.getNodeName().equals("foreignObject")) {
+                child = getForeignObject((Element) obj);
+            } else if (obj.getNodeName().equals("image")) {
+                child = getImage((Element) obj);
+            }
+        }
+        if (child == null) {
+            return null;
+        }
+        Viewport viewport = new Viewport(child);
+        return viewport;
+    }
+
+    Container getContainer(Element root) {
+        Container cont = new Container();
+        List blocks = getBlocks(root);
+        for (int i = 0; i < blocks.size(); i++) {
+            Block obj = (Block) blocks.get(i);
+            cont.addBlock(obj);
+        }
+        return cont;
+    }
+
+    ForeignObject getForeignObject(Element root) {
+        Document doc;
+        String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
+
+        NodeList childs = root.getChildNodes();
+        for (int i = 0; i < childs.getLength(); i++) {
+            Node obj = childs.item(i);
+            if (obj instanceof Element) {
+                //System.out.println(obj.getNodeName());
+                Element rootEle = (Element) obj;
+                String space = rootEle.getAttribute("xmlns");
+                if (space.equals(svgNS)) {
+                    try {
+                        doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().
+                              newDocumentBuilder().newDocument();
+                        Node node = doc.importNode(obj, true);
+                        doc.appendChild(node);
+                        DOMImplementation impl =
+                          SVGDOMImplementation.getDOMImplementation();
+                        // due to namespace problem attributes are not cloned
+                        //doc = DOMUtilities.deepCloneDocument(doc, impl);
+
+                        ForeignObject fo = new ForeignObject(doc, svgNS);
+                        return fo;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                } else {
+                    try {
+                        doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().
+                              newDocumentBuilder().newDocument();
+                        Node node = doc.importNode(obj, true);
+                        doc.appendChild(node);
+                        ForeignObject fo = new ForeignObject(doc, space);
+                        return fo;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    Image getImage(Element root) {
+        String url = root.getAttribute("url");
+        Image image = new Image(url);
+        return image;
+    }
+
+    Leader getLeader(Element root) {
+        Leader leader = new Leader();
+        String rs = root.getAttribute("ruleStyle");
+        if ("solid".equals(rs)) {
+            leader.setRuleStyle(Leader.SOLID);
+        } else if ("dotted".equals(rs)) {
+            leader.setRuleStyle(Leader.DOTTED);
+        } else if ("dashed".equals(rs)) {
+            leader.setRuleStyle(Leader.DASHED);
+        } else if ("double".equals(rs)) {
+            leader.setRuleStyle(Leader.DOUBLE);
+        } else if ("groove".equals(rs)) {
+            leader.setRuleStyle(Leader.GROOVE);
+        } else if ("ridge".equals(rs)) {
+            leader.setRuleStyle(Leader.RIDGE);
+        }
+        String rt = root.getAttribute("ruleThickness");
+        int thick = Integer.parseInt(rt);
+        leader.setRuleThickness(thick);
+        addProperties(root, leader);
+        return leader;
+    }
+
+    Word getWord(Element root) {
+        String url = root.getAttribute("url");
+        Word word = new Word();
+        addProperties(root, word);
+        return word;
+    }
+
+    public void addProperties(Element ele, InlineArea inline) {
+        List props = getProperties(ele);
+        for (int count = 0; count < props.size(); count++) {
+            inline.addProperty((Property) props.get(count));
+        }
+        String str = ele.getAttribute("width");
+
+    }
+
+    public List getProperties(Element ele) {
+        ArrayList list = new ArrayList();
+        String str = ele.getAttribute("props");
+        StringTokenizer st = new StringTokenizer(str, ";");
+        while (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            int index = tok.indexOf(":");
+            String id = tok.substring(0, index);
+            String val = tok.substring(index + 1);
+            Property prop = new Property();
+            if ("internal-link".equals(id)) {
+                prop.propType = Property.INTERNAL_LINK;
+                prop.data = val;
+                list.add(prop);
+            } else if ("external-link".equals(id)) {
+                prop.propType = Property.EXTERNAL_LINK;
+                prop.data = val;
+                list.add(prop);
+            } else if ("font-family".equals(id)) {
+                prop.propType = Property.FONT_FAMILY;
+                prop.data = val;
+                list.add(prop);
+            } else if ("font-size".equals(id)) {
+                prop.propType = Property.FONT_SIZE;
+                prop.data = Integer.valueOf(val);
+                list.add(prop);
+            } else if ("font-weight".equals(id)) {
+                prop.propType = Property.FONT_WEIGHT;
+                prop.data = val;
+                list.add(prop);
+            } else if ("font-style".equals(id)) {
+                prop.propType = Property.FONT_STYLE;
+                prop.data = val;
+                list.add(prop);
+            } else if ("color".equals(id)) {
+                prop.propType = Property.COLOR;
+                prop.data = val;
+                list.add(prop);
+            } else if ("background".equals(id)) {
+                prop.propType = Property.BACKGROUND;
+                prop.data = val;
+                list.add(prop);
+            } else if ("underline".equals(id)) {
+                prop.propType = Property.UNDERLINE;
+                prop.data = new Boolean(val);
+                list.add(prop);
+            } else if ("overline".equals(id)) {
+                prop.propType = Property.OVERLINE;
+                prop.data = new Boolean(val);
+                list.add(prop);
+            } else if ("linethrough".equals(id)) {
+                prop.propType = Property.LINETHROUGH;
+                prop.data = new Boolean(val);
+                list.add(prop);
+            } else if ("offset".equals(id)) {
+                prop.propType = Property.OFFSET;
+                prop.data = Integer.valueOf(val);
+                list.add(prop);
+            } else if ("shadow".equals(id)) {
+                prop.propType = Property.SHADOW;
+                prop.data = val;
+                list.add(prop);
+            }
+        }
+        return list;
+    }
+
+    public List getRanges(Element ele) {
+        ArrayList list = new ArrayList();
+        String str = ele.getAttribute("ranges");
+        StringTokenizer st = new StringTokenizer(str, ";");
+        while (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+        }
+        return list;
+    }
+
     public String getString(Element ele) {
         String str = "";
         NodeList childs = ele.getChildNodes();
@@ -351,6 +712,5 @@ class TreeLoader {
         return str;
     }
 
-
 }