Module: Fontisan::Converters::ConversionStrategy

Included in:
OutlineConverter, SvgGenerator, TableCopier, Type1Converter, Woff2Encoder, WoffWriter
Defined in:
lib/fontisan/converters/conversion_strategy.rb

Overview

Interface module and declarative options DSL for conversion strategies

ConversionStrategy defines the contract that all conversion strategy classes must implement, plus a declarative DSL for declaring the options each strategy accepts.

Why a declarative options DSL

Each format has its own spec-mandated knobs (WOFF: zlib level, WOFF2: Brotli quality, etc.). Letting each strategy declare its own options keeps the schema with the code that consumes it (encapsulation), and makes adding a new format a pure additive change (OCP): write a new strategy class, declare its options, done — no edits to central option lists, the CLI option parser, or ConversionOptions.

The strategy is also the sole validator of its own options. The runtime check at FormatConverter#convert calls strategy.class.validate_options! to enforce the format ↔ option mapping (e.g., rejecting --zlib-level on a WOFF2 conversion). This is the MECE guarantee: every option belongs to exactly one strategy, and a strategy rejects anything it did not declare.

Examples:

Declaring options

class WoffWriter
  include ConversionStrategy

  option :zlib_level, type: :integer, range: 0..9, default: 6,
         cli: "--zlib-level", desc: "zlib compression level"
  option :uncompressed, type: :boolean, default: false,
         cli: "--uncompressed", desc: "store tables uncompressed"

  def convert(font, options = {})
    self.class.validate_options!(options)
    # ...
  end
end

Defined Under Namespace

Modules: ClassMethods Classes: Option

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Mix ClassMethods into any class that includes this module.



162
163
164
# File 'lib/fontisan/converters/conversion_strategy.rb', line 162

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

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

Convert font to target format.

Strategies must implement this. Subclasses should call self.class.validate_options!(options) first to enforce their schema.

Parameters:

Returns:

  • (Hash<String, String>)

    Map of table tags to binary data

Raises:

  • (NotImplementedError)

    If not implemented by strategy



175
176
177
178
# File 'lib/fontisan/converters/conversion_strategy.rb', line 175

def convert(font, options = {})
  raise NotImplementedError,
        "#{self.class.name} must implement convert(font, options)"
end

#supported_conversionsArray<Array<Symbol>>

Get list of supported conversions.

Returns:

  • (Array<Array<Symbol>>)

    Supported [source, target] pairs

Raises:

  • (NotImplementedError)

    If not implemented by strategy



184
185
186
187
# File 'lib/fontisan/converters/conversion_strategy.rb', line 184

def supported_conversions
  raise NotImplementedError,
        "#{self.class.name} must implement supported_conversions"
end

#supports?(source_format, target_format) ⇒ Boolean

Check if strategy supports a given conversion.

Parameters:

  • source_format (Symbol)
  • target_format (Symbol)

Returns:

  • (Boolean)


206
207
208
# File 'lib/fontisan/converters/conversion_strategy.rb', line 206

def supports?(source_format, target_format)
  supported_conversions.include?([source_format, target_format])
end

#validate(font, target_format) ⇒ Boolean

Validate that conversion is possible.

Parameters:

Returns:

  • (Boolean)

    True if valid

Raises:

  • (Error)

    If conversion is not possible

  • (NotImplementedError)

    If not implemented by strategy



196
197
198
199
# File 'lib/fontisan/converters/conversion_strategy.rb', line 196

def validate(font, target_format)
  raise NotImplementedError,
        "#{self.class.name} must implement validate(font, target_format)"
end