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();