1package drawing
2
3// Liner receive segment definition
4type Liner interface {
5	// LineTo Draw a line from the current position to the point (x, y)
6	LineTo(x, y float64)
7}
8
9// Flattener receive segment definition
10type Flattener interface {
11	// MoveTo Start a New line from the point (x, y)
12	MoveTo(x, y float64)
13	// LineTo Draw a line from the current position to the point (x, y)
14	LineTo(x, y float64)
15	// LineJoin add the most recent starting point to close the path to create a polygon
16	LineJoin()
17	// Close add the most recent starting point to close the path to create a polygon
18	Close()
19	// End mark the current line as finished so we can draw caps
20	End()
21}
22
23// Flatten convert curves into straight segments keeping join segments info
24func Flatten(path *Path, flattener Flattener, scale float64) {
25	// First Point
26	var startX, startY float64
27	// Current Point
28	var x, y float64
29	var i int
30	for _, cmp := range path.Components {
31		switch cmp {
32		case MoveToComponent:
33			x, y = path.Points[i], path.Points[i+1]
34			startX, startY = x, y
35			if i != 0 {
36				flattener.End()
37			}
38			flattener.MoveTo(x, y)
39			i += 2
40		case LineToComponent:
41			x, y = path.Points[i], path.Points[i+1]
42			flattener.LineTo(x, y)
43			flattener.LineJoin()
44			i += 2
45		case QuadCurveToComponent:
46			// we include the previous point for the start of the curve
47			TraceQuad(flattener, path.Points[i-2:], 0.5)
48			x, y = path.Points[i+2], path.Points[i+3]
49			flattener.LineTo(x, y)
50			i += 4
51		case CubicCurveToComponent:
52			TraceCubic(flattener, path.Points[i-2:], 0.5)
53			x, y = path.Points[i+4], path.Points[i+5]
54			flattener.LineTo(x, y)
55			i += 6
56		case ArcToComponent:
57			x, y = TraceArc(flattener, path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3], path.Points[i+4], path.Points[i+5], scale)
58			flattener.LineTo(x, y)
59			i += 6
60		case CloseComponent:
61			flattener.LineTo(startX, startY)
62			flattener.Close()
63		}
64	}
65	flattener.End()
66}
67
68// SegmentedPath is a path of disparate point sectinos.
69type SegmentedPath struct {
70	Points []float64
71}
72
73// MoveTo implements the path interface.
74func (p *SegmentedPath) MoveTo(x, y float64) {
75	p.Points = append(p.Points, x, y)
76	// TODO need to mark this point as moveto
77}
78
79// LineTo implements the path interface.
80func (p *SegmentedPath) LineTo(x, y float64) {
81	p.Points = append(p.Points, x, y)
82}
83
84// LineJoin implements the path interface.
85func (p *SegmentedPath) LineJoin() {
86	// TODO need to mark the current point as linejoin
87}
88
89// Close implements the path interface.
90func (p *SegmentedPath) Close() {
91	// TODO Close
92}
93
94// End implements the path interface.
95func (p *SegmentedPath) End() {
96	// Nothing to do
97}
98