Class: Fontisan::TrueTypeCollection

Inherits:
BaseCollection show all
Defined in:
lib/fontisan/true_type_collection.rb

Overview

TrueType Collection domain object

Represents a complete TrueType Collection file. Inherits all shared functionality from BaseCollection and implements TTC-specific behavior.

Examples:

Reading and extracting fonts

File.open("Helvetica.ttc", "rb") do |io|
  ttc = TrueTypeCollection.read(io)
  puts ttc.num_fonts  # => 6
  fonts = ttc.extract_fonts(io)  # => [TrueTypeFont, TrueTypeFont, ...]
end

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseCollection

#collection_info, #font_count, from_file, #valid?, #version, #version_string

Class Method Details

.collection_formatString

Get the collection format identifier

Returns:

  • (String)

    “TTC” for TrueType Collection



29
30
31
# File 'lib/fontisan/true_type_collection.rb', line 29

def self.collection_format
  "TTC"
end

.font_classClass

Get the font class for TrueType collections

Returns:

  • (Class)

    TrueTypeFont class



21
22
23
24
# File 'lib/fontisan/true_type_collection.rb', line 21

def self.font_class
  require_relative "true_type_font"
  TrueTypeFont
end

Instance Method Details

#extract_fonts(io) ⇒ Array<TrueTypeFont>

Extract fonts as TrueTypeFont objects

Reads each font from the TTC file and returns them as TrueTypeFont objects. This method uses the TTC-specific from_ttc method.

Parameters:

  • io (IO)

    Open file handle to read fonts from

Returns:



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

def extract_fonts(io)
  require_relative "true_type_font"

  font_offsets.map do |offset|
    TrueTypeFont.from_ttc(io, offset)
  end
end

#font(index, io, mode: LoadingModes::FULL) ⇒ TrueTypeFont?

Get a single font from the collection

Overrides BaseCollection to use TrueType-specific from_ttc method.

Parameters:

  • index (Integer)

    Index of the font (0-based)

  • io (IO)

    Open file handle

  • mode (Symbol) (defaults to: LoadingModes::FULL)

    Loading mode (:metadata or :full, default: :full)

Returns:

  • (TrueTypeFont, nil)

    Font object or nil if index out of range



41
42
43
44
45
46
# File 'lib/fontisan/true_type_collection.rb', line 41

def font(index, io, mode: LoadingModes::FULL)
  return nil if index >= num_fonts

  require_relative "true_type_font"
  TrueTypeFont.from_ttc(io, font_offsets[index], mode: mode)
end

#list_fonts(io) ⇒ CollectionListInfo

List all fonts in the collection with basic metadata

Overrides BaseCollection to use TrueType-specific from_ttc method.

Parameters:

  • io (IO)

    Open file handle to read fonts from

Returns:

  • (CollectionListInfo)

    List of fonts with metadata



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/fontisan/true_type_collection.rb', line 69

def list_fonts(io)
  require_relative "models/collection_list_info"
  require_relative "models/collection_font_summary"
  require_relative "true_type_font"
  require_relative "tables/name"

  fonts = font_offsets.map.with_index do |offset, index|
    font = TrueTypeFont.from_ttc(io, offset)

    # Extract basic font info
    name_table = font.table("name")
    post_table = font.table("post")

    family_name = name_table&.english_name(Tables::Name::FAMILY) || "Unknown"
    subfamily_name = name_table&.english_name(Tables::Name::SUBFAMILY) || "Regular"
    postscript_name = name_table&.english_name(Tables::Name::POSTSCRIPT_NAME) || "Unknown"

    # Determine font format
    sfnt = font.header.sfnt_version
    font_format = case sfnt
                  when 0x00010000, 0x74727565 # 0x74727565 = 'true'
                    "TrueType"
                  when 0x4F54544F # 'OTTO'
                    "OpenType"
                  else
                    "Unknown"
                  end

    num_glyphs = post_table&.glyph_names&.length || 0
    num_tables = font.table_names.length

    Models::CollectionFontSummary.new(
      index: index,
      family_name: family_name,
      subfamily_name: subfamily_name,
      postscript_name: postscript_name,
      font_format: font_format,
      num_glyphs: num_glyphs,
      num_tables: num_tables,
    )
  end

  Models::CollectionListInfo.new(
    collection_path: nil, # Will be set by command
    num_fonts: num_fonts,
    fonts: fonts,
  )
end