forked from wcharczuk/go-chart
-
Notifications
You must be signed in to change notification settings - Fork 1
/
stack_graphic_context.go
211 lines (175 loc) · 5.38 KB
/
stack_graphic_context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package drawing
import (
"image"
"image/color"
"github.com/golang/freetype/truetype"
)
// StackGraphicContext is a context that does thngs.
type StackGraphicContext struct {
current *ContextStack
}
// ContextStack is a graphic context implementation.
type ContextStack struct {
Tr Matrix
Path *Path
LineWidth float64
Dash []float64
DashOffset float64
StrokeColor color.Color
FillColor color.Color
FillRule FillRule
Cap LineCap
Join LineJoin
FontSizePoints float64
Font *truetype.Font
Scale float64
Previous *ContextStack
}
// NewStackGraphicContext Create a new Graphic context from an image
func NewStackGraphicContext() *StackGraphicContext {
gc := &StackGraphicContext{}
gc.current = new(ContextStack)
gc.current.Tr = NewIdentityMatrix()
gc.current.Path = new(Path)
gc.current.LineWidth = 1.0
gc.current.StrokeColor = image.Black
gc.current.FillColor = image.White
gc.current.Cap = RoundCap
gc.current.FillRule = FillRuleEvenOdd
gc.current.Join = RoundJoin
gc.current.FontSizePoints = 10
return gc
}
// GetMatrixTransform returns the matrix transform.
func (gc *StackGraphicContext) GetMatrixTransform() Matrix {
return gc.current.Tr
}
// SetMatrixTransform sets the matrix transform.
func (gc *StackGraphicContext) SetMatrixTransform(tr Matrix) {
gc.current.Tr = tr
}
// ComposeMatrixTransform composes a transform into the current transform.
func (gc *StackGraphicContext) ComposeMatrixTransform(tr Matrix) {
gc.current.Tr.Compose(tr)
}
// Rotate rotates the matrix transform by an angle in degrees.
func (gc *StackGraphicContext) Rotate(angle float64) {
gc.current.Tr.Rotate(angle)
}
// Translate translates a transform.
func (gc *StackGraphicContext) Translate(tx, ty float64) {
gc.current.Tr.Translate(tx, ty)
}
// Scale scales a transform.
func (gc *StackGraphicContext) Scale(sx, sy float64) {
gc.current.Tr.Scale(sx, sy)
}
// SetStrokeColor sets the stroke color.
func (gc *StackGraphicContext) SetStrokeColor(c color.Color) {
gc.current.StrokeColor = c
}
// SetFillColor sets the fill color.
func (gc *StackGraphicContext) SetFillColor(c color.Color) {
gc.current.FillColor = c
}
// SetFillRule sets the fill rule.
func (gc *StackGraphicContext) SetFillRule(f FillRule) {
gc.current.FillRule = f
}
// SetLineWidth sets the line width.
func (gc *StackGraphicContext) SetLineWidth(lineWidth float64) {
gc.current.LineWidth = lineWidth
}
// SetLineCap sets the line cap.
func (gc *StackGraphicContext) SetLineCap(cap LineCap) {
gc.current.Cap = cap
}
// SetLineJoin sets the line join.
func (gc *StackGraphicContext) SetLineJoin(join LineJoin) {
gc.current.Join = join
}
// SetLineDash sets the line dash.
func (gc *StackGraphicContext) SetLineDash(dash []float64, dashOffset float64) {
gc.current.Dash = dash
gc.current.DashOffset = dashOffset
}
// SetFontSize sets the font size.
func (gc *StackGraphicContext) SetFontSize(fontSizePoints float64) {
gc.current.FontSizePoints = fontSizePoints
}
// GetFontSize gets the font size.
func (gc *StackGraphicContext) GetFontSize() float64 {
return gc.current.FontSizePoints
}
// SetFont sets the current font.
func (gc *StackGraphicContext) SetFont(f *truetype.Font) {
gc.current.Font = f
}
// GetFont returns the font.
func (gc *StackGraphicContext) GetFont() *truetype.Font {
return gc.current.Font
}
// BeginPath starts a new path.
func (gc *StackGraphicContext) BeginPath() {
gc.current.Path.Clear()
}
// IsEmpty returns if the path is empty.
func (gc *StackGraphicContext) IsEmpty() bool {
return gc.current.Path.IsEmpty()
}
// LastPoint returns the last point on the path.
func (gc *StackGraphicContext) LastPoint() (x float64, y float64) {
return gc.current.Path.LastPoint()
}
// MoveTo moves the cursor for a path.
func (gc *StackGraphicContext) MoveTo(x, y float64) {
gc.current.Path.MoveTo(x, y)
}
// LineTo draws a line.
func (gc *StackGraphicContext) LineTo(x, y float64) {
gc.current.Path.LineTo(x, y)
}
// QuadCurveTo draws a quad curve.
func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) {
gc.current.Path.QuadCurveTo(cx, cy, x, y)
}
// CubicCurveTo draws a cubic curve.
func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
gc.current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y)
}
// ArcTo draws an arc.
func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
gc.current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle)
}
// Close closes a path.
func (gc *StackGraphicContext) Close() {
gc.current.Path.Close()
}
// Save pushes a context onto the stack.
func (gc *StackGraphicContext) Save() {
context := new(ContextStack)
context.FontSizePoints = gc.current.FontSizePoints
context.Font = gc.current.Font
context.LineWidth = gc.current.LineWidth
context.StrokeColor = gc.current.StrokeColor
context.FillColor = gc.current.FillColor
context.FillRule = gc.current.FillRule
context.Dash = gc.current.Dash
context.DashOffset = gc.current.DashOffset
context.Cap = gc.current.Cap
context.Join = gc.current.Join
context.Path = gc.current.Path.Copy()
context.Font = gc.current.Font
context.Scale = gc.current.Scale
copy(context.Tr[:], gc.current.Tr[:])
context.Previous = gc.current
gc.current = context
}
// Restore restores the previous context.
func (gc *StackGraphicContext) Restore() {
if gc.current.Previous != nil {
oldContext := gc.current
gc.current = gc.current.Previous
oldContext.Previous = nil
}
}