123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- <?php
- //============================================================+
- // File name : makefont.php
- // Begin : 2004-12-31
- // Last Update : 2010-12-03
- // Version : 1.2.007
- // License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
- // ----------------------------------------------------------------------------
- // Copyright (C) 2008-2010 Nicola Asuni - Tecnick.com S.r.l.
- //
- // 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 : Utility to generate font definition files fot TCPDF
- //
- // Authors: Nicola Asuni, Olivier Plathey, Steven Wittens
- //
- // (c) Copyright:
- // Nicola Asuni
- // Tecnick.com S.r.l.
- // Via della Pace, 11
- // 09044 Quartucciu (CA)
- // ITALY
- // www.tecnick.com
- // info@tecnick.com
- //============================================================+
- /**
- * @file
- * Utility to generate font definition files fot TCPDF.
- * @author Nicola Asuni, Olivier Plathey, Steven Wittens
- * @package com.tecnick.tcpdf
- */
- /**
- * Convert a Font for TCPDF
- * @param $fontfile (string) path to font file (TTF, OTF or PFB).
- * @param $fmfile (string) font metrics file (UFM or AFM).
- * @param $embedded (boolean) Set to false to not embed the font, true otherwise (default).
- * @param $enc (string) Name of the encoding table to use. Omit this parameter for TrueType Unicode, OpenType Unicode and symbolic fonts like Symbol or ZapfDingBats.
- * @param $patch (array) Optional modification of the encoding
- */
- function MakeFont($fontfile, $fmfile, $embedded=true, $enc='cp1252', $patch=array()) {
- //Generate a font definition file
- if(!defined('PHP_VERSION_ID')) {
- $version = PHP_VERSION;
- define('PHP_VERSION_ID', (($version{0} * 10000) + ($version{2} * 100) + $version{4}));
- }
- if (PHP_VERSION_ID < 50300) {
- @set_magic_quotes_runtime(0);
- }
- ini_set('auto_detect_line_endings', '1');
- if (!file_exists($fontfile)) {
- die('Error: file not found: '.$fontfile);
- }
- if (!file_exists($fmfile)) {
- die('Error: file not found: '.$fmfile);
- }
- $cidtogidmap = '';
- $map = array();
- $diff = '';
- $dw = 0; // default width
- $ffext = strtolower(substr($fontfile, -3));
- $fmext = strtolower(substr($fmfile, -3));
- if ($fmext == 'afm') {
- if (($ffext == 'ttf') OR ($ffext == 'otf')) {
- $type = 'TrueType';
- } elseif ($ffext == 'pfb') {
- $type = 'Type1';
- } else {
- die('Error: unrecognized font file extension: '.$ffext);
- }
- if ($enc) {
- $map = ReadMap($enc);
- foreach ($patch as $cc => $gn) {
- $map[$cc] = $gn;
- }
- }
- $fm = ReadAFM($fmfile, $map);
- if (isset($widths['.notdef'])) {
- $dw = $widths['.notdef'];
- }
- if ($enc) {
- $diff = MakeFontEncoding($map);
- }
- $fd = MakeFontDescriptor($fm, empty($map));
- } elseif ($fmext == 'ufm') {
- $enc = '';
- if (($ffext == 'ttf') OR ($ffext == 'otf')) {
- $type = 'TrueTypeUnicode';
- } else {
- die('Error: not a TrueType font: '.$ffext);
- }
- $fm = ReadUFM($fmfile, $cidtogidmap);
- $dw = $fm['MissingWidth'];
- $fd = MakeFontDescriptor($fm, false);
- }
- //Start generation
- $s = '<?php'."\n";
- $s .= '$type=\''.$type."';\n";
- $s .= '$name=\''.$fm['FontName']."';\n";
- $s .= '$desc='.$fd.";\n";
- if (!isset($fm['UnderlinePosition'])) {
- $fm['UnderlinePosition'] = -100;
- }
- if (!isset($fm['UnderlineThickness'])) {
- $fm['UnderlineThickness'] = 50;
- }
- $s .= '$up='.$fm['UnderlinePosition'].";\n";
- $s .= '$ut='.$fm['UnderlineThickness'].";\n";
- if ($dw <= 0) {
- if (isset($fm['Widths'][32]) AND ($fm['Widths'][32] > 0)) {
- // assign default space width
- $dw = $fm['Widths'][32];
- } else {
- $dw = 600;
- }
- }
- $s .= '$dw='.$dw.";\n";
- $w = MakeWidthArray($fm);
- $s .= '$cw='.$w.";\n";
- $s .= '$enc=\''.$enc."';\n";
- $s .= '$diff=\''.$diff."';\n";
- $basename = substr(basename($fmfile), 0, -4);
- if ($embedded) {
- //Embedded font
- if (($type == 'TrueType') OR ($type == 'TrueTypeUnicode')) {
- CheckTTF($fontfile);
- }
- $f = fopen($fontfile,'rb');
- if (!$f) {
- die('Error: Unable to open '.$fontfile);
- }
- $file = fread($f, filesize($fontfile));
- fclose($f);
- if ($type == 'Type1') {
- //Find first two sections and discard third one
- $header = (ord($file{0}) == 128);
- if ($header) {
- //Strip first binary header
- $file = substr($file, 6);
- }
- $pos = strpos($file, 'eexec');
- if (!$pos) {
- die('Error: font file does not seem to be valid Type1');
- }
- $size1 = $pos + 6;
- if ($header AND (ord($file{$size1}) == 128)) {
- //Strip second binary header
- $file = substr($file, 0, $size1).substr($file, $size1+6);
- }
- $pos = strpos($file, '00000000');
- if (!$pos) {
- die('Error: font file does not seem to be valid Type1');
- }
- $size2 = $pos - $size1;
- $file = substr($file, 0, ($size1 + $size2));
- }
- $basename = strtolower($basename);
- if (function_exists('gzcompress')) {
- $cmp = $basename.'.z';
- SaveToFile($cmp, gzcompress($file, 9), 'b');
- $s .= '$file=\''.$cmp."';\n";
- print "Font file compressed (".$cmp.")\n";
- if (!empty($cidtogidmap)) {
- $cmp = $basename.'.ctg.z';
- SaveToFile($cmp, gzcompress($cidtogidmap, 9), 'b');
- print "CIDToGIDMap created and compressed (".$cmp.")\n";
- $s .= '$ctg=\''.$cmp."';\n";
- }
- } else {
- $s .= '$file=\''.basename($fontfile)."';\n";
- print "Notice: font file could not be compressed (zlib extension not available)\n";
- if (!empty($cidtogidmap)) {
- $cmp = $basename.'.ctg';
- $f = fopen($cmp, 'wb');
- fwrite($f, $cidtogidmap);
- fclose($f);
- print "CIDToGIDMap created (".$cmp.")\n";
- $s .= '$ctg=\''.$cmp."';\n";
- }
- }
- if($type == 'Type1') {
- $s .= '$size1='.$size1.";\n";
- $s .= '$size2='.$size2.";\n";
- } else {
- $s.='$originalsize='.filesize($fontfile).";\n";
- }
- } else {
- //Not embedded font
- $s .= '$file='."'';\n";
- }
- $s .= '// --- EOF ---';
- SaveToFile($basename.'.php',$s);
- print "Font definition file generated (".$basename.".php)\n";
- }
- /**
- * Read the specified encoding map.
- * @param $enc (string) map name (see /enc/ folder for valid names).
- */
- function ReadMap($enc) {
- //Read a map file
- $file = dirname(__FILE__).'/enc/'.strtolower($enc).'.map';
- $a = file($file);
- if (empty($a)) {
- die('Error: encoding not found: '.$enc);
- }
- $cc2gn = array();
- foreach ($a as $l) {
- if ($l{0} == '!') {
- $e = preg_split('/[ \\t]+/',rtrim($l));
- $cc = hexdec(substr($e[0],1));
- $gn = $e[2];
- $cc2gn[$cc] = $gn;
- }
- }
- for($i = 0; $i <= 255; $i++) {
- if(!isset($cc2gn[$i])) {
- $cc2gn[$i] = '.notdef';
- }
- }
- return $cc2gn;
- }
- /**
- * Read UFM file
- */
- function ReadUFM($file, &$cidtogidmap) {
- //Prepare empty CIDToGIDMap
- $cidtogidmap = str_pad('', (256 * 256 * 2), "\x00");
- //Read a font metric file
- $a = file($file);
- if (empty($a)) {
- die('File not found');
- }
- $widths = array();
- $fm = array();
- foreach($a as $l) {
- $e = explode(' ',chop($l));
- if(count($e) < 2) {
- continue;
- }
- $code = $e[0];
- $param = $e[1];
- if($code == 'U') {
- // U 827 ; WX 0 ; N squaresubnosp ; G 675 ;
- //Character metrics
- $cc = (int)$e[1];
- if ($cc != -1) {
- $gn = $e[7];
- $w = $e[4];
- $glyph = $e[10];
- $widths[$cc] = $w;
- if($cc == ord('X')) {
- $fm['CapXHeight'] = $e[13];
- }
- // Set GID
- if (($cc >= 0) AND ($cc < 0xFFFF) AND $glyph) {
- $cidtogidmap{($cc * 2)} = chr($glyph >> 8);
- $cidtogidmap{(($cc * 2) + 1)} = chr($glyph & 0xFF);
- }
- }
- if((isset($gn) AND ($gn == '.notdef')) AND (!isset($fm['MissingWidth']))) {
- $fm['MissingWidth'] = $w;
- }
- } elseif($code == 'FontName') {
- $fm['FontName'] = $param;
- } elseif($code == 'Weight') {
- $fm['Weight'] = $param;
- } elseif($code == 'ItalicAngle') {
- $fm['ItalicAngle'] = (double)$param;
- } elseif($code == 'Ascender') {
- $fm['Ascender'] = (int)$param;
- } elseif($code == 'Descender') {
- $fm['Descender'] = (int)$param;
- } elseif($code == 'UnderlineThickness') {
- $fm['UnderlineThickness'] = (int)$param;
- } elseif($code == 'UnderlinePosition') {
- $fm['UnderlinePosition'] = (int)$param;
- } elseif($code == 'IsFixedPitch') {
- $fm['IsFixedPitch'] = ($param == 'true');
- } elseif($code == 'FontBBox') {
- $fm['FontBBox'] = array($e[1], $e[2], $e[3], $e[4]);
- } elseif($code == 'CapHeight') {
- $fm['CapHeight'] = (int)$param;
- } elseif($code == 'StdVW') {
- $fm['StdVW'] = (int)$param;
- }
- }
- if(!isset($fm['MissingWidth'])) {
- $fm['MissingWidth'] = 600;
- }
- if(!isset($fm['FontName'])) {
- die('FontName not found');
- }
- $fm['Widths'] = $widths;
- return $fm;
- }
- /**
- * Read AFM file
- */
- function ReadAFM($file,&$map) {
- //Read a font metric file
- $a = file($file);
- if(empty($a)) {
- die('File not found');
- }
- $widths = array();
- $fm = array();
- $fix = array(
- 'Edot'=>'Edotaccent',
- 'edot'=>'edotaccent',
- 'Idot'=>'Idotaccent',
- 'Zdot'=>'Zdotaccent',
- 'zdot'=>'zdotaccent',
- 'Odblacute' => 'Ohungarumlaut',
- 'odblacute' => 'ohungarumlaut',
- 'Udblacute'=>'Uhungarumlaut',
- 'udblacute'=>'uhungarumlaut',
- 'Gcedilla'=>'Gcommaaccent'
- ,'gcedilla'=>'gcommaaccent',
- 'Kcedilla'=>'Kcommaaccent',
- 'kcedilla'=>'kcommaaccent',
- 'Lcedilla'=>'Lcommaaccent',
- 'lcedilla'=>'lcommaaccent',
- 'Ncedilla'=>'Ncommaaccent',
- 'ncedilla'=>'ncommaaccent',
- 'Rcedilla'=>'Rcommaaccent',
- 'rcedilla'=>'rcommaaccent',
- 'Scedilla'=>'Scommaaccent',
- 'scedilla'=>'scommaaccent',
- 'Tcedilla'=>'Tcommaaccent',
- 'tcedilla'=>'tcommaaccent',
- 'Dslash'=>'Dcroat',
- 'dslash'=>'dcroat',
- 'Dmacron'=>'Dcroat',
- 'dmacron'=>'dcroat',
- 'combininggraveaccent'=>'gravecomb',
- 'combininghookabove'=>'hookabovecomb',
- 'combiningtildeaccent'=>'tildecomb',
- 'combiningacuteaccent'=>'acutecomb',
- 'combiningdotbelow'=>'dotbelowcomb',
- 'dongsign'=>'dong'
- );
- foreach($a as $l) {
- $e = explode(' ', rtrim($l));
- if (count($e) < 2) {
- continue;
- }
- $code = $e[0];
- $param = $e[1];
- if ($code == 'C') {
- //Character metrics
- $cc = (int)$e[1];
- $w = $e[4];
- $gn = $e[7];
- if (substr($gn, -4) == '20AC') {
- $gn = 'Euro';
- }
- if (isset($fix[$gn])) {
- //Fix incorrect glyph name
- foreach ($map as $c => $n) {
- if ($n == $fix[$gn]) {
- $map[$c] = $gn;
- }
- }
- }
- if (empty($map)) {
- //Symbolic font: use built-in encoding
- $widths[$cc] = $w;
- } else {
- $widths[$gn] = $w;
- if($gn == 'X') {
- $fm['CapXHeight'] = $e[13];
- }
- }
- if($gn == '.notdef') {
- $fm['MissingWidth'] = $w;
- }
- } elseif($code == 'FontName') {
- $fm['FontName'] = $param;
- } elseif($code == 'Weight') {
- $fm['Weight'] = $param;
- } elseif($code == 'ItalicAngle') {
- $fm['ItalicAngle'] = (double)$param;
- } elseif($code == 'Ascender') {
- $fm['Ascender'] = (int)$param;
- } elseif($code == 'Descender') {
- $fm['Descender'] = (int)$param;
- } elseif($code == 'UnderlineThickness') {
- $fm['UnderlineThickness'] = (int)$param;
- } elseif($code == 'UnderlinePosition') {
- $fm['UnderlinePosition'] = (int)$param;
- } elseif($code == 'IsFixedPitch') {
- $fm['IsFixedPitch'] = ($param == 'true');
- } elseif($code == 'FontBBox') {
- $fm['FontBBox'] = array($e[1], $e[2], $e[3], $e[4]);
- } elseif($code == 'CapHeight') {
- $fm['CapHeight'] = (int)$param;
- } elseif($code == 'StdVW') {
- $fm['StdVW'] = (int)$param;
- }
- }
- if (!isset($fm['FontName'])) {
- die('FontName not found');
- }
- if (!empty($map)) {
- if (!isset($widths['.notdef'])) {
- $widths['.notdef'] = 600;
- }
- if (!isset($widths['Delta']) AND isset($widths['increment'])) {
- $widths['Delta'] = $widths['increment'];
- }
- //Order widths according to map
- for ($i = 0; $i <= 255; $i++) {
- if (!isset($widths[$map[$i]])) {
- print "Warning: character ".$map[$i]." is missing\n";
- $widths[$i] = $widths['.notdef'];
- } else {
- $widths[$i] = $widths[$map[$i]];
- }
- }
- }
- $fm['Widths'] = $widths;
- return $fm;
- }
- function MakeFontDescriptor($fm, $symbolic=false) {
- //Ascent
- $asc = (isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
- $fd = "array('Ascent'=>".$asc;
- //Descent
- $desc = (isset($fm['Descender']) ? $fm['Descender'] : -200);
- $fd .= ",'Descent'=>".$desc;
- //CapHeight
- if (isset($fm['CapHeight'])) {
- $ch = $fm['CapHeight'];
- } elseif (isset($fm['CapXHeight'])) {
- $ch = $fm['CapXHeight'];
- } else {
- $ch = $asc;
- }
- $fd .= ",'CapHeight'=>".$ch;
- //Flags
- $flags = 0;
- if (isset($fm['IsFixedPitch']) AND $fm['IsFixedPitch']) {
- $flags += 1<<0;
- }
- if ($symbolic) {
- $flags += 1<<2;
- } else {
- $flags += 1<<5;
- }
- if (isset($fm['ItalicAngle']) AND ($fm['ItalicAngle'] != 0)) {
- $flags += 1<<6;
- }
- $fd .= ",'Flags'=>".$flags;
- //FontBBox
- if (isset($fm['FontBBox'])) {
- $fbb = $fm['FontBBox'];
- } else {
- $fbb = array(0, ($desc - 100), 1000, ($asc + 100));
- }
- $fd .= ",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
- //ItalicAngle
- $ia = (isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
- $fd .= ",'ItalicAngle'=>".$ia;
- //StemV
- if (isset($fm['StdVW'])) {
- $stemv = $fm['StdVW'];
- } elseif (isset($fm['Weight']) AND preg_match('/(bold|black)/i', $fm['Weight'])) {
- $stemv = 120;
- } else {
- $stemv = 70;
- }
- $fd .= ",'StemV'=>".$stemv;
- //MissingWidth
- if(isset($fm['MissingWidth'])) {
- $fd .= ",'MissingWidth'=>".$fm['MissingWidth'];
- }
- $fd .= ')';
- return $fd;
- }
- function MakeWidthArray($fm) {
- //Make character width array
- $s = 'array(';
- $cw = $fm['Widths'];
- $els = array();
- $c = 0;
- foreach ($cw as $i => $w) {
- if (is_numeric($i)) {
- $els[] = (((($c++)%10) == 0) ? "\n" : '').$i.'=>'.$w;
- }
- }
- $s .= implode(',', $els);
- $s .= ')';
- return $s;
- }
- function MakeFontEncoding($map) {
- //Build differences from reference encoding
- $ref = ReadMap('cp1252');
- $s = '';
- $last = 0;
- for ($i = 32; $i <= 255; $i++) {
- if ($map[$i] != $ref[$i]) {
- if ($i != $last+1) {
- $s .= $i.' ';
- }
- $last = $i;
- $s .= '/'.$map[$i].' ';
- }
- }
- return rtrim($s);
- }
- function SaveToFile($file, $s, $mode='t') {
- $f = fopen($file, 'w'.$mode);
- if(!$f) {
- die('Can\'t write to file '.$file);
- }
- fwrite($f, $s, strlen($s));
- fclose($f);
- }
- function ReadShort($f) {
- $a = unpack('n1n', fread($f, 2));
- return $a['n'];
- }
- function ReadLong($f) {
- $a = unpack('N1N', fread($f, 4));
- return $a['N'];
- }
- function CheckTTF($file) {
- //Check if font license allows embedding
- $f = fopen($file, 'rb');
- if (!$f) {
- die('Error: unable to open '.$file);
- }
- //Extract number of tables
- fseek($f, 4, SEEK_CUR);
- $nb = ReadShort($f);
- fseek($f, 6, SEEK_CUR);
- //Seek OS/2 table
- $found = false;
- for ($i = 0; $i < $nb; $i++) {
- if (fread($f, 4) == 'OS/2') {
- $found = true;
- break;
- }
- fseek($f, 12, SEEK_CUR);
- }
- if (!$found) {
- fclose($f);
- return;
- }
- fseek($f, 4, SEEK_CUR);
- $offset = ReadLong($f);
- fseek($f, $offset, SEEK_SET);
- //Extract fsType flags
- fseek($f, 8, SEEK_CUR);
- $fsType = ReadShort($f);
- $rl = ($fsType & 0x02) != 0;
- $pp = ($fsType & 0x04) != 0;
- $e = ($fsType & 0x08) != 0;
- fclose($f);
- if($rl AND (!$pp) AND (!$e)) {
- print 'Warning: font license does not allow embedding.'."\n";
- }
- }
- // -------------------------------------------------------------------
- $arg = $GLOBALS['argv'];
- if (count($arg) >= 3) {
- ob_start();
- array_shift($arg);
- if (sizeof($arg) == 3) {
- $arg[3] = $arg[2];
- $arg[2] = true;
- } else {
- if (!isset($arg[2])) {
- $arg[2] = true;
- }
- if (!isset($arg[3])) {
- $arg[3] = 'cp1252';
- }
- }
- if (!isset($arg[4])) {
- $arg[4] = array();
- }
- MakeFont($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);
- $t = ob_get_clean();
- print preg_replace('!<BR( /)?>!i', "\n", $t);
- } else {
- print 'Usage: makefont.php <ttf/otf/pfb file> <afm/ufm file> <encoding> <patch>'."\n";
- }
- //============================================================+
- // END OF FILE
- //============================================================+
|