Class: Fontisan::Stitcher::Source
- Inherits:
-
Object
- Object
- Fontisan::Stitcher::Source
- Defined in:
- lib/fontisan/stitcher/source.rb
Overview
Wraps a source font (UFO or loaded TTF/OTF) behind a single extraction API used by the selectors.
For UFO sources, glyphs are accessed by name directly. For TTF or OTF sources, individual glyphs are extracted on demand from the BinData tables (glyf/loca/head for TTF, CFF for OTF). This is O(1) per glyph rather than the previous O(n) full-donor conversion.
CBDT/CBLC sources (e.g. NotoColorEmoji) are detected via #bitmap_mode. When a source is :cbdt, the Stitcher propagates the raw CBDT/CBLC tables into the output instead of extracting outlines. The glyph data lives in the bitmap tables, not in glyf.
Codepoint remap
Some donor fonts ship glyphs at non-canonical codepoints — a
keyboard-mapped font whose "A" is at U+0041, or a PUA-allocated
pre-Unicode font. Pass a remap: hash at construction to expose
those glyphs at their canonical codepoints without mutating the
donor font's cmap:
Source.new(font, remap: { 0x41 => 0x11DB0 })
With a remap set, the source answers gid_for_codepoint for the
target codepoints (0x11DB0 in the example) by translating them
to the donor's source codepoints (0x41). Source codepoints not
listed in the remap are hidden — only the remapped coverage is
exposed. This matches the typical "use this donor for exactly
these output characters" intent, and avoids leaking the donor's
ASCII/PUA noise into the output.
Constant Summary collapse
- MAX_COMPOUND_DEPTH =
32
Instance Attribute Summary collapse
-
#font ⇒ Object
readonly
Returns the value of attribute font.
-
#remap ⇒ Object
readonly
Returns the value of attribute remap.
Instance Method Summary collapse
-
#bitmap_mode ⇒ Symbol
Detect how this source stores glyph data.
-
#format ⇒ Symbol
:ufo, :ttf, :otf.
-
#gid_for_codepoint(codepoint) ⇒ Integer?
Find the gid for a Unicode codepoint in this source.
-
#glyph_for_gid(gid) ⇒ Fontisan::Ufo::Glyph?
Extract a glyph by gid.
-
#glyph_width(gid) ⇒ Integer
Width of a specific glyph (extracted from hmtx).
-
#initialize(font, remap: nil) ⇒ Source
constructor
A new instance of Source.
-
#raw_table_bytes(tag) ⇒ String?
Raw table bytes from the loaded font (for passthrough).
Constructor Details
#initialize(font, remap: nil) ⇒ Source
Returns a new instance of Source.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/fontisan/stitcher/source.rb', line 47 def initialize(font, remap: nil) @font = font @bin_data_cache = nil # Distinguish "no remap kwarg" (nil → passthrough) from # "explicit empty remap" ({} → drop everything). The latter # still flips the source into remapped mode, just with no # entries — every donor codepoint gets filtered out. return unless remap @remap = remap.to_h.transform_keys(&:to_i).transform_values(&:to_i) @inverse_remap = @remap.each_with_object({}) do |(src, target), h| h[target] = src end end |
Instance Attribute Details
#font ⇒ Object (readonly)
Returns the value of attribute font.
39 40 41 |
# File 'lib/fontisan/stitcher/source.rb', line 39 def font @font end |
#remap ⇒ Object (readonly)
Returns the value of attribute remap.
39 40 41 |
# File 'lib/fontisan/stitcher/source.rb', line 39 def remap @remap end |
Instance Method Details
#bitmap_mode ⇒ Symbol
Detect how this source stores glyph data.
- :glyf — TrueType outlines (glyf table present)
- :cbdt — Color bitmaps (CBDT + CBLC tables, no glyf)
- :mixed — Both glyf and CBDT
- :none — UFO source or neither table present
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/fontisan/stitcher/source.rb', line 81 def bitmap_mode return :none if @font.is_a?(Fontisan::Ufo::Font) return :none unless @font.respond_to?(:has_table?) has_cbdt = @font.has_table?("CBDT") && @font.has_table?("CBLC") has_glyf = @font.has_table?("glyf") || @font.has_table?("CFF ") return :mixed if has_cbdt && has_glyf return :cbdt if has_cbdt return :glyf if has_glyf :none end |
#format ⇒ Symbol
Returns :ufo, :ttf, :otf.
64 65 66 67 68 69 70 71 |
# File 'lib/fontisan/stitcher/source.rb', line 64 def format case @font when Fontisan::Ufo::Font then :ufo when Fontisan::TrueTypeFont then :ttf when Fontisan::OpenTypeFont then :otf else :unknown end end |
#gid_for_codepoint(codepoint) ⇒ Integer?
Find the gid for a Unicode codepoint in this source.
When remap was set at construction, codepoint is treated as
a target codepoint — the source codepoint that maps to it via
remap is what actually gets looked up. Returns nil for
codepoints the remap does not cover.
103 104 105 106 107 108 109 110 111 |
# File 'lib/fontisan/stitcher/source.rb', line 103 def gid_for_codepoint(codepoint) src_cp = source_codepoint_for(codepoint) return nil unless src_cp case @font when Fontisan::Ufo::Font then ufo_gid_for(src_cp) else bin_data_gid_for(src_cp) end end |
#glyph_for_gid(gid) ⇒ Fontisan::Ufo::Glyph?
Extract a glyph by gid.
For TTF/OTF sources, this is O(1) per glyph: it parses just the requested glyph from glyf/CFF on demand, not the entire donor. The full-donor conversion is avoided entirely.
For CBDT sources, returns a placeholder glyph (no contours) since the glyph data is in the bitmap tables, not outlines.
124 125 126 127 128 129 |
# File 'lib/fontisan/stitcher/source.rb', line 124 def glyph_for_gid(gid) case @font when Fontisan::Ufo::Font then ufo_glyph_at(gid) else extract_single_glyph_from_bindata(gid) end end |
#glyph_width(gid) ⇒ Integer
Width of a specific glyph (extracted from hmtx). Falls back to 0 if hmtx is missing.
147 148 149 150 |
# File 'lib/fontisan/stitcher/source.rb', line 147 def glyph_width(gid) widths = bin_data_widths widths[gid] || 0 end |
#raw_table_bytes(tag) ⇒ String?
Raw table bytes from the loaded font (for passthrough).
134 135 136 137 138 139 140 141 |
# File 'lib/fontisan/stitcher/source.rb', line 134 def raw_table_bytes(tag) sfnt_table = @font.table(tag) return nil unless sfnt_table sfnt_table.raw_data rescue StandardError nil end |