Class: Fontisan::Tables::CompoundGlyph

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/tables/glyf/compound_glyph.rb

Overview

Represents a compound TrueType glyph composed of other glyphs

A compound glyph is built by referencing other glyphs (components) and applying transformations to them. Each component references another glyph by ID and specifies positioning and optional scaling, rotation, or affine transformation.

The glyph structure consists of:

  • Header: numberOfContours (-1), xMin, yMin, xMax, yMax (10 bytes)

  • Components: array of component descriptions (variable length)

  • Instructions: optional TrueType hinting instructions

Each component has:

  • flags (uint16): component flags

  • glyphIndex (uint16): referenced glyph ID

  • arguments: positioning (arg1, arg2) - interpretation depends on flags

  • transformation: optional scale/rotation/affine matrix

Component flags (16-bit) indicate:

  • Bit 0 (0x0001): ARG_1_AND_2_ARE_WORDS - arguments are 16-bit

  • Bit 1 (0x0002): ARGS_ARE_XY_VALUES - arguments are x,y offsets

  • Bit 2 (0x0004): ROUND_XY_TO_GRID - round x,y to grid

  • Bit 3 (0x0008): WE_HAVE_A_SCALE - uniform scale follows

  • Bit 5 (0x0020): MORE_COMPONENTS - more components follow

  • Bit 6 (0x0040): WE_HAVE_AN_X_AND_Y_SCALE - separate x,y scale

  • Bit 7 (0x0080): WE_HAVE_A_TWO_BY_TWO - 2x2 affine matrix

  • Bit 8 (0x0100): WE_HAVE_INSTRUCTIONS - instructions follow components

  • Bit 9 (0x0200): USE_MY_METRICS - use this component’s metrics

  • Bit 10 (0x0400): OVERLAP_COMPOUND - component outlines overlap

  • Bit 11 (0x0800): SCALED_COMPONENT_OFFSET - scale offset values

  • Bit 12 (0x1000): UNSCALED_COMPONENT_OFFSET - don’t scale offsets

Reference: OpenType specification, glyf table - Compound Glyph Description docs.microsoft.com/en-us/typography/opentype/spec/glyf#compound-glyph-description

Defined Under Namespace

Classes: Component

Constant Summary collapse

ARG_1_AND_2_ARE_WORDS =

Component flag constants

0x0001
ARGS_ARE_XY_VALUES =
0x0002
ROUND_XY_TO_GRID =
0x0004
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
USE_MY_METRICS =
0x0200
OVERLAP_COMPOUND =
0x0400
SCALED_COMPONENT_OFFSET =
0x0800
UNSCALED_COMPONENT_OFFSET =
0x1000

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(glyph_id) ⇒ CompoundGlyph

Initialize a new compound glyph

Parameters:

  • glyph_id (Integer)

    Glyph ID



136
137
138
139
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 136

def initialize(glyph_id)
  @glyph_id = glyph_id
  @components = []
end

Instance Attribute Details

#componentsObject (readonly)

Compound glyph data



119
120
121
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 119

def components
  @components
end

#glyph_idObject (readonly)

Glyph header fields



114
115
116
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114

def glyph_id
  @glyph_id
end

#instruction_lengthObject (readonly)

Returns the value of attribute instruction_length.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def instruction_length
  @instruction_length
end

#instructionsObject (readonly)

Returns the value of attribute instructions.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def instructions
  @instructions
end

#x_maxObject (readonly)

Returns the value of attribute x_max.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def x_max
  @x_max
end

#x_minObject (readonly)

Returns the value of attribute x_min.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def x_min
  @x_min
end

#y_maxObject (readonly)

Returns the value of attribute y_max.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def y_max
  @y_max
end

#y_minObject (readonly)

Returns the value of attribute y_min.



115
116
117
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 115

def y_min
  @y_min
end

Class Method Details

.parse(data, glyph_id) ⇒ CompoundGlyph

Parse compound glyph data

Parameters:

  • data (String)

    Binary glyph data

  • glyph_id (Integer)

    Glyph ID for error reporting

Returns:

Raises:



127
128
129
130
131
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 127

def self.parse(data, glyph_id)
  glyph = new(glyph_id)
  glyph.parse_data(data)
  glyph
end

Instance Method Details

#bounding_boxArray<Integer>

Get bounding box as array

Returns:

  • (Array<Integer>)

    Bounding box [xMin, yMin, xMax, yMax]



180
181
182
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 180

def bounding_box
  [x_min, y_min, x_max, y_max]
end

#component_glyph_idsArray<Integer>

Get all component glyph IDs (for dependency tracking)

This method returns the glyph IDs of all components that make up this compound glyph. This is essential for subsetting operations, where all dependent glyphs must be included.

Examples:

Getting component dependencies

glyph = glyf.glyph_for(100, loca, head)
if glyph.compound?
  deps = glyph.component_glyph_ids
  puts "Glyph 100 depends on: #{deps.join(', ')}"
end

Returns:

  • (Array<Integer>)

    Array of component glyph IDs



198
199
200
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 198

def component_glyph_ids
  components.map(&:glyph_index)
end

#compound?Boolean

Check if this is a compound glyph

Returns:

  • (Boolean)

    Always true for CompoundGlyph



166
167
168
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 166

def compound?
  true
end

#empty?Boolean

Check if glyph has no components

Returns:

  • (Boolean)

    True if no components



173
174
175
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 173

def empty?
  components.empty?
end

#metrics_componentComponent?

Get the component that provides metrics (if any)

Returns:

  • (Component, nil)

    Component with USE_MY_METRICS flag, or nil



227
228
229
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 227

def metrics_component
  components.find(&:use_my_metrics?)
end

#num_componentsInteger

Get number of components

Returns:

  • (Integer)

    Component count



213
214
215
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 213

def num_components
  components.length
end

#parse_data(data) ⇒ Object

Parse glyph data

Parameters:

  • data (String)

    Binary glyph data

Raises:



145
146
147
148
149
150
151
152
153
154
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 145

def parse_data(data)
  io = StringIO.new(data)
  io.set_encoding(Encoding::BINARY)

  parse_header(io)
  parse_components(io)
  parse_instructions(io) if has_instructions?

  validate_parsed_data!
end

#simple?Boolean

Check if this is a simple glyph

Returns:

  • (Boolean)

    Always false for CompoundGlyph



159
160
161
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 159

def simple?
  false
end

#uses_component?(glyph_id) ⇒ Boolean

Check if glyph uses a specific component

Parameters:

  • glyph_id (Integer)

    Glyph ID to check

Returns:

  • (Boolean)

    True if glyph uses this component



206
207
208
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 206

def uses_component?(glyph_id)
  component_glyph_ids.include?(glyph_id)
end

#uses_component_metrics?Boolean

Check if any component uses metrics from referenced glyph

Returns:

  • (Boolean)

    True if any component has USE_MY_METRICS flag



220
221
222
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 220

def uses_component_metrics?
  components.any?(&:use_my_metrics?)
end