makefont.php ➔ MakeFont()   F
last analyzed

Complexity

Conditions 24
Paths 2698

Size

Total Lines 118

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 24
nc 2698
nop 5
dl 0
loc 118
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
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=__DIR__.'/'.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
    if($l{0}=='!')
19
    {
20
      $e=preg_split('/[ \\t]+/',rtrim($l));
21
      $cc=hexdec(substr($e[0],1));
22
      $gn=$e[2];
23
      $cc2gn[$cc]=$gn;
24
    }
25
  }
26
  for($i=0;$i<=255;$i++)
27
  {
28
    if(!isset($cc2gn[$i]))
29
      $cc2gn[$i]='.notdef';
30
  }
31
32
  return $cc2gn;
33
}
34
35
function ReadAFM($file,&$map)
36
{
37
  //Read a font metric file
38
  $a=file($file);
39
  if(empty($a))
40
    die('File not found');
41
  $widths=array();
42
  $fm=array();
43
  $fix=array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent',
44
    'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut',
45
    'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent',
46
    'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent',
47
    'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent',
48
    'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat',
49
    'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb',
50
    'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong');
51
  foreach($a as $l)
52
  {
53
    $e=explode(' ',rtrim($l));
54
    if(count($e)<2)
55
      continue;
56
    $code=$e[0];
57
    $param=$e[1];
58
    if($code=='C')
59
    {
60
      //Character metrics
61
      $cc=(int)$e[1];
62
      $w=$e[4];
63
      $gn=$e[7];
64
      if(substr($gn,-4)=='20AC')
65
        $gn='Euro';
66
      if(isset($fix[$gn]))
67
      {
68
        //Fix incorrect glyph name
69
        foreach($map as $c=>$n)
70
        {
71
          if($n==$fix[$gn])
72
            $map[$c]=$gn;
73
        }
74
      }
75
      if(empty($map))
76
      {
77
        //Symbolic font: use built-in encoding
78
        $widths[$cc]=$w;
79
      }
80
      else
81
      {
82
        $widths[$gn]=$w;
83
        if($gn=='X')
84
          $fm['CapXHeight']=$e[13];
85
      }
86
      if($gn=='.notdef')
87
        $fm['MissingWidth']=$w;
88
    }
89
    elseif($code=='FontName')
90
      $fm['FontName']=$param;
91
    elseif($code=='Weight')
92
      $fm['Weight']=$param;
93
    elseif($code=='ItalicAngle')
94
      $fm['ItalicAngle']=(double)$param;
95
    elseif($code=='Ascender')
96
      $fm['Ascender']=(int)$param;
97
    elseif($code=='Descender')
98
      $fm['Descender']=(int)$param;
99
    elseif($code=='UnderlineThickness')
100
      $fm['UnderlineThickness']=(int)$param;
101
    elseif($code=='UnderlinePosition')
102
      $fm['UnderlinePosition']=(int)$param;
103
    elseif($code=='IsFixedPitch')
104
      $fm['IsFixedPitch']=($param=='true');
105
    elseif($code=='FontBBox')
106
      $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
107
    elseif($code=='CapHeight')
108
      $fm['CapHeight']=(int)$param;
109
    elseif($code=='StdVW')
110
      $fm['StdVW']=(int)$param;
111
  }
112
  if(!isset($fm['FontName']))
113
    die('FontName not found');
114
  if(!empty($map))
115
  {
116
    if(!isset($widths['.notdef']))
117
      $widths['.notdef']=600;
118
    if(!isset($widths['Delta']) and isset($widths['increment']))
119
      $widths['Delta']=$widths['increment'];
120
    //Order widths according to map
121
    for($i=0;$i<=255;$i++)
122
    {
123
      if(!isset($widths[$map[$i]]))
124
      {
125
        echo '<B>Warning:</B> character '.$map[$i].' is missing<BR>';
126
        $widths[$i]=$widths['.notdef'];
127
      }
128
      else
129
        $widths[$i]=$widths[$map[$i]];
130
    }
131
  }
132
  $fm['Widths']=$widths;
133
134
  return $fm;
135
}
136
137
function MakeFontDescriptor($fm,$symbolic)
138
{
139
  //Ascent
140
  $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
141
  $fd="array('Ascent'=>".$asc;
142
  //Descent
143
  $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
144
  $fd.=",'Descent'=>".$desc;
145
  //CapHeight
146
  if(isset($fm['CapHeight']))
147
    $ch=$fm['CapHeight'];
148
  elseif(isset($fm['CapXHeight']))
149
    $ch=$fm['CapXHeight'];
150
  else
151
    $ch=$asc;
152
  $fd.=",'CapHeight'=>".$ch;
153
  //Flags
154
  $flags=0;
155
  if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
156
    $flags+=1<<0;
157
  if($symbolic)
158
    $flags+=1<<2;
159
  if(!$symbolic)
160
    $flags+=1<<5;
161
  if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
162
    $flags+=1<<6;
163
  $fd.=",'Flags'=>".$flags;
164
  //FontBBox
165
  if(isset($fm['FontBBox']))
166
    $fbb=$fm['FontBBox'];
167
  else
168
    $fbb=array(0,$des-100,1000,$asc+100);
0 ignored issues
show
Bug introduced by
The variable $des does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
169
  $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
170
  //ItalicAngle
171
  $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
172
  $fd.=",'ItalicAngle'=>".$ia;
173
  //StemV
174
  if(isset($fm['StdVW']))
175
    $stemv=$fm['StdVW'];
176
  elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
177
    $stemv=120;
178
  else
179
    $stemv=70;
180
  $fd.=",'StemV'=>".$stemv;
181
  //MissingWidth
182
  if(isset($fm['MissingWidth']))
183
    $fd.=",'MissingWidth'=>".$fm['MissingWidth'];
184
  $fd.=')';
185
186
  return $fd;
187
}
188
189
function MakeWidthArray($fm)
190
{
191
  //Make character width array
192
  $s="array(\n\t";
193
  $cw=$fm['Widths'];
0 ignored issues
show
Unused Code introduced by
$cw is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
194
  for($i=0;$i<=255;$i++)
195
  {
196
    if(chr($i)=="'")
197
      $s.="'\\''";
198
    elseif(chr($i)=="\\")
199
      $s.="'\\\\'";
200
    elseif($i>=32 and $i<=126)
201
      $s.="'".chr($i)."'";
202
    else
203
      $s.="chr($i)";
204
    $s.='=>'.$fm['Widths'][$i];
205
    if($i<255)
206
      $s.=',';
207
    if(($i+1)%22==0)
208
      $s.="\n\t";
209
  }
210
  $s.=')';
211
212
  return $s;
213
}
214
215
function MakeFontEncoding($map)
216
{
217
  //Build differences from reference encoding
218
  $ref=ReadMap('cp1252');
219
  $s='';
220
  $last=0;
221
  for($i=32;$i<=255;$i++)
222
  {
223
    if($map[$i]!=$ref[$i])
224
    {
225
      if($i!=$last+1)
226
        $s.=$i.' ';
227
      $last=$i;
228
      $s.='/'.$map[$i].' ';
229
    }
230
  }
231
232
  return rtrim($s);
233
}
234
235
function SaveToFile($file,$s,$mode='t')
236
{
237
  $f=fopen($file,'w'.$mode);
238
  if(!$f)
239
    die('Can\'t write to file '.$file);
240
  fwrite($f,$s,strlen($s));
241
  fclose($f);
242
}
243
244
function ReadShort($f)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
245
{
246
  $a=unpack('n1n',fread($f,2));
247
248
  return $a['n'];
249
}
250
251
function ReadLong($f)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
252
{
253
  $a=unpack('N1N',fread($f,4));
254
255
  return $a['N'];
256
}
257
258
function CheckTTF($file)
259
{
260
  //Check if font license allows embedding
261
  $f=fopen($file,'rb');
262
  if(!$f)
263
    die('<B>Error:</B> Can\'t open '.$file);
264
  //Extract number of tables
265
  fseek($f,4,SEEK_CUR);
266
  $nb=ReadShort($f);
267
  fseek($f,6,SEEK_CUR);
268
  //Seek OS/2 table
269
  $found=false;
270
  for($i=0;$i<$nb;$i++)
271
  {
272
    if(fread($f,4)=='OS/2')
273
    {
274
      $found=true;
275
      break;
276
    }
277
    fseek($f,12,SEEK_CUR);
278
  }
279
  if(!$found)
280
  {
281
    fclose($f);
282
283
    return;
284
  }
285
  fseek($f,4,SEEK_CUR);
286
  $offset=ReadLong($f);
287
  fseek($f,$offset,SEEK_SET);
288
  //Extract fsType flags
289
  fseek($f,8,SEEK_CUR);
290
  $fsType=ReadShort($f);
291
  $rl=($fsType & 0x02)!=0;
292
  $pp=($fsType & 0x04)!=0;
293
  $e=($fsType & 0x08)!=0;
294
  fclose($f);
295
  if($rl and !$pp and !$e)
296
    echo '<B>Warning:</B> font license does not allow embedding';
297
}
298
299
/*******************************************************************************
300
* $fontfile : chemin du fichier TTF (ou cha�ne vide si pas d'incorporation)    *
301
* $afmfile :  chemin du fichier AFM                                            *
302
* $enc :      encodage (ou cha�ne vide si la police est symbolique)            *
303
* $patch :    patch optionnel pour l'encodage                                  *
304
* $type :     type de la police si $fontfile est vide                          *
305
*******************************************************************************/
306
function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=array(),$type='TrueType')
307
{
308
  //Generate a font definition file
309
  set_magic_quotes_runtime(0);
310
  ini_set('auto_detect_line_endings','1');
311
  if($enc)
312
  {
313
    $map=ReadMap($enc);
314
    foreach($patch as $cc=>$gn)
315
      $map[$cc]=$gn;
316
  }
317
  else
318
    $map=array();
319
  if(!file_exists($afmfile))
320
    die('<B>Error:</B> AFM file not found: '.$afmfile);
321
  $fm=ReadAFM($afmfile,$map);
322
  if($enc)
323
    $diff=MakeFontEncoding($map);
324
  else
325
    $diff='';
326
  $fd=MakeFontDescriptor($fm,empty($map));
327
  //Find font type
328
  if($fontfile)
329
  {
330
    $ext=strtolower(substr($fontfile,-3));
331
    if($ext=='ttf')
332
      $type='TrueType';
333
    elseif($ext=='pfb')
334
      $type='Type1';
335
    else
336
      die('<B>Error:</B> unrecognized font file extension: '.$ext);
337
  }
338
  else
339
  {
340
    if($type!='TrueType' and $type!='Type1')
341
      die('<B>Error:</B> incorrect font type: '.$type);
342
  }
343
  //Start generation
344
  $s='<?php'."\n";
345
  $s.='$type=\''.$type."';\n";
346
  $s.='$name=\''.$fm['FontName']."';\n";
347
  $s.='$desc='.$fd.";\n";
348
  if(!isset($fm['UnderlinePosition']))
349
    $fm['UnderlinePosition']=-100;
350
  if(!isset($fm['UnderlineThickness']))
351
    $fm['UnderlineThickness']=50;
352
  $s.='$up='.$fm['UnderlinePosition'].";\n";
353
  $s.='$ut='.$fm['UnderlineThickness'].";\n";
354
  $w=MakeWidthArray($fm);
355
  $s.='$cw='.$w.";\n";
356
  $s.='$enc=\''.$enc."';\n";
357
  $s.='$diff=\''.$diff."';\n";
358
  $basename=substr(basename($afmfile),0,-4);
359
  if($fontfile)
360
  {
361
    //Embedded font
362
    if(!file_exists($fontfile))
363
      die('<B>Error:</B> font file not found: '.$fontfile);
364
    if($type=='TrueType')
365
      CheckTTF($fontfile);
366
    $f=fopen($fontfile,'rb');
367
    if(!$f)
368
      die('<B>Error:</B> Can\'t open '.$fontfile);
369
    $file=fread($f,filesize($fontfile));
370
    fclose($f);
371
    if($type=='Type1')
372
    {
373
      //Find first two sections and discard third one
374
      $header=(ord($file{0})==128);
375
      if($header)
376
      {
377
        //Strip first binary header
378
        $file=substr($file,6);
379
      }
380
      $pos=strpos($file,'eexec');
381
      if(!$pos)
382
        die('<B>Error:</B> font file does not seem to be valid Type1');
383
      $size1=$pos+6;
384
      if($header and ord($file{$size1})==128)
385
      {
386
        //Strip second binary header
387
        $file=substr($file,0,$size1).substr($file,$size1+6);
388
      }
389
      $pos=strpos($file,'00000000');
390
      if(!$pos)
391
        die('<B>Error:</B> font file does not seem to be valid Type1');
392
      $size2=$pos-$size1;
393
      $file=substr($file,0,$size1+$size2);
394
    }
395
    if(function_exists('gzcompress'))
396
    {
397
      $cmp=$basename.'.z';
398
      SaveToFile($cmp,gzcompress($file),'b');
399
      $s.='$file=\''.$cmp."';\n";
400
      echo 'Font file compressed ('.$cmp.')<BR>';
401
    }
402
    else
403
    {
404
      $s.='$file=\''.basename($fontfile)."';\n";
405
      echo '<B>Notice:</B> font file could not be compressed (zlib extension not available)<BR>';
406
    }
407
    if($type=='Type1')
408
    {
409
      $s.='$size1='.$size1.";\n";
0 ignored issues
show
Bug introduced by
The variable $size1 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
410
      $s.='$size2='.$size2.";\n";
0 ignored issues
show
Bug introduced by
The variable $size2 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
411
    }
412
    else
413
      $s.='$originalsize='.filesize($fontfile).";\n";
414
  }
415
  else
416
  {
417
    //Not embedded font
418
    $s.='$file='."'';\n";
419
  }
420
  $s.="?>\n";
421
  SaveToFile($basename.'.php',$s);
422
  echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
423
}
424