[
https://issues.apache.org/jira/browse/FOP-3344?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18124654#comment-18124654
]
Jason Harrop commented on FOP-3344:
-----------------------------------
An FO with a font from the test tree: attached FOP-3344-letter-spacing-dp.fo
and fop-test-fonts.xconf. Copy the config to the root of a checkout and run
from there:
{noformat}
fop -c fop-test-fonts.xconf -fo FOP-3344-letter-spacing-dp.fo -pdf out.pdf
mutool draw -F stext out.pdf
{noformat}
Two blocks in DejaVuLGCSerif, 12pt, {{language="az"}} so that GPOS kerning
applies and the word takes the position-adjustments path: {{Try
<fo:inline>AVATAR</fo:inline> next}} and the same with {{letter-spacing="3pt"}}
on the inline. Read the glyph x positions from the stext output.
On main at 5be8c69b6 the two lines are identical: A V A T A R at 80.99, 89.07,
96.93, 104.94, 112.29, 120.95 (steps 8.08 7.86 8.02 7.34 8.66, the kerned
advances) and "next" at 133.78 in both. The 3pt of letter spacing is painted
nowhere.
With the pull request's change the second line has A V A T A R at 80.99, 92.07,
102.93, 113.94, 124.29, 135.95 (each step 3pt wider) and "next" still at
133.78, so the R and the n overprint: the layout did not count the letter
spaces in the word's width, which is FOP-2349 (pull request 118, stacked on
this one). With both, "next" is at 148.78.
> letter-spacing is not painted on text that carries glyph position adjustments
> (GPOS kerning): the word is drawn at its bare advances inside an area that
> keeps the letter spaces
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: FOP-3344
> URL: https://issues.apache.org/jira/browse/FOP-3344
> Project: FOP
> Issue Type: Bug
> Components: renderer/pdf
> Affects Versions: 2.11
> Reporter: Jason Harrop
> Priority: Minor
> Attachments: FOP-3344-letter-spacing-dp.fo, fop-test-fonts.xconf
>
>
> PDFPainter.drawText takes one of two paths. With no position adjustments, or
> adjustments that are DX-only, drawTextWithDX writes the word as one TJ array
> and sets Tc to the letter spacing, which the PDF viewer adds after every
> glyph. With general adjustments (a GPOS kern produces an x-advance
> adjustment, so IFUtil.isDPOnlyDX is false), drawTextWithDP writes each glyph
> with its own Td and Tj and advances by
> {noformat}
> xc += xa + pa[2];
> {noformat}
> that is, the glyph width plus the advance adjustment. It sets Tc too, but Tc
> acts only between glyphs inside a TJ array; with one glyph per Tj and an
> explicit Td before each, the letter spacing never reaches the next glyph.
> The layout side is consistent with the first path. TextLayoutManager puts the
> letter spaces into the word's Knuth elements and the TextArea, and
> addMappingAreas computes the word-space adjustment on the assumption that the
> renderer "adds the character spacing even to the last character of a word and
> to space characters" (its own comment). So a letter-spaced word in a font
> that positions is measured with its letter spaces and painted without them,
> and the gap to the next word absorbs the difference: negative letter spacing
> opens the gap, positive closes it, to the point of overprinting.
> Reproducer: Arimo (or any font whose GPOS kern applies; Liberation, DejaVu
> Serif, Noto), kerning="true", 11pt,
> {noformat}
> <fo:block font-family="Arimo">During <fo:inline
> letter-spacing="-0.417pt">repair,</fo:inline> if however</fo:block>
> {noformat}
> Per-glyph steps read back with mutool draw -F stext, 2.11:
> {noformat}
> r>e 3.663 e>p 6.116 p>a 6.116 a>i 6.116 i>r 2.442 r>, 3.058
> comma>space 3.047
> {noformat}
> Every step is the bare advance (r>, carries the kern), and the space after
> the comma is 2.5 pt narrower than the same text without kerning, where the
> steps are 3.246 5.699 5.699 5.699 2.025 3.246 and the gap 5.549. On the
> docx4j corpus the collapsed gap made pdftotext read "repair, if" as
> "repair,if"; with positive letter spacing the words overprint.
> h3. Fix
> PDFPainter.drawTextWithDP: add the letter spacing to the advance of every
> glyph, spaces and the last glyph included, which is what Tc does on the other
> path and what the layout's word-space adjustment assumes:
> {noformat}
> xc += xa + pa[2] + letterSpacing;
> {noformat}
> Java2DPainter and PCLPainter already add letterSpacing per glyph in their dp
> loops; PSPainter applies it through ATJ; AFPPainter converts dp to dx. Only
> the PDF painter was missing it.
> After the fix, same sample: 3.246 5.699 5.699 5.699 2.025 2.641, gap 5.549;
> the last step is the advance less the letter spacing less the kern.
> Test: PDFPainterTestCase.testDrawDpTextKeepsLetterSpacing, two zero-width
> glyphs with a kern of -100 and a letter spacing of 500; the second glyph's Td
> must be 0.4, not -0.1.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)