Class: Fontisan::Ufo::Info

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/ufo/info.rb

Overview

Typed wrapper around a UFO's fontinfo.plist. Provides accessor methods for every standard UFO 3 field, with sensible defaults when reading a UFO that omits some fields.

Field naming follows UFO 3 (camelCase in the plist, snake_case in Ruby). Fields are looked up case-insensitively on read.

Constant Summary collapse

STANDARD_FIELDS =

Convenience: standard fields. Add to this list as new compiler needs arise; serialization walks all known fields.

%i[
  family_name style_name version_major version_minor units_per_em
  ascender descender cap_height x_height italic_angle
  postscript_font_name postscript_full_name postscript_weight_name
  copyright created modified note
  open_type_head_created open_type_head_flags
  open_type_hhea_ascender open_type_hhea_descender
  open_type_hhea_line_gap open_type_name_records
  open_type_os2_weight_class open_type_os2_width_class
  open_type_vhea_ascender open_type_vhea_descender open_type_vhea_line_gap
  year_month_day_time_seconds_since_epoch
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(values = {}) ⇒ Info

Returns a new instance of Info.



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fontisan/ufo/info.rb', line 32

def initialize(values = {})
  @extras = {}
  values.each do |key, value|
    attr = camel_to_snake(key.to_s).to_sym
    if STANDARD_FIELDS.include?(attr)
      public_send("#{attr}=", value)
    else
      @extras[key.to_s] = value
    end
  end
end

Instance Attribute Details

#extrasObject

Catch-all for non-standard (vendor-specific) fields.



30
31
32
# File 'lib/fontisan/ufo/info.rb', line 30

def extras
  @extras
end

Class Method Details

.for_subfont(family:, subfont:, version:, subfamily: "Regular", copyright: nil, trademark: nil) ⇒ Info

Build a Ufo::Info for one subfont of a collection. The family name embeds the subfont name (e.g. "MyFont CJK"), and the PostScript name uses the hyphenated form (e.g. "MyFont-CJK").

version is parsed into version_major / version_minor per the UFO major.minor shape (patch is dropped).

trademark is stored under extras["openTypeNameTrademark"] because it is not in STANDARD_FIELDS yet — see TODO 71 out-of-scope follow-up.

Parameters:

  • family (String)

    collection-wide family name

  • subfont (String, Symbol)

    subfont identifier (appended to family)

  • version (String, Integer)

    e.g. "0.1", "1", "1.2.3"

  • subfamily (String) (defaults to: "Regular")

    OpenType subfamily (default "Regular")

  • copyright (String, nil) (defaults to: nil)
  • trademark (String, nil) (defaults to: nil)

Returns:



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/fontisan/ufo/info.rb', line 62

def self.for_subfont(family:, subfont:, version:,
                     subfamily: "Regular",
                     copyright: nil, trademark: nil)
  major, minor = parse_version(version)
  subfont_str = subfont.to_s
  values = {
    family_name: "#{family} #{subfont_str}",
    style_name: subfamily,
    version_major: major,
    version_minor: minor,
    postscript_font_name: "#{family}-#{subfont_str}",
    postscript_full_name: "#{family} #{subfont_str}",
  }
  values[:copyright] = copyright if copyright
  values["openTypeNameTrademark"] = trademark if trademark
  new(values)
end

Instance Method Details

#to_plistHash

Returns a Hash<String, Object> suitable for emit() to serialize back to plist. Keys are in camelCase per UFO 3.

Returns:

  • (Hash)

    a Hash<String, Object> suitable for emit() to serialize back to plist. Keys are in camelCase per UFO 3.



94
95
96
97
98
99
100
101
102
# File 'lib/fontisan/ufo/info.rb', line 94

def to_plist
  h = {}
  STANDARD_FIELDS.each do |attr|
    value = public_send(attr)
    h[snake_to_camel(attr.to_s)] = value unless value.nil?
  end
  @extras.each { |k, v| h[k] = v }
  h
end