5 Modification information for LGPL compliance
7 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
9 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
11 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
13 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
15 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
17 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
19 r47930 - 2009-06-02 16:21:39 -0700 (Tue, 02 Jun 2009) - jenny - Updating with changes from bsoufflet.
25 // BEGIN SUGARCRM SPECIFIC
26 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
27 // END SUGARCRM SPECIFIC
29 //============================================================+
30 // File name : makefont.php
32 // Last Update : 2008-12-06
34 // License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
35 // ----------------------------------------------------------------------------
36 // Copyright (C) 2008 Nicola Asuni - Tecnick.com S.r.l.
38 // This program is free software: you can redistribute it and/or modify
39 // it under the terms of the GNU Lesser General Public License as published by
40 // the Free Software Foundation, either version 2.1 of the License, or
41 // (at your option) any later version.
43 // This program is distributed in the hope that it will be useful,
44 // but WITHOUT ANY WARRANTY; without even the implied warranty of
45 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 // GNU Lesser General Public License for more details.
48 // You should have received a copy of the GNU Lesser General Public License
49 // along with this program. If not, see <http://www.gnu.org/licenses/>.
51 // See LICENSE.TXT file for more information.
52 // ----------------------------------------------------------------------------
54 // Description : Utility to generate font definition files fot TCPDF
56 // Authors: Nicola Asuni, Olivier Plathey, Steven Wittens
62 // 09044 Quartucciu (CA)
66 //============================================================+
69 * Utility to generate font definition files fot TCPDF.
70 * @author Nicola Asuni, Olivier Plathey, Steven Wittens
71 * @copyright 2004-2009 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
72 * @package com.tecnick.tcpdf
73 * @link http://www.tcpdf.org
74 * @license http://www.gnu.org/copyleft/lesser.html LGPL
79 * @param string $fontfile path to font file (TTF, OTF or PFB).
80 * @param string $fmfile font metrics file (UFM or AFM).
81 * @param boolean $embedded Set to false to not embed the font, true otherwise (default).
82 * @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.
83 * @param array $patch Optional modification of the encoding
85 function MakeFont($fontfile, $fmfile, $embedded=true, $enc='cp1252', $patch=array()/* BEGIN SUGARCRM SPECIFIC */, $cidInfo=""/* END SUGARCRM SPECIFIC */) {
86 //Generate a font definition file
87 set_magic_quotes_runtime(0);
88 ini_set('auto_detect_line_endings', '1');
89 if (!file_exists($fontfile)) {
90 die('Error: file not found: '.$fontfile);
92 if (!file_exists($fmfile)) {
93 die('Error: file not found: '.$fmfile);
98 $dw = 0; // default width
99 $ffext = strtolower(substr($fontfile, -3));
100 $fmext = strtolower(substr($fmfile, -3));
101 if ($fmext == 'afm') {
102 if (($ffext == 'ttf') OR ($ffext == 'otf')) {
104 } elseif ($ffext == 'pfb') {
107 die('Error: unrecognized font file extension: '.$ffext);
110 $map = ReadMap($enc);
111 foreach ($patch as $cc => $gn) {
115 $fm = ReadAFM($fmfile, $map);
116 if (isset($widths['.notdef'])) {
117 $dw = $widths['.notdef'];
120 $diff = MakeFontEncoding($map);
122 $fd = MakeFontDescriptor($fm, empty($map));
123 } elseif ($fmext == 'ufm') {
125 if (($ffext == 'ttf') OR ($ffext == 'otf')) {
126 $type = 'TrueTypeUnicode';
128 die('Error: not a TrueType font: '.$ffext);
130 $fm = ReadUFM($fmfile, $cidtogidmap);
131 $dw = $fm['MissingWidth'];
132 $fd = MakeFontDescriptor($fm, false);
139 Modification information for LGPL compliance
141 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
143 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
145 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
147 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
149 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
151 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
153 r47930 - 2009-06-02 16:21:39 -0700 (Tue, 02 Jun 2009) - jenny - Updating with changes from bsoufflet.
159 // BEGIN SUGARCRM SPECIFIC
161 // END SUGARCRM SPECIFIC
162 $s .= '$type=\''.$type."';\n";
163 // BEGIN SUGARCRM SPECIFIC
165 $s .= '$type=\''."cidfont0';\n";
167 // END SUGARCRM SPECIFIC
168 $s .= '$name=\''.$fm['FontName']."';\n";
169 $s .= '$desc='.$fd.";\n";
170 if (!isset($fm['UnderlinePosition'])) {
171 $fm['UnderlinePosition'] = -100;
173 if (!isset($fm['UnderlineThickness'])) {
174 $fm['UnderlineThickness'] = 50;
176 $s .= '$up='.$fm['UnderlinePosition'].";\n";
177 $s .= '$ut='.$fm['UnderlineThickness'].";\n";
179 if (isset($fm['Widths'][32]) AND ($fm['Widths'][32] > 0)) {
180 // assign default space width
181 $dw = $fm['Widths'][32];
186 // BEGIN SUGARCRM SPECIFIC
188 // END SUGARCRM SPECIFIC
189 $s .= '$dw='.$dw.";\n";
190 // BEGIN SUGARCRM SPECIFIC
192 $s .= '$dw='."1000;\n";
194 // END SUGARCRM SPECIFIC
195 $w = MakeWidthArray($fm);
196 $s .= '$cw='.$w.";\n";
197 // BEGIN SUGARCRM SPECIFIC
199 // END SUGARCRM SPECIFIC
200 $s .= '$enc=\''.$enc."';\n";
201 // BEGIN SUGARCRM SPECIFIC
203 // END SUGARCRM SPECIFIC
204 $s .= '$diff=\''.$diff."';\n";
205 $basename = substr(basename($fmfile), 0, -4);
206 // BEGIN SUGARCRM SPECIFIC
207 $dirname = dirname($fmfile);
208 // END SUGARCRM SPECIFIC
211 if (($type == 'TrueType') OR ($type == 'TrueTypeUnicode')) {
214 $f = fopen($fontfile,'rb');
216 die('Error: Unable to open '.$fontfile);
218 $file = stream_get_contents($f);
220 if ($type == 'Type1') {
221 //Find first two sections and discard third one
222 $header = (ord($file{0}) == 128);
224 //Strip first binary header
225 $file = substr($file, 6);
227 $pos = strpos($file, 'eexec');
229 die('Error: font file does not seem to be valid Type1');
232 if ($header AND (ord($file{$size1}) == 128)) {
233 //Strip second binary header
234 $file = substr($file, 0, $size1).substr($file, $size1+6);
236 $pos = strpos($file, '00000000');
238 die('Error: font file does not seem to be valid Type1');
240 $size2 = $pos - $size1;
241 $file = substr($file, 0, ($size1 + $size2));
243 $basename = strtolower($basename);
244 if (function_exists('gzcompress')) {
245 $cmp = $basename.'.z';
246 // BEGIN SUGARCRM SPECIFIC
248 // END SUGARCRM SPECIFIC
249 SaveToFile($cmp, gzcompress($file, 9), 'b');
250 // BEGIN SUGARCRM SPECIFIC
252 SaveToFile($dirname."/".$cmp, gzcompress($file, 9), 'b');
253 // END SUGARCRM SPECIFIC
254 $s .= '$file=\''.$cmp."';\n";
255 print "Font file compressed (".$cmp.")\n";
256 if (!empty($cidtogidmap)) {
257 $cmp = $basename.'.ctg.z';
258 // BEGIN SUGARCRM SPECIFIC
260 // END SUGARCRM SPECIFIC
261 SaveToFile($cmp, gzcompress($cidtogidmap, 9), 'b');
262 // BEGIN SUGARCRM SPECIFIC
264 SaveToFile($dirname."/".$cmp, gzcompress($cidtogidmap, 9), 'b');
265 // END SUGARCRM SPECIFIC
266 print "CIDToGIDMap created and compressed (".$cmp.")\n";
267 $s .= '$ctg=\''.$cmp."';\n";
270 $s .= '$file=\''.basename($fontfile)."';\n";
271 print "Notice: font file could not be compressed (zlib extension not available)\n";
272 if (!empty($cidtogidmap)) {
273 $cmp = $basename.'.ctg';
274 // BEGIN SUGARCRM SPECIFIC
276 // END SUGARCRM SPECIFIC
277 $f = fopen($cmp, 'wb');
278 // BEGIN SUGARCRM SPECIFIC
280 $f = fopen($dirname."/".$cmp, 'wb');
281 // END SUGARCRM SPECIFIC
282 fwrite($f, $cidtogidmap);
284 print "CIDToGIDMap created (".$cmp.")\n";
285 $s .= '$ctg=\''.$cmp."';\n";
288 if($type == 'Type1') {
289 $s .= '$size1='.$size1.";\n";
290 $s .= '$size2='.$size2.";\n";
292 $s.='$originalsize='.filesize($fontfile).";\n";
296 // BEGIN SUGARCRM SPECIFIC
298 // END SUGARCRM SPECIFIC
299 $s .= '$file='."'';\n";
300 // BEGIN SUGARCRM SPECIFIC
303 // END SUGARCRM SPECIFIC
306 // BEGIN SUGARCRM SPECIFIC
308 // END SUGARCRM SPECIFIC
309 SaveToFile($basename.'.php',$s);
310 // BEGIN SUGARCRM SPECIFIC
312 SaveToFile($dirname."/".$basename.'.php',$s);
313 // END SUGARCRM SPECIFIC
314 print "Font definition file generated (".$basename.".php)\n";
315 // BEGIN SUGARCRM SPECIFIC
316 return $dirname."/".$basename;
317 // END SUGARCRM SPECIFIC
321 * Read the specified encoding map.
322 * @param string $enc map name (see /enc/ folder for valid names).
324 function ReadMap($enc) {
326 $file = dirname(__FILE__).'/enc/'.strtolower($enc).'.map';
329 die('Error: encoding not found: '.$enc);
334 $e = preg_split('/[ \\t]+/',rtrim($l));
335 $cc = hexdec(substr($e[0],1));
340 for($i = 0; $i <= 255; $i++) {
341 if(!isset($cc2gn[$i])) {
342 $cc2gn[$i] = '.notdef';
351 function ReadUFM($file, &$cidtogidmap) {
352 //Prepare empty CIDToGIDMap
353 $cidtogidmap = str_pad('', (256 * 256 * 2), "\x00");
354 //Read a font metric file
357 die('File not found');
362 $e = explode(' ',chop($l));
369 // U 827 ; WX 0 ; N squaresubnosp ; G 675 ;
377 if($cc == ord('X')) {
378 $fm['CapXHeight'] = $e[13];
381 if (($cc >= 0) AND ($cc < 0xFFFF) AND $glyph) {
382 $cidtogidmap{($cc * 2)} = chr($glyph >> 8);
383 $cidtogidmap{(($cc * 2) + 1)} = chr($glyph & 0xFF);
386 if(($gn == '.notdef') AND (!isset($fm['MissingWidth']))) {
387 $fm['MissingWidth'] = $w;
389 } elseif($code == 'FontName') {
390 $fm['FontName'] = $param;
391 } elseif($code == 'Weight') {
392 $fm['Weight'] = $param;
393 } elseif($code == 'ItalicAngle') {
394 $fm['ItalicAngle'] = (double)$param;
395 } elseif($code == 'Ascender') {
396 $fm['Ascender'] = (int)$param;
397 } elseif($code == 'Descender') {
398 $fm['Descender'] = (int)$param;
399 } elseif($code == 'UnderlineThickness') {
400 $fm['UnderlineThickness'] = (int)$param;
401 } elseif($code == 'UnderlinePosition') {
402 $fm['UnderlinePosition'] = (int)$param;
403 } elseif($code == 'IsFixedPitch') {
404 $fm['IsFixedPitch'] = ($param == 'true');
405 } elseif($code == 'FontBBox') {
406 $fm['FontBBox'] = array($e[1], $e[2], $e[3], $e[4]);
407 } elseif($code == 'CapHeight') {
408 $fm['CapHeight'] = (int)$param;
409 } elseif($code == 'StdVW') {
410 $fm['StdVW'] = (int)$param;
413 if(!isset($fm['MissingWidth'])) {
414 $fm['MissingWidth'] = 600;
416 if(!isset($fm['FontName'])) {
417 die('FontName not found');
419 $fm['Widths'] = $widths;
426 function ReadAFM($file,&$map) {
427 //Read a font metric file
430 die('File not found');
435 'Edot'=>'Edotaccent',
436 'edot'=>'edotaccent',
437 'Idot'=>'Idotaccent',
438 'Zdot'=>'Zdotaccent',
439 'zdot'=>'zdotaccent',
440 'Odblacute' => 'Ohungarumlaut',
441 'odblacute' => 'ohungarumlaut',
442 'Udblacute'=>'Uhungarumlaut',
443 'udblacute'=>'uhungarumlaut',
444 'Gcedilla'=>'Gcommaaccent'
445 ,'gcedilla'=>'gcommaaccent',
446 'Kcedilla'=>'Kcommaaccent',
447 'kcedilla'=>'kcommaaccent',
448 'Lcedilla'=>'Lcommaaccent',
449 'lcedilla'=>'lcommaaccent',
450 'Ncedilla'=>'Ncommaaccent',
451 'ncedilla'=>'ncommaaccent',
452 'Rcedilla'=>'Rcommaaccent',
453 'rcedilla'=>'rcommaaccent',
454 'Scedilla'=>'Scommaaccent',
455 'scedilla'=>'scommaaccent',
456 'Tcedilla'=>'Tcommaaccent',
457 'tcedilla'=>'tcommaaccent',
462 'combininggraveaccent'=>'gravecomb',
463 'combininghookabove'=>'hookabovecomb',
464 'combiningtildeaccent'=>'tildecomb',
465 'combiningacuteaccent'=>'acutecomb',
466 'combiningdotbelow'=>'dotbelowcomb',
470 $e = explode(' ', rtrim($l));
481 if (substr($gn, -4) == '20AC') {
484 if (isset($fix[$gn])) {
485 //Fix incorrect glyph name
486 foreach ($map as $c => $n) {
487 if ($n == $fix[$gn]) {
493 //Symbolic font: use built-in encoding
498 $fm['CapXHeight'] = $e[13];
501 if($gn == '.notdef') {
502 $fm['MissingWidth'] = $w;
504 } elseif($code == 'FontName') {
505 $fm['FontName'] = $param;
506 } elseif($code == 'Weight') {
507 $fm['Weight'] = $param;
508 } elseif($code == 'ItalicAngle') {
509 $fm['ItalicAngle'] = (double)$param;
510 } elseif($code == 'Ascender') {
511 $fm['Ascender'] = (int)$param;
512 } elseif($code == 'Descender') {
513 $fm['Descender'] = (int)$param;
514 } elseif($code == 'UnderlineThickness') {
515 $fm['UnderlineThickness'] = (int)$param;
516 } elseif($code == 'UnderlinePosition') {
517 $fm['UnderlinePosition'] = (int)$param;
518 } elseif($code == 'IsFixedPitch') {
519 $fm['IsFixedPitch'] = ($param == 'true');
520 } elseif($code == 'FontBBox') {
521 $fm['FontBBox'] = array($e[1], $e[2], $e[3], $e[4]);
522 } elseif($code == 'CapHeight') {
523 $fm['CapHeight'] = (int)$param;
524 } elseif($code == 'StdVW') {
525 $fm['StdVW'] = (int)$param;
528 if (!isset($fm['FontName'])) {
529 die('FontName not found');
532 if (!isset($widths['.notdef'])) {
533 $widths['.notdef'] = 600;
535 if (!isset($widths['Delta']) AND isset($widths['increment'])) {
536 $widths['Delta'] = $widths['increment'];
538 //Order widths according to map
539 for ($i = 0; $i <= 255; $i++) {
540 if (!isset($widths[$map[$i]])) {
541 print "Warning: character ".$map[$i]." is missing\n";
542 $widths[$i] = $widths['.notdef'];
544 $widths[$i] = $widths[$map[$i]];
548 $fm['Widths'] = $widths;
552 function MakeFontDescriptor($fm, $symbolic=false) {
554 $asc = (isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
555 $fd = "array('Ascent'=>".$asc;
557 $desc = (isset($fm['Descender']) ? $fm['Descender'] : -200);
558 $fd .= ",'Descent'=>".$desc;
560 if (isset($fm['CapHeight'])) {
561 $ch = $fm['CapHeight'];
562 } elseif (isset($fm['CapXHeight'])) {
563 $ch = $fm['CapXHeight'];
567 $fd .= ",'CapHeight'=>".$ch;
570 if (isset($fm['IsFixedPitch']) AND $fm['IsFixedPitch']) {
578 if (isset($fm['ItalicAngle']) AND ($fm['ItalicAngle'] != 0)) {
581 $fd .= ",'Flags'=>".$flags;
583 if (isset($fm['FontBBox'])) {
584 $fbb = $fm['FontBBox'];
586 $fbb = array(0, ($desc - 100), 1000, ($asc + 100));
588 $fd .= ",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
590 $ia = (isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
591 $fd .= ",'ItalicAngle'=>".$ia;
593 if (isset($fm['StdVW'])) {
594 $stemv = $fm['StdVW'];
595 } elseif (isset($fm['Weight']) and eregi('(bold|black)', $fm['Weight'])) {
600 $fd .= ",'StemV'=>".$stemv;
602 if(isset($fm['MissingWidth'])) {
603 $fd .= ",'MissingWidth'=>".$fm['MissingWidth'];
609 function MakeWidthArray($fm) {
610 //Make character width array
615 foreach ($cw as $i => $w) {
616 if (is_numeric($i)) {
617 $els[] = (((($c++)%10) == 0) ? "\n" : '').$i.'=>'.$w;
620 $s .= implode(',', $els);
625 function MakeFontEncoding($map) {
626 //Build differences from reference encoding
627 $ref = ReadMap('cp1252');
630 for ($i = 32; $i <= 255; $i++) {
631 if ($map[$i] != $ref[$i]) {
636 $s .= '/'.$map[$i].' ';
642 function SaveToFile($file, $s, $mode='t') {
643 $f = fopen($file, 'w'.$mode);
645 die('Can\'t write to file '.$file);
647 fwrite($f, $s, strlen($s));
651 function ReadShort($f) {
652 $a = unpack('n1n', fread($f, 2));
656 function ReadLong($f) {
657 $a = unpack('N1N', fread($f, 4));
661 function CheckTTF($file) {
662 //Check if font license allows embedding
663 $f = fopen($file, 'rb');
665 die('Error: unable to open '.$file);
667 //Extract number of tables
668 fseek($f, 4, SEEK_CUR);
670 fseek($f, 6, SEEK_CUR);
673 for ($i = 0; $i < $nb; $i++) {
674 if (fread($f, 4) == 'OS/2') {
678 fseek($f, 12, SEEK_CUR);
684 fseek($f, 4, SEEK_CUR);
685 $offset = ReadLong($f);
686 fseek($f, $offset, SEEK_SET);
687 //Extract fsType flags
688 fseek($f, 8, SEEK_CUR);
689 $fsType = ReadShort($f);
690 $rl = ($fsType & 0x02) != 0;
691 $pp = ($fsType & 0x04) != 0;
692 $e = ($fsType & 0x08) != 0;
694 if($rl AND (!$pp) AND (!$e)) {
695 print "Warning: font license does not allow embedding\n";
698 // BEGIN SUGARCRM SPECIFIC
700 // END SUGARCRM SPECIFIC
702 $arg = $GLOBALS['argv'];
703 if (count($arg) >= 3) {
706 if (sizeof($arg) == 3) {
710 if (!isset($arg[2])) {
713 if (!isset($arg[3])) {
717 if (!isset($arg[4])) {
720 MakeFont($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);
722 print preg_replace('!<BR( /)?>!i', "\n", $t);
724 print "Usage: makefont.php <ttf/otf/pfb file> <afm/ufm file> <encoding> <patch>\n";
727 // BEGIN SUGARCRM SPECIFIC
729 // END SUGARCRM SPECIFIC