Chris@909
|
1 <?php
|
Chris@909
|
2 /*******************************************************************************
|
Chris@909
|
3 * Utility to generate font definition files for Unicode Truetype fonts *
|
Chris@909
|
4 * Version: 1.12 *
|
Chris@909
|
5 * Date: 2003-12-30 *
|
Chris@909
|
6 *******************************************************************************/
|
Chris@909
|
7
|
Chris@909
|
8 function ReadUFM($file, &$cidtogidmap)
|
Chris@909
|
9 {
|
Chris@909
|
10 //Prepare empty CIDToGIDMap
|
Chris@909
|
11 $cidtogidmap = str_pad('', 256*256*2, "\x00");
|
Chris@909
|
12
|
Chris@909
|
13 //Read a font metric file
|
Chris@909
|
14 $a=file($file);
|
Chris@909
|
15 if(empty($a))
|
Chris@909
|
16 die('File not found');
|
Chris@909
|
17 $widths=array();
|
Chris@909
|
18 $fm=array();
|
Chris@909
|
19 foreach($a as $l)
|
Chris@909
|
20 {
|
Chris@909
|
21 $e=explode(' ',chop($l));
|
Chris@909
|
22 if(count($e)<2)
|
Chris@909
|
23 continue;
|
Chris@909
|
24 $code=$e[0];
|
Chris@909
|
25 $param=$e[1];
|
Chris@909
|
26 if($code=='U')
|
Chris@909
|
27 {
|
Chris@909
|
28 // U 827 ; WX 0 ; N squaresubnosp ; G 675 ;
|
Chris@909
|
29 //Character metrics
|
Chris@909
|
30 $cc=(int)$e[1];
|
Chris@909
|
31 if ($cc != -1) {
|
Chris@909
|
32 $gn = $e[7];
|
Chris@909
|
33 $w = $e[4];
|
Chris@909
|
34 $glyph = $e[10];
|
Chris@909
|
35 $widths[$cc] = $w;
|
Chris@909
|
36 if($cc == ord('X'))
|
Chris@909
|
37 $fm['CapXHeight'] = $e[13];
|
Chris@909
|
38
|
Chris@909
|
39 // Set GID
|
Chris@909
|
40 if ($cc >= 0 && $cc < 0xFFFF && $glyph) {
|
Chris@909
|
41 $cidtogidmap{$cc*2} = chr($glyph >> 8);
|
Chris@909
|
42 $cidtogidmap{$cc*2 + 1} = chr($glyph & 0xFF);
|
Chris@909
|
43 }
|
Chris@909
|
44 }
|
Chris@909
|
45 if($gn=='.notdef' && !isset($fm['MissingWidth']))
|
Chris@909
|
46 $fm['MissingWidth']=$w;
|
Chris@909
|
47 }
|
Chris@909
|
48 elseif($code=='FontName')
|
Chris@909
|
49 $fm['FontName']=$param;
|
Chris@909
|
50 elseif($code=='Weight')
|
Chris@909
|
51 $fm['Weight']=$param;
|
Chris@909
|
52 elseif($code=='ItalicAngle')
|
Chris@909
|
53 $fm['ItalicAngle']=(double)$param;
|
Chris@909
|
54 elseif($code=='Ascender')
|
Chris@909
|
55 $fm['Ascender']=(int)$param;
|
Chris@909
|
56 elseif($code=='Descender')
|
Chris@909
|
57 $fm['Descender']=(int)$param;
|
Chris@909
|
58 elseif($code=='UnderlineThickness')
|
Chris@909
|
59 $fm['UnderlineThickness']=(int)$param;
|
Chris@909
|
60 elseif($code=='UnderlinePosition')
|
Chris@909
|
61 $fm['UnderlinePosition']=(int)$param;
|
Chris@909
|
62 elseif($code=='IsFixedPitch')
|
Chris@909
|
63 $fm['IsFixedPitch']=($param=='true');
|
Chris@909
|
64 elseif($code=='FontBBox')
|
Chris@909
|
65 $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
|
Chris@909
|
66 elseif($code=='CapHeight')
|
Chris@909
|
67 $fm['CapHeight']=(int)$param;
|
Chris@909
|
68 elseif($code=='StdVW')
|
Chris@909
|
69 $fm['StdVW']=(int)$param;
|
Chris@909
|
70 }
|
Chris@909
|
71 if(!isset($fm['MissingWidth']))
|
Chris@909
|
72 $fm['MissingWidth']=600;
|
Chris@909
|
73
|
Chris@909
|
74 if(!isset($fm['FontName']))
|
Chris@909
|
75 die('FontName not found');
|
Chris@909
|
76
|
Chris@909
|
77 $fm['Widths']=$widths;
|
Chris@909
|
78
|
Chris@909
|
79 return $fm;
|
Chris@909
|
80 }
|
Chris@909
|
81
|
Chris@909
|
82 function MakeFontDescriptor($fm)
|
Chris@909
|
83 {
|
Chris@909
|
84 //Ascent
|
Chris@909
|
85 $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
|
Chris@909
|
86 $fd="{'Ascent'=>".$asc;
|
Chris@909
|
87 //Descent
|
Chris@909
|
88 $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
|
Chris@909
|
89 $fd.=",'Descent'=>".$desc;
|
Chris@909
|
90 //CapHeight
|
Chris@909
|
91 if(isset($fm['CapHeight']))
|
Chris@909
|
92 $ch=$fm['CapHeight'];
|
Chris@909
|
93 elseif(isset($fm['CapXHeight']))
|
Chris@909
|
94 $ch=$fm['CapXHeight'];
|
Chris@909
|
95 else
|
Chris@909
|
96 $ch=$asc;
|
Chris@909
|
97 $fd.=",'CapHeight'=>".$ch;
|
Chris@909
|
98 //Flags
|
Chris@909
|
99 $flags=0;
|
Chris@909
|
100 if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
|
Chris@909
|
101 $flags+=1<<0;
|
Chris@909
|
102 $flags+=1<<5;
|
Chris@909
|
103 if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
|
Chris@909
|
104 $flags+=1<<6;
|
Chris@909
|
105 $fd.=",'Flags'=>".$flags;
|
Chris@909
|
106 //FontBBox
|
Chris@909
|
107 if(isset($fm['FontBBox']))
|
Chris@909
|
108 $fbb=$fm['FontBBox'];
|
Chris@909
|
109 else
|
Chris@909
|
110 $fbb=array(0,$des-100,1000,$asc+100);
|
Chris@909
|
111 $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
|
Chris@909
|
112 //ItalicAngle
|
Chris@909
|
113 $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
|
Chris@909
|
114 $fd.=",'ItalicAngle'=>".$ia;
|
Chris@909
|
115 //StemV
|
Chris@909
|
116 if(isset($fm['StdVW']))
|
Chris@909
|
117 $stemv=$fm['StdVW'];
|
Chris@909
|
118 elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
|
Chris@909
|
119 $stemv=120;
|
Chris@909
|
120 else
|
Chris@909
|
121 $stemv=70;
|
Chris@909
|
122 $fd.=",'StemV'=>".$stemv;
|
Chris@909
|
123 //MissingWidth
|
Chris@909
|
124 if(isset($fm['MissingWidth']))
|
Chris@909
|
125 $fd.=",'MissingWidth'=>".$fm['MissingWidth'];
|
Chris@909
|
126 $fd.='}';
|
Chris@909
|
127 return $fd;
|
Chris@909
|
128 }
|
Chris@909
|
129
|
Chris@909
|
130 function MakeWidthArray($fm)
|
Chris@909
|
131 {
|
Chris@909
|
132 //Make character width array
|
Chris@909
|
133 $s="{";
|
Chris@909
|
134 $cw=$fm['Widths'];
|
Chris@909
|
135 $els=array();
|
Chris@909
|
136 $c=0;
|
Chris@909
|
137 foreach ($cw as $i => $w)
|
Chris@909
|
138 {
|
Chris@909
|
139 $els[] = ((($c++)%16==0)?"\n\t":'').$i.'=>'.$w;
|
Chris@909
|
140 }
|
Chris@909
|
141 $s .= implode(', ', $els);
|
Chris@909
|
142 $s.='}';
|
Chris@909
|
143 return $s;
|
Chris@909
|
144 }
|
Chris@909
|
145
|
Chris@909
|
146 function SaveToFile($file,$s,$mode='t')
|
Chris@909
|
147 {
|
Chris@909
|
148 $f=fopen($file,'w'.$mode);
|
Chris@909
|
149 if(!$f)
|
Chris@909
|
150 die('Can\'t write to file '.$file);
|
Chris@909
|
151 fwrite($f,$s,strlen($s));
|
Chris@909
|
152 fclose($f);
|
Chris@909
|
153 }
|
Chris@909
|
154
|
Chris@909
|
155 function ReadShort($f)
|
Chris@909
|
156 {
|
Chris@909
|
157 $a=unpack('n1n',fread($f,2));
|
Chris@909
|
158 return $a['n'];
|
Chris@909
|
159 }
|
Chris@909
|
160
|
Chris@909
|
161 function ReadLong($f)
|
Chris@909
|
162 {
|
Chris@909
|
163 $a=unpack('N1N',fread($f,4));
|
Chris@909
|
164 return $a['N'];
|
Chris@909
|
165 }
|
Chris@909
|
166
|
Chris@909
|
167 function CheckTTF($file)
|
Chris@909
|
168 {
|
Chris@909
|
169 //Check if font license allows embedding
|
Chris@909
|
170 $f=fopen($file,'rb');
|
Chris@909
|
171 if(!$f)
|
Chris@909
|
172 die('<B>Error:</B> Can\'t open '.$file);
|
Chris@909
|
173 //Extract number of tables
|
Chris@909
|
174 fseek($f,4,SEEK_CUR);
|
Chris@909
|
175 $nb=ReadShort($f);
|
Chris@909
|
176 fseek($f,6,SEEK_CUR);
|
Chris@909
|
177 //Seek OS/2 table
|
Chris@909
|
178 $found=false;
|
Chris@909
|
179 for($i=0;$i<$nb;$i++)
|
Chris@909
|
180 {
|
Chris@909
|
181 if(fread($f,4)=='OS/2')
|
Chris@909
|
182 {
|
Chris@909
|
183 $found=true;
|
Chris@909
|
184 break;
|
Chris@909
|
185 }
|
Chris@909
|
186 fseek($f,12,SEEK_CUR);
|
Chris@909
|
187 }
|
Chris@909
|
188 if(!$found)
|
Chris@909
|
189 {
|
Chris@909
|
190 fclose($f);
|
Chris@909
|
191 return;
|
Chris@909
|
192 }
|
Chris@909
|
193 fseek($f,4,SEEK_CUR);
|
Chris@909
|
194 $offset=ReadLong($f);
|
Chris@909
|
195 fseek($f,$offset,SEEK_SET);
|
Chris@909
|
196 //Extract fsType flags
|
Chris@909
|
197 fseek($f,8,SEEK_CUR);
|
Chris@909
|
198 $fsType=ReadShort($f);
|
Chris@909
|
199 $rl=($fsType & 0x02)!=0;
|
Chris@909
|
200 $pp=($fsType & 0x04)!=0;
|
Chris@909
|
201 $e=($fsType & 0x08)!=0;
|
Chris@909
|
202 fclose($f);
|
Chris@909
|
203 if($rl and !$pp and !$e)
|
Chris@909
|
204 echo '<B>Warning:</B> font license does not allow embedding';
|
Chris@909
|
205 }
|
Chris@909
|
206
|
Chris@909
|
207 /*******************************************************************************
|
Chris@909
|
208 * $fontfile: path to TTF file (or empty string if not to be embedded) *
|
Chris@909
|
209 * $ufmfile: path to UFM file *
|
Chris@909
|
210 *******************************************************************************/
|
Chris@909
|
211 function MakeFont($fontfile,$ufmfile)
|
Chris@909
|
212 {
|
Chris@909
|
213 //Generate a font definition file
|
Chris@909
|
214 set_magic_quotes_runtime(0);
|
Chris@909
|
215 if(!file_exists($ufmfile))
|
Chris@909
|
216 die('<B>Error:</B> UFM file not found: '.$ufmfile);
|
Chris@909
|
217 $cidtogidmap = '';
|
Chris@909
|
218 $fm=ReadUFM($ufmfile, $cidtogidmap);
|
Chris@909
|
219 $fd=MakeFontDescriptor($fm);
|
Chris@909
|
220 //Find font type
|
Chris@909
|
221 if($fontfile)
|
Chris@909
|
222 {
|
Chris@909
|
223 $ext=strtolower(substr($fontfile,-3));
|
Chris@909
|
224 if($ext=='ttf')
|
Chris@909
|
225 $type='TrueTypeUnicode';
|
Chris@909
|
226 else
|
Chris@909
|
227 die('<B>Error:</B> not a truetype font: '.$ext);
|
Chris@909
|
228 }
|
Chris@909
|
229 else
|
Chris@909
|
230 {
|
Chris@909
|
231 if($type!='TrueTypeUnicode')
|
Chris@909
|
232 die('<B>Error:</B> incorrect font type: '.$type);
|
Chris@909
|
233 }
|
Chris@909
|
234 //Start generation
|
Chris@909
|
235 $basename=strtolower(substr(basename($ufmfile),0,-4));
|
Chris@909
|
236 $s='TCPDFFontDescriptor.define(\''.$basename."') do |font|\n";
|
Chris@909
|
237 $s.=" font[:type]='".$type."'\n";
|
Chris@909
|
238 $s.=" font[:name]='".$fm['FontName']."'\n";
|
Chris@909
|
239 $s.=" font[:desc]=".$fd."\n";
|
Chris@909
|
240 if(!isset($fm['UnderlinePosition']))
|
Chris@909
|
241 $fm['UnderlinePosition']=-100;
|
Chris@909
|
242 if(!isset($fm['UnderlineThickness']))
|
Chris@909
|
243 $fm['UnderlineThickness']=50;
|
Chris@909
|
244 $s.=" font[:up]=".$fm['UnderlinePosition']."\n";
|
Chris@909
|
245 $s.=" font[:ut]=".$fm['UnderlineThickness']."\n";
|
Chris@909
|
246 $s.=" font[:cw]=".MakeWidthArray($fm)."\n";
|
Chris@909
|
247 $s.=" font[:enc]=''\n";
|
Chris@909
|
248 $s.=" font[:diff]=''\n";
|
Chris@909
|
249 if($fontfile)
|
Chris@909
|
250 {
|
Chris@909
|
251 //Embedded font
|
Chris@909
|
252 if(!file_exists($fontfile))
|
Chris@909
|
253 die('<B>Error:</B> font file not found: '.$fontfile);
|
Chris@909
|
254 CheckTTF($fontfile);
|
Chris@909
|
255 $f=fopen($fontfile,'rb');
|
Chris@909
|
256 if(!$f)
|
Chris@909
|
257 die('<B>Error:</B> Can\'t open '.$fontfile);
|
Chris@909
|
258 $file=fread($f,filesize($fontfile));
|
Chris@909
|
259 fclose($f);
|
Chris@909
|
260 if(function_exists('gzcompress'))
|
Chris@909
|
261 {
|
Chris@909
|
262 $cmp=$basename.'.z';
|
Chris@909
|
263 SaveToFile($cmp,gzcompress($file),'b');
|
Chris@909
|
264 $s.=' font[:file]=\''.$cmp."'\n";
|
Chris@909
|
265 echo 'Font file compressed ('.$cmp.')<BR>';
|
Chris@909
|
266
|
Chris@909
|
267 $cmp=$basename.'.ctg.z';
|
Chris@909
|
268 SaveToFile($cmp,gzcompress($cidtogidmap),'b');
|
Chris@909
|
269 echo 'CIDToGIDMap created and compressed ('.$cmp.')<BR>';
|
Chris@909
|
270 $s.=' font[:ctg]=\''.$cmp."'\n";
|
Chris@909
|
271 }
|
Chris@909
|
272 else
|
Chris@909
|
273 {
|
Chris@909
|
274 $s.='$file=\''.basename($fontfile)."'\n";
|
Chris@909
|
275 echo '<B>Notice:</B> font file could not be compressed (gzcompress not available)<BR>';
|
Chris@909
|
276
|
Chris@909
|
277 $cmp=$basename.'.ctg';
|
Chris@909
|
278 $f = fopen($cmp, 'wb');
|
Chris@909
|
279 fwrite($f, $cidtogidmap);
|
Chris@909
|
280 fclose($f);
|
Chris@909
|
281 echo 'CIDToGIDMap created ('.$cmp.')<BR>';
|
Chris@909
|
282 $s.=' font[:ctg]=\''.$cmp."'\n";
|
Chris@909
|
283 }
|
Chris@909
|
284 if($type=='Type1')
|
Chris@909
|
285 {
|
Chris@909
|
286 $s.=' font[:size1]='.$size1."\n";
|
Chris@909
|
287 $s.=' font[:size2]='.$size2."\n";
|
Chris@909
|
288 }
|
Chris@909
|
289 else
|
Chris@909
|
290 $s.=' font[:originalsize]='.filesize($fontfile)."\n";
|
Chris@909
|
291 }
|
Chris@909
|
292 else
|
Chris@909
|
293 {
|
Chris@909
|
294 //Not embedded font
|
Chris@909
|
295 $s.=' font[:file]='."''\n";
|
Chris@909
|
296 }
|
Chris@909
|
297 $s.="end\n";
|
Chris@909
|
298 SaveToFile($basename.'.rb',$s);
|
Chris@909
|
299 echo 'Font definition file generated ('.$basename.'.rb'.')<BR>';
|
Chris@909
|
300 }
|
Chris@909
|
301
|
Chris@909
|
302 $arg = $GLOBALS['argv'];
|
Chris@909
|
303 if (count($arg) >= 3) {
|
Chris@909
|
304 ob_start();
|
Chris@909
|
305 array_shift($arg);
|
Chris@909
|
306 MakeFont($arg[0], $arg[1]);
|
Chris@909
|
307 $t = ob_get_clean();
|
Chris@909
|
308 print preg_replace('!<BR( /)?>!i', "\n", $t);
|
Chris@909
|
309 }
|
Chris@909
|
310 else {
|
Chris@909
|
311 print "Usage: makefontuni_ruby.php <ttf-file> <ufm-file>\n";
|
Chris@909
|
312 }
|
Chris@909
|
313 ?> |