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->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.')'); } } }
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); } } } }
/** * TrueType embedded SUBSETS or FULL */ protected function _outputTtfFont($k, $font) { $output = $this->_pdfOutput; $this->fonts[$k]['n'] = $output->getPdfObjects() + 1; require_once $this->_pdfOutput->getDocument()->getFontPath() . 'Unifonts/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 $output->newObj(); $output->out('<</Type /Font'); $output->out('/Subtype /Type0'); $output->out('/BaseFont /' . $fontname . ''); $output->out('/Encoding /Identity-H'); $output->out('/DescendantFonts [' . ($output->getPdfObjects() + 1) . ' 0 R]'); $output->out('/ToUnicode ' . ($output->getPdfObjects() + 2) . ' 0 R'); $output->out('>>'); $output->out('endobj'); // CIDFontType2 // A CIDFont whose glyph descriptions are based on TrueType font technology $output->newObj(); $output->out('<</Type /Font'); $output->out('/Subtype /CIDFontType2'); $output->out('/BaseFont /' . $fontname . ''); $output->out('/CIDSystemInfo ' . ($output->getPdfObjects() + 2) . ' 0 R'); $output->out('/FontDescriptor ' . ($output->getPdfObjects() + 3) . ' 0 R'); if (isset($font['desc']['MissingWidth'])) { $output->out('/DW ' . $font['desc']['MissingWidth'] . ''); } $this->_putTTfontwidths($font, $ttf->maxUni); $output->out('/CIDToGIDMap ' . ($output->getPdfObjects() + 4) . ' 0 R'); $output->out('>>'); $output->out('endobj'); // ToUnicode $output->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"; $output->out('<</Length ' . strlen($toUni) . '>>'); $output->putStream($toUni); $output->out('endobj'); // CIDSystemInfo dictionary $output->newObj(); $output->out('<</Registry (Adobe)'); $output->out('/Ordering (UCS)'); $output->out('/Supplement 0'); $output->out('>>'); $output->out('endobj'); // Font descriptor $output->newObj(); $output->out('<</Type /FontDescriptor'); $output->out('/FontName /' . $fontname); foreach ($font['desc'] as $kd => $v) { if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } $output->out(' /' . $kd . ' ' . $v); } $output->out('/FontFile2 ' . ($output->getPdfObjects() + 2) . ' 0 R'); $output->out('>>'); $output->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); $output->newObj(); $output->out('<</Length ' . strlen($cidtogidmap) . ''); $output->out('/Filter /FlateDecode'); $output->out('>>'); $output->putStream($cidtogidmap); $output->out('endobj'); //Font file $output->newObj(); $output->out('<</Length ' . strlen($fontstream)); $output->out('/Filter /FlateDecode'); $output->out('/Length1 ' . $ttfontsize); $output->out('>>'); $output->putStream($fontstream); $output->out('endobj'); unset($ttf); }