aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Cumiskey <acumiskey@apache.org>2008-06-23 09:46:41 +0000
committerAdrian Cumiskey <acumiskey@apache.org>2008-06-23 09:46:41 +0000
commit2f451f9c4dae507df76e77bc13e0839c98724fd0 (patch)
tree1c82c51e1a4cf8f89a9e587179a0b91dc1a6b60c
parent08f0da8adadb9fda358992ad204948570ad41d11 (diff)
downloadxmlgraphics-fop-2f451f9c4dae507df76e77bc13e0839c98724fd0.tar.gz
xmlgraphics-fop-2f451f9c4dae507df76e77bc13e0839c98724fd0.zip
Merged revisions 669423,669436,669835,670217,670222,670323,670325,670332,670335-670336,670341,670344,670401,670409,670411-670412,670422-670424,670492 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r669423 | jeremias | 2008-06-19 09:25:46 +0100 (Thu, 19 Jun 2008) | 1 line Simplifications and a Checkstyle fix. ........ r669436 | jeremias | 2008-06-19 10:46:12 +0100 (Thu, 19 Jun 2008) | 2 lines Separation of concerns: Split FOEventHandler into FOEventHandler and FOTreeBuilderContext. The latter contains stuff only used at tree-building stage. FOEventHandler is oriented towards output. ........ r669835 | acumiskey | 2008-06-20 10:18:56 +0100 (Fri, 20 Jun 2008) | 1 line Strict/loose validation of <fo:table-footer/> ordering somehow got lost in processing feedback branch merge. ........ r670217 | acumiskey | 2008-06-21 17:10:03 +0100 (Sat, 21 Jun 2008) | 1 line Moved the contents of TableBody into a new abstract base class TablePart, which is now subclassed by TableBody, TableHeader and TableFooter. ........ r670222 | acumiskey | 2008-06-21 17:28:56 +0100 (Sat, 21 Jun 2008) | 1 line Moved the contents of TableBody into a new abstract base class TablePart, which is now subclassed by TableBody, TableHeader and TableFooter. ........ r670323 | adelmelle | 2008-06-22 10:07:47 +0100 (Sun, 22 Jun 2008) | 1 line Addition to r670217 ........ r670325 | adelmelle | 2008-06-22 10:28:56 +0100 (Sun, 22 Jun 2008) | 1 line Minor javadoc correction ........ r670332 | adelmelle | 2008-06-22 11:21:03 +0100 (Sun, 22 Jun 2008) | 1 line Minor tweak: avoid warning when running through Saxon ........ r670335 | adelmelle | 2008-06-22 11:53:51 +0100 (Sun, 22 Jun 2008) | 1 line Avoid StackOverflow on TableColumn.toString() during debugging. ........ r670336 | adelmelle | 2008-06-22 12:01:27 +0100 (Sun, 22 Jun 2008) | 1 line Minor tweak: use XG Commons version of the interface ........ r670341 | adelmelle | 2008-06-22 12:18:03 +0100 (Sun, 22 Jun 2008) | 2 lines Changed FONode.addCharacters() signature to match the characters() event (use 'length' as a parameter instead of 'end') ........ r670344 | adelmelle | 2008-06-22 12:28:06 +0100 (Sun, 22 Jun 2008) | 1 line Changed signature for static handleWhiteSpaceFor(), and used internally to make the code a bit more compact ........ r670401 | adelmelle | 2008-06-22 20:19:17 +0100 (Sun, 22 Jun 2008) | 1 line Correction: characters() expects a 'length' not an 'endIndex' ........ r670409 | adelmelle | 2008-06-22 21:18:27 +0100 (Sun, 22 Jun 2008) | 1 line Very minor tweak: simplify conditional ........ r670411 | adelmelle | 2008-06-22 21:38:28 +0100 (Sun, 22 Jun 2008) | 2 lines Deleted deprecated interface; unused after r670336 ........ r670412 | adelmelle | 2008-06-22 21:57:43 +0100 (Sun, 22 Jun 2008) | 6 lines Partial fix of FOEventHandler call sequence (see also Bugzilla #45237): call startOfNode() after addChildNode() moved initialization for tableFOs to processNode() moved finishing code to a finalizeNode() method (which is now also used by AbstractRetrieveMarker) restored protected status of startOfNode()/endOfNode() in fo.flow.table package ........ r670422 | adelmelle | 2008-06-22 23:10:55 +0100 (Sun, 22 Jun 2008) | 4 lines Switch FOText to use a java.nio.CharBuffer, and implement the CharSequence interface. TextLayoutManager no longer duplicates the char array, operates on the FOText (charAt(i)) Additionally: endOfNode() for FOText and Character deferred until after white-space handling. ........ r670423 | adelmelle | 2008-06-22 23:17:00 +0100 (Sun, 22 Jun 2008) | 1 line Added missing file from r670422 ........ r670424 | adelmelle | 2008-06-22 23:18:53 +0100 (Sun, 22 Jun 2008) | 1 line Another missing file... ........ r670492 | lfurini | 2008-06-23 10:24:14 +0100 (Mon, 23 Jun 2008) | 2 lines Added support for non-zero borders and padding on page regions. Testcase included, now disabled because it is supposed to run with relaxed validation switched on. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@670500 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/fop/area/Page.java5
-rw-r--r--src/java/org/apache/fop/area/RegionReference.java14
-rw-r--r--src/java/org/apache/fop/fo/FOEventHandler.java109
-rw-r--r--src/java/org/apache/fop/fo/FONode.java36
-rw-r--r--src/java/org/apache/fop/fo/FOText.java445
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java45
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilderContext.java107
-rw-r--r--src/java/org/apache/fop/fo/FObj.java4
-rw-r--r--src/java/org/apache/fop/fo/FObjMixed.java169
-rw-r--r--src/java/org/apache/fop/fo/RecursiveCharIterator.java2
-rw-r--r--src/java/org/apache/fop/fo/expr/PropertyException.java2
-rw-r--r--src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java35
-rw-r--r--src/java/org/apache/fop/fo/flow/Marker.java10
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderResolver.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java10
-rw-r--r--src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java6
-rw-r--r--src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java4
-rw-r--r--src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java8
-rw-r--r--src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/table/Table.java51
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableBody.java219
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCell.java19
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCellContainer.java4
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableColumn.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java16
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFooter.java18
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableHeader.java18
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TablePart.java239
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableRow.java29
-rw-r--r--src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java4
-rw-r--r--src/java/org/apache/fop/fo/pagination/Root.java25
-rw-r--r--src/java/org/apache/fop/fo/properties/PageDimensionMaker.java5
-rw-r--r--src/java/org/apache/fop/fonts/FontSelector.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java124
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowPainter.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java23
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java6
-rw-r--r--src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java85
-rw-r--r--src/java/org/apache/fop/render/rtf/RTFHandler.java64
-rw-r--r--src/java/org/apache/fop/render/rtf/TableAttributesConverter.java5
-rw-r--r--src/java/org/apache/fop/util/CharUtilities.java24
-rw-r--r--src/java/org/apache/fop/util/XMLizable.java35
-rw-r--r--status.xml4
-rw-r--r--test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java10
-rw-r--r--test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java6
-rw-r--r--test/layoutengine/disabled-testcases.xml7
-rw-r--r--test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml136
-rw-r--r--test/layoutengine/testcase2fo.xsl8
52 files changed, 1309 insertions, 919 deletions
diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java
index 64a6db576..94a394014 100644
--- a/src/java/org/apache/fop/area/Page.java
+++ b/src/java/org/apache/fop/area/Page.java
@@ -126,6 +126,10 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable {
} else {
rr = new RegionReference(r, rvp);
}
+ // set borders and padding traits
+ // (a little extensions wrt what prescribed by the specs at 6.4.14)
+ TraitSetter.addBorders(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null);
+ TraitSetter.addPadding(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null);
setRegionReferencePosition(rr, r, rvp.getViewArea());
rvp.setRegionReference(rr);
setRegionViewport(r.getNameId(), rvp);
@@ -289,3 +293,4 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable {
}
+
diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java
index c41de7c7a..467aadd85 100644
--- a/src/java/org/apache/fop/area/RegionReference.java
+++ b/src/java/org/apache/fop/area/RegionReference.java
@@ -73,6 +73,18 @@ public class RegionReference extends Area implements Cloneable {
blocks.add(child);
}
+ /** {@inheritDoc} */
+ public int getBPD() {
+ // subtract bpd of borders and padding before / after
+ return super.getBPD() - getBorderAndPaddingWidthBefore() - getBorderAndPaddingWidthAfter();
+ }
+
+ /** {@inheritDoc} */
+ public int getIPD() {
+ // subtract ipd of borders and padding start / end
+ return super.getIPD() - getBorderAndPaddingWidthStart() - getBorderAndPaddingWidthEnd();
+ }
+
/**
* Set the Coordinate Transformation Matrix which transforms content
* coordinates in this region reference area which are specified in
@@ -133,7 +145,7 @@ public class RegionReference extends Area implements Cloneable {
public void addBlock(Block block) {
addChildArea(block);
}
-
+
/**
* Clone this region.
* This is used when cloning the page by the page master.
diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java
index 7521d398c..90856d57a 100644
--- a/src/java/org/apache/fop/fo/FOEventHandler.java
+++ b/src/java/org/apache/fop/fo/FOEventHandler.java
@@ -19,9 +19,6 @@
package org.apache.fop.fo;
-import java.util.HashSet;
-import java.util.Set;
-
import org.xml.sax.SAXException;
import org.apache.fop.apps.FOUserAgent;
@@ -43,6 +40,9 @@ import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.PageNumberCitationLast;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
@@ -75,27 +75,6 @@ public abstract class FOEventHandler {
protected FontInfo fontInfo;
/**
- * The current set of id's in the FO tree.
- * This is used so we know if the FO tree contains duplicates.
- */
- private Set idReferences = new HashSet();
-
- /**
- * The property list maker.
- */
- protected PropertyListMaker propertyListMaker;
-
- /**
- * The XMLWhitespaceHandler for this tree
- */
- protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler();
-
- /**
- * Indicates whether processing descendants of a marker
- */
- private boolean inMarker = false;
-
- /**
* Main constructor
* @param foUserAgent the apps.FOUserAgent instance for this process
*/
@@ -106,14 +85,6 @@ public abstract class FOEventHandler {
}
/**
- * Retuns the set of ID references.
- * @return the ID references
- */
- public Set getIDReferences() {
- return idReferences;
- }
-
- /**
* Returns the User Agent object associated with this FOEventHandler.
* @return the User Agent object
*/
@@ -130,54 +101,6 @@ public abstract class FOEventHandler {
}
/**
- * Return the propertyListMaker.
- *
- * @return the currently active {@link PropertyListMaker}
- */
- public PropertyListMaker getPropertyListMaker() {
- return propertyListMaker;
- }
-
- /**
- * Set a new propertyListMaker.
- *
- * @param propertyListMaker the new {@link PropertyListMaker} to use
- */
- public void setPropertyListMaker(PropertyListMaker propertyListMaker) {
- this.propertyListMaker = propertyListMaker;
- }
-
- /**
- * Return the XMLWhiteSpaceHandler
- * @return the whiteSpaceHandler
- */
- public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() {
- return whiteSpaceHandler;
- }
-
- /**
- * Switch to or from marker context
- * (used by FOTreeBuilder when processing
- * a marker)
- *
- * @param inMarker true if a marker is being processed;
- * false otherwise
- *
- */
- protected void switchMarkerContext(boolean inMarker) {
- this.inMarker = inMarker;
- }
-
- /**
- * Check whether in marker context
- *
- * @return true if a marker is being processed
- */
- protected boolean inMarker() {
- return this.inMarker;
- }
-
- /**
* This method is called to indicate the start of a new document run.
* @throws SAXException In case of a problem
*/
@@ -337,44 +260,44 @@ public abstract class FOEventHandler {
/**
*
- * @param th TableBody that is starting;
+ * @param header TableHeader that is starting;
*/
- public void startHeader(TableBody th) {
+ public void startHeader(TableHeader header) {
}
/**
*
- * @param th TableBody that is ending.
+ * @param header TableHeader that is ending.
*/
- public void endHeader(TableBody th) {
+ public void endHeader(TableHeader header) {
}
/**
*
- * @param tf TableFooter that is starting.
+ * @param footer TableFooter that is starting.
*/
- public void startFooter(TableBody tf) {
+ public void startFooter(TableFooter footer) {
}
/**
*
- * @param tf TableFooter that is ending.
+ * @param footer TableFooter that is ending.
*/
- public void endFooter(TableBody tf) {
+ public void endFooter(TableFooter footer) {
}
/**
*
- * @param tb TableBody that is starting.
+ * @param body TableBody that is starting.
*/
- public void startBody(TableBody tb) {
+ public void startBody(TableBody body) {
}
/**
*
- * @param tb TableBody that is ending.
+ * @param body TableBody that is ending.
*/
- public void endBody(TableBody tb) {
+ public void endBody(TableBody body) {
}
/**
@@ -566,7 +489,7 @@ public abstract class FOEventHandler {
* @param start Offset for characters to process.
* @param length Portion of array to process.
*/
- public void characters(char data[], int start, int length) {
+ public void characters(char[] data, int start, int length) {
}
/**
diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index 951e4c430..87d3bfa3c 100644
--- a/src/java/org/apache/fop/fo/FONode.java
+++ b/src/java/org/apache/fop/fo/FONode.java
@@ -22,7 +22,6 @@ package org.apache.fop.fo;
// Java
import java.util.ListIterator;
import java.util.Map;
-import java.util.NoSuchElementException;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
@@ -158,11 +157,19 @@ public abstract class FONode implements Cloneable {
}
/**
+ * Returns the context class providing information used during FO tree building.
+ * @return the builder context
+ */
+ public FOTreeBuilderContext getBuilderContext() {
+ return parent.getBuilderContext();
+ }
+
+ /**
* Indicates whether this node is a child of an fo:marker.
* @return true if this node is a child of an fo:marker
*/
protected boolean inMarker() {
- return getFOEventHandler().inMarker();
+ return getBuilderContext().inMarker();
}
/**
@@ -267,12 +274,12 @@ public abstract class FONode implements Cloneable {
*
* @param data array of characters containing text to be added
* @param start starting array element to add
- * @param end ending array element to add
+ * @param length number of elements to add
* @param pList currently applicable PropertyList
* @param locator location in the XSL-FO source file.
* @throws FOPException if there's a problem during processing
*/
- protected void addCharacters(char[] data, int start, int end,
+ protected void addCharacters(char[] data, int start, int length,
PropertyList pList,
Locator locator) throws FOPException {
// ignore
@@ -291,11 +298,16 @@ public abstract class FONode implements Cloneable {
* Primarily used for making final content model validation checks
* and/or informing the {@link FOEventHandler} that the end of this FO
* has been reached.
+ * The default implementation simply calls {@link #finalizeNode()}, without
+ * sending any event to the {@link FOEventHandler}.
+ * <br/><i>Note: the recommended way to override this method in subclasses is</i>
+ * <br/><br/><code>super.endOfNode(); // invoke finalizeNode()
+ * <br/>getFOEventHandler().endXXX(); // send endOfNode() notification</code>
*
* @throws FOPException if there's a problem during processing
*/
protected void endOfNode() throws FOPException {
- // do nothing by default
+ this.finalizeNode();
}
/**
@@ -320,6 +332,20 @@ public abstract class FONode implements Cloneable {
}
/**
+ * Finalize this node.
+ * This method can be overridden by subclasses to perform finishing
+ * tasks (cleanup, validation checks, ...) without triggering
+ * endXXX() events in the {@link FOEventHandler}.
+ * The method is called by the default {@link #endOfNode()}
+ * implementation.
+ *
+ * @throws FOPException in case there was an error
+ */
+ public void finalizeNode() throws FOPException {
+ // do nothing by default
+ }
+
+ /**
* Return the parent node of this node
*
* @return the parent node of this node
diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java
index f21386075..217997ace 100644
--- a/src/java/org/apache/fop/fo/FOText.java
+++ b/src/java/org/apache/fop/fo/FOText.java
@@ -20,6 +20,7 @@
package org.apache.fop.fo;
import java.awt.Color;
+import java.nio.CharBuffer;
import java.util.NoSuchElementException;
import org.xml.sax.Locator;
@@ -33,48 +34,17 @@ import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.SpaceProperty;
+import org.apache.fop.util.CharUtilities;
/**
* A text node (PCDATA) in the formatting object tree.
- *
- * Unfortunately the BufferManager implementation holds
- * onto references to the character data in this object
- * longer than the lifetime of the object itself, causing
- * excessive memory consumption and OOM errors.
*/
-public class FOText extends FONode {
+public class FOText extends FONode implements CharSequence {
- /**
- * the character array containing the text
- */
- public char[] ca;
-
- /**
- * The starting valid index of the ca array
- * to be processed.
- *
- * This value is originally equal to 0, but becomes
- * incremented during leading whitespace removal by the flow.Block class,
- * via the TextCharIterator.remove() method below.
- */
- public int startIndex = 0;
+ /** the <code>CharBuffer</code> containing the text */
+ private CharBuffer charBuffer;
- /**
- * The ending valid index of the ca array
- * to be processed.
- *
- * This value is originally equal to ca.length, but becomes
- * decremented during between-word whitespace removal by the
- * XMLWhiteSpaceHandler via the TextCharIterator.remove()
- * method below.
- */
- public int endIndex = 0;
-
- /** properties relevant for PCDATA */
- /* TODO: these are basically always the same as the parent FObj or FObjMixed
- * so maybe those can be removed, and the accessors could
- * dispatch the call to the parent?
- */
+ /** properties relevant for #PCDATA */
private CommonFont commonFont;
private CommonHyphenation commonHyphenation;
private Color color;
@@ -105,10 +75,10 @@ public class FOText extends FONode {
* which FOText nodes are descendants of the same block.
*/
private Block ancestorBlock = null;
-
+
/** Holds the text decoration values. May be null */
private CommonTextDecoration textDecoration;
-
+
private static final int IS_WORD_CHAR_FALSE = 0;
private static final int IS_WORD_CHAR_TRUE = 1;
private static final int IS_WORD_CHAR_MAYBE = 2;
@@ -123,37 +93,61 @@ public class FOText extends FONode {
}
/** {@inheritDoc} */
- protected void addCharacters(char[] data, int start, int end,
+ protected void addCharacters(char[] data, int start, int length,
PropertyList list, Locator locator) throws FOPException {
- int length = end - start;
- int calength = 0;
- char[] nca;
- if (ca != null) {
- calength = ca.length;
- nca = new char[calength + length];
- System.arraycopy(ca, 0, nca, 0, calength);
+ if (this.charBuffer == null) {
+ // buffer not yet initialized, do so now
+ this.charBuffer = CharBuffer.allocate(length);
} else {
- nca = new char[length];
+ // allocate a larger buffer, and transfer contents
+ int newLength = this.charBuffer.limit() + length;
+ CharBuffer newBuffer = CharBuffer.allocate(newLength);
+ this.charBuffer.rewind();
+ newBuffer.put(this.charBuffer);
+ this.charBuffer = newBuffer;
}
- System.arraycopy(data, start, nca, calength, length);
- endIndex = nca.length;
- this.ca = nca;
- }
+ // append characters
+ this.charBuffer.put(data, start, length);
+
+ }
/**
- * {@inheritDoc}
+ * Return the array of characters for this instance.
+ *
+ * @return a char array containing the text
*/
+ public char[] getCharArray() {
+
+ if (this.charBuffer == null) {
+ return null;
+ }
+
+ if (this.charBuffer.hasArray()) {
+ return this.charBuffer.array();
+ }
+
+ // only if the buffer implementation has
+ // no accessible backing array, return a new one
+ char[] ca = new char[this.charBuffer.limit()];
+ this.charBuffer.rewind();
+ this.charBuffer.get(ca);
+ return ca;
+
+ }
+
+ /** {@inheritDoc} */
public FONode clone(FONode parent, boolean removeChildren)
throws FOPException {
FOText ft = (FOText) super.clone(parent, removeChildren);
if (removeChildren) {
- //not really removing, but just make sure the char array
- //pointed to is really a different one, and reset any
- //possible whitespace-handling effects
- if (ca != null) {
- ft.ca = new char[ca.length];
- System.arraycopy(ca, 0, ft.ca, 0, ca.length);
+ // not really removing, just make sure the char buffer
+ // pointed to is really a different one
+ if (this.charBuffer != null) {
+ ft.charBuffer = CharBuffer.allocate(this.charBuffer.limit());
+ this.charBuffer.rewind();
+ ft.charBuffer.put(this.charBuffer);
+ ft.charBuffer.rewind();
}
}
ft.prevFOTextThisBlock = null;
@@ -162,29 +156,33 @@ public class FOText extends FONode {
return ft;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
- commonFont = pList.getFontProps();
- commonHyphenation = pList.getHyphenationProps();
- color = pList.get(Constants.PR_COLOR).getColor(getUserAgent());
- keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep();
- lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace();
- letterSpacing = pList.get(Constants.PR_LETTER_SPACING);
- whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum();
- whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum();
- textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum();
- wordSpacing = pList.get(Constants.PR_WORD_SPACING);
- wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum();
- textDecoration = pList.getTextDecorationProps();
- baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength();
+ this.commonFont = pList.getFontProps();
+ this.commonHyphenation = pList.getHyphenationProps();
+ this.color = pList.get(Constants.PR_COLOR).getColor(getUserAgent());
+ this.keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep();
+ this.lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace();
+ this.letterSpacing = pList.get(Constants.PR_LETTER_SPACING);
+ this.whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum();
+ this.whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum();
+ this.textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum();
+ this.wordSpacing = pList.get(Constants.PR_WORD_SPACING);
+ this.wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum();
+ this.textDecoration = pList.getTextDecorationProps();
+ this.baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength();
}
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().characters(
+ this.getCharArray(), 0, this.charBuffer.limit());
+ }
+
+ /** {@inheritDoc} */
+ public void finalizeNode() {
textTransform();
- getFOEventHandler().characters(ca, startIndex, endIndex);
}
/**
@@ -198,16 +196,20 @@ public class FOText extends FONode {
*/
public boolean willCreateArea() {
if (whiteSpaceCollapse == Constants.EN_FALSE
- && endIndex - startIndex > 0) {
+ && this.charBuffer.limit() > 0) {
return true;
}
- for (int i = startIndex; i < endIndex; i++) {
- char ch = ca[i];
- if (!((ch == ' ')
- || (ch == '\n')
- || (ch == '\r')
- || (ch == '\t'))) { // whitespace
+ char ch;
+ this.charBuffer.rewind();
+ while (this.charBuffer.hasRemaining()) {
+ ch = this.charBuffer.get();
+ if (!((ch == CharUtilities.SPACE)
+ || (ch == CharUtilities.LINEFEED_CHAR)
+ || (ch == CharUtilities.CARRIAGE_RETURN)
+ || (ch == CharUtilities.TAB))) {
+ // not whitespace
+ this.charBuffer.rewind();
return true;
}
}
@@ -222,7 +224,7 @@ public class FOText extends FONode {
}
/**
- * This method is run as part of the ancestor Block's flushText(), to
+ * This method is run as part of the ancestor Block's flushText(), to
* create xref pointers to the previous FOText objects within the same Block
* @param ancestorBlock the ancestor fo:block
*/
@@ -230,7 +232,7 @@ public class FOText extends FONode {
this.ancestorBlock = ancestorBlock;
// if the last FOText is a sibling, point to it, and have it point here
if (ancestorBlock.lastFOTextProcessed != null) {
- if (ancestorBlock.lastFOTextProcessed.ancestorBlock
+ if (ancestorBlock.lastFOTextProcessed.ancestorBlock
== this.ancestorBlock) {
prevFOTextThisBlock = ancestorBlock.lastFOTextProcessed;
prevFOTextThisBlock.nextFOTextThisBlock = this;
@@ -241,16 +243,47 @@ public class FOText extends FONode {
}
/**
- * This method is run as part of the Constructor, to handle the
- * text-transform property.
+ * This method is run as part of endOfNode(), to handle the
+ * text-transform property for accumulated FOText
*/
private void textTransform() {
- if (getFOEventHandler().inMarker()
+ if (getBuilderContext().inMarker()
|| textTransform == Constants.EN_NONE) {
return;
}
- for (int i = 0; i < endIndex; i++) {
- ca[i] = charTransform(i);
+
+ this.charBuffer.rewind();
+ CharBuffer tmp = this.charBuffer.slice();
+ char c;
+ int lim = this.charBuffer.limit();
+ int pos = -1;
+ while (++pos < lim) {
+ c = this.charBuffer.get();
+ switch (textTransform) {
+ case Constants.EN_UPPERCASE:
+ tmp.put(Character.toUpperCase(c));
+ break;
+ case Constants.EN_LOWERCASE:
+ tmp.put(Character.toLowerCase(c));
+ break;
+ case Constants.EN_CAPITALIZE:
+ if (isStartOfWord(pos)) {
+ /*
+ Use toTitleCase here. Apparently, some languages use
+ a different character to represent a letter when using
+ initial caps than when all of the letters in the word
+ are capitalized. We will try to let Java handle this.
+ */
+ tmp.put(Character.toTitleCase(c));
+ } else {
+ tmp.put(c);
+ }
+ break;
+ default:
+ //should never happen as the property subsystem catches that case
+ assert false;
+ //nop
+ }
}
}
@@ -261,7 +294,7 @@ public class FOText extends FONode {
* well, such as word-spacing. The definition of "word" is somewhat ambiguous
* and appears to be definable by the user agent.
*
- * @param i index into ca[]
+ * @param i index into charBuffer
*
* @return True if the character at this location is the start of a new
* word.
@@ -269,33 +302,33 @@ public class FOText extends FONode {
private boolean isStartOfWord(int i) {
char prevChar = getRelativeCharInBlock(i, -1);
/* All we are really concerned about here is of what type prevChar
- is. If inputChar is not part of a word, then the Java
- conversions will (we hope) simply return inputChar.
- */
- switch (isWordChar(prevChar)) {
- case IS_WORD_CHAR_TRUE:
- return false;
- case IS_WORD_CHAR_FALSE:
- return true;
- /* "MAYBE" implies that additional context is needed. An example is a
- * single-quote, either straight or closing, which might be interpreted
- * as a possessive or a contraction, or might be a closing quote.
+ * is. If inputChar is not part of a word, then the Java
+ * conversions will (we hope) simply return inputChar.
*/
- case IS_WORD_CHAR_MAYBE:
- char prevPrevChar = getRelativeCharInBlock(i, -2);
- switch (isWordChar(prevPrevChar)) {
+ switch (isWordChar(prevChar)) {
case IS_WORD_CHAR_TRUE:
return false;
case IS_WORD_CHAR_FALSE:
return true;
+ /* "MAYBE" implies that additional context is needed. An example is a
+ * single-quote, either straight or closing, which might be interpreted
+ * as a possessive or a contraction, or might be a closing quote.
+ */
case IS_WORD_CHAR_MAYBE:
- return true;
+ char prevPrevChar = getRelativeCharInBlock(i, -2);
+ switch (isWordChar(prevPrevChar)) {
+ case IS_WORD_CHAR_TRUE:
+ return false;
+ case IS_WORD_CHAR_FALSE:
+ return true;
+ case IS_WORD_CHAR_MAYBE:
+ return true;
+ default:
+ return false;
+ }
default:
return false;
}
- default:
- return false;
- }
}
/**
@@ -304,7 +337,7 @@ public class FOText extends FONode {
* block as one unit, allowing text in adjoining FOText objects to be
* returned if the parameters are outside of the current object.
*
- * @param i index into ca[]
+ * @param i index into the CharBuffer
* @param offset signed integer with relative position within the
* block of the character to return. To return the character immediately
* preceding i, pass -1. To return the character immediately after i,
@@ -313,30 +346,34 @@ public class FOText extends FONode {
* the offset points to an area outside of the block.
*/
private char getRelativeCharInBlock(int i, int offset) {
+
+ int charIndex = i + offset;
// The easy case is where the desired character is in the same FOText
- if (((i + offset) >= 0) && ((i + offset) <= this.endIndex)) {
- return ca[i + offset];
+ if (charIndex >= 0 && charIndex < this.length()) {
+ return this.charAt(i + offset);
}
+
// For now, we can't look at following FOText nodes
if (offset > 0) {
- return '\u0000';
- }
+ return CharUtilities.NULL_CHAR;
+ }
+
// Remaining case has the text in some previous FOText node
boolean foundChar = false;
- char charToReturn = '\u0000';
+ char charToReturn = CharUtilities.NULL_CHAR;
FOText nodeToTest = this;
int remainingOffset = offset + i;
while (!foundChar) {
if (nodeToTest.prevFOTextThisBlock == null) {
- foundChar = true;
break;
}
nodeToTest = nodeToTest.prevFOTextThisBlock;
- if ((nodeToTest.endIndex + remainingOffset) >= 0) {
- charToReturn = nodeToTest.ca[nodeToTest.endIndex + remainingOffset];
+ int diff = nodeToTest.length() + remainingOffset - 1;
+ if (diff >= 0) {
+ charToReturn = nodeToTest.charAt(diff);
foundChar = true;
} else {
- remainingOffset = remainingOffset + nodeToTest.endIndex;
+ remainingOffset += diff;
}
}
return charToReturn;
@@ -367,39 +404,6 @@ public class FOText extends FONode {
}
/**
- * Transforms one character in ca[] using the text-transform property.
- *
- * @param i the index into ca[]
- * @return char with transformed value
- */
- private char charTransform(int i) {
- switch (textTransform) {
- /* put NONE first, as this is probably the common case */
- case Constants.EN_NONE:
- return ca[i];
- case Constants.EN_UPPERCASE:
- return Character.toUpperCase(ca[i]);
- case Constants.EN_LOWERCASE:
- return Character.toLowerCase(ca[i]);
- case Constants.EN_CAPITALIZE:
- if (isStartOfWord(i)) {
- /*
- Use toTitleCase here. Apparently, some languages use
- a different character to represent a letter when using
- initial caps than when all of the letters in the word
- are capitalized. We will try to let Java handle this.
- */
- return Character.toTitleCase(ca[i]);
- } else {
- return ca[i];
- }
- default:
- assert false; //should never happen as the property subsystem catches that case
- return ca[i];
- }
- }
-
- /**
* Determines whether the input char should be considered part of a
* "word". This is used primarily to determine whether the character
* immediately following starts a new word, but may have other uses.
@@ -484,57 +488,64 @@ public class FOText extends FONode {
}
private class TextCharIterator extends CharIterator {
- private int curIndex = 0;
-
- /* Current space removal process: just increment the startIndex
- to "remove" leading spaces from ca, until an unremoved character
- is found. Then perform arraycopy's to remove extra spaces
- between words. nextCharCalled is used to determine if an
- unremoved character has already been found--if its value > 2
- than it means that has occurred (it is reset to zero each time we
- remove a space via incrementing the startIndex.) */
- private int nextCharCalled = 0;
-
+
+ int currentPosition = 0;
+
+ boolean canRemove = false;
+ boolean canReplace = false;
+
+ /** {@inheritDoc} */
public boolean hasNext() {
- if (curIndex == 0) {
-// log.debug("->" + new String(ca) + "<-");
- }
- return (curIndex < endIndex);
+ return (this.currentPosition < charBuffer.limit());
}
+ /** {@inheritDoc} */
public char nextChar() {
- if (curIndex < endIndex) {
- nextCharCalled++;
- // Just a char class? Don't actually care about the value!
- return ca[curIndex++];
+
+ if (this.currentPosition < charBuffer.limit()) {
+ this.canRemove = true;
+ this.canReplace = true;
+ return charBuffer.get(currentPosition++);
} else {
throw new NoSuchElementException();
}
+
}
+ /** {@inheritDoc} */
public void remove() {
- if (curIndex < endIndex && nextCharCalled < 2) {
- startIndex++;
- nextCharCalled = 0;
-// log.debug("removeA: " + new String(ca, startIndex, endIndex - startIndex));
- } else if (curIndex < endIndex) {
- // copy from curIndex to end to curIndex-1
- System.arraycopy(ca, curIndex, ca, curIndex - 1,
- endIndex - curIndex);
- endIndex--;
- curIndex--;
-// log.debug("removeB: " + new String(ca, startIndex, endIndex - startIndex));
- } else if (curIndex == endIndex) {
-// log.debug("removeC: " + new String(ca, startIndex, endIndex - startIndex));
- endIndex--;
- curIndex--;
+
+ if (this.canRemove) {
+ charBuffer.position(currentPosition);
+ // Slice the buffer at the current position
+ CharBuffer tmp = charBuffer.slice();
+ // Reset position to before current character
+ charBuffer.position(--currentPosition);
+ if (tmp.hasRemaining()) {
+ // Transfer any remaining characters
+ charBuffer.mark();
+ charBuffer.put(tmp);
+ charBuffer.reset();
+ }
+ // Decrease limit
+ charBuffer.limit(charBuffer.limit() - 1);
+ // Make sure following calls fail, unless nextChar() was called
+ this.canRemove = false;
+ } else {
+ throw new IllegalStateException();
}
+
}
+ /** {@inheritDoc} */
public void replaceChar(char c) {
- if (curIndex > 0 && curIndex <= endIndex) {
- ca[curIndex - 1] = c;
+
+ if (this.canReplace) {
+ charBuffer.put(currentPosition - 1, c);
+ } else {
+ throw new IllegalStateException();
}
+
}
}
@@ -560,7 +571,7 @@ public class FOText extends FONode {
return color;
}
- /**
+ /**
* @return the "keep-together" property.
*/
public KeepProperty getKeepTogether() {
@@ -571,40 +582,40 @@ public class FOText extends FONode {
* @return the "letter-spacing" property.
*/
public Property getLetterSpacing() {
- return letterSpacing;
+ return letterSpacing;
}
-
+
/**
* @return the "line-height" property.
*/
public SpaceProperty getLineHeight() {
return lineHeight;
}
-
+
/**
* @return the "white-space-treatment" property
*/
public int getWhitespaceTreatment() {
return whiteSpaceTreatment;
}
-
+
/**
* @return the "word-spacing" property.
*/
public Property getWordSpacing() {
- return wordSpacing;
+ return wordSpacing;
}
-
+
/**
* @return the "wrap-option" property.
*/
public int getWrapOption() {
- return wrapOption;
+ return wrapOption;
}
-
+
/** @return the "text-decoration" property. */
public CommonTextDecoration getTextDecoration() {
- return textDecoration;
+ return textDecoration;
}
/** @return the baseline-shift property */
@@ -614,14 +625,12 @@ public class FOText extends FONode {
/** {@inheritDoc} */
public String toString() {
- StringBuffer sb = new StringBuffer(super.toString());
- sb.append(" (").append(ca).append(")");
- return sb.toString();
+ return (this.charBuffer == null) ? "" : this.charBuffer.toString();
}
-
+
/** {@inheritDoc} */
public String getLocalName() {
- return null;
+ return "#PCDATA";
}
/** {@inheritDoc} */
@@ -631,10 +640,34 @@ public class FOText extends FONode {
/** {@inheritDoc} */
protected String gatherContextInfo() {
- if (getLocator() != null) {
+ if (this.locator != null) {
return super.gatherContextInfo();
} else {
- return new String(ca).trim();
+ return this.toString();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public char charAt(int position) {
+ return this.charBuffer.get(position);
+ }
+
+ /** {@inheritDoc} */
+ public CharSequence subSequence(int start, int end) {
+ return this.charBuffer.subSequence(start, end);
+ }
+
+ /** {@inheritDoc} */
+ public int length() {
+ return this.charBuffer.limit();
+ }
+
+ /**
+ * Resets the backing <code>java.nio.CharBuffer</code>
+ */
+ public void resetBuffer() {
+ if (this.charBuffer != null) {
+ this.charBuffer.rewind();
}
- }
-} \ No newline at end of file
+ }
+}
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index 84abc4b8b..6682ff703 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -66,6 +66,9 @@ public class FOTreeBuilder extends DefaultHandler {
/** Current delegate ContentHandler to receive the SAX events */
protected ContentHandler delegate;
+
+ /** Provides information used during tree building stage. */
+ private FOTreeBuilderContext builderContext;
/** The object that handles formatting and rendering to a stream */
private FOEventHandler foEventHandler;
@@ -101,7 +104,8 @@ public class FOTreeBuilder extends DefaultHandler {
//one of the RTF-, MIF- etc. Handlers.
foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler(
foUserAgent, outputFormat, stream);
- foEventHandler.setPropertyListMaker(new PropertyListMaker() {
+ builderContext = new FOTreeBuilderContext();
+ builderContext.setPropertyListMaker(new PropertyListMaker() {
public PropertyList make(FObj fobj, PropertyList parentPropertyList) {
return new StaticPropertyList(fobj, parentPropertyList);
}
@@ -140,7 +144,7 @@ public class FOTreeBuilder extends DefaultHandler {
log.debug("Building formatting object tree");
}
foEventHandler.startDocument();
- this.mainFOHandler = new MainFOHandler();
+ this.mainFOHandler = new MainFOHandler();
this.mainFOHandler.startDocument();
this.delegate = this.mainFOHandler;
}
@@ -150,8 +154,7 @@ public class FOTreeBuilder extends DefaultHandler {
this.delegate.endDocument();
if (this.rootFObj == null && empty) {
FOValidationEventProducer eventProducer
- = FOValidationEventProducer.Provider.get(
- foEventHandler.getUserAgent().getEventBroadcaster());
+ = FOValidationEventProducer.Provider.get(userAgent.getEventBroadcaster());
eventProducer.emptyDocument(this);
}
rootFObj = null;
@@ -221,7 +224,7 @@ public class FOTreeBuilder extends DefaultHandler {
} else {
//No formatting results available for output formats no
//involving the layout engine.
- return null;
+ return null;
}
}
@@ -254,7 +257,7 @@ public class FOTreeBuilder extends DefaultHandler {
|| !localName.equals("root")) {
FOValidationEventProducer eventProducer
= FOValidationEventProducer.Provider.get(
- foEventHandler.getUserAgent().getEventBroadcaster());
+ userAgent.getEventBroadcaster());
eventProducer.invalidFORoot(this, FONode.getNodeString(namespaceURI, localName),
getEffectiveLocator());
}
@@ -271,6 +274,7 @@ public class FOTreeBuilder extends DefaultHandler {
foNode = fobjMaker.make(currentFObj);
if (rootFObj == null) {
rootFObj = (Root) foNode;
+ rootFObj.setBuilderContext(builderContext);
rootFObj.setFOEventHandler(foEventHandler);
}
propertyList = foNode.createPropertyList(
@@ -278,13 +282,12 @@ public class FOTreeBuilder extends DefaultHandler {
foNode.processNode(localName, getEffectiveLocator(),
attlist, propertyList);
if (foNode.getNameId() == Constants.FO_MARKER) {
- if (foEventHandler.inMarker()) {
+ if (builderContext.inMarker()) {
nestedMarkerDepth++;
} else {
- foEventHandler.switchMarkerContext(true);
+ builderContext.switchMarkerContext(true);
}
}
- foNode.startOfNode();
} catch (IllegalArgumentException e) {
throw new SAXException(e);
}
@@ -310,9 +313,16 @@ public class FOTreeBuilder extends DefaultHandler {
}
currentFObj = foNode;
- if (propertyList != null && !foEventHandler.inMarker()) {
+ if (propertyList != null && !builderContext.inMarker()) {
currentPropertyList = propertyList;
}
+
+ // fo:characters can potentially be removed during
+ // white-space handling.
+ // Do not notify the FOEventHandler.
+ if (currentFObj.getNameId() != Constants.FO_CHARACTER) {
+ currentFObj.startOfNode();
+ }
}
/** {@inheritDoc} */
@@ -329,17 +339,22 @@ public class FOTreeBuilder extends DefaultHandler {
+ ") vs. " + localName + " (" + uri + ")");
}
- currentFObj.endOfNode();
+ // fo:characters can potentially be removed during
+ // white-space handling.
+ // Do not notify the FOEventHandler.
+ if (currentFObj.getNameId() != Constants.FO_CHARACTER) {
+ currentFObj.endOfNode();
+ }
if (currentPropertyList != null
&& currentPropertyList.getFObj() == currentFObj
- && !foEventHandler.inMarker()) {
+ && !builderContext.inMarker()) {
currentPropertyList = currentPropertyList.getParentPropertyList();
}
if (currentFObj.getNameId() == Constants.FO_MARKER) {
if (nestedMarkerDepth == 0) {
- foEventHandler.switchMarkerContext(false);
+ builderContext.switchMarkerContext(false);
} else {
nestedMarkerDepth--;
}
@@ -356,7 +371,7 @@ public class FOTreeBuilder extends DefaultHandler {
public void characters(char[] data, int start, int length)
throws FOPException {
if (currentFObj != null) {
- currentFObj.addCharacters(data, start, start + length,
+ currentFObj.addCharacters(data, start, length,
currentPropertyList, getEffectiveLocator());
}
}
@@ -379,7 +394,7 @@ public class FOTreeBuilder extends DefaultHandler {
if (maker instanceof UnknownXMLObj.Maker) {
FOValidationEventProducer eventProducer
= FOValidationEventProducer.Provider.get(
- foEventHandler.getUserAgent().getEventBroadcaster());
+ userAgent.getEventBroadcaster());
eventProducer.unknownFormattingObject(this, currentFObj.getName(),
new QName(namespaceURI, localName),
getEffectiveLocator());
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilderContext.java b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java
new file mode 100644
index 000000000..0cbdd7797
--- /dev/null
+++ b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Context class providing information needed while building the FO tree.
+ */
+public class FOTreeBuilderContext {
+
+ /**
+ * The current set of id's in the FO tree.
+ * This is used so we know if the FO tree contains duplicates.
+ */
+ private Set idReferences = new HashSet();
+
+ /**
+ * The property list maker.
+ */
+ protected PropertyListMaker propertyListMaker;
+
+ /**
+ * The XMLWhitespaceHandler for this tree
+ */
+ protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler();
+
+ /**
+ * Indicates whether processing descendants of a marker
+ */
+ private boolean inMarker = false;
+
+ /**
+ * Returns the set of ID references.
+ * @return the ID references
+ */
+ public Set getIDReferences() {
+ return idReferences;
+ }
+
+ /**
+ * Return the propertyListMaker.
+ *
+ * @return the currently active {@link PropertyListMaker}
+ */
+ public PropertyListMaker getPropertyListMaker() {
+ return propertyListMaker;
+ }
+
+ /**
+ * Set a new propertyListMaker.
+ *
+ * @param propertyListMaker the new {@link PropertyListMaker} to use
+ */
+ public void setPropertyListMaker(PropertyListMaker propertyListMaker) {
+ this.propertyListMaker = propertyListMaker;
+ }
+
+ /**
+ * Return the XMLWhiteSpaceHandler
+ * @return the whiteSpaceHandler
+ */
+ public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() {
+ return whiteSpaceHandler;
+ }
+
+ /**
+ * Switch to or from marker context
+ * (used by FOTreeBuilder when processing
+ * a marker)
+ *
+ * @param inMarker true if a marker is being processed;
+ * false otherwise
+ *
+ */
+ protected void switchMarkerContext(boolean inMarker) {
+ this.inMarker = inMarker;
+ }
+
+ /**
+ * Check whether in marker context
+ *
+ * @return true if a marker is being processed
+ */
+ protected boolean inMarker() {
+ return this.inMarker;
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java
index 150abda24..20573fa7a 100644
--- a/src/java/org/apache/fop/fo/FObj.java
+++ b/src/java/org/apache/fop/fo/FObj.java
@@ -130,7 +130,7 @@ public abstract class FObj extends FONode implements Constants {
*/
protected PropertyList createPropertyList(PropertyList parent,
FOEventHandler foEventHandler) throws FOPException {
- return foEventHandler.getPropertyListMaker().make(this, parent);
+ return getBuilderContext().getPropertyListMaker().make(this, parent);
}
/**
@@ -165,7 +165,7 @@ public abstract class FObj extends FONode implements Constants {
*/
private void checkId(String id) throws ValidationException {
if (!inMarker() && !id.equals("")) {
- Set idrefs = getFOEventHandler().getIDReferences();
+ Set idrefs = getBuilderContext().getIDReferences();
if (!idrefs.contains(id)) {
idrefs.add(id);
} else {
diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java
index bf7383398..068c2d635 100644
--- a/src/java/org/apache/fop/fo/FObjMixed.java
+++ b/src/java/org/apache/fop/fo/FObjMixed.java
@@ -28,29 +28,29 @@ import org.apache.fop.apps.FOPException;
* (= those that can contain both child {@link FONode}s and <code>#PCDATA</code>).
*/
public abstract class FObjMixed extends FObj {
-
+
/** Represents accumulated, pending FO text. See {@link #flushText()}. */
- protected FOText ft = null;
-
+ private FOText ft = null;
+
/** Used for white-space handling; start CharIterator at node ... */
protected FONode currentTextNode;
-
+
/** Used in creating pointers between subsequent {@link FOText} nodes
- * in the same {@link org.apache.fop.fo.flow.Block}
+ * in the same {@link org.apache.fop.fo.flow.Block}
* (for handling text-transform) */
protected FOText lastFOTextProcessed = null;
-
+
/**
* Base constructor
- *
+ *
* @param parent FONode that is the parent of this object
*/
protected FObjMixed(FONode parent) {
super(parent);
}
-
+
/** {@inheritDoc} */
- protected void addCharacters(char[] data, int start, int end,
+ protected void addCharacters(char[] data, int start, int length,
PropertyList pList,
Locator locator) throws FOPException {
if (ft == null) {
@@ -60,113 +60,124 @@ public abstract class FObjMixed extends FObj {
ft.bind(pList);
}
}
- ft.addCharacters(data, start, end, null, null);
+ ft.addCharacters(data, start, length, null, null);
}
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
- flushText();
- if (!inMarker()
- || getNameId() == FO_MARKER) {
- getFOEventHandler().whiteSpaceHandler
- .handleWhiteSpace(this, currentTextNode);
- }
+
super.endOfNode();
+ if (!inMarker() || getNameId() == FO_MARKER) {
+ // send character[s]() events to the FOEventHandler
+ sendCharacters();
+ }
+
}
/**
- * Handles white-space for the node that is passed in,
+ * Handles white-space for the node that is passed in,
* starting at its current text-node
- * (used by {@link org.apache.fop.fo.flow.RetrieveMarker}
+ * (used by {@link org.apache.fop.fo.flow.RetrieveMarker}
* to trigger 'end-of-node' white-space handling)
- *
+ *
* @param fobj the node for which to handle white-space
+ * @param nextChild the next child to be added
*/
- protected static void handleWhiteSpaceFor(FObjMixed fobj) {
- fobj.getFOEventHandler().getXMLWhiteSpaceHandler()
- .handleWhiteSpace(fobj, fobj.currentTextNode);
+ protected static void handleWhiteSpaceFor(FObjMixed fobj, FONode nextChild) {
+ fobj.getBuilderContext().getXMLWhiteSpaceHandler()
+ .handleWhiteSpace(fobj, fobj.currentTextNode, nextChild);
}
-
+
/**
- * Adds accumulated text as one FOText instance, unless
- * the one instance's <code>char</code> array contains more than
- * <code>Short.MAX_VALUE</code> characters. In the latter case the
- * instance is split up into more manageable chunks.
- *
+ * Creates block-pointers between subsequent FOText nodes
+ * in the same Block. (used for handling text-transform)
+ *
+ * TODO: !! Revisit: does not take into account fo:characters !!
+ *
* @throws FOPException if there is a problem during processing
*/
- protected void flushText() throws FOPException {
+ private void flushText() throws FOPException {
if (ft != null) {
FOText lft = ft;
/* make sure nested calls to itself have no effect */
ft = null;
- FOText tmpText;
- int indexStart = 0;
- int indexEnd = (lft.ca.length > Short.MAX_VALUE
- ? Short.MAX_VALUE : lft.ca.length) - 1;
- int charCount = 0;
- short tmpSize;
- while (charCount < lft.ca.length) {
- tmpSize = (short) (indexEnd - indexStart + 1);
- charCount += tmpSize;
- tmpText = (FOText) lft.clone(this, false);
- tmpText.ca = new char[tmpSize];
- tmpText.startIndex = 0;
- tmpText.endIndex = tmpSize;
- System.arraycopy(lft.ca, indexStart,
- tmpText.ca, 0, indexEnd - indexStart + 1);
- if (getNameId() == FO_BLOCK) {
- tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) this);
- this.lastFOTextProcessed = tmpText;
- } else if (getNameId() != FO_MARKER
- && getNameId() != FO_TITLE
- && getNameId() != FO_BOOKMARK_TITLE) {
- FONode fo = parent;
- int foNameId = fo.getNameId();
- while (foNameId != FO_BLOCK
- && foNameId != FO_MARKER
- && foNameId != FO_TITLE
- && foNameId != FO_BOOKMARK_TITLE
- && foNameId != FO_PAGE_SEQUENCE) {
- fo = fo.getParent();
- foNameId = fo.getNameId();
- }
- if (foNameId == FO_BLOCK) {
- tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) fo);
- ((FObjMixed) fo).lastFOTextProcessed = tmpText;
- } else if (foNameId == FO_PAGE_SEQUENCE
- && tmpText.willCreateArea()) {
- log.error("Could not create block pointers."
- + " FOText w/o Block ancestor.");
- }
+ if (getNameId() == FO_BLOCK) {
+ lft.createBlockPointers((org.apache.fop.fo.flow.Block) this);
+ this.lastFOTextProcessed = lft;
+ } else if (getNameId() != FO_MARKER
+ && getNameId() != FO_TITLE
+ && getNameId() != FO_BOOKMARK_TITLE) {
+ FONode fo = parent;
+ int foNameId = fo.getNameId();
+ while (foNameId != FO_BLOCK
+ && foNameId != FO_MARKER
+ && foNameId != FO_TITLE
+ && foNameId != FO_BOOKMARK_TITLE
+ && foNameId != FO_PAGE_SEQUENCE) {
+ fo = fo.getParent();
+ foNameId = fo.getNameId();
+ }
+ if (foNameId == FO_BLOCK) {
+ lft.createBlockPointers((org.apache.fop.fo.flow.Block) fo);
+ ((FObjMixed) fo).lastFOTextProcessed = lft;
+ } else if (foNameId == FO_PAGE_SEQUENCE
+ && lft.willCreateArea()) {
+ log.error("Could not create block pointers."
+ + " FOText w/o Block ancestor.");
+ }
+ }
+ this.addChildNode(lft);
+ }
+ }
+
+ private void sendCharacters() throws FOPException {
+
+ if (this.currentTextNode != null) {
+ FONodeIterator nodeIter
+ = this.getChildNodes(this.currentTextNode);
+ FONode node;
+ while (nodeIter.hasNext()) {
+ node = nodeIter.nextNode();
+ assert (node instanceof FOText
+ || node.getNameId() == FO_CHARACTER);
+ if (node.getNameId() == FO_CHARACTER) {
+ node.startOfNode();
}
- tmpText.endOfNode();
- addChildNode(tmpText);
- indexStart = indexEnd + 1;
- indexEnd = (((lft.ca.length - charCount) < Short.MAX_VALUE)
- ? lft.ca.length : charCount + Short.MAX_VALUE) - 1;
+ node.endOfNode();
}
}
+ this.currentTextNode = null;
}
/** {@inheritDoc} */
protected void addChildNode(FONode child) throws FOPException {
+
flushText();
if (!inMarker()) {
if (child instanceof FOText || child.getNameId() == FO_CHARACTER) {
- if (currentTextNode == null) {
- currentTextNode = child;
+ if (this.currentTextNode == null) {
+ this.currentTextNode = child;
}
} else {
// handle white-space for all text up to here
- getFOEventHandler().whiteSpaceHandler
- .handleWhiteSpace(this, currentTextNode, child);
- currentTextNode = null;
+ handleWhiteSpaceFor(this, child);
+ // send character[s]() events to the FOEventHandler
+ sendCharacters();
}
}
super.addChildNode(child);
}
-
+
+ /** {@inheritDoc} */
+ public void finalizeNode() throws FOPException {
+
+ flushText();
+ if (!inMarker() || getNameId() == FO_MARKER) {
+ handleWhiteSpaceFor(this, null);
+ }
+
+ }
+
/**
* Returns a {@link CharIterator} over this FO's character content
*
diff --git a/src/java/org/apache/fop/fo/RecursiveCharIterator.java b/src/java/org/apache/fop/fo/RecursiveCharIterator.java
index 22ece76f3..a4aa28e37 100644
--- a/src/java/org/apache/fop/fo/RecursiveCharIterator.java
+++ b/src/java/org/apache/fop/fo/RecursiveCharIterator.java
@@ -113,7 +113,7 @@ public class RecursiveCharIterator extends CharIterator {
*/
public boolean hasNext() {
while (curCharIter != null) {
- if (curCharIter.hasNext() == false) {
+ if (!curCharIter.hasNext()) {
getNextCharIter();
} else {
return true;
diff --git a/src/java/org/apache/fop/fo/expr/PropertyException.java b/src/java/org/apache/fop/fo/expr/PropertyException.java
index 16055a738..d16d1c8ff 100644
--- a/src/java/org/apache/fop/fo/expr/PropertyException.java
+++ b/src/java/org/apache/fop/fo/expr/PropertyException.java
@@ -37,7 +37,7 @@ public class PropertyException extends FOPException {
/**
* Constructor
- * @param the Exception causing this PropertyException
+ * @param cause the Exception causing this PropertyException
*/
public PropertyException(Exception cause) {
super(cause);
diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java
index f08b1f433..bdfd1fc29 100644
--- a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java
+++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java
@@ -22,7 +22,7 @@ package org.apache.fop.fo.extensions.xmp;
import java.io.Serializable;
import org.apache.fop.fo.extensions.ExtensionAttachment;
-import org.apache.fop.util.XMLizable;
+import org.apache.xmlgraphics.util.XMLizable;
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.XMPConstants;
import org.xml.sax.ContentHandler;
diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
index 83a0ddbdc..c88147350 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
@@ -16,20 +16,22 @@
*/
/* $Id$ */
+
package org.apache.fop.fo.flow;
+import java.util.Iterator;
+
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.flow.table.TableFObj;
import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.apps.FOPException;
-import org.xml.sax.Locator;
-
-import java.util.Iterator;
+import org.apache.fop.fo.flow.table.TableFObj;
/**
* Abstract base class for the <a href="http://www.w3.org/TR/xsl/#fo_retrieve-marker">
@@ -80,7 +82,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
}
private PropertyList createPropertyListFor(FObj fo, PropertyList parent) {
- return getFOEventHandler().getPropertyListMaker().make(fo, parent);
+ return getBuilderContext().getPropertyListMaker().make(fo, parent);
}
private void cloneSingleNode(FONode child, FONode newParent,
@@ -100,16 +102,10 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
getLocator(),
pList,
newPropertyList);
- if (newChild instanceof TableFObj) {
- // TODO calling startOfNode (and endOfNode, below) on other fobjs may
- // have undesirable side-effects. This is really ugly and will need to
- // be addressed sooner or later
- ((TableFObj) newChild).startOfNode();
- }
addChildTo(newChild, (FObj) newParent);
if (newChild.getNameId() == FO_TABLE) {
Table t = (Table) child;
- cloneSubtree(t.getColumns().listIterator(),
+ cloneSubtree(t.getColumns().iterator(),
newChild, marker, newPropertyList);
cloneSingleNode(t.getTableHeader(),
newChild, marker, newPropertyList);
@@ -118,18 +114,15 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
}
cloneSubtree(child.getChildNodes(), newChild,
marker, newPropertyList);
- if (newChild instanceof TableFObj) {
- // TODO this is ugly
- ((TableFObj) newChild).endOfNode();
- }
} else if (child instanceof FOText) {
FOText ft = (FOText) newChild;
ft.bind(parentPropertyList);
addChildTo(newChild, (FObj) newParent);
}
- if (newChild instanceof FObjMixed) {
- handleWhiteSpaceFor((FObjMixed) newChild);
- }
+
+ // trigger end-of-node white-space handling
+ // and finalization for table-FOs
+ newChild.finalizeNode();
}
}
@@ -167,7 +160,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
}
cloneSubtree(marker.getChildNodes(), this,
marker, propertyList);
- handleWhiteSpaceFor(this);
+ handleWhiteSpaceFor(this, null);
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java
index 7eda2101e..ea6721686 100644
--- a/src/java/org/apache/fop/fo/flow/Marker.java
+++ b/src/java/org/apache/fop/fo/flow/Marker.java
@@ -26,8 +26,8 @@ import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
-import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOTreeBuilderContext;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.PropertyList;
@@ -84,10 +84,10 @@ public class Marker extends FObjMixed {
/** {@inheritDoc} */
protected void startOfNode() {
- FOEventHandler foEventHandler = getFOEventHandler();
+ FOTreeBuilderContext builderContext = getBuilderContext();
// Push a new property list maker which will make MarkerPropertyLists.
- savePropertyListMaker = foEventHandler.getPropertyListMaker();
- foEventHandler.setPropertyListMaker(new PropertyListMaker() {
+ savePropertyListMaker = builderContext.getPropertyListMaker();
+ builderContext.setPropertyListMaker(new PropertyListMaker() {
public PropertyList make(FObj fobj, PropertyList parentPropertyList) {
PropertyList pList = new MarkerPropertyList(fobj, parentPropertyList);
descendantPropertyLists.put(fobj, pList);
@@ -100,7 +100,7 @@ public class Marker extends FObjMixed {
protected void endOfNode() throws FOPException {
super.endOfNode();
// Pop the MarkerPropertyList maker.
- getFOEventHandler().setPropertyListMaker(savePropertyListMaker);
+ getBuilderContext().setPropertyListMaker(savePropertyListMaker);
savePropertyListMaker = null;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
index 5322b08d3..82bdac845 100644
--- a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
+++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
@@ -40,7 +40,7 @@ interface BorderResolver {
*
* @param part the part that has started
*/
- void startPart(TableBody part);
+ void startPart(TablePart part);
/**
* Receives notification of the end of a table-header/footer/body.
diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
index 2d48380ee..3a887166a 100644
--- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
+++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
@@ -73,7 +73,7 @@ class CollapsingBorderResolver implements BorderResolver {
*/
private abstract class Resolver {
- protected TableBody tablePart;
+ protected TablePart tablePart;
protected boolean firstInPart;
@@ -177,7 +177,7 @@ class CollapsingBorderResolver implements BorderResolver {
}
}
- void startPart(TableBody part) {
+ void startPart(TablePart part) {
tablePart = part;
firstInPart = true;
borderStartTableAndBody = collapsingBorderModel.determineWinner(table.borderStart,
@@ -415,8 +415,8 @@ class CollapsingBorderResolver implements BorderResolver {
}
/** {@inheritDoc} */
- public void startPart(TableBody part) {
- if (part.isTableHeader()) {
+ public void startPart(TablePart part) {
+ if (part instanceof TableHeader) {
delegate = new ResolverInHeader();
} else {
if (leadingBorders == null || table.omitHeaderAtBreak()) {
@@ -427,7 +427,7 @@ class CollapsingBorderResolver implements BorderResolver {
leadingBorders.add(border);
}
}
- if (part.isTableFooter()) {
+ if (part instanceof TableFooter) {
resolverInFooter = new ResolverInFooter();
delegate = resolverInFooter;
} else {
diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
index 0d24491d9..a7719528a 100644
--- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
@@ -143,8 +143,8 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
}
/** {@inheritDoc} */
- void endRow(TableBody body) {
- handleRowEnd(body);
+ void endRow(TablePart part) {
+ handleRowEnd(part);
}
private void handleRowEnd(TableCellContainer container) {
@@ -172,7 +172,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
}
/** {@inheritDoc} */
- void startTablePart(TableBody part) {
+ void startTablePart(TablePart part) {
firstInPart = true;
borderResolver.startPart(part);
}
diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
index 915208e2d..a4b064a53 100644
--- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
@@ -78,12 +78,12 @@ public class PrimaryGridUnit extends GridUnit {
*
* @return the enclosing table part
*/
- public TableBody getTableBody() {
+ public TablePart getTablePart() {
FONode node = cell.getParent();
if (node instanceof TableRow) {
node = node.getParent();
}
- return (TableBody) node;
+ return (TablePart) node;
}
public TableCellLayoutManager getCellLM() {
diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
index c954be711..9748a77aa 100644
--- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
@@ -57,7 +57,7 @@ abstract class RowGroupBuilder {
/**
* Receives notification of the end of the current row. If the current row finishes
- * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table
+ * the row group, the {@link TablePart#addRowGroup(List)} method of the parent table
* part will be called.
*/
abstract void endTableRow();
@@ -65,21 +65,21 @@ abstract class RowGroupBuilder {
/**
* Receives notification of the end of the current row, when the source contains no
* fo:table-row element. If the current row finishes the row group, the
- * {@link TableBody#addRowGroup(List)} method of the given table part will be called.
+ * {@link TablePart#addRowGroup(List)} method of the given table part will be called.
*
* <p>If the source does contain explicit fo:table-row elements, then the
* {@link #endTableRow()} method will be called instead.</p>
*
* @param part the part containing the current row
*/
- abstract void endRow(TableBody part);
+ abstract void endRow(TablePart part);
/**
* Receives notification of the start of a table-header/footer/body.
*
* @param part the part being started
*/
- abstract void startTablePart(TableBody part);
+ abstract void startTablePart(TablePart part);
/**
* Receives notification of the end of a table-header/footer/body. The current
diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
index c6d46ecf5..afd05823b 100644
--- a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
+++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
@@ -31,7 +31,7 @@ class SeparateBorderResolver implements BorderResolver {
}
/** {@inheritDoc} */
- public void startPart(TableBody part) {
+ public void startPart(TablePart part) {
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java
index 5b96a668e..9feb77c9c 100644
--- a/src/java/org/apache/fop/fo/flow/table/Table.java
+++ b/src/java/org/apache/fop/fo/flow/table/Table.java
@@ -76,8 +76,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
private ColumnNumberManager columnNumberManager = new ColumnNumberManager();
/** the table-header and -footer */
- private TableBody tableHeader = null;
- private TableBody tableFooter = null;
+ private TableHeader tableHeader = null;
+ private TableFooter tableFooter = null;
/** used for validation */
private boolean tableColumnFound = false;
@@ -157,10 +157,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
this.propList = pList;
}
- /**
- * {@inheritDoc}
- */
- public void startOfNode() throws FOPException {
+ /** {@inheritDoc} */
+ protected void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startTable(this);
}
@@ -200,7 +198,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
} else {
tableFooterFound = true;
if (tableBodyFound) {
- nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true);
+ if (getUserAgent().validateStrictly()) {
+ nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true);
+ }
if (!isSeparateBorderModel()) {
TableEventProducer eventProducer = TableEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
@@ -216,11 +216,15 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
}
- /**
- * {@inheritDoc}
- */
- public void endOfNode() throws FOPException {
+ /** {@inheritDoc} */
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endTable(this);
+ }
+ /** {@inheritDoc} */
+ public void finalizeNode() throws FOPException {
+
if (!tableBodyFound) {
missingChildElementError(
"(marker*,table-column*,table-header?,table-footer?"
@@ -242,13 +246,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
this.propList = null;
rowGroupBuilder = null;
}
- getFOEventHandler().endTable(this);
-
+
}
-
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
protected void addChildNode(FONode child) throws FOPException {
int childId = child.getNameId();
@@ -277,10 +278,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
switch (childId) {
case FO_TABLE_FOOTER:
- tableFooter = (TableBody) child;
+ tableFooter = (TableFooter) child;
break;
case FO_TABLE_HEADER:
- tableHeader = (TableBody) child;
+ tableHeader = (TableHeader) child;
break;
default:
super.addChildNode(child);
@@ -402,12 +403,12 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
/** @return the body for the table-header. */
- public TableBody getTableHeader() {
+ public TableHeader getTableHeader() {
return tableHeader;
}
/** @return the body for the table-footer. */
- public TableBody getTableFooter() {
+ public TableFooter getTableFooter() {
return tableFooter;
}
@@ -521,17 +522,17 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
return FO_TABLE;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public FONode clone(FONode parent, boolean removeChildren)
throws FOPException {
Table clone = (Table) super.clone(parent, removeChildren);
- clone.columnsFinalized = false;
if (removeChildren) {
clone.columns = new ArrayList();
+ clone.columnsFinalized = false;
+ clone.columnNumberManager = new ColumnNumberManager();
clone.tableHeader = null;
clone.tableFooter = null;
+ clone.rowGroupBuilder = null;
}
return clone;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java
index b4e48d2e6..b4071e255 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java
@@ -15,53 +15,18 @@
* limitations under the License.
*/
-/* $Id$ */
+/* $Id: $ */
package org.apache.fop.fo.flow.table;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.Locator;
-
-import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.PropertyList;
-import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.apps.FOPException;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-body">
* <code>fo:table-body</code></a> object.
*/
-public class TableBody extends TableCellContainer {
- // The value of properties relevant for fo:table-body.
- private CommonBorderPaddingBackground commonBorderPaddingBackground;
- // Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
- // private CommonAural commonAural;
- // private CommonRelativePosition commonRelativePosition;
- // private int visibility;
- // End of property values
-
- /**
- * used for validation
- */
- protected boolean tableRowsFound = false;
- protected boolean tableCellsFound = false;
-
- private boolean firstRow = true;
-
- private boolean rowsStarted = false;
-
- private boolean lastCellEndsRow = true;
-
- /** The last encountered table-row. */
- private TableRow lastRow;
-
- private List rowGroups = new LinkedList();
+public class TableBody extends TablePart {
/**
* Create a TableBody instance with the given {@link FONode}
@@ -73,159 +38,15 @@ public class TableBody extends TableCellContainer {
}
/** {@inheritDoc} */
- public void bind(PropertyList pList) throws FOPException {
- commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
- super.bind(pList);
- }
-
- /** {@inheritDoc} */
- public void processNode(String elementName, Locator locator,
- Attributes attlist, PropertyList pList)
- throws FOPException {
- if (!inMarker()) {
- Table t = getTable();
- if (t.hasExplicitColumns()) {
- int size = t.getNumberOfColumns();
- pendingSpans = new ArrayList(size);
- for (int i = 0; i < size; i++) {
- pendingSpans.add(null);
- }
- } else {
- pendingSpans = new ArrayList();
- }
- columnNumberManager = new ColumnNumberManager();
- }
- super.processNode(elementName, locator, attlist, pList);
- }
-
- /** {@inheritDoc} */
- public void startOfNode() throws FOPException {
+ protected void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startBody(this);
}
/** {@inheritDoc} */
- public void endOfNode() throws FOPException {
-
- if (!inMarker()) {
- pendingSpans = null;
- columnNumberManager = null;
- }
-
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
getFOEventHandler().endBody(this);
-
- if (!(tableRowsFound || tableCellsFound)) {
- missingChildElementError("marker* (table-row+|table-cell+)", true);
- getParent().removeChild(this);
- } else {
- finishLastRowGroup();
- }
- }
-
- /** {@inheritDoc} */
- TableBody getTablePart() {
- return this;
- }
-
- protected void finishLastRowGroup() throws ValidationException {
- if (!inMarker()) {
- RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
- if (tableRowsFound) {
- rowGroupBuilder.endTableRow();
- } else if (!lastCellEndsRow) {
- rowGroupBuilder.endRow(this);
- }
- try {
- rowGroupBuilder.endTablePart();
- } catch (ValidationException e) {
- e.setLocator(locator);
- throw e;
- }
- }
- }
-
- /**
- * {@inheritDoc}
- * <br>XSL Content Model: marker* (table-row+|table-cell+)
- */
- protected void validateChildNode(Locator loc, String nsURI, String localName)
- throws ValidationException {
- if (FO_URI.equals(nsURI)) {
- if (localName.equals("marker")) {
- if (tableRowsFound || tableCellsFound) {
- nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)");
- }
- } else if (localName.equals("table-row")) {
- tableRowsFound = true;
- if (tableCellsFound) {
- TableEventProducer eventProducer = TableEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.noMixRowsAndCells(this, getName(), getLocator());
- }
- } else if (localName.equals("table-cell")) {
- tableCellsFound = true;
- if (tableRowsFound) {
- TableEventProducer eventProducer = TableEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.noMixRowsAndCells(this, getName(), getLocator());
- }
- } else {
- invalidChildError(loc, nsURI, localName);
- }
- }
- }
-
- /** {@inheritDoc} */
- protected void addChildNode(FONode child) throws FOPException {
- if (!inMarker()) {
- switch (child.getNameId()) {
- case FO_TABLE_ROW:
- if (!rowsStarted) {
- getTable().getRowGroupBuilder().startTablePart(this);
- } else {
- columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().endTableRow();
- }
- rowsStarted = true;
- lastRow = (TableRow) child;
- getTable().getRowGroupBuilder().startTableRow(lastRow);
- break;
- case FO_TABLE_CELL:
- if (!rowsStarted) {
- getTable().getRowGroupBuilder().startTablePart(this);
- }
- rowsStarted = true;
- TableCell cell = (TableCell) child;
- addTableCellChild(cell, firstRow);
- lastCellEndsRow = cell.endsRow();
- if (lastCellEndsRow) {
- firstRow = false;
- columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().endRow(this);
- }
- break;
- default:
- //nop
- }
- }
- super.addChildNode(child);
- }
-
- void addRowGroup(List rowGroup) {
- rowGroups.add(rowGroup);
- }
-
- public List getRowGroups() {
- return rowGroups;
- }
-
- /**
- * Get the {@link CommonBorderPaddingBackground} instance attached
- * to this TableBody.
- * @return the {@link CommonBorderPaddingBackground} instance.
- */
- public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
- return commonBorderPaddingBackground;
}
/** {@inheritDoc} */
@@ -240,32 +61,4 @@ public class TableBody extends TableCellContainer {
public int getNameId() {
return FO_TABLE_BODY;
}
-
- protected boolean isTableHeader() {
- return false;
- }
-
- protected boolean isTableFooter() {
- return false;
- }
-
- /**
- * @param obj table row in question
- * @return true if the given table row is the first row of this body.
- */
- public boolean isFirst(TableRow obj) {
- return (firstChild == null
- || firstChild == obj);
- }
-
- void signalNewRow() {
- if (rowsStarted) {
- firstRow = false;
- if (!lastCellEndsRow) {
- columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().endRow(this);
- }
- }
- }
-
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java
index 2781bf082..21da54128 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java
@@ -81,7 +81,7 @@ public class TableCell extends TableFObj {
startsRow = pList.get(PR_STARTS_ROW).getEnum();
// For properly computing columnNumber
if (startsRow() && getParent().getNameId() != FO_TABLE_ROW) {
- ((TableBody) getParent()).signalNewRow();
+ ((TablePart) getParent()).signalNewRow();
}
endsRow = pList.get(PR_ENDS_ROW).getEnum();
columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue();
@@ -91,17 +91,24 @@ public class TableCell extends TableFObj {
}
/** {@inheritDoc} */
- public void startOfNode() throws FOPException {
+ protected void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startCell(this);
}
/**
* Make sure content model satisfied, if so then tell the
- * FOEventHandler that we are at the end of the flow.
+ * FOEventHandler that we are at the end of the table-cell.
* {@inheritDoc}
*/
- public void endOfNode() throws FOPException {
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endCell(this);
+ }
+
+ /** {@inheritDoc} */
+ public void finalizeNode() throws FOPException {
+
if (!blockItemFound) {
missingChildElementError("marker* (%block;)+", true);
}
@@ -111,9 +118,9 @@ public class TableCell extends TableFObj {
getUserAgent().getEventBroadcaster());
eventProducer.startEndRowUnderTableRowWarning(this, getLocator());
}
- getFOEventHandler().endCell(this);
+
}
-
+
/**
* {@inheritDoc}
* <br>XSL Content Model: marker* (%block;)+
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
index de9f271b5..1d1a29b35 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
@@ -95,9 +95,9 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
/**
* Returns the enclosing table-header/footer/body of this container.
*
- * @return <code>this</code> for TableBody, or the parent element for TableRow
+ * @return <code>this</code> for TablePart, or the parent element for TableRow
*/
- abstract TableBody getTablePart();
+ abstract TablePart getTablePart();
/** {@inheritDoc} */
public ColumnNumberManager getColumnNumberManager() {
diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
index 6916e090b..025f5a74f 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
@@ -239,7 +239,7 @@ public class TableColumn extends TableFObj {
sb.append(" number-columns-spanned=")
.append(getNumberColumnsSpanned());
}
- sb.append(" column-width=").append(getColumnWidth());
+ sb.append(" column-width=").append(((Property)getColumnWidth()).getString());
return sb.toString();
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index 016046ae2..370bb9de4 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
@@ -34,6 +34,8 @@ import org.apache.fop.fo.properties.NumberProperty;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.PropertyMaker;
import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
/**
* Common base class for table-related FOs
@@ -207,8 +209,8 @@ public abstract class TableFObj extends FObj {
}
/** {@inheritDoc} */
- public void startOfNode() throws FOPException {
- super.startOfNode();
+ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException {
+ super.processNode(elementName, locator, attlist, pList);
Table table = getTable();
if (!inMarker() && !table.isSeparateBorderModel()) {
collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
@@ -216,15 +218,7 @@ public abstract class TableFObj extends FObj {
setCollapsedBorders();
}
}
-
- /*
- * TODO made public so that RetrieveMarker can access it.
- */
- /** {@inheritDoc} */
- public void endOfNode() throws FOPException {
- super.endOfNode();
- }
-
+
/**
* Prepares the borders of this element if the collapsing-border model is in use.
* Conflict resolution with parent elements is done where applicable.
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
index d05824e95..a89a2e431 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
@@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-footer">
* <code>fo:table-footer</code></a> object.
*/
-public class TableFooter extends TableBody {
+public class TableFooter extends TablePart {
/**
* Create a TableFooter instance with the given {@link FONode}
@@ -41,17 +41,15 @@ public class TableFooter extends TableBody {
}
/** {@inheritDoc} */
- public void startOfNode() throws FOPException {
+ protected void startOfNode() throws FOPException {
super.startOfNode();
+ getFOEventHandler().startFooter(this);
}
/** {@inheritDoc} */
- public void endOfNode() throws FOPException {
- if (!(tableRowsFound || tableCellsFound)) {
- missingChildElementError("marker* (table-row+|table-cell+)");
- } else {
- finishLastRowGroup();
- }
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endFooter(this);
}
/** {@inheritDoc} */
@@ -67,8 +65,4 @@ public class TableFooter extends TableBody {
return FO_TABLE_FOOTER;
}
- /** {@inheritDoc} */
- protected boolean isTableFooter() {
- return true;
- }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
index 252ba1b8b..7f4173754 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
@@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-header">
* <code>fo:table-header</code></a> object.
*/
-public class TableHeader extends TableBody {
+public class TableHeader extends TablePart {
/**
* Create a TableHeader instance with the given {@link FONode}
@@ -40,17 +40,15 @@ public class TableHeader extends TableBody {
}
/** {@inheritDoc} */
- public void startOfNode() throws FOPException {
+ protected void startOfNode() throws FOPException {
super.startOfNode();
+ getFOEventHandler().startHeader(this);
}
/** {@inheritDoc} */
- public void endOfNode() throws FOPException {
- if (!(tableRowsFound || tableCellsFound)) {
- missingChildElementError("marker* (table-row+|table-cell+)");
- } else {
- finishLastRowGroup();
- }
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endHeader(this);
}
/** {@inheritDoc} */
@@ -66,8 +64,4 @@ public class TableHeader extends TableBody {
return FO_TABLE_HEADER;
}
- /** {@inheritDoc} */
- protected boolean isTableHeader() {
- return true;
- }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java
new file mode 100644
index 000000000..4d20db8c4
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: TableBody.java 655614 2008-05-12 19:37:39Z vhennebert $ */
+
+package org.apache.fop.fo.flow.table;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+
+/**
+ * An abstract base class modelling a TablePart
+ * (i.e. fo:table-header, fo:table-footer and fo:table-body).
+ */
+public abstract class TablePart extends TableCellContainer {
+ // The value of properties relevant for fo:table-body.
+ private CommonBorderPaddingBackground commonBorderPaddingBackground;
+ // Unused but valid items, commented out for performance:
+ // private CommonAccessibility commonAccessibility;
+ // private CommonAural commonAural;
+ // private CommonRelativePosition commonRelativePosition;
+ // private int visibility;
+ // End of property values
+
+ /**
+ * used for validation
+ */
+ protected boolean tableRowsFound = false;
+ protected boolean tableCellsFound = false;
+
+ private boolean firstRow = true;
+
+ private boolean rowsStarted = false;
+
+ private boolean lastCellEndsRow = true;
+
+ private List rowGroups = new LinkedList();
+
+ /**
+ * Create a TablePart instance with the given {@link FONode}
+ * as parent.
+ * @param parent FONode that is the parent of the object
+ */
+ public TablePart(FONode parent) {
+ super(parent);
+ }
+
+ /** {@inheritDoc} */
+ public void bind(PropertyList pList) throws FOPException {
+ commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
+ super.bind(pList);
+ }
+
+ /** {@inheritDoc} */
+ public void processNode(String elementName, Locator locator,
+ Attributes attlist, PropertyList pList)
+ throws FOPException {
+
+ super.processNode(elementName, locator, attlist, pList);
+ if (!inMarker()) {
+ Table t = getTable();
+ if (t.hasExplicitColumns()) {
+ int size = t.getNumberOfColumns();
+ pendingSpans = new ArrayList(size);
+ for (int i = 0; i < size; i++) {
+ pendingSpans.add(null);
+ }
+ } else {
+ pendingSpans = new ArrayList();
+ }
+ columnNumberManager = new ColumnNumberManager();
+ }
+
+ }
+
+ /** {@inheritDoc} */
+ public void finalizeNode() throws FOPException {
+ if (!inMarker()) {
+ pendingSpans = null;
+ columnNumberManager = null;
+ }
+
+ if (!(tableRowsFound || tableCellsFound)) {
+ missingChildElementError("marker* (table-row+|table-cell+)", true);
+ getParent().removeChild(this);
+ } else {
+ finishLastRowGroup();
+ }
+ }
+
+ /** {@inheritDoc} */
+ TablePart getTablePart() {
+ return this;
+ }
+
+ protected void finishLastRowGroup() throws ValidationException {
+ if (!inMarker()) {
+ RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
+ if (tableRowsFound) {
+ rowGroupBuilder.endTableRow();
+ } else if (!lastCellEndsRow) {
+ rowGroupBuilder.endRow(this);
+ }
+ try {
+ rowGroupBuilder.endTablePart();
+ } catch (ValidationException e) {
+ e.setLocator(locator);
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <br>XSL Content Model: marker* (table-row+|table-cell+)
+ */
+ protected void validateChildNode(Locator loc, String nsURI, String localName)
+ throws ValidationException {
+ if (FO_URI.equals(nsURI)) {
+ if (localName.equals("marker")) {
+ if (tableRowsFound || tableCellsFound) {
+ nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)");
+ }
+ } else if (localName.equals("table-row")) {
+ tableRowsFound = true;
+ if (tableCellsFound) {
+ TableEventProducer eventProducer = TableEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.noMixRowsAndCells(this, getName(), getLocator());
+ }
+ } else if (localName.equals("table-cell")) {
+ tableCellsFound = true;
+ if (tableRowsFound) {
+ TableEventProducer eventProducer = TableEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.noMixRowsAndCells(this, getName(), getLocator());
+ }
+ } else {
+ invalidChildError(loc, nsURI, localName);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void addChildNode(FONode child) throws FOPException {
+ if (!inMarker()) {
+ switch (child.getNameId()) {
+ case FO_TABLE_ROW:
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ } else {
+ columnNumberManager.prepareForNextRow(pendingSpans);
+ getTable().getRowGroupBuilder().endTableRow();
+ }
+ rowsStarted = true;
+ getTable().getRowGroupBuilder().startTableRow((TableRow)child);
+ break;
+ case FO_TABLE_CELL:
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ }
+ rowsStarted = true;
+ TableCell cell = (TableCell) child;
+ addTableCellChild(cell, firstRow);
+ lastCellEndsRow = cell.endsRow();
+ if (lastCellEndsRow) {
+ firstRow = false;
+ columnNumberManager.prepareForNextRow(pendingSpans);
+ getTable().getRowGroupBuilder().endRow(this);
+ }
+ break;
+ default:
+ //nop
+ }
+ }
+ super.addChildNode(child);
+ }
+
+ void addRowGroup(List rowGroup) {
+ rowGroups.add(rowGroup);
+ }
+
+ public List getRowGroups() {
+ return rowGroups;
+ }
+
+ /**
+ * Get the {@link CommonBorderPaddingBackground} instance attached
+ * to this TableBody.
+ * @return the {@link CommonBorderPaddingBackground} instance.
+ */
+ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return commonBorderPaddingBackground;
+ }
+
+ /**
+ * @param obj table row in question
+ * @return true if the given table row is the first row of this body.
+ */
+ public boolean isFirst(TableRow obj) {
+ return (firstChild == null
+ || firstChild == obj);
+ }
+
+ void signalNewRow() {
+ if (rowsStarted) {
+ firstRow = false;
+ if (!lastCellEndsRow) {
+ columnNumberManager.prepareForNextRow(pendingSpans);
+ getTable().getRowGroupBuilder().endRow(this);
+ }
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java
index 3be794fbd..ac6eafc2f 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableRow.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java
@@ -78,32 +78,38 @@ public class TableRow extends TableCellContainer {
/** {@inheritDoc} */
public void processNode(String elementName, Locator locator,
Attributes attlist, PropertyList pList) throws FOPException {
+ super.processNode(elementName, locator, attlist, pList);
if (!inMarker()) {
- TableBody body = (TableBody) parent;
- pendingSpans = body.pendingSpans;
- columnNumberManager = body.columnNumberManager;
+ TablePart part = (TablePart) parent;
+ pendingSpans = part.pendingSpans;
+ columnNumberManager = part.columnNumberManager;
}
- super.processNode(elementName, locator, attlist, pList);
}
/** {@inheritDoc} */
protected void addChildNode(FONode child) throws FOPException {
if (!inMarker()) {
TableCell cell = (TableCell) child;
- TableBody body = (TableBody) getParent();
- addTableCellChild(cell, body.isFirst(this));
+ TablePart part = (TablePart) getParent();
+ addTableCellChild(cell, part.isFirst(this));
}
super.addChildNode(child);
}
/** {@inheritDoc} */
- public void startOfNode() throws FOPException {
+ protected void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startRow(this);
}
/** {@inheritDoc} */
- public void endOfNode() throws FOPException {
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endRow(this);
+ }
+
+ /** {@inheritDoc} */
+ public void finalizeNode() throws FOPException {
if (firstChild == null) {
missingChildElementError("(table-cell+)");
}
@@ -111,9 +117,8 @@ public class TableRow extends TableCellContainer {
pendingSpans = null;
columnNumberManager = null;
}
- getFOEventHandler().endRow(this);
}
-
+
/**
* {@inheritDoc} String, String)
* <br>XSL Content Model: (table-cell+)
@@ -129,8 +134,8 @@ public class TableRow extends TableCellContainer {
}
/** {@inheritDoc} */
- TableBody getTablePart() {
- return (TableBody) parent;
+ TablePart getTablePart() {
+ return (TablePart) parent;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
index d59870f0a..23c16d1f2 100644
--- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
@@ -82,7 +82,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {
}
/** {@inheritDoc} */
- void endRow(final TableBody part) {
+ void endRow(final TablePart part) {
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) {
rowGroupBuilder.endRow(part);
@@ -91,7 +91,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {
}
/** {@inheritDoc} */
- void startTablePart(final TableBody part) {
+ void startTablePart(final TablePart part) {
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) {
rowGroupBuilder.startTablePart(part);
diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java
index 04014f6fc..c6346e9fb 100644
--- a/src/java/org/apache/fop/fo/pagination/Root.java
+++ b/src/java/org/apache/fop/fo/pagination/Root.java
@@ -27,6 +27,7 @@ import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOTreeBuilderContext;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
@@ -59,6 +60,11 @@ public class Root extends FObj {
private int totalPagesGenerated = 0;
/**
+ * Context class used while building the FO tree.
+ */
+ private FOTreeBuilderContext builderContext;
+
+ /**
* FOEventHandler object for this FO Tree
*/
private FOEventHandler foEventHandler = null;
@@ -164,10 +170,23 @@ public class Root extends FObj {
return foEventHandler;
}
- /**
- * Gets the last page number generated by the previous page-sequence
- * @return the last page number, 0 if no page sequences yet generated
+ /**
+ * Sets the builder context for this FO tree.
+ * @param context the builder context to be used
*/
+ public void setBuilderContext(FOTreeBuilderContext context) {
+ this.builderContext = context;
+ }
+
+ /** {@inheritDoc} */
+ public FOTreeBuilderContext getBuilderContext() {
+ return this.builderContext;
+ }
+
+ /**
+ * Gets the last page number generated by the previous page-sequence
+ * @return the last page number, 0 if no page sequences yet generated
+ */
public int getEndingPageNumberOfPreviousSequence() {
return endingPageNumberOfPreviousSequence;
}
diff --git a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java
index 839ac7022..542dcac32 100644
--- a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java
+++ b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java
@@ -23,7 +23,6 @@ import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
-import org.apache.fop.fo.properties.LengthProperty;
/**
* Custom Maker for page-height / page-width
@@ -54,8 +53,8 @@ public class PageDimensionMaker extends LengthProperty.Maker {
Property p = super.get(0, propertyList, tryInherit, tryDefault);
FObj fo = propertyList.getFObj();
String fallbackValue = (propId == Constants.PR_PAGE_HEIGHT)
- ? fo.getFOEventHandler().getUserAgent().getPageHeight()
- : fo.getFOEventHandler().getUserAgent().getPageWidth();
+ ? fo.getUserAgent().getPageHeight()
+ : fo.getUserAgent().getPageWidth();
if (p.getEnum() == Constants.EN_INDEFINITE) {
int otherId = (propId == Constants.PR_PAGE_HEIGHT)
diff --git a/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java
index ec5ea26bf..5e3ed816e 100644
--- a/src/java/org/apache/fop/fonts/FontSelector.java
+++ b/src/java/org/apache/fop/fonts/FontSelector.java
@@ -88,7 +88,7 @@ public final class FontSelector {
/**
* Selects a font which is able to display the most of the given characters.
*
- * @param textArray
+ * @param charSeq
* Text to go through
* @param firstIndex
* first index within text.
@@ -100,9 +100,10 @@ public final class FontSelector {
* the Percent-based context needed for creating the actual font.
* @return a Font object.
*/
- public static Font selectFontForCharactersInText(char[] textArray,
+ public static Font selectFontForCharactersInText(CharSequence charSeq,
int firstIndex, int breakIndex, FOText text,
PercentBaseContext context) {
+
final FontInfo fi = text.getFOEventHandler().getFontInfo();
final CommonFont commonFont = text.getCommonFont();
final FontTriplet[] fontkeys = commonFont.getFontState(fi);
@@ -115,7 +116,7 @@ public final class FontSelector {
commonFont.fontSize.getValue(context));
fonts[fontnum] = font;
for (int pos = firstIndex; pos < breakIndex; pos++) {
- if (font.hasChar(textArray[pos])) {
+ if (font.hasChar(charSeq.charAt(pos))) {
fontCount[fontnum]++;
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
index 087963013..862c0a4be 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
@@ -41,8 +41,8 @@ import org.apache.fop.fo.flow.Character;
import org.apache.fop.fo.flow.ExternalGraphic;
import org.apache.fop.fo.flow.Footnote;
import org.apache.fop.fo.flow.Inline;
-import org.apache.fop.fo.flow.InlineLevel;
import org.apache.fop.fo.flow.InlineContainer;
+import org.apache.fop.fo.flow.InlineLevel;
import org.apache.fop.fo.flow.InstreamForeignObject;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fo.flow.ListBlock;
@@ -224,7 +224,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
public static class FOTextLayoutManagerMaker extends Maker {
public void make(FONode node, List lms) {
FOText foText = (FOText) node;
- if (foText.endIndex - foText.startIndex > 0) {
+ if (foText.length() > 0) {
lms.add(new TextLayoutManager(foText));
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
index 575728f0d..c6210edce 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
@@ -61,20 +61,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
* Number of word-spaces?
*/
private class AreaInfo {
- private final short startIndex;
- private final short breakIndex;
- private final short wordSpaceCount;
- private short letterSpaceCount;
+ private final int startIndex;
+ private final int breakIndex;
+ private final int wordSpaceCount;
+ private int letterSpaceCount;
private final MinOptMax areaIPD;
private final boolean isHyphenated;
private final boolean isSpace;
private boolean breakOppAfter;
private final Font font;
- AreaInfo(final short startIndex,
- final short breakIndex,
- final short wordSpaceCount,
- final short letterSpaceCount,
+ AreaInfo(final int startIndex,
+ final int breakIndex,
+ final int wordSpaceCount,
+ final int letterSpaceCount,
final MinOptMax areaIPD,
final boolean isHyphenated,
final boolean isSpace,
@@ -132,7 +132,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0);
private final FOText foText;
- private final char[] textArray;
+
/**
* Contains an array of widths to adjust for kerning. The first entry can
* be used to influence the start position of the first letter. The entry i+1 defines the
@@ -143,7 +143,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
/** Font used for the space between words. */
private Font spaceFont = null;
/** Start index of next TextArea */
- private short nextStart = 0;
+ private int nextStart = 0;
/** size of a space character (U+0020) glyph in current font */
private int spaceCharIPD;
private MinOptMax wordSpaceIPD;
@@ -155,8 +155,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
private boolean hasChanged = false;
private int returnedIndex = 0;
- private short thisStart = 0;
- private short tempStart = 0;
+ private int thisStart = 0;
+ private int tempStart = 0;
private List changeList = null;
private AlignmentContext alignmentContext = null;
@@ -177,10 +177,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
super();
this.foText = node;
- this.textArray = new char[node.endIndex - node.startIndex];
- System.arraycopy(node.ca, node.startIndex, this.textArray, 0,
- node.endIndex - node.startIndex);
- this.letterAdjustArray = new MinOptMax[this.textArray.length + 1];
+ this.letterAdjustArray = new MinOptMax[node.length() + 1];
this.vecAreaInfo = new java.util.ArrayList();
}
@@ -205,6 +202,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
+ this.foText.resetBuffer();
+
this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this);
// With CID fonts, space isn't neccesary currentFontState.width(32)
@@ -296,7 +295,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
int letterSpaceCount, final int firstAreaInfoIndex,
final int lastAreaInfoIndex, final MinOptMax realWidth, final LayoutContext context) {
- // TODO: These two statements (if, for) where like this before my recent
+ // TODO: These two statements (if, for) were like this before my recent
// changes. However, it seems as if they should use the AreaInfo from
// firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai.
// This needs to be checked.
@@ -441,7 +440,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
// areaInfo stores information about spaces
// add the spaces - except zero-width spaces - to the TextArea
for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) {
- final char spaceChar = this.textArray[j];
+ final char spaceChar = this.foText.charAt(j);
if (!CharUtilities.isZeroWidthSpace(spaceChar)) {
textArea.addSpace(spaceChar, 0,
CharUtilities.isAdjustableSpace(spaceChar));
@@ -469,8 +468,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
for (int j = wordStartIndex; j <= i; j++) {
final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(j);
int lsCount = ai.letterSpaceCount;
- wordChars.append(this.textArray, ai.startIndex,
- ai.breakIndex - ai.startIndex);
+ /* TODO: in Java 5, StringBuffer has an append() variant
+ * for CharSequence, so the below iteration can be replaced
+ * by:
+ * wordChars.append(this.foText, ai.startIndex,
+ * ai.breakIndex - ai.startIndex);
+ */
+ for (int ci = ai.startIndex; ci < ai.breakIndex; ci++) {
+ wordChars.append(this.foText.charAt(ci));
+ }
for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) {
final MinOptMax adj = this.letterAdjustArray[ai.startIndex + k];
if (letter > 0) {
@@ -522,7 +528,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
|| CharUtilities.isNonBreakableSpace(ch)
|| CharUtilities.isFixedWidthSpace(ch);
}
-
+
/** {@inheritDoc} */
public List getNextKnuthElements(final LayoutContext context, final int alignment) {
this.lineStartBAP = context.getLineStartBorderAndPaddingWidth();
@@ -540,8 +546,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
boolean inWord = false;
boolean inWhitespace = false;
char ch = 0;
- while (this.nextStart < this.textArray.length) {
- ch = this.textArray[this.nextStart];
+ while (this.nextStart < this.foText.length()) {
+ ch = this.foText.charAt(this.nextStart);
boolean breakOpportunity = false;
final byte breakAction = this.keepTogether ? LineBreakStatus.PROHIBITED_BREAK
: lbs.nextChar(ch);
@@ -560,10 +566,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction);
}
if (inWord) {
- if (breakOpportunity
+ if (breakOpportunity
|| TextLayoutManager.isSpace(ch)
|| CharUtilities.isExplicitBreak(ch)) {
- // this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN
+ // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN
prevAi = this.processWord(alignment, sequence, prevAi, ch,
breakOpportunity, true);
}
@@ -588,24 +594,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
|| ch == CharUtilities.NBSPACE) {
// preserved space or non-breaking space:
// create the AreaInfo object
- ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1),
- (short) 1, (short) 0, this.wordSpaceIPD, false, true,
+ ai = new AreaInfo(this.nextStart, this.nextStart + 1,
+ 1, 0, this.wordSpaceIPD, false, true,
breakOpportunity, this.spaceFont);
- this.thisStart = (short) (this.nextStart + 1);
+ this.thisStart = this.nextStart + 1;
} else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) {
// create the AreaInfo object
final Font font = FontSelector.selectFontForCharacterInText(ch,
this.foText, this);
final MinOptMax ipd = new MinOptMax(font.getCharWidth(ch));
- ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1),
- (short) 0, (short) 0, ipd, false, true,
+ ai = new AreaInfo(this.nextStart, this.nextStart + 1,
+ 0, 0, ipd, false, true,
breakOpportunity, font);
- this.thisStart = (short) (this.nextStart + 1);
+ this.thisStart = this.nextStart + 1;
} else if (CharUtilities.isExplicitBreak(ch)) {
//mandatory break-character: only advance index
- this.thisStart = (short) (this.nextStart + 1);
+ this.thisStart = this.nextStart + 1;
}
-
+
inWord = !TextLayoutManager.isSpace(ch)
&& !CharUtilities.isExplicitBreak(ch);
inWhitespace = ch == CharUtilities.SPACE
@@ -619,17 +625,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
} else if (inWhitespace) {
this.processWhitespace(alignment, sequence, true);
} else if (ai != null) {
- ai = this.processLeftoverAi(alignment, sequence, ai, ch,
+ this.processLeftoverAi(alignment, sequence, ai, ch,
ch == CharUtilities.ZERO_WIDTH_SPACE);
} else if (CharUtilities.isExplicitBreak(ch)) {
- sequence = this.processLinebreak(returnList, sequence);
+ this.processLinebreak(returnList, sequence);
}
if (((List) ListUtil.getLast(returnList)).isEmpty()) {
//Remove an empty sequence because of a trailing newline
ListUtil.removeLast(returnList);
}
-
+
this.setFinished(true);
if (returnList.isEmpty()) {
return null;
@@ -663,24 +669,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
private AreaInfo processWhitespace(final int alignment,
final KnuthSequence sequence, final boolean breakOpportunity) {
- AreaInfo ai;
- AreaInfo prevAi;
// End of whitespace
// create the AreaInfo object
- ai = new AreaInfo(this.thisStart, this.nextStart,
- (short) (this.nextStart - this.thisStart), (short) 0,
+ AreaInfo ai = new AreaInfo(this.thisStart, this.nextStart,
+ this.nextStart - this.thisStart, 0,
MinOptMax.multiply(this.wordSpaceIPD, this.nextStart
- this.thisStart), false, true,
breakOpportunity, this.spaceFont);
this.vecAreaInfo.add(ai);
- prevAi = ai;
// create the elements
this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1);
- ai = null;
this.thisStart = this.nextStart;
- return prevAi;
+ return ai;
}
private AreaInfo processWord(final int alignment, final KnuthSequence sequence,
@@ -688,21 +690,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
final boolean checkEndsWithHyphen) {
AreaInfo ai;
//Word boundary found, process widths and kerning
- short lastIndex = this.nextStart;
+ int lastIndex = this.nextStart;
while (lastIndex > 0
- && this.textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) {
+ && this.foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) {
lastIndex--;
}
final boolean endsWithHyphen = checkEndsWithHyphen
- && this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN;
+ && this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN;
final Font font = FontSelector
- .selectFontForCharactersInText(this.textArray,
+ .selectFontForCharactersInText(this.foText,
this.thisStart, lastIndex, this.foText, this);
final int wordLength = lastIndex - this.thisStart;
final boolean kerning = font.hasKerning();
final MinOptMax wordIPD = new MinOptMax(0);
for (int i = this.thisStart; i < lastIndex; i++) {
- final char c = this.textArray[i];
+ final char c = this.foText.charAt(i);
//character width
final int charWidth = font.getCharWidth(c);
@@ -712,10 +714,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
if (kerning) {
int kern = 0;
if (i > this.thisStart) {
- final char previous = this.textArray[i - 1];
+ final char previous = this.foText.charAt(i - 1);
kern = font.getKernValue(previous, c) * font.getFontSize() / 1000;
} else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) {
- final char previous = this.textArray[prevAi.breakIndex - 1];
+ final char previous = this.foText.charAt(prevAi.breakIndex - 1);
kern = font.getKernValue(previous, c) * font.getFontSize() / 1000;
}
if (kern != 0) {
@@ -730,7 +732,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
&& lastIndex > 0
&& endsWithHyphen) {
final int kern = font.getKernValue(
- this.textArray[lastIndex - 1], ch)
+ this.foText.charAt(lastIndex - 1), ch)
* font.getFontSize() / 1000;
if (kern != 0) {
this.addToLetterAdjust(lastIndex, kern);
@@ -746,8 +748,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces));
// create the AreaInfo object
- ai = new AreaInfo(this.thisStart, lastIndex, (short) 0,
- (short) iLetterSpaces, wordIPD,
+ ai = new AreaInfo(this.thisStart, lastIndex, 0,
+ iLetterSpaces, wordIPD,
endsWithHyphen,
false, breakOpportunity, font);
prevAi = ai;
@@ -776,7 +778,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(idx);
ai.letterSpaceCount++;
ai.areaIPD.add(this.letterSpaceIPD);
- if (TextLayoutManager.BREAK_CHARS.indexOf(this.textArray[this.tempStart - 1]) >= 0) {
+ if (TextLayoutManager.BREAK_CHARS.indexOf(this.foText.charAt(this.tempStart - 1)) >= 0) {
// the last character could be used as a line break
// append new elements to oldList
oldListIterator = oldList.listIterator(oldList.size());
@@ -867,7 +869,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
//log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex));
for (int i = startIndex; i < stopIndex; i++) {
- final char c = this.textArray[i];
+ final char c = this.foText.charAt(i);
newIPD.add(new MinOptMax(font.getCharWidth(c)));
//if (i > startIndex) {
if (i < stopIndex) {
@@ -899,8 +901,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
this.changeList = new LinkedList();
}
this.changeList.add(new PendingChange(new AreaInfo(
- (short) startIndex, (short) stopIndex, (short) 0,
- (short) (isWordEnd ? stopIndex - startIndex - 1
+ startIndex, stopIndex, 0,
+ (isWordEnd ? stopIndex - startIndex - 1
: stopIndex - startIndex), newIPD,
hyphenFollows, false, false, font),
((LeafPosition) pos).getLeafPos()));
@@ -973,7 +975,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
final int leafValue = ((LeafPosition) pos).getLeafPos();
if (leafValue != -1) {
final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(leafValue);
- sbChars.append(this.textArray, ai.startIndex, ai.breakIndex - ai.startIndex);
+ for (int i = ai.startIndex; i < ai.breakIndex; ++i) {
+ sbChars.append(this.foText.charAt(i));
+ }
}
}
@@ -999,7 +1003,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
mainPosition, true));
}
} else {
- if (this.textArray[ai.startIndex] != CharUtilities.SPACE
+ if (this.foText.charAt(ai.startIndex) != CharUtilities.SPACE
|| this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) {
// a breaking space that needs to be preserved
this.addElementsForBreakingSpace(baseList, alignment, ai,
@@ -1153,7 +1157,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
// or it ends with a character that can be used as a line break
if (ai.isHyphenated) {
MinOptMax widthIfNoBreakOccurs = null;
- if (ai.breakIndex < this.textArray.length) {
+ if (ai.breakIndex < this.foText.length()) {
//Add in kerning in no-break condition
widthIfNoBreakOccurs = this.letterAdjustArray[ai.breakIndex];
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
index d432c7657..38f1a7b30 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
@@ -32,7 +32,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
-import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthElement;
@@ -94,7 +94,7 @@ class RowPainter {
this.firstRowOnPageIndex = -1;
}
- void startTablePart(TableBody tablePart) {
+ void startTablePart(TablePart tablePart) {
CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground();
if (background.hasBackground()) {
tablePartBackground = background;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index 43b34e4b7..52915c008 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -31,7 +31,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
@@ -439,7 +439,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
-startIndent);
}
- TableBody body = primaryGridUnit.getTableBody();
+ TablePart body = primaryGridUnit.getTablePart();
if (body.getCommonBorderPaddingBackground().hasBackground()) {
painter.registerPartBackgroundArea(
getBackgroundArea(paddingRectBPD, borderBeforeWidth));
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index 9b4a03a67..80e904f8f 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -19,7 +19,6 @@
package org.apache.fop.layoutmgr.table;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -35,7 +34,7 @@ import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ElementListUtils;
@@ -324,7 +323,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
this.usedBPD = 0;
RowPainter painter = new RowPainter(this, layoutContext);
- List tablePositions = new ArrayList();
+ List tablePositions = new java.util.ArrayList();
List headerElements = null;
List footerElements = null;
Position firstPos = null;
@@ -417,9 +416,9 @@ public class TableContentLayoutManager implements PercentBaseContext {
}
}
- private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter,
+ private void addHeaderFooterAreas(List elements, TablePart part, RowPainter painter,
boolean lastOnPage) {
- List lst = new ArrayList(elements.size());
+ List lst = new java.util.ArrayList(elements.size());
for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) {
Position pos = (Position) iter.next();
/*
@@ -446,32 +445,32 @@ public class TableContentLayoutManager implements PercentBaseContext {
private void addBodyAreas(Iterator iterator, RowPainter painter,
boolean lastOnPage) {
painter.startBody();
- List lst = new ArrayList();
+ List lst = new java.util.ArrayList();
TableContentPosition pos = (TableContentPosition) iterator.next();
boolean isFirstPos = pos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
&& pos.getRow().getFlag(EffRow.FIRST_IN_PART);
- TableBody body = pos.getTableBody();
+ TablePart part = pos.getTablePart();
lst.add(pos);
while (iterator.hasNext()) {
pos = (TableContentPosition) iterator.next();
- if (pos.getTableBody() != body) {
- addTablePartAreas(lst, painter, body, isFirstPos, true, false, false);
+ if (pos.getTablePart() != part) {
+ addTablePartAreas(lst, painter, part, isFirstPos, true, false, false);
isFirstPos = true;
lst.clear();
- body = pos.getTableBody();
+ part = pos.getTablePart();
}
lst.add(pos);
}
boolean isLastPos = pos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
&& pos.getRow().getFlag(EffRow.LAST_IN_PART);
- addTablePartAreas(lst, painter, body, isFirstPos, isLastPos, true, lastOnPage);
+ addTablePartAreas(lst, painter, part, isFirstPos, isLastPos, true, lastOnPage);
painter.endBody();
}
/**
* Adds the areas corresponding to a single fo:table-header/footer/body element.
*/
- private void addTablePartAreas(List positions, RowPainter painter, TableBody body,
+ private void addTablePartAreas(List positions, RowPainter painter, TablePart body,
boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) {
getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
true, isFirstPos, isLastPos);
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
index 260b8cfdf..62d25fcb1 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
@@ -22,7 +22,7 @@ package org.apache.fop.layoutmgr.table;
import java.util.List;
import org.apache.fop.fo.flow.table.EffRow;
-import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.Position;
@@ -80,8 +80,8 @@ class TableContentPosition extends Position {
return row;
}
- TableBody getTableBody() {
- return ((CellPart) cellParts.get(0)).pgu.getTableBody();
+ TablePart getTablePart() {
+ return ((CellPart) cellParts.get(0)).pgu.getTablePart();
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
index 62e308c13..282cd0fd5 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
@@ -28,6 +28,7 @@ import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
/**
@@ -69,7 +70,7 @@ public class TableRowIterator {
case FOOTER:
rowGroupsIter = table.getTableFooter().getRowGroups().iterator();
break;
- default:
+ case BODY:
List rowGroupsList = new LinkedList();
// TODO this is ugly
for (FONodeIterator iter = table.getChildNodes(); iter.hasNext();) {
@@ -79,6 +80,9 @@ public class TableRowIterator {
}
}
rowGroupsIter = rowGroupsList.iterator();
+ break;
+ default:
+ throw new IllegalArgumentException("Unrecognised TablePart: " + tablePart);
}
}
diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
index 86210b07a..a6c08747f 100644
--- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
@@ -38,6 +38,7 @@ import org.apache.fop.area.Block;
import org.apache.fop.area.BlockViewport;
import org.apache.fop.area.CTM;
import org.apache.fop.area.NormalFlow;
+import org.apache.fop.area.RegionReference;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.ForeignObject;
@@ -96,19 +97,20 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
*/
protected void handleRegionTraits(RegionViewport region) {
Rectangle2D viewArea = region.getViewArea();
+ RegionReference referenceArea = region.getRegionReference();
float startx = (float)(viewArea.getX() / 1000f);
float starty = (float)(viewArea.getY() / 1000f);
float width = (float)(viewArea.getWidth() / 1000f);
float height = (float)(viewArea.getHeight() / 1000f);
- if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) {
- currentBPPosition = region.getBorderAndPaddingWidthBefore();
- currentIPPosition = region.getBorderAndPaddingWidthStart();
- }
- drawBackAndBorders(region, startx, starty, width, height);
+ // adjust the current position according to region borders and padding
+ currentBPPosition = referenceArea.getBorderAndPaddingWidthBefore();
+ currentIPPosition = referenceArea.getBorderAndPaddingWidthStart();
+ // draw background (traits are in the RegionViewport)
+ // and borders (traits are in the RegionReference)
+ drawBackAndBorders(region, referenceArea, startx, starty, width, height);
}
-
/**
* Draw the background and borders.
* This draws the background and border traits for an area given
@@ -123,14 +125,57 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
protected void drawBackAndBorders(Area area,
float startx, float starty,
float width, float height) {
+ drawBackAndBorders(area, area, startx, starty, width, height);
+ }
+
+ /**
+ * Draw the background and borders.
+ * This draws the background and border traits for an area given
+ * the position.
+ *
+ * @param backgroundArea the area to get the background traits from
+ * @param borderArea the area to get the border traits from
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void drawBackAndBorders(Area backgroundArea, Area borderArea,
+ float startx, float starty,
+ float width, float height) {
// draw background then border
- BorderProps bpsBefore = (BorderProps)area.getTrait(Trait.BORDER_BEFORE);
- BorderProps bpsAfter = (BorderProps)area.getTrait(Trait.BORDER_AFTER);
- BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START);
- BorderProps bpsEnd = (BorderProps)area.getTrait(Trait.BORDER_END);
+ BorderProps bpsBefore = (BorderProps)borderArea.getTrait(Trait.BORDER_BEFORE);
+ BorderProps bpsAfter = (BorderProps)borderArea.getTrait(Trait.BORDER_AFTER);
+ BorderProps bpsStart = (BorderProps)borderArea.getTrait(Trait.BORDER_START);
+ BorderProps bpsEnd = (BorderProps)borderArea.getTrait(Trait.BORDER_END);
- Trait.Background back = (Trait.Background)area.getTrait(Trait.BACKGROUND);
+ drawBackground(startx, starty, width, height,
+ (Trait.Background) backgroundArea.getTrait(Trait.BACKGROUND),
+ bpsBefore, bpsAfter, bpsStart, bpsEnd);
+ drawBorders(startx, starty, width, height,
+ bpsBefore, bpsAfter, bpsStart, bpsEnd);
+ }
+
+ /**
+ * Draw the background.
+ * This draws the background given the position and the traits.
+ *
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ * @param back the background traits
+ * @param bpsBefore the border-before traits
+ * @param bpsAfter the border-after traits
+ * @param bpsStart the border-start traits
+ * @param bpsEnd the border-end traits
+ */
+ protected void drawBackground(float startx, float starty,
+ float width, float height,
+ Trait.Background back,
+ BorderProps bpsBefore, BorderProps bpsAfter,
+ BorderProps bpsStart, BorderProps bpsEnd) {
if (back != null) {
endTextObject();
@@ -201,7 +246,25 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
restoreGraphicsState();
}
}
+ }
+ /**
+ * Draw the borders.
+ * This draws the border traits given the position and the traits.
+ *
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ * @param bpsBefore the border-before traits
+ * @param bpsAfter the border-after traits
+ * @param bpsStart the border-start traits
+ * @param bpsEnd the border-end traits
+ */
+ protected void drawBorders(float startx, float starty,
+ float width, float height,
+ BorderProps bpsBefore, BorderProps bpsAfter,
+ BorderProps bpsStart, BorderProps bpsEnd) {
Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height);
drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
}
diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java
index 05aade551..6171e68b4 100644
--- a/src/java/org/apache/fop/render/rtf/RTFHandler.java
+++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java
@@ -76,6 +76,8 @@ import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableHeader;
@@ -611,25 +613,29 @@ public class RTFHandler extends FOEventHandler {
/**
* {@inheritDoc}
*/
- public void startHeader(TableBody th) {
+ public void startHeader(TableHeader header) {
+ startPart(header);
}
/**
* {@inheritDoc}
*/
- public void endHeader(TableBody th) {
+ public void endHeader(TableHeader header) {
+ endPart(header);
}
/**
* {@inheritDoc}
*/
- public void startFooter(TableBody tf) {
+ public void startFooter(TableFooter footer) {
+ startPart(footer);
}
/**
* {@inheritDoc}
*/
- public void endFooter(TableBody tf) {
+ public void endFooter(TableFooter footer) {
+ endPart(footer);
}
/**
@@ -687,31 +693,25 @@ public class RTFHandler extends FOEventHandler {
}
}
- /**
- * {@inheritDoc}
- */
- public void startBody(TableBody tb) {
+ private void startPart(TablePart part) {
if (bDefer) {
return;
}
try {
- RtfAttributes atts = TableAttributesConverter.convertTableBodyAttributes(tb);
+ RtfAttributes atts = TableAttributesConverter.convertTablePartAttributes(part);
RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
tbl.setHeaderAttribs(atts);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
- log.error("startBody: " + e.getMessage());
+ log.error("startPart: " + e.getMessage());
throw new RuntimeException(e.getMessage());
- }
+ }
}
- /**
- * {@inheritDoc}
- */
- public void endBody(TableBody tb) {
+ private void endPart(TablePart tb) {
if (bDefer) {
return;
}
@@ -722,9 +722,25 @@ public class RTFHandler extends FOEventHandler {
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
- log.error("endBody: " + e.getMessage());
+ log.error("endPart: " + e.getMessage());
throw new RuntimeException(e.getMessage());
- }
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startBody(TableBody body) {
+ startPart(body);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endBody(TableBody body) {
+ endPart(body);
}
/**
@@ -1552,7 +1568,7 @@ public class RTFHandler extends FOEventHandler {
} else if (foNode instanceof FOText) {
if (bStart) {
FOText text = (FOText) foNode;
- text(text, text.ca, text.startIndex, text.endIndex);
+ text(text, text.getCharArray(), 0, text.length());
}
} else if (foNode instanceof Character) {
if (bStart) {
@@ -1607,6 +1623,18 @@ public class RTFHandler extends FOEventHandler {
} else {
endTable( (Table) foNode);
}
+ } else if (foNode instanceof TableHeader) {
+ if (bStart) {
+ startHeader( (TableHeader) foNode);
+ } else {
+ endHeader( (TableHeader) foNode);
+ }
+ } else if (foNode instanceof TableFooter) {
+ if (bStart) {
+ startFooter( (TableFooter) foNode);
+ } else {
+ endFooter( (TableFooter) foNode);
+ }
} else if (foNode instanceof TableBody) {
if (bStart) {
startBody( (TableBody) foNode);
diff --git a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java
index 677832418..a28d91d36 100644
--- a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java
+++ b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java
@@ -24,12 +24,11 @@ import java.awt.Color;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
-import org.apache.fop.fo.properties.FixedLength;
import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
@@ -91,7 +90,7 @@ public final class TableAttributesConverter {
*
* @throws ConverterException On convertion error
*/
- static RtfAttributes convertTableBodyAttributes(TableBody fobj)
+ static RtfAttributes convertTablePartAttributes(TablePart part)
throws FOPException {
FOPRtfAttributes attrib = new FOPRtfAttributes();
return attrib;
diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java
index 6baa5c0fd..eb56cd331 100644
--- a/src/java/org/apache/fop/util/CharUtilities.java
+++ b/src/java/org/apache/fop/util/CharUtilities.java
@@ -54,10 +54,14 @@ public class CharUtilities {
public static final int XMLWHITESPACE = 4;
+ /** null char */
+ public static final char NULL_CHAR = '\u0000';
/** linefeed character */
public static final char LINEFEED_CHAR = '\n';
/** carriage return */
public static final char CARRIAGE_RETURN = '\r';
+ /** normal tab */
+ public static final char TAB = '\t';
/** normal space */
public static final char SPACE = '\u0020';
/** non-breaking space */
@@ -80,9 +84,12 @@ public class CharUtilities {
public static final char PARAGRAPH_SEPARATOR = '\u2029';
/** missing ideograph */
public static final char MISSING_IDEOGRAPH = '\u25A1';
+ /** Ideogreaphic space */
+ public static final char IDEOGRAPHIC_SPACE = '\u3000';
/** Unicode value indicating the the character is "not a character". */
public static final char NOT_A_CHARACTER = '\uFFFF';
+
/**
* Utility class: Constructor prevents instantiating when subclassed.
*/
@@ -97,11 +104,18 @@ public class CharUtilities {
* @return the determined character class
*/
public static int classOf(char c) {
- if (c == CODE_EOT) { return EOT; }
- if (c == '\n') { return LINEFEED; }
- if (c == ' ' || c == '\r' || c == '\t') { return XMLWHITESPACE; }
- if (isAnySpace(c)) { return UCWHITESPACE; }
- return NONWHITESPACE;
+ switch (c) {
+ case CODE_EOT:
+ return EOT;
+ case LINEFEED_CHAR:
+ return LINEFEED;
+ case SPACE:
+ case CARRIAGE_RETURN:
+ case TAB:
+ return XMLWHITESPACE;
+ default:
+ return isAnySpace(c) ? UCWHITESPACE : NONWHITESPACE;
+ }
}
diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/XMLizable.java
deleted file mode 100644
index a16131989..000000000
--- a/src/java/org/apache/fop/util/XMLizable.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.util;
-
-/*
- * Copied from Apache Excalibur:
- * https://svn.apache.org/repos/asf/excalibur/trunk/components/xmlutil/
- * src/java/org/apache/excalibur/xml/sax/XMLizable.java
- */
-
-/**
- * This interface can be implemented by classes willing to provide an XML representation
- * of their current state as SAX events.
- * @deprecated Use the interface in Apache XML Graphics Commons instead.
- */
-public interface XMLizable extends org.apache.xmlgraphics.util.XMLizable {
-
-}
diff --git a/status.xml b/status.xml
index 3f30869ca..42996789e 100644
--- a/status.xml
+++ b/status.xml
@@ -53,6 +53,10 @@
<changes>
<release version="FOP Trunk" date="TBD">
+ <action context="Layout" dev="LF" type="add">
+ Allowing non-zero borders and padding on page regions when
+ relaxed validation is turned on.
+ </action>
<action context="Layout" dev="LF" type="fix">
Fixed an inconsistency in footnote handling that led to unnecessary
empty areas in pages whose last normal line contains footnotes
diff --git a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
index 3abc2f73b..d26426513 100644
--- a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
@@ -108,7 +108,7 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase {
super();
}
- private static GridUnit getGridUnit(TableBody part) {
+ private static GridUnit getGridUnit(TablePart part) {
return (GridUnit) ((List) ((List) part.getRowGroups().get(0)).get(0)).get(0);
}
@@ -137,8 +137,8 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase {
do {
String baseErrorMsge = "table " + Integer.toString(tableNum) + " (0-based), ";
Table table = (Table) tableIterator.next();
- TableBody body = (TableBody) table.getChildNodes().nextNode();
- GridUnit gu = getGridUnit(body);
+ TablePart part = (TablePart) table.getChildNodes().nextNode();
+ GridUnit gu = getGridUnit(part);
String errorMsge = baseErrorMsge + "border-before";
checkBorder(errorMsge, gu.borderBefore.normal, 8000, Color.black);
@@ -163,14 +163,14 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase {
int borderNum = 0;
Table table = (Table) tableIterator.next();
- TableBody header = table.getTableHeader();
+ TableHeader header = table.getTableHeader();
GridUnit gu = getGridUnit(header);
checkBorder(errorMsge, gu.borderBefore.normal,
resolvedBordersHF[tableNum][borderNum++]);
checkBorder(errorMsge, gu.borderBefore.rest,
resolvedBordersHF[tableNum][borderNum++]);
- TableBody footer = table.getTableFooter();
+ TableFooter footer = table.getTableFooter();
gu = getGridUnit(footer);
checkBorder(errorMsge, gu.borderAfter.normal,
resolvedBordersHF[tableNum][borderNum++]);
diff --git a/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java b/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
index a89ff2eea..498df92b4 100644
--- a/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
@@ -38,12 +38,12 @@ public class RowGroupBuilderTestCase extends AbstractTableTestCase {
* given array, and that the number of rows inside each row group is equal to the
* corresponding integer in the array.
*
- * @param body a body whose row groups are to be checked
+ * @param part a table part whose row groups are to be checked
* @param expectedRowLengths expected lengths of all the row groups of this part of
* the table
*/
- private void checkTablePartRowGroups(TableBody body, int[] expectedRowLengths) {
- Iterator rowGroupIter = body.getRowGroups().iterator();
+ private void checkTablePartRowGroups(TablePart part, int[] expectedRowLengths) {
+ Iterator rowGroupIter = part.getRowGroups().iterator();
for (int i = 0; i < expectedRowLengths.length; i++) {
assertTrue(rowGroupIter.hasNext());
List rowGroup = (List) rowGroupIter.next();
diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml
index ba985bf8d..ca05b156b 100644
--- a/test/layoutengine/disabled-testcases.xml
+++ b/test/layoutengine/disabled-testcases.xml
@@ -216,4 +216,11 @@
<description>A soft hyphen should be a preferred as break compared to a
normal hyphenation point but is not.</description>
</testcase>
+ <testcase>
+ <name>Borders and padding on page regions</name>
+ <file>simple-page-master_borders_padding.xml</file>
+ <description>Borders and padding on regions are now implemented but
+ relaxed validation must be switched on, otherwise there is a validation
+ exception.</description>
+ </testcase>
</disabled-testcases>
diff --git a/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml b/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml
new file mode 100644
index 000000000..8ce6101a3
--- /dev/null
+++ b/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+ <info>
+ <p>
+ This test checks page-masters (all regions). The empty block-containers are used to check that all the base widths are set correctly so
+ length evaluation using percentages is possible.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="master1" page-width="5in" page-height="5in" margin="10pt">
+ <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="50pt" border-before-width="1pt" border-color="rgb(50%, 50%, 40%)" border-style="solid" border-end-width="2pt" border-after-width="3pt" border-start-width="4pt" padding-before="9pt" padding-end="8pt" padding-after="7pt" padding-start="6pt"/>
+ <fo:region-before background-color="rgb(100%, 80%, 80%)" border="solid 5pt rgb(50%, 40%, 40%)" extent="50pt"/>
+ <fo:region-after background-color="rgb(80%, 80%, 80%)" border="solid 1pt rgb(40%, 40%, 50%)" padding="3pt" extent="50pt" precedence="true" display-align="after"/>
+ <fo:region-start background-color="rgb(80%, 100%, 80%)" padding="3pt" extent="50pt"/>
+ <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="50pt" reference-orientation="270"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="master1" white-space-collapse="true" orphans="0" widows="0">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block-container absolute-position="absolute" width="100%" height="100%" top="0pt" left="0pt">
+ <fo:block/>
+ </fo:block-container>
+ <fo:block>region-before1</fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-after">
+ <fo:block-container absolute-position="absolute" width="100%" height="100%" top="0pt" left="0pt">
+ <fo:block/>
+ </fo:block-container>
+ <fo:block font-size="50%">region-after1 with precedence and display-align="after"</fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-start">
+ <fo:block-container absolute-position="absolute" width="100%" height="100%" top="0pt" left="0pt">
+ <fo:block/>
+ </fo:block-container>
+ <fo:block>region-start1</fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-end">
+ <fo:block-container absolute-position="absolute" width="100%" height="100%" top="0pt" left="0pt">
+ <fo:block/>
+ </fo:block-container>
+ <fo:block>region-end1</fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block-container absolute-position="absolute" width="100%" height="100%" top="0pt" left="0pt">
+ <fo:block/>
+ </fo:block-container>
+ <fo:block>testing all-regions1</fo:block>
+ <fo:block>testing all-regions2</fo:block>
+ <fo:block>testing all-regions3</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="0 0 360000 360000" xpath="//pageViewport/@bounds"/>
+
+ <eval expected="50000" xpath="//regionBefore/@bpda"/>
+ <eval expected="240000" xpath="//regionBefore/@ipda"/>
+ <eval expected="40000" xpath="//regionBefore/@bpd"/>
+ <eval expected="230000" xpath="//regionBefore/@ipd"/>
+ <eval expected="(solid,#806666,5000)" xpath="//regionBefore/@border-before"/>
+ <eval expected="(solid,#806666,5000)" xpath="//regionBefore/@border-after"/>
+ <eval expected="(solid,#806666,5000)" xpath="//regionBefore/@border-start"/>
+ <eval expected="(solid,#806666,5000)" xpath="//regionBefore/@border-end"/>
+ <eval expected="40000" xpath="//regionBefore/block[@positioning='absolute']/@bpda"/>
+ <eval expected="230000" xpath="//regionBefore/block[@positioning='absolute']/@ipda"/>
+
+ <eval expected="50000" xpath="//regionAfter/@bpda"/>
+ <eval expected="340000" xpath="//regionAfter/@ipda"/>
+ <eval expected="42000" xpath="//regionAfter/@bpd"/>
+ <eval expected="332000" xpath="//regionAfter/@ipd"/>
+ <eval expected="(solid,#666680,1000)" xpath="//regionAfter/@border-before"/>
+ <eval expected="(solid,#666680,1000)" xpath="//regionAfter/@border-after"/>
+ <eval expected="(solid,#666680,1000)" xpath="//regionAfter/@border-start"/>
+ <eval expected="(solid,#666680,1000)" xpath="//regionAfter/@border-end"/>
+ <eval expected="3000" xpath="//regionAfter/@padding-before"/>
+ <eval expected="3000" xpath="//regionAfter/@padding-after"/>
+ <eval expected="3000" xpath="//regionAfter/@padding-start"/>
+ <eval expected="3000" xpath="//regionAfter/@padding-end"/>
+ <eval expected="42000" xpath="//regionAfter/block[@positioning='absolute']/@bpda"/>
+ <eval expected="332000" xpath="//regionAfter/block[@positioning='absolute']/@ipda"/>
+
+ <eval expected="290000" xpath="//regionStart/@bpda"/>
+ <eval expected="50000" xpath="//regionStart/@ipda"/>
+ <eval expected="284000" xpath="//regionStart/@bpd"/>
+ <eval expected="44000" xpath="//regionStart/@ipd"/>
+ <eval expected="3000" xpath="//regionStart/@padding-before"/>
+ <eval expected="3000" xpath="//regionStart/@padding-after"/>
+ <eval expected="3000" xpath="//regionStart/@padding-start"/>
+ <eval expected="3000" xpath="//regionStart/@padding-end"/>
+ <eval expected="284000" xpath="//regionStart/block[@positioning='absolute']/@bpda"/>
+ <eval expected="44000" xpath="//regionStart/block[@positioning='absolute']/@ipda"/>
+
+ <eval expected="50000" xpath="//regionEnd/@bpda"/>
+ <eval expected="290000" xpath="//regionEnd/@ipda"/>
+ <eval expected="50000" xpath="//regionEnd/@bpd"/>
+ <eval expected="290000" xpath="//regionEnd/@ipd"/>
+ <eval expected="50000" xpath="//regionEnd/block[@positioning='absolute']/@bpda"/>
+ <eval expected="290000" xpath="//regionEnd/block[@positioning='absolute']/@ipda"/>
+
+ <eval expected="240000" xpath="//regionBody/@bpda"/>
+ <eval expected="240000" xpath="//regionBody/@ipda"/>
+ <eval expected="220000" xpath="//regionBody/@bpda"/>
+ <eval expected="220000" xpath="//regionBody/@ipda"/>
+ <eval expected="(solid,#808066,1000)" xpath="//regionBody/@border-before"/>
+ <eval expected="(solid,#808066,3000)" xpath="//regionBody/@border-after"/>
+ <eval expected="(solid,#808066,4000)" xpath="//regionBody/@border-start"/>
+ <eval expected="(solid,#808066,2000)" xpath="//regionBody/@border-end"/>
+ <eval expected="9000" xpath="//regionBody/@padding-before"/>
+ <eval expected="7000" xpath="//regionBody/@padding-after"/>
+ <eval expected="6000" xpath="//regionBody/@padding-start"/>
+ <eval expected="8000" xpath="//regionBody/@padding-end"/>
+ <eval expected="220000" xpath="//regionBody/mainReference/span/flow/block[@positioning='absolute']/@bpda"/>
+ <eval expected="220000" xpath="//regionBody/mainReference/span/flow/block[@positioning='absolute']/@ipda"/>
+
+ </checks>
+</testcase>
diff --git a/test/layoutengine/testcase2fo.xsl b/test/layoutengine/testcase2fo.xsl
index 0b677471d..522f53fa7 100644
--- a/test/layoutengine/testcase2fo.xsl
+++ b/test/layoutengine/testcase2fo.xsl
@@ -50,16 +50,12 @@ value as subsitution value.
</xsl:when>
<xsl:otherwise>
<!-- if variable isn't defined, just copy -->
- <xsl:copy>
- <xsl:apply-templates select="node()" mode="copy"/>
- </xsl:copy>
+ <xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
- <xsl:copy>
- <xsl:apply-templates select="node()" mode="copy"/>
- </xsl:copy>
+ <xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>