66         public static function addTTFfont($fontfile, $fonttype=
'', $enc=
'', $flags=32, $outpath=
'', $platid=3, $encid=1, $addcbbox=
false, $link=
false) {
 
   67                 if (!file_exists($fontfile)) {
 
   74                 $font_path_parts = pathinfo($fontfile);
 
   75                 if (!isset($font_path_parts[
'filename'])) {
 
   76                         $font_path_parts[
'filename'] = substr($font_path_parts[
'basename'], 0, -(strlen($font_path_parts[
'extension']) + 1));
 
   78                 $font_name = strtolower($font_path_parts[
'filename']);
 
   79                 $font_name = preg_replace(
'/[^a-z0-9_]/', 
'', $font_name);
 
   80                 $search  = array(
'bold', 
'oblique', 
'italic', 
'regular');
 
   81                 $replace = array(
'b', 
'i', 
'i', 
'');
 
   82                 $font_name = str_replace($search, $replace, $font_name);
 
   83                 if (empty($font_name)) {
 
   85                         $font_name = 
'tcpdffont';
 
   88                 if (empty($outpath)) {
 
   92                 if (file_exists($outpath.$font_name.
'.php')) {
 
   96                 $fmetric[
'file'] = $font_name;
 
   97                 $fmetric[
'ctg'] = $font_name.
'.ctg.z';
 
   99                 $font = file_get_contents($fontfile);
 
  100                 $fmetric[
'originalsize'] = strlen($font);
 
  102                 if (empty($fonttype)) {
 
  105                                 $fonttype = 
'TrueTypeUnicode';
 
  106                         } elseif (substr($font, 0, 4) == 
'OTTO') {
 
  121                                 $fmetric[
'type'] = 
'cidfont0';
 
  125                                 $fmetric[
'type'] = 
'Type1';
 
  126                                 if (empty($enc) AND (($flags & 4) == 0)) {
 
  132                                 $fmetric[
'type'] = 
'TrueType';
 
  135                         case 'TrueTypeUnicode':
 
  137                                 $fmetric[
'type'] = 
'TrueTypeUnicode';
 
  142                 $fmetric[
'enc'] = preg_replace(
'/[^A-Za-z0-9_\-]/', 
'', $enc);
 
  143                 $fmetric[
'diff'] = 
'';
 
  144                 if (($fmetric[
'type'] == 
'TrueType') OR ($fmetric[
'type'] == 
'Type1')) {
 
  150                                 for ($i = 32; $i <= 255; ++$i) {
 
  151                                         if ($enc_target != $enc_ref[$i]) {
 
  152                                                 if ($i != ($last + 1)) {
 
  153                                                         $fmetric[
'diff'] .= $i.
' ';
 
  156                                                 $fmetric[
'diff'] .= 
'/'.$enc_target[$i].
' ';
 
  162                 if ($fmetric[
'type'] == 
'Type1') {
 
  165                         $a = unpack(
'Cmarker/Ctype/Vsize', substr($font, 0, 6));
 
  166                         if ($a[
'marker'] != 128) {
 
  170                         $fmetric[
'size1'] = $a[
'size'];
 
  171                         $data = substr($font, 6, $fmetric[
'size1']);
 
  173                         $a = unpack(
'Cmarker/Ctype/Vsize', substr($font, (6 + $fmetric[
'size1']), 6));
 
  174                         if ($a[
'marker'] != 128) {
 
  178                         $fmetric[
'size2'] = $a[
'size'];
 
  179                         $encrypted = substr($font, (12 + $fmetric[
'size1']), $fmetric[
'size2']);
 
  182                         $fmetric[
'file'] .= 
'.z';
 
  183                         $fp = fopen($outpath.$fmetric[
'file'], 
'wb');
 
  184                         fwrite($fp, gzcompress($data));
 
  187                         $fmetric[
'Flags'] = $flags;
 
  188                         preg_match (
'#/FullName[\s]*\(([^\)]*)#', $font, $matches);
 
  189                         $fmetric[
'name'] = preg_replace(
'/[^a-zA-Z0-9_\-]/', 
'', $matches[1]);
 
  190                         preg_match(
'#/FontBBox[\s]*{([^}]*)#', $font, $matches);
 
  191                         $fmetric[
'bbox'] = trim($matches[1]);
 
  192                         $bv = explode(
' ', $fmetric[
'bbox']);
 
  193                         $fmetric[
'Ascent'] = intval($bv[3]);
 
  194                         $fmetric[
'Descent'] = intval($bv[1]);
 
  195                         preg_match(
'#/ItalicAngle[\s]*([0-9\+\-]*)#', $font, $matches);
 
  196                         $fmetric[
'italicAngle'] = intval($matches[1]);
 
  197                         if ($fmetric[
'italicAngle'] != 0) {
 
  198                                 $fmetric[
'Flags'] |= 64;
 
  200                         preg_match(
'#/UnderlinePosition[\s]*([0-9\+\-]*)#', $font, $matches);
 
  201                         $fmetric[
'underlinePosition'] = intval($matches[1]);
 
  202                         preg_match(
'#/UnderlineThickness[\s]*([0-9\+\-]*)#', $font, $matches);
 
  203                         $fmetric[
'underlineThickness'] = intval($matches[1]);
 
  204                         preg_match(
'#/isFixedPitch[\s]*([^\s]*)#', $font, $matches);
 
  205                         if ($matches[1] == 
'true') {
 
  206                                 $fmetric[
'Flags'] |= 1;
 
  210                         if (preg_match_all(
'#dup[\s]([0-9]+)[\s]*/([^\s]*)[\s]put#sU', $font, $fmap, PREG_SET_ORDER) > 0) {
 
  211                                 foreach ($fmap as $v) {
 
  212                                         $imap[$v[2]] = $v[1];
 
  219                         $elen = strlen($encrypted);
 
  221                         for ($i = 0; $i < $elen; ++$i) {
 
  222                                 $chr = ord($encrypted[$i]);
 
  223                                 $eplain .= chr($chr ^ ($r >> 8));
 
  224                                 $r = ((($chr + $r) * $c1 + $c2) % 65536);
 
  226                         if (preg_match(
'#/ForceBold[\s]*([^\s]*)#', $eplain, $matches) > 0) {
 
  227                                 if ($matches[1] == 
'true') {
 
  228                                         $fmetric[
'Flags'] |= 0x40000;
 
  231                         if (preg_match(
'#/StdVW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
 
  232                                 $fmetric[
'StemV'] = intval($matches[1]);
 
  234                                 $fmetric[
'StemV'] = 70;
 
  236                         if (preg_match(
'#/StdHW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
 
  237                                 $fmetric[
'StemH'] = intval($matches[1]);
 
  239                                 $fmetric[
'StemH'] = 30;
 
  241                         if (preg_match(
'#/BlueValues[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
 
  242                                 $bv = explode(
' ', $matches[1]);
 
  243                                 if (count($bv) >= 6) {
 
  244                                         $v1 = intval($bv[2]);
 
  245                                         $v2 = intval($bv[4]);
 
  247                                                 $fmetric[
'XHeight'] = $v1;
 
  248                                                 $fmetric[
'CapHeight'] = $v2;
 
  250                                                 $fmetric[
'XHeight'] = $v2;
 
  251                                                 $fmetric[
'CapHeight'] = $v1;
 
  254                                         $fmetric[
'XHeight'] = 450;
 
  255                                         $fmetric[
'CapHeight'] = 700;
 
  258                                 $fmetric[
'XHeight'] = 450;
 
  259                                 $fmetric[
'CapHeight'] = 700;
 
  262                         if (preg_match(
'#/lenIV[\s]*([0-9]*)#', $eplain, $matches) > 0) {
 
  263                                 $lenIV = intval($matches[1]);
 
  267                         $fmetric[
'Leading'] = 0;
 
  269                         $eplain = substr($eplain, (strpos($eplain, 
'/CharStrings') + 1));
 
  270                         preg_match_all(
'#/([A-Za-z0-9\.]*)[\s][0-9]+[\s]RD[\s](.*)[\s]ND#sU', $eplain, $matches, PREG_SET_ORDER);
 
  277                         $fmetric[
'MaxWidth'] = 0;
 
  279                         foreach ($matches as $k => $v) {
 
  281                                 if (isset($imap[$v[1]])) {
 
  283                                 } elseif ($enc_map !== 
false) {
 
  284                                         $cid = array_search($v[1], $enc_map);
 
  285                                         if ($cid === 
false) {
 
  287                                         } elseif ($cid > 1000) {
 
  298                                 for ($i = 0; $i < $clen; ++$i) {
 
  300                                         $ccom[] = ($chr ^ ($r >> 8));
 
  301                                         $r = ((($chr + $r) * $c1 + $c2) % 65536);
 
  308                                         if ($ccom[$i] < 32) {
 
  309                                                 $cdec[$ck] = $ccom[$i];
 
  310                                                 if (($ck > 0) AND ($cdec[$ck] == 13)) {
 
  312                                                         $cwidths[$cid] = $cdec[($ck - 1)];
 
  315                                         } elseif (($ccom[$i] >= 32) AND ($ccom[$i] <= 246)) {
 
  316                                                 $cdec[$ck] = ($ccom[$i] - 139);
 
  318                                         } elseif (($ccom[$i] >= 247) AND ($ccom[$i] <= 250)) {
 
  319                                                 $cdec[$ck] = ((($ccom[$i] - 247) * 256) + $ccom[($i + 1)] + 108);
 
  321                                         } elseif (($ccom[$i] >= 251) AND ($ccom[$i] <= 254)) {
 
  322                                                 $cdec[$ck] = ((-($ccom[$i] - 251) * 256) - $ccom[($i + 1)] - 108);
 
  324                                         } elseif ($ccom[$i] == 255) {
 
  325                                                 $sval = chr($ccom[($i + 1)]).chr($ccom[($i + 2)]).chr($ccom[($i + 3)]).chr($ccom[($i + 4)]);
 
  326                                                 $vsval = unpack(
'li', $sval);
 
  327                                                 $cdec[$ck] = $vsval[
'i'];
 
  333                         $fmetric[
'MissingWidth'] = $cwidths[0];
 
  334                         $fmetric[
'MaxWidth'] = $fmetric[
'MissingWidth'];
 
  335                         $fmetric[
'AvgWidth'] = 0;
 
  337                         for ($cid = 0; $cid <= 255; ++$cid) {
 
  338                                 if (isset($cwidths[$cid])) {
 
  339                                         if ($cwidths[$cid] > $fmetric[
'MaxWidth']) {
 
  340                                                 $fmetric[
'MaxWidth'] = $cwidths[$cid];
 
  342                                         $fmetric[
'AvgWidth'] += $cwidths[$cid];
 
  343                                         $fmetric[
'cw'] .= 
','.$cid.
'=>'.$cwidths[$cid];
 
  345                                         $fmetric[
'cw'] .= 
','.$cid.
'=>'.$fmetric[
'MissingWidth'];
 
  348                         $fmetric[
'AvgWidth'] = round($fmetric[
'AvgWidth'] / count($cwidths));
 
  351                         if ($fmetric[
'type'] != 
'cidfont0') {
 
  354                                         symlink($fontfile, $outpath.$fmetric[
'file']);
 
  357                                         $fmetric[
'file'] .= 
'.z';
 
  358                                         $fp = fopen($outpath.$fmetric[
'file'], 
'wb');
 
  359                                         fwrite($fp, gzcompress($font));
 
  377                         for ($i = 0; $i < $numTables; ++$i) {
 
  379                                 $tag = substr($font, $offset, 4);
 
  381                                 $table[$tag] = array();
 
  390                         $offset = $table[
'head'][
'offset'] + 12;
 
  401                         $urk = (1000 / $fmetric[
'unitsPerEm']);
 
  411                         $fmetric[
'bbox'] = 
''.$xMin.
' '.$yMin.
' '.$xMax.
' '.$yMax.
'';
 
  415                         $fmetric[
'Flags'] = $flags;
 
  416                         if (($macStyle & 2) == 2) {
 
  418                                 $fmetric[
'Flags'] |= 64;
 
  421                         $offset = $table[
'head'][
'offset'] + 50;
 
  425                         $indexToLoc = array();
 
  426                         $offset = $table[
'loca'][
'offset'];
 
  429                                 $tot_num_glyphs = ($table[
'loca'][
'length'] / 2); 
 
  430                                 for ($i = 0; $i < $tot_num_glyphs; ++$i) {
 
  436                                 $tot_num_glyphs = ($table[
'loca'][
'length'] / 4); 
 
  437                                 for ($i = 0; $i < $tot_num_glyphs; ++$i) {
 
  443                         $offset = $table[
'cmap'][
'offset'] + 2;
 
  446                         $encodingTables = array();
 
  447                         for ($i = 0; $i < $numEncodingTables; ++$i) {
 
  456                         $offset = $table[
'OS/2'][
'offset'];
 
  464                         $fmetric[
'StemV'] = round((70 * $usWeightClass) / 400);
 
  465                         $fmetric[
'StemH'] = round((30 * $usWeightClass) / 400);
 
  475                         $fmetric[
'name'] = 
'';
 
  476                         $offset = $table[
'name'][
'offset'];
 
  484                         for ($i = 0; $i < $numNameRecords; ++$i) {
 
  496                                         $offset = ($table[
'name'][
'offset'] + $stringStorageOffset + $stringOffset);
 
  497                                         $fmetric[
'name'] = substr($font, $offset, $stringLength);
 
  498                                         $fmetric[
'name'] = preg_replace(
'/[^a-zA-Z0-9_\-]/', 
'', $fmetric[
'name']);
 
  504                         if (empty($fmetric[
'name'])) {
 
  505                                 $fmetric[
'name'] = $font_name;
 
  508                         $offset = $table[
'post'][
'offset'];
 
  519                                 $fmetric[
'Flags'] |= 1;
 
  522                         $offset = $table[
'hhea'][
'offset'];
 
  540                         $offset = $table[
'maxp'][
'offset'];
 
  546                         foreach ($encodingTables as $enctable) {
 
  548                                 if (($enctable[
'platformID'] == $platid) AND ($enctable[
'encodingID'] == $encid)) {
 
  549                                         $offset = $table[
'cmap'][
'offset'] + $enctable[
'offset'];
 
  555                                                         for ($c = 0; $c < 256; ++$c) {
 
  565                                                         for ($i = 0; $i < 256; ++$i) {
 
  569                                                                 if ($numSubHeaders < $subHeaderKeys[$i]) {
 
  570                                                                         $numSubHeaders = $subHeaderKeys[$i];
 
  576                                                         $subHeaders = array();
 
  577                                                         $numGlyphIndexArray = 0;
 
  578                                                         for ($k = 0; $k < $numSubHeaders; ++$k) {
 
  587                                                                 $subHeaders[$k][
'idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8));
 
  588                                                                 $subHeaders[$k][
'idRangeOffset'] /= 2;
 
  589                                                                 $numGlyphIndexArray += $subHeaders[$k][
'entryCount'];
 
  591                                                         for ($k = 0; $k < $numGlyphIndexArray; ++$k) {
 
  595                                                         for ($i = 0; $i < 256; ++$i) {
 
  596                                                                 $k = $subHeaderKeys[$i];
 
  600                                                                         $g = $glyphIndexArray[0];
 
  604                                                                         $start_byte = $subHeaders[$k][
'firstCode'];
 
  605                                                                         $end_byte = $start_byte + $subHeaders[$k][
'entryCount'];
 
  606                                                                         for ($j = $start_byte; $j < $end_byte; ++$j) {
 
  608                                                                                 $c = (($i << 8) + $j);
 
  609                                                                                 $idRangeOffset = ($subHeaders[$k][
'idRangeOffset'] + $j - $subHeaders[$k][
'firstCode']);
 
  610                                                                                 $g = ($glyphIndexArray[$idRangeOffset] + $idDelta[$k]) % 65536;
 
  628                                                         for ($k = 0; $k < $segCount; ++$k) {
 
  633                                                         $startCount = array(); 
 
  634                                                         for ($k = 0; $k < $segCount; ++$k) {
 
  639                                                         for ($k = 0; $k < $segCount; ++$k) {
 
  643                                                         $idRangeOffset = array(); 
 
  644                                                         for ($k = 0; $k < $segCount; ++$k) {
 
  648                                                         $gidlen = ($length / 2) - 8 - (4 * $segCount);
 
  649                                                         $glyphIdArray = array(); 
 
  650                                                         for ($k = 0; $k < $gidlen; ++$k) {
 
  654                                                         for ($k = 0; $k < $segCount; ++$k) {
 
  655                                                                 for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) {
 
  656                                                                         if ($idRangeOffset[$k] == 0) {
 
  657                                                                                 $g = ($idDelta[$k] + $c) % 65536;
 
  659                                                                                 $gid = (($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k));
 
  660                                                                                 $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536;
 
  676                                                         for ($k = 0; $k < $entryCount; ++$k) {
 
  677                                                                 $c = ($k + $firstCode);
 
  686                                                         for ($k = 0; $k < 8192; ++$k) {
 
  692                                                         for ($i = 0; $i < $nGroups; ++$i) {
 
  699                                                                 for ($k = $startCharCode; $k <= $endCharCode; ++$k) {
 
  700                                                                         $is32idx = floor($c / 8);
 
  701                                                                         if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) {
 
  708                                                                                 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888;
 
  722                                                         for ($k = 0; $k < $numChars; ++$k) {
 
  723                                                                 $c = ($k + $startCharCode);
 
  734                                                         for ($k = 0; $k < $nGroups; ++$k) {
 
  741                                                                 for ($c = $startCharCode; $c <= $endCharCode; ++$c) {
 
  742                                                                         $ctg[$c] = $startGlyphCode;
 
  759                         if (!isset($ctg[0])) {
 
  763                         $offset = ($table[
'glyf'][
'offset'] + $indexToLoc[$ctg[120]] + 4);
 
  768                         $fmetric[
'XHeight'] = round(($yMax - $yMin) * $urk);
 
  770                         $offset = ($table[
'glyf'][
'offset'] + $indexToLoc[$ctg[72]] + 4);
 
  775                         $fmetric[
'CapHeight'] = round(($yMax - $yMin) * $urk);
 
  778                         $offset = $table[
'hmtx'][
'offset'];
 
  779                         for ($i = 0 ; $i < $numberOfHMetrics; ++$i) {
 
  783                         if ($numberOfHMetrics < $numGlyphs) {
 
  785                                 $cw = array_pad($cw, $numGlyphs, $cw[($numberOfHMetrics - 1)]);
 
  787                         $fmetric[
'MissingWidth'] = $cw[0];
 
  789                         for ($cid = 0; $cid <= 65535; ++$cid) {
 
  790                                 if (isset($ctg[$cid])) {
 
  791                                         if (isset($cw[$ctg[$cid]])) {
 
  792                                                 $fmetric[
'cw'] .= 
','.$cid.
'=>'.$cw[$ctg[$cid]];
 
  794                                         if ($addcbbox AND isset($indexToLoc[$ctg[$cid]])) {
 
  795                                                 $offset = ($table[
'glyf'][
'offset'] + $indexToLoc[$ctg[$cid]]);
 
  800                                                 $fmetric[
'cbbox'] .= 
','.$cid.
'=>array('.$xMin.
','.$yMin.
','.$xMax.
','.$yMax.
')';
 
  805                 if (($fmetric[
'type'] == 
'TrueTypeUnicode') AND (count($ctg) == 256)) {
 
  806                         $fmetric[
'type'] == 
'TrueType';
 
  809                 $pfile = 
'<'.
'?'.
'php'.
"\n";
 
  810                 $pfile .= 
'// TCPDF FONT FILE DESCRIPTION'.
"\n";
 
  811                 $pfile .= 
'$type=\''.$fmetric[
'type'].
'\';
'."\n"; 
  812                 $pfile .= '$name=\
''.$fmetric[
'name'].
'\';
'."\n"; 
  813                 $pfile .= '$up=
'.$fmetric['underlinePosition
'].';
'."\n"; 
  814                 $pfile .= '$ut=
'.$fmetric['underlineThickness
'].';
'."\n"; 
  815                 if ($fmetric['MissingWidth
'] > 0) { 
  816                         $pfile .= '$dw=
'.$fmetric['MissingWidth
'].';
'."\n"; 
  818                         $pfile .= '$dw=
'.$fmetric['AvgWidth
'].';
'."\n"; 
  820                 $pfile .= '$diff=\
''.$fmetric[
'diff'].
'\';
'."\n"; 
  821                 if ($fmetric['type
'] == 'Type1
') { 
  823                         $pfile .= '$enc=\
''.$fmetric[
'enc'].
'\';
'."\n"; 
  824                         $pfile .= '$file=\
''.$fmetric[
'file'].
'\';
'."\n"; 
  825                         $pfile .= '$size1=
'.$fmetric['size1
'].';
'."\n"; 
  826                         $pfile .= '$size2=
'.$fmetric['size2
'].';
'."\n"; 
  828                         $pfile .= '$originalsize=
'.$fmetric['originalsize
'].';
'."\n"; 
  829                         if ($fmetric['type
'] == 'cidfont0
') { 
  834                                                 $pfile .= 
'$enc=\'UniJIS-UTF16-H\';'.
"\n";
 
  835                                                 $pfile .= 
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Japan1\',\'Supplement\'=>5);'.
"\n";
 
  836                                                 $pfile .= 
'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'.
"\n";
 
  840                                                 $pfile .= 
'// Korean'.
"\n";
 
  841                                                 $pfile .= 
'$enc=\'UniKS-UTF16-H\';'.
"\n";
 
  842                                                 $pfile .= 
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Korea1\',\'Supplement\'=>0);'.
"\n";
 
  843                                                 $pfile .= 
'include(dirname(__FILE__).\'/uni2cid_ak12.php\');'.
"\n";
 
  847                                                 $pfile .= 
'// Chinese Simplified'.
"\n";
 
  848                                                 $pfile .= 
'$enc=\'UniGB-UTF16-H\';'.
"\n";
 
  849                                                 $pfile .= 
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'GB1\',\'Supplement\'=>2);'.
"\n";
 
  850                                                 $pfile .= 
'include(dirname(__FILE__).\'/uni2cid_ag15.php\');'.
"\n";
 
  855                                                 $pfile .= 
'// Chinese Traditional'.
"\n";
 
  856                                                 $pfile .= 
'$enc=\'UniCNS-UTF16-H\';'.
"\n";
 
  857                                                 $pfile .= 
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'CNS1\',\'Supplement\'=>0);'.
"\n";
 
  858                                                 $pfile .= 
'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'.
"\n";
 
  864                                 $pfile .= 
'$enc=\''.$fmetric[
'enc'].
'\';
'."\n"; 
  865                                 $pfile .= '$file=\
''.$fmetric[
'file'].
'\';
'."\n"; 
  866                                 $pfile .= '$ctg=\
''.$fmetric[
'ctg'].
'\';
'."\n"; 
  867                                 // create CIDToGIDMap 
  868                                 $cidtogidmap = str_pad('', 131072, "\x00"); // (256 * 256 * 2) = 131072 
  869                                 foreach ($ctg as $cid => $gid) { 
  870                                         $cidtogidmap = self::updateCIDtoGIDmap($cidtogidmap, $cid, $ctg[$cid]); 
  872                                 // store compressed CIDToGIDMap 
  873                                 $fp = fopen($outpath.$fmetric['ctg
'], 'wb
'); 
  874                                 fwrite($fp, gzcompress($cidtogidmap)); 
  878                 $pfile .= '$desc=array(
'; 
  879                 $pfile .= '\
'Flags\'=>'.$fmetric[
'Flags'].
',';
 
  880                 $pfile .= 
'\'FontBBox\
'=>\'['.$fmetric[
'bbox'].
']\',';
 
  881                 $pfile .= 
'\'ItalicAngle\
'=>'.$fmetric[
'italicAngle'].
',';
 
  882                 $pfile .= 
'\'Ascent\
'=>'.$fmetric[
'Ascent'].
',';
 
  883                 $pfile .= 
'\'Descent\
'=>'.$fmetric[
'Descent'].
',';
 
  884                 $pfile .= 
'\'Leading\
'=>'.$fmetric[
'Leading'].
',';
 
  885                 $pfile .= 
'\'CapHeight\
'=>'.$fmetric[
'CapHeight'].
',';
 
  886                 $pfile .= 
'\'XHeight\
'=>'.$fmetric[
'XHeight'].
',';
 
  887                 $pfile .= 
'\'StemV\
'=>'.$fmetric[
'StemV'].
',';
 
  888                 $pfile .= 
'\'StemH\
'=>'.$fmetric[
'StemH'].
',';
 
  889                 $pfile .= 
'\'AvgWidth\
'=>'.$fmetric[
'AvgWidth'].
',';
 
  890                 $pfile .= 
'\'MaxWidth\
'=>'.$fmetric[
'MaxWidth'].
',';
 
  891                 $pfile .= 
'\'MissingWidth\
'=>'.$fmetric[
'MissingWidth'].
'';
 
  893                 if (isset($fmetric[
'cbbox'])) {
 
  894                         $pfile .= 
'$cbbox=array('.substr($fmetric[
'cbbox'], 1).
');'.
"\n";
 
  896                 $pfile .= 
'$cw=array('.substr($fmetric[
'cw'], 1).
');'.
"\n";
 
  897                 $pfile .= 
'// --- EOF ---'.
"\n";
 
  899                 $fp = fopen($outpath.$font_name.
'.php', 
'w');
 
  917                 $tlen = ($length / 4);
 
  919                 for ($i = 0; $i < $tlen; ++$i) {
 
  920                         $v = unpack(
'Ni', substr($table, $offset, 4));
 
  924                 $sum = unpack(
'Ni', pack(
'N', $sum));
 
  953                 for ($i = 0; $i < $numTables; ++$i) {
 
  955                         $tag = substr($font, $offset, 4);
 
  957                         $table[$tag] = array();
 
  966                 $offset = $table[
'head'][
'offset'] + 12;
 
  973                 $offset = $table[
'head'][
'offset'] + 50;
 
  977                 $indexToLoc = array();
 
  978                 $offset = $table[
'loca'][
'offset'];
 
  981                         $tot_num_glyphs = ($table[
'loca'][
'length'] / 2); 
 
  982                         for ($i = 0; $i < $tot_num_glyphs; ++$i) {
 
  988                         $tot_num_glyphs = ($table[
'loca'][
'length'] / 4); 
 
  989                         for ($i = 0; $i < $tot_num_glyphs; ++$i) {
 
  995                 $subsetglyphs = array(); 
 
  996                 $subsetglyphs[0] = 
true; 
 
  997                 $offset = $table[
'cmap'][
'offset'] + 2;
 
 1000                 $encodingTables = array();
 
 1001                 for ($i = 0; $i < $numEncodingTables; ++$i) {
 
 1009                 foreach ($encodingTables as $enctable) {
 
 1011                         $offset = $table[
'cmap'][
'offset'] + $enctable[
'offset'];
 
 1017                                         for ($c = 0; $c < 256; ++$c) {
 
 1018                                                 if (isset($subsetchars[$c])) {
 
 1020                                                         $subsetglyphs[$g] = 
true;
 
 1029                                         for ($i = 0; $i < 256; ++$i) {
 
 1033                                                 if ($numSubHeaders < $subHeaderKeys[$i]) {
 
 1034                                                         $numSubHeaders = $subHeaderKeys[$i];
 
 1040                                         $subHeaders = array();
 
 1041                                         $numGlyphIndexArray = 0;
 
 1042                                         for ($k = 0; $k < $numSubHeaders; ++$k) {
 
 1051                                                 $subHeaders[$k][
'idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8));
 
 1052                                                 $subHeaders[$k][
'idRangeOffset'] /= 2;
 
 1053                                                 $numGlyphIndexArray += $subHeaders[$k][
'entryCount'];
 
 1055                                         for ($k = 0; $k < $numGlyphIndexArray; ++$k) {
 
 1059                                         for ($i = 0; $i < 256; ++$i) {
 
 1060                                                 $k = $subHeaderKeys[$i];
 
 1064                                                         if (isset($subsetchars[$c])) {
 
 1065                                                                 $g = $glyphIndexArray[0];
 
 1066                                                                 $subsetglyphs[$g] = 
true;
 
 1070                                                         $start_byte = $subHeaders[$k][
'firstCode'];
 
 1071                                                         $end_byte = $start_byte + $subHeaders[$k][
'entryCount'];
 
 1072                                                         for ($j = $start_byte; $j < $end_byte; ++$j) {
 
 1074                                                                 $c = (($i << 8) + $j);
 
 1075                                                                 if (isset($subsetchars[$c])) {
 
 1076                                                                         $idRangeOffset = ($subHeaders[$k][
'idRangeOffset'] + $j - $subHeaders[$k][
'firstCode']);
 
 1077                                                                         $g = ($glyphIndexArray[$idRangeOffset] + $idDelta[$k]) % 65536;
 
 1081                                                                         $subsetglyphs[$g] = 
true;
 
 1095                                         $endCount = array(); 
 
 1096                                         for ($k = 0; $k < $segCount; ++$k) {
 
 1101                                         $startCount = array(); 
 
 1102                                         for ($k = 0; $k < $segCount; ++$k) {
 
 1107                                         for ($k = 0; $k < $segCount; ++$k) {
 
 1111                                         $idRangeOffset = array(); 
 
 1112                                         for ($k = 0; $k < $segCount; ++$k) {
 
 1116                                         $gidlen = ($length / 2) - 8 - (4 * $segCount);
 
 1117                                         $glyphIdArray = array(); 
 
 1118                                         for ($k = 0; $k < $gidlen; ++$k) {
 
 1122                                         for ($k = 0; $k < $segCount; ++$k) {
 
 1123                                                 for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) {
 
 1124                                                         if (isset($subsetchars[$c])) {
 
 1125                                                                 if ($idRangeOffset[$k] == 0) {
 
 1126                                                                         $g = ($idDelta[$k] + $c) % 65536;
 
 1128                                                                         $gid = (($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k));
 
 1129                                                                         $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536;
 
 1134                                                                 $subsetglyphs[$g] = 
true;
 
 1146                                         for ($k = 0; $k < $entryCount; ++$k) {
 
 1147                                                 $c = ($k + $firstCode);
 
 1148                                                 if (isset($subsetchars[$c])) {
 
 1150                                                         $subsetglyphs[$g] = 
true;
 
 1158                                         for ($k = 0; $k < 8192; ++$k) {
 
 1164                                         for ($i = 0; $i < $nGroups; ++$i) {
 
 1171                                                 for ($k = $startCharCode; $k <= $endCharCode; ++$k) {
 
 1172                                                         $is32idx = floor($c / 8);
 
 1173                                                         if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) {
 
 1180                                                                 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888;
 
 1182                                                         if (isset($subsetchars[$c])) {
 
 1183                                                                 $subsetglyphs[$startGlyphID] = 
true;
 
 1196                                         for ($k = 0; $k < $numChars; ++$k) {
 
 1197                                                 $c = ($k + $startCharCode);
 
 1198                                                 if (isset($subsetchars[$c])) {
 
 1200                                                         $subsetglyphs[$g] = 
true;
 
 1210                                         for ($k = 0; $k < $nGroups; ++$k) {
 
 1217                                                 for ($c = $startCharCode; $c <= $endCharCode; ++$c) {
 
 1218                                                         if (isset($subsetchars[$c])) {
 
 1219                                                                 $subsetglyphs[$startGlyphCode] = 
true;
 
 1237                 $new_sga = $subsetglyphs;
 
 1238                 while (!empty($new_sga)) {
 
 1241                         foreach ($sga as $key => $val) {
 
 1242                                 if (isset($indexToLoc[$key])) {
 
 1243                                         $offset = ($table[
'glyf'][
'offset'] + $indexToLoc[$key]);
 
 1246                                         if ($numberOfContours < 0) { 
 
 1253                                                         if (!isset($subsetglyphs[$glyphIndex])) {
 
 1255                                                                 $new_sga[$glyphIndex] = 
true;
 
 1265                                                         } elseif ($flags & 64) {
 
 1267                                                         } elseif ($flags & 128) {
 
 1270                                                 } 
while ($flags & 32);
 
 1274                         $subsetglyphs += $new_sga;
 
 1277                 ksort($subsetglyphs);
 
 1282                 $glyf_offset = $table[
'glyf'][
'offset'];
 
 1283                 for ($i = 0; $i < $tot_num_glyphs; ++$i) {
 
 1284                         if (isset($subsetglyphs[$i])) {
 
 1285                                 $length = ($indexToLoc[($i + 1)] - $indexToLoc[$i]);
 
 1286                                 $glyf .= substr($font, ($glyf_offset + $indexToLoc[$i]), $length);
 
 1290                         if ($short_offset) {
 
 1291                                 $loca .= pack(
'n', ($offset / 2));
 
 1293                                 $loca .= pack(
'N', $offset);
 
 1299                 $table_names = array (
'head', 
'hhea', 
'hmtx', 
'maxp', 
'cvt ', 
'fpgm', 
'prep'); 
 
 1302                 foreach ($table as $tag => $val) {
 
 1303                         if (in_array($tag, $table_names)) {
 
 1304                                 $table[$tag][
'data'] = substr($font, $table[$tag][
'offset'], $table[$tag][
'length']);
 
 1305                                 if ($tag == 
'head') {
 
 1307                                         $table[$tag][
'data'] = substr($table[$tag][
'data'], 0, 8).
"\x0\x0\x0\x0".substr($table[$tag][
'data'], 12);
 
 1309                                 $pad = 4 - ($table[$tag][
'length'] % 4);
 
 1312                                         $table[$tag][
'length'] += $pad;
 
 1313                                         $table[$tag][
'data'] .= str_repeat(
"\x0", $pad);
 
 1315                                 $table[$tag][
'offset'] = $offset;
 
 1316                                 $offset += $table[$tag][
'length'];
 
 1320                                 unset($table[$tag]);
 
 1324                 $table[
'loca'][
'data'] = $loca;
 
 1325                 $table[
'loca'][
'length'] = strlen($loca);
 
 1326                 $pad = 4 - ($table[
'loca'][
'length'] % 4);
 
 1329                         $table[
'loca'][
'length'] += $pad;
 
 1330                         $table[
'loca'][
'data'] .= str_repeat(
"\x0", $pad);
 
 1332                 $table[
'loca'][
'offset'] = $offset;
 
 1333                 $table[
'loca'][
'checkSum'] = self::_getTTFtableChecksum($table[
'loca'][
'data'], $table[
'loca'][
'length']);
 
 1334                 $offset += $table[
'loca'][
'length'];
 
 1336                 $table[
'glyf'][
'data'] = $glyf;
 
 1337                 $table[
'glyf'][
'length'] = strlen($glyf);
 
 1338                 $pad = 4 - ($table[
'glyf'][
'length'] % 4);
 
 1341                         $table[
'glyf'][
'length'] += $pad;
 
 1342                         $table[
'glyf'][
'data'] .= str_repeat(
"\x0", $pad);
 
 1344                 $table[
'glyf'][
'offset'] = $offset;
 
 1345                 $table[
'glyf'][
'checkSum'] = self::_getTTFtableChecksum($table[
'glyf'][
'data'], $table[
'glyf'][
'length']);
 
 1348                 $font .= pack(
'N', 0x10000); 
 
 1349                 $numTables = count($table);
 
 1350                 $font .= pack(
'n', $numTables); 
 
 1351                 $entrySelector = floor(log($numTables, 2));
 
 1352                 $searchRange = pow(2, $entrySelector) * 16;
 
 1353                 $rangeShift = ($numTables * 16) - $searchRange;
 
 1354                 $font .= pack(
'n', $searchRange); 
 
 1355                 $font .= pack(
'n', $entrySelector); 
 
 1356                 $font .= pack(
'n', $rangeShift); 
 
 1357                 $offset = ($numTables * 16);
 
 1358                 foreach ($table as $tag => $data) {
 
 1360                         $font .= pack(
'N', $data[
'checkSum']); 
 
 1361                         $font .= pack(
'N', ($data[
'offset'] + $offset)); 
 
 1362                         $font .= pack(
'N', $data[
'length']); 
 
 1364                 foreach ($table as $data) {
 
 1365                         $font .= $data[
'data'];
 
 1368                 $checkSumAdjustment = 0xB1B0AFBA - self::_getTTFtableChecksum($font, strlen($font));
 
 1369                 $font = substr($font, 0, $table[
'head'][
'offset'] + 8).pack(
'N', $checkSumAdjustment).substr($font, $table[
'head'][
'offset'] + 12);
 
 1390                 foreach ($font[
'cw'] as $cid => $width) {
 
 1392                         if ($font[
'subset'] AND (!isset($font[
'subsetchars'][$cid]))) {
 
 1396                         if ($width != $font[
'dw']) {
 
 1397                                 if ($cid == ($prevcid + 1)) {
 
 1399                                         if ($width == $prevwidth) {
 
 1400                                                 if ($width == $range[$rangeid][0]) {
 
 1401                                                         $range[$rangeid][] = $width;
 
 1403                                                         array_pop($range[$rangeid]);
 
 1405                                                         $rangeid = $prevcid;
 
 1406                                                         $range[$rangeid] = array();
 
 1407                                                         $range[$rangeid][] = $prevwidth;
 
 1408                                                         $range[$rangeid][] = $width;
 
 1411                                                 $range[$rangeid][
'interval'] = 
true;
 
 1416                                                         $range[$rangeid] = array();
 
 1417                                                         $range[$rangeid][] = $width;
 
 1419                                                         $range[$rangeid][] = $width;
 
 1426                                         $range[$rangeid] = array();
 
 1427                                         $range[$rangeid][] = $width;
 
 1431                                 $prevwidth = $width;
 
 1438                 foreach ($range as $k => $ws) {
 
 1440                         if (($k == $nextk) AND (!$prevint) AND ((!isset($ws[
'interval'])) OR ($cws < 4))) {
 
 1441                                 if (isset($range[$k][
'interval'])) {
 
 1442                                         unset($range[$k][
'interval']);
 
 1444                                 $range[$prevk] = array_merge($range[$prevk], $range[$k]);
 
 1450                         if (isset($ws[
'interval'])) {
 
 1456                                 if (isset($range[$k][
'interval'])) {
 
 1457                                         unset($range[$k][
'interval']);
 
 1466                 foreach ($range as $k => $ws) {
 
 1467                         if (count(array_count_values($ws)) == 1) {
 
 1469                                 $w .= 
' '.$k.
' '.($k + count($ws) - 1).
' '.$ws[0];
 
 1472                                 $w .= 
' '.$k.
' [ '.implode(
' ', $ws).
' ]';
 
 1475                 return '/W ['.$w.
' ]';
 
 1486         public static function unichr($c, $unicode=
true) {
 
 1489                 } elseif ($c <= 0x7F) {
 
 1492                 } elseif ($c <= 0x7FF) {
 
 1494                         return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F);
 
 1495                 } elseif ($c <= 0xFFFF) {
 
 1497                         return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
 
 1498                 } elseif ($c <= 0x10FFFF) {
 
 1500                         return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
 
 1513                 return self::unichr($c, 
true);
 
 1523                 return self::unichr($c, 
false);
 
 1567                         $outstr .= 
"\xFE\xFF"; 
 
 1569                 foreach ($unicode as $char) {
 
 1570                         if ($char == 0x200b) {
 
 1572                         } elseif ($char == 0xFFFD) {
 
 1573                                 $outstr .= 
"\xFF\xFD"; 
 
 1574                         } elseif ($char < 0x10000) {
 
 1575                                 $outstr .= chr($char >> 0x08);
 
 1576                                 $outstr .= chr($char & 0xFF);
 
 1579                                 $w1 = 0xD800 | ($char >> 0x0a);
 
 1580                                 $w2 = 0xDC00 | ($char & 0x3FF);
 
 1581                                 $outstr .= chr($w1 >> 0x08);
 
 1582                                 $outstr .= chr($w1 & 0xFF);
 
 1583                                 $outstr .= chr($w2 >> 0x08);
 
 1584                                 $outstr .= chr($w2 & 0xFF);
 
 1600                         return array_map(array(
'self', 
'unichrUnicode'), $ta);
 
 1602                 return array_map(array(
'self', 
'unichrASCII'), $ta);
 
 1615                 if (strlen($start) == 0) {
 
 1618                 if (strlen($end) == 0) {
 
 1619                         $end = count($strarr);
 
 1622                 for ($i = $start; $i < $end; ++$i) {
 
 1623                         $string .= self::unichr($strarr[$i], $unicode);
 
 1638                 if (strlen($start) == 0) {
 
 1641                 if (strlen($end) == 0) {
 
 1642                         $end = count($uniarr);
 
 1645                 for ($i=$start; $i < $end; ++$i) {
 
 1646                         $string .= $uniarr[$i];
 
 1662                 if (($cid >= 0) AND ($cid <= 0xFFFF) AND ($gid >= 0)) {
 
 1663                         if ($gid > 0xFFFF) {
 
 1666                         $map[($cid * 2)] = chr($gid >> 8);
 
 1667                         $map[(($cid * 2) + 1)] = chr($gid & 0xFF);
 
 1678                 if (!defined(
'K_PATH_FONTS') AND is_dir($fdir = realpath(dirname(__FILE__).
'/../fonts'))) {
 
 1679                         if (substr($fdir, -1) != 
'/') {
 
 1682                         define(
'K_PATH_FONTS', $fdir);
 
 1684                 return defined(
'K_PATH_FONTS') ? K_PATH_FONTS : 
'';
 
 1697                 foreach ($unicode as $char) {
 
 1703                         } elseif ($char == 0xFFFD) {
 
 1722                 foreach ($unicode as $char) {
 
 1724                                 $outstr .= chr($char);
 
 1728                         } elseif ($char == 0xFFFD) {
 
 1771                 if (function_exists(
'mb_convert_encoding')) {
 
 1772                         list(, $char) = @unpack(
'N', mb_convert_encoding($uch, 
'UCS-4BE', 
'UTF-8'));
 
 1780                 $length = strlen($uch);
 
 1781                 for ($i = 0; $i < $length; ++$i) {
 
 1782                         $char = ord($uch[$i]); 
 
 1783                         if ($countbytes == 0) { 
 
 1784                                 if ($char <= 0x7F) {
 
 1786                                 } elseif (($char >> 0x05) == 0x06) { 
 
 1787                                         $bytes[] = ($char - 0xC0) << 0x06;
 
 1790                                 } elseif (($char >> 0x04) == 0x0E) { 
 
 1791                                         $bytes[] = ($char - 0xE0) << 0x0C;
 
 1794                                 } elseif (($char >> 0x03) == 0x1E) { 
 
 1795                                         $bytes[] = ($char - 0xF0) << 0x12;
 
 1802                         } elseif (($char >> 0x06) == 0x02) { 
 
 1803                                 $bytes[] = $char - 0x80;
 
 1805                                 if ($countbytes == $numbytes) {
 
 1808                                         for ($j = 1; $j < $numbytes; ++$j) {
 
 1809                                                 $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06));
 
 1811                                         if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) {
 
 1842                         $chars = preg_split(
"//u", $str, -1, PREG_SPLIT_NO_EMPTY);
 
 1843                         $carr = array_map(array(
'self', 
'uniord'), $chars);
 
 1845                         $chars = str_split($str);
 
 1846                         $carr = array_map(
'ord', $chars);
 
 1848                 $currentfont[
'subsetchars'] += array_fill_keys($carr, 
true);
 
 1861         public static function UTF8ToLatin1($str, $isunicode=
true, &$currentfont) {
 
 1862                 $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont); 
 
 1863                 return self::UTF8ArrToLatin1($unicode);
 
 1877         public static function UTF8ToUTF16BE($str, $setbom=
false, $isunicode=
true, &$currentfont) {
 
 1881                 $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont); 
 
 1882                 return self::arrUTF8ToUTF16BE($unicode, $setbom);
 
 1897         public static function utf8StrRev($str, $setbom=
false, $forcertl=
false, $isunicode=
true, &$currentfont) {
 
 1898                 return self::utf8StrArrRev(self::UTF8StringToArray($str, $isunicode, $currentfont), $str, $setbom, $forcertl, $isunicode, $currentfont);
 
 1914         public static function utf8StrArrRev($arr, $str=
'', $setbom=
false, $forcertl=
false, $isunicode=
true, &$currentfont) {
 
 1915                 return self::arrUTF8ToUTF16BE(self::utf8Bidi($arr, $str, $forcertl, $isunicode, $currentfont), $setbom);
 
 1930         public static function utf8Bidi($ta, $str=
'', $forcertl=
false, $isunicode=
true, &$currentfont) {
 
 1937                         $str = self::UTF8ArrSubString($ta, 
'', 
'', $isunicode);
 
 1951                 $numchars = count($ta);
 
 1953                 if ($forcertl == 
'R') {
 
 1955                 } elseif ($forcertl == 
'L') {
 
 1960                         for ($i=0; $i < $numchars; ++$i) {
 
 1965                                 } elseif (($type == 
'AL') OR ($type == 
'R')) {
 
 1976                 $remember = array();
 
 1978                 $sor = $pel % 2 ? 
'R' : 
'L';
 
 1982                 $chardata = Array();
 
 1986                 for ($i=0; $i < $numchars; ++$i) {
 
 1991                                 $next_level = $cel + ($cel % 2) + 1;
 
 1992                                 if ($next_level < 62) {
 
 1997                                         $eor = $cel % 2 ? 
'R' : 
'L';
 
 2003                                 $next_level = $cel + 2 - ($cel % 2);
 
 2004                                 if ( $next_level < 62 ) {
 
 2009                                         $eor = $cel % 2 ? 
'R' : 
'L';
 
 2015                                 $next_level = $cel + ($cel % 2) + 1;
 
 2016                                 if ($next_level < 62) {
 
 2021                                         $eor = $cel % 2 ? 
'R' : 
'L';
 
 2027                                 $next_level = $cel + 2 - ($cel % 2);
 
 2028                                 if ( $next_level < 62 ) {
 
 2033                                         $eor = $cel % 2 ? 
'R' : 
'L';
 
 2037                                 if (count($remember)) {
 
 2038                                         $last = count($remember ) - 1;
 
 2043                                                 $match = array_pop($remember);
 
 2044                                                 $cel = $match[
'cel'];
 
 2045                                                 $dos = $match[
'dos'];
 
 2047                                                 $eor = ($cel > $match[
'cel'] ? $cel : $match[
'cel']) % 2 ? 
'R' : 
'L';
 
 2068                                 $chardata[] = array(
'char' => $ta[$i], 
'level' => $cel, 
'type' => $chardir, 
'sor' => $sor, 
'eor' => $eor);
 
 2079                 $numchars = count($chardata);
 
 2084                 for ($i=0; $i < $numchars; ++$i) {
 
 2085                         if ($chardata[$i][
'type'] == 
'NSM') {
 
 2087                                         $chardata[$i][
'type'] = $chardata[$i][
'sor'];
 
 2089                                         $chardata[$i][
'type'] = $chardata[($i-1)][
'type'];
 
 2092                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2097                         $prevlevel = $chardata[$i][
'level'];
 
 2103                 for ($i=0; $i < $numchars; ++$i) {
 
 2104                         if ($chardata[$i][
'char'] == 
'EN') {
 
 2105                                 for ($j=$levcount; $j >= 0; $j--) {
 
 2106                                         if ($chardata[$j][
'type'] == 
'AL') {
 
 2107                                                 $chardata[$i][
'type'] = 
'AN';
 
 2108                                         } elseif (($chardata[$j][
'type'] == 
'L') OR ($chardata[$j][
'type'] == 
'R')) {
 
 2113                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2118                         $prevlevel = $chardata[$i][
'level'];
 
 2122                 for ($i=0; $i < $numchars; ++$i) {
 
 2123                         if ($chardata[$i][
'type'] == 
'AL') {
 
 2124                                 $chardata[$i][
'type'] = 
'R';
 
 2131                 for ($i=0; $i < $numchars; ++$i) {
 
 2132                         if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)][
'level'] == $prevlevel)) {
 
 2133                                 if (($chardata[$i][
'type'] == 
'ES') AND ($chardata[($i-1)][
'type'] == 
'EN') AND ($chardata[($i+1)][
'type'] == 
'EN')) {
 
 2134                                         $chardata[$i][
'type'] = 
'EN';
 
 2135                                 } elseif (($chardata[$i][
'type'] == 
'CS') AND ($chardata[($i-1)][
'type'] == 
'EN') AND ($chardata[($i+1)][
'type'] == 
'EN')) {
 
 2136                                         $chardata[$i][
'type'] = 
'EN';
 
 2137                                 } elseif (($chardata[$i][
'type'] == 
'CS') AND ($chardata[($i-1)][
'type'] == 
'AN') AND ($chardata[($i+1)][
'type'] == 
'AN')) {
 
 2138                                         $chardata[$i][
'type'] = 
'AN';
 
 2141                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2146                         $prevlevel = $chardata[$i][
'level'];
 
 2152                 for ($i=0; $i < $numchars; ++$i) {
 
 2153                         if ($chardata[$i][
'type'] == 
'ET') {
 
 2154                                 if (($levcount > 0) AND ($chardata[($i-1)][
'type'] == 
'EN')) {
 
 2155                                         $chardata[$i][
'type'] = 
'EN';
 
 2158                                         while (($j < $numchars) AND ($chardata[$j][
'level'] == $prevlevel)) {
 
 2159                                                 if ($chardata[$j][
'type'] == 
'EN') {
 
 2160                                                         $chardata[$i][
'type'] = 
'EN';
 
 2162                                                 } elseif ($chardata[$j][
'type'] != 
'ET') {
 
 2169                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2174                         $prevlevel = $chardata[$i][
'level'];
 
 2180                 for ($i=0; $i < $numchars; ++$i) {
 
 2181                         if (($chardata[$i][
'type'] == 
'ET') OR ($chardata[$i][
'type'] == 
'ES') OR ($chardata[$i][
'type'] == 
'CS')) {
 
 2182                                 $chardata[$i][
'type'] = 
'ON';
 
 2184                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2189                         $prevlevel = $chardata[$i][
'level'];
 
 2195                 for ($i=0; $i < $numchars; ++$i) {
 
 2196                         if ($chardata[$i][
'char'] == 
'EN') {
 
 2197                                 for ($j=$levcount; $j >= 0; $j--) {
 
 2198                                         if ($chardata[$j][
'type'] == 
'L') {
 
 2199                                                 $chardata[$i][
'type'] = 
'L';
 
 2200                                         } elseif ($chardata[$j][
'type'] == 
'R') {
 
 2205                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2210                         $prevlevel = $chardata[$i][
'level'];
 
 2216                 for ($i=0; $i < $numchars; ++$i) {
 
 2217                         if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)][
'level'] == $prevlevel)) {
 
 2218                                 if (($chardata[$i][
'type'] == 
'N') AND ($chardata[($i-1)][
'type'] == 
'L') AND ($chardata[($i+1)][
'type'] == 
'L')) {
 
 2219                                         $chardata[$i][
'type'] = 
'L';
 
 2220                                 } elseif (($chardata[$i][
'type'] == 
'N') AND
 
 2221                                  (($chardata[($i-1)][
'type'] == 
'R') OR ($chardata[($i-1)][
'type'] == 
'EN') OR ($chardata[($i-1)][
'type'] == 
'AN')) AND
 
 2222                                  (($chardata[($i+1)][
'type'] == 
'R') OR ($chardata[($i+1)][
'type'] == 
'EN') OR ($chardata[($i+1)][
'type'] == 
'AN'))) {
 
 2223                                         $chardata[$i][
'type'] = 
'R';
 
 2224                                 } elseif ($chardata[$i][
'type'] == 
'N') {
 
 2226                                         $chardata[$i][
'type'] = $chardata[$i][
'sor'];
 
 2228                         } elseif (($levcount == 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)][
'level'] == $prevlevel)) {
 
 2230                                 if (($chardata[$i][
'type'] == 
'N') AND ($chardata[$i][
'sor'] == 
'L') AND ($chardata[($i+1)][
'type'] == 
'L')) {
 
 2231                                         $chardata[$i][
'type'] = 
'L';
 
 2232                                 } elseif (($chardata[$i][
'type'] == 
'N') AND
 
 2233                                  (($chardata[$i][
'sor'] == 
'R') OR ($chardata[$i][
'sor'] == 
'EN') OR ($chardata[$i][
'sor'] == 
'AN')) AND
 
 2234                                  (($chardata[($i+1)][
'type'] == 
'R') OR ($chardata[($i+1)][
'type'] == 
'EN') OR ($chardata[($i+1)][
'type'] == 
'AN'))) {
 
 2235                                         $chardata[$i][
'type'] = 
'R';
 
 2236                                 } elseif ($chardata[$i][
'type'] == 
'N') {
 
 2238                                         $chardata[$i][
'type'] = $chardata[$i][
'sor'];
 
 2240                         } elseif (($levcount > 0) AND ((($i+1) == $numchars) OR (($i+1) < $numchars) AND ($chardata[($i+1)][
'level'] != $prevlevel))) {
 
 2242                                 if (($chardata[$i][
'type'] == 
'N') AND ($chardata[($i-1)][
'type'] == 
'L') AND ($chardata[$i][
'eor'] == 
'L')) {
 
 2243                                         $chardata[$i][
'type'] = 
'L';
 
 2244                                 } elseif (($chardata[$i][
'type'] == 
'N') AND
 
 2245                                  (($chardata[($i-1)][
'type'] == 
'R') OR ($chardata[($i-1)][
'type'] == 
'EN') OR ($chardata[($i-1)][
'type'] == 
'AN')) AND
 
 2246                                  (($chardata[$i][
'eor'] == 
'R') OR ($chardata[$i][
'eor'] == 
'EN') OR ($chardata[$i][
'eor'] == 
'AN'))) {
 
 2247                                         $chardata[$i][
'type'] = 
'R';
 
 2248                                 } elseif ($chardata[$i][
'type'] == 
'N') {
 
 2250                                         $chardata[$i][
'type'] = $chardata[$i][
'sor'];
 
 2252                         } elseif ($chardata[$i][
'type'] == 
'N') {
 
 2254                                 $chardata[$i][
'type'] = $chardata[$i][
'sor'];
 
 2256                         if ($chardata[$i][
'level'] != $prevlevel) {
 
 2261                         $prevlevel = $chardata[$i][
'level'];
 
 2266                 for ($i=0; $i < $numchars; ++$i) {
 
 2267                         $odd = $chardata[$i][
'level'] % 2;
 
 2269                                 if (($chardata[$i][
'type'] == 
'L') OR ($chardata[$i][
'type'] == 
'AN') OR ($chardata[$i][
'type'] == 
'EN')) {
 
 2270                                         $chardata[$i][
'level'] += 1;
 
 2273                                 if ($chardata[$i][
'type'] == 
'R') {
 
 2274                                         $chardata[$i][
'level'] += 1;
 
 2275                                 } elseif (($chardata[$i][
'type'] == 
'AN') OR ($chardata[$i][
'type'] == 
'EN')) {
 
 2276                                         $chardata[$i][
'level'] += 2;
 
 2279                         $maxlevel = max($chardata[$i][
'level'],$maxlevel);
 
 2287                 for ($i=0; $i < $numchars; ++$i) {
 
 2288                         if (($chardata[$i][
'type'] == 
'B') OR ($chardata[$i][
'type'] == 
'S')) {
 
 2289                                 $chardata[$i][
'level'] = $pel;
 
 2290                         } elseif ($chardata[$i][
'type'] == 
'WS') {
 
 2292                                 while ($j < $numchars) {
 
 2293                                         if ((($chardata[$j][
'type'] == 
'B') OR ($chardata[$j][
'type'] == 
'S')) OR
 
 2294                                                 (($j == ($numchars-1)) AND ($chardata[$j][
'type'] == 
'WS'))) {
 
 2295                                                 $chardata[$i][
'level'] = $pel;
 
 2297                                         } elseif ($chardata[$j][
'type'] != 
'WS') {
 
 2308                         $endedletter = array(1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688);
 
 2309                         $alfletter = array(1570,1571,1573,1575);
 
 2310                         $chardata2 = $chardata;
 
 2314                         for ($i=0; $i < $numchars; ++$i) {
 
 2315                                 if ((
TCPDF_FONT_DATA::$uni_type[$chardata[$i][
'char']] == 
'AL') OR ($chardata[$i][
'char'] == 32) OR ($chardata[$i][
'char'] == 8204)) {
 
 2316                                         $charAL[$x] = $chardata[$i];
 
 2317                                         $charAL[$x][
'i'] = $i;
 
 2318                                         $chardata[$i][
'x'] = $x;
 
 2323                         for ($i=0; $i < $numchars; ++$i) {
 
 2324                                 $thischar = $chardata[$i];
 
 2326                                         $prevchar = $chardata[($i-1)];
 
 2330                                 if (($i+1) < $numchars) {
 
 2331                                         $nextchar = $chardata[($i+1)];
 
 2336                                         $x = $thischar[
'x'];
 
 2338                                                 $prevchar = $charAL[($x-1)];
 
 2342                                         if (($x+1) < $numAL) {
 
 2343                                                 $nextchar = $charAL[($x+1)];
 
 2348                                         if (($prevchar !== 
false) AND ($prevchar[
'char'] == 1604) AND (in_array($thischar[
'char'], $alfletter))) {
 
 2352                                                         $prevchar = $charAL[($x-2)];
 
 2360                                         if (($prevchar !== 
false) AND ($nextchar !== 
false) AND
 
 2363                                                 ($prevchar[
'type'] == $thischar[
'type']) AND
 
 2364                                                 ($nextchar[
'type'] == $thischar[
'type']) AND
 
 2365                                                 ($nextchar[
'char'] != 1567)) {
 
 2366                                                 if (in_array($prevchar[
'char'], $endedletter)) {
 
 2367                                                         if (isset($arabicarr[$thischar[
'char']][2])) {
 
 2369                                                                 $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][2];
 
 2372                                                         if (isset($arabicarr[$thischar[
'char']][3])) {
 
 2374                                                                 $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][3];
 
 2377                                         } elseif (($nextchar !== 
false) AND
 
 2379                                                 ($nextchar[
'type'] == $thischar[
'type']) AND
 
 2380                                                 ($nextchar[
'char'] != 1567)) {
 
 2381                                                 if (isset($arabicarr[$chardata[$i][
'char']][2])) {
 
 2383                                                         $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][2];
 
 2385                                         } elseif ((($prevchar !== 
false) AND
 
 2387                                                 ($prevchar[
'type'] == $thischar[
'type'])) OR
 
 2388                                                 (($nextchar !== 
false) AND ($nextchar[
'char'] == 1567))) {
 
 2390                                                 if (($i > 1) AND ($thischar[
'char'] == 1607) AND
 
 2391                                                         ($chardata[$i-1][
'char'] == 1604) AND
 
 2392                                                         ($chardata[$i-2][
'char'] == 1604)) {
 
 2395                                                         $chardata2[$i-2][
'char'] = 
false;
 
 2396                                                         $chardata2[$i-1][
'char'] = 
false;
 
 2397                                                         $chardata2[$i][
'char'] = 65010;
 
 2399                                                         if (($prevchar !== 
false) AND in_array($prevchar[
'char'], $endedletter)) {
 
 2400                                                                 if (isset($arabicarr[$thischar[
'char']][0])) {
 
 2402                                                                         $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][0];
 
 2405                                                                 if (isset($arabicarr[$thischar[
'char']][1])) {
 
 2407                                                                         $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][1];
 
 2411                                         } elseif (isset($arabicarr[$thischar[
'char']][0])) {
 
 2413                                                 $chardata2[$i][
'char'] = $arabicarr[$thischar[
'char']][0];
 
 2418                                                 $chardata2[($charAL[($x-1)][
'i'])][
'char'] = 
false;
 
 2426                         for ($i = 0; $i < ($numchars-1); ++$i) {
 
 2430                                                 $chardata2[$i][
'char'] = 
false;
 
 2436                         foreach ($chardata2 as $key => $value) {
 
 2437                                 if ($value[
'char'] === 
false) {
 
 2438                                         unset($chardata2[$key]);
 
 2441                         $chardata = array_values($chardata2);
 
 2442                         $numchars = count($chardata);
 
 2450                 for ($j=$maxlevel; $j > 0; $j--) {
 
 2451                         $ordarray = Array();
 
 2454                         for ($i=0; $i < $numchars; ++$i) {
 
 2455                                 if ($chardata[$i][
'level'] >= $j) {
 
 2461                                         $revarr[] = $chardata[$i];
 
 2464                                                 $revarr = array_reverse($revarr);
 
 2465                                                 $ordarray = array_merge($ordarray, $revarr);
 
 2469                                         $ordarray[] = $chardata[$i];
 
 2473                                 $revarr = array_reverse($revarr);
 
 2474                                 $ordarray = array_merge($ordarray, $revarr);
 
 2476                         $chardata = $ordarray;
 
 2478                 $ordarray = array();
 
 2479                 foreach ($chardata as $cd) {
 
 2480                         $ordarray[] = $cd[
'char'];
 
 2482                         $currentfont[
'subsetchars'][$cd[
'char']] = 
true;
 
 2497                                 $size = ($refsize - 4);
 
 2501                                 $size = ($refsize - 3);
 
 2505                                 $size = ($refsize - 2);
 
 2513                                 $size = ($refsize + 2);
 
 2517                                 $size = ($refsize + 4);
 
 2521                                 $size = ($refsize + 6);
 
 2525                                 $size = ($refsize - 3);
 
 2529                                 $size = ($refsize + 3);