Class: Fontisan::Converters::WoffWriter
- Inherits:
-
Object
- Object
- Fontisan::Converters::WoffWriter
- 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 leveluncompressed(bool) — store tables uncompressed (legal per WOFF 1.0 §5.1;compLength == origLength). Metadata is still compressed per spec §7 ("it is never stored in uncompressed form").compression_threshold(bytes) — skip compression for tables smaller than N bytes (rarely needed; keeps tiny tables uncompressed)metadata_xml(string) — optional metadata blockprivate_data(string) — optional private data block
Cross-format options (e.g., brotli_quality) are rejected by
ConversionStrategy#validate_options! — see ConversionStrategy.
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
-
#convert(font, options = {}) ⇒ String
Convert font to WOFF format.
-
#initialize ⇒ WoffWriter
constructor
Initialize writer.
-
#supported_conversions ⇒ Array<Array<Symbol>>
Get supported conversions.
-
#validate(font, target_format) ⇒ Boolean
Validate that the given font can be converted to WOFF.
-
#write_font(font, zlib_level:, uncompressed:, compression_threshold:, metadata: nil, private_data: nil) ⇒ Hash{Symbol => String}
Write font to WOFF binary.
Methods included from ConversionStrategy
Constructor Details
#initialize ⇒ WoffWriter
Initialize writer. The writer is stateless per call; all knobs come through the per-convert options hash.
63 |
# File 'lib/fontisan/converters/woff_writer.rb', line 63 def initialize; end |
Instance Method Details
#convert(font, options = {}) ⇒ String
Convert font to WOFF format.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/fontisan/converters/woff_writer.rb', line 76 def convert(font, = {}) self.class.(()) validate(font, :woff) opts = self.class..merge(()) 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_conversions ⇒ Array<Array<Symbol>>
Get supported conversions.
94 95 96 97 98 99 |
# File 'lib/fontisan/converters/woff_writer.rb', line 94 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.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/fontisan/converters/woff_writer.rb', line 108 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.
Layout per WOFF 1.0 spec:
[header (44)] [table directory (20 × N)] [font tables, 4-byte aligned]
[optional metadata, 4-byte aligned] [optional private data, 4-byte aligned]
Each font table is padded with 0-3 null bytes to a 4-byte boundary (spec §5/§6: "Font data tables in the WOFF file have the same requirement: they MUST begin on 4-byte boundaries and be zero-padded to the next 4-byte boundary"). Padding aligns the next block.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/fontisan/converters/woff_writer.rb', line 140 def write_font(font, zlib_level:, uncompressed:, compression_threshold:, metadata: nil, private_data: nil) tables = collect_tables_data(font) compressed_tables = compress_tables( tables, zlib_level: uncompressed ? 0 : zlib_level, skip_compression: uncompressed, compression_threshold: compression_threshold, ) # Per spec §7, metadata MUST always be zlib-compressed regardless of # the per-table `uncompressed` flag. = (, zlib_level:) binary = build_woff_file(compressed_tables, font, , private_data) { woff_binary: binary } end |