aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorLuca Furini <lfurini@apache.org>2005-09-27 11:47:05 +0000
committerLuca Furini <lfurini@apache.org>2005-09-27 11:47:05 +0000
commit82b0754a00bb3cde82dbb71fd43a0b201bad0bce (patch)
treed4f0db898f998c1e6c23b2f4ac755aa993c8a4ad /src/java/org/apache
parent0aeafe0ea0e5faad1839610e710c7b96b3327498 (diff)
downloadxmlgraphics-fop-82b0754a00bb3cde82dbb71fd43a0b201bad0bce.tar.gz
xmlgraphics-fop-82b0754a00bb3cde82dbb71fd43a0b201bad0bce.zip
Correct handling of letter spaces, in combination with different text alignments and optional breaks ("-" and "/" characters in the text)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@291913 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java25
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java139
2 files changed, 92 insertions, 72 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
index 7056f4dbb..c7a702f1c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
@@ -93,19 +93,18 @@ public class LineLayoutManager extends InlineStackingLayoutManager
* inline break positions.
*/
private static class LineBreakPosition extends LeafPosition {
- // int iPos;
- int iParIndex; // index of the Paragraph this Position refers to
- int availableShrink;
- int availableStretch;
- int difference;
- double dAdjust; // Percentage to adjust (stretch or shrink)
- double ipdAdjust; // Percentage to adjust (stretch or shrink)
- int startIndent;
- int lineHeight;
- int lineWidth;
- int baseline;
- int topShift;
- int bottomShift;
+ private int iParIndex; // index of the Paragraph this Position refers to
+ private int availableShrink;
+ private int availableStretch;
+ private int difference;
+ private double dAdjust; // Percentage to adjust (stretch or shrink)
+ private double ipdAdjust; // Percentage to adjust (stretch or shrink)
+ private int startIndent;
+ private int lineHeight;
+ private int lineWidth;
+ private int baseline;
+ private int topShift;
+ private int bottomShift;
LineBreakPosition(LayoutManager lm, int index, int iBreakIndex,
int shrink, int stretch, int diff,
diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
index 3f4de96a1..8edd09f08 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
@@ -287,6 +287,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
}
if (ai == null) {
return;
+ } else if (ai.iLScount == ai.iBreakIndex - ai.iStartIndex
+ && context.isLastArea()) {
+ // the line ends at a character like "/" or "-";
+ // remove the letter space after the last character
+ realWidth.add(MinOptMax.multiply(letterSpaceIPD, -1));
+ iLScount --;
}
// Make an area containing all characters between start and end.
@@ -343,6 +349,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
// there are no word spaces in this area
}
iTotalAdjust += (iWordSpaceDim - wordSpaceIPD.opt) * iWScount;
+ if (iTotalAdjust != iDifference) {
+ // the applied adjustment is greater or smaller than the needed one
+ log.trace("TextLM.addAreas: error in word / letter space adjustment = "
+ + (iTotalAdjust - iDifference));
+ // set iTotalAdjust = iDifference, so that the width of the TextArea
+ // will counterbalance the error and the other inline areas will be
+ // placed correctly
+ iTotalAdjust = iDifference;
+ }
TextArea t = createTextArea(str, realWidth, iTotalAdjust, context,
wordSpaceIPD.opt - spaceCharIPD);
@@ -478,27 +493,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
&& textArray[iTempStart] != NBSPACE
&& textArray[iTempStart] != NEWLINE
&& !(iTempStart > iNextStart
- && alignment == EN_JUSTIFY
&& BREAK_CHARS.indexOf(textArray[iTempStart - 1]) >= 0);
iTempStart++) {
wordIPD.add(fs.getCharWidth(textArray[iTempStart]));
}
int iLetterSpaces = iTempStart - iThisStart - 1;
+ // if the last character is '-' or '/' 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 (BREAK_CHARS.indexOf(textArray[iTempStart - 1]) >= 0
+ && iTempStart < textArray.length
+ && textArray[iTempStart] != SPACE
+ && textArray[iTempStart] != NBSPACE) {
+ iLetterSpaces ++;
+ }
wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces));
// create the AreaInfo object
ai = new AreaInfo(iThisStart, iTempStart, (short) 0,
(short) iLetterSpaces,
wordIPD, false);
- // if the last character is '-' or '/' and other characters
- // follows, it could be used as a line end; update the
- // information in the AreaInfo, adding one more letter space
- if (BREAK_CHARS.indexOf(textArray[iTempStart - 1]) >= 0
- && iTempStart < textArray.length
- && textArray[iTempStart] != SPACE
- && textArray[iTempStart] != NBSPACE) {
- ai.iLScount ++;
- }
vecAreaInfo.add(ai);
// create the elements
@@ -804,79 +818,79 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
AreaInfo ai, int leafValue, MinOptMax letterSpaceWidth) {
LinkedList wordElements = new LinkedList();
LeafPosition mainPosition = new LeafPosition(this, leafValue);
- int unsuppressibleLetterSpaces = ai.iLScount;
- // if the last character of the word fragment is '-' or '/' and
- // the next one is not a space, the fragment could end a line;
- // in this case, it loses one of its letter spaces;
- if (BREAK_CHARS.indexOf(textArray[ai.iBreakIndex - 1]) >= 0
- && ai.iLScount == (ai.iBreakIndex - ai.iStartIndex)) {
- unsuppressibleLetterSpaces --;
- }
+ // if the last character of the word fragment is '-' or '/',
+ // the fragment could end a line; in this case, it loses one
+ // of its letter spaces;
+ boolean bSuppressibleLetterSpace =
+ ai.iLScount == (ai.iBreakIndex - ai.iStartIndex)
+ && BREAK_CHARS.indexOf(textArray[ai.iBreakIndex - 1]) >= 0;
if (letterSpaceWidth.min == letterSpaceWidth.max) {
// constant letter spacing
wordElements.add
- (new KnuthInlineBox(ai.ipdArea.opt, lead, total, middle,
- mainPosition, false));
+ (new KnuthInlineBox(
+ bSuppressibleLetterSpace ?
+ ai.ipdArea.opt - letterSpaceWidth.opt :
+ ai.ipdArea.opt,
+ lead, total, middle,
+ mainPosition, false));
} else {
// adjustable letter spacing
+ int unsuppressibleLetterSpaces = bSuppressibleLetterSpace ?
+ ai.iLScount - 1 :
+ ai.iLScount;
wordElements.add
- (new KnuthInlineBox(ai.ipdArea.opt
- - ai.iLScount * letterSpaceWidth.opt,
- lead, total, middle,
- mainPosition, false));
+ (new KnuthInlineBox(ai.ipdArea.opt
+ - ai.iLScount * letterSpaceWidth.opt,
+ lead, total, middle,
+ mainPosition, false));
wordElements.add
- (new KnuthPenalty(0, KnuthElement.INFINITE, false,
- new LeafPosition(this, -1), true));
+ (new KnuthPenalty(0, KnuthElement.INFINITE, false,
+ new LeafPosition(this, -1), true));
wordElements.add
- (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt,
- unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt),
- unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min),
- new LeafPosition(this, -1), true));
+ (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt,
+ unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt),
+ unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min),
+ new LeafPosition(this, -1), true));
wordElements.add
- (new KnuthInlineBox(0, 0, 0, 0,
- new LeafPosition(this, -1), true));
+ (new KnuthInlineBox(0, 0, 0, 0,
+ new LeafPosition(this, -1), true));
}
+
+ // extra-elements if the word fragment is the end of a syllable,
+ // or it ends with a character that can be used as a line break
if (ai.bHyphenated) {
- wordElements.addAll(createElementsForAHyphen(alignment));
+ // the word fragment ends at the end of a syllable:
+ // if a break occurs the content width increases,
+ // otherwise nothing happens
+ wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, new MinOptMax(0)));
+ } else if (bSuppressibleLetterSpace) {
+ // the word framgent ends with a character that acts as a hyphen
+ // if a break occurs the width does not increase,
+ // otherwise there is one more letter space
+ wordElements.addAll(createElementsForAHyphen(alignment, 0, letterSpaceWidth));
}
- // add a flagged penalty element and a glue element representing a suppressible
- // letter space if the next character is not a space
- if (ai.iLScount - unsuppressibleLetterSpaces == 1) {
- //TODO: this is correct only if text is justified
- wordElements.add
- (new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true,
- new LeafPosition(this, -1), false));
- wordElements.add
- (new KnuthGlue(letterSpaceWidth.opt,
- letterSpaceWidth.max - letterSpaceWidth.opt,
- letterSpaceWidth.opt - letterSpaceWidth.min,
- new LeafPosition(this, -1), false));
- }
-
return wordElements;
}
- private LinkedList createElementsForAHyphen(int alignment) {
+ private LinkedList createElementsForAHyphen(int alignment,
+ int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs) {
LinkedList hyphenElements = new LinkedList();
switch (alignment) {
case EN_CENTER :
// centered text:
- // if the second element is chosen as a line break these elements
- // add a constant amount of stretch at the end of a line and at the
- // beginning of the next one, otherwise they don't add any stretch
hyphenElements.add
(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
new LeafPosition(this, -1), false));
hyphenElements.add
- (new KnuthPenalty(hyphIPD,
+ (new KnuthPenalty(widthIfBreakOccurs,
KnuthPenalty.FLAGGED_PENALTY, true,
new LeafPosition(this, -1), false));
hyphenElements.add
- (new KnuthGlue(0,
+ (new KnuthGlue(widthIfNoBreakOccurs.opt,
- 6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
new LeafPosition(this, -1), false));
hyphenElements.add
@@ -893,18 +907,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
case EN_START : // fall through
case EN_END :
// left- or right-aligned text:
- // if the second element is chosen as a line break these elements
- // add a constant amount of stretch at the end of a line, otherwise
- // they don't add any stretch
hyphenElements.add
(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
new LeafPosition(this, -1), false));
hyphenElements.add
- (new KnuthPenalty(hyphIPD,
+ (new KnuthPenalty(widthIfBreakOccurs,
KnuthPenalty.FLAGGED_PENALTY, true,
new LeafPosition(this, -1), false));
hyphenElements.add
- (new KnuthGlue(0,
+ (new KnuthGlue(widthIfNoBreakOccurs.opt,
- 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
new LeafPosition(this, -1), false));
break;
@@ -913,9 +924,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
// justified text, or last line justified:
// just a flagged penalty
hyphenElements.add
- (new KnuthPenalty(hyphIPD,
+ (new KnuthPenalty(widthIfBreakOccurs,
KnuthPenalty.FLAGGED_PENALTY, true,
new LeafPosition(this, -1), false));
+ // extra elements representing a letter space that is suppressed
+ // if a break occurs
+ if (widthIfNoBreakOccurs.min != 0
+ || widthIfNoBreakOccurs.max != 0) {
+ hyphenElements.add
+ (new KnuthGlue(widthIfNoBreakOccurs.opt,
+ widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt,
+ widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min,
+ new LeafPosition(this, -1), false));
+ }
}
return hyphenElements;