/** * Parse PNG stream * * @param $f * @param $file * @return array * @throws PdfException */ protected function _parsePngStream($f, $file) { if ($this->_readStream($f, 8) != chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) { throw new PdfException('Not a PNG file: ' . $file); } $this->_readStream($f, 4); if ($this->_readStream($f, 4) != 'IHDR') { throw new PdfException('Incorrect PNG file: ' . $file); } $w = $this->_readInt($f); $h = $this->_readInt($f); $bpc = ord($this->_readStream($f, 1)); if ($bpc > 8) { throw new PdfException('16-bit depth not supported: ' . $file); } $ct = ord($this->_readStream($f, 1)); if ($ct == 0 || $ct == 4) { $colspace = 'DeviceGray'; } elseif ($ct == 2 || $ct == 6) { $colspace = 'DeviceRGB'; } elseif ($ct == 3) { $colspace = 'Indexed'; } else { throw new PdfException('Unknown color type: ' . $file); } if (ord($this->_readStream($f, 1)) != 0) { throw new PdfException('Unknown compression method: ' . $file); } if (ord($this->_readStream($f, 1)) != 0) { throw new PdfException('Unknown filter method: ' . $file); } if (ord($this->_readStream($f, 1)) != 0) { throw new PdfException('Interlacing not supported: ' . $file); } $this->_readStream($f, 4); $dp = '/Predictor 15 /Colors ' . ($colspace == 'DeviceRGB' ? 3 : 1) . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w; $pal = ''; $trns = ''; $data = ''; do { $n = $this->_readInt($f); $type = $this->_readStream($f, 4); if ($type == 'PLTE') { $pal = $this->_readStream($f, $n); $this->_readStream($f, 4); } elseif ($type == 'tRNS') { $t = $this->_readStream($f, $n); if ($ct == 0) { $trns = array(ord(substr($t, 1, 1))); } elseif ($ct == 2) { $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))); } else { $pos = strpos($t, chr(0)); if ($pos !== false) { $trns = array($pos); } } $this->_readStream($f, 4); } elseif ($type == 'IDAT') { $data .= $this->_readStream($f, $n); $this->_readStream($f, 4); } elseif ($type == 'IEND') { break; } else { $this->_readStream($f, $n + 4); } } while ($n); if ($colspace == 'Indexed' && empty($pal)) { throw new PdfException('Missing palette in ' . $file); } $info = array('w' => $w, 'h' => $h, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'dp' => $dp, 'pal' => $pal, 'trns' => $trns); if ($ct >= 4) { if (!function_exists('gzuncompress')) { throw new PdfException('Zlib not available, can\'t handle alpha channel: ' . $file); } $data = gzuncompress($data); $color = ''; $alpha = ''; if ($ct == 4) { $len = 2 * $w; for ($i = 0; $i < $h; $i++) { $pos = (1 + $len) * $i; $color .= $data[$pos]; $alpha .= $data[$pos]; $line = substr($data, $pos + 1, $len); $color .= preg_replace('/(.)./s', '$1', $line); $alpha .= preg_replace('/.(.)/s', '$1', $line); } } else { $len = 4 * $w; for ($i = 0; $i < $h; $i++) { $pos = (1 + $len) * $i; $color .= $data[$pos]; $alpha .= $data[$pos]; $line = substr($data, $pos + 1, $len); $color .= preg_replace('/(.{3})./s', '$1', $line); $alpha .= preg_replace('/.{3}(.)/s', '$1', $line); } } unset($data); $data = gzcompress($color); $info['smask'] = gzcompress($alpha); if ($this->_pdfOutput->getDocument()->pdfVersion < '1.4') { $this->_pdfOutput->getDocument()->pdfVersion = '1.4'; } } $info['data'] = $data; return $info; }
/** * 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; } }