diff options
Diffstat (limited to 'src/org/apache')
32 files changed, 1155 insertions, 612 deletions
diff --git a/src/org/apache/fop/apps/CommandLineStarter.java b/src/org/apache/fop/apps/CommandLineStarter.java index e3db06fe8..45c01940f 100644 --- a/src/org/apache/fop/apps/CommandLineStarter.java +++ b/src/org/apache/fop/apps/CommandLineStarter.java @@ -26,7 +26,6 @@ import org.apache.fop.configuration.Configuration; * * Modified to use new streaming API by Mark Lillywhite, mark-fop@inomial.com */ - public class CommandLineStarter extends Starter { CommandLineOptions commandLineOptions; diff --git a/src/org/apache/fop/area/Block.java b/src/org/apache/fop/area/Block.java index 9073c23a7..5dcbb7df4 100644 --- a/src/org/apache/fop/area/Block.java +++ b/src/org/apache/fop/area/Block.java @@ -10,6 +10,7 @@ package org.apache.fop.area; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Iterator; import java.awt.geom.Rectangle2D; // block areas hold either more block areas or line @@ -54,6 +55,18 @@ public class Block extends BlockParent implements Serializable { children.add(line); } + public MinOptMax getContentBPD() { + MinOptMax bpd = new MinOptMax(); + if(children != null) { + for(Iterator iter = children.iterator(); iter.hasNext(); ) { + Area area = (Area)iter.next(); + MinOptMax mom = area.getContentBPD(); + bpd.add(mom); + } + } + return bpd; + } + public int getPositioning() { return positioning; } diff --git a/src/org/apache/fop/area/LineArea.java b/src/org/apache/fop/area/LineArea.java index 5da4fee09..7496dd10a 100644 --- a/src/org/apache/fop/area/LineArea.java +++ b/src/org/apache/fop/area/LineArea.java @@ -39,6 +39,10 @@ public class LineArea extends Area { return lineHeight; } + public MinOptMax getContentBPD() { + return new MinOptMax(lineHeight); + } + public void addInlineArea(InlineArea area) { inlineAreas.add(area); } diff --git a/src/org/apache/fop/area/inline/Stretch.java b/src/org/apache/fop/area/inline/Stretch.java index fee1a3333..ed1ba2254 100644 --- a/src/org/apache/fop/area/inline/Stretch.java +++ b/src/org/apache/fop/area/inline/Stretch.java @@ -7,11 +7,21 @@ package org.apache.fop.area.inline; +import org.apache.fop.area.MinOptMax; + public class Stretch extends InlineArea { + MinOptMax contentIPD; - // min size - // set size - // get size - // height 0 + public void setAllocationIPD(MinOptMax mom) { + contentIPD = mom; + } + public MinOptMax getAllocationIPD() { + // Should also account for any borders and padding in the + // inline progression dimension + if (contentIPD != null) { + return contentIPD; + } + return super.getAllocationIPD(); + } } diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java index ac18fb1c7..a54dce5be 100644 --- a/src/org/apache/fop/fo/FOText.java +++ b/src/org/apache/fop/fo/FOText.java @@ -19,6 +19,7 @@ import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.TextLayoutManager; import java.util.NoSuchElementException; +import java.util.List; /** * a text node in the formatting object tree @@ -41,21 +42,21 @@ public class FOText extends FObj { super(null); this.start = 0; this.ca = new char[e - s]; - System.arraycopy(chars, s, ca, 0, e-s); + System.arraycopy(chars, s, ca, 0, e - s); this.length = e - s; textInfo = ti; } public boolean willCreateArea() { - if (textInfo.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE - && length > 0) { + if (textInfo.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE && + length > 0) { return true; } for (int i = start; i < start + length; i++) { char ch = ca[i]; - if (!((ch == ' ') || (ch == '\n') || (ch == '\r') - || (ch == '\t'))) { // whitespace + if (!((ch == ' ') || (ch == '\n') || (ch == '\r') || + (ch == '\t'))) { // whitespace return true; } } @@ -65,61 +66,59 @@ public class FOText extends FObj { // Just to keep PageNumber and PageNumber citation happy for now. // The real code is moved to TextLayoutManager! - public static int addText(BlockArea ba, FontState fontState, float red, - float green, float blue, int wrapOption, - LinkSet ls, int whiteSpaceCollapse, - char data[], int start, int end, - TextState textState, int vAlign) { - return 0; + public static int addText(BlockArea ba, FontState fontState, + float red, float green, float blue, int wrapOption, + LinkSet ls, int whiteSpaceCollapse, char data[], + int start, int end, TextState textState, int vAlign) { + return 0; } - public LayoutManager getLayoutManager() { - // What if nothing left (length=0)? - if (length < ca.length) { - char[] tmp = ca; - ca = new char[length]; - System.arraycopy(tmp, 0, ca, 0, length); - } - return new TextLayoutManager(this, ca, textInfo); + public void addLayoutManager(List list) { + // What if nothing left (length=0)? + if (length < ca.length) { + char[] tmp = ca; + ca = new char[length]; + System.arraycopy(tmp, 0, ca, 0, length); + } + list.add(new TextLayoutManager(this, ca, textInfo)); } public CharIterator charIterator() { - return new TextCharIterator(); + return new TextCharIterator(); } private class TextCharIterator extends AbstractCharIterator { - int curIndex = 0; - public boolean hasNext() { - return (curIndex < length); - } - - public char nextChar() { - if (curIndex < length) { - // Just a char class? Don't actually care about the value! - return ca[curIndex++]; - } - else throw new NoSuchElementException(); - } - - public void remove() { - if (curIndex>0 && curIndex < length) { - // copy from curIndex to end to curIndex-1 - System.arraycopy(ca, curIndex, ca, curIndex-1, - length-curIndex); - length--; - curIndex--; - } - else if (curIndex == length) { - curIndex = --length; - } - } - - - public void replaceChar(char c) { - if (curIndex>0 && curIndex <= length) { - ca[curIndex-1]=c; - } - } + int curIndex = 0; + public boolean hasNext() { + return (curIndex < length); + } + + public char nextChar() { + if (curIndex < length) { + // Just a char class? Don't actually care about the value! + return ca[curIndex++]; + } else + throw new NoSuchElementException(); + } + + public void remove() { + if (curIndex > 0 && curIndex < length) { + // copy from curIndex to end to curIndex-1 + System.arraycopy(ca, curIndex, ca, curIndex - 1, + length - curIndex); + length--; + curIndex--; + } else if (curIndex == length) { + curIndex = --length; + } + } + + + public void replaceChar(char c) { + if (curIndex > 0 && curIndex <= length) { + ca[curIndex - 1] = c; + } + } } diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java index e6bb8205c..01ae205d4 100644 --- a/src/org/apache/fop/fo/FObj.java +++ b/src/org/apache/fop/fo/FObj.java @@ -26,6 +26,7 @@ import org.xml.sax.Attributes; import java.util.Iterator; import java.util.ListIterator; import java.util.ArrayList; +import java.util.List; import java.util.HashMap; /** @@ -53,7 +54,7 @@ public class FObj extends FONode { */ protected int marker = START; - protected ArrayList children = new ArrayList(); // made public for searching for id's + protected ArrayList children = new ArrayList(); // made public for searching for id's protected boolean isInTableCell = false; @@ -75,7 +76,7 @@ public class FObj extends FONode { super(parent); markers = new HashMap(); if (parent instanceof FObj) - this.areaClass = ((FObj)parent).areaClass; + this.areaClass = ((FObj) parent).areaClass; } public void setName(String str) { @@ -85,14 +86,16 @@ public class FObj extends FONode { protected static PropertyListBuilder plb = null; protected PropertyListBuilder getListBuilder() { - if(plb == null) { + if (plb == null) { plb = new PropertyListBuilder(); plb.addList(FOPropertyMapping.getGenericMappings()); - for (Iterator iter = FOPropertyMapping.getElementMappings().iterator(); - iter.hasNext(); ) { - String elem = (String)iter.next(); - plb.addElementList(elem, FOPropertyMapping.getElementMapping(elem)); + for (Iterator iter = + FOPropertyMapping.getElementMappings().iterator(); + iter.hasNext();) { + String elem = (String) iter.next(); + plb.addElementList(elem, + FOPropertyMapping.getElementMapping(elem)); } } return plb; @@ -106,22 +109,22 @@ public class FObj extends FONode { public void handleAttrs(Attributes attlist) throws FOPException { String uri = "http://www.w3.org/1999/XSL/Format"; FONode par = parent; - while(par != null && !(par instanceof FObj)) { + while (par != null && !(par instanceof FObj)) { par = par.parent; } PropertyList props = null; - if(par != null) { - props = ((FObj)par).properties; + if (par != null) { + props = ((FObj) par).properties; } - properties = - getListBuilder().makeList(uri, name, attlist, - props, (FObj)par); + properties = getListBuilder().makeList(uri, name, attlist, props, + (FObj) par); properties.setFObj(this); this.propMgr = makePropertyManager(properties); setWritingMode(); } - protected PropertyManager makePropertyManager(PropertyList propertyList) { + protected PropertyManager makePropertyManager( + PropertyList propertyList) { return new PropertyManager(propertyList); } @@ -158,15 +161,16 @@ public class FObj extends FONode { * @param idReferences the id to remove */ public void removeID(IDReferences idReferences) { - if (((FObj)this).properties.get("id") == null - || ((FObj)this).properties.get("id").getString() == null) + if (((FObj) this).properties.get("id") == null || + ((FObj) this).properties.get("id").getString() == null) return; - idReferences.removeID(((FObj)this).properties.get("id").getString()); + idReferences.removeID( + ((FObj) this).properties.get("id").getString()); int numChildren = this.children.size(); for (int i = 0; i < numChildren; i++) { - FONode child = (FONode)children.get(i); + FONode child = (FONode) children.get(i); if ((child instanceof FObj)) { - ((FObj)child).removeID(idReferences); + ((FObj) child).removeID(idReferences); } } } @@ -189,18 +193,19 @@ public class FObj extends FONode { protected void setWritingMode() { FObj p; FONode parent; - for (p = this; - !p.generatesReferenceAreas() && (parent = p.getParent()) != null && (parent instanceof FObj); - p = (FObj)parent); - this.properties.setWritingMode(p.getProperty("writing-mode").getEnum()); + for (p = this; !p.generatesReferenceAreas() && + (parent = p.getParent()) != null && + (parent instanceof FObj); p = (FObj) parent) + ; + this.properties.setWritingMode( + p.getProperty("writing-mode").getEnum()); } /** * Return a LayoutManager responsible for laying out this FObj's content. * Must override in subclasses if their content can be laid out. */ - public LayoutManager getLayoutManager() { - return null; + public void addLayoutManager(List list) { } /** @@ -208,7 +213,7 @@ public class FObj extends FONode { * @return A ListIterator. */ public ListIterator getChildren() { - return children.listIterator(); + return children.listIterator(); } /** @@ -219,11 +224,11 @@ public class FObj extends FONode { * this FObj. */ public ListIterator getChildren(FONode childNode) { - int i = children.indexOf(childNode); - if (i >= 0) { - return children.listIterator(i); - } - else return null; + int i = children.indexOf(childNode); + if (i >= 0) { + return children.listIterator(i); + } else + return null; } public void setIsInTableCell() { @@ -231,20 +236,20 @@ public class FObj extends FONode { // made recursive by Eric Schaeffer for (int i = 0; i < this.children.size(); i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.setIsInTableCell(); } } } - + public void forceStartOffset(int offset) { - this.forcedStartOffset = offset; + this.forcedStartOffset = offset; // made recursive by Eric Schaeffer for (int i = 0; i < this.children.size(); i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.forceStartOffset(offset); } } @@ -255,8 +260,8 @@ public class FObj extends FONode { // made recursive by Eric Schaeffer for (int i = 0; i < this.children.size(); i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.forceWidth(width); } } @@ -267,8 +272,8 @@ public class FObj extends FONode { int numChildren = this.children.size(); for (int i = 0; i < numChildren; i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.resetMarker(); } } @@ -277,7 +282,7 @@ public class FObj extends FONode { public void setWidows(int wid) { widows = wid; } - + public void setOrphans(int orph) { orphans = orph; } @@ -290,8 +295,8 @@ public class FObj extends FONode { this.linkSet = linkSet; for (int i = 0; i < this.children.size(); i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.setLinkSet(linkSet); } } @@ -317,7 +322,8 @@ public class FObj extends FONode { else if (children.isEmpty()) return snapshot; else - return ((FObj)children.get(this.marker)).getMarkerSnapshot(snapshot); + return ( (FObj) children.get(this.marker)).getMarkerSnapshot( + snapshot); } /** @@ -327,7 +333,7 @@ public class FObj extends FONode { * @param snapshot the ArrayList of saved markers (Integers) */ public void rollback(ArrayList snapshot) { - this.marker = ((Integer)snapshot.get(0)).intValue(); + this.marker = ((Integer) snapshot.get(0)).intValue(); snapshot.remove(0); if (this.marker == START) { @@ -345,12 +351,12 @@ public class FObj extends FONode { for (int i = this.marker + 1; i < numChildren; i++) { Object obj = this.children.get(i); - if(obj instanceof FObj) { - FObj child = (FObj)obj; + if (obj instanceof FObj) { + FObj child = (FObj) obj; child.resetMarker(); } } - ((FObj)children.get(this.marker)).rollback(snapshot); + ((FObj) children.get(this.marker)).rollback(snapshot); } @@ -359,10 +365,9 @@ public class FObj extends FONode { if (!markers.containsKey(mcname) && children.isEmpty()) { markers.put(mcname, marker); } else { - log.error("fo:marker must be an initial child," - + "and 'marker-class-name' must be unique for same parent"); - throw new FOPException("fo:marker must be an initial child," - + "and 'marker-class-name' must be unique for same parent"); + log.error("fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent"); + throw new FOPException( + "fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent"); } } diff --git a/src/org/apache/fop/fo/FObjMixed.java b/src/org/apache/fop/fo/FObjMixed.java index 75f736bd7..f2a180f65 100644 --- a/src/org/apache/fop/fo/FObjMixed.java +++ b/src/org/apache/fop/fo/FObjMixed.java @@ -14,6 +14,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.apps.StreamRenderer; import org.apache.fop.datatypes.ColorType; +import java.util.List; /** * base class for representation of mixed content formatting objects @@ -21,37 +22,48 @@ import org.apache.fop.datatypes.ColorType; */ public class FObjMixed extends FObj { TextInfo textInfo = null; - protected FontInfo fontInfo=null; + protected FontInfo fontInfo = null; public FObjMixed(FONode parent) { super(parent); } public void setStreamRenderer(StreamRenderer st) { - fontInfo = st.getFontInfo(); + fontInfo = st.getFontInfo(); } - protected void addCharacters(char data[], int start, int length) { - if(textInfo == null) { - textInfo = new TextInfo(); + public void addLayoutManager(List lms) { + // set start and end properties for this element, id, etc. + int numChildren = this.children.size(); + for (int i = 0; i < numChildren; i++) { + Object o = children.get(i); + if (o instanceof FObj) { + FObj fo = (FObj) o; + fo.addLayoutManager(lms); + } + } + } - try { - textInfo.fs = propMgr.getFontState(fontInfo); - } catch (FOPException fopex) { - log.error("Error setting FontState for characters: " + - fopex.getMessage()); - } + protected void addCharacters(char data[], int start, int length) { + if (textInfo == null) { + textInfo = new TextInfo(); + + try { + textInfo.fs = propMgr.getFontState(fontInfo); + } catch (FOPException fopex) { + log.error("Error setting FontState for characters: " + + fopex.getMessage()); + } ColorType c = getProperty("color").getColorType(); textInfo.color = c; textInfo.verticalAlign = - getProperty("vertical-align").getEnum(); + getProperty("vertical-align").getEnum(); - textInfo.wrapOption = - getProperty("wrap-option").getEnum(); + textInfo.wrapOption = getProperty("wrap-option").getEnum(); textInfo.whiteSpaceCollapse = - getProperty("white-space-collapse").getEnum(); + getProperty("white-space-collapse").getEnum(); } @@ -82,7 +94,7 @@ public class FObjMixed extends FObj { int numChildren = this.children.size(); for (int i = this.marker; i < numChildren; i++) { - FONode fo = (FONode)children.get(i); + FONode fo = (FONode) children.get(i); Status status; if ((status = fo.layout(area)).isIncomplete()) { this.marker = i; @@ -93,7 +105,7 @@ public class FObjMixed extends FObj { } public CharIterator charIterator() { - return new RecursiveCharIterator(this); + return new RecursiveCharIterator(this); } } diff --git a/src/org/apache/fop/fo/flow/BasicLink.java b/src/org/apache/fop/fo/flow/BasicLink.java index 5b8344341..938c43dcc 100644 --- a/src/org/apache/fop/fo/flow/BasicLink.java +++ b/src/org/apache/fop/fo/flow/BasicLink.java @@ -17,6 +17,7 @@ import org.apache.fop.datatypes.ColorType; // Java import java.util.Enumeration; import java.awt.Rectangle; +import java.util.List; public class BasicLink extends Inline { @@ -24,6 +25,11 @@ public class BasicLink extends Inline { super(parent); } + // add start and end properties for the link + public void addLayoutManager(List lms) { + super.addLayoutManager(lms); + } + public Status layout(Area area) throws FOPException { String destination; int linkType; diff --git a/src/org/apache/fop/fo/flow/BidiOverride.java b/src/org/apache/fop/fo/flow/BidiOverride.java index 208f2ae0f..d7123ed39 100644 --- a/src/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/org/apache/fop/fo/flow/BidiOverride.java @@ -9,21 +9,48 @@ package org.apache.fop.fo.flow; // FOP import org.apache.fop.fo.*; -import org.apache.fop.layout.*; +import org.apache.fop.layout.AuralProps; +import org.apache.fop.layout.RelativePositionProps; import org.apache.fop.fo.flow.*; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.AreaTree; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.Word; + +import java.util.List; +import java.util.ArrayList; + /** */ -public class BidiOverride extends ToBeImplementedElement { +public class BidiOverride extends FObjMixed { public BidiOverride(FONode parent) { super(parent); } - public Status layout(Area area) throws FOPException { + public void addLayoutManager(List list) { + if (false) { + super.addLayoutManager(list); + } else { + ArrayList childList = new ArrayList(); + super.addLayoutManager(childList); + for (int count = childList.size() - 1; count >= 0; count--) { + LayoutManager lm = (LayoutManager) childList.get(count); + if (lm.generatesInlineAreas()) { + list.add( new BidiLayoutManager(this, + (LeafNodeLayoutManager) lm)); + } else { + list.add(lm); + } + } + } + } + + public void setup() { // Common Aural Properties AuralProps mAurProps = propMgr.getAuralProps(); @@ -46,6 +73,37 @@ public class BidiOverride extends ToBeImplementedElement { // this.properties.get("unicode-bidi"); // this.properties.get("word-spacing"); - return super.layout(area); + } + + /** + * If this bidi has a different writing mode direction + * ltr or rtl than its parent writing mode then this + * reverses the inline areas (at the character level). + */ + class BidiLayoutManager extends LeafNodeLayoutManager { + List childs; + + BidiLayoutManager(FObj obj, LeafNodeLayoutManager cLM) { + super(obj); + childs = new ArrayList(); + for (int count = cLM.size() - 1; count >= 0; count--) { + InlineArea ia = cLM.get(count); + if (ia instanceof Word) { + // reverse word + Word word = (Word) ia; + StringBuffer sb = new StringBuffer(word.getWord()); + word.setWord(sb.reverse().toString()); + } + childs.add(ia); + } + } + + public int size() { + return childs.size(); + } + + public InlineArea get(int index) { + return (InlineArea) childs.get(index); + } } } diff --git a/src/org/apache/fop/fo/flow/Block.java b/src/org/apache/fop/fo/flow/Block.java index d234cc159..1bf604eb8 100644 --- a/src/org/apache/fop/fo/flow/Block.java +++ b/src/org/apache/fop/fo/flow/Block.java @@ -20,6 +20,8 @@ import org.apache.fop.apps.StreamRenderer; import org.xml.sax.Attributes; +import java.util.List; + /* Modified by Mark Lillywhite mark-fop@inomial.com. The changes here are based on memory profiling and do not change functionality. @@ -31,9 +33,9 @@ import org.xml.sax.Attributes; the reference to BlockArea was made local, the required information is now stored (instead of a reference to the complex BlockArea object) and it appears that there are a lot of changes in this file, in fact - there are only a few sematic changes; mostly I just got rid of + there are only a few sematic changes; mostly I just got rid of "this." from blockArea since BlockArea is now local. - */ + */ public class Block extends FObjMixed { @@ -76,10 +78,13 @@ public class Block extends FObjMixed { public void handleAttrs(Attributes attlist) throws FOPException { super.handleAttrs(attlist); this.span = this.properties.get("span").getEnum(); - this.wsTreatment = this.properties.get("white-space-treatment").getEnum(); - this.bWScollapse = (this.properties.get("white-space-collapse").getEnum() == - Constants.TRUE); - this.lfTreatment = this.properties.get("linefeed-treatment").getEnum(); + this.wsTreatment = + this.properties.get("white-space-treatment").getEnum(); + this.bWScollapse = + (this.properties.get("white-space-collapse").getEnum() + == Constants.TRUE); + this.lfTreatment = + this.properties.get("linefeed-treatment").getEnum(); } public Status layout(Area area) throws FOPException { @@ -114,7 +119,8 @@ public class Block extends FObjMixed { MarginProps mProps = propMgr.getMarginProps(); // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); // this.properties.get("break-after"); // this.properties.get("break-before"); @@ -145,29 +151,30 @@ public class Block extends FObjMixed { // this.properties.get("z-index"); this.align = this.properties.get("text-align").getEnum(); - this.alignLast = this.properties.get("text-align-last").getEnum(); + this.alignLast = + this.properties.get("text-align-last").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(); + 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(); this.keepWithNext = - this.properties.get("keep-with-next").getEnum(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); + this.properties.get("keep-with-next").getEnum(); + this.backgroundColor = this.properties.get( + "background-color").getColorType(); this.blockWidows = - this.properties.get("widows").getNumber().intValue(); + this.properties.get("widows").getNumber().intValue(); this.blockOrphans = - this.properties.get("orphans").getNumber().intValue(); + this.properties.get("orphans").getNumber().intValue(); this.id = this.properties.get("id").getString(); @@ -189,9 +196,9 @@ public class Block extends FObjMixed { int numChildren = this.children.size(); for (int i = 0; i < numChildren; i++) { - FONode fo = (FONode)children.get(i); + FONode fo = (FONode) children.get(i); if (fo instanceof FOText) { - if (((FOText)fo).willCreateArea()) { + if (((FOText) fo).willCreateArea()) { //fo.setWidows(blockWidows); break; } else { @@ -206,9 +213,9 @@ public class Block extends FObjMixed { } for (int i = numChildren - 1; i >= 0; i--) { - FONode fo = (FONode)children.get(i); + FONode fo = (FONode) children.get(i); if (fo instanceof FOText) { - if (((FOText)fo).willCreateArea()) { + if (((FOText) fo).willCreateArea()) { //fo.setOrphans(blockOrphans); break; } @@ -232,11 +239,10 @@ public class Block extends FObjMixed { } int spaceLeft = area.spaceLeft(); - blockArea = - new BlockArea(propMgr.getFontState(area.getFontInfo()), - area.getAllocationWidth(), area.spaceLeft(), - startIndent, endIndent, textIndent, align, - alignLast, lineHeight); + blockArea = new BlockArea( propMgr.getFontState(area.getFontInfo()), + area.getAllocationWidth(), area.spaceLeft(), + startIndent, endIndent, textIndent, align, alignLast, + lineHeight); blockArea.setGeneratedBy(this); this.areasGenerated++; if (this.areasGenerated == 1) @@ -246,9 +252,9 @@ public class Block extends FObjMixed { // markers //if (this.hasMarkers()) - //blockArea.addMarkers(this.getMarkers()); + //blockArea.addMarkers(this.getMarkers()); - blockArea.setParent(area); // BasicLink needs it + blockArea.setParent(area); // BasicLink needs it blockArea.setPage(area.getPage()); blockArea.setBackgroundColor(backgroundColor); blockArea.setBorderAndPadding(propMgr.getBorderAndPadding()); @@ -262,7 +268,7 @@ public class Block extends FObjMixed { int numChildren = this.children.size(); for (int i = this.marker; i < numChildren; i++) { - FONode fo = (FONode)children.get(i); + FONode fo = (FONode) children.get(i); Status status; if ((status = fo.layout(blockArea)).isIncomplete()) { this.marker = i; @@ -280,14 +286,15 @@ public class Block extends FObjMixed { if ((i != 0)) { status = new Status(Status.AREA_FULL_SOME); area.addChild(blockArea); - area.setMaxHeight(area.getMaxHeight() - spaceLeft - + blockArea.getMaxHeight()); + area.setMaxHeight(area.getMaxHeight() - + spaceLeft + blockArea.getMaxHeight()); area.increaseHeight(blockArea.getHeight()); - area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); + area.setAbsoluteHeight( + blockArea.getAbsoluteHeight()); anythingLaidOut = true; return status; - } else // i == 0 nothing was laid out.. + } else // i == 0 nothing was laid out.. { anythingLaidOut = false; return status; @@ -296,8 +303,8 @@ public class Block extends FObjMixed { // blockArea.end(); area.addChild(blockArea); - area.setMaxHeight(area.getMaxHeight() - spaceLeft - + blockArea.getMaxHeight()); + area.setMaxHeight(area.getMaxHeight() - spaceLeft + + blockArea.getMaxHeight()); area.increaseHeight(blockArea.getHeight()); area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); anythingLaidOut = true; @@ -308,8 +315,8 @@ public class Block extends FObjMixed { blockArea.end(); - area.setMaxHeight(area.getMaxHeight() - spaceLeft - + blockArea.getMaxHeight()); + area.setMaxHeight(area.getMaxHeight() - spaceLeft + + blockArea.getMaxHeight()); area.addChild(blockArea); @@ -327,8 +334,8 @@ public class Block extends FObjMixed { } // This is not needed any more and it consumes a LOT // of memory. So we release it for the GC. - areaHeight= blockArea.getHeight(); - contentWidth= blockArea.getContentWidth(); + areaHeight = blockArea.getHeight(); + contentWidth = blockArea.getContentWidth(); // no break if last in area tree, or trailing in context // area @@ -359,7 +366,7 @@ public class Block extends FObjMixed { * Return the content width of the boxes generated by this FO. */ public int getContentWidth() { - return contentWidth; // getAllocationWidth()?? + return contentWidth; // getAllocationWidth()?? } @@ -367,26 +374,25 @@ public class Block extends FObjMixed { return this.span; } - public LayoutManager getLayoutManager() { -BlockLayoutManager blm = new BlockLayoutManager(this); -TextInfo ti = new TextInfo(); + public void addLayoutManager(List list) { + BlockLayoutManager blm = new BlockLayoutManager(this); + TextInfo ti = new TextInfo(); - try { - ti.fs = propMgr.getFontState(fontInfo); - } catch (FOPException fopex) { - log.error("Error setting FontState for characters: " + - fopex.getMessage()); - } - ti.lineHeight = this.lineHeight; + try { + ti.fs = propMgr.getFontState(fontInfo); + } catch (FOPException fopex) { + log.error("Error setting FontState for characters: " + + fopex.getMessage()); + } + ti.lineHeight = this.lineHeight; - ColorType c = getProperty("color").getColorType(); - ti.color = c; + ColorType c = getProperty("color").getColorType(); + ti.color = c; - ti.verticalAlign = - getProperty("vertical-align").getEnum(); + ti.verticalAlign = getProperty("vertical-align").getEnum(); -blm.setBlockTextInfo(ti); - return blm; + blm.setBlockTextInfo(ti); + list.add(blm); } public boolean generatesInlineAreas() { @@ -394,144 +400,142 @@ blm.setBlockTextInfo(ti); } public void addChild(FONode child) { - // Handle whitespace based on values of properties - // Handle a sequence of inline-producing children in - // one pass - if (((FObj)child).generatesInlineAreas()) { - if (firstInlineChild == null) { - firstInlineChild = child; - } - // lastInlineChild = children.size(); - } - else { - // Handle whitespace in preceeding inline areas if any - handleWhiteSpace(); - } - super.addChild(child); + // Handle whitespace based on values of properties + // Handle a sequence of inline-producing children in + // one pass + if (((FObj) child).generatesInlineAreas()) { + if (firstInlineChild == null) { + firstInlineChild = child; + } + // lastInlineChild = children.size(); + } else { + // Handle whitespace in preceeding inline areas if any + handleWhiteSpace(); + } + super.addChild(child); } public void end() { - handleWhiteSpace(); + handleWhiteSpace(); } private void handleWhiteSpace() { - log.debug("fo:block: handleWhiteSpace"); - if (firstInlineChild != null) { - boolean bInWS=false; - boolean bPrevWasLF=false; - RecursiveCharIterator charIter = - new RecursiveCharIterator(this, firstInlineChild); - LFchecker lfCheck = new LFchecker(charIter); - - while (charIter.hasNext()) { - switch (CharUtilities.classOf(charIter.nextChar())) { - case CharUtilities.XMLWHITESPACE: - /* Some kind of whitespace character, except linefeed. */ - boolean bIgnore=false; - - switch (wsTreatment) { - case Constants.IGNORE: - bIgnore=true; - break; - case Constants.IGNORE_IF_BEFORE_LINEFEED: - bIgnore = lfCheck.nextIsLF(); - break; - case Constants.IGNORE_IF_SURROUNDING_LINEFEED: - bIgnore = (bPrevWasLF || lfCheck.nextIsLF()); - break; - case Constants.IGNORE_IF_AFTER_LINEFEED: - bIgnore = bPrevWasLF; - break; - } - // Handle ignore - if (bIgnore) { - charIter.remove(); - } - else if (bWScollapse) { - if (bInWS || (lfTreatment == Constants.PRESERVE && - (bPrevWasLF || lfCheck.nextIsLF()))) { - charIter.remove(); - } - else { - bInWS = true; - } - } - break; - - case CharUtilities.LINEFEED: - /* A linefeed */ - lfCheck.reset(); - bPrevWasLF=true; // for following whitespace - - switch (lfTreatment) { - case Constants.IGNORE: - charIter.remove(); - break; - case Constants.TREAT_AS_SPACE: - if (bInWS) { - // only if bWScollapse=true - charIter.remove(); - } - else { - if (bWScollapse) bInWS=true; - charIter.replaceChar('\u0020'); - } - break; - case Constants.TREAT_AS_ZERO_WIDTH_SPACE: - charIter.replaceChar('\u200b'); - // Fall through: this isn't XML whitespace - case Constants.PRESERVE: - bInWS=false; - break; - } - break; - - case CharUtilities.EOT: - // A "boundary" objects such as non-character inline - // or nested block object was encountered. - // If any whitespace run in progress, finish it. - // FALL THROUGH - - case CharUtilities.UCWHITESPACE: // Non XML-whitespace - case CharUtilities.NONWHITESPACE: - /* Any other character */ - bInWS = bPrevWasLF=false; - lfCheck.reset(); - break; - } - } - firstInlineChild = null; - } + log.debug("fo:block: handleWhiteSpace"); + if (firstInlineChild != null) { + boolean bInWS = false; + boolean bPrevWasLF = false; + RecursiveCharIterator charIter = + new RecursiveCharIterator(this, firstInlineChild); + LFchecker lfCheck = new LFchecker(charIter); + + while (charIter.hasNext()) { + switch (CharUtilities.classOf(charIter.nextChar())) { + case CharUtilities.XMLWHITESPACE: + /* Some kind of whitespace character, except linefeed. */ + boolean bIgnore = false; + + switch (wsTreatment) { + case Constants.IGNORE: + bIgnore = true; + break; + case Constants.IGNORE_IF_BEFORE_LINEFEED: + bIgnore = lfCheck.nextIsLF(); + break; + case Constants.IGNORE_IF_SURROUNDING_LINEFEED: + bIgnore = (bPrevWasLF || + lfCheck.nextIsLF()); + break; + case Constants.IGNORE_IF_AFTER_LINEFEED: + bIgnore = bPrevWasLF; + break; + } + // Handle ignore + if (bIgnore) { + charIter.remove(); + } else if (bWScollapse) { + if (bInWS || (lfTreatment == + Constants.PRESERVE && + (bPrevWasLF || lfCheck.nextIsLF()))) { + charIter.remove(); + } else { + bInWS = true; + } + } + break; + + case CharUtilities.LINEFEED: + /* A linefeed */ + lfCheck.reset(); + bPrevWasLF = true; // for following whitespace + + switch (lfTreatment) { + case Constants.IGNORE: + charIter.remove(); + break; + case Constants.TREAT_AS_SPACE: + if (bInWS) { + // only if bWScollapse=true + charIter.remove(); + } else { + if (bWScollapse) + bInWS = true; + charIter.replaceChar('\u0020'); + } + break; + case Constants.TREAT_AS_ZERO_WIDTH_SPACE: + charIter.replaceChar('\u200b'); + // Fall through: this isn't XML whitespace + case Constants.PRESERVE: + bInWS = false; + break; + } + break; + + case CharUtilities.EOT: + // A "boundary" objects such as non-character inline + // or nested block object was encountered. + // If any whitespace run in progress, finish it. + // FALL THROUGH + + case CharUtilities.UCWHITESPACE: // Non XML-whitespace + case CharUtilities.NONWHITESPACE: + /* Any other character */ + bInWS = bPrevWasLF = false; + lfCheck.reset(); + break; + } + } + firstInlineChild = null; + } } private static class LFchecker { - private boolean bNextIsLF=false; - private RecursiveCharIterator charIter; - - LFchecker(RecursiveCharIterator charIter) { - this.charIter = charIter; - } - - boolean nextIsLF() { - if (bNextIsLF==false) { - CharIterator lfIter = charIter.mark(); - while (lfIter.hasNext()) { - char c = lfIter.nextChar(); - if (c == '\n') { - bNextIsLF=true; - break; - } - else if (CharUtilities.classOf(c) != - CharUtilities.XMLWHITESPACE) { - break; - } - } - } - return bNextIsLF; - } - - void reset() { - bNextIsLF=false; - } + private boolean bNextIsLF = false; + private RecursiveCharIterator charIter; + + LFchecker(RecursiveCharIterator charIter) { + this.charIter = charIter; + } + + boolean nextIsLF() { + if (bNextIsLF == false) { + CharIterator lfIter = charIter.mark(); + while (lfIter.hasNext()) { + char c = lfIter.nextChar(); + if (c == '\n') { + bNextIsLF = true; + break; + } else if (CharUtilities.classOf(c) != + CharUtilities.XMLWHITESPACE) { + break; + } + } + } + return bNextIsLF; + } + + void reset() { + bNextIsLF = false; + } } } diff --git a/src/org/apache/fop/fo/flow/Character.java b/src/org/apache/fop/fo/flow/Character.java index 9f22c7c30..17243d949 100644 --- a/src/org/apache/fop/fo/flow/Character.java +++ b/src/org/apache/fop/fo/flow/Character.java @@ -24,6 +24,7 @@ import org.apache.fop.area.inline.InlineArea; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import java.util.List; /** * this class represents the flow object 'fo:character'. Its use is defined by @@ -48,13 +49,23 @@ public class Character extends FObj { super(parent); } - public LayoutManager getLayoutManager() { - LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); - lm.setCurrentArea(getInlineArea()); - return lm; + public void addLayoutManager(List list) { + InlineArea inline = getInlineArea(); + if (inline != null) { + LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); + lm.setCurrentArea(inline); + list.add(lm); + } } protected InlineArea getInlineArea() { + String str = this.properties.get("character").getString(); + if (str.length() == 1) { + org.apache.fop.area.inline.Character ch = + new org.apache.fop.area.inline.Character( + str.charAt(0)); + return ch; + } return null; } @@ -77,7 +88,8 @@ public class Character extends FObj { MarginInlineProps mProps = propMgr.getMarginInlineProps(); // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); // this.properties.get("alignment-adjust"); // this.properties.get("treat-as-word-space"); @@ -105,8 +117,8 @@ public class Character extends FObj { } public CharIterator charIterator() { - return new OneCharIterator(characterValue); - // But what it the character is ignored due to white space handling? + return new OneCharIterator(characterValue); + // But what it the character is ignored due to white space handling? } diff --git a/src/org/apache/fop/fo/flow/ExternalGraphic.java b/src/org/apache/fop/fo/flow/ExternalGraphic.java index 1183afdea..96689b8c4 100644 --- a/src/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/org/apache/fop/fo/flow/ExternalGraphic.java @@ -22,6 +22,7 @@ import org.apache.fop.area.inline.Viewport; // Java import java.net.URL; import java.net.MalformedURLException; +import java.util.List; public class ExternalGraphic extends FObj { String url; @@ -41,10 +42,10 @@ public class ExternalGraphic extends FObj { super(parent); } - public LayoutManager getLayoutManager() { + public void addLayoutManager(List list) { LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); lm.setCurrentArea(getInlineArea()); - return lm; + list.add(lm); } protected InlineArea getInlineArea() { diff --git a/src/org/apache/fop/fo/flow/Flow.java b/src/org/apache/fop/fo/flow/Flow.java index f0828f426..bdeb21db8 100644 --- a/src/org/apache/fop/fo/flow/Flow.java +++ b/src/org/apache/fop/fo/flow/Flow.java @@ -19,6 +19,7 @@ import org.apache.fop.layoutmgr.FlowLayoutManager; // Java import java.util.ArrayList; +import java.util.List; import org.xml.sax.Attributes; @@ -59,36 +60,35 @@ public class Flow extends FObj { public void handleAttrs(Attributes attlist) throws FOPException { super.handleAttrs(attlist); if (parent.getName().equals("fo:page-sequence")) { - this.pageSequence = (PageSequence)parent; + this.pageSequence = (PageSequence) parent; } else { - throw new FOPException("flow must be child of " - + "page-sequence, not " - + parent.getName()); + throw new FOPException("flow must be child of " + + "page-sequence, not " + parent.getName()); } // according to communication from Paul Grosso (XSL-List, // 001228, Number 406), confusion in spec section 6.4.5 about // multiplicity of fo:flow in XSL 1.0 is cleared up - one (1) // fo:flow per fo:page-sequence only. -/* if (pageSequence.isFlowSet()) { - if (this.name.equals("fo:flow")) { - throw new FOPException("Only a single fo:flow permitted" - + " per fo:page-sequence"); - } else { - throw new FOPException(this.name - + " not allowed after fo:flow"); - } - } -*/ + /* if (pageSequence.isFlowSet()) { + if (this.name.equals("fo:flow")) { + throw new FOPException("Only a single fo:flow permitted" + + " per fo:page-sequence"); + } else { + throw new FOPException(this.name + + " not allowed after fo:flow"); + } + } + */ setFlowName(getProperty("flow-name").getString()); - // Now done in addChild of page-sequence + // Now done in addChild of page-sequence //pageSequence.addFlow(this); } protected void setFlowName(String name) throws FOPException { if (name == null || name.equals("")) { - throw new FOPException("A 'flow-name' is required for " - + getName()); + throw new FOPException("A 'flow-name' is required for " + + getName()); } else { _flowName = name; } @@ -109,7 +109,7 @@ public class Flow extends FObj { } // flow is *always* laid out into a BodyAreaContainer - BodyAreaContainer bac = (BodyAreaContainer)area; + BodyAreaContainer bac = (BodyAreaContainer) area; boolean prevChildMustKeepWithNext = false; ArrayList pageMarker = this.getMarkerSnapshot(new ArrayList()); @@ -119,7 +119,7 @@ public class Flow extends FObj { throw new FOPException("fo:flow must contain block-level children"); } for (int i = this.marker; i < numChildren; i++) { - FObj fo = (FObj)children.get(i); + FObj fo = (FObj) children.get(i); if (bac.isBalancingRequired(fo)) { // reset the the just-done span area in preparation @@ -139,8 +139,8 @@ public class Flow extends FObj { this.marker = i; markerSnapshot = this.getMarkerSnapshot(new ArrayList()); } - // Set current content width for percent-based lengths in children - setContentWidth(currentArea.getContentWidth()); + // Set current content width for percent-based lengths in children + setContentWidth(currentArea.getContentWidth()); _status = fo.layout(currentArea); @@ -155,9 +155,10 @@ public class Flow extends FObj { * } */ if (_status.isIncomplete()) { - if ((prevChildMustKeepWithNext) && (_status.laidOutNone())) { + if ((prevChildMustKeepWithNext) && + (_status.laidOutNone())) { this.marker = i - 1; - FObj prevChild = (FObj)children.get(this.marker); + FObj prevChild = (FObj) children.get(this.marker); prevChild.removeAreas(); prevChild.resetMarker(); prevChild.removeID(area.getIDReferences()); @@ -169,8 +170,8 @@ public class Flow extends FObj { if (bac.isLastColumn()) if (_status.getCode() == Status.FORCE_COLUMN_BREAK) { this.marker = i; - _status = - new Status(Status.FORCE_PAGE_BREAK); // same thing + _status = new Status(Status.FORCE_PAGE_BREAK); + // same thing return _status; } else { this.marker = i; @@ -183,7 +184,8 @@ public class Flow extends FObj { return _status; } // I don't much like exposing this. (AHS 001217) - ((org.apache.fop.layout.ColumnArea)currentArea).incrementSpanIndex(); + ((org.apache.fop.layout.ColumnArea) currentArea). + incrementSpanIndex(); i--; } } @@ -197,14 +199,14 @@ public class Flow extends FObj { } protected void setContentWidth(int contentWidth) { - this.contentWidth = contentWidth; + this.contentWidth = contentWidth; } /** * Return the content width of this flow (really of the region * in which it is flowing). */ public int getContentWidth() { - return this.contentWidth; + return this.contentWidth; } public Status getStatus() { @@ -215,8 +217,8 @@ public class Flow extends FObj { return true; } - public LayoutManager getLayoutManager() { - return new FlowLayoutManager(this); + public void addLayoutManager(List list) { + list.add(new FlowLayoutManager(this)); } } diff --git a/src/org/apache/fop/fo/flow/Footnote.java b/src/org/apache/fop/fo/flow/Footnote.java index 0374e0400..103e6665c 100644 --- a/src/org/apache/fop/fo/flow/Footnote.java +++ b/src/org/apache/fop/fo/flow/Footnote.java @@ -12,6 +12,11 @@ import org.apache.fop.fo.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafNodeLayoutManager; + +import java.util.List; // Java import java.util.ArrayList; @@ -22,6 +27,13 @@ public class Footnote extends FObj { super(parent); } + public void addLayoutManager(List lms) { + // add inlines layout manager + //inline.addLayoutManager(lms); + // set start and end footnote reference + } + + public Status layout(Area area) throws FOPException { FONode inline = null; FONode fbody = null; diff --git a/src/org/apache/fop/fo/flow/Inline.java b/src/org/apache/fop/fo/flow/Inline.java index c6f78e8d0..c25104ac3 100644 --- a/src/org/apache/fop/fo/flow/Inline.java +++ b/src/org/apache/fop/fo/flow/Inline.java @@ -89,7 +89,7 @@ public class Inline extends FObjMixed { public CharIterator charIterator() { - return new InlineCharIterator(this, propMgr.getBorderAndPadding()); + return new InlineCharIterator(this, propMgr.getBorderAndPadding()); } } diff --git a/src/org/apache/fop/fo/flow/InlineContainer.java b/src/org/apache/fop/fo/flow/InlineContainer.java index 78bbbce04..d3a46f016 100644 --- a/src/org/apache/fop/fo/flow/InlineContainer.java +++ b/src/org/apache/fop/fo/flow/InlineContainer.java @@ -13,17 +13,28 @@ import org.apache.fop.fo.flow.*; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import org.apache.fop.area.inline.InlineArea; import org.xml.sax.Attributes; +import java.util.List; +import java.util.ArrayList; + /** */ -public class InlineContainer extends ToBeImplementedElement { +public class InlineContainer extends FObj { public InlineContainer(FONode parent) { super(parent); } + public void addLayoutManager(List lms) { + ArrayList childList = new ArrayList(); + super.addLayoutManager(childList); + lms.add(new ICLayoutManager(this, childList)); + } + public void handleAttrs(Attributes attlist) throws FOPException { super.handleAttrs(attlist); // Common Border, Padding, and Background Properties @@ -34,7 +45,8 @@ public class InlineContainer extends ToBeImplementedElement { MarginInlineProps mProps = propMgr.getMarginInlineProps(); // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); // this.properties.get("alignment-adjust"); // this.properties.get("alignment-baseline"); @@ -57,4 +69,21 @@ public class InlineContainer extends ToBeImplementedElement { // this.properties.get("writing-mode"); } + /** + * This creates a single inline container area after + * laying out the child block areas. All footnotes, floats + * and id areas are maintained for later retrieval. + */ + class ICLayoutManager extends LeafNodeLayoutManager { + List childrenLM; + + ICLayoutManager(FObj obj, List childLM) { + super(obj); + childrenLM = childLM; + } + + public InlineArea get(int index) { + return null; + } + } } diff --git a/src/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/org/apache/fop/fo/flow/InstreamForeignObject.java index 9dc8682b6..df30fccaf 100644 --- a/src/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -29,6 +29,7 @@ import org.apache.fop.layoutmgr.LayoutInfo; import org.w3c.dom.Document; import java.awt.geom.Point2D; +import java.util.List; public class InstreamForeignObject extends FObj { @@ -60,10 +61,10 @@ public class InstreamForeignObject extends FObj { super(parent); } - public LayoutManager getLayoutManager() { + public void addLayoutManager(List list) { LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); lm.setCurrentArea(getInlineArea()); - return lm; + list.add(lm); } /** @@ -144,6 +145,10 @@ public class InstreamForeignObject extends FObj { return areaCurrent; } + public boolean generatesInlineAreas() { + return true; + } + /** * layout this formatting object. * diff --git a/src/org/apache/fop/fo/flow/Leader.java b/src/org/apache/fop/fo/flow/Leader.java index 7089ce78a..92cbf999a 100644 --- a/src/org/apache/fop/fo/flow/Leader.java +++ b/src/org/apache/fop/fo/flow/Leader.java @@ -20,6 +20,9 @@ import org.apache.fop.layout.FontState; import org.apache.fop.apps.FOPException; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import org.apache.fop.area.MinOptMax; + +import java.util.List; /** * Implements fo:leader; main property of leader leader-pattern. @@ -32,14 +35,22 @@ public class Leader extends FObjMixed { super(parent); } - public LayoutManager getLayoutManager() { - LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); - lm.setCurrentArea(getInlineArea()); - return lm; + public void addLayoutManager(List list) { + list.add(new LeafNodeLayoutManager(this) { + public InlineArea get(int index) { + if(index > 0) + return null; + int contentIPD = parentLM.getContentIPD(); + return getInlineArea(contentIPD); + } + }); } - protected InlineArea getInlineArea() { - return null; + protected InlineArea getInlineArea(int maxIPD) { + org.apache.fop.area.inline.Leader leader = new org.apache.fop.area.inline.Leader(); + leader.setWidth(maxIPD / 2); + leader.setAllocationIPD(new MinOptMax(0, maxIPD / 2, maxIPD)); + return leader; } public Status layout(Area area) throws FOPException { diff --git a/src/org/apache/fop/fo/flow/PageNumber.java b/src/org/apache/fop/fo/flow/PageNumber.java index b1eb6a696..a1dfb10ce 100644 --- a/src/org/apache/fop/fo/flow/PageNumber.java +++ b/src/org/apache/fop/fo/flow/PageNumber.java @@ -15,8 +15,12 @@ import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.Word; + // Java -import java.util.Enumeration; +import java.util.List; public class PageNumber extends FObj { @@ -31,6 +35,24 @@ public class PageNumber extends FObj { super(parent); } + public void addLayoutManager(List lms) { + lms.add(new LeafNodeLayoutManager(this) { + public InlineArea get(int index) { + if(index > 0) + return null; + // get page string from parent, build area + Word inline = new Word(); + //String parentLM.getCurrentPageNumber(); + inline.setWord("01"); + return inline; + } + + public boolean resolved() { + return true; + } + }); + } + public Status layout(Area area) throws FOPException { if (!(area instanceof BlockArea)) { log.warn("page-number outside block area"); diff --git a/src/org/apache/fop/fo/flow/PageNumberCitation.java b/src/org/apache/fop/fo/flow/PageNumberCitation.java index af9d1eeaf..0c705a8af 100644 --- a/src/org/apache/fop/fo/flow/PageNumberCitation.java +++ b/src/org/apache/fop/fo/flow/PageNumberCitation.java @@ -14,7 +14,11 @@ import org.apache.fop.datatypes.*; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.LeafNodeLayoutManager; +import org.apache.fop.area.inline.InlineArea; +import java.util.List; +import java.util.ArrayList; /** * 6.6.11 fo:page-number-citation @@ -88,6 +92,18 @@ public class PageNumberCitation extends FObj { super(parent); } + public void addLayoutManager(List lms) { + LeafNodeLayoutManager lnlm = new LeafNodeLayoutManager(this); + lnlm.setCurrentArea(getInlineArea()); + lms.add(lnlm); + } + + // is id can be resolved then simply return a word, otherwise + // return a resolveable area + private InlineArea getInlineArea() { + return null; + } + public Status layout(Area area) throws FOPException { if (!(area instanceof BlockArea)) { log.warn("page-number-citation outside block area"); @@ -98,37 +114,38 @@ public class PageNumberCitation extends FObj { this.area = area; if (this.marker == START) { - // Common Accessibility Properties + // Common Accessibility Properties AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); - // Common Aural Properties - AuralProps mAurProps = propMgr.getAuralProps(); + // Common Aural Properties + AuralProps mAurProps = propMgr.getAuralProps(); - // Common Border, Padding, and Background Properties - BorderAndPadding bap = propMgr.getBorderAndPadding(); - BackgroundProps bProps = propMgr.getBackgroundProps(); + // Common Border, Padding, and Background Properties + BorderAndPadding bap = propMgr.getBorderAndPadding(); + BackgroundProps bProps = propMgr.getBackgroundProps(); - // Common Font Properties - //this.fontState = propMgr.getFontState(area.getFontInfo()); + // Common Font Properties + //this.fontState = propMgr.getFontState(area.getFontInfo()); - // Common Margin Properties-Inline - MarginInlineProps mProps = propMgr.getMarginInlineProps(); + // Common Margin Properties-Inline + MarginInlineProps mProps = propMgr.getMarginInlineProps(); - // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); + // Common Relative Position Properties + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); - // this.properties.get("alignment-adjust"); - // this.properties.get("alignment-baseline"); - // this.properties.get("baseline-shift"); - // this.properties.get("dominant-baseline"); - // this.properties.get("id"); - // this.properties.get("keep-with-next"); + // this.properties.get("alignment-adjust"); + // this.properties.get("alignment-baseline"); + // this.properties.get("baseline-shift"); + // this.properties.get("dominant-baseline"); + // this.properties.get("id"); + // this.properties.get("keep-with-next"); // this.properties.get("keep-with-previous"); // this.properties.get("letter-spacing"); // this.properties.get("line-height"); - // this.properties.get("line-height-shift-adjustment"); - // this.properties.get("ref-id"); - // this.properties.get("score-spaces"); + // this.properties.get("line-height-shift-adjustment"); + // this.properties.get("ref-id"); + // this.properties.get("score-spaces"); // this.properties.get("text-decoration"); // this.properties.get("text-shadow"); // this.properties.get("text-transform"); @@ -141,7 +158,7 @@ public class PageNumberCitation extends FObj { this.wrapOption = this.properties.get("wrap-option").getEnum(); this.whiteSpaceCollapse = - this.properties.get("white-space-collapse").getEnum(); + this.properties.get("white-space-collapse").getEnum(); this.refId = this.properties.get("ref-id").getString(); @@ -164,16 +181,14 @@ public class PageNumberCitation extends FObj { pageNumber = idReferences.getPageNumber(refId); - if (pageNumber != null) { // if we already know the page number - this.marker = - FOText.addText((BlockArea)area, - propMgr.getFontState(area.getFontInfo()), red, - green, blue, wrapOption, null, - whiteSpaceCollapse, pageNumber.toCharArray(), - 0, pageNumber.length(), ts, - VerticalAlign.BASELINE); - } else { // add pageNumberCitation to area to be resolved during rendering - BlockArea blockArea = (BlockArea)area; + if (pageNumber != null) { // if we already know the page number + this.marker = FOText.addText((BlockArea) area, + propMgr.getFontState(area.getFontInfo()), red, + green, blue, wrapOption, null, whiteSpaceCollapse, + pageNumber.toCharArray(), 0, pageNumber.length(), + ts, VerticalAlign.BASELINE); + } else { // add pageNumberCitation to area to be resolved during rendering + BlockArea blockArea = (BlockArea) area; LineArea la = blockArea.getCurrentLineArea(); if (la == null) { return new Status(Status.AREA_FULL_NONE); diff --git a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java index df6d58a45..50d4b643a 100644 --- a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -12,6 +12,7 @@ import org.apache.fop.fo.FONode; import org.apache.fop.area.Area; import java.util.ListIterator; +import java.util.ArrayList; /** * The base class for all LayoutManagers. @@ -20,6 +21,12 @@ public abstract class AbstractLayoutManager implements LayoutManager { protected LayoutManager parentLM; protected FObj fobj; + protected LayoutPos curPos = new LayoutPos(); + + static class LayoutPos { + int lmIndex = 0; + int subIndex = 0; + } public AbstractLayoutManager(FObj fobj) { this.fobj = fobj; @@ -39,19 +46,27 @@ public abstract class AbstractLayoutManager implements LayoutManager { * children of its FO, asks each for its LayoutManager and calls * its generateAreas method. */ - public void generateAreas() { - ListIterator children = fobj.getChildren(); - while (children.hasNext()) { - FONode node = (FONode) children.next(); - if (node instanceof FObj) { - LayoutManager lm = ((FObj) node).getLayoutManager(); - if (lm != null) { - lm.setParentLM(this); - lm.generateAreas(); + public boolean generateAreas() { + ArrayList lms = new ArrayList(); + if (fobj != null) { + ListIterator children = fobj.getChildren(); + while (children.hasNext()) { + FONode node = (FONode) children.next(); + if (node instanceof FObj) { + ((FObj) node).addLayoutManager(lms); } } + fobj = null; + } + + for (int count = 0; count < lms.size(); count++) { + LayoutManager lm = (LayoutManager) lms.get(count); + lm.setParentLM(this); + if (lm.generateAreas()) { + break; + } } - flush(); // Add last area to parent + return flush(); // Add last area to parent } // /** @@ -77,7 +92,7 @@ public abstract class AbstractLayoutManager implements LayoutManager { /** * Force current area to be added to parent area. */ - abstract protected void flush(); + abstract protected boolean flush(); /** @@ -93,18 +108,16 @@ public abstract class AbstractLayoutManager implements LayoutManager { abstract public Area getParentArea(Area childArea); - - // public boolean generatesInlineAreas() { - // return false; - // } - + public boolean generatesInlineAreas() { + return false; + } /** * Add a child area to the current area. If this causes the maximum * dimension of the current area to be exceeded, the parent LM is called * to add it. */ - abstract public void addChild(Area childArea); + abstract public boolean addChild(Area childArea); /** Do nothing */ public boolean splitArea(Area areaToSplit, SplitContext context) { diff --git a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java index 94993b722..b1c537e85 100644 --- a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -13,8 +13,10 @@ import org.apache.fop.area.Area; import org.apache.fop.area.BlockParent; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; +import org.apache.fop.area.MinOptMax; import java.util.ListIterator; +import java.util.ArrayList; /** * LayoutManager for a block FO. @@ -45,7 +47,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { */ public int getContentIPD() { // adjust for side floats and indents - //getParentArea(null); // make if not existing + getParentArea(null); // make if not existing return curBlockArea.getIPD(); } @@ -53,23 +55,46 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { * Generate areas by tellings all layout managers for its FO's * children to generate areas. */ - public void generateAreas() { - ListIterator children = fobj.getChildren(); + public boolean generateAreas() { + ArrayList lms = new ArrayList(); LayoutManager lm = null; - while (children.hasNext()) { - FObj childFO = (FObj) children.next(); - if (childFO.generatesInlineAreas()) { - children.previous(); - lm = new LineLayoutManager(children, lineHeight, lead, follow); - } else { - lm = childFO.getLayoutManager(); + + if (fobj != null) { + ListIterator children = fobj.getChildren(); + while (children.hasNext()) { + FObj childFO = (FObj) children.next(); + childFO.addLayoutManager(lms); + } + fobj = null; + } + + for (int count = 0; count < lms.size(); count++) { + lm = (LayoutManager) lms.get(count); + if (lm.generatesInlineAreas()) { + ArrayList inlines = new ArrayList(); + inlines.add(lm); + //lms.remove(count); + while (count + 1 < lms.size()) { + lm = (LayoutManager) lms.get(count + 1); + if (lm.generatesInlineAreas()) { + inlines.add(lm); + lms.remove(count + 1); + } else { + break; + } + } + lm = new LineLayoutManager(inlines, lineHeight, lead, + follow); + lms.set(count, lm); } - if (lm != null) { - lm.setParentLM(this); - lm.generateAreas(); + lm.setParentLM(this); + if (lm.generateAreas()) { + if (flush()) { + return true; + } } } - flush(); // Add last area to parent + return flush(); // Add last area to parent } @@ -98,16 +123,28 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { } - public void addChild(Area childArea) { + public boolean addChild(Area childArea) { if (curBlockArea != null) { if (childArea instanceof LineArea) { // Something about widows and orphans // Position the line area and calculate size... curBlockArea.addLineArea((LineArea) childArea); + + MinOptMax targetDim = parentArea.getAvailBPD(); + MinOptMax currentDim = curBlockArea.getContentBPD(); + //if(currentDim.min > targetDim.max) { + // return true; + //} + + return false; } else { - super.addChild(childArea); + curBlockArea.addBlock((Block) childArea); + //return super.addChild(childArea); + + return false; } } + return false; } diff --git a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 423af36d3..52156eca4 100644 --- a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -30,12 +30,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { super(fobj); } - - public boolean splitArea(Area area, SplitContext splitContext) { // Divide area so that it will be within targetLength if possible // If not, it can be shorter, but not longer. - /* Iterate over contents of the area. */ + /* Iterate over contents of the area. * // Need to figure out if we can do this generically // Logically a BlockStacking LM only handles Block-type areas @@ -66,13 +64,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { /* Split 'area', placing all children after * minBreakCost.getArea() into a new area, * which we store in the splitContext. - */ + * // splitContext.nextArea = area.splitAfter(minBreakCost.getArea()); } else { /* This area will be shorter than the desired minimum. * Split before the current childArea (which will be * the first area in the newly created Area. - */ + * //splitContext.nextArea = area.splitBefore(childArea); } } else @@ -94,7 +92,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { } // True if some part of area can be placed, false if none is placed return (splitContext.nextArea != area); - + */ + return false; } private BreakCost evaluateBreakCost(Area parent, Area child) { @@ -136,11 +135,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { * @param childArea the area to add: will be some block-stacked Area. * @param parentArea the area in which to add the childArea */ - protected void addChildToArea(Area childArea, BlockParent parentArea) { + protected boolean addChildToArea(Area childArea, BlockParent parentArea) { // This should be a block-level Area (Block in the generic sense) if (!(childArea instanceof Block)) { System.err.println("Child not a Block in BlockStackingLM!"); - return; + return false; } // See if the whole thing fits, including space before @@ -151,23 +150,28 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { if (targetDim.max >= childArea.getAllocationBPD().min) { //parentArea.addBlock(new InterBlockSpace(spaceBefore)); parentArea.addBlock((Block) childArea); - return; + return false; } else { + parentArea.addBlock((Block) childArea); + flush(); // hand off current area to parent // Probably need something like max BPD so we don't get into // infinite loops with large unbreakable chunks - SplitContext splitContext = new SplitContext(targetDim); + //SplitContext splitContext = new SplitContext(targetDim); - LayoutManager childLM = + /*LayoutManager childLM = childArea.getGeneratingFObj(). getLayoutManager(); if (childLM.splitArea(childArea, splitContext)) { //parentArea.addBlock(new InterBlockSpace(spaceBefore)); parentArea.addBlock((Block) childArea); - } - flush(); // hand off current area to parent - getParentArea(splitContext.nextArea); + }*/ + //flush(); // hand off current area to parent + //getParentArea(splitContext.nextArea); + //getParentArea(childArea); // Check that reference IPD hasn't changed!!! // If it has, we must "reflow" the content - addChild(splitContext.nextArea); + //addChild(splitContext.nextArea); + //addChild(childArea); + return true; } } @@ -180,17 +184,18 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { * If so, add it. Otherwise initiate breaking. * @param childArea the area to add: will be some block-stacked Area. */ - public void addChild(Area childArea) { - addChildToArea(childArea, getCurrentArea()); + public boolean addChild(Area childArea) { + return addChildToArea(childArea, getCurrentArea()); } /** * Force current area to be added to parent area. */ - protected void flush() { + protected boolean flush() { if (getCurrentArea() != null) - parentLM.addChild(getCurrentArea()); + return parentLM.addChild(getCurrentArea()); + return false; } - } + diff --git a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java index 9c9a05a56..9bdd93abe 100644 --- a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -38,8 +38,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager { * area class. A Flow can fill at most one area container of any class * at any one time. The actual work is done by BlockStackingLM. */ - public void addChild(Area childArea) { - addChildToArea(childArea, + public boolean addChild(Area childArea) { + return addChildToArea(childArea, this.currentAreas[childArea.getAreaClass()]); } diff --git a/src/org/apache/fop/layoutmgr/LayoutInfo.java b/src/org/apache/fop/layoutmgr/LayoutInfo.java index 0c6e0f6aa..b9187aa3b 100644 --- a/src/org/apache/fop/layoutmgr/LayoutInfo.java +++ b/src/org/apache/fop/layoutmgr/LayoutInfo.java @@ -14,6 +14,11 @@ public class LayoutInfo { public int alignment; public int lead; public boolean blOffset = false; + public boolean breakAfter = false; + + public boolean keepNext = false; + public boolean keepPrev = false; + public boolean isText = false; public LayoutInfo() { } diff --git a/src/org/apache/fop/layoutmgr/LayoutManager.java b/src/org/apache/fop/layoutmgr/LayoutManager.java index 4d3878b99..15763ec0b 100644 --- a/src/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LayoutManager.java @@ -14,10 +14,10 @@ import org.apache.fop.area.Area; * The interface for all LayoutManagers. */ public interface LayoutManager { - public void generateAreas(); - //public boolean generatesInlineAreas(); + public boolean generateAreas(); + public boolean generatesInlineAreas(); public Area getParentArea (Area childArea); - public void addChild (Area childArea); + public boolean addChild (Area childArea); public boolean splitArea(Area areaToSplit, SplitContext context); public void setParentLM(LayoutManager lm); public int getContentIPD(); diff --git a/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java b/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java index 1bd8e9095..c97f85855 100644 --- a/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java @@ -19,29 +19,46 @@ import org.apache.fop.area.inline.InlineArea; */ public class LeafNodeLayoutManager extends AbstractLayoutManager { - private InlineArea curArea; + private InlineArea curArea = null; public LeafNodeLayoutManager(FObj fobj) { super(fobj); } + public int size() { + return 1; + } + + public InlineArea get(int index) { + if(index > 0) + return null; + return curArea; + } + + public boolean generatesInlineAreas() { + return true; + } + + public boolean resolved() { + return false; + } public void setCurrentArea(InlineArea ia) { curArea = ia; } - public void generateAreas() { - flush(); + public boolean generateAreas() { + return flush(); } - protected void flush() { - parentLM.addChild(curArea); + protected boolean flush() { + return false; } /** * This is a leaf-node, so this method is never called. */ - public void addChild(Area childArea) {} + public boolean addChild(Area childArea) {return false;} /** diff --git a/src/org/apache/fop/layoutmgr/LineLayoutManager.java b/src/org/apache/fop/layoutmgr/LineLayoutManager.java index b3b863a41..fdf6cc60b 100644 --- a/src/org/apache/fop/layoutmgr/LineLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LineLayoutManager.java @@ -16,150 +16,342 @@ import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.properties.VerticalAlign; import org.apache.fop.area.inline.Word; +import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.Character; import java.util.ListIterator; import java.util.List; +import java.util.ArrayList; import java.util.Iterator; /** * LayoutManager for lines. It builds one or more lines containing * inline areas generated by its sub layout managers. + * + * The line layout manager does the following things: + * receives a list of inline creating layout managers + * adds the inline areas retrieved from the child layout managers + * finds the best line break position + * adds complete line to parent + * stores the starting position for each line in case of recreation + * if ipd not changed but line contains resolved values (eg. page number), redoes from that line + * when freeing memory, release all layout managers and inline areas before current position + * As each child layout manager is used it gets the start, end and normal references for id area, footnotes, floats, links, colour-back properties + * first line properties are set and used by the child when retrieving the inline area(s) + * + * Hyphenation is handled by asking the child to split the words then this + * adds the hyph char. If redone then exra char ignored. + * + * How do we handle Unicode BIDI? */ public class LineLayoutManager extends AbstractLayoutManager { - /** Reference to FO whose areas it's managing or to the traits - * of the FO. - */ - private ListIterator fobjIter; - private LineArea lineArea = null; - private boolean bFirstLine; - private LayoutManager curLM; - private MinOptMax remainingIPD; + private LineInfo currentLine = null; + private boolean bFirstLine = true; + private MinOptMax totalIPD; // the following values must be set by the block // these are the dominant basline and lineheight values private int lineHeight; private int lead; private int follow; - public LineLayoutManager(ListIterator fobjIter, int lh, int l, int f) { + List lmList; + List lines = new ArrayList(); + + private LayoutPos bestPos = null; + private MinOptMax bestIPD = null; + + static class LineInfo { + LayoutPos startPos; + LineArea area; + boolean hasResolved = false; + boolean noJustify = false; + // footnotes, floats? + } + + public LineLayoutManager(List lms, int lh, int l, int f) { super(null); - this.fobjIter = fobjIter; + lmList = lms; lineHeight = lh; lead = l; follow = f; } + public int getContentIPD() { + return parentLM.getContentIPD(); + } + /** * Call child layout managers to generate content as long as they * generate inline areas. If a block-level generating LM is found, * finish any line being filled and return to the parent LM. */ - public void generateAreas() { - this.bFirstLine = true; - while (fobjIter.hasNext()) { - FObj childFO = (FObj) fobjIter.next(); - if (childFO.generatesInlineAreas() == false) { - // It generates blocks, pass back to parent - // Back up one - fobjIter.previous(); - break; - } else { // generates inline area - curLM = childFO.getLayoutManager(); - if (curLM != null) { - curLM.setParentLM(this); - curLM.generateAreas(); + public boolean generateAreas() { + // if a side float is added and the line contains content + // where the ipd depends on the line width then restart + // the line with the adjusted length + + while (curPos.lmIndex < lmList.size()) { + LeafNodeLayoutManager curLM = + (LeafNodeLayoutManager) lmList.get(curPos.lmIndex); + curLM.setParentLM(this); + + LeafNodeLayoutManager nextLM = null; + if (curPos.lmIndex + 1 < lmList.size()) { + nextLM = (LeafNodeLayoutManager) lmList.get( + curPos.lmIndex + 1); + while (nextLM.size() == 0) { + lmList.remove(curPos.lmIndex + 1); + if (curPos.lmIndex + 1 == lmList.size()) { + nextLM = null; + break; + } + nextLM = (LeafNodeLayoutManager) lmList.get( + curPos.lmIndex + 1); + + } + } + if (nextLM != null) { + nextLM.setParentLM(this); + } + if (curLM.resolved()) { + currentLine.hasResolved = true; + } + while (curPos.subIndex < curLM.size()) { + InlineArea ia = curLM.get(curPos.subIndex); + InlineArea next = null; + if (curPos.subIndex + 1 < curLM.size()) { + next = curLM.get(curPos.subIndex + 1); + } else if (curPos.lmIndex + 1 < lmList.size()) { + if (nextLM != null) { + next = nextLM.get(0); + } } + if (currentLine != null && !currentLine.noJustify && + (curPos.subIndex + 1 == curLM.size() && + curPos.lmIndex + 1 == lmList.size())) { + currentLine.noJustify = true; + } + if (addChild(ia, next)) { + if (flush()) { + return true; + } + } + // flush final line in same context as other lines + // handle last line concepts + if (curPos.subIndex + 1 == curLM.size() && + curPos.lmIndex + 1 == lmList.size()) { + if (flush()) { + return true; + } + if (curPos.subIndex + 1 == curLM.size() && + curPos.lmIndex + 1 == lmList.size()) { + return false; + } + + } + curPos.subIndex++; } + curPos.lmIndex++; + curPos.subIndex = 0; } - flush(); // Add last area to parent + return false; } /** * Align and position curLine and add it to parentContainer. * Set curLine to null. */ - public void flush() { - if (lineArea != null) { + public boolean flush() { + if (currentLine != null) { // Adjust spacing as necessary - + adjustSpacing(); verticalAlign(); - parentLM.addChild(lineArea); - lineArea = null; + boolean res = parentLM.addChild(currentLine.area); + + lines.add(currentLine); + currentLine = null; + bestPos = null; + bestIPD = null; + + return res; } + return false; + } + + /** + * Do the ipd adjustment for stretch areas etc. + * Consecutive spaces need to be collapsed if possible. + * should this be on the line area so it can finish resolved areas? + */ + private void adjustSpacing() { + List inlineAreas = currentLine.area.getInlineAreas(); + + // group text elements to split at hyphen if available + // remove collapsable spaces at start or end on line + + // backtrack to best position + while (true) { + if (curPos.lmIndex == bestPos.lmIndex && + curPos.subIndex == bestPos.subIndex) { + break; + } + + InlineArea inline = + (InlineArea) inlineAreas.get(inlineAreas.size() - 1); + MinOptMax ipd = inline.getAllocationIPD(); + totalIPD.subtract(ipd); + + inlineAreas.remove(inlineAreas.size() - 1); + currentLine.noJustify = false; + + curPos.subIndex--; + if (curPos.subIndex == -1) { + curPos.lmIndex--; + LeafNodeLayoutManager curLM = + (LeafNodeLayoutManager) lmList.get( curPos.lmIndex); + curPos.subIndex = curLM.size() - 1; + } + } + + + // for justify also stretch spaces to fill + // stretch to best match + float percentAdjust = 0; + boolean maxSide = false; + int realWidth = bestIPD.opt; + if (bestIPD.opt > parentLM.getContentIPD()) { + if (bestIPD.opt - parentLM.getContentIPD() < + (bestIPD.max - bestIPD.opt)) { + percentAdjust = (bestIPD.opt - parentLM.getContentIPD()) / + (float)(bestIPD.max - bestIPD.opt); + realWidth = parentLM.getContentIPD(); + } else { + percentAdjust = 1; + realWidth = bestIPD.max; + } + maxSide = true; + } else { + if (parentLM.getContentIPD() - bestIPD.opt < + bestIPD.opt - bestIPD.min) { + percentAdjust = (parentLM.getContentIPD() - bestIPD.opt) / + (float)(bestIPD.opt - bestIPD.min); + realWidth = parentLM.getContentIPD(); + } else { + percentAdjust = 1; + realWidth = bestIPD.min; + } + } + if (percentAdjust > 0) { + for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { + InlineArea inline = (InlineArea) iter.next(); + int width; + MinOptMax iipd = inline.getAllocationIPD(); + if (!maxSide) { + width = iipd.opt + + (int)((iipd.max - iipd.opt) * percentAdjust); + } else { + width = iipd.opt - + (int)((iipd.opt - iipd.min) * percentAdjust); + } + inline.setWidth(width); + } + } + + // don't justify lines ending with U+000A or last line + if (/*justify && */!currentLine.noJustify && + realWidth != parentLM.getContentIPD()) { + ArrayList spaces = new ArrayList(); + for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { + InlineArea inline = (InlineArea) iter.next(); + if (inline instanceof Space /* && !((Space)inline).fixed*/) { + spaces.add(inline); + } + } + for (Iterator iter = spaces.iterator(); iter.hasNext();) { + Space space = (Space) iter.next(); + space.setWidth(space.getWidth() + + (parentLM.getContentIPD() - realWidth) / + spaces.size()); + } + } + } private void verticalAlign() { int maxHeight = lineHeight; - List inlineAreas = lineArea.getInlineAreas(); + List inlineAreas = currentLine.area.getInlineAreas(); // get smallest possible offset to before edge // this depends on the height of no and middle alignments int before = lead; int after = follow; - for(Iterator iter = inlineAreas.iterator(); iter.hasNext(); ) { - InlineArea inline = (InlineArea)iter.next(); + int halfLeading = (lineHeight - lead - follow) / 2; + before += halfLeading; + for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { + InlineArea inline = (InlineArea) iter.next(); LayoutInfo info = inline.info; int al; int ld = inline.getHeight(); - if(info != null) { + if (info != null) { al = info.alignment; ld = info.lead; } else { al = VerticalAlign.BASELINE; } - if(al == VerticalAlign.BASELINE) { - if(ld > before) { + if (al == VerticalAlign.BASELINE) { + if (ld > before) { before = ld; } - if(inline.getHeight() > before) { + if (inline.getHeight() > before) { before = inline.getHeight(); } - } else if(al == VerticalAlign.MIDDLE) { - if(inline.getHeight() / 2 + lead / 2 > before) { + } else if (al == VerticalAlign.MIDDLE) { + if (inline.getHeight() / 2 + lead / 2 > before) { before = inline.getHeight() / 2 + lead / 2; } - if(inline.getHeight() / 2 - lead / 2 > after) { + if (inline.getHeight() / 2 - lead / 2 > after) { after = inline.getHeight() / 2 - lead / 2; } - } else if(al == VerticalAlign.TOP) { - } else if(al == VerticalAlign.BOTTOM) { + } else if (al == VerticalAlign.TOP) { + } else if (al == VerticalAlign.BOTTOM) { } } // then align all before, no and middle alignment - for(Iterator iter = inlineAreas.iterator(); iter.hasNext(); ) { - InlineArea inline = (InlineArea)iter.next(); + for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { + InlineArea inline = (InlineArea) iter.next(); LayoutInfo info = inline.info; int al; int ld = inline.getHeight(); boolean bloffset = false; - if(info != null) { + if (info != null) { al = info.alignment; ld = info.lead; bloffset = info.blOffset; } else { al = VerticalAlign.BASELINE; } - if(al == VerticalAlign.BASELINE) { + if (al == VerticalAlign.BASELINE) { // the offset position for text is the baseline - if(bloffset) { + if (bloffset) { inline.setOffset(before); } else { inline.setOffset(before - ld); } - if(inline.getHeight() - ld > after) { + if (inline.getHeight() - ld > after) { after = inline.getHeight() - ld; } - } else if(al == VerticalAlign.MIDDLE) { - inline.setOffset(before - inline.getHeight() / 2 - lead / 2); - } else if(al == VerticalAlign.TOP) { + } else if (al == VerticalAlign.MIDDLE) { + inline.setOffset(before - inline.getHeight() / 2 - + lead / 2); + } else if (al == VerticalAlign.TOP) { inline.setOffset(0); - if(inline.getHeight() - before > after) { + if (inline.getHeight() - before > after) { after = inline.getHeight() - before; } - } else if(al == VerticalAlign.BOTTOM) { - if(inline.getHeight() - before > after) { + } else if (al == VerticalAlign.BOTTOM) { + if (inline.getHeight() - before > after) { after = inline.getHeight() - before; } } @@ -167,26 +359,26 @@ public class LineLayoutManager extends AbstractLayoutManager { // after alignment depends on maximum height of before // and middle alignments - for(Iterator iter = inlineAreas.iterator(); iter.hasNext(); ) { - InlineArea inline = (InlineArea)iter.next(); + for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { + InlineArea inline = (InlineArea) iter.next(); LayoutInfo info = inline.info; - int al; - if(info != null) { + int al; + if (info != null) { al = info.alignment; } else { al = VerticalAlign.BASELINE; } - if(al == VerticalAlign.BASELINE) { - } else if(al == VerticalAlign.MIDDLE) { - } else if(al == VerticalAlign.TOP) { - } else if(al == VerticalAlign.BOTTOM) { + if (al == VerticalAlign.BASELINE) { + } else if (al == VerticalAlign.MIDDLE) { + } else if (al == VerticalAlign.TOP) { + } else if (al == VerticalAlign.BOTTOM) { inline.setOffset(before + after - inline.getHeight()); } } - if(before + after > maxHeight) { - lineArea.setHeight(before + after); + if (before + after > maxHeight) { + currentLine.area.setHeight(before + after); } else { - lineArea.setHeight(maxHeight); + currentLine.area.setHeight(maxHeight); } } @@ -194,25 +386,27 @@ public class LineLayoutManager extends AbstractLayoutManager { * Return current lineArea or generate a new one if necessary. */ public Area getParentArea(Area childArea) { - if (lineArea == null) { + if (currentLine.area == null) { createLine(); } - return lineArea; + return currentLine.area; } private void createLine() { - lineArea = new LineArea(); + currentLine = new LineInfo(); + currentLine.startPos = curPos; + currentLine.area = new LineArea(); /* Set line IPD from parentArea * This accounts for indents. What about first line indent? * Should we set an "isFirst" flag on the lineArea to signal * that to the parent (Block) LM? That's where indent property * information will be managed. */ - Area parent = parentLM.getParentArea(lineArea); - // lineArea.setContentIPD(parent.getContentIPD()); - // remainingIPD = parent.getContentIPD(); + Area parent = parentLM.getParentArea(currentLine.area); + // currentLine.area.setContentIPD(parent.getContentIPD()); + // totalIPD = new MinOptMax(); // OR??? - remainingIPD = new MinOptMax(parentLM.getContentIPD()); + totalIPD = new MinOptMax(); this.bFirstLine = false; } @@ -223,55 +417,73 @@ public class LineLayoutManager extends AbstractLayoutManager { * This should also handle floats if childArea is an anchor. * @param childArea the area to add: should be an InlineArea subclass! */ - public void addChild(Area childArea) { - if ((childArea instanceof InlineArea) == false) { - // SIGNAL AN ERROR!!! - return; - } - InlineArea inlineArea = (InlineArea) childArea; - if (lineArea == null) { + public boolean addChild(InlineArea inlineArea, InlineArea nextArea) { + if (currentLine == null) { createLine(); } - if (inlineArea.getAllocationIPD().min < remainingIPD.max) { - lineArea.addInlineArea(inlineArea); - remainingIPD.subtract(inlineArea.getAllocationIPD()); - // Calculate number of spaces - // Forced line break after this area (ex. ends with LF in nowrap) - /* NOTYET! - if (inlineArea.breakAfter()) { - flush(); - } - */ - /* Check if line could end after this area (potential line-break - * character. If not, it must be joined with following inline - * area to make a word. Otherwise, if the line could break here - * and if it is "full", add it to the parent area. - */ - if (remainingIPD.min <= 0) { - flush(); - } + + // add side floats first + + int pIPD = parentLM.getContentIPD(); + + currentLine.area.addInlineArea(inlineArea); + totalIPD.add(inlineArea.getAllocationIPD()); + + LayoutInfo info = inlineArea.info; + if (info == null) { + info = new LayoutInfo(); } - else { - /* The inline area won't entirely fit in this line. Ask its - * layout manager to split it (by hyphenation for example), - * in order to fit part of it in the line. - * Note: only the current child LM could have generated this - * area, so we ask it to do the split. - */ - SplitContext splitContext = new SplitContext(remainingIPD); - if (curLM.splitArea(inlineArea, splitContext)) { - // inlineArea should now fit - lineArea.addInlineArea(inlineArea); - flush(); - addChild(splitContext.nextArea); - } else { - lineArea.addInlineArea((InlineArea)splitContext.nextArea); - remainingIPD.subtract(inlineArea.getAllocationIPD()); - if (remainingIPD.min <= 0) { - flush(); - } + LayoutInfo ninfo; + if (nextArea != null && nextArea.info != null) { + ninfo = nextArea.info; + } else { + ninfo = new LayoutInfo(); + } + + // the best pos cannot be before the first area + if (bestPos == null || bestIPD == null) { + bestPos = new LayoutPos(); + bestPos.lmIndex = curPos.lmIndex; + bestPos.subIndex = curPos.subIndex; + MinOptMax imop = inlineArea.getAllocationIPD(); + bestIPD = new MinOptMax(imop.min, imop.opt, imop.max); + } else { + + // bestPos changed only when it can break + // before/after a space or other atomic inlines + // check keep-with on this and next + // since chars are optimized as words we cannot assume a + // word is complete and therefore hyphenate or break after + // side floats effect the available ipd but do not add to line + + if (!ninfo.keepPrev && !info.keepNext && + !(info.isText && ninfo.isText)) { + if (Math.abs(bestIPD.opt - pIPD) > + Math.abs(totalIPD.opt - pIPD) && + (totalIPD.min <= pIPD)) { + bestPos.lmIndex = curPos.lmIndex; + bestPos.subIndex = curPos.subIndex; + bestIPD = new MinOptMax(totalIPD.min, totalIPD.opt, + totalIPD.max); + } } } + + // Forced line break after this area (ex. ends with LF in nowrap) + if (info.breakAfter) { + currentLine.noJustify = true; + return true; + } + + if (totalIPD.min > pIPD) { + return true; + } + + return false; } + public boolean addChild(Area childArea) { + return false; + } } + diff --git a/src/org/apache/fop/layoutmgr/PageLayoutManager.java b/src/org/apache/fop/layoutmgr/PageLayoutManager.java index d88d5d410..5d8a05804 100644 --- a/src/org/apache/fop/layoutmgr/PageLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/PageLayoutManager.java @@ -41,6 +41,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable * references? */ private AreaTree areaTree; + private PageSequence pageSequence; /** * This is the top level layout manager. @@ -49,6 +50,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable public PageLayoutManager(AreaTree areaTree, PageSequence pageseq) { super(pageseq); this.areaTree = areaTree; + pageSequence = pageseq; } @@ -69,13 +71,14 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable /** * For now, only handle normal flow areas. */ - public void addChild(Area childArea) { + public boolean addChild(Area childArea) { if (childArea == null) - return; + return false; if (childArea.getAreaClass() == Area.CLASS_NORMAL) { - placeFlowRefArea(childArea); + return placeFlowRefArea(childArea); } else ; // TODO: all the others! + return false; } /** @@ -85,7 +88,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable * current span, so we are just checking to see if the span is "full", * possibly moving to the next column or to the next page. */ - protected void placeFlowRefArea(Area area) { + protected boolean placeFlowRefArea(Area area) { // assert (curSpan != null); // assert (area == curFlow); // assert (curFlow == curSpan.getFlow(curSpan.getColumnCount()-1)); @@ -100,13 +103,16 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable // end the page. // Alternatively the child LM indicates to parent that it's full? +System.out.println("size: " + area.getAllocationBPD().max + ":" + curSpan.getMaxBPD().min); if (area.getAllocationBPD().max >= curSpan.getMaxBPD().min) { // Consider it filled if (curSpan.getColumnCount() == curSpanColumns) { finishPage(); + return true; } else curFlow = null; // Create new flow on next getParentArea() } + return false; } @@ -133,7 +139,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable private PageViewport makeNewPage(boolean bIsBlank, boolean bIsLast) { finishPage(); try { - curPage = ((PageSequence) fobj).createPage(bIsBlank, bIsLast); + curPage = pageSequence.createPage(bIsBlank, bIsLast); } catch (FOPException fopex) { /* ???? */ fopex.printStackTrace(); } @@ -308,6 +314,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable private Flow createFlow() { curFlow = new Flow(); curFlow.setIPD(curSpan.getIPD()); // adjust for columns + //curFlow.setBPD(100000); // Set IPD and max BPD on the curFlow from curBody curSpan.addFlow(curFlow); return curFlow; @@ -336,8 +343,9 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable } // See finishPage... - protected void flush() { + protected boolean flush() { finishPage(); + return false; } } diff --git a/src/org/apache/fop/layoutmgr/TextLayoutManager.java b/src/org/apache/fop/layoutmgr/TextLayoutManager.java index ac8f83436..04add7dfb 100644 --- a/src/org/apache/fop/layoutmgr/TextLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/TextLayoutManager.java @@ -11,6 +11,7 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.TextInfo; import org.apache.fop.area.Area; import org.apache.fop.area.Trait; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.Word; import org.apache.fop.area.inline.Space; import org.apache.fop.util.CharUtilities; @@ -19,6 +20,7 @@ import org.apache.fop.fo.properties.VerticalAlign; import org.apache.fop.fo.properties.*; import java.util.ListIterator; +import java.util.ArrayList; /** * LayoutManager for text (a sequence of characters) which generates one @@ -29,6 +31,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private char[] chars; private TextInfo textInfo; + ArrayList words = new ArrayList(); + private static final char NEWLINE = '\n'; private static final char RETURN = '\r'; private static final char TAB = '\t'; @@ -49,29 +53,36 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.textInfo = textInfo; } + public int size() { + parseChars(); + return words.size(); + } + + public InlineArea get(int index) { + parseChars(); + return (InlineArea)words.get(index); + } + /** * Generate inline areas for words in text. */ - public void generateAreas() { + public boolean generateAreas() { // Handle white-space characteristics. Maybe there is no area to // generate.... // Iterate over characters and make text areas. // Add each one to parent. Handle word-space. - // Word curWordArea = new Word(); - // curWordArea.setWord(new String(chars)); - //System.out.println("word:" + new String(chars)); - //parentLM.addChild(curWordArea); - parseChars(); - - //setCurrentArea(curWordArea); - //flush(); + return false; } protected void parseChars() { + if(chars == null) { + return; + } + int whitespaceWidth; // With CID fonts, space isn't neccesary currentFontState.width(32) - int whitespaceWidth = CharUtilities.getCharWidth(' ', textInfo.fs); + whitespaceWidth = CharUtilities.getCharWidth(' ', textInfo.fs); int wordStart = -1; int wordLength = 0; @@ -79,9 +90,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int spaceWidth = 0; int prev = NOTHING; + int i = 0; /* iterate over each character */ - for (int i = 0; i < chars.length; i++) { + for (; i < chars.length; i++) { int charWidth; /* get the character */ char c = chars[i]; @@ -115,8 +127,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (spaceWidth > 0) { Space is = new Space(); is.setWidth(spaceWidth); - parentLM.addChild(is); spaceWidth = 0; + words.add(is); } } else if (c == TAB) { spaceWidth += 8 * whitespaceWidth; @@ -127,8 +139,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (spaceWidth > 0) { Space is = new Space(); is.setWidth(spaceWidth); - parentLM.addChild(is); + is.info = new LayoutInfo(); + is.info.breakAfter = true; spaceWidth = 0; + words.add(is); } } @@ -142,8 +156,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (spaceWidth > 0) { Space is = new Space(); is.setWidth(spaceWidth); - parentLM.addChild(is); spaceWidth = 0; + words.add(is); } // add the current word @@ -153,7 +167,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // spaces. Split the word and add Space // as necessary. All spaces inside the word // Have a fixed width. - parentLM.addChild(createWord(new String(chars, wordStart + 1, + words.add(createWord(new String(chars, wordStart + 1, wordLength), wordWidth)); // reset word width @@ -190,7 +204,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // textdecoration not used because spaceWidth is 0 Space is = new Space(); is.setWidth(spaceWidth); - parentLM.addChild(is); + words.add(is); } else if (c == TAB) { prev = WHITESPACE; spaceWidth = 8 * whitespaceWidth; @@ -215,8 +229,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordLength = chars.length - 1 - wordStart; } - parentLM.addChild(createWord(new String(chars, wordStart + 1, wordLength), wordWidth)); - + words.add(createWord(new String(chars, wordStart + 1, wordLength), wordWidth)); } chars = null; diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index 0db612f8d..cedd387c3 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -569,5 +569,15 @@ public class PDFRenderer extends PrintRenderer { }*/ super.renderViewport(viewport); } + + public void renderLeader(Leader area) { + currentStream.add("ET\n"); + currentStream.add((((float)currentBlockIPPosition) / 1000f) + " " + + ((currentBPPosition + area.getOffset()) / 1000f) + " m\n"); + currentStream.add(((currentBlockIPPosition + area.getWidth()) / 1000f) + " " + ((currentBPPosition + area.getOffset()) / 1000f) + " l\n"); + currentStream.add("S\n"); + currentStream.add("BT\n"); + super.renderLeader(area); + } } diff --git a/src/org/apache/fop/svg/SVGElement.java b/src/org/apache/fop/svg/SVGElement.java index 7f6373536..0bfa212e4 100644 --- a/src/org/apache/fop/svg/SVGElement.java +++ b/src/org/apache/fop/svg/SVGElement.java @@ -97,6 +97,10 @@ public class SVGElement extends SVGObj { return new AffineTransform(); } + public AffineTransform getGlobalTransform() { + return new AffineTransform(); + } + public float getViewportWidth() { return (float)view.getX(); } |