<?php

$ascii_chars = Array(
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00
,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00
,0x00,0x6c,0xfe,0x6c,0x6c,0xfe,0x6c,0x00
,0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00
,0x62,0x66,0x0c,0x18,0x30,0x66,0x46,0x00
,0x1c,0x36,0x1c,0x38,0x6b,0x66,0x3b,0x00
,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00
,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00
,0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00
,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00
,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60
,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00
,0x02,0x06,0x0c,0x18,0x30,0x60,0x40,0x00
,0x38,0x4c,0xce,0xc6,0xe6,0x64,0x38,0x00
,0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00
,0x7c,0xc6,0x0e,0x3c,0x78,0xe0,0xfe,0x00
,0x7e,0x0c,0x18,0x3c,0x06,0xc6,0x7c,0x00
,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x00
,0xfc,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00
,0x3c,0x60,0xc0,0xfc,0xc6,0xc6,0x7c,0x00
,0xfe,0xc6,0x0c,0x18,0x30,0x30,0x30,0x00
,0x78,0xc4,0xe4,0x78,0x86,0x86,0x7c,0x00
,0x7c,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00
,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00
,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x60
,0x00,0x18,0x30,0x60,0x30,0x18,0x00,0x00
,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00
,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x00
,0x7c,0xc6,0x06,0x1c,0x30,0x00,0x30,0x00
,0x3c,0x66,0x6e,0x6a,0x6e,0x60,0x3e,0x00
,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x00
,0xfc,0xc6,0xc6,0xfc,0xc6,0xc6,0xfc,0x00
,0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00
,0xf8,0xcc,0xc6,0xc6,0xc6,0xcc,0xf8,0x00
,0xfe,0xc0,0xc0,0xfc,0xc0,0xc0,0xfe,0x00
,0xfe,0xc0,0xc0,0xfc,0xc0,0xc0,0xc0,0x00
,0x3e,0x60,0xc0,0xce,0xc6,0x66,0x3e,0x00
,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00
,0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00
,0x1e,0x06,0x06,0x06,0xc6,0xc6,0x7c,0x00
,0xc6,0xcc,0xd8,0xf0,0xd8,0xcc,0xc6,0x00
,0x60,0x60,0x60,0x60,0x60,0x60,0x7e,0x00
,0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0x00
,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0x00
,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00
,0xfc,0xc6,0xc6,0xfc,0xc0,0xc0,0xc0,0x00
,0x7c,0xc6,0xc6,0xc6,0xda,0xcc,0x76,0x00
,0xfc,0xc6,0xc6,0xfc,0xd8,0xcc,0xc6,0x00
,0x7c,0xc6,0xc0,0x7c,0x06,0xc6,0x7c,0x00
,0xfc,0x30,0x30,0x30,0x30,0x30,0x30,0x00
,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00
,0xc6,0xc6,0xc6,0xee,0x7c,0x38,0x10,0x00
,0xc6,0xc6,0xd6,0xfe,0xfe,0xee,0xc6,0x00
,0xc6,0xee,0x7c,0x38,0x7c,0xee,0xc6,0x00
,0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00
,0xfe,0x0e,0x1c,0x38,0x70,0xe0,0xfe,0x00
,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00
,0x40,0x60,0x30,0x18,0x0c,0x06,0x02,0x00
,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00
,0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00
,0xc0,0x60,0x30,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00
,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0xf8,0x00
,0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00
,0x0c,0x0c,0x7c,0xcc,0xcc,0xcc,0x7c,0x00
,0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00
,0x1c,0x30,0x30,0x78,0x30,0x30,0x30,0x00
,0x00,0x00,0x7c,0xcc,0xcc,0x7c,0x0c,0x78
,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0xcc,0x00
,0x00,0x30,0x00,0x30,0x30,0x30,0x30,0x00
,0x00,0x18,0x00,0x18,0x18,0x18,0x18,0x70
,0xc0,0xc0,0xcc,0xd8,0xf0,0xd8,0xcc,0x00
,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00
,0x00,0x00,0xec,0xfe,0xd6,0xd6,0xd6,0x00
,0x00,0x00,0xd8,0xec,0xcc,0xcc,0xcc,0x00
,0x00,0x00,0x3c,0x66,0x66,0x66,0x3c,0x00
,0x00,0x00,0xf8,0xcc,0xcc,0xf8,0xc0,0xc0
,0x00,0x00,0x7c,0xcc,0xcc,0x7c,0x0c,0x0c
,0x00,0x00,0xd8,0xec,0xc0,0xc0,0xc0,0x00
,0x00,0x00,0x78,0xc0,0x78,0x0c,0xf8,0x00
,0x00,0x30,0x7c,0x30,0x30,0x30,0x1c,0x00
,0x00,0x00,0xcc,0xcc,0xcc,0xdc,0x6c,0x00
,0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x00
,0x00,0x00,0xd6,0xd6,0xd6,0xfe,0x6c,0x00
,0x00,0x00,0xcc,0x78,0x30,0x78,0xcc,0x00
,0x00,0x00,0xcc,0xcc,0xcc,0x7c,0x0c,0x78
,0x00,0x00,0xfc,0x18,0x30,0x60,0xfc,0x00
,0x0e,0x18,0x18,0x30,0x18,0x18,0x0e,0x00
,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00
,0x70,0x18,0x18,0x0c,0x18,0x18,0x70,0x00
,0x60,0xf2,0x9e,0x0c,0x00,0x00,0x00,0x00
,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
);

// Empty margins on left and right, in pixels
// Array(character_number => Array(left_margin, right_margin).
$character_margins = function()
{
  global $ascii_chars;
  $result = Array();
  
  for($c=0; $c<96; ++$c)
  {
    $margin_left = 8;
    $margin_right = 8;
    
    for($y=0; $y<8; ++$y)
    {
      $byte = $ascii_chars[$c*8 + $y];
      
      // For the purposes of collision checking, space is always a vertical colum
      if($c == 0) $byte = 0x10;
      
      for($x=0; $x<8; ++$x)
        if($byte & (0x80 >> $x))
        {
          if($margin_left > $x) $margin_left = $x;
          $m = 7-$x;
          if($margin_right > $m) $margin_right = $m;
        }
    }
    $result[$c] = Array($margin_left, $margin_right);
  }
  return $result;
};
$character_margins = $character_margins();

// Kerning table: How many pixels to add to X coordinate
//                after left_character to render right_character.
//                This may be smaller than the combined margin thereof,
//                but never larger.
// Array(left_character => Array(right_character => num_pixels)).
$kerning_table = function()
{
  global $ascii_chars, $character_margins;
  $result = Array();
  for($c1=0; $c1<96; ++$c1)
  {
    $lresult = Array();
    for($c2=0; $c2<96; ++$c2)
    {
      $best_offset  = 8;
      $best_touches = 99999;
      for($offset = 8; $offset > 0; --$offset)
      {
        // Test if the bitmaps collide if offseted this way
        $num_touches = 0;
        for($y1=0; $y1<8; ++$y1)
        {
          // For each pixel of the left character, 
          $byte1 = $ascii_chars[$c1*8 + $y1];

          // For the purposes of collision checking, space is always a vertical colum
          for($x1=0; $x1<8; ++$x1)
            if($byte1 & (0x80 >> $x1))
            {
              // Left character has a pixel here
              for($y2 = $y1-1; $y2 <= $y1+1; ++$y2)
              {
                if($y2 < 0 || $y2 >= 8) continue;
                $byte2 = $ascii_chars[$c2*8 + $y2];

                // For the purposes of collision checking, space is always a vertical colum
                if($c2 == 0) $byte2 = 0x18;

                $x2 = $x1-$offset;
                if($x2 >= 0 && $x2 < 8)
                  if($byte2 & (0x80 >> $x2))
                  {
                    ++$num_touches;
                  }
              }
            }
        }
        if($num_touches > $best_touches) break;
        $best_touches = $num_touches;
        $best_offset  = $offset;
      }
      if($c2 == 0) $best_offset += 5; // For space, add extra pixel
      if($c1 == ord('r')-32 && $c2 == ord('.')-32)
      {
        $best_offset = 4; // Add some space between r and .
      }
      $lresult[$c2] = $best_offset+1;
    }
    $result[$c1] = $lresult;
  }
  return $result;
};
$kerning_table = $kerning_table();
