From aa26e120ea76254da8fb7a0585f51fdd1c9bbf39 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 23 Aug 2006 11:28:29 +0000 Subject: [PATCH] Minor improvement: avoid potential problems in case of nested blocks git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@434010 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/XMLWhiteSpaceHandler.java | 152 ++++++++++-------- 1 file changed, 89 insertions(+), 63 deletions(-) diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index 183224ce1..3a5fcf23a 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -31,11 +31,11 @@ import org.apache.fop.util.CharUtilities; */ public class XMLWhiteSpaceHandler { - // True if we are in a run of white space + /** True if we are in a run of white space */ private boolean inWhiteSpace = false; - // True if the last char was a linefeed + /** True if the last char was a linefeed */ private boolean afterLinefeed = true; - // Counter, increased every time a non-white-space is encountered + /** Counter, increased every time a non-white-space is encountered */ private int nonWhiteSpaceCount; private Block currentBlock; @@ -50,6 +50,7 @@ public class XMLWhiteSpaceHandler { private List discardableFOCharacters; private List pendingInlines; + private List nestedBlockStack = new java.util.ArrayList(5); private CharIterator firstWhiteSpaceInSeq; /** @@ -72,65 +73,66 @@ public class XMLWhiteSpaceHandler { * @param firstTextNode the node at which to start */ public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode) { - if (fo.getNameId() == Constants.FO_BLOCK - || fo.getNameId() == Constants.FO_RETRIEVE_MARKER) { - if (fo.getNameId() == Constants.FO_BLOCK) { - this.currentBlock = (Block) fo; - } else { - FONode ancestor = fo.parent; - while (ancestor.getNameId() != Constants.FO_BLOCK - && ancestor.getNameId() != Constants.FO_STATIC_CONTENT) { - ancestor = ancestor.getParent(); - } - if (ancestor.getNameId() == Constants.FO_BLOCK) { - this.currentBlock = (Block) ancestor; - } - } - if (currentBlock != null) { - this.linefeedTreatment = currentBlock.getLinefeedTreatment(); - this.whiteSpaceCollapse = currentBlock.getWhitespaceCollapse(); - this.whiteSpaceTreatment = - currentBlock.getWhitespaceTreatment(); - } else { - /* fo:retrieve-marker as direct child of static-content - * set properties to their initial values + + int foId = fo.getNameId(); + + if (foId == Constants.FO_BLOCK) { + if (nextChild != null && currentBlock != null) { + /* if already in a block, push the current block + * onto the stack of nested blocks */ - this.linefeedTreatment = Constants.EN_TREAT_AS_SPACE; - this.whiteSpaceCollapse = Constants.EN_TRUE; - this.whiteSpaceTreatment = - Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; + pushNestedBlockStack(); } - } else if (fo.getNameId() == Constants.FO_TITLE - || fo.getNameId() == Constants.FO_BOOKMARK_TITLE) { - /* Two special types of FO that can contain #PCDATA - * set properties to their initial values - */ - this.linefeedTreatment = Constants.EN_TREAT_AS_SPACE; - this.whiteSpaceCollapse = Constants.EN_TRUE; - this.whiteSpaceTreatment = - Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; + currentBlock = (Block) fo; + } else if (foId == Constants.FO_RETRIEVE_MARKER) { + /* look for the nearest block ancestor, if any */ + FONode ancestor; + do { + ancestor = fo.getParent(); + } while (ancestor.getNameId() != Constants.FO_BLOCK + && ancestor.getNameId() != Constants.FO_STATIC_CONTENT); + + if (ancestor.getNameId() == Constants.FO_BLOCK) { + currentBlock = (Block) ancestor; + } + } + + if (currentBlock != null) { + linefeedTreatment = currentBlock.getLinefeedTreatment(); + whiteSpaceCollapse = currentBlock.getWhitespaceCollapse(); + whiteSpaceTreatment = currentBlock.getWhitespaceTreatment(); + } else { + linefeedTreatment = Constants.EN_TREAT_AS_SPACE; + whiteSpaceCollapse = Constants.EN_TRUE; + whiteSpaceTreatment = Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; } + currentFO = fo; + if (firstTextNode == null) { //nothing to do but initialize related properties return; } + charIter = new RecursiveCharIterator(fo, firstTextNode); inWhiteSpace = false; - int textNodeIndex = -1; + if (currentFO == currentBlock || currentBlock == null - || (currentFO.getNameId() == Constants.FO_RETRIEVE_MARKER + || (foId == Constants.FO_RETRIEVE_MARKER && currentFO.getParent() == currentBlock)) { - textNodeIndex = fo.childNodes.indexOf(firstTextNode); - afterLinefeed = ((textNodeIndex == 0) - || (textNodeIndex > 0 + int textNodeIndex = fo.childNodes.indexOf(firstTextNode); + afterLinefeed = ( + (textNodeIndex == 0) + || (textNodeIndex > 0 && ((FONode) fo.childNodes.get(textNodeIndex - 1)) - .getNameId() == Constants.FO_BLOCK)); + .getNameId() == Constants.FO_BLOCK)); } + endOfBlock = (nextChild == null && currentFO == currentBlock); + if (nextChild != null) { - int nextChildId = nextChild.getNameId(); + int nextChildId = this.nextChild.getNameId(); nextChildIsBlockLevel = ( nextChildId == Constants.FO_BLOCK || nextChildId == Constants.FO_TABLE_AND_CAPTION @@ -140,7 +142,9 @@ public class XMLWhiteSpaceHandler { } else { nextChildIsBlockLevel = false; } + handleWhiteSpace(); + if (currentFO == currentBlock && pendingInlines != null && !pendingInlines.isEmpty()) { @@ -151,7 +155,8 @@ public class XMLWhiteSpaceHandler { PendingInline p; for (int i = pendingInlines.size(); --i >= 0;) { p = (PendingInline) pendingInlines.get(i); - charIter = (RecursiveCharIterator) p.firstTrailingWhiteSpace; + charIter = + (RecursiveCharIterator) p.firstTrailingWhiteSpace; handleWhiteSpace(); pendingInlines.remove(p); } @@ -163,24 +168,28 @@ public class XMLWhiteSpaceHandler { } } } - if (currentFO != currentBlock && nextChild == null) { - /* current FO is not a block, and is about to end */ - if (nonWhiteSpaceCount > 0 && pendingInlines != null) { - /* there is non-white-space text between the pending - * inline(s) and the end of the non-block node; - * clear list of pending inlines */ - pendingInlines.clear(); - } - if (inWhiteSpace) { - /* means there is at least one trailing space in the - inline FO that is about to end */ - addPendingInline(fo); - } - } - if (currentFO == currentBlock && nextChild == null) { - /* end of block: clear the reference */ - currentBlock = null; + if (nextChild == null) { + if (currentFO != currentBlock) { + /* current FO is not a block, and is about to end */ + if (nonWhiteSpaceCount > 0 && pendingInlines != null) { + /* there is non-white-space text between the pending + * inline(s) and the end of the non-block node; + * clear list of pending inlines */ + pendingInlines.clear(); + } + if (inWhiteSpace) { + /* means there is at least one trailing space in the + inline FO that is about to end */ + addPendingInline(fo); + } + } else { + /* end of block: clear the references and pop the + * nested block stack */ + popNestedBlockStack(); + currentFO = null; + charIter = null; + } } } @@ -311,6 +320,23 @@ public class XMLWhiteSpaceHandler { pendingInlines.add(new PendingInline(fo, firstWhiteSpaceInSeq)); } + private void pushNestedBlockStack() { + this.nestedBlockStack.add( + this.nestedBlockStack.size(), this.currentBlock); + } + + private void popNestedBlockStack() { + + if (this.nestedBlockStack.isEmpty()) { + this.currentBlock = null; + } else { + this.currentBlock = (Block) this.nestedBlockStack.get( + this.nestedBlockStack.size() - 1); + this.nestedBlockStack.remove(this.currentBlock); + } + + } + private class EOLchecker { private boolean nextIsEOL = false; private RecursiveCharIterator charIter; -- 2.39.5