To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / b0 / b00b19ae72ee99ad4406b689ee8ffd14f04ede96.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (10.5 KB)

1

    
2
#*****************************************************************************
3
# Utility to generate font definition files                                   #
4
# Version: 1.13                                                               #
5
# Date:    2004-12-31                                                         #
6
******************************************************************************#
7

    
8
function ReadMap($enc)
9
{
10
	#Read a map file
11
	$file=dirname(__FILE__) + '/' + $enc.downcase + '.map';
12
	$a=file($file);
13
	if ($a))
14
		die('<B>Error:</B> encoding not found: '.$enc);
15
	$cc2gn = []
16
	foreach($a as $l)
17
	{
18
		if ($l{0}=='!')
19
		{
20
			$e=rtrim($l).scan('/[ \\t]+/');
21
			$cc=hexdec(substr($e[0],1));
22
			$gn=$e[2];
23
			$cc2gn[$cc]=$gn;
24
		end
25
	end
26
	for($i=0;$i<=255;$i++)
27
	{
28
		if (!$cc2gn[$i].nil?)
29
			$cc2gn[$i]='.notdef';
30
	end
31
	return $cc2gn;
32
}
33

    
34
function ReadAFM($file,&$map)
35
{
36
	#Read a font metric file
37
	$a=file($file);
38
	if ($a.empty?)
39
		die('File not found');
40
	$widths = []
41
	$fm = []
42
	$fix=Hash.new('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 ($e.length<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 ($fix[$gn].nil?)
66
			{
67
				#Fix incorrect glyph name
68
				foreach($map as $c=>$n)
69
				{
70
					if ($n==$fix[$gn])
71
						$map[$c]=$gn;
72
				end
73
			end
74
			if ($map.empty?)
75
			{
76
				#Symbolic font: use built-in encoding
77
				$widths[$cc]=$w;
78
			else
79
			{
80
				$widths[$gn]=$w;
81
				if ($gn=='X')
82
					$fm['CapXHeight']=$e[13];
83
			end
84
			if ($gn=='.notdef')
85
				$fm['MissingWidth']=$w;
86
		elsif ($code=='FontName')
87
			$fm['FontName']=$param;
88
		elsif ($code=='Weight')
89
			$fm['Weight']=$param;
90
		elsif ($code=='ItalicAngle')
91
			$fm['ItalicAngle']=(double)$param;
92
		elsif ($code=='Ascender')
93
			$fm['Ascender']=(int)$param;
94
		elsif ($code=='Descender')
95
			$fm['Descender']=(int)$param;
96
		elsif ($code=='UnderlineThickness')
97
			$fm['UnderlineThickness']=(int)$param;
98
		elsif ($code=='UnderlinePosition')
99
			$fm['UnderlinePosition']=(int)$param;
100
		elsif ($code=='IsFixedPitch')
101
			$fm['IsFixedPitch']=($param=='true');
102
		elsif ($code=='FontBBox')
103
			$fm['FontBBox']=Hash.new($e[1],$e[2],$e[3],$e[4]);
104
		elsif ($code=='CapHeight')
105
			$fm['CapHeight']=(int)$param;
106
		elsif ($code=='StdVW')
107
			$fm['StdVW']=(int)$param;
108
	end
109
	if (!$fm['FontName'].nil?)
110
		die('FontName not found');
111
	if (!$map.empty?)
112
	{
113
		if (!$widths['.notdef'].nil?)
114
			$widths['.notdef']=600;
115
		if (!$widths['Delta'].nil? and $widths['increment'].nil?)
116
			$widths['Delta']=$widths['increment'];
117
		#Order widths according to map
118
		for($i=0;$i<=255;$i++)
119
		{
120
			if (!$widths[$map[$i]].nil?)
121
			{
122
				echo '<B>Warning:</B> character '.$map[$i].' is missing<BR>';
123
				$widths[$i]=$widths['.notdef'];
124
			else
125
				$widths[$i]=$widths[$map[$i]];
126
		end
127
	end
128
	$fm['Widths']=$widths;
129
	return $fm;
130
}
131

    
132
function MakeFontDescriptor($fm,$symbolic)
133
{
134
	#Ascent
135
	$asc=($fm['Ascender'].nil? ? $fm['Ascender'] : 1000);
136
	$fd="Hash.new('Ascent'=>".$asc;
137
	#Descent
138
	$desc=($fm['Descender'].nil? ? $fm['Descender'] : -200);
139
	$fd<<",'Descent'=>".$desc;
140
	#CapHeight
141
	if ($fm['CapHeight'].nil?)
142
		$ch=$fm['CapHeight'];
143
	elsif ($fm['CapXHeight'].nil?)
144
		$ch=$fm['CapXHeight'];
145
	else
146
		$ch=$asc;
147
	$fd<<",'CapHeight'=>".$ch;
148
	#Flags
149
	$flags=0;
150
	if ($fm['IsFixedPitch'].nil? and $fm['IsFixedPitch'])
151
		$flags+=1<<0;
152
	if ($symbolic)
153
		$flags+=1<<2;
154
	if (!$symbolic)
155
		$flags+=1<<5;
156
	if ($fm['ItalicAngle'].nil? and $fm['ItalicAngle']!=0)
157
		$flags+=1<<6;
158
	$fd<<",'Flags'=>".$flags;
159
	#FontBBox
160
	if ($fm['FontBBox'].nil?)
161
		$fbb=$fm['FontBBox'];
162
	else
163
		$fbb=Hash.new(0,$des-100,1000,$asc+100);
164
	$fd<<",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
165
	#ItalicAngle
166
	$ia=($fm['ItalicAngle'].nil? ? $fm['ItalicAngle'] : 0);
167
	$fd<<",'ItalicAngle'=>".$ia;
168
	#StemV
169
	if ($fm['StdVW'].nil?)
170
		$stemv=$fm['StdVW'];
171
	elsif ($fm['Weight'].nil? and eregi('(bold|black)',$fm['Weight']))
172
		$stemv=120;
173
	else
174
		$stemv=70;
175
	$fd<<",'StemV'=>".$stemv;
176
	#MissingWidth
177
	if ($fm['MissingWidth'].nil?)
178
		$fd<<",'MissingWidth'=>".$fm['MissingWidth'];
179
	$fd<<')';
180
	return $fd;
181
}
182

    
183
function MakeWidthArray($fm)
184
{
185
	#Make character width array
186
	$s="Hash.new(\n\t";
187
	$cw=$fm['Widths'];
188
	for($i=0;$i<=255;$i++)
189
	{
190
		if ($i.chr=="'")
191
			$s<<"'\\''";
192
		elsif ($i.chr=="\\")
193
			$s<<"'\\\\'";
194
		elsif ($i>=32 and $i<=126)
195
			$s<<"'".$i.chr."'";
196
		else
197
			$s<<"$i.chr";
198
		$s<<'=>'.$fm['Widths'][$i];
199
		if ($i<255)
200
			$s<<',';
201
		if (($i+1)%22==0)
202
			$s<<"\n\t";
203
	end
204
	$s<<')';
205
	return $s;
206
}
207

    
208
function MakeFontEncoding($map)
209
{
210
	#Build differences from reference encoding
211
	$ref=ReadMap('cp1252');
212
	$s='';
213
	$last=0;
214
	for($i=32;$i<=255;$i++)
215
	{
216
		if ($map[$i]!=$ref[$i])
217
		{
218
			if ($i!=$last+1)
219
				$s<<$i.' ';
220
			$last=$i;
221
			$s<<'/'.$map[$i].' ';
222
		end
223
	end
224
	return rtrim($s);
225
}
226

    
227
function SaveToFile($file,$s,$mode='t')
228
{
229
	$f=fopen($file,'w'.$mode);
230
	if (!$f)
231
		die('Can\'t write to file '.$file);
232
	fwrite($f,$s,$s.length);
233
	fclose($f);
234
}
235

    
236
function ReadShort($f)
237
{
238
	$a=unpack('n1n',fread($f,2));
239
	return $a['n'];
240
}
241

    
242
function ReadLong($f)
243
{
244
	$a=unpack('N1N',fread($f,4));
245
	return $a['N'];
246
}
247

    
248
function CheckTTF($file)
249
{
250
	#Check if font license allows embedding
251
	$f=fopen($file,'rb');
252
	if (!$f)
253
		die('<B>Error:</B> Can\'t open '.$file);
254
	#Extract number of tables
255
	fseek($f,4,SEEK_CUR);
256
	$nb=ReadShort($f);
257
	fseek($f,6,SEEK_CUR);
258
	#Seek OS/2 table
259
	$found=false;
260
	for($i=0;$i<$nb;$i++)
261
	{
262
		if (fread($f,4)=='OS/2')
263
		{
264
			$found=true;
265
			break;
266
		end
267
		fseek($f,12,SEEK_CUR);
268
	end
269
	if (!$found)
270
	{
271
		fclose($f);
272
		return;
273
	end
274
	fseek($f,4,SEEK_CUR);
275
	$offset=ReadLong($f);
276
	fseek($f,$offset,SEEK_SET);
277
	#Extract fsType flags
278
	fseek($f,8,SEEK_CUR);
279
	$fsType=ReadShort($f);
280
	$rl=($fsType & 0x02)!=0;
281
	$pp=($fsType & 0x04)!=0;
282
	$e=($fsType & 0x08)!=0;
283
	fclose($f);
284
	if ($rl and !$pp and !$e)
285
		echo '<B>Warning:</B> font license does not allow embedding';
286
}
287

    
288
#*****************************************************************************
289
# $fontfile : chemin du fichier TTF (ou cha?ne vide si pas d'incorporation)   #
290
# $afmfile :  chemin du fichier AFM                                           #
291
# $enc :      encodage (ou cha?ne vide si la police est symbolique)           #
292
# $patch :    patch optionnel pour l'encodage                                 #
293
# $type :     type de la police si $fontfile est vide                         #
294
******************************************************************************#
295
function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=Hash.new(),$type='TrueType')
296
{
297
	#Generate a font definition file
298
	set_magic_quotes_runtime(0);
299
	ini_set('auto_detect_line_endings','1');
300
	if ($enc)
301
	{
302
		$map=ReadMap($enc);
303
		foreach($patch as $cc=>$gn)
304
			$map[$cc]=$gn;
305
	end
306
	else
307
		$map = []
308
	if (!file_exists($afmfile))
309
		die('<B>Error:</B> AFM file not found: '.$afmfile);
310
	$fm=ReadAFM($afmfile,$map);
311
	if ($enc)
312
		$diff=MakeFontEncoding($map);
313
	else
314
		$diff='';
315
	$fd=MakeFontDescriptor($fm,$map.empty?);
316
	#Find font type
317
	if ($fontfile)
318
	{
319
		$ext=strtolower(substr($fontfile,-3));
320
		if ($ext=='ttf')
321
			$type='TrueType';
322
		elsif ($ext=='pfb')
323
			$type='Type1';
324
		else
325
			die('<B>Error:</B> unrecognized font file extension: '.$ext);
326
	end
327
	else
328
	{
329
		if ($type!='TrueType' and $type!='Type1')
330
			die('<B>Error:</B> incorrect font type: '.$type);
331
	end
332
	#Start generation
333
	$s=''."\n";
334
	$s<<'$type=\''.$type."';\n";
335
	$s<<'$name=\''.$fm['FontName']."';\n";
336
	$s<<'$desc='.$fd.";\n";
337
	if (!$fm['UnderlinePosition'].nil?)
338
		$fm['UnderlinePosition']=-100;
339
	if (!$fm['UnderlineThickness'].nil?)
340
		$fm['UnderlineThickness']=50;
341
	$s<<'$up='.$fm['UnderlinePosition'].";\n";
342
	$s<<'$ut='.$fm['UnderlineThickness'].";\n";
343
	$w=MakeWidthArray($fm);
344
	$s<<'$cw='.$w.";\n";
345
	$s<<'$enc=\''.$enc."';\n";
346
	$s<<'$diff=\''.$diff."';\n";
347
	$basename=substr(basename($afmfile),0,-4);
348
	if ($fontfile)
349
	{
350
		#Embedded font
351
		if (!file_exists($fontfile))
352
			die('<B>Error:</B> font file not found: '.$fontfile);
353
		if ($type=='TrueType')
354
			CheckTTF($fontfile);
355
		$f=fopen($fontfile,'rb');
356
		if (!$f)
357
			die('<B>Error:</B> Can\'t open '.$fontfile);
358
		$file=fread($f,filesize($fontfile));
359
		fclose($f);
360
		if ($type=='Type1')
361
		{
362
			#Find first two sections and discard third one
363
			$header=($file[0][0]==128);
364
			if ($header)
365
			{
366
				#Strip first binary header
367
				$file=substr($file,6);
368
			end
369
			$pos=$file.include?('eexec');
370
			if (!$pos)
371
				die('<B>Error:</B> font file does not seem to be valid Type1');
372
			$size1=$pos+6;
373
			if ($header and ?($file{$size1})==128)
374
			{
375
				#Strip second binary header
376
				$file=substr($file,0,$size1).substr($file,$size1+6);
377
			end
378
			$pos=$file.include?('00000000');
379
			if (!$pos)
380
				die('<B>Error:</B> font file does not seem to be valid Type1');
381
			$size2=$pos-$size1;
382
			$file=substr($file,0,$size1+$size2);
383
		end
384
		if (respond_to('gzcompress'))
385
		{
386
			$cmp=$basename.'.z';
387
			SaveToFile($cmp,gzcompress($file),'b');
388
			$s<<'$file=\''.$cmp."';\n";
389
			echo 'Font file compressed ('.$cmp.')<BR>';
390
		else
391
		{
392
			$s<<'$file=\''.basename($fontfile)."';\n";
393
			echo '<B>Notice:</B> font file could not be compressed (zlib extension not available)<BR>';
394
		end
395
		if ($type=='Type1')
396
		{
397
			$s<<'$size1='.$size1.";\n";
398
			$s<<'$size2='.$size2.";\n";
399
		else
400
			$s<<'$originalsize='.filesize($fontfile).";\n";
401
	end
402
	else
403
	{
404
		#Not embedded font
405
		$s<<'$file='."'';\n";
406
	end
407
	$s<<"\n";
408
	SaveToFile($basename.'.rb',$s);
409
	echo 'Font definition file generated ('.$basename.'.rb'.')<BR>';
410
}
411