72 public static function addTTFfont($fontfile, $fonttype=
'', $enc=
'', $flags=32, $outpath=
'', $platid=3, $encid=1, $addcbbox=
false, $link=
false) {
73 if (!file_exists($fontfile)) {
80 $font_path_parts = pathinfo($fontfile);
81 if (!isset($font_path_parts[
'filename'])) {
82 $font_path_parts[
'filename'] = substr($font_path_parts[
'basename'], 0, -(strlen($font_path_parts[
'extension']) + 1));
84 $font_name = strtolower($font_path_parts[
'filename']);
85 $font_name = preg_replace(
'/[^a-z0-9_]/',
'', $font_name);
86 $search =
array(
'bold',
'oblique',
'italic',
'regular');
87 $replace =
array(
'b',
'i',
'i',
'');
88 $font_name = str_replace($search, $replace, $font_name);
89 if (empty($font_name)) {
91 $font_name =
'tcpdffont';
94 if (empty($outpath)) {
95 $outpath = self::_getfontpath();
98 if (@file_exists($outpath.$font_name.
'.php')) {
102 $fmetric[
'file'] = $font_name;
103 $fmetric[
'ctg'] = $font_name.
'.ctg.z';
105 $font = file_get_contents($fontfile);
106 $fmetric[
'originalsize'] = strlen($font);
108 if (empty($fonttype)) {
111 $fonttype =
'TrueTypeUnicode';
112 } elseif (substr($font, 0, 4) ==
'OTTO') {
127 $fmetric[
'type'] =
'cidfont0';
131 $fmetric[
'type'] =
'Type1';
132 if (empty($enc) AND (($flags & 4) == 0)) {
138 $fmetric[
'type'] =
'TrueType';
141 case 'TrueTypeUnicode':
143 $fmetric[
'type'] =
'TrueTypeUnicode';
148 $fmetric[
'enc'] = preg_replace(
'/[^A-Za-z0-9_\-]/',
'', $enc);
149 $fmetric[
'diff'] =
'';
150 if (($fmetric[
'type'] ==
'TrueType') OR ($fmetric[
'type'] ==
'Type1')) {
156 for (
$i = 32;
$i <= 255; ++
$i) {
157 if ($enc_target[
$i] != $enc_ref[
$i]) {
158 if ($i != ($last + 1)) {
159 $fmetric[
'diff'] .= $i.
' ';
162 $fmetric[
'diff'] .=
'/'.$enc_target[
$i].
' ';
168 if ($fmetric[
'type'] ==
'Type1') {
171 $a = unpack(
'Cmarker/Ctype/Vsize', substr($font, 0, 6));
172 if ($a[
'marker'] != 128) {
176 $fmetric[
'size1'] = $a[
'size'];
177 $data = substr($font, 6, $fmetric[
'size1']);
179 $a = unpack(
'Cmarker/Ctype/Vsize', substr($font, (6 + $fmetric[
'size1']), 6));
180 if ($a[
'marker'] != 128) {
184 $fmetric[
'size2'] = $a[
'size'];
185 $encrypted = substr($font, (12 + $fmetric[
'size1']), $fmetric[
'size2']);
188 $fmetric[
'file'] .=
'.z';
190 fwrite($fp, gzcompress(
$data));
193 $fmetric[
'Flags'] = $flags;
194 preg_match (
'#/FullName[\s]*\(([^\)]*)#', $font, $matches);
195 $fmetric[
'name'] = preg_replace(
'/[^a-zA-Z0-9_\-]/',
'', $matches[1]);
196 preg_match(
'#/FontBBox[\s]*{([^}]*)#', $font, $matches);
197 $fmetric[
'bbox'] = trim($matches[1]);
198 $bv = explode(
' ', $fmetric[
'bbox']);
199 $fmetric[
'Ascent'] = intval($bv[3]);
200 $fmetric[
'Descent'] = intval($bv[1]);
201 preg_match(
'#/ItalicAngle[\s]*([0-9\+\-]*)#', $font, $matches);
202 $fmetric[
'italicAngle'] = intval($matches[1]);
203 if ($fmetric[
'italicAngle'] != 0) {
204 $fmetric[
'Flags'] |= 64;
206 preg_match(
'#/UnderlinePosition[\s]*([0-9\+\-]*)#', $font, $matches);
207 $fmetric[
'underlinePosition'] = intval($matches[1]);
208 preg_match(
'#/UnderlineThickness[\s]*([0-9\+\-]*)#', $font, $matches);
209 $fmetric[
'underlineThickness'] = intval($matches[1]);
210 preg_match(
'#/isFixedPitch[\s]*([^\s]*)#', $font, $matches);
211 if ($matches[1] ==
'true') {
212 $fmetric[
'Flags'] |= 1;
216 if (preg_match_all(
'#dup[\s]([0-9]+)[\s]*/([^\s]*)[\s]put#sU', $font, $fmap, PREG_SET_ORDER) > 0) {
217 foreach ($fmap as $v) {
218 $imap[$v[2]] = $v[1];
225 $elen = strlen($encrypted);
227 for (
$i = 0;
$i < $elen; ++
$i) {
228 $chr = ord($encrypted[
$i]);
229 $eplain .= chr($chr ^ (
$r >> 8));
230 $r = ((($chr +
$r) * $c1 + $c2) % 65536);
232 if (preg_match(
'#/ForceBold[\s]*([^\s]*)#', $eplain, $matches) > 0) {
233 if ($matches[1] ==
'true') {
234 $fmetric[
'Flags'] |= 0x40000;
237 if (preg_match(
'#/StdVW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
238 $fmetric[
'StemV'] = intval($matches[1]);
240 $fmetric[
'StemV'] = 70;
242 if (preg_match(
'#/StdHW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
243 $fmetric[
'StemH'] = intval($matches[1]);
245 $fmetric[
'StemH'] = 30;
247 if (preg_match(
'#/BlueValues[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
248 $bv = explode(
' ', $matches[1]);
249 if (count($bv) >= 6) {
250 $v1 = intval($bv[2]);
251 $v2 = intval($bv[4]);
253 $fmetric[
'XHeight'] = $v1;
254 $fmetric[
'CapHeight'] = $v2;
256 $fmetric[
'XHeight'] = $v2;
257 $fmetric[
'CapHeight'] = $v1;
260 $fmetric[
'XHeight'] = 450;
261 $fmetric[
'CapHeight'] = 700;
264 $fmetric[
'XHeight'] = 450;
265 $fmetric[
'CapHeight'] = 700;
268 if (preg_match(
'#/lenIV[\s]*([0-9]*)#', $eplain, $matches) > 0) {
269 $lenIV = intval($matches[1]);
273 $fmetric[
'Leading'] = 0;
275 $eplain = substr($eplain, (strpos($eplain,
'/CharStrings') + 1));
276 preg_match_all(
'#/([A-Za-z0-9\.]*)[\s][0-9]+[\s]RD[\s](.*)[\s]ND#sU', $eplain, $matches, PREG_SET_ORDER);
283 $fmetric[
'MaxWidth'] = 0;
285 foreach ($matches as $k => $v) {
287 if (isset($imap[$v[1]])) {
289 } elseif ($enc_map !==
false) {
290 $cid = array_search($v[1], $enc_map);
291 if ($cid ===
false) {
293 } elseif ($cid > 1000) {
304 for (
$i = 0;
$i < $clen; ++
$i) {
306 $ccom[] = ($chr ^ (
$r >> 8));
307 $r = ((($chr +
$r) * $c1 + $c2) % 65536);
314 if ($ccom[
$i] < 32) {
315 $cdec[$ck] = $ccom[
$i];
316 if (($ck > 0) AND ($cdec[$ck] == 13)) {
318 $cwidths[$cid] = $cdec[($ck - 1)];
321 } elseif (($ccom[
$i] >= 32) AND ($ccom[
$i] <= 246)) {
322 $cdec[$ck] = ($ccom[
$i] - 139);
324 } elseif (($ccom[
$i] >= 247) AND ($ccom[
$i] <= 250)) {
325 $cdec[$ck] = ((($ccom[
$i] - 247) * 256) + $ccom[(
$i + 1)] + 108);
327 } elseif (($ccom[
$i] >= 251) AND ($ccom[
$i] <= 254)) {
328 $cdec[$ck] = ((-($ccom[
$i] - 251) * 256) - $ccom[(
$i + 1)] - 108);
330 } elseif ($ccom[
$i] == 255) {
331 $sval = chr($ccom[(
$i + 1)]).chr($ccom[(
$i + 2)]).chr($ccom[(
$i + 3)]).chr($ccom[(
$i + 4)]);
332 $vsval = unpack(
'li', $sval);
333 $cdec[$ck] = $vsval[
'i'];
339 $fmetric[
'MissingWidth'] = $cwidths[0];
340 $fmetric[
'MaxWidth'] = $fmetric[
'MissingWidth'];
341 $fmetric[
'AvgWidth'] = 0;
343 for ($cid = 0; $cid <= 255; ++$cid) {
344 if (isset($cwidths[$cid])) {
345 if ($cwidths[$cid] > $fmetric[
'MaxWidth']) {
346 $fmetric[
'MaxWidth'] = $cwidths[$cid];
348 $fmetric[
'AvgWidth'] += $cwidths[$cid];
349 $fmetric[
'cw'] .=
','.$cid.
'=>'.$cwidths[$cid];
351 $fmetric[
'cw'] .=
','.$cid.
'=>'.$fmetric[
'MissingWidth'];
354 $fmetric[
'AvgWidth'] = round($fmetric[
'AvgWidth'] / count($cwidths));
362 if ($fmetric[
'type'] !=
'cidfont0') {
365 symlink($fontfile, $outpath.$fmetric[
'file']);
368 $fmetric[
'file'] .=
'.z';
370 fwrite($fp, gzcompress($font));
383 for (
$i = 0;
$i < $numTables; ++
$i) {
385 $tag = substr($font, $offset, 4);
396 $offset =
$table[
'head'][
'offset'] + 12;
407 $urk = (1000 / $fmetric[
'unitsPerEm']);
417 $fmetric[
'bbox'] =
''.$xMin.
' '.$yMin.
' '.$xMax.
' '.$yMax.
'';
421 $fmetric[
'Flags'] = $flags;
422 if (($macStyle & 2) == 2) {
424 $fmetric[
'Flags'] |= 64;
427 $offset =
$table[
'head'][
'offset'] + 50;
431 $indexToLoc =
array();
432 $offset =
$table[
'loca'][
'offset'];
435 $tot_num_glyphs = floor(
$table[
'loca'][
'length'] / 2);
436 for (
$i = 0;
$i < $tot_num_glyphs; ++
$i) {
438 if (isset($indexToLoc[(
$i - 1)]) && ($indexToLoc[
$i] == $indexToLoc[(
$i - 1)])) {
440 unset($indexToLoc[(
$i - 1)]);
446 $tot_num_glyphs = floor(
$table[
'loca'][
'length'] / 4);
447 for (
$i = 0;
$i < $tot_num_glyphs; ++
$i) {
449 if (isset($indexToLoc[(
$i - 1)]) && ($indexToLoc[
$i] == $indexToLoc[(
$i - 1)])) {
451 unset($indexToLoc[(
$i - 1)]);
457 $offset =
$table[
'cmap'][
'offset'] + 2;
460 $encodingTables =
array();
461 for (
$i = 0;
$i < $numEncodingTables; ++
$i) {
470 $offset =
$table[
'OS/2'][
'offset'];
478 $fmetric[
'StemV'] = round((70 * $usWeightClass) / 400);
479 $fmetric[
'StemH'] = round((30 * $usWeightClass) / 400);
489 $fmetric[
'name'] =
'';
490 $offset =
$table[
'name'][
'offset'];
498 for (
$i = 0;
$i < $numNameRecords; ++
$i) {
510 $offset = (
$table[
'name'][
'offset'] + $stringStorageOffset + $stringOffset);
511 $fmetric[
'name'] = substr($font, $offset, $stringLength);
512 $fmetric[
'name'] = preg_replace(
'/[^a-zA-Z0-9_\-]/',
'', $fmetric[
'name']);
518 if (empty($fmetric[
'name'])) {
519 $fmetric[
'name'] = $font_name;
522 $offset =
$table[
'post'][
'offset'];
533 $fmetric[
'Flags'] |= 1;
536 $offset =
$table[
'hhea'][
'offset'];
554 $offset =
$table[
'maxp'][
'offset'];
560 foreach ($encodingTables as $enctable) {
562 if (($enctable[
'platformID'] == $platid) AND ($enctable[
'encodingID'] == $encid)) {
563 $offset =
$table[
'cmap'][
'offset'] + $enctable[
'offset'];
569 for ($c = 0; $c < 256; ++$c) {
579 for (
$i = 0;
$i < 256; ++
$i) {
583 if ($numSubHeaders < $subHeaderKeys[
$i]) {
584 $numSubHeaders = $subHeaderKeys[
$i];
590 $subHeaders =
array();
591 $numGlyphIndexArray = 0;
592 for ($k = 0; $k < $numSubHeaders; ++$k) {
601 $subHeaders[$k][
'idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8));
602 $subHeaders[$k][
'idRangeOffset'] /= 2;
603 $numGlyphIndexArray += $subHeaders[$k][
'entryCount'];
605 for ($k = 0; $k < $numGlyphIndexArray; ++$k) {
609 for (
$i = 0;
$i < 256; ++
$i) {
610 $k = $subHeaderKeys[
$i];
614 $g = $glyphIndexArray[0];
618 $start_byte = $subHeaders[$k][
'firstCode'];
619 $end_byte = $start_byte + $subHeaders[$k][
'entryCount'];
620 for ($j = $start_byte; $j < $end_byte; ++$j) {
622 $c = ((
$i << 8) + $j);
623 $idRangeOffset = ($subHeaders[$k][
'idRangeOffset'] + $j - $subHeaders[$k][
'firstCode']);
624 $g = ($glyphIndexArray[$idRangeOffset] + $subHeaders[$k][
'idDelta']) % 65536;
642 for ($k = 0; $k < $segCount; ++$k) {
647 $startCount =
array();
648 for ($k = 0; $k < $segCount; ++$k) {
653 for ($k = 0; $k < $segCount; ++$k) {
657 $idRangeOffset =
array();
658 for ($k = 0; $k < $segCount; ++$k) {
662 $gidlen = (floor($length / 2) - 8 - (4 * $segCount));
663 $glyphIdArray =
array();
664 for ($k = 0; $k < $gidlen; ++$k) {
668 for ($k = 0; $k < $segCount; ++$k) {
669 for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) {
670 if ($idRangeOffset[$k] == 0) {
671 $g = ($idDelta[$k] + $c) % 65536;
673 $gid = (floor($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k));
674 $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536;
690 for ($k = 0; $k < $entryCount; ++$k) {
691 $c = ($k + $firstCode);
700 for ($k = 0; $k < 8192; ++$k) {
706 for (
$i = 0;
$i < $nGroups; ++
$i) {
713 for ($k = $startCharCode; $k <= $endCharCode; ++$k) {
714 $is32idx = floor($c / 8);
715 if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) {
722 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888;
736 for ($k = 0; $k < $numChars; ++$k) {
737 $c = ($k + $startCharCode);
748 for ($k = 0; $k < $nGroups; ++$k) {
755 for ($c = $startCharCode; $c <= $endCharCode; ++$c) {
756 $ctg[$c] = $startGlyphCode;
773 if (!isset($ctg[0])) {
777 $offset = (
$table[
'glyf'][
'offset'] + $indexToLoc[$ctg[120]] + 4);
782 $fmetric[
'XHeight'] = round(($yMax - $yMin) * $urk);
784 $offset = (
$table[
'glyf'][
'offset'] + $indexToLoc[$ctg[72]] + 4);
789 $fmetric[
'CapHeight'] = round(($yMax - $yMin) * $urk);
792 $offset =
$table[
'hmtx'][
'offset'];
793 for (
$i = 0 ;
$i < $numberOfHMetrics; ++
$i) {
797 if ($numberOfHMetrics < $numGlyphs) {
799 $cw = array_pad($cw, $numGlyphs, $cw[($numberOfHMetrics - 1)]);
801 $fmetric[
'MissingWidth'] = $cw[0];
803 $fmetric[
'cbbox'] =
'';
804 for ($cid = 0; $cid <= 65535; ++$cid) {
805 if (isset($ctg[$cid])) {
806 if (isset($cw[$ctg[$cid]])) {
807 $fmetric[
'cw'] .=
','.$cid.
'=>'.$cw[$ctg[$cid]];
809 if ($addcbbox AND isset($indexToLoc[$ctg[$cid]])) {
810 $offset = (
$table[
'glyf'][
'offset'] + $indexToLoc[$ctg[$cid]]);
815 $fmetric[
'cbbox'] .=
','.$cid.
'=>array('.$xMin.
','.$yMin.
','.$xMax.
','.$yMax.
')';
820 if (($fmetric[
'type'] ==
'TrueTypeUnicode') AND (count($ctg) == 256)) {
821 $fmetric[
'type'] =
'TrueType';
824 $pfile =
'<'.
'?'.
'php'.
"\n";
825 $pfile .=
'// TCPDF FONT FILE DESCRIPTION'.
"\n";
826 $pfile .=
'$type=\''.$fmetric[
'type'].
'\';
'."\n"; 827 $pfile .= '$name=\
''.$fmetric[
'name'].
'\';
'."\n"; 828 $pfile .= '$up=
'.$fmetric['underlinePosition
'].';
'."\n"; 829 $pfile .= '$ut=
'.$fmetric['underlineThickness
'].';
'."\n"; 830 if ($fmetric['MissingWidth
'] > 0) { 831 $pfile .= '$dw=
'.$fmetric['MissingWidth
'].';
'."\n"; 833 $pfile .= '$dw=
'.$fmetric['AvgWidth
'].';
'."\n"; 835 $pfile .= '$diff=\
''.$fmetric[
'diff'].
'\';
'."\n"; 836 if ($fmetric['type
'] == 'Type1
') { 838 $pfile .= '$enc=\
''.$fmetric[
'enc'].
'\';
'."\n"; 839 $pfile .= '$file=\
''.$fmetric[
'file'].
'\';
'."\n"; 840 $pfile .= '$size1=
'.$fmetric['size1
'].';
'."\n"; 841 $pfile .= '$size2=
'.$fmetric['size2
'].';
'."\n"; 843 $pfile .= '$originalsize=
'.$fmetric['originalsize
'].';
'."\n"; 844 if ($fmetric['type
'] == 'cidfont0
') { 849 $pfile .=
'$enc=\'UniJIS-UTF16-H\';'.
"\n";
850 $pfile .=
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Japan1\',\'Supplement\'=>5);'.
"\n";
851 $pfile .=
'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'.
"\n";
855 $pfile .=
'// Korean'.
"\n";
856 $pfile .=
'$enc=\'UniKS-UTF16-H\';'.
"\n";
857 $pfile .=
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Korea1\',\'Supplement\'=>0);'.
"\n";
858 $pfile .=
'include(dirname(__FILE__).\'/uni2cid_ak12.php\');'.
"\n";
862 $pfile .=
'// Chinese Simplified'.
"\n";
863 $pfile .=
'$enc=\'UniGB-UTF16-H\';'.
"\n";
864 $pfile .=
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'GB1\',\'Supplement\'=>2);'.
"\n";
865 $pfile .=
'include(dirname(__FILE__).\'/uni2cid_ag15.php\');'.
"\n";
870 $pfile .=
'// Chinese Traditional'.
"\n";
871 $pfile .=
'$enc=\'UniCNS-UTF16-H\';'.
"\n";
872 $pfile .=
'$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'CNS1\',\'Supplement\'=>0);'.
"\n";
873 $pfile .=
'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'.
"\n";
879 $pfile .=
'$enc=\''.$fmetric[
'enc'].
'\';
'."\n"; 880 $pfile .= '$file=\
''.$fmetric[
'file'].
'\';
'."\n"; 881 $pfile .= '$ctg=\
''.$fmetric[
'ctg'].
'\';
'."\n"; 882 // create CIDToGIDMap 883 $cidtogidmap = str_pad('', 131072, "\x00"); // (256 * 256 * 2) = 131072 884 foreach ($ctg as $cid => $gid) { 885 $cidtogidmap = self::updateCIDtoGIDmap($cidtogidmap, $cid, $ctg[$cid]); 887 // store compressed CIDToGIDMap 888 $fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['ctg
'], 'wb
'); 889 fwrite($fp, gzcompress($cidtogidmap)); 893 $pfile .= '$desc=
array(
'; 894 $pfile .= '\
'Flags\'=>'.$fmetric[
'Flags'].
',';
895 $pfile .=
'\'FontBBox\
'=>\'['.$fmetric[
'bbox'].
']\',';
896 $pfile .=
'\'ItalicAngle\
'=>'.$fmetric[
'italicAngle'].
',';
897 $pfile .=
'\'Ascent\
'=>'.$fmetric[
'Ascent'].
',';
898 $pfile .=
'\'Descent\
'=>'.$fmetric[
'Descent'].
',';
899 $pfile .=
'\'Leading\
'=>'.$fmetric[
'Leading'].
',';
900 $pfile .=
'\'CapHeight\
'=>'.$fmetric[
'CapHeight'].
',';
901 $pfile .=
'\'XHeight\
'=>'.$fmetric[
'XHeight'].
',';
902 $pfile .=
'\'StemV\
'=>'.$fmetric[
'StemV'].
',';
903 $pfile .=
'\'StemH\
'=>'.$fmetric[
'StemH'].
',';
904 $pfile .=
'\'AvgWidth\
'=>'.$fmetric[
'AvgWidth'].
',';
905 $pfile .=
'\'MaxWidth\
'=>'.$fmetric[
'MaxWidth'].
',';
906 $pfile .=
'\'MissingWidth\
'=>'.$fmetric[
'MissingWidth'].
'';
908 if (!empty($fmetric[
'cbbox'])) {
909 $pfile .=
'$cbbox=array('.substr($fmetric[
'cbbox'], 1).
');'.
"\n";
911 $pfile .=
'$cw=array('.substr($fmetric[
'cw'], 1).
');'.
"\n";
912 $pfile .=
'// --- EOF ---'.
"\n";
932 $tlen = ($length / 4);
934 for (
$i = 0;
$i < $tlen; ++
$i) {
935 $v = unpack(
'Ni', substr(
$table, $offset, 4));
939 $sum = unpack(
'Ni', pack(
'N', $sum));
968 for (
$i = 0;
$i < $numTables; ++
$i) {
970 $tag = substr($font, $offset, 4);
981 $offset =
$table[
'head'][
'offset'] + 12;
988 $offset =
$table[
'head'][
'offset'] + 50;
992 $indexToLoc =
array();
993 $offset =
$table[
'loca'][
'offset'];
996 $tot_num_glyphs = floor(
$table[
'loca'][
'length'] / 2);
997 for (
$i = 0;
$i < $tot_num_glyphs; ++
$i) {
1003 $tot_num_glyphs = (
$table[
'loca'][
'length'] / 4);
1004 for (
$i = 0;
$i < $tot_num_glyphs; ++
$i) {
1010 $subsetglyphs =
array();
1011 $subsetglyphs[0] =
true;
1012 $offset =
$table[
'cmap'][
'offset'] + 2;
1015 $encodingTables =
array();
1016 for (
$i = 0;
$i < $numEncodingTables; ++
$i) {
1024 foreach ($encodingTables as $enctable) {
1026 $offset =
$table[
'cmap'][
'offset'] + $enctable[
'offset'];
1032 for ($c = 0; $c < 256; ++$c) {
1033 if (isset($subsetchars[$c])) {
1035 $subsetglyphs[$g] =
true;
1044 for (
$i = 0;
$i < 256; ++
$i) {
1048 if ($numSubHeaders < $subHeaderKeys[
$i]) {
1049 $numSubHeaders = $subHeaderKeys[
$i];
1055 $subHeaders =
array();
1056 $numGlyphIndexArray = 0;
1057 for ($k = 0; $k < $numSubHeaders; ++$k) {
1066 $subHeaders[$k][
'idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8));
1067 $subHeaders[$k][
'idRangeOffset'] /= 2;
1068 $numGlyphIndexArray += $subHeaders[$k][
'entryCount'];
1070 for ($k = 0; $k < $numGlyphIndexArray; ++$k) {
1074 for (
$i = 0;
$i < 256; ++
$i) {
1075 $k = $subHeaderKeys[
$i];
1079 if (isset($subsetchars[$c])) {
1080 $g = $glyphIndexArray[0];
1081 $subsetglyphs[$g] =
true;
1085 $start_byte = $subHeaders[$k][
'firstCode'];
1086 $end_byte = $start_byte + $subHeaders[$k][
'entryCount'];
1087 for ($j = $start_byte; $j < $end_byte; ++$j) {
1089 $c = ((
$i << 8) + $j);
1090 if (isset($subsetchars[$c])) {
1091 $idRangeOffset = ($subHeaders[$k][
'idRangeOffset'] + $j - $subHeaders[$k][
'firstCode']);
1092 $g = ($glyphIndexArray[$idRangeOffset] + $subHeaders[$k][
'idDelta']) % 65536;
1096 $subsetglyphs[$g] =
true;
1110 $endCount =
array();
1111 for ($k = 0; $k < $segCount; ++$k) {
1116 $startCount =
array();
1117 for ($k = 0; $k < $segCount; ++$k) {
1122 for ($k = 0; $k < $segCount; ++$k) {
1126 $idRangeOffset =
array();
1127 for ($k = 0; $k < $segCount; ++$k) {
1131 $gidlen = (floor($length / 2) - 8 - (4 * $segCount));
1132 $glyphIdArray =
array();
1133 for ($k = 0; $k < $gidlen; ++$k) {
1137 for ($k = 0; $k < $segCount; ++$k) {
1138 for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) {
1139 if (isset($subsetchars[$c])) {
1140 if ($idRangeOffset[$k] == 0) {
1141 $g = ($idDelta[$k] + $c) % 65536;
1143 $gid = (floor($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k));
1144 $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536;
1149 $subsetglyphs[$g] =
true;
1161 for ($k = 0; $k < $entryCount; ++$k) {
1162 $c = ($k + $firstCode);
1163 if (isset($subsetchars[$c])) {
1165 $subsetglyphs[$g] =
true;
1173 for ($k = 0; $k < 8192; ++$k) {
1179 for (
$i = 0;
$i < $nGroups; ++
$i) {
1186 for ($k = $startCharCode; $k <= $endCharCode; ++$k) {
1187 $is32idx = floor($c / 8);
1188 if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) {
1195 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888;
1197 if (isset($subsetchars[$c])) {
1198 $subsetglyphs[$startGlyphID] =
true;
1211 for ($k = 0; $k < $numChars; ++$k) {
1212 $c = ($k + $startCharCode);
1213 if (isset($subsetchars[$c])) {
1215 $subsetglyphs[$g] =
true;
1225 for ($k = 0; $k < $nGroups; ++$k) {
1232 for ($c = $startCharCode; $c <= $endCharCode; ++$c) {
1233 if (isset($subsetchars[$c])) {
1234 $subsetglyphs[$startGlyphCode] =
true;
1252 $new_sga = $subsetglyphs;
1253 while (!empty($new_sga)) {
1256 foreach ($sga as
$key => $val) {
1257 if (isset($indexToLoc[
$key])) {
1258 $offset = (
$table[
'glyf'][
'offset'] + $indexToLoc[
$key]);
1261 if ($numberOfContours < 0) {
1268 if (!isset($subsetglyphs[$glyphIndex])) {
1270 $new_sga[$glyphIndex] =
true;
1280 } elseif ($flags & 64) {
1282 } elseif ($flags & 128) {
1285 }
while ($flags & 32);
1289 $subsetglyphs += $new_sga;
1292 ksort($subsetglyphs);
1297 $glyf_offset =
$table[
'glyf'][
'offset'];
1298 for (
$i = 0;
$i < $tot_num_glyphs; ++
$i) {
1299 if (isset($subsetglyphs[
$i])) {
1300 $length = ($indexToLoc[($i + 1)] - $indexToLoc[$i]);
1301 $glyf .= substr($font, ($glyf_offset + $indexToLoc[$i]), $length);
1305 if ($short_offset) {
1306 $loca .= pack(
'n', floor($offset / 2));
1308 $loca .= pack(
'N', $offset);
1314 $table_names =
array (
'head',
'hhea',
'hmtx',
'maxp',
'cvt ',
'fpgm',
'prep');
1318 if (in_array(
$tag, $table_names)) {
1320 if ($tag ==
'head') {
1322 $table[
$tag][
'data'] = substr(
$table[$tag][
'data'], 0, 8).
"\x0\x0\x0\x0".substr(
$table[$tag][
'data'], 12);
1328 $table[
$tag][
'data'] .= str_repeat(
"\x0", $pad);
1339 $table[
'loca'][
'data'] = $loca;
1340 $table[
'loca'][
'length'] = strlen($loca);
1341 $pad = 4 - (
$table[
'loca'][
'length'] % 4);
1344 $table[
'loca'][
'length'] += $pad;
1345 $table[
'loca'][
'data'] .= str_repeat(
"\x0", $pad);
1347 $table[
'loca'][
'offset'] = $offset;
1348 $table[
'loca'][
'checkSum'] = self::_getTTFtableChecksum(
$table[
'loca'][
'data'],
$table[
'loca'][
'length']);
1349 $offset +=
$table[
'loca'][
'length'];
1351 $table[
'glyf'][
'data'] = $glyf;
1352 $table[
'glyf'][
'length'] = strlen($glyf);
1353 $pad = 4 - (
$table[
'glyf'][
'length'] % 4);
1356 $table[
'glyf'][
'length'] += $pad;
1357 $table[
'glyf'][
'data'] .= str_repeat(
"\x0", $pad);
1359 $table[
'glyf'][
'offset'] = $offset;
1360 $table[
'glyf'][
'checkSum'] = self::_getTTFtableChecksum(
$table[
'glyf'][
'data'],
$table[
'glyf'][
'length']);
1363 $font .= pack(
'N', 0x10000);
1364 $numTables = count(
$table);
1365 $font .= pack(
'n', $numTables);
1366 $entrySelector = floor(log($numTables, 2));
1367 $searchRange = pow(2, $entrySelector) * 16;
1368 $rangeShift = ($numTables * 16) - $searchRange;
1369 $font .= pack(
'n', $searchRange);
1370 $font .= pack(
'n', $entrySelector);
1371 $font .= pack(
'n', $rangeShift);
1372 $offset = ($numTables * 16);
1375 $font .= pack(
'N',
$data[
'checkSum']);
1376 $font .= pack(
'N', (
$data[
'offset'] + $offset));
1377 $font .= pack(
'N',
$data[
'length']);
1380 $font .= $data[
'data'];
1383 $checkSumAdjustment = 0xB1B0AFBA - self::_getTTFtableChecksum($font, strlen($font));
1384 $font = substr($font, 0,
$table[
'head'][
'offset'] + 8).pack(
'N', $checkSumAdjustment).substr($font,
$table[
'head'][
'offset'] + 12);
1405 foreach ($font[
'cw'] as $cid => $width) {
1407 if ($font[
'subset'] AND (!isset($font[
'subsetchars'][$cid]))) {
1411 if ($width != $font[
'dw']) {
1412 if ($cid == ($prevcid + 1)) {
1414 if ($width == $prevwidth) {
1415 if ($width == $range[$rangeid][0]) {
1416 $range[$rangeid][] = $width;
1418 array_pop($range[$rangeid]);
1420 $rangeid = $prevcid;
1421 $range[$rangeid] =
array();
1422 $range[$rangeid][] = $prevwidth;
1423 $range[$rangeid][] = $width;
1426 $range[$rangeid][
'interval'] =
true;
1431 $range[$rangeid] =
array();
1432 $range[$rangeid][] = $width;
1434 $range[$rangeid][] = $width;
1441 $range[$rangeid] =
array();
1442 $range[$rangeid][] = $width;
1446 $prevwidth = $width;
1453 foreach ($range as $k => $ws) {
1455 if (($k == $nextk) AND (!$prevint) AND ((!isset($ws[
'interval'])) OR ($cws < 4))) {
1456 if (isset($range[$k][
'interval'])) {
1457 unset($range[$k][
'interval']);
1459 $range[$prevk] = array_merge($range[$prevk], $range[$k]);
1465 if (isset($ws[
'interval'])) {
1471 if (isset($range[$k][
'interval'])) {
1472 unset($range[$k][
'interval']);
1481 foreach ($range as $k => $ws) {
1482 if (count(array_count_values($ws)) == 1) {
1484 $w .=
' '.$k.
' '.($k + count($ws) - 1).
' '.$ws[0];
1487 $w .=
' '.$k.
' [ '.implode(
' ', $ws).
' ]';
1490 return '/W ['.$w.
' ]';
1507 if (($cid >= 0) AND ($cid <= 0xFFFF) AND ($gid >= 0)) {
1508 if ($gid > 0xFFFF) {
1511 $map[($cid * 2)] = chr($gid >> 8);
1512 $map[(($cid * 2) + 1)] = chr($gid & 0xFF);
1523 if (!
defined(
'K_PATH_FONTS') AND is_dir($fdir = realpath(dirname(__FILE__).
'/../fonts'))) {
1524 if (substr($fdir, -1) !=
'/') {
1527 define(
'K_PATH_FONTS', $fdir);
1529 return defined(
'K_PATH_FONTS') ? K_PATH_FONTS :
'';
1546 if (($fontdir !==
false) AND @file_exists($fontdir.$file)) {
1547 $fontfile = $fontdir.$file;
1548 } elseif (@file_exists(self::_getfontpath().
$file)) {
1549 $fontfile = self::_getfontpath().$file;
1550 } elseif (@file_exists(
$file)) {
1569 $size = ($refsize - 4);
1573 $size = ($refsize - 3);
1577 $size = ($refsize - 2);
1585 $size = ($refsize + 2);
1589 $size = ($refsize + 4);
1593 $size = ($refsize + 6);
1597 $size = ($refsize - 3);
1601 $size = ($refsize + 3);
1666 public static function unichr($c, $unicode=
true) {
1669 } elseif ($c <= 0x7F) {
1672 } elseif ($c <= 0x7FF) {
1674 return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F);
1675 } elseif ($c <= 0xFFFF) {
1677 return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
1678 } elseif ($c <= 0x10FFFF) {
1680 return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
1747 $outstr .=
"\xFE\xFF";
1749 foreach ($unicode as $char) {
1750 if ($char == 0x200b) {
1752 } elseif ($char == 0xFFFD) {
1753 $outstr .=
"\xFF\xFD";
1754 } elseif ($char < 0x10000) {
1755 $outstr .= chr($char >> 0x08);
1756 $outstr .= chr($char & 0xFF);
1759 $w1 = 0xD800 | ($char >> 0x0a);
1760 $w2 = 0xDC00 | ($char & 0x3FF);
1761 $outstr .= chr($w1 >> 0x08);
1762 $outstr .= chr($w1 & 0xFF);
1763 $outstr .= chr($w2 >> 0x08);
1764 $outstr .= chr($w2 & 0xFF);
1780 return array_map(
array(
'TCPDF_FONTS',
'unichrUnicode'), $ta);
1782 return array_map(
array(
'TCPDF_FONTS',
'unichrASCII'), $ta);
1795 if (strlen($start) == 0) {
1798 if (strlen(
$end) == 0) {
1799 $end = count($strarr);
1818 if (strlen($start) == 0) {
1821 if (strlen(
$end) == 0) {
1822 $end = count($uniarr);
1826 $string .= $uniarr[
$i];
1841 foreach ($unicode as $char) {
1847 } elseif ($char == 0xFFFD) {
1866 foreach ($unicode as $char) {
1868 $outstr .= chr($char);
1872 } elseif ($char == 0xFFFD) {
1889 if (!isset(self::$cache_uniord[$uch])) {
1890 self::$cache_uniord[$uch] = self::getUniord($uch);
1892 return self::$cache_uniord[$uch];
1929 if (function_exists(
'mb_convert_encoding')) {
1930 list(, $char) = @unpack(
'N', mb_convert_encoding($uch,
'UCS-4BE',
'UTF-8'));
1938 $length = strlen($uch);
1939 for (
$i = 0;
$i < $length; ++
$i) {
1940 $char = ord($uch[
$i]);
1941 if ($countbytes == 0) {
1942 if ($char <= 0x7F) {
1944 } elseif (($char >> 0x05) == 0x06) {
1945 $bytes[] = ($char - 0xC0) << 0x06;
1948 } elseif (($char >> 0x04) == 0x0E) {
1949 $bytes[] = ($char - 0xE0) << 0x0C;
1952 } elseif (($char >> 0x03) == 0x1E) {
1953 $bytes[] = ($char - 0xF0) << 0x12;
1960 } elseif (($char >> 0x06) == 0x02) {
1961 $bytes[] = $char - 0x80;
1963 if ($countbytes == $numbytes) {
1966 for ($j = 1; $j < $numbytes; ++$j) {
1967 $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06));
1969 if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) {
2001 $carr = array_map(
array(
'TCPDF_FONTS',
'uniord'), $chars);
2003 $chars = str_split($str);
2004 $carr = array_map(
'ord', $chars);
2006 $currentfont[
'subsetchars'] += array_fill_keys($carr,
true);
2019 public static function UTF8ToLatin1($str, $isunicode=
true, &$currentfont) {
2020 $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont);
2021 return self::UTF8ArrToLatin1($unicode);
2035 public static function UTF8ToUTF16BE($str, $setbom=
false, $isunicode=
true, &$currentfont) {
2039 $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont);
2040 return self::arrUTF8ToUTF16BE($unicode, $setbom);
2055 public static function utf8StrRev($str, $setbom=
false, $forcertl=
false, $isunicode=
true, &$currentfont) {
2056 return self::utf8StrArrRev(self::UTF8StringToArray($str, $isunicode, $currentfont), $str, $setbom, $forcertl, $isunicode, $currentfont);
2072 public static function utf8StrArrRev($arr, $str=
'', $setbom=
false, $forcertl=
false, $isunicode=
true, &$currentfont) {
2073 return self::arrUTF8ToUTF16BE(self::utf8Bidi($arr, $str, $forcertl, $isunicode, $currentfont), $setbom);
2088 public static function utf8Bidi($ta, $str=
'', $forcertl=
false, $isunicode=
true, &$currentfont) {
2095 $str = self::UTF8ArrSubString($ta,
'',
'', $isunicode);
2109 $numchars = count($ta);
2111 if ($forcertl ==
'R') {
2113 } elseif ($forcertl ==
'L') {
2118 for (
$i=0;
$i < $numchars; ++
$i) {
2123 } elseif ((
$type ==
'AL') OR (
$type ==
'R')) {
2134 $remember =
array();
2136 $sor = $pel % 2 ?
'R' :
'L';
2140 $chardata = Array();
2144 for (
$i=0;
$i < $numchars; ++
$i) {
2149 $next_level = $cel + ($cel % 2) + 1;
2150 if ($next_level < 62) {
2155 $eor = $cel % 2 ?
'R' :
'L';
2161 $next_level = $cel + 2 - ($cel % 2);
2162 if ( $next_level < 62 ) {
2167 $eor = $cel % 2 ?
'R' :
'L';
2173 $next_level = $cel + ($cel % 2) + 1;
2174 if ($next_level < 62) {
2179 $eor = $cel % 2 ?
'R' :
'L';
2185 $next_level = $cel + 2 - ($cel % 2);
2186 if ( $next_level < 62 ) {
2191 $eor = $cel % 2 ?
'R' :
'L';
2195 if (count($remember)) {
2196 $last = count($remember ) - 1;
2201 $match = array_pop($remember);
2202 $cel = $match[
'cel'];
2203 $dos = $match[
'dos'];
2205 $eor = ($cel > $match[
'cel'] ? $cel : $match[
'cel']) % 2 ?
'R' :
'L';
2226 $chardata[] =
array(
'char' => $ta[
$i],
'level' => $cel,
'type' => $chardir,
'sor' => $sor,
'eor' => $eor);
2237 $numchars = count($chardata);
2242 for (
$i=0;
$i < $numchars; ++
$i) {
2243 if ($chardata[
$i][
'type'] ==
'NSM') {
2245 $chardata[
$i][
'type'] = $chardata[
$i][
'sor'];
2247 $chardata[
$i][
'type'] = $chardata[(
$i-1)][
'type'];
2250 if ($chardata[
$i][
'level'] != $prevlevel) {
2255 $prevlevel = $chardata[
$i][
'level'];
2261 for (
$i=0;
$i < $numchars; ++
$i) {
2262 if ($chardata[
$i][
'char'] ==
'EN') {
2263 for ($j=$levcount; $j >= 0; $j--) {
2264 if ($chardata[$j][
'type'] ==
'AL') {
2265 $chardata[
$i][
'type'] =
'AN';
2266 } elseif (($chardata[$j][
'type'] ==
'L') OR ($chardata[$j][
'type'] ==
'R')) {
2271 if ($chardata[
$i][
'level'] != $prevlevel) {
2276 $prevlevel = $chardata[
$i][
'level'];
2280 for (
$i=0;
$i < $numchars; ++
$i) {
2281 if ($chardata[
$i][
'type'] ==
'AL') {
2282 $chardata[
$i][
'type'] =
'R';
2289 for (
$i=0;
$i < $numchars; ++
$i) {
2290 if (($levcount > 0) AND ((
$i+1) < $numchars) AND ($chardata[(
$i+1)][
'level'] == $prevlevel)) {
2291 if (($chardata[
$i][
'type'] ==
'ES') AND ($chardata[(
$i-1)][
'type'] ==
'EN') AND ($chardata[(
$i+1)][
'type'] ==
'EN')) {
2292 $chardata[
$i][
'type'] =
'EN';
2293 } elseif (($chardata[
$i][
'type'] ==
'CS') AND ($chardata[(
$i-1)][
'type'] ==
'EN') AND ($chardata[(
$i+1)][
'type'] ==
'EN')) {
2294 $chardata[
$i][
'type'] =
'EN';
2295 } elseif (($chardata[
$i][
'type'] ==
'CS') AND ($chardata[(
$i-1)][
'type'] ==
'AN') AND ($chardata[(
$i+1)][
'type'] ==
'AN')) {
2296 $chardata[
$i][
'type'] =
'AN';
2299 if ($chardata[
$i][
'level'] != $prevlevel) {
2304 $prevlevel = $chardata[
$i][
'level'];
2310 for (
$i=0;
$i < $numchars; ++
$i) {
2311 if ($chardata[
$i][
'type'] ==
'ET') {
2312 if (($levcount > 0) AND ($chardata[(
$i-1)][
'type'] ==
'EN')) {
2313 $chardata[
$i][
'type'] =
'EN';
2316 while (($j < $numchars) AND ($chardata[$j][
'level'] == $prevlevel)) {
2317 if ($chardata[$j][
'type'] ==
'EN') {
2318 $chardata[
$i][
'type'] =
'EN';
2320 } elseif ($chardata[$j][
'type'] !=
'ET') {
2327 if ($chardata[
$i][
'level'] != $prevlevel) {
2332 $prevlevel = $chardata[
$i][
'level'];
2338 for (
$i=0;
$i < $numchars; ++
$i) {
2339 if (($chardata[
$i][
'type'] ==
'ET') OR ($chardata[
$i][
'type'] ==
'ES') OR ($chardata[
$i][
'type'] ==
'CS')) {
2340 $chardata[
$i][
'type'] =
'ON';
2342 if ($chardata[
$i][
'level'] != $prevlevel) {
2347 $prevlevel = $chardata[
$i][
'level'];
2353 for (
$i=0;
$i < $numchars; ++
$i) {
2354 if ($chardata[
$i][
'char'] ==
'EN') {
2355 for ($j=$levcount; $j >= 0; $j--) {
2356 if ($chardata[$j][
'type'] ==
'L') {
2357 $chardata[
$i][
'type'] =
'L';
2358 } elseif ($chardata[$j][
'type'] ==
'R') {
2363 if ($chardata[
$i][
'level'] != $prevlevel) {
2368 $prevlevel = $chardata[
$i][
'level'];
2374 for (
$i=0;
$i < $numchars; ++
$i) {
2375 if (($levcount > 0) AND ((
$i+1) < $numchars) AND ($chardata[(
$i+1)][
'level'] == $prevlevel)) {
2376 if (($chardata[
$i][
'type'] ==
'N') AND ($chardata[(
$i-1)][
'type'] ==
'L') AND ($chardata[(
$i+1)][
'type'] ==
'L')) {
2377 $chardata[
$i][
'type'] =
'L';
2378 } elseif (($chardata[
$i][
'type'] ==
'N') AND
2379 (($chardata[(
$i-1)][
'type'] ==
'R') OR ($chardata[(
$i-1)][
'type'] ==
'EN') OR ($chardata[(
$i-1)][
'type'] ==
'AN')) AND
2380 (($chardata[(
$i+1)][
'type'] ==
'R') OR ($chardata[(
$i+1)][
'type'] ==
'EN') OR ($chardata[(
$i+1)][
'type'] ==
'AN'))) {
2381 $chardata[
$i][
'type'] =
'R';
2382 } elseif ($chardata[
$i][
'type'] ==
'N') {
2384 $chardata[
$i][
'type'] = $chardata[
$i][
'sor'];
2386 } elseif (($levcount == 0) AND ((
$i+1) < $numchars) AND ($chardata[(
$i+1)][
'level'] == $prevlevel)) {
2388 if (($chardata[
$i][
'type'] ==
'N') AND ($chardata[
$i][
'sor'] ==
'L') AND ($chardata[(
$i+1)][
'type'] ==
'L')) {
2389 $chardata[
$i][
'type'] =
'L';
2390 } elseif (($chardata[
$i][
'type'] ==
'N') AND
2391 (($chardata[
$i][
'sor'] ==
'R') OR ($chardata[
$i][
'sor'] ==
'EN') OR ($chardata[
$i][
'sor'] ==
'AN')) AND
2392 (($chardata[(
$i+1)][
'type'] ==
'R') OR ($chardata[(
$i+1)][
'type'] ==
'EN') OR ($chardata[(
$i+1)][
'type'] ==
'AN'))) {
2393 $chardata[
$i][
'type'] =
'R';
2394 } elseif ($chardata[
$i][
'type'] ==
'N') {
2396 $chardata[
$i][
'type'] = $chardata[
$i][
'sor'];
2398 } elseif (($levcount > 0) AND (((
$i+1) == $numchars) OR ((
$i+1) < $numchars) AND ($chardata[(
$i+1)][
'level'] != $prevlevel))) {
2400 if (($chardata[
$i][
'type'] ==
'N') AND ($chardata[(
$i-1)][
'type'] ==
'L') AND ($chardata[
$i][
'eor'] ==
'L')) {
2401 $chardata[
$i][
'type'] =
'L';
2402 } elseif (($chardata[
$i][
'type'] ==
'N') AND
2403 (($chardata[(
$i-1)][
'type'] ==
'R') OR ($chardata[(
$i-1)][
'type'] ==
'EN') OR ($chardata[(
$i-1)][
'type'] ==
'AN')) AND
2404 (($chardata[
$i][
'eor'] ==
'R') OR ($chardata[
$i][
'eor'] ==
'EN') OR ($chardata[
$i][
'eor'] ==
'AN'))) {
2405 $chardata[
$i][
'type'] =
'R';
2406 } elseif ($chardata[
$i][
'type'] ==
'N') {
2408 $chardata[
$i][
'type'] = $chardata[
$i][
'sor'];
2410 } elseif ($chardata[
$i][
'type'] ==
'N') {
2412 $chardata[
$i][
'type'] = $chardata[
$i][
'sor'];
2414 if ($chardata[
$i][
'level'] != $prevlevel) {
2419 $prevlevel = $chardata[
$i][
'level'];
2424 for (
$i=0;
$i < $numchars; ++
$i) {
2425 $odd = $chardata[
$i][
'level'] % 2;
2427 if (($chardata[
$i][
'type'] ==
'L') OR ($chardata[
$i][
'type'] ==
'AN') OR ($chardata[
$i][
'type'] ==
'EN')) {
2428 $chardata[
$i][
'level'] += 1;
2431 if ($chardata[
$i][
'type'] ==
'R') {
2432 $chardata[
$i][
'level'] += 1;
2433 } elseif (($chardata[
$i][
'type'] ==
'AN') OR ($chardata[
$i][
'type'] ==
'EN')) {
2434 $chardata[
$i][
'level'] += 2;
2437 $maxlevel = max($chardata[
$i][
'level'],$maxlevel);
2445 for (
$i=0;
$i < $numchars; ++
$i) {
2446 if (($chardata[
$i][
'type'] ==
'B') OR ($chardata[
$i][
'type'] ==
'S')) {
2447 $chardata[
$i][
'level'] = $pel;
2448 } elseif ($chardata[
$i][
'type'] ==
'WS') {
2450 while ($j < $numchars) {
2451 if ((($chardata[$j][
'type'] ==
'B') OR ($chardata[$j][
'type'] ==
'S')) OR
2452 (($j == ($numchars-1)) AND ($chardata[$j][
'type'] ==
'WS'))) {
2453 $chardata[
$i][
'level'] = $pel;
2455 } elseif ($chardata[$j][
'type'] !=
'WS') {
2466 $endedletter =
array(1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688);
2467 $alfletter =
array(1570,1571,1573,1575);
2468 $chardata2 = $chardata;
2472 for (
$i=0;
$i < $numchars; ++
$i) {
2474 $charAL[
$x] = $chardata[
$i];
2475 $charAL[
$x][
'i'] =
$i;
2476 $chardata[
$i][
'x'] =
$x;
2481 for (
$i=0;
$i < $numchars; ++
$i) {
2482 $thischar = $chardata[
$i];
2484 $prevchar = $chardata[(
$i-1)];
2488 if ((
$i+1) < $numchars) {
2489 $nextchar = $chardata[(
$i+1)];
2494 $x = $thischar[
'x'];
2496 $prevchar = $charAL[(
$x-1)];
2500 if ((
$x+1) < $numAL) {
2501 $nextchar = $charAL[(
$x+1)];
2506 if (($prevchar !==
false) AND ($prevchar[
'char'] == 1604) AND (in_array($thischar[
'char'], $alfletter))) {
2510 $prevchar = $charAL[(
$x-2)];
2518 if (($prevchar !==
false) AND ($nextchar !==
false) AND
2521 ($prevchar[
'type'] == $thischar[
'type']) AND
2522 ($nextchar[
'type'] == $thischar[
'type']) AND
2523 ($nextchar[
'char'] != 1567)) {
2524 if (in_array($prevchar[
'char'], $endedletter)) {
2525 if (isset($arabicarr[$thischar[
'char']][2])) {
2527 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][2];
2530 if (isset($arabicarr[$thischar[
'char']][3])) {
2532 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][3];
2535 } elseif (($nextchar !==
false) AND
2537 ($nextchar[
'type'] == $thischar[
'type']) AND
2538 ($nextchar[
'char'] != 1567)) {
2539 if (isset($arabicarr[$chardata[
$i][
'char']][2])) {
2541 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][2];
2543 } elseif ((($prevchar !==
false) AND
2545 ($prevchar[
'type'] == $thischar[
'type'])) OR
2546 (($nextchar !==
false) AND ($nextchar[
'char'] == 1567))) {
2548 if ((
$i > 1) AND ($thischar[
'char'] == 1607) AND
2549 ($chardata[
$i-1][
'char'] == 1604) AND
2550 ($chardata[
$i-2][
'char'] == 1604)) {
2553 $chardata2[
$i-2][
'char'] =
false;
2554 $chardata2[
$i-1][
'char'] =
false;
2555 $chardata2[
$i][
'char'] = 65010;
2557 if (($prevchar !==
false) AND in_array($prevchar[
'char'], $endedletter)) {
2558 if (isset($arabicarr[$thischar[
'char']][0])) {
2560 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][0];
2563 if (isset($arabicarr[$thischar[
'char']][1])) {
2565 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][1];
2569 } elseif (isset($arabicarr[$thischar[
'char']][0])) {
2571 $chardata2[
$i][
'char'] = $arabicarr[$thischar[
'char']][0];
2576 $chardata2[($charAL[(
$x-1)][
'i'])][
'char'] =
false;
2584 for (
$i = 0;
$i < ($numchars-1); ++
$i) {
2588 $chardata2[
$i][
'char'] =
false;
2594 foreach ($chardata2 as
$key => $value) {
2595 if ($value[
'char'] ===
false) {
2596 unset($chardata2[
$key]);
2599 $chardata = array_values($chardata2);
2600 $numchars = count($chardata);
2608 for ($j=$maxlevel; $j > 0; $j--) {
2609 $ordarray = Array();
2612 for (
$i=0;
$i < $numchars; ++
$i) {
2613 if ($chardata[
$i][
'level'] >= $j) {
2619 $revarr[] = $chardata[
$i];
2622 $revarr = array_reverse($revarr);
2623 $ordarray = array_merge($ordarray, $revarr);
2627 $ordarray[] = $chardata[
$i];
2631 $revarr = array_reverse($revarr);
2632 $ordarray = array_merge($ordarray, $revarr);
2634 $chardata = $ordarray;
2636 $ordarray =
array();
2637 foreach ($chardata as $cd) {
2638 $ordarray[] = $cd[
'char'];
2640 $currentfont[
'subsetchars'][$cd[
'char']] =
true;
static unichrUnicode($c)
Returns the unicode caracter specified by UTF-8 value.
static addTTFfont($fontfile, $fonttype='', $enc='', $flags=32, $outpath='', $platid=3, $encid=1, $addcbbox=false, $link=false)
Convert and add the selected TrueType or Type1 font to the fonts folder (that must be writeable)...
static _getTrueTypeFontSubset($font, $subsetchars)
Returns a subset of the TrueType font data without the unused glyphs.
static _getFIXED($str, $offset)
Get FIXED from string (32-bit signed fixed-point number (16.16).
static uniord($uch)
Converts UTF-8 character to integer value.
static arrUTF8ToUTF16BE($unicode, $setbom=false)
Converts array of UTF-8 characters to UTF16-BE string.
static utf8StrArrRev($arr, $str='', $setbom=false, $forcertl=false, $isunicode=true, &$currentfont)
Reverse the RLT substrings array using the Bidirectional Algorithm (http://unicode.org/reports/tr9/).
static $uni_PDF
Unicode code for Pop Directional Format.
static UTF8ArrToLatin1($unicode)
Converts UTF-8 characters array to array of Latin1 string
static $uni_diacritics
Array of character substitutions for sequences of two diacritics symbols.
static _putfontwidths($font, $cidoffset=0)
Outputs font widths.
static utf8Bidi($ta, $str='', $forcertl=false, $isunicode=true, &$currentfont)
Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/).
static updateCIDtoGIDmap($map, $cid, $gid)
Update the CIDToGIDMap string with a new value.
static _getUFWORD($str, $offset)
Get UFWORD from string (Big Endian 16-bit unsigned integer).
static unichr($c, $unicode=true)
Returns the unicode caracter specified by the value.
static _getfontpath()
Return fonts path.
static UTF8StringToArray($str, $isunicode=true, &$currentfont)
Converts UTF-8 strings to codepoints array.
static pregSplit($pattern, $modifiers, $subject, $limit=NULL, $flags=NULL)
Split string by a regular expression.
static unichrASCII($c)
Returns the unicode caracter specified by ASCII value.
static $uni_RLE
Unicode code for Right-to-Left Embedding.
static $uni_type
Array of Unicode types.
static empty_string($str)
Determine whether a string is empty.
static UTF8ArrToLatin1Arr($unicode)
Converts UTF-8 characters array to array of Latin1 characters array
static _getSHORT($str, $offset)
Get SHORT from string (Big Endian 16-bit signed integer).
static $uni_utf8tolatin
Array of character substitutions from UTF-8 Unicode to Latin1.
static getFontRefSize($size, $refsize=12)
Get a reference font size.
static _getFWORD($str, $offset)
Get FWORD from string (Big Endian 16-bit signed integer).
static utf8StrRev($str, $setbom=false, $forcertl=false, $isunicode=true, &$currentfont)
Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/).
static $uni_LRE
Unicode code for Left-to-Right Embedding.
static UTF8ToUTF16BE($str, $setbom=false, $isunicode=true, &$currentfont)
Converts UTF-8 strings to UTF16-BE.
static $uni_RLO
Unicode code for Right-to-Left Override.
static $uni_RE_PATTERN_ARABIC
Pattern to test Arabic strings using regular expressions.
static UTF8ArrSubString($strarr, $start='', $end='', $unicode=true)
Extract a slice of the $strarr array and return it as string.
static getFontFullPath($file, $fontdir=false)
Return font full path.
static UniArrSubString($uniarr, $start='', $end='')
Extract a slice of the $uniarr array and return it as string.
Create styles array
The data for the language used.
static _getULONG($str, $offset)
Get ULONG from string (Big Endian 32-bit unsigned integer).
static _getUSHORT($str, $offset)
Get USHORT from string (Big Endian 16-bit unsigned integer).
static $uni_arabicsubst
Arabic shape substitutions: char code => (isolated, final, initial, medial).
static $cache_uniord
Static cache used for speed up uniord performances.
static $uni_mirror
Mirror unicode characters.
static $encmap
Array of Encoding Maps.
static UTF8ToLatin1($str, $isunicode=true, &$currentfont)
Converts UTF-8 strings to Latin1 when using the standard 14 core fonts.
static $uni_LRO
Unicode code for Left-to-Right Override.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
if(empty($password)) $table
static getUniord($uch)
Converts UTF-8 character to integer value.
static _getTTFtableChecksum($table, $length)
Returs the checksum of a TTF table.
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
static _getBYTE($str, $offset)
Get BYTE from string (8-bit unsigned integer).
static $uni_RE_PATTERN_RTL
Pattern to test RTL (Righ-To-Left) strings using regular expressions.
static UTF8ArrayToUniArray($ta, $isunicode=true)
Convert an array of UTF8 values to array of unicode characters.
Font methods for TCPDF library.
static fopenLocal($filename, $mode)
Wrapper to use fopen only with local files.
static $uni_laa_array
Arabic laa letter: (char code => isolated, final, initial, medial).
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag