PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/public/pdfgen/font/makefont/makefont.php

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