Error: encoding not found: '.$enc);
}
$cc2gn=array();
foreach ($a as $l) {
if ($l[0]=='!') {
$e=preg_split('/[ \\t]+/', rtrim($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',
'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb',
'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong');
foreach ($a as $l) {
$e=explode(' ', rtrim($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']=(float)$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']) && isset($widths['increment'])) {
$widths['Delta']=$widths['increment'];
}
//Order widths according to map
for ($i=0;$i<=255;$i++) {
if (!isset($widths[$map[$i]])) {
echo 'Warning: character '.$map[$i].' is missing
';
$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']) && $fm['IsFixedPitch']) {
$flags+=1<<0;
}
if ($symbolic) {
$flags+=1<<2;
}
if (!$symbolic) {
$flags+=1<<5;
}
if (isset($fm['ItalicAngle']) && $fm['ItalicAngle']!=0) {
$flags+=1<<6;
}
$fd.=",'Flags'=>".$flags;
//FontBBox
if (isset($fm['FontBBox'])) {
$fbb=$fm['FontBBox'];
} else {
$fbb=array(0,$desc-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']) && preg_match('/bold|black/i', $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 && $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 rtrim($s);
}
function SaveToFile($file, $s, $mode)
{
$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('Error: 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 && !$pp && !$e) {
echo 'Warning: 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
if (false) {
/* magic quotes: removed in PHP 8.0, and a no-op since 5.4 */ ;
}
ini_set('auto_detect_line_endings', '1');
if ($enc) {
$map=ReadMap($enc);
foreach ($patch as $cc=>$gn) {
$map[$cc]=$gn;
}
} else {
$map=array();
}
if (!file_exists($afmfile)) {
die('Error: 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('Error: unrecognized font file extension: '.$ext);
}
} else {
if ($type!='TrueType' && $type!='Type1') {
die('Error: incorrect font type: '.$type);
}
}
//Start generation
$s='Error: font file not found: '.$fontfile);
}
if ($type=='TrueType') {
CheckTTF($fontfile);
}
$f=fopen($fontfile, 'rb');
if (!$f) {
die('Error: Can\'t open '.$fontfile);
}
$file=fread($f, filesize($fontfile));
fclose($f);
if ($type=='Type1') {
//Find first two sections and discard third one
$header=(ord($file[0])==128);
if ($header) {
//Strip first binary header
$file=substr($file, 6);
}
$pos=strpos($file, 'eexec');
if (!$pos) {
die('Error: font file does not seem to be valid Type1');
}
$size1=$pos+6;
if ($header && ord($file[$size1])==128) {
//Strip second binary header
$file=substr($file, 0, $size1).substr($file, $size1+6);
}
$pos=strpos($file, '00000000');
if (!$pos) {
die('Error: 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.')
';
} else {
$s.='$file=\''.basename($fontfile)."';\n";
echo 'Notice: font file could not be compressed (zlib extension not available)
';
}
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, 't');
echo 'Font definition file generated ('.$basename.'.php'.')
';
}