Class: Fontisan::Converters::CollectionConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/converters/collection_converter.rb

Overview

CollectionConverter handles conversion between collection formats

Main responsibility: Convert between TTC, OTC, and dfont collection formats using a three-step strategy:

  1. Unpack: Extract individual fonts from source collection
  2. Convert: Transform each font's outline format if requested
  3. Repack: Rebuild collection in target format

Supported conversions:

  • TTC ↔ OTC (preserves mixed TTF+OTF by default)
  • TTC → dfont (repackage)
  • OTC → dfont (repackage)
  • dfont → TTC (preserves mixed formats)
  • dfont → OTC (preserves mixed formats)

Examples:

Convert TTC to OTC (preserve formats)

converter = CollectionConverter.new
result = converter.convert(ttc_path, target_type: :otc, output: 'family.otc')

Convert with ConversionOptions

options = ConversionOptions.recommended(from: :ttc, to: :otc)
converter = CollectionConverter.new
result = converter.convert(ttc_path, target_type: :otc, options: { output: 'family.otc', options: options })

Convert TTC to OTC with outline conversion

converter = CollectionConverter.new
result = converter.convert(ttc_path, target_type: :otc,
                           options: { output: 'family.otc', target_format: 'otf' })

Instance Method Summary collapse

Instance Method Details

#convert(collection_path, target_type:, options: {}) ⇒ Hash

Convert collection to target format

Parameters:

  • collection_path (String)

    Path to source collection

  • target_type (Symbol)

    Target collection type (:ttc, :otc, :dfont)

  • options (Hash) (defaults to: {})

    Conversion options

Options Hash (options:):

  • :output (String)

    Output file path (required)

  • :target_format (String)

    Target outline format: 'preserve' (default), 'ttf', or 'otf'

  • :optimize (Boolean)

    Enable table sharing (default: true, TTC/OTC only)

  • :verbose (Boolean)

    Enable verbose output (default: false)

  • :options (ConversionOptions)

    ConversionOptions object

Returns:

  • (Hash)

    Conversion result with:

    • :input [String] - Input collection path
    • :output [String] - Output collection path
    • :source_type [Symbol] - Source collection type
    • :target_type [Symbol] - Target collection type
    • :num_fonts [Integer] - Number of fonts converted
    • :conversions [Array] - Per-font conversion details

Raises:

  • (ArgumentError)

    if parameters invalid

  • (Error)

    if conversion fails



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
# File 'lib/fontisan/converters/collection_converter.rb', line 53

def convert(collection_path, target_type:, options: {})
  validate_parameters!(collection_path, target_type, options)

  # Extract ConversionOptions if provided
  conv_options = extract_conversion_options(options)

  verbose = options.fetch(:verbose, false)
  output_path = options[:output]

  # Determine target format from ConversionOptions or options hash
  target_format = if conv_options&.generating_option?(:target_format,
                                                      "otf")
                    conv_options.generating[:target_format]
                  else
                    options.fetch(:target_format, "preserve").to_s
                  end

  # Validate target_format
  unless %w[preserve ttf otf].include?(target_format)
    raise ArgumentError,
          "Invalid target_format: #{target_format}. Must be 'preserve', 'ttf', or 'otf'"
  end

  puts "Converting collection to #{target_type.to_s.upcase}..." if verbose

  # Step 1: Unpack - extract fonts from source collection
  puts "  Unpacking fonts from source collection..." if verbose
  fonts, source_type = unpack_fonts(collection_path)

  # Check if conversion is needed
  if source_type == target_type
    puts "  Source and target formats are the same, copying collection..." if verbose
    FileUtils.cp(collection_path, output_path)
    return build_result(collection_path, output_path, source_type,
                        target_type, fonts.size, [])
  end

  # Step 2: Convert - transform fonts if requested
  puts "  Converting #{fonts.size} font(s)..." if verbose
  converted_fonts, conversions = convert_fonts(fonts, source_type,
                                               target_type, options.merge(target_format: target_format),
                                               conv_options)

  # Step 3: Repack - build target collection
  puts "  Repacking into #{target_type.to_s.upcase} format..." if verbose
  repack_fonts(converted_fonts, target_type, output_path, options)

  # Build result
  result = build_result(collection_path, output_path, source_type,
                        target_type, fonts.size, conversions)

  if verbose
    display_result(result)
  end

  result
end