Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/Shaper/OtlTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,12 @@ public static function language($ietf, $available)
$country = strtolower($tags[2]);
}

$region = $lang . '-' . $country;

if ($lang != '' && isset(Ucdn::$ot_languages[$lang])) {
$langsys = Ucdn::$ot_languages[$lang];
} elseif ($lang != '' && $country != '' && isset(Ucdn::$ot_languages[$lang . $country])) {
// Never matches: the region keys are written 'zh-hk' (#191)
$langsys = Ucdn::$ot_languages[$lang . $country];
} elseif ($lang != '' && $country != '' && isset(Ucdn::$ot_languages[$region])) {
$langsys = Ucdn::$ot_languages[$region];
} else {
$langsys = 'DFLT';
}
Expand Down
55 changes: 55 additions & 0 deletions tests/Mpdf/ChineseRegionLangSysTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Mpdf;

/**
* A Chinese region in the lang attribute selects the font's language system for it: ZHH for Hong
* Kong, ZHT for Taiwan and Macao, ZHS for mainland China and Singapore.
*
* No font in the corpus has a Chinese language system, so NotoSansTC-RegionLangSys-Synthetic is a
* subset of Noto Sans TC 2.004 (OFL 1.1) with its GSUB replaced. Its hani script has no features by
* default, and one 'locl' lookup under each of ZHH, ZHS and ZHT, which gives 骨 the glyph of 三, 一
* and 二 in turn. `hb-shape --language` draws the same glyph for each of these tags.
*/
class ChineseRegionLangSysTest extends \Yoast\PHPUnitPolyfills\TestCases\TestCase
{

const BONE = 0x9AA8;

const ZHS = 0x4E00;

const ZHT = 0x4E8C;

const ZHH = 0x4E09;

public function regions()
{
return [
'zh-HK' => ['zh-HK', self::ZHH],
'zh-TW' => ['zh-TW', self::ZHT],
'zh-CN' => ['zh-CN', self::ZHS],
];
}

/**
* @dataProvider regions
*/
public function testTheRegionSelectsTheLanguageSystem($lang, $expected)
{
$mpdf = new TextRecordingMpdf([
'mode' => 'utf-8',
'fontDir' => [__DIR__ . '/../data/ttf'],
'fontdata' => ['notosanstcregionlangsyssynthetic' => [
'R' => 'NotoSansTC-RegionLangSys-Synthetic.ttf',
'useOTL' => 0xFF,
]],
'default_font' => 'notosanstcregionlangsyssynthetic',
]);
$mpdf->WriteHTML(sprintf('<p lang="%s">&#x%04X;</p>', $lang, self::BONE));

$drawn = array_values(unpack('N*', mb_convert_encoding($mpdf->drawnText[0], 'UTF-32BE', 'UTF-8')));

$this->assertSame([$expected], $drawn);
}

}
33 changes: 33 additions & 0 deletions tests/Mpdf/Shaper/OtlTagsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,37 @@ public function languages()
];
}

/**
* @dataProvider chineseRegions
*/
public function testAChineseRegionSelectsItsLanguageSystem($ietf, $expected)
{
$this->assertSame($expected, OtlTags::language($ietf, 'DFLT ZHH ZHS ZHT '));
}

public function chineseRegions()
{
return [
'Hong Kong' => ['zh-HK', 'ZHH '],
'Hong Kong, after the script' => ['zh-Hant-HK', 'ZHH '],
'Taiwan' => ['zh-TW', 'ZHT '],
'Macao' => ['zh-MO', 'ZHT '],
'China' => ['zh-CN', 'ZHS '],
'Singapore' => ['zh-SG', 'ZHS '],
'lower case' => ['zh-tw', 'ZHT '],
'a region the table has no entry for' => ['zh-US', 'DFLT'],
];
}

/**
* Pins #201 as it stands: without a region, Chinese has no language system, where HarfBuzz
* takes ZHS for zh and zh-Hans and ZHT for zh-Hant.
*/
public function testChineseWithoutARegionHasNoLanguageSystem()
{
$this->assertSame('DFLT', OtlTags::language('zh', 'DFLT ZHH ZHS ZHT '));
$this->assertSame('DFLT', OtlTags::language('zh-Hant', 'DFLT ZHH ZHS ZHT '));
$this->assertSame('DFLT', OtlTags::language('zh-Hans', 'DFLT ZHH ZHS ZHT '));
}

}
92 changes: 92 additions & 0 deletions tests/data/fontcache/NotoSansTC-RegionLangSys-Synthetic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"_": "Generated by composer fontcache:update. See tests/Mpdf/Fonts/ParserGoldenMaster.php.",
"fullName": "NotoSansTC-RegionLangSys-Synthetic",
"mtx": {
"GSUBScriptLang": {
"hani": "DFLT ZHH ZHS ZHT "
},
"GSUBFeatures": {
"hani": {
"ZHH ": {
"locl": [
0
]
},
"ZHS ": {
"locl": [
1
]
},
"ZHT ": {
"locl": [
2
]
}
}
},
"GSUBLookups": [
{
"Type": 1,
"Flag": 0,
"SubtableCount": 1,
"Subtables": [
124
],
"MarkFilteringSet": ""
},
{
"Type": 1,
"Flag": 0,
"SubtableCount": 1,
"Subtables": [
138
],
"MarkFilteringSet": ""
},
{
"Type": 1,
"Flag": 0,
"SubtableCount": 1,
"Subtables": [
152
],
"MarkFilteringSet": ""
}
],
"GPOSScriptLang": [],
"GPOSFeatures": [],
"GPOSLookups": [],
"MarkGlyphSets": [],
"rtlPUAstr": "",
"haskernGPOS": false,
"hassmallcapsGSUB": false
},
"cache": {
"GDEFdata.json": {
"GlyphClassBases": " 04E00| 04E09| 04E8C| 09AA8",
"GlyphClassMarks": "",
"GlyphClassLigatures": "",
"GlyphClassComponents": "",
"MarkGlyphSets": [],
"MarkAttachmentType": []
},
"GSUB.dat": "164 bytes, sha256 806298eba96771ffa947e91279efff39c5b091473cd2d52e8caf0c74bf95a2a0",
"GSUBdata.json": [
[
{
"39592": 0
}
],
[
{
"39592": 0
}
],
[
{
"39592": 0
}
]
]
}
}
17 changes: 17 additions & 0 deletions tests/data/otldump/NotoSansTC-RegionLangSys-Synthetic.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<h1>GDEF table</h1>
<h2>Glyph classes</h2>
<h3>Glyph class 1</h3>
<h5>Base glyph (single character, spacing glyph)</h5>
<div class="glyphs">&#x04E00; &#x04E09; &#x04E8C; &#x09AA8; </div>
<h1>GSUB Tables</h1>
<h3>GSUB Scripts &amp; Languages</h3>
<div class="glyphs">
<h5>hani</h5><div><a href="font_dump_otl.php?script=hani&amp;lang=ZHH">ZHH </a></b>: locl </div><div><a href="font_dump_otl.php?script=hani&amp;lang=ZHS">ZHS </a></b>: locl </div><div><a href="font_dump_otl.php?script=hani&amp;lang=ZHT">ZHT </a></b>: locl </div>
</div>
<div>GPOS table not defined</div>

=== detail: script hani language DFLT ===
<h1>GSUB Tables</h1>
<div class="notoffered">This font's GSUB script "hani" offers no language system "DFLT". It has: ZHH, ZHS, ZHT</div>
<bookmark level="0" content="GSUB features">
<div>GPOS table not defined</div>
92 changes: 92 additions & 0 deletions tests/data/shaping/NotoSansTC-RegionLangSys-Synthetic.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
=== 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
0x80 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC
0xFF +kern -liga 0628 0640 0645 0644 0627 => 0628 0640 0645 0644 0627 group=CCCCC
=== 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 0937 093F group=CCCC
0x80 0915 094D 0937 093F => 0915 094D 0937 093F group=CCCC
0xFF +kern -liga 0915 094D 0937 093F => 0915 094D 0937 093F group=CCCC
=== bengali ===
0xFF 0995 09CD 09B7 09BF => 0995 09CD 09B7 09BF group=CCCC
0x80 0995 09CD 09B7 09BF => 0995 09CD 09B7 09BF group=CCCC
0xFF +kern -liga 0995 09CD 09B7 09BF => 0995 09CD 09B7 09BF group=CCCC
=== gurmukhi ===
0xFF 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A38 0A3F group=CCCC
0x80 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A38 0A3F group=CCCC
0xFF +kern -liga 0A15 0A4D 0A38 0A3F => 0A15 0A4D 0A38 0A3F 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 => 1780 17D2 1781 17C1 group=CCCC
0x80 1780 17D2 1781 17C1 => 1780 17D2 1781 17C1 group=CCCC
0xFF +kern -liga 1780 17D2 1781 17C1 => 1780 17D2 1781 17C1 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 4E00 4E09 4E8C 9AA8 => 0020 4E00 4E09 4E8C 9AA8 group=SCCCC
0x80 0020 4E00 4E09 4E8C 9AA8 => 0020 4E00 4E09 4E8C 9AA8 group=SCCCC
0xFF +kern -liga 0020 4E00 4E09 4E8C 9AA8 => 0020 4E00 4E09 4E8C 9AA8 group=SCCCC
Loading
Loading