Skip to content

Commit 106fb16

Browse files
Replace em-like whitespaces with adjusted space if not-def glyph is used for them
DEVSIX-1319
1 parent e9e3d28 commit 106fb16

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

layout/src/main/java/com/itextpdf/layout/renderer/TextRenderer.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ protected TextRenderer(TextRenderer other) {
161161
public LayoutResult layout(LayoutContext layoutContext) {
162162
updateFontAndText();
163163
if (null != text) {
164-
text = getGlyphlineWithSpacesInsteadOfTabs(text);
164+
// if text != null => font != null
165+
text = replaceSpecialWhitespaceGlyphs(text, font);
165166
}
166167

167168
LayoutArea area = layoutContext.getArea();
@@ -1139,7 +1140,9 @@ protected boolean resolveFonts(List<IRenderer> addTo) {
11391140
FontSelectorStrategy strategy = provider.getStrategy(strToBeConverted,
11401141
FontFamilySplitter.splitFontFamily((String) font), fc, fontSet);
11411142
while (!strategy.endOfText()) {
1142-
TextRenderer textRenderer = createCopy(getGlyphlineWithSpacesInsteadOfTabs(new GlyphLine(strategy.nextGlyphs())), strategy.getCurrentFont());
1143+
GlyphLine nextGlyphs = new GlyphLine(strategy.nextGlyphs());
1144+
PdfFont currentFont = strategy.getCurrentFont();
1145+
TextRenderer textRenderer = createCopy(replaceSpecialWhitespaceGlyphs(nextGlyphs, currentFont), currentFont);
11431146
addTo.add(textRenderer);
11441147
}
11451148
return true;
@@ -1296,21 +1299,42 @@ private void saveWordBreakIfNotYetSaved(Glyph wordBreak) {
12961299
}
12971300
}
12981301

1299-
private GlyphLine getGlyphlineWithSpacesInsteadOfTabs(GlyphLine line) {
1302+
private static GlyphLine replaceSpecialWhitespaceGlyphs(GlyphLine line, PdfFont font) {
13001303
if (null != line) {
1301-
Glyph space = new Glyph(resolveFirstPdfFont().getGlyph('\u0020'));
1302-
space.setXAdvance((short) (3 * space.getWidth()));
1304+
Glyph space = font.getGlyph('\u0020');
13031305
Glyph glyph;
13041306
for (int i = 0; i < line.size(); i++) {
13051307
glyph = line.get(i);
1306-
if ('\t' == glyph.getUnicode()) {
1307-
line.set(i, space);
1308+
Integer xAdvance = getSpecialWhitespaceXAdvance(glyph, space, font.getFontProgram().getFontMetrics().isFixedPitch());
1309+
if (xAdvance != null) {
1310+
Glyph newGlyph = new Glyph(space, glyph.getUnicode());
1311+
assert xAdvance <= Short.MAX_VALUE && xAdvance >= Short.MIN_VALUE;
1312+
newGlyph.setXAdvance((short) (int)xAdvance);
1313+
line.set(i, newGlyph);
13081314
}
13091315
}
13101316
}
13111317
return line;
13121318
}
13131319

1320+
private static Integer getSpecialWhitespaceXAdvance(Glyph glyph, Glyph spaceGlyph, boolean isMonospaceFont) {
1321+
if (glyph.getCode() > 0) {
1322+
return null;
1323+
}
1324+
switch (glyph.getUnicode()) {
1325+
case '\u2002': // ensp
1326+
return isMonospaceFont ? 0 : 500 - spaceGlyph.getWidth();
1327+
case '\u2003': // emsp
1328+
return isMonospaceFont ? 0 : 1000 - spaceGlyph.getWidth();
1329+
case '\u2009': // thinsp
1330+
return isMonospaceFont ? 0 : 200 - spaceGlyph.getWidth();
1331+
case '\t':
1332+
return 3 * spaceGlyph.getWidth();
1333+
}
1334+
1335+
return null;
1336+
}
1337+
13141338
private static class ReversedCharsIterator implements Iterator<GlyphLine.GlyphLinePart> {
13151339
private List<Integer> outStart;
13161340
private List<Integer> outEnd;

0 commit comments

Comments
 (0)