Class: Fontisan::Stitcher::Source

Inherits:
Object
  • Object
show all
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.

Constant Summary collapse

MAX_COMPOUND_DEPTH =
32

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font) ⇒ Source

Returns a new instance of Source.



23
24
25
26
# File 'lib/fontisan/stitcher/source.rb', line 23

def initialize(font)
  @font = font
  @bin_data_cache = nil
end

Instance Attribute Details

#fontObject (readonly)

Returns the value of attribute font.



21
22
23
# File 'lib/fontisan/stitcher/source.rb', line 21

def font
  @font
end

Instance Method Details

#bitmap_modeSymbol

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

Returns:

  • (Symbol)


46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fontisan/stitcher/source.rb', line 46

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

#formatSymbol

Returns :ufo, :ttf, :otf.

Returns:

  • (Symbol)

    :ufo, :ttf, :otf



29
30
31
32
33
34
35
36
# File 'lib/fontisan/stitcher/source.rb', line 29

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.

Parameters:

  • codepoint (Integer)

Returns:

  • (Integer, nil)


62
63
64
65
66
67
# File 'lib/fontisan/stitcher/source.rb', line 62

def gid_for_codepoint(codepoint)
  case @font
  when Fontisan::Ufo::Font then ufo_gid_for(codepoint)
  else bin_data_gid_for(codepoint)
  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.

Parameters:

  • gid (Integer)

Returns:



80
81
82
83
84
85
# File 'lib/fontisan/stitcher/source.rb', line 80

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.

Parameters:

  • gid (Integer)

Returns:

  • (Integer)


103
104
105
106
# File 'lib/fontisan/stitcher/source.rb', line 103

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).

Parameters:

  • tag (String)

    4-byte table tag (e.g. "CBDT", "CBLC")

Returns:

  • (String, nil)

    raw bytes or nil if table not present



90
91
92
93
94
95
96
97
# File 'lib/fontisan/stitcher/source.rb', line 90

def raw_table_bytes(tag)
  sfnt_table = @font.table(tag)
  return nil unless sfnt_table

  sfnt_table.raw_data
rescue StandardError
  nil
end