396 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			396 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
| <?php
 | |
| /****************************************************************************
 | |
| * Utility to generate font definition files                                 *
 | |
| * Version: 1.11                                                             *
 | |
| * Date:    2002-11-02                                                       *
 | |
| ****************************************************************************/
 | |
| 
 | |
| function ReadMap($enc)
 | |
| {
 | |
| 	//Read a map file
 | |
| 	$file=dirname(__FILE__).'/'.strtolower($enc).'.map';
 | |
| 	$a=file($file);
 | |
| 	if(empty($a))
 | |
| 		die('<B>Error:</B> encoding not found: '.$enc);
 | |
| 	$cc2gn=array();
 | |
| 	foreach($a as $l)
 | |
| 	{
 | |
| 		$e=explode(' ',chop($l));
 | |
| 		$cc=hexdec(substr($e[0],1));
 | |
| 		$gn=$e[2];
 | |
| 		$cc2gn[$cc]=$gn;
 | |
| 	}
 | |
| 	for($i=0;$i<=255;$i++)
 | |
| 		if(!isset($cc2gn[$i]))
 | |
| 			$cc2gn[$i]='.notdef';
 | |
| 	return $cc2gn;
 | |
| }
 | |
| 
 | |
| function ReadAFM($file,&$map)
 | |
| {
 | |
| 	//Read a font metric file
 | |
| 	$a=file($file);
 | |
| 	if(empty($a))
 | |
| 		die('File not found');
 | |
| 	$widths=array();
 | |
| 	$fm=array();
 | |
| 	$fix=array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent',
 | |
| 		'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut',
 | |
| 		'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent',
 | |
| 		'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent',
 | |
| 		'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent',
 | |
| 		'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat');
 | |
| 	foreach($a as $l)
 | |
| 	{
 | |
| 		$e=explode(' ',chop($l));
 | |
| 		if(count($e)<2)
 | |
| 			continue;
 | |
| 		$code=$e[0];
 | |
| 		$param=$e[1];
 | |
| 		if($code=='C')
 | |
| 		{
 | |
| 			//Character metrics
 | |
| 			$cc=(int)$e[1];
 | |
| 			$w=$e[4];
 | |
| 			$gn=$e[7];
 | |
| 			if(substr($gn,-4)=='20AC')
 | |
| 				$gn='Euro';
 | |
| 			if(isset($fix[$gn]))
 | |
| 			{
 | |
| 				//Fix incorrect glyph name
 | |
| 				foreach($map as $c=>$n)
 | |
| 					if($n==$fix[$gn])
 | |
| 						$map[$c]=$gn;
 | |
| 			}
 | |
| 			if(empty($map))
 | |
| 			{
 | |
| 				//Symbolic font: use built-in encoding
 | |
| 				$widths[$cc]=$w;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				$widths[$gn]=$w;
 | |
| 				if($gn=='X')
 | |
| 					$fm['CapXHeight']=$e[13];
 | |
| 			}
 | |
| 			if($gn=='.notdef')
 | |
| 				$fm['MissingWidth']=$w;
 | |
| 		}
 | |
| 		elseif($code=='FontName')
 | |
| 			$fm['FontName']=$param;
 | |
| 		elseif($code=='Weight')
 | |
| 			$fm['Weight']=$param;
 | |
| 		elseif($code=='ItalicAngle')
 | |
| 			$fm['ItalicAngle']=(double)$param;
 | |
| 		elseif($code=='Ascender')
 | |
| 			$fm['Ascender']=(int)$param;
 | |
| 		elseif($code=='Descender')
 | |
| 			$fm['Descender']=(int)$param;
 | |
| 		elseif($code=='UnderlineThickness')
 | |
| 			$fm['UnderlineThickness']=(int)$param;
 | |
| 		elseif($code=='UnderlinePosition')
 | |
| 			$fm['UnderlinePosition']=(int)$param;
 | |
| 		elseif($code=='IsFixedPitch')
 | |
| 			$fm['IsFixedPitch']=($param=='true');
 | |
| 		elseif($code=='FontBBox')
 | |
| 			$fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
 | |
| 		elseif($code=='CapHeight')
 | |
| 			$fm['CapHeight']=(int)$param;
 | |
| 		elseif($code=='StdVW')
 | |
| 			$fm['StdVW']=(int)$param;
 | |
| 	}
 | |
| 	if(!isset($fm['FontName']))
 | |
| 		die('FontName not found');
 | |
| 	if(!empty($map))
 | |
| 	{
 | |
| 		if(!isset($widths['.notdef']))
 | |
| 			$widths['.notdef']=600;
 | |
| 		if(!isset($widths['Delta']) and isset($widths['increment']))
 | |
| 			$widths['Delta']=$widths['increment'];
 | |
| 		//Order widths according to map
 | |
| 		for($i=0;$i<=255;$i++)
 | |
| 		{
 | |
| 			if(!isset($widths[$map[$i]]))
 | |
| 			{
 | |
| 				echo '<B>Warning:</B> character '.$map[$i].' is missing<BR>';
 | |
| 				$widths[$i]=$widths['.notdef'];
 | |
| 			}
 | |
| 			else
 | |
| 				$widths[$i]=$widths[$map[$i]];
 | |
| 		}
 | |
| 	}
 | |
| 	$fm['Widths']=$widths;
 | |
| 	return $fm;
 | |
| }
 | |
| 
 | |
| function MakeFontDescriptor($fm,$symbolic)
 | |
| {
 | |
| 	//Ascent
 | |
| 	$asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
 | |
| 	$fd="array('Ascent'=>".$asc;
 | |
| 	//Descent
 | |
| 	$desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
 | |
| 	$fd.=",'Descent'=>".$desc;
 | |
| 	//CapHeight
 | |
| 	if(isset($fm['CapHeight']))
 | |
| 		$ch=$fm['CapHeight'];
 | |
| 	elseif(isset($fm['CapXHeight']))
 | |
| 		$ch=$fm['CapXHeight'];
 | |
| 	else
 | |
| 		$ch=$asc;
 | |
| 	$fd.=",'CapHeight'=>".$ch;
 | |
| 	//Flags
 | |
| 	$flags=0;
 | |
| 	if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
 | |
| 		$flags+=1<<0;
 | |
| 	if($symbolic)
 | |
| 		$flags+=1<<2;
 | |
| 	if(!$symbolic)
 | |
| 		$flags+=1<<5;
 | |
| 	if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
 | |
| 		$flags+=1<<6;
 | |
| 	$fd.=",'Flags'=>".$flags;
 | |
| 	//FontBBox
 | |
| 	if(isset($fm['FontBBox']))
 | |
| 		$fbb=$fm['FontBBox'];
 | |
| 	else
 | |
| 		$fbb=array(0,$des-100,1000,$asc+100);
 | |
| 	$fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
 | |
| 	//ItalicAngle
 | |
| 	$ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
 | |
| 	$fd.=",'ItalicAngle'=>".$ia;
 | |
| 	//StemV
 | |
| 	if(isset($fm['StdVW']))
 | |
| 		$stemv=$fm['StdVW'];
 | |
| 	elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
 | |
| 		$stemv=120;
 | |
| 	else
 | |
| 		$stemv=70;
 | |
| 	$fd.=",'StemV'=>".$stemv;
 | |
| 	//MissingWidth
 | |
| 	if(isset($fm['MissingWidth']))
 | |
| 		$fd.=",'MissingWidth'=>".$fm['MissingWidth'];
 | |
| 	$fd.=')';
 | |
| 	return $fd;
 | |
| }
 | |
| 
 | |
| function MakeWidthArray($fm)
 | |
| {
 | |
| 	//Make character width array
 | |
| 	$s="array(\n\t";
 | |
| 	$cw=$fm['Widths'];
 | |
| 	for($i=0;$i<=255;$i++)
 | |
| 	{
 | |
| 		if(chr($i)=="'")
 | |
| 			$s.="'\\''";
 | |
| 		elseif(chr($i)=="\\")
 | |
| 			$s.="'\\\\'";
 | |
| 		elseif($i>=32 and $i<=126)
 | |
| 			$s.="'".chr($i)."'";
 | |
| 		else
 | |
| 			$s.="chr($i)";
 | |
| 		$s.="=>".$fm['Widths'][$i];
 | |
| 		if($i<255)
 | |
| 			$s.=",";
 | |
| 		if(($i+1)%22==0)
 | |
| 			$s.="\n\t";
 | |
| 	}
 | |
| 	$s.=")";
 | |
| 	return $s;
 | |
| }
 | |
| 
 | |
| function MakeFontEncoding($map)
 | |
| {
 | |
| 	//Build differences from reference encoding
 | |
| 	$ref=ReadMap('cp1252');
 | |
| 	$s='';
 | |
| 	$last=0;
 | |
| 	for($i=32;$i<=255;$i++)
 | |
| 	{
 | |
| 		if($map[$i]!=$ref[$i])
 | |
| 		{
 | |
| 			if($i!=$last+1)
 | |
| 				$s.=$i.' ';
 | |
| 			$last=$i;
 | |
| 			$s.='/'.$map[$i].' ';
 | |
| 		}
 | |
| 	}
 | |
| 	return chop($s);
 | |
| }
 | |
| 
 | |
| function SaveToFile($file,$s,$mode='t')
 | |
| {
 | |
| 	$f=fopen($file,'w'.$mode);
 | |
| 	if(!$f)
 | |
| 		die('Can\'t write to file '.$file);
 | |
| 	fwrite($f,$s,strlen($s));
 | |
| 	fclose($f);
 | |
| }
 | |
| 
 | |
| function ReadShort($f)
 | |
| {
 | |
| 	$a=unpack('n1n',fread($f,2));
 | |
| 	return $a['n'];
 | |
| }
 | |
| 
 | |
| function ReadLong($f)
 | |
| {
 | |
| 	$a=unpack('N1N',fread($f,4));
 | |
| 	return $a['N'];
 | |
| }
 | |
| 
 | |
| function CheckTTF($file)
 | |
| {
 | |
| 	//Check if font license allows embedding
 | |
| 	$f=fopen($file,'rb');
 | |
| 	if(!$f)
 | |
| 		die('<B>Error:</B> Can\'t open '.$file);
 | |
| 	//Extract number of tables
 | |
| 	fseek($f,4,SEEK_CUR);
 | |
| 	$nb=ReadShort($f);
 | |
| 	fseek($f,6,SEEK_CUR);
 | |
| 	//Seek OS/2 table
 | |
| 	$found=false;
 | |
| 	for($i=0;$i<$nb;$i++)
 | |
| 	{
 | |
| 		if(fread($f,4)=='OS/2')
 | |
| 		{
 | |
| 			$found=true;
 | |
| 			break;
 | |
| 		}
 | |
| 		fseek($f,12,SEEK_CUR);
 | |
| 	}
 | |
| 	if(!$found)
 | |
| 	{
 | |
| 		fclose($f);
 | |
| 		return;
 | |
| 	}
 | |
| 	fseek($f,4,SEEK_CUR);
 | |
| 	$offset=ReadLong($f);
 | |
| 	fseek($f,$offset,SEEK_SET);
 | |
| 	//Extract fsType flags
 | |
| 	fseek($f,8,SEEK_CUR);
 | |
| 	$fsType=ReadShort($f);
 | |
| 	$rl=($fsType & 0x02)!=0;
 | |
| 	$pp=($fsType & 0x04)!=0;
 | |
| 	$e=($fsType & 0x08)!=0;
 | |
| 	fclose($f);
 | |
| 	if($rl and !$pp and !$e)
 | |
| 		echo '<B>Warning:</B> font license does not allow embedding';
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
| * $fontfile: path to TTF file (or empty string if not to be embedded)       *
 | |
| * $afmfile:  path to AFM file                                               *
 | |
| * $enc:      font encoding (or empty string for symbolic fonts)             *
 | |
| * $patch:    optional patch for encoding                                    *
 | |
| * $type :    font type if $fontfile is empty                                *
 | |
| ****************************************************************************/
 | |
| function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=array(),$type='TrueType')
 | |
| {
 | |
| 	//Generate a font definition file
 | |
| 	set_magic_quotes_runtime(0);
 | |
| 	if($enc)
 | |
| 	{
 | |
| 		$map=ReadMap($enc);
 | |
| 		foreach($patch as $cc=>$gn)
 | |
| 			$map[$cc]=$gn;
 | |
| 	}
 | |
| 	else
 | |
| 		$map=array();
 | |
| 	if(!file_exists($afmfile))
 | |
| 		die('<B>Error:</B> AFM file not found: '.$afmfile);
 | |
| 	$fm=ReadAFM($afmfile,$map);
 | |
| 	if($enc)
 | |
| 		$diff=MakeFontEncoding($map);
 | |
| 	else
 | |
| 		$diff='';
 | |
| 	$fd=MakeFontDescriptor($fm,empty($map));
 | |
| 	//Find font type
 | |
| 	if($fontfile)
 | |
| 	{
 | |
| 		$ext=strtolower(substr($fontfile,-3));
 | |
| 		if($ext=='ttf')
 | |
| 			$type='TrueType';
 | |
| 		elseif($ext=='pfb')
 | |
| 			$type='Type1';
 | |
| 		else
 | |
| 			die('<B>Error:</B> unrecognized font file extension: '.$ext);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		if($type!='TrueType' and $type!='Type1')
 | |
| 			die('<B>Error:</B> incorrect font type: '.$type);
 | |
| 	}
 | |
| 	//Start generation
 | |
| 	$s='<?php'."\n";
 | |
| 	$s.='$type=\''.$type."';\n";
 | |
| 	$s.='$name=\''.$fm['FontName']."';\n";
 | |
| 	$s.='$desc='.$fd.";\n";
 | |
| 	if(!isset($fm['UnderlinePosition']))
 | |
| 		$fm['UnderlinePosition']=-100;
 | |
| 	if(!isset($fm['UnderlineThickness']))
 | |
| 		$fm['UnderlineThickness']=50;
 | |
| 	$s.='$up='.$fm['UnderlinePosition'].";\n";
 | |
| 	$s.='$ut='.$fm['UnderlineThickness'].";\n";
 | |
| 	$w=MakeWidthArray($fm);
 | |
| 	$s.='$cw='.$w.";\n";
 | |
| 	$s.='$enc=\''.$enc."';\n";
 | |
| 	$s.='$diff=\''.$diff."';\n";
 | |
| 	$basename=substr(basename($afmfile),0,-4);
 | |
| 	if($fontfile)
 | |
| 	{
 | |
| 		//Embedded font
 | |
| 		if(!file_exists($fontfile))
 | |
| 			die('<B>Error:</B> font file not found: '.$fontfile);
 | |
| 		if($type=='TrueType')
 | |
| 			CheckTTF($fontfile);
 | |
| 		$f=fopen($fontfile,'rb');
 | |
| 		if(!$f)
 | |
| 			die('<B>Error:</B> Can\'t open '.$fontfile);
 | |
| 		$file=fread($f,filesize($fontfile));
 | |
| 		fclose($f);
 | |
| 		if($type=='Type1')
 | |
| 		{
 | |
| 			//Find first two sections and discard third one
 | |
| 			$pos=strpos($file,'eexec');
 | |
| 			if(!$pos)
 | |
| 				die('<B>Error:</B> font file does not seem to be valid Type1');
 | |
| 			$size1=$pos+6;
 | |
| 			$pos=strpos($file,'00000000');
 | |
| 			if(!$pos)
 | |
| 				die('<B>Error:</B> font file does not seem to be valid Type1');
 | |
| 			$size2=$pos-$size1;
 | |
| 			$file=substr($file,0,$size1+$size2);
 | |
| 		}
 | |
| 		if(function_exists('gzcompress'))
 | |
| 		{
 | |
| 			$cmp=$basename.'.z';
 | |
| 			SaveToFile($cmp,gzcompress($file),'b');
 | |
| 			$s.='$file=\''.$cmp."';\n";
 | |
| 			echo 'Font file compressed ('.$cmp.')<BR>';
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$s.='$file=\''.basename($fontfile)."';\n";
 | |
| 			echo '<B>Notice:</B> font file could not be compressed (gzcompress not available)<BR>';
 | |
| 		}
 | |
| 		if($type=='Type1')
 | |
| 		{
 | |
| 			$s.='$size1='.$size1.";\n";
 | |
| 			$s.='$size2='.$size2.";\n";
 | |
| 		}
 | |
| 		else
 | |
| 			$s.='$originalsize='.filesize($fontfile).";\n";
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		//Not embedded font
 | |
| 		$s.='$file='."'';\n";
 | |
| 	}
 | |
| 	$s.="?>\n";
 | |
| 	SaveToFile($basename.'.php',$s);
 | |
| 	echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
 | |
| }
 | |
| ?>
 |