Class: TTFunk::Table::Glyf::Compound

Inherits:
Object
  • Object
show all
Includes:
Reader
Defined in:
lib/ttfunk/table/glyf/compound.rb

Overview

Composite TrueType glyph.

Defined Under Namespace

Classes: Component

Constant Summary collapse

ARG_1_AND_2_ARE_WORDS =

Flags bit 0: arg1 and arg2 are words.

0x0001
WE_HAVE_A_SCALE =

Flags bit 3: there is a simple scale for the component.

0x0008
MORE_COMPONENTS =

Flags bit 5: at least one more glyph after this one.

0x0020
WE_HAVE_AN_X_AND_Y_SCALE =

Flags bit 6: the x direction will use a different scale from the y direction.

0x0040
WE_HAVE_A_TWO_BY_TWO =

Flags bit 7: there is a 2 by 2 transformation that will be used to scale the component.

0x0080
WE_HAVE_INSTRUCTIONS =

Flags bit 8: following the last component are instructions for the composite character.

0x0100

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, raw) ⇒ Compound

Returns a new instance of Compound.

Parameters:

  • id (Integer)

    glyph ID.

  • raw (String)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/ttfunk/table/glyf/compound.rb', line 85

def initialize(id, raw)
  @id = id
  @raw = raw
  io = StringIO.new(raw)

  @number_of_contours, @x_min, @y_min, @x_max, @y_max =
    io.read(10).unpack('n*').map { |i|
      BinUtils.twos_comp_to_int(i, bit_width: 16)
    }

  # 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 if (flags & MORE_COMPONENTS).zero?

    offset += 4

    offset +=
      if (flags & ARG_1_AND_2_ARE_WORDS).zero?
        2
      else
        4
      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

Instance Attribute Details

#glyph_idsObject (readonly)

IDs of compound glyphs.



62
63
64
# File 'lib/ttfunk/table/glyf/compound.rb', line 62

def glyph_ids
  @glyph_ids
end

#idInteger (readonly)

Glyph ID.

Returns:

  • (Integer)


35
36
37
# File 'lib/ttfunk/table/glyf/compound.rb', line 35

def id
  @id
end

#number_of_contoursInteger (readonly)

Number of contours in this glyph.

Returns:

  • (Integer)


43
44
45
# File 'lib/ttfunk/table/glyf/compound.rb', line 43

def number_of_contours
  @number_of_contours
end

#rawString (readonly)

Binary serialization of this glyph.

Returns:

  • (String)


39
40
41
# File 'lib/ttfunk/table/glyf/compound.rb', line 39

def raw
  @raw
end

#x_maxInteger (readonly)

Maximum x for coordinate.

Returns:

  • (Integer)


55
56
57
# File 'lib/ttfunk/table/glyf/compound.rb', line 55

def x_max
  @x_max
end

#x_minInteger (readonly)

Minimum x for coordinate.

Returns:

  • (Integer)


47
48
49
# File 'lib/ttfunk/table/glyf/compound.rb', line 47

def x_min
  @x_min
end

#y_maxInteger (readonly)

Maximum y for coordinate.

Returns:

  • (Integer)


59
60
61
# File 'lib/ttfunk/table/glyf/compound.rb', line 59

def y_max
  @y_max
end

#y_minInteger (readonly)

Minimum y for coordinate.

Returns:

  • (Integer)


51
52
53
# File 'lib/ttfunk/table/glyf/compound.rb', line 51

def y_min
  @y_min
end

Instance Method Details

#compound?true

Is this a composite glyph?

Returns:

  • (true)


136
137
138
# File 'lib/ttfunk/table/glyf/compound.rb', line 136

def compound?
  true
end

#recode(mapping) ⇒ String

Recode glyph.

Parameters:

  • mapping (Hash{Integer => Integer})

    a hash mapping old glyph IDs to new glyph IDs.

Returns:

  • (String)


145
146
147
148
149
150
151
152
153
154
# File 'lib/ttfunk/table/glyf/compound.rb', line 145

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

  result
end