From 28cc03268d35227dc6830297856f262a063d5b94 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 16 Sep 2026 10:53:23 +1000 Subject: [PATCH 1/2] Read four lookup keys for what the font states, not for what the read assumed (#113) Four keys read without checking they are there, each the same shape as #104: a key the font never set, which PHP 7 answered with a notice and PHP 8 answers with a warning. Two of them were doing more than warning, and the fourth is already guarded. A Single Substitution Format 1 states its replacement as a number to add to the glyph id, and the spec adds it modulo 65536 - which is how a font names a glyph below the one it covers, or above the end of the range. Cactus Classical Serif reaches its extended em dash with -7504 from glyph 504, Noto Sans SignWriting its alternate forms with -28287 from glyphs 8 to 27, and Chiron Sung HK wraps both ways, glyph 50768 up past 65536 and glyph 1 down under zero. Both halves of mPDF added without the modulo: the parser then read glyphToChar outside its keys, and unicode_hex() made U+0000 of the null that came back, so the rule named the null character. A sum that is still outside the font after the modulo is a glyph the font has not got and records nothing, which is what the Alternate Substitution beside it already did, so the two share substituteGlyph() - and so, now, do the Ligature and Reverse Chaining branches, which spelt the same guard out by hand. The shaper has its own copy of that sum, and the issue does not name it. Otl's Format 1 path indexes glyphIDtoUni by the unmasked id, where a negative one is read from the end of the string and happens to come out right and one past 65535 reads off the end and comes out U+0000. Chiron Sung HK, Chiron Hei HK and Chiron GoRound TC all hold the historical form of U+3127 above 65536, so `font-variant-alternates: historical-forms` over that character drew nothing at all in any of the three. It draws the glyph `hb-shape` draws now. A lookup flag naming a mark attachment class says to skip every mark outside that class. Which marks those are is GDEF's MarkAttachClassDef to say, and a font may set the flag without defining that table at all - Carlito and NATS both do. No mark is then in the class, so the lookup skips all of them; reading MarkAttachmentType by the class gave null, which is no marks skipped. This is the one place a page moves. Carlito's 'ccmp' replaces i and j with their dotless forms before a mark above, and that rule was firing where HarfBuzz, reading the same flag, leaves the dot on. NATS does not move: its 58 mark glyphs are the subscript consonant forms, and every Telugu matra and the halant its ligatures stand on is GDEF class 1. Class 0 of a Class Definition is every glyph the other classes do not name, so it has no list of glyphs to match against. Every input position of a context rule above the first already said so, with the comment explaining why; the first read InputClasses by the class and got null. Molengo is the one font here, and its rule set for class 0 cannot fire either way - the subtable's Coverage holds nothing but glyphs the font puts in class 1. The fourth, a feature whose LookupListIndex is empty, is already guarded: #117 added it while splitting the readers. Sedan SC's 'smcp' lists no lookups at all, which is the font the comment there said no one carried, so it says so now and there is a fixture for it. Nothing else moves. Over the nine families the issue names, every artefact the parser writes to the font cache is byte-identical - 77 files across the nine - and eight of the nine render byte-identical pages. Test fonts: Carlito-MarkAttachmentType-Subset (Carlito 1.104, OFL 1.1), Molengo-GSUB52Class0-Subset (Molengo 0.11, OFL 1.1), SedanSC-EmptyFeature-Subset (Sedan SC 1.100, OFL 1.1) and NotoSansArabic-GSUB11Wrap-Synthetic, whose letters are Noto Sans Arabic 2.012 (OFL 1.1) and whose 32,771 glyphs are what it takes for an int16 delta to carry a sum past either end of the range. Co-Authored-By: Claude Opus 5 (1M context) --- src/Otl.php | 28 +- src/TTFontFile.php | 90 +++++-- tests/Mpdf/DeltaGlyphIdTest.php | 76 ++++++ tests/Mpdf/MarkAttachmentTypeTest.php | 62 +++++ tests/Mpdf/TTFontFileTest.php | 72 ++++++ .../Carlito-MarkAttachmentType-Subset.json | 239 ++++++++++++++++++ .../Molengo-GSUB52Class0-Subset.json | 150 +++++++++++ .../NotoSansArabic-GSUB11Wrap-Synthetic.json | 62 +++++ .../SedanSC-EmptyFeature-Subset.json | 163 ++++++++++++ .../Carlito-MarkAttachmentType-Subset.txt | 24 ++ .../otldump/Molengo-GSUB52Class0-Subset.txt | 27 ++ .../NotoSansArabic-GSUB11Wrap-Synthetic.txt | 16 ++ .../otldump/SedanSC-EmptyFeature-Subset.txt | 21 ++ .../Carlito-MarkAttachmentType-Subset.txt | 96 +++++++ .../shaping/Molengo-GSUB52Class0-Subset.txt | 184 ++++++++++++++ .../NotoSansArabic-GSUB11Wrap-Synthetic.txt | 184 ++++++++++++++ .../shaping/SedanSC-EmptyFeature-Subset.txt | 92 +++++++ .../Carlito-MarkAttachmentType-Subset.json | 141 +++++++++++ .../subset/Molengo-GSUB52Class0-Subset.json | 141 +++++++++++ .../NotoSansArabic-GSUB11Wrap-Synthetic.json | 117 +++++++++ .../subset/SedanSC-EmptyFeature-Subset.json | 141 +++++++++++ .../ttf/Carlito-MarkAttachmentType-Subset.ttf | Bin 0 -> 5792 bytes .../data/ttf/Molengo-GSUB52Class0-Subset.ttf | Bin 0 -> 9364 bytes .../NotoSansArabic-GSUB11Wrap-Synthetic.ttf | Bin 0 -> 132540 bytes .../data/ttf/SedanSC-EmptyFeature-Subset.ttf | Bin 0 -> 8232 bytes 25 files changed, 2092 insertions(+), 34 deletions(-) create mode 100644 tests/Mpdf/DeltaGlyphIdTest.php create mode 100644 tests/Mpdf/MarkAttachmentTypeTest.php create mode 100644 tests/data/fontcache/Carlito-MarkAttachmentType-Subset.json create mode 100644 tests/data/fontcache/Molengo-GSUB52Class0-Subset.json create mode 100644 tests/data/fontcache/NotoSansArabic-GSUB11Wrap-Synthetic.json create mode 100644 tests/data/fontcache/SedanSC-EmptyFeature-Subset.json create mode 100644 tests/data/otldump/Carlito-MarkAttachmentType-Subset.txt create mode 100644 tests/data/otldump/Molengo-GSUB52Class0-Subset.txt create mode 100644 tests/data/otldump/NotoSansArabic-GSUB11Wrap-Synthetic.txt create mode 100644 tests/data/otldump/SedanSC-EmptyFeature-Subset.txt create mode 100644 tests/data/shaping/Carlito-MarkAttachmentType-Subset.txt create mode 100644 tests/data/shaping/Molengo-GSUB52Class0-Subset.txt create mode 100644 tests/data/shaping/NotoSansArabic-GSUB11Wrap-Synthetic.txt create mode 100644 tests/data/shaping/SedanSC-EmptyFeature-Subset.txt create mode 100644 tests/data/subset/Carlito-MarkAttachmentType-Subset.json create mode 100644 tests/data/subset/Molengo-GSUB52Class0-Subset.json create mode 100644 tests/data/subset/NotoSansArabic-GSUB11Wrap-Synthetic.json create mode 100644 tests/data/subset/SedanSC-EmptyFeature-Subset.json create mode 100644 tests/data/ttf/Carlito-MarkAttachmentType-Subset.ttf create mode 100644 tests/data/ttf/Molengo-GSUB52Class0-Subset.ttf create mode 100644 tests/data/ttf/NotoSansArabic-GSUB11Wrap-Synthetic.ttf create mode 100644 tests/data/ttf/SedanSC-EmptyFeature-Subset.ttf diff --git a/src/Otl.php b/src/Otl.php index 13d1dd9a9..55908e07a 100644 --- a/src/Otl.php +++ b/src/Otl.php @@ -2061,7 +2061,9 @@ private function _applyGSUBsingleSubst($lookupID, $subtable, $ptr, $currGlyph, $ $DeltaGlyphID = $this->reader->readInt16(); $this->reader->seek($CoverageOffset); $glyphs = $this->_getCoverageGID(); - $GlyphID = $glyphs[$GlyphPos] + $DeltaGlyphID; + // The modulo is how a font names a glyph below the one it covers, or above the end of the + // range: Chiron Hei HK's 'hist' reaches glyph 1688 with 15324 from glyph 51900 + $GlyphID = ($glyphs[$GlyphPos] + $DeltaGlyphID) & 0xFFFF; } // Format 2: elseif ($SubstFormat == 2) { // Specified output glyph indices @@ -4616,6 +4618,23 @@ private function marksOutsideFilteringSet($marks, $set) return $keep ? ' ' . implode('| ', $keep) : ''; } + /** + * The marks a lookup naming a mark attachment class skips: every mark outside that class, which is + * what the parser keeps MarkAttachmentType as. + * + * A font may name a class GDEF does not define - Carlito and NATS set the flag without a + * MarkAttachClassDef table at all - and then no mark is in the class, so the lookup skips every one + * of them. + * + * @param int $class The mark attachment class the lookup's flags name + * + * @return string Its glyphs, space-prefixed and "|"-separated + */ + private function marksOutsideAttachmentClass($class) + { + return isset($this->MarkAttachmentType[$class]) ? $this->MarkAttachmentType[$class] : $this->GlyphClassMarks; + } + /** * The characters a Lookup's flag says to skip over, as a set keyed by codepoint. * @@ -4660,10 +4679,8 @@ private function buildGCOMignoreList($flag, $MarkFilteringSet) // Flag & 0xFF?? = MarkAttachmentType if ($flag & 0xFF00) { // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" - // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table - $MarkAttachmentType = $flag >> 8; $ignoreflag = $flag; - $str = $this->MarkAttachmentType[$MarkAttachmentType]; + $str = $this->marksOutsideAttachmentClass($flag >> 8); } // Flag & 0x0010 = UseMarkFilteringSet @@ -4726,8 +4743,7 @@ private function _checkGCOMignore($flag, $glyph, $MarkFilteringSet) // Flag & 0xFF?? = MarkAttachmentType if ($flag & 0xFF00) { // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" - // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table - if (strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) { + if (strpos($this->marksOutsideAttachmentClass($flag >> 8), $glyph)) { $ignore = true; } } diff --git a/src/TTFontFile.php b/src/TTFontFile.php index 4087e44cf..b8eb7167a 100644 --- a/src/TTFontFile.php +++ b/src/TTFontFile.php @@ -1698,16 +1698,21 @@ private function readGSUBrules(array &$Lookup) $glyphs = $this->_getCoverage(false); for ($g = 0; $g < count($glyphs); $g++) { $replace = []; - $substitute = []; $replace[] = unicode_hex($this->glyphToChar[$glyphs[$g]][0]); // Flag = Ignore if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { continue; } if (isset($Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])) { // Format 1 - $substitute[] = unicode_hex($this->glyphToChar[($glyphs[$g] + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])][0]); + // The modulo is how a font names a glyph below the one it covers: Cactus + // Classical Serif reaches its extended em dash with -7504 from glyph 504 + $gid = ($glyphs[$g] + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID']) & 0xFFFF; } else { // Format 2 - $substitute[] = unicode_hex($this->glyphToChar[($Lookup[$i]['Subtable'][$c]['Glyphs'][$g])][0]); + $gid = $Lookup[$i]['Subtable'][$c]['Glyphs'][$g]; + } + $substitute = $this->substituteGlyph($gid); + if ($substitute === null) { + continue; } $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; } @@ -1717,7 +1722,6 @@ private function readGSUBrules(array &$Lookup) $glyphs = $this->_getCoverage(); for ($g = 0; $g < count($glyphs); $g++) { $replace = []; - $substitute = []; $replace[] = $glyphs[$g]; // Flag = Ignore if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { @@ -1738,7 +1742,6 @@ private function readGSUBrules(array &$Lookup) $glyphs = $this->_getCoverage(); for ($g = 0; $g < count($glyphs); $g++) { $replace = []; - $substitute = []; $replace[] = $glyphs[$g]; // Flag = Ignore if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { @@ -1758,7 +1761,6 @@ private function readGSUBrules(array &$Lookup) for ($s = 0; $s < $LigSetCount; $s++) { for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { $replace = []; - $substitute = []; $replace[] = $glyphs[$s]; // Flag = Ignore if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { @@ -1774,10 +1776,10 @@ private function readGSUBrules(array &$Lookup) $replace[] = $rpl; } $gid = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph']; - if (!isset($this->glyphToChar[$gid][0])) { + $substitute = $this->substituteGlyph($gid); + if ($substitute === null) { continue; } - $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute, 'CompCount' => $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']]; } } @@ -1977,7 +1979,6 @@ private function readGSUBrules(array &$Lookup) $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs'] = [implode("|", $glyphs)]; for ($g = 0; $g < count($glyphs); $g++) { $replace = []; - $substitute = []; $replace[] = $glyphs[$g]; // Flag = Ignore if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { @@ -1986,11 +1987,10 @@ private function readGSUBrules(array &$Lookup) if (!isset($Lookup[$i]['Subtable'][$c]['SubstituteGlyphID'][$g])) { continue; } // The substitutes must run parallel to the Coverage table; either an error in the font, or something has gone wrong - $gid = $Lookup[$i]['Subtable'][$c]['SubstituteGlyphID'][$g]; - if (!isset($this->glyphToChar[$gid][0])) { + $substitute = $this->substituteGlyph($Lookup[$i]['Subtable'][$c]['SubstituteGlyphID'][$g]); + if ($substitute === null) { continue; } - $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; } for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']; $b++) { @@ -2431,7 +2431,11 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) $inputGlyphs = []; - $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + if (isset($Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass])) { + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + } else { + $inputGlyphs[0] = ''; + } if ($rule['InputGlyphCount'] > 1) { // NB starts at 1 for ($gcl = 1; $gcl < $rule['InputGlyphCount']; $gcl++) { @@ -2871,8 +2875,7 @@ function _checkGSUBignore($flag, $glyph, $MarkFilteringSet) // Flag & 0xFF?? = MarkAttachmentType if ($flag & 0xFF00) { // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" - // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table - if (strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) { + if (strpos($this->marksOutsideAttachmentClass($flag >> 8), $glyph)) { $ignore = true; } } @@ -2936,6 +2939,23 @@ private function marksOutsideFilteringSet($marks, $set) return $keep ? ' ' . implode('| ', $keep) : ''; } + /** + * The marks a lookup naming a mark attachment class skips: every mark outside that class, which + * is what _getGDEFtables() keeps MarkAttachmentType as. + * + * A font may name a class GDEF does not define - Carlito and NATS set the flag without a + * MarkAttachClassDef table at all - and then no mark is in the class, so the lookup skips every + * one of them. + * + * @param int $class The mark attachment class the lookup's flags name + * + * @return string Its glyphs, space-prefixed and "|"-separated + */ + private function marksOutsideAttachmentClass($class) + { + return isset($this->MarkAttachmentType[$class]) ? $this->MarkAttachmentType[$class] : $this->GlyphClassMarks; + } + /** * The glyphs a lookup's flags say to skip, as a pattern that matches a run of them. * @@ -2959,10 +2979,8 @@ function _getGSUBignoreString($flag, $MarkFilteringSet) // Flag & 0xFF?? = MarkAttachmentType if ($flag & 0xFF00) { // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" - // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table - $MarkAttachmentType = $flag >> 8; $ignoreflag = $flag; - $str = $this->MarkAttachmentType[$MarkAttachmentType]; + $str = $this->marksOutsideAttachmentClass($flag >> 8); } // Flag & 0x0010 = UseMarkFilteringSet @@ -3434,9 +3452,11 @@ private function readScriptsAndFeatures($scriptListOffset, $featureListOffset) $byFirstLookup = []; foreach ($featureIndices as $featureIndex) { $feature = $features[$featureIndex]; - // A feature that runs no lookups has nothing to be ordered by and nothing to do. - // The spec permits one; no font in the 183 installed carries one, which is why the - // GSUB reader went without this guard for years and the GPOS one grew it. + // A feature that runs no lookups has nothing to be ordered by and nothing to do. The + // spec permits one and fonts in the wild carry one - Sedan SC's 'smcp' lists no + // lookups at all - so dropping it is the whole of what is right to do with it: keying + // the row by the lookup it has not got put it under '', which ksort() then ordered + // ahead of every real lookup index. if (isset($feature['LookupListIndex'][0])) { $byFirstLookup[$feature['LookupListIndex'][0]] = $feature; } @@ -3604,6 +3624,26 @@ protected function multipleSubstitutes(array $sequence) return $substitute; } + /** + * One replacement glyph, as the character the shaper names it by. + * + * Every glyph of a font read with useOTL has a character: the ones the cmap does not reach are + * mapped into the Private Use Area. So the only glyph id without one is a glyph the font has not + * got, which Single, Ligature, Alternate and Reverse Chaining Substitution can all name. + * + * @param int $gid The glyph the rule replaces its match with + * + * @return array|null It as hex in a list of one, or null to record nothing for this one + */ + private function substituteGlyph($gid) + { + if (!isset($this->glyphToChar[$gid][0])) { + return null; + } + + return [unicode_hex($this->glyphToChar[$gid][0])]; + } + /** * What an Alternate Substitution puts in place of the glyph it covers. * @@ -3616,13 +3656,7 @@ protected function multipleSubstitutes(array $sequence) */ protected function alternateSubstitutes(array $alternateSet) { - $gid = $alternateSet['SubstituteGlyphID'][0]; - - if (!isset($this->glyphToChar[$gid][0])) { - return null; - } - - return [unicode_hex($this->glyphToChar[$gid][0])]; + return $this->substituteGlyph($alternateSet['SubstituteGlyphID'][0]); } /** diff --git a/tests/Mpdf/DeltaGlyphIdTest.php b/tests/Mpdf/DeltaGlyphIdTest.php new file mode 100644 index 000000000..9fa4b3210 --- /dev/null +++ b/tests/Mpdf/DeltaGlyphIdTest.php @@ -0,0 +1,76 @@ + 'utf-8', + 'fontDir' => [__DIR__ . '/../data/ttf'], + 'fontdata' => ['gsub11wrap' => [ + 'R' => 'NotoSansArabic-GSUB11Wrap-Synthetic.ttf', + 'useOTL' => 0xFF, + ]], + 'default_font' => 'gsub11wrap', + ]); + $mpdf->WriteHTML('

' . $html . '

'); + + return array_values(unpack('N*', mb_convert_encoding($mpdf->drawnText[0], 'UTF-32BE', 'UTF-8'))); + } + + /** + * The lookup covers glyph 32770 and adds 32767, so the sum is 65537 and the substitute is glyph + * 1. Without the modulo the letter drew as nothing at all. + */ + public function testTheGlyphTheDeltaWrapsOntoIsDrawn() + { + $this->assertSame([self::ALEF_FINA], $this->drawn([self::ALEF])); + } + + /** + * Text is drawn in visual order, which for Arabic is the reverse of the order it is written in. + * The letter the lookup does not cover is left where it is. + */ + public function testALetterTheLookupDoesNotCoverIsLeftAlone() + { + $this->assertSame([self::ALEF_FINA, self::BEH], $this->drawn([self::BEH, self::ALEF])); + } + +} diff --git a/tests/Mpdf/MarkAttachmentTypeTest.php b/tests/Mpdf/MarkAttachmentTypeTest.php new file mode 100644 index 000000000..7d22eeb51 --- /dev/null +++ b/tests/Mpdf/MarkAttachmentTypeTest.php @@ -0,0 +1,62 @@ + 'utf-8', + 'fontDir' => [__DIR__ . '/../data/ttf'], + 'fontdata' => ['markattachment' => [ + 'R' => 'Carlito-MarkAttachmentType-Subset.ttf', + 'useOTL' => 0xFF, + ]], + 'default_font' => 'markattachment', + ]); + $mpdf->WriteHTML('

' . $html . '

'); + + return array_values(unpack('N*', mb_convert_encoding($mpdf->drawnText[0], 'UTF-32BE', 'UTF-8'))); + } + + /** + * The two characters draw as themselves: the lookup that would replace the i skips the mark its + * lookahead needs, so it cannot match. `hb-shape` draws the same pair of glyphs. + */ + public function testALookupNamingAnUndefinedMarkAttachmentClassSkipsTheMarkItLooksAheadFor() + { + $this->assertSame([self::I, self::COMMA_ABOVE], $this->drawn([self::I, self::COMMA_ABOVE])); + } + +} diff --git a/tests/Mpdf/TTFontFileTest.php b/tests/Mpdf/TTFontFileTest.php index 715c525fb..4e4d14cac 100644 --- a/tests/Mpdf/TTFontFileTest.php +++ b/tests/Mpdf/TTFontFileTest.php @@ -120,6 +120,78 @@ public function testAJoiningFormOfMoreThanOneGlyphContributesEachOfThem() $this->assertSame('\x{0E000}-\x{0E003}\x{0E005}-\x{0E007}', $this->ttf->rtlPUAstr); } + /** + * The parser's half of the modulo the spec adds a Single Substitution Format 1 delta by. Adding + * without it lands outside glyphToChar, and unicode_hex() made U+0000 of the null that came back, + * so the rule named the null character. @see DeltaGlyphIdTest for the shaper's half and for the + * fonts that wrap. + * + * The synthetic covers glyph 32770 and adds 32767, so the sum is 65537 and the substitute is glyph + * 1 - the only glyph in the font with no character of its own, which is why it is the only one in + * the Private Use Area. A font can only spell a wrap with tens of thousands of glyphs: an int16 + * delta cannot carry a sum past either end from anywhere closer. + */ + public function testASingleSubstitutionDeltaIsAddedModulo65536() + { + $raised = $this->diagnosticsWhileParsing('NotoSansArabic-GSUB11Wrap-Synthetic.ttf'); + + $this->assertSame([], $raised); + $this->assertSame('\x{0E000}', $this->ttf->rtlPUAstr); + } + + /** + * A lookup flag naming a mark attachment class says to skip every mark outside that class. A font + * may name a class GDEF does not define - Carlito and NATS both set the flag without a + * MarkAttachClassDef table at all - and then no mark is in the class, so every one of them is + * skipped. Reading MarkAttachmentType by the class instead gave null, which is no marks skipped. + * + * The subset is Carlito 1.104 (OFL 1.1) cut to U+0069, U+006A and U+0313, keeping the two 'ccmp' + * chained contexts that carry the flag and the dotless forms they substitute. + */ + public function testALookupNamingAMarkAttachmentClassTheFontDoesNotDefineParses() + { + $raised = $this->diagnosticsWhileParsing('Carlito-MarkAttachmentType-Subset.ttf'); + + $this->assertSame([], $raised); + $this->assertSame('Carlito-Regular', $this->ttf->fullName); + } + + /** + * Class 0 of a Class Definition is every glyph the other classes do not name, so it has no list of + * glyphs to match against and mPDF matches nothing at such a position. Every input position above + * the first already said so; the first read InputClasses by the class and got null. + * + * The subset is Molengo 0.11 (OFL 1.1) cut to U+0069, U+006A, U+0268 and the marks its one 'ccmp' + * lookup classifies. That lookup's only rule set is class 0's, and its Coverage holds nothing but + * glyphs the font puts in class 1, so the rules it states cannot fire either way. + */ + public function testAContextRuleSetForClassZeroIsReadLikeEveryOther() + { + $raised = $this->diagnosticsWhileParsing('Molengo-GSUB52Class0-Subset.ttf'); + + $this->assertSame([], $raised); + $this->assertSame('Molengo-Regular', $this->ttf->fullName); + } + + /** + * A feature that runs no lookups is not offered to the shaper: there is nothing for it to do, and + * the lookup index the features are ordered by is the one it has not got. + * + * The subset is Sedan SC 1.100 (OFL 1.1), whose 'smcp' lists no lookups at all. The subsetter drops + * a feature with none, so it is put back. The 'aalt' and 'c2sc' left in it are what says the real + * features still come out in lookup order. + */ + public function testAFeatureThatRunsNoLookupsIsNotOffered() + { + $raised = $this->diagnosticsWhileParsing('SedanSC-EmptyFeature-Subset.ttf'); + + $this->assertSame([], $raised); + $this->assertSame( + ['aalt' => [0, 1], 'c2sc' => [2], 'ccmp' => [3]], + $this->ttf->GSUBFeatures['latn']['DFLT'] + ); + } + /** * Parse a font, collecting every diagnostic PHP raised doing it. Deprecations are not converted to * exceptions, so a handler is what sees them. diff --git a/tests/data/fontcache/Carlito-MarkAttachmentType-Subset.json b/tests/data/fontcache/Carlito-MarkAttachmentType-Subset.json new file mode 100644 index 000000000..b36a2dc8a --- /dev/null +++ b/tests/data/fontcache/Carlito-MarkAttachmentType-Subset.json @@ -0,0 +1,239 @@ +{ + "_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.", + "fullName": "Carlito-Regular", + "mtx": { + "GSUBScriptLang": { + "cyrl": "DFLT ", + "grek": "DFLT ", + "latn": "DFLT IPPH TRK " + }, + "GSUBFeatures": { + "cyrl": { + "DFLT": { + "ccmp": [ + 2, + 3 + ], + "sups": [ + 4 + ] + } + }, + "grek": { + "DFLT": { + "ccmp": [ + 2, + 3 + ], + "sups": [ + 4 + ] + } + }, + "latn": { + "DFLT": { + "ccmp": [ + 2, + 3 + ], + "sups": [ + 4 + ], + "dlig": [ + 5 + ], + "ordn": [ + 6 + ] + }, + "IPPH": { + "ccmp": [ + 2, + 3 + ] + }, + "TRK ": { + "ccmp": [ + 3 + ], + "sups": [ + 4 + ], + "dlig": [ + 5 + ], + "ordn": [ + 6 + ] + } + } + }, + "GSUBLookups": [ + { + "Type": 1, + "Flag": 256, + "SubtableCount": 1, + "Subtables": [ + 246 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 256, + "SubtableCount": 1, + "Subtables": [ + 260 + ], + "MarkFilteringSet": "" + }, + { + "Type": 6, + "Flag": 256, + "SubtableCount": 1, + "Subtables": [ + 274 + ], + "MarkFilteringSet": "" + }, + { + "Type": 6, + "Flag": 256, + "SubtableCount": 1, + "Subtables": [ + 300 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 370 + ], + "MarkFilteringSet": "" + }, + { + "Type": 4, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 338 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 370 + ], + "MarkFilteringSet": "" + } + ], + "GPOSScriptLang": { + "cyrl": "DFLT ", + "grek": "DFLT ", + "latn": "DFLT " + }, + "GPOSFeatures": { + "cyrl": { + "DFLT": { + "kern": [ + 0 + ] + } + }, + "grek": { + "DFLT": { + "kern": [ + 0 + ] + } + }, + "latn": { + "DFLT": { + "kern": [ + 0 + ] + } + } + }, + "GPOSLookups": [ + { + "Type": 2, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 112 + ], + "MarkFilteringSet": "" + } + ], + "MarkGlyphSets": [], + "rtlPUAstr": "", + "haskernGPOS": true, + "hassmallcapsGSUB": false + }, + "cache": { + "GDEFdata.json": { + "GlyphClassBases": " 00020| 00069| 0006A| 0E000| 0E001| 0E002| 0E003| 0E004| 0FFFF", + "GlyphClassMarks": " 00313", + "GlyphClassLigatures": "", + "GlyphClassComponents": "", + "MarkGlyphSets": [], + "MarkAttachmentType": [] + }, + "GPOS.dat": "162 bytes, sha256 df60dbaa624bc282b48a5cf9b4c37ce951c001f9d70cfe4096f54dbbd1c0212e", + "GPOSdata.json": [ + [ + { + "105": 0, + "106": 1 + } + ] + ], + "GSUB.dat": "388 bytes, sha256 4a3088648e0017ee922740a2b4220e5de9ab7c0930d919e8de5bb4f32e68bddc", + "GSUBdata.json": [ + [ + { + "105": 0 + } + ], + [ + { + "106": 0 + } + ], + [ + { + "105": 0 + } + ], + [ + { + "106": 0 + } + ], + [ + { + "105": 0, + "106": 1 + } + ], + [ + { + "105": 0 + } + ], + [ + { + "105": 0, + "106": 1 + } + ] + ] + } +} diff --git a/tests/data/fontcache/Molengo-GSUB52Class0-Subset.json b/tests/data/fontcache/Molengo-GSUB52Class0-Subset.json new file mode 100644 index 000000000..62a96b20d --- /dev/null +++ b/tests/data/fontcache/Molengo-GSUB52Class0-Subset.json @@ -0,0 +1,150 @@ +{ + "_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.", + "fullName": "Molengo-Regular", + "mtx": { + "GSUBScriptLang": { + "DFLT": "DFLT ", + "latn": "DFLT " + }, + "GSUBFeatures": { + "DFLT": { + "DFLT": { + "ccmp": [ + 0 + ] + } + }, + "latn": { + "DFLT": { + "ccmp": [ + 0 + ] + } + } + }, + "GSUBLookups": [ + { + "Type": 5, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 64 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 184 + ], + "MarkFilteringSet": "" + } + ], + "GPOSScriptLang": { + "DFLT": "DFLT ", + "latn": "DFLT " + }, + "GPOSFeatures": { + "DFLT": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "latn": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + } + }, + "GPOSLookups": [ + { + "Type": 4, + "Flag": 0, + "SubtableCount": 2, + "Subtables": [ + 80, + 120 + ], + "MarkFilteringSet": "" + }, + { + "Type": 6, + "Flag": 0, + "SubtableCount": 2, + "Subtables": [ + 172, + 276 + ], + "MarkFilteringSet": "" + } + ], + "MarkGlyphSets": [], + "rtlPUAstr": "", + "haskernGPOS": false, + "hassmallcapsGSUB": false + }, + "cache": { + "GDEFdata.json": { + "GlyphClassBases": " 00020| 00069| 0006A| 00268| 00307| 0E000| 0E001| 0E002| 0E003| 0E004| 0E005| 0E006| 0E007| 0E008| 0E009| 0E00A| 0E00B| 0E00C| 0E00D| 0E00E| 0E00F| 0E010| 0E011| 0E012| 0E013| 0E014| 0E015| 0E016| 0E017| 0E018| 0E019| 0E01A| 0E01B| 0E01C| 0E01D| 0E01E| 0E01F| 0E020| 0E021| 0E022| 0E023| 0E024| 0E025| 0E026| 0E027| 0E028| 0E029| 0E02A| 0E02B| 0E02C| 0E02D| 0E02E| 0E02F| 0E030| 0E031| 0E032| 0E033| 0E034| 0E035| 0E036| 0E037| 0E038| 0E039| 0E03A| 0E03B| 0E03C| 0E03D| 0E03E| 0E03F| 0E040| 0E041| 0E042| 0E043| 0E044| 0E045| 0E046| 0E047| 0E048| 0E049| 0E04A| 0E04B| 0E04C| 0E04D| 0E04E| 0E04F| 0E050| 0E051| 0E052| 0E053| 0E054| 0E055| 0E056| 0E057| 0E058| 0E059| 0E05A| 0E05B| 0E05C| 0E05D| 0E05E| 0E05F| 0E060| 0E061| 0E062| 0E063| 0E064| 0E065| 0E066| 0E067| 0E068| 0E069| 0E06A| 0E06B| 0E06C| 0E06D| 0E06E| 0E06F| 0E070| 0E071| 0E072| 0E073| 0E074| 0E075| 0E076| 0E077| 0E078| 0E079| 0E07A| 0E07B| 0E07C| 0E07D| 0E07E| 0E07F| 0E080| 0E081| 0E082| 0E083| 0E084| 0E085| 0E086| 0E087| 0E088| 0E089| 0E08A| 0E08B| 0E08C| 0E08D| 0E08E| 0E08F| 0E090| 0E091| 0E092| 0E093| 0E094| 0E095| 0E096| 0E097| 0E098| 0E099| 0E09A| 0E09B| 0E09C| 0E09D| 0E09E| 0E09F| 0E0A0| 0E0A1| 0E0A2| 0E0A3| 0E0A4| 0E0A5| 0E0A6| 0E0A7| 0E0A8| 0E0A9| 0E0AA| 0E0AB| 0E0AC| 0E0AD| 0E0AE| 0E0AF| 0E0B0| 0E0B1| 0E0B2| 0E0B3| 0E0B4| 0E0B5| 0E0B6| 0E0B7| 0E0B8| 0E0B9| 0E0BA| 0E0BB| 0E0BC| 0E0BD| 0E0BE| 0E0BF| 0E0C0| 0E0C1| 0E0C2| 0E0C3| 0E0C4| 0E0C5| 0E0C6| 0E0C7| 0E0C8| 0E0C9| 0E0CA| 0E0CB| 0E0CC| 0E0CD| 0E0CE| 0E0CF| 0E0D0| 0E0D1| 0E0D2| 0E0D3| 0E0D4| 0E0D5| 0E0D6| 0E0D7| 0E0D8| 0E0D9| 0E0DA| 0E0DB| 0E0DC| 0E0DD| 0E0DE| 0E0DF| 0E0E0| 0E0E1| 0E0E2| 0E0E3| 0E0E4| 0E0E5| 0E0E7| 0E0E8| 0E0E9| 0E0EA| 0E0EB| 0E0EC| 0E0ED| 0E0EE| 0E0EF| 0E0F0| 0E0F1| 0E0F2| 0E0F3| 0E0F4| 0E0F5| 0E0F6| 0E0F7| 0E0F8| 0E0F9| 0E0FA| 0E0FB| 0E0FC| 0E0FD| 0E0FE| 0E0FF| 0E100| 0E101| 0E102| 0E103| 0E104| 0E105| 0E106| 0E121| 0E122| 0E123| 0E124| 0E125| 0E126| 0E127| 0E128| 0E129| 0E12A| 0E12B| 0E12C| 0E12D| 0E12E| 0E12F| 0E130| 0E131| 0E132| 0E133| 0E134| 0E135| 0E136| 0E137| 0E138| 0E139| 0E13A| 0E13B| 0E13C| 0E13D| 0E13E| 0E13F| 0E140| 0E141| 0E142| 0E143| 0E144| 0E145| 0E146| 0E147| 0E148| 0E149| 0E14A| 0E14B| 0E14C| 0E14D| 0E14E| 0E14F| 0E150| 0E151| 0E152| 0E153| 0E154| 0E155| 0E156| 0E157| 0E158| 0E159| 0E15A| 0E15B| 0E15C| 0E15D| 0E15E| 0E15F| 0E160| 0E161| 0E162| 0E163| 0E164| 0E165| 0E166| 0E167| 0E168| 0E169", + "GlyphClassMarks": " 00301| 00303| 00309| 00323| 0E0E6| 0E107| 0E108| 0E109| 0E10A| 0E10B| 0E10C| 0E10D| 0E10E| 0E10F| 0E110| 0E111| 0E112| 0E113| 0E114| 0E115| 0E116| 0E117| 0E118| 0E119| 0E11A| 0E11B| 0E11C| 0E11D| 0E11E| 0E11F| 0E120", + "GlyphClassLigatures": "", + "GlyphClassComponents": "", + "MarkGlyphSets": [], + "MarkAttachmentType": [] + }, + "GPOS.dat": "316 bytes, sha256 795e0b128ee67d7f00f7409cdc761260d9f2ff9cffbaab81181e0366ca4513b8", + "GPOSdata.json": [ + [ + { + "769": 0, + "771": 1, + "775": 2, + "777": 3 + }, + { + "803": 0 + } + ], + [ + { + "769": 0, + "771": 1, + "775": 2, + "777": 3 + }, + { + "803": 0 + } + ] + ], + "GSUB.dat": "206 bytes, sha256 8e01a7de9aa9e628960031a108897444f339a79f46c3d7788edd400810d577cf", + "GSUBdata.json": [ + [ + { + "105": 0, + "106": 1, + "616": 2 + } + ], + [ + { + "105": 0, + "106": 1, + "616": 2 + } + ] + ] + } +} diff --git a/tests/data/fontcache/NotoSansArabic-GSUB11Wrap-Synthetic.json b/tests/data/fontcache/NotoSansArabic-GSUB11Wrap-Synthetic.json new file mode 100644 index 000000000..a70cb1cc0 --- /dev/null +++ b/tests/data/fontcache/NotoSansArabic-GSUB11Wrap-Synthetic.json @@ -0,0 +1,62 @@ +{ + "_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.", + "fullName": "NotoSansArabic-GSUB11Wrap-Synthetic", + "mtx": { + "GSUBScriptLang": { + "DFLT": "DFLT ", + "arab": "DFLT " + }, + "GSUBFeatures": { + "DFLT": { + "DFLT": { + "ccmp": [ + 0 + ] + } + }, + "arab": { + "DFLT": { + "ccmp": [ + 0 + ] + } + } + }, + "GSUBLookups": [ + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 62 + ], + "MarkFilteringSet": "" + } + ], + "GPOSScriptLang": [], + "GPOSFeatures": [], + "GPOSLookups": [], + "MarkGlyphSets": [], + "rtlPUAstr": "\\x{0E000}", + "haskernGPOS": false, + "hassmallcapsGSUB": false + }, + "cache": { + "GDEFdata.json": { + "GlyphClassBases": " 00020| 00627| 00628| 0E000", + "GlyphClassMarks": "", + "GlyphClassLigatures": "", + "GlyphClassComponents": "", + "MarkGlyphSets": [], + "MarkAttachmentType": [] + }, + "GSUB.dat": "74 bytes, sha256 6a09e5dce6613a9dead0e55896bee67a475c7fc6c8b34ca2881392dcc9a04168", + "GSUBdata.json": [ + [ + { + "1575": 0 + } + ] + ] + } +} diff --git a/tests/data/fontcache/SedanSC-EmptyFeature-Subset.json b/tests/data/fontcache/SedanSC-EmptyFeature-Subset.json new file mode 100644 index 000000000..9e68c91a2 --- /dev/null +++ b/tests/data/fontcache/SedanSC-EmptyFeature-Subset.json @@ -0,0 +1,163 @@ +{ + "_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.", + "fullName": "SedanSC-Regular", + "mtx": { + "GSUBScriptLang": { + "DFLT": "DFLT ", + "latn": "DFLT " + }, + "GSUBFeatures": { + "DFLT": { + "DFLT": { + "aalt": [ + 0, + 1 + ], + "c2sc": [ + 2 + ], + "ccmp": [ + 3 + ] + } + }, + "latn": { + "DFLT": { + "aalt": [ + 0, + 1 + ], + "c2sc": [ + 2 + ], + "ccmp": [ + 3 + ] + } + } + }, + "GSUBLookups": [ + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 134 + ], + "MarkFilteringSet": "" + }, + { + "Type": 3, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 160 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 192 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 214 + ], + "MarkFilteringSet": "" + } + ], + "GPOSScriptLang": { + "DFLT": "DFLT ", + "latn": "DFLT " + }, + "GPOSFeatures": { + "latn": { + "DFLT": { + "kern": [ + 0 + ] + } + } + }, + "GPOSLookups": [ + { + "Type": 2, + "Flag": 8, + "SubtableCount": 2, + "Subtables": [ + 74, + 146 + ], + "MarkFilteringSet": "" + } + ], + "MarkGlyphSets": [], + "rtlPUAstr": "", + "haskernGPOS": true, + "hassmallcapsGSUB": true + }, + "cache": { + "GDEFdata.json": { + "GlyphClassBases": " 00041| 00061| 0E000", + "GlyphClassMarks": "", + "GlyphClassLigatures": "", + "GlyphClassComponents": "", + "MarkGlyphSets": [], + "MarkAttachmentType": [] + }, + "GPOS.dat": "238 bytes, sha256 4d53e06509aa43a448e5fc03fa941ae40d1b10d0467578f8709d24685ee6b265", + "GPOSdata.json": [ + [ + { + "65": 0, + "97": 1, + "98": 2, + "57344": 3, + "57345": 4, + "57346": 5 + }, + { + "65": 0, + "97": 1, + "98": 2, + "57344": 3 + } + ] + ], + "GSUB.dat": "228 bytes, sha256 fb3a2c6189b002e3ea031ac9922a44622afe67ec4f1ae9d0b512ef4a71fe3766", + "GSUBdata.json": [ + [ + { + "66": 0, + "98": 1 + } + ], + [ + { + "65": 0, + "97": 1 + } + ], + [ + { + "65": 0, + "66": 1 + } + ], + [ + { + "97": 0, + "98": 1 + } + ] + ] + } +} diff --git a/tests/data/otldump/Carlito-MarkAttachmentType-Subset.txt b/tests/data/otldump/Carlito-MarkAttachmentType-Subset.txt new file mode 100644 index 000000000..e2c782730 --- /dev/null +++ b/tests/data/otldump/Carlito-MarkAttachmentType-Subset.txt @@ -0,0 +1,24 @@ +

GDEF table

+

Glyph classes

+

Glyph class 1

+
Base glyph (single character, spacing glyph)
+
i j      ￿
+

Glyph class 3

+
Mark glyph (non-spacing combining glyph)
+
◌̓
+

GSUB Tables

+

GSUB Scripts & Languages

+
+
cyrl
DFLT: ccmp sups
grek
DFLT: ccmp sups
latn
DFLT: ccmp sups dlig ordn
IPPH: ccmp
TRK : ccmp sups dlig ordn
+
+

GPOS Tables

+

GPOS Scripts & Languages

+
+
cyrl
DFLT: kern
grek
DFLT: kern
latn
DFLT: kern
+
+ +=== detail: script latn language DFLT === +

GSUB Tables

+
Lookup #2 [tag: ccmp]
Ignoring: MarkAttachmentType[1]
Subtable #0
LookupType 6: Chaining Contextual Substitution Subtable
Format 3: Coverage-based Chaining Context Glyph Substitution
CONTEXT:
Input #0:  i 
Lookahead #0: U+0313
Substitution Position: 0
Lookup #0 [tag: ccmp]
Ignoring: MarkAttachmentType[1]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0069   i◌̓  » »   ◌̓  M+E000
Lookup #3 [tag: ccmp]
Ignoring: MarkAttachmentType[1]
Subtable #0
LookupType 6: Chaining Contextual Substitution Subtable
Format 3: Coverage-based Chaining Context Glyph Substitution
CONTEXT:
Input #0:  j 
Lookahead #0: U+0313
Substitution Position: 0
Lookup #1 [tag: ccmp]
Ignoring: MarkAttachmentType[1]
Subtable #0
LookupType 1: Single Substitution Subtable
U+006A   j◌̓  » »   ◌̓  M+E002
Lookup #4 [tag: sups]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0069   i  » »     M+E003
U+006A   j  » »     M+E004
Lookup #5 [tag: dlig]
Subtable #0
LookupType 4: Ligature Substitution Subtable
U+0069, U+006A   i j  » »     M+E001
Lookup #6 [tag: ordn]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0069   i  » »     M+E003
U+006A   j  » »     M+E004
+

GPOS Tables

+
Lookup #0 [tag: kern]
Subtable #0
LookupType 2: Pair adjustment e.g. Kerning [Format 2]
diff --git a/tests/data/otldump/Molengo-GSUB52Class0-Subset.txt b/tests/data/otldump/Molengo-GSUB52Class0-Subset.txt new file mode 100644 index 000000000..72df64dbe --- /dev/null +++ b/tests/data/otldump/Molengo-GSUB52Class0-Subset.txt @@ -0,0 +1,27 @@ +

GDEF table

+

Glyph classes

+

Glyph class 1

+
Base glyph (single character, spacing glyph)
+
i j ɨ ̇                                                                                                                                                                                                                                                                                                                                               
+

Glyph class 3

+
Mark glyph (non-spacing combining glyph)
+
◌́ ◌̃ ◌̉ ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌
+

GSUB Tables

+

GSUB Scripts & Languages

+
+
DFLT
DFLT: ccmp
latn
DFLT: ccmp
+
+

GPOS Tables

+

GPOS Scripts & Languages

+
+
DFLT
DFLT: mark mkmk
latn
DFLT: mark mkmk
+
+ +=== detail: script latn language DFLT === +8863 bytes, sha256 e037777f271dbdbe76e45f8cada8702b31aa5456ac2599e7dbe0a651e7648242 +first 8192 bytes: +

GSUB Tables

+
Lookup #0 [tag: ccmp]
Subtable #0
LookupType 5: Contextual Substitution Subtable
Format 2: Class-based Context Glyph Substitution
Input Class: 0
Rule: 0
CONTEXT:
Input #0:  [NOT i j ɨ ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌] 
Input #1:  ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Substitution Position: 0
Lookup #1 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
Rule: 1
CONTEXT:
Input #0:  [NOT i j ɨ ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌] 
Input #1:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #2:  ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Substitution Position: 0
Lookup #1 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
Rule: 2
CONTEXT:
Input #0:  [NOT i j ɨ ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌] 
Input #1:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #2:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #3:  ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Substitution Position: 0
Lookup #1 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
Rule: 3
CONTEXT:
Input #0:  [NOT i j ɨ ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌] 
Input #1:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #2:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #3:  ◌̣ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Input #4:  ◌́ ◌ ◌̃ ◌ ◌ ̇ ◌ ◌̉ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 
Substitution Position: 0
Lookup #1 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
+

GPOS Tables

+
Lookup #0 [tag: mark]
Subtable #0
LookupType 4: MarkToBase attachment
Marks: ◌́ ◌̃ ̇ ◌̉
Bases: ɨ
Example(s): ɨ́  
Subtable #1
LookupType 4: MarkToBase attachment
Marks: ◌̣
Bases: i ɨ
Example(s): ị   ɨ̣  
Lookup #1 [tag: mkmk]
Subtable #0
LookupType 6: MarkToMark attachment
Marks: ◌́ ◌̃ ̇ ◌̉
Bases: i ◌́ ◌̃ ̇ ◌̉
ا ب 
+

GSUB Tables

+

GSUB Scripts & Languages

+
+
DFLT
DFLT: ccmp
arab
DFLT: ccmp
+
+
GPOS table not defined
+ +=== detail: script arab language DFLT === +

GSUB Tables

+
Lookup #0 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0627   ا  » »     M+E000
+
GPOS table not defined
diff --git a/tests/data/otldump/SedanSC-EmptyFeature-Subset.txt b/tests/data/otldump/SedanSC-EmptyFeature-Subset.txt new file mode 100644 index 000000000..1891d603e --- /dev/null +++ b/tests/data/otldump/SedanSC-EmptyFeature-Subset.txt @@ -0,0 +1,21 @@ +

GDEF table

+

Glyph classes

+

Glyph class 1

+
Base glyph (single character, spacing glyph)
+
A a 
+

GSUB Tables

+

GSUB Scripts & Languages

+
+
DFLT
DFLT: aalt c2sc ccmp
latn
DFLT: aalt c2sc ccmp
+
+

GPOS Tables

+

GPOS Scripts & Languages

+
+
latn
DFLT: kern
+
+ +=== detail: script latn language DFLT === +

GSUB Tables

+
Lookup #0 [tag: aalt]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0042   B  » »     M+E001
U+0062   b  » »     M+E001
Lookup #1 [tag: aalt]
Subtable #0
LookupType 3: Alternate Forms
U+0041   A  » »     M+E002   |   ALT #1      M+E000
U+0061   a  » »     M+E002   |   ALT #1      M+E000
Lookup #2 [tag: c2sc]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0041   A  » »     M+E000
U+0042   B  » »     M+E001
Lookup #3 [tag: ccmp]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0061   a  » »     M+E000
U+0062   b  » »     M+E001
+

GPOS Tables

+
Lookup #0 [tag: kern]
Ignoring: Mark Glyphs
Subtable #0
LookupType 2: Pair adjustment e.g. Kerning [Format 1]
 A
 a b
 b
 
 
  A 
Subtable #1
LookupType 2: Pair adjustment e.g. Kerning [Format 2]
diff --git a/tests/data/shaping/Carlito-MarkAttachmentType-Subset.txt b/tests/data/shaping/Carlito-MarkAttachmentType-Subset.txt new file mode 100644 index 000000000..086b38621 --- /dev/null +++ b/tests/data/shaping/Carlito-MarkAttachmentType-Subset.txt @@ -0,0 +1,96 @@ +=== latin === +0xFF 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0x80 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0xFF +kern -liga 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +=== cyrillic === +0xFF 0416 0430 0439 => 0416 0430 0439 group=CCC +0x80 0416 0430 0439 => 0416 0430 0439 group=CCC +0xFF +kern -liga 0416 0430 0439 => 0416 0430 0439 group=CCC +=== greek === +0xFF 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0x80 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0xFF +kern -liga 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +=== hiragana === +0xFF 3042 3043 3044 => 3042 3043 3044 group=CCC +0x80 3042 3043 3044 => 3042 3043 3044 group=CCC +0xFF +kern -liga 3042 3043 3044 => 3042 3043 3044 group=CCC +=== arabic === +0xFF 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0x80 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0xFF +kern -liga 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +=== syriac === +0xFF 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0x80 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0xFF +kern -liga 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +=== nko === +0xFF 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0x80 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0xFF +kern -liga 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +=== devanagari === +0xFF 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0x80 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0xFF +kern -liga 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +=== bengali === +0xFF 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0x80 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0xFF +kern -liga 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +=== gurmukhi === +0xFF 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0x80 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0xFF +kern -liga 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +=== tamil === +0xFF 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0x80 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0xFF +kern -liga 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +=== malayalam === +0xFF 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0x80 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0xFF +kern -liga 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +=== sinhala === +0xFF 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0x80 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0xFF +kern -liga 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +=== khmer === +0xFF 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0x80 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0xFF +kern -liga 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +=== thai === +0xFF 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0x80 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0xFF +kern -liga 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +=== lao === +0xFF 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0x80 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0xFF +kern -liga 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +=== myanmar === +0xFF 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0x80 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0xFF +kern -liga 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +=== new tai lue === +0xFF 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0x80 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0xFF +kern -liga 1980 19B0 1981 => 1980 19B0 1981 group=CCC +=== cham === +0xFF AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0x80 AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0xFF +kern -liga AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +=== tai tham === +0xFF 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0x80 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0xFF +kern -liga 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +=== mixed scripts === +0xFF 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0x80 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0xFF +kern -liga 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +=== spaced === +0xFF 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0x80 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0xFF +kern -liga 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +=== font characters 0 === +0xFF 0020 0069 006A 0313 E000 E001 E002 E003 => 0020 0069 006A 0313 E000 E001 E002 E003 group=SCCMCCCC +0x80 0020 0069 006A 0313 E000 E001 E002 E003 => 0020 0069 006A 0313 E000 E001 E002 E003 group=SCCMCCCC +0xFF +kern -liga 0020 0069 006A 0313 E000 E001 E002 E003 => 0020 0069 006A 0313 E000 E001 E002 E003 group=SCCMCCCC +=== font characters 1 === +0xFF E004 E005 E006 E007 => E004 E005 E006 E007 group=CCCC +0x80 E004 E005 E006 E007 => E004 E005 E006 E007 group=CCCC +0xFF +kern -liga E004 E005 E006 E007 => E004 E005 E006 E007 group=CCCC diff --git a/tests/data/shaping/Molengo-GSUB52Class0-Subset.txt b/tests/data/shaping/Molengo-GSUB52Class0-Subset.txt new file mode 100644 index 000000000..c0cedf1f6 --- /dev/null +++ b/tests/data/shaping/Molengo-GSUB52Class0-Subset.txt @@ -0,0 +1,184 @@ +=== latin === +0xFF 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0x80 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0xFF +kern -liga 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +=== cyrillic === +0xFF 0416 0430 0439 => 0416 0430 0439 group=CCC +0x80 0416 0430 0439 => 0416 0430 0439 group=CCC +0xFF +kern -liga 0416 0430 0439 => 0416 0430 0439 group=CCC +=== greek === +0xFF 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0x80 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0xFF +kern -liga 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +=== hiragana === +0xFF 3042 3043 3044 => 3042 3043 3044 group=CCC +0x80 3042 3043 3044 => 3042 3043 3044 group=CCC +0xFF +kern -liga 3042 3043 3044 => 3042 3043 3044 group=CCC +=== arabic === +0xFF 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0x80 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0xFF +kern -liga 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +=== syriac === +0xFF 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0x80 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0xFF +kern -liga 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +=== nko === +0xFF 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0x80 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0xFF +kern -liga 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +=== devanagari === +0xFF 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0x80 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0xFF +kern -liga 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +=== bengali === +0xFF 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0x80 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0xFF +kern -liga 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +=== gurmukhi === +0xFF 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0x80 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0xFF +kern -liga 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +=== tamil === +0xFF 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0x80 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0xFF +kern -liga 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +=== malayalam === +0xFF 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0x80 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0xFF +kern -liga 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +=== sinhala === +0xFF 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0x80 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0xFF +kern -liga 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +=== khmer === +0xFF 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0x80 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0xFF +kern -liga 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +=== thai === +0xFF 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0x80 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0xFF +kern -liga 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +=== lao === +0xFF 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0x80 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0xFF +kern -liga 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +=== myanmar === +0xFF 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0x80 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0xFF +kern -liga 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +=== new tai lue === +0xFF 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0x80 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0xFF +kern -liga 1980 19B0 1981 => 1980 19B0 1981 group=CCC +=== cham === +0xFF AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0x80 AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0xFF +kern -liga AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +=== tai tham === +0xFF 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0x80 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0xFF +kern -liga 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +=== mixed scripts === +0xFF 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0x80 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0xFF +kern -liga 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +=== spaced === +0xFF 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0x80 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0xFF +kern -liga 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +=== font characters 0 === +0xFF 0020 0069 006A 0268 0301 0303 0307 0309 => 0020 0069 006A 0268 0301 0303 0307 0309 group=SCCCMMCM gpos={"4":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":519},"5":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":959},"6":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":1249},"7":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":1768}} +0x80 0020 0069 006A 0268 0301 0303 0307 0309 => 0020 0069 006A 0268 0301 0303 0307 0309 group=SCCCMMCM +0xFF +kern -liga 0020 0069 006A 0268 0301 0303 0307 0309 => 0020 0069 006A 0268 0301 0303 0307 0309 group=SCCCMMCM gpos={"4":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":519},"5":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":959},"6":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":1249},"7":{"BaseWidth":604.16,"XPlacement":302,"YPlacement":1768}} +=== font characters 1 === +0xFF 0323 E000 E001 E002 E003 E004 E005 E006 => 0323 E000 E001 E002 E003 E004 E005 E006 group=MCCCCCCC +0x80 0323 E000 E001 E002 E003 E004 E005 E006 => 0323 E000 E001 E002 E003 E004 E005 E006 group=MCCCCCCC +0xFF +kern -liga 0323 E000 E001 E002 E003 E004 E005 E006 => 0323 E000 E001 E002 E003 E004 E005 E006 group=MCCCCCCC +=== font characters 2 === +0xFF E007 E008 E009 E00A E00B E00C E00D E00E => E007 E008 E009 E00A E00B E00C E00D E00E group=CCCCCCCC +0x80 E007 E008 E009 E00A E00B E00C E00D E00E => E007 E008 E009 E00A E00B E00C E00D E00E group=CCCCCCCC +0xFF +kern -liga E007 E008 E009 E00A E00B E00C E00D E00E => E007 E008 E009 E00A E00B E00C E00D E00E group=CCCCCCCC +=== font characters 3 === +0xFF E00F E010 E011 E012 E013 E014 E015 E016 => E00F E010 E011 E012 E013 E014 E015 E016 group=CCCCCCCC +0x80 E00F E010 E011 E012 E013 E014 E015 E016 => E00F E010 E011 E012 E013 E014 E015 E016 group=CCCCCCCC +0xFF +kern -liga E00F E010 E011 E012 E013 E014 E015 E016 => E00F E010 E011 E012 E013 E014 E015 E016 group=CCCCCCCC +=== font characters 4 === +0xFF E017 E018 E019 E01A E01B E01C E01D E01E => E017 E018 E019 E01A E01B E01C E01D E01E group=CCCCCCCC +0x80 E017 E018 E019 E01A E01B E01C E01D E01E => E017 E018 E019 E01A E01B E01C E01D E01E group=CCCCCCCC +0xFF +kern -liga E017 E018 E019 E01A E01B E01C E01D E01E => E017 E018 E019 E01A E01B E01C E01D E01E group=CCCCCCCC +=== font characters 5 === +0xFF E01F E020 E021 E022 E023 E024 E025 E026 => E01F E020 E021 E022 E023 E024 E025 E026 group=CCCCCCCC +0x80 E01F E020 E021 E022 E023 E024 E025 E026 => E01F E020 E021 E022 E023 E024 E025 E026 group=CCCCCCCC +0xFF +kern -liga E01F E020 E021 E022 E023 E024 E025 E026 => E01F E020 E021 E022 E023 E024 E025 E026 group=CCCCCCCC +=== font characters 6 === +0xFF E027 E028 E029 E02A E02B E02C E02D E02E => E027 E028 E029 E02A E02B E02C E02D E02E group=CCCCCCCC +0x80 E027 E028 E029 E02A E02B E02C E02D E02E => E027 E028 E029 E02A E02B E02C E02D E02E group=CCCCCCCC +0xFF +kern -liga E027 E028 E029 E02A E02B E02C E02D E02E => E027 E028 E029 E02A E02B E02C E02D E02E group=CCCCCCCC +=== font characters 7 === +0xFF E02F E030 E031 E032 E033 E034 E035 E036 => E02F E030 E031 E032 E033 E034 E035 E036 group=CCCCCCCC +0x80 E02F E030 E031 E032 E033 E034 E035 E036 => E02F E030 E031 E032 E033 E034 E035 E036 group=CCCCCCCC +0xFF +kern -liga E02F E030 E031 E032 E033 E034 E035 E036 => E02F E030 E031 E032 E033 E034 E035 E036 group=CCCCCCCC +=== font characters 8 === +0xFF E037 E038 E039 E03A E03B E03C E03D E03E => E037 E038 E039 E03A E03B E03C E03D E03E group=CCCCCCCC +0x80 E037 E038 E039 E03A E03B E03C E03D E03E => E037 E038 E039 E03A E03B E03C E03D E03E group=CCCCCCCC +0xFF +kern -liga E037 E038 E039 E03A E03B E03C E03D E03E => E037 E038 E039 E03A E03B E03C E03D E03E group=CCCCCCCC +=== font characters 9 === +0xFF E03F E040 E041 E042 E043 E044 E045 E046 => E03F E040 E041 E042 E043 E044 E045 E046 group=CCCCCCCC +0x80 E03F E040 E041 E042 E043 E044 E045 E046 => E03F E040 E041 E042 E043 E044 E045 E046 group=CCCCCCCC +0xFF +kern -liga E03F E040 E041 E042 E043 E044 E045 E046 => E03F E040 E041 E042 E043 E044 E045 E046 group=CCCCCCCC +=== font characters 10 === +0xFF E047 E048 E049 E04A E04B E04C E04D E04E => E047 E048 E049 E04A E04B E04C E04D E04E group=CCCCCCCC +0x80 E047 E048 E049 E04A E04B E04C E04D E04E => E047 E048 E049 E04A E04B E04C E04D E04E group=CCCCCCCC +0xFF +kern -liga E047 E048 E049 E04A E04B E04C E04D E04E => E047 E048 E049 E04A E04B E04C E04D E04E group=CCCCCCCC +=== font characters 11 === +0xFF E04F E050 E051 E052 E053 E054 E055 E056 => E04F E050 E051 E052 E053 E054 E055 E056 group=CCCCCCCC +0x80 E04F E050 E051 E052 E053 E054 E055 E056 => E04F E050 E051 E052 E053 E054 E055 E056 group=CCCCCCCC +0xFF +kern -liga E04F E050 E051 E052 E053 E054 E055 E056 => E04F E050 E051 E052 E053 E054 E055 E056 group=CCCCCCCC +=== font characters 12 === +0xFF E057 E058 E059 E05A E05B E05C E05D E05E => E057 E058 E059 E05A E05B E05C E05D E05E group=CCCCCCCC +0x80 E057 E058 E059 E05A E05B E05C E05D E05E => E057 E058 E059 E05A E05B E05C E05D E05E group=CCCCCCCC +0xFF +kern -liga E057 E058 E059 E05A E05B E05C E05D E05E => E057 E058 E059 E05A E05B E05C E05D E05E group=CCCCCCCC +=== font characters 13 === +0xFF E05F E060 E061 E062 E063 E064 E065 E066 => E05F E060 E061 E062 E063 E064 E065 E066 group=CCCCCCCC +0x80 E05F E060 E061 E062 E063 E064 E065 E066 => E05F E060 E061 E062 E063 E064 E065 E066 group=CCCCCCCC +0xFF +kern -liga E05F E060 E061 E062 E063 E064 E065 E066 => E05F E060 E061 E062 E063 E064 E065 E066 group=CCCCCCCC +=== font characters 14 === +0xFF E067 E068 E069 E06A E06B E06C E06D E06E => E067 E068 E069 E06A E06B E06C E06D E06E group=CCCCCCCC +0x80 E067 E068 E069 E06A E06B E06C E06D E06E => E067 E068 E069 E06A E06B E06C E06D E06E group=CCCCCCCC +0xFF +kern -liga E067 E068 E069 E06A E06B E06C E06D E06E => E067 E068 E069 E06A E06B E06C E06D E06E group=CCCCCCCC +=== font characters 15 === +0xFF E06F E070 E071 E072 E073 E074 E075 E076 => E06F E070 E071 E072 E073 E074 E075 E076 group=CCCCCCCC +0x80 E06F E070 E071 E072 E073 E074 E075 E076 => E06F E070 E071 E072 E073 E074 E075 E076 group=CCCCCCCC +0xFF +kern -liga E06F E070 E071 E072 E073 E074 E075 E076 => E06F E070 E071 E072 E073 E074 E075 E076 group=CCCCCCCC +=== font characters 16 === +0xFF E077 E078 E079 E07A E07B E07C E07D E07E => E077 E078 E079 E07A E07B E07C E07D E07E group=CCCCCCCC +0x80 E077 E078 E079 E07A E07B E07C E07D E07E => E077 E078 E079 E07A E07B E07C E07D E07E group=CCCCCCCC +0xFF +kern -liga E077 E078 E079 E07A E07B E07C E07D E07E => E077 E078 E079 E07A E07B E07C E07D E07E group=CCCCCCCC +=== font characters 17 === +0xFF E07F E080 E081 E082 E083 E084 E085 E086 => E07F E080 E081 E082 E083 E084 E085 E086 group=CCCCCCCC +0x80 E07F E080 E081 E082 E083 E084 E085 E086 => E07F E080 E081 E082 E083 E084 E085 E086 group=CCCCCCCC +0xFF +kern -liga E07F E080 E081 E082 E083 E084 E085 E086 => E07F E080 E081 E082 E083 E084 E085 E086 group=CCCCCCCC +=== font characters 18 === +0xFF E087 E088 E089 E08A E08B E08C E08D E08E => E087 E088 E089 E08A E08B E08C E08D E08E group=CCCCCCCC +0x80 E087 E088 E089 E08A E08B E08C E08D E08E => E087 E088 E089 E08A E08B E08C E08D E08E group=CCCCCCCC +0xFF +kern -liga E087 E088 E089 E08A E08B E08C E08D E08E => E087 E088 E089 E08A E08B E08C E08D E08E group=CCCCCCCC +=== font characters 19 === +0xFF E08F E090 E091 E092 E093 E094 E095 E096 => E08F E090 E091 E092 E093 E094 E095 E096 group=CCCCCCCC +0x80 E08F E090 E091 E092 E093 E094 E095 E096 => E08F E090 E091 E092 E093 E094 E095 E096 group=CCCCCCCC +0xFF +kern -liga E08F E090 E091 E092 E093 E094 E095 E096 => E08F E090 E091 E092 E093 E094 E095 E096 group=CCCCCCCC +=== font characters 20 === +0xFF E097 E098 E099 E09A E09B E09C E09D E09E => E097 E098 E099 E09A E09B E09C E09D E09E group=CCCCCCCC +0x80 E097 E098 E099 E09A E09B E09C E09D E09E => E097 E098 E099 E09A E09B E09C E09D E09E group=CCCCCCCC +0xFF +kern -liga E097 E098 E099 E09A E09B E09C E09D E09E => E097 E098 E099 E09A E09B E09C E09D E09E group=CCCCCCCC +=== font characters 21 === +0xFF E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 => E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 group=CCCCCCCC +0x80 E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 => E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 group=CCCCCCCC +0xFF +kern -liga E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 => E09F E0A0 E0A1 E0A2 E0A3 E0A4 E0A5 E0A6 group=CCCCCCCC +=== font characters 22 === +0xFF E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE => E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE group=CCCCCCCC +0x80 E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE => E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE group=CCCCCCCC +0xFF +kern -liga E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE => E0A7 E0A8 E0A9 E0AA E0AB E0AC E0AD E0AE group=CCCCCCCC +=== font characters 23 === +0xFF E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 => E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 group=CCCCCCCC +0x80 E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 => E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 group=CCCCCCCC +0xFF +kern -liga E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 => E0AF E0B0 E0B1 E0B2 E0B3 E0B4 E0B5 E0B6 group=CCCCCCCC diff --git a/tests/data/shaping/NotoSansArabic-GSUB11Wrap-Synthetic.txt b/tests/data/shaping/NotoSansArabic-GSUB11Wrap-Synthetic.txt new file mode 100644 index 000000000..35de6e2c5 --- /dev/null +++ b/tests/data/shaping/NotoSansArabic-GSUB11Wrap-Synthetic.txt @@ -0,0 +1,184 @@ +=== latin === +0xFF 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0x80 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0xFF +kern -liga 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +=== cyrillic === +0xFF 0416 0430 0439 => 0416 0430 0439 group=CCC +0x80 0416 0430 0439 => 0416 0430 0439 group=CCC +0xFF +kern -liga 0416 0430 0439 => 0416 0430 0439 group=CCC +=== greek === +0xFF 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0x80 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0xFF +kern -liga 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +=== hiragana === +0xFF 3042 3043 3044 => 3042 3043 3044 group=CCC +0x80 3042 3043 3044 => 3042 3043 3044 group=CCC +0xFF +kern -liga 3042 3043 3044 => 3042 3043 3044 group=CCC +=== arabic === +0xFF 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 E000 group=CCCCC gpos={"1":{"kashida":8},"4":{"kashida":2}} +0x80 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 E000 group=CCCCC gpos={"1":{"kashida":8},"4":{"kashida":2}} +0xFF +kern -liga 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 E000 group=CCCCC gpos={"1":{"kashida":8},"4":{"kashida":2}} +=== syriac === +0xFF 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0x80 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0xFF +kern -liga 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +=== nko === +0xFF 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0x80 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0xFF +kern -liga 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +=== devanagari === +0xFF 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0x80 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0xFF +kern -liga 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +=== bengali === +0xFF 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0x80 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0xFF +kern -liga 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +=== gurmukhi === +0xFF 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0x80 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0xFF +kern -liga 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +=== tamil === +0xFF 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0x80 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0xFF +kern -liga 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +=== malayalam === +0xFF 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0x80 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0xFF +kern -liga 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +=== sinhala === +0xFF 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0x80 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0xFF +kern -liga 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +=== khmer === +0xFF 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0x80 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0xFF +kern -liga 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +=== thai === +0xFF 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0x80 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0xFF +kern -liga 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +=== lao === +0xFF 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0x80 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0xFF +kern -liga 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +=== myanmar === +0xFF 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0x80 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0xFF +kern -liga 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +=== new tai lue === +0xFF 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0x80 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0xFF +kern -liga 1980 19B0 1981 => 1980 19B0 1981 group=CCC +=== cham === +0xFF AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0x80 AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0xFF +kern -liga AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +=== tai tham === +0xFF 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0x80 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0xFF +kern -liga 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +=== mixed scripts === +0xFF 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0x80 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0xFF +kern -liga 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +=== spaced === +0xFF 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0x80 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0xFF +kern -liga 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +=== font characters 0 === +0xFF 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 => 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 group=SCCCCCCC +0x80 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 => 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 group=SCCCCCCC +0xFF +kern -liga 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 => 0020 4EA7 4F51 4FFB 50A5 514F 51F9 52A3 group=SCCCCCCC +=== font characters 1 === +0xFF 534D 53F7 54A1 554B 55F5 569F 5749 57F3 => 534D 53F7 54A1 554B 55F5 569F 5749 57F3 group=CCCCCCCC +0x80 534D 53F7 54A1 554B 55F5 569F 5749 57F3 => 534D 53F7 54A1 554B 55F5 569F 5749 57F3 group=CCCCCCCC +0xFF +kern -liga 534D 53F7 54A1 554B 55F5 569F 5749 57F3 => 534D 53F7 54A1 554B 55F5 569F 5749 57F3 group=CCCCCCCC +=== font characters 2 === +0xFF 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 => 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 group=CCCCCCCC +0x80 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 => 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 group=CCCCCCCC +0xFF +kern -liga 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 => 589D 5947 59F1 5A9B 5B45 5BEF 5C99 5D43 group=CCCCCCCC +=== font characters 3 === +0xFF 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 => 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 group=CCCCCCCC +0x80 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 => 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 group=CCCCCCCC +0xFF +kern -liga 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 => 5DED 5E97 5F41 5FEB 6095 613F 61E9 6293 group=CCCCCCCC +=== font characters 4 === +0xFF 633D 63E7 6491 653B 65E5 668F 6739 67E3 => 633D 63E7 6491 653B 65E5 668F 6739 67E3 group=CCCCCCCC +0x80 633D 63E7 6491 653B 65E5 668F 6739 67E3 => 633D 63E7 6491 653B 65E5 668F 6739 67E3 group=CCCCCCCC +0xFF +kern -liga 633D 63E7 6491 653B 65E5 668F 6739 67E3 => 633D 63E7 6491 653B 65E5 668F 6739 67E3 group=CCCCCCCC +=== font characters 5 === +0xFF 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 => 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 group=CCCCCCCC +0x80 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 => 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 group=CCCCCCCC +0xFF +kern -liga 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 => 688D 6937 69E1 6A8B 6B35 6BDF 6C89 6D33 group=CCCCCCCC +=== font characters 6 === +0xFF 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 => 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 group=CCCCCCCC +0x80 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 => 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 group=CCCCCCCC +0xFF +kern -liga 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 => 6DDD 6E87 6F31 6FDB 7085 712F 71D9 7283 group=CCCCCCCC +=== font characters 7 === +0xFF 732D 73D7 7481 752B 75D5 767F 7729 77D3 => 732D 73D7 7481 752B 75D5 767F 7729 77D3 group=CCCCCCCC +0x80 732D 73D7 7481 752B 75D5 767F 7729 77D3 => 732D 73D7 7481 752B 75D5 767F 7729 77D3 group=CCCCCCCC +0xFF +kern -liga 732D 73D7 7481 752B 75D5 767F 7729 77D3 => 732D 73D7 7481 752B 75D5 767F 7729 77D3 group=CCCCCCCC +=== font characters 8 === +0xFF 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 => 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 group=CCCCCCCC +0x80 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 => 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 group=CCCCCCCC +0xFF +kern -liga 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 => 787D 7927 79D1 7A7B 7B25 7BCF 7C79 7D23 group=CCCCCCCC +=== font characters 9 === +0xFF 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 => 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 group=CCCCCCCC +0x80 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 => 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 group=CCCCCCCC +0xFF +kern -liga 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 => 7DCD 7E77 7F21 7FCB 8075 811F 81C9 8273 group=CCCCCCCC +=== font characters 10 === +0xFF 831D 83C7 8471 851B 85C5 866F 8719 87C3 => 831D 83C7 8471 851B 85C5 866F 8719 87C3 group=CCCCCCCC +0x80 831D 83C7 8471 851B 85C5 866F 8719 87C3 => 831D 83C7 8471 851B 85C5 866F 8719 87C3 group=CCCCCCCC +0xFF +kern -liga 831D 83C7 8471 851B 85C5 866F 8719 87C3 => 831D 83C7 8471 851B 85C5 866F 8719 87C3 group=CCCCCCCC +=== font characters 11 === +0xFF 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 => 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 group=CCCCCCCC +0x80 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 => 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 group=CCCCCCCC +0xFF +kern -liga 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 => 886D 8917 89C1 8A6B 8B15 8BBF 8C69 8D13 group=CCCCCCCC +=== font characters 12 === +0xFF 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 => 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 group=CCCCCCCC +0x80 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 => 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 group=CCCCCCCC +0xFF +kern -liga 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 => 8DBD 8E67 8F11 8FBB 9065 910F 91B9 9263 group=CCCCCCCC +=== font characters 13 === +0xFF 930D 93B7 9461 950B 95B5 965F 9709 97B3 => 930D 93B7 9461 950B 95B5 965F 9709 97B3 group=CCCCCCCC +0x80 930D 93B7 9461 950B 95B5 965F 9709 97B3 => 930D 93B7 9461 950B 95B5 965F 9709 97B3 group=CCCCCCCC +0xFF +kern -liga 930D 93B7 9461 950B 95B5 965F 9709 97B3 => 930D 93B7 9461 950B 95B5 965F 9709 97B3 group=CCCCCCCC +=== font characters 14 === +0xFF 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 => 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 group=CCCCCCCC +0x80 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 => 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 group=CCCCCCCC +0xFF +kern -liga 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 => 985D 9907 99B1 9A5B 9B05 9BAF 9C59 9D03 group=CCCCCCCC +=== font characters 15 === +0xFF 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 => 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 group=CCCCCCCC +0x80 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 => 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 group=CCCCCCCC +0xFF +kern -liga 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 => 9DAD 9E57 9F01 9FAB A055 A0FF A1A9 A253 group=CCCCCCCC +=== font characters 16 === +0xFF A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 => A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 group=CCCCCCCC +0x80 A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 => A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 group=CCCCCCCC +0xFF +kern -liga A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 => A2FD A3A7 A451 A4FB A5A5 A64F A6F9 A7A3 group=CCCCCCCC +=== font characters 17 === +0xFF A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 => A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 group=CCCCCCCC +0x80 A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 => A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 group=CCCCCCCC +0xFF +kern -liga A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 => A84D A8F7 A9A1 AA4B AAF5 AB9F AC49 ACF3 group=CCCCCCCC +=== font characters 18 === +0xFF AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 => AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 group=CCCCCCCC +0x80 AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 => AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 group=CCCCCCCC +0xFF +kern -liga AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 => AD9D AE47 AEF1 AF9B B045 B0EF B199 B243 group=CCCCCCCC +=== font characters 19 === +0xFF B2ED B397 B441 B4EB B595 B63F B6E9 B793 => B2ED B397 B441 B4EB B595 B63F B6E9 B793 group=CCCCCCCC +0x80 B2ED B397 B441 B4EB B595 B63F B6E9 B793 => B2ED B397 B441 B4EB B595 B63F B6E9 B793 group=CCCCCCCC +0xFF +kern -liga B2ED B397 B441 B4EB B595 B63F B6E9 B793 => B2ED B397 B441 B4EB B595 B63F B6E9 B793 group=CCCCCCCC +=== font characters 20 === +0xFF B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 => B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 group=CCCCCCCC +0x80 B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 => B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 group=CCCCCCCC +0xFF +kern -liga B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 => B83D B8E7 B991 BA3B BAE5 BB8F BC39 BCE3 group=CCCCCCCC +=== font characters 21 === +0xFF BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 => BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 group=CCCCCCCC +0x80 BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 => BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 group=CCCCCCCC +0xFF +kern -liga BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 => BD8D BE37 BEE1 BF8B C035 C0DF C189 C233 group=CCCCCCCC +=== font characters 22 === +0xFF C2DD C387 C431 C4DB C585 C62F C6D9 C783 => C2DD C387 C431 C4DB C585 C62F C6D9 C783 group=CCCCCCCC +0x80 C2DD C387 C431 C4DB C585 C62F C6D9 C783 => C2DD C387 C431 C4DB C585 C62F C6D9 C783 group=CCCCCCCC +0xFF +kern -liga C2DD C387 C431 C4DB C585 C62F C6D9 C783 => C2DD C387 C431 C4DB C585 C62F C6D9 C783 group=CCCCCCCC +=== font characters 23 === +0xFF C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 => C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 group=CCCCCCCC +0x80 C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 => C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 group=CCCCCCCC +0xFF +kern -liga C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 => C82D C8D7 C981 CA2B CAD5 CB7F CC29 CCD3 group=CCCCCCCC diff --git a/tests/data/shaping/SedanSC-EmptyFeature-Subset.txt b/tests/data/shaping/SedanSC-EmptyFeature-Subset.txt new file mode 100644 index 000000000..be8834bae --- /dev/null +++ b/tests/data/shaping/SedanSC-EmptyFeature-Subset.txt @@ -0,0 +1,92 @@ +=== latin === +0xFF 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 E000 0072 group=CCCCCC +0x80 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 0061 0072 group=CCCCCC +0xFF +kern -liga 0041 0056 0041 0054 0061 0072 => 0041 0056 0041 0054 E000 0072 group=CCCCCC +=== cyrillic === +0xFF 0416 0430 0439 => 0416 0430 0439 group=CCC +0x80 0416 0430 0439 => 0416 0430 0439 group=CCC +0xFF +kern -liga 0416 0430 0439 => 0416 0430 0439 group=CCC +=== greek === +0xFF 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0x80 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +0xFF +kern -liga 03B1 03B2 03C2 => 03B1 03B2 03C2 group=CCC +=== hiragana === +0xFF 3042 3043 3044 => 3042 3043 3044 group=CCC +0x80 3042 3043 3044 => 3042 3043 3044 group=CCC +0xFF +kern -liga 3042 3043 3044 => 3042 3043 3044 group=CCC +=== arabic === +0xFF 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0x80 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0xFF +kern -liga 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +=== syriac === +0xFF 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0x80 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +0xFF +kern -liga 0710 0712 0713 0715 => 0710 0712 0713 0715 group=CCCC +=== nko === +0xFF 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0x80 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +0xFF +kern -liga 07CA 07CB 07CC => 07CA 07CB 07CC group=CCC +=== devanagari === +0xFF 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0x80 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +0xFF +kern -liga 0915 094D 0937 093F => 0915 094D 093F 0937 group=CCCC +=== bengali === +0xFF 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0x80 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +0xFF +kern -liga 0995 09CD 09B7 09BF => 0995 09CD 09BF 09B7 group=CCCC +=== gurmukhi === +0xFF 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0x80 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +0xFF +kern -liga 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A3F 0A38 group=CCCC +=== tamil === +0xFF 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0x80 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +0xFF +kern -liga 0B95 0BCD 0BB7 0BBF => 0B95 0BCD 0BB7 0BBF group=CCCC +=== malayalam === +0xFF 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0x80 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +0xFF +kern -liga 0D15 0D4D 0D37 0D3F => 0D15 0D4D 0D37 0D3F group=CCCC +=== sinhala === +0xFF 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0x80 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +0xFF +kern -liga 0D9A 0DCA 0DBB 0DBB => 0D9A 0DCA 0DBB 0DBB group=CCCC +=== khmer === +0xFF 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0x80 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +0xFF +kern -liga 1780 17D2 1781 17C1 => 17C1 1780 17D2 1781 group=CCCC +=== thai === +0xFF 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0x80 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +0xFF +kern -liga 0E01 0E34 0E48 0E23 => 0E01 0E34 0E48 0E23 group=CCCC +=== lao === +0xFF 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0x80 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +0xFF +kern -liga 0E81 0EB4 0E8D => 0E81 0EB4 0E8D group=CCC +=== myanmar === +0xFF 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0x80 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +0xFF +kern -liga 1000 103A 1039 1001 => 1000 103A 1039 1001 group=CCCC +=== new tai lue === +0xFF 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0x80 1980 19B0 1981 => 1980 19B0 1981 group=CCC +0xFF +kern -liga 1980 19B0 1981 => 1980 19B0 1981 group=CCC +=== cham === +0xFF AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0x80 AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +0xFF +kern -liga AA00 AA33 AA01 => AA00 AA33 AA01 group=CCC +=== tai tham === +0xFF 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0x80 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +0xFF +kern -liga 1A20 1A60 1A21 => 1A20 1A60 1A21 group=CCC +=== mixed scripts === +0xFF 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0x80 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +0xFF +kern -liga 0041 0628 0915 0042 => 0041 0628 0915 0042 group=CCCC +=== spaced === +0xFF 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0x80 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +0xFF +kern -liga 0041 0020 0628 0020 0042 => 0041 0020 0628 0020 0042 group=CSCSC +=== font characters 0 === +0xFF 0020 0041 0042 0061 0062 E000 E001 E002 => 0020 0041 0042 E000 E001 E000 E001 E002 group=SCCCCCCC +0x80 0020 0041 0042 0061 0062 E000 E001 E002 => 0020 0041 0042 0061 0062 E000 E001 E002 group=SCCCCCCC +0xFF +kern -liga 0020 0041 0042 0061 0062 E000 E001 E002 => 0020 0041 0042 E000 E001 E000 E001 E002 group=SCCCCCCC gpos={"6":{"XAdvanceL":-40,"XAdvanceR":-40}} diff --git a/tests/data/subset/Carlito-MarkAttachmentType-Subset.json b/tests/data/subset/Carlito-MarkAttachmentType-Subset.json new file mode 100644 index 000000000..f395565dd --- /dev/null +++ b/tests/data/subset/Carlito-MarkAttachmentType-Subset.json @@ -0,0 +1,141 @@ +{ + "_": "Generated by composer subset:update. See tests/Mpdf/Fonts/SubsetGoldenMaster.php.", + "useOTL=0x00": { + "characters": 5, + "makeSubset": { + "bytes": 4540, + "sha256": "c2a9b378305be0b8ebd27810ac8e9f6c95a44b164ca6b9a42f36c326a9c103ae", + "tables": { + "OS/2": "96 bytes, checksum 0x78D79A16, sha256 fd5f0101bc702aa5db66a77d6e7c85900cc984770e380f38af3db363c459e218", + "cmap": "96 bytes, checksum 0xFDBC06AE, sha256 0da3b7508e72c4aeb630d0ac86d6addf710ec8dffeffe142fe10aab0f4e92118", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "592 bytes, checksum 0x0D1B0968, sha256 dbced69058b90d0fc7277a30c174ab7aee97ad0f7c4ca3052c61c39c4dda841d", + "head": "54 bytes, checksum 0x0B117750, sha256 52297c13fa9f20fb8cb5d93a42ab73d6a108e236aa40aafbfc4423327be1234b", + "hhea": "36 bytes, checksum 0x0CE600A0, sha256 1385b89dfcc664468b95b65199384412061d94930da35299ed941d4c39535cde", + "hmtx": "40 bytes, checksum 0x16970162, sha256 87b33daa5cfc2ae71c6b8d4085d1ac205101733c6b5723f13b1cd6f70d819c11", + "loca": "22 bytes, checksum 0x02A2020A, sha256 56c2af74f2ee27b0633ed290f441ed8dd553093ac9141feb2903d4f8dc678556", + "maxp": "32 bytes, checksum 0x01D50C56, sha256 a7b58a79501f2224181dc424ec4012f5a01879d92bf0ecfba651e234f25634ff", + "name": "422 bytes, checksum 0x243C3B06, sha256 cc80a1a66d20a8ba6e26ace0f2e892d8d12f6f3c5f550216962bb98cae10111e", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUni": 65535, + "defaultWidth": 1038, + "codeToGlyph": "5 entries, sha256 71485bf2795e5d26b6698ee3cddc1fe155ef71a1d28bcf372975773b74d1480c" + }, + "makeSubsetSIP": { + "bytes": 4536, + "sha256": "ebf37bc7663172cf1b91f617c621e9b36488716af16367fc5682f6a45b495a1c", + "tables": { + "OS/2": "96 bytes, checksum 0x78620F03, sha256 f95fc5c29593446c6760743556656e96bdb775013cb1f90ea9124123163c1990", + "cmap": "92 bytes, checksum 0x00300094, sha256 48cd1bfd713cfcc3cf1619bbfb08e9a4f8ad39538efb1fde30edfb0829efb5b0", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "592 bytes, checksum 0x0D1B0968, sha256 dbced69058b90d0fc7277a30c174ab7aee97ad0f7c4ca3052c61c39c4dda841d", + "head": "54 bytes, checksum 0x0B117750, sha256 5d6f095f264c5879eb075e003eb608da8a22768026a16ecd19d9cb4e98649f77", + "hhea": "36 bytes, checksum 0x0CE600A0, sha256 1385b89dfcc664468b95b65199384412061d94930da35299ed941d4c39535cde", + "hmtx": "40 bytes, checksum 0x16970162, sha256 87b33daa5cfc2ae71c6b8d4085d1ac205101733c6b5723f13b1cd6f70d819c11", + "loca": "22 bytes, checksum 0x02A2020A, sha256 56c2af74f2ee27b0633ed290f441ed8dd553093ac9141feb2903d4f8dc678556", + "maxp": "32 bytes, checksum 0x01D50C56, sha256 a7b58a79501f2224181dc424ec4012f5a01879d92bf0ecfba651e234f25634ff", + "name": "422 bytes, checksum 0x24353B06, sha256 fea5ba1e0769be1c90a1e805a45f36d3da6989673d4594c3af8ae3090f994af3", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUniChar": 65535, + "defaultWidth": 1038 + }, + "repackageTTF": { + "bytes": 5164, + "sha256": "2b46607d317a6a670944585cdf3a13d8e0c0141bcdd4fc090def6186051ba8c3", + "tables": { + "OS/2": "96 bytes, checksum 0x78D79A16, sha256 fd5f0101bc702aa5db66a77d6e7c85900cc984770e380f38af3db363c459e218", + "cmap": "72 bytes, checksum 0x00870413, sha256 1023fac740fbdf91b259632bfab37d8ff7bafe823c93c761e45606b9a6865bd6", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1224 bytes, checksum 0x4CA9D281, sha256 70b9e2281ef31ba5098f76fcc9106a9e48b39c6be98db67f15b72d6f7a311cbe", + "head": "54 bytes, checksum 0x0B117750, sha256 af94f3a11e43a8378a3d381833bb32f93c34226bb8c66963e065e3e7de0d59a5", + "hhea": "36 bytes, checksum 0x0CE600A3, sha256 0b205b836c82a46e063393e057eac95fa9834e7ef3383141b559db65266461ab", + "hmtx": "52 bytes, checksum 0x1D850245, sha256 e1c3c5eac66ce3b48f052b0a0c47a8a98c26f70e1cdaba80f37de1221a3cb1f6", + "loca": "28 bytes, checksum 0x0708089A, sha256 3c76f17baead2d341af2bb63328f428045ddb091108e3c0d96b6eb060f7a293d", + "maxp": "32 bytes, checksum 0x01D80C56, sha256 5ba32950076f5fe3d1199fd95f3259bb5fb841dcbcbdf1df45ee6534e2589d7e", + "name": "422 bytes, checksum 0x243C3B06, sha256 cc80a1a66d20a8ba6e26ace0f2e892d8d12f6f3c5f550216962bb98cae10111e", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUni": 0 + } + }, + "useOTL=0xFF": { + "characters": 13, + "makeSubset": { + "bytes": 5240, + "sha256": "3c1bf9749af45e95877bb3016ac42c3996924d0bdbe2fb305f0908172431a9b7", + "tables": { + "OS/2": "96 bytes, checksum 0x78D79A16, sha256 fd5f0101bc702aa5db66a77d6e7c85900cc984770e380f38af3db363c459e218", + "cmap": "144 bytes, checksum 0x06C49EBA, sha256 80182390f0150f7632b5139fe6fd3a857768cb4d0906f93e6a23fdca70bb1c2d", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1228 bytes, checksum 0x84039B25, sha256 f9e48d85dc64ac1df33fa668d6ecb2069e86b868569f802385f46c5f4c060e06", + "head": "54 bytes, checksum 0x0B117750, sha256 ecd32f00229cc26ff11c70614f94563e20c1b029327c0d6d0f2c4bfbfd6ec6c2", + "hhea": "36 bytes, checksum 0x0CE600A3, sha256 0b205b836c82a46e063393e057eac95fa9834e7ef3383141b559db65266461ab", + "hmtx": "52 bytes, checksum 0x1D850245, sha256 e1c3c5eac66ce3b48f052b0a0c47a8a98c26f70e1cdaba80f37de1221a3cb1f6", + "loca": "28 bytes, checksum 0x070C08A0, sha256 a64bc1e83d6dbef5b62805efd44a4af82040d5c820f41a36cf1907ba7bcc6da6", + "maxp": "32 bytes, checksum 0x01D80C56, sha256 5ba32950076f5fe3d1199fd95f3259bb5fb841dcbcbdf1df45ee6534e2589d7e", + "name": "422 bytes, checksum 0x243C3B06, sha256 cc80a1a66d20a8ba6e26ace0f2e892d8d12f6f3c5f550216962bb98cae10111e", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUni": 65535, + "defaultWidth": 1038, + "codeToGlyph": "13 entries, sha256 d382373a79b85a6555735fe10f8b56a1d75a783f6a4d5a3c080097e16acd1bd3" + }, + "makeSubsetSIP": { + "bytes": 5220, + "sha256": "c17db14748a904a3e2cbb3ba8173f78041d4fb244afcae2fe43cf31cf2d23bd7", + "tables": { + "OS/2": "96 bytes, checksum 0x78620F0B, sha256 cee942d42ecacec7fa716a9426c449518164cf981baf0610fcee0ab2ea7c8b66", + "cmap": "124 bytes, checksum 0x008C00FB, sha256 6b9156b829c8b5c71b6ee076927a6edf575a9969ee70c18af60f170b8d0dbdb1", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1228 bytes, checksum 0x84069B28, sha256 6cde1ad6a24a3c4b2a71e31b879d71d8bd515ea36eca6ad23760e52b4ff6ab5e", + "head": "54 bytes, checksum 0x0B117750, sha256 467e33e15e18c3b149a71ade184f4b70ea4e4436c144f4f1f061d2313c31a9f0", + "hhea": "36 bytes, checksum 0x0CE600A3, sha256 0b205b836c82a46e063393e057eac95fa9834e7ef3383141b559db65266461ab", + "hmtx": "52 bytes, checksum 0x1D850245, sha256 814b648e96ab77417424e1259cc2dc46a9a739a2d6a113ccd69bbeaeee36dba0", + "loca": "28 bytes, checksum 0x067007C8, sha256 9ebef80ca31ec11c91472109080c6330e15f85f82f167e9453d2be31f648eb94", + "maxp": "32 bytes, checksum 0x01D80C56, sha256 5ba32950076f5fe3d1199fd95f3259bb5fb841dcbcbdf1df45ee6534e2589d7e", + "name": "422 bytes, checksum 0x24353B06, sha256 fea5ba1e0769be1c90a1e805a45f36d3da6989673d4594c3af8ae3090f994af3", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUniChar": 65535, + "defaultWidth": 1038 + }, + "repackageTTF": { + "bytes": 5228, + "sha256": "6de0498c902df420e1d939dda282ea394192d84d4d7f2cb9184d3d67befdb369", + "tables": { + "OS/2": "96 bytes, checksum 0x78D79A16, sha256 fd5f0101bc702aa5db66a77d6e7c85900cc984770e380f38af3db363c459e218", + "cmap": "134 bytes, checksum 0xE3D3C19E, sha256 bc6adace54e90c1fa5c672f99263f19b23d77e5a8505d808a25ea7784d4200d0", + "cvt ": "56 bytes, checksum 0x25FE01C2, sha256 e3db322ed3df4de6b36549931ce7f6d0935bacdc92a6821bf6e3c2a670046610", + "fpgm": "2677 bytes, checksum 0xDBB62E8C, sha256 3714687bfb8520386d0219ded888a94f719555081ce5c58fe6c86524202cf458", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1224 bytes, checksum 0x4CA9D281, sha256 70b9e2281ef31ba5098f76fcc9106a9e48b39c6be98db67f15b72d6f7a311cbe", + "head": "54 bytes, checksum 0x0B117750, sha256 67631db3089b53fb31279345d1afdf6dd53f1a776df9ec10c651ba3d3112b361", + "hhea": "36 bytes, checksum 0x0CE600A3, sha256 0b205b836c82a46e063393e057eac95fa9834e7ef3383141b559db65266461ab", + "hmtx": "52 bytes, checksum 0x1D850245, sha256 e1c3c5eac66ce3b48f052b0a0c47a8a98c26f70e1cdaba80f37de1221a3cb1f6", + "loca": "28 bytes, checksum 0x0708089A, sha256 3c76f17baead2d341af2bb63328f428045ddb091108e3c0d96b6eb060f7a293d", + "maxp": "32 bytes, checksum 0x01D80C56, sha256 5ba32950076f5fe3d1199fd95f3259bb5fb841dcbcbdf1df45ee6534e2589d7e", + "name": "422 bytes, checksum 0x243C3B06, sha256 cc80a1a66d20a8ba6e26ace0f2e892d8d12f6f3c5f550216962bb98cae10111e", + "post": "32 bytes, checksum 0xFF9C00C2, sha256 5755f0a5cfde4cfda9160c38cbdb686eeefdf4708193f4fd81fce8f81dc682eb", + "prep": "129 bytes, checksum 0x9A783A38, sha256 3ef25e2da89a077e0fc85664b659aa52f31c8334ee7bdd299f575504f60a3c8d" + }, + "maxUni": 0 + } + } +} diff --git a/tests/data/subset/Molengo-GSUB52Class0-Subset.json b/tests/data/subset/Molengo-GSUB52Class0-Subset.json new file mode 100644 index 000000000..41f43927e --- /dev/null +++ b/tests/data/subset/Molengo-GSUB52Class0-Subset.json @@ -0,0 +1,141 @@ +{ + "_": "Generated by composer subset:update. See tests/Mpdf/Fonts/SubsetGoldenMaster.php.", + "useOTL=0x00": { + "characters": 10, + "makeSubset": { + "bytes": 4408, + "sha256": "d434ff925f5b5bc7b2ee277121102ffc3a60d95c67dcdce00c2d9cb2ef92a252", + "tables": { + "OS/2": "96 bytes, checksum 0x75E46B84, sha256 ee253da421d103c42ca28e0e55736e74c7aea0ee78a3042e089c40f111929eda", + "cmap": "146 bytes, checksum 0x09F309B1, sha256 dc25a1342824950b062a1d1f214b2a8a71fd8af03efb69d973faf97e1c85c67f", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1136 bytes, checksum 0x5ABF546E, sha256 ea91b967956e71a295c403c71d814da74826db66a9d23d36d435fc57e465356c", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 622995b1eb60ae11221f16156b7aa7780899571793902016d71cf3213552aeea", + "hhea": "36 bytes, checksum 0x0DD10453, sha256 922c105650942e4e0eaf9fa485ff2dde7b22de7fed371ec8f51a1eaf46f329e3", + "hmtx": "64 bytes, checksum 0x1767FE0E, sha256 cff6884681b78640bd29f14bab46de0aee81c4de887f30bbc9e5c5e9b565256c", + "loca": "34 bytes, checksum 0x08640780, sha256 08bf6ca2773dcffdf4d6fdb6c747d0f493e3ae5259a4374ad021c3a3359b68a0", + "maxp": "32 bytes, checksum 0x00F5082D, sha256 aaa0db599fd3e03384b3f7c771c6ee5b38dd93b147fdbf4d106142e14e027843", + "name": "500 bytes, checksum 0x283B3F4F, sha256 900c2bc9b1ddad4fbfc9d578e9a24a116a4b63f0d08cba92077f701e74d495b6", + "post": "32 bytes, checksum 0xFF12005A, sha256 6bf3093f805df1de7c9c099e6d922957801b768518d8d0e7ed42ea6ca7131fb1", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUni": 65535, + "defaultWidth": 886, + "codeToGlyph": "10 entries, sha256 46b7126035c7f89fd0b822976b9b3539d87832080e7e3717d01f72f1b0da6863" + }, + "makeSubsetSIP": { + "bytes": 4360, + "sha256": "4a7596df688d91b5c4fc0de33b96fb8bfd8aaa9d7b4344d0842314491c6d3c57", + "tables": { + "OS/2": "96 bytes, checksum 0x7973E96B, sha256 857bd041a7023cc86c67a7c856847df9a3629243d3db298ea9767b62f9d7327c", + "cmap": "112 bytes, checksum 0x007700B7, sha256 50ee851afa0fee6e04adb5e69494254cf010dbfacf8f246ad1dfd6370e17ad5c", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1136 bytes, checksum 0x5AB35468, sha256 aee2d574dc8222aea13a0225de2e87abc872d8bc0fed225e3fc8fbdb79cbecd2", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 f5fd6c314b7896e8c06b0d6a3a45d98da85ee0537cae3eb81e504e56227a909a", + "hhea": "36 bytes, checksum 0x0DD10451, sha256 079a7765850ab9b2c5776e397439c4d02556cad3bf813b99ee9e19e7e17dcccf", + "hmtx": "56 bytes, checksum 0x1767FE0E, sha256 4f23f147875bbd70c01b6ee833f93fbf78b64fd81317493c2006867bac6628f9", + "loca": "30 bytes, checksum 0x08640780, sha256 c05cc02fb0a1f0efa65fec60686121afd60b5405e8d5424f83a5223799da15f2", + "maxp": "32 bytes, checksum 0x00F3082D, sha256 c8a0e4a3cdafd92646e4812e1f3287ef19a3ce1892960dcdf2eb5caaad737417", + "name": "500 bytes, checksum 0x28343F4F, sha256 db3212125e5b0b8277c197da6cc3141b6dd6859a49cdc5281392ec4796cad4f5", + "post": "32 bytes, checksum 0xFF12005A, sha256 6bf3093f805df1de7c9c099e6d922957801b768518d8d0e7ed42ea6ca7131fb1", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUniChar": 65535, + "defaultWidth": 886 + }, + "repackageTTF": { + "bytes": 8732, + "sha256": "836386abd9d7f8af27641affff5549d3a7ea0e20c18a77307d4de7128674a3d3", + "tables": { + "OS/2": "96 bytes, checksum 0x75E46B84, sha256 ee253da421d103c42ca28e0e55736e74c7aea0ee78a3042e089c40f111929eda", + "cmap": "108 bytes, checksum 0x0DDF0BBB, sha256 60e0acd470c74bd2a6e4b482300b92cd5bbb7b7ea4512c5b599eddec816e7080", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1122 bytes, checksum 0x59885FF8, sha256 02c08eaefbefdf5c85b0b7aefdf6a889c3d82464b2429c1879550d5d3240417a", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 a8935390d69e563055487dcccbcd0948409f53dee7e421d69dc7abcffc7a6809", + "hhea": "36 bytes, checksum 0x0DD105B8, sha256 56118c1064548c884609deb6648aadc12d81c8c221e77982d6a2c8d5b4cafaf5", + "hmtx": "1492 bytes, checksum 0x1767FE0E, sha256 32c288ccca35fb8a50357ab3189eaa257aa81bc10056b9b36cadd162c8fb9239", + "loca": "748 bytes, checksum 0x99F49B69, sha256 d1393554612c6569f844c23854102130953b21a55603c7d46b374ffac2f6a8e2", + "maxp": "32 bytes, checksum 0x025A082D, sha256 36f47c6798b386499c18b76a4a79bbe305d0281d83b93973f86f34b0748c3975", + "name": "500 bytes, checksum 0x283B3F4F, sha256 900c2bc9b1ddad4fbfc9d578e9a24a116a4b63f0d08cba92077f701e74d495b6", + "post": "2268 bytes, checksum 0xEF711D54, sha256 24460e5d3c428404998920f40ccee7e35dd55d8e8e8cdc4d725c09ab79b1f035", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUni": 0 + } + }, + "useOTL=0xFF": { + "characters": 373, + "makeSubset": { + "bytes": 7344, + "sha256": "1f353358babe08cd8fcc3352ede8058842524f08d2700547c9b361f32054f0d7", + "tables": { + "OS/2": "96 bytes, checksum 0x75E46B84, sha256 ee253da421d103c42ca28e0e55736e74c7aea0ee78a3042e089c40f111929eda", + "cmap": "944 bytes, checksum 0x3BD3DD9F, sha256 f759f3d554728f8c8724b8b0c8ad8be2ff059ff3295aa0a6c3777626372b9ba7", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1136 bytes, checksum 0x6215576C, sha256 d26907d63c4476faddcf42bf6551e421ba45a1c3a5cb57bf352330c40e72701a", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 dfdf533c2b8bc7d166048bcb60acc340c77c35335ae2b5d1e0c98f409e2465d9", + "hhea": "36 bytes, checksum 0x0DD105B8, sha256 56118c1064548c884609deb6648aadc12d81c8c221e77982d6a2c8d5b4cafaf5", + "hmtx": "1492 bytes, checksum 0x1767FE0E, sha256 32c288ccca35fb8a50357ab3189eaa257aa81bc10056b9b36cadd162c8fb9239", + "loca": "748 bytes, checksum 0x9BEA9D64, sha256 6d0a1eba9dfb620a1468dad795d45563cb72860581e41dc61d5e38777f12151a", + "maxp": "32 bytes, checksum 0x025A082D, sha256 36f47c6798b386499c18b76a4a79bbe305d0281d83b93973f86f34b0748c3975", + "name": "500 bytes, checksum 0x283B3F4F, sha256 900c2bc9b1ddad4fbfc9d578e9a24a116a4b63f0d08cba92077f701e74d495b6", + "post": "32 bytes, checksum 0xFF12005A, sha256 6bf3093f805df1de7c9c099e6d922957801b768518d8d0e7ed42ea6ca7131fb1", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUni": 65535, + "defaultWidth": 886, + "codeToGlyph": "373 entries, sha256 b007c346a8ff05c7f81c3e3ea579513c0961b9725043b481b10f59a6cfb92980" + }, + "makeSubsetSIP": { + "bytes": 7964, + "sha256": "b5a85a113f4bcb98395b52ec3ae1d41278f6854440878a56053fdf1a90940778", + "tables": { + "OS/2": "96 bytes, checksum 0x7973EAD6, sha256 4e4f05d2493e53fbe192fff81b8c4905e67a5e54abb5cc5cc82c98d1e6a36224", + "cmap": "1564 bytes, checksum 0x137916B7, sha256 af46ad33374ad0d645701c4238f4a456621d4c3285f1470163f1641b6021e077", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1136 bytes, checksum 0x5EF15778, sha256 f39e3a3df0249ef7ccfec98143140ee3bdbf4ef31317e1d587159780466e472e", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 9a3ea3fd1d30f1f67121a5ab6a48f0b045b6adbc6693e47f554428c7f9ec3d8a", + "hhea": "36 bytes, checksum 0x0DD105B8, sha256 56118c1064548c884609deb6648aadc12d81c8c221e77982d6a2c8d5b4cafaf5", + "hmtx": "1492 bytes, checksum 0x1767FE0E, sha256 d3b8fcd789415dae1dbf22a5b261b6d65fdb9d2bf06b29bb2c7938a551863c4e", + "loca": "748 bytes, checksum 0x51915332, sha256 e5848f01b125cd1641a5851fca26b7c2014e4667f4feba56e2f2622017774d5c", + "maxp": "32 bytes, checksum 0x025A082D, sha256 36f47c6798b386499c18b76a4a79bbe305d0281d83b93973f86f34b0748c3975", + "name": "500 bytes, checksum 0x28343F4F, sha256 db3212125e5b0b8277c197da6cc3141b6dd6859a49cdc5281392ec4796cad4f5", + "post": "32 bytes, checksum 0xFF12005A, sha256 6bf3093f805df1de7c9c099e6d922957801b768518d8d0e7ed42ea6ca7131fb1", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUniChar": 65535, + "defaultWidth": 886 + }, + "repackageTTF": { + "bytes": 9560, + "sha256": "4233126bb7bf1895dff7e0875d5551461e1cab0d77e4913b24c93741773779cd", + "tables": { + "OS/2": "96 bytes, checksum 0x75E46B84, sha256 ee253da421d103c42ca28e0e55736e74c7aea0ee78a3042e089c40f111929eda", + "cmap": "934 bytes, checksum 0x1B2FFE36, sha256 b643c40adbaafbcff1f6bda18b078d069d5399c06c3b203d76b41aa0c5468228", + "cvt ": "48 bytes, checksum 0x17FD0532, sha256 44c0dafeb26a8bf9c71a449fed0d6b8441c94b2c894d890d7ca5a564a1955bfc", + "fpgm": "1865 bytes, checksum 0x4179FF97, sha256 829f333b3c9c7e8defe7eaaef94648ccfeccacb615ca9e5eb31c383cab31cfe1", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1122 bytes, checksum 0x59885FF8, sha256 02c08eaefbefdf5c85b0b7aefdf6a889c3d82464b2429c1879550d5d3240417a", + "head": "54 bytes, checksum 0xFCEDC3CD, sha256 6a3e99c9a95a53e80f73abe901fcd871949706e33c9a922b2efa416fa9874b8e", + "hhea": "36 bytes, checksum 0x0DD105B8, sha256 56118c1064548c884609deb6648aadc12d81c8c221e77982d6a2c8d5b4cafaf5", + "hmtx": "1492 bytes, checksum 0x1767FE0E, sha256 32c288ccca35fb8a50357ab3189eaa257aa81bc10056b9b36cadd162c8fb9239", + "loca": "748 bytes, checksum 0x99F49B69, sha256 d1393554612c6569f844c23854102130953b21a55603c7d46b374ffac2f6a8e2", + "maxp": "32 bytes, checksum 0x025A082D, sha256 36f47c6798b386499c18b76a4a79bbe305d0281d83b93973f86f34b0748c3975", + "name": "500 bytes, checksum 0x283B3F4F, sha256 900c2bc9b1ddad4fbfc9d578e9a24a116a4b63f0d08cba92077f701e74d495b6", + "post": "2268 bytes, checksum 0xEF711D54, sha256 24460e5d3c428404998920f40ccee7e35dd55d8e8e8cdc4d725c09ab79b1f035", + "prep": "111 bytes, checksum 0x7448E75E, sha256 1040160105cb46aed32c3d7aa1fe9c5badd154f5bc93c399c8110fab5d9d2e60" + }, + "maxUni": 0 + } + } +} diff --git a/tests/data/subset/NotoSansArabic-GSUB11Wrap-Synthetic.json b/tests/data/subset/NotoSansArabic-GSUB11Wrap-Synthetic.json new file mode 100644 index 000000000..76c04d2c9 --- /dev/null +++ b/tests/data/subset/NotoSansArabic-GSUB11Wrap-Synthetic.json @@ -0,0 +1,117 @@ +{ + "_": "Generated by composer subset:update. See tests/Mpdf/Fonts/SubsetGoldenMaster.php.", + "useOTL=0x00": { + "characters": 32770, + "makeSubset": { + "bytes": 263512, + "sha256": "14bf1707ac349bfb896ba2b9d57930482b19082f8750789b350b872f14a904ee", + "tables": { + "OS/2": "96 bytes, checksum 0x83C42380, sha256 a9aae6f5015b805e58965c9f49b1ce65c2952d881034ce23c9d4c1032f5eb051", + "cmap": "65634 bytes, checksum 0x243E86FA, sha256 19fe0d0e24adb3f6168a0100b630697fa7f9121038eda21c12286a4f032ba36f", + "glyf": "280 bytes, checksum 0x7E05754F, sha256 d461908c7946b227247f9d2f1e8778bc50256c2fec4da8ed71f154bb25558890", + "head": "54 bytes, checksum 0x26907313, sha256 fead9e2f48bb89e90bcd27df4072457ee92ac2b457effb04cf4d0b7315855097", + "hhea": "36 bytes, checksum 0x092E7E23, sha256 8329cfdae3620de0e031f5360e3430c500f458cb6f1dd7653f57e61fcb3f27ba", + "hmtx": "131084 bytes, checksum 0x0708010C, sha256 df6ea878c1b33df79b88ebd3619b436d12b1d08869e72923709c2f1c58378eee", + "loca": "65544 bytes, checksum 0x008B00A0, sha256 1327b121a13405755727b5d1090c0708ad357d02027efc2445a7e22d9ee4bed0", + "maxp": "32 bytes, checksum 0x80070034, sha256 e47a8c23c74980a1e15db2899d8f8313094fc8ed227fdcc274df54de08c02863", + "name": "544 bytes, checksum 0x2E3145B0, sha256 941746858bd019b7dac7e3ba9146b4d976d37b18a50da1df5ba563b152c2a773", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUni": 65535, + "defaultWidth": 600, + "codeToGlyph": "32770 entries, sha256 da9072bac1c28e45a0226ace491abec353fdb84b4ce9ecc53dbed42ef2a2cb24" + }, + "makeSubsetSIP": { + "bytes": 328960, + "sha256": "34170f0783c6fc69d8687a44da8e478058f3e3298f202b47db4536fc7790f169", + "tables": { + "OS/2": "96 bytes, checksum 0x69A35685, sha256 5215cdffe0ff65edc4fb2da4d6fe596341df5f1a6ae4cb89ac86358ef8dc904a", + "cmap": "131152 bytes, checksum 0xA03E0057, sha256 e7d4f8d9a1e95b3d97a273892cf53f170259edc9d36030218fda3077e1d7ba97", + "glyf": "216 bytes, checksum 0xDA855C9E, sha256 70e1b514e67c939fd608d245c43b114a5b2a0b10f20c9d33c0e6d86a66470f30", + "head": "54 bytes, checksum 0x26907313, sha256 bcc462f8a3511693816f063eb920d053b7f5d3c48920e728e86934bd014b4b8a", + "hhea": "36 bytes, checksum 0x092E7E22, sha256 049c5d99fe0ea7b1fa71d91e36f9ef0a0a8af5b68656025f2b936fc0ed1742e5", + "hmtx": "131080 bytes, checksum 0x04B000C4, sha256 bb03ba5b0d5186c4a3c148787895d6a764aa87986362558ef1650fc59ebd4ae1", + "loca": "65542 bytes, checksum 0x002EFFCA, sha256 0d0759c43c8d3b3caefef2858fbdb87a036e244e60326c8abe1a9f1998db3df3", + "maxp": "32 bytes, checksum 0x80060034, sha256 ca811bcca93c03ad0cab957d6fa1a8648d7e0bfb3553bd87ea1ad68b58d17e36", + "name": "544 bytes, checksum 0x2E2A45B0, sha256 072a7c05088244ee3582476baf8b33b89b6a050fdefd9907b0097437ff51f0dd", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUniChar": 65535, + "defaultWidth": 600 + }, + "repackageTTF": { + "bytes": 132404, + "sha256": "a42743bf35c8db217a8983ccdf7ebe22c8c353baa04b51f8671237d85b1991ed", + "tables": { + "OS/2": "96 bytes, checksum 0x83C42380, sha256 a9aae6f5015b805e58965c9f49b1ce65c2952d881034ce23c9d4c1032f5eb051", + "cmap": "72 bytes, checksum 0x863F54B7, sha256 770cfb6cad2f7bf7681cf721fb58ac00ec9ccc54775a2239dfc0bf3e292ea24c", + "glyf": "276 bytes, checksum 0x7E7B74DC, sha256 3453ef47e98a6dd797ae61efa604f6120f6d411cff967240e739ff499147e071", + "head": "54 bytes, checksum 0x26907313, sha256 236b71fb3e2f9e085285553c1a4a4bbeea45508b8d97a1766febf5934343483e", + "hhea": "36 bytes, checksum 0x092DFE21, sha256 9d376f195b2d98859b1d719bfb2f9e5e4b2d98559ec563e8384b293dd24ace0c", + "hmtx": "65544 bytes, checksum 0x02BE00A6, sha256 30ae8773de73e9f642e15f027b9bf7baeb83809fbc0dd0add86b566720280b69", + "loca": "65544 bytes, checksum 0xC089C09E, sha256 2071e00324c703a6fbf28d38bb05333de91b8561c0454590b04fc87f30fdfeae", + "maxp": "32 bytes, checksum 0x80070034, sha256 e47a8c23c74980a1e15db2899d8f8313094fc8ed227fdcc274df54de08c02863", + "name": "544 bytes, checksum 0x2E3145B0, sha256 941746858bd019b7dac7e3ba9146b4d976d37b18a50da1df5ba563b152c2a773", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUni": 0 + } + }, + "useOTL=0xFF": { + "characters": 32771, + "makeSubset": { + "bytes": 263520, + "sha256": "f70c7efd8ee8900041704461a6f5427f03cd00abcd640ff3159cbe2bd51578ad", + "tables": { + "OS/2": "96 bytes, checksum 0x83C42380, sha256 a9aae6f5015b805e58965c9f49b1ce65c2952d881034ce23c9d4c1032f5eb051", + "cmap": "65644 bytes, checksum 0x9221F926, sha256 de2df2502dcb2852eef7bddc8f29f79feb9f3b7aab65dd18acad7f66eacd76d6", + "glyf": "280 bytes, checksum 0x7E05754F, sha256 d461908c7946b227247f9d2f1e8778bc50256c2fec4da8ed71f154bb25558890", + "head": "54 bytes, checksum 0x26907313, sha256 1389e4b3ab304ed3f03c3818a86b609081e4307532126210e7c19812f0ad552c", + "hhea": "36 bytes, checksum 0x092E7E23, sha256 8329cfdae3620de0e031f5360e3430c500f458cb6f1dd7653f57e61fcb3f27ba", + "hmtx": "131084 bytes, checksum 0x0708010C, sha256 df6ea878c1b33df79b88ebd3619b436d12b1d08869e72923709c2f1c58378eee", + "loca": "65544 bytes, checksum 0x008B00A0, sha256 1327b121a13405755727b5d1090c0708ad357d02027efc2445a7e22d9ee4bed0", + "maxp": "32 bytes, checksum 0x80070034, sha256 e47a8c23c74980a1e15db2899d8f8313094fc8ed227fdcc274df54de08c02863", + "name": "544 bytes, checksum 0x2E3145B0, sha256 941746858bd019b7dac7e3ba9146b4d976d37b18a50da1df5ba563b152c2a773", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUni": 65535, + "defaultWidth": 600, + "codeToGlyph": "32771 entries, sha256 4a011a02c6f37e7f1e65c7c5df00ebed381b44d46a874ba77b1de0fb95bd4745" + }, + "makeSubsetSIP": { + "bytes": 329032, + "sha256": "ca4857cb1c6e949e3abadd527bbbd305735227a3b4687003115a592b23fb3f2a", + "tables": { + "OS/2": "96 bytes, checksum 0x69A35686, sha256 fe6e701dfe345fd8e63a6a8471957d43e5ea1a6de8c739be451f699bd0473cdd", + "cmap": "131156 bytes, checksum 0xE025C07E, sha256 dea42deee74fe5c203f583ff25ecf8624025afa4f908915959195d9a35bf945e", + "glyf": "280 bytes, checksum 0x7E05754F, sha256 c1e32cbca0458183228bb1d91a482d4a1215e8ba9619ccb3b6747b18f2b74d43", + "head": "54 bytes, checksum 0x26907313, sha256 b3ca160a62c62c183162040cf75e76380266183d3cb01143779910f5bdb363ee", + "hhea": "36 bytes, checksum 0x092E7E23, sha256 8329cfdae3620de0e031f5360e3430c500f458cb6f1dd7653f57e61fcb3f27ba", + "hmtx": "131084 bytes, checksum 0x0708010C, sha256 5d92708d1bad519433decc7b2644c18659e798b8ec8a287819d0d1257a32c56d", + "loca": "65544 bytes, checksum 0x002F0056, sha256 cbeee760d3efd08910014626c7f3871398d25e9bd3ff0f60366b16b59d1b420f", + "maxp": "32 bytes, checksum 0x80070034, sha256 e47a8c23c74980a1e15db2899d8f8313094fc8ed227fdcc274df54de08c02863", + "name": "544 bytes, checksum 0x2E2A45B0, sha256 072a7c05088244ee3582476baf8b33b89b6a050fdefd9907b0097437ff51f0dd", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUniChar": 65535, + "defaultWidth": 600 + }, + "repackageTTF": { + "bytes": 197968, + "sha256": "3efc4e5858d9637276367581c7a67e1d927cdf407f445eb0b367c7679f4e9f8a", + "tables": { + "OS/2": "96 bytes, checksum 0x83C42380, sha256 a9aae6f5015b805e58965c9f49b1ce65c2952d881034ce23c9d4c1032f5eb051", + "cmap": "65634 bytes, checksum 0x243F66FC, sha256 7fb9b8a01931f62b9002eecdc21a05589ef88ec6037752db02fb58dc2688d467", + "glyf": "276 bytes, checksum 0x7E7B74DC, sha256 3453ef47e98a6dd797ae61efa604f6120f6d411cff967240e739ff499147e071", + "head": "54 bytes, checksum 0x26907313, sha256 be89d5a505dcd54001764a8637a5e0cced79566c87836d875fde836d946c1414", + "hhea": "36 bytes, checksum 0x092DFE21, sha256 9d376f195b2d98859b1d719bfb2f9e5e4b2d98559ec563e8384b293dd24ace0c", + "hmtx": "65544 bytes, checksum 0x02BE00A6, sha256 30ae8773de73e9f642e15f027b9bf7baeb83809fbc0dd0add86b566720280b69", + "loca": "65544 bytes, checksum 0xC089C09E, sha256 2071e00324c703a6fbf28d38bb05333de91b8561c0454590b04fc87f30fdfeae", + "maxp": "32 bytes, checksum 0x80070034, sha256 e47a8c23c74980a1e15db2899d8f8313094fc8ed227fdcc274df54de08c02863", + "name": "544 bytes, checksum 0x2E3145B0, sha256 941746858bd019b7dac7e3ba9146b4d976d37b18a50da1df5ba563b152c2a773", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83" + }, + "maxUni": 0 + } + } +} diff --git a/tests/data/subset/SedanSC-EmptyFeature-Subset.json b/tests/data/subset/SedanSC-EmptyFeature-Subset.json new file mode 100644 index 000000000..ceec7453d --- /dev/null +++ b/tests/data/subset/SedanSC-EmptyFeature-Subset.json @@ -0,0 +1,141 @@ +{ + "_": "Generated by composer subset:update. See tests/Mpdf/Fonts/SubsetGoldenMaster.php.", + "useOTL=0x00": { + "characters": 6, + "makeSubset": { + "bytes": 6396, + "sha256": "11cb8467996c0c440f02e5915a36da445398b5d04f840874151f576bd755344d", + "tables": { + "OS/2": "96 bytes, checksum 0x5F5F5B76, sha256 cc4ad6c0e41dc604446972f590368ab428d9ad2c941312922acc9c17dda14d3e", + "cmap": "98 bytes, checksum 0x0028016C, sha256 21f95cbfea69e55f8b505c89926ba9f79ca688a848bdcb646e18648876cd9308", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1320 bytes, checksum 0x7B40DF1B, sha256 b0819e4c5dbed8a1305bf2561b901177bbd909a449e590b8868a865532023aaf", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 383de87587da6ca4ce0043d1b25a47a49bbb101281d1d7170ff93a3873b1cf42", + "hhea": "36 bytes, checksum 0x073C01D8, sha256 e9b18e8db175b148df31d63d84879346b65e2c6370dfeb2224d360499a0210f4", + "hmtx": "24 bytes, checksum 0x0C520095, sha256 2ffce9f6317c5f18156d66550dca5eaa62139b1718fb2b4d6ea524e7abb440b9", + "loca": "14 bytes, checksum 0x0544040A, sha256 abe7cb76e2ad2ffd8e78e9c8449f34113b157315dc0d19227b434d23f3ebbd1f", + "maxp": "32 bytes, checksum 0x01800FD8, sha256 027a72c2d57b6996a98befba8643ca030fe5050789c703c07c8d71cea07012a3", + "name": "482 bytes, checksum 0x26DA3F33, sha256 9a6431fdb319205c516f8ac2746e3eeead418c6a954a03b649ddc3eacbf02b6b", + "post": "32 bytes, checksum 0xFFB80032, sha256 77a232e4db6b60c21f7b76ccf821e3c80c519901f11d10efb8c8df04ca82a4e8", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUni": 65535, + "defaultWidth": 500, + "codeToGlyph": "6 entries, sha256 27503d13c6eb370e18366d20cc9675abc21d6c8ddddac6ff2c861c5c0d44acff" + }, + "makeSubsetSIP": { + "bytes": 6392, + "sha256": "d450a0f03a5e767f8882566ea3c0fd794f87cf36e5178d14cd20a71bb7e9cac8", + "tables": { + "OS/2": "96 bytes, checksum 0x653EDC1A, sha256 9160104e07c9b843fe6979036a1ec3b9b502031e34a6549a8dfb1e941a2f0d2d", + "cmap": "96 bytes, checksum 0x004F007F, sha256 588392d8cf8860afe595b2209402ddb835c17fb546a9d41e52754b1421c2b2fe", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "1320 bytes, checksum 0x7B40DF1B, sha256 b0819e4c5dbed8a1305bf2561b901177bbd909a449e590b8868a865532023aaf", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 f963458d194045550b3abc098b163379ca52d12c858520eac08bc3ac003049a5", + "hhea": "36 bytes, checksum 0x073C01D8, sha256 e9b18e8db175b148df31d63d84879346b65e2c6370dfeb2224d360499a0210f4", + "hmtx": "24 bytes, checksum 0x0C520095, sha256 4a4408dda373138cf3b85e1b5bc50aea05c97a8ba2ff86426c77ce66ade2e1dc", + "loca": "14 bytes, checksum 0x040A02B0, sha256 64d145868c12ba92ca86625b27e35c09b356cceddc9922a7c122341ab8379a37", + "maxp": "32 bytes, checksum 0x01800FD8, sha256 027a72c2d57b6996a98befba8643ca030fe5050789c703c07c8d71cea07012a3", + "name": "482 bytes, checksum 0x26D33F33, sha256 08e689f505887f14686e1200d7ca05d5e2f5dfcfd6d137a95a274b92153bff8d", + "post": "32 bytes, checksum 0xFFB80032, sha256 77a232e4db6b60c21f7b76ccf821e3c80c519901f11d10efb8c8df04ca82a4e8", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUniChar": 65535, + "defaultWidth": 500 + }, + "repackageTTF": { + "bytes": 7688, + "sha256": "061883fc9d1a39d0b9d243c566a33ae4ad3e4a798c1ea6c1d2baa654e6a0d141", + "tables": { + "OS/2": "96 bytes, checksum 0x5F5F5B76, sha256 cc4ad6c0e41dc604446972f590368ab428d9ad2c941312922acc9c17dda14d3e", + "cmap": "68 bytes, checksum 0x005D00EB, sha256 4b1175340994cbca5f116e230466c3a5a293c97bf6c232501176cfa3cf6fe72c", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "2596 bytes, checksum 0xAEE9E758, sha256 d93e16d96b6eaacecb69608ef281b6db5ed6da9be4716032abd2b152e7cd073d", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 83e09ce2983f2babfc13ccb805f4e816c139f57b245844cf7b5c050ab670df55", + "hhea": "36 bytes, checksum 0x073C01DB, sha256 4a0396d7fc07fc169ca30bfabf25c5753a9733d743a9e19a5cfe7ab402d5521c", + "hmtx": "36 bytes, checksum 0x11CC00FA, sha256 bf88d36bd5dc51e87e487d86d5975f4063b0a9e5a315f90788664a7f00a8380b", + "loca": "20 bytes, checksum 0x0B050D0D, sha256 5c8231a6bad4dfacf454bf57603b53ad7e649fd41b5697c3baa5d5dbb03519a8", + "maxp": "32 bytes, checksum 0x01830FD8, sha256 e3a9fe933752196fb755e0adc0fdfd624263cc6fd921dd79e7e43210a80695c1", + "name": "482 bytes, checksum 0x26DA3F33, sha256 9a6431fdb319205c516f8ac2746e3eeead418c6a954a03b649ddc3eacbf02b6b", + "post": "62 bytes, checksum 0xDC8F9243, sha256 d7666fbc36debeae35b76f8a2fa860e94cbfa7ffef8a0701fbaf3ed0d3469b11", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUni": 0 + } + }, + "useOTL=0xFF": { + "characters": 9, + "makeSubset": { + "bytes": 7708, + "sha256": "e9114e5c0ebbdc17cfc71b9d3da8bfbc6534ea0192cdc3969851dc89eecb8fb2", + "tables": { + "OS/2": "96 bytes, checksum 0x5F5F5B76, sha256 cc4ad6c0e41dc604446972f590368ab428d9ad2c941312922acc9c17dda14d3e", + "cmap": "112 bytes, checksum 0xE079014A, sha256 8324f76c37d13136da2f3a9b9753616e830978d969d872853f5a1d321da06268", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "2604 bytes, checksum 0xFDEE9853, sha256 c061f5e466a1ea3ff797cb3147cbac68bd69d21700bb92a8ce0b88fe90b843f3", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 5381a291ac15be069c8265649b3a540cd8372c47987b804097ae00d8b6cb2405", + "hhea": "36 bytes, checksum 0x073C01DB, sha256 4a0396d7fc07fc169ca30bfabf25c5753a9733d743a9e19a5cfe7ab402d5521c", + "hmtx": "36 bytes, checksum 0x11CC00FA, sha256 bf88d36bd5dc51e87e487d86d5975f4063b0a9e5a315f90788664a7f00a8380b", + "loca": "20 bytes, checksum 0x0B0C0D16, sha256 173ee040c3073c3c62a09ed45db2481deda43acc6cc7e8b734ed69298dbb2c87", + "maxp": "32 bytes, checksum 0x01830FD8, sha256 e3a9fe933752196fb755e0adc0fdfd624263cc6fd921dd79e7e43210a80695c1", + "name": "482 bytes, checksum 0x26DA3F33, sha256 9a6431fdb319205c516f8ac2746e3eeead418c6a954a03b649ddc3eacbf02b6b", + "post": "32 bytes, checksum 0xFFB80032, sha256 77a232e4db6b60c21f7b76ccf821e3c80c519901f11d10efb8c8df04ca82a4e8", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUni": 65535, + "defaultWidth": 500, + "codeToGlyph": "9 entries, sha256 7bad91db95d2c06667bf276d931334fb627449ea09d18604973ae109befe86df" + }, + "makeSubsetSIP": { + "bytes": 7704, + "sha256": "e741372a0d3f8e7107a76a4fec81e55082454e59f0b7ede42122089f3270d951", + "tables": { + "OS/2": "96 bytes, checksum 0x653EDC1D, sha256 554ce119256ca51e4d7b0a178453afa831328b48da8f9fa403da882b5cd996a9", + "cmap": "108 bytes, checksum 0x005600BD, sha256 5294bf45a982e84705f3e9fb390ee1d8b211d2cc76df18225b959b8f98b66e14", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "2604 bytes, checksum 0xFDEE9853, sha256 c061f5e466a1ea3ff797cb3147cbac68bd69d21700bb92a8ce0b88fe90b843f3", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 41cb44175a8c0bb73b3ab1008320de96db0173ed8d5b4df21dc6461eb8e81f39", + "hhea": "36 bytes, checksum 0x073C01DB, sha256 4a0396d7fc07fc169ca30bfabf25c5753a9733d743a9e19a5cfe7ab402d5521c", + "hmtx": "36 bytes, checksum 0x11CC00FA, sha256 99cf9827642b44d84ef6a6979f7ac746e132e37cea80bf00f6b74c117ab2eddc", + "loca": "20 bytes, checksum 0x08000B0C, sha256 9a266d4f17b6aa97692c3cca1e4a71b16073f39405c86b9b211685afd5371734", + "maxp": "32 bytes, checksum 0x01830FD8, sha256 e3a9fe933752196fb755e0adc0fdfd624263cc6fd921dd79e7e43210a80695c1", + "name": "482 bytes, checksum 0x26D33F33, sha256 08e689f505887f14686e1200d7ca05d5e2f5dfcfd6d137a95a274b92153bff8d", + "post": "32 bytes, checksum 0xFFB80032, sha256 77a232e4db6b60c21f7b76ccf821e3c80c519901f11d10efb8c8df04ca82a4e8", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUniChar": 65535, + "defaultWidth": 500 + }, + "repackageTTF": { + "bytes": 7724, + "sha256": "eaab3f08c782fc1dad90a8af709b9226f3aee98d8dde4860d89ca916d5324fdf", + "tables": { + "OS/2": "96 bytes, checksum 0x5F5F5B76, sha256 cc4ad6c0e41dc604446972f590368ab428d9ad2c941312922acc9c17dda14d3e", + "cmap": "102 bytes, checksum 0xC038217F, sha256 a1b184efcc22e1eaf3755cc9bb944649ddbdced8a28cb81f10faa61f050e6c43", + "cvt ": "144 bytes, checksum 0x190A07A3, sha256 1e7c2ec1797e1ae814f510add7a144d6c11ebe4c121bd03c55de3375b7ef2e25", + "fpgm": "3596 bytes, checksum 0x622F037F, sha256 24c7d2293020be24d28f973149e99b5e04536533dfb66a518191cc7fa206f99b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "2596 bytes, checksum 0xAEE9E758, sha256 d93e16d96b6eaacecb69608ef281b6db5ed6da9be4716032abd2b152e7cd073d", + "head": "54 bytes, checksum 0x29BD2C4A, sha256 2d4d61d8637e2aaac8a1f0e5d3e4882d408a3659e8178f694937491297195a19", + "hhea": "36 bytes, checksum 0x073C01DB, sha256 4a0396d7fc07fc169ca30bfabf25c5753a9733d743a9e19a5cfe7ab402d5521c", + "hmtx": "36 bytes, checksum 0x11CC00FA, sha256 bf88d36bd5dc51e87e487d86d5975f4063b0a9e5a315f90788664a7f00a8380b", + "loca": "20 bytes, checksum 0x0B050D0D, sha256 5c8231a6bad4dfacf454bf57603b53ad7e649fd41b5697c3baa5d5dbb03519a8", + "maxp": "32 bytes, checksum 0x01830FD8, sha256 e3a9fe933752196fb755e0adc0fdfd624263cc6fd921dd79e7e43210a80695c1", + "name": "482 bytes, checksum 0x26DA3F33, sha256 9a6431fdb319205c516f8ac2746e3eeead418c6a954a03b649ddc3eacbf02b6b", + "post": "62 bytes, checksum 0xDC8F9243, sha256 d7666fbc36debeae35b76f8a2fa860e94cbfa7ffef8a0701fbaf3ed0d3469b11", + "prep": "214 bytes, checksum 0x4D565F16, sha256 e0d9caca58b52c80ed328dcf3e608416e387c10522c7fcfebd3478542b7f2703" + }, + "maxUni": 0 + } + } +} diff --git a/tests/data/ttf/Carlito-MarkAttachmentType-Subset.ttf b/tests/data/ttf/Carlito-MarkAttachmentType-Subset.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f3b3653bfc3f791864ad69027db074d3f4c5199d GIT binary patch literal 5792 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 uWk2F&VqXaPtD5OOZ-T-#Dob-)k!&e8VX zd+oK?+558{MMP|kcGThv(@#EiqCME|i?a7jMt4uooIU? ze|__J(ddlTZj`rjn)j@t`Q*Od*|kP){#rC{zgxS}t+c+j{U!y;&t2lmlYV)q$)2B{N$IWQIzqWpc-Z#sSGryZtKF~dBGy1aT zY*gwV0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly(1??XP-d%TtLM+6+xNso_FM9;)|!0> z-(Tx=x}yWnMW@sGIO6x~xqTUpcG+IvHy&OB1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAJ z9^Z@CqKw&y;y>lBs6~Io_>Mh0KC@@Xp4sB(x8EuzZ~wWxwKg?go{J(*cK%zO&Afq# z-o2xv2WsPkjdHxTbEw`|?0f!fv#g)4m)j>F85-Q(yZ@QT%6)5VMQU6N4x^71M z)|`TIg`;V-Re)= zkG3WzSB9{yv=6aJFAX;qQYiw zGr#r!pQ8DRDlg=zDxXW;+g8Gx=i02lS^e&_eA*4i@+8;0X4UUzwX0RjzleM~zsSm; z_7oZ1y0K8^e^^nqcG0dz)!MzWKX;Z-o_OX=Y@53}_fq~X^;G$tPItYSpI=;#Eg7h? Si(Fgpw`AY<{VJ!b75@XVV{Z5W literal 0 HcmV?d00001 diff --git a/tests/data/ttf/SedanSC-EmptyFeature-Subset.ttf b/tests/data/ttf/SedanSC-EmptyFeature-Subset.ttf new file mode 100644 index 0000000000000000000000000000000000000000..df38c419b124366697ce2e6eab84b57bebaac012 GIT binary patch literal 8232 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 Y6p*n!A-hP93fSP1<{9 literal 0 HcmV?d00001 From 315a8106f4d407bd27a55b97f286fbda1c8f6e09 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 16 Sep 2026 11:25:17 +1000 Subject: [PATCH 2/2] Regenerate the wrap synthetic's shaping fixture from a cold font cache The fixture was written from a stale one. The synthetic was rebuilt part way through this branch - its one lookup moved from 'fina' to 'ccmp', so that the shaper applies it directly rather than only through the joining table the parser derives - and mPDF's font cache keys the derived GSUB.