Class: Fontisan::Variation::InstanceGenerator
- Inherits:
-
Object
- Object
- Fontisan::Variation::InstanceGenerator
- Includes:
- TableAccessor
- Defined in:
- lib/fontisan/variation/instance_generator.rb
Overview
Generates static font instances from variable fonts
This class creates static font instances by applying variation deltas at specific design space coordinates. It supports both TrueType (gvar) and PostScript (CFF2) variable fonts.
Process:
- Extract variation data (axes, deltas, regions)
- Calculate interpolation scalars for given coordinates
- Apply deltas to outlines (gvar or CFF2)
- Apply deltas to metrics (HVAR, VVAR, MVAR)
- Remove variation tables to create static font
Instance Attribute Summary collapse
-
#context ⇒ VariationContext
readonly
Variation context.
-
#coordinates ⇒ Hash<String, Float>
readonly
Design space coordinates.
-
#font ⇒ TrueTypeFont, OpenTypeFont
readonly
Variable font.
Instance Method Summary collapse
-
#apply_cff2_blend(_tables) ⇒ Object
Apply CFF2 blend operators.
-
#apply_glyph_deltas(glyph_id, gvar, _glyf) ⇒ Object
Apply deltas to a specific glyph.
-
#apply_gvar_deltas(_tables) ⇒ Object
Apply gvar deltas to TrueType outlines.
-
#apply_hvar_deltas(_tables) ⇒ Object
Apply HVAR deltas to horizontal metrics.
-
#apply_metrics_deltas(tables) ⇒ Object
Apply metrics variations.
-
#apply_mvar_deltas(_tables) ⇒ Object
Apply MVAR deltas to font-wide metrics.
-
#apply_vvar_deltas(_tables) ⇒ Object
Apply VVAR deltas to vertical metrics.
-
#calculate_variation_scalars ⇒ Array<Float>
Calculate variation scalars for current coordinates.
-
#generate ⇒ Hash<String, String>
Generate static font instance.
-
#generate_named_instance(instance_index) ⇒ Hash<String, String>
Generate a named instance.
-
#initialize(font, coordinates = {}, options = {}) ⇒ InstanceGenerator
constructor
Initialize generator with font and optional coordinates.
-
#interpolate_point(base_point, delta_points, scalars) ⇒ Hash
Interpolate a point.
-
#interpolate_value(base_value, deltas, scalars) ⇒ Float
Interpolate a single value.
-
#remove_variation_tables(tables) ⇒ Object
Remove variation tables from static font.
Methods included from TableAccessor
#clear_variation_cache, #clear_variation_table, #has_variation_table?, #require_variation_table, #variation_table
Constructor Details
#initialize(font, coordinates = {}, options = {}) ⇒ InstanceGenerator
Initialize generator with font and optional coordinates
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/fontisan/variation/instance_generator.rb', line 43 def initialize(font, coordinates = {}, = {}) @font = font @coordinates = coordinates # Initialize variation context @context = VariationContext.new(@font) @context.validate! unless [:skip_validation] # Initialize table cache for lazy loading @variation_tables = {} end |
Instance Attribute Details
#context ⇒ VariationContext (readonly)
Returns Variation context.
35 36 37 |
# File 'lib/fontisan/variation/instance_generator.rb', line 35 def context @context end |
#coordinates ⇒ Hash<String, Float> (readonly)
Returns Design space coordinates.
32 33 34 |
# File 'lib/fontisan/variation/instance_generator.rb', line 32 def coordinates @coordinates end |
#font ⇒ TrueTypeFont, OpenTypeFont (readonly)
Returns Variable font.
29 30 31 |
# File 'lib/fontisan/variation/instance_generator.rb', line 29 def font @font end |
Instance Method Details
#apply_cff2_blend(_tables) ⇒ Object
Apply CFF2 blend operators
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/fontisan/variation/instance_generator.rb', line 150 def apply_cff2_blend(_tables) cff2 = variation_table("CFF2") return unless cff2 # Set number of axes for CFF2 cff2.num_axes = @context.axis_count # Process each glyph's CharString glyph_count = cff2.glyph_count return if glyph_count.zero? # Calculate variation scalars once calculate_variation_scalars # Apply blend to each glyph # This is a placeholder - full implementation would: # 1. Parse CharString with blend operators # 2. Apply scalars to blend operands # 3. Rebuild CharStrings without blend operators # 4. Update CFF2 table end |
#apply_glyph_deltas(glyph_id, gvar, _glyf) ⇒ Object
Apply deltas to a specific glyph
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/fontisan/variation/instance_generator.rb', line 125 def apply_glyph_deltas(glyph_id, gvar, _glyf) # Get tuple variations for this glyph tuple_data = gvar.glyph_tuple_variations(glyph_id) return unless tuple_data # Match tuples to current coordinates matches = @context.region_matcher.match_tuples( coordinates: @coordinates, tuples: tuple_data[:tuples], ) nil if matches.empty? # Get base glyph outline # Apply matched deltas with their scalars # This is a placeholder - full implementation would: # 1. Parse glyph outline points # 2. Parse delta data for each tuple # 3. Apply: new_point = base_point + Σ(delta * scalar) # 4. Update glyph outline end |
#apply_gvar_deltas(_tables) ⇒ Object
Apply gvar deltas to TrueType outlines
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/fontisan/variation/instance_generator.rb', line 102 def apply_gvar_deltas(_tables) gvar = variation_table("gvar") glyf = @font.table("glyf") return unless gvar && glyf # Get glyph count maxp = @font.table("maxp") glyph_count = maxp ? maxp.num_glyphs : gvar.glyph_count # Process each glyph glyph_count.times do |glyph_id| apply_glyph_deltas(glyph_id, gvar, glyf) end # Rebuild glyf and loca tables with adjusted outlines # This is a placeholder - full implementation would reconstruct tables end |
#apply_hvar_deltas(_tables) ⇒ Object
Apply HVAR deltas to horizontal metrics
199 200 201 202 |
# File 'lib/fontisan/variation/instance_generator.rb', line 199 def apply_hvar_deltas(_tables) adjuster = MetricsAdjuster.new(@font, @context.interpolator) adjuster.apply_hvar_deltas(@coordinates) end |
#apply_metrics_deltas(tables) ⇒ Object
Apply metrics variations
185 186 187 188 189 190 191 192 193 194 |
# File 'lib/fontisan/variation/instance_generator.rb', line 185 def apply_metrics_deltas(tables) # Apply HVAR (horizontal metrics) apply_hvar_deltas(tables) if has_variation_table?("HVAR") # Apply VVAR (vertical metrics) apply_vvar_deltas(tables) if has_variation_table?("VVAR") # Apply MVAR (font-wide metrics) apply_mvar_deltas(tables) if has_variation_table?("MVAR") end |
#apply_mvar_deltas(_tables) ⇒ Object
Apply MVAR deltas to font-wide metrics
215 216 217 218 |
# File 'lib/fontisan/variation/instance_generator.rb', line 215 def apply_mvar_deltas(_tables) adjuster = MetricsAdjuster.new(@font, @context.interpolator) adjuster.apply_mvar_deltas(@coordinates) end |
#apply_vvar_deltas(_tables) ⇒ Object
Apply VVAR deltas to vertical metrics
207 208 209 210 |
# File 'lib/fontisan/variation/instance_generator.rb', line 207 def apply_vvar_deltas(_tables) adjuster = MetricsAdjuster.new(@font, @context.interpolator) adjuster.apply_vvar_deltas(@coordinates) end |
#calculate_variation_scalars ⇒ Array<Float>
Calculate variation scalars for current coordinates
175 176 177 178 179 180 |
# File 'lib/fontisan/variation/instance_generator.rb', line 175 def calculate_variation_scalars @context.axes.map do |axis| coord = @coordinates[axis.axis_tag] || axis.default_value @context.interpolator.normalize_coordinate(coord, axis.axis_tag) end end |
#generate ⇒ Hash<String, String>
Generate static font instance
Applies variation deltas and returns static font tables.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/fontisan/variation/instance_generator.rb', line 60 def generate # Start with base font tables tables = @font.table_data.dup # Determine variation type if has_variation_table?("gvar") # TrueType outlines with gvar apply_gvar_deltas(tables) elsif has_variation_table?("CFF2") # PostScript outlines with CFF2 blend apply_cff2_blend(tables) end # Apply metrics variations if present apply_metrics_deltas(tables) if @context.has_metrics_variations? # Remove variation-specific tables to create static font remove_variation_tables(tables) tables end |
#generate_named_instance(instance_index) ⇒ Hash<String, String>
Generate a named instance
86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/fontisan/variation/instance_generator.rb', line 86 def generate_named_instance(instance_index) # Extract instance coordinates from fvar return generate if instance_index.nil? || !@context.fvar instances = @context.fvar.instances return generate if instance_index >= instances.length instance = instances[instance_index] @coordinates = build_coordinates_from_instance(instance, @context.axes) generate end |
#interpolate_point(base_point, delta_points, scalars) ⇒ Hash
Interpolate a point
244 245 246 247 |
# File 'lib/fontisan/variation/instance_generator.rb', line 244 def interpolate_point(base_point, delta_points, scalars) @context.interpolator.interpolate_point(base_point, delta_points, scalars) end |
#interpolate_value(base_value, deltas, scalars) ⇒ Float
Interpolate a single value
234 235 236 |
# File 'lib/fontisan/variation/instance_generator.rb', line 234 def interpolate_value(base_value, deltas, scalars) @context.interpolator.interpolate_value(base_value, deltas, scalars) end |
#remove_variation_tables(tables) ⇒ Object
Remove variation tables from static font
223 224 225 226 |
# File 'lib/fontisan/variation/instance_generator.rb', line 223 def remove_variation_tables(tables) variation_tables = %w[fvar gvar cvar HVAR VVAR MVAR avar STAT] variation_tables.each { |tag| tables.delete(tag) } end |