Class: Fontisan::Woff2::EncoderRules

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/woff2/encoder_rules.rb

Overview

Applies WOFF2 spec "encoder MUST" rules to a table collection before the table directory is built and brotli compression is applied.

Each spec-mandated transform lives here so the encoder stays a thin orchestrator and new rules are MECE/discoverable instead of sprinkled as inline conditionals across Woff2Encoder.

Reference: W3C WOFF2 spec, section 5 ("Recommended table directory").

Constant Summary collapse

EXCLUDED_TABLES =

Tables that MUST NOT appear in WOFF2 output.

Per spec section 5: "The compliant WOFF2 encoder MUST remove the DSIG table from an input font data, prior to applying transformations and entropy coding steps." Chrome's OpenType Sanitizer (OTS) rejects WOFF2 files that still contain DSIG.

%w[DSIG].freeze
TRANSFORMED_TABLES =

Tables that MUST be transformed (when present) per WOFF2 spec section 5.3: glyf and loca are paired — both are either transformed (version 0) or null-transformed (version 3) together. Browsers (Chrome OTS) only accept the transformed form.

%w[glyf loca].freeze

Class Method Summary collapse

Class Method Details

.apply!(table_data) ⇒ Hash{String => String}

Apply all WOFF2 encoder rules to table_data in place.

Parameters:

  • table_data (Hash{String => String})

    Map of tag → binary table data. Mutated.

Returns:

  • (Hash{String => String})

    The same hash, for chaining.



33
34
35
36
37
# File 'lib/fontisan/woff2/encoder_rules.rb', line 33

def self.apply!(table_data)
  exclude_tables!(table_data)
  mark_lossless_modifying!(table_data)
  table_data
end

.exclude_tables!(table_data) ⇒ Object

Drop spec-excluded tables from the collection.



45
46
47
# File 'lib/fontisan/woff2/encoder_rules.rb', line 45

def self.exclude_tables!(table_data)
  EXCLUDED_TABLES.each { |tag| table_data.delete(tag) }
end

.excluded?(tag) ⇒ Boolean

Whether tag is dropped by WOFF2 spec rules.

Returns:

  • (Boolean)


40
41
42
# File 'lib/fontisan/woff2/encoder_rules.rb', line 40

def self.excluded?(tag)
  EXCLUDED_TABLES.include?(tag)
end

.mark_lossless_modifying!(table_data) ⇒ Object

Set head.flags bit 11 to indicate the font was losslessly modified.

Per spec section 5: "The WOFF 2.0 encoders MUST also set bit 11 of the 'flags' field of the head table ... to indicate that a recreated font file was subjected to lossless modifying transform."

Uses the model-driven Head BinData record so the bits are set via a named attribute on a typed object, not via raw byte slicing.



57
58
59
60
61
62
63
# File 'lib/fontisan/woff2/encoder_rules.rb', line 57

def self.mark_lossless_modifying!(table_data)
  return unless table_data.key?("head")

  head = Tables::Head.read(table_data["head"])
  head.flags |= Tables::Head::FLAG_LOSSLESS_MODIFYING
  table_data["head"] = head.to_binary_s
end