Repository navigation
Conversation
…on adjustments PDFPainter.drawText takes one of two paths. With no position adjustments, or DX-only ones, drawTextWithDX writes the word as one TJ array and sets Tc to the letter spacing, which the viewer adds after every glyph. With general adjustments (a GPOS kern is an x-advance adjustment, so IFUtil.isDPOnlyDX is false) drawTextWithDP writes each glyph with its own Td and Tj and advanced by the glyph width plus the adjustment. It set 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 reached the next glyph. The layout is consistent with the first path: TextLayoutManager puts the letter spaces into the word's elements and its area, 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". So a letter-spaced word in a font that positions was measured with its letter spaces and painted without them, and the gap to the next word absorbed the difference: negative letter spacing opens the gap, positive closes it, to the point of overprinting. The letter spacing is now added to the advance on this path, for every glyph, spaces and the last one included, which is what Tc does on the other. Java2DPainter and PCLPainter already add it per glyph in their dp loops, PSPainter applies it through ATJ, AFPPainter converts dp to dx; only the PDF painter was missing it. Measured on this branch, Arimo 11pt, kerning on, "During <fo:inline letter-spacing="-0.417pt">repair,</fo:inline> if however", per-glyph steps read back with mutool draw -F stext: before 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 after r>e 3.246 e>p 5.699 p>a 5.699 a>i 5.699 i>r 2.025 r>, 2.641 comma>space 5.549 After: each step is the advance less 0.417, and r>, carries the kern (-55/1000 em) too. PDFPainterTestCase.testDrawDpTextKeepsLetterSpacing: two zero-width glyphs, a kern of -100 and a letter spacing of 500; the second Td must be 0.4, not -0.1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes FOP-3344.
PDFPainter.drawText takes one of two paths. With no position adjustments, or DX-only ones,
drawTextWithDX writes the word as one TJ array and sets Tc to the letter spacing, which the
viewer adds after every glyph. With general adjustments (a GPOS kern is an x-advance
adjustment, so IFUtil.isDPOnlyDX is false) drawTextWithDP writes each glyph with its own Td
and Tj and advanced by the glyph width plus the adjustment. It set 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 reached the next glyph.
The layout is consistent with the first path: TextLayoutManager puts the letter spaces into
the word's elements and its area, 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". So a letter-spaced word in a font that positions was
measured with its letter spaces and painted without them, and the gap to the next word
absorbed the difference: negative letter spacing opens the gap, positive closes it, to the
point of overprinting.
The letter spacing is now added to the advance on this path, for every glyph, spaces and
the last one included, which is what Tc does on the other. Java2DPainter and PCLPainter
already add it per glyph in their dp loops, PSPainter applies it through ATJ, AFPPainter
converts dp to dx; only the PDF painter was missing it.
Measured on this branch, Arimo 11pt, kerning on,
"During <fo:inline letter-spacing="-0.417pt">repair,</fo:inline> if however", per-glyph
steps read back with mutool draw -F stext:
After: each step is the advance less 0.417, and r>, carries the kern (-55/1000 em) too.
PDFPainterTestCase.testDrawDpTextKeepsLetterSpacing: two zero-width glyphs, a kern of -100
and a letter spacing of 500; the second Td must be 0.4, not -0.1.
🤖 Generated with Claude Code