source: trunk/phpgwapi/inc/fpdf/font/makefont/makefont.php @ 2

Revision 2, 9.8 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

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