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 80 81
|
require 'ttfunk/reader'
module TTFunk
class Table
class Glyf
class Compound
include Reader
ARG_1_AND_2_ARE_WORDS = 0x0001
WE_HAVE_A_SCALE = 0x0008
MORE_COMPONENTS = 0x0020
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040
WE_HAVE_A_TWO_BY_TWO = 0x0080
WE_HAVE_INSTRUCTIONS = 0x0100
attr_reader :raw
attr_reader :x_min, :y_min, :x_max, :y_max
attr_reader :glyph_ids
Component = Struct.new(:flags, :glyph_index, :arg1, :arg2, :transform)
def initialize(raw, x_min, y_min, x_max, y_max)
@raw = raw
@x_min, @y_min, @x_max, @y_max = x_min, y_min, x_max, y_max
# Because TTFunk only cares about glyphs insofar as they (1) provide
# a bounding box for each glyph, and (2) can be rewritten into a
# font subset, we don't really care about the rest of the glyph data
# except as a whole. Thus, we don't actually decompose the glyph
# into it's parts--all we really care about are the locations within
# the raw string where the component glyph ids are stored, so that
# when we rewrite this glyph into a subset we can rewrite the
# component glyph-ids so they are correct for the subset.
@glyph_ids = []
@glyph_id_offsets = []
offset = 10 # 2 bytes for each of num-contours, min x/y, max x/y
loop do
flags, glyph_id = @raw[offset, 4].unpack("n*")
@glyph_ids << glyph_id
@glyph_id_offsets << offset + 2
break unless flags & MORE_COMPONENTS != 0
offset += 4
if flags & ARG_1_AND_2_ARE_WORDS != 0
offset += 4
else
offset += 2
end
if flags & WE_HAVE_A_TWO_BY_TWO != 0
offset += 8
elsif flags & WE_HAVE_AN_X_AND_Y_SCALE != 0
offset += 4
elsif flags & WE_HAVE_A_SCALE != 0
offset += 2
end
end
end
def compound?
true
end
def recode(mapping)
result = @raw.dup
new_ids = glyph_ids.map { |id| mapping[id] }
new_ids.zip(@glyph_id_offsets).each do |new_id, offset|
result[offset, 2] = [new_id].pack("n")
end
return result
end
end
end
end
end
|