PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/fpdf/font/makefont/makefont.php

https://github.com/nadavkav/MoodleTAO
PHP | 416 lines | 366 code | 10 blank | 40 comment | 59 complexity | e8a09b1411ffb2196d9017ccca53a036 MD5 | raw file
  1. <?php
  2. /*******************************************************************************
  3. * Utility to generate font definition files *
  4. * Version: 1.13 *
  5. * Date: 2004-12-31 *
  6. *******************************************************************************/
  7. function ReadMap($enc)
  8. {
  9. //Read a map file
  10. $file=dirname(__FILE__).'/'.strtolower($enc).'.map';
  11. $a=file($file);
  12. if(empty($a))
  13. die('<B>Error:</B> encoding not found: '.$enc);
  14. $cc2gn=array();
  15. foreach($a as $l)
  16. {
  17. if($l{0}=='!')
  18. {
  19. $e=preg_split('/[ \\t]+/',rtrim($l));
  20. $cc=hexdec(substr($e[0],1));
  21. $gn=$e[2];
  22. $cc2gn[$cc]=$gn;
  23. }
  24. }
  25. for($i=0;$i<=255;$i++)
  26. {
  27. if(!isset($cc2gn[$i]))
  28. $cc2gn[$i]='.notdef';
  29. }
  30. return $cc2gn;
  31. }
  32. function ReadAFM($file,&$map)
  33. {
  34. //Read a font metric file
  35. $a=file($file);
  36. if(empty($a))
  37. die('File not found');
  38. $widths=array();
  39. $fm=array();
  40. $fix=array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent',
  41. 'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut',
  42. 'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent',
  43. 'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent',
  44. 'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent',
  45. 'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat',
  46. 'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb',
  47. 'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong');
  48. foreach($a as $l)
  49. {
  50. $e=explode(' ',rtrim($l));
  51. if(count($e)<2)
  52. continue;
  53. $code=$e[0];
  54. $param=$e[1];
  55. if($code=='C')
  56. {
  57. //Character metrics
  58. $cc=(int)$e[1];
  59. $w=$e[4];
  60. $gn=$e[7];
  61. if(substr($gn,-4)=='20AC')
  62. $gn='Euro';
  63. if(isset($fix[$gn]))
  64. {
  65. //Fix incorrect glyph name
  66. foreach($map as $c=>$n)
  67. {
  68. if($n==$fix[$gn])
  69. $map[$c]=$gn;
  70. }
  71. }
  72. if(empty($map))
  73. {
  74. //Symbolic font: use built-in encoding
  75. $widths[$cc]=$w;
  76. }
  77. else
  78. {
  79. $widths[$gn]=$w;
  80. if($gn=='X')
  81. $fm['CapXHeight']=$e[13];
  82. }
  83. if($gn=='.notdef')
  84. $fm['MissingWidth']=$w;
  85. }
  86. elseif($code=='FontName')
  87. $fm['FontName']=$param;
  88. elseif($code=='Weight')
  89. $fm['Weight']=$param;
  90. elseif($code=='ItalicAngle')
  91. $fm['ItalicAngle']=(double)$param;
  92. elseif($code=='Ascender')
  93. $fm['Ascender']=(int)$param;
  94. elseif($code=='Descender')
  95. $fm['Descender']=(int)$param;
  96. elseif($code=='UnderlineThickness')
  97. $fm['UnderlineThickness']=(int)$param;
  98. elseif($code=='UnderlinePosition')
  99. $fm['UnderlinePosition']=(int)$param;
  100. elseif($code=='IsFixedPitch')
  101. $fm['IsFixedPitch']=($param=='true');
  102. elseif($code=='FontBBox')
  103. $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
  104. elseif($code=='CapHeight')
  105. $fm['CapHeight']=(int)$param;
  106. elseif($code=='StdVW')
  107. $fm['StdVW']=(int)$param;
  108. }
  109. if(!isset($fm['FontName']))
  110. die('FontName not found');
  111. if(!empty($map))
  112. {
  113. if(!isset($widths['.notdef']))
  114. $widths['.notdef']=600;
  115. if(!isset($widths['Delta']) and isset($widths['increment']))
  116. $widths['Delta']=$widths['increment'];
  117. //Order widths according to map
  118. for($i=0;$i<=255;$i++)
  119. {
  120. if(!isset($widths[$map[$i]]))
  121. {
  122. echo '<B>Warning:</B> character '.$map[$i].' is missing<BR>';
  123. $widths[$i]=$widths['.notdef'];
  124. }
  125. else
  126. $widths[$i]=$widths[$map[$i]];
  127. }
  128. }
  129. $fm['Widths']=$widths;
  130. return $fm;
  131. }
  132. function MakeFontDescriptor($fm,$symbolic)
  133. {
  134. //Ascent
  135. $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
  136. $fd="array('Ascent'=>".$asc;
  137. //Descent
  138. $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
  139. $fd.=",'Descent'=>".$desc;
  140. //CapHeight
  141. if(isset($fm['CapHeight']))
  142. $ch=$fm['CapHeight'];
  143. elseif(isset($fm['CapXHeight']))
  144. $ch=$fm['CapXHeight'];
  145. else
  146. $ch=$asc;
  147. $fd.=",'CapHeight'=>".$ch;
  148. //Flags
  149. $flags=0;
  150. if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
  151. $flags+=1<<0;
  152. if($symbolic)
  153. $flags+=1<<2;
  154. if(!$symbolic)
  155. $flags+=1<<5;
  156. if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
  157. $flags+=1<<6;
  158. $fd.=",'Flags'=>".$flags;
  159. //FontBBox
  160. if(isset($fm['FontBBox']))
  161. $fbb=$fm['FontBBox'];
  162. else
  163. $fbb=array(0,$des-100,1000,$asc+100);
  164. $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
  165. //ItalicAngle
  166. $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
  167. $fd.=",'ItalicAngle'=>".$ia;
  168. //StemV
  169. if(isset($fm['StdVW']))
  170. $stemv=$fm['StdVW'];
  171. elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
  172. $stemv=120;
  173. else
  174. $stemv=70;
  175. $fd.=",'StemV'=>".$stemv;
  176. //MissingWidth
  177. if(isset($fm['MissingWidth']))
  178. $fd.=",'MissingWidth'=>".$fm['MissingWidth'];
  179. $fd.=')';
  180. return $fd;
  181. }
  182. function MakeWidthArray($fm)
  183. {
  184. //Make character width array
  185. $s="array(\n\t";
  186. $cw=$fm['Widths'];
  187. for($i=0;$i<=255;$i++)
  188. {
  189. if(chr($i)=="'")
  190. $s.="'\\''";
  191. elseif(chr($i)=="\\")
  192. $s.="'\\\\'";
  193. elseif($i>=32 and $i<=126)
  194. $s.="'".chr($i)."'";
  195. else
  196. $s.="chr($i)";
  197. $s.='=>'.$fm['Widths'][$i];
  198. if($i<255)
  199. $s.=',';
  200. if(($i+1)%22==0)
  201. $s.="\n\t";
  202. }
  203. $s.=')';
  204. return $s;
  205. }
  206. function MakeFontEncoding($map)
  207. {
  208. //Build differences from reference encoding
  209. $ref=ReadMap('cp1252');
  210. $s='';
  211. $last=0;
  212. for($i=32;$i<=255;$i++)
  213. {
  214. if($map[$i]!=$ref[$i])
  215. {
  216. if($i!=$last+1)
  217. $s.=$i.' ';
  218. $last=$i;
  219. $s.='/'.$map[$i].' ';
  220. }
  221. }
  222. return rtrim($s);
  223. }
  224. function SaveToFile($file,$s,$mode='t')
  225. {
  226. $f=fopen($file,'w'.$mode);
  227. if(!$f)
  228. die('Can\'t write to file '.$file);
  229. fwrite($f,$s,strlen($s));
  230. fclose($f);
  231. }
  232. function ReadShort($f)
  233. {
  234. $a=unpack('n1n',fread($f,2));
  235. return $a['n'];
  236. }
  237. function ReadLong($f)
  238. {
  239. $a=unpack('N1N',fread($f,4));
  240. return $a['N'];
  241. }
  242. function CheckTTF($file)
  243. {
  244. //Check if font license allows embedding
  245. $f=fopen($file,'rb');
  246. if(!$f)
  247. die('<B>Error:</B> Can\'t open '.$file);
  248. //Extract number of tables
  249. fseek($f,4,SEEK_CUR);
  250. $nb=ReadShort($f);
  251. fseek($f,6,SEEK_CUR);
  252. //Seek OS/2 table
  253. $found=false;
  254. for($i=0;$i<$nb;$i++)
  255. {
  256. if(fread($f,4)=='OS/2')
  257. {
  258. $found=true;
  259. break;
  260. }
  261. fseek($f,12,SEEK_CUR);
  262. }
  263. if(!$found)
  264. {
  265. fclose($f);
  266. return;
  267. }
  268. fseek($f,4,SEEK_CUR);
  269. $offset=ReadLong($f);
  270. fseek($f,$offset,SEEK_SET);
  271. //Extract fsType flags
  272. fseek($f,8,SEEK_CUR);
  273. $fsType=ReadShort($f);
  274. $rl=($fsType & 0x02)!=0;
  275. $pp=($fsType & 0x04)!=0;
  276. $e=($fsType & 0x08)!=0;
  277. fclose($f);
  278. if($rl and !$pp and !$e)
  279. echo '<B>Warning:</B> font license does not allow embedding';
  280. }
  281. /*******************************************************************************
  282. * $fontfile : chemin du fichier TTF (ou chaîne vide si pas d'incorporation) *
  283. * $afmfile : chemin du fichier AFM *
  284. * $enc : encodage (ou chaîne vide si la police est symbolique) *
  285. * $patch : patch optionnel pour l'encodage *
  286. * $type : type de la police si $fontfile est vide *
  287. *******************************************************************************/
  288. function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=array(),$type='TrueType')
  289. {
  290. //Generate a font definition file
  291. set_magic_quotes_runtime(0);
  292. ini_set('auto_detect_line_endings','1');
  293. if($enc)
  294. {
  295. $map=ReadMap($enc);
  296. foreach($patch as $cc=>$gn)
  297. $map[$cc]=$gn;
  298. }
  299. else
  300. $map=array();
  301. if(!file_exists($afmfile))
  302. die('<B>Error:</B> AFM file not found: '.$afmfile);
  303. $fm=ReadAFM($afmfile,$map);
  304. if($enc)
  305. $diff=MakeFontEncoding($map);
  306. else
  307. $diff='';
  308. $fd=MakeFontDescriptor($fm,empty($map));
  309. //Find font type
  310. if($fontfile)
  311. {
  312. $ext=strtolower(substr($fontfile,-3));
  313. if($ext=='ttf')
  314. $type='TrueType';
  315. elseif($ext=='pfb')
  316. $type='Type1';
  317. else
  318. die('<B>Error:</B> unrecognized font file extension: '.$ext);
  319. }
  320. else
  321. {
  322. if($type!='TrueType' and $type!='Type1')
  323. die('<B>Error:</B> incorrect font type: '.$type);
  324. }
  325. //Start generation
  326. $s='<?php'."\n";
  327. $s.='$type=\''.$type."';\n";
  328. $s.='$name=\''.$fm['FontName']."';\n";
  329. $s.='$desc='.$fd.";\n";
  330. if(!isset($fm['UnderlinePosition']))
  331. $fm['UnderlinePosition']=-100;
  332. if(!isset($fm['UnderlineThickness']))
  333. $fm['UnderlineThickness']=50;
  334. $s.='$up='.$fm['UnderlinePosition'].";\n";
  335. $s.='$ut='.$fm['UnderlineThickness'].";\n";
  336. $w=MakeWidthArray($fm);
  337. $s.='$cw='.$w.";\n";
  338. $s.='$enc=\''.$enc."';\n";
  339. $s.='$diff=\''.$diff."';\n";
  340. $basename=substr(basename($afmfile),0,-4);
  341. if($fontfile)
  342. {
  343. //Embedded font
  344. if(!file_exists($fontfile))
  345. die('<B>Error:</B> font file not found: '.$fontfile);
  346. if($type=='TrueType')
  347. CheckTTF($fontfile);
  348. $f=fopen($fontfile,'rb');
  349. if(!$f)
  350. die('<B>Error:</B> Can\'t open '.$fontfile);
  351. $file=fread($f,filesize($fontfile));
  352. fclose($f);
  353. if($type=='Type1')
  354. {
  355. //Find first two sections and discard third one
  356. $header=(ord($file{0})==128);
  357. if($header)
  358. {
  359. //Strip first binary header
  360. $file=substr($file,6);
  361. }
  362. $pos=strpos($file,'eexec');
  363. if(!$pos)
  364. die('<B>Error:</B> font file does not seem to be valid Type1');
  365. $size1=$pos+6;
  366. if($header and ord($file{$size1})==128)
  367. {
  368. //Strip second binary header
  369. $file=substr($file,0,$size1).substr($file,$size1+6);
  370. }
  371. $pos=strpos($file,'00000000');
  372. if(!$pos)
  373. die('<B>Error:</B> font file does not seem to be valid Type1');
  374. $size2=$pos-$size1;
  375. $file=substr($file,0,$size1+$size2);
  376. }
  377. if(function_exists('gzcompress'))
  378. {
  379. $cmp=$basename.'.z';
  380. SaveToFile($cmp,gzcompress($file),'b');
  381. $s.='$file=\''.$cmp."';\n";
  382. echo 'Font file compressed ('.$cmp.')<BR>';
  383. }
  384. else
  385. {
  386. $s.='$file=\''.basename($fontfile)."';\n";
  387. echo '<B>Notice:</B> font file could not be compressed (zlib extension not available)<BR>';
  388. }
  389. if($type=='Type1')
  390. {
  391. $s.='$size1='.$size1.";\n";
  392. $s.='$size2='.$size2.";\n";
  393. }
  394. else
  395. $s.='$originalsize='.filesize($fontfile).";\n";
  396. }
  397. else
  398. {
  399. //Not embedded font
  400. $s.='$file='."'';\n";
  401. }
  402. $s.="?>\n";
  403. SaveToFile($basename.'.php',$s);
  404. echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
  405. }
  406. ?>