You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by "plutext (via GitHub)" <gi...@apache.org> on 2026/10/02 21:34:42 UTC
[PR] FOP-3340: A CJK ideograph sharing a glyph with a Kangxi radical is written to ToUnicode as the radical [xmlgraphics-fop]
plutext opened a new pull request, #109:
URL: https://github.com/apache/xmlgraphics-fop/pull/109
Fixes [FOP-3340](https://issues.apache.org/jira/browse/FOP-3340).
With complex script features enabled, CJK text is painted correctly but extracts,
searches and reads out as the Kangxi radicals which share the ideographs' glyphs.
One FO, one font (Source Han Sans CN), stock FOP, only the complex-script flag
changed:
```
features on 0003=U+2F63 0004=U+2F45 0005=U+2F08 0006=U+FF0C 0007=U+724B
features off 0003=U+751F 0004=U+65B9 0005=U+4EBA 0006=U+FF0C 0007=U+724B
```
The glyphs drawn are identical either way - glyph 3,4,5,6,7 at x=0,12,24,36,48,
advance 1 each. U+724B, which no radical shares, is right either way: the control.
MultiByteFont.performSubstitution runs the font's layout tables over characters -
chars to glyphs, GSUB, then mapGlyphsToChars - and mapGlyphsToChars takes each
glyph's character from findCharacterFromGlyphIndex, which returns the first code
point in the cmap mapped to that glyph ("if more than one correspondence exists,
then the first one is returned"). A CJK font maps a radical and the ideograph it
is the radical of to one glyph: in Source Han Sans CN, U+2F63 and U+751F are both
glyph 18742, U+2F45 and U+65B9 are both 14819, U+2F08 and U+4EBA are both 8966.
The radical is the lower code point, so the reverse lookup hands back the radical,
and that is what reaches the PDF's ToUnicode.
mapGlyphsToChars now prefers the character the glyph came from, which the
GlyphSequence already carries in its CharAssociation, wherever the substitution
left the glyph alone - the association covers exactly one character and the
character map maps that character to this same glyph. Anything the substitution
did produce, a ligature or a glyph with no character of its own, still goes
through findCharacterFromGlyphIndex as before, and a supplementary plane
character still comes back as its surrogate pair.
MultiByteFontTestCase covers all four cases against a hand-built character map
holding the three radical/ideograph pairs above, so it needs no font installed.
Without the fix its first case fails with the radicals for the ideographs, which
is the defect above.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org