makeSubset() public method

public makeSubset ( $file, &$subset )
Ejemplo n.º 1
0
 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);
             }
         }
     }
 }
Ejemplo n.º 2
0
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.')'); }
	}
}
Ejemplo n.º 3
0
 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);
             }
         }
     }
 }
Ejemplo n.º 4
0
 /**
  * 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);
 }