Class: Fontisan::OpenTypeCollection

Inherits:
BinData::Record
  • Object
show all
Defined in:
lib/fontisan/open_type_collection.rb

Overview

OpenType Collection domain object using BinData

Represents a complete OpenType Collection file (OTC) using BinData’s declarative DSL for binary structure definition. Parallel to TrueTypeCollection but for OpenType fonts.

Examples:

Reading and extracting fonts

File.open("fonts.otc", "rb") do |io|
  otc = OpenTypeCollection.read(io)
  puts otc.num_fonts  # => 4
  fonts = otc.extract_fonts(io)  # => [OpenTypeFont, OpenTypeFont, ...]
end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_file(path) ⇒ OpenTypeCollection

Read OpenType Collection from a file

Parameters:

  • path (String)

    Path to the OTC file

Returns:

Raises:

  • (ArgumentError)

    if path is nil or empty

  • (Errno::ENOENT)

    if file does not exist

  • (RuntimeError)

    if file format is invalid



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/fontisan/open_type_collection.rb', line 34

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") { |io| read(io) }
rescue BinData::ValidityError => e
  raise "Invalid OTC file: #{e.message}"
rescue EOFError => e
  raise "Invalid OTC file: unexpected end of file - #{e.message}"
end

Instance Method Details

#extract_fonts(io) ⇒ Array<OpenTypeFont>

Extract fonts as OpenTypeFont objects

Reads each font from the OTC file and returns them as OpenTypeFont objects.

Parameters:

  • io (IO)

    Open file handle to read fonts from

Returns:



54
55
56
57
58
59
60
# File 'lib/fontisan/open_type_collection.rb', line 54

def extract_fonts(io)
  require_relative "open_type_font"

  font_offsets.map do |offset|
    OpenTypeFont.from_collection(io, offset)
  end
end

#font(index, io) ⇒ OpenTypeFont?

Get a single font from the collection

Parameters:

  • index (Integer)

    Index of the font (0-based)

  • io (IO)

    Open file handle

Returns:

  • (OpenTypeFont, nil)

    Font object or nil if index out of range



67
68
69
70
71
72
# File 'lib/fontisan/open_type_collection.rb', line 67

def font(index, io)
  return nil if index >= num_fonts

  require_relative "open_type_font"
  OpenTypeFont.from_collection(io, font_offsets[index])
end

#font_countInteger

Get font count

Returns:

  • (Integer)

    Number of fonts in collection



77
78
79
# File 'lib/fontisan/open_type_collection.rb', line 77

def font_count
  num_fonts
end

#valid?Boolean

Validate format correctness

Returns:

  • (Boolean)

    true if the format is valid, false otherwise



84
85
86
87
88
# File 'lib/fontisan/open_type_collection.rb', line 84

def valid?
  tag == Constants::TTC_TAG && num_fonts.positive? && font_offsets.length == num_fonts
rescue StandardError
  false
end

#versionInteger

Get the OTC version as a single integer

Returns:

  • (Integer)

    Version number (e.g., 0x00010000 for version 1.0)



93
94
95
# File 'lib/fontisan/open_type_collection.rb', line 93

def version
  (major_version << 16) | minor_version
end