Class: Fontisan::Woff2Collection

Inherits:
Object
  • Object
show all
Includes:
Collection::SharedLogic
Defined in:
lib/fontisan/woff2_collection.rb

Overview

WOFF2 font collection (spec section 4.2).

Wraps a WOFF2 collection file (flavor='ttcf') and exposes the same interface as TrueTypeCollection/OpenTypeCollection so collection consumers don't need to know which container format they're holding.

Unlike TTC/OTC (which subclass BaseCollection for BinData parsing), WOFF2 collections are decoded eagerly via Woff2::CollectionDecoder because the per-font tables require Brotli decompression + glyf/loca reconstruction before they can be returned.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Collection::SharedLogic

#calculate_table_sharing_for_fonts

Constructor Details

#initialize(data) ⇒ Woff2Collection

Returns a new instance of Woff2Collection.

Parameters:

  • data (String)

    WOFF2 collection binary



23
24
25
# File 'lib/fontisan/woff2_collection.rb', line 23

def initialize(data)
  @data = data.force_encoding(Encoding::BINARY)
end

Instance Attribute Details

#dataString (readonly)

Returns Source WOFF2 binary.

Returns:

  • (String)

    Source WOFF2 binary



20
21
22
# File 'lib/fontisan/woff2_collection.rb', line 20

def data
  @data
end

Class Method Details

.from_file(path) ⇒ Woff2Collection

Load a WOFF2 collection from a file path.

Parameters:

  • path (String)

Returns:



31
32
33
# File 'lib/fontisan/woff2_collection.rb', line 31

def self.from_file(path)
  new(File.binread(path))
end

Instance Method Details

#collection?Boolean

Whether this object represents a font collection. WOFF2 collections are always collections.

Returns:

  • (Boolean)


78
# File 'lib/fontisan/woff2_collection.rb', line 78

def collection? = true

#extract_fonts(_io = nil) ⇒ Array<TrueTypeFont, OpenTypeFont>

Extract every font in the collection.

Parameters:

  • _io (IO, nil) (defaults to: nil)

    Ignored — WOFF2 collections decode in memory.

Returns:



57
58
59
# File 'lib/fontisan/woff2_collection.rb', line 57

def extract_fonts(_io = nil)
  decoded.map { |entry| build_font(entry) }
end

#font(index, _io = nil, _mode: LoadingModes::FULL) ⇒ TrueTypeFont, ...

Get a single font by index.

Parameters:

  • index (Integer)

    0-based font index

  • _io (IO, nil) (defaults to: nil)

    Ignored.

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

    Ignored — full mode only (WOFF2 collections are decoded eagerly).

Returns:



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

def font(index, _io = nil, _mode: LoadingModes::FULL)
  return nil if index >= num_fonts

  build_font(decoded[index])
end

#font_offsetsArray<Integer>

Per-font synthetic offsets. WOFF2 collections don't have byte offsets like TTC (each font is reconstructed in memory); the index is the only identifier. Returned for compatibility with BaseCollection's interface.

Returns:

  • (Array<Integer>)

    0..num_fonts-1



49
50
51
# File 'lib/fontisan/woff2_collection.rb', line 49

def font_offsets
  (0...num_fonts).to_a
end

#formatSymbol

High-level pipeline format identifier. Owned by the collection class so the conversion pipeline can dispatch without case statements.

Returns:

  • (Symbol)

    :woff2_collection



99
# File 'lib/fontisan/woff2_collection.rb', line 99

def format = :woff2_collection

#num_fontsInteger Also known as: font_count

Number of fonts in the collection.

Returns:

  • (Integer)


38
39
40
# File 'lib/fontisan/woff2_collection.rb', line 38

def num_fonts
  decoded.length
end

#table_namesArray<String>

Collections have no single SFNT table directory.

Returns:

  • (Array<String>)

    empty



83
# File 'lib/fontisan/woff2_collection.rb', line 83

def table_names = []

#valid?Boolean

Validate format correctness.

Returns:

  • (Boolean)


88
89
90
91
92
93
# File 'lib/fontisan/woff2_collection.rb', line 88

def valid?
  flavor = @data[4, 4].unpack1("N")
  flavor == Woff2::CollectionDecoder::TTC_FLAVOR
rescue StandardError
  false
end