Class: Fontisan::Variation::MetricsAdjuster
- Inherits:
-
Object
- Object
- Fontisan::Variation::MetricsAdjuster
- Includes:
- TableAccessor
- Defined in:
- lib/fontisan/variation/metrics_adjuster.rb
Overview
Applies metrics variation deltas to font metrics tables
This class handles applying variation deltas from HVAR, VVAR, and MVAR tables to the corresponding metrics tables (hmtx, vmtx, head, hhea, etc.).
Process:
- Parse ItemVariationStore from HVAR/VVAR/MVAR
- Calculate scalars for current coordinates using regions
- Apply deltas to base metrics
- Update metrics tables with adjusted values
Constant Summary collapse
- METRIC_SOURCES =
Maps MVAR metric tags to [table_tag, method] for base value lookup.
{ "hasc" => ["hhea", :ascender], "hdsc" => ["hhea", :descender], "hlgp" => ["hhea", :line_gap], "xhgt" => ["OS/2", :sx_height], "cpht" => ["OS/2", :s_cap_height], }.freeze
Instance Attribute Summary collapse
-
#font ⇒ TrueTypeFont, OpenTypeFont
readonly
Font instance.
-
#interpolator ⇒ Interpolator
readonly
Coordinate interpolator.
Instance Method Summary collapse
-
#apply_hvar_deltas(coordinates) ⇒ Boolean
Apply HVAR deltas to horizontal metrics.
-
#apply_mvar_deltas(coordinates) ⇒ Boolean
Apply MVAR deltas to font-wide metrics.
-
#apply_vvar_deltas(coordinates) ⇒ Boolean
Apply VVAR deltas to vertical metrics.
-
#build_hmtx_data(metrics) ⇒ String?
Build hmtx binary data from metrics.
- #get_base_metric_value(tag) ⇒ Object
-
#initialize(font, interpolator) ⇒ MetricsAdjuster
constructor
Initialize metrics adjuster.
-
#rebuild_hmtx_table(metrics) ⇒ Object
Rebuild hmtx table with adjusted metrics.
-
#update_font_metric(tag, value) ⇒ Object
Update font metric in appropriate table.
-
#update_hhea_number_of_h_metrics(count) ⇒ Object
Update hhea table's numberOfHMetrics field.
Methods included from TableAccessor
#clear_variation_cache, #clear_variation_table, #has_variation_table?, #require_variation_table, #variation_table
Constructor Details
#initialize(font, interpolator) ⇒ MetricsAdjuster
Initialize metrics adjuster
32 33 34 35 36 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 32 def initialize(font, interpolator) @font = font @interpolator = interpolator @variation_tables = {} end |
Instance Attribute Details
#font ⇒ TrueTypeFont, OpenTypeFont (readonly)
Returns Font instance.
23 24 25 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 23 def font @font end |
#interpolator ⇒ Interpolator (readonly)
Returns Coordinate interpolator.
26 27 28 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 26 def interpolator @interpolator end |
Instance Method Details
#apply_hvar_deltas(coordinates) ⇒ Boolean
Apply HVAR deltas to horizontal metrics
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 42 def apply_hvar_deltas(coordinates) return false unless has_variation_table?("HVAR") return false unless has_variation_table?("hmtx") hvar = variation_table("HVAR") return false unless hvar&.item_variation_store # Parse region list and calculate scalars regions = extract_regions_from_store(hvar.item_variation_store) return false if regions.empty? scalars = @interpolator.calculate_scalars(coordinates, regions) # Get hmtx table hmtx = variation_table("hmtx") return false unless hmtx&.parsed? # Get glyph count maxp = variation_table("maxp") glyph_count = maxp ? maxp.num_glyphs : 0 return false if glyph_count.zero? # Apply deltas to each glyph adjusted_metrics = apply_horizontal_metrics_deltas( hvar, hmtx, glyph_count, scalars ) # Rebuild hmtx table with adjusted metrics rebuild_hmtx_table(adjusted_metrics) true end |
#apply_mvar_deltas(coordinates) ⇒ Boolean
Apply MVAR deltas to font-wide metrics
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 103 def apply_mvar_deltas(coordinates) return false unless has_variation_table?("MVAR") mvar = variation_table("MVAR") return false unless mvar&.item_variation_store # Parse region list and calculate scalars regions = extract_regions_from_store(mvar.item_variation_store) return false if regions.empty? scalars = @interpolator.calculate_scalars(coordinates, regions) # Apply deltas to each metric tag apply_font_wide_metrics_deltas(mvar, scalars) true end |
#apply_vvar_deltas(coordinates) ⇒ Boolean
Apply VVAR deltas to vertical metrics
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 79 def apply_vvar_deltas(coordinates) return false unless has_variation_table?("VVAR") return false unless has_variation_table?("vmtx") vvar = variation_table("VVAR") return false unless vvar&.item_variation_store # Parse region list and calculate scalars regions = extract_regions_from_store(vvar.item_variation_store) return false if regions.empty? @interpolator.calculate_scalars(coordinates, regions) # Apply deltas to vmtx # Similar to HVAR but for vertical metrics # Placeholder for full implementation true end |
#build_hmtx_data(metrics) ⇒ String?
Build hmtx binary data from metrics
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 262 def build_hmtx_data(metrics) return nil if metrics.empty? # Find last unique advance width last_advance = metrics.last[:advance_width] number_of_h_metrics = metrics.length # Optimize: count from end while advance width is same (metrics.length - 1).downto(1) do |i| break if metrics[i][:advance_width] != last_advance number_of_h_metrics = i end # Build binary data data = String.new("", encoding: Encoding::BINARY) # Write hMetrics array number_of_h_metrics.times do |i| metric = metrics[i] data << [metric[:advance_width]].pack("n") # uint16 data << [metric[:lsb]].pack("n") # int16 (as uint16, will be interpreted as signed) end # Write remaining LSBs (number_of_h_metrics...metrics.length).each do |i| data << [metrics[i][:lsb]].pack("n") # int16 end # Update hhea's numberOfHMetrics update_hhea_number_of_h_metrics(number_of_h_metrics) data end |
#get_base_metric_value(tag) ⇒ Object
227 228 229 230 231 232 233 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 227 def get_base_metric_value(tag) source = METRIC_SOURCES[tag] return nil unless source table_tag, method = source variation_table(table_tag)&.public_send(method) end |
#rebuild_hmtx_table(metrics) ⇒ Object
Rebuild hmtx table with adjusted metrics
250 251 252 253 254 255 256 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 250 def rebuild_hmtx_table(metrics) # Build new hmtx binary data data = build_hmtx_data(metrics) # Update font's table data @font.table_data["hmtx"] = data if data end |
#update_font_metric(tag, value) ⇒ Object
Update font metric in appropriate table
239 240 241 242 243 244 245 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 239 def update_font_metric(tag, value) # This is a placeholder - full implementation would: # 1. Modify the appropriate table's binary data # 2. Update the font's table data # For now, we just log the update # In production, this would rebuild the affected tables end |
#update_hhea_number_of_h_metrics(count) ⇒ Object
Update hhea table's numberOfHMetrics field
300 301 302 303 304 305 306 307 308 |
# File 'lib/fontisan/variation/metrics_adjuster.rb', line 300 def update_hhea_number_of_h_metrics(count) return unless has_variation_table?("hhea") hhea = variation_table("hhea") return unless hhea # Update the field if hhea supports it hhea.number_of_h_metrics = count end |