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