Generate the cursive joining tables from Unicode, so a letter beside a recently added character joins (#251) - #261
Open
jakejackson1 wants to merge 3 commits into
Open
jakejackson1 wants to merge 3 commits into
jakejackson1 wants to merge 3 commits into
Conversation
…a recently added character joins (#251) Shaper\Arabic's two joining tables stopped at the blocks Unicode had when they were last extended by hand. A character in neither table joins nothing and unjoins its neighbour, so the letter before a recently added one was drawn with no form where HarfBuzz gives it init or medi. Both tables are now written by composer arabicjoining:update from ArabicShaping.txt, beside a test that the checked-in tables are what the generator writes - the pattern Ucdn::$ot_languages already uses. What is in scope is read from Ucdn's script for each character, because the script is what routes a run to this shaper, which is why the generator reads the same Unicode version Ucdn's scripts were built from. 77 characters change: the 72 the issue measured over Mandaic, the Syriac Supplement and Arabic Extended-A and -B, and five in Arabic Extended-C, which is script Arabic and so resolved here for the same reason. U+0847 MANDAIC IT was the one filed in the wrong table and is now right-joining only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eads them (#251) The scope test read Ucdn's script and admitted Common and Inherited, on the grounds that a character Ucdn has no script for reaches no shaper. It does: Otl::analyseCharacters() will not start a run on Unknown any more than on those two, so the character stays in the run before it and the Arabic shaper is handed it. Measured through Lateef, a Beh after U+10EE8 CROWN FEH - Arabic and left-joining as of Unicode 18, Unknown to Ucdn's Unicode 17 - is drawn with no form until the table has it, which is this defect with a shorter fuse. Unknown is now in scope with the other two, and the tables are no longer tied to Ucdn's release to be correct. The four scripts are Otl::selectShaper()'s decision rather than the generator's, so a test holds the two lists together; a fifth script in that branch would otherwise bring the defect back for it with nothing failing. Also: the version line each generator rewrites was a third copy of one preg_replace, so it moves to GeneratedTable and gains the missing-marker check replaceArray() already had; the partition reads the three joining types it wants rather than the two it does not; and U+0883 to U+0885 and U+07FA are Join_Causing with scripts of their own, so the comment claiming Join_Causing means "no script" is gone. No table content moves: no character of Unicode 17 is Unknown to Ucdn 17. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ed-joining-tables
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.
Shaper\Arabic::$leftJoiningand::$rightJoiningstopped at the blocks Unicode had when they werewritten, so a character added since was in neither. A character in neither table joins nothing and
unjoins its neighbour: the letter before it is drawn with no form where HarfBuzz gives it
initormedi.Both tables are now generated from Unicode's
ArabicShaping.txt, the wayUcdn::$ot_languagesisgenerated from HarfBuzz's table. Hand-extending was the alternative; the lists had already lagged twice,
and generating them also turned up a data error nobody was looking for (U+0847, below).
Scope: five blocks, not the four the issue lists
77 characters change, every one of them in a script
resolveJoining()is actually called for —arab,syrc,nkoandmand.$leftJoining218 → 262,$rightJoining300 → 375.Arabic Extended-C belongs by the same test as the others:
Ucdn::get_script(0x10EC2)isUcdn::SCRIPT_ARABIC, so those characters reach the Arabic shaper exactly as U+0870 does. Measured,beh + U+10EC2drew a formless beh before and drawsinitafter, identically tobeh + U+0870.Nothing from Mongolian, Phags-pa, Adlam, Manichaean, Hanifi Rohingya, Sogdian, Old Uyghur, Psalter
Pahlavi or Chorasmian.
resolveJoining()is never called for those, and whether mPDF claims them is aseparate question.
One correction rather than an addition
U+0847 MANDAIC IT is
Joining_Type=R, but it was in both tables, so it drew the following letteras though that letter joined backwards over it. It is right-joining only now. No Mandaic font is in the
corpus, so the oracle reads it with an Arabic letter — the joining type is the character's own:
Measured, before and after
The last pair is why this composes with #244. That change made the Alaph read its form from joining
types instead of a hard-coded Syriac block range; this makes the types complete.
E005is EstrangeloEdessa's
finaAlaph andE004itsmed2, sobeth + alaph + U+0860is only correct with bothchanges in. U+0860 is
MALAYALAM NGA; D, dual-joining, so it must join back over the Alaph exactly asthe Sogdian U+074F does.
Mandaic is reached at the
Arabic::resolveJoining()/shape()seam with script tagmand, notthrough a rendered page — no font in the corpus draws it.
The generator
tests/Mpdf/ArabicJoining.php+utils/arabicjoining_update.php+composer arabicjoining:update,following
UcdnTablesandOtLanguageTagsin every respect:Mpdf\underautoload-dev,GeneratedTable, aDEFAULT_VERSION, a rewritten// UNIDATA_VERSIONmarker, autils/data/ucd/<version>cache, and a round-trip test asserting the checked-in tables are what the generator writes.
Unicode 17.0.0, as
const DEFAULT_VERSION = UcdnTables::DEFAULT_VERSION, so the repo names itsUnicode release in one place. Unicode 18 would add 22 more Arabic Extended-C characters; which Unicode
mPDF claims is a decision to make alongside
ucdn:update, not one to slip in here.composer arabicjoining:update 18.0.0is all it takes later.Source data is fetched, not checked in, as both existing generators do. One consequence worth
knowing: the round-trip test skips where the UCD tree is not unpacked, so CI reports 4 skipped where
it reported 3 (measured against PR #262, which adds no generator test and reports 3). It does not skip
locally, where its one cached file is present, so the local count stays at 2.
The arrays are one ascending sequence now rather than hand-grouped by script — the generator has no
block names, and sorted order is what keeps a future diff readable. Formatting stays at 8 entries a line.
ArabicJoining::scripts()restatedOtl::selectShaper()'s decision about which scripts reach thisshaper, so it is held against it by a reflection test that goes red if a fifth script joins that branch.
The
// X_VERSIONrewrite was a third copy of onepreg_replace, so it moved toGeneratedTable::replaceVersion()and gained the missing-marker checkreplaceArray()already had;that touches
tests/Mpdf/UcdnTables.phpandtests/Mpdf/OtLanguageTags.phpby one line each, and bothround-trip tests still pass.
Verified
tests/Mpdf/Shaper/JoiningTableCoverageTest.php, 15 tests, 14 fail against the previoussrc/Shaper/Arabic.php. The one that passes is[ATT, 084F], because U+084F was already in$rightJoiningso that direction already worked; its companion[084F, ATT]fails.No master or fixture moved.
tests/Snapshots/JoiningTablesSnapshotTest.phpexercises U+0712,U+0723, U+074F, U+0628, U+0627 and U+08AD, and all six come out identically — U+08AD is
Joining_Type=U, absent from both tables before and after.The third table in the same file,
$transparent, has the identical gap and is not fixed here:#259. It needs
DerivedJoiningType.txtrather thanArabicShaping.txt, and a decision about thefive U+FC5E–FC62 presentation-form ligatures that table also carries.
Closes #251
🤖 Generated with Claude Code