To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
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 |
|