Lines Matching +full:font +full:- +full:size +(+path:plugin +path:dw2pdf) -(+path:plugin +path:dw2pdf +path:lang)

8 // Either seems to work for a font embedded in a PDF file
167 $this->mpdf = $mpdf;
168 $this->maxStrLenRead = 200000; // Maximum size of glyf table to read in as string (otherwise reads each glyph from file)
174 $this->mode = $mode;
175 $this->useOTL = $useOTL; // mPDF 5.7.1
176 $this->fontkey = $fontkey; // mPDF 5.7.1
177 $this->filename = $file;
178 $this->fh = fopen($file, 'rb');
180 if (!$this->fh) {
184 $this->_pos = 0;
185 $this->charWidths = '';
186 $this->glyphPos = [];
187 $this->charToGlyph = [];
188 $this->tables = [];
189 $this->otables = [];
190 $this->kerninfo = [];
191 $this->ascent = 0;
192 $this->descent = 0;
193 $this->numTTCFonts = 0;
194 $this->TTCFonts = [];
195 $this->version = $version = $this->read_ulong();
196 $this->panose = [];
207 throw new \Mpdf\Exception\FontException("Not a TrueType font: version=" . $version);
211 $this->version = $version = $this->read_ulong(); // TTC Header version now
213 throw new \Mpdf\Exception\FontException("Error parsing TrueType Collection: version=" . $version . " - " . $file);
215 $this->numTTCFonts = $this->read_ulong();
216 for ($i = 1; $i <= $this->numTTCFonts; $i++) {
217 $this->TTCFonts[$i]['offset'] = $this->read_ulong();
219 $this->seek($this->TTCFonts[$TTCfontID]['offset']);
220 $this->version = $version = $this->read_ulong(); // TTFont version again now
222 $this->readTableDirectory($debug);
223 $this->extractInfo($debug, $BMPonly, $kerninfo, $useOTL);
224 fclose($this->fh);
229 $this->numTables = $this->read_ushort();
230 $this->searchRange = $this->read_ushort();
231 $this->entrySelector = $this->read_ushort();
232 $this->rangeShift = $this->read_ushort();
233 $this->tables = [];
234 for ($i = 0; $i < $this->numTables; $i++) {
236 $record['tag'] = $this->read_tag();
237 $record['checksum'] = [$this->read_ushort(), $this->read_ushort()];
238 $record['offset'] = $this->read_ulong();
239 $record['length'] = $this->read_ulong();
240 $this->tables[$record['tag']] = $record;
243 $this->checksumTables();
250 foreach ($this->tables as $t) {
251 if ($t['length'] > 0 && $t['length'] < $this->maxStrLenRead) { // 1.02
252 $table = $this->get_chunk($t['offset'], $t['length']);
253 $checksum = $this->calcChecksum($table);
258 $checksum = $this->sub32($checksum, $adjustment);
262 throw new \Mpdf\Exception\FontException(sprintf('TTF file "%s": invalid checksum %s table: %s (expected %s)', $this->filename, dechex($checksum[0]) . dechex($checksum[1]), $t['tag'], dechex($xchecksum[0]) . dechex($xchecksum[1])));
278 $reslo = $xlo - $ylo;
282 $reshi = $xhi - $yhi;
291 $data .= str_repeat("\0", (4 - (strlen($data) % 4)));
308 $offset = isset($this->tables[$tag]['offset']) ? $this->tables[$tag]['offset'] : null;
309 $length = isset($this->tables[$tag]['length']) ? $this->tables[$tag]['length'] : null;
316 $this->_pos = $pos;
317 fseek($this->fh, $this->_pos);
322 $this->_pos = $this->_pos + $delta;
323 fseek($this->fh, $delta, SEEK_CUR);
328 $tpos = $this->get_table_pos($tag);
329 $this->_pos = $tpos[0] + $offset_in_table;
330 fseek($this->fh, $this->_pos);
332 return $this->_pos;
337 $this->_pos += 4;
339 return fread($this->fh, 4);
344 $this->_pos += 2;
345 $s = fread($this->fh, 2);
348 $a = ($a - (1 << 16));
358 $a = ($a - (1 << 16));
366 $this->_pos += 2;
367 $s = fread($this->fh, 2);
374 $this->_pos += 4;
375 $s = fread($this->fh, 4);
377 // if large uInt32 as an integer, PHP converts it to -ve
383 fseek($this->fh, $pos);
384 $s = fread($this->fh, 2);
391 fseek($this->fh, $pos);
392 $s = fread($this->fh, 4);
394 // iF large uInt32 as an integer, PHP converts it to -ve
418 return $this->splice($stream, $offset, $up);
430 return $this->splice($stream, $offset, $up);
435 fseek($this->fh, $pos);
440 return (fread($this->fh, $length));
445 list($pos, $length) = $this->get_table_pos($tag);
449 fseek($this->fh, $pos);
451 return (fread($this->fh, $length));
457 $data = $this->splice($data, 8, "\0\0\0\0");
459 $this->otables[$tag] = $data;
467 $this->panose = [];
468 $this->sFamilyClass = 0;
469 $this->sFamilySubClass = 0;
471 // name - Naming table
473 $name_offset = $this->seek_table("name");
474 $format = $this->read_ushort();
476 throw new \Mpdf\Exception\FontException("Error loading font: Unknown name table format " . $format);
478 $numRecords = $this->read_ushort();
479 $string_data_offset = $name_offset + $this->read_ushort();
484 $platformId = $this->read_ushort();
485 $encodingId = $this->read_ushort();
486 $languageId = $this->read_ushort();
487 $nameId = $this->read_ushort();
488 $length = $this->read_ushort();
489 $offset = $this->read_ushort();
495 $opos = $this->_pos;
496 $this->seek($string_data_offset + $offset);
498 throw new \Mpdf\Exception\FontException("Error loading font: PostScript name is UTF-16BE string of odd length");
503 $char = $this->read_ushort();
505 $length -= 1;
507 $this->_pos = $opos;
508 $this->seek($opos);
511 $opos = $this->_pos;
512 $N = $this->get_chunk($string_data_offset + $offset, $length);
513 $this->_pos = $opos;
514 $this->seek($opos);
519 $nameCount -= 1;
529 $psName = preg_replace('/ /', '-', $names[4]);
532 $psName = preg_replace('/ /', '-', $names[1]);
539 throw new \Mpdf\Exception\FontException("Error loading font: Could not find PostScript font name: " . $this->filename);
550 $this->name = $psName;
552 $this->familyName = $names[1];
554 $this->familyName = $psName;
557 $this->styleName = $names[2];
559 $this->styleName = 'Regular';
562 $this->fullName = $names[4];
564 $this->fullName = $psName;
567 $this->uniqueFontID = $names[3];
569 $this->uniqueFontID = $psName;
573 $this->fullName = $names[6];
577 // head - Font header table
579 $this->seek_table("head");
581 $ver_maj = $this->read_ushort();
582 $ver_min = $this->read_ushort();
584 throw new \Mpdf\Exception\FontException('Error loading font: Unknown head table version ' . $ver_maj . '.' . $ver_min);
586 $this->fontRevision = $this->read_ushort() . $this->read_ushort();
588 $this->skip(4);
589 $magic = $this->read_ulong();
591 throw new \Mpdf\Exception\FontException('Error loading font: Invalid head table magic ' . $magic);
593 $this->skip(2);
595 $this->skip(18);
597 $this->unitsPerEm = $unitsPerEm = $this->read_ushort();
599 $this->skip(16);
600 $xMin = $this->read_short();
601 $yMin = $this->read_short();
602 $xMax = $this->read_short();
603 $yMax = $this->read_short();
604 $this->bbox = [($xMin * $scale), ($yMin * $scale), ($xMax * $scale), ($yMax * $scale)];
605 $this->skip(3 * 2);
606 $indexToLocFormat = $this->read_ushort();
607 $glyphDataFormat = $this->read_ushort();
609 throw new \Mpdf\Exception\FontException('Error loading font: Unknown glyph data format ' . $glyphDataFormat);
615 // ttf2t1 seems to use this value rather than the one in OS/2 - so put in for compatibility
616 if (isset($this->tables["hhea"])) {
617 $this->seek_table("hhea");
618 $this->skip(4);
619 $hheaAscender = $this->read_short();
620 $hheaDescender = $this->read_short();
621 $this->ascent = ($hheaAscender * $scale);
622 $this->descent = ($hheaDescender * $scale);
626 // OS/2 - OS/2 and Windows metrics table
628 if (isset($this->tables["OS/2"])) {
629 $this->seek_table("OS/2");
630 $version = $this->read_ushort();
631 $this->skip(2);
632 $usWeightClass = $this->read_ushort();
633 $this->skip(2);
634 $fsType = $this->read_ushort();
638 throw new \Mpdf\Exception\FontException('Font file ' . $this->filename . ' cannot be embedded due to copyright restrictions.');
640 $this->restrictedUse = true;
642 $this->skip(20);
643 $sF = $this->read_short();
644 $this->sFamilyClass = ($sF >> 8);
645 $this->sFamilySubClass = ($sF & 0xFF);
646 $this->_pos += 10; //PANOSE = 10 byte length
647 $panose = fread($this->fh, 10);
648 $this->panose = [];
650 $this->panose[] = ord($panose[$p]);
652 $this->skip(26);
653 $sTypoAscender = $this->read_short();
654 $sTypoDescender = $this->read_short();
655 if (!$this->ascent) {
656 $this->ascent = ($sTypoAscender * $scale);
658 if (!$this->descent) {
659 $this->descent = ($sTypoDescender * $scale);
662 $this->skip(16);
663 $sCapHeight = $this->read_short();
664 $this->capHeight = ($sCapHeight * $scale);
666 $this->capHeight = $this->ascent;
670 if (!$this->ascent) {
671 $this->ascent = ($yMax * $scale);
673 if (!$this->descent) {
674 $this->descent = ($yMin * $scale);
676 $this->capHeight = $this->ascent;
678 $this->stemV = 50 + intval(pow(($usWeightClass / 65.0), 2));
681 // post - PostScript table
683 $this->seek_table("post");
685 $ver_maj = $this->read_ushort();
686 $ver_min = $this->read_ushort();
688 throw new \Mpdf\Exception\FontException('Error loading font: Unknown post table version ' . $ver_maj);
691 $this->skip(4);
693 $this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0;
694 $this->underlinePosition = $this->read_short() * $scale;
695 $this->underlineThickness = $this->read_short() * $scale;
696 $isFixedPitch = $this->read_ulong();
698 $this->flags = 4;
700 if ($this->italicAngle != 0) {
701 $this->flags = $this->flags | 64;
704 $this->flags = $this->flags | 262144;
707 $this->flags = $this->flags | 1;
711 // hhea - Horizontal header table
713 $this->seek_table("hhea");
715 $ver_maj = $this->read_ushort();
716 $ver_min = $this->read_ushort();
718 throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown hhea table version %s', $ver_maj));
720 $this->skip(28);
722 $this->skip(32);
724 $metricDataFormat = $this->read_ushort();
726 throw new \Mpdf\Exception\FontException('Error loading font: Unknown horizontal metric data format ' . $metricDataFormat);
728 $numberOfHMetrics = $this->read_ushort();
730 throw new \Mpdf\Exception\FontException('Error loading font: Number of horizontal metrics is 0');
734 // maxp - Maximum profile table
736 $this->seek_table("maxp");
738 $ver_maj = $this->read_ushort();
739 $ver_min = $this->read_ushort();
741 throw new \Mpdf\Exception\FontException('Error loading font: Unknown maxp table version ' . $ver_maj);
744 $this->skip(4);
746 $numGlyphs = $this->read_ushort();
749 // cmap - Character to glyph index mapping table
751 $cmap_offset = $this->seek_table("cmap");
752 $this->skip(2);
753 $cmapTableCount = $this->read_ushort();
756 $platformID = $this->read_ushort();
757 $encodingID = $this->read_ushort();
758 $offset = $this->read_ulong();
759 $save_pos = $this->_pos;
761 $format = $this->get_ushort($cmap_offset + $offset);
773 $format = $this->get_ushort($cmap_offset + $offset);
780 $this->seek($save_pos);
784 throw new \Mpdf\Exception\FontException('Font (' . $this->filename . ') does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)');
791 $this->GSUBScriptLang = [];
792 $this->rtlPUAstr = '';
793 $this->rtlPUAarr = [];
794 $this->GSUBFeatures = [];
795 $this->GSUBLookups = [];
796 $this->GPOSScriptLang = [];
797 $this->GPOSFeatures = [];
798 $this->GPOSLookups = [];
799 $this->glyphIDtoUni = '';
803 $this->maxUniChar = 0;
804 $this->seek($unicode_cmap_offset + 4);
805 $length = $this->read_ulong();
807 $this->skip(4);
809 $nGroups = $this->read_ulong();
814 $startCharCode = $this->read_ulong();
815 $endCharCode = $this->read_ulong();
816 $startGlyphCode = $this->read_ulong();
830 $this->maxUniChar = max($unichar, $this->maxUniChar);
838 $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph);
840 $this->sipset = $sipset;
841 $this->smpset = $smpset;
845 // Map Unmapped glyphs - from $numGlyphs
846 if ($this->useOTL) {
856 $this->sipset = $sipset = true; // forces subsetting; also ensure charwidths are saved
861 throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)', $this->filename));
866 $this->maxUniChar = max($bctr, $this->maxUniChar);
871 $this->glyphToChar = $glyphToChar;
872 $this->charToGlyph = $charToGlyph;
875 $this->GSUBScriptLang = [];
876 $this->rtlPUAstr = '';
877 $this->rtlPUAarr = [];
879 $this->_getGDEFtables();
880 list($this->GSUBScriptLang, $this->GSUBFeatures, $this->GSUBLookups, $this->rtlPUAstr, $this->rtlPUAarr) = $this->_getGSUBtables();
881 list($this->GPOSScriptLang, $this->GPOSFeatures, $this->GPOSLookups) = $this->_getGPOStables();
882 $this->glyphIDtoUni = str_pad('', 256 * 256 * 3, "\x00");
887 $this->glyphIDtoUni[$gid * 3] = chr($char >> 16);
888 $this->glyphIDtoUni[$gid * 3 + 1] = chr(($char >> 8) & 0xFF);
889 $this->glyphIDtoUni[$gid * 3 + 2] = chr($char & 0xFF);
896 // hmtx - Horizontal metrics table
898 $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale);
901 // kern - Kerning pair table
904 // Recognises old form of Kerning table - as required by Windows - Format 0 only
905 $kern_offset = $this->seek_table("kern");
906 $version = $this->read_ushort();
907 $nTables = $this->read_ushort();
909 $sversion = $this->read_ushort();
910 $slength = $this->read_ushort();
911 $scoverage = $this->read_ushort();
915 $nPairs = $this->read_ushort();
916 $this->skip(6);
918 $left = $this->read_ushort();
919 $right = $this->read_ushort();
920 $val = $this->read_short();
923 $this->kerninfo[$glyphToChar[$left][0]][$glyphToChar[$right][0]] = intval($val * $scale);
935 // GDEF - Glyph Definition
938 if (isset($this->tables["GDEF"])) {
939 if ($this->mode == 'summary') {
940 $this->mpdf->WriteHTML('<h1>GDEF table</h1>');
942 $gdef_offset = $this->seek_table("GDEF");
943 // ULONG Version of the GDEF table-currently 0x00010000
944 $ver_maj = $this->read_ushort();
945 $ver_min = $this->read_ushort();
947 $GlyphClassDef_offset = $this->read_ushort();
948 $AttachList_offset = $this->read_ushort();
949 $LigCaretList_offset = $this->read_ushort();
950 $MarkAttachClassDef_offset = $this->read_ushort();
952 $MarkGlyphSetsDef_offset = $this->read_ushort();
956 $this->seek($gdef_offset + $GlyphClassDef_offset);
960 3 Mark glyph (non-spacing combining glyph)
963 $GlyphByClass = $this->_getClassDefinitionTable();
965 if ($this->mode == 'summary') {
966 $this->mpdf->WriteHTML('<h2>Glyph classes</h2>');
970 $this->GlyphClassBases = $this->formatClassArr($GlyphByClass[1]);
971 if ($this->mode == 'summary') {
972 $this->mpdf->WriteHTML('<h3>Glyph class 1</h3>');
973 $this->mpdf->WriteHTML('<h5>Base glyph (single character, spacing glyph)</h5>');
980 $this->mpdf->WriteHTML($html);
983 $this->GlyphClassBases = '';
986 $this->GlyphClassLigatures = $this->formatClassArr($GlyphByClass[2]);
987 if ($this->mode == 'summary') {
988 $this->mpdf->WriteHTML('<h3>Glyph class 2</h3>');
989 $this->mpdf->WriteHTML('<h5>Ligature glyph (multiple character, spacing glyph)</h5>');
996 $this->mpdf->WriteHTML($html);
999 $this->GlyphClassLigatures = '';
1002 $this->GlyphClassMarks = $this->formatClassArr($GlyphByClass[3]);
1003 if ($this->mode == 'summary') {
1004 $this->mpdf->WriteHTML('<h3>Glyph class 3</h3>');
1005 $this->mpdf->WriteHTML('<h5>Mark glyph (non-spacing combining glyph)</h5>');
1012 $this->mpdf->WriteHTML($html);
1015 $this->GlyphClassMarks = '';
1018 $this->GlyphClassComponents = $this->formatClassArr($GlyphByClass[4]);
1019 if ($this->mode == 'summary') {
1020 $this->mpdf->WriteHTML('<h3>Glyph class 4</h3>');
1021 $this->mpdf->WriteHTML('<h5>Component glyph (part of single character, spacing glyph)</h5>');
1028 $this->mpdf->WriteHTML($html);
1031 $this->GlyphClassComponents = '';
1039 $this->seek($gdef_offset+$AttachList_offset );
1048 Offset Coverage Offset to Coverage table - from beginning of AttachList table
1050 Offset AttachPoint[GlyphCount] Array of offsets to AttachPoint tables-from beginning of AttachList table-in Coverage Index order
1057 uint16 PointIndex[PointCount] Array of contour point indices -in increasing numerical order
1059 See Example 3 - http://www.microsoft.com/typography/otspec/gdef.htm
1063 // The Ligature Caret List table (LigCaretList) defines caret positions for all the ligatures in a font.
1067 if ($this->mode == 'summary') {
1068 $this->mpdf->WriteHTML('<h1>Mark Attachment Types</h1>');
1070 $this->seek($gdef_offset + $MarkAttachClassDef_offset);
1071 $MarkAttachmentTypes = $this->_getClassDefinitionTable();
1080 $this->MarkAttachmentType[$class] = $this->formatClassArr($mat);
1082 if ($this->mode == 'summary') {
1083 $this->mpdf->WriteHTML('<h3>Mark Attachment Type: ' . $class . '</h3>');
1090 $this->mpdf->WriteHTML($html);
1094 $this->MarkAttachmentType = [];
1099 if ($this->mode == 'summary') {
1100 $this->mpdf->WriteHTML('<h1>Mark Glyph Sets</h1>');
1102 $this->seek($gdef_offset + $MarkGlyphSetsDef_offset);
1103 $MarkSetTableFormat = $this->read_ushort();
1104 $MarkSetCount = $this->read_ushort();
1107 $MarkSetOffset[] = $this->read_ulong();
1110 $this->seek($MarkSetOffset[$i]);
1111 $glyphs = $this->_getCoverage();
1112 $this->MarkGlyphSets[$i] = $this->formatClassArr($glyphs);
1113 if ($this->mode == 'summary') {
1114 $this->mpdf->WriteHTML('<h3>Mark Glyph Set class: ' . $i . '</h3>');
1121 $this->mpdf->WriteHTML($html);
1125 $this->MarkGlyphSets = [];
1128 $this->mpdf->WriteHTML('<div>GDEF table not defined</div>');
1131 //echo $this->GlyphClassMarks ; exit;
1140 $this->seek($offset);
1144 $ClassFormat = $this->read_ushort();
1147 $StartGlyph = $this->read_ushort();
1148 $GlyphCount = $this->read_ushort();
1151 $class = $this->read_ushort();
1152 $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]);
1156 $tableCount = $this->read_ushort();
1158 $startGlyphID = $this->read_ushort();
1159 $endGlyphID = $this->read_ushort();
1160 $class = $this->read_ushort();
1162 $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]);
1175 // GSUB - Glyph Substitution
1177 if (isset($this->tables["GSUB"])) {
1178 $this->mpdf->WriteHTML('<h1>GSUB Tables</h1>');
1180 $gsub_offset = $this->seek_table("GSUB");
1181 $this->skip(4);
1182 $ScriptList_offset = $gsub_offset + $this->read_ushort();
1183 $FeatureList_offset = $gsub_offset + $this->read_ushort();
1184 $LookupList_offset = $gsub_offset + $this->read_ushort();
1187 $this->seek($ScriptList_offset);
1188 $ScriptCount = $this->read_ushort();
1190 $ScriptTag = $this->read_tag(); // = "beng", "deva" etc.
1191 $ScriptTableOffset = $this->read_ushort();
1198 $this->seek($o);
1199 $DefLangSys_offset = $this->read_ushort();
1203 $LangSysCount = $this->read_ushort();
1205 $LangTag = $this->read_tag(); // =
1206 $LangTableOffset = $this->read_ushort();
1213 // LangSys Table - from first listed langsys
1218 $this->seek($langsystable_offset);
1219 $LookUpOrder = $this->read_ushort(); //==NULL
1220 $ReqFeatureIndex = $this->read_ushort();
1224 $FeatureCount = $this->read_ushort();
1226 $FeatureIndex[] = $this->read_ushort(); // = index of feature
1233 $this->seek($FeatureList_offset);
1234 $FeatureCount = $this->read_ushort();
1237 $Feature[$i] = ['tag' => $this->read_tag()];
1238 $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort();
1241 $this->seek($Feature[$i]['offset']);
1242 $this->read_ushort(); // null
1243 $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort();
1246 $Feature[$i]['LookupListIndex'][] = $this->read_ushort();
1281 if ($this->mode == 'summary') {
1282 $this->mpdf->WriteHTML('<h3>GSUB Scripts &amp; Languages</h3>');
1283 $this->mpdf->WriteHTML('<div class="glyphs">');
1299 $this->mpdf->WriteHTML($html);
1300 $this->mpdf->WriteHTML('</div>');
1307 $this->seek($LookupList_offset);
1308 $LookupCount = $this->read_ushort();
1313 $Offsets[$i] = $LookupList_offset + $this->read_ushort();
1316 $this->seek($Offsets[$i]);
1317 $GSLookup[$i]['Type'] = $this->read_ushort();
1318 $GSLookup[$i]['Flag'] = $flag = $this->read_ushort();
1319 $GSLookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort();
1321 $GSLookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort();
1325 $GSLookup[$i]['MarkFilteringSet'] = $this->read_ushort();
1330 // Overwrites new offset (32-bit) for each subtable, and a new lookup Type
1332 $this->seek($GSLookup[$i]['Subtables'][$c]);
1333 $ExtensionPosFormat = $this->read_ushort();
1334 $type = $this->read_ushort();
1335 $GSLookup[$i]['Subtables'][$c] = $GSLookup[$i]['Subtables'][$c] + $this->read_ulong();
1343 // Process Whole LookupList - Get LuCoverage = Lookup coverage just for first glyph
1344 $this->GSLuCoverage = [];
1347 $this->seek($GSLookup[$i]['Subtables'][$c]);
1348 $PosFormat = $this->read_ushort();
1351 $this->skip(4);
1354 $BacktrackGlyphCount = $this->read_ushort();
1355 $this->skip(2 * $BacktrackGlyphCount + 2);
1359 $Coverage = $GSLookup[$i]['Subtables'][$c] + $this->read_ushort();
1360 $this->seek($Coverage);
1361 $glyphs = $this->_getCoverage();
1362 $this->GSLuCoverage[$i][$c] = implode('|', $glyphs);
1366 // $this->GSLuCoverage and $GSLookup
1369 $GSLuCoverage = ' . var_export($this->GSLuCoverage, true) . ';
1374 $GlyphClassBases = \'' . $this->GlyphClassBases . '\';
1375 $GlyphClassMarks = \'' . $this->GlyphClassMarks . '\';
1376 $GlyphClassLigatures = \'' . $this->GlyphClassLigatures . '\';
1377 $GlyphClassComponents = \'' . $this->GlyphClassComponents . '\';
1378 $MarkGlyphSets = ' . var_export($this->MarkGlyphSets, true) . ';
1379 $MarkAttachmentType = ' . var_export($this->MarkAttachmentType, true) . ';
1390 $this->seek($LookupList_offset);
1391 $LookupCount = $this->read_ushort();
1394 $Lookup[$i]['offset'] = $LookupList_offset + $this->read_ushort();
1397 $this->seek($Lookup[$i]['offset']);
1398 $Lookup[$i]['Type'] = $this->read_ushort();
1399 $Lookup[$i]['Flag'] = $flag = $this->read_ushort();
1400 $Lookup[$i]['SubtableCount'] = $this->read_ushort();
1402 $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['offset'] + $this->read_ushort();
1406 $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort();
1413 // Overwrites new offset (32-bit) for each subtable, and a new lookup Type
1415 $this->seek($Lookup[$i]['Subtable'][$c]['Offset']);
1416 $ExtensionPosFormat = $this->read_ushort();
1417 $type = $this->read_ushort();
1418 $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ulong();
1429 $this->seek($Lookup[$i]['Subtable'][$c]['Offset']);
1430 $SubstFormat = $this->read_ushort();
1448 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1450 $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'] = $this->read_short();
1453 $GlyphCount = $this->read_ushort();
1455 $Lookup[$i]['Subtable'][$c]['Glyphs'][] = $this->read_ushort();
1462 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1463 $Lookup[$i]['Subtable'][$c]['SequenceCount'] = $SequenceCount = $this->read_short();
1465 $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short();
1469 $this->seek($Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset']);
1470 $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['GlyphCount'] = $this->read_short();
1472 $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['SubstituteGlyphID'][] = $this->read_ushort();
1478 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1479 $Lookup[$i]['Subtable'][$c]['AlternateSetCount'] = $AlternateSetCount = $this->read_short();
1481 $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short();
1486 $this->seek($Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset']);
1487 $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['GlyphCount'] = $this->read_short();
1489 $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['SubstituteGlyphID'][] = $this->read_ushort();
1495 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1496 $Lookup[$i]['Subtable'][$c]['LigSetCount'] = $LigSetCount = $this->read_short();
1498 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short();
1502 $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset']);
1503 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount'] = $this->read_short();
1505 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g] = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] + $this->read_ushort();
1511 $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g]);
1512 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph'] = $this->read_ushort();
1513 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount'] = $this->read_ushort();
1515 $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['GlyphID'][$l] = $this->read_ushort();
1524 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1525 $Lookup[$i]['Subtable'][$c]['SubRuleSetCount'] = $SubRuleSetCount = $this->read_short();
1527 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short();
1531 $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset']);
1532 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount'] = $this->read_short();
1534 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g] = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] + $this->read_ushort();
1541 $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g]);
1543 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['GlyphCount'] = $this->read_ushort();
1544 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstCount'] = $this->read_ushort();
1545 // "Input"::[GlyphCount - 1]::Array of input GlyphIDs-start with second glyph
1547 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['Input'][$l] = $this->read_ushort();
1549 // "SubstLookupRecord"::[SubstCount]::Array of SubstLookupRecords-in design order
1551 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['SequenceIndex'] = $this->read_ushort();
1552 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['LookupListIndex'] = $this->read_ushort();
1556 } // Format 2: Class-based Context Glyph Substitution
1559 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1560 $Lookup[$i]['Subtable'][$c]['ClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1561 $Lookup[$i]['Subtable'][$c]['SubClassSetCnt'] = $this->read_ushort();
1563 $offset = $this->read_ushort();
1579 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1580 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount'] = $this->read_ushort();
1582 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1584 } // Format 2: Class-based Chaining Context Glyph Substitution p257
1587 $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1588 $Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1589 $Lookup[$i]['Subtable'][$c]['InputClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1590 $Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1591 $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt'] = $this->read_ushort();
1593 $offset = $this->read_ushort();
1600 } // Format 3: Coverage-based Chaining Context Glyph Substitution p259
1603 $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount'] = $this->read_ushort();
1605 $Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1607 $Lookup[$i]['Subtable'][$c]['InputGlyphCount'] = $this->read_ushort();
1609 $Lookup[$i]['Subtable'][$c]['CoverageInput'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1611 $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount'] = $this->read_ushort();
1613 $Lookup[$i]['Subtable'][$c]['CoverageLookahead'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort();
1615 $Lookup[$i]['Subtable'][$c]['SubstCount'] = $this->read_ushort();
1617 $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex'] = $this->read_ushort();
1618 $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex'] = $this->read_ushort();
1647 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1648 $glyphs = $this->_getCoverage(false);
1652 $replace[] = unicode_hex($this->glyphToChar[$glyphs[$g]][0]);
1654 if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) {
1658 $substitute[] = unicode_hex($this->glyphToChar[($glyphs[$g] + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])][0]);
1660 $substitute[] = unicode_hex($this->glyphToChar[($Lookup[$i]['Subtable'][$c]['Glyphs'][$g])][0]);
1667 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1668 $glyphs = $this->_getCoverage();
1674 if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) {
1679 } // Illegal for GlyphCount to be 0; either error in font, or something has gone wrong - lets carry on for now!
1681 $substitute[] = unicode_hex($this->glyphToChar[$sub][0]);
1688 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1689 $glyphs = $this->_getCoverage();
1695 if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) {
1701 $substitute[] = unicode_hex($this->glyphToChar[$gid][0]);
1705 //$substitute[] = unicode_hex($this->glyphToChar[$gid][0]);
1716 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1717 $glyphs = $this->_getCoverage();
1725 if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) {
1730 $rpl = unicode_hex($this->glyphToChar[$gid][0]);
1732 if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $rpl, $Lookup[$i]['MarkFilteringSet'])) {
1738 $substitute[] = unicode_hex($this->glyphToChar[$gid][0]);
1747 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1748 $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage();
1757 $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]);
1761 } // Format 2: Class-based Context Glyph Substitution
1764 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1765 $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage();
1767 $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['ClassDefOffset']);
1772 $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s]);
1773 $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRuleCnt'] = $SubClassRuleCnt = $this->read_ushort();
1776 $SubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] + $this->read_ushort();
1786 $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b]);
1788 $Rule['InputGlyphCount'] = $this->read_ushort();
1789 $Rule['SubstCount'] = $this->read_ushort();
1791 $Rule['Input'][$r] = $this->read_ushort();
1794 $Rule['SequenceIndex'][$r] = $this->read_ushort();
1795 $Rule['LookupListIndex'][$r] = $this->read_ushort();
1802 } // Format 3: Coverage-based Context Glyph Substitution
1806 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]);
1807 $glyphs = $this->_getCoverage();
1810 throw new \Mpdf\Exception\FontException("Lookup Type 5, SubstFormat 3 not tested. Please report this with the name of font used - " . $this->fontkey);
1819 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1820 $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage();
1825 $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s]);
1826 $ChainSubRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleCount'] = $this->read_ushort();
1828 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r] = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s] + $this->read_ushort();
1835 $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r]);
1837 $BacktrackGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphCount'] = $this->read_ushort();
1839 $glyphID = $this->read_ushort();
1840 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]);
1843 $InputGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphCount'] = $this->read_ushort();
1845 $glyphID = $this->read_ushort();
1846 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]);
1849 $LookaheadGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphCount'] = $this->read_ushort();
1851 $glyphID = $this->read_ushort();
1852 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]);
1855 $SubstCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SubstCount'] = $this->read_ushort();
1857 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SequenceIndex'][$lu] = $this->read_ushort();
1858 $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookupListIndex'][$lu] = $this->read_ushort();
1862 } // Format 2: Class-based Chaining Context Glyph Substitution p257
1865 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']);
1866 $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage();
1868 $BacktrackClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset']);
1871 $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['InputClassDefOffset']);
1874 $LookaheadClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset']);
1879 $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s]);
1880 $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt'] = $ChainSubClassRuleCnt = $this->read_ushort();
1883 $ChainSubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] + $this->read_ushort();
1893 $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b]);
1895 $Rule['BacktrackGlyphCount'] = $this->read_ushort();
1897 $Rule['Backtrack'][$r] = $this->read_ushort();
1899 $Rule['InputGlyphCount'] = $this->read_ushort();
1901 $Rule['Input'][$r] = $this->read_ushort();
1903 $Rule['LookaheadGlyphCount'] = $this->read_ushort();
1905 $Rule['Lookahead'][$r] = $this->read_ushort();
1907 $Rule['SubstCount'] = $this->read_ushort();
1909 $Rule['SequenceIndex'][$r] = $this->read_ushort();
1910 $Rule['LookupListIndex'][$r] = $this->read_ushort();
1917 } // Format 3: Coverage-based Chaining Context Glyph Substitution p259
1921 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][$b]);
1922 $glyphs = $this->_getCoverage();
1926 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]);
1927 $glyphs = $this->_getCoverage();
1932 $this->seek($Lookup[$i]['Subtable'][$c]['CoverageLookahead'][$b]);
1933 $glyphs = $this->_getCoverage();
1952 $st = $this->mpdf->OTLscript;
1953 $t = $this->mpdf->OTLlang;
1964 $this->_getGSUBarray($Lookup, $lul, $st);
1977 // Process (3) LookupList for specific Script-LangSys
1990 $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']);
2022 $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . '&nbsp;</span> ';
2026 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($inputGlyphs[0]) . '</span>';
2034 $html .= '<span class="changed">&nbsp;' . $this->formatEntity($substitute) . '</span>';
2038 $html .= '&nbsp; <span class="unicode">' . $this->formatUni($substitute) . '</span> ';
2052 $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . '&nbsp;</span> ';
2056 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($inputGlyphs[0]) . '</span>';
2064 $html .= '<span class="changed">&nbsp;' . $this->formatEntityArr($substitute) . '</span>';
2068 $html .= '&nbsp; <span class="unicode">' . $this->formatUniArr($substitute) . '</span> ';
2082 $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . '&nbsp;</span> ';
2086 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($inputGlyphs[0]) . '</span>';
2094 $html .= '<span class="changed">&nbsp;' . $this->formatEntity($substitute) . '</span>';
2098 $html .= '&nbsp; <span class="unicode">' . $this->formatUni($substitute) . '</span> ';
2103 $html .= '<span class="changed">&nbsp;' . $this->formatEntity($substitute) . '</span>';
2104 $html .= '&nbsp; <span class="unicode">' . $this->formatUni($substitute) . '</span> ';
2120 $html .= '<span class="unicode">' . $this->formatUniArr($inputGlyphs) . '&nbsp;</span> ';
2124 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntityArr($inputGlyphs) . '</span>';
2132 $html .= '<span class="changed">&nbsp;' . $this->formatEntity($substitute) . '</span>';
2136 $html .= '&nbsp; <span class="unicode">' . $this->formatUni($substitute) . '</span> ';
2164 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2165 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2179 $exB .= $this->formatEntity($inputGlyphs[$ip]) . '&#x200d;';
2186 $exL .= $this->formatEntity($inputGlyphs[$ip]) . '&#x200d;';
2198 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2206 } // Format 2: Class-based Context Glyph Substitution
2209 $html .= '<div class="lookuptypesub">Format 2: Class-based Context Glyph Substitution</div>';
2235 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;[NOT ' . $this->formatEntityStr($class0excl) . ']&nbsp;</span></div>';
2236 $exampleI[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']';
2238 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2239 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2258 $exB .= $this->formatEntityFirst($inputGlyphs[$ip]) . '&#x200d;';
2270 $exL .= $this->formatEntityFirst($inputGlyphs[$ip]) . '&#x200d;';
2284 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2291 } // Format 3: Coverage-based Context Glyph Substitution p259
2294 $html .= '<div class="lookuptypesub">Format 3: Coverage-based Context Glyph Substitution </div>';
2303 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2304 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2338 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2348 //print_r($volt[(count($volt)-1)]); exit;
2388 for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) {
2389 $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>';
2390 $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]);
2393 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2394 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2397 $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>';
2398 $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]);
2416 $exB .= $this->formatEntity($inputGlyphs[$ip]) . '&#x200d;';
2424 $exL .= $this->formatEntity($inputGlyphs[$ip]) . '&#x200d;';
2441 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2449 } // Format 2: Class-based Chaining Context Glyph Substitution p257
2452 $html .= '<div class="lookuptypesub">Format 2: Class-based Chaining Context Glyph Substitution </div>';
2503 for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) {
2505 $html .= '<div>Backtrack #' . $ff . ': <span class="unchanged">&nbsp;[NOT ' . $this->formatEntityStr($class0excl) . ']&nbsp;</span></div>';
2506 $exampleB[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']';
2508 $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>';
2509 $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]);
2514 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;[NOT ' . $this->formatEntityStr($class0excl) . ']&nbsp;</span></div>';
2515 $exampleI[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']';
2517 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2518 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2523 $html .= '<div>Lookahead #' . $ff . ': <span class="unchanged">&nbsp;[NOT ' . $this->formatEntityStr($class0excl) . ']&nbsp;</span></div>';
2524 $exampleL[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']';
2526 $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>';
2527 $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]);
2549 $exB .= $this->formatEntityFirst($inputGlyphs[$ip]) . '&#x200d;';
2561 $exL .= $this->formatEntityFirst($inputGlyphs[$ip]) . '&#x200d;';
2579 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2585 } // Format 3: Coverage-based Chaining Context Glyph Substitution p259
2588 $html .= '<div class="lookuptypesub">Format 3: Coverage-based Chaining Context Glyph Substitution </div>';
2610 for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) {
2611 $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>';
2612 $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]);
2615 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
2616 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
2619 $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>';
2620 $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]);
2663 $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
2678 $this->mpdf->WriteHTML($html);
2692 if ((($flag & 0x0008) == 0x0008) && strpos($this->GlyphClassMarks, $glyph)) {
2695 if ((($flag & 0x0004) == 0x0004) && strpos($this->GlyphClassLigatures, $glyph)) {
2698 if ((($flag & 0x0002) == 0x0002) && strpos($this->GlyphClassBases, $glyph)) {
2702 if (($flag & 0xFF00) && strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) {
2706 if (($flag & 0x0010) && strpos($this->MarkGlyphSets[$MarkFilteringSet], $glyph)) {
2715 // If ignoreFlag set, combine all ignore glyphs into -> "((?:(?: FBA1| FBA2| FBA3))*)"
2717 // for Input - set on secondary Lookup table if in Context, and set Backtrack and Lookahead on Context Lookup
2725 //$str = $this->MarkAttachmentType[$MarkAttachmentType];
2731 throw new \Mpdf\Exception\FontException("This font " . $this->fontkey . " contains MarkGlyphSets");
2733 $str .= $this->MarkGlyphSets[$MarkFilteringSet];
2740 //$str = $this->GlyphClassMarks;
2750 //$str .= $this->GlyphClassLigatures;
2759 //$str .= $this->GlyphClassBases;
2775 ---------------- ---------------- ----- ------------ --------------- ---------------
2777 -------- --- --------- --- ---- --- ---- --- --------- --- -------
2783 "\${1}\${2} " (nInput*2)-1 "\${5+} \${6+}"
2793 ----- ------------ ------------ ------------ ------------
2804 A - "REPL\${2} \${3}\${4} \${5}\${6} \${7}\${8} \${9}"
2805 B - "REPL\${2}\${4} \${5}\${6} \${7}\${8} \${9}"
2806 C - "REPL\${2}\${4}\${6} \${7}\${8} \${9}"
2807 D - "\${1} REPL\${2}\${4}\${6} \${7}\${8} \${9}"
2808 E - "\${1} REPL\${2}\${4}\${6}\${8} \${9}"
2809 F - "\${1}\${2} \${3}\${4} \${5} REPL\${6}\${8}"
2826 $str .= "" . $lookupGlyphs[($i - $seqIndex)] . "";
2840 // $lookupGlyphs = array of glyphs making up Lookup Input sequence - if applicable
2846 $str .= "" . $inputGlyphs[($i - 1)] . "";
2860 for ($i = (count($backtrackGlyphs) - 1); $i >= 0; $i--) {
2889 // $mLen nGlyphs in the secondary Lookup match - if no secondary lookup, should=$nInput
2906 $str .= '\\' . ($nBsubs + (2 * ($x - 1)));
2915 $str .= '\\' . ($nBsubs + (2 * ($x - 1)));
2917 $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1)));
2926 $str .= '\\' . ($nBsubs + (2 * ($x - 1)));
2931 $str .= '\\' . ($nBsubs + (2 * ($x - 1)));
2933 $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1)));
2946 $CoverageFormat = $this->read_ushort();
2948 $CoverageGlyphCount = $this->read_ushort();
2950 $glyphID = $this->read_ushort();
2952 $g[] = unicode_hex($this->glyphToChar[$glyphID][0]);
2959 $RangeCount = $this->read_ushort();
2961 $start = $this->read_ushort();
2962 $end = $this->read_ushort();
2963 $StartCoverageIndex = $this->read_ushort(); // n/a
2967 $g[] = unicode_hex($this->glyphToChar[$glyphID][0]);
2981 $this->seek($offset);
2982 $ClassFormat = $this->read_ushort();
2985 $StartGlyph = $this->read_ushort();
2986 $GlyphCount = $this->read_ushort();
2990 $class = $this->read_ushort();
2992 if ($this->glyphToChar[$g][0]) {
2993 $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]);
2999 $tableCount = $this->read_ushort();
3001 $startGlyphID = $this->read_ushort();
3002 $endGlyphID = $this->read_ushort();
3003 $class = $this->read_ushort();
3005 if ($this->glyphToChar[$g][0]) {
3006 $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]);
3028 // GPOS - Glyph Positioning
3030 if (isset($this->tables["GPOS"])) {
3031 $this->mpdf->WriteHTML('<h1>GPOS Tables</h1>');
3033 $gpos_offset = $this->seek_table("GPOS");
3034 $this->skip(4);
3035 $ScriptList_offset = $gpos_offset + $this->read_ushort();
3036 $FeatureList_offset = $gpos_offset + $this->read_ushort();
3037 $LookupList_offset = $gpos_offset + $this->read_ushort();
3040 $this->seek($ScriptList_offset);
3041 $ScriptCount = $this->read_ushort();
3043 $ScriptTag = $this->read_tag(); // = "beng", "deva" etc.
3044 $ScriptTableOffset = $this->read_ushort();
3051 $this->seek($o);
3052 $DefLangSys_offset = $this->read_ushort();
3056 $LangSysCount = $this->read_ushort();
3058 $LangTag = $this->read_tag(); // =
3059 $LangTableOffset = $this->read_ushort();
3066 // LangSys Table - from first listed langsys
3071 $this->seek($langsystable_offset);
3072 $LookUpOrder = $this->read_ushort(); //==NULL
3073 $ReqFeatureIndex = $this->read_ushort();
3077 $FeatureCount = $this->read_ushort();
3079 $FeatureIndex[] = $this->read_ushort(); // = index of feature
3086 $this->seek($FeatureList_offset);
3087 $FeatureCount = $this->read_ushort();
3090 $Feature[$i] = ['tag' => $this->read_tag()];
3091 $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort();
3094 $this->seek($Feature[$i]['offset']);
3095 $this->read_ushort(); // null
3096 $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort();
3099 $Feature[$i]['LookupListIndex'][] = $this->read_ushort();
3132 if ($this->mode == 'summary') {
3133 $this->mpdf->WriteHTML('<h3>GPOS Scripts &amp; Languages</h3>');
3149 $this->mpdf->WriteHTML($html);
3150 $this->mpdf->WriteHTML('</div>');
3157 $this->seek($LookupList_offset);
3158 $LookupCount = $this->read_ushort();
3163 $Offsets[$i] = $LookupList_offset + $this->read_ushort();
3166 $this->seek($Offsets[$i]);
3167 $Lookup[$i]['Type'] = $this->read_ushort();
3168 $Lookup[$i]['Flag'] = $flag = $this->read_ushort();
3169 $Lookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort();
3171 $Lookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort();
3175 $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort();
3180 // Overwrites new offset (32-bit) for each subtable, and a new lookup Type
3182 $this->seek($Lookup[$i]['Subtables'][$c]);
3183 $ExtensionPosFormat = $this->read_ushort();
3184 $type = $this->read_ushort();
3185 $Lookup[$i]['Subtables'][$c] = $Lookup[$i]['Subtables'][$c] + $this->read_ulong();
3193 $st = $this->mpdf->OTLscript;
3194 $t = $this->mpdf->OTLlang;
3207 $this->_getGPOSarray($Lookup, $lul, $st);
3223 // Process (3) LookupList for specific Script-LangSys
3235 $ignore = $this->_getGSUBignoreString($Lookup[$luli]['Flag'], $Lookup[$luli]['MarkFilteringSet']);
3257 $this->seek($subtable_offset);
3258 $PosFormat = $this->read_ushort();
3269 $Coverage = $subtable_offset + $this->read_ushort();
3270 $ValueFormat = $this->read_ushort();
3271 $Value = $this->_getValueRecord($ValueFormat);
3273 $this->seek($Coverage);
3274 $glyphs = $this->_getCoverage(); // Array of Hex Glyphs
3281 $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . '&nbsp;</span> ';
3285 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
3293 $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
3315 $Coverage = $subtable_offset + $this->read_ushort();
3316 $ValueFormat = $this->read_ushort();
3317 $ValueCount = $this->read_ushort();
3320 $Values[] = $this->_getValueRecord($ValueFormat);
3323 $this->seek($Coverage);
3324 $glyphs = $this->_getCoverage(); // Array of Hex Glyphs
3333 $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . '&nbsp;</span> ';
3337 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
3345 $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
3370 $Coverage = $subtable_offset + $this->read_ushort();
3371 $ValueFormat1 = $this->read_ushort();
3372 $ValueFormat2 = $this->read_ushort();
3377 $PairSetCount = $this->read_ushort();
3380 $PairSetOffset[] = $subtable_offset + $this->read_ushort();
3382 $this->seek($Coverage);
3383 $glyphs = $this->_getCoverage(); // Array of Hex Glyphs
3388 $this->seek($PairSetOffset[$p]);
3390 // Takes too long e.g. Calibri font - just list kerning pairs with this:
3392 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$p]) . ' </span>';
3395 $PairValueCount = $this->read_ushort();
3398 $gid = $this->read_ushort();
3399 $SecondGlyph = unicode_hex($this->glyphToChar[$gid][0]);
3400 $Value1 = $this->_getValueRecord($ValueFormat1);
3401 $Value2 = $this->_getValueRecord($ValueFormat2);
3403 // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take
3406 $Value1['XPlacement'] -= $Value1['XAdvance'];
3410 // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take
3413 $Value2['XPlacement'] -= $Value2['XAdvance'];
3417 $html .= ' ' . $this->formatEntity($SecondGlyph) . ' ';
3421 $html .= '<span class="unicode">'.$this->formatUni($glyphs[$p]).'&nbsp;</span> ';
3423 $html .= '<span class="unchanged">&nbsp;'.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>';
3427 $html .= '<span class="changed" style="font-feature-settings:\''.$tag.'\' 1;">&nbsp;'.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>';
3447 $ClassDef1 = $subtable_offset + $this->read_ushort();
3448 $ClassDef2 = $subtable_offset + $this->read_ushort();
3449 $Class1Count = $this->read_ushort();
3450 $Class2Count = $this->read_ushort();
3452 $sizeOfPair = (2 * $this->count_bits($ValueFormat1)) + (2 * $this->count_bits($ValueFormat2));
3456 // i.e. Class1Count = 5; Class1 will contain array(indices 1-4);
3457 $Class1 = $this->_getClassDefinitionTable($ClassDef1);
3458 $Class2 = $this->_getClassDefinitionTable($ClassDef2);
3460 $this->seek($subtable_offset + 16);
3464 $Value1 = $this->_getValueRecord($ValueFormat1);
3465 $Value2 = $this->_getValueRecord($ValueFormat2);
3467 // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180
3470 $Value1['XPlacement'] -= $Value1['XAdvance'];
3474 $Value2['XPlacement'] -= $Value2['XAdvance'];
3492 $html .= '<span class="unicode">' . $this->formatUni($FirstGlyph) . '&nbsp;</span> ';
3496 $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>';
3504 $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>';
3541 $Coverage = $subtable_offset + $this->read_ushort();
3542 $EntryExitCount = $this->read_ushort();
3546 $EntryAnchors[$i] = $this->read_ushort();
3547 $ExitAnchors[$i] = $this->read_ushort();
3550 $this->seek($Coverage);
3551 $Glyphs = $this->_getCoverage();
3554 $pdfWidth = $this->mpdf->_getCharWidth($this->mpdf->fonts[$this->fontkey]['cw'], hexdec($Glyphs[$i]));
3558 $html .= '<span class="unchanged">' . $this->formatEntity($Glyphs[$i]) . ' </span> ';
3559 $html .= '<span class="unicode"> ' . $this->formatUni($Glyphs[$i]) . ' => ';
3563 list($x, $y) = $this->_getAnchorTable($EntryAnchor);
3565 if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) {
3568 $x = $x - ($pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000);
3575 list($x, $y) = $this->_getAnchorTable($ExitAnchor);
3577 if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) {
3580 $x = $x - ($pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000);
3594 $MarkCoverage = $subtable_offset + $this->read_ushort();
3595 $BaseCoverage = $subtable_offset + $this->read_ushort();
3597 $this->seek($MarkCoverage);
3598 $MarkGlyphs = $this->_getCoverage();
3600 $this->seek($BaseCoverage);
3601 $BaseGlyphs = $this->_getCoverage();
3613 $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' ';
3622 $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . ' ';
3627 $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): ';
3629 $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . $this->formatEntity($firstMark, true) . ' &nbsp; ';
3638 $MarkCoverage = $subtable_offset + $this->read_ushort();
3640 $LigatureCoverage = $subtable_offset + $this->read_ushort();
3641 $ClassCount = $this->read_ushort(); // Number of classes defined for marks = Number of mark glyphs in the MarkCoverage table
3642 $MarkArray = $subtable_offset + $this->read_ushort(); // Offset to MarkArray table
3643 $LigatureArray = $subtable_offset + $this->read_ushort(); // Offset to LigatureArray table
3645 $this->seek($MarkCoverage);
3646 $MarkGlyphs = $this->_getCoverage();
3647 $this->seek($LigatureCoverage);
3648 $LigatureGlyphs = $this->_getCoverage();
3662 $MarkRecord[$i] = $this->_getMarkRecord($MarkArray, $i);
3664 $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' ';
3671 $this->seek($LigatureArray);
3672 $LigatureCount = $this->read_ushort();
3677 $LigatureAttach[$j] = $LigatureArray + $this->read_ushort();
3678 $html .= ' ' . $this->formatEntity($LigatureGlyphs[$j]) . ' ';
3685 $html .= '<span class="unchanged">'.$this->formatEntity($MarkGlyphs[$i]).'</span>';
3688 $this->seek($LigatureAttach[$j]);
3689 $ComponentCount = $this->read_ushort();
3690 $html .= '<span class="unchanged">'.$this->formatEntity($LigatureGlyphs[$j]).'</span>';
3695 $offset = $this->read_ushort();
3713 $Mark1Coverage = $subtable_offset + $this->read_ushort(); // Combining Mark
3715 $Mark2Coverage = $subtable_offset + $this->read_ushort(); // Base Mark
3716 $ClassCount = $this->read_ushort(); // Number of classes defined for marks = No. of Combining mark1 glyphs in the MarkCoverage table
3717 $this->seek($Mark1Coverage);
3718 $Mark1Glyphs = $this->_getCoverage();
3719 $this->seek($Mark2Coverage);
3720 $Mark2Glyphs = $this->_getCoverage();
3732 $html .= ' ' . $this->formatEntity($Mark1Glyphs[$i]) . ' ';
3739 $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . ' ';
3744 $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): <span class="changed">';
3746 $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . $this->formatEntity($firstMark, true) . ' &nbsp; ';
3796 /* NB When developing - cf. GSUB 6.2 */
3803 $BacktrackGlyphCount = $this->read_ushort();
3806 $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order
3808 $InputGlyphCount = $this->read_ushort();
3811 $CoverageInputOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order
3813 $LookaheadGlyphCount = $this->read_ushort();
3816 $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order
3818 $PosCount = $this->read_ushort();
3823 $PosLookupRecord[$p]['SequenceIndex'] = $this->read_ushort();
3824 $PosLookupRecord[$p]['LookupListIndex'] = $this->read_ushort();
3829 $this->seek($CoverageBacktrackOffset[$b]);
3830 $backtrackGlyphs[$b] = implode('|', $this->_getCoverage());
3834 $this->seek($CoverageInputOffset[$b]);
3835 $inputGlyphs[$b] = implode('|', $this->_getCoverage());
3839 $this->seek($CoverageLookaheadOffset[$b]);
3840 $lookaheadGlyphs[$b] = implode('|', $this->_getCoverage());
3847 for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) {
3848 $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>';
3849 $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]);
3852 $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
3853 $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
3856 $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>';
3857 $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]);
3900 $html .= $this->_getGPOSarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
3917 $this->mpdf->WriteHTML($html);
3932 $n &= $n - 1; // clear the least significant bit set
3943 // Horizontal adjustment for placement-in design units
3945 $vra['XPlacement'] = $this->read_short();
3947 // Vertical adjustment for placement-in design units
3949 $vra['YPlacement'] = $this->read_short();
3951 // Horizontal adjustment for advance-in design units (only used for horizontal writing)
3953 $vra['XAdvance'] = $this->read_short();
3955 // Vertical adjustment for advance-in design units (only used for vertical writing)
3957 $this->read_short();
3959 // Offset to Device table for horizontal placement-measured from beginning of PosTable (may be NULL)
3961 $this->read_ushort();
3963 // Offset to Device table for vertical placement-measured from beginning of PosTable (may be NULL)
3965 $this->read_ushort();
3967 // Offset to Device table for horizontal advance-measured from beginning of PosTable (may be NULL)
3969 $this->read_ushort();
3971 // Offset to Device table for vertical advance-measured from beginning of PosTable (may be NULL)
3973 $this->read_ushort();
3982 $this->seek($offset);
3984 $AnchorFormat = $this->read_ushort();
3985 $XCoordinate = $this->read_short();
3986 $YCoordinate = $this->read_short();
3994 $this->seek($offset);
3995 $MarkCount = $this->read_ushort();
3996 $this->skip($MarkPos * 4);
3997 $Class = $this->read_ushort();
3998 $MarkAnchor = $offset + $this->read_ushort(); // = Offset to anchor table
3999 list($x, $y) = $this->_getAnchorTable($MarkAnchor);
4011 if (count($this->glyphdata[$originalGlyphIdx]['compGlyphs'])) {
4012 foreach ($this->glyphdata[$originalGlyphIdx]['compGlyphs'] as $glyphIdx) {
4013 $this->getGlyphData($glyphIdx, $maxdepth, $depth, $points, $contours);
4016 if (($this->glyphdata[$originalGlyphIdx]['nContours'] > 0) && $depth > 0) { // simple
4017 $contours += $this->glyphdata[$originalGlyphIdx]['nContours'];
4018 $points += $this->glyphdata[$originalGlyphIdx]['nPoints'];
4021 $depth--;
4028 $glyphPos = $this->glyphPos[$originalGlyphIdx];
4029 $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos;
4033 $this->seek($start + $glyphPos);
4034 $numberOfContours = $this->read_short();
4036 $this->skip(8);
4039 $flags = $this->read_ushort();
4041 $glyphIdx = $this->read_ushort();
4046 $savepos = ftell($this->fh);
4047 $this->getGlyphs($glyphIdx, $start, $glyphSet, $subsetglyphs);
4048 $this->seek($savepos);
4050 $this->skip(4);
4052 $this->skip(2);
4055 $this->skip(2);
4058 $this->skip(4);
4061 $this->skip(8);
4073 $start = $this->seek_table("hmtx");
4075 $this->charWidths = str_pad('', 256 * 256 * 2, "\x00");
4076 if ($this->maxUniChar > 65536) {
4077 $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00");
4079 if ($this->maxUniChar > 131072) {
4080 $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00");
4083 if (($numberOfHMetrics * 4) < $this->maxStrLenRead) {
4084 $data = $this->get_chunk($start, ($numberOfHMetrics * 4));
4087 $this->seek($start);
4090 if (($numberOfHMetrics * 4) < $this->maxStrLenRead) {
4093 $aw = $this->read_ushort();
4094 $lsb = $this->read_ushort();
4099 } // 1.03 Some (arabic) fonts have -ve values for width
4100 // although should be unsigned value - comes out as e.g. 65108 (intended -50)
4102 $this->defaultWidth = $scale * $aw;
4106 //$this->charWidths[$char] = intval(round($scale*$aw));
4113 $this->charWidths[$char * 2] = chr($w >> 8);
4114 $this->charWidths[$char * 2 + 1] = chr($w & 0xFF);
4121 $data = $this->get_chunk(($start + $numberOfHMetrics * 4), ($numGlyphs * 2));
4123 $diff = $numGlyphs - $numberOfHMetrics;
4134 $this->charWidths[$char * 2] = chr($w >> 8);
4135 $this->charWidths[$char * 2 + 1] = chr($w & 0xFF);
4143 // First bytes define number of chars in font
4144 $this->charWidths[0] = chr($nCharWidths >> 8);
4145 $this->charWidths[1] = chr($nCharWidths & 0xFF);
4150 $start = $this->seek_table("hmtx");
4152 $this->seek($start + ($gid * 4));
4153 $hm = fread($this->fh, 4);
4155 $this->seek($start + (($numberOfHMetrics - 1) * 4));
4156 $hm = fread($this->fh, 2);
4157 $this->seek($start + ($numberOfHMetrics * 2) + ($gid * 2));
4158 $hm .= fread($this->fh, 2);
4166 $start = $this->seek_table('loca');
4167 $this->glyphPos = [];
4169 $data = $this->get_chunk($start, ($numGlyphs * 2) + 2);
4172 $this->glyphPos[] = ($arr[$n + 1] * 2);
4176 $data = $this->get_chunk($start, ($numGlyphs * 4) + 4);
4179 $this->glyphPos[] = ($arr[$n + 1]);
4190 $this->maxUniChar = 0;
4191 $this->seek($unicode_cmap_offset + 2);
4192 $length = $this->read_ushort();
4194 $this->skip(2);
4196 $segCount = $this->read_ushort() / 2;
4197 $this->skip(6);
4200 $endCount[] = $this->read_ushort();
4202 $this->skip(2);
4205 $startCount[] = $this->read_ushort();
4209 $idDelta[] = $this->read_short();
4211 $idRangeOffset_start = $this->_pos;
4214 $idRangeOffset[] = $this->read_ushort();
4223 $offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n];
4228 $glyph = $this->get_ushort($offset);
4236 $this->maxUniChar = max($unichar, $this->maxUniChar);
4250 } // E000 - F8FF, 1E000-1F000
4262 if (strpos($this->GlyphClassMarks, $char) !== false) {
4279 } // E000 - F8FF, 1E000-1F000
4295 if (strpos($this->GlyphClassMarks, $c) !== false) {
4312 } // E000 - F8FF, 1E000-1F000
4331 } // E000 - F8FF, 1E000-1F000
4348 if (strpos($this->GlyphClassMarks, $c) !== false) {
4362 if (strpos($this->GlyphClassMarks, $char) !== false) {