Class: Fontisan::Tables::CompoundGlyph
- Inherits:
-
Object
- Object
- Fontisan::Tables::CompoundGlyph
- 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 https://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
-
#components ⇒ Object
readonly
Compound glyph data.
-
#glyph_id ⇒ Object
readonly
Glyph header fields.
-
#instruction_length ⇒ Object
readonly
Returns the value of attribute instruction_length.
-
#instructions ⇒ Object
readonly
Returns the value of attribute instructions.
-
#x_max ⇒ Object
readonly
Returns the value of attribute x_max.
-
#x_min ⇒ Object
readonly
Returns the value of attribute x_min.
-
#y_max ⇒ Object
readonly
Returns the value of attribute y_max.
-
#y_min ⇒ Object
readonly
Returns the value of attribute y_min.
Class Method Summary collapse
-
.parse(data, glyph_id) ⇒ CompoundGlyph
Parse compound glyph data.
Instance Method Summary collapse
-
#bounding_box ⇒ Array<Integer>
Get bounding box as array.
-
#component_glyph_ids ⇒ Array<Integer>
Get all component glyph IDs (for dependency tracking).
-
#compound? ⇒ Boolean
Check if this is a compound glyph.
-
#empty? ⇒ Boolean
Check if glyph has no components.
-
#initialize(glyph_id) ⇒ CompoundGlyph
constructor
Initialize a new compound glyph.
-
#metrics_component ⇒ Component?
Get the component that provides metrics (if any).
-
#num_components ⇒ Integer
Get number of components.
-
#parse_data(data) ⇒ Object
Parse glyph data.
-
#simple? ⇒ Boolean
Check if this is a simple glyph.
-
#uses_component?(glyph_id) ⇒ Boolean
Check if glyph uses a specific component.
-
#uses_component_metrics? ⇒ Boolean
Check if any component uses metrics from referenced glyph.
Constructor Details
#initialize(glyph_id) ⇒ CompoundGlyph
Initialize a new compound glyph
135 136 137 138 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 135 def initialize(glyph_id) @glyph_id = glyph_id @components = [] end |
Instance Attribute Details
#components ⇒ Object (readonly)
Compound glyph data
118 119 120 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 118 def components @components end |
#glyph_id ⇒ Object (readonly)
Glyph header fields
113 114 115 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 113 def glyph_id @glyph_id end |
#instruction_length ⇒ Object (readonly)
Returns the value of attribute instruction_length.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def instruction_length @instruction_length end |
#instructions ⇒ Object (readonly)
Returns the value of attribute instructions.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def instructions @instructions end |
#x_max ⇒ Object (readonly)
Returns the value of attribute x_max.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def x_max @x_max end |
#x_min ⇒ Object (readonly)
Returns the value of attribute x_min.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def x_min @x_min end |
#y_max ⇒ Object (readonly)
Returns the value of attribute y_max.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def y_max @y_max end |
#y_min ⇒ Object (readonly)
Returns the value of attribute y_min.
114 115 116 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 114 def y_min @y_min end |
Class Method Details
.parse(data, glyph_id) ⇒ CompoundGlyph
Parse compound glyph data
126 127 128 129 130 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 126 def self.parse(data, glyph_id) glyph = new(glyph_id) glyph.parse_data(data) glyph end |
Instance Method Details
#bounding_box ⇒ Array<Integer>
Get bounding box as array
179 180 181 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 179 def bounding_box [x_min, y_min, x_max, y_max] end |
#component_glyph_ids ⇒ Array<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.
197 198 199 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 197 def component_glyph_ids components.map(&:glyph_index) end |
#compound? ⇒ Boolean
Check if this is a compound glyph
165 166 167 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 165 def compound? true end |
#empty? ⇒ Boolean
Check if glyph has no components
172 173 174 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 172 def empty? components.empty? end |
#metrics_component ⇒ Component?
Get the component that provides metrics (if any)
226 227 228 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 226 def metrics_component components.find(&:use_my_metrics?) end |
#num_components ⇒ Integer
Get number of components
212 213 214 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 212 def num_components components.length end |
#parse_data(data) ⇒ Object
Parse glyph data
144 145 146 147 148 149 150 151 152 153 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 144 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
158 159 160 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 158 def simple? false end |
#uses_component?(glyph_id) ⇒ Boolean
Check if glyph uses a specific component
205 206 207 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 205 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
219 220 221 |
# File 'lib/fontisan/tables/glyf/compound_glyph.rb', line 219 def uses_component_metrics? components.any?(&:use_my_metrics?) end |