Class: Fontist::FormatMatcher

Inherits:
Object
  • Object
show all
Defined in:
lib/fontist/format_matcher.rb

Overview

Centralized format matching service

All format matching logic exists here. Other classes delegate to this. Supports matching across:

  • Resources (formula download sources)

  • Styles (font style entries)

  • Indexed fonts (system/user/fontist indexes)

  • Collections (TTC/OTC with multiple fonts)

For transcoding, delegates to Fontisan library.

Constant Summary collapse

DESKTOP_FORMATS =

All supported formats

%w[ttf otf ttc otc dfont].freeze
WEB_FORMATS =
%w[woff woff2].freeze
ALL_FORMATS =
(DESKTOP_FORMATS + WEB_FORMATS).freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format_spec) ⇒ FormatMatcher

Returns a new instance of FormatMatcher.



18
19
20
# File 'lib/fontist/format_matcher.rb', line 18

def initialize(format_spec)
  @spec = format_spec || FormatSpec.new
end

Class Method Details

.can_convert?(from_format, to_format) ⇒ Boolean

Class method for checking Fontisan conversion capability

Returns:

  • (Boolean)


141
142
143
144
145
146
147
# File 'lib/fontist/format_matcher.rb', line 141

def self.can_convert?(from_format, to_format)
  return false unless from_format && to_format

  # Fontisan supports conversion from desktop to web formats
  DESKTOP_FORMATS.include?(from_format.to_s) &&
    WEB_FORMATS.include?(to_format.to_s)
end

Instance Method Details

#can_convert?(from_format, to_format) ⇒ Boolean

Check if Fontisan can convert between formats (instance method for convenience)

Returns:

  • (Boolean)


136
137
138
# File 'lib/fontist/format_matcher.rb', line 136

def can_convert?(from_format, to_format)
  self.class.can_convert?(from_format, to_format)
end

#filter_indexed_fonts(fonts) ⇒ Object

Filter indexed fonts to only matching ones



84
85
86
# File 'lib/fontist/format_matcher.rb', line 84

def filter_indexed_fonts(fonts)
  fonts.select { |f| matches_indexed_font?(f) }
end

#filter_resources(resources) ⇒ Object

Filter resources to only matching ones



74
75
76
# File 'lib/fontist/format_matcher.rb', line 74

def filter_resources(resources)
  resources.select { |r| matches_resource?(r) }
end

#filter_styles(styles) ⇒ Object

Filter styles to only matching ones



79
80
81
# File 'lib/fontist/format_matcher.rb', line 79

def filter_styles(styles)
  styles.select { |s| matches_style?(s) }
end

#installation_strategy(available_formats) ⇒ Object

Check if requested format needs transcoding from available formats



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/fontist/format_matcher.rb', line 107

def installation_strategy(available_formats)
  requested = @spec.format

  if !requested
    return { strategy: :install, format: available_formats.first }
  end

  if available_formats.include?(requested)
    return { strategy: :install, format: requested }
  end

  # Check if Fontisan can convert from any available format
  convertible = available_formats.find { |f| self.class.can_convert?(f, requested) }
  if convertible
    return {
      strategy: :convert,
      from: convertible,
      to: requested,
    }
  end

  {
    strategy: :unavailable,
    requested: requested,
    available: available_formats,
  }
end

#matches_indexed_font?(indexed_font) ⇒ Boolean

Check if an indexed font matches the format spec

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fontist/format_matcher.rb', line 60

def matches_indexed_font?(indexed_font)
  return true unless @spec.has_constraints?
  return false if @spec.format && indexed_font.format != @spec.format

  if @spec.variable_requested?
    return false unless indexed_font.variable_font

    return axes_match?(indexed_font.variable_axes) if @spec.axes.any?
  end

  true
end

#matches_resource?(resource) ⇒ Boolean

Check if a resource matches the format spec

Returns:

  • (Boolean)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fontist/format_matcher.rb', line 23

def matches_resource?(resource)
  return true unless @spec.has_constraints?

  if @spec.format && resource.format && resource.format != @spec.format
    return false
  end

  if @spec.variable_requested?
    return false unless resource.variable_font?
    return axes_match?(resource.variable_axes) if @spec.axes.any?
  end

  true
end

#matches_style?(style) ⇒ Boolean

Check if a style matches the format spec

Parameters:

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fontist/format_matcher.rb', line 40

def matches_style?(style)
  return true unless @spec.has_constraints?

  # Check format constraint for FontStyle (v5 formulas have formats)
  if @spec.format && style.is_a?(FontStyle) && style.formats && !Array(style.formats).include?(@spec.format)
    return false
  end

  if @spec.variable_requested?
    # Check if style is variable
    is_variable = style.variable_font?
    return false unless is_variable

    return axes_match?(style.variable_axes) if @spec.axes.any?
  end

  true
end

#select_preferred_resource(resources) ⇒ Object

Select best resource based on preferences



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/fontist/format_matcher.rb', line 89

def select_preferred_resource(resources)
  return resources.first if resources.empty?
  return resources.first unless @spec.has_constraints?

  # Match exact format first (e.g. format: "ttf" selects the ttf resource)
  exact = find_exact_format(resources)
  return exact if exact

  preferred = find_preferred_format(resources)
  return preferred if preferred

  variable = find_variable_resource(resources)
  return variable if variable

  resources.first
end