source: branches/version-2_11-dev/data/module/fpdf/makefont/makefont.php @ 20993

Revision 20993, 9.3 KB checked in by Seasoft, 13 years ago (diff)

#1374 (依存ライブラリのアップデート)

  • FPDF 1.6 -> 1.7
  • FPDI 1.4 -> 1.4.1 (配置パスをFPDFから分離)
Line 
1<?php
2/*******************************************************************************
3* Utility to generate font definition files                                    *
4*                                                                              *
5* Version: 1.2                                                                 *
6* Date:    2011-06-18                                                          *
7* Author:  Olivier PLATHEY                                                     *
8*******************************************************************************/
9
10require('ttfparser.php');
11
12function Message($txt, $severity='')
13{
14    if(PHP_SAPI=='cli')
15    {
16        if($severity)
17            echo "$severity: ";
18        echo "$txt\n";
19    }
20    else
21    {
22        if($severity)
23            echo "<b>$severity</b>: ";
24        echo "$txt<br>";
25    }
26}
27
28function Notice($txt)
29{
30    Message($txt, 'Notice');
31}
32
33function Warning($txt)
34{
35    Message($txt, 'Warning');
36}
37
38function Error($txt)
39{
40    Message($txt, 'Error');
41    exit;
42}
43
44function LoadMap($enc)
45{
46    $file = dirname(__FILE__).'/'.strtolower($enc).'.map';
47    $a = file($file);
48    if(empty($a))
49        Error('Encoding not found: '.$enc);
50    $map = array_fill(0, 256, array('uv'=>-1, 'name'=>'.notdef'));
51    foreach($a as $line)
52    {
53        $e = explode(' ', rtrim($line));
54        $c = hexdec(substr($e[0],1));
55        $uv = hexdec(substr($e[1],2));
56        $name = $e[2];
57        $map[$c] = array('uv'=>$uv, 'name'=>$name);
58    }
59    return $map;
60}
61
62function GetInfoFromTrueType($file, $embed, $map)
63{
64    // Return informations from a TrueType font
65    $ttf = new TTFParser();
66    $ttf->Parse($file);
67    if($embed)
68    {
69        if(!$ttf->Embeddable)
70            Error('Font license does not allow embedding');
71        $info['Data'] = file_get_contents($file);
72        $info['OriginalSize'] = filesize($file);
73    }
74    $k = 1000/$ttf->unitsPerEm;
75    $info['FontName'] = $ttf->postScriptName;
76    $info['Bold'] = $ttf->Bold;
77    $info['ItalicAngle'] = $ttf->italicAngle;
78    $info['IsFixedPitch'] = $ttf->isFixedPitch;
79    $info['Ascender'] = round($k*$ttf->typoAscender);
80    $info['Descender'] = round($k*$ttf->typoDescender);
81    $info['UnderlineThickness'] = round($k*$ttf->underlineThickness);
82    $info['UnderlinePosition'] = round($k*$ttf->underlinePosition);
83    $info['FontBBox'] = array(round($k*$ttf->xMin), round($k*$ttf->yMin), round($k*$ttf->xMax), round($k*$ttf->yMax));
84    $info['CapHeight'] = round($k*$ttf->capHeight);
85    $info['MissingWidth'] = round($k*$ttf->widths[0]);
86    $widths = array_fill(0, 256, $info['MissingWidth']);
87    for($c=0;$c<=255;$c++)
88    {
89        if($map[$c]['name']!='.notdef')
90        {
91            $uv = $map[$c]['uv'];
92            if(isset($ttf->chars[$uv]))
93            {
94                $w = $ttf->widths[$ttf->chars[$uv]];
95                $widths[$c] = round($k*$w);
96            }
97            else
98                Warning('Character '.$map[$c]['name'].' is missing');
99        }
100    }
101    $info['Widths'] = $widths;
102    return $info;
103}
104
105function GetInfoFromType1($file, $embed, $map)
106{
107    // Return informations from a Type1 font
108    if($embed)
109    {
110        $f = fopen($file, 'rb');
111        if(!$f)
112            Error('Can\'t open font file');
113        // Read first segment
114        $a = unpack('Cmarker/Ctype/Vsize', fread($f,6));
115        if($a['marker']!=128)
116            Error('Font file is not a valid binary Type1');
117        $size1 = $a['size'];
118        $data = fread($f, $size1);
119        // Read second segment
120        $a = unpack('Cmarker/Ctype/Vsize', fread($f,6));
121        if($a['marker']!=128)
122            Error('Font file is not a valid binary Type1');
123        $size2 = $a['size'];
124        $data .= fread($f, $size2);
125        fclose($f);
126        $info['Data'] = $data;
127        $info['Size1'] = $size1;
128        $info['Size2'] = $size2;
129    }
130
131    $afm = substr($file, 0, -3).'afm';
132    if(!file_exists($afm))
133        Error('AFM font file not found: '.$afm);
134    $a = file($afm);
135    if(empty($a))
136        Error('AFM file empty or not readable');
137    foreach($a as $line)
138    {
139        $e = explode(' ', rtrim($line));
140        if(count($e)<2)
141            continue;
142        $entry = $e[0];
143        if($entry=='C')
144        {
145            $w = $e[4];
146            $name = $e[7];
147            $cw[$name] = $w;
148        }
149        elseif($entry=='FontName')
150            $info['FontName'] = $e[1];
151        elseif($entry=='Weight')
152            $info['Weight'] = $e[1];
153        elseif($entry=='ItalicAngle')
154            $info['ItalicAngle'] = (int)$e[1];
155        elseif($entry=='Ascender')
156            $info['Ascender'] = (int)$e[1];
157        elseif($entry=='Descender')
158            $info['Descender'] = (int)$e[1];
159        elseif($entry=='UnderlineThickness')
160            $info['UnderlineThickness'] = (int)$e[1];
161        elseif($entry=='UnderlinePosition')
162            $info['UnderlinePosition'] = (int)$e[1];
163        elseif($entry=='IsFixedPitch')
164            $info['IsFixedPitch'] = ($e[1]=='true');
165        elseif($entry=='FontBBox')
166            $info['FontBBox'] = array((int)$e[1], (int)$e[2], (int)$e[3], (int)$e[4]);
167        elseif($entry=='CapHeight')
168            $info['CapHeight'] = (int)$e[1];
169        elseif($entry=='StdVW')
170            $info['StdVW'] = (int)$e[1];
171    }
172
173    if(!isset($info['FontName']))
174        Error('FontName missing in AFM file');
175    $info['Bold'] = isset($info['Weight']) && preg_match('/bold|black/i', $info['Weight']);
176    if(isset($cw['.notdef']))
177        $info['MissingWidth'] = $cw['.notdef'];
178    else
179        $info['MissingWidth'] = 0;
180    $widths = array_fill(0, 256, $info['MissingWidth']);
181    for($c=0;$c<=255;$c++)
182    {
183        $name = $map[$c]['name'];
184        if($name!='.notdef')
185        {
186            if(isset($cw[$name]))
187                $widths[$c] = $cw[$name];
188            else
189                Warning('Character '.$name.' is missing');
190        }
191    }
192    $info['Widths'] = $widths;
193    return $info;
194}
195
196function MakeFontDescriptor($info)
197{
198    // Ascent
199    $fd = "array('Ascent'=>".$info['Ascender'];
200    // Descent
201    $fd .= ",'Descent'=>".$info['Descender'];
202    // CapHeight
203    if(!empty($info['CapHeight']))
204        $fd .= ",'CapHeight'=>".$info['CapHeight'];
205    else
206        $fd .= ",'CapHeight'=>".$info['Ascender'];
207    // Flags
208    $flags = 0;
209    if($info['IsFixedPitch'])
210        $flags += 1<<0;
211    $flags += 1<<5;
212    if($info['ItalicAngle']!=0)
213        $flags += 1<<6;
214    $fd .= ",'Flags'=>".$flags;
215    // FontBBox
216    $fbb = $info['FontBBox'];
217    $fd .= ",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
218    // ItalicAngle
219    $fd .= ",'ItalicAngle'=>".$info['ItalicAngle'];
220    // StemV
221    if(isset($info['StdVW']))
222        $stemv = $info['StdVW'];
223    elseif($info['Bold'])
224        $stemv = 120;
225    else
226        $stemv = 70;
227    $fd .= ",'StemV'=>".$stemv;
228    // MissingWidth
229    $fd .= ",'MissingWidth'=>".$info['MissingWidth'].')';
230    return $fd;
231}
232
233function MakeWidthArray($widths)
234{
235    $s = "array(\n\t";
236    for($c=0;$c<=255;$c++)
237    {
238        if(chr($c)=="'")
239            $s .= "'\\''";
240        elseif(chr($c)=="\\")
241            $s .= "'\\\\'";
242        elseif($c>=32 && $c<=126)
243            $s .= "'".chr($c)."'";
244        else
245            $s .= "chr($c)";
246        $s .= '=>'.$widths[$c];
247        if($c<255)
248            $s .= ',';
249        if(($c+1)%22==0)
250            $s .= "\n\t";
251    }
252    $s .= ')';
253    return $s;
254}
255
256function MakeFontEncoding($map)
257{
258    // Build differences from reference encoding
259    $ref = LoadMap('cp1252');
260    $s = '';
261    $last = 0;
262    for($c=32;$c<=255;$c++)
263    {
264        if($map[$c]['name']!=$ref[$c]['name'])
265        {
266            if($c!=$last+1)
267                $s .= $c.' ';
268            $last = $c;
269            $s .= '/'.$map[$c]['name'].' ';
270        }
271    }
272    return rtrim($s);
273}
274
275function SaveToFile($file, $s, $mode)
276{
277    $f = fopen($file, 'w'.$mode);
278    if(!$f)
279        Error('Can\'t write to file '.$file);
280    fwrite($f, $s, strlen($s));
281    fclose($f);
282}
283
284function MakeDefinitionFile($file, $type, $enc, $embed, $map, $info)
285{
286    $s = "<?php\n";
287    $s .= '$type = \''.$type."';\n";
288    $s .= '$name = \''.$info['FontName']."';\n";
289    $s .= '$desc = '.MakeFontDescriptor($info).";\n";
290    $s .= '$up = '.$info['UnderlinePosition'].";\n";
291    $s .= '$ut = '.$info['UnderlineThickness'].";\n";
292    $s .= '$cw = '.MakeWidthArray($info['Widths']).";\n";
293    $s .= '$enc = \''.$enc."';\n";
294    $diff = MakeFontEncoding($map);
295    if($diff)
296        $s .= '$diff = \''.$diff."';\n";
297    if($embed)
298    {
299        $s .= '$file = \''.$info['File']."';\n";
300        if($type=='Type1')
301        {
302            $s .= '$size1 = '.$info['Size1'].";\n";
303            $s .= '$size2 = '.$info['Size2'].";\n";
304        }
305        else
306            $s .= '$originalsize = '.$info['OriginalSize'].";\n";
307    }
308    $s .= "?>\n";
309    SaveToFile($file, $s, 't');
310}
311
312function MakeFont($fontfile, $enc='cp1252', $embed=true)
313{
314    // Generate a font definition file
315    if(get_magic_quotes_runtime())
316        @set_magic_quotes_runtime(0);
317    ini_set('auto_detect_line_endings', '1');
318
319    if(!file_exists($fontfile))
320        Error('Font file not found: '.$fontfile);
321    $ext = strtolower(substr($fontfile,-3));
322    if($ext=='ttf' || $ext=='otf')
323        $type = 'TrueType';
324    elseif($ext=='pfb')
325        $type = 'Type1';
326    else
327        Error('Unrecognized font file extension: '.$ext);
328
329    $map = LoadMap($enc);
330
331    if($type=='TrueType')
332        $info = GetInfoFromTrueType($fontfile, $embed, $map);
333    else
334        $info = GetInfoFromType1($fontfile, $embed, $map);
335
336    $basename = substr(basename($fontfile), 0, -4);
337    if($embed)
338    {
339        if(function_exists('gzcompress'))
340        {
341            $file = $basename.'.z';
342            SaveToFile($file, gzcompress($info['Data']), 'b');
343            $info['File'] = $file;
344            Message('Font file compressed: '.$file);
345        }
346        else
347        {
348            $info['File'] = basename($fontfile);
349            Notice('Font file could not be compressed (zlib extension not available)');
350        }
351    }
352
353    MakeDefinitionFile($basename.'.php', $type, $enc, $embed, $map, $info);
354    Message('Font definition file generated: '.$basename.'.php');
355}
356
357if(PHP_SAPI=='cli')
358{
359    // Command-line interface
360    if($argc==1)
361        die("Usage: php makefont.php fontfile [enc] [embed]\n");
362    $fontfile = $argv[1];
363    if($argc>=3)
364        $enc = $argv[2];
365    else
366        $enc = 'cp1252';
367    if($argc>=4)
368        $embed = ($argv[3]=='true' || $argv[3]=='1');
369    else
370        $embed = true;
371    MakeFont($fontfile, $enc, $embed);
372}
373?>
Note: See TracBrowser for help on using the repository browser.