Class: Fontisan::Tables::CompoundGlyphResolver
- Inherits:
-
Object
- Object
- Fontisan::Tables::CompoundGlyphResolver
- Defined in:
- lib/fontisan/tables/glyf/compound_glyph_resolver.rb
Overview
Resolves compound glyphs into simple outlines
CompoundGlyphResolver
handles the recursive resolution of compound (composite) glyphs in TrueType fonts.
Compound glyphs are composed of references to other glyphs with transformation
matrices applied. This resolver:
- Recursively resolves component glyphs (which may themselves be compound)
- Applies transformation matrices to each component
- Merges all components into a single simple outline
- Handles nested compound glyphs (compound glyphs referencing other compounds)
- Detects and prevents circular references
Transformation Process:
Each component has a transformation matrix [a, b, c, d, e, f] representing:
x' = a*x + c*y + e
y' = b*x + d*y + f
Where:
- a, d: Scale factors for x and y
- b, c: Rotation/skew components
- e, f: Translation offsets (x, y)
Resolution Strategy:
- Start with compound glyph
- For each component:
- Get component glyph (may be simple or compound)
- If compound, recursively resolve it first
- Apply component's transformation matrix
- Merge into result outline
- Return merged simple outline
Constant Summary collapse
- MAX_DEPTH =
Maximum recursion depth to prevent infinite loops
32
Instance Attribute Summary collapse
-
#glyf ⇒ Glyf
readonly
The glyf table.
-
#head ⇒ Head
readonly
The head table.
-
#loca ⇒ Loca
readonly
The loca table.
Instance Method Summary collapse
-
#initialize(glyf, loca, head) ⇒ CompoundGlyphResolver
constructor
Initialize resolver with required tables.
-
#resolve(compound_glyph, visited = Set.new, depth = 0) ⇒ Outline
Resolve a compound glyph into a simple outline.
Constructor Details
#initialize(glyf, loca, head) ⇒ CompoundGlyphResolver
Initialize resolver with required tables
64 65 66 67 68 |
# File 'lib/fontisan/tables/glyf/compound_glyph_resolver.rb', line 64 def initialize(glyf, loca, head) @glyf = glyf @loca = loca @head = head end |
Instance Attribute Details
#glyf ⇒ Glyf (readonly)
Returns The glyf table.
51 52 53 |
# File 'lib/fontisan/tables/glyf/compound_glyph_resolver.rb', line 51 def glyf @glyf end |
#head ⇒ Head (readonly)
Returns The head table.
57 58 59 |
# File 'lib/fontisan/tables/glyf/compound_glyph_resolver.rb', line 57 def head @head end |
#loca ⇒ Loca (readonly)
Returns The loca table.
54 55 56 |
# File 'lib/fontisan/tables/glyf/compound_glyph_resolver.rb', line 54 def loca @loca end |
Instance Method Details
#resolve(compound_glyph, visited = Set.new, depth = 0) ⇒ Outline
Resolve a compound glyph into a simple outline
77 78 79 80 81 82 83 84 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/fontisan/tables/glyf/compound_glyph_resolver.rb', line 77 def resolve(compound_glyph, visited = Set.new, depth = 0) # Check recursion depth if depth > MAX_DEPTH raise Fontisan::Error, "Maximum recursion depth (#{MAX_DEPTH}) exceeded resolving compound glyph #{compound_glyph.glyph_id}" end # Check for circular reference if visited.include?(compound_glyph.glyph_id) raise Fontisan::Error, "Circular reference detected in compound glyph #{compound_glyph.glyph_id}" end # Mark as visited visited = visited.dup.add(compound_glyph.glyph_id) # Start with empty merged outline merged_outline = Models::Outline.new( glyph_id: compound_glyph.glyph_id, commands: [], bbox: { x_min: compound_glyph.x_min, y_min: compound_glyph.y_min, x_max: compound_glyph.x_max, y_max: compound_glyph.y_max, }, ) # Resolve each component compound_glyph.components.each do |component| # Get component glyph component_glyph = glyf.glyph_for(component.glyph_index, loca, head) # Skip empty components next if component_glyph.nil? || component_glyph.empty? # Get component outline (recursively if compound) component_outline = if component_glyph.compound? # Recursively resolve compound component resolve(component_glyph, visited, depth + 1) else # Convert simple glyph to outline Models::Outline.from_truetype(component_glyph, component.glyph_index) end # Apply transformation matrix matrix = component.transformation_matrix transformed_outline = component_outline.transform(matrix) # Merge into result merged_outline.merge!(transformed_outline) end merged_outline end |