diff options
author | Keiron Liddle <keiron@apache.org> | 2002-09-13 08:21:55 +0000 |
---|---|---|
committer | Keiron Liddle <keiron@apache.org> | 2002-09-13 08:21:55 +0000 |
commit | 6e820767d19b85e1475c6560a887bda5698120d2 (patch) | |
tree | 123e44a06a1b0c28197d91b9406ea1603d0949d5 /src/org | |
parent | cbfb6d81293a14bee16b2a3c41d7fd72bf92ec85 (diff) | |
download | xmlgraphics-fop-6e820767d19b85e1475c6560a887bda5698120d2.tar.gz xmlgraphics-fop-6e820767d19b85e1475c6560a887bda5698120d2.zip |
starting implementation of tables
fixed some more styling errors
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195177 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org')
39 files changed, 2176 insertions, 704 deletions
diff --git a/src/org/apache/fop/apps/StructureHandler.java b/src/org/apache/fop/apps/StructureHandler.java index cdbed0b22..0d68ef8bf 100644 --- a/src/org/apache/fop/apps/StructureHandler.java +++ b/src/org/apache/fop/apps/StructureHandler.java @@ -86,19 +86,19 @@ public class StructureHandler extends AbstractLogEnabled { } - public void startHeader(TableHeader th) { + public void startHeader(TableBody th) { } - public void endHeader(TableHeader th) { + public void endHeader(TableBody th) { } - public void startFooter(TableFooter tf) { + public void startFooter(TableBody tf) { } - public void endFooter(TableFooter tf) { + public void endFooter(TableBody tf) { } diff --git a/src/org/apache/fop/area/Area.java b/src/org/apache/fop/area/Area.java index dd060d1c2..fe9832d1e 100644 --- a/src/org/apache/fop/area/Area.java +++ b/src/org/apache/fop/area/Area.java @@ -1,6 +1,6 @@ /* * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ @@ -24,38 +24,96 @@ import java.util.HashMap; */ public class Area implements Serializable { // stacking directions + /** + * Stacking left to right + */ public static final int LR = 0; + + /** + * Stacking right to left + */ public static final int RL = 1; + + /** + * Stacking top to bottom + */ public static final int TB = 2; + + /** + * Stacking bottom to top + */ public static final int BT = 3; // orientations for reference areas + /** + * Normal orientation + */ public static final int ORIENT_0 = 0; + + /** + * Rotated 90 degrees clockwise + */ public static final int ORIENT_90 = 1; + + /** + * Rotate 180 degrees + */ public static final int ORIENT_180 = 2; + + /** + * Rotated 270 degrees clockwise + */ public static final int ORIENT_270 = 3; // area class values + + /** + * Normal class + */ public static final int CLASS_NORMAL = 0; + + /** + * Fixed position class + */ public static final int CLASS_FIXED = 1; + + /** + * Absolute position class + */ public static final int CLASS_ABSOLUTE = 2; + + /** + * Before float class + */ public static final int CLASS_BEFORE_FLOAT = 3; + + /** + * Footnote class + */ public static final int CLASS_FOOTNOTE = 4; + + /** + * Side float class + */ public static final int CLASS_SIDE_FLOAT = 5; + // IMPORTANT: make sure this is the maximum + 1 - public static final int CLASS_MAX = CLASS_SIDE_FLOAT+1; + /** + * Maximum class count + */ + public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1; private int areaClass = CLASS_NORMAL; private int ipd; - protected Area parent =null; // Doesn't need to be saved in serialization + protected Area parent = null; // Doesn't need to be saved in serialization public int getAreaClass() { - return areaClass; + return areaClass; } public void setAreaClass(int areaClass) { - this.areaClass = areaClass; + this.areaClass = areaClass; } public void setIPD(int i) { @@ -73,7 +131,7 @@ public class Area implements Serializable { * and its current content. */ public MinOptMax getAvailBPD() { - return MinOptMax.subtract(getMaxBPD(), getContentBPD()); + return MinOptMax.subtract(getMaxBPD(), getContentBPD()); } /** @@ -85,10 +143,11 @@ public class Area implements Serializable { * for the sizes of the conditional areas. */ public MinOptMax getMaxBPD() { - if (parent != null) { - return parent.getMaxBPD(); - } - else return new MinOptMax(); + if (parent != null) { + return parent.getMaxBPD(); + } else { + return new MinOptMax(); + } } /** @@ -98,7 +157,7 @@ public class Area implements Serializable { * the area. */ public MinOptMax getContentBPD() { - return new MinOptMax(); + return new MinOptMax(); } /** @@ -112,11 +171,11 @@ public class Area implements Serializable { * to the allocation BPD, depending on conditionality. */ public MinOptMax getAllocationBPD() { - return getContentBPD(); + return getContentBPD(); } public void setParent(Area parent) { - this.parent = parent; + this.parent = parent; } // Do nothing! Let subclasses do something if they can have child areas. @@ -141,10 +200,11 @@ public class Area implements Serializable { } public HashMap getTraits() { - return this.props; + return this.props; } public Object getTrait(Object oTraitCode) { - return (props != null? props.get(oTraitCode) : null); + return (props != null ? props.get(oTraitCode) : null); } } + diff --git a/src/org/apache/fop/area/Block.java b/src/org/apache/fop/area/Block.java index 0d745207c..1c4961d72 100644 --- a/src/org/apache/fop/area/Block.java +++ b/src/org/apache/fop/area/Block.java @@ -24,10 +24,14 @@ public class Block extends BlockParent implements Serializable { public static final int STACK = 0; // placed relative to the parent area public static final int RELATIVE = 1; - // placed relative to the page or viewport + + /** + * Relative to the block parent but not effecting the stacking + * Used for block-container, tables and lists. + */ public static final int ABSOLUTE = 2; - int stacking = TB; + private int stacking = TB; // list of marker fo objects that are associated with this area // if a retrieve marker resolves this area it will format the @@ -45,6 +49,7 @@ public class Block extends BlockParent implements Serializable { if (children == null) { children = new ArrayList(); } + height += block.getHeight(); children.add(block); } @@ -52,6 +57,7 @@ public class Block extends BlockParent implements Serializable { if (children == null) { children = new ArrayList(); } + height += line.getHeight(); children.add(line); } diff --git a/src/org/apache/fop/area/BlockParent.java b/src/org/apache/fop/area/BlockParent.java index f265e6d10..90f494e27 100644 --- a/src/org/apache/fop/area/BlockParent.java +++ b/src/org/apache/fop/area/BlockParent.java @@ -20,7 +20,10 @@ public class BlockParent extends Area implements Serializable { // this position is used for absolute position // or as an indent // this has the size in the block progression dimension - Rectangle2D bounds = null; + protected int xOffset = 0; + protected int yOffset = 0; + protected int width = 0; + protected int height = 0; ArrayList children = null; @@ -38,11 +41,36 @@ public class BlockParent extends Area implements Serializable { return children; } - public void setBounds(Rectangle2D b) { - bounds = b; + public void setXOffset(int off) { + xOffset = off; } - public Rectangle2D getBounds() { - return bounds; + public void setYOffset(int off) { + yOffset = off; } + + public void setWidth(int w) { + width = w; + } + + public void setHeight(int h) { + height = h; + } + + public int getXOffset() { + return xOffset; + } + + public int getYOffset() { + return yOffset; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + } diff --git a/src/org/apache/fop/area/Trait.java b/src/org/apache/fop/area/Trait.java index 06fcd75f4..8d2f06e29 100644 --- a/src/org/apache/fop/area/Trait.java +++ b/src/org/apache/fop/area/Trait.java @@ -19,155 +19,153 @@ import java.util.Iterator; // properties should be serialized by the holder public class Trait implements Serializable { public static final Integer ID_LINK = new Integer(0); - public static final Integer INTERNAL_LINK = new Integer(1); //resolved - public static final Integer EXTERNAL_LINK = new Integer(2); - public static final Integer FONT_NAME = new Integer(3); - public static final Integer FONT_SIZE = new Integer(4); - public static final Integer COLOR = new Integer(7); - public static final Integer ID_AREA = new Integer(8); - public static final Integer BACKGROUND = new Integer(9); - public static final Integer UNDERLINE = new Integer(10); - public static final Integer OVERLINE = new Integer(11); - public static final Integer LINETHROUGH = new Integer(12); - public static final Integer OFFSET = new Integer(13); - public static final Integer SHADOW = new Integer(14); - public static final Integer BORDER_START = new Integer(15); - public static final Integer BORDER_END = new Integer(16); - public static final Integer BORDER_BEFORE = new Integer(17); - public static final Integer BORDER_AFTER = new Integer(18); - public static final Integer PADDING_START = new Integer(19); - public static final Integer PADDING_END = new Integer(20); - public static final Integer PADDING_BEFORE = new Integer(21); - public static final Integer PADDING_AFTER = new Integer(22); + public static final Integer INTERNAL_LINK = new Integer(1); //resolved + public static final Integer EXTERNAL_LINK = new Integer(2); + public static final Integer FONT_NAME = new Integer(3); + public static final Integer FONT_SIZE = new Integer(4); + public static final Integer COLOR = new Integer(7); + public static final Integer ID_AREA = new Integer(8); + public static final Integer BACKGROUND = new Integer(9); + public static final Integer UNDERLINE = new Integer(10); + public static final Integer OVERLINE = new Integer(11); + public static final Integer LINETHROUGH = new Integer(12); + public static final Integer OFFSET = new Integer(13); + public static final Integer SHADOW = new Integer(14); + public static final Integer BORDER_START = new Integer(15); + public static final Integer BORDER_END = new Integer(16); + public static final Integer BORDER_BEFORE = new Integer(17); + public static final Integer BORDER_AFTER = new Integer(18); + public static final Integer PADDING_START = new Integer(19); + public static final Integer PADDING_END = new Integer(20); + public static final Integer PADDING_BEFORE = new Integer(21); + public static final Integer PADDING_AFTER = new Integer(22); static HashMap s_hmTraitInfo; private static class TraitInfo { - String sName; - Class sClass; // Class of trait data - TraitInfo(String sName, Class sClass) { - this.sName = sName; - this.sClass = sClass; - } + String sName; + Class sClass; // Class of trait data + TraitInfo(String sName, Class sClass) { + this.sName = sName; + this.sClass = sClass; + } } static { - // Create a hashmap mapping trait code to name for external representation - s_hmTraitInfo = new HashMap(); - s_hmTraitInfo.put(ID_LINK, - new TraitInfo("id-link", String.class)); - s_hmTraitInfo.put(INTERNAL_LINK, - new TraitInfo("internal-link", PageViewport.class)); - s_hmTraitInfo.put(EXTERNAL_LINK, - new TraitInfo("external-link", String.class)); - s_hmTraitInfo.put(FONT_NAME, - new TraitInfo("font-family", String.class)); - s_hmTraitInfo.put(FONT_SIZE, - new TraitInfo("font-size", Integer.class)); - s_hmTraitInfo.put(COLOR, - new TraitInfo("color", String.class)); - s_hmTraitInfo.put(ID_AREA, - new TraitInfo("id-area", String.class)); - s_hmTraitInfo.put(BACKGROUND, - new TraitInfo("background", String.class)); - s_hmTraitInfo.put(UNDERLINE, - new TraitInfo("underline", Integer.class)); - s_hmTraitInfo.put(OVERLINE, - new TraitInfo("overline", Integer.class)); - s_hmTraitInfo.put(LINETHROUGH, - new TraitInfo("linethrough", Integer.class)); - s_hmTraitInfo.put(OFFSET, - new TraitInfo("offset", Integer.class)); - s_hmTraitInfo.put(SHADOW, - new TraitInfo("shadow", Integer.class)); - s_hmTraitInfo.put(BORDER_START, - new TraitInfo("border-start", BorderProps.class)); - s_hmTraitInfo.put(BORDER_END, - new TraitInfo("border-end", BorderProps.class)); - s_hmTraitInfo.put(BORDER_BEFORE, - new TraitInfo("border-before", BorderProps.class)); - s_hmTraitInfo.put(BORDER_AFTER, - new TraitInfo("border-after", BorderProps.class)); - s_hmTraitInfo.put(PADDING_START, - new TraitInfo("padding-start", Integer.class)); - s_hmTraitInfo.put(PADDING_END, - new TraitInfo("padding-end", Integer.class)); - s_hmTraitInfo.put(PADDING_BEFORE, - new TraitInfo("padding-before", Integer.class)); - s_hmTraitInfo.put(PADDING_AFTER, - new TraitInfo("padding-after", Integer.class)); + // Create a hashmap mapping trait code to name for external representation + s_hmTraitInfo = new HashMap(); + s_hmTraitInfo.put(ID_LINK, new TraitInfo("id-link", String.class)); + s_hmTraitInfo.put(INTERNAL_LINK, + new TraitInfo("internal-link", PageViewport.class)); + s_hmTraitInfo.put(EXTERNAL_LINK, + new TraitInfo("external-link", String.class)); + s_hmTraitInfo.put(FONT_NAME, + new TraitInfo("font-family", String.class)); + s_hmTraitInfo.put(FONT_SIZE, + new TraitInfo("font-size", Integer.class)); + s_hmTraitInfo.put(COLOR, new TraitInfo("color", String.class)); + s_hmTraitInfo.put(ID_AREA, new TraitInfo("id-area", String.class)); + s_hmTraitInfo.put(BACKGROUND, + new TraitInfo("background", Background.class)); + s_hmTraitInfo.put(UNDERLINE, + new TraitInfo("underline", Integer.class)); + s_hmTraitInfo.put(OVERLINE, + new TraitInfo("overline", Integer.class)); + s_hmTraitInfo.put(LINETHROUGH, + new TraitInfo("linethrough", Integer.class)); + s_hmTraitInfo.put(OFFSET, new TraitInfo("offset", Integer.class)); + s_hmTraitInfo.put(SHADOW, new TraitInfo("shadow", Integer.class)); + s_hmTraitInfo.put(BORDER_START, + new TraitInfo("border-start", BorderProps.class)); + s_hmTraitInfo.put(BORDER_END, + new TraitInfo("border-end", BorderProps.class)); + s_hmTraitInfo.put(BORDER_BEFORE, + new TraitInfo("border-before", BorderProps.class)); + s_hmTraitInfo.put(BORDER_AFTER, + new TraitInfo("border-after", BorderProps.class)); + s_hmTraitInfo.put(PADDING_START, + new TraitInfo("padding-start", Integer.class)); + s_hmTraitInfo.put(PADDING_END, + new TraitInfo("padding-end", Integer.class)); + s_hmTraitInfo.put(PADDING_BEFORE, + new TraitInfo("padding-before", Integer.class)); + s_hmTraitInfo.put(PADDING_AFTER, + new TraitInfo("padding-after", Integer.class)); } public static String getTraitName(Object traitCode) { - Object obj = s_hmTraitInfo.get(traitCode); - if (obj != null) { - return ((TraitInfo)obj).sName; - } - else { - return "unknown-trait-" + traitCode.toString(); - } + Object obj = s_hmTraitInfo.get(traitCode); + if (obj != null) { + return ((TraitInfo) obj).sName; + } else { + return "unknown-trait-" + traitCode.toString(); + } } public static Object getTraitCode(String sTraitName) { - Iterator iter = s_hmTraitInfo.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Map.Entry)iter.next(); - TraitInfo ti = (TraitInfo)entry.getValue(); - if (ti != null && ti.sName.equals(sTraitName)) { - return entry.getKey(); - } - } - return null; + Iterator iter = s_hmTraitInfo.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + TraitInfo ti = (TraitInfo) entry.getValue(); + if (ti != null && ti.sName.equals(sTraitName)) { + return entry.getKey(); + } + } + return null; } private static Class getTraitClass(Object oTraitCode) { - TraitInfo ti = (TraitInfo)s_hmTraitInfo.get(oTraitCode); - return (ti != null? ti.sClass : null); + TraitInfo ti = (TraitInfo) s_hmTraitInfo.get(oTraitCode); + return (ti != null ? ti.sClass : null); } public Object propType; public Object data; public Trait() { - this.propType = null; - this.data = null; + this.propType = null; + this.data = null; } public Trait(Object propType, Object data) { - this.propType = propType; - this.data = data; + this.propType = propType; + this.data = data; } public String toString() { - return data.toString(); + return data.toString(); } public static Object makeTraitValue(Object oCode, String sTraitValue) { - // Get the code from the name - // See what type of object it is - // Convert string value to an object of that type - Class tclass = getTraitClass(oCode); - if (tclass == null) return null; - if (tclass.equals(String.class)) { - return sTraitValue; - } - if (tclass.equals(Integer.class)) { - return new Integer(sTraitValue); - } - // See if the class has a constructor from string or can read from a string - try { - Object o = tclass.newInstance(); - //return o.fromString(sTraitValue); - } catch (IllegalAccessException e1) { - System.err.println("Can't create instance of " + tclass.getName()); - return null; - } catch (InstantiationException e2) { - System.err.println("Can't create instance of " + tclass.getName()); - return null; - } - - - return null; + // Get the code from the name + // See what type of object it is + // Convert string value to an object of that type + Class tclass = getTraitClass(oCode); + if (tclass == null) + return null; + if (tclass.equals(String.class)) { + return sTraitValue; + } + if (tclass.equals(Integer.class)) { + return new Integer(sTraitValue); + } + // See if the class has a constructor from string or can read from a string + try { + Object o = tclass.newInstance(); + //return o.fromString(sTraitValue); + } catch (IllegalAccessException e1) { + System.err.println("Can't create instance of " + + tclass.getName()); + return null; + } + catch (InstantiationException e2) { + System.err.println("Can't create instance of " + + tclass.getName()); + return null; + } + + + return null; } public static class Background { diff --git a/src/org/apache/fop/fo/FOElementMapping.java b/src/org/apache/fop/fo/FOElementMapping.java index 0599b9a2f..543f3cd0b 100644 --- a/src/org/apache/fop/fo/FOElementMapping.java +++ b/src/org/apache/fop/fo/FOElementMapping.java @@ -72,8 +72,8 @@ public class FOElementMapping implements ElementMapping { foObjs.put("table", new Ta()); foObjs.put("table-column", new TC()); foObjs.put("table-caption", new TCaption()); - foObjs.put("table-header", new TH()); - foObjs.put("table-footer", new TF()); + foObjs.put("table-header", new TB()); + foObjs.put("table-footer", new TB()); foObjs.put("table-body", new TB()); foObjs.put("table-row", new TR()); foObjs.put("table-cell", new TCell()); @@ -323,18 +323,6 @@ public class FOElementMapping implements ElementMapping { } } - static class TH extends ElementMapping.Maker { - public FONode make(FONode parent) { - return new TableHeader(parent); - } - } - - static class TF extends ElementMapping.Maker { - public FONode make(FONode parent) { - return new TableFooter(parent); - } - } - static class TB extends ElementMapping.Maker { public FONode make(FONode parent) { return new TableBody(parent); diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java index 53dead6a1..0fb07f47d 100644 --- a/src/org/apache/fop/fo/FObj.java +++ b/src/org/apache/fop/fo/FObj.java @@ -206,6 +206,7 @@ public class FObj extends FONode { /** * Return a LayoutManager responsible for laying out this FObj's content. * Must override in subclasses if their content can be laid out. + * @param list the list to add the layout manager(s) to */ public void addLayoutManager(List list) { } diff --git a/src/org/apache/fop/fo/FObjMixed.java b/src/org/apache/fop/fo/FObjMixed.java index f0a0d1f7e..9e8dd79dc 100644 --- a/src/org/apache/fop/fo/FObjMixed.java +++ b/src/org/apache/fop/fo/FObjMixed.java @@ -35,17 +35,8 @@ public class FObjMixed extends FObj { } public void addLayoutManager(List lms) { - lms.add(new InlineStackingLayoutManager(this, + lms.add(new InlineStackingLayoutManager(this, new LMiter(children.listIterator()))); - // 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); -// } -// } } protected void addCharacters(char data[], int start, int length) { diff --git a/src/org/apache/fop/fo/flow/Footnote.java b/src/org/apache/fop/fo/flow/Footnote.java index 9ab5e13e2..4520ce636 100644 --- a/src/org/apache/fop/fo/flow/Footnote.java +++ b/src/org/apache/fop/fo/flow/Footnote.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.ArrayList; public class Footnote extends FObj { + Inline inlineFO = null; + FootnoteBody body; public Footnote(FONode parent) { super(parent); @@ -29,9 +31,22 @@ public class Footnote extends FObj { public void addLayoutManager(List lms) { // add inlines layout manager - //inline.addLayoutManager(lms); - // set start and end footnote reference + if(inlineFO == null) { + getLogger().error("inline required in footnote"); + return; + } + inlineFO.addLayoutManager(lms); } + public void addChild(FONode child) { + String name = child.getName(); + if ("fo:inline".equals(name)) { + inlineFO = (Inline)child; + } else if ("fo:footnote-body".equals(name)) { + body = (FootnoteBody)child; + } else { + getLogger().error("invalid child of footnote: " + name); + } + } } diff --git a/src/org/apache/fop/fo/flow/Leader.java b/src/org/apache/fop/fo/flow/Leader.java index be4274cc3..54779f7ec 100644 --- a/src/org/apache/fop/fo/flow/Leader.java +++ b/src/org/apache/fop/fo/flow/Leader.java @@ -36,8 +36,7 @@ import java.util.ArrayList; /** * Implements fo:leader; main property of leader leader-pattern. - * The following patterns are treated: rule, space, dots. - * The pattern use-content is ignored, i.e. it still must be implemented. + * The following patterns are treated: rule, space, dots and use-content. */ public class Leader extends FObjMixed { int ruleStyle; @@ -61,6 +60,12 @@ public class Leader extends FObjMixed { protected MinOptMax getAllocationIPD(int refIPD) { return getAllocIPD(refIPD); } + + /*protected void offsetArea(LayoutContext context) { + if(leaderPattern == LeaderPattern.DOTS) { + curArea.setOffset(context.getBaseline()); + } + }*/ }; lm.setAlignment(properties.get("leader-alignment").getEnum()); list.add(lm); @@ -87,7 +92,7 @@ public class Leader extends FObjMixed { leaderArea = new Space(); } else if(leaderPattern == LeaderPattern.DOTS) { Word w = new Word(); - char dot = '.'; // userAgent.getLeaderDotChar(); + char dot = '.'; // userAgent.getLeaderDotCharacter(); w.setWord("" + dot); w.addTrait(Trait.FONT_NAME, fontState.getFontName()); @@ -108,6 +113,7 @@ public class Leader extends FObjMixed { if(spacer != null) { fa.addChild(spacer); } + fa.setHeight(fontState.getAscender()); leaderArea = fa; } else if(leaderPattern == LeaderPattern.USECONTENT) { diff --git a/src/org/apache/fop/fo/flow/RowSpanMgr.java b/src/org/apache/fop/fo/flow/RowSpanMgr.java deleted file mode 100644 index aaae9fe53..000000000 --- a/src/org/apache/fop/fo/flow/RowSpanMgr.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * -- $Id$ -- - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.fo.flow; - -import java.util.Enumeration; - -public class RowSpanMgr { - class SpanInfo { - int cellHeight; - int totalRowHeight; - int rowsRemaining; - // int numCols; // both V and H span - TableCell cell; - - SpanInfo(TableCell cell, int cellHeight, int rowsSpanned) { - this.cell = cell; - this.cellHeight = cellHeight; - this.totalRowHeight = 0; - this.rowsRemaining = rowsSpanned; - } - - /** - * Return the height remaining in the span. - */ - int heightRemaining() { - int hl = cellHeight - totalRowHeight; - return (hl > 0) ? hl : 0; - } - - boolean isInLastRow() { - return (rowsRemaining == 1); - } - - boolean finishRow(int rowHeight) { - totalRowHeight += rowHeight; - if (--rowsRemaining == 0) { - if (cell != null) { - } - return true; - } else - return false; - } - - } - - private SpanInfo spanInfo[]; - - public RowSpanMgr(int numCols) { - this.spanInfo = new SpanInfo[numCols]; - } - - public void addRowSpan(TableCell cell, int firstCol, int numCols, - int cellHeight, int rowsSpanned) { - spanInfo[firstCol - 1] = new SpanInfo(cell, cellHeight, rowsSpanned); - for (int i = 0; i < numCols - 1; i++) { - spanInfo[firstCol + i] = new SpanInfo(null, cellHeight, - rowsSpanned); // copy! - } - } - - public boolean isSpanned(int colNum) { - return (spanInfo[colNum - 1] != null); - } - - - public TableCell getSpanningCell(int colNum) { - if (spanInfo[colNum - 1] != null) { - return spanInfo[colNum - 1].cell; - } else - return null; - } - - - /** - * Return true if any column has an unfinished vertical span. - */ - public boolean hasUnfinishedSpans() { - for (int i = 0; i < spanInfo.length; i++) { - if (spanInfo[i] != null) - return true; - } - return false; - } - - /** - * Done with a row. - * Any spans with only one row left are done - * This means that we can now set the total height for this cell box - * Loop over all cells with spans and find number of rows remaining - * if rows remaining = 1, set the height on the cell area and - * then remove the cell from the list of spanned cells. For other - * spans, add the rowHeight to the spanHeight. - */ - public void finishRow(int rowHeight) { - for (int i = 0; i < spanInfo.length; i++) { - if (spanInfo[i] != null && spanInfo[i].finishRow(rowHeight)) - spanInfo[i] = null; - } - } - - /** - * If the cell in this column is in the last row of its vertical - * span, return the height left. If it's not in the last row, or if - * the content height <= the content height of the previous rows - * of the span, return 0. - */ - public int getRemainingHeight(int colNum) { - if (spanInfo[colNum - 1] != null) { - return spanInfo[colNum - 1].heightRemaining(); - } else - return 0; - } - - public boolean isInLastRow(int colNum) { - if (spanInfo[colNum - 1] != null) { - return spanInfo[colNum - 1].isInLastRow(); - } else - return false; - } - -} diff --git a/src/org/apache/fop/fo/flow/Table.java b/src/org/apache/fop/fo/flow/Table.java index 526ff429a..848cf34bc 100644 --- a/src/org/apache/fop/fo/flow/Table.java +++ b/src/org/apache/fop/fo/flow/Table.java @@ -14,13 +14,22 @@ import org.apache.fop.layout.*; import org.apache.fop.datatypes.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.table.TableLayoutManager; + // Java import java.util.ArrayList; +import java.util.List; import java.util.Iterator; public class Table extends FObj { - private static final int MINCOLWIDTH = 10000; // 10pt + + protected ArrayList columns = null; + TableBody tableHeader = null; + TableBody tableFooter = null; + boolean omitHeaderAtBreak = false; + boolean omitFooterAtBreak = false; + int breakBefore; int breakAfter; int spaceBefore; @@ -28,14 +37,8 @@ public class Table extends FObj { ColorType backgroundColor; LengthRange ipd; int height; - TableHeader tableHeader = null; - TableFooter tableFooter = null; - boolean omitHeaderAtBreak = false; - boolean omitFooterAtBreak = false; - ArrayList columns = new ArrayList(); - int bodyCount = 0; - private boolean bAutoLayout=false; + private boolean bAutoLayout = false; private int contentWidth = 0; // Sum of column widths /** Optimum inline-progression-dimension */ private int optIPD; @@ -48,65 +51,97 @@ public class Table extends FObj { super(parent); } + protected void addChild(FONode child) { + if(child.getName().equals("fo:table-column")) { + if(columns == null) { + columns = new ArrayList(); + } + columns.add(((TableColumn)child).getLayoutManager()); + } else if(child.getName().equals("fo:table-footer")) { + tableFooter = (TableBody)child; + } else if(child.getName().equals("fo:table-header")) { + tableHeader = (TableBody)child; + } else { + // add bodies + children.add(child); + } + } + + /** + * Return a LayoutManager responsible for laying out this FObj's content. + * Must override in subclasses if their content can be laid out. + */ + public void addLayoutManager(List list) { + TableLayoutManager tlm = new TableLayoutManager(this); + tlm.setColumns(columns); + if(tableHeader != null) { + tlm.setTableHeader(tableHeader.getLayoutManager()); + } + if(tableFooter != null) { + tlm.setTableFooter(tableFooter.getLayoutManager()); + } + list.add(tlm); + } + public void setup() { - // Common Accessibility Properties - AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); - - // Common Aural Properties - AuralProps mAurProps = propMgr.getAuralProps(); - - // Common Border, Padding, and Background Properties - BorderAndPadding bap = propMgr.getBorderAndPadding(); - BackgroundProps bProps = propMgr.getBackgroundProps(); - - // Common Margin Properties-Block - MarginProps mProps = propMgr.getMarginProps(); - - // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); - - // this.properties.get("block-progression-dimension"); - // this.properties.get("border-after-precendence"); - // this.properties.get("border-before-precedence"); - // this.properties.get("border-collapse"); - // this.properties.get("border-end-precendence"); - // this.properties.get("border-separation"); - // this.properties.get("border-start-precendence"); - // this.properties.get("break-after"); - // this.properties.get("break-before"); - setupID(); - // this.properties.get("inline-progression-dimension"); - // this.properties.get("height"); - // this.properties.get("keep-together"); - // this.properties.get("keep-with-next"); - // this.properties.get("keep-with-previous"); - // this.properties.get("table-layout"); - // this.properties.get("table-omit-footer-at-break"); - // this.properties.get("table-omit-header-at-break"); - // this.properties.get("width"); - // this.properties.get("writing-mode"); - - this.breakBefore = this.properties.get("break-before").getEnum(); - this.breakAfter = this.properties.get("break-after").getEnum(); - this.spaceBefore = - this.properties.get("space-before.optimum").getLength().mvalue(); - this.spaceAfter = - this.properties.get("space-after.optimum").getLength().mvalue(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); - this.ipd = - this.properties.get("inline-progression-dimension"). - getLengthRange(); - this.height = this.properties.get("height").getLength().mvalue(); - this.bAutoLayout = (this.properties.get("table-layout").getEnum() == - TableLayout.AUTO); - - this.omitHeaderAtBreak = - this.properties.get("table-omit-header-at-break").getEnum() - == TableOmitHeaderAtBreak.TRUE; - this.omitFooterAtBreak = - this.properties.get("table-omit-footer-at-break").getEnum() - == TableOmitFooterAtBreak.TRUE; + // Common Accessibility Properties + AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); + + // Common Aural Properties + AuralProps mAurProps = propMgr.getAuralProps(); + + // Common Border, Padding, and Background Properties + BorderAndPadding bap = propMgr.getBorderAndPadding(); + BackgroundProps bProps = propMgr.getBackgroundProps(); + + // Common Margin Properties-Block + MarginProps mProps = propMgr.getMarginProps(); + + // Common Relative Position Properties + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); + + // this.properties.get("block-progression-dimension"); + // this.properties.get("border-after-precendence"); + // this.properties.get("border-before-precedence"); + // this.properties.get("border-collapse"); + // this.properties.get("border-end-precendence"); + // this.properties.get("border-separation"); + // this.properties.get("border-start-precendence"); + // this.properties.get("break-after"); + // this.properties.get("break-before"); + setupID(); + // this.properties.get("inline-progression-dimension"); + // this.properties.get("height"); + // this.properties.get("keep-together"); + // this.properties.get("keep-with-next"); + // this.properties.get("keep-with-previous"); + // this.properties.get("table-layout"); + // this.properties.get("table-omit-footer-at-break"); + // this.properties.get("table-omit-header-at-break"); + // this.properties.get("width"); + // this.properties.get("writing-mode"); + + this.breakBefore = this.properties.get("break-before").getEnum(); + this.breakAfter = this.properties.get("break-after").getEnum(); + this.spaceBefore = this.properties.get( + "space-before.optimum").getLength().mvalue(); + this.spaceAfter = this.properties.get( + "space-after.optimum").getLength().mvalue(); + this.backgroundColor = + this.properties.get("background-color").getColorType(); + this.ipd = this.properties.get( + "inline-progression-dimension"). getLengthRange(); + this.height = this.properties.get("height").getLength().mvalue(); + this.bAutoLayout = (this.properties.get("table-layout").getEnum() == + TableLayout.AUTO); + + this.omitHeaderAtBreak = this.properties.get( + "table-omit-header-at-break").getEnum() == + TableOmitHeaderAtBreak.TRUE; + this.omitFooterAtBreak = this.properties.get( + "table-omit-footer-at-break").getEnum() == + TableOmitFooterAtBreak.TRUE; } diff --git a/src/org/apache/fop/fo/flow/TableBody.java b/src/org/apache/fop/fo/flow/TableBody.java index 7d9d07940..b593b2f54 100644 --- a/src/org/apache/fop/fo/flow/TableBody.java +++ b/src/org/apache/fop/fo/flow/TableBody.java @@ -14,8 +14,11 @@ import org.apache.fop.datatypes.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.table.Body; + // Java import java.util.ArrayList; +import java.util.List; import java.util.Iterator; public class TableBody extends FObj { @@ -24,39 +27,46 @@ public class TableBody extends FObj { int spaceAfter; ColorType backgroundColor; - ArrayList columns; - RowSpanMgr rowSpanMgr; // manage information about spanning rows - public TableBody(FONode parent) { super(parent); } - public void setColumns(ArrayList columns) { - this.columns = columns; + /** + * Return a LayoutManager responsible for laying out this FObj's content. + * Must override in subclasses if their content can be laid out. + */ + public void addLayoutManager(List list) { + list.add(getLayoutManager()); + } + + public Body getLayoutManager() { + Body blm = new Body(this); + return blm; } public void setup() throws FOPException { - // Common Accessibility Properties - AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); - - // Common Aural Properties - AuralProps mAurProps = propMgr.getAuralProps(); - - // Common Border, Padding, and Background Properties - BorderAndPadding bap = propMgr.getBorderAndPadding(); - BackgroundProps bProps = propMgr.getBackgroundProps(); - - // Common Relative Position Properties - RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); - - setupID(); - - this.spaceBefore = - this.properties.get("space-before.optimum").getLength().mvalue(); - this.spaceAfter = - this.properties.get("space-after.optimum").getLength().mvalue(); - this.backgroundColor = - this.properties.get("background-color").getColorType(); + // Common Accessibility Properties + AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); + + // Common Aural Properties + AuralProps mAurProps = propMgr.getAuralProps(); + + // Common Border, Padding, and Background Properties + BorderAndPadding bap = propMgr.getBorderAndPadding(); + BackgroundProps bProps = propMgr.getBackgroundProps(); + + // Common Relative Position Properties + RelativePositionProps mRelProps = + propMgr.getRelativePositionProps(); + + setupID(); + + this.spaceBefore = this.properties.get( + "space-before.optimum").getLength().mvalue(); + this.spaceAfter = this.properties.get( + "space-after.optimum").getLength().mvalue(); + this.backgroundColor = + this.properties.get("background-color").getColorType(); } diff --git a/src/org/apache/fop/fo/flow/TableCell.java b/src/org/apache/fop/fo/flow/TableCell.java index 21dc31e71..5fe6caad1 100644 --- a/src/org/apache/fop/fo/flow/TableCell.java +++ b/src/org/apache/fop/fo/flow/TableCell.java @@ -14,8 +14,12 @@ import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.*; +import org.apache.fop.layoutmgr.table.Cell; + import org.xml.sax.Attributes; +import java.util.List; + public class TableCell extends FObj { // int spaceBefore; @@ -92,6 +96,13 @@ public class TableCell extends FObj { doSetup(); // init some basic property values } + /** + */ + public void addLayoutManager(List list) { + Cell clm = new Cell(this); + list.add(clm); + } + // Set position relative to table (set by body?) public void setStartOffset(int offset) { startOffset = offset; diff --git a/src/org/apache/fop/fo/flow/TableColumn.java b/src/org/apache/fop/fo/flow/TableColumn.java index 17390e672..cc014323a 100644 --- a/src/org/apache/fop/fo/flow/TableColumn.java +++ b/src/org/apache/fop/fo/flow/TableColumn.java @@ -14,6 +14,10 @@ import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.*; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.table.Column; + + public class TableColumn extends FObj { ColorType backgroundColor; @@ -30,6 +34,11 @@ public class TableColumn extends FObj { super(parent); } + public LayoutManager getLayoutManager() { + doSetup(); + return new Column(this); + } + public Length getColumnWidthAsLength() { return columnWidthPropVal; } @@ -54,7 +63,7 @@ public class TableColumn extends FObj { return numColumnsRepeated; } - public void doSetup() throws FOPException { + public void doSetup() { // Common Border, Padding, and Background Properties // only background apply, border apply if border-collapse @@ -88,3 +97,4 @@ public class TableColumn extends FObj { } } + diff --git a/src/org/apache/fop/fo/flow/TableRow.java b/src/org/apache/fop/fo/flow/TableRow.java index cec10dde9..fdf2284d5 100644 --- a/src/org/apache/fop/fo/flow/TableRow.java +++ b/src/org/apache/fop/fo/flow/TableRow.java @@ -14,8 +14,11 @@ import org.apache.fop.datatypes.*; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; +import org.apache.fop.layoutmgr.table.Row; + // Java import java.util.ArrayList; +import java.util.List; import java.util.Iterator; public class TableRow extends FObj { @@ -29,140 +32,17 @@ public class TableRow extends FObj { KeepValue keepWithPrevious; KeepValue keepTogether; - int widthOfCellsSoFar = 0; - int largestCellHeight = 0; int minHeight = 0; // force row height - ArrayList columns; - - boolean areaAdded = false; - - private RowSpanMgr rowSpanMgr = null; - private CellArray cellArray = null; - - private static class CellArray { - public static final byte EMPTY = 0; - public static final byte CELLSTART = 1; - public static final byte CELLSPAN = 2; - - private TableCell[] cells; - private byte[] states; - - public CellArray(RowSpanMgr rsi, int numColumns) { - // Initialize the cell array by marking any cell positions - // occupied by spans from previous rows - cells = new TableCell[numColumns]; - states = new byte[numColumns]; - for (int i = 0; i < numColumns; i++) { - if (rsi.isSpanned(i + 1)) { - cells[i] = rsi.getSpanningCell(i + 1); - states[i] = CELLSPAN; - } else - states[i] = EMPTY; - } - } - - /** - * Return column which doesn't already contain a span or a cell - * If past the end or no free cells after colNum, return -1 - * Otherwise return value >= input value. - */ - int getNextFreeCell(int colNum) { - for (int i = colNum - 1; i < states.length; i++) { - if (states[i] == EMPTY) - return i + 1; - } - return -1; - } - - - /** - * Return type of cell in colNum (1 based) - */ - int getCellType(int colNum) { - if (colNum > 0 && colNum <= cells.length) { - return states[colNum - 1]; - } else - return -1; // probably should throw exception - } - - /** - * Return cell in colNum (1 based) - */ - TableCell getCell(int colNum) { - if (colNum > 0 && colNum <= cells.length) { - return cells[colNum - 1]; - } else - return null; // probably should throw exception - } - - /** - * Store cell starting at cellColNum (1 based) and spanning numCols - * If any of the columns is already occupied, return false, else true - */ - boolean storeCell(TableCell cell, int colNum, int numCols) { - boolean rslt = true; - int index = colNum - 1; - for (int count = 0; index < cells.length && count < numCols; - count++, index++) { - if (cells[index] == null) { - cells[index] = cell; - states[index] = (count == 0) ? CELLSTART : CELLSPAN; - } else { - rslt = false; - // print a message but continue!!! - } - } - return rslt; - } - - // private class EnumCells implements Enumeration { - // private int iNextIndex=0; - // private Object nextCell = null; - // EnumCells() { - // findNextCell(); - // } - - // private void findNextCell() { - // for (; iNextIndex < cells.length; iNextIndex++) { - // if (states[iNextIndex] == CELLSTART) { - // nextCell = cells[iNextIndex]; - // return; - // } - // } - // nextCell = null; - // } - - // public boolean hasMoreElements() { - // return (nextCell != null); - // } - - // public Object nextElement() { - // if (nextCell != null) { - // Object cell = nextCell; - // findNextCell(); - // return cell; - // } - // else throw new java.util.NoSuchElementException("No more cells"); - // } - // } - - // /** - // * Return an enumeration over all cells in this row - // * Return each element in cells whose state is CELLSTART or EMPTY? - // * Skip spanning elements. - // */ - // Enumeration getCells() { - // return new EnumCells(); - // } - } - public TableRow(FONode parent) { super(parent); } - public void setColumns(ArrayList columns) { - this.columns = columns; + /** + */ + public void addLayoutManager(List list) { + Row rlm = new Row(this); + list.add(rlm); } public KeepValue getKeepWithPrevious() { @@ -225,78 +105,5 @@ public class TableRow extends FObj { // break; } } - - /** - * Called by parent FO to initialize information about - * cells started in previous rows which span into this row. - * The layout operation modifies rowSpanMgr - */ - public void setRowSpanMgr(RowSpanMgr rowSpanMgr) { - this.rowSpanMgr = rowSpanMgr; - } - - /** - * Before starting layout for the first time, initialize information - * about spanning rows, empty cells and spanning columns. - */ - private void initCellArray() { - cellArray = new CellArray(rowSpanMgr, columns.size()); - int colNum = 1; - Iterator eCells = children.iterator(); - while (eCells.hasNext()) { - colNum = cellArray.getNextFreeCell(colNum); - // If off the end, the rest of the cells had better be - // explicitly positioned!!! (returns -1) - - TableCell cell = (TableCell)eCells.next(); - int numCols = cell.getNumColumnsSpanned(); - int numRows = cell.getNumRowsSpanned(); - int cellColNum = cell.getColumnNumber(); - - if (cellColNum == 0) { - // Not explicitly specified, so put in next available colummn - // cell.setColumnNumber(colNum); - // If cellColNum "off the end", this cell is in limbo! - if (colNum < 1) { - // ERROR!!! - continue; - } else - cellColNum = colNum; - } else if (cellColNum > columns.size()) { - // Explicit specification out of range! - // Skip it and print an ERROR MESSAGE - continue; - } - // see if it fits and doesn't overwrite anything - if (cellColNum + numCols - 1 > columns.size()) { - // MESSAGE: TOO MANY COLUMNS SPANNED! - numCols = columns.size() - cellColNum + 1; - } - // Check for overwriting other cells (returns false) - if (cellArray.storeCell(cell, cellColNum, numCols) == false) { - // Print out some kind of warning message. - } - if (cellColNum > colNum) { - // Cells are initialized as empty already - colNum = cellColNum; - } else if (cellColNum < colNum) { - // MESSAGE ? cells out of order? - colNum = cellColNum; // CR "to the letter"! - } - int cellWidth = getCellWidth(cellColNum, numCols); - cell.setWidth(cellWidth); - colNum += numCols; // next cell in this column - } - } - - // ATTENTION if startCol + numCols > number of columns in table! - private int getCellWidth(int startCol, int numCols) { - int width = 0; - for (int count = 0; count < numCols; count++) { - width += ((TableColumn)columns.get(startCol + count - - 1)).getColumnWidth(); - } - return width; - } - } + diff --git a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 519eaade8..34682b143 100644 --- a/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -8,14 +8,12 @@ package org.apache.fop.layoutmgr; import org.apache.fop.fo.FObj; -import org.apache.fop.fo.FONode; import org.apache.fop.area.Area; import org.apache.fop.area.Resolveable; import org.apache.fop.area.PageViewport; import org.apache.fop.fo.PropertyManager; import java.util.ListIterator; -import java.util.ArrayList; /** * The base class for all LayoutManagers. @@ -106,18 +104,10 @@ public abstract class AbstractLayoutManager implements LayoutManager { return m_curChildLM; } while (m_childLMiter.hasNext()) { - Object obj = m_childLMiter.next(); - if (obj instanceof LayoutManager) { - m_curChildLM = (LayoutManager) obj; - m_curChildLM.setParentLM(this); - m_curChildLM.init(); - return m_curChildLM; - } else { - m_childLMiter.remove(); - //log.warn( - // "child LM not a LayoutManager: " + - // obj.getClass().getName()); - } + m_curChildLM = (LayoutManager) m_childLMiter.next(); + m_curChildLM.setParentLM(this); + m_curChildLM.init(); + return m_curChildLM; } return null; } @@ -257,26 +247,69 @@ public abstract class AbstractLayoutManager implements LayoutManager { return false; } + /** + * Delegate getting the current page number to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ public String getCurrentPageNumber() { return parentLM.getCurrentPageNumber(); } + /** + * Delegate resolving the id reference to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ public PageViewport resolveRefID(String ref) { return parentLM.resolveRefID(ref); } + /** + * Add the id to the page. + * If the id string is not null then add the id to the current page. + */ protected void addID() { if(foID != null) { addIDToPage(foID); } } + /** + * Delegate adding id reference to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ public void addIDToPage(String id) { parentLM.addIDToPage(id); } + /** + * Delegate adding unresolved area to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ public void addUnresolvedArea(String id, Resolveable res) { parentLM.addUnresolvedArea(id, res); } + + /** + * Delegate adding marker to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ + public void addMarker(String name, LayoutManager lm, boolean start) { + parentLM.addMarker(name, lm, start); + } + + /** + * Delegate retrieve marker to the parent layout manager. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ + public LayoutManager retrieveMarker(String name, int pos, int boundary) { + return parentLM.retrieveMarker(name, pos, boundary); + } + } diff --git a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 4c6ea73ff..dbca5cdd0 100644 --- a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -231,27 +231,26 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { if (curBlockArea == null) { viewportBlockArea = new BlockViewport(); if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { - Rectangle2D rect = new Rectangle2D.Double(abProps.left, - abProps.top, abProps.right - abProps.left, - abProps.bottom - abProps.top); - viewportBlockArea.setBounds(rect); + viewportBlockArea.setXOffset(abProps.left); + viewportBlockArea.setYOffset(abProps.top); + viewportBlockArea.setWidth(abProps.right - abProps.left); + viewportBlockArea.setHeight(abProps.bottom - abProps.top); + viewportBlockArea.setCTM(absoluteCTM); viewportBlockArea.setClip(clip); } else { double[] vals = absoluteCTM.toArray(); boolean rotated = vals[0] == 0.0; if(rotated) { - Rectangle2D rect = new Rectangle2D.Double(0, 0, - relDims.bpd, getRotatedIPD()); - viewportBlockArea.setBounds(rect); + viewportBlockArea.setWidth(relDims.bpd); + viewportBlockArea.setHeight(getRotatedIPD()); viewportBlockArea.setCTM(absoluteCTM); viewportBlockArea.setClip(clip); } else if(vals[0] == -1.0) { // need to set bpd to actual size for rotation // and stacking - Rectangle2D rect = new Rectangle2D.Double(0, 0, - relDims.ipd, relDims.bpd); - viewportBlockArea.setBounds(rect); + viewportBlockArea.setWidth(relDims.ipd); + viewportBlockArea.setWidth(relDims.bpd); viewportBlockArea.setCTM(absoluteCTM); viewportBlockArea.setClip(clip); } @@ -289,5 +288,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { reset(null); } } + + public void addMarker(String name, LayoutManager lm, boolean start) { + parentLM.addMarker(name, lm, start); + } + } diff --git a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java index bf507a965..ec6e58c18 100644 --- a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -211,20 +211,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { 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 { curBlockArea.addBlock((Block) childArea); - //return super.addChild(childArea); return false; } diff --git a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 1b091a662..249500931 100644 --- a/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -1,6 +1,6 @@ /* * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ @@ -48,8 +48,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { this.parentArea = parentArea; } - - protected MinOptMax resolveSpaceSpecifier(Area nextArea) { SpaceSpecifier spaceSpec = new SpaceSpecifier(false); // Area prevArea = getCurrentArea().getLast(); @@ -126,8 +124,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager { * Force current area to be added to parent area. */ protected boolean flush() { - if (getCurrentArea() != null) + if (getCurrentArea() != null) { return parentLM.addChild(getCurrentArea()); + } return false; } diff --git a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java index b9342b28c..9d9eaf5d5 100644 --- a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java +++ b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java @@ -13,7 +13,7 @@ import java.util.List; public class BreakPossPosIter extends PositionIterator { private int m_iterCount ; - BreakPossPosIter(List bpList, int startPos, int endPos) { + public BreakPossPosIter(List bpList, int startPos, int endPos) { super(bpList.listIterator(startPos)); m_iterCount = endPos - startPos; } diff --git a/src/org/apache/fop/layoutmgr/ContentLayoutManager.java b/src/org/apache/fop/layoutmgr/ContentLayoutManager.java index 7ca005c0c..a27d7f120 100644 --- a/src/org/apache/fop/layoutmgr/ContentLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/ContentLayoutManager.java @@ -178,5 +178,15 @@ public class ContentLayoutManager implements LayoutManager { public void addUnresolvedArea(String id, Resolveable res) { parentLM.addUnresolvedArea(id, res); } + + /** @see org.apache.fop.layoutmgr.LayoutManager */ + public void addMarker(String name, LayoutManager lm, boolean start) { + parentLM.addMarker(name, lm, start); + } + + /** @see org.apache.fop.layoutmgr.LayoutManager */ + public LayoutManager retrieveMarker(String name, int pos, int boundary) { + return parentLM.retrieveMarker(name, pos, boundary); + } } diff --git a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java index 4b12bd385..4d4dc0e02 100644 --- a/src/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -138,5 +138,16 @@ public class FlowLayoutManager extends BlockStackingLayoutManager { reset(null); } } + + /** + * Retrieve marker is not allowed in the flow so this reports an + * error and returns null. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ + public LayoutManager retrieveMarker(String name, int pos, int boundary) { + // error cannot retrieve markers in flow + return null; + } } diff --git a/src/org/apache/fop/layoutmgr/LayoutManager.java b/src/org/apache/fop/layoutmgr/LayoutManager.java index cac65a075..664730fd9 100644 --- a/src/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LayoutManager.java @@ -64,11 +64,60 @@ public interface LayoutManager { public void getWordChars(StringBuffer sbChars, Position bp1, Position bp2); + /** + * Get the string of the current page number. + * + * @return the string for the current page number + */ public String getCurrentPageNumber(); + /** + * Resolve the id reference. + * This is called by an area looking for an id reference. + * If the id reference is not found then it should add a resolveable object. + * + * @param ref the id reference + * @return the page containing the id reference or null if not found + */ public PageViewport resolveRefID(String ref); + /** + * Add an id to the page. + * @todo add the location of the area on the page + * + * @param id the id reference to add. + */ public void addIDToPage(String id); + /** + * Add an unresolved area. + * The is used to add a resolveable object to the page for a given id. + * + * @param id the id reference this object needs for resolving + * @param res the resolveable object + */ public void addUnresolvedArea(String id, Resolveable res); + + /** + * Add the marker. + * A number of formatting objects may contain markers. This + * method is used to add those markers to the page. + * + * @param name the marker class name + * @param lm the layout manager of the marker child + * @param start true if the formatting object is starting false is finishing + */ + public void addMarker(String name, LayoutManager lm, boolean start); + + /** + * Retrieve a marker. + * This method is used when retrieve a marker. + * + * @param name the class name of the marker + * @param pos the retrieve position + * @param boundary the boundary for retrieving the marker + * @return the layout manaager of the retrieved marker if any + */ + public LayoutManager retrieveMarker(String name, int pos, int boundary); + } diff --git a/src/org/apache/fop/layoutmgr/PageLayoutManager.java b/src/org/apache/fop/layoutmgr/PageLayoutManager.java index a1a09d6f7..c22bc589e 100644 --- a/src/org/apache/fop/layoutmgr/PageLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/PageLayoutManager.java @@ -164,6 +164,19 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable areaTree.addUnresolvedID(id, curPage); } + public void addMarker(String name, LayoutManager lm, boolean start) { + if(start) { + // add marker to page on area tree + } else { + // add end marker to page on area tree + } + } + + public LayoutManager retrieveMarker(String name, int pos, int boundary) { + // get marker from the current markers on area tree + return null; + } + /** * For now, only handle normal flow areas. */ diff --git a/src/org/apache/fop/layoutmgr/PositionIterator.java b/src/org/apache/fop/layoutmgr/PositionIterator.java index 66d5e3a3e..5e951a09f 100644 --- a/src/org/apache/fop/layoutmgr/PositionIterator.java +++ b/src/org/apache/fop/layoutmgr/PositionIterator.java @@ -23,7 +23,7 @@ public abstract class PositionIterator implements Iterator { //checkNext(); } - LayoutManager getNextChildLM() { + public LayoutManager getNextChildLM() { // Move to next "segment" of iterator, ie: new childLM if (m_childLM == null && m_nextObj != null) { m_childLM = getLM(m_nextObj); diff --git a/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 9932e1a45..b4c673e74 100644 --- a/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -1,19 +1,18 @@ /* * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ package org.apache.fop.layoutmgr; -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FObj; -import org.apache.fop.fo.properties.Constants; -import org.apache.fop.area.*; +import org.apache.fop.area.RegionReference; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import java.util.ArrayList; -import java.util.List; /** * LayoutManager for an fo:flow object. @@ -24,7 +23,7 @@ import java.util.List; public class StaticContentLayoutManager extends BlockStackingLayoutManager { private RegionReference region; - ArrayList blockBreaks = new ArrayList(); + private ArrayList blockBreaks = new ArrayList(); public StaticContentLayoutManager(FObj fobj) { super(fobj); @@ -46,7 +45,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { if (!curLM.isFinished()) { if ((bp = curLM.getNextBreakPoss(childLC)) != null) { blockBreaks.add(bp); - if(bp.isForcedBreak()) { + if (bp.isForcedBreak()) { System.out.println("Forced breaks are not allowed in static content"); return null; } @@ -98,5 +97,14 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { return region; } + /** + * Markers are not allowed in static areas so this reports an + * error and does nothing. + * + * @see org.apache.fop.layoutmgr.LayoutManager + */ + public void addMarker(String name, LayoutManager lm, boolean start) { + // error markers not allowed in static + } } diff --git a/src/org/apache/fop/layoutmgr/table/Body.java b/src/org/apache/fop/layoutmgr/table/Body.java new file mode 100644 index 000000000..902c14bea --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/Body.java @@ -0,0 +1,213 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.MinOptMax; + +import java.util.ArrayList; +import java.util.List; + +/** + * LayoutManager for a table-header, table-footer and table body FO. + * These fo objects have either rows or cells underneath. + * Cells are organised into rows. + */ +public class Body extends BlockStackingLayoutManager { + + private boolean rows = true; + private List columns; + + private int yoffset; + private int bodyHeight; + + private Block curBlockArea; + + private ArrayList childBreaks = new ArrayList(); + + /** + * Create a new body layout manager. + * + * @param fobj the formatting object that created this manager + */ + public Body(FObj fobj) { + super(fobj); + } + + /** + * Set the columns from the table. + * + * @param cols the list of columns used for this body + */ + public void setColumns(List cols) { + columns = cols; + } + + /** + * Breaks for this layout manager are of the form of before + * or after a row and inside a row. + * + * @param context the layout context for finding the breaks + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + Row curLM; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + BreakPoss lastPos = null; + + while ((curLM = (Row)getChildLM()) != null) { + // Make break positions + // Set up a LayoutContext + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit( + MinOptMax.subtract(context.getStackLimit(), + stackSize)); + childLC.setRefIPD(ipd); + + curLM.setColumns(columns); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + + setFinished(true); + return null; + } + + /** + * Set the y offset of this body within the table. + * This is used to set the row offsets. + * + * @param off the y offset position + */ + public void setYOffset(int off) { + yoffset = off; + } + + /** + * Add the areas for the break points. + * This sets the offset of each row as it is added. + * + * @param parentIter the position iterator + * @param layoutContext the layout context for adding areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + Row childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + int rowoffset = 0; + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = (Row)breakPosIter.getNextChildLM()) != null) { + childLM.setYOffset(yoffset + rowoffset); + childLM.addAreas(breakPosIter, lc); + rowoffset += childLM.getRowHeight(); + } + } + bodyHeight = rowoffset; + + flush(); + + childBreaks.clear(); + curBlockArea = null; + } + + /** + * Get the body height of the body after adjusting. + * Should only be called after adding the body areas. + * + * @return the body height of this body + */ + public int getBodyHeight() { + return bodyHeight; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area + * @return the parent are of the child + */ + public Area getParentArea(Area childArea) { + return parentLM.getParentArea(childArea); + } + + /** + * Add the child area. + * The table-header, table-footer and table-body areas return + * the areas return by the children. + * + * @param childArea the child area to add + * @return unused + */ + public boolean addChild(Area childArea) { + return parentLM.addChild(childArea); + } + + /** + * Reset the position of the layout manager. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/Caption.java b/src/org/apache/fop/layoutmgr/table/Caption.java new file mode 100644 index 000000000..4e310034c --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/Caption.java @@ -0,0 +1,190 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.MinOptMax; + +import java.util.ArrayList; + +/** + * LayoutManager for a table-caption FO. + * The table caption contains blocks that are placed beside the + * table. + */ +public class Caption extends BlockStackingLayoutManager { + + private Block curBlockArea; + + private ArrayList childBreaks = new ArrayList(); + + /** + * Create a new Caption layout manager. + * + * @param fobj the formatting object that created this manager + */ + public Caption(FObj fobj) { + super(fobj); + } + + /** + * Get the next break position for the caption. + * + * @param context the layout context for finding breaks + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + LayoutManager curLM; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + // if there is a caption then get the side and work out when + // to handle it + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + // if line layout manager then set stack limit to ipd + // line LM actually generates a LineArea which is a block + childLC.setStackLimit( + MinOptMax.subtract(context.getStackLimit(), + stackSize)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + setFinished(true); + return null; + } + + /** + * Add the areas to the parent. + * + * @param parentIter the position iterator of the breaks + * @param layoutContext the layout context for adding areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + LayoutManager childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + } + } + + flush(); + + childBreaks.clear(); + curBlockArea = null; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area + * @return the parent area from this caption + */ + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + curBlockArea = new Block(); + // Set up dimensions + // Must get dimensions from parent area + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(curBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + /** + * Add the child to the caption area. + * + * @param childArea the child area to add + * @return unused + */ + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + //return super.addChild(childArea); + + return false; + } + return false; + } + + /** + * Reset the layout position. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/Cell.java b/src/org/apache/fop/layoutmgr/table/Cell.java new file mode 100644 index 000000000..57dd6b2cf --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/Cell.java @@ -0,0 +1,215 @@ +/* + * $Id$ + * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.MinOptMax; + +import java.util.ArrayList; + +/** + * LayoutManager for a table-cell FO. + * A cell contains blocks. These blocks fill the cell. + */ +public class Cell extends BlockStackingLayoutManager { + + private Block curBlockArea; + + private ArrayList childBreaks = new ArrayList(); + + private int xoffset; + private int yoffset; + private int cellIPD; + + /** + * Create a new Cell layout manager. + * @param fobj the formatting object for the cell + */ + public Cell(FObj fobj) { + super(fobj); + } + + /** + * Get the next break possibility for this cell. + * A cell contains blocks so there are breaks around the blocks + * and inside the blocks. + * + * @param context the layout context + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + LayoutManager curLM; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + cellIPD = context.getRefIPD(); + + while ((curLM = getChildLM()) != null) { + // Set up a LayoutContext + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit(MinOptMax.subtract(context.getStackLimit(), + stackSize)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + setFinished(true); + return null; + } + + /** + * Set the y offset of this cell. + * This offset is used to set the absolute position of the cell. + * + * @param off the y direction offset + */ + public void setYOffset(int off) { + yoffset = off; + } + + /** + * Set the x offset of this cell. + * This offset is used to set the absolute position of the cell. + * + * @param off the x offset + */ + public void setXOffset(int off) { + xoffset = off; + } + + /** + * Add the areas for the break points. + * The cell contains block stacking layout managers + * that add block areas. + * + * @param parentIter the iterator of the break positions + * @param layoutContext the layout context for adding the areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + LayoutManager childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + } + } + + flush(); + + childBreaks.clear(); + curBlockArea = null; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area to get the parent for + * @return the parent area + */ + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + curBlockArea = new Block(); + curBlockArea.setPositioning(Block.ABSOLUTE); + // set position + curBlockArea.setXOffset(xoffset); + curBlockArea.setYOffset(yoffset); + curBlockArea.setWidth(cellIPD); + //curBlockArea.setHeight(); + + // Set up dimensions + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(curBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + /** + * Add the child to the cell block area. + * + * @param childArea the child to add to the cell + * @return unused + */ + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + return false; + } + return false; + } + + /** + * Reset the position of the layout. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/Column.java b/src/org/apache/fop/layoutmgr/table/Column.java new file mode 100644 index 000000000..c44de25cb --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/Column.java @@ -0,0 +1,92 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.AbstractLayoutManager; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.fo.flow.TableColumn; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; + +/** + * LayoutManager for a table-column FO. + * The table creates an area for the table-column background, this class + * is used to do the area creation. This is used during the layout to handle + * column properties. + */ +public class Column extends AbstractLayoutManager { + private int columnWidth; + + /** + * Create a new column layout manager. + * + * @param fobj the table-column formatting object + */ + public Column(TableColumn fobj) { + super(fobj); + columnWidth = fobj.getColumnWidth(); + } + + /** + * Get the next break possibility. + * Columns do not create or return any areas. + * + * @param context the layout context + * @return the break possibility, always null + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + return null; + } + + /** + * Add the areas. + * Although this adds no areas it is used to add the id + * reference of the table-column. + * + * @param parentIter the position iterator + * @param layoutContext the context + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + addID(); + } + + /** + * Get the parent area. + * This does nothing. + * + * @param childArea the child area + * @return always null + */ + public Area getParentArea(Area childArea) { + return null; + } + + /** + * Get the width of this column. + * + * @return the width of the column + */ + public int getWidth() { + return columnWidth; + } + + /** + * Create a column area. + * This area has the background and width set. + * The Body manager will then set the offset of the column. + * + * @return the new column area + */ + public Area createColumnArea() { + return new Block(); + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/Row.java b/src/org/apache/fop/layoutmgr/table/Row.java new file mode 100644 index 000000000..ebca76f59 --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/Row.java @@ -0,0 +1,277 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.MinOptMax; + +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; + +/** + * LayoutManager for a table-row FO. + * The row contains cells that are organised according to the columns. + * A break in a table row will contain breaks for each table cell. + * If there are row spanning cells then these cells belong to this row + * but effect the occupied columns of future rows. + */ +public class Row extends BlockStackingLayoutManager { + + private List cellList = null; + private List columns = null; + private int rowHeight; + private int yoffset; + + private class RowPosition extends LeafPosition { + protected List cellBreaks; + protected RowPosition(LayoutManager lm, int pos, List l) { + super(lm, pos); + cellBreaks = l; + } + } + + /** + * Create a new row layout manager. + * + * @param fobj the table-row formatting object + */ + public Row(FObj fobj) { + super(fobj); + } + + /** + * Set the columns from the table. + * + * @param cols the list of columns for this table + */ + public void setColumns(List cols) { + columns = cols; + } + + private void setupCells() { + cellList = new ArrayList(); + // add cells to list + while (m_childLMiter.hasNext()) { + m_curChildLM = (LayoutManager) m_childLMiter.next(); + m_curChildLM.setParentLM(this); + m_curChildLM.init(); + cellList.add(m_curChildLM); + } + } + + /** + * Get the layout manager for a cell. + * + * @param pos the position of the cell + * @return the cell layout manager + */ + protected Cell getCellLM(int pos) { + if (cellList == null) { + setupCells(); + } + if (pos < cellList.size()) { + return (Cell)cellList.get(pos); + } + return null; + } + + /** + * Get the next break possibility. + * A row needs to get the possible breaks for each cell + * in the row and find a suitable break across all cells. + * + * @param context the layout context for getting breaks + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + LayoutManager curLM; // currently active LM + + BreakPoss lastPos = null; + ArrayList breakList = new ArrayList(); + + int min = 0; + int opt = 0; + int max = 0; + + int cellcount = 0; + while ((curLM = getCellLM(cellcount++)) != null) { + + ArrayList childBreaks = new ArrayList(); + MinOptMax stackSize = new MinOptMax(); + + // Set up a LayoutContext + // the ipd is from the current column + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit( + MinOptMax.subtract(context.getStackLimit(), + stackSize)); + + Column col = (Column)columns.get(cellcount - 1); + childLC.setRefIPD(col.getWidth()); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + // the min is the maximum min of all cells + if (stackSize.min > min) { + min = stackSize.min; + } + // the optimum is the average of all optimums + opt += stackSize.opt; + // the maximum is the largest maximum + if (stackSize.max > max) { + max = stackSize.max; + } + + breakList.add(childBreaks); + } + opt = opt / cellcount; + if (opt < min) { + opt = min; + } + rowHeight = opt; + + MinOptMax rowSize = new MinOptMax(min, opt, max); + + setFinished(true); + RowPosition rp = new RowPosition(this, breakList.size() - 1, breakList); + BreakPoss breakPoss = new BreakPoss(rp); + breakPoss.setStackingSize(rowSize); + return breakPoss; + } + + /** + * Set the y position offset of this row. + * This is used to set the position of the areas returned by this row. + * + * @param off the y offset + */ + public void setYOffset(int off) { + yoffset = off; + } + + /** + * Add the areas for the break points. + * This sets the offset of each cell as it is added. + * + * @param parentIter the position iterator + * @param layoutContext the layout context for adding areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + Cell childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + RowPosition lfp = (RowPosition) parentIter.next(); + // Add the block areas to Area + + int cellcount = 0; + int xoffset = 0; + for (Iterator iter = lfp.cellBreaks.iterator(); iter.hasNext();) { + List cellsbr = (List)iter.next(); + PositionIterator breakPosIter; + breakPosIter = new BreakPossPosIter(cellsbr, 0, cellsbr.size()); + iStartPos = lfp.getLeafPos() + 1; + Column col = (Column)columns.get(cellcount++); + while ((childLM = (Cell)breakPosIter.getNextChildLM()) != null) { + childLM.setXOffset(xoffset); + childLM.setYOffset(yoffset); + childLM.addAreas(breakPosIter, lc); + } + xoffset += col.getWidth(); + } + } + + flush(); + + } + + /** + * Get the row height of the row after adjusting. + * Should only be called after adding the row areas. + * + * @return the row height of this row after adjustment + */ + public int getRowHeight() { + return rowHeight; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area + * @return the parent are for the child + */ + public Area getParentArea(Area childArea) { + return parentLM.getParentArea(childArea); + } + + /** + * Add the child. + * Rows return the areas returned by the child elements. + * This simply adds the area to the parent layout manager. + * + * @param childArea the child area + * @return unused + */ + public boolean addChild(Area childArea) { + return parentLM.addChild(childArea); + } + + /** + * Reset the position of this layout manager. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java new file mode 100644 index 000000000..dc7ffe21c --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -0,0 +1,192 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.MinOptMax; + +import java.util.ArrayList; + +/** + * LayoutManager for a table-and-caption FO. + * A table and caption consists of a table and a caption. + * The caption contains blocks that are positioned next to the + * table on the caption side. + * The caption blocks have an implicit keep with the table. + */ +public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { + + private Block curBlockArea; + + private ArrayList childBreaks = new ArrayList(); + + /** + * Create a new table and caption layout manager. + * + * @param fobj the table-and-caption formatting object + */ + public TableAndCaptionLayoutManager(FObj fobj) { + super(fobj); + } + + /** + * Get the next break possibility. + * + * @param context the layout context for getting breaks + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + LayoutManager curLM; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + // if there is a caption then get the side and work out when + // to handle it + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + // if line layout manager then set stack limit to ipd + // line LM actually generates a LineArea which is a block + childLC.setStackLimit( + MinOptMax.subtract(context.getStackLimit(), + stackSize)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + setFinished(true); + return null; + } + + /** + * Add the areas. + * + * @param parentIter the position iterator + * @param layoutContext the layout context for adding areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + LayoutManager childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + } + } + + flush(); + + childBreaks.clear(); + curBlockArea = null; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area to locate the parent + * @return the area for this table and caption + */ + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + curBlockArea = new Block(); + // Set up dimensions + // Must get dimensions from parent area + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(curBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + /** + * Add the child to the current area. + * + * @param childArea the area to add + * @return unused + */ + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + //return super.addChild(childArea); + + return false; + } + return false; + } + + /** + * Reset the position of this layout manager. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java new file mode 100644 index 000000000..9dda28697 --- /dev/null +++ b/src/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -0,0 +1,291 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr.table; + +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.LeafPosition; +import org.apache.fop.layoutmgr.BreakPoss; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.BreakPossPosIter; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.MinOptMax; + +import java.util.ArrayList; +import java.util.List; + +/** + * LayoutManager for a table FO. + * A table consists of columns, table header, table footer and multiple + * table bodies. + * The header, footer and body add the areas created from the table cells. + * The table then creates areas for the columns, bodies and rows + * the render background. + */ +public class TableLayoutManager extends BlockStackingLayoutManager { + private List columns = null; + private Body tableHeader = null; + private Body tableFooter = null; + + private Block curBlockArea; + + private ArrayList bodyBreaks = new ArrayList(); + private BreakPoss headerBreak; + private BreakPoss footerBreak; + + private class SectionPosition extends LeafPosition { + protected List list; + protected SectionPosition(LayoutManager lm, int pos, List l) { + super(lm, pos); + list = l; + } + } + + /** + * Create a new table layout manager. + * + * @param fobj the table formatting object + */ + public TableLayoutManager(FObj fobj) { + super(fobj); + } + + /** + * Set the columns for this table. + * + * @param cols the list of column layout managers + */ + public void setColumns(List cols) { + columns = cols; + } + + /** + * Set the table header. + * + * @param th the table header layout manager + */ + public void setTableHeader(Body th) { + tableHeader = th; + } + + /** + * Set the table footer. + * + * @param tf the table footer layout manager + */ + public void setTableFooter(Body tf) { + tableFooter = tf; + } + + /** + * Get the next break possibility. + * The break possibility depends on the height of the header and footer + * and possible breaks inside the table body. + * + * @param context the layout context for finding breaks + * @return the next break possibility + */ + public BreakPoss getNextBreakPoss(LayoutContext context) { + Body curLM; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + MinOptMax headerSize = null; + if (tableHeader != null) { + headerBreak = getHeight(tableHeader, context); + headerSize = headerBreak.getStackingSize(); + } + + MinOptMax footerSize = null; + if (tableFooter != null) { + footerBreak = getHeight(tableFooter, context); + footerSize = footerBreak.getStackingSize(); + } + + while ((curLM = (Body)getChildLM()) != null) { + // Make break positions + // Set up a LayoutContext + int ipd = context.getRefIPD(); + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit( + MinOptMax.subtract(context.getStackLimit(), + stackSize)); + childLC.setRefIPD(ipd); + + curLM.setColumns(columns); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > context.getStackLimit().max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + bodyBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, bodyBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + setFinished(true); + return null; + } + + /** + * Get the break possibility and height of the table header or footer. + * + * @param lm the header or footer layout manager + * @param context the parent layout context + * @return the break possibility containing the stacking size + */ + protected BreakPoss getHeight(Body lm, LayoutContext context) { + int ipd = context.getRefIPD(); + BreakPoss bp; + + MinOptMax stackSize = new MinOptMax(); + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit(context.getStackLimit()); + childLC.setRefIPD(ipd); + + lm.setColumns(columns); + + ArrayList breaks = new ArrayList(); + while (!lm.isFinished()) { + if ((bp = lm.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + breaks.add(bp); + childLC.setStackLimit(MinOptMax.subtract( + context.getStackLimit(), stackSize)); + } + } + BreakPoss breakPoss = new BreakPoss( + new SectionPosition(this, breaks.size() - 1, breaks)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + + } + + /** + * The table area is a reference area that contains areas for + * columns, bodies, rows and the contents are in cells. + * + * @param parentIter the position iterator + * @param layoutContext the layout context for adding areas + */ + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + addID(); + + // add column, body then row areas + + // add table header areas + + int tableHeight = 0; + + Body childLM; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(bodyBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = (Body)breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + tableHeight += childLM.getBodyHeight(); + } + } + + // add footer areas + + curBlockArea.setHeight(tableHeight); + + flush(); + + bodyBreaks.clear(); + curBlockArea = null; + } + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + * + * @param childArea the child area + * @return the parent area of the child + */ + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + curBlockArea = new Block(); + // Set up dimensions + // Must get dimensions from parent area + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(curBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + /** + * Add the child area to this layout manager. + * + * @param childArea the child area to add + * @return unused + */ + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + + return false; + } + return false; + } + + /** + * Reset the position of this layout manager. + * + * @param resetPos the position to reset to + */ + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java index 42660c85f..36a9f1cc4 100644 --- a/src/org/apache/fop/render/AbstractRenderer.java +++ b/src/org/apache/fop/render/AbstractRenderer.java @@ -80,6 +80,19 @@ public abstract class AbstractRenderer extends AbstractLogEnabled */ protected int currentBlockIPPosition = 0; + /** + * the block progression position of the containing block used for + * absolutely positioned blocks + */ + protected int containingBPPosition = 0; + + /** + * the inline progression position of the containing block used for + * absolutely positioned blocks + */ + protected int containingIPPosition = 0; + + /** @see org.apache.fop.render.Renderer */ public void setUserAgent(FOUserAgent agent) { userAgent = agent; @@ -344,10 +357,33 @@ public abstract class AbstractRenderer extends AbstractLogEnabled List children = block.getChildAreas(); if (children == null) { // simply move position + currentBPPosition += block.getHeight(); } else if (block instanceof BlockViewport) { renderBlockViewport((BlockViewport) block, children); } else { - renderBlocks(children); + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + if (block.getPositioning() == Block.ABSOLUTE) { + currentIPPosition += block.getXOffset(); + currentBPPosition += block.getYOffset(); + + renderBlocks(children); + + // absolute blocks do not effect the layout + currentBPPosition = saveBP; + } else { + // relative blocks are offset + currentIPPosition += block.getXOffset(); + currentBPPosition += block.getYOffset(); + + renderBlocks(children); + + // stacked and relative blocks effect stacking + currentBPPosition = saveBP + block.getHeight(); + } + currentIPPosition = saveIP; } } @@ -493,10 +529,21 @@ public abstract class AbstractRenderer extends AbstractLogEnabled * @param blocks The block areas */ protected void renderBlocks(List blocks) { + // the position of the containing block is used for + // absolutely positioned areas + int contBP = currentBPPosition; + int contIP = currentIPPosition; + containingBPPosition = contBP; + containingIPPosition = contIP; + for (int count = 0; count < blocks.size(); count++) { Object obj = blocks.get(count); if (obj instanceof Block) { + containingBPPosition = contBP; + containingIPPosition = contIP; renderBlock((Block) obj); + containingBPPosition = contBP; + containingIPPosition = contIP; } else { // a line area is rendered from the top left position // of the line, each inline object is offset from there diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index 4565ad800..66bb16c20 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -360,16 +360,17 @@ public class PDFRenderer extends PrintRenderer { currentStream.add("ET\n"); if (bv.getClip()) { - Rectangle2D rect = bv.getBounds(); - currentStream.add("q\n"); - float x = (float)rect.getX() / 1000f; - float y = (float)rect.getY() / 1000f; - float width = (float)rect.getWidth() / 1000f; - float height = (float)rect.getHeight() / 1000f; + float x = (float)(bv.getXOffset() + containingIPPosition) / 1000f; + float y = (float)(bv.getYOffset() + containingBPPosition) / 1000f; + float width = (float)bv.getWidth() / 1000f; + float height = (float)bv.getHeight() / 1000f; clip(x, y, width, height); } + CTM tempctm = new CTM(containingIPPosition, containingBPPosition); + ctm = tempctm.multiply(ctm); + startVParea(ctm); renderBlocks(children); endVParea(); @@ -385,8 +386,6 @@ public class PDFRenderer extends PrintRenderer { currentBPPosition = saveBP; } else { - Rectangle2D rect = bv.getBounds(); - if (ctm != null) { currentIPPosition = 0; currentBPPosition = 0; @@ -396,20 +395,20 @@ public class PDFRenderer extends PrintRenderer { double[] vals = ctm.toArray(); boolean aclock = vals[2] == 1.0; if (vals[2] == 1.0) { - ctm = ctm.translate(-saveBP - rect.getHeight(), -saveIP); + ctm = ctm.translate(-saveBP - bv.getHeight(), -saveIP); } else if (vals[0] == -1.0) { - ctm = ctm.translate(-saveIP - rect.getWidth(), -saveBP - rect.getHeight()); + ctm = ctm.translate(-saveIP - bv.getWidth(), -saveBP - bv.getHeight()); } else { - ctm = ctm.translate(saveBP, saveIP - rect.getWidth()); + ctm = ctm.translate(saveBP, saveIP - bv.getWidth()); } } if (bv.getClip()) { currentStream.add("q\n"); - float x = (float)rect.getX() / 1000f; - float y = (float)rect.getY() / 1000f; - float width = (float)rect.getWidth() / 1000f; - float height = (float)rect.getHeight() / 1000f; + float x = (float)bv.getXOffset() / 1000f; + float y = (float)bv.getYOffset() / 1000f; + float width = (float)bv.getWidth() / 1000f; + float height = (float)bv.getHeight() / 1000f; clip(x, y, width, height); } @@ -430,11 +429,9 @@ public class PDFRenderer extends PrintRenderer { // clip if necessary - if (rect != null) { - currentIPPosition = saveIP; - currentBPPosition = saveBP; - currentBPPosition += (int)(rect.getHeight()); - } + currentIPPosition = saveIP; + currentBPPosition = saveBP; + currentBPPosition += (int)(bv.getHeight()); } } diff --git a/src/org/apache/fop/traits/BlockProps.java b/src/org/apache/fop/traits/BlockProps.java index 56996c953..c63c6051a 100755 --- a/src/org/apache/fop/traits/BlockProps.java +++ b/src/org/apache/fop/traits/BlockProps.java @@ -15,7 +15,7 @@ import org.apache.fop.datatypes.Length; */ public class BlockProps { public int firstIndent; // text-indent - public int lastIndent; // last-line-indent + public int lastIndent; // last-line-indent public int textAlign; public int textAlignLast; public int lineStackType; // line-stacking-strategy (enum) diff --git a/src/org/apache/fop/traits/BorderProps.java b/src/org/apache/fop/traits/BorderProps.java index 99303eee2..e7753f4c3 100644 --- a/src/org/apache/fop/traits/BorderProps.java +++ b/src/org/apache/fop/traits/BorderProps.java @@ -10,25 +10,25 @@ package org.apache.fop.traits; import org.apache.fop.datatypes.ColorType; public class BorderProps { - public int style; // Enum for border style - public ColorType color; // Border color - public int width; // Border width + public int style; // Enum for border style + public ColorType color; // Border color + public int width; // Border width public BorderProps(int style, int width, ColorType color) { - this.style = style; - this.width = width; - this.color = color; + this.style = style; + this.width = width; + this.color = color; } public String toString() { - StringBuffer sbuf = new StringBuffer(); - sbuf.append('('); - sbuf.append(style); // Should get a String value for this enum constant - sbuf.append(','); - sbuf.append(color); - sbuf.append(','); - sbuf.append(width); - sbuf.append(')'); - return sbuf.toString(); + StringBuffer sbuf = new StringBuffer(); + sbuf.append('('); + sbuf.append(style); // Should get a String value for this enum constant + sbuf.append(','); + sbuf.append(color); + sbuf.append(','); + sbuf.append(width); + sbuf.append(')'); + return sbuf.toString(); } } diff --git a/src/org/apache/fop/traits/LayoutProps.java b/src/org/apache/fop/traits/LayoutProps.java index d1839e5a2..5aa34db96 100644 --- a/src/org/apache/fop/traits/LayoutProps.java +++ b/src/org/apache/fop/traits/LayoutProps.java @@ -16,43 +16,43 @@ import org.apache.fop.fo.properties.Constants; * Public "structure" allows direct member access. */ public class LayoutProps { - public int breakBefore; // enum constant BreakBefore.xxx - public int breakAfter; // enum constant BreakAfter.xxx + public int breakBefore; // enum constant BreakBefore.xxx + public int breakAfter; // enum constant BreakAfter.xxx public boolean bIsSpan; public SpaceVal spaceBefore; public SpaceVal spaceAfter; - private static final int[] s_breakPriorities = new int[] { - Constants.AUTO, Constants.COLUMN, Constants.PAGE }; + private static final int[] s_breakPriorities = + new int[]{ Constants.AUTO, Constants.COLUMN, Constants.PAGE }; public LayoutProps() { - breakBefore = breakAfter = Constants.AUTO; - bIsSpan = false; + breakBefore = breakAfter = Constants.AUTO; + bIsSpan = false; } -// public static int higherBreak(int brkParent, int brkChild) { -// if (brkParent == brkChild) return brkChild; -// for (int i=0; i < s_breakPriorities.length; i++) { -// int bp = s_breakPriorities[i]; -// if (bp == brkParent) return brkChild; -// else if (bp == brkChild) return brkParent; -// } -// return brkChild; -// } + // public static int higherBreak(int brkParent, int brkChild) { + // if (brkParent == brkChild) return brkChild; + // for (int i=0; i < s_breakPriorities.length; i++) { + // int bp = s_breakPriorities[i]; + // if (bp == brkParent) return brkChild; + // else if (bp == brkChild) return brkParent; + // } + // return brkChild; + // } public void combineWithParent(LayoutProps parentLP) { - if (parentLP.breakBefore != breakBefore) { - for (int i=0; i < s_breakPriorities.length; i++) { - int bp = s_breakPriorities[i]; - if (bp == breakBefore) { - breakBefore = parentLP.breakBefore; - break; - } - else if (bp == parentLP.breakBefore) break; - } - } - // Parent span always overrides child span - bIsSpan = parentLP.bIsSpan; + if (parentLP.breakBefore != breakBefore) { + for (int i = 0; i < s_breakPriorities.length; i++) { + int bp = s_breakPriorities[i]; + if (bp == breakBefore) { + breakBefore = parentLP.breakBefore; + break; + } else if (bp == parentLP.breakBefore) + break; + } + } + // Parent span always overrides child span + bIsSpan = parentLP.bIsSpan; } } |