Module: Fontisan::Ufo::Compile::Cff2
- Defined in:
- lib/fontisan/ufo/compile/cff2.rb
Overview
Builds the OpenType CFF2 table from UFO glyphs.
CFF2 is simpler than CFF1: no Name INDEX, String INDEX, Encoding, or Charset. The Top DICT references CharStrings and a Font DICT INDEX (which wraps at least one Font DICT pointing to a Private DICT).
Layout (static font, single Font DICT, empty Private DICT):
Header (5 bytes)
Top DICT (variable — offsets to CharStrings + Font DICT INDEX)
Global Subr INDEX (4 bytes — empty)
CharStrings INDEX (variable)
Font DICT INDEX (variable — wraps one Font DICT)
Font DICT: DICT with Private operator [0, 0] (empty Private)
The Top DICT offsets depend on the Top DICT's own size — a circular dependency resolved with fixed-point iteration (the same pattern as the CFF1 builder).
Constant Summary collapse
- CHARSTRINGS_OPERATOR =
CFF2 Top DICT operator encodings.
17- VARIATION_STORE_OPERATOR =
0x11
24- FONT_DICT_INDEX_OPERATOR =
0x18
[12, 36].freeze
- PRIVATE_OPERATOR =
0x12
18
Class Method Summary collapse
-
.build(_font, glyphs:, variation_store: nil) ⇒ String
CFF2 table bytes.
Class Method Details
.build(_font, glyphs:, variation_store: nil) ⇒ String
Returns CFF2 table bytes.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/fontisan/ufo/compile/cff2.rb', line 41 def self.build(_font, glyphs:, variation_store: nil) charstrings = glyphs.map { |g| charstring_for(g) } global_subr_index = empty_global_subr_index font_dict = build_font_dict(private_size: 0, private_offset: 0) font_dict_index = Tables::Cff2::IndexBuilder.build([font_dict]) vs_bytes = variation_store&.b # Fixed-point iteration: encode Top DICT, compute offsets, repeat. top_dict = encode_top_dict( charstrings_offset: 0, font_dict_index_offset: 0, variation_store_offset: vs_bytes ? 0 : nil ) layout = compute_layout(top_dict:, charstrings:, global_subr_index:, font_dict_index:, variation_store: vs_bytes) 10.times do top_dict = encode_top_dict( charstrings_offset: layout[:charstrings_offset], font_dict_index_offset: layout[:font_dict_index_offset], variation_store_offset: layout[:variation_store_offset], ) next_layout = compute_layout(top_dict:, charstrings:, global_subr_index:, font_dict_index:, variation_store: vs_bytes) break if same_offsets?(layout, next_layout) layout = next_layout end assemble(layout:) end |