1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
require 'ttfunk/table'
module TTFunk
class Table
class Kern < Table
attr_reader :version
attr_reader :tables
def self.encode(kerning, mapping)
return nil unless kerning.exists? && kerning.tables.any?
tables = kerning.tables.map { |table| table.recode(mapping) }.compact
return nil if tables.empty?
[0, tables.length, tables.join].pack("nnA*")
end
private
def parse!
@version, num_tables = read(4, "n*")
@tables = []
if @version == 1 # Mac OS X fonts
@version = (@version << 16) + num_tables
num_tables = read(4, "N").first
parse_version_1_tables(num_tables)
else
parse_version_0_tables(num_tables)
end
end
def parse_version_0_tables(num_tables)
# It looks like some MS fonts report their kerning subtable lengths
# wrong. In one case, the length was reported to be some 19366, and yet
# the table also claimed to hold 14148 pairs (each pair consisting of 6 bytes).
# You do the math!
#
# We're going to assume that the microsoft fonts hold only a single kerning
# subtable, which occupies the entire length of the kerning table. Worst
# case, we lose any other subtables that the font contains, but it's better
# than reading a truncated kerning table.
#
# And what's more, it appears to work. So.
version, length, coverage = read(6, "n*")
format = coverage >> 8
add_table format, :version => version, :length => length,
:coverage => coverage, :data => raw[10..-1],
:vertical => (coverage & 0x1 == 0),
:minimum => (coverage & 0x2 != 0),
:cross => (coverage & 0x4 != 0),
:override => (coverage & 0x8 != 0)
end
def parse_version_1_tables(num_tables)
num_tables.times do
length, coverage, tuple_index = read(8, "Nnn")
format = coverage & 0x0FF
add_table format, :length => length, :coverage => coverage,
:tuple_index => tuple_index, :data => io.read(length-8),
:vertical => (coverage & 0x8000 != 0),
:cross => (coverage & 0x4000 != 0),
:variation => (coverage & 0x2000 != 0)
end
end
def add_table(format, attributes={})
if format == 0
@tables << Kern::Format0.new(attributes)
else
# silently ignore unsupported kerning tables
end
end
end
end
end
require 'ttfunk/table/kern/format0'
|