Class: Fontisan::Variation::DeltaApplier

Inherits:
Object
  • Object
show all
Includes:
TableAccessor
Defined in:
lib/fontisan/variation/delta_applier.rb

Overview

Applies variation deltas to glyph outlines

This class handles the complete delta application process for TrueType variable fonts using gvar table data:

  1. Parse base glyph outline points

  2. Match active tuple variations to coordinates

  3. Parse and decompress deltas

  4. Apply deltas: new_point = base + Σ(delta × scalar)

  5. Expand IUP (Inferred Untouched Points)

Reference: OpenType specification, gvar table

Examples:

Applying deltas to a glyph

applier = Fontisan::Variation::DeltaApplier.new(font, interpolator, region_matcher)
adjusted_points = applier.apply_deltas(glyph_id, coordinates)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from TableAccessor

#clear_variation_cache, #clear_variation_table, #has_variation_table?, #require_variation_table, #variation_table

Constructor Details

#initialize(font, interpolator, region_matcher) ⇒ DeltaApplier

Initialize delta applier

Parameters:



45
46
47
48
49
50
51
# File 'lib/fontisan/variation/delta_applier.rb', line 45

def initialize(font, interpolator, region_matcher)
  @font = font
  @interpolator = interpolator
  @region_matcher = region_matcher
  @delta_parser = DeltaParser.new
  @variation_tables = {}
end

Instance Attribute Details

#delta_parserDeltaParser (readonly)

Returns Delta parser.

Returns:



38
39
40
# File 'lib/fontisan/variation/delta_applier.rb', line 38

def delta_parser
  @delta_parser
end

#fontFont (readonly)

Returns Font object.

Returns:

  • (Font)

    Font object



29
30
31
# File 'lib/fontisan/variation/delta_applier.rb', line 29

def font
  @font
end

#interpolatorInterpolator (readonly)

Returns Coordinate interpolator.

Returns:



32
33
34
# File 'lib/fontisan/variation/delta_applier.rb', line 32

def interpolator
  @interpolator
end

#region_matcherRegionMatcher (readonly)

Returns Region matcher.

Returns:



35
36
37
# File 'lib/fontisan/variation/delta_applier.rb', line 35

def region_matcher
  @region_matcher
end

Instance Method Details

#apply_deltas(glyph_id, coordinates) ⇒ Array<Hash>?

Apply deltas to a glyph at given coordinates

Parameters:

  • glyph_id (Integer)

    Glyph ID

  • coordinates (Hash<String, Float>)

    Design space coordinates

Returns:

  • (Array<Hash>, nil)

    Adjusted points or nil if not applicable



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/fontisan/variation/delta_applier.rb', line 58

def apply_deltas(glyph_id, coordinates)
  gvar = variation_table("gvar")
  glyf = variation_table("glyf")
  return nil unless gvar && glyf

  # Get base glyph outline points
  base_points = extract_glyph_points(glyph_id, glyf)
  return nil if base_points.nil? || base_points.empty?

  # Get tuple variations for this glyph
  tuple_data = gvar.glyph_tuple_variations(glyph_id)
  return base_points if tuple_data.nil? || tuple_data[:tuples].empty?

  # Match active tuples to coordinates
  matches = @region_matcher.match_tuples(
    coordinates: coordinates,
    tuples: tuple_data[:tuples],
  )

  return base_points if matches.empty?

  # Apply each active tuple's deltas
  adjusted_points = base_points.dup
  matches.each do |match|
    apply_tuple_deltas(adjusted_points, match, tuple_data, base_points.length)
  end

  adjusted_points
end

#extract_glyph_points(glyph_id, glyf) ⇒ Array<Hash>?

Extract outline points from glyph

Parameters:

  • glyph_id (Integer)

    Glyph ID

  • glyf (Glyf)

    Glyf table

Returns:

  • (Array<Hash>, nil)

    Array of points with :x, :y, :on_curve



93
94
95
96
97
98
99
100
101
102
# File 'lib/fontisan/variation/delta_applier.rb', line 93

def extract_glyph_points(glyph_id, glyf)
  # This is a simplified version - full implementation would parse
  # complete glyf table data including composite glyphs
  glyph_data = glyf.glyph_data(glyph_id)
  return nil if glyph_data.nil?

  # Parse glyph outline (simplified)
  # Real implementation would fully parse SimpleGlyph or CompositeGlyph
  []
end