function _getClasses($offset)
 {
     $this->seek($offset);
     $ClassFormat = $this->read_ushort();
     $GlyphByClass = array();
     if ($ClassFormat == 1) {
         $StartGlyph = $this->read_ushort();
         $GlyphCount = $this->read_ushort();
         for ($i = 0; $i < $GlyphCount; $i++) {
             $startGlyphID = $StartGlyph + $i;
             $endGlyphID = $StartGlyph + $i;
             $class = $this->read_ushort();
             for ($g = $startGlyphID; $g <= $endGlyphID; $g++) {
                 if (isset($this->glyphToChar[$g][0])) {
                     $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]);
                 }
             }
         }
     } else {
         if ($ClassFormat == 2) {
             $tableCount = $this->read_ushort();
             for ($i = 0; $i < $tableCount; $i++) {
                 $startGlyphID = $this->read_ushort();
                 $endGlyphID = $this->read_ushort();
                 $class = $this->read_ushort();
                 for ($g = $startGlyphID; $g <= $endGlyphID; $g++) {
                     if ($this->glyphToChar[$g][0]) {
                         $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]);
                     }
                 }
             }
         }
     }
     $gbc = array();
     foreach ($GlyphByClass as $class => $garr) {
         $gbc[$class] = implode('|', $garr);
     }
     return $gbc;
 }
Exemple #2
0
 function _getGPOSarray(&$Lookup, $lul, $scripttag, $level = 1, $lcoverage = '', $exB = '', $exL = '')
 {
     // Process (3) LookupList for specific Script-LangSys
     $html = '';
     if ($level == 1) {
         $html .= '<bookmark level="0" content="GPOS features">';
     }
     foreach ($lul as $luli => $tag) {
         $html .= '<div class="level' . $level . '">';
         $html .= '<h5 class="level' . $level . '">';
         if ($level == 1) {
             $html .= '<bookmark level="1" content="' . $tag . ' [#' . $luli . ']">';
         }
         $html .= 'Lookup #' . $luli . ' [tag: <span style="color:#000066;">' . $tag . '</span>]</h5>';
         $ignore = $this->_getGSUBignoreString($Lookup[$luli]['Flag'], $Lookup[$luli]['MarkFilteringSet']);
         if ($ignore) {
             $html .= '<div class="ignore">Ignoring: ' . $ignore . '</div> ';
         }
         $Type = $Lookup[$luli]['Type'];
         $Flag = $Lookup[$luli]['Flag'];
         if (($Flag & 0x1) == 1) {
             $dir = 'RTL';
         } else {
             $dir = 'LTR';
         }
         for ($c = 0; $c < $Lookup[$luli]['SubtableCount']; $c++) {
             $html .= '<div class="subtable">Subtable #' . $c;
             if ($level == 1) {
                 $html .= '<bookmark level="2" content="Subtable #' . $c . '">';
             }
             $html .= '</div>';
             // Lets start
             $subtable_offset = $Lookup[$luli]['Subtables'][$c];
             $this->seek($subtable_offset);
             $PosFormat = $this->read_ushort();
             ////////////////////////////////////////////////////////////////////////////////
             // LookupType 1: Single adjustment 	Adjust position of a single glyph (e.g. SmallCaps/Sups/Subs)
             ////////////////////////////////////////////////////////////////////////////////
             if ($Lookup[$luli]['Type'] == 1) {
                 $html .= '<div class="lookuptype">LookupType 1: Single adjustment [Format ' . $PosFormat . ']</div>';
                 //===========
                 // Format 1:
                 //===========
                 if ($PosFormat == 1) {
                     $Coverage = $subtable_offset + $this->read_ushort();
                     $ValueFormat = $this->read_ushort();
                     $Value = $this->_getValueRecord($ValueFormat);
                     $this->seek($Coverage);
                     $glyphs = $this->_getCoverage();
                     // Array of Hex Glyphs
                     for ($g = 0; $g < count($glyphs); $g++) {
                         if ($level == 2 && strpos($lcoverage, $glyphs[$g]) === false) {
                             continue;
                         }
                         $html .= '<div class="substitution">';
                         $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . '&nbsp;</span> ';
                         if ($level == 2 && $exB) {
                             $html .= $exB;
                         }
                         $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
                         if ($level == 2 && $exL) {
                             $html .= $exL;
                         }
                         $html .= '&nbsp; &raquo; &raquo; &nbsp;';
                         if ($level == 2 && $exB) {
                             $html .= $exB;
                         }
                         $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
                         if ($level == 2 && $exL) {
                             $html .= $exL;
                         }
                         $html .= ' <span class="unicode">';
                         if ($Value['XPlacement']) {
                             $html .= ' Xpl: ' . $Value['XPlacement'] . ';';
                         }
                         if ($Value['YPlacement']) {
                             $html .= ' YPl: ' . $Value['YPlacement'] . ';';
                         }
                         if ($Value['XAdvance']) {
                             $html .= ' Xadv: ' . $Value['XAdvance'];
                         }
                         $html .= '</span>';
                         $html .= '</div>';
                     }
                 } else {
                     if ($PosFormat == 2) {
                         $Coverage = $subtable_offset + $this->read_ushort();
                         $ValueFormat = $this->read_ushort();
                         $ValueCount = $this->read_ushort();
                         $Values = array();
                         for ($v = 0; $v < $ValueCount; $v++) {
                             $Values[] = $this->_getValueRecord($ValueFormat);
                         }
                         $this->seek($Coverage);
                         $glyphs = $this->_getCoverage();
                         // Array of Hex Glyphs
                         for ($g = 0; $g < count($glyphs); $g++) {
                             if ($level == 2 && strpos($lcoverage, $glyphs[$g]) === false) {
                                 continue;
                             }
                             $Value = $Values[$g];
                             $html .= '<div class="substitution">';
                             $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . '&nbsp;</span> ';
                             if ($level == 2 && $exB) {
                                 $html .= $exB;
                             }
                             $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
                             if ($level == 2 && $exL) {
                                 $html .= $exL;
                             }
                             $html .= '&nbsp; &raquo; &raquo; &nbsp;';
                             if ($level == 2 && $exB) {
                                 $html .= $exB;
                             }
                             $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($glyphs[$g]) . '</span>';
                             if ($level == 2 && $exL) {
                                 $html .= $exL;
                             }
                             $html .= ' <span class="unicode">';
                             if ($Value['XPlacement']) {
                                 $html .= ' Xpl: ' . $Value['XPlacement'] . ';';
                             }
                             if ($Value['YPlacement']) {
                                 $html .= ' YPl: ' . $Value['YPlacement'] . ';';
                             }
                             if ($Value['XAdvance']) {
                                 $html .= ' Xadv: ' . $Value['XAdvance'];
                             }
                             $html .= '</span>';
                             $html .= '</div>';
                         }
                     }
                 }
             } else {
                 if ($Lookup[$luli]['Type'] == 2) {
                     $html .= '<div class="lookuptype">LookupType 2: Pair adjustment e.g. Kerning [Format ' . $PosFormat . ']</div>';
                     $Coverage = $subtable_offset + $this->read_ushort();
                     $ValueFormat1 = $this->read_ushort();
                     $ValueFormat2 = $this->read_ushort();
                     //===========
                     // Format 1:
                     //===========
                     if ($PosFormat == 1) {
                         $PairSetCount = $this->read_ushort();
                         $PairSetOffset = array();
                         for ($p = 0; $p < $PairSetCount; $p++) {
                             $PairSetOffset[] = $subtable_offset + $this->read_ushort();
                         }
                         $this->seek($Coverage);
                         $glyphs = $this->_getCoverage();
                         // Array of Hex Glyphs
                         for ($p = 0; $p < $PairSetCount; $p++) {
                             if ($level == 2 && strpos($lcoverage, $glyphs[$p]) === false) {
                                 continue;
                             }
                             $this->seek($PairSetOffset[$p]);
                             // First Glyph = $glyphs[$p]
                             // Takes too long e.g. Calibri font - just list kerning pairs with this:
                             $html .= '<div class="glyphs">';
                             $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($glyphs[$p]) . ' </span>';
                             //PairSet table
                             $PairValueCount = $this->read_ushort();
                             for ($pv = 0; $pv < $PairValueCount; $pv++) {
                                 //PairValueRecord
                                 $gid = $this->read_ushort();
                                 $SecondGlyph = unicode_hex($this->glyphToChar[$gid][0]);
                                 $Value1 = $this->_getValueRecord($ValueFormat1);
                                 $Value2 = $this->_getValueRecord($ValueFormat2);
                                 // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take
                                 // account of direction. mPDF does not need the XPlacement adjustment
                                 if ($dir == 'RTL' && $Value1['XPlacement']) {
                                     $Value1['XPlacement'] -= $Value1['XAdvance'];
                                 }
                                 if ($ValueFormat2) {
                                     // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take
                                     // account of direction. mPDF does not need the XPlacement adjustment
                                     if ($dir == 'RTL' && $Value2['XPlacement'] && $Value2['XAdvance']) {
                                         $Value2['XPlacement'] -= $Value2['XAdvance'];
                                     }
                                 }
                                 $html .= ' ' . $this->formatEntity($SecondGlyph) . ' ';
                                 /*
                                 									$html .= '<div class="substitution">';
                                 									$html .= '<span class="unicode">'.$this->formatUni($glyphs[$p]).'&nbsp;</span> ';
                                 									if ($level==2 && $exB) { $html .= $exB; }
                                 									$html .= '<span class="unchanged">&nbsp;'.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>';
                                 									if ($level==2 && $exL) { $html .= $exL; }
                                 									$html .= '&nbsp; &raquo; &raquo; &nbsp;';
                                 									if ($level==2 && $exB) { $html .= $exB; }
                                 									$html .= '<span class="changed" style="font-feature-settings:\''.$tag.'\' 1;">&nbsp;'.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>';
                                 									if ($level==2 && $exL) { $html .= $exL; }
                                 									$html .= ' <span class="unicode">';
                                 									if ($Value1['XPlacement']) { $html .= ' Xpl[1]: '.$Value1['XPlacement'].';'; }
                                 									if ($Value1['YPlacement']) { $html .= ' YPl[1]: '.$Value1['YPlacement'].';'; }
                                 									if ($Value1['XAdvance']) { $html .= ' Xadv[1]: '.$Value1['XAdvance']; }
                                 									if ($Value2['XPlacement']) { $html .= ' Xpl[2]: '.$Value2['XPlacement'].';'; }
                                 									if ($Value2['YPlacement']) { $html .= ' YPl[2]: '.$Value2['YPlacement'].';'; }
                                 									if ($Value2['XAdvance']) { $html .= ' Xadv[2]: '.$Value2['XAdvance']; }
                                 									$html .= '</span>';
                                 									$html .= '</div>'; 
                                 */
                             }
                             $html .= '</div>';
                         }
                     } else {
                         if ($PosFormat == 2) {
                             $ClassDef1 = $subtable_offset + $this->read_ushort();
                             $ClassDef2 = $subtable_offset + $this->read_ushort();
                             $Class1Count = $this->read_ushort();
                             $Class2Count = $this->read_ushort();
                             $sizeOfPair = 2 * $this->count_bits($ValueFormat1) + 2 * $this->count_bits($ValueFormat2);
                             $sizeOfValueRecords = $Class1Count * $Class2Count * $sizeOfPair;
                             // NB Class1Count includes Class 0 even though it is not defined by $ClassDef1
                             // i.e. Class1Count = 5; Class1 will contain array(indices 1-4);
                             $Class1 = $this->_getClassDefinitionTable($ClassDef1);
                             $Class2 = $this->_getClassDefinitionTable($ClassDef2);
                             $this->seek($subtable_offset + 16);
                             for ($i = 0; $i < $Class1Count; $i++) {
                                 for ($j = 0; $j < $Class2Count; $j++) {
                                     $Value1 = $this->_getValueRecord($ValueFormat1);
                                     $Value2 = $this->_getValueRecord($ValueFormat2);
                                     // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180
                                     // of direction. mPDF does not need the XPlacement adjustment
                                     if ($dir == 'RTL' && $Value1['XPlacement'] && $Value1['XAdvance']) {
                                         $Value1['XPlacement'] -= $Value1['XAdvance'];
                                     }
                                     if ($ValueFormat2) {
                                         if ($dir == 'RTL' && $Value2['XPlacement'] && $Value2['XAdvance']) {
                                             $Value2['XPlacement'] -= $Value2['XAdvance'];
                                         }
                                     }
                                     for ($c1 = 0; $c1 < count($Class1[$i]); $c1++) {
                                         $FirstGlyph = $Class1[$i][$c1];
                                         if ($level == 2 && strpos($lcoverage, $FirstGlyph) === false) {
                                             continue;
                                         }
                                         for ($c2 = 0; $c2 < count($Class2[$j]); $c2++) {
                                             $SecondGlyph = $Class2[$j][$c2];
                                             if (!$Value1['XPlacement'] && !$Value1['YPlacement'] && !$Value1['XAdvance'] && !$Value2['XPlacement'] && !$Value2['YPlacement'] && !$Value2['XAdvance']) {
                                                 continue;
                                             }
                                             $html .= '<div class="substitution">';
                                             $html .= '<span class="unicode">' . $this->formatUni($FirstGlyph) . '&nbsp;</span> ';
                                             if ($level == 2 && $exB) {
                                                 $html .= $exB;
                                             }
                                             $html .= '<span class="unchanged">&nbsp;' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>';
                                             if ($level == 2 && $exL) {
                                                 $html .= $exL;
                                             }
                                             $html .= '&nbsp; &raquo; &raquo; &nbsp;';
                                             if ($level == 2 && $exB) {
                                                 $html .= $exB;
                                             }
                                             $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;">&nbsp;' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>';
                                             if ($level == 2 && $exL) {
                                                 $html .= $exL;
                                             }
                                             $html .= ' <span class="unicode">';
                                             if ($Value1['XPlacement']) {
                                                 $html .= ' Xpl[1]: ' . $Value1['XPlacement'] . ';';
                                             }
                                             if ($Value1['YPlacement']) {
                                                 $html .= ' YPl[1]: ' . $Value1['YPlacement'] . ';';
                                             }
                                             if ($Value1['XAdvance']) {
                                                 $html .= ' Xadv[1]: ' . $Value1['XAdvance'];
                                             }
                                             if ($Value2['XPlacement']) {
                                                 $html .= ' Xpl[2]: ' . $Value2['XPlacement'] . ';';
                                             }
                                             if ($Value2['YPlacement']) {
                                                 $html .= ' YPl[2]: ' . $Value2['YPlacement'] . ';';
                                             }
                                             if ($Value2['XAdvance']) {
                                                 $html .= ' Xadv[2]: ' . $Value2['XAdvance'];
                                             }
                                             $html .= '</span>';
                                             $html .= '</div>';
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 } else {
                     if ($Lookup[$luli]['Type'] == 3) {
                         $html .= '<div class="lookuptype">LookupType 3: Cursive attachment </div>';
                         $Coverage = $subtable_offset + $this->read_ushort();
                         $EntryExitCount = $this->read_ushort();
                         $EntryAnchors = array();
                         $ExitAnchors = array();
                         for ($i = 0; $i < $EntryExitCount; $i++) {
                             $EntryAnchors[$i] = $this->read_ushort();
                             $ExitAnchors[$i] = $this->read_ushort();
                         }
                         $this->seek($Coverage);
                         $Glyphs = $this->_getCoverage();
                         for ($i = 0; $i < $EntryExitCount; $i++) {
                             // Need default XAdvance for glyph
                             $pdfWidth = $this->mpdf->_getCharWidth($this->mpdf->fonts[$this->fontkey]['cw'], hexdec($Glyphs[$i]));
                             $EntryAnchor = $EntryAnchors[$i];
                             $ExitAnchor = $ExitAnchors[$i];
                             $html .= '<div class="glyphs">';
                             $html .= '<span class="unchanged">' . $this->formatEntity($Glyphs[$i]) . ' </span> ';
                             $html .= '<span class="unicode"> ' . $this->formatUni($Glyphs[$i]) . ' => ';
                             if ($EntryAnchor != 0) {
                                 $EntryAnchor += $subtable_offset;
                                 list($x, $y) = $this->_getAnchorTable($EntryAnchor);
                                 if ($dir == 'RTL') {
                                     if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) {
                                         $x = 0;
                                     } else {
                                         $x = $x - $pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000;
                                     }
                                 }
                                 $html .= " Entry X: " . $x . " Y: " . $y . "; ";
                             }
                             if ($ExitAnchor != 0) {
                                 $ExitAnchor += $subtable_offset;
                                 list($x, $y) = $this->_getAnchorTable($ExitAnchor);
                                 if ($dir == 'LTR') {
                                     if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) {
                                         $x = 0;
                                     } else {
                                         $x = $x - $pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000;
                                     }
                                 }
                                 $html .= " Exit X: " . $x . " Y: " . $y . "; ";
                             }
                             $html .= '</span></div>';
                         }
                     } else {
                         if ($Lookup[$luli]['Type'] == 4) {
                             $html .= '<div class="lookuptype">LookupType 4: MarkToBase attachment </div>';
                             $MarkCoverage = $subtable_offset + $this->read_ushort();
                             $BaseCoverage = $subtable_offset + $this->read_ushort();
                             $this->seek($MarkCoverage);
                             $MarkGlyphs = $this->_getCoverage();
                             $this->seek($BaseCoverage);
                             $BaseGlyphs = $this->_getCoverage();
                             $firstMark = '';
                             $html .= '<div class="glyphs">Marks: ';
                             for ($i = 0; $i < count($MarkGlyphs); $i++) {
                                 if ($level == 2 && strpos($lcoverage, $MarkGlyphs[$i]) === false) {
                                     continue;
                                 } else {
                                     if (!$firstMark) {
                                         $firstMark = $MarkGlyphs[$i];
                                     }
                                 }
                                 $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' ';
                             }
                             $html .= '</div>';
                             if (!$firstMark) {
                                 return;
                             }
                             $html .= '<div class="glyphs">Bases: ';
                             for ($j = 0; $j < count($BaseGlyphs); $j++) {
                                 $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . ' ';
                             }
                             $html .= '</div>';
                             // Example
                             $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): ';
                             for ($j = 0; $j < min(count($BaseGlyphs), 20); $j++) {
                                 $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . $this->formatEntity($firstMark, true) . ' &nbsp; ';
                             }
                             $html .= '</div>';
                         } else {
                             if ($Lookup[$luli]['Type'] == 5) {
                                 $html .= '<div class="lookuptype">LookupType 5: MarkToLigature attachment </div>';
                                 $MarkCoverage = $subtable_offset + $this->read_ushort();
                                 //$MarkCoverage is already set in $lcoverage 00065|00073 etc
                                 $LigatureCoverage = $subtable_offset + $this->read_ushort();
                                 $ClassCount = $this->read_ushort();
                                 // Number of classes defined for marks = Number of mark glyphs in the MarkCoverage table
                                 $MarkArray = $subtable_offset + $this->read_ushort();
                                 // Offset to MarkArray table
                                 $LigatureArray = $subtable_offset + $this->read_ushort();
                                 // Offset to LigatureArray table
                                 $this->seek($MarkCoverage);
                                 $MarkGlyphs = $this->_getCoverage();
                                 $this->seek($LigatureCoverage);
                                 $LigatureGlyphs = $this->_getCoverage();
                                 $firstMark = '';
                                 $html .= '<div class="glyphs">Marks: <span class="unchanged">';
                                 $MarkRecord = array();
                                 for ($i = 0; $i < count($MarkGlyphs); $i++) {
                                     if ($level == 2 && strpos($lcoverage, $MarkGlyphs[$i]) === false) {
                                         continue;
                                     } else {
                                         if (!$firstMark) {
                                             $firstMark = $MarkGlyphs[$i];
                                         }
                                     }
                                     // Get the relevant MarkRecord
                                     $MarkRecord[$i] = $this->_getMarkRecord($MarkArray, $i);
                                     //Mark Class is = $MarkRecord[$i]['Class']
                                     $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' ';
                                 }
                                 $html .= '</span></div>';
                                 if (!$firstMark) {
                                     return;
                                 }
                                 $this->seek($LigatureArray);
                                 $LigatureCount = $this->read_ushort();
                                 $LigatureAttach = array();
                                 $html .= '<div class="glyphs">Ligatures: <span class="unchanged">';
                                 for ($j = 0; $j < count($LigatureGlyphs); $j++) {
                                     // Get the relevant LigatureRecord
                                     $LigatureAttach[$j] = $LigatureArray + $this->read_ushort();
                                     $html .= ' ' . $this->formatEntity($LigatureGlyphs[$j]) . ' ';
                                 }
                                 $html .= '</span></div>';
                                 /*
                                 						for ($i=0;$i<count($MarkGlyphs);$i++) {
                                 							$html .= '<div class="glyphs">';
                                 							$html .= '<span class="unchanged">'.$this->formatEntity($MarkGlyphs[$i]).'</span>';
                                 
                                 							for ($j=0;$j<count($LigatureGlyphs);$j++) {
                                 								$this->seek($LigatureAttach[$j]);
                                 								$ComponentCount = $this->read_ushort();
                                 								$html .= '<span class="unchanged">'.$this->formatEntity($LigatureGlyphs[$j]).'</span>';
                                 								$offsets = array();
                                 								for ($comp=0;$comp<$ComponentCount;$comp++) {
                                 									// ComponentRecords
                                 									for ($class=0;$class<$ClassCount;$class++) {
                                 										$offset = $this->read_ushort();
                                 										if ($offset!= 0 && $class == $MarkRecord[$i]['Class']) {
                                 
                                 											$html .= ' ['.$comp.'] ';
                                 
                                 										}
                                 									}
                                 								}
                                 							}
                                 							$html .= '</span></div>';
                                 						}
                                 */
                             } else {
                                 if ($Lookup[$luli]['Type'] == 6) {
                                     $html .= '<div class="lookuptype">LookupType 6: MarkToMark attachment </div>';
                                     $Mark1Coverage = $subtable_offset + $this->read_ushort();
                                     // Combining Mark
                                     //$Mark1Coverage is already set in $LuCoverage 0065|0073 etc
                                     $Mark2Coverage = $subtable_offset + $this->read_ushort();
                                     // Base Mark
                                     $ClassCount = $this->read_ushort();
                                     // Number of classes defined for marks = No. of Combining mark1 glyphs in the MarkCoverage table
                                     $this->seek($Mark1Coverage);
                                     $Mark1Glyphs = $this->_getCoverage();
                                     $this->seek($Mark2Coverage);
                                     $Mark2Glyphs = $this->_getCoverage();
                                     $firstMark = '';
                                     $html .= '<div class="glyphs">Marks: <span class="unchanged">';
                                     for ($i = 0; $i < count($Mark1Glyphs); $i++) {
                                         if ($level == 2 && strpos($lcoverage, $Mark1Glyphs[$i]) === false) {
                                             continue;
                                         } else {
                                             if (!$firstMark) {
                                                 $firstMark = $Mark1Glyphs[$i];
                                             }
                                         }
                                         $html .= ' ' . $this->formatEntity($Mark1Glyphs[$i]) . ' ';
                                     }
                                     $html .= '</span></div>';
                                     if ($firstMark) {
                                         $html .= '<div class="glyphs">Bases: <span class="unchanged">';
                                         for ($j = 0; $j < count($Mark2Glyphs); $j++) {
                                             $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . ' ';
                                         }
                                         $html .= '</span></div>';
                                         // Example
                                         $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): <span class="changed">';
                                         for ($j = 0; $j < min(count($Mark2Glyphs), 20); $j++) {
                                             $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . $this->formatEntity($firstMark, true) . ' &nbsp; ';
                                         }
                                         $html .= '</span></div>';
                                     }
                                 } else {
                                     if ($Lookup[$luli]['Type'] == 7) {
                                         $html .= '<div class="lookuptype">LookupType 7: Context positioning [Format ' . $PosFormat . ']</div>';
                                         //===========
                                         // Format 1:
                                         //===========
                                         if ($PosFormat == 1) {
                                             die("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED.");
                                         } else {
                                             if ($PosFormat == 2) {
                                                 die("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED.");
                                             } else {
                                                 if ($PosFormat == 3) {
                                                     die("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED.");
                                                 } else {
                                                     die("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported.");
                                                 }
                                             }
                                         }
                                     } else {
                                         if ($Lookup[$luli]['Type'] == 8) {
                                             $html .= '<div class="lookuptype">LookupType 8: Chained Context positioning [Format ' . $PosFormat . ']</div>';
                                             //===========
                                             // Format 1:
                                             //===========
                                             if ($PosFormat == 1) {
                                                 die("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET.");
                                             } else {
                                                 if ($PosFormat == 2) {
                                                     $html .= '<div>GPOS Lookup Type 8: Format 2 not yet supported in OTL dump</div>';
                                                     continue;
                                                     /* NB When developing - cf. GSUB 6.2 */
                                                     die("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET.");
                                                 } else {
                                                     if ($PosFormat == 3) {
                                                         $BacktrackGlyphCount = $this->read_ushort();
                                                         $CoverageBacktrackOffset = array();
                                                         for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
                                                             $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort();
                                                             // in glyph sequence order
                                                         }
                                                         $InputGlyphCount = $this->read_ushort();
                                                         $CoverageInputOffset = array();
                                                         for ($b = 0; $b < $InputGlyphCount; $b++) {
                                                             $CoverageInputOffset[] = $subtable_offset + $this->read_ushort();
                                                             // in glyph sequence order
                                                         }
                                                         $LookaheadGlyphCount = $this->read_ushort();
                                                         $CoverageLookaheadOffset = array();
                                                         for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
                                                             $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort();
                                                             // in glyph sequence order
                                                         }
                                                         $PosCount = $this->read_ushort();
                                                         $PosLookupRecord = array();
                                                         for ($p = 0; $p < $PosCount; $p++) {
                                                             // PosLookupRecord
                                                             $PosLookupRecord[$p]['SequenceIndex'] = $this->read_ushort();
                                                             $PosLookupRecord[$p]['LookupListIndex'] = $this->read_ushort();
                                                         }
                                                         $backtrackGlyphs = array();
                                                         for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
                                                             $this->seek($CoverageBacktrackOffset[$b]);
                                                             $backtrackGlyphs[$b] = implode('|', $this->_getCoverage());
                                                         }
                                                         $inputGlyphs = array();
                                                         for ($b = 0; $b < $InputGlyphCount; $b++) {
                                                             $this->seek($CoverageInputOffset[$b]);
                                                             $inputGlyphs[$b] = implode('|', $this->_getCoverage());
                                                         }
                                                         $lookaheadGlyphs = array();
                                                         for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
                                                             $this->seek($CoverageLookaheadOffset[$b]);
                                                             $lookaheadGlyphs[$b] = implode('|', $this->_getCoverage());
                                                         }
                                                         $exampleB = array();
                                                         $exampleI = array();
                                                         $exampleL = array();
                                                         $html .= '<div class="context">CONTEXT: ';
                                                         for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) {
                                                             $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>';
                                                             $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]);
                                                         }
                                                         for ($ff = 0; $ff < count($inputGlyphs); $ff++) {
                                                             $html .= '<div>Input #' . $ff . ': <span class="unchanged">&nbsp;' . $this->formatEntityStr($inputGlyphs[$ff]) . '&nbsp;</span></div>';
                                                             $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]);
                                                         }
                                                         for ($ff = 0; $ff < count($lookaheadGlyphs); $ff++) {
                                                             $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>';
                                                             $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]);
                                                         }
                                                         $html .= '</div>';
                                                         for ($p = 0; $p < $PosCount; $p++) {
                                                             $lup = $PosLookupRecord[$p]['LookupListIndex'];
                                                             $seqIndex = $PosLookupRecord[$p]['SequenceIndex'];
                                                             // GENERATE exampleB[n] exampleI[<seqIndex] .... exampleI[>seqIndex] exampleL[n]
                                                             $exB = '';
                                                             $exL = '';
                                                             if (count($exampleB)) {
                                                                 $exB .= '<span class="backtrack">' . implode('&#x200d;', $exampleB) . '</span>';
                                                             }
                                                             if ($seqIndex > 0) {
                                                                 $exB .= '<span class="inputother">';
                                                                 for ($ip = 0; $ip < $seqIndex; $ip++) {
                                                                     $exB .= $exampleI[$ip] . '&#x200d;';
                                                                 }
                                                                 $exB .= '</span>';
                                                             }
                                                             if (count($inputGlyphs) > $seqIndex + 1) {
                                                                 $exL .= '<span class="inputother">';
                                                                 for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) {
                                                                     $exL .= '&#x200d;' . $exampleI[$ip];
                                                                 }
                                                                 $exL .= '</span>';
                                                             }
                                                             if (count($exampleL)) {
                                                                 $exL .= '<span class="lookahead">' . implode('&#x200d;', $exampleL) . '</span>';
                                                             }
                                                             $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>';
                                                             $lul2 = array($lup => $tag);
                                                             // Only apply if the (first) 'Replace' glyph from the
                                                             // Lookup list is in the [inputGlyphs] at ['SequenceIndex']
                                                             // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656
                                                             // to level 2 and only apply if first Replace glyph is in this list
                                                             $html .= $this->_getGPOSarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL);
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         $html .= '</div>';
     }
     if ($level == 1) {
         $this->mpdf->WriteHTML($html);
     } else {
         return $html;
     }
     //print_r($Lookup); exit;
 }