Class: Fontisan::Tables::Hmtx
- Inherits:
-
Binary::BaseRecord
- Object
- BinData::Record
- Binary::BaseRecord
- Fontisan::Tables::Hmtx
- Extended by:
- Registered
- 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 included from Registered
Methods inherited from Binary::BaseRecord
Instance Attribute Details
#h_metrics ⇒ Array<Hash> (readonly)
Parsed horizontal metrics array
60 61 62 |
# File 'lib/fontisan/tables/hmtx.rb', line 60 def h_metrics @h_metrics end |
#left_side_bearings ⇒ Array<Integer> (readonly)
Parsed left side bearings array
64 65 66 |
# File 'lib/fontisan/tables/hmtx.rb', line 64 def left_side_bearings @left_side_bearings end |
#num_glyphs ⇒ Integer (readonly)
Total number of glyphs from maxp table
72 73 74 |
# File 'lib/fontisan/tables/hmtx.rb', line 72 def num_glyphs @num_glyphs end |
#number_of_h_metrics ⇒ Integer (readonly)
Number of horizontal metrics from hhea table
68 69 70 |
# File 'lib/fontisan/tables/hmtx.rb', line 68 def number_of_h_metrics @number_of_h_metrics end |
#raw_data ⇒ Object
Store the raw data for deferred parsing
56 57 58 |
# File 'lib/fontisan/tables/hmtx.rb', line 56 def raw_data @raw_data end |
Class Method Details
.read(io) ⇒ Hmtx
Override read to capture raw data
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/fontisan/tables/hmtx.rb', line 78 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
162 163 164 165 166 167 168 |
# File 'lib/fontisan/tables/hmtx.rb', line 162 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.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/fontisan/tables/hmtx.rb', line 134 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.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/fontisan/tables/hmtx.rb', line 102 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
155 156 157 |
# File 'lib/fontisan/tables/hmtx.rb', line 155 def parsed? !@h_metrics.nil? end |