Class: Skrift::Outline

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

Defined Under Namespace

Classes: Segment

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Geometry

midpoint, transform_points

Constructor Details

#initializeOutline

Returns a new instance of Outline.



9
10
11
# File 'lib/skrift/outline.rb', line 9

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

Instance Attribute Details

#pointsObject (readonly)

Returns the value of attribute points.



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

def points
  @points
end

#segmentsObject (readonly)

Returns the value of attribute segments.



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

def segments
  @segments
end

Instance Method Details

#clip_points(width, height) ⇒ Object



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

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.



47
48
49
50
51
# File 'lib/skrift/outline.rb', line 47

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



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

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



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/skrift/outline.rb', line 31

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