Class: Fontisan::Converters::WoffWriter

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

Overview

WOFF font writer for creating WOFF files from TTF/OTF fonts

WoffWriter converts TrueType/OpenType fonts to WOFF 1.0 format. The WOFF spec mandates zlib compression; this writer exposes the spec-legal knobs only:

  • zlib_level (0–9) — zlib compression level
  • uncompressed (bool) — store tables uncompressed (legal per WOFF 1.0 §5.1; compLength == origLength)
  • compression_threshold (bytes) — skip compression for tables smaller than N bytes (rarely needed; keeps tiny tables uncompressed)
  • metadata_xml (string) — optional metadata block
  • private_data (string) — optional private data block

Cross-format options (e.g., brotli_quality) are rejected by ConversionStrategy#validate_options! — see ConversionStrategy.

Examples:

Convert TTF to WOFF with max zlib

writer = WoffWriter.new
woff = writer.convert(ttf_font, zlib_level: 9)
File.binwrite("out.woff", woff)

Uncompressed WOFF (legal per spec; useful for tooling pipelines)

writer = WoffWriter.new
woff = writer.convert(ttf_font, uncompressed: true)

Constant Summary collapse

WOFF_SIGNATURE =

WOFF signature constant

0x774F4646
WOFF_VERSION_MAJOR =

WOFF version 1.0

1
WOFF_VERSION_MINOR =
0

Instance Method Summary collapse

Methods included from ConversionStrategy

included, #supports?

Constructor Details

#initializeWoffWriter

Initialize writer. The writer is stateless per call; all knobs come through the per-convert options hash.



62
# File 'lib/fontisan/converters/woff_writer.rb', line 62

def initialize; end

Instance Method Details

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

Convert font to WOFF format.

Parameters:

  • font (TrueTypeFont, OpenTypeFont)

    Source font

  • options (Hash{Symbol => Object}) (defaults to: {})

    Per-call options; see declared options above. Unknown keys (framework metadata like target_format) are tolerated silently. Cross-format misuse (brotli_quality on a WOFF target) is caught upstream by FormatConverter.validate_options_for_target!.

Returns:

  • (String)

    WOFF file data as binary string

Raises:

  • (ArgumentError)

    if any declared option fails validation

  • (ArgumentError)

    if font does not respond to required methods



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/fontisan/converters/woff_writer.rb', line 75

def convert(font, options = {})
  self.class.validate_options!(strategy_options(options))
  validate(font, :woff)

  opts = self.class.default_options.merge(strategy_options(options))
  write_font(
    font,
    zlib_level: opts[:zlib_level],
    uncompressed: opts[:uncompressed],
    compression_threshold: opts[:compression_threshold],
    metadata: opts[:metadata_xml],
    private_data: opts[:private_data],
  )[:woff_binary]
end

#supported_conversionsArray<Array<Symbol>>

Get supported conversions.

Returns:

  • (Array<Array<Symbol>>)

    Pairs this strategy handles



93
94
95
96
97
98
# File 'lib/fontisan/converters/woff_writer.rb', line 93

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

#validate(font, target_format) ⇒ Boolean

Validate that the given font can be converted to WOFF.

Parameters:

  • font (Object)

    Font to validate

  • target_format (Symbol)

    Must be :woff

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)

    if font is nil or missing required methods

  • (Fontisan::Error)

    if target_format is not :woff



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/fontisan/converters/woff_writer.rb', line 107

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

  raise ArgumentError, "Font cannot be nil" if font.nil?

  unless font.respond_to?(:tables) && font.respond_to?(:table_data)
    raise ArgumentError, "Font must respond to :tables and :table_data"
  end
end

#write_font(font, zlib_level:, uncompressed:, compression_threshold:, metadata: nil, private_data: nil) ⇒ Hash{Symbol => String}

Write font to WOFF binary.

Parameters:

  • font (TrueTypeFont, OpenTypeFont)

    Source font

  • zlib_level (Integer)

    0–9

  • uncompressed (Boolean)

    skip zlib; store as-is

  • compression_threshold (Integer)

    skip compression below N bytes

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

    optional metadata XML

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

    optional private data

Returns:

  • (Hash{Symbol => String})

    { woff_binary: <bytes> }



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/fontisan/converters/woff_writer.rb', line 129

def write_font(font, zlib_level:, uncompressed:, compression_threshold:,
               metadata: nil, private_data: nil)
  tables_data = collect_tables_data(font)
  compressed_tables = compress_tables(
    tables_data,
    zlib_level: uncompressed ? 0 : zlib_level,
    skip_compression: uncompressed,
    compression_threshold: compression_threshold,
  )
   = (, zlib_level: zlib_level,
                                                    skip_compression: uncompressed)
  binary = build_woff_file(compressed_tables, font, ,
                           private_data)
  { woff_binary: binary }
end