Class: Skrift::Renderer

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

Overview

The scaling/rendering façade: set a scale, look up glyphs, measure and render them. (Formerly named SFT, after libschrift’s handle struct.)

Constant Summary collapse

DOWNWARD_Y =
0x01

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font) ⇒ Renderer

Returns a new instance of Renderer.



9
10
11
12
13
14
15
16
# File 'lib/skrift/sft.rb', line 9

def initialize(font)
  @font = font
  @x_scale  = 32
  @y_scale  = 32
  @x_offset = 0
  @y_offset = 0
  @flags = DOWNWARD_Y
end

Instance Attribute Details

#flagsObject

Returns the value of attribute flags.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def flags
  @flags
end

#fontObject

Returns the value of attribute font.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def font
  @font
end

#x_offsetObject

Returns the value of attribute x_offset.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def x_offset
  @x_offset
end

#x_scaleObject

Returns the value of attribute x_scale.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def x_scale
  @x_scale
end

#y_offsetObject

Returns the value of attribute y_offset.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def y_offset
  @y_offset
end

#y_scaleObject

Returns the value of attribute y_scale.



7
8
9
# File 'lib/skrift/sft.rb', line 7

def y_scale
  @y_scale
end

Instance Method Details

#glyph_bbox(outline) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/skrift/sft.rb', line 28

def glyph_bbox(outline)
  box = @font.glyph_bbox(outline)
  raise if !box
  # Transform the bounding box into Renderer coordinate space
  xs = @x_scale.to_f / @font.units_per_em
  ys = @y_scale.to_f / @font.units_per_em
  box[0] = (box[0] * xs + @x_offset).floor
  box[1] = (box[1] * ys + @y_offset).floor
  box[2] = (box[2] * xs + @x_offset).ceil
  box[3] = (box[3] * ys + @y_offset).ceil
  return box
end

#gmetrics(glyph) ⇒ Object

149



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/skrift/sft.rb', line 41

def gmetrics(glyph) # 149
  return nil if glyph.nil?
  raise "out of bounds" if glyph < 0
  xs = @x_scale.to_f / @font.units_per_em
  adv, lsb = @font.hor_metrics(glyph)

  return nil if adv.nil?
  metrics = GMetrics.new(adv * xs, lsb * xs + @x_offset)

  outline = @font.outline_offset(glyph)
  return metrics if outline.nil?
  bbox = glyph_bbox(outline)
  return nil if !bbox
  metrics.min_width = bbox[2] - bbox[0] + 1
  metrics.min_height = bbox[3] - bbox[1] + 1
  metrics.y_offset = @flags & DOWNWARD_Y != 0 ? bbox[3] : bbox[1]
  return metrics
end

#kerning(left_glyph, right_glyph) ⇒ Object

176



93
94
95
# File 'lib/skrift/sft.rb', line 93

def kerning(left_glyph, right_glyph) # 176
  @font.kerning[[left_glyph,right_glyph].pack("n*")]
end

#lmetricsObject



60
61
62
63
64
65
66
67
68
# File 'lib/skrift/sft.rb', line 60

def lmetrics
  hhea = font.reqtable("hhea")
  factor = @y_scale.to_f / @font.units_per_em
  LMetrics.new(
    font.geti16(hhea + 4) * factor, # ascender
    font.geti16(hhea + 6) * factor, # descender
    font.geti16(hhea + 8) * factor  # line_gap
  )
end

#lookup(codepoint, variation: nil) ⇒ Object

Glyph id for codepoint. With variation (a variation selector such as Font::VS_EMOJI), resolve the <codepoint, selector> sequence via cmap-14 first, falling back to the plain glyph when the font omits the sequence.



21
22
23
24
25
26
# File 'lib/skrift/sft.rb', line 21

def lookup(codepoint, variation: nil)
  if variation && (g = font.variation_glyph_id(codepoint, variation))
    return g
  end
  font.glyph_id(codepoint)
end

#render(glyph, image) ⇒ Object

Rasterise glyph into image (mutated in place). Returns true if the glyph had a renderable outline, false otherwise (e.g. a space).



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/skrift/sft.rb', line 72

def render(glyph, image) # 239
  outline = @font.outline_offset(glyph)
  return false if outline.nil?
  bbox = glyph_bbox(outline)
  return false if !bbox
  # Set up the transformation matrix such that
  # the transformed bounding boxes min corner lines
  # up with the (0, 0) point.
  xr = [@x_scale.to_f / @font.units_per_em, 0.0, @x_offset - bbox[0]]
  ys = @y_scale.to_f / @font.units_per_em
  if @flags.allbits?(DOWNWARD_Y)
    transform = [xr, [0.0, -ys, bbox[3] - @y_offset]]
  else
    transform = [xr, [0.0, +ys, @y_offset - bbox[1] ]]
  end
  outl = @font.decode_outline(outline)
  return false unless outl
  outl.render(transform, image)
  true
end