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);