source: branches/version-2_5-dev/data/module/fpdf/font/makefont/makefont.php @ 20116

Revision 20116, 10.2 KB checked in by nanasess, 13 years ago (diff)
  • svn properties を再設定
  • 再設定用のスクリプト追加
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*******************************************************************************
3* Utility to generate font definition files                                    *
4* Version: 1.13                                                                *
5* Date:    2004-12-31                                                          *
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]+/',rtrim($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    {
28        if(!isset($cc2gn[$i]))
29            $cc2gn[$i]='.notdef';
30    }
31    return $cc2gn;
32}
33
34function ReadAFM($file,&$map)
35{
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)
51    {
52        $e=explode(' ',rtrim($l));
53        if(count($e)<2)
54            continue;
55        $code=$e[0];
56        $param=$e[1];
57        if($code=='C')
58        {
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]))
66            {
67                //Fix incorrect glyph name
68                foreach($map as $c=>$n)
69                {
70                    if($n==$fix[$gn])
71                        $map[$c]=$gn;
72                }
73            }
74            if(empty($map))
75            {
76                //Symbolic font: use built-in encoding
77                $widths[$cc]=$w;
78            }
79            else
80            {
81                $widths[$gn]=$w;
82                if($gn=='X')
83                    $fm['CapXHeight']=$e[13];
84            }
85            if($gn=='.notdef')
86                $fm['MissingWidth']=$w;
87        }
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;
110    }
111    if(!isset($fm['FontName']))
112        die('FontName not found');
113    if(!empty($map))
114    {
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++)
121        {
122            if(!isset($widths[$map[$i]]))
123            {
124                echo '<B>Warning:</B> character '.$map[$i].' is missing<BR>';
125                $widths[$i]=$widths['.notdef'];
126            }
127            else
128                $widths[$i]=$widths[$map[$i]];
129        }
130    }
131    $fm['Widths']=$widths;
132    return $fm;
133}
134
135function MakeFontDescriptor($fm,$symbolic)
136{
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;
184}
185
186function MakeWidthArray($fm)
187{
188    //Make character width array
189    $s="array(\n\t";
190    $cw=$fm['Widths'];
191    for($i=0;$i<=255;$i++)
192    {
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";
206    }
207    $s.=')';
208    return $s;
209}
210
211function MakeFontEncoding($map)
212{
213    //Build differences from reference encoding
214    $ref=ReadMap('cp1252');
215    $s='';
216    $last=0;
217    for($i=32;$i<=255;$i++)
218    {
219        if($map[$i]!=$ref[$i])
220        {
221            if($i!=$last+1)
222                $s.=$i.' ';
223            $last=$i;
224            $s.='/'.$map[$i].' ';
225        }
226    }
227    return rtrim($s);
228}
229
230function SaveToFile($file,$s,$mode='t')
231{
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);
237}
238
239function ReadShort($f)
240{
241    $a=unpack('n1n',fread($f,2));
242    return $a['n'];
243}
244
245function ReadLong($f)
246{
247    $a=unpack('N1N',fread($f,4));
248    return $a['N'];
249}
250
251function CheckTTF($file)
252{
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++)
264    {
265        if(fread($f,4)=='OS/2')
266        {
267            $found=true;
268            break;
269        }
270        fseek($f,12,SEEK_CUR);
271    }
272    if(!$found)
273    {
274        fclose($f);
275        return;
276    }
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';
289}
290
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*******************************************************************************/
298function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=array(),$type='TrueType')
299{
300    //Generate a font definition file
301    set_magic_quotes_runtime(0);
302    ini_set('auto_detect_line_endings','1');
303    if($enc)
304    {
305        $map=ReadMap($enc);
306        foreach($patch as $cc=>$gn)
307            $map[$cc]=$gn;
308    }
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)
321    {
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);
329    }
330    else
331    {
332        if($type!='TrueType' and $type!='Type1')
333            die('<B>Error:</B> incorrect font type: '.$type);
334    }
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)
352    {
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')
364        {
365            //Find first two sections and discard third one
366            $header=(ord($file{0})==128);
367            if($header)
368            {
369                //Strip first binary header
370                $file=substr($file,6);
371            }
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)
377            {
378                //Strip second binary header
379                $file=substr($file,0,$size1).substr($file,$size1+6);
380            }
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);
386        }
387        if(function_exists('gzcompress'))
388        {
389            $cmp=$basename.'.z';
390            SaveToFile($cmp,gzcompress($file),'b');
391            $s.='$file=\''.$cmp."';\n";
392            echo 'Font file compressed ('.$cmp.')<BR>';
393        }
394        else
395        {
396            $s.='$file=\''.basename($fontfile)."';\n";
397            echo '<B>Notice:</B> font file could not be compressed (zlib extension not available)<BR>';
398        }
399        if($type=='Type1')
400        {
401            $s.='$size1='.$size1.";\n";
402            $s.='$size2='.$size2.";\n";
403        }
404        else
405            $s.='$originalsize='.filesize($fontfile).";\n";
406    }
407    else
408    {
409        //Not embedded font
410        $s.='$file='."'';\n";
411    }
412    $s.="?>\n";
413    SaveToFile($basename.'.php',$s);
414    echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
415}
416?>
Note: See TracBrowser for help on using the repository browser.