/** * Output fonts. * @author Nicola Asuni * @protected */ protected function _putfonts() { $nf = $this->n; foreach ($this->diffs as $diff) { //Encodings $this->_newobj(); $this->_out('<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . '] >>' . "\n" . 'endobj'); } $mqr = TCPDF_STATIC::get_mqr(); TCPDF_STATIC::set_mqr(false); foreach ($this->FontFiles as $file => $info) { // search and get font file to embedd $fontfile = TCPDF_FONTS::getFontFullPath($file, $info['fontdir']); if (!TCPDF_STATIC::empty_string($fontfile)) { $font = file_get_contents($fontfile); $compressed = substr($file, -2) == '.z'; if (!$compressed and isset($info['length2'])) { $header = ord($font[0]) == 128; if ($header) { // strip first binary header $font = substr($font, 6); } if ($header and ord($font[$info['length1']]) == 128) { // strip second binary header $font = substr($font, 0, $info['length1']) . substr($font, $info['length1'] + 6); } } elseif ($info['subset'] and (!$compressed or $compressed and function_exists('gzcompress'))) { if ($compressed) { // uncompress font $font = gzuncompress($font); } // merge subset characters $subsetchars = array(); // used chars foreach ($info['fontkeys'] as $fontkey) { $fontinfo = $this->getFontBuffer($fontkey); $subsetchars += $fontinfo['subsetchars']; } // rebuild a font subset $font = TCPDF_FONTS::_getTrueTypeFontSubset($font, $subsetchars); // calculate new font length $info['length1'] = strlen($font); if ($compressed) { // recompress font $font = gzcompress($font); } } $this->_newobj(); $this->FontFiles[$file]['n'] = $this->n; $stream = $this->_getrawstream($font); $out = '<< /Length ' . strlen($stream); if ($compressed) { $out .= ' /Filter /FlateDecode'; } $out .= ' /Length1 ' . $info['length1']; if (isset($info['length2'])) { $out .= ' /Length2 ' . $info['length2'] . ' /Length3 0'; } $out .= ' >>'; $out .= ' stream' . "\n" . $stream . "\n" . 'endstream'; $out .= "\n" . 'endobj'; $this->_out($out); } } TCPDF_STATIC::set_mqr($mqr); foreach ($this->fontkeys as $k) { //Font objects $font = $this->getFontBuffer($k); $type = $font['type']; $name = $font['name']; if ($type == 'core') { // standard core font $out = $this->_getobj($this->font_obj_ids[$k]) . "\n"; $out .= '<</Type /Font'; $out .= ' /Subtype /Type1'; $out .= ' /BaseFont /' . $name; $out .= ' /Name /F' . $font['i']; if (strtolower($name) != 'symbol' and strtolower($name) != 'zapfdingbats') { $out .= ' /Encoding /WinAnsiEncoding'; } if ($k == 'helvetica') { // add default font for annotations $this->annotation_fonts[$k] = $font['i']; } $out .= ' >>'; $out .= "\n" . 'endobj'; $this->_out($out); } elseif ($type == 'Type1' or $type == 'TrueType') { // additional Type1 or TrueType font $out = $this->_getobj($this->font_obj_ids[$k]) . "\n"; $out .= '<</Type /Font'; $out .= ' /Subtype /' . $type; $out .= ' /BaseFont /' . $name; $out .= ' /Name /F' . $font['i']; $out .= ' /FirstChar 32 /LastChar 255'; $out .= ' /Widths ' . ($this->n + 1) . ' 0 R'; $out .= ' /FontDescriptor ' . ($this->n + 2) . ' 0 R'; if ($font['enc']) { if (isset($font['diff'])) { $out .= ' /Encoding ' . ($nf + $font['diff']) . ' 0 R'; } else { $out .= ' /Encoding /WinAnsiEncoding'; } } $out .= ' >>'; $out .= "\n" . 'endobj'; $this->_out($out); // Widths $this->_newobj(); $s = '['; for ($i = 32; $i < 256; ++$i) { if (isset($font['cw'][$i])) { $s .= $font['cw'][$i] . ' '; } else { $s .= $font['dw'] . ' '; } } $s .= ']'; $s .= "\n" . 'endobj'; $this->_out($s); //Descriptor $this->_newobj(); $s = '<</Type /FontDescriptor /FontName /' . $name; foreach ($font['desc'] as $fdk => $fdv) { if (is_float($fdv)) { $fdv = sprintf('%F', $fdv); } $s .= ' /' . $fdk . ' ' . $fdv . ''; } if (!TCPDF_STATIC::empty_string($font['file'])) { $s .= ' /FontFile' . ($type == 'Type1' ? '' : '2') . ' ' . $this->FontFiles[$font['file']]['n'] . ' 0 R'; } $s .= '>>'; $s .= "\n" . 'endobj'; $this->_out($s); } else { // additional types $mtd = '_put' . strtolower($type); if (!method_exists($this, $mtd)) { $this->Error('Unsupported font type: ' . $type); } $this->{$mtd}($font); } } }