Class: Outline

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

Defined Under Namespace

Classes: Segment

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeOutline

Returns a new instance of Outline.



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

def initialize
  @points, @segments = [], []
end

Instance Attribute Details

#pointsObject (readonly)

Returns the value of attribute points.



14
15
16
# File 'lib/skrift/outline.rb', line 14

def points
  @points
end

#segmentsObject (readonly)

Returns the value of attribute segments.



14
15
16
# File 'lib/skrift/outline.rb', line 14

def segments
  @segments
end

Instance Method Details

#clip_points(width, height) ⇒ Object



20
21
22
23
24
25
# File 'lib/skrift/outline.rb', line 20

def clip_points(width, height)
  @points.each do |pt|
    pt[0] = pt[0].clamp(0, width.pred)
    pt[1] = pt[1].clamp(0, height.pred)
  end
end

#is_flat(curve) ⇒ Object

A heuristic to tell whether a given curve can be approximated closely enough by a line. */



54
55
56
57
58
# File 'lib/skrift/outline.rb', line 54

def is_flat(curve)
  g = @points[curve.ctrl] - @points[curve.beg]
  h = @points[curve.end]  - @points[curve.beg]
  (g[0]*h[1]-g[1]*h[0]).abs <= 2.0
end

#render(transform, image) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/skrift/outline.rb', line 27

def render(transform, image)
  transform_points(transform, @points)
  clip_points(image.width, image.height)
  buf = Raster.new(image.width, image.height)
  @segments.each do |seg|
    seg.ctrl ? tesselate_curve(seg) : buf.draw_line(@points[seg.beg], @points[seg.end])
  end
  image.pixels = buf.post_process
  return image
end

#tesselate_curve(curve) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/skrift/outline.rb', line 38

def tesselate_curve(curve)
  if is_flat(curve)
    @segments << Segment[curve.beg, curve.end]
    return
  end
  ctrl0 = @points.length
  @points << midpoint(@points[curve.beg], @points[curve.ctrl])
  ctrl1 = @points.length
  @points << midpoint(@points[curve.ctrl], @points[curve.end])
  pivot = @points.length
  @points << midpoint(@points[ctrl0], @points[ctrl1])
  tesselate_curve(Segment[curve.beg, pivot, ctrl0])
  tesselate_curve(Segment[pivot, curve.end, ctrl1])
end