source: trunk/client/inc/hpdf/_fpdf/font/makefont/makefont.php@ 194

Last change on this file since 194 was 2, checked in by root, 15 years ago

importo il progetto

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