Class: Fontisan::Tables::Hmtx
- Inherits:
-
Binary::BaseRecord
- Object
- BinData::Record
- Binary::BaseRecord
- Fontisan::Tables::Hmtx
- Defined in:
- lib/fontisan/tables/hmtx.rb
Overview
Parser for the 'hmtx' (Horizontal Metrics) table
The hmtx table contains horizontal metrics for each glyph in the font. It provides advance width and left sidebearing values needed for proper glyph positioning and text layout.
Structure:
-
hMetrics: Array of LongHorMetric records
Each record contains:
- advanceWidth (uint16): Advance width in FUnits
- lsb (int16): Left side bearing in FUnits
- leftSideBearings[numGlyphs - numberOfHMetrics]: Array of int16 values Additional LSB values for glyphs beyond numberOfHMetrics
The table is context-dependent and requires:
- numberOfHMetrics from hhea table
- numGlyphs from maxp table
Reference: OpenType specification, hmtx table https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
Defined Under Namespace
Classes: LongHorMetric
Instance Attribute Summary collapse
-
#h_metrics ⇒ Array<Hash>
readonly
Parsed horizontal metrics array.
-
#left_side_bearings ⇒ Array<Integer>
readonly
Parsed left side bearings array.
-
#num_glyphs ⇒ Integer
readonly
Total number of glyphs from maxp table.
-
#number_of_h_metrics ⇒ Integer
readonly
Number of horizontal metrics from hhea table.
-
#raw_data ⇒ Object
Store the raw data for deferred parsing.
Class Method Summary collapse
-
.read(io) ⇒ Hmtx
Override read to capture raw data.
Instance Method Summary collapse
-
#expected_min_size ⇒ Integer
Get the expected minimum size for this table.
-
#metric_for(glyph_id) ⇒ Hash?
Get horizontal metrics for a specific glyph ID.
-
#parse_with_context(number_of_h_metrics, num_glyphs) ⇒ Object
Parse the table with font context.
-
#parsed? ⇒ Boolean
Check if the table has been parsed with context.
Methods inherited from Binary::BaseRecord
Instance Attribute Details
#h_metrics ⇒ Array<Hash> (readonly)
Parsed horizontal metrics array
64 65 66 |
# File 'lib/fontisan/tables/hmtx.rb', line 64 def h_metrics @h_metrics end |
#left_side_bearings ⇒ Array<Integer> (readonly)
Parsed left side bearings array
68 69 70 |
# File 'lib/fontisan/tables/hmtx.rb', line 68 def left_side_bearings @left_side_bearings end |
#num_glyphs ⇒ Integer (readonly)
Total number of glyphs from maxp table
76 77 78 |
# File 'lib/fontisan/tables/hmtx.rb', line 76 def num_glyphs @num_glyphs end |
#number_of_h_metrics ⇒ Integer (readonly)
Number of horizontal metrics from hhea table
72 73 74 |
# File 'lib/fontisan/tables/hmtx.rb', line 72 def number_of_h_metrics @number_of_h_metrics end |
#raw_data ⇒ Object
Store the raw data for deferred parsing
60 61 62 |
# File 'lib/fontisan/tables/hmtx.rb', line 60 def raw_data @raw_data end |
Class Method Details
.read(io) ⇒ Hmtx
Override read to capture raw data
82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/fontisan/tables/hmtx.rb', line 82 def self.read(io) instance = new # Handle nil or empty data gracefully instance.raw_data = if io.nil? "".b elsif io.is_a?(String) io else io.read || "".b end instance end |
Instance Method Details
#expected_min_size ⇒ Integer
Get the expected minimum size for this table
166 167 168 169 170 171 172 |
# File 'lib/fontisan/tables/hmtx.rb', line 166 def expected_min_size return nil unless parsed? # numberOfHMetrics × 4 bytes (uint16 + int16) # + (numGlyphs - numberOfHMetrics) × 2 bytes (int16) (number_of_h_metrics * 4) + ((num_glyphs - number_of_h_metrics) * 2) end |
#metric_for(glyph_id) ⇒ Hash?
Get horizontal metrics for a specific glyph ID
For glyph IDs less than numberOfHMetrics, returns the corresponding hMetrics entry. For glyph IDs >= numberOfHMetrics, uses the last advance width from hMetrics with the indexed left side bearing.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/fontisan/tables/hmtx.rb', line 138 def metric_for(glyph_id) raise "Table not parsed. Call parse_with_context first." unless @h_metrics return nil if glyph_id >= num_glyphs || glyph_id.negative? if glyph_id < h_metrics.length # Direct lookup in hMetrics array h_metrics[glyph_id] else # Use last advance width with indexed LSB lsb_index = glyph_id - h_metrics.length { advance_width: h_metrics.last[:advance_width], lsb: left_side_bearings[lsb_index], } end end |
#parse_with_context(number_of_h_metrics, num_glyphs) ⇒ Object
Parse the table with font context
This method must be called after reading the table data, providing the numberOfHMetrics from hhea and numGlyphs from maxp.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/fontisan/tables/hmtx.rb', line 106 def parse_with_context(number_of_h_metrics, num_glyphs) validate_context_params(number_of_h_metrics, num_glyphs) @number_of_h_metrics = number_of_h_metrics @num_glyphs = num_glyphs io = StringIO.new(raw_data) io.set_encoding(Encoding::BINARY) # Parse hMetrics array @h_metrics = parse_h_metrics(io, number_of_h_metrics) # Parse additional left side bearings lsb_count = num_glyphs - number_of_h_metrics @left_side_bearings = parse_left_side_bearings(io, lsb_count) validate_parsed_data!(io) end |
#parsed? ⇒ Boolean
Check if the table has been parsed with context
159 160 161 |
# File 'lib/fontisan/tables/hmtx.rb', line 159 def parsed? !@h_metrics.nil? end |