Browse Source

updates to area tree and reading/rendering with xml

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
pull/30/head
Keiron Liddle 22 years ago
parent
commit
5bd0b605a5
34 changed files with 1380 additions and 184 deletions
  1. 4
    0
      src/org/apache/fop/apps/XSLTInputHandler.java
  2. 4
    2
      src/org/apache/fop/area/Area.java
  3. 33
    14
      src/org/apache/fop/area/AreaTree.java
  4. 11
    0
      src/org/apache/fop/area/BeforeFloat.java
  5. 16
    1
      src/org/apache/fop/area/Block.java
  6. 13
    0
      src/org/apache/fop/area/BodyRegion.java
  7. 4
    0
      src/org/apache/fop/area/Flow.java
  8. 11
    0
      src/org/apache/fop/area/Footnote.java
  9. 23
    7
      src/org/apache/fop/area/LineArea.java
  10. 13
    0
      src/org/apache/fop/area/LineProperty.java
  11. 6
    1
      src/org/apache/fop/area/MainReference.java
  12. 3
    1
      src/org/apache/fop/area/Page.java
  13. 22
    1
      src/org/apache/fop/area/PageViewport.java
  14. 33
    0
      src/org/apache/fop/area/Property.java
  15. 2
    1
      src/org/apache/fop/area/Region.java
  16. 30
    2
      src/org/apache/fop/area/RegionViewport.java
  17. 9
    1
      src/org/apache/fop/area/Span.java
  18. 7
    1
      src/org/apache/fop/area/inline/Container.java
  19. 12
    0
      src/org/apache/fop/area/inline/ForeignObject.java
  20. 9
    1
      src/org/apache/fop/area/inline/Image.java
  21. 25
    0
      src/org/apache/fop/area/inline/InlineArea.java
  22. 35
    0
      src/org/apache/fop/area/inline/Leader.java
  23. 38
    1
      src/org/apache/fop/area/inline/Viewport.java
  24. 5
    0
      src/org/apache/fop/area/inline/Word.java
  25. 54
    8
      src/org/apache/fop/fo/FOUserAgent.java
  26. 3
    3
      src/org/apache/fop/pdf/PDFDocument.java
  27. 47
    19
      src/org/apache/fop/render/AbstractRenderer.java
  28. 7
    15
      src/org/apache/fop/render/Renderer.java
  29. 37
    0
      src/org/apache/fop/render/RendererContext.java
  30. 26
    0
      src/org/apache/fop/render/XMLHandler.java
  31. 58
    10
      src/org/apache/fop/render/pdf/PDFRenderer.java
  32. 231
    67
      src/org/apache/fop/render/xml/XMLRenderer.java
  33. 161
    0
      src/org/apache/fop/render/xml/XMLXMLHandler.java
  34. 388
    28
      src/org/apache/fop/tools/AreaTreeBuilder.java

+ 4
- 0
src/org/apache/fop/apps/XSLTInputHandler.java View File

// FOP // FOP
import org.apache.fop.tools.xslt.XSLTransform; import org.apache.fop.tools.xslt.XSLTransform;


/*
add url constructer
*/

/** /**
* XSLTInputHandler basically takes an xmlfile and transforms it with an xsltfile * XSLTInputHandler basically takes an xmlfile and transforms it with an xsltfile
* and the resulting xsl:fo document is input for Fop. * and the resulting xsl:fo document is input for Fop.

+ 4
- 2
src/org/apache/fop/area/Area.java View File



package org.apache.fop.area; 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 // stacking directions
public static final int LR = 0; public static final int LR = 0;
public static final int RL = 1; public static final int RL = 1;

+ 33
- 14
src/org/apache/fop/area/AreaTree.java View File



import java.util.ArrayList; 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 { public class AreaTree {
// allows for different models to deal with adding/rendering // allows for different models to deal with adding/rendering
// in different situations // in different situations
public abstract void addPage(PageViewport page); 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 // this class stores all the pages in the document
// for interactive agents // for interactive agents
public static class StorePagesModel extends AreaTreeModel { public static class StorePagesModel extends AreaTreeModel {
return (PageViewport) sequence.get(count); 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);
}

} }


+ 11
- 0
src/org/apache/fop/area/BeforeFloat.java View File



ArrayList blocks = null; 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() { public List getBlocks() {
return blocks; return blocks;
} }

+ 16
- 1
src/org/apache/fop/area/Block.java View File



package org.apache.fop.area; package org.apache.fop.area;


import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
// or by relative to the parent for floats, tables and lists // or by relative to the parent for floats, tables and lists
// cacheable object // cacheable object
// has id information // has id information
public class Block extends Area {
public class Block extends Area implements Serializable {
// normally stacked with other blocks // normally stacked with other blocks
public static final int STACK = 0; public static final int STACK = 0;
// placed relative to the parent area // placed relative to the parent area
public int getPositioning() { public int getPositioning() {
return positioning; 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;
}
} }

+ 13
- 0
src/org/apache/fop/area/BodyRegion.java View File

super(BODY); 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() { public BeforeFloat getBeforeFloat() {
return beforeFloat; return beforeFloat;
} }

+ 4
- 0
src/org/apache/fop/area/Flow.java View File

int stacking = TB; int stacking = TB;
int width; int width;


public void addBlock(Block block) {
blocks.add(block);
}

public List getBlocks() { public List getBlocks() {
return blocks; return blocks;
} }

+ 11
- 0
src/org/apache/fop/area/Footnote.java View File



ArrayList blocks = null; 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() { public Block getSeparator() {
return separator; return separator;
} }

+ 23
- 7
src/org/apache/fop/area/LineArea.java View File



ArrayList inlineAreas = new ArrayList(); ArrayList inlineAreas = new ArrayList();


public void setHeight(int height) {
lineHeight = height;
}

public int getHeight() {
return lineHeight;
}

public void addInlineArea(InlineArea area) { public void addInlineArea(InlineArea area) {
inlineAreas.add(area); inlineAreas.add(area);
} }
public List getInlineAreas() { public List getInlineAreas() {
return inlineAreas; 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;
}
*/


+ 13
- 0
src/org/apache/fop/area/LineProperty.java View File

/*
* $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;
}


+ 6
- 1
src/org/apache/fop/area/MainReference.java View File



package org.apache.fop.area; package org.apache.fop.area;


import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;


// the area that contains the flow via the span areas // the area that contains the flow via the span areas
public class MainReference {
public class MainReference implements Serializable {
List spanAreas = new ArrayList(); List spanAreas = new ArrayList();
int columnGap; int columnGap;
int width; int width;


public void addSpan(Span span) {
spanAreas.add(span);
}

public List getSpans() { public List getSpans() {
return spanAreas; return spanAreas;
} }

+ 3
- 1
src/org/apache/fop/area/Page.java View File



package org.apache.fop.area; 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 // contains before, start, body, end and after regions
RegionViewport regionBefore = null; RegionViewport regionBefore = null;
RegionViewport regionStart = null; RegionViewport regionStart = null;

+ 22
- 1
src/org/apache/fop/area/PageViewport.java View File

package org.apache.fop.area; package org.apache.fop.area;


import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList; import java.util.ArrayList;


// this is the level that creates the page // this is the level that creates the page
public class PageViewport { public class PageViewport {
Page page; Page page;
Rectangle2D viewArea; Rectangle2D viewArea;
boolean clip = false;


public PageViewport(Page p) {
public PageViewport(Page p, Rectangle2D bounds) {
page = p; page = p;
viewArea = bounds;
} }


// this list is only used when the page is discarded // this list is only used when the page is discarded
// the information is kept for future reference // the information is kept for future reference
ArrayList idReferences = null; ArrayList idReferences = null;


public void setClip(boolean c) {
clip = c;
}

public Rectangle2D getViewArea() {
return viewArea;
}

// a viewport area for page and reference areas // a viewport area for page and reference areas
public Page getPage() { public Page getPage() {
return page; 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();
}
} }

+ 33
- 0
src/org/apache/fop/area/Property.java View File

/*
* $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;

}


+ 2
- 1
src/org/apache/fop/area/Region.java View File



package org.apache.fop.area; package org.apache.fop.area;


import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;


public class Region {
public class Region implements Serializable {
public static final int BEFORE = 0; public static final int BEFORE = 0;
public static final int START = 1; public static final int START = 1;
public static final int BODY = 2; public static final int BODY = 2;

+ 30
- 2
src/org/apache/fop/area/RegionViewport.java View File

package org.apache.fop.area; package org.apache.fop.area;


import java.awt.geom.Rectangle2D; 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 // this rectangle is relative to the page
Rectangle2D regionArea; Rectangle2D regionArea;
boolean clip;
boolean clip = false;


Region region; Region region;


public RegionViewport(Rectangle2D area) {
regionArea = area;
}

public void setRegion(Region reg) { public void setRegion(Region reg) {
region = reg; region = reg;
} }


public Rectangle2D getViewArea() {
return regionArea;
}

public Region getRegion() { public Region getRegion() {
return region; 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();
}

} }

+ 9
- 1
src/org/apache/fop/area/Span.java View File

// this is a reference area block area with 0 border and padding // this is a reference area block area with 0 border and padding
public class Span extends Area { public class Span extends Area {
// the list of flow reference areas in this span area // the list of flow reference areas in this span area
ArrayList flowAreas = new ArrayList();
ArrayList flowAreas;
int height; int height;


public Span(int cols) {
flowAreas = new ArrayList(cols);
}

public void addFlow(Flow flow) {
flowAreas.add(flow);
}

public int getColumnCount() { public int getColumnCount() {
return flowAreas.size(); return flowAreas.size();
} }

+ 7
- 1
src/org/apache/fop/area/inline/Container.java View File



package org.apache.fop.area.inline; 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 org.apache.fop.render.Renderer;


import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;


public class Container extends InlineArea {
public class Container extends Area {
ArrayList blocks = new ArrayList(); ArrayList blocks = new ArrayList();


// this is an inline area that can have blocks as children // this is an inline area that can have blocks as children
renderer.renderContainer(this); renderer.renderContainer(this);
} }


public void addBlock(Block block) {
blocks.add(block);
}

public List getBlocks() { public List getBlocks() {
return blocks; return blocks;
} }

+ 12
- 0
src/org/apache/fop/area/inline/ForeignObject.java View File

// dom object // dom object
// height, width // height, width


public ForeignObject(Document d, String ns) {
doc = d;
namespace = ns;
}

public Document getDocument() {
return doc;
}

public String getNameSpace() {
return namespace;
}
} }

+ 9
- 1
src/org/apache/fop/area/inline/Image.java View File

import org.apache.fop.area.Area; import org.apache.fop.area.Area;


// cacheable object // cacheable object
// image object, mime type, url
public class Image extends Area { public class Image extends Area {
String url;


// image object, mime type, url
public Image(String u) {
url = u;
}

public String getURL() {
return url;
}


} }

+ 25
- 0
src/org/apache/fop/area/inline/InlineArea.java View File

package org.apache.fop.area.inline; package org.apache.fop.area.inline;


import org.apache.fop.area.Area; import org.apache.fop.area.Area;
import org.apache.fop.area.Property;
import org.apache.fop.render.Renderer; 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 { public class InlineArea extends Area {
int width; int width;
int height; int height;
int verticalPosition; int verticalPosition;
// width, height, vertical alignment // width, height, vertical alignment


// store properties in array list, need better solution
ArrayList props = null;

// inline areas are expected to implement this method // inline areas are expected to implement this method
// to render themselves // to render themselves
public void render(Renderer renderer) { public void render(Renderer renderer) {
public int getWidth() { public int getWidth() {
return width; return width;
} }

public void addProperty(Property prop) {
if (props == null) {
props = new ArrayList();
}
props.add(prop);
}

public List getPropertyList() {
return props;
}
} }

+ 35
- 0
src/org/apache/fop/area/inline/Leader.java View File



package org.apache.fop.area.inline; package org.apache.fop.area.inline;


import org.apache.fop.render.Renderer;

public class Leader extends Stretch { public class Leader extends Stretch {


// pattern, length min opt max // pattern, length min opt max
// if space replaced with a space // if space replaced with a space
// otherwise this is a holder for a line // 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);
}
} }

+ 38
- 1
src/org/apache/fop/area/inline/Viewport.java View File

package org.apache.fop.area.inline; package org.apache.fop.area.inline;


import org.apache.fop.area.Area; import org.apache.fop.area.Area;
import org.apache.fop.render.Renderer;


import java.io.IOException;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;


public class Viewport extends InlineArea { public class Viewport extends InlineArea {
// contents could be foreign object or image
// contents could be container, foreign object or image
Area content; Area content;
// an inline-level viewport area for graphic and instream foreign object // an inline-level viewport area for graphic and instream foreign object
boolean clip = false; boolean clip = false;
// position relative to this area // position relative to this area
Rectangle2D contentPosition; 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();
}

} }

+ 5
- 0
src/org/apache/fop/area/inline/Word.java View File



package org.apache.fop.area.inline; package org.apache.fop.area.inline;


import org.apache.fop.render.Renderer;

public class Word extends InlineArea { public class Word extends InlineArea {


// character info: font, char spacing, colour, baseline // character info: font, char spacing, colour, baseline
String word; String word;


public void render(Renderer renderer) {
renderer.renderWord(this);
}
} }

+ 54
- 8
src/org/apache/fop/fo/FOUserAgent.java View File



package org.apache.fop.fo; package org.apache.fop.fo;


import org.apache.fop.render.XMLHandler;
import org.apache.fop.render.RendererContext;

import org.w3c.dom.*; import org.w3c.dom.*;


import java.util.HashMap;

/** /**
* The User Agent for fo. * The User Agent for fo.
* This user agent is used by the processing to obtain user configurable * This user agent is used by the processing to obtain user configurable
* options. * options.
*
*
* Renderer specific extensions (that do not produce normal areas on * Renderer specific extensions (that do not produce normal areas on
* the output) will be done like so: * the output) will be done like so:
* The extension will create an area, custom if necessary * The extension will create an area, custom if necessary
* These areas may contain resolveable areas that will be processed * These areas may contain resolveable areas that will be processed
* with other resolveable areas * 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
}
}
} }



+ 3
- 3
src/org/apache/fop/pdf/PDFDocument.java View File

* @return the created /Page object * @return the created /Page object
*/ */
public PDFPage makePage(PDFResources resources, PDFStream contents, 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 * create a PDFPage with the next object number, the given
} }
pendingLinks = null; pendingLinks = null;
} }
/*
if (currentPage != null) { if (currentPage != null) {
Enumeration enum = currentPage.getIDList().elements(); Enumeration enum = currentPage.getIDList().elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
page.referencePDF()); page.referencePDF());
} }
} }
*/
/* add it to the list of objects */ /* add it to the list of objects */
this.objects.addElement(page); this.objects.addElement(page);



+ 47
- 19
src/org/apache/fop/render/AbstractRenderer.java View File

* Abstract base class for all renderers. * Abstract base class for all renderers.
* The Abstract renderer does all the top level processing * The Abstract renderer does all the top level processing
* of the area tree and adds some abstract methods to handle * 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 { public abstract class AbstractRenderer implements Renderer {
protected Logger log; protected Logger log;
} }


public void setUserAgent(FOUserAgent agent) { public void setUserAgent(FOUserAgent agent) {
userAgent = agent;
userAgent = agent;
} }


public void setOptions(HashMap opt) { public void setOptions(HashMap opt) {
FOPException { FOPException {


Page p = page.getPage(); Page p = page.getPage();
renderPageAreas(p);
renderPageAreas(p);
} }


protected void renderPageAreas(Page page) { protected void renderPageAreas(Page page) {
// the region may clip the area and it establishes // the region may clip the area and it establishes
// a position from where the region is placed // a position from where the region is placed
protected void renderRegionViewport(RegionViewport port) { 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);
}
} }
} }




protected void renderBodyRegion(BodyRegion region) { protected void renderBodyRegion(BodyRegion region) {
BeforeFloat bf = region.getBeforeFloat(); BeforeFloat bf = region.getBeforeFloat();
if(bf != null) {
renderBeforeFloat(bf);
}
if (bf != null) {
renderBeforeFloat(bf);
}
MainReference mr = region.getMainReference(); MainReference mr = region.getMainReference();
if(mr != null) {
renderMainReference(mr);
}
if (mr != null) {
renderMainReference(mr);
}
Footnote foot = region.getFootnote(); Footnote foot = region.getFootnote();
if(foot != null) {
renderFootnote(foot);
}
if (foot != null) {
renderFootnote(foot);
}
} }


protected void renderBeforeFloat(BeforeFloat bf) { protected void renderBeforeFloat(BeforeFloat bf) {
if (children == null) { if (children == null) {
// simply move position // simply move position
} else { } 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++) { for (int count = 0; count < children.size(); count++) {
LineArea line = (LineArea) children.get(count); LineArea line = (LineArea) children.get(count);
renderLineArea(line); renderLineArea(line);


} }


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) { public void renderContainer(Container cont) {
List blocks = cont.getBlocks(); List blocks = cont.getBlocks();
renderBlocks(blocks); renderBlocks(blocks);
}

public void renderForeignObject(ForeignObject fo) {


} }


currentBlockIPPosition += space.getWidth(); currentBlockIPPosition += space.getWidth();
} }


public void renderLeader(Leader area) {
currentBlockIPPosition += area.getWidth();
}

public void renderWord(Word word) {
currentBlockIPPosition += word.getWidth();
}

protected void renderBlocks(List blocks) { protected void renderBlocks(List blocks) {
for (int count = 0; count < blocks.size(); count++) { for (int count = 0; count < blocks.size(); count++) {
Block block = (Block) blocks.get(count); Block block = (Block) blocks.get(count);

+ 7
- 15
src/org/apache/fop/render/Renderer.java View File

*/ */
public interface Renderer { 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 * Set the logger


public void startPageSequence(Title seqTitle); 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 renderContainer(Container cont);
/*
public void renderInlineViewport(org.apache.fop.area.inline.Viewport view);


public void renderWord(Word area); 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); public void renderLeader(Leader area);
*/
} }



+ 37
- 0
src/org/apache/fop/render/RendererContext.java View File

/*
* $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);
}

}


+ 26
- 0
src/org/apache/fop/render/XMLHandler.java View File

/*
* $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;
}


+ 58
- 10
src/org/apache/fop/render/pdf/PDFRenderer.java View File

import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; 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 * Renderer that renders areas to PDF
* *
*/ */
protected PDFDocument pdfDoc; protected PDFDocument pdfDoc;


protected String producer;

protected OutputStream ostream;

/** /**
* the /Resources object of the PDF document being created * the /Resources object of the PDF document being created
*/ */
int prevWordX = 0; 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; int prevWordWidth = 0;


* create the PDF renderer * create the PDF renderer
*/ */
public PDFRenderer() { public PDFRenderer() {
this.pdfDoc = new PDFDocument();
} }


/** /**
* *
* @param producer string indicating application producing PDF * @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); 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(); 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);


} }



+ 231
- 67
src/org/apache/fop/render/xml/XMLRenderer.java View File

import org.apache.fop.svg.*; import org.apache.fop.svg.*;
import org.apache.fop.render.Renderer; import org.apache.fop.render.Renderer;
import org.apache.fop.render.AbstractRenderer; 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.image.ImageArea;
import org.apache.fop.area.*; import org.apache.fop.area.*;
import org.apache.fop.area.inline.*; import org.apache.fop.area.inline.*;
import org.apache.fop.pdf.*; import org.apache.fop.pdf.*;
import org.apache.fop.fo.properties.LeaderPattern; import org.apache.fop.fo.properties.LeaderPattern;
import org.apache.fop.fo.FOUserAgent;
import org.apache.fop.layout.FontInfo; import org.apache.fop.layout.FontInfo;
import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOPException;


import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.awt.geom.Rectangle2D;

import org.w3c.dom.Document;


/** /**
* Renderer that renders areas to XML for debugging purposes. * Renderer that renders areas to XML for debugging purposes.
*/ */
public class XMLRenderer extends AbstractRenderer { 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) { public void setProducer(String producer) {
} }
*/ */
private boolean consistentOutput = 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 * write out spaces to make indent
} }


private boolean isCoarseXml() { private boolean isCoarseXml() {
return ((Boolean)options.get("fineDetail")).booleanValue();
return ((Boolean) options.get("fineDetail")).booleanValue();
} }


/** /**
*/
*/
public void startRenderer(OutputStream outputStream) public void startRenderer(OutputStream outputStream)
throws IOException { throws IOException {
log.debug("rendering areas to XML"); log.debug("rendering areas to XML");
} }


/** /**
*/
public void stopRenderer()
throws IOException {
*/
public void stopRenderer() throws IOException {
writeEndTag("</pageSequence>"); writeEndTag("</pageSequence>");
writeEndTag("</areaTree>"); writeEndTag("</areaTree>");
this.writer.flush(); this.writer.flush();
log.debug("written out XML"); 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>"); writeStartTag("<page>");
super.renderPage(page);
super.renderPage(page);
writeEndTag("</page>"); writeEndTag("</page>");
writeEndTag("</pageViewport>"); 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) { public void startPageSequence(Title seqTitle) {
if(startedSequence) {
writeEndTag("</pageSequence>");
}
startedSequence = true;
if (startedSequence) {
writeEndTag("</pageSequence>");
}
startedSequence = true;
writeStartTag("<pageSequence>"); 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) { 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) { protected void renderBeforeFloat(BeforeFloat bf) {
writeStartTag("<beforeFloat>"); writeStartTag("<beforeFloat>");
super.renderBeforeFloat(bf);
super.renderBeforeFloat(bf);
writeEndTag("</beforeFloat>"); writeEndTag("</beforeFloat>");
}
}


protected void renderFootnote(Footnote footnote) { protected void renderFootnote(Footnote footnote) {
writeStartTag("<footnote>"); writeStartTag("<footnote>");
super.renderFootnote(footnote);
super.renderFootnote(footnote);
writeEndTag("</footnote>"); writeEndTag("</footnote>");
}
}


protected void renderMainReference(MainReference mr) { 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>"); 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) { 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>"); writeEndTag("</block>");
} }


protected void renderLineArea(LineArea line) { 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>"); 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) { 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;
}
} }


+ 161
- 0
src/org/apache/fop/render/xml/XMLXMLHandler.java View File

/*
* $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();
}

}


+ 388
- 28
src/org/apache/fop/tools/AreaTreeBuilder.java View File

import org.apache.fop.render.pdf.*; import org.apache.fop.render.pdf.*;
import org.apache.fop.render.svg.*; import org.apache.fop.render.svg.*;
import org.apache.fop.render.xml.*; 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.*;
import org.apache.log.format.*; import org.apache.log.format.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;


import java.awt.geom.Rectangle2D;
import java.util.StringTokenizer;

import org.w3c.dom.*; import org.w3c.dom.*;


import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.dom.util.DOMUtilities;

/** /**
* Area tree tester. * Area tree tester.
* The purpose of this class is to create and render an area tree * The purpose of this class is to create and render an area tree
*/ */
public class AreaTreeBuilder { public class AreaTreeBuilder {
private Logger log; private Logger log;
String baseName = "temp";
//String baseName = "temp";


/** /**
*/ */
public static void main(String[] args) { public static void main(String[] args) {
AreaTreeBuilder atb = new AreaTreeBuilder(); AreaTreeBuilder atb = new AreaTreeBuilder();


atb.runTests();
atb.runTests(args[0], args[1], args[2]);
System.exit(0);
} }


public AreaTreeBuilder() { public AreaTreeBuilder() {
/** /**
* *
*/ */
protected void runTests() {
protected void runTests(String in, String type, String out) {
log.debug("Starting tests"); log.debug("Starting tests");
runTest();
runTest(in, type, out);
log.debug("Finished"); 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(); AreaTree.StorePagesModel sm = AreaTree.createStorePagesModel();
TreeLoader tl = new TreeLoader();
TreeLoader tl = new TreeLoader(fi);
tl.setTreeModel(sm); tl.setTreeModel(sm);
try { try {
InputStream is = InputStream is =
new BufferedInputStream(new FileInputStream("doc.xml"));
new BufferedInputStream(new FileInputStream(in));
tl.buildAreaTree(is); tl.buildAreaTree(is);
renderAreaTree(sm);
renderAreaTree(sm, rend, out);
} catch (IOException e) { } catch (IOException e) {
log.error("error reading file" + e.getMessage(), 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 { 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.setLogger(log);
rend.startRenderer(os); rend.startRenderer(os);


while (c < pagec) { while (c < pagec) {
PageViewport page = sm.getPage(count, c); PageViewport page = sm.getPage(count, c);
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); rend.renderPage(page);
} }
count++; count++;
class TreeLoader { class TreeLoader {
AreaTree areaTree; AreaTree areaTree;
AreaTree.AreaTreeModel model; AreaTree.AreaTreeModel model;
TreeLoader() {
FontInfo fontInfo;


TreeLoader(FontInfo fi) {
fontInfo = fi;
} }


public void setTreeModel(AreaTree.AreaTreeModel mo) { public void setTreeModel(AreaTree.AreaTreeModel mo) {
readPageSequence((Element) obj); readPageSequence((Element) obj);
} }
} }

} }


public void readPageSequence(Element root) { public void readPageSequence(Element root) {
} }


public PageViewport readPageViewport(Element root) { public PageViewport readPageViewport(Element root) {
String bounds = root.getAttribute("bounds");
Rectangle2D bounds = getRectangle(root, "bounds");
PageViewport viewport = null; PageViewport viewport = null;
NodeList childs = root.getChildNodes(); NodeList childs = root.getChildNodes();
for (int i = 0; i < childs.getLength(); i++) { for (int i = 0; i < childs.getLength(); i++) {
Node obj = childs.item(i); Node obj = childs.item(i);
if (obj.getNodeName().equals("page")) { if (obj.getNodeName().equals("page")) {
Page page = readPage((Element) obj); Page page = readPage((Element) obj);
viewport = new PageViewport(page);
viewport = new PageViewport(page, bounds);
} }
} }
return viewport; return viewport;
return page; 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) { public RegionViewport readRegionViewport(Page page, Element root) {
RegionViewport reg = new RegionViewport();
RegionViewport reg = new RegionViewport(getRectangle(root, "rect"));
NodeList childs = root.getChildNodes(); NodeList childs = root.getChildNodes();
for (int i = 0; i < childs.getLength(); i++) { for (int i = 0; i < childs.getLength(); i++) {
Node obj = childs.item(i); Node obj = childs.item(i);
public Region readRegion(Element root, int type) { public Region readRegion(Element root, int type) {
Region reg; Region reg;
if (type == Region.BODY) { 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 { } else {
reg = new Region(type); 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); List blocks = getBlocks(root);
for (int i = 0; i < blocks.size(); i++) { for (int i = 0; i < blocks.size(); i++) {
Block obj = (Block) blocks.get(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) { List getBlocks(Element root) {
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
NodeList childs = root.getChildNodes(); NodeList childs = root.getChildNodes();
Node obj = childs.item(i); Node obj = childs.item(i);
if (obj.getNodeName().equals("block")) { if (obj.getNodeName().equals("block")) {
Block block = new 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); addBlockChildren(block, (Element) obj);
list.add(block); list.add(block);
} }
// error // error
} }
LineArea line = new LineArea(); 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); block.addLineArea(line);
type = 2; type = 2;
if (obj.getNodeName().equals("char")) { if (obj.getNodeName().equals("char")) {
Character ch = Character ch =
new Character(getString((Element) obj).charAt(0)); new Character(getString((Element) obj).charAt(0));
addProperties((Element) obj, ch);
list.add(ch); list.add(ch);
} else if (obj.getNodeName().equals("space")) { } else if (obj.getNodeName().equals("space")) {
Space space = new Space(); Space space = new Space();
int w = Integer.parseInt(width); int w = Integer.parseInt(width);
space.setWidth(w); space.setWidth(w);
list.add(space); list.add(space);
} else if (obj.getNodeName().equals("container")) {
} else if (obj.getNodeName().equals("viewport")) { } else if (obj.getNodeName().equals("viewport")) {
Viewport viewport = getViewport((Element) obj);
if (viewport != null) {
list.add(viewport);
}
} else if (obj.getNodeName().equals("leader")) { } 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 { } else {
} }
} }
return list; 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) { public String getString(Element ele) {
String str = ""; String str = "";
NodeList childs = ele.getChildNodes(); NodeList childs = ele.getChildNodes();
return str; return str;
} }



} }



Loading…
Cancel
Save