Просмотр исходного кода

Bugfix: The combination of hyphenation and kerning resulted in slightly ragged right ends for right-aligned and justified text. The kerning values were not correctly placed and summed up for hyphenation and no-hyphenation conditions.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@407774 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_93
Jeremias Maerki 18 лет назад
Родитель
Сommit
5db4640176

+ 41
- 11
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Просмотреть файл

@@ -106,12 +106,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
/** Non-space characters on which we can end a line. */
private static final String BREAK_CHARS = "-/";

/** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */
private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0);
private FOText foText;
private char[] textArray;
/** Contains an array of widths to adjust for kerning and letter spacing */
/**
* 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
* cursor advancement after the character i. A null entry means no special advancement.
*/
private MinOptMax[] letterAdjustArray; //size = textArray.length + 1
/** The sum of all entries in the letterAdjustArray */
private MinOptMax totalLetterAdjust = new MinOptMax(0);

private static final char NEWLINE = '\n';

@@ -310,8 +315,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
iLScount--;
}
for (int i = ai.iStartIndex + 1; i < ai.iBreakIndex + 1; i++) {
MinOptMax ladj = letterAdjustArray[i];
for (int i = ai.iStartIndex; i < ai.iBreakIndex; i++) {
MinOptMax ladj = letterAdjustArray[i + 1];
if (ladj != null && ladj.isElastic()) {
iLScount++;
}
@@ -466,8 +471,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
int[] letterAdjust = new int[wordChars.length()];
int lsCount = areaInfo.iLScount;
for (int letter = 0; letter < len; letter++) {
MinOptMax adj = letterAdjustArray[letter + wordStartIndex + 1];
letterAdjust[letter] = (adj != null ? adj.opt : 0);
MinOptMax adj = letterAdjustArray[letter + wordStartIndex];
if (letter > 0) {
letterAdjust[letter] = (adj != null ? adj.opt : 0);
}
if (lsCount > 0) {
letterAdjust[letter] += textArea.getTextLetterSpaceAdjust();
lsCount--;
@@ -492,7 +499,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
} else {
letterAdjustArray[index].add(width);
}
totalLetterAdjust.add(width);
}

private void addToLetterAdjust(int index, MinOptMax width) {
@@ -501,7 +507,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
} else {
letterAdjustArray[index].add(width);
}
totalLetterAdjust.add(width);
}

/**
@@ -625,7 +630,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
char previous = textArray[i - 1];
kern = font.getKernValue(previous, c) * font.getFontSize() / 1000;
if (kern != 0) {
addToLetterAdjust(i + 1, kern);
//log.info("Kerning between " + previous + " and " + c + ": " + kern);
addToLetterAdjust(i, kern);
}
wordIPD.add(kern);
}
@@ -761,9 +767,22 @@ public class TextLayoutManager extends LeafNodeLayoutManager {

hc.updateOffset(iStopIndex - iStartIndex);

//log.info("Word: " + new String(textArray, iStartIndex, iStopIndex - iStartIndex));
for (int i = iStartIndex; i < iStopIndex; i++) {
char c = textArray[i];
newIPD.add(new MinOptMax(font.getCharWidth(c)));
//if (i > iStartIndex) {
if (i < iStopIndex) {
MinOptMax la = this.letterAdjustArray[i + 1];
if ((i == iStopIndex - 1) && bHyphenFollows) {
//the letter adjust here needs to be handled further down during
//element generation because it depends on hyph/no-hyph condition
la = null;
}
if (la != null) {
newIPD.add(la);
}
}
}
// add letter spaces
boolean bIsWordEnd
@@ -854,6 +873,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
iReturnedIndex++;
} // end of while
setFinished(true);
//ElementListObserver.observe(returnList, "text-changed", null);
return returnList;
}

@@ -1152,10 +1172,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
// 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) {
MinOptMax widthIfNoBreakOccurs = null;
if (ai.iBreakIndex < textArray.length) {
//Add in kerning in no-break condition
widthIfNoBreakOccurs = letterAdjustArray[ai.iBreakIndex];
}
//if (ai.iBreakIndex)
// 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)));
wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, widthIfNoBreakOccurs));
} else if (bSuppressibleLetterSpace) {
// the word fragment ends with a character that acts as a hyphen
// if a break occurs the width does not increase,
@@ -1167,6 +1194,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager {

private LinkedList createElementsForAHyphen(int alignment,
int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs) {
if (widthIfNoBreakOccurs == null) {
widthIfNoBreakOccurs = ZERO_MINOPTMAX;
}
LinkedList hyphenElements = new LinkedList();
switch (alignment) {

+ 16
- 0
status.xml Просмотреть файл

@@ -27,6 +27,22 @@

<changes>
<release version="FOP Trunk">
<action context="Code" dev="JM" type="fix">
Bugfix: The combination of hyphenation and kerning resulted in slightly ragged
right ends for right-aligned and justified text.
</action>
<action context="Code" dev="JM" type="fix">
Bugfix: NullPointerException in AreaAdditionUtil in a table-cell spanning
multiple pages and with a marker.
</action>
<action context="Code" dev="JM" type="fix" fixes-bug="39533">
Bugfix: NullPointerException in RTF output when a table does not contain
table-columns.
</action>
<action context="Code" dev="JM" type="fix" fixes-bug="39607" due-to="Julien Aymé">
Bugfix: NullPointerException in RTF library when there are no borders on
the parent table.
</action>
<action context="Code" dev="JM" type="add">
Automatic support for all fonts available to the Java2D subsystem for all
Java2D-descendant renderers (TIFF, PNG, print, AWT).

+ 60
- 0
test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml Просмотреть файл

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2006 The Apache Software Foundation

Licensed 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>
Checks hyphenation in combination with kerning.
</p>
</info>
<cfg>
<base14kerning>true</base14kerning>
</cfg>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" hyphenate="true">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple" page-height="5in" page-width="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="20pt" line-height="1.0" text-align="justify" text-align-last="justify" background-color="lightgray" start-indent="10pt" end-indent="10pt" border="solid 1pt">
hyphenation regression advantage foundation vandalism AVAVAVA vandavanda
hyphenation regression advantage foundation vandalism AVAVAVA vandavanda
hyphenation regression
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="1" xpath="count(//pageViewport)"/>
<eval expected="17230" xpath="//flow/block[1]/lineArea[1]/text[1]/@twsadjust"/>
<eval expected="-1339" xpath="//flow/block[1]/lineArea[2]/text[1]/@twsadjust"/>
<eval expected="2393" xpath="//flow/block[1]/lineArea[3]/text[1]/@twsadjust"/>
<eval expected="5900" xpath="//flow/block[1]/lineArea[4]/text[1]/@twsadjust"/>
<eval expected="9900" xpath="//flow/block[1]/lineArea[5]/text[1]/@twsadjust"/>
<!-- In no-break condition there's a -400 kerning between a and v. It musn't occur if "vandavanda" is hyphenated. -->
<eval expected="vanda-" xpath="//flow/block[1]/lineArea[2]/text[1]/word[4]"/>
<eval expected="0 -500 0 0 0 0" xpath="//flow/block[1]/lineArea[2]/text[1]/word[4]/@letter-adjust"/>
<eval expected="vanda" xpath="//flow/block[1]/lineArea[3]/text[1]/word[1]"/>
<eval expected="0 -500 0 0 0" xpath="//flow/block[1]/lineArea[3]/text[1]/word[1]/@letter-adjust"/>
</checks>
</testcase>

Загрузка…
Отмена
Сохранить