Class: Skrift::GlyphCache

Inherits:
Object
  • Object
show all
Defined in:
lib/skrift/glyph_cache.rb

Overview

The platform-independent glyph pipeline shared by every backend: resolve a codepoint through a FontSet, rasterise it (with optional fit-to-cell scaling), and cache the result. Backends (XRender glyphsets, software RGB blending, …) consume the RenderedGlyph and place it however they like.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fontset, x_scale:, y_scale:, fixed: nil, maxheight: nil, fit: false, special: nil, color: nil) ⇒ GlyphCache

special is an optional callable codepoint -> Skrift::Image (alpha) used to override font rasterisation (e.g. a box-drawing plugin); return nil to fall through to the font.

color is an optional colour delegate: any object responding to #render(codepoint) and returning an RGBA colour image (with #width, #height and #pixels of packed 0xRRGGBBAA), or nil to fall through to monochrome. skrift core knows nothing about colour formats — all of that lives in the delegate (e.g. the skrift-color gem).



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/skrift/glyph_cache.rb', line 27

def initialize(fontset, x_scale:, y_scale:, fixed: nil, maxheight: nil, fit: false, special: nil, color: nil)
  @fontset   = fontset.is_a?(FontSet) ? fontset : FontSet.new(fontset)
  @x_scale   = x_scale
  @y_scale   = y_scale
  @fixed     = fixed
  @maxheight = maxheight
  @fit       = fit
  @special   = special
  @color     = color
  @cache     = {}

  @sft = Renderer.new(@fontset[0])
  @sft.x_scale = x_scale
  @sft.y_scale = y_scale
  lm = @sft.lmetrics
  @ascent, @descent, @line_gap = lm.ascender, lm.descender, lm.line_gap

  # +fixed+ enables monospace cells: pass a Numeric cell width, or true to
  # derive it from the 'M' advance. Either way @fixed stays truthy so glyphs
  # render at the cell width.
  g = @sft.gmetrics(@sft.lookup("M".ord)) || @sft.gmetrics(0)
  @cell_width = (fixed if fixed.is_a?(Numeric)) || (g ? g.advance_width.ceil : x_scale)
end

Instance Attribute Details

#ascentObject (readonly)

Returns the value of attribute ascent.



16
17
18
# File 'lib/skrift/glyph_cache.rb', line 16

def ascent
  @ascent
end

#cell_widthObject (readonly)

Returns the value of attribute cell_width.



16
17
18
# File 'lib/skrift/glyph_cache.rb', line 16

def cell_width
  @cell_width
end

#descentObject (readonly)

Returns the value of attribute descent.



16
17
18
# File 'lib/skrift/glyph_cache.rb', line 16

def descent
  @descent
end

#fontsetObject (readonly)

Returns the value of attribute fontset.



16
17
18
# File 'lib/skrift/glyph_cache.rb', line 16

def fontset
  @fontset
end

#line_gapObject (readonly)

Returns the value of attribute line_gap.



16
17
18
# File 'lib/skrift/glyph_cache.rb', line 16

def line_gap
  @line_gap
end

Instance Method Details

#baselineObject



51
# File 'lib/skrift/glyph_cache.rb', line 51

def baseline = @ascent.round

#cell_heightObject

Cell height unified on ascent - descent (line gap excluded), clamped to maxheight when given.



55
56
57
# File 'lib/skrift/glyph_cache.rb', line 55

def cell_height
  @cell_height ||= [@maxheight, @ascent.ceil - @descent.ceil].compact.min
end

#glyph(codepoint) ⇒ Object

RenderedGlyph for codepoint, or nil if no font in the set maps it.



60
61
62
63
# File 'lib/skrift/glyph_cache.rb', line 60

def glyph(codepoint)
  return @cache[codepoint] if @cache.key?(codepoint)
  @cache[codepoint] = build(codepoint)
end

#text_width(str) ⇒ Object

Total advance for str: the fixed cell width per character in fixed mode, otherwise the sum of per-glyph advances.



67
68
69
70
71
72
# File 'lib/skrift/glyph_cache.rb', line 67

def text_width(str)
  str.to_s.each_char.sum do |ch|
    next @cell_width if @fixed
    (g = glyph(ch.ord)) ? g.advance_width : 0
  end
end