}
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.
// 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);
&& 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
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
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;
// 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;