Class: Fontisan::Converters::Woff2Encoder

Inherits:
Object
  • Object
show all
Includes:
ConversionStrategy
Defined in:
lib/fontisan/converters/woff2_encoder.rb

Overview

WOFF2 encoder conversion strategy

[‘Woff2Encoder`](lib/fontisan/converters/woff2_encoder.rb) implements the ConversionStrategy interface to convert TTF or OTF fonts to WOFF2 format with Brotli compression.

WOFF2 encoding process:

  1. Load configuration settings

  2. Determine font flavor (TTF or CFF)

  3. Collect and order tables

  4. Transform tables (placeholder for glyf/loca/hmtx optimization)

  5. Compress all tables with single Brotli stream

  6. Build WOFF2 header and table directory

  7. Assemble complete WOFF2 binary

For Phase 2 Milestone 2.1:

  • Basic WOFF2 structure generation

  • Brotli compression of table data

  • Valid WOFF2 files for web font delivery

  • Table transformations are architectural placeholders

Examples:

Convert TTF to WOFF2

encoder = Woff2Encoder.new
woff2_binary = encoder.convert(font)
File.binwrite('font.woff2', woff2_binary)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ConversionStrategy

#supports?

Constructor Details

#initialize(config_path: nil) ⇒ Woff2Encoder

Initialize encoder with configuration

Parameters:

  • config_path (String, nil) (defaults to: nil)

    Path to config file



47
48
49
# File 'lib/fontisan/converters/woff2_encoder.rb', line 47

def initialize(config_path: nil)
  @config = load_configuration(config_path)
end

Instance Attribute Details

#configHash (readonly)

Returns Configuration settings.

Returns:

  • (Hash)

    Configuration settings



42
43
44
# File 'lib/fontisan/converters/woff2_encoder.rb', line 42

def config
  @config
end

Instance Method Details

#convert(font, options = {}) ⇒ Hash

Convert font to WOFF2 format

Returns a hash with :woff2_binary key containing complete WOFF2 file. This is different from other converters that return table data.

Parameters:

Options Hash (options):

  • :quality (Integer)

    Brotli quality (0-11)

  • :transform_tables (Boolean)

    Apply table transformations

Returns:

  • (Hash)

    Hash with :woff2_binary key containing WOFF2 binary

Raises:

  • (Error)

    If encoding fails



62
63
64
65
66
67
68
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
# File 'lib/fontisan/converters/woff2_encoder.rb', line 62

def convert(font, options = {})
  validate(font, :woff2)

  # Get Brotli quality from options or config
  quality = options[:quality] || config["brotli"]["quality"]

  # Detect font flavor
  flavor = detect_flavor(font)

  # Collect all tables
  table_data = collect_tables(font, options)

  # Transform tables (if enabled)
  transformer = Woff2::TableTransformer.new(font)
  transform_enabled = options.fetch(:transform_tables, false)

  # Build table directory entries
  entries = build_table_entries(table_data, transformer,
                                transform_enabled)

  # Compress all table data into single stream
  compressed_data = compress_tables(entries, table_data, quality)

  # Calculate sizes
  total_sfnt_size = calculate_sfnt_size(table_data)
  total_compressed_size = compressed_data.bytesize

  # Build WOFF2 header
  header = build_header(
    flavor: flavor,
    num_tables: entries.size,
    total_sfnt_size: total_sfnt_size,
    total_compressed_size: total_compressed_size,
  )

  # Assemble WOFF2 binary
  woff2_binary = assemble_woff2(header, entries, compressed_data)

  # Return in special format for ConvertCommand to handle
  { woff2_binary: woff2_binary }
end

#supported_conversionsArray<Array<Symbol>>

Get list of supported conversions

Returns:

  • (Array<Array<Symbol>>)

    Supported conversion pairs



107
108
109
110
111
112
# File 'lib/fontisan/converters/woff2_encoder.rb', line 107

def supported_conversions
  [
    %i[ttf woff2],
    %i[otf woff2],
  ]
end

#validate(font, target_format) ⇒ Boolean

Validate that conversion is possible

Parameters:

Returns:

  • (Boolean)

    True if valid

Raises:

  • (Error)

    If conversion is not possible



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/fontisan/converters/woff2_encoder.rb', line 120

def validate(font, target_format)
  unless target_format == :woff2
    raise Fontisan::Error,
          "Woff2Encoder only supports conversion to woff2, " \
          "got: #{target_format}"
  end

  # Verify font has required tables
  required_tables = %w[head hhea maxp]
  required_tables.each do |tag|
    unless font.table(tag)
      raise Fontisan::Error,
            "Font is missing required table: #{tag}"
    end
  end

  # Verify font has either glyf or CFF table
  unless font.has_table?("glyf") || font.has_table?("CFF ") || font.has_table?("CFF2")
    raise Fontisan::Error,
          "Font must have either glyf or CFF/CFF2 table"
  end

  true
end