source: trunk/reports/inc/font/makefont/makefont.php @ 5291

Revision 5291, 10.8 KB checked in by alexandrecorreia, 12 years ago (diff)

Ticket #2408 - Recolocando o módulo reports dentro do trunk novamente.

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 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*******************************************************************************/
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.