diff options
Diffstat (limited to 'src/org/apache/fop/fo/FObj.java')
-rw-r--r-- | src/org/apache/fop/fo/FObj.java | 298 |
1 files changed, 124 insertions, 174 deletions
diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java index 1a3061de5..1f977da88 100644 --- a/src/org/apache/fop/fo/FObj.java +++ b/src/org/apache/fop/fo/FObj.java @@ -24,65 +24,73 @@ import java.util.ListIterator; import java.util.ArrayList; import java.util.List; import java.util.HashMap; -import java.util.HashSet; +import java.util.Set; +import java.util.Map; /** * base class for representation of formatting objects and their processing */ public class FObj extends FONode { - protected StructureHandler structHandler; - public PropertyList properties; - protected PropertyManager propMgr; - protected String areaClass = AreaClass.UNASSIGNED; - protected String id = null; + private final static String FO_URI = "http://www.w3.org/1999/XSL/Format"; /** - * value of marker before layout begins + * Static property list builder that converts xml attributes + * into fo properties. This is static since the underlying + * property mappings for fo are also static. */ - public static final int START = -1000; + protected static PropertyListBuilder plb = null; /** - * value of marker after break-after + * Structure handler used to notify structure events + * such as start end element. */ - public static final int BREAK_AFTER = -1001; + protected StructureHandler structHandler; /** - * where the layout was up to. - * for FObjs it is the child number - * for FOText it is the character number + * Formatting properties for this fo element. */ - protected int marker = START; - - protected ArrayList children = new ArrayList(); // made public for searching for id's - - protected boolean isInTableCell = false; + public PropertyList properties; - protected int forcedStartOffset = 0; - protected int forcedWidth = 0; + /** + * Property manager for handler some common properties. + */ + protected PropertyManager propMgr; - protected int widows = 0; - protected int orphans = 0; + /** + * Id of this fo element of null if no id. + */ + protected String id = null; - // count of areas generated-by/returned-by - public int areasGenerated = 0; + /** + * The children of this node. + */ + protected ArrayList children = null; - // markers - protected HashMap markers; + /** + * Markers added to this element. + */ + protected Map markers = null; + /** + * Create a new formatting object. + * All formatting object classes extend this class. + * + * @param parent the parent node + */ public FObj(FONode parent) { super(parent); - markers = new HashMap(); - if (parent instanceof FObj) { - this.areaClass = ((FObj) parent).areaClass; - } } + /** + * Set the name of this element. + * The prepends "fo:" to the name to indicate it is in the fo namespace. + * + * @param str the xml element name + */ public void setName(String str) { name = "fo:" + str; } - protected static PropertyListBuilder plb = null; - protected PropertyListBuilder getListBuilder() { if (plb == null) { plb = new PropertyListBuilder(); @@ -105,7 +113,6 @@ public class FObj extends FONode { * will be altered for the next element. */ public void handleAttrs(Attributes attlist) throws FOPException { - String uri = "http://www.w3.org/1999/XSL/Format"; FONode par = parent; while (par != null && !(par instanceof FObj)) { par = par.parent; @@ -114,7 +121,7 @@ public class FObj extends FONode { if (par != null) { props = ((FObj) par).properties; } - properties = getListBuilder().makeList(uri, name, attlist, props, + properties = getListBuilder().makeList(FO_URI, name, attlist, props, (FObj) par); properties.setFObj(this); this.propMgr = makePropertyManager(properties); @@ -126,10 +133,27 @@ public class FObj extends FONode { return new PropertyManager(propertyList); } + /** + * Add the child to this object. + * + * @param child the child node to add + */ protected void addChild(FONode child) { - children.add(child); + if (containsMarkers() && child.isMarker()) { + addMarker((Marker)child); + } else { + if (children == null) { + children = new ArrayList(); + } + children.add(child); + } } + /** + * Set the structure handler for handling structure events. + * + * @param st the structure handler + */ public void setStructHandler(StructureHandler st) { structHandler = st; } @@ -144,12 +168,18 @@ public class FObj extends FONode { return (properties.get(name)); } + /** + * Setup the id for this formatting object. + * Most formatting objects can have an id that can be referenced. + * This methods checks that the id isn't already used by another + * fo and sets the id attribute of this object. + */ protected void setupID() { Property prop = this.properties.get("id"); if (prop != null) { String str = prop.getString(); if (str != null && !str.equals("")) { - HashSet idrefs = structHandler.getIDReferences(); + Set idrefs = structHandler.getIDReferences(); if (!idrefs.contains(str)) { id = str; idrefs.add(id); @@ -160,34 +190,44 @@ public class FObj extends FONode { } } + /** + * Get the id string for this formatting object. + * This will be unique for the fo document. + * + * @return the id string or null if not set + */ public String getID() { return id; } /** - * Return the "content width" of the areas generated by this FO. - * This is used by percent-based properties to get the dimension of - * the containing block. - * If an FO has a property with a percentage value, that value - * is usually calculated on the basis of the corresponding dimension - * of the area which contains areas generated by the FO. - * NOTE: subclasses of FObj should implement this to return a reasonable - * value! + * Check if this formatting object generates reference areas. + * + * @return true if generates reference areas */ - public int getContentWidth() { - return 0; - } - public boolean generatesReferenceAreas() { return false; } - + /** + * Check if this formatting object generates inline areas. + * + * @return true if generates inline areas + */ public boolean generatesInlineAreas() { return true; } /** + * Check if this formatting object may contain markers. + * + * @return true if this can contian markers + */ + protected boolean containsMarkers() { + return false; + } + + /** * Set writing mode for this FO. * Find nearest ancestor, including self, which generates * reference areas and use the value of its writing-mode property. @@ -231,147 +271,57 @@ public class FObj extends FONode { * this FObj. */ public ListIterator getChildren(FONode childNode) { - int i = children.indexOf(childNode); - if (i >= 0) { - return children.listIterator(i); - } else { - return null; - } - } - - public void setIsInTableCell() { - this.isInTableCell = true; - // made recursive by Eric Schaeffer - for (int i = 0; i < this.children.size(); i++) { - Object obj = this.children.get(i); - if (obj instanceof FObj) { - FObj child = (FObj) obj; - child.setIsInTableCell(); - } - } - } - - public void forceStartOffset(int offset) { - this.forcedStartOffset = offset; - // made recursive by Eric Schaeffer - for (int i = 0; i < this.children.size(); i++) { - Object obj = this.children.get(i); - if (obj instanceof FObj) { - FObj child = (FObj) obj; - child.forceStartOffset(offset); - } - } - } - - public void forceWidth(int width) { - this.forcedWidth = width; - // made recursive by Eric Schaeffer - for (int i = 0; i < this.children.size(); i++) { - Object obj = this.children.get(i); - if (obj instanceof FObj) { - FObj child = (FObj) obj; - child.forceWidth(width); - } - } - } - - public void resetMarker() { - this.marker = START; - int numChildren = this.children.size(); - for (int i = 0; i < numChildren; i++) { - Object obj = this.children.get(i); - if (obj instanceof FObj) { - FObj child = (FObj) obj; - child.resetMarker(); + if (children != null) { + int i = children.indexOf(childNode); + if (i >= 0) { + return children.listIterator(i); } } - } - - public void setWidows(int wid) { - widows = wid; - } - - public void setOrphans(int orph) { - orphans = orph; - } - - public void removeAreas() { - // still to do - } - - /** - * At the start of a new span area layout may be partway through a - * nested FO, and balancing requires rollback to this known point. - * The snapshot records exactly where layout is at. - * @param snapshot a ArrayList of markers (Integer) - * @returns the updated ArrayList of markers (Integers) - */ - public ArrayList getMarkerSnapshot(ArrayList snapshot) { - snapshot.add(new Integer(this.marker)); - - // terminate if no kids or child not yet accessed - if (this.marker < 0) { - return snapshot; - } else if (children.isEmpty()) { - return snapshot; - } else { - return ( (FObj) children.get(this.marker)).getMarkerSnapshot( - snapshot); - } + return null; } /** - * When balancing occurs, the flow layout() method restarts at the - * point specified by the current marker snapshot, which is retrieved - * and restored using this method. - * @param snapshot the ArrayList of saved markers (Integers) + * Add the marker to this formatting object. + * If this object can contain markers it checks that the marker + * has a unique class-name for this object and that it is + * the first child. */ - public void rollback(ArrayList snapshot) { - this.marker = ((Integer) snapshot.get(0)).intValue(); - snapshot.remove(0); - - if (this.marker == START) { - // make sure all the children of this FO are also reset - resetMarker(); - return; - } else if ((this.marker == -1) || children.isEmpty()) { - return; - } - - int numChildren = this.children.size(); - - if (this.marker <= START) { - return; - } - - for (int i = this.marker + 1; i < numChildren; i++) { - Object obj = this.children.get(i); - if (obj instanceof FObj) { - FObj child = (FObj) obj; - child.resetMarker(); + public void addMarker(Marker marker) { + String mcname = marker.getMarkerClassName(); + if (children != null) { + // check for empty children + for (Iterator iter = children.iterator(); iter.hasNext();) { + FONode node = (FONode)iter.next(); + if (node instanceof FOText) { + FOText text = (FOText)node; + if (text.willCreateArea()) { + getLogger().error("fo:marker must be an initial child: " + mcname); + return; + } else { + iter.remove(); + } + } else { + getLogger().error("fo:marker must be an initial child: " + mcname); + return; + } } } - ((FObj) children.get(this.marker)).rollback(snapshot); - } - - - public void addMarker(Marker marker) throws FOPException { - String mcname = marker.getMarkerClassName(); - if (!markers.containsKey(mcname) && children.isEmpty()) { + if (markers == null) { + markers = new HashMap(); + } + if (!markers.containsKey(mcname)) { markers.put(mcname, marker); } else { - getLogger().error("fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent"); - throw new FOPException( - "fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent"); + getLogger().error("fo:marker 'marker-class-name' must be unique for same parent: " + mcname); } } public boolean hasMarkers() { - return !markers.isEmpty(); + return markers != null && !markers.isEmpty(); } - public ArrayList getMarkers() { - return new ArrayList(markers.values()); + public Map getMarkers() { + return markers; } /** |