Source for file makefont.php
Documentation is available at makefont.php 
//============================================================+  
// File name   : makefont.php  
// Last Update : 2010-08-08  
// 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  
//============================================================+  
 * Utility to generate font definition files fot TCPDF.  
 * @author Nicola Asuni, Olivier Plathey, Steven Wittens  
 * @copyright 2004-2008 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com  
 * @package com.tecnick.tcpdf  
 * @link http://www.tcpdf.org  
 * @license http://www.gnu.org/copyleft/lesser.html LGPL  
 * @param string $fontfile path to font file (TTF, OTF or PFB).  
 * @param string $fmfile font metrics file (UFM or AFM).  
 * @param boolean $embedded Set to false to not embed the font, true otherwise (default).  
 * @param string $enc Name of the encoding table to use. Omit this parameter for TrueType Unicode, OpenType Unicode and symbolic fonts like Symbol or ZapfDingBats.  
 * @param array $patch Optional modification of the encoding  
function MakeFont($fontfile, $fmfile, $embedded= true, $enc= 'cp1252', $patch= array()) {  
    //Generate a font definition file  
    ini_set('auto_detect_line_endings', '1');  
        die('Error: file not found: '. $fontfile);  
        die('Error: file not found: '. $fmfile);  
    $dw =  0; // default width  
        if (($ffext ==  'ttf') OR ($ffext ==  'otf')) {  
        } elseif ($ffext ==  'pfb') {  
            die('Error: unrecognized font file extension: '. $ffext);  
            foreach ($patch as $cc =>  $gn) {  
        if (isset ($widths['.notdef'])) {  
            $dw =  $widths['.notdef'];  
    } elseif ($fmext ==  'ufm') {  
        if (($ffext ==  'ttf') OR ($ffext ==  'otf')) {  
            $type =  'TrueTypeUnicode';  
            die('Error: not a TrueType font: '. $ffext);  
        $fm =  ReadUFM($fmfile, $cidtogidmap);  
        $dw =  $fm['MissingWidth'];  
    $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 (isset ($fm['Widths'][32]) AND ($fm['Widths'][32] >  0)) {  
            // assign default space width  
    $s .=  '$enc=\''. $enc. "';\n";  
    $s .=  '$diff=\''. $diff. "';\n";  
        if (($type ==  'TrueType') OR ($type ==  'TrueTypeUnicode')) {  
        $f =  fopen($fontfile,'rb');  
            die('Error: Unable to open '. $fontfile);  
            //Find first two sections and discard third one  
            $header =  (ord($file{0}) ==  128);  
                //Strip first binary header  
            $pos =  strpos($file, 'eexec');  
                die('Error: font file does not seem to be valid Type1');  
            if ($header AND (ord($file{$size1}) ==  128)) {  
                //Strip second binary header  
            $pos =  strpos($file, '00000000');  
                die('Error: font file does not seem to be valid Type1');  
            $file =  substr($file, 0, ($size1 +  $size2));  
            $s .=  '$file=\''. $cmp. "';\n";  
            print  "Font file compressed (". $cmp. ")\n"; 
            if (!empty($cidtogidmap)) {  
                $cmp =  $basename. '.ctg.z';  
                print  "CIDToGIDMap created and compressed (". $cmp. ")\n"; 
                $s .=  '$ctg=\''. $cmp. "';\n";  
            $s .=  '$file=\''. basename($fontfile). "';\n";  
            print  "Notice: font file could not be compressed (zlib extension not available)\n"; 
            if (!empty($cidtogidmap)) {  
                print  "CIDToGIDMap created (". $cmp. ")\n"; 
                $s .=  '$ctg=\''. $cmp. "';\n";  
            $s .=  '$size1='. $size1. ";\n";  
            $s .=  '$size2='. $size2. ";\n";  
            $s.= '$originalsize='. filesize($fontfile). ";\n";  
    print  "Font definition file generated (". $basename. ".php)\n"; 
 * Read the specified encoding map.  
 * @param string $enc map name (see /enc/ folder for valid names).  
        die('Error: encoding not found: '. $enc);  
    for($i =  0; $i <=  255; $i++ ) {  
function ReadUFM($file, &$cidtogidmap) {  
    //Prepare empty CIDToGIDMap  
    $cidtogidmap =  str_pad('', (256 *  256 *  2), "\x00");  
    //Read a font metric file  
            // U 827 ; WX 0 ; N squaresubnosp ; G 675 ;  
                $fm['CapXHeight'] =  $e[13];  
            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') {  
        } 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');  
    //Read a font metric file  
        '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',  
        'combininggraveaccent'=> 'gravecomb',  
        'combininghookabove'=> 'hookabovecomb',  
        'combiningtildeaccent'=> 'tildecomb',  
        'combiningacuteaccent'=> 'acutecomb',  
        'combiningdotbelow'=> 'dotbelowcomb',  
            if (substr($gn, - 4) ==  '20AC') {  
                //Fix incorrect glyph name  
                foreach ($map as $c =>  $n) {  
                //Symbolic font: use built-in encoding  
                    $fm['CapXHeight'] =  $e[13];  
                $fm['MissingWidth'] =  $w;  
        } elseif($code ==  'FontName') {  
            $fm['FontName'] =  $param;  
        } elseif($code ==  'Weight') {  
        } 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 (!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'];  
                $widths[$i] =  $widths[$map[$i]];  
    $asc =  (isset ($fm['Ascender']) ?  $fm['Ascender'] :  1000);  
    $fd =  "array('Ascent'=>". $asc;  
    $desc =  (isset ($fm['Descender']) ?  $fm['Descender'] : - 200);  
    $fd .=  ",'Descent'=>". $desc;  
    if (isset ($fm['CapHeight'])) {  
    } elseif (isset ($fm['CapXHeight'])) {  
    $fd .=  ",'CapHeight'=>". $ch;  
    if (isset ($fm['IsFixedPitch']) AND $fm['IsFixedPitch']) {  
    if (isset ($fm['ItalicAngle']) AND ($fm['ItalicAngle'] !=  0)) {  
    $fd .=  ",'Flags'=>". $flags;  
    if (isset ($fm['FontBBox'])) {  
        $fbb =  array(0, ($desc -  100), 1000, ($asc +  100));  
    $fd .=  ",'FontBBox'=>'[". $fbb[0]. ' '. $fbb[1]. ' '. $fbb[2]. ' '. $fbb[3]. "]'";  
    $ia =  (isset ($fm['ItalicAngle']) ?  $fm['ItalicAngle'] :  0);  
    $fd .=  ",'ItalicAngle'=>". $ia;  
    if (isset ($fm['StdVW'])) {  
    } elseif (isset ($fm['Weight']) AND preg_match('/(bold|black)/i', $fm['Weight'])) {  
    $fd .=  ",'StemV'=>". $stemv;  
    if(isset ($fm['MissingWidth'])) {  
        $fd .=  ",'MissingWidth'=>". $fm['MissingWidth'];  
    //Make character width array  
    foreach ($cw as $i =>  $w) {  
            $els[] =  (((($c++ )% 10) ==  0) ?  "\n" :  ''). $i. '=>'. $w;  
    //Build differences from reference encoding  
    for ($i =  32; $i <=  255; $i++ ) {  
        if ($map[$i] !=  $ref[$i]) {  
    $f =  fopen($file, 'w'. $mode);  
        die('Can\'t write to file '. $file);  
    //Check if font license allows embedding  
        die('Error: unable to open '. $file);  
    //Extract number of tables  
    for ($i =  0; $i <  $nb; $i++ ) {  
        if (fread($f, 4) ==  'OS/2') {  
    fseek($f, $offset, SEEK_SET);  
    $rl =  ($fsType & 0x02) !=  0;  
    $pp =  ($fsType & 0x04) !=  0;  
    $e =  ($fsType & 0x08) !=  0;  
    if($rl AND (!$pp) AND (!$e)) {  
        print  "Warning: font license does not allow embedding\n"; 
    MakeFont($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);  
    print  "Usage: makefont.php <ttf/otf/pfb file> <afm/ufm file> <encoding> <patch>\n"; 
//============================================================+  
//============================================================+  
 
 
        
       |