function _putfonts() { $nf = $this->n; foreach ($this->diffs as $diff) { //Encodings $this->_newobj(); $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>'); $this->_out('endobj'); } foreach ($this->FontFiles as $file => $info) { if (!isset($info['type']) || $info['type'] != 'TrueTypesubset') { //Font file embedding $this->_newobj(); $this->FontFiles[$file]['n'] = $this->n; $font = ''; $f = fopen($this->_getfontpath() . $file, 'rb', 1); if (!$f) { $this->Error('Font file not found'); } while (!feof($f)) { $font .= fread($f, 8192); } fclose($f); $compressed = substr($file, -2) == '.z'; if (!$compressed && isset($info['length2'])) { $header = ord($font[0]) == 128; if ($header) { //Strip first binary header $font = substr($font, 6); } if ($header && ord($font[$info['length1']]) == 128) { //Strip second binary header $font = substr($font, 0, $info['length1']) . substr($font, $info['length1'] + 6); } } $this->_out('<</Length ' . strlen($font)); if ($compressed) { $this->_out('/Filter /FlateDecode'); } $this->_out('/Length1 ' . $info['length1']); if (isset($info['length2'])) { $this->_out('/Length2 ' . $info['length2'] . ' /Length3 0'); } $this->_out('>>'); $this->_putstream($font); $this->_out('endobj'); } } foreach ($this->fonts as $k => $font) { //Font objects //$this->fonts[$k]['n']=$this->n+1; $type = $font['type']; $name = $font['name']; if ($type == 'core') { //Standard font $this->fonts[$k]['n'] = $this->n + 1; $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $name); $this->_out('/Subtype /Type1'); if ($name != 'Symbol' && $name != 'ZapfDingbats') { $this->_out('/Encoding /WinAnsiEncoding'); } $this->_out('>>'); $this->_out('endobj'); } elseif ($type == 'Type1' || $type == 'TrueType') { //Additional Type1 or TrueType font $this->fonts[$k]['n'] = $this->n + 1; $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $name); $this->_out('/Subtype /' . $type); $this->_out('/FirstChar 32 /LastChar 255'); $this->_out('/Widths ' . ($this->n + 1) . ' 0 R'); $this->_out('/FontDescriptor ' . ($this->n + 2) . ' 0 R'); if ($font['enc']) { if (isset($font['diff'])) { $this->_out('/Encoding ' . ($nf + $font['diff']) . ' 0 R'); } else { $this->_out('/Encoding /WinAnsiEncoding'); } } $this->_out('>>'); $this->_out('endobj'); //Widths $this->_newobj(); $cw =& $font['cw']; $s = '['; for ($i = 32; $i <= 255; $i++) { $s .= $cw[chr($i)] . ' '; } $this->_out($s . ']'); $this->_out('endobj'); //Descriptor $this->_newobj(); $s = '<</Type /FontDescriptor /FontName /' . $name; foreach ($font['desc'] as $k => $v) { $s .= ' /' . $k . ' ' . $v; } $file = $font['file']; if ($file) { $s .= ' /FontFile' . ($type == 'Type1' ? '' : '2') . ' ' . $this->FontFiles[$file]['n'] . ' 0 R'; } $this->_out($s . '>>'); $this->_out('endobj'); } else { if ($type == 'TrueTypesubset') { $ssfaid = "A"; include_once $this->_getfontpath() . 'unifont/ttfonts.php'; $ttf = new TTFontFile(); $ttf->getMetrics($font['file'], 1); for ($sfid = 0; $sfid < count($font['subsetfontids']); $sfid++) { $this->fonts[$k]['n'][$sfid] = $this->n + 1; // NB an array for subset $subsetname = 'MPDFA' . $ssfaid . '+' . $font['name']; $ssfaid++; $subset = $font['subsets'][$sfid]; unset($subset[0]); $ttfontstream = $ttf->makeSubset($subset); $ttfontsize = strlen($ttfontstream); $fontstream = gzcompress($ttfontstream); $widthstring = ''; $toUnistring = ''; foreach ($font['subsets'][$sfid] as $cp => $u) { if (isset($font['cw'][$u])) { $widthstring .= $font['cw'][$u] . ' '; } else { $widthstring .= $ttf->defaultWidth . ' '; } $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u))); } //Additional Type1 or TrueType font $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $subsetname); $this->_out('/Subtype /TrueType'); $this->_out('/FirstChar 0 /LastChar ' . count($font['subsets'][$sfid])); $this->_out('/Widths ' . ($this->n + 1) . ' 0 R'); $this->_out('/FontDescriptor ' . ($this->n + 2) . ' 0 R'); $this->_out('/ToUnicode ' . ($this->n + 3) . ' 0 R'); $this->_out('>>'); $this->_out('endobj'); //Widths $this->_newobj(); $this->_out('[' . $widthstring . ']'); $this->_out('endobj'); //Descriptor $this->_newobj(); $s = '<</Type /FontDescriptor /FontName /' . $subsetname . "\n"; foreach ($font['desc'] as $kd => $v) { if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } $s .= ' /' . $kd . ' ' . $v . "\n"; } $s .= '/FontFile2 ' . ($this->n + 2) . ' 0 R'; $this->_out($s . '>>'); $this->_out('endobj'); // ToUnicode $toUni = "stream\n"; $toUni .= "/CIDInit /ProcSet findresource begin\n"; $toUni .= "12 dict begin\n"; $toUni .= "begincmap\n"; $toUni .= "/CIDSystemInfo\n"; $toUni .= "<</Registry (Adobe)\n"; $toUni .= "/Ordering (UCS)\n"; $toUni .= "/Supplement 0\n"; $toUni .= ">> def\n"; $toUni .= "/CMapName /Adobe-Identity-UCS def\n"; $toUni .= "/CMapType 2 def\n"; $toUni .= "1 begincodespacerange\n"; $toUni .= "<00> <FF>\n"; $toUni .= "endcodespacerange\n"; $toUni .= count($font['subsets'][$sfid]) . " beginbfchar\n"; $toUni .= $toUnistring; $toUni .= "endbfchar\n"; $toUni .= "endcmap\n"; $toUni .= "CMapName currentdict /CMap defineresource pop\n"; $toUni .= "end\n"; $toUni .= "end\n"; $toUni .= "endstream\n"; $toUni .= "endobj"; $this->_newobj(); $this->_out('<</Length ' . (strlen($toUni) - 24) . '>>'); $this->_out($toUni); //Font file $this->_newobj(); $this->_out('<</Length ' . strlen($fontstream)); $this->_out('/Filter /FlateDecode'); $this->_out('/Length1 ' . $ttfontsize); $this->_out('>>'); $this->_putstream($fontstream); $this->_out('endobj'); } unset($ttf); } else { //Allow for additional types $this->fonts[$k]['n'] = $this->n + 1; $mtd = '_put' . strtolower($type); if (!method_exists($this, $mtd)) { $this->Error('Unsupported font type: ' . $type); } $this->{$mtd}($font); } } } }
function _putfonts() { $nf = $this->n; foreach ($this->diffs as $diff) { // Encodings $this->_newobj(); $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>'); $this->_out('endobj'); } foreach ($this->FontFiles as $file => $info) { if (!isset($info['type']) || $info['type'] != 'TTF') { // Font file embedding $this->_newobj(); $this->FontFiles[$file]['n'] = $this->n; $font = ''; $f = fopen($this->_getfontpath() . $file, 'rb', 1); if (!$f) { $this->Error('Font file not found'); } while (!feof($f)) { $font .= fread($f, 8192); } fclose($f); $compressed = substr($file, -2) == '.z'; if (!$compressed && isset($info['length2'])) { $header = ord($font[0]) == 128; if ($header) { // Strip first binary header $font = substr($font, 6); } if ($header && ord($font[$info['length1']]) == 128) { // Strip second binary header $font = substr($font, 0, $info['length1']) . substr($font, $info['length1'] + 6); } } $this->_out('<</Length ' . strlen($font)); if ($compressed) { $this->_out('/Filter /FlateDecode'); } $this->_out('/Length1 ' . $info['length1']); if (isset($info['length2'])) { $this->_out('/Length2 ' . $info['length2'] . ' /Length3 0'); } $this->_out('>>'); $this->_putstream($font); $this->_out('endobj'); } } foreach ($this->fonts as $k => $font) { // Font objects //$this->fonts[$k]['n']=$this->n+1; $type = $font['type']; $name = $font['name']; if ($type == 'Core') { // Standard font $this->fonts[$k]['n'] = $this->n + 1; $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $name); $this->_out('/Subtype /Type1'); if ($name != 'Symbol' && $name != 'ZapfDingbats') { $this->_out('/Encoding /WinAnsiEncoding'); } $this->_out('>>'); $this->_out('endobj'); } elseif ($type == 'Type1' || $type == 'TrueType') { // Additional Type1 or TrueType font $this->fonts[$k]['n'] = $this->n + 1; $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /' . $name); $this->_out('/Subtype /' . $type); $this->_out('/FirstChar 32 /LastChar 255'); $this->_out('/Widths ' . ($this->n + 1) . ' 0 R'); $this->_out('/FontDescriptor ' . ($this->n + 2) . ' 0 R'); if ($font['enc']) { if (isset($font['diff'])) { $this->_out('/Encoding ' . ($nf + $font['diff']) . ' 0 R'); } else { $this->_out('/Encoding /WinAnsiEncoding'); } } $this->_out('>>'); $this->_out('endobj'); // Widths $this->_newobj(); $cw =& $font['cw']; $s = '['; for ($i = 32; $i <= 255; $i++) { $s .= $cw[chr($i)] . ' '; } $this->_out($s . ']'); $this->_out('endobj'); // Descriptor $this->_newobj(); $s = '<</Type /FontDescriptor /FontName /' . $name; foreach ($font['desc'] as $k => $v) { $s .= ' /' . $k . ' ' . $v; } $file = $font['file']; if ($file) { $s .= ' /FontFile' . ($type == 'Type1' ? '' : '2') . ' ' . $this->FontFiles[$file]['n'] . ' 0 R'; } $this->_out($s . '>>'); $this->_out('endobj'); } else { if ($type == 'TTF') { $this->fonts[$k]['n'] = $this->n + 1; require_once $this->_getfontpath() . 'unifont/ttfonts.php'; $ttf = new TTFontFile(); $fontname = 'MPDFAA' . '+' . $font['name']; $subset = $font['subset']; unset($subset[0]); $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset); $ttfontsize = strlen($ttfontstream); $fontstream = gzcompress($ttfontstream); $codeToGlyph = $ttf->codeToGlyph; unset($codeToGlyph[0]); // Type0 Font // A composite font - a font composed of other fonts, organized hierarchically $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/Subtype /Type0'); $this->_out('/BaseFont /' . $fontname . ''); $this->_out('/Encoding /Identity-H'); $this->_out('/DescendantFonts [' . ($this->n + 1) . ' 0 R]'); $this->_out('/ToUnicode ' . ($this->n + 2) . ' 0 R'); $this->_out('>>'); $this->_out('endobj'); // CIDFontType2 // A CIDFont whose glyph descriptions are based on TrueType font technology $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/Subtype /CIDFontType2'); $this->_out('/BaseFont /' . $fontname . ''); $this->_out('/CIDSystemInfo ' . ($this->n + 2) . ' 0 R'); $this->_out('/FontDescriptor ' . ($this->n + 3) . ' 0 R'); if (isset($font['desc']['MissingWidth'])) { $this->_out('/DW ' . $font['desc']['MissingWidth'] . ''); } $this->_putTTfontwidths($font, $ttf->maxUni); $this->_out('/CIDToGIDMap ' . ($this->n + 4) . ' 0 R'); $this->_out('>>'); $this->_out('endobj'); // ToUnicode $this->_newobj(); $toUni = "/CIDInit /ProcSet findresource begin\n"; $toUni .= "12 dict begin\n"; $toUni .= "begincmap\n"; $toUni .= "/CIDSystemInfo\n"; $toUni .= "<</Registry (Adobe)\n"; $toUni .= "/Ordering (UCS)\n"; $toUni .= "/Supplement 0\n"; $toUni .= ">> def\n"; $toUni .= "/CMapName /Adobe-Identity-UCS def\n"; $toUni .= "/CMapType 2 def\n"; $toUni .= "1 begincodespacerange\n"; $toUni .= "<0000> <FFFF>\n"; $toUni .= "endcodespacerange\n"; $toUni .= "1 beginbfrange\n"; $toUni .= "<0000> <FFFF> <0000>\n"; $toUni .= "endbfrange\n"; $toUni .= "endcmap\n"; $toUni .= "CMapName currentdict /CMap defineresource pop\n"; $toUni .= "end\n"; $toUni .= "end"; $this->_out('<</Length ' . strlen($toUni) . '>>'); $this->_putstream($toUni); $this->_out('endobj'); // CIDSystemInfo dictionary $this->_newobj(); $this->_out('<</Registry (Adobe)'); $this->_out('/Ordering (UCS)'); $this->_out('/Supplement 0'); $this->_out('>>'); $this->_out('endobj'); // Font descriptor $this->_newobj(); $this->_out('<</Type /FontDescriptor'); $this->_out('/FontName /' . $fontname); foreach ($font['desc'] as $kd => $v) { if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag $this->_out(' /' . $kd . ' ' . $v); } $this->_out('/FontFile2 ' . ($this->n + 2) . ' 0 R'); $this->_out('>>'); $this->_out('endobj'); // Embed CIDToGIDMap // A specification of the mapping from CIDs to glyph indices $cidtogidmap = ''; $cidtogidmap = str_pad('', 256 * 256 * 2, ""); foreach ($codeToGlyph as $cc => $glyph) { $cidtogidmap[$cc * 2] = chr($glyph >> 8); $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xff); } $cidtogidmap = gzcompress($cidtogidmap); $this->_newobj(); $this->_out('<</Length ' . strlen($cidtogidmap) . ''); $this->_out('/Filter /FlateDecode'); $this->_out('>>'); $this->_putstream($cidtogidmap); $this->_out('endobj'); //Font file $this->_newobj(); $this->_out('<</Length ' . strlen($fontstream)); $this->_out('/Filter /FlateDecode'); $this->_out('/Length1 ' . $ttfontsize); $this->_out('>>'); $this->_putstream($fontstream); $this->_out('endobj'); unset($ttf); } else { // Allow for additional types $this->fonts[$k]['n'] = $this->n + 1; $mtd = '_put' . strtolower($type); if (!method_exists($this, $mtd)) { $this->Error('Unsupported font type: ' . $type); } $this->{$mtd}($font); } } } }
} } } } // loads array $unicode_ranges include 'UnicodeRanges.php'; //============================================================== $html = '<html><head><style>td { border: 0.1mm solid #555555; } body { font-weight: normal; font-family: helvetica;font-size:8pt; } td { font-family: helvetica;font-size:8pt; vertical-align: top;} </style></head><body>'; //============================================================== $ff = scandir($ttfdir); $tempfontdata = array(); foreach ($ff as $f) { $ttf = new TTFontFile(); $ret = array(); $isTTC = false; if (strtolower(substr($f, -4, 4)) == '.ttf' || strtolower(substr($f, -4, 4)) == '.otf') { $ret[] = $ttf->extractCoreInfo($ttfdir . $f); } for ($i = 0; $i < count($ret); $i++) { if (is_array($ret[$i])) { $tfname = $ret[$i][0]; $bold = $ret[$i][1]; $italic = $ret[$i][2]; $fname = strtolower($tfname); $fname = preg_replace('/[ ()]/', '', $fname); //$tempfonttrans[$tfname] = $fname; $style = ''; if ($bold) {
include "../mpdf.php"; $mpdf = new mPDF('s'); $mpdf->useSubstitutions = true; if ($checkdir) { $ttfdir = $checkdir; } else { $ttfdir = _MPDF_TTFONTPATH; } $mqr = ini_get("magic_quotes_runtime"); if ($mqr) { set_magic_quotes_runtime(0); } if (!class_exists('TTFontFile', false)) { include _MPDF_PATH . 'classes/ttfontsuni.php'; } $ttf = new TTFontFile(); $tempfontdata = array(); $tempsansfonts = array(); $tempseriffonts = array(); $tempmonofonts = array(); $tempfonttrans = array(); $ff = scandir($ttfdir); foreach ($ff as $f) { $ret = array(); $isTTC = false; if (strtolower(substr($f, -4, 4)) == '.ttc' || strtolower(substr($f, -5, 5)) == '.ttcf') { // Mac ttcf $isTTC = true; $ttf->getTTCFonts($ttfdir . $f); $nf = $ttf->numTTCFonts; for ($i = 1; $i <= $nf; $i++) {
function _putfonts() { $nf=$this->n; foreach($this->FontFiles as $fontkey=>$info) { // TrueType embedded if (isset($info['type']) && $info['type']=='TTF' && !$info['sip'] && !$info['smp']) { $used = true; $asSubset = false; foreach($this->fonts AS $k=>$f) { if ($f['fontkey'] == $fontkey && $f['type']=='TTF') { $used = $f['used']; if ($used) { $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]); $usage = intval(count($f['subset'])*100 / $nChars); $fsize = $info['length1']; // Always subset the very large TTF files if ($fsize > ($this->maxTTFFilesize *1024)) { $asSubset = true; } else if ($usage < $this->percentSubset) { $asSubset = true; } } if ($f['unAGlyphs']) $aaSubset = true; // mPDF 5.4.05 if ($this->PDFA || $this->PDFX) $asSubset = false; $this->fonts[$k]['asSubset'] = $asSubset; break; } } if ($used && !$asSubset) { //Font file embedding $this->_newobj(); $this->FontFiles[$fontkey]['n']=$this->n; $font=''; $originalsize = $info['length1']; if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID']>0) { // First see if there is a cached compressed file if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z')) { $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z','rb'); if(!$f) { $this->Error('Font file .ps.z not found'); } while(!feof($f)) { $font .= fread($f, 2048); } fclose($f); include(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php'); // sets $originalsize (of repackaged font) } else { if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); } $ttf = new TTFontFile(); $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['unAGlyphs']); // mPDF 5.4.05 $originalsize = strlen($font); $font = gzcompress($font); unset($ttf); if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) { $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z',"wb"); fwrite($fh,$font,strlen($font)); fclose($fh); $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php',"wb"); $len = "<?php \n"; $len.='$originalsize='.$originalsize.";\n"; $len.="?>"; fwrite($fh,$len,strlen($len)); fclose($fh); } } } else { // First see if there is a cached compressed file if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) { $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z','rb'); if(!$f) { $this->Error('Font file not found'); } while(!feof($f)) { $font .= fread($f, 2048); } fclose($f); } else { $f=fopen($this->FontFiles[$fontkey]['ttffile'],'rb'); if(!$f) { $this->Error('Font file not found'); } while(!feof($f)) { $font .= fread($f, 2048); } fclose($f); $font = gzcompress($font); if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) { $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z',"wb"); fwrite($fh,$font,strlen($font)); fclose($fh); } } } $this->_out('<</Length '.strlen($font)); $this->_out('/Filter /FlateDecode'); $this->_out('/Length1 '.$originalsize); $this->_out('>>'); $this->_putstream($font); $this->_out('endobj'); } } } $nfonts = count($this->fonts); $fctr = 1; foreach($this->fonts as $k=>$font) { //Font objects $type=$font['type']; $name=$font['name']; if ((!isset($font['used']) || !$font['used']) && $type=='TTF') { continue; } if ($this->progressBar) { $this->UpdateProgressBar(2,intval($fctr*100/$nfonts),'Writing Fonts'); $fctr++; } // *PROGRESS-BAR* if (isset($font['asSubset'])) { $asSubset = $font['asSubset']; } else { $asSubset = ''; } /*-- CJK-FONTS --*/ if($type=='Type0') { // = Adobe CJK Fonts $this->fonts[$k]['n']=$this->n+1; $this->_newobj(); $this->_out('<</Type /Font'); $this->_putType0($font); } else /*-- END CJK-FONTS --*/ if($type=='core') { //Standard font $this->fonts[$k]['n']=$this->n+1; if ($this->PDFA || $this->PDFX) { $this->Error('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)'); } $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /'.$name); $this->_out('/Subtype /Type1'); if($name!='Symbol' && $name!='ZapfDingbats') { $this->_out('/Encoding /WinAnsiEncoding'); } $this->_out('>>'); $this->_out('endobj'); } // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2) // Or Unicode Plane 1 - Supplementary Multilingual Plane else if ($type=='TTF' && ($font['sip'] || $font['smp'])) { if (!$font['used']) { continue; } $ssfaid="AA"; if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); } $ttf = new TTFontFile(); for($sfid=0;$sfid<count($font['subsetfontids']);$sfid++) { $this->fonts[$k]['n'][$sfid]=$this->n+1; // NB an array for subset $subsetname = 'MPDF'.$ssfaid.'+'.$font['name']; $ssfaid++; $subset = $font['subsets'][$sfid]; unset($subset[0]); $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts); $ttfontsize = strlen($ttfontstream); $fontstream = gzcompress($ttfontstream); $widthstring = ''; $toUnistring = ''; foreach($font['subsets'][$sfid] AS $cp=>$u) { $w = $this->_getCharWidth($font['cw'], $u); if ($w !== false) { $widthstring .= $w.' '; } else { $widthstring .= round($ttf->defaultWidth).' '; } if ($u > 65535) { $utf8 = chr(($u>>18)+240).chr((($u>>12)&63)+128).chr((($u>>6)&63)+128) .chr(($u&63)+128); $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8'); $l1 = ord($utf16[0]); $h1 = ord($utf16[1]); $l2 = ord($utf16[2]); $h2 = ord($utf16[3]); $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2))); } else { $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u))); } } //Additional Type1 or TrueType font $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/BaseFont /'.$subsetname); $this->_out('/Subtype /TrueType'); $this->_out('/FirstChar 0 /LastChar '.(count($font['subsets'][$sfid])-1)); $this->_out('/Widths '.($this->n+1).' 0 R'); $this->_out('/FontDescriptor '.($this->n+2).' 0 R'); $this->_out('/ToUnicode '.($this->n + 3).' 0 R'); $this->_out('>>'); $this->_out('endobj'); //Widths $this->_newobj(); $this->_out('['.$widthstring.']'); $this->_out('endobj'); //Descriptor $this->_newobj(); $s='<</Type /FontDescriptor /FontName /'.$subsetname."\n"; foreach($font['desc'] as $kd=>$v) { if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag $s.=' /'.$kd.' '.$v."\n"; } $s.='/FontFile2 '.($this->n + 2).' 0 R'; $this->_out($s.'>>'); $this->_out('endobj'); // ToUnicode $this->_newobj(); $toUni = "/CIDInit /ProcSet findresource begin\n"; $toUni .= "12 dict begin\n"; $toUni .= "begincmap\n"; $toUni .= "/CIDSystemInfo\n"; $toUni .= "<</Registry (Adobe)\n"; $toUni .= "/Ordering (UCS)\n"; $toUni .= "/Supplement 0\n"; $toUni .= ">> def\n"; $toUni .= "/CMapName /Adobe-Identity-UCS def\n"; $toUni .= "/CMapType 2 def\n"; $toUni .= "1 begincodespacerange\n"; $toUni .= "<00> <FF>\n"; $toUni .= "endcodespacerange\n"; $toUni .= count($font['subsets'][$sfid])." beginbfchar\n"; $toUni .= $toUnistring; $toUni .= "endbfchar\n"; $toUni .= "endcmap\n"; $toUni .= "CMapName currentdict /CMap defineresource pop\n"; $toUni .= "end\n"; $toUni .= "end\n"; $this->_out('<</Length '.(strlen($toUni)).'>>'); $this->_putstream($toUni); $this->_out('endobj'); //Font file $this->_newobj(); $this->_out('<</Length '.strlen($fontstream)); $this->_out('/Filter /FlateDecode'); $this->_out('/Length1 '.$ttfontsize); $this->_out('>>'); $this->_putstream($fontstream); $this->_out('endobj'); } // foreach subset unset($ttf); } // TrueType embedded SUBSETS or FULL else if ($type=='TTF') { $this->fonts[$k]['n']=$this->n+1; if ($asSubset ) { $ssfaid="A"; if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); } $ttf = new TTFontFile(); $fontname = 'MPDFA'.$ssfaid.'+'.$font['name']; $subset = $font['subset']; unset($subset[0]); $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05 $ttfontsize = strlen($ttfontstream); $fontstream = gzcompress($ttfontstream); $codeToGlyph = $ttf->codeToGlyph; unset($codeToGlyph[0]); } else { $fontname = $font['name']; } // Type0 Font // A composite font - a font composed of other fonts, organized hierarchically $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/Subtype /Type0'); $this->_out('/BaseFont /'.$fontname.''); $this->_out('/Encoding /Identity-H'); $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]'); $this->_out('/ToUnicode '.($this->n + 2).' 0 R'); $this->_out('>>'); $this->_out('endobj'); // CIDFontType2 // A CIDFont whose glyph descriptions are based on TrueType font technology $this->_newobj(); $this->_out('<</Type /Font'); $this->_out('/Subtype /CIDFontType2'); $this->_out('/BaseFont /'.$fontname.''); $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R'); $this->_out('/FontDescriptor '.($this->n + 3).' 0 R'); if (isset($font['desc']['MissingWidth'])){ $this->_out('/DW '.$font['desc']['MissingWidth'].''); } if (!$asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw')) { $w = ''; $w=file_get_contents(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw'); $this->_out($w); } else { $this->_putTTfontwidths($font, $asSubset, $ttf->maxUni); } $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R'); $this->_out('>>'); $this->_out('endobj'); // ToUnicode $this->_newobj(); $toUni = "/CIDInit /ProcSet findresource begin\n"; $toUni .= "12 dict begin\n"; $toUni .= "begincmap\n"; $toUni .= "/CIDSystemInfo\n"; $toUni .= "<</Registry (Adobe)\n"; $toUni .= "/Ordering (UCS)\n"; $toUni .= "/Supplement 0\n"; $toUni .= ">> def\n"; $toUni .= "/CMapName /Adobe-Identity-UCS def\n"; $toUni .= "/CMapType 2 def\n"; $toUni .= "1 begincodespacerange\n"; $toUni .= "<0000> <FFFF>\n"; $toUni .= "endcodespacerange\n"; $toUni .= "1 beginbfrange\n"; $toUni .= "<0000> <FFFF> <0000>\n"; $toUni .= "endbfrange\n"; $toUni .= "endcmap\n"; $toUni .= "CMapName currentdict /CMap defineresource pop\n"; $toUni .= "end\n"; $toUni .= "end\n"; $this->_out('<</Length '.(strlen($toUni)).'>>'); $this->_putstream($toUni); $this->_out('endobj'); // CIDSystemInfo dictionary $this->_newobj(); $this->_out('<</Registry (Adobe)'); $this->_out('/Ordering (UCS)'); $this->_out('/Supplement 0'); $this->_out('>>'); $this->_out('endobj'); // Font descriptor $this->_newobj(); $this->_out('<</Type /FontDescriptor'); $this->_out('/FontName /'.$fontname); foreach($font['desc'] as $kd=>$v) { if ($asSubset && $kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag $this->_out(' /'.$kd.' '.$v); } if ($font['panose']) { $this->_out(' /Style << /Panose <'.$font['panose'].'> >>'); } if ($asSubset ) { $this->_out('/FontFile2 '.($this->n + 2).' 0 R'); } else if ($font['fontkey']) { // obj ID of a stream containing a TrueType font program $this->_out('/FontFile2 '.$this->FontFiles[$font['fontkey']]['n'].' 0 R'); } $this->_out('>>'); $this->_out('endobj'); // Embed CIDToGIDMap // A specification of the mapping from CIDs to glyph indices if ($asSubset ) { $cidtogidmap = ''; $cidtogidmap = str_pad('', 256*256*2, "\x00"); foreach($codeToGlyph as $cc=>$glyph) { $cidtogidmap[$cc*2] = chr($glyph >> 8); $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF); } $cidtogidmap = gzcompress($cidtogidmap); } else { // First see if there is a cached CIDToGIDMapfile $cidtogidmap = ''; if (file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm')) { $f=fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm','rb'); while(!feof($f)) { $cidtogidmap .= fread($f, 2048); } fclose($f); } else { if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); } $ttf = new TTFontFile(); $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05 $cidtogidmap = str_pad('', 256*256*2, "\x00"); foreach($charToGlyph as $cc=>$glyph) { $cidtogidmap[$cc*2] = chr($glyph >> 8); $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF); } unset($ttf); $cidtogidmap = gzcompress($cidtogidmap); if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) { $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm',"wb"); fwrite($fh,$cidtogidmap,strlen($cidtogidmap)); fclose($fh); } } } $this->_newobj(); $this->_out('<</Length '.strlen($cidtogidmap).''); $this->_out('/Filter /FlateDecode'); $this->_out('>>'); $this->_putstream($cidtogidmap); $this->_out('endobj'); //Font file if ($asSubset ) { $this->_newobj(); $this->_out('<</Length '.strlen($fontstream)); $this->_out('/Filter /FlateDecode'); $this->_out('/Length1 '.$ttfontsize); $this->_out('>>'); $this->_putstream($fontstream); $this->_out('endobj'); unset($ttf); } } else { $this->Error('Unsupported font type: '.$type.' ('.$name.')'); } } }
/** * Add a TrueType, OpenType or Type1 font * * @param $family * @param string $style * @param string $file * @param bool $uni */ public function addFont($family, $style = '', $file = '', $uni = false) { $family = strtolower($family); $style = strtoupper($style); $fontPath = $this->_pdfOutput->getDocument()->getFontPath(); if ($style == 'IB') { $style = 'BI'; } if ($file == '') { if ($uni) { $file = str_replace(' ', '', $family) . strtolower($style) . '.ttf'; } else { $file = str_replace(' ', '', $family) . strtolower($style) . '.php'; } } $fontkey = $family . $style; if (isset($this->fonts[$fontkey])) { return; } if ($uni) { if (defined("_SYSTEM_TTFONTS") && file_exists(_SYSTEM_TTFONTS . $file)) { $ttffilename = _SYSTEM_TTFONTS . $file; } else { $ttffilename = $fontPath . 'Unifonts/' . $file; } $unifilename = $fontPath . 'Unifonts/' . strtolower(substr($file, 0, strpos($file, '.'))); $name = ''; $originalsize = 0; $ttfstat = @stat($ttffilename); if (file_exists($unifilename . '.mtx.php')) { include $unifilename . '.mtx.php'; } if (!isset($type) || !isset($name) || $originalsize != $ttfstat['size']) { $ttffile = $ttffilename; require_once $fontPath . 'Unifonts/ttfonts.php'; $ttf = new \TTFontFile(); $ttf->getMetrics($ttffile); $cw = $ttf->charWidths; $name = preg_replace('/[ ()]/', '', $ttf->fullName); $desc = array('Ascent' => round($ttf->ascent), 'Descent' => round($ttf->descent), 'CapHeight' => round($ttf->capHeight), 'Flags' => $ttf->flags, 'FontBBox' => '[' . round($ttf->bbox[0]) . " " . round($ttf->bbox[1]) . " " . round($ttf->bbox[2]) . " " . round($ttf->bbox[3]) . ']', 'ItalicAngle' => $ttf->italicAngle, 'StemV' => round($ttf->stemV), 'MissingWidth' => round($ttf->defaultWidth)); $up = round($ttf->underlinePosition); $ut = round($ttf->underlineThickness); $originalsize = $ttfstat['size'] + 0; $type = 'TTF'; // Generate metrics .php file $s = '<?php' . "\n"; $s .= '$name = \'' . $name . "';\n"; $s .= '$type = \'' . $type . "';\n"; $s .= '$desc = ' . var_export($desc, true) . ";\n"; $s .= '$up = ' . $up . ";\n"; $s .= '$ut = ' . $ut . ";\n"; $s .= '$ttffile = \'' . $ttffile . "';\n"; $s .= '$originalsize = ' . $originalsize . ";\n"; $s .= '$fontkey = \'' . $fontkey . "';\n"; if (is_writable(dirname($this->_pdfOutput->getDocument()->getFontPath() . 'Unifonts/' . 'x'))) { $fh = fopen($unifilename . '.mtx.php', "w"); fwrite($fh, $s, strlen($s)); fclose($fh); $fh = fopen($unifilename . '.cw.dat', "wb"); fwrite($fh, $cw, strlen($cw)); fclose($fh); @unlink($unifilename . '.cw127.php'); } unset($ttf); } else { $cw = @file_get_contents($unifilename . '.cw.dat'); } $i = count($this->fonts) + 1; $aliasNbPages = $this->_pdfOutput->getDocument()->getAliasNbPages(); if (!empty($aliasNbPages)) { $sbarr = range(0, 57); } else { $sbarr = range(0, 32); } $this->fonts[$fontkey] = array('i' => $i, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'ttffile' => $ttffile, 'fontkey' => $fontkey, 'subset' => $sbarr, 'unifilename' => $unifilename); $this->_fontFiles[$fontkey] = array('length1' => $originalsize, 'type' => "TTF", 'ttffile' => $ttffile); $this->_fontFiles[$file] = array('type' => "TTF"); unset($cw); } else { $info = $this->_loadfont($file); $info['i'] = count($this->fonts) + 1; if (!empty($info['diff'])) { $n = array_search($info['diff'], $this->_diffs); if (!$n) { $n = count($this->_diffs) + 1; $this->_diffs[$n] = $info['diff']; } $info['diffn'] = $n; } if (!empty($info['file'])) { if ($info['type'] == 'TrueType') { $this->_fontFiles[$info['file']] = array('length1' => $info['originalsize']); } else { $this->_fontFiles[$info['file']] = array('length1' => $info['size1'], 'length2' => $info['size2']); } } $this->fonts[$fontkey] = $info; } }