Author: adelmelle
Date: Thu Nov 25 21:27:44 2010
New Revision: 1039188
URL: http://svn.apache.org/viewvc?rev=1039188&view=rev
Log:
Bugzilla 38264: hyphenation in combination with preserved linefeeds and/or
white-space
no longer causes duplication of content and missing hyphens
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
xmlgraphics/fop/trunk/status.xml
xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.xml
xmlgraphics/fop/trunk/test/layoutengine/hyphenation-testcases/block_hyphenation_linefeed_preserve.xml
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java?rev=1039188&r1=1039187&r2=1039188&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
(original)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
Thu Nov 25 21:27:44 2010
@@ -771,7 +771,7 @@ public class LineLayoutManager extends I
// we only need an entry in lineLayoutsList.
llPoss = new LineLayoutPossibilities();
} else {
- llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq);
+ llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq,
!paragraphsIterator.hasNext());
}
lineLayoutsList[i] = llPoss;
}
@@ -783,12 +783,13 @@ public class LineLayoutManager extends I
}
/**
- * Fint the optimal linebreaks for a paragraph
+ * Find the optimal linebreaks for a paragraph
* @param alignment alignment of the paragraph
* @param currPar the Paragraph for which the linebreaks are found
+ * @param isLastPar flag indicating whether currPar is the last paragraph
* @return the line layout possibilities for the paragraph
*/
- private LineLayoutPossibilities findOptimalBreakingPoints(int alignment,
Paragraph currPar) {
+ private LineLayoutPossibilities findOptimalBreakingPoints(int alignment,
Paragraph currPar, boolean isLastPar) {
// use the member lineLayouts, which is read by
LineBreakingAlgorithm.updateData1 and 2
lineLayouts = new LineLayoutPossibilities();
double maxAdjustment = 1;
@@ -808,7 +809,7 @@ public class LineLayoutManager extends I
if (canHyphenate && !hyphenationPerformed) {
// make sure findHyphenationPoints() is bypassed if
// the method is called twice (e.g. due to changing page-ipd)
- hyphenationPerformed = true;
+ hyphenationPerformed = isLastPar;
findHyphenationPoints(currPar);
}
@@ -1423,8 +1424,6 @@ public class LineLayoutManager extends I
*/
private void addInlineArea(LayoutContext context, LineBreakPosition lbp,
boolean isLastPosition) {
- // the TLM which created the last KnuthElement in this line
- LayoutManager lastLM = null;
KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(lbp.parIndex);
int startElementIndex = lbp.startIndex;
@@ -1456,15 +1455,16 @@ public class LineLayoutManager extends I
}
}
- // Remove trailing spaces if allowed so
- if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED
- || whiteSpaceTreament == EN_IGNORE
- || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) {
- // ignore the last element in the line if it is a KnuthGlue object
- ListIterator seqIterator = seq.listIterator(endElementIndex);
- KnuthElement lastElement = (KnuthElement) seqIterator.next();
- lastLM = lastElement.getLayoutManager();
- if (lastElement.isGlue()) {
+ // ignore the last element in the line if it is a KnuthGlue object
+ ListIterator seqIterator = seq.listIterator(endElementIndex);
+ KnuthElement lastElement = (KnuthElement) seqIterator.next();
+ // the TLM which created the last KnuthElement in this line
+ LayoutManager lastLM = lastElement.getLayoutManager();
+ if (lastElement.isGlue()) {
+ // Remove trailing spaces if allowed so
+ if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED
+ || whiteSpaceTreament == EN_IGNORE
+ || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) {
endElementIndex--;
// this returns the same KnuthElement
seqIterator.previous();
@@ -1480,7 +1480,7 @@ public class LineLayoutManager extends I
|| whiteSpaceTreament == EN_IGNORE_IF_AFTER_LINEFEED) {
// ignore KnuthGlue and KnuthPenalty objects
// at the beginning of the line
- ListIterator seqIterator = seq.listIterator(startElementIndex);
+ seqIterator = seq.listIterator(startElementIndex);
while (seqIterator.hasNext() && !((KnuthElement)
seqIterator.next()).isBox()) {
startElementIndex++;
}
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java?rev=1039188&r1=1039187&r2=1039188&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
(original)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
Thu Nov 25 21:27:44 2010
@@ -165,7 +165,8 @@ public class TextLayoutManager extends L
private int hyphIPD;
private boolean hasChanged = false;
- private int returnedIndex = 0;
+ private int[] returnedIndices = {0, 0};
+ private int changeOffset = 0;
private int thisStart = 0;
private int tempStart = 0;
private List changeList = new LinkedList();
@@ -811,19 +812,19 @@ public class TextLayoutManager extends L
//TODO: add kern to wordIPD?
}
}
- int iLetterSpaces = wordLength - 1;
+ int letterSpaces = wordLength - 1;
// if there is a break opportunity and the next one
// is not a space, it could be used as a line end;
// add one more letter space, in case other text follows
if (breakOpportunity && !TextLayoutManager.isSpace(ch)) {
- iLetterSpaces++;
+ letterSpaces++;
}
- assert iLetterSpaces >= 0;
- wordIPD = wordIPD.plus(letterSpaceIPD.mult(iLetterSpaces));
+ assert letterSpaces >= 0;
+ wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces));
// create the AreaInfo object
AreaInfo areaInfo = new AreaInfo(thisStart, lastIndex, 0,
- iLetterSpaces, wordIPD,
+ letterSpaces, wordIPD,
endsWithHyphen,
false, breakOpportunity, font);
prevAreaInfo = areaInfo;
@@ -903,11 +904,9 @@ public class TextLayoutManager extends L
}
}
- /**
- * {...@inheritdoc}
- */
+ /** {...@inheritdoc} */
public void hyphenate(Position pos, HyphContext hyphContext) {
- AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos());
+ AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos() +
changeOffset);
int startIndex = areaInfo.startIndex;
int stopIndex;
boolean nothingChanged = true;
@@ -962,7 +961,7 @@ public class TextLayoutManager extends L
// the new AreaInfo object is not equal to the old one
changeList.add(new PendingChange(new AreaInfo(startIndex,
stopIndex, 0,
letterSpaceCount, newIPD, hyphenFollows, false, false,
font),
- ((LeafPosition) pos).getLeafPos()));
+ ((LeafPosition) pos).getLeafPos() + changeOffset));
nothingChanged = false;
}
startIndex = stopIndex;
@@ -972,11 +971,41 @@ public class TextLayoutManager extends L
/** {...@inheritdoc} */
public boolean applyChanges(final List oldList) {
+
+ // make sure the LM appears unfinished in between this call
+ // and the next call to getChangedKnuthElements()
setFinished(false);
+ if (oldList.isEmpty()) {
+ return false;
+ }
+
+ // Find the first and last positions in oldList that point to an
AreaInfo
+ // (i.e. getLeafPos() != -1)
+ LeafPosition startPos = null, endPos = null;
+ ListIterator oldListIter;
+ for (oldListIter = oldList.listIterator(); oldListIter.hasNext();) {
+ startPos = (LeafPosition) ((KnuthElement)
oldListIter.next()).getPosition();
+ if (startPos != null && startPos.getLeafPos() != -1) {
+ break;
+ }
+ }
+ for (oldListIter = oldList.listIterator(oldList.size());
oldListIter.hasPrevious();) {
+ endPos = (LeafPosition) ((KnuthElement)
oldListIter.previous()).getPosition();
+ if (endPos != null && endPos.getLeafPos() != -1) {
+ break;
+ }
+ }
+
+ // set start/end index, taking into account any offset due to
+ // changes applied to previous paragraphs
+ returnedIndices[0] = (startPos != null ? startPos.getLeafPos() : -1) +
changeOffset;
+ returnedIndices[1] = (endPos != null ? endPos.getLeafPos() : -1) +
changeOffset;
+
+ int areaInfosAdded = 0;
+ int areaInfosRemoved = 0;
+
if (!changeList.isEmpty()) {
- int areaInfosAdded = 0;
- int areaInfosRemoved = 0;
int oldIndex = -1, changeIndex;
PendingChange currChange;
ListIterator changeListIterator = changeList.listIterator();
@@ -997,7 +1026,11 @@ public class TextLayoutManager extends L
changeList.clear();
}
- returnedIndex = 0;
+ // increase the end index for getChangedKnuthElements()
+ returnedIndices[1] += (areaInfosAdded - areaInfosRemoved);
+ // increase offset to use for subsequent paragraphs
+ changeOffset += (areaInfosAdded - areaInfosRemoved);
+
return hasChanged;
}
@@ -1009,27 +1042,24 @@ public class TextLayoutManager extends L
final LinkedList returnList = new LinkedList();
- while (returnedIndex < areaInfos.size()) {
- AreaInfo areaInfo = getAreaInfo(returnedIndex);
+ for (; returnedIndices[0] <= returnedIndices[1]; returnedIndices[0]++)
{
+ AreaInfo areaInfo = getAreaInfo(returnedIndices[0]);
if (areaInfo.wordSpaceCount == 0) {
// areaInfo refers either to a word or a word fragment
- addElementsForAWordFragment(returnList, alignment, areaInfo,
returnedIndex);
+ addElementsForAWordFragment(returnList, alignment, areaInfo,
returnedIndices[0]);
} else {
// areaInfo refers to a space
- addElementsForASpace(returnList, alignment, areaInfo,
returnedIndex);
+ addElementsForASpace(returnList, alignment, areaInfo,
returnedIndices[0]);
}
- returnedIndex++;
}
- setFinished(true);
+ setFinished(returnedIndices[0] == areaInfos.size() - 1);
//ElementListObserver.observe(returnList, "text-changed", null);
return returnList;
}
- /**
- * {...@inheritdoc}
- */
+ /** {...@inheritdoc} */
public String getWordChars(Position pos) {
- int leafValue = ((LeafPosition) pos).getLeafPos();
+ int leafValue = ((LeafPosition) pos).getLeafPos() + changeOffset;
if (leafValue != -1) {
AreaInfo areaInfo = getAreaInfo(leafValue);
StringBuffer buffer = new StringBuffer(areaInfo.getCharLength());
Modified: xmlgraphics/fop/trunk/status.xml
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=1039188&r1=1039187&r2=1039188&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Nov 25 21:27:44 2010
@@ -58,6 +58,9 @@
documents. Example: the fix of marks layering will be such a case when
it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Layout" dev="AD" type="fix" fixes-bug="38264">
+ Fixed behavior when combining hyphenation with preserved linefeeds or
whitespace.
+ </action>
<action context="Code" dev="VH" type="fix" fixes-bug="49695"
due-to="Joshua Marquart">
Replaced magic numbers with constants from UnitConv and
GraphicsConstants.
</action>
Modified: xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.xml
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.xml?rev=1039188&r1=1039187&r2=1039188&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.xml (original)
+++ xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.xml Thu Nov 25
21:27:44 2010
@@ -39,12 +39,6 @@
<description>Font-stretch is not implemented, yet.</description>
</testcase>
<testcase>
- <name>Hyphenation with preserved linefeeds</name>
- <file>block_hyphenation_linefeed_preserve.xml</file>
- <description>When hyphenation is enabled and linefeeds are preserved,
- the text is output multiple times.</description>
- </testcase>
- <testcase>
<name>linefeed-treatment</name>
<file>block_linefeed-treatment.xml</file>
<description>Preserved linefeeds in a fo:character are not handled
Modified:
xmlgraphics/fop/trunk/test/layoutengine/hyphenation-testcases/block_hyphenation_linefeed_preserve.xml
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/hyphenation-testcases/block_hyphenation_linefeed_preserve.xml?rev=1039188&r1=1039187&r2=1039188&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/test/layoutengine/hyphenation-testcases/block_hyphenation_linefeed_preserve.xml
(original)
+++
xmlgraphics/fop/trunk/test/layoutengine/hyphenation-testcases/block_hyphenation_linefeed_preserve.xml
Thu Nov 25 21:27:44 2010
@@ -19,7 +19,11 @@
<testcase>
<info>
<p>
- Check for bug: Duplicate content and linefeeds as "#".
+ Check for bug 38264:
+ <ul>
+ <li>duplication of content with linefeed-treatment="preserve" and
hyphenate="true"</li>
+ <li>missing hyphens with white-space-treatment="preserve" and
hyphenate="true"</li>
+ </ul>
</p>
</info>
<fo>
@@ -31,21 +35,39 @@
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">
- <fo:block line-height="10pt" background-color="orange"
- white-space-collapse="false" white-space-treatment="preserve"
linefeed-treatment="preserve">Lorem ipsum dolor sit amet, consectetuer
adipiscing elit. Maecenas semper. Proin at.</fo:block>
- <fo:block line-height="10pt" background-color="orange"
- white-space-collapse="false" white-space-treatment="preserve"
linefeed-treatment="preserve">
+ <fo:block white-space-collapse="false"
white-space-treatment="preserve" linefeed-treatment="preserve">
line1
line2
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas semper.
Proin at1.
-</fo:block>
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas semper.
Proin at.
+ </fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
- <!-- Dummy check. We don't want an NPE. -->
- <eval expected="2" xpath="count(//*[contains(text(), 'adipiscing')])"/>
+ <!-- check number of lines and word fragments -->
+ <eval expected="13" xpath="count(//flow[1]/block/lineArea)" />
+ <eval expected="17" xpath="count(//flow[1]/block/lineArea/text/word)" />
+ <!-- check individual word fragments -->
+ <eval expected="line1" xpath="(//flow[1]/block/lineArea/text/word)[1]" />
+ <eval expected="line2" xpath="(//flow[1]/block/lineArea/text/word)[2]" />
+ <eval expected="Lorem" xpath="(//flow[1]/block/lineArea/text/word)[3]" />
+ <eval expected="ip-" xpath="(//flow[1]/block/lineArea/text/word)[4]" />
+ <eval expected="sum" xpath="(//flow[1]/block/lineArea/text/word)[5]" />
+ <eval expected="dolor" xpath="(//flow[1]/block/lineArea/text/word)[6]" />
+ <eval expected="sit" xpath="(//flow[1]/block/lineArea/text/word)[7]" />
+ <eval expected="amet," xpath="(//flow[1]/block/lineArea/text/word)[8]" />
+ <eval expected="con-" xpath="(//flow[1]/block/lineArea/text/word)[9]" />
+ <eval expected="sectetuer"
xpath="(//flow[1]/block/lineArea/text/word)[10]" />
+ <eval expected="adipiscing"
xpath="(//flow[1]/block/lineArea/text/word)[11]" />
+ <eval expected="elit." xpath="(//flow[1]/block/lineArea/text/word)[12]" />
+ <eval expected="Maece-" xpath="(//flow[1]/block/lineArea/text/word)[13]" />
+ <eval expected="nas" xpath="(//flow[1]/block/lineArea/text/word)[14]" />
+ <eval expected="semper." xpath="(//flow[1]/block/lineArea/text/word)[15]"
/>
+ <eval expected="Proin" xpath="(//flow[1]/block/lineArea/text/word)[16]" />
+ <eval expected="at." xpath="(//flow[1]/block/lineArea/text/word)[17]" />
+ <!-- check preservation of spaces on the last line -->
+ <eval expected="10"
xpath="count((//flow[1]/block/lineArea)[13]/text/space)" />
</checks>
</testcase>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]