Class: Fontisan::Tables::Hvar

Inherits:
Binary::BaseRecord show all
Defined in:
lib/fontisan/tables/hvar.rb

Overview

Parser for the 'HVAR' (Horizontal Metrics Variations) table

The HVAR table provides variation data for horizontal metrics including:

  • Advance width variations
  • Left side bearing (LSB) variations

This table uses the ItemVariationStore structure to efficiently store delta values for different regions in the design space.

Reference: OpenType specification, HVAR table

Examples:

Reading an HVAR table

data = font.table_data("HVAR")
hvar = Fontisan::Tables::Hvar.read(data)
advance_deltas = hvar.advance_width_deltas(glyph_id, coordinates)

Instance Method Summary collapse

Methods inherited from Binary::BaseRecord

#raw_data, read

Instance Method Details

#advance_width_delta_set(glyph_id) ⇒ Array<Integer>?

Get advance width delta set for a glyph

Parameters:

  • glyph_id (Integer)

    Glyph ID

Returns:

  • (Array<Integer>, nil)

    Delta values or nil



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/fontisan/tables/hvar.rb', line 115

def advance_width_delta_set(glyph_id)
  return nil unless item_variation_store

  # If no mapping, use glyph_id directly
  if advance_width_mapping.nil?
    return item_variation_store.delta_set(0, glyph_id)
  end

  # Use mapping to get delta set indices
  map_data = advance_width_mapping.map_data
  return nil if glyph_id >= map_data.length

  delta_index = map_data[glyph_id]
  outer_index = (delta_index >> 16) & 0xFFFF
  inner_index = delta_index & 0xFFFF

  item_variation_store.delta_set(outer_index, inner_index)
end

#advance_width_mappingVariationCommon::DeltaSetIndexMap?

Parse advance width mapping

Returns:



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fontisan/tables/hvar.rb', line 57

def advance_width_mapping
  return @advance_width_mapping if defined?(@advance_width_mapping)
  return @advance_width_mapping = nil if advance_width_mapping_offset.zero?

  data = raw_data
  offset = advance_width_mapping_offset

  return @advance_width_mapping = nil if offset >= data.bytesize

  map_data = data.byteslice(offset..-1)
  @advance_width_mapping = VariationCommon::DeltaSetIndexMap.read(map_data)
rescue StandardError => e
  warn "Failed to parse HVAR advance width mapping: #{e.message}"
  @advance_width_mapping = nil
end

#item_variation_storeVariationCommon::ItemVariationStore?

Parse the item variation store

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fontisan/tables/hvar.rb', line 38

def item_variation_store
  return @item_variation_store if defined?(@item_variation_store)
  return @item_variation_store = nil if item_variation_store_offset.zero?

  data = raw_data
  offset = item_variation_store_offset

  return @item_variation_store = nil if offset >= data.bytesize

  store_data = data.byteslice(offset..-1)
  @item_variation_store = VariationCommon::ItemVariationStore.read(store_data)
rescue StandardError => e
  warn "Failed to parse HVAR item variation store: #{e.message}"
  @item_variation_store = nil
end

#lsb_delta_set(glyph_id) ⇒ Array<Integer>?

Get LSB delta set for a glyph

Parameters:

  • glyph_id (Integer)

    Glyph ID

Returns:

  • (Array<Integer>, nil)

    Delta values or nil



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/fontisan/tables/hvar.rb', line 138

def lsb_delta_set(glyph_id)
  return nil unless item_variation_store

  # If no mapping, use glyph_id directly
  if lsb_mapping.nil?
    return item_variation_store.delta_set(0, glyph_id)
  end

  # Use mapping to get delta set indices
  map_data = lsb_mapping.map_data
  return nil if glyph_id >= map_data.length

  delta_index = map_data[glyph_id]
  outer_index = (delta_index >> 16) & 0xFFFF
  inner_index = delta_index & 0xFFFF

  item_variation_store.delta_set(outer_index, inner_index)
end

#lsb_mappingVariationCommon::DeltaSetIndexMap?

Parse LSB (left side bearing) mapping

Returns:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/fontisan/tables/hvar.rb', line 76

def lsb_mapping
  return @lsb_mapping if defined?(@lsb_mapping)
  return @lsb_mapping = nil if lsb_mapping_offset.zero?

  data = raw_data
  offset = lsb_mapping_offset

  return @lsb_mapping = nil if offset >= data.bytesize

  map_data = data.byteslice(offset..-1)
  @lsb_mapping = VariationCommon::DeltaSetIndexMap.read(map_data)
rescue StandardError => e
  warn "Failed to parse HVAR LSB mapping: #{e.message}"
  @lsb_mapping = nil
end

#rsb_delta_set(glyph_id) ⇒ Array<Integer>?

Get RSB delta set for a glyph

Parameters:

  • glyph_id (Integer)

    Glyph ID

Returns:

  • (Array<Integer>, nil)

    Delta values or nil



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/fontisan/tables/hvar.rb', line 161

def rsb_delta_set(glyph_id)
  return nil unless item_variation_store

  # If no mapping, use glyph_id directly
  if rsb_mapping.nil?
    return item_variation_store.delta_set(0, glyph_id)
  end

  # Use mapping to get delta set indices
  map_data = rsb_mapping.map_data
  return nil if glyph_id >= map_data.length

  delta_index = map_data[glyph_id]
  outer_index = (delta_index >> 16) & 0xFFFF
  inner_index = delta_index & 0xFFFF

  item_variation_store.delta_set(outer_index, inner_index)
end

#rsb_mappingVariationCommon::DeltaSetIndexMap?

Parse RSB (right side bearing) mapping

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/fontisan/tables/hvar.rb', line 95

def rsb_mapping
  return @rsb_mapping if defined?(@rsb_mapping)
  return @rsb_mapping = nil if rsb_mapping_offset.zero?

  data = raw_data
  offset = rsb_mapping_offset

  return @rsb_mapping = nil if offset >= data.bytesize

  map_data = data.byteslice(offset..-1)
  @rsb_mapping = VariationCommon::DeltaSetIndexMap.read(map_data)
rescue StandardError => e
  warn "Failed to parse HVAR RSB mapping: #{e.message}"
  @rsb_mapping = nil
end

#valid?Boolean

Check if table is valid

Returns:

  • (Boolean)

    True if valid



183
184
185
# File 'lib/fontisan/tables/hvar.rb', line 183

def valid?
  major_version == 1 && minor_version.zero?
end

#versionFloat

Get version as a float

Returns:

  • (Float)

    Version number (e.g., 1.0)



31
32
33
# File 'lib/fontisan/tables/hvar.rb', line 31

def version
  major_version + (minor_version / 10.0)
end