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 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
66 67 68 |
# File 'lib/fontisan/tables/hmtx.rb', line 66 def h_metrics @h_metrics end |
#left_side_bearings ⇒ Array<Integer> (readonly)
Parsed left side bearings array
70 71 72 |
# File 'lib/fontisan/tables/hmtx.rb', line 70 def left_side_bearings @left_side_bearings end |
#num_glyphs ⇒ Integer (readonly)
Total number of glyphs from maxp table
78 79 80 |
# File 'lib/fontisan/tables/hmtx.rb', line 78 def num_glyphs @num_glyphs end |
#number_of_h_metrics ⇒ Integer (readonly)
Number of horizontal metrics from hhea table
74 75 76 |
# File 'lib/fontisan/tables/hmtx.rb', line 74 def number_of_h_metrics @number_of_h_metrics end |
#raw_data ⇒ Object
Store the raw data for deferred parsing
62 63 64 |
# File 'lib/fontisan/tables/hmtx.rb', line 62 def raw_data @raw_data end |
Class Method Details
.read(io) ⇒ Hmtx
Override read to capture raw data
84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/fontisan/tables/hmtx.rb', line 84 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
168 169 170 171 172 173 174 |
# File 'lib/fontisan/tables/hmtx.rb', line 168 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.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/fontisan/tables/hmtx.rb', line 140 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.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/fontisan/tables/hmtx.rb', line 108 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
161 162 163 |
# File 'lib/fontisan/tables/hmtx.rb', line 161 def parsed? !@h_metrics.nil? end |