Class: Fontisan::Converters::Woff2Encoder
- Inherits:
-
Object
- Object
- Fontisan::Converters::Woff2Encoder
- Includes:
- ConversionStrategy
- Defined in:
- lib/fontisan/converters/woff2_encoder.rb
Overview
WOFF2 encoder conversion strategy
Woff2Encoder implements
the ConversionStrategy interface to convert TTF or OTF fonts to WOFF2
format with Brotli compression.
WOFF2 encoding process:
- Load configuration settings
- Determine font flavor (TTF or CFF)
- Collect and order tables
- Apply WOFF2 spec encoder rules (drop DSIG, mark head.flags)
- Transform tables (placeholder for glyf/loca/hmtx optimization)
- Compress all tables with single Brotli stream
- Build WOFF2 header and table directory
- Assemble complete WOFF2 binary
Constant Summary collapse
- SHORT_LOCA_GLYF_MAX =
Highest glyf offset addressable by short loca (uint16 max × 2). Above this, loca MUST use the long format. Public so specs can reference the same threshold the encoder uses.
0x1FFFE
Instance Attribute Summary collapse
-
#config ⇒ Hash
readonly
Configuration settings.
Instance Method Summary collapse
-
#convert(font, options = {}) ⇒ Hash{Symbol => String}
Convert font to WOFF2 format.
-
#initialize(config_path: nil) ⇒ Woff2Encoder
constructor
Initialize encoder with configuration.
-
#supported_conversions ⇒ Array<Array<Symbol>>
Get list of supported conversions.
-
#validate(font, target_format) ⇒ Boolean
Validate that conversion is possible.
Methods included from ConversionStrategy
Constructor Details
#initialize(config_path: nil) ⇒ Woff2Encoder
Initialize encoder with configuration.
The encoder is stateless per call; all conversion knobs come through the per-convert options hash. The config file supplies default values only for fields not expressed via the DSL.
46 47 48 |
# File 'lib/fontisan/converters/woff2_encoder.rb', line 46 def initialize(config_path: nil) @config = load_configuration(config_path) end |
Instance Attribute Details
#config ⇒ Hash (readonly)
Returns Configuration settings.
37 38 39 |
# File 'lib/fontisan/converters/woff2_encoder.rb', line 37 def config @config end |
Instance Method Details
#convert(font, options = {}) ⇒ Hash{Symbol => String}
Convert font to WOFF2 format.
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 103 104 105 106 107 108 109 110 111 |
# File 'lib/fontisan/converters/woff2_encoder.rb', line 68 def convert(font, = {}) validate(font, :woff2) resolved = normalize_legacy_quality() self.class.((resolved)) quality = resolved.fetch(:brotli_quality) do config["brotli"]["quality"] end flavor = detect_flavor(font) table_data = collect_tables(font, ) Woff2::EncoderRules.apply!(table_data) glyf_transform = apply_glyf_loca_transform!(table_data, font) transformer = Woff2::TableTransformer.new(font) transform_enabled = resolved.fetch(:transform_tables, false) entries, transformed_data = build_table_entries(table_data, transformer, transform_enabled, glyf_transform:) # Recompute head.checksumAdjustment for the SFNT the decoder # reconstructs. Chrome's OTS validates this strictly; a stale # source value fails once glyf/loca/head have been modified. # Must run AFTER touch_head_modified! so the modified timestamp # change is included in the checksum. update_checksum_adjustment!(table_data, flavor:, glyf_transform:) compressed_data = compress_tables(entries, table_data, transformed_data, quality) total_sfnt_size = calculate_sfnt_size(table_data, glyf_transform:) header = build_header( flavor: flavor, num_tables: entries.size, total_sfnt_size: total_sfnt_size, total_compressed_size: compressed_data.bytesize, ) { woff2_binary: assemble_woff2(header, entries, compressed_data) } end |
#supported_conversions ⇒ Array<Array<Symbol>>
Get list of supported conversions
116 117 118 119 120 121 |
# File 'lib/fontisan/converters/woff2_encoder.rb', line 116 def supported_conversions [ %i[ttf woff2], %i[otf woff2], ] end |
#validate(font, target_format) ⇒ Boolean
Validate that conversion is possible
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/fontisan/converters/woff2_encoder.rb', line 129 def validate(font, target_format) unless target_format == :woff2 raise Fontisan::Error, "Woff2Encoder only supports conversion to woff2, " \ "got: #{target_format}" end 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 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 |