Class: Fontisan::Stitcher::GlyphCopier
- Inherits:
-
Object
- Object
- Fontisan::Stitcher::GlyphCopier
- Defined in:
- lib/fontisan/stitcher/glyph_copier.rb
Overview
Owns the mechanical concerns of copying glyphs from donor sources into a target UFO font.
The Stitcher's per-subfont build needs to:
- inject a `.notdef` glyph at GID 0
- copy outline glyphs from donor sources, optionally skipping
donors the caller names (e.g. the CBDT source, whose glyphs
take a different code path)
- register each copied glyph with the deduplicator so visually
identical glyphs from different donors share a gid
GlyphCopier centralizes that logic in one stateless-per-call collaborator. The Stitcher constructs one with a deduplicator and calls its methods in the order the cmap contract requires (see Fontisan::Ufo::Compile::Cmap for first-wins semantics).
Instance Method Summary collapse
-
#copy_outlines(bindings, target, skip_sources: []) ⇒ Object
Copy outline glyphs from
bindingsintotarget, skipping any sources the caller names (e.g. the CBDT source). -
#initialize(deduplicator) ⇒ GlyphCopier
constructor
A new instance of GlyphCopier.
-
#inject_notdef(bindings, target) ⇒ Object
Inject a
.notdefglyph at GID 0 oftarget.
Constructor Details
#initialize(deduplicator) ⇒ GlyphCopier
Returns a new instance of GlyphCopier.
24 25 26 |
# File 'lib/fontisan/stitcher/glyph_copier.rb', line 24 def initialize(deduplicator) @deduplicator = deduplicator end |
Instance Method Details
#copy_outlines(bindings, target, skip_sources: []) ⇒ Object
Copy outline glyphs from bindings into target, skipping any
sources the caller names (e.g. the CBDT source).
Bindings are sorted by [codepoint, donor_gid] for deterministic
output. For each binding:
- if deduplicator has seen a visually identical glyph that's
already in the target, attach the codepoint to that glyph
(extra unicode mapping);
- otherwise copy the glyph under a unique name and register
with the deduplicator.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/fontisan/stitcher/glyph_copier.rb', line 65 def copy_outlines(bindings, target, skip_sources: []) sorted_bindings(bindings).each do |binding| next if binding[:donor_gid].zero? next if skip_sources.any? { |s| s.equal?(binding[:source]) } glyph = binding[:source].glyph_for_gid(binding[:donor_gid]) next unless glyph canonical = @deduplicator&.find(glyph) if canonical && target.glyphs.key?(canonical) add_extra_unicode(target, canonical, binding[:codepoint]) else name = UniqueGlyphName.in(target, glyph.name) copy_glyph_into(target, name: name, source: binding[:source], donor_gid: binding[:donor_gid], codepoint: binding[:codepoint]) @deduplicator&.register(glyph, name) end end end |
#inject_notdef(bindings, target) ⇒ Object
Inject a .notdef glyph at GID 0 of target.
If a binding exists with donor_gid == 0, copy the donor's
.notdef; otherwise synthesize an empty one. The injected glyph
is registered with the deduplicator so subsequent .notdef
references deduplicate against it.
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/fontisan/stitcher/glyph_copier.rb', line 37 def inject_notdef(bindings, target) notdef_binding = bindings.find { |b| b[:donor_gid].zero? } if notdef_binding copy_glyph_into(target, name: ".notdef", source: notdef_binding[:source], donor_gid: 0) else target.layers.default_layer.add(Ufo::Glyph.new(name: ".notdef")) end dedup_target = target.glyphs[".notdef"] @deduplicator&.register(dedup_target, ".notdef") if dedup_target end |