| Current Path : /proc/1908984/root/proc/1908984/root/tmp/ |
| Current File : //proc/1908984/root/proc/1908984/root/tmp/php4TzDfF |
<?php
//============================================================+
// File name : tcpdf_fonts.php
// Version : 1.1.0
// Begin : 2008-01-01
// Last Update : 2014-12-10
// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
// -------------------------------------------------------------------
// Copyright (C) 2008-2014 Nicola Asuni - Tecnick.com LTD
//
// This file is part of TCPDF software library.
//
// TCPDF is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// TCPDF is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with TCPDF. If not, see <http://www.gnu.org/licenses/>.
//
// See LICENSE.TXT file for more information.
// -------------------------------------------------------------------
//
// Description :Font methods for TCPDF library.
//
//============================================================+
/**
* @file
* Unicode data and font methods for TCPDF library.
* @author Nicola Asuni
* @package com.tecnick.tcpdf
*/
/**
* @class TCPDF_FONTS
* Font methods for TCPDF library.
* @package com.tecnick.tcpdf
* @version 1.1.0
* @author Nicola Asuni - info@tecnick.com
*/
class TCPDF_FONTS {
/**
* Static cache used for speed up uniord performances
* @protected
*/
protected static $cache_uniord = array();
/**
* Convert and add the selected TrueType or Type1 font to the fonts folder (that must be writeable).
* @param $fontfile (string) Font file (full path).
* @param $fonttype (string) Font type. Leave empty for autodetect mode. Valid values are: TrueTypeUnicode, TrueType, Type1, CID0JP = CID-0 Japanese, CID0KR = CID-0 Korean, CID0CS = CID-0 Chinese Simplified, CID0CT = CID-0 Chinese Traditional.
* @param $enc (string) Name of the encoding table to use. Leave empty for default mode. Omit this parameter for TrueType Unicode and symbolic fonts like Symbol or ZapfDingBats.
* @param $flags (int) Unsigned 32-bit integer containing flags specifying various characteristics of the font (PDF32000:2008 - 9.8.2 Font Descriptor Flags): +1 for fixed font; +4 for symbol or +32 for non-symbol; +64 for italic. Fixed and Italic mode are generally autodetected so you have to set it to 32 = non-symbolic font (default) or 4 = symbolic font.
* @param $outpath (string) Output path for generated font files (must be writeable by the web server). Leave empty for default font folder.
* @param $platid (int) Platform ID for CMAP table to extract (when building a Unicode font for Windows this value should be 3, for Macintosh should be 1).
* @param $encid (int) Encoding ID for CMAP table to extract (when building a Unicode font for Windows this value should be 1, for Macintosh should be 0). When Platform ID is 3, legal values for Encoding ID are: 0=Symbol, 1=Unicode, 2=ShiftJIS, 3=PRC, 4=Big5, 5=Wansung, 6=Johab, 7=Reserved, 8=Reserved, 9=Reserved, 10=UCS-4.
* @param $addcbbox (boolean) If true includes the character bounding box information on the php font file.
* @param $link (boolean) If true link to system font instead of copying the font data (not transportable) - Note: do not work with Type1 fonts.
* @return (string) TCPDF font name or boolean false in case of error.
* @author Nicola Asuni
* @since 5.9.123 (2010-09-30)
* @public static
*/
public static function addTTFfont($fontfile, $fonttype='', $enc='', $flags=32, $outpath='', $platid=3, $encid=1, $addcbbox=false, $link=false) {
if (!TCPDF_STATIC::file_exists($fontfile)) {
// Could not find file
return false;
}
// font metrics
$fmetric = array();
// build new font name for TCPDF compatibility
$font_path_parts = pathinfo($fontfile);
if (!isset($font_path_parts['filename'])) {
$font_path_parts['filename'] = substr($font_path_parts['basename'], 0, -(strlen($font_path_parts['extension']) + 1));
}
$font_name = strtolower($font_path_parts['filename']);
$font_name = preg_replace('/[^a-z0-9_]/', '', $font_name);
$search = array('bold', 'oblique', 'italic', 'regular');
$replace = array('b', 'i', 'i', '');
$font_name = str_replace($search, $replace, $font_name);
if (empty($font_name)) {
// set generic name
$font_name = 'tcpdffont';
}
// set output path
if (empty($outpath)) {
$outpath = self::_getfontpath();
}
// check if this font already exist
if (@TCPDF_STATIC::file_exists($outpath.$font_name.'.php')) {
// this font already exist (delete it from fonts folder to rebuild it)
return $font_name;
}
$fmetric['file'] = $font_name;
$fmetric['ctg'] = $font_name.'.ctg.z';
// get font data
$font = file_get_contents($fontfile);
$fmetric['originalsize'] = strlen($font);
// autodetect font type
if (empty($fonttype)) {
if (TCPDF_STATIC::_getULONG($font, 0) == 0x10000) {
// True Type (Unicode or not)
$fonttype = 'TrueTypeUnicode';
} elseif (substr($font, 0, 4) == 'OTTO') {
// Open Type (Unicode or not)
//Unsupported font format: OpenType with CFF data
return false;
} else {
// Type 1
$fonttype = 'Type1';
}
}
// set font type
switch ($fonttype) {
case 'CID0CT':
case 'CID0CS':
case 'CID0KR':
case 'CID0JP': {
$fmetric['type'] = 'cidfont0';
break;
}
case 'Type1': {
$fmetric['type'] = 'Type1';
if (empty($enc) AND (($flags & 4) == 0)) {
$enc = 'cp1252';
}
break;
}
case 'TrueType': {
$fmetric['type'] = 'TrueType';
break;
}
case 'TrueTypeUnicode':
default: {
$fmetric['type'] = 'TrueTypeUnicode';
break;
}
}
// set encoding maps (if any)
$fmetric['enc'] = preg_replace('/[^A-Za-z0-9_\-]/', '', $enc);
$fmetric['diff'] = '';
if (($fmetric['type'] == 'TrueType') OR ($fmetric['type'] == 'Type1')) {
if (!empty($enc) AND ($enc != 'cp1252') AND isset(TCPDF_FONT_DATA::$encmap[$enc])) {
// build differences from reference encoding
$enc_ref = TCPDF_FONT_DATA::$encmap['cp1252'];
$enc_target = TCPDF_FONT_DATA::$encmap[$enc];
$last = 0;
for ($i = 32; $i <= 255; ++$i) {
if ($enc_target[$i] != $enc_ref[$i]) {
if ($i != ($last + 1)) {
$fmetric['diff'] .= $i.' ';
}
$last = $i;
$fmetric['diff'] .= '/'.$enc_target[$i].' ';
}
}
}
}
// parse the font by type
if ($fmetric['type'] == 'Type1') {
// ---------- TYPE 1 ----------
// read first segment
$a = unpack('Cmarker/Ctype/Vsize', substr($font, 0, 6));
if ($a['marker'] != 128) {
// Font file is not a valid binary Type1
return false;
}
$fmetric['size1'] = $a['size'];
$data = substr($font, 6, $fmetric['size1']);
// read second segment
$a = unpack('Cmarker/Ctype/Vsize', substr($font, (6 + $fmetric['size1']), 6));
if ($a['marker'] != 128) {
// Font file is not a valid binary Type1
return false;
}
$fmetric['size2'] = $a['size'];
$encrypted = substr($font, (12 + $fmetric['size1']), $fmetric['size2']);
$data .= $encrypted;
// store compressed font
$fmetric['file'] .= '.z';
$fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['file'], 'wb');
fwrite($fp, gzcompress($data));
fclose($fp);
// get font info
$fmetric['Flags'] = $flags;
preg_match ('#/FullName[\s]*\(([^\)]*)#', $font, $matches);
$fmetric['name'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $matches[1]);
preg_match('#/FontBBox[\s]*{([^}]*)#', $font, $matches);
$fmetric['bbox'] = trim($matches[1]);
$bv = explode(' ', $fmetric['bbox']);
$fmetric['Ascent'] = intval($bv[3]);
$fmetric['Descent'] = intval($bv[1]);
preg_match('#/ItalicAngle[\s]*([0-9\+\-]*)#', $font, $matches);
$fmetric['italicAngle'] = intval($matches[1]);
if ($fmetric['italicAngle'] != 0) {
$fmetric['Flags'] |= 64;
}
preg_match('#/UnderlinePosition[\s]*([0-9\+\-]*)#', $font, $matches);
$fmetric['underlinePosition'] = intval($matches[1]);
preg_match('#/UnderlineThickness[\s]*([0-9\+\-]*)#', $font, $matches);
$fmetric['underlineThickness'] = intval($matches[1]);
preg_match('#/isFixedPitch[\s]*([^\s]*)#', $font, $matches);
if ($matches[1] == 'true') {
$fmetric['Flags'] |= 1;
}
// get internal map
$imap = array();
if (preg_match_all('#dup[\s]([0-9]+)[\s]*/([^\s]*)[\s]put#sU', $font, $fmap, PREG_SET_ORDER) > 0) {
foreach ($fmap as $v) {
$imap[$v[2]] = $v[1];
}
}
// decrypt eexec encrypted part
$r = 55665; // eexec encryption constant
$c1 = 52845;
$c2 = 22719;
$elen = strlen($encrypted);
$eplain = '';
for ($i = 0; $i < $elen; ++$i) {
$chr = ord($encrypted[$i]);
$eplain .= chr($chr ^ ($r >> 8));
$r = ((($chr + $r) * $c1 + $c2) % 65536);
}
if (preg_match('#/ForceBold[\s]*([^\s]*)#', $eplain, $matches) > 0) {
if ($matches[1] == 'true') {
$fmetric['Flags'] |= 0x40000;
}
}
if (preg_match('#/StdVW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
$fmetric['StemV'] = intval($matches[1]);
} else {
$fmetric['StemV'] = 70;
}
if (preg_match('#/StdHW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
$fmetric['StemH'] = intval($matches[1]);
} else {
$fmetric['StemH'] = 30;
}
if (preg_match('#/BlueValues[\s]*\[([^\]]*)#', $eplain, $matches) > 0) {
$bv = explode(' ', $matches[1]);
if (count($bv) >= 6) {
$v1 = intval($bv[2]);
$v2 = intval($bv[4]);
if ($v1 <= $v2) {
$fmetric['XHeight'] = $v1;
$fmetric['CapHeight'] = $v2;
} else {
$fmetric['XHeight'] = $v2;
$fmetric['CapHeight'] = $v1;
}
} else {
$fmetric['XHeight'] = 450;
$fmetric['CapHeight'] = 700;
}
} else {
$fmetric['XHeight'] = 450;
$fmetric['CapHeight'] = 700;
}
// get the number of random bytes at the beginning of charstrings
if (preg_match('#/lenIV[\s]*([0-9]*)#', $eplain, $matches) > 0) {
$lenIV = intval($matches[1]);
} else {
$lenIV = 4;
}
$fmetric['Leading'] = 0;
// get charstring data
$eplain = substr($eplain, (strpos($eplain, '/CharStrings') + 1));
preg_match_all('#/([A-Za-z0-9\.]*)[\s][0-9]+[\s]RD[\s](.*)[\s]ND#sU', $eplain, $matches, PREG_SET_ORDER);
if (!empty($enc) AND isset(TCPDF_FONT_DATA::$encmap[$enc])) {
$enc_map = TCPDF_FONT_DATA::$encmap[$enc];
} else {
$enc_map = false;
}
$fmetric['cw'] = '';
$fmetric['MaxWidth'] = 0;
$cwidths = array();
foreach ($matches as $k => $v) {
$cid = 0;
if (isset($imap[$v[1]])) {
$cid = $imap[$v[1]];
} elseif ($enc_map !== false) {
$cid = array_search($v[1], $enc_map);
if ($cid === false) {
$cid = 0;
} elseif ($cid > 1000) {
$cid -= 1000;
}
}
// decrypt charstring encrypted part
$r = 4330; // charstring encryption constant
$c1 = 52845;
$c2 = 22719;
$cd = $v[2];
$clen = strlen($cd);
$ccom = array();
for ($i = 0; $i < $clen; ++$i) {
$chr = ord($cd[$i]);
$ccom[] = ($chr ^ ($r >> 8));
$r = ((($chr + $r) * $c1 + $c2) % 65536);
}
// decode numbers
$cdec = array();
$ck = 0;
$i = $lenIV;
while ($i < $clen) {
if ($ccom[$i] < 32) {
$cdec[$ck] = $ccom[$i];
if (($ck > 0) AND ($cdec[$ck] == 13)) {
// hsbw command: update width
$cwidths[$cid] = $cdec[($ck - 1)];
}
++$i;
} elseif (($ccom[$i] >= 32) AND ($ccom[$i] <= 246)) {
$cdec[$ck] = ($ccom[$i] - 139);
++$i;
} elseif (($ccom[$i] >= 247) AND ($ccom[$i] <= 250)) {
$cdec[$ck] = ((($ccom[$i] - 247) * 256) + $ccom[($i + 1)] + 108);
$i += 2;
} elseif (($ccom[$i] >= 251) AND ($ccom[$i] <= 254)) {
$cdec[$ck] = ((-($ccom[$i] - 251) * 256) - $ccom[($i + 1)] - 108);
$i += 2;
} elseif ($ccom[$i] == 255) {
$sval = chr($ccom[($i + 1)]).chr($ccom[($i + 2)]).chr($ccom[($i + 3)]).chr($ccom[($i + 4)]);
$vsval = unpack('li', $sval);
$cdec[$ck] = $vsval['i'];
$i += 5;
}
++$ck;
}
} // end for each matches
$fmetric['MissingWidth'] = $cwidths[0];
$fmetric['MaxWidth'] = $fmetric['MissingWidth'];
$fmetric['AvgWidth'] = 0;
// set chars widths
for ($cid = 0; $cid <= 255; ++$cid) {
if (isset($cwidths[$cid])) {
if ($cwidths[$cid] > $fmetric['MaxWidth']) {
$fmetric['MaxWidth'] = $cwidths[$cid];
}
$fmetric['AvgWidth'] += $cwidths[$cid];
$fmetric['cw'] .= ','.$cid.'=>'.$cwidths[$cid];
} else {
$fmetric['cw'] .= ','.$cid.'=>'.$fmetric['MissingWidth'];
}
}
$fmetric['AvgWidth'] = round($fmetric['AvgWidth'] / count($cwidths));
} else {
// ---------- TRUE TYPE ----------
$offset = 0; // offset position of the font data
if (TCPDF_STATIC::_getULONG($font, $offset) != 0x10000) {
// sfnt version must be 0x00010000 for TrueType version 1.0.
return false;
}
if ($fmetric['type'] != 'cidfont0') {
if ($link) {
// creates a symbolic link to the existing font
symlink($fontfile, $outpath.$fmetric['file']);
} else {
// store compressed font
$fmetric['file'] .= '.z';
$fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['file'], 'wb');
fwrite($fp, gzcompress($font));
fclose($fp);
}
}
$offset += 4;
// get number of tables
$numTables = TCPDF_STATIC::_getUSHORT($font, $offset);
$offset += 2;
// skip searchRange, entrySelector and rangeShift
$offset += 6;
// tables array
$table = array();
// ---------- get tables ----------
for ($i = 0; $i < $numTables; ++$i) {
// get table info
$tag = substr($font, $offset, 4);
$offset += 4;
$table[$tag] = array();
$table[$tag]['checkSum'] = TCPDF_STATIC::_getULONG($font, $offset);
$offset += 4;
$table[$tag]['offset'] = TCPDF_STATIC::_getULONG($font, $offset);
$offset += 4;
$table[$tag]['length'] = TCPDF_STATIC::_getULONG($font, $offset);
$offset += 4;
}
// check magicNumber
$offset = $table['head']['offset'] + 12;
if (TCPDF_STATIC::_getULONG($font, $offset) != 0x5F0F3CF5) {
// magicNumber must be 0x5F0F3CF5
return false;
}
$offset += 4;
$offset += 2; // skip flags
// get FUnits
$fmetric['unitsPerEm'] = TCPDF_STATIC::_getUSHORT($font, $offset);
$offset += 2;
// units ratio constant
$urk = (1000 / $fmetric['unitsPerEm']);
$offset += 16; // skip created, modified
$xMin = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk);
$offset += 2;
$yMin = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk);
$offset += 2;
$xMax = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk);
$offset += 2;
$yMax = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk);
$offset += 2;
$fmetric['bbox'] = ''.$xMin.' '.$yMin.' '.$xMax.' '.$yMax.'';
$macStyle = TCPDF_STATIC::_getUSHORT($font, $offset);
$offset += 2;
// PDF font flags
$fmetric['Flags'] = $flags;
if (($macStyle & 2) == 2) {
// italic flag
$fmetric['Flags'] |= 64;
}
// get offset mode (indexToLocFormat : 0 = short, 1 = long)
$offset = $table['head']['offset'] + 50;
$short_offset = (TCPDF_STATIC::_getSHORT($font, $offset) == 0);
$offset += 2;
// get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table
$indexToLoc = array();
$offset = $table['loca']['offset'];
if ($short_offset) {
// short version
$tot_num_glyphs = floor($table['loca']['length'] / 2); // numGlyphs + 1
for ($i = 0; $i < $tot_num_glyphs; ++$i) {
$indexToLoc[$i] = TCPDF_STATIC::_getUSHORT($font, $offset) * 2;
if (isset($indexToLoc[($i - 1)]) && ($indexToLoc[$i] == $indexToLoc[($i - 1)])) {
// the last glyph didn't have an outline
unset($indexToLoc[($i - 1)]);
}
$offset += 2;
}
} else {
// long version
$tot_num_glyphs = floor($table['loca']['length'] / 4); // numGlyphs + 1
for ($i = 0; $i < $tot_num_glyphs; ++$i) {
$indexToLoc[$i] = TCPDF_STATIC: