Class: ExtractTtc::TrueTypeFont

Inherits:
BinData::Record
  • Object
show all
Defined in:
lib/extract_ttc/true_type_font.rb

Overview

TrueType Font domain object using BinData

Represents a complete TrueType Font file using BinData’s declarative DSL for binary structure definition. The structure definition IS the documentation, and BinData handles all low-level reading/writing.

Examples:

Writing a font

ttc = TrueTypeCollection.from_file("Helvetica.ttc")
fonts = ttc.extract_fonts
fonts[0].to_file("Helvetica_0.ttf")

Reading a font

ttf = TrueTypeFont.from_file("font.ttf")
puts ttf.header.num_tables  # => 14

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#table_dataObject

Table data is stored separately since it’s at variable offsets



50
51
52
# File 'lib/extract_ttc/true_type_font.rb', line 50

def table_data
  @table_data
end

Class Method Details

.from_file(path) ⇒ TrueTypeFont

Read TrueType Font from a file

Parameters:

  • path (String)

    Path to the TTF file

Returns:

Raises:

  • (ArgumentError)

    if path is nil or empty

  • (Errno::ENOENT)

    if file does not exist

  • (RuntimeError)

    if file format is invalid



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/extract_ttc/true_type_font.rb', line 59

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.read_table_data(io)
    font
  end
rescue BinData::ValidityError, EOFError => e
  raise "Invalid TTF file: #{e.message}"
end

.from_ttc(io, offset) ⇒ TrueTypeFont

Read TrueType Font from TTC at specific offset

Parameters:

  • io (IO)

    Open file handle

  • offset (Integer)

    Byte offset to the font

Returns:



80
81
82
83
84
85
# File 'lib/extract_ttc/true_type_font.rb', line 80

def self.from_ttc(io, offset)
  io.seek(offset)
  font = read(io)
  font.read_table_data(io)
  font
end

Instance Method Details

#find_table_entry(tag) ⇒ TableDirectory?

Find a table entry by tag

Parameters:

  • tag (String)

    The table tag to find

Returns:



149
150
151
# File 'lib/extract_ttc/true_type_font.rb', line 149

def find_table_entry(tag)
  tables.find { |entry| entry.tag == tag }
end

#has_table?(tag) ⇒ Boolean

Check if font has a specific table

Parameters:

  • tag (String)

    The table tag to check for

Returns:

  • (Boolean)

    true if table exists, false otherwise



141
142
143
# File 'lib/extract_ttc/true_type_font.rb', line 141

def has_table?(tag)
  tables.any? { |entry| entry.tag == tag }
end

#head_tableTableDirectory?

Get the head table entry

Returns:



156
157
158
# File 'lib/extract_ttc/true_type_font.rb', line 156

def head_table
  find_table_entry(Constants::HEAD_TAG)
end

#read_table_data(io) ⇒ void

This method returns an undefined value.

Read table data for all tables

Parameters:

  • io (IO)

    Open file handle



91
92
93
94
95
96
97
# File 'lib/extract_ttc/true_type_font.rb', line 91

def read_table_data(io)
  @table_data = {}
  tables.each do |entry|
    io.seek(entry.offset)
    @table_data[entry.tag] = io.read(entry.table_length)
  end
end

#to_file(path) ⇒ Integer

Write TrueType Font to a file

Writes the complete TTF structure to disk, including proper checksum calculation and table alignment.

Parameters:

  • path (String)

    Path where the TTF file will be written

Returns:

  • (Integer)

    Number of bytes written

Raises:

  • (IOError)

    if writing fails



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/extract_ttc/true_type_font.rb', line 107

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

#valid?Boolean

Validate format correctness

Returns:

  • (Boolean)

    true if the TTF format is valid, false otherwise



127
128
129
130
131
132
133
134
135
# File 'lib/extract_ttc/true_type_font.rb', line 127

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

  true
end