Repository navigation
Move a Plane 2 character into Sun-ExtB only when Sun-ExtB has it (v6) - #847
Merged
Merged
Conversation
gravitypdf-bot
force-pushed
the
fix/837-sip-coverage-v6
branch
from
November 4, 2026 22:57
bd6a135 to
1f31df9
Compare
Base automatically changed from
feature/827-character-ranges-v6
to
gravitypdf-v6
November 4, 2026 22:57
A character the current font lacks joins a SIP run only when it is in Plane 2 and FontSubstitution::sipFontFor() names the font's sip-ext font or backupSIPFont as having it. Anything else, Plane 3 and above included, is offered to the backup fonts like any other missing character, whether or not the document has a Plane 2 character. With useSubstitutions on, the substitution scan moves Plane 2 into the sip-ext font itself, so a Plane 2 character the current font has stays in it. SubstituteCharsSIP() now runs only where the scan does not, and takes the first run of Plane 2 characters the sip-ext font has through the same check. Adapted to v6, whose scan handles one run per token and has no emoji handling. The run is cut by position in the new moveRun() rather than with a regular expression. SubstitutionFontCacheTest used DejaVu Sans as backupSIPFont and expected U+20000 to be drawn in it, which it lacks, so it now uses Sun-ExtB. (cherry picked from commit 2d66b2a) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jakejackson1
force-pushed
the
fix/837-sip-coverage-v6
branch
from
November 4, 2026 23:05
1f31df9 to
43c9c9e
Compare
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.
Backports #838 (fixes #837) to
gravitypdf-v6.Stacked on #845. The fix reads Sun-ExtB's coverage through
FontSubstitution::widths(), and the ranges files in #845 are what let it answer without loading the font. Merge #845 first; this PR's base then needs to move togravitypdf-v6.The bug
When the HTML held a Plane 2 character, the scan put every character above U+1FFFF that the current font lacked into one SIP run, and counted the run as covered with
_charDefined($cw, $char) || $char > 131071. The second half was always true, so a CJK Extension E character, or a Plane 3 one, went to Sun-ExtB, which lacks it. Sun-ExtB was found and loaded to draw its missing-character box, andbackupSubsFontwas never tried.SubstituteCharsSIP()had the same fault for text in a font with asip-extfont.The fix
The rule is the same as on
gravitypdf:FontSubstitution::sipFontFor($char)names the current font'ssip-extfont if it has the character, thenbackupSIPFontif that has it, otherwise neither. Anything outside Plane 2 gets neither.sipFontFor()names a font. Everything else the current font lacks takes the core font andbackupSubsFontpath. If nothing has it, it stays in the current font.SubstituteCharsSIP()now runs only where the scan doesn't: withoutuseSubstitutions, or for aType0font. It takes the first run of Plane 2 characters thesip-extfont has.Two things change for text in a font with a
sip-extfont when substitution is on: the text before a Plane 2 run is now substituted, and a Plane 2 character the font has itself stays in it.Differences from #838
moveRun(): new on v6. It cuts the run out by position and writes the text before it back to the token list. The old code found the run again with a regular expression, in a pattern with nosflag.SubstitutionFontCacheTest: this v6-only test used DejaVu Sans asbackupSIPFontand asserted U+20000 was drawn in it, which is the bug. It now uses Sun-ExtB and asserts U+20000 is in that font'ssubsets. Its checks on the characters after U+20000 are unchanged.SipSubstitutionCoverageTest: v6 only includes PHP ranges files shipped forFontVariablesfamilies, so the test font's ranges file is written to the font cache as JSON instead.SubstitutionRunSplitTestdoesn't exist on v6, so its "a font keeps the Plane 2 text it has" case moved here.TextRecordingMpdfgainsdrawnFontFamilyanddrawnPieces(). Thesip-coveragefixture is regenerated on v6 and setsbackupSubsFontto Sun-ExtA, as the caption says.SubstitutionRunCutTest(doesn't exist on v6) and theCHANGELOG-GRAVITYPDF.mdentry (nor does that file).Checks
CI=1composer cssip-coverageand looked at it. U+20BB7 is in Sun-ExtB, and U+2B820 is DejaVu Sans's box, or blank in the Sun-ExtA paragraph.Mpdf.phpchange: the snapshot fails, 9 of the 12SipSubstitutionCoverageTestcases fail, andSubstitutionFontCacheTesterrors.There are no benchmarks: this changes which font a character goes to, and isn't a speed change.
Not changed
Plane 3 characters still can't be drawn, on either branch, because
TTFontFilereads no cmap entry from U+30000 up; that's #846. A character no font has, left in a font with nosiporsmpflag, is still written as two glyphs; that's #839.