root / docs / www / colonyscout / internal / fpdf16 / font / makefont / makefont.php @ f59acf11
History | View | Annotate | Download (10.4 KB)
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 |
|
10 |
function 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 |
|
36 |
function 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 |
|
137 |
function 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 |
|
188 |
function 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 |
|
213 |
function 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 |
|
232 |
function 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 |
|
241 |
function ReadShort($f) |
242 |
{ |
243 |
$a=unpack('n1n',fread($f,2)); |
244 |
return $a['n']; |
245 |
} |
246 |
|
247 |
function ReadLong($f) |
248 |
{ |
249 |
$a=unpack('N1N',fread($f,4)); |
250 |
return $a['N']; |
251 |
} |
252 |
|
253 |
function 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 embedded) *
|
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 |
*******************************************************************************/
|
300 |
function 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 |
?>
|