Class: Fontisan::SfntTable Abstract
- Inherits:
-
Object
- Object
- Fontisan::SfntTable
- Defined in:
- lib/fontisan/sfnt_table.rb
Overview
Subclasses should override ‘parser_class` and `validate_parsed_table?`
Base class for SFNT font tables
Represents a single table in an SFNT font file, encapsulating:
-
Table metadata (tag, checksum, offset, length)
-
Lazy loading of table data
-
Parsing of table data into structured objects
-
Table-specific validation
This class provides an OOP representation of font tables, replacing the previous separation of TableDirectory (metadata), @table_data (raw bytes), and @parsed_tables (parsed objects) with a single cohesive domain object.
Direct Known Subclasses
Tables::CmapTable, Tables::GlyfTable, Tables::HeadTable, Tables::HheaTable, Tables::HmtxTable, Tables::LocaTable, Tables::MaxpTable, Tables::NameTable, Tables::Os2Table, Tables::PostTable
Instance Attribute Summary collapse
-
#data ⇒ String?
readonly
Raw table data (loaded lazily).
-
#entry ⇒ TableDirectory
readonly
Table metadata entry (from TableDirectory).
-
#font ⇒ SfntFont
readonly
Parent font containing this table.
-
#parsed ⇒ Object?
readonly
Parsed table object (cached).
Instance Method Summary collapse
-
#available? ⇒ Boolean
Check if table is available in current loading mode.
-
#calculate_checksum ⇒ Integer
Calculate table checksum.
-
#checksum ⇒ Integer
Table checksum.
-
#data_loaded? ⇒ Boolean
Check if table data is loaded.
-
#human_name ⇒ String
Get human-readable table name.
-
#initialize(font, entry) ⇒ SfntTable
constructor
Initialize a new SfntTable.
-
#inspect ⇒ String
String representation.
-
#length ⇒ Integer
Table length in bytes.
-
#load_data! ⇒ self
Load raw table data from font file.
-
#offset ⇒ Integer
Table offset in font file.
-
#parse ⇒ Object?
Parse table data into structured object.
-
#parsed? ⇒ Boolean
Check if table has been parsed.
-
#required? ⇒ Boolean
Check if table is required for the font.
-
#tag ⇒ String
Table tag (4-character string).
-
#to_s ⇒ String
String representation for display.
-
#validate! ⇒ Boolean
Validate the table.
Constructor Details
#initialize(font, entry) ⇒ SfntTable
Initialize a new SfntTable
91 92 93 94 95 96 |
# File 'lib/fontisan/sfnt_table.rb', line 91 def initialize(font, entry) @font = font @entry = entry @data = nil @parsed = nil end |
Instance Attribute Details
#data ⇒ String? (readonly)
Raw table data (loaded lazily)
52 53 54 |
# File 'lib/fontisan/sfnt_table.rb', line 52 def data @data end |
#entry ⇒ TableDirectory (readonly)
Table metadata entry (from TableDirectory)
42 43 44 |
# File 'lib/fontisan/sfnt_table.rb', line 42 def entry @entry end |
#font ⇒ SfntFont (readonly)
Parent font containing this table
47 48 49 |
# File 'lib/fontisan/sfnt_table.rb', line 47 def font @font end |
#parsed ⇒ Object? (readonly)
Parsed table object (cached)
57 58 59 |
# File 'lib/fontisan/sfnt_table.rb', line 57 def parsed @parsed end |
Instance Method Details
#available? ⇒ Boolean
Check if table is available in current loading mode
208 209 210 |
# File 'lib/fontisan/sfnt_table.rb', line 208 def available? @font.table_available?(tag) end |
#calculate_checksum ⇒ Integer
Calculate table checksum
198 199 200 201 202 203 |
# File 'lib/fontisan/sfnt_table.rb', line 198 def calculate_checksum load_data! unless data_loaded? require_relative "utilities/checksum_calculator" Utilities::ChecksumCalculator.calculate_table_checksum(@data) end |
#checksum ⇒ Integer
Table checksum
69 70 71 |
# File 'lib/fontisan/sfnt_table.rb', line 69 def checksum @entry.checksum end |
#data_loaded? ⇒ Boolean
Check if table data is loaded
128 129 130 |
# File 'lib/fontisan/sfnt_table.rb', line 128 def data_loaded? !@data.nil? end |
#human_name ⇒ String
Get human-readable table name
222 223 224 |
# File 'lib/fontisan/sfnt_table.rb', line 222 def human_name Constants::TABLE_NAMES[tag] || tag end |
#inspect ⇒ String
String representation
229 230 231 |
# File 'lib/fontisan/sfnt_table.rb', line 229 def inspect "#<#{self.class.name} tag=#{tag.inspect} offset=0x#{offset.to_s(16).upcase} length=#{length}>" end |
#length ⇒ Integer
Table length in bytes
83 84 85 |
# File 'lib/fontisan/sfnt_table.rb', line 83 def length @entry.table_length end |
#load_data! ⇒ self
Load raw table data from font file
Reads the table data from the font’s IO source or from cached table data. This method supports lazy loading.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/fontisan/sfnt_table.rb', line 105 def load_data! # Check if already loaded return self if @data # Try to get from font's table_data cache if @font.table_data && @font.table_data[tag] @data = @font.table_data[tag] return self end # Load from IO source if available if @font.io_source @font.io_source.seek(offset) @data = @font.io_source.read(length) return self end raise "Cannot load table '#{tag}': no IO source or cached data" end |
#offset ⇒ Integer
Table offset in font file
76 77 78 |
# File 'lib/fontisan/sfnt_table.rb', line 76 def offset @entry.offset end |
#parse ⇒ Object?
Parse table data into structured object
Loads data if needed, then parses using the table-specific parser class. Results are cached for subsequent calls.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/fontisan/sfnt_table.rb', line 146 def parse return @parsed if parsed? # Load data if not already loaded load_data! unless data_loaded? # Get parser class for this table type parser = parser_class return nil unless parser # Parse and cache @parsed = parser.read(@data) @parsed end |
#parsed? ⇒ Boolean
Check if table has been parsed
135 136 137 |
# File 'lib/fontisan/sfnt_table.rb', line 135 def parsed? !@parsed.nil? end |
#required? ⇒ Boolean
Check if table is required for the font
215 216 217 |
# File 'lib/fontisan/sfnt_table.rb', line 215 def required? Constants::REQUIRED_TABLES.include?(tag) end |
#tag ⇒ String
Table tag (4-character string)
62 63 64 |
# File 'lib/fontisan/sfnt_table.rb', line 62 def tag @entry.tag end |
#to_s ⇒ String
String representation for display
236 237 238 |
# File 'lib/fontisan/sfnt_table.rb', line 236 def to_s "#{tag}: #{human_name} (#{length} bytes @ 0x#{offset.to_s(16).upcase})" end |
#validate! ⇒ Boolean
Validate the table
Performs table-specific validation. Subclasses should override ‘validate_parsed_table?` to provide custom validation logic.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/fontisan/sfnt_table.rb', line 168 def validate! # Ensure data is loaded load_data! unless data_loaded? # Basic validation: data size matches expected size if @data.bytesize != length raise InvalidFontError, "Table '#{tag}' data size mismatch: expected #{length} bytes, got #{@data.bytesize}" end # Validate checksum if not head table (head table checksum is special) if tag != Constants::HEAD_TAG expected_checksum = calculate_checksum if checksum != expected_checksum # Checksum mismatch might be OK for some tables, log a warning # But don't fail validation for it end end # Table-specific validation (if parsed) if parsed? validate_parsed_table? end true end |