Class: Fontisan::OpenTypeFont
- Inherits:
-
BinData::Record
- Object
- BinData::Record
- Fontisan::OpenTypeFont
- Defined in:
- lib/fontisan/open_type_font.rb
Overview
OpenType Font domain object using BinData
Represents a complete OpenType Font file (CFF outlines) using BinData’s declarative DSL for binary structure definition. Parallel to TrueTypeFont but for CFF format.
Instance Attribute Summary collapse
-
#parsed_tables ⇒ Object
Parsed table instances cache.
-
#table_data ⇒ Object
Table data is stored separately since it’s at variable offsets.
Class Method Summary collapse
-
.from_collection(io, offset) ⇒ OpenTypeFont
Read OpenType Font from collection at specific offset.
-
.from_file(path) ⇒ OpenTypeFont
Read OpenType Font from a file.
Instance Method Summary collapse
-
#find_table_entry(tag) ⇒ TableDirectory?
Find a table entry by tag.
-
#has_table?(tag) ⇒ Boolean
Check if font has a specific table.
-
#head_table ⇒ TableDirectory?
Get the head table entry.
-
#initialize_storage ⇒ void
Initialize storage hashes.
-
#read_table_data(io) ⇒ void
Read table data for all tables.
-
#table(tag) ⇒ Tables::*?
Get parsed table instance.
-
#table_names ⇒ Array<String>
Get list of all table tags.
-
#to_file(path) ⇒ Integer
Write OpenType Font to a file.
-
#units_per_em ⇒ Integer?
Get units per em from head table.
-
#valid? ⇒ Boolean
Validate format correctness.
Instance Attribute Details
#parsed_tables ⇒ Object
Parsed table instances cache
33 34 35 |
# File 'lib/fontisan/open_type_font.rb', line 33 def parsed_tables @parsed_tables end |
#table_data ⇒ Object
Table data is stored separately since it’s at variable offsets
30 31 32 |
# File 'lib/fontisan/open_type_font.rb', line 30 def table_data @table_data end |
Class Method Details
.from_collection(io, offset) ⇒ OpenTypeFont
Read OpenType Font from collection at specific offset
64 65 66 67 68 69 70 |
# File 'lib/fontisan/open_type_font.rb', line 64 def self.from_collection(io, offset) io.seek(offset) font = read(io) font.initialize_storage font.read_table_data(io) font end |
.from_file(path) ⇒ OpenTypeFont
Read OpenType Font from a file
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/fontisan/open_type_font.rb', line 42 def self.from_file(path) if path.nil? || path.to_s.empty? raise ArgumentError, "path cannot be nil or empty" end raise Errno::ENOENT, "File not found: #{path}" unless File.exist?(path) File.open(path, "rb") do |io| font = read(io) font.initialize_storage font.read_table_data(io) font end rescue BinData::ValidityError, EOFError => e raise "Invalid OTF file: #{e.}" end |
Instance Method Details
#find_table_entry(tag) ⇒ TableDirectory?
Find a table entry by tag
145 146 147 |
# File 'lib/fontisan/open_type_font.rb', line 145 def find_table_entry(tag) tables.find { |entry| entry.tag == tag } end |
#has_table?(tag) ⇒ Boolean
Check if font has a specific table
137 138 139 |
# File 'lib/fontisan/open_type_font.rb', line 137 def has_table?(tag) tables.any? { |entry| entry.tag == tag } end |
#head_table ⇒ TableDirectory?
Get the head table entry
152 153 154 |
# File 'lib/fontisan/open_type_font.rb', line 152 def head_table find_table_entry(Constants::HEAD_TAG) end |
#initialize_storage ⇒ void
This method returns an undefined value.
Initialize storage hashes
75 76 77 78 |
# File 'lib/fontisan/open_type_font.rb', line 75 def initialize_storage @table_data = {} @parsed_tables = {} end |
#read_table_data(io) ⇒ void
This method returns an undefined value.
Read table data for all tables
84 85 86 87 88 89 90 91 92 |
# File 'lib/fontisan/open_type_font.rb', line 84 def read_table_data(io) @table_data = {} tables.each do |entry| io.seek(entry.offset) # Force UTF-8 encoding on tag for hash key consistency tag_key = entry.tag.dup.force_encoding("UTF-8") @table_data[tag_key] = io.read(entry.table_length) end end |
#table(tag) ⇒ Tables::*?
Get parsed table instance
This method parses the raw table data into a structured table object and caches the result for subsequent calls.
170 171 172 |
# File 'lib/fontisan/open_type_font.rb', line 170 def table(tag) @parsed_tables[tag] ||= parse_table(tag) end |
#table_names ⇒ Array<String>
Get list of all table tags
159 160 161 |
# File 'lib/fontisan/open_type_font.rb', line 159 def table_names tables.map(&:tag) end |
#to_file(path) ⇒ Integer
Write OpenType Font to a file
Writes the complete OTF structure to disk, including proper checksum calculation and table alignment.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/fontisan/open_type_font.rb', line 102 def to_file(path) File.open(path, "wb") do |io| # Write header and tables (directory) write_structure(io) # Write table data with updated offsets write_table_data_with_offsets(io) io.pos end # Update checksum adjustment in head table update_checksum_adjustment_in_file(path) if head_table File.size(path) end |
#units_per_em ⇒ Integer?
Get units per em from head table
177 178 179 180 |
# File 'lib/fontisan/open_type_font.rb', line 177 def units_per_em head = table(Constants::HEAD_TAG) head&.units_per_em end |
#valid? ⇒ Boolean
Validate format correctness
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/fontisan/open_type_font.rb', line 122 def valid? return false unless header return false unless tables.respond_to?(:length) return false unless @table_data.is_a?(Hash) return false if tables.length != header.num_tables return false unless head_table return false unless has_table?(Constants::CFF_TAG) true end |