diff --git a/src/TTFontFile.php b/src/TTFontFile.php index 9b9444b78..957316dcc 100644 --- a/src/TTFontFile.php +++ b/src/TTFontFile.php @@ -2412,11 +2412,6 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) { $volt = []; - // A Type 5 Format 1 or 2 rule reads these without setting them, so hands whatever the last - // chained rule left in them to the Arabic shaper (#189). - $backtrackGlyphs = []; - $lookaheadGlyphs = []; - foreach ($lul as $i => $tag) { $this->reportGSUBlookupStart($Lookup, $i, $tag); @@ -2471,9 +2466,7 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) [], $inputGlyphs, [], - count($inputGlyphs), - ['', '', ''], - [$backtrackGlyphs, $lookaheadGlyphs] + count($inputGlyphs) ))); } } @@ -2494,8 +2487,7 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) $this->classInputGlyphs($subtable['InputClasses'], $inputClass, $rule), [], $rule['InputGlyphCount'], - $class0excl, - [$backtrackGlyphs, $lookaheadGlyphs] + $class0excl ))); } } @@ -2517,15 +2509,12 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) $inputGlyphs[0] = $firstInputGlyph; ksort($inputGlyphs); - $backtrackGlyphs = $rule['BacktrackGlyphCount'] ? $rule['BacktrackGlyphs'] : []; - $lookaheadGlyphs = $rule['LookaheadGlyphCount'] ? $rule['LookaheadGlyphs'] : []; - $this->addTo($volt, $this->gsubContextRule($Lookup, $i, $c, $tag, $scripttag, $ignore, $this->contextRule( $rctr, $rule['SubstLookupRecord'], - $backtrackGlyphs, + $rule['BacktrackGlyphCount'] ? $rule['BacktrackGlyphs'] : [], $inputGlyphs, - $lookaheadGlyphs, + $rule['LookaheadGlyphCount'] ? $rule['LookaheadGlyphs'] : [], count($inputGlyphs) ))); } @@ -2590,17 +2579,11 @@ function _getGSUBarray(array $Lookup, $lul, $scripttag) * @param string[] $class0excl For a class-based rule, every glyph some class of the input, * backtrack and lookahead Class Definitions names, which is what each * one's class 0 excludes - * @param array $arabic [backtrack, lookahead] for the entry an Arabic joining form's rule - * becomes, where that is not the rule's own: see _getGSUBarray() * * @return array */ - private function contextRule($index, array $records, array $backtrack, array $input, array $lookahead, $nInput, array $class0excl = ['', '', ''], $arabic = null) + private function contextRule($index, array $records, array $backtrack, array $input, array $lookahead, $nInput, array $class0excl = ['', '', '']) { - if ($arabic === null) { - $arabic = [$backtrack, $lookahead]; - } - return [ 'index' => $index, 'records' => $records, @@ -2609,8 +2592,6 @@ private function contextRule($index, array $records, array $backtrack, array $in 'lookahead' => $lookahead, 'nInput' => $nInput, 'class0excl' => $class0excl, - 'prel' => $arabic[0], - 'postl' => $arabic[1], ]; } @@ -2767,7 +2748,7 @@ protected function gsubContextRule(array $Lookup, $i, $c, $tag, $scripttag, $ign } if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { - $volt[] = ['match' => $lookupGlyphs[0], 'replace' => implode(" ", $luss['substitute']), 'tag' => $tag, 'prel' => $rule['prel'], 'postl' => $rule['postl'], 'ignore' => $ignore]; + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => implode(" ", $luss['substitute']), 'tag' => $tag, 'prel' => $rule['backtrack'], 'postl' => $rule['lookahead'], 'ignore' => $ignore]; } else { $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; } diff --git a/tests/Mpdf/ContextRuleArabicFormTest.php b/tests/Mpdf/ContextRuleArabicFormTest.php new file mode 100644 index 000000000..0652e4ff0 --- /dev/null +++ b/tests/Mpdf/ContextRuleArabicFormTest.php @@ -0,0 +1,81 @@ + 'utf-8', + 'fontDir' => [__DIR__ . '/../data/ttf'], + 'fontdata' => ['notosansarabicgsub5formsynthetic' => [ + 'R' => 'NotoSansArabic-GSUB5Form-Synthetic.ttf', + 'useOTL' => 0xFF, + ]], + 'default_font' => 'notosansarabicgsub5formsynthetic', + ]); + $mpdf->WriteHTML('

' . $html . '

'); + + return array_values(unpack('N*', mb_convert_encoding($mpdf->drawnText[0], 'UTF-32BE', 'UTF-8'))); + } + + public function dataRuns() + { + return [ + 'an initial form from Format 1, with nothing before it' => [ + [self::BEH, self::BEH], + [self::BEH, self::DOTLESS_BEH_INITIAL], + ], + 'an initial form from Format 1, before the chained rule\'s final form' => [ + [self::BEH, self::BEH, self::LOW_ALEF], + [self::LOW_ALEF, self::DOTLESS_BEH_FINAL, self::DOTLESS_BEH_INITIAL], + ], + 'a medial form from Format 2, with no low alef after it' => [ + [self::BEH, self::BEH, self::BEH, self::LOW_ALEF], + [self::LOW_ALEF, self::DOTLESS_BEH_FINAL, self::DOTLESS_BEH_MEDIAL, self::DOTLESS_BEH_INITIAL], + ], + ]; + } + + /** + * @dataProvider dataRuns + */ + public function testTheFormNeedsNoContext($codepoints, $expected) + { + $this->assertSame($expected, $this->drawn($codepoints)); + } + +} diff --git a/tests/Mpdf/Fonts/GsubArrayTest.php b/tests/Mpdf/Fonts/GsubArrayTest.php index 8fbaaf8d2..8b7961579 100644 --- a/tests/Mpdf/Fonts/GsubArrayTest.php +++ b/tests/Mpdf/Fonts/GsubArrayTest.php @@ -54,10 +54,10 @@ public function testTheDumpReportsEachClassRuleWithItsOwnPositions() } /** - * A Type 5 rule has no backtrack or lookahead, yet where it belongs to an Arabic joining form the - * parser hands the shaper the sequences of the chained rule it read last (#189). + * A Type 5 rule has no backtrack or lookahead, so where it belongs to an Arabic joining form the + * shaper gets none, not those of the chained rule read before it (#189). */ - public function testAPlainContextRuleOfAnArabicFormCarriesTheLastChainedRulesSequences() + public function testAPlainContextRuleOfAnArabicFormHasNoBacktrackOrLookahead() { $parser = $this->withGdef(new TTFontFile($this->cache(), 'win')); @@ -78,7 +78,7 @@ public function testAPlainContextRuleOfAnArabicFormCarriesTheLastChainedRulesSeq $volt = $parser->_getGSUBarray($Lookup, [0 => 'init', 2 => 'init'], 'arab'); - $this->assertSame(['match' => '00041', 'replace' => '00044', 'tag' => 'init', 'prel' => ['00043'], 'postl' => [], 'ignore' => '()'], end($volt)); + $this->assertSame(['match' => '00041', 'replace' => '00044', 'tag' => 'init', 'prel' => [], 'postl' => [], 'ignore' => '()'], end($volt)); } private function chainedClassRules() diff --git a/tests/data/fontcache/NotoSansArabic-GSUB5Form-Synthetic.json b/tests/data/fontcache/NotoSansArabic-GSUB5Form-Synthetic.json new file mode 100644 index 000000000..111bb6fe7 --- /dev/null +++ b/tests/data/fontcache/NotoSansArabic-GSUB5Form-Synthetic.json @@ -0,0 +1,278 @@ +{ + "_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.", + "fullName": "NotoSansArabicGSUB5FormSynthetic-Regular", + "mtx": { + "GSUBScriptLang": { + "DFLT": "DFLT ", + "arab": "DFLT " + }, + "GSUBFeatures": { + "DFLT": { + "DFLT": { + "fina": [ + 0 + ], + "init": [ + 1 + ], + "medi": [ + 2 + ] + } + }, + "arab": { + "DFLT": { + "fina": [ + 0 + ], + "init": [ + 1 + ], + "medi": [ + 2 + ] + } + } + }, + "GSUBLookups": [ + { + "Type": 6, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 100 + ], + "MarkFilteringSet": "" + }, + { + "Type": 5, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 134 + ], + "MarkFilteringSet": "" + }, + { + "Type": 5, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 162 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 202 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 216 + ], + "MarkFilteringSet": "" + }, + { + "Type": 1, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 230 + ], + "MarkFilteringSet": "" + } + ], + "GPOSScriptLang": { + "DFLT": "DFLT ", + "arab": "DFLT ", + "cyrl": "DFLT ", + "dev2": "DFLT ", + "grek": "DFLT ", + "latn": "DFLT " + }, + "GPOSFeatures": { + "DFLT": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "arab": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "cyrl": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "dev2": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "grek": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + }, + "latn": { + "DFLT": { + "mark": [ + 0 + ], + "mkmk": [ + 1 + ] + } + } + }, + "GPOSLookups": [ + { + "Type": 4, + "Flag": 0, + "SubtableCount": 1, + "Subtables": [ + 102 + ], + "MarkFilteringSet": "" + }, + { + "Type": 6, + "Flag": 16, + "SubtableCount": 1, + "Subtables": [ + 194 + ], + "MarkFilteringSet": 0 + } + ], + "MarkGlyphSets": [ + " 0E005" + ], + "rtlPUAstr": "\\x{0E002}-\\x{0E004}", + "haskernGPOS": false, + "hassmallcapsGSUB": false + }, + "cache": { + "GDEFdata.json": { + "GlyphClassBases": " 00020| 00627| 008AD| 0E000| 0E001| 0E002| 0E003| 0E004", + "GlyphClassMarks": " 0E005", + "GlyphClassLigatures": "", + "GlyphClassComponents": "", + "MarkGlyphSets": [ + " 0E005" + ], + "MarkAttachmentType": [] + }, + "GPOS.dat": "234 bytes, sha256 0f363351c5ea276d72ca75127977045024304d1f2b19b04e8cfded715c737a13", + "GPOSdata.json": [ + [ + { + "57349": 0 + } + ], + [ + { + "57349": 0 + } + ] + ], + "GSUB.arab.DFLT.json": { + "rtlSUB": { + "00628": { + "1": "0E002", + "prel": { + "1": [ + "00628" + ] + }, + "postl": { + "1": [ + "008AD" + ] + }, + "ignore": { + "1": "()", + "2": "()", + "3": "()" + }, + "2": "0E004", + "3": "0E003" + } + }, + "finals": "0E002 ", + "rphf": [], + "half": [], + "pref": [], + "blwf": [], + "pstf": [] + }, + "GSUB.dat": "242 bytes, sha256 233543ea71d43c7342390dd0ebd1a6fa9a480924f1ea1ef2e97cf4873a7fbd84", + "GSUBdata.json": [ + [ + { + "1576": 0 + } + ], + [ + { + "1576": 0 + } + ], + [ + { + "1576": 0 + } + ], + [ + { + "1576": 0 + } + ], + [ + { + "1576": 0 + } + ], + [ + { + "1576": 0 + } + ] + ] + } +} diff --git a/tests/data/otldump/NotoSansArabic-GSUB5Form-Synthetic.txt b/tests/data/otldump/NotoSansArabic-GSUB5Form-Synthetic.txt new file mode 100644 index 000000000..908812490 --- /dev/null +++ b/tests/data/otldump/NotoSansArabic-GSUB5Form-Synthetic.txt @@ -0,0 +1,27 @@ +

GDEF table

+

Glyph classes

+

Glyph class 1

+
Base glyph (single character, spacing glyph)
+
ا ࢭ     
+

Glyph class 3

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

Mark Glyph Sets

+

Mark Glyph Set class: 0

+
◌
+

GSUB Tables

+

GSUB Scripts & Languages

+
+
DFLT
DFLT: fina init medi
arab
DFLT: fina init medi
+
+

GPOS Tables

+

GPOS Scripts & Languages

+
+
DFLT
DFLT: mark mkmk
arab
DFLT: mark mkmk
cyrl
DFLT: mark mkmk
dev2
DFLT: mark mkmk
grek
DFLT: mark mkmk
latn
DFLT: mark mkmk
+
+ +=== detail: script arab language DFLT === +

GSUB Tables

+
Lookup #0 [tag: fina]
Subtable #0
LookupType 6: Chaining Contextual Substitution Subtable
Format 3: Coverage-based Chaining Context Glyph Substitution
CONTEXT:
Backtrack #0: U+0628
Input #0:  ب 
Lookahead #0: U+08AD
Substitution Position: 0
Lookup #3 [tag: fina]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0628  ب ب  » »  ب   M+E002
Lookup #1 [tag: init]
Subtable #0
LookupType 5: Contextual Substitution Subtable
Format 1: Context Substitution
SubRule: 0
CONTEXT:
Input #0:  ب 
Substitution Position: 0
Lookup #4 [tag: init]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0628   ب  » »     M+E004
Lookup #2 [tag: medi]
Subtable #0
LookupType 5: Contextual Substitution Subtable
Format 2: Class-based Context Glyph Substitution
Input Class: 1
Rule: 0
CONTEXT:
Input #0:  ب 
Substitution Position: 0
Lookup #5 [tag: medi]
Subtable #0
LookupType 1: Single Substitution Subtable
U+0628   ب  » »     M+E003
+

GPOS Tables

+
Lookup #0 [tag: mark]
Subtable #0
LookupType 4: MarkToBase attachment
Marks: ◌
Bases: ا      ࢭ
Example(s):    ا                  ࢭ  
Lookup #1 [tag: mkmk]
Ignoring: Marks outside Mark Glyph Set[0]
Subtable #0
LookupType 6: MarkToMark attachment
Marks: ◌
Bases: ◌
Example(s): ◌  
diff --git a/tests/data/shaping/NotoSansArabic-GSUB5Form-Synthetic.txt b/tests/data/shaping/NotoSansArabic-GSUB5Form-Synthetic.txt new file mode 100644 index 000000000..46b19791d --- /dev/null +++ b/tests/data/shaping/NotoSansArabic-GSUB5Form-Synthetic.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 => E004 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0x80 0628 0640 0645 0644 0627 => E004 0640 0645 0644 0627 group=CCCCC gpos={"1":{"kashida":8}} +0xFF +kern -liga 0628 0640 0645 0644 0627 => E004 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 0627 0628 08AD E000 E001 E002 E003 => 0020 0627 0628 08AD E000 E001 E002 E003 group=SCCCCCCC gpos={"6":{"kashida":2}} +0x80 0020 0627 0628 08AD E000 E001 E002 E003 => 0020 0627 0628 08AD E000 E001 E002 E003 group=SCCCCCCC gpos={"6":{"kashida":2}} +0xFF +kern -liga 0020 0627 0628 08AD E000 E001 E002 E003 => 0020 0627 0628 08AD E000 E001 E002 E003 group=SCCCCCCC gpos={"6":{"kashida":2}} +=== font characters 1 === +0xFF E004 E005 => E004 E005 group=CM gpos={"1":{"BaseWidth":269,"XPlacement":31,"YPlacement":-3}} +0x80 E004 E005 => E004 E005 group=CM gpos={"1":{"BaseWidth":269,"XPlacement":31,"YPlacement":-3}} +0xFF +kern -liga E004 E005 => E004 E005 group=CM gpos={"1":{"BaseWidth":269,"XPlacement":31,"YPlacement":-3}} diff --git a/tests/data/subset/NotoSansArabic-GSUB5Form-Synthetic.json b/tests/data/subset/NotoSansArabic-GSUB5Form-Synthetic.json new file mode 100644 index 000000000..d22479446 --- /dev/null +++ b/tests/data/subset/NotoSansArabic-GSUB5Form-Synthetic.json @@ -0,0 +1,129 @@ +{ + "_": "Generated by composer subset:update. See tests/Mpdf/Fonts/SubsetGoldenMaster.php.", + "useOTL=0x00": { + "characters": 5, + "makeSubset": { + "bytes": 1504, + "sha256": "f4fdd245fc504f91d29aa1d36d25bf23f52fe641b72b15b2fdaed6a680d2fcc4", + "tables": { + "OS/2": "96 bytes, checksum 0x83C35E30, sha256 c8d44e1e3e21744fb6447d75613e7d094658598ae11cd4ecd6ea51953585ed86", + "cmap": "92 bytes, checksum 0x0EEF06F5, sha256 ae6fb5dc97aecd1fc550113941bb8dd17c1e315a921037dd742091775397192d", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "304 bytes, checksum 0x7C5B4089, sha256 dda0aee857654d74b832394e016fc1e1e7710819c3dd061b666da107b0c39414", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 cbb13f84aeb4bc2a151fc56903ba6630710ff42a0221bc6906f2448cebaa5cd4", + "hhea": "36 bytes, checksum 0x29871F54, sha256 b6790f08d7b49267a846ddaa6976fa1ae4f2c482adfd5ca104166fe4ec48ca93", + "hmtx": "28 bytes, checksum 0x0CF90144, sha256 5a0c3e3815967f5179a662960145cd59d1377b1065498bb99d512c035752a67d", + "loca": "16 bytes, checksum 0x00D00114, sha256 82987de0caadd775301bb7f92dc6663a42f1351074a37aaa9e8f43ddd2629de3", + "maxp": "32 bytes, checksum 0x0058052C, sha256 712fd6ee38e7ed3e4f3271a00a1ea02f9588b526df499378ee6c2db8aeed859e", + "name": "590 bytes, checksum 0x32D14B7E, sha256 6f9cda0e4d4ba9540d0577c856ff741507bd754cc02fd0458f25bc4384698b52", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUni": 65535, + "defaultWidth": 600, + "codeToGlyph": "5 entries, sha256 e330c81f30e51088fd0070ff21260ad702c20dd4487cd3b50ac48068aee467ca" + }, + "makeSubsetSIP": { + "bytes": 1492, + "sha256": "3597e5849f5bbdc804e1760189c3fbd33f05dc7885b36c63ef551e6fd8a9baff", + "tables": { + "OS/2": "96 bytes, checksum 0x69A2D688, sha256 69a32b780b72e95ba9dfa002a1b8a2d0019efbe42ba74209c65095bc15e06732", + "cmap": "80 bytes, checksum 0x002C0083, sha256 3d0e58f1892397e1e94f3d0f75c6038f1212ed4d46a99eef47bc722bc366ee41", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "304 bytes, checksum 0x7C5B4089, sha256 184dd6f6301fa823051edcb9ea0c09851b5c5fd96ef911f898c134000990f13b", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 da78ebc30f918b92dffae4ba54332a58ba40685d424626ded224e4b0486b0c81", + "hhea": "36 bytes, checksum 0x29871F54, sha256 b6790f08d7b49267a846ddaa6976fa1ae4f2c482adfd5ca104166fe4ec48ca93", + "hmtx": "28 bytes, checksum 0x0CF90144, sha256 cd581a635bc9a3a20a5f498d3842038b3b5acfb25d1187221fab16a8cf9430ee", + "loca": "16 bytes, checksum 0x00C40114, sha256 b012200316381b41dc293cfa1f58f92eb79c195dbc958907b7309a3fcab6d76e", + "maxp": "32 bytes, checksum 0x0058052C, sha256 712fd6ee38e7ed3e4f3271a00a1ea02f9588b526df499378ee6c2db8aeed859e", + "name": "590 bytes, checksum 0x32CA4B7E, sha256 f90f89fb915f6df91ba20cca75fe74cd14b13f91214149ea9be3b728e6d6b2f4", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUniChar": 65535, + "defaultWidth": 600 + }, + "repackageTTF": { + "bytes": 1992, + "sha256": "2733c4c6d88c604fcca928312f2ed7f294e790e64cf952fcd07d4ba064db3009", + "tables": { + "OS/2": "96 bytes, checksum 0x83C35E30, sha256 c8d44e1e3e21744fb6447d75613e7d094658598ae11cd4ecd6ea51953585ed86", + "cmap": "72 bytes, checksum 0x06420F70, sha256 e29b8cf3f1e636faa27f210c98884c21505fdd6b6b8acf965ef0b86eafa0c480", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "668 bytes, checksum 0xD2CBF85C, sha256 64df708dd07ef438ab78c2fa6ec037cb9d2ec39a026eeecb018460dbe43ab527", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 301a6f9e7dc4cd406ad7250e6ebd6c819f3d4f839b1c340d7295dd620460532f", + "hhea": "36 bytes, checksum 0x29871F58, sha256 d5c8aa00ac210ae41f8cae1f3201846d77c0ac04d04e11627ee19851bdfdcd08", + "hmtx": "44 bytes, checksum 0x14C501AA, sha256 af3326b0ee31557a2ee01c72ee59dac76903c6a84f8a077b74b99271f2ba42f5", + "loca": "24 bytes, checksum 0x036E041D, sha256 0a4cc922874d893e9926bbbf0eece0202d5cab7ec6724963cafca63946eec457", + "maxp": "32 bytes, checksum 0x005C052C, sha256 26689100d5138bb752af4293a4bbb556b534aa9d94134a46edd960ec269019ec", + "name": "590 bytes, checksum 0x32D14B7E, sha256 6f9cda0e4d4ba9540d0577c856ff741507bd754cc02fd0458f25bc4384698b52", + "post": "151 bytes, checksum 0xB924F86C, sha256 4baf6477b5a1ef33145e61b8c7bb9c828d6b17629e10af34eaf47d20e2978446", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUni": 0 + } + }, + "useOTL=0xFF": { + "characters": 11, + "makeSubset": { + "bytes": 1920, + "sha256": "1f970b9545ee2fb139c012a537448808c4590c7effdfc58a7a936edf94b44b50", + "tables": { + "OS/2": "96 bytes, checksum 0x83C35E30, sha256 c8d44e1e3e21744fb6447d75613e7d094658598ae11cd4ecd6ea51953585ed86", + "cmap": "108 bytes, checksum 0xEF02E71C, sha256 78a92931bee3fd46f5a9c5415eedaa0f295efa03625ca4afa41c4480a898243b", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "680 bytes, checksum 0x41A9897B, sha256 56ca9bb7742204cbdc96a05b2385d3fa81b1179034b69c093b9aa272a3e64d52", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 34c7bb3f1f15e1bcff72d5ec4cd8526a5c6dcd484124e091f7c8ccb55b332c7c", + "hhea": "36 bytes, checksum 0x29871F58, sha256 d5c8aa00ac210ae41f8cae1f3201846d77c0ac04d04e11627ee19851bdfdcd08", + "hmtx": "44 bytes, checksum 0x14C501AA, sha256 af3326b0ee31557a2ee01c72ee59dac76903c6a84f8a077b74b99271f2ba42f5", + "loca": "24 bytes, checksum 0x03800432, sha256 2cb2965a2d09fea2eb65e980cd64ac413ab3d2cfcd850e65997ad5fef232b95b", + "maxp": "32 bytes, checksum 0x005C052C, sha256 26689100d5138bb752af4293a4bbb556b534aa9d94134a46edd960ec269019ec", + "name": "590 bytes, checksum 0x32D14B7E, sha256 6f9cda0e4d4ba9540d0577c856ff741507bd754cc02fd0458f25bc4384698b52", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUni": 65535, + "defaultWidth": 600, + "codeToGlyph": "11 entries, sha256 4976a91e70c6d83b58a35c5bf0afec8d29c446258274744a3317930df09fa365" + }, + "makeSubsetSIP": { + "bytes": 1904, + "sha256": "286b25d292d3372d1ce1abed6b578d197cd7b63075b8f575184f08ca4a4f5684", + "tables": { + "OS/2": "96 bytes, checksum 0x69A2D68E, sha256 d3e6c0234f8db691dbb73991a5141f8184691d245eda464e73fcfd0645daf3a7", + "cmap": "92 bytes, checksum 0x005600B0, sha256 5febc775230d1d4c2ff1203cc3ba03258d79c52651c9eb23a521082d323ea414", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "680 bytes, checksum 0x41AB897C, sha256 78d00159157d7c704efacfa95bba99beebb11d2b1c4313852a6f55f06936c1af", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 3545e46340e5ee740e00cef07d31694654f7157a48f88eef6fa8456a0616a280", + "hhea": "36 bytes, checksum 0x29871F58, sha256 d5c8aa00ac210ae41f8cae1f3201846d77c0ac04d04e11627ee19851bdfdcd08", + "hmtx": "44 bytes, checksum 0x14C501AA, sha256 1bcad69d16f9d4b7cdb1a2e30f1e1b5172902317c43c2383364b125bc9287e90", + "loca": "24 bytes, checksum 0x02D2038E, sha256 276b53cc6f655d4a16fd4168880b6fba91e36f6b119e3f1b5905dd0725dba35c", + "maxp": "32 bytes, checksum 0x005C052C, sha256 26689100d5138bb752af4293a4bbb556b534aa9d94134a46edd960ec269019ec", + "name": "590 bytes, checksum 0x32CA4B7E, sha256 f90f89fb915f6df91ba20cca75fe74cd14b13f91214149ea9be3b728e6d6b2f4", + "post": "32 bytes, checksum 0xFF9F0032, sha256 4fdc83d5e42fe44650fe86f15a645d5cc926d07355ba945e1ede42737607bf83", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUniChar": 65535, + "defaultWidth": 600 + }, + "repackageTTF": { + "bytes": 2020, + "sha256": "79220e4158e2fd618c233b23c77194e0062bf4c6581bc874e1f773dfe4b4e293", + "tables": { + "OS/2": "96 bytes, checksum 0x83C35E30, sha256 c8d44e1e3e21744fb6447d75613e7d094658598ae11cd4ecd6ea51953585ed86", + "cmap": "100 bytes, checksum 0xF793DE7F, sha256 0dbe9edb138b44d6281c2fb3bff43096c4966deba0e380e4bed0d7e8887d0cba", + "gasp": "8 bytes, checksum 0x00000010, sha256 4ca731f86ad506ac0e320283dc9461926346de3c4d91d539ea7f6620d3826940", + "glyf": "668 bytes, checksum 0xD2CBF85C, sha256 64df708dd07ef438ab78c2fa6ec037cb9d2ec39a026eeecb018460dbe43ab527", + "head": "54 bytes, checksum 0x46EA9EA3, sha256 d17965018acdace96214a0b6245317e968ecfa19183925f30e5e4d6c0e6ea9ad", + "hhea": "36 bytes, checksum 0x29871F58, sha256 d5c8aa00ac210ae41f8cae1f3201846d77c0ac04d04e11627ee19851bdfdcd08", + "hmtx": "44 bytes, checksum 0x14C501AA, sha256 af3326b0ee31557a2ee01c72ee59dac76903c6a84f8a077b74b99271f2ba42f5", + "loca": "24 bytes, checksum 0x036E041D, sha256 0a4cc922874d893e9926bbbf0eece0202d5cab7ec6724963cafca63946eec457", + "maxp": "32 bytes, checksum 0x005C052C, sha256 26689100d5138bb752af4293a4bbb556b534aa9d94134a46edd960ec269019ec", + "name": "590 bytes, checksum 0x32D14B7E, sha256 6f9cda0e4d4ba9540d0577c856ff741507bd754cc02fd0458f25bc4384698b52", + "post": "151 bytes, checksum 0xB924F86C, sha256 4baf6477b5a1ef33145e61b8c7bb9c828d6b17629e10af34eaf47d20e2978446", + "prep": "7 bytes, checksum 0x68068C85, sha256 907c4106ff9989c1805827d5581bdf107a253b098cb71eb374f5e47c35604452" + }, + "maxUni": 0 + } + } +} diff --git a/tests/data/ttf/NotoSansArabic-GSUB5Form-Synthetic.ttf b/tests/data/ttf/NotoSansArabic-GSUB5Form-Synthetic.ttf new file mode 100644 index 000000000..a336b9f30 Binary files /dev/null and b/tests/data/ttf/NotoSansArabic-GSUB5Form-Synthetic.ttf differ