fixed some more styling errors git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195177 13f79535-47bb-0310-9956-ffa450edef68pull/30/head
@@ -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) { | |||
} | |||
@@ -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); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
@@ -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; | |||
} | |||
} |
@@ -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 { |
@@ -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); |
@@ -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) { | |||
} |
@@ -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) { |
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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) { |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
@@ -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(); | |||
} | |||
@@ -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; |
@@ -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 { | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
@@ -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; | |||
} |
@@ -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; | |||
} | |||
@@ -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; | |||
} |
@@ -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); | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
@@ -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); | |||
} |
@@ -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. | |||
*/ |
@@ -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); |
@@ -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 | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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(); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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 |
@@ -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()); | |||
} | |||
} | |||
@@ -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) |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |