[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 //============================================================+ 3 // File name : makefont.php 4 // Begin : 2004-12-31 5 // Last Update : 2008-11-24 6 // Version : 1.2.002 7 // License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html) 8 // ---------------------------------------------------------------------------- 9 // Copyright (C) 2008 Nicola Asuni - Tecnick.com S.r.l. 10 // 11 // This program is free software: you can redistribute it and/or modify 12 // it under the terms of the GNU Lesser General Public License as published by 13 // the Free Software Foundation, either version 2.1 of the License, or 14 // (at your option) any later version. 15 // 16 // This program is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU Lesser General Public License for more details. 20 // 21 // You should have received a copy of the GNU Lesser General Public License 22 // along with this program. If not, see <http://www.gnu.org/licenses/>. 23 // 24 // See LICENSE.TXT file for more information. 25 // ---------------------------------------------------------------------------- 26 // 27 // Description : Utility to generate font definition files fot TCPDF 28 // 29 // Author: Nicola Asuni, Olivier Plathey, Steven Wittens 30 // 31 // (c) Copyright: 32 // Nicola Asuni 33 // Tecnick.com S.r.l. 34 // Via della Pace, 11 35 // 09044 Quartucciu (CA) 36 // ITALY 37 // www.tecnick.com 38 // [email protected] 39 //============================================================+ 40 41 /** 42 * Utility to generate font definition files fot TCPDF. 43 * @author Nicola Asuni, Olivier Plathey, Steven Wittens 44 * @copyright 2004-2008 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - [email protected] 45 * @package com.tecnick.tcpdf 46 * @link http://www.tcpdf.org 47 * @license http://www.gnu.org/copyleft/lesser.html LGPL 48 */ 49 50 /** 51 * 52 * @param string $fontfile path to font file (TTF, OTF or PFB). 53 * @param string $fmfile font metrics file (UFM or AFM). 54 * @param boolean $embedded Set to false to not embed the font, true otherwise (default). 55 * @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. 56 * @param array $patch Optional modification of the encoding 57 */ 58 function MakeFont($fontfile, $fmfile, $embedded=true, $enc="cp1252", $patch=array()) { 59 //Generate a font definition file 60 set_magic_quotes_runtime(0); 61 ini_set('auto_detect_line_endings','1'); 62 if (!file_exists($fontfile)) { 63 die('Error: file not found: '.$fontfile); 64 } 65 if (!file_exists($fmfile)) { 66 die('Error: file not found: '.$fmfile); 67 } 68 $cidtogidmap = ''; 69 $map = array(); 70 $diff=''; 71 $ffext = strtolower(substr($fontfile,-3)); 72 $fmext = strtolower(substr($fmfile,-3)); 73 if ($fmext == 'afm') { 74 if (($ffext == 'ttf') OR ($ffext == 'otf')) { 75 $type = 'TrueType'; 76 } elseif ($ffext == 'pfb') { 77 $type = 'Type1'; 78 } else { 79 die('Error: unrecognized font file extension: '.$ffext); 80 } 81 if ($enc) { 82 $map = ReadMap($enc); 83 foreach ($patch as $cc => $gn) { 84 $map[$cc] = $gn; 85 } 86 } 87 $fm = ReadAFM($fmfile, $map); 88 if ($enc) { 89 $diff = MakeFontEncoding($map); 90 } 91 $fd = MakeFontDescriptor($fm, empty($map)); 92 } elseif ($fmext == 'ufm') { 93 $enc = ""; 94 if (($ffext == 'ttf') OR ($ffext == 'otf')) { 95 $type = 'TrueTypeUnicode'; 96 } else { 97 die('Error: not a TrueType font: '.$ffext); 98 } 99 $fm = ReadUFM($fmfile, $cidtogidmap); 100 $fd = MakeFontDescriptor($fm, false); 101 } 102 103 //Start generation 104 $s = '<?php'."\n"; 105 $s .= '$type=\''.$type."';\n"; 106 $s .= '$name=\''.$fm['FontName']."';\n"; 107 $s .= '$desc='.$fd.";\n"; 108 if (!isset($fm['UnderlinePosition'])) { 109 $fm['UnderlinePosition'] = -100; 110 } 111 if (!isset($fm['UnderlineThickness'])) { 112 $fm['UnderlineThickness'] = 50; 113 } 114 $s .= '$up='.$fm['UnderlinePosition'].";\n"; 115 $s .= '$ut='.$fm['UnderlineThickness'].";\n"; 116 $w = MakeWidthArray($fm); 117 $s .= '$cw='.$w.";\n"; 118 $s .= '$enc=\''.$enc."';\n"; 119 $s .= '$diff=\''.$diff."';\n"; 120 $basename = substr(basename($fmfile),0,-4); 121 if ($embedded) { 122 //Embedded font 123 if (($type == 'TrueType') OR ($type == 'TrueTypeUnicode')) { 124 CheckTTF($fontfile); 125 } 126 $f = fopen($fontfile,'rb'); 127 if (!$f) { 128 die('Error: Unable to open '.$fontfile); 129 } 130 $file = fread($f,filesize($fontfile)); 131 fclose($f); 132 if ($type == 'Type1') { 133 //Find first two sections and discard third one 134 $header = (ord($file{0}) == 128); 135 if ($header) { 136 //Strip first binary header 137 $file = substr($file, 6); 138 } 139 $pos = strpos($file, 'eexec'); 140 if (!$pos) { 141 die('Error: font file does not seem to be valid Type1'); 142 } 143 $size1 = $pos+6; 144 if ($header AND (ord($file{$size1}) == 128)) { 145 //Strip second binary header 146 $file = substr($file, 0, $size1).substr($file, $size1+6); 147 } 148 $pos = strpos($file, '00000000'); 149 if (!$pos) { 150 die('Error: font file does not seem to be valid Type1'); 151 } 152 $size2 = $pos - $size1; 153 $file = substr($file, 0, $size1+$size2); 154 } 155 if (function_exists('gzcompress')) { 156 $cmp = $basename.'.z'; 157 SaveToFile($cmp, gzcompress($file), 'b'); 158 $s .= '$file=\''.$cmp."';\n"; 159 print "Font file compressed (".$cmp.")\n"; 160 if (!empty($cidtogidmap)) { 161 $cmp = $basename.'.ctg.z'; 162 SaveToFile($cmp, gzcompress($cidtogidmap), 'b'); 163 print "CIDToGIDMap created and compressed (".$cmp.")\n"; 164 $s .= '$ctg=\''.$cmp."';\n"; 165 } 166 } else { 167 $s .= '$file=\''.basename($fontfile)."';\n"; 168 print "Notice: font file could not be compressed (zlib extension not available)\n"; 169 if (!empty($cidtogidmap)) { 170 $cmp = $basename.'.ctg'; 171 $f = fopen($cmp, 'wb'); 172 fwrite($f, $cidtogidmap); 173 fclose($f); 174 print "CIDToGIDMap created (".$cmp.")\n"; 175 $s .= '$ctg=\''.$cmp."';\n"; 176 } 177 } 178 if($type == 'Type1') { 179 $s .= '$size1='.$size1.";\n"; 180 $s .= '$size2='.$size2.";\n"; 181 } else { 182 $s.='$originalsize='.filesize($fontfile).";\n"; 183 } 184 } else { 185 //Not embedded font 186 $s .= '$file='."'';\n"; 187 } 188 $s .= "?>"; 189 SaveToFile($basename.'.php',$s); 190 print "Font definition file generated (".$basename.".php)\n"; 191 } 192 193 /** 194 * Read the specified encoding map. 195 * @param string $enc map name (see /enc/ folder for valid names). 196 */ 197 function ReadMap($enc) { 198 //Read a map file 199 $file = dirname(__FILE__).'/enc/'.strtolower($enc).'.map'; 200 $a = file($file); 201 if (empty($a)) { 202 die('Error: encoding not found: '.$enc); 203 } 204 $cc2gn = array(); 205 foreach ($a as $l) { 206 if ($l{0} == '!') { 207 $e = preg_split('/[ \\t]+/',rtrim($l)); 208 $cc = hexdec(substr($e[0],1)); 209 $gn = $e[2]; 210 $cc2gn[$cc] = $gn; 211 } 212 } 213 for($i=0; $i <= 255; $i++) { 214 if(!isset($cc2gn[$i])) { 215 $cc2gn[$i] = '.notdef'; 216 } 217 } 218 return $cc2gn; 219 } 220 221 /** 222 * Read UFM file 223 */ 224 function ReadUFM($file, &$cidtogidmap) { 225 //Prepare empty CIDToGIDMap 226 $cidtogidmap = str_pad('', 256*256*2, "\x00"); 227 //Read a font metric file 228 $a = file($file); 229 if (empty($a)) { 230 die('File not found'); 231 } 232 $widths = array(); 233 $fm = array(); 234 foreach($a as $l) { 235 $e = explode(' ',chop($l)); 236 if(count($e) < 2) { 237 continue; 238 } 239 $code = $e[0]; 240 $param = $e[1]; 241 if($code == 'U') { 242 // U 827 ; WX 0 ; N squaresubnosp ; G 675 ; 243 //Character metrics 244 $cc = (int)$e[1]; 245 if ($cc != -1) { 246 $gn = $e[7]; 247 $w = $e[4]; 248 $glyph = $e[10]; 249 $widths[$cc] = $w; 250 if($cc == ord('X')) { 251 $fm['CapXHeight'] = $e[13]; 252 } 253 // Set GID 254 if ($cc >= 0 && $cc < 0xFFFF && $glyph) { 255 $cidtogidmap{$cc*2} = chr($glyph >> 8); 256 $cidtogidmap{$cc*2 + 1} = chr($glyph & 0xFF); 257 } 258 } 259 if(($gn == '.notdef') AND (!isset($fm['MissingWidth']))) { 260 $fm['MissingWidth'] = $w; 261 } 262 } elseif($code=='FontName') { 263 $fm['FontName']=$param; 264 } elseif($code=='Weight') { 265 $fm['Weight']=$param; 266 } elseif($code=='ItalicAngle') { 267 $fm['ItalicAngle']=(double)$param; 268 } elseif($code=='Ascender') { 269 $fm['Ascender']=(int)$param; 270 } elseif($code=='Descender') { 271 $fm['Descender']=(int)$param; 272 } elseif($code=='UnderlineThickness') { 273 $fm['UnderlineThickness']=(int)$param; 274 } elseif($code=='UnderlinePosition') { 275 $fm['UnderlinePosition']=(int)$param; 276 } elseif($code=='IsFixedPitch') { 277 $fm['IsFixedPitch']=($param=='true'); 278 } elseif($code=='FontBBox') { 279 $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]); 280 } elseif($code=='CapHeight') { 281 $fm['CapHeight']=(int)$param; 282 } elseif($code=='StdVW') { 283 $fm['StdVW']=(int)$param; 284 } 285 } 286 if(!isset($fm['MissingWidth'])) { 287 $fm['MissingWidth'] = 600; 288 } 289 if(!isset($fm['FontName'])) { 290 die('FontName not found'); 291 } 292 $fm['Widths'] = $widths; 293 return $fm; 294 } 295 296 /** 297 * Read AFM file 298 */ 299 function ReadAFM($file,&$map) { 300 //Read a font metric file 301 $a = file($file); 302 if(empty($a)) { 303 die('File not found'); 304 } 305 $widths = array(); 306 $fm = array(); 307 $fix = array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent', 308 'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut', 309 'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent', 310 'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent', 311 'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent', 312 'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat', 313 'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb', 314 'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong'); 315 foreach($a as $l) { 316 $e = explode(' ',rtrim($l)); 317 if (count($e) < 2) { 318 continue; 319 } 320 $code = $e[0]; 321 $param = $e[1]; 322 if ($code == 'C') { 323 //Character metrics 324 $cc = (int)$e[1]; 325 $w = $e[4]; 326 $gn = $e[7]; 327 if(substr($gn,-4) == '20AC') { 328 $gn = 'Euro'; 329 } 330 if (isset($fix[$gn])) { 331 //Fix incorrect glyph name 332 foreach ($map as $c => $n) { 333 if ($n == $fix[$gn]) { 334 $map[$c] = $gn; 335 } 336 } 337 } 338 if (empty($map)) { 339 //Symbolic font: use built-in encoding 340 $widths[$cc] = $w; 341 } else { 342 $widths[$gn] = $w; 343 if($gn == 'X') { 344 $fm['CapXHeight'] = $e[13]; 345 } 346 } 347 if($gn == '.notdef') { 348 $fm['MissingWidth'] = $w; 349 } 350 } elseif($code=='FontName') { 351 $fm['FontName']=$param; 352 } elseif($code=='Weight') { 353 $fm['Weight']=$param; 354 } elseif($code=='ItalicAngle') { 355 $fm['ItalicAngle']=(double)$param; 356 } elseif($code=='Ascender') { 357 $fm['Ascender']=(int)$param; 358 } elseif($code=='Descender') { 359 $fm['Descender']=(int)$param; 360 } elseif($code=='UnderlineThickness') { 361 $fm['UnderlineThickness']=(int)$param; 362 } elseif($code=='UnderlinePosition') { 363 $fm['UnderlinePosition']=(int)$param; 364 } elseif($code=='IsFixedPitch') { 365 $fm['IsFixedPitch']=($param=='true'); 366 } elseif($code=='FontBBox') { 367 $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]); 368 } elseif($code=='CapHeight') { 369 $fm['CapHeight']=(int)$param; 370 } elseif($code=='StdVW') { 371 $fm['StdVW']=(int)$param; 372 } 373 } 374 if (!isset($fm['FontName'])) { 375 die('FontName not found'); 376 } 377 if (!empty($map)) { 378 if (!isset($widths['.notdef'])) { 379 $widths['.notdef'] = 600; 380 } 381 if (!isset($widths['Delta']) AND isset($widths['increment'])) { 382 $widths['Delta']=$widths['increment']; 383 } 384 //Order widths according to map 385 for ($i=0; $i <= 255; $i++) { 386 if (!isset($widths[$map[$i]])) { 387 print "Warning: character ".$map[$i]." is missing\n"; 388 $widths[$i] = $widths['.notdef']; 389 } else { 390 $widths[$i] = $widths[$map[$i]]; 391 } 392 } 393 } 394 $fm['Widths'] = $widths; 395 return $fm; 396 } 397 398 function MakeFontDescriptor($fm, $symbolic = false) { 399 //Ascent 400 $asc = (isset($fm['Ascender']) ? $fm['Ascender'] : 1000); 401 $fd = "array('Ascent'=>".$asc; 402 //Descent 403 $desc = (isset($fm['Descender']) ? $fm['Descender'] : -200); 404 $fd .= ",'Descent'=>".$desc; 405 //CapHeight 406 if (isset($fm['CapHeight'])) { 407 $ch=$fm['CapHeight']; 408 } elseif (isset($fm['CapXHeight'])) { 409 $ch=$fm['CapXHeight']; 410 } else { 411 $ch = $asc; 412 } 413 $fd .= ",'CapHeight'=>".$ch; 414 //Flags 415 $flags = 0; 416 if (isset($fm['IsFixedPitch']) AND $fm['IsFixedPitch']) { 417 $flags += 1<<0; 418 } 419 if ($symbolic) { 420 $flags += 1<<2; 421 } else { 422 $flags += 1<<5; 423 } 424 if (isset($fm['ItalicAngle']) AND ($fm['ItalicAngle'] != 0)) { 425 $flags += 1<<6; 426 } 427 $fd .= ",'Flags'=>".$flags; 428 //FontBBox 429 if (isset($fm['FontBBox'])) { 430 $fbb = $fm['FontBBox']; 431 } else { 432 $fbb = array(0, $desc-100, 1000, $asc+100); 433 } 434 $fd .= ",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'"; 435 //ItalicAngle 436 $ia = (isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0); 437 $fd .= ",'ItalicAngle'=>".$ia; 438 //StemV 439 if (isset($fm['StdVW'])) { 440 $stemv = $fm['StdVW']; 441 } elseif (isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight'])) { 442 $stemv=120; 443 } else { 444 $stemv = 70; 445 } 446 $fd .= ",'StemV'=>".$stemv; 447 //MissingWidth 448 if(isset($fm['MissingWidth'])) { 449 $fd .= ",'MissingWidth'=>".$fm['MissingWidth']; 450 } 451 $fd .= ')'; 452 return $fd; 453 } 454 455 function MakeWidthArray($fm) { 456 //Make character width array 457 $s = "array("; 458 $cw = $fm['Widths']; 459 $els = array(); 460 $c = 0; 461 foreach ($cw as $i => $w) { 462 if (is_numeric($i)) { 463 $els[] = $i.'=>'.$w; 464 } 465 } 466 $s .= implode(',', $els); 467 $s .= ')'; 468 return $s; 469 } 470 471 function MakeFontEncoding($map) { 472 //Build differences from reference encoding 473 $ref = ReadMap('cp1252'); 474 $s = ''; 475 $last = 0; 476 for ($i=32; $i <= 255; $i++) { 477 if ($map[$i] != $ref[$i]) { 478 if ($i != $last+1) { 479 $s .= $i.' '; 480 } 481 $last = $i; 482 $s .= '/'.$map[$i].' '; 483 } 484 } 485 return rtrim($s); 486 } 487 488 function SaveToFile($file, $s, $mode='t') { 489 $f = fopen($file, 'w'.$mode); 490 if(!$f) { 491 die('Can\'t write to file '.$file); 492 } 493 fwrite($f, $s, strlen($s)); 494 fclose($f); 495 } 496 497 function ReadShort($f) { 498 $a = unpack('n1n',fread($f,2)); 499 return $a['n']; 500 } 501 502 function ReadLong($f) { 503 $a = unpack('N1N',fread($f,4)); 504 return $a['N']; 505 } 506 507 function CheckTTF($file) { 508 //Check if font license allows embedding 509 $f = fopen($file,'rb'); 510 if(!$f) { 511 die('Error: unable to open '.$file); 512 } 513 //Extract number of tables 514 fseek($f, 4, SEEK_CUR); 515 $nb = ReadShort($f); 516 fseek($f, 6, SEEK_CUR); 517 //Seek OS/2 table 518 $found = false; 519 for ($i=0; $i < $nb; $i++) { 520 if (fread($f,4)=='OS/2') { 521 $found = true; 522 break; 523 } 524 fseek($f, 12, SEEK_CUR); 525 } 526 if(!$found) { 527 fclose($f); 528 return; 529 } 530 fseek($f, 4, SEEK_CUR); 531 $offset = ReadLong($f); 532 fseek($f, $offset, SEEK_SET); 533 //Extract fsType flags 534 fseek($f, 8, SEEK_CUR); 535 $fsType = ReadShort($f); 536 $rl = ($fsType & 0x02)!=0; 537 $pp = ($fsType & 0x04)!=0; 538 $e = ($fsType & 0x08)!=0; 539 fclose($f); 540 if($rl AND (!$pp) AND (!$e)) { 541 print "Warning: font license does not allow embedding\n"; 542 } 543 } 544 545 $arg = $GLOBALS['argv']; 546 if (count($arg) >= 3) { 547 ob_start(); 548 array_shift($arg); 549 if (!isset($arg[2])) { 550 $arg[2] = true; 551 } 552 if (!isset($arg[3])) { 553 $arg[3] = 'cp1252'; 554 } 555 if (!isset($arg[4])) { 556 $arg[4] = array(); 557 } 558 MakeFont($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]); 559 $t = ob_get_clean(); 560 print preg_replace('!<BR( /)?>!i', "\n", $t); 561 } else { 562 print "Usage: makefont.php <ttf/otf/pfb file> <afm/ufm file> <encoding> <patch>\n"; 563 } 564 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |