Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

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