Skip to content

Fix issue 2057: Take letter-spacing into account for width calculation #2060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public void setBaseLevel(byte baseLevel) {

@Override
public void addChild(IArea area) {
// FIXME ?
int childHorizontalSpan = area.getX() + area.getWidth();
int childVerticalSpan = area.getY() + area.getHeight();

Expand Down Expand Up @@ -122,28 +121,28 @@ public void align(boolean endParagraph, LayoutContext context) {
boolean isJustified = CSSValueConstants.JUSTIFY_VALUE.equals(align) && !endParagraph;

// single line
int spacing = width - currentIP;
spacing -= adjustSpacingForSoftHyphen();
int spaceRemaining = width - currentIP;
spaceRemaining -= adjustSpacingForSoftHyphen();
int adjustLeftWhiteSpace = ignoreLeftMostWhiteSpace();
int adjustRightWhiteSpace = ignoreRightMostWhiteSpace();
if ((isRightAligned)) {
Iterator<IArea> iter = getChildren();
while (iter.hasNext()) {
AbstractArea area = (AbstractArea) iter.next();
if (parent.content.isDirectionRTL()) {
area.setPosition(spacing + area.getX(), area.getY());
area.setPosition(spaceRemaining + area.getX(), area.getY());
} else {
area.setPosition(spacing + area.getX() + adjustRightWhiteSpace, area.getY());
area.setPosition(spaceRemaining + area.getX() + adjustRightWhiteSpace, area.getY());
}
}
} else if (isCentered) {
Iterator<IArea> iter = getChildren();
while (iter.hasNext()) {
AbstractArea area = (AbstractArea) iter.next();
area.setPosition(spacing / 2 + area.getX() - adjustLeftWhiteSpace + adjustRightWhiteSpace, area.getY());
area.setPosition(spaceRemaining / 2 + area.getX() - adjustLeftWhiteSpace + adjustRightWhiteSpace, area.getY());
}
} else if (isJustified) {
justify(spacing, adjustLeftWhiteSpace, adjustRightWhiteSpace);
justify(spaceRemaining, adjustLeftWhiteSpace, adjustRightWhiteSpace);
} else {
// is left aligned
if (parent.content != null && !parent.content.isDirectionRTL()) {
Expand Down Expand Up @@ -182,14 +181,16 @@ private int adjustSpacingForSoftHyphen() {
private int ignoreRightMostWhiteSpace() {
if (lastTextArea != null) {
String text = lastTextArea.getText();
int letterSpacing = lastTextArea.getTextStyle().getLetterSpacing();
if (null != text) {
char[] charArray = text.toCharArray();
int len = charArray.length;
while (len > 0 && (charArray[len - 1] <= ' ')) {
len--;
}
if (len != charArray.length) {
return lastTextArea.getTextWidth(text.substring(len));
return (1 + charArray.length - len) * letterSpacing
+ lastTextArea.getTextWidth(text.substring(len));
}
}
}
Expand All @@ -200,14 +201,15 @@ private int ignoreLeftMostWhiteSpace() {
TextArea firstTextArea = findFirstNonEmptyTextArea(this);
if (firstTextArea != null) {
String text = firstTextArea.getText();
int letterSpacing = lastTextArea.getTextStyle().getLetterSpacing();
if (null != text) {
char[] charArray = text.toCharArray();
int len = 0;
while (len < charArray.length && (charArray[len] <= ' ')) {
len++;
}
if (len > 0) {
return firstTextArea.getTextWidth(text.substring(0, len));
return len * letterSpacing + firstTextArea.getTextWidth(text.substring(0, len));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@ private String calculateText() {
*
* @since 4.14
*/
public void addWord(int textLength, WordWidth wordWidth) {
public void addWord(int textLength, WordWidth wordWidth, int letterSpacing) {
this.textLength += textLength;
this.width += wordWidth.width;
this.width += wordWidth.width + textLength * letterSpacing;
this.softHyphenWidth = wordWidth.softHyphenWidth;
}

Expand Down Expand Up @@ -332,13 +332,18 @@ public void accept(IAreaVisitor visitor) {
visitor.visitText(this);
}

/**
* Return the text width, ignoring wordSpacing and letterSpacing.
*
* @param text
* @return text width
*/
public int getTextWidth(String text) {
FontInfo fontInfo = style.getFontInfo();
if (null != fontInfo) {
return (int) (style.getFontInfo().getWordWidth(text) * PDFConstants.LAYOUT_TO_PDF_RATIO);
} else {
return 0;
}
return 0;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ private void addWordIntoTextArea(TextArea textArea, Word word) {

int adjustWordSize = fontInfo.getItalicAdjust() + width;
if (textArea.hasSpace(adjustWordSize + wordWidth.softHyphenWidth * letterSpacing)) {
addWord(textArea, textLength, wordWidth);
addWord(textArea, textLength, wordWidth, letterSpacing);
wordVestige = null;
if (remainWords.hasWord()) {
// test if we can append the word spacing
Expand All @@ -385,7 +385,7 @@ private void addWordIntoTextArea(TextArea textArea, Word word) {
} else {
// If width of a word is larger than the max line width,
// add it into the line directly.
addWord(textArea, textLength, wordWidth);
addWord(textArea, textLength, wordWidth, letterSpacing);
}
} else {
wordVestige = null;
Expand All @@ -401,26 +401,27 @@ private void doWordBreak(String str, TextArea area) {
IHyphenationManager hm = new DefaultHyphenationManager();
Hyphenation wb = hm.getHyphenation(str);
FontInfo fi = area.getStyle().getFontInfo();
int letterSpacing = textStyle.getLetterSpacing();
if (area.getMaxWidth() < 0) {
addWordVestige(area, 1, new WordWidth(fi, wb.getHyphenText(0, 1)), str.substring(1));
addWordVestige(area, 1, new WordWidth(fi, wb.getHyphenText(0, 1)), str.substring(1), letterSpacing);
return;
}
int endHyphenIndex = hyphen(0, area.getMaxWidth() - area.getWidth(), wb, fi);
// current line can't even place one character. Force to add the first
// character into the line.
if (endHyphenIndex == 0 && area.getWidth() == 0) {
addWordVestige(area, 1, new WordWidth(fi, wb.getHyphenText(0, 1)), str.substring(1));
addWordVestige(area, 1, new WordWidth(fi, wb.getHyphenText(0, 1)), str.substring(1), letterSpacing);
} else {
WordWidth wordWidth = new WordWidth(fi, wb.getHyphenText(0, endHyphenIndex));
// Take letter spacing into account
wordWidth = new WordWidth(wordWidth.width + textStyle.getLetterSpacing() * (endHyphenIndex - 1), 0);
addWordVestige(area, endHyphenIndex, wordWidth, str.substring(endHyphenIndex));
addWordVestige(area, endHyphenIndex, wordWidth, str.substring(endHyphenIndex), letterSpacing);
}
}

private void addWordVestige(TextArea area, int vestigeTextLength, WordWidth vestigeWordWidth,
String vestigeString) {
addWord(area, vestigeTextLength, vestigeWordWidth);
String vestigeString, int letterSpacing) {
addWord(area, vestigeTextLength, vestigeWordWidth, letterSpacing);
if (vestigeString.length() == 0) {
wordVestige = null;
} else {
Expand Down Expand Up @@ -469,8 +470,8 @@ private WordWidth getWordWidth(FontInfo fontInfo, Word word) {
return new WordWidth(fontInfo, word.getValue());
}

private void addWord(TextArea textArea, int textLength, WordWidth wordWidth) {
textArea.addWord(textLength, wordWidth);
private void addWord(TextArea textArea, int textLength, WordWidth wordWidth, int letterSpacing) {
textArea.addWord(textLength, wordWidth, letterSpacing);
}

private void addWord(TextArea textArea, int textLength) {
Expand Down