diff options
Diffstat (limited to 'src/org/apache/fop/fo')
42 files changed, 3326 insertions, 0 deletions
diff --git a/src/org/apache/fop/fo/ElementMapping.java b/src/org/apache/fop/fo/ElementMapping.java new file mode 100644 index 000000000..04fc3a0eb --- /dev/null +++ b/src/org/apache/fop/fo/ElementMapping.java @@ -0,0 +1,6 @@ +package org.apache.xml.fop.fo; + +public interface ElementMapping { + + public void addToBuilder(FOTreeBuilder builder); +} diff --git a/src/org/apache/fop/fo/FONode.java b/src/org/apache/fop/fo/FONode.java new file mode 100644 index 000000000..ede968d78 --- /dev/null +++ b/src/org/apache/fop/fo/FONode.java @@ -0,0 +1,110 @@ +package org.apache.xml.fop.fo; + +// FOP +import org.apache.xml.fop.apps.FOPException; +import org.apache.xml.fop.layout.Area; + +// Java +import java.util.Vector; + +/** + * base class for nodes in the formatting object tree + */ +abstract public class FONode { + + protected FObj parent; + protected Vector children = new Vector(); + + /** value of marker before layout begins */ + public final static int START = -1000; + + /** value of marker after break-after */ + public final static int BREAK_AFTER = -1001; + + /** + * where the layout was up to. + * for FObjs it is the child number + * for FOText it is the character number + */ + protected int marker = START; + + protected boolean isInLabel = false; + protected boolean isInListBody = false; + protected boolean isInTableCell = false; + + protected int bodyIndent; + protected int distanceBetweenStarts; + protected int labelSeparation; + + protected int forcedStartOffset = 0; + protected int forcedWidth = 0; + + protected FONode(FObj parent) { + this.parent = parent; + } + + public void setIsInLabel() { + this.isInLabel = true; + } + + public void setIsInListBody() { + this.isInListBody = true; + } + + public void setIsInTableCell() { + this.isInTableCell = true; + } + + public void setDistanceBetweenStarts(int distance) { + this.distanceBetweenStarts = distance; + } + + public void setLabelSeparation(int separation) { + this.labelSeparation = separation; + } + + public void setBodyIndent(int indent) { + this.bodyIndent = indent; + } + + public void forceStartOffset(int offset) { + this.forcedStartOffset = offset; + } + + public void forceWidth(int width) { + this.forcedWidth = width; + } + + public void resetMarker() { + this.marker = START; + int numChildren = this.children.size(); + for (int i = 0; i < numChildren; i++) { + ((FONode) children.elementAt(i)).resetMarker(); + } + } + + protected void addChild(FONode child) { + children.addElement(child); + } + + public FObj getParent() { + return this.parent; + } + + /* status */ + /* layout was fully completed */ + public final static int OK = 1; + /* none of the formatting object could be laid out because the + containing area was full (end of page) */ + public final static int AREA_FULL_NONE = 2; + /* some of the formatting object could not be laid out because the + containing area was full (end of page) */ + public final static int AREA_FULL_SOME = 3; + /* force page break */ + public final static int FORCE_PAGE_BREAK = 4; + public final static int FORCE_PAGE_BREAK_EVEN = 5; + public final static int FORCE_PAGE_BREAK_ODD = 6; + + abstract public int layout(Area area) + throws FOPException; +} diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java new file mode 100644 index 000000000..f61995a88 --- /dev/null +++ b/src/org/apache/fop/fo/FOText.java @@ -0,0 +1,80 @@ +package org.apache.xml.fop.fo; + +// FOP +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.BlockArea; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.datatypes.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.apps.FOPException; + +/** + * a text node in the formatting object tree + */ +public class FOText extends FONode { + + protected char[] ca; + protected int start; + protected int length; + + FontState fs; + float red; + float green; + float blue; + int wrapOption; + int whiteSpaceTreatment; + + protected FOText(char[] chars, int s, int e, FObj parent) { + super(parent); + this.start = 0; + this.ca = new char[e - s]; + for (int i = s; i < e; i++) + this.ca[i - s] = chars[i]; + this.length = e - s; + } + + public int layout(Area area) throws FOPException { + if (!(area instanceof BlockArea)) { + System.err.println("WARNING: text outside block area" + new String(ca, start, length)); + return OK; + } + if (this.marker == START) { + String fontFamily = + this.parent.properties.get("font-family").getString(); + String fontStyle = + this.parent.properties.get("font-style").getString(); + String fontWeight = + this.parent.properties.get("font-weight").getString(); + int fontSize = + this.parent.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, fontStyle, + fontWeight, fontSize); + + ColorType c = + this.parent.properties.get("color").getColorType(); + this.red = c.red(); + this.green = c.green(); + this.blue = c.blue(); + + this.wrapOption = + this.parent.properties.get("wrap-option").getEnum(); + this.whiteSpaceTreatment = + this.parent.properties.get("white-space-treatment").getEnum(); + + this.marker = this.start; + } + int orig_start = this.marker; + this.marker = ((BlockArea) area).addText(fs, red, green, blue, + wrapOption, + whiteSpaceTreatment, + ca, this.marker, length); + if (this.marker == -1) { + return OK; + } else if (this.marker != orig_start) { + return AREA_FULL_SOME; + } else { + return AREA_FULL_NONE; + } + } +} diff --git a/src/org/apache/fop/fo/FOTreeBuilder.java b/src/org/apache/fop/fo/FOTreeBuilder.java new file mode 100644 index 000000000..d4a1f5d09 --- /dev/null +++ b/src/org/apache/fop/fo/FOTreeBuilder.java @@ -0,0 +1,204 @@ +package org.apache.xml.fop.fo; + +// FOP +import org.apache.xml.fop.layout.AreaTree; +import org.apache.xml.fop.apps.FOPException; +import org.apache.xml.fop.fo.pagination.Root; + +// SAX +import org.xml.sax.HandlerBase; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; +import org.xml.sax.AttributeList; + +// Java +import java.util.Hashtable; +import java.util.Stack; +import java.io.IOException; + +/** + * SAX Handler that builds the formatting object tree. + */ +public class FOTreeBuilder extends HandlerBase { + + /** + * table mapping element names to the makers of objects + * representing formatting objects + */ + protected Hashtable fobjTable = new Hashtable(); + + /** + * class that builds a property list for each formatting object + */ + protected PropertyListBuilder propertyListBuilder = new + PropertyListBuilder(); + + /** + * current formatting object being handled + */ + protected FObj currentFObj = null; + + /** + * the root of the formatting object tree + */ + protected FObj rootFObj = null; + + /** + * set of names of formatting objects encountered but unknown + */ + protected Hashtable unknownFOs = new Hashtable(); + + // namespace implementation ideas pinched from John Cowan + protected static class NSMap { + String prefix; + String uri; + int level; + + NSMap(String prefix, String uri, int level) { + this.prefix = prefix; + this.uri = uri; + this.level = level; + } + } + + protected int level = 0; + protected Stack namespaceStack = new Stack(); + + { + namespaceStack.push(new NSMap("xml", + "http://www.w3.org/XML/1998/namespace", + -1)); + namespaceStack.push(new NSMap("", "", -1)); + } + + protected String findURI(String prefix) { + for (int i = namespaceStack.size() - 1; i >= 0; i--) { + NSMap nsMap = (NSMap) (namespaceStack.elementAt(i)); + if (prefix.equals(nsMap.prefix)) return nsMap.uri; + } + return null; + } + + protected String mapName(String name) + throws SAXException { + int colon = name.indexOf(':'); + String prefix = ""; + String localPart = name; + if (colon != -1) { + prefix = name.substring(0, colon); + localPart = name.substring(colon + 1); + } + String uri = findURI(prefix); + if (uri == null) { + if (prefix.equals("")) { + return name; + } else { + throw new SAXException(new FOPException("Unknown namespace prefix " + prefix)); + } + } + return uri + "^" + localPart; + } + + /** + * add a mapping from element name to maker. + * + * @param namespaceURI namespace URI of formatting object element + * @param localName local name of formatting object element + * @param maker Maker for class representing formatting object + */ + public void addMapping(String namespaceURI, String localName, + FObj.Maker maker) { + this.fobjTable.put(namespaceURI + "^" + localName, maker); + } + + /** SAX Handler for characters */ + public void characters(char data[], int start, int length) { + currentFObj.addCharacters(data, start, start + length); + } + + /** SAX Handler for the end of an element */ + public void endElement(String name) { + currentFObj.end(); + currentFObj = (FObj) currentFObj.getParent(); + level--; + while (((NSMap) namespaceStack.peek()).level > level) { + namespaceStack.pop(); + } + } + + /** SAX Handler for the start of the document */ + public void startDocument() { + System.err.println("building formatting object tree"); + } + + /** SAX Handler for the start of an element */ + public void startElement(String name, AttributeList attlist) + throws SAXException { + + /* the formatting object started */ + FObj fobj; + + /* the maker for the formatting object started */ + FObj.Maker fobjMaker; + + level++; + int length = attlist.getLength(); + for (int i = 0; i < length; i++) { + String att = attlist.getName(i); + if (att.equals("xmlns")) { + namespaceStack.push( new NSMap("", + attlist.getValue(i), + level)); + } else if (att.startsWith("xmlns:")) { + String value = attlist.getValue(i); + namespaceStack.push(new NSMap(att.substring(6), value, + level)); + } + } + String fullName = mapName(name); + + fobjMaker = (FObj.Maker) fobjTable.get(fullName); + + if (fobjMaker == null) { + if (!this.unknownFOs.containsKey(fullName)) { + this.unknownFOs.put(fullName, ""); + System.err.println("WARNING: Unknown formatting object " + + fullName); + } + fobjMaker = new FObjMixed.Maker(); // fall back + } + + try { + fobj = + fobjMaker.make(currentFObj, + this.propertyListBuilder.makeList(attlist, + (currentFObj == null) ? null : currentFObj.properties)); + } catch (FOPException e) { + throw new SAXException(e); + } + + if (rootFObj == null) { + rootFObj = fobj; + if (!fobj.getName().equals("fo:root")) { + throw new SAXException(new FOPException("Root element must" + + " be root, not " + + fobj.getName())); + } + } else { + currentFObj.addChild(fobj); + } + + currentFObj = fobj; + } + + /** + * format this formatting object tree + * + * @param areaTree the area tree to format into + */ + public void format(AreaTree areaTree) + throws FOPException { + System.err.println("formatting FOs into areas"); + ((Root) this.rootFObj).format(areaTree); + } +} diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java new file mode 100644 index 000000000..a94cbcad6 --- /dev/null +++ b/src/org/apache/fop/fo/FObj.java @@ -0,0 +1,57 @@ +package org.apache.xml.fop.fo; + +// FOP +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Hashtable; +import java.util.Enumeration; + +/** + * base class for representation of formatting objects and their processing + */ +public class FObj extends FONode { + + public static class Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new FObj(parent, propertyList); + } + } + + public static Maker maker() { + return new Maker(); + } + + protected PropertyList properties; + protected String name; + + protected FObj(FObj parent, PropertyList propertyList) { + super(parent); + this.properties = propertyList; + this.name = "default FO"; + } + + protected void addCharacters(char data[], int start, int length) { + // ignore + } + + public int layout(Area area) throws FOPException { + // should always be overridden + return OK; + } + + public String getName() { + return this.name; + } + + protected void start() { + // do nothing by default + } + + protected void end() { + // do nothing by default + } +} + diff --git a/src/org/apache/fop/fo/FObjMixed.java b/src/org/apache/fop/fo/FObjMixed.java new file mode 100644 index 000000000..177e940b1 --- /dev/null +++ b/src/org/apache/fop/fo/FObjMixed.java @@ -0,0 +1,49 @@ +package org.apache.xml.fop.fo; + +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +/** + * base class for representation of mixed content formatting objects + * and their processing + */ +public class FObjMixed extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new FObjMixed(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new FObjMixed.Maker(); + } + + protected FObjMixed(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + } + + protected void addCharacters(char data[], int start, int length) { + children.addElement(new FOText(data,start,length,this)); + } + + public int layout(Area area) throws FOPException { + + if (this.marker == START) { + this.marker = 0; + } + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FONode fo = (FONode) children.elementAt(i); + int status; + if ((status = fo.layout(area)) != OK) { + this.marker = i; + return status; + } + } + return OK; + } +} + diff --git a/src/org/apache/fop/fo/Makefile b/src/org/apache/fop/fo/Makefile new file mode 100644 index 000000000..da4211088 --- /dev/null +++ b/src/org/apache/fop/fo/Makefile @@ -0,0 +1,33 @@ + + +BASEDIR:=../../../../.. +include $(BASEDIR)/Makefile.rules + +SUBDIRS=flow \ + pagination + + +SOURCES=FONode.java \ + FOText.java \ + FOTreeBuilder.java \ + FObj.java \ + FObjMixed.java \ + Property.java \ + PropertyList.java \ + PropertyListBuilder.java \ + StandardElementMapping.java + +CLASSES=$(SOURCES:.java=.class) + +all: $(CLASSES) allsubs + +clean: cleanme cleansubs + +cleanme: + rm -f *.class + +$(TARGETS:%=%subs): %subs : + for dir in $(SUBDIRS) ; do \ + (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \ + done + diff --git a/src/org/apache/fop/fo/Property.java b/src/org/apache/fop/fo/Property.java new file mode 100644 index 000000000..420bee8cb --- /dev/null +++ b/src/org/apache/fop/fo/Property.java @@ -0,0 +1,41 @@ +package org.apache.xml.fop.fo; + +import org.apache.xml.fop.datatypes.*; +import org.apache.xml.fop.apps.FOPException; + +public class Property { + + public static class Maker { + + public boolean isInherited() { return false; } + + public Property make(PropertyList propertyList, String value) throws FOPException { + return null; + } + + public Property make(PropertyList propertyList) throws FOPException { // default + return null; + } + + public Property compute(PropertyList propertyList) { // compute + return null; + } + } + protected PropertyList propertyList; + + public Length getLength() { return null; } + public String getString() { return null; } + public ColorType getColorType() { return null; } + public int getEnum() { return 0; } + + public static double toDouble(String s) { + double d; + try { + d = Double.valueOf(s).doubleValue(); + } catch (NumberFormatException e) { + d = Double.NaN; + } + return d; + } + +} diff --git a/src/org/apache/fop/fo/PropertyList.java b/src/org/apache/fop/fo/PropertyList.java new file mode 100644 index 000000000..e3a6092b7 --- /dev/null +++ b/src/org/apache/fop/fo/PropertyList.java @@ -0,0 +1,41 @@ +package org.apache.xml.fop.fo; + +import java.util.Hashtable; + +import org.apache.xml.fop.apps.FOPException; + +public class PropertyList extends Hashtable { + private PropertyListBuilder builder; + private PropertyList parentPropertyList = null; + + public PropertyList(PropertyList parentPropertyList) { + this.parentPropertyList = parentPropertyList; + } + + public Property get(String propertyName) { + + if (builder == null) + System.err.println("OH OH, builder has not been set"); + Property p = (Property)super.get(propertyName); + + if (p == null) { // if not explicit + p = this.builder.computeProperty(this,propertyName); + if (p == null) { // else inherit + if ((this.parentPropertyList != null)&&(this.builder.isInherited(propertyName))) { // check for parent + p = this.parentPropertyList.get(propertyName); // retrieve parent's value + } else { // default + try { + p = this.builder.makeProperty(this,propertyName); + } catch (FOPException e) { + // don't know what to do here + } + } + } + } + return p; + } + + public void setBuilder(PropertyListBuilder builder) { + this.builder = builder; + } +} diff --git a/src/org/apache/fop/fo/PropertyListBuilder.java b/src/org/apache/fop/fo/PropertyListBuilder.java new file mode 100644 index 000000000..7c12763d6 --- /dev/null +++ b/src/org/apache/fop/fo/PropertyListBuilder.java @@ -0,0 +1,120 @@ +package org.apache.xml.fop.fo; + +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.svg.*; + +import org.apache.xml.fop.apps.FOPException; + +import org.xml.sax.AttributeList; + +import java.util.Hashtable; + +public class PropertyListBuilder { + private Hashtable propertyTable; + + public PropertyListBuilder() { + this.propertyTable = new Hashtable(); + + propertyTable.put("end-indent",EndIndent.maker()); + propertyTable.put("page-master-name",PageMasterName.maker()); + propertyTable.put("page-master-first",PageMasterFirst.maker()); + propertyTable.put("page-master-repeating",PageMasterRepeating.maker()); + propertyTable.put("page-master-odd",PageMasterOdd.maker()); + propertyTable.put("page-master-even",PageMasterEven.maker()); + propertyTable.put("margin-top",MarginTop.maker()); + propertyTable.put("margin-bottom",MarginBottom.maker()); + propertyTable.put("margin-left",MarginLeft.maker()); + propertyTable.put("margin-right",MarginRight.maker()); + propertyTable.put("extent",Extent.maker()); + propertyTable.put("page-width",PageWidth.maker()); + propertyTable.put("page-height",PageHeight.maker()); + propertyTable.put("flow-name",FlowName.maker()); + propertyTable.put("font-family",FontFamily.maker()); + propertyTable.put("font-style",FontStyle.maker()); + propertyTable.put("font-weight",FontWeight.maker()); + propertyTable.put("font-size",FontSize.maker()); + propertyTable.put("line-height",LineHeight.maker()); + propertyTable.put("text-align",TextAlign.maker()); + propertyTable.put("text-align-last",TextAlignLast.maker()); + propertyTable.put("space-before.optimum",SpaceBeforeOptimum.maker()); + propertyTable.put("space-after.optimum",SpaceAfterOptimum.maker()); + propertyTable.put("start-indent",StartIndent.maker()); + propertyTable.put("end-indent",EndIndent.maker()); + propertyTable.put("provisional-distance-between-starts",ProvisionalDistanceBetweenStarts.maker()); + propertyTable.put("provisional-label-separation",ProvisionalLabelSeparation.maker()); + propertyTable.put("rule-thickness",RuleThickness.maker()); + propertyTable.put("color",Color.maker()); + propertyTable.put("wrap-option",WrapOption.maker()); + propertyTable.put("white-space-treatment",WhiteSpaceTreatment.maker()); + propertyTable.put("break-before",BreakBefore.maker()); + propertyTable.put("break-after",BreakAfter.maker()); + propertyTable.put("text-indent",TextIndent.maker()); + propertyTable.put("href",HRef.maker()); + propertyTable.put("column-width",ColumnWidth.maker()); + propertyTable.put("height",SVGLength.maker()); + propertyTable.put("width",SVGLength.maker()); + propertyTable.put("x",SVGLength.maker()); + propertyTable.put("y",SVGLength.maker()); + propertyTable.put("x1",SVGLength.maker()); + propertyTable.put("x2",SVGLength.maker()); + propertyTable.put("y1",SVGLength.maker()); + propertyTable.put("y2",SVGLength.maker()); + } + + public Property computeProperty(PropertyList propertyList, String propertyName) { + + Property p = null; + + Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName); + if (propertyMaker != null) { + p = propertyMaker.compute(propertyList); + } else { + //System.err.println("WARNING: property " + propertyName + " ignored"); + } + return p; + } + + public boolean isInherited(String propertyName) { + boolean b; + + Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName); + if (propertyMaker != null) { + b = propertyMaker.isInherited(); + } else { + //System.err.println("WARNING: Unknown property " + propertyName); + b = true; + } + return b; + } + + public PropertyList makeList(AttributeList attributes, PropertyList parentPropertyList) throws FOPException { + + PropertyList p = new PropertyList(parentPropertyList); + p.setBuilder(this); + + for (int i = 0; i < attributes.getLength(); i++) { + String attributeName = attributes.getName(i); + Property.Maker propertyMaker = (Property.Maker)propertyTable.get(attributeName); + if (propertyMaker != null) { + p.put(attributeName,propertyMaker.make(p,attributes.getValue(i))); + } else { + //System.err.println("WARNING: property " + attributeName + " ignored"); + } + } + + return p; + } + + public Property makeProperty(PropertyList propertyList, String propertyName) throws FOPException { + + Property p = null; + + Property.Maker propertyMaker = (Property.Maker)propertyTable.get(propertyName); + if (propertyMaker != null) { + p = propertyMaker.make(propertyList); + } else { + //System.err.println("WARNING: property " + propertyName + " ignored"); + } + return p; + } +} diff --git a/src/org/apache/fop/fo/StandardElementMapping.java b/src/org/apache/fop/fo/StandardElementMapping.java new file mode 100644 index 000000000..396b01aeb --- /dev/null +++ b/src/org/apache/fop/fo/StandardElementMapping.java @@ -0,0 +1,52 @@ +package org.apache.xml.fop.fo; + +import org.apache.xml.fop.fo.flow.*; +import org.apache.xml.fop.fo.pagination.*; + +public class StandardElementMapping implements ElementMapping { + + public void addToBuilder(FOTreeBuilder builder) { + + String uri = "http://www.w3.org/1999/XSL/Format"; + + builder.addMapping(uri, "root", Root.maker()); + builder.addMapping(uri, "layout-master-set", + LayoutMasterSet.maker()); + builder.addMapping(uri, "simple-page-master", + SimplePageMaster.maker()); + builder.addMapping(uri, "region-body", RegionBody.maker()); + builder.addMapping(uri, "region-before", RegionBefore.maker()); + builder.addMapping(uri, "region-after", RegionAfter.maker()); + builder.addMapping(uri, "page-sequence", PageSequence.maker()); + builder.addMapping(uri, "sequence-specification", + SequenceSpecification.maker()); + builder.addMapping(uri, "sequence-specifier-single", + SequenceSpecifierSingle.maker()); + builder.addMapping(uri, "sequence-specifier-repeating", + SequenceSpecifierRepeating.maker()); + builder.addMapping(uri, "sequence-specifier-alternating", + SequenceSpecifierAlternating.maker()); + builder.addMapping(uri, "flow", Flow.maker()); + builder.addMapping(uri, "static-content", + StaticContent.maker()); + builder.addMapping(uri, "block", Block.maker()); + builder.addMapping(uri, "list-block", ListBlock.maker()); + builder.addMapping(uri, "list-item", ListItem.maker()); + builder.addMapping(uri, "list-item-label", + ListItemLabel.maker()); + builder.addMapping(uri, "list-item-body", ListItemBody.maker()); + builder.addMapping(uri, "page-number", PageNumber.maker()); + builder.addMapping(uri, "display-sequence", + DisplaySequence.maker()); + builder.addMapping(uri, "inline-sequence", + InlineSequence.maker()); + builder.addMapping(uri, "display-rule", DisplayRule.maker()); + builder.addMapping(uri, "display-graphic", + DisplayGraphic.maker()); + builder.addMapping(uri, "table", Table.maker()); + builder.addMapping(uri, "table-column", TableColumn.maker()); + builder.addMapping(uri, "table-body", TableBody.maker()); + builder.addMapping(uri, "table-row", TableRow.maker()); + builder.addMapping(uri, "table-cell", TableCell.maker()); + } +} diff --git a/src/org/apache/fop/fo/flow/Block.java b/src/org/apache/fop/fo/flow/Block.java new file mode 100644 index 000000000..61e28108a --- /dev/null +++ b/src/org/apache/fop/fo/flow/Block.java @@ -0,0 +1,192 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +public class Block extends FObjMixed { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new Block(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new Block.Maker(); + } + + FontState fs; + int align; + int alignLast; + int breakBefore; + int breakAfter; + int lineHeight; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + int textIndent; + + BlockArea blockArea; + + // this may be helpful on other FOs too + boolean anythingLaidOut = false; + + public Block(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:block"; + } + + public int layout(Area area) throws FOPException { + // System.err.print(" b:LAY[" + marker + "] "); + + if (this.marker == BREAK_AFTER) { + return OK; + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + this.align = this.properties.get("text-align").getEnum(); + this.alignLast = + this.properties.get("text-align-last").getEnum(); + this.breakBefore = + this.properties.get("break-before").getEnum(); + this.breakAfter = + this.properties.get("break-after").getEnum(); + this.lineHeight = + this.properties.get("line-height").getLength().mvalue(); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + this.textIndent = + this.properties.get("text-indent").getLength().mvalue(); + + if (area instanceof BlockArea) { + area.end(); + } + if (this.isInLabel) { + startIndent += bodyIndent; + endIndent += (area.getAllocationWidth() + - distanceBetweenStarts - startIndent) + + labelSeparation; + } + + if (this.isInListBody) { + startIndent += bodyIndent + distanceBetweenStarts; + } + + if (this.isInTableCell) { + startIndent += forcedStartOffset; + endIndent = area.getAllocationWidth() - startIndent - + forcedWidth; + } + + this.marker = 0; + + if (breakBefore == BreakBefore.PAGE) { + return FORCE_PAGE_BREAK; + } + + if (breakBefore == BreakBefore.ODD_PAGE) { + return FORCE_PAGE_BREAK_ODD; + } + + if (breakBefore == BreakBefore.EVEN_PAGE) { + return FORCE_PAGE_BREAK_EVEN; + } + } + + if ((spaceBefore != 0) && (this.marker ==0)) { + area.addDisplaySpace(spaceBefore); + } + + if (anythingLaidOut) { + this.textIndent = 0; + } + + this.blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, + textIndent, align, alignLast, lineHeight); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FONode fo = (FONode) children.elementAt(i); + if (this.isInListBody) { + fo.setIsInListBody(); + fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + fo.setBodyIndent(this.bodyIndent); + } + int status; + if ((status = fo.layout(blockArea)) != OK) { + this.marker = i; + if ((i != 0) && (status == AREA_FULL_NONE)) { + status = AREA_FULL_SOME; + } + //blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + anythingLaidOut = true; + return status; + } + anythingLaidOut = true; + } + + blockArea.end(); + area.addChild(blockArea); + + /* should this be combined into above? */ + area.increaseHeight(blockArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + if (breakAfter == BreakAfter.PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK; + } + + if (breakAfter == BreakAfter.ODD_PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK_ODD; + } + + if (breakAfter == BreakAfter.EVEN_PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK_EVEN; + } + + //System.err.print(" b:OK" + marker + " "); + return OK; + } + + public int getAreaHeight() { + return blockArea.getHeight(); + } +} diff --git a/src/org/apache/fop/fo/flow/DisplayGraphic.java b/src/org/apache/fop/fo/flow/DisplayGraphic.java new file mode 100644 index 000000000..90f4508e5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplayGraphic.java @@ -0,0 +1,132 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.BlockArea; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; +import org.apache.xml.fop.image.*; + +// Java +import java.util.Enumeration; +import java.util.Hashtable; + +public class DisplayGraphic extends FObj { + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new DisplayGraphic(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new DisplayGraphic.Maker(); + } + + FontState fs; + int align; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + String href; + int height; + int width; + + ImageArea imageArea; + + public DisplayGraphic(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:display-graphic"; + } + + public int layout(Area area) throws FOPException { + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + + // FIXME + this.align = this.properties.get("text-align").getEnum(); + + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + + this.href = this.properties.get("href").getString(); + this.width = + this.properties.get("width").getLength().mvalue(); + this.height = + this.properties.get("height").getLength().mvalue(); + + if (area instanceof BlockArea) { + area.end(); + } + + if (this.isInLabel) { + startIndent += bodyIndent; + endIndent += (area.getAllocationWidth() + - distanceBetweenStarts - startIndent) + + labelSeparation; + } + + if (this.isInListBody) { + startIndent += bodyIndent + distanceBetweenStarts; + } + + if (this.isInTableCell) { + startIndent += forcedStartOffset; + endIndent = area.getAllocationWidth() - startIndent - + forcedWidth; + } + + this.marker = 0; + } + + if ((spaceBefore != 0) && (this.marker == 0)) { + area.addDisplaySpace(spaceBefore); + } + + FopImage img = FopImageFactory.Make(href, 0, 0, width, height); + + this.imageArea = new ImageArea(fs, + img, + area.getAllocationWidth(), + img.getWidth(), + img.getHeight(), + startIndent, endIndent, + align); + + imageArea.start(); + imageArea.end(); + area.addChild(imageArea); + area.increaseHeight(imageArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/DisplayRule.java b/src/org/apache/fop/fo/flow/DisplayRule.java new file mode 100644 index 000000000..83784816e --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplayRule.java @@ -0,0 +1,88 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.datatypes.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.BlockArea; +import org.apache.xml.fop.layout.RuleArea; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; + +public class DisplayRule extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new DisplayRule(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new DisplayRule.Maker(); + } + + public DisplayRule(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:display-rule"; + } + + public int layout(Area area) throws FOPException { + // FIXME: doesn't check to see if it will fit + + String fontFamily = this.properties.get("font-family").getString(); + String fontStyle = this.properties.get("font-style").getString(); + String fontWeight = this.properties.get("font-weight").getString(); + int fontSize = this.properties.get("font-size").getLength().mvalue(); + + FontState fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + + int align = this.properties.get("text-align").getEnum(); + int startIndent = + this.properties.get("start-indent").getLength().mvalue(); + int endIndent = + this.properties.get("end-indent").getLength().mvalue(); + int spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + int spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + int ruleThickness = + this.properties.get("rule-thickness").getLength().mvalue(); + int ruleLength = 0; // not used; + + ColorType c = this.properties.get("color").getColorType(); + float red = c.red(); + float green = c.green(); + float blue = c.blue(); + + if (area instanceof BlockArea) { + area.end(); + } + + if (spaceBefore != 0) { + area.addDisplaySpace(spaceBefore); + } + + RuleArea ruleArea = new RuleArea(fs, + area.getAllocationWidth(), + area.spaceLeft(), + startIndent, endIndent, + align, ruleThickness, + ruleLength, red, green, + blue); + area.addChild(ruleArea); + area.increaseHeight(ruleArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/DisplaySequence.java b/src/org/apache/fop/fo/flow/DisplaySequence.java new file mode 100644 index 000000000..c50b6bc6a --- /dev/null +++ b/src/org/apache/fop/fo/flow/DisplaySequence.java @@ -0,0 +1,52 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class DisplaySequence extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new DisplaySequence(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new DisplaySequence.Maker(); + } + + public DisplaySequence(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:display-sequence"; + } + + public int layout(Area area) throws FOPException { + if (this.marker == START) { + this.marker = 0; + } + // this is such common code, perhaps it should be in the super class + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FObj fo = (FObj) children.elementAt(i); + int status; + if ((status = fo.layout(area)) != OK) { + /* message from child */ + if (status > OK) { + /* child still successful */ + this.marker = i+1; + } else { + /* child unsucessful */ + this.marker = i; + } + return status; + } + } + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/Flow.java b/src/org/apache/fop/fo/flow/Flow.java new file mode 100644 index 000000000..b9b66a1b8 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Flow.java @@ -0,0 +1,59 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.fo.pagination.PageSequence; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Hashtable; +import java.util.Enumeration; + +public class Flow extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new Flow(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new Flow.Maker(); + } + + PageSequence pageSequence; + + protected Flow(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:flow"; + + if (parent.getName().equals("fo:page-sequence")) { + this.pageSequence = (PageSequence) parent; + } else { + throw new FOPException("flow must be child of " + + "page-sequence, not " + + parent.getName()); + } + pageSequence.setFlow(this); + } + + public int layout(Area area) throws FOPException { + if (this.marker == START) { + this.marker = 0; + } + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FObj fo = (FObj) children.elementAt(i); + int status; + if ((status = fo.layout(area)) != OK) { + this.marker = i; + return status; + } + } + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/InlineSequence.java b/src/org/apache/fop/fo/flow/InlineSequence.java new file mode 100644 index 000000000..33efc6b31 --- /dev/null +++ b/src/org/apache/fop/fo/flow/InlineSequence.java @@ -0,0 +1,35 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class InlineSequence extends FObjMixed { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new InlineSequence(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new InlineSequence.Maker(); + } + + public InlineSequence(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:inline-sequence"; + + if (parent.getName().equals("fo:flow")) { + throw new FOPException("inline-sequence can't be directly" + + " under flow"); + } + } + +} diff --git a/src/org/apache/fop/fo/flow/ListBlock.java b/src/org/apache/fop/fo/flow/ListBlock.java new file mode 100644 index 000000000..6810825d5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListBlock.java @@ -0,0 +1,143 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.BlockArea; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class ListBlock extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new ListBlock(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new ListBlock.Maker(); + } + + FontState fs; + int align; + int alignLast; + int breakBefore; + int breakAfter; + int lineHeight; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + int provisionalDistanceBetweenStarts; + int provisionalLabelSeparation; + int spaceBetweenListRows = 0; + + public ListBlock(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:list-block"; + } + + public int layout(Area area) throws FOPException { + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + + this.align = this.properties.get("text-align").getEnum(); + this.alignLast = + this.properties.get("text-align-last").getEnum(); + this.lineHeight = + this.properties.get("line-height").getLength().mvalue(); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + this.provisionalDistanceBetweenStarts = + this.properties.get("provisional-distance-between-starts").getLength().mvalue(); + this.provisionalLabelSeparation = + this.properties.get("provisional-label-separation").getLength().mvalue(); + this.spaceBetweenListRows = 0; // not used at present + + this.marker = 0; + + if (area instanceof BlockArea) { + area.end(); + } + + if (spaceBefore != 0) { + area.addDisplaySpace(spaceBefore); + } + + if (this.isInListBody) { + startIndent += bodyIndent + distanceBetweenStarts; + bodyIndent = startIndent; + } + } + + BlockArea blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, 0, + align, alignLast, lineHeight); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + if (!(children.elementAt(i) instanceof ListItem)) { + System.err.println("WARNING: This version of FOP requires list-items inside list-blocks"); + return OK; + } + ListItem listItem = (ListItem) children.elementAt(i); + listItem.setDistanceBetweenStarts(this.provisionalDistanceBetweenStarts); + listItem.setLabelSeparation(this.provisionalLabelSeparation); + listItem.setBodyIndent(this.bodyIndent); + int status; + if ((status = listItem.layout(blockArea)) != OK) { + /* message from child */ + if (status > OK) { + /* child still successful */ + this.marker = i+1; + } else { + /* child unsucessful */ + this.marker = i; + } + blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + return status; + } + } + + blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/ListItem.java b/src/org/apache/fop/fo/flow/ListItem.java new file mode 100644 index 000000000..f69cf45da --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItem.java @@ -0,0 +1,144 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.BlockArea; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class ListItem extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new ListItem(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new ListItem.Maker(); + } + + FontState fs; + int align; + int alignLast; + int breakBefore; + int breakAfter; + int lineHeight; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + + public ListItem(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:list-item"; + } + + public int layout(Area area) throws FOPException { + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + + this.align = this.properties.get("text-align").getEnum(); + this.alignLast = + this.properties.get("text-align-last").getEnum(); + this.lineHeight = + this.properties.get("line-height").getLength().mvalue(); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + + this.marker = 0; + } + + /* not sure this is needed given we know area is from list block */ + if (area instanceof BlockArea) { + area.end(); + } + + if (spaceBefore != 0) { + area.addDisplaySpace(spaceBefore); + } + + startIndent += this.bodyIndent; + + BlockArea blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, + 0, align, alignLast, lineHeight); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + if (numChildren != 2) { + throw new FOPException("list-item must have exactly two children"); + } + ListItemLabel label = (ListItemLabel) children.elementAt(0); + ListItemBody body = (ListItemBody) children.elementAt(1); + + label.setDistanceBetweenStarts(this.distanceBetweenStarts); + label.setLabelSeparation(this.labelSeparation); + label.setBodyIndent(this.bodyIndent); + + body.setDistanceBetweenStarts(this.distanceBetweenStarts); + body.setBodyIndent(this.bodyIndent); + + /* this doesn't actually do anything */ + body.setLabelSeparation(this.labelSeparation); + + int status; + + // what follows doesn't yet take into account whether the + // body failed completely or only got some text in + + if (this.marker == 0) { + status = label.layout(blockArea); + if (status != OK) { + return status; + } + } + + status = body.layout(blockArea); + if (status != OK) { + blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + this.marker = 1; + return status; + } + + blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + /* not sure this is needed given we know area is from list block */ + if (area instanceof BlockArea) { + area.start(); + } + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/ListItemBody.java b/src/org/apache/fop/fo/flow/ListItemBody.java new file mode 100644 index 000000000..c348355f5 --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItemBody.java @@ -0,0 +1,54 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class ListItemBody extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new ListItemBody(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new ListItemBody.Maker(); + } + + public ListItemBody(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:list-item-body"; + } + + public int layout(Area area) throws FOPException { + if (this.marker == START) { + this.marker = 0; + } + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FObj fo = (FObj) children.elementAt(i); + fo.setIsInListBody(); + fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + fo.setLabelSeparation(this.labelSeparation); + fo.setBodyIndent(this.bodyIndent); + int status; + if ((status = fo.layout(area)) != OK) { + this.marker = i; + if ((i == 0) && (status == AREA_FULL_NONE)) { + return AREA_FULL_NONE; + } else { + return AREA_FULL_SOME; + } + } + } + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/ListItemLabel.java b/src/org/apache/fop/fo/flow/ListItemLabel.java new file mode 100644 index 000000000..fe7c0513a --- /dev/null +++ b/src/org/apache/fop/fo/flow/ListItemLabel.java @@ -0,0 +1,49 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.FontState; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class ListItemLabel extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new ListItemLabel(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new ListItemLabel.Maker(); + } + + public ListItemLabel(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:list-item-label"; + } + + public int layout(Area area) throws FOPException { + int numChildren = this.children.size(); + + if (numChildren != 1) { + throw new FOPException("list-item-label must have exactly one block in this version of FOP"); + } + Block block = (Block) children.elementAt(0); + + block.setIsInLabel(); + block.setDistanceBetweenStarts(this.distanceBetweenStarts); + block.setLabelSeparation(this.labelSeparation); + block.setBodyIndent(this.bodyIndent); + + int status; + status = block.layout(area); + area.addDisplaySpace(-block.getAreaHeight()); + return status; + } +} diff --git a/src/org/apache/fop/fo/flow/Makefile b/src/org/apache/fop/fo/flow/Makefile new file mode 100644 index 000000000..72876ca68 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Makefile @@ -0,0 +1,39 @@ + + +BASEDIR:=../../../../../.. +include $(BASEDIR)/Makefile.rules + +SUBDIRS= + + +SOURCES=Block.java \ + DisplayGraphic.java \ + DisplayRule.java \ + DisplaySequence.java \ + Flow.java \ + InlineSequence.java \ + ListBlock.java \ + ListItemBody.java \ + ListItemLabel.java \ + PageNumber.java \ + StaticContent.java \ + Table.java \ + TableBody.java \ + TableCell.java \ + TableColumn.java \ + TableRow.java + +CLASSES=$(SOURCES:.java=.class) + +all: $(CLASSES) allsubs + +clean: cleanme cleansubs + +cleanme: + rm -f *.class + +$(TARGETS:%=%subs): %subs : + for dir in $(SUBDIRS) ; do \ + (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \ + done + diff --git a/src/org/apache/fop/fo/flow/PageNumber.java b/src/org/apache/fop/fo/flow/PageNumber.java new file mode 100644 index 000000000..3a3f59813 --- /dev/null +++ b/src/org/apache/fop/fo/flow/PageNumber.java @@ -0,0 +1,66 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.datatypes.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class PageNumber extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new PageNumber(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new PageNumber.Maker(); + } + + FontState fs; + float red; + float green; + float blue; + int wrapOption; + int whiteSpaceTreatment; + + public PageNumber(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:page-number"; + } + + public int layout(Area area) throws FOPException { + if (!(area instanceof BlockArea)) { + System.err.println("WARNING: page-number outside block area"); + return OK; + } + if (this.marker == START) { + String fontFamily = this.properties.get("font-family").getString(); + String fontStyle = this.properties.get("font-style").getString(); + String fontWeight = this.properties.get("font-weight").getString(); + int fontSize = this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + + ColorType c = this.properties.get("color").getColorType(); + this.red = c.red(); + this.green = c.green(); + this.blue = c.blue(); + + this.wrapOption = this.properties.get("wrap-option").getEnum(); + this.whiteSpaceTreatment = this.properties.get("white-space-treatment").getEnum(); + + this.marker = 0; + } + String p = Integer.toString(area.getPage().getNumber()); + this.marker = ((BlockArea) area).addText(fs, red, green, blue, wrapOption, whiteSpaceTreatment, p.toCharArray(), 0, p.length()); + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/StaticContent.java b/src/org/apache/fop/fo/flow/StaticContent.java new file mode 100644 index 000000000..5dc6971e1 --- /dev/null +++ b/src/org/apache/fop/fo/flow/StaticContent.java @@ -0,0 +1,54 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.fo.pagination.PageSequence; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Enumeration; + +public class StaticContent extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new StaticContent(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new StaticContent.Maker(); + } + + PageSequence pageSequence; + + protected StaticContent(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:static-content"; + + if (parent.getName().equals("fo:page-sequence")) { + this.pageSequence = (PageSequence) parent; + } else { + throw new FOPException("static-content must be child of " + + "fo:page-sequence, not " + + parent.getName()); + } + String flowName = this.properties.get("flow-name").getString(); + + pageSequence.setStaticContent(flowName, this); + } + + public int layout(Area area) throws FOPException { + int numChildren = this.children.size(); + for (int i = 0; i < numChildren; i++) { + FObj fo = (FObj) children.elementAt(i); + fo.layout(area); + } + resetMarker(); + return OK; + } +} diff --git a/src/org/apache/fop/fo/flow/Table.java b/src/org/apache/fop/fo/flow/Table.java new file mode 100644 index 000000000..f838a7947 --- /dev/null +++ b/src/org/apache/fop/fo/flow/Table.java @@ -0,0 +1,183 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Vector; + +public class Table extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new Table(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new Table.Maker(); + } + + FontState fs; + int breakBefore; + int breakAfter; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + + Vector columns = new Vector(); + int currentColumnNumber = 0; + + BlockArea blockArea; + + public Table(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:table"; + } + + public int layout(Area area) throws FOPException { + if (this.marker == BREAK_AFTER) { + return OK; + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + this.breakBefore = + this.properties.get("break-before").getEnum(); + this.breakAfter = + this.properties.get("break-after").getEnum(); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + if (area instanceof BlockArea) { + area.end(); + } + + if (this.isInListBody) { + startIndent += bodyIndent + distanceBetweenStarts; + } + + this.marker = 0; + + if (breakBefore == BreakBefore.PAGE) { + return FORCE_PAGE_BREAK; + } + + if (breakBefore == BreakBefore.ODD_PAGE) { + return FORCE_PAGE_BREAK_ODD; + } + + if (breakBefore == BreakBefore.EVEN_PAGE) { + return FORCE_PAGE_BREAK_EVEN; + } + } + + if ((spaceBefore != 0) && (this.marker ==0)) { + area.addDisplaySpace(spaceBefore); + } + + this.blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, 0, + 0, 0, 0); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FONode fo = (FONode) children.elementAt(i); + if (fo instanceof TableColumn) { + TableColumn c = (TableColumn) fo; + int num = c.getColumnNumber(); + if (num == 0) { + num = currentColumnNumber + 1; + } + currentColumnNumber = num; + if (num > columns.size()) { + columns.setSize(num); + } + columns.setElementAt(c, num-1); + } else if (fo instanceof TableBody) { + if (columns.size() == 0) { + System.err.println("WARNING: current implementation of tables requires a table-column for each column, indicating column-width"); + return OK; + } + + //if (this.isInListBody) { + //fo.setIsInListBody(); + //fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + //fo.setBodyIndent(this.bodyIndent); + //} + + ((TableBody) fo).setColumns(columns); + + int status; + if ((status = fo.layout(blockArea)) != OK) { + this.marker = i; + if ((i != 0) && (status == AREA_FULL_NONE)) { + status = AREA_FULL_SOME; + } + //blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + return status; + } + } + } + + blockArea.end(); + area.addChild(blockArea); + + /* should this be combined into above? */ + area.increaseHeight(blockArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + if (breakAfter == BreakAfter.PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK; + } + + if (breakAfter == BreakAfter.ODD_PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK_ODD; + } + + if (breakAfter == BreakAfter.EVEN_PAGE) { + this.marker = BREAK_AFTER; + return FORCE_PAGE_BREAK_EVEN; + } + + return OK; + } + + public int getAreaHeight() { + return blockArea.getHeight(); + } +} diff --git a/src/org/apache/fop/fo/flow/TableBody.java b/src/org/apache/fop/fo/flow/TableBody.java new file mode 100644 index 000000000..9ff6a842c --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableBody.java @@ -0,0 +1,137 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Vector; + +public class TableBody extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new TableBody(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new TableBody.Maker(); + } + + FontState fs; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + + Vector columns; + + BlockArea blockArea; + + public TableBody(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:table-body"; + } + + public void setColumns(Vector columns) { + this.columns = columns; + } + + public int layout(Area area) throws FOPException { + if (this.marker == BREAK_AFTER) { + return OK; + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + if (area instanceof BlockArea) { + area.end(); + } + + //if (this.isInListBody) { + //startIndent += bodyIndent + distanceBetweenStarts; + //} + + this.marker = 0; + + } + + if ((spaceBefore != 0) && (this.marker ==0)) { + area.addDisplaySpace(spaceBefore); + } + + this.blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, 0, + 0, 0, 0); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + TableRow row = (TableRow) children.elementAt(i); + + //if (this.isInListBody) { + //fo.setIsInListBody(); + //fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + //fo.setBodyIndent(this.bodyIndent); + //} + + row.setColumns(columns); + + int status; + if ((status = row.layout(blockArea)) != OK) { + this.marker = i; + if ((i != 0) && (status == AREA_FULL_NONE)) { + status = AREA_FULL_SOME; + } + //blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + return status; + } + } + + blockArea.end(); + area.addChild(blockArea); + + /* should this be combined into above? */ + area.increaseHeight(blockArea.getHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + return OK; + } + + public int getAreaHeight() { + return blockArea.getHeight(); + } +} diff --git a/src/org/apache/fop/fo/flow/TableCell.java b/src/org/apache/fop/fo/flow/TableCell.java new file mode 100644 index 000000000..f2df8328c --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableCell.java @@ -0,0 +1,122 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +public class TableCell extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new TableCell(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new TableCell.Maker(); + } + + FontState fs; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + + protected int startOffset; + protected int width; + protected int height = 0; + + BlockArea blockArea; + + public TableCell(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:table-cell"; + } + + public void setStartOffset(int offset) { + startOffset = offset; + } + + public void setWidth(int width) { + this.width = width; + } + + public int layout(Area area) throws FOPException { + if (this.marker == BREAK_AFTER) { + return OK; + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + if (area instanceof BlockArea) { + area.end(); + } + + //if (this.isInListBody) { + //startIndent += bodyIndent + distanceBetweenStarts; + //} + + this.marker = 0; + + } + + if ((spaceBefore != 0) && (this.marker ==0)) { + area.addDisplaySpace(spaceBefore); + } + + this.blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, 0, + 0, 0, 0); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FObj fo = (FObj) children.elementAt(i); + fo.setIsInTableCell(); + fo.forceStartOffset(startOffset); + fo.forceWidth(width); + int status; + if ((status = fo.layout(blockArea)) != OK) { + this.marker = i; + if ((i == 0) && (status == AREA_FULL_NONE)) { + return AREA_FULL_NONE; + } else { + return AREA_FULL_SOME; + } + } + height += blockArea.getHeight(); + + } + blockArea.end(); + area.addChild(blockArea); + + return OK; + } + + public int getHeight() { + return height; + } +} diff --git a/src/org/apache/fop/fo/flow/TableColumn.java b/src/org/apache/fop/fo/flow/TableColumn.java new file mode 100644 index 000000000..6888bbef9 --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableColumn.java @@ -0,0 +1,34 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +public class TableColumn extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new TableColumn(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new TableColumn.Maker(); + } + + public TableColumn(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:table-column"; + } + + public int getColumnWidth() { + return this.properties.get("column-width").getLength().mvalue(); + } + + public int getColumnNumber() { + return 0; // not implemented yet + } +} diff --git a/src/org/apache/fop/fo/flow/TableRow.java b/src/org/apache/fop/fo/flow/TableRow.java new file mode 100644 index 000000000..4f2f27a6a --- /dev/null +++ b/src/org/apache/fop/fo/flow/TableRow.java @@ -0,0 +1,155 @@ +package org.apache.xml.fop.fo.flow; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.*; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Vector; + +public class TableRow extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new TableRow(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new TableRow.Maker(); + } + + FontState fs; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + + int widthOfCellsSoFar = 0; + int largestCellHeight = 0; + + Vector columns; + + BlockArea blockArea; + + public TableRow(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:table-row"; + } + + public void setColumns(Vector columns) { + this.columns = columns; + } + + public int layout(Area area) throws FOPException { + if (this.marker == BREAK_AFTER) { + return OK; + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize); + this.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + this.endIndent = + this.properties.get("end-indent").getLength().mvalue(); + this.spaceBefore = + this.properties.get("space-before.optimum").getLength().mvalue(); + this.spaceAfter = + this.properties.get("space-after.optimum").getLength().mvalue(); + if (area instanceof BlockArea) { + area.end(); + } + + //if (this.isInListBody) { + //startIndent += bodyIndent + distanceBetweenStarts; + //} + + this.marker = 0; + + } + + if ((spaceBefore != 0) && (this.marker ==0)) { + area.addDisplaySpace(spaceBefore); + } + + this.blockArea = + new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, 0, + 0, 0, 0); + blockArea.setPage(area.getPage()); + blockArea.start(); + + int numChildren = this.children.size(); + if (numChildren != columns.size()) { + System.err.println("WARNING: Number of children under table-row not equal to number of table-columns"); + return OK; + } + + for (int i = this.marker; i < numChildren; i++) { + TableCell cell = (TableCell) children.elementAt(i); + + //if (this.isInListBody) { + //fo.setIsInListBody(); + //fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + //fo.setBodyIndent(this.bodyIndent); + //} + + cell.setStartOffset(widthOfCellsSoFar); + int width = ((TableColumn) columns.elementAt(i)).getColumnWidth(); + + cell.setWidth(width); + widthOfCellsSoFar += width; + + int status; + if ((status = cell.layout(blockArea)) != OK) { + this.marker = i; + if ((i != 0) && (status == AREA_FULL_NONE)) { + status = AREA_FULL_SOME; + } + //blockArea.end(); + area.addChild(blockArea); + area.increaseHeight(blockArea.getHeight()); + return status; + } + + int h = cell.getHeight(); + blockArea.addDisplaySpace(-h); + if (h > largestCellHeight) { + largestCellHeight = h; + } + + } + + blockArea.end(); + area.addChild(blockArea); + area.addDisplaySpace(largestCellHeight); + area.increaseHeight(largestCellHeight); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + return OK; + } + + public int getAreaHeight() { + return blockArea.getHeight(); + } +} diff --git a/src/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java new file mode 100644 index 000000000..5e4d01dba --- /dev/null +++ b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java @@ -0,0 +1,50 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Hashtable; + +public class LayoutMasterSet extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new LayoutMasterSet(parent,propertyList); + } + } + + public static FObj.Maker maker() { + return new LayoutMasterSet.Maker(); + } + + private Hashtable layoutMasters; + private Root root; + + protected LayoutMasterSet(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:layout-master-set"; + + this.layoutMasters = new Hashtable(); + if (parent.getName().equals("fo:root")) { + this.root = (Root)parent; + root.setLayoutMasterSet(this); + } else { + throw + new FOPException("fo:layout-master-set must be child of fo:root, not " + + parent.getName()); + } + } + + protected void addLayoutMaster(String masterName, SimplePageMaster layoutMaster) { + this.layoutMasters.put(masterName, layoutMaster); + } + + protected SimplePageMaster getLayoutMaster(String masterName) { + return (SimplePageMaster)this.layoutMasters.get(masterName); + } +} diff --git a/src/org/apache/fop/fo/pagination/Makefile b/src/org/apache/fop/fo/pagination/Makefile new file mode 100644 index 000000000..ca1a2a346 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/Makefile @@ -0,0 +1,36 @@ + + +BASEDIR:=../../../../../.. +include $(BASEDIR)/Makefile.rules + +SUBDIRS= + + +SOURCES=LayoutMasterSet.java \ + PageSequence.java \ + RegionAfter.java \ + RegionBefore.java \ + RegionBody.java \ + Root.java \ + SequenceSpecification.java \ + SequenceSpecifier.java \ + SequenceSpecifierAlternating.java \ + SequenceSpecifierRepeating.java \ + SequenceSpecifierSingle.java \ + SimplePageMaster.java + + +CLASSES=$(SOURCES:.java=.class) + +all: $(CLASSES) allsubs + +clean: cleanme cleansubs + +cleanme: + rm -f *.class + +$(TARGETS:%=%subs): %subs : + for dir in $(SUBDIRS) ; do \ + (cd $$dir && pwd && $(MAKE) $(MFLAGS) $*) || exit 1 ; \ + done + diff --git a/src/org/apache/fop/fo/pagination/PageSequence.java b/src/org/apache/fop/fo/pagination/PageSequence.java new file mode 100644 index 000000000..eaae6366d --- /dev/null +++ b/src/org/apache/fop/fo/pagination/PageSequence.java @@ -0,0 +1,138 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.fo.flow.Flow; +import org.apache.xml.fop.fo.flow.StaticContent; +import org.apache.xml.fop.layout.Area; +import org.apache.xml.fop.layout.AreaContainer; +import org.apache.xml.fop.layout.AreaTree; +import org.apache.xml.fop.layout.Page; +import org.apache.xml.fop.layout.PageMaster; +import org.apache.xml.fop.layout.PageMasterFactory; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Hashtable; +import java.util.Vector; + +public class PageSequence extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new PageSequence(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new PageSequence.Maker(); + } + + protected Root root; + protected SequenceSpecification sequenceSpecification; + protected Flow flow; + protected StaticContent staticBefore; + protected StaticContent staticAfter; + protected LayoutMasterSet layoutMasterSet; + + protected Page currentPage; + protected int currentPageNumber = 0; + + protected PageSequence(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:page-sequence"; + + if (parent.getName().equals("fo:root")) { + this.root = (Root) parent; + this.root.addPageSequence(this); + } else { + throw + new FOPException("page-sequence must be child of root, not " + + parent.getName()); + } + layoutMasterSet = root.getLayoutMasterSet(); + } + + protected Page makePage(AreaTree areaTree) throws FOPException { + PageMaster pageMaster; + // layout this page sequence + + // while there is still stuff in the flow, ask the + // sequence-specification for a new page + + if (this.sequenceSpecification == null) { + throw new FOPException("page-sequence is missing an" + + " sequence-specification"); + } + + PageMasterFactory pmf = + this.sequenceSpecification.getFirstPageMasterFactory(); + + pageMaster = pmf.getNextPageMaster(); + + while (pageMaster == null) { + /* move on to next sequence specifier */ + pmf = pmf.getNext(); + if (pmf == null) { + throw new FOPException("out of sequence specifiers" + + " (FOP will eventually allow this)"); + } + pageMaster = pmf.getNextPageMaster(); + } + return pageMaster.makePage(areaTree); + } + + public void format(AreaTree areaTree) throws FOPException { + int status = OK; + + do { + currentPage = makePage(areaTree); + currentPage.setNumber(++this.currentPageNumber); + System.err.print(" [" + currentPageNumber); + if ((this.staticBefore != null) && + (currentPage.getBefore() != null)) { + AreaContainer beforeArea = currentPage.getBefore(); + this.staticBefore.layout(beforeArea); + } + if ((this.staticAfter != null) && + (currentPage.getAfter() != null)) { + AreaContainer afterArea = currentPage.getAfter(); + this.staticAfter.layout(afterArea); + } + if ((status == FORCE_PAGE_BREAK_EVEN) && + ((currentPageNumber % 2) == 1)) { + } else if ((status == FORCE_PAGE_BREAK_ODD) && + ((currentPageNumber % 2) == 0)) { + } else { + AreaContainer bodyArea = currentPage.getBody(); + status = this.flow.layout(bodyArea); + } + System.err.print("]"); + areaTree.addPage(currentPage); + } while (status != OK); + System.err.println(); + } + + public void setFlow(Flow flow) { + this.flow = flow; + } + + protected void setSequenceSpecification(SequenceSpecification sequenceSpecification) { + this.sequenceSpecification = sequenceSpecification; + sequenceSpecification.setLayoutMasterSet(this.layoutMasterSet); + } + + public void setStaticContent(String name, StaticContent staticContent) { + if (name.equals("xsl-before")) { + this.staticBefore = staticContent; + } else if (name.equals("xsl-after")) { + this.staticAfter = staticContent; + } else { + System.err.println("WARNING: this version of FOP only supports " + + "static-content in region-before and region-after"); + } + } +} diff --git a/src/org/apache/fop/fo/pagination/RegionAfter.java b/src/org/apache/fop/fo/pagination/RegionAfter.java new file mode 100644 index 000000000..afac8fd1a --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionAfter.java @@ -0,0 +1,54 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Region; +import org.apache.xml.fop.apps.FOPException; + +public class RegionAfter extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) throws FOPException { + return new RegionAfter(parent,propertyList); + } + } + + public static FObj.Maker maker() { + return new RegionAfter.Maker(); + } + + SimplePageMaster layoutMaster; + + protected RegionAfter(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:region-after"; + + if (parent.getName().equals("fo:simple-page-master")) { + this.layoutMaster = (SimplePageMaster) parent; + this.layoutMaster.setRegionAfter(this); + } else { + throw new FOPException("region-after must be child " + + "of simple-page-master, not " + + parent.getName()); + } + } + + Region makeRegion(int allocationRectangleXPosition, + int allocationRectangleYPosition, + int allocationRectangleWidth, + int allocationRectangleHeight) { + int marginTop = this.properties.get("margin-top").getLength().mvalue(); + int marginBottom = this.properties.get("margin-bottom").getLength().mvalue(); + int marginLeft = this.properties.get("margin-left").getLength().mvalue(); + int marginRight = this.properties.get("margin-right").getLength().mvalue(); + int extent = this.properties.get("extent").getLength().mvalue(); + + return new Region(allocationRectangleXPosition + marginLeft, + allocationRectangleYPosition - + allocationRectangleHeight + extent, + allocationRectangleWidth - marginLeft - + marginRight,extent); + } +} diff --git a/src/org/apache/fop/fo/pagination/RegionBefore.java b/src/org/apache/fop/fo/pagination/RegionBefore.java new file mode 100644 index 000000000..79994d00f --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionBefore.java @@ -0,0 +1,53 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Region; +import org.apache.xml.fop.apps.FOPException; + +public class RegionBefore extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) throws FOPException { + return new RegionBefore(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new RegionBefore.Maker(); + } + + SimplePageMaster layoutMaster; + + protected RegionBefore(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:region-before"; + + if (parent.getName().equals("fo:simple-page-master")) { + this.layoutMaster = (SimplePageMaster) parent; + this.layoutMaster.setRegionBefore(this); + } else { + throw new FOPException("region-before must be child of " + + "simple-page-master, not " + + parent.getName()); + } + } + + Region makeRegion(int allocationRectangleXPosition, + int allocationRectangleYPosition, + int allocationRectangleWidth, + int allocationRectangleHeight) { + int marginTop = this.properties.get("margin-top").getLength().mvalue(); + int marginBottom = this.properties.get("margin-bottom").getLength().mvalue(); + int marginLeft = this.properties.get("margin-left").getLength().mvalue(); + int marginRight = this.properties.get("margin-right").getLength().mvalue(); + int extent = this.properties.get("extent").getLength().mvalue(); + + return new Region(allocationRectangleXPosition + marginLeft, + allocationRectangleYPosition - marginTop, + allocationRectangleWidth - marginLeft - + marginRight, extent); + } +} diff --git a/src/org/apache/fop/fo/pagination/RegionBody.java b/src/org/apache/fop/fo/pagination/RegionBody.java new file mode 100644 index 000000000..dfeaa880a --- /dev/null +++ b/src/org/apache/fop/fo/pagination/RegionBody.java @@ -0,0 +1,50 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.Region; +import org.apache.xml.fop.apps.FOPException; + +public class RegionBody extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) throws FOPException { + return new RegionBody(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new RegionBody.Maker(); + } + + protected RegionBody(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:region-body"; + + if (parent.getName().equals("fo:simple-page-master")) { + ((SimplePageMaster) parent).setRegionBody(this); + } else { + throw new FOPException("region-body must be child of " + + "simple-page-master, not " + + parent.getName()); + } + } + + Region makeRegion(int allocationRectangleXPosition, + int allocationRectangleYPosition, + int allocationRectangleWidth, + int allocationRectangleHeight) { + int marginTop = this.properties.get("margin-top").getLength().mvalue(); + int marginBottom = this.properties.get("margin-bottom").getLength().mvalue(); + int marginLeft = this.properties.get("margin-left").getLength().mvalue(); + int marginRight = this.properties.get("margin-right").getLength().mvalue(); + + return new Region(allocationRectangleXPosition + marginLeft, + allocationRectangleYPosition - marginTop, + allocationRectangleWidth - marginLeft - + marginRight, allocationRectangleHeight - + marginTop - marginBottom); + } +} diff --git a/src/org/apache/fop/fo/pagination/Root.java b/src/org/apache/fop/fo/pagination/Root.java new file mode 100644 index 000000000..ecfb42ba3 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/Root.java @@ -0,0 +1,61 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.AreaTree; +import org.apache.xml.fop.apps.FOPException; + +// Java +import java.util.Vector; +import java.util.Enumeration; + +public class Root extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new Root(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new Root.Maker(); + } + + LayoutMasterSet layoutMasterSet; + Vector pageSequences; + + protected Root(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:root"; + + pageSequences = new Vector(); + if (parent != null) { + throw new FOPException("root must be root element"); + } + } + + public void addPageSequence(PageSequence pageSequence) { + this.pageSequences.addElement(pageSequence); + } + + public LayoutMasterSet getLayoutMasterSet() { + return this.layoutMasterSet; + } + + public void format(AreaTree areaTree) throws FOPException { + if (layoutMasterSet == null) { + throw new FOPException("No layout master set."); + } + Enumeration e = pageSequences.elements(); + while (e.hasMoreElements()) { + ((PageSequence) e.nextElement()).format(areaTree); + } + } + + public void setLayoutMasterSet(LayoutMasterSet layoutMasterSet) { + this.layoutMasterSet = layoutMasterSet; + } +} diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecification.java b/src/org/apache/fop/fo/pagination/SequenceSpecification.java new file mode 100644 index 000000000..abea78aa0 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecification.java @@ -0,0 +1,66 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.PageMasterFactory; +import org.apache.xml.fop.apps.FOPException; + +public class SequenceSpecification extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new SequenceSpecification(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new SequenceSpecification.Maker(); + } + + private PageSequence pageSequence; + private LayoutMasterSet layoutMasterSet; + private PageMasterFactory firstPMF; + private PageMasterFactory currentPMF; + + protected SequenceSpecification(FObj parent, + PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:sequence-specification"; + + if (parent.getName().equals("fo:page-sequence")) { + this.pageSequence = (PageSequence) parent; + this.pageSequence.setSequenceSpecification(this); + } else { + throw new FOPException("sequence-specification must be child" + + " of page-sequence, not " + + parent.getName()); + } + this.firstPMF = null; + this.currentPMF = null; + +} + + protected void addSequenceSpecifier(SequenceSpecifier sequenceSpecifier) { + if (this.firstPMF == null) { + this.firstPMF = sequenceSpecifier.getPageMasterFactory(); + } else { + this.currentPMF.setNext(sequenceSpecifier.getPageMasterFactory()); + } + this.currentPMF = sequenceSpecifier.getPageMasterFactory(); + } + + protected PageMasterFactory getFirstPageMasterFactory() { + return this.firstPMF; + } + + LayoutMasterSet getLayoutMasterSet() { + return this.layoutMasterSet; + } + + protected void setLayoutMasterSet(LayoutMasterSet layoutMasterSet) { + this.layoutMasterSet = layoutMasterSet; + } +} diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifier.java b/src/org/apache/fop/fo/pagination/SequenceSpecifier.java new file mode 100644 index 000000000..eef8433c5 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifier.java @@ -0,0 +1,13 @@ +package org.apache.xml.fop.fo.pagination; + +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.layout.PageMasterFactory; + +abstract public class SequenceSpecifier extends FObj { + + protected SequenceSpecifier(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + } + + public abstract PageMasterFactory getPageMasterFactory(); +} diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java new file mode 100644 index 000000000..f81bd1224 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierAlternating.java @@ -0,0 +1,65 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.PageMasterFactory; +import org.apache.xml.fop.layout.AlternatingPageMasterFactory; +import org.apache.xml.fop.layout.PageMaster; +import org.apache.xml.fop.apps.FOPException; + +public class SequenceSpecifierAlternating extends SequenceSpecifier { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new SequenceSpecifierAlternating(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new SequenceSpecifierAlternating.Maker(); + } + + private SequenceSpecification sequenceSpecification; + private LayoutMasterSet layoutMasterSet; + private AlternatingPageMasterFactory pageMasterFactory; + + protected SequenceSpecifierAlternating(FObj parent, + PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + PageMaster pf, pe, po; + + this.name = "fo:sequence-specifer-alternating"; + + if (parent.getName().equals("fo:sequence-specification")) { + this.sequenceSpecification = (SequenceSpecification) parent; + this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet(); + } else { + throw new FOPException("fo:sequence-specifier-alternating must be " + + " child of fo:sequence-specification, not " + + parent.getName()); + } + + String pageMasterFirst = this.properties.get("page-master-first").getString(); + String pageMasterOdd = this.properties.get("page-master-odd").getString(); + String pageMasterEven = this.properties.get("page-master-even").getString(); + + try { + pf = this.layoutMasterSet.getLayoutMaster(pageMasterFirst).getPageMaster(); + pe = this.layoutMasterSet.getLayoutMaster(pageMasterEven).getPageMaster(); + po = this.layoutMasterSet.getLayoutMaster(pageMasterOdd).getPageMaster(); + this.pageMasterFactory = new AlternatingPageMasterFactory(pf,pe,po); + } catch (java.lang.NullPointerException e) { + throw new FOPException("at least one of the page-master names in" + + " sequence-specifier-alternating is not in" + + " layout-master-set"); + } + this.sequenceSpecification.addSequenceSpecifier(this); + } + + public PageMasterFactory getPageMasterFactory() { + return this.pageMasterFactory; + } +} diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java new file mode 100644 index 000000000..1a5185137 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierRepeating.java @@ -0,0 +1,61 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.PageMasterFactory; +import org.apache.xml.fop.layout.RepeatingPageMasterFactory; +import org.apache.xml.fop.layout.PageMaster; +import org.apache.xml.fop.apps.FOPException; + +public class SequenceSpecifierRepeating extends SequenceSpecifier { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new SequenceSpecifierRepeating(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new SequenceSpecifierRepeating.Maker(); + } + + private SequenceSpecification sequenceSpecification; + private LayoutMasterSet layoutMasterSet; + private RepeatingPageMasterFactory pageMasterFactory; + + protected SequenceSpecifierRepeating(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + PageMaster pf, pr; + + this.name = "fo:sequence-specifer-repeating"; + + if (parent.getName().equals("fo:sequence-specification")) { + this.sequenceSpecification = (SequenceSpecification) parent; + this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet(); + } else { + throw new FOPException("sequence-specifier-repeating must be " + + "child of fo:sequence-specification, " + + "not " + parent.getName()); + } + + String pageMasterFirst = this.properties.get("page-master-first").getString(); + String pageMasterRepeating = this.properties.get("page-master-repeating").getString(); + try { + pf = this.layoutMasterSet.getLayoutMaster(pageMasterFirst).getPageMaster(); + pr = this.layoutMasterSet.getLayoutMaster(pageMasterRepeating).getPageMaster(); + this.pageMasterFactory = new RepeatingPageMasterFactory(pf, pr); + } catch (java.lang.NullPointerException e) { + throw new FOPException("at least one of the page-master names in " + + "sequence-specifier-repeating is not in " + + "layout-master-set"); + } + this.sequenceSpecification.addSequenceSpecifier(this); + } + + public PageMasterFactory getPageMasterFactory() { + return this.pageMasterFactory; + } +} diff --git a/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java b/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java new file mode 100644 index 000000000..bb46eff2f --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SequenceSpecifierSingle.java @@ -0,0 +1,59 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.PageMasterFactory; +import org.apache.xml.fop.layout.SinglePageMasterFactory; +import org.apache.xml.fop.layout.PageMaster; +import org.apache.xml.fop.apps.FOPException; + +public class SequenceSpecifierSingle extends SequenceSpecifier { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new SequenceSpecifierSingle(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new SequenceSpecifierSingle.Maker(); + } + + private SequenceSpecification sequenceSpecification; + private LayoutMasterSet layoutMasterSet; + private SinglePageMasterFactory pageMasterFactory; + + protected SequenceSpecifierSingle(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:sequence-specifer-single"; + + if (parent.getName().equals("fo:sequence-specification")) { + this.sequenceSpecification = (SequenceSpecification) parent; + this.layoutMasterSet = this.sequenceSpecification.getLayoutMasterSet(); + } else { + throw new FOPException("sequence-specifier-single must be " + + "child of fo:sequence-specification, " + + "not " + parent.getName()); + } + + String pageMasterName = this.properties.get("page-master-name").getString(); + try { + this.pageMasterFactory = new SinglePageMasterFactory(this.layoutMasterSet.getLayoutMaster(pageMasterName).getPageMaster()); + } catch (java.lang.NullPointerException e) { + throw new FOPException("page-master-name " + + pageMasterName + " must be in layout-master-set"); + } + this.sequenceSpecification.addSequenceSpecifier(this); + } + + public PageMasterFactory getPageMasterFactory() { + return this.pageMasterFactory; + } + + public String getPageMasterName() { + return this.properties.get("page-master-name").getString(); + } +} diff --git a/src/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/org/apache/fop/fo/pagination/SimplePageMaster.java new file mode 100644 index 000000000..7f0a38841 --- /dev/null +++ b/src/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -0,0 +1,89 @@ +package org.apache.xml.fop.fo.pagination; + +// FOP +import org.apache.xml.fop.fo.*; +import org.apache.xml.fop.fo.properties.*; +import org.apache.xml.fop.layout.PageMaster; +import org.apache.xml.fop.layout.Region; +import org.apache.xml.fop.apps.FOPException; + +public class SimplePageMaster extends FObj { + + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, PropertyList propertyList) + throws FOPException { + return new SimplePageMaster(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new SimplePageMaster.Maker(); + } + + RegionBody regionBody; + RegionBefore regionBefore; + RegionAfter regionAfter; + + LayoutMasterSet layoutMasterSet; + PageMaster pageMaster; + + protected SimplePageMaster(FObj parent, PropertyList propertyList) + throws FOPException { + super(parent, propertyList); + this.name = "fo:simple-page-master"; + + if (parent.getName().equals("fo:layout-master-set")) { + this.layoutMasterSet = (LayoutMasterSet) parent; + String pm = this.properties.get("page-master-name").getString(); + if (pm == null) { + System.err.println("WARNING: simple-page-master does not have " + + "a page-master-name and so is being ignored"); + } else { + this.layoutMasterSet.addLayoutMaster(pm, this); + } + } else { + throw new FOPException("fo:simple-page-master must be child " + + "of fo:layout-master-set, not " + + parent.getName()); + } + } + + protected void end() { + int pageWidth = this.properties.get("page-width").getLength().mvalue(); + int pageHeight = this.properties.get("page-height").getLength().mvalue(); + + int marginTop = this.properties.get("margin-top").getLength().mvalue(); + int marginBottom = this.properties.get("margin-bottom").getLength().mvalue(); + int marginLeft = this.properties.get("margin-left").getLength().mvalue(); + int marginRight = this.properties.get("margin-right").getLength().mvalue(); + + int contentRectangleXPosition = marginLeft; + int contentRectangleYPosition = pageHeight - marginTop; + int contentRectangleWidth = pageWidth - marginLeft - marginRight; + int contentRectangleHeight = pageHeight - marginTop - marginBottom; + + this.pageMaster = new PageMaster(pageWidth, pageHeight); + this.pageMaster.addBody(this.regionBody.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + + if (this.regionBefore != null) + this.pageMaster.addBefore(this.regionBefore.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + if (this.regionAfter != null) + this.pageMaster.addAfter(this.regionAfter.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + } + + PageMaster getPageMaster() { + return this.pageMaster; + } + + protected void setRegionAfter(RegionAfter region) { + this.regionAfter = region; + } + + protected void setRegionBefore(RegionBefore region) { + this.regionBefore = region; + } + + protected void setRegionBody(RegionBody region) { + this.regionBody = region; + } +} |