forked from tdewolff/canvas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gochart.go
188 lines (157 loc) · 4.87 KB
/
gochart.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
package canvas
import (
"io"
"math"
"github.com/golang/freetype/truetype"
"github.com/wcharczuk/go-chart"
"github.com/wcharczuk/go-chart/drawing"
)
// GoChart is a github.com/wcharczuk/go-chart renderer.
type GoChart struct {
c *Canvas
ctx *Context
height float64
writer Writer
dpi float64
font *FontFamily
fontSize float64
fontColor drawing.Color
textRotation float64
}
// NewGoChart returns a new github.com/wcharczuk/go-chart renderer.
func NewGoChart(writer Writer) func(int, int) (chart.Renderer, error) {
return func(w, h int) (chart.Renderer, error) {
font := NewFontFamily("font")
font.LoadLocalFont("Arimo", FontRegular)
c := New(float64(w), float64(h))
return &GoChart{
c: c,
ctx: NewContext(c),
height: float64(h),
writer: writer,
dpi: 72.0,
font: font,
}, nil
}
}
// ResetStyle should reset any style related settings on the renderer.
func (r *GoChart) ResetStyle() {
r.ctx.ResetStyle()
r.textRotation = 0.0
}
// GetDPI gets the DPI for the renderer.
func (r *GoChart) GetDPI() float64 {
return r.dpi
}
// SetDPI sets the DPI for the renderer.
func (r *GoChart) SetDPI(dpi float64) {
r.dpi = dpi
}
// SetClassName sets the current class name.
func (r *GoChart) SetClassName(name string) {
// TODO
}
// SetStrokeColor sets the current stroke color.
func (r *GoChart) SetStrokeColor(col drawing.Color) {
r.ctx.SetStrokeColor(col)
}
// SetFillColor sets the current fill color.
func (r *GoChart) SetFillColor(col drawing.Color) {
r.ctx.SetFillColor(col)
}
// SetStrokeWidth sets the stroke width.
func (r *GoChart) SetStrokeWidth(width float64) {
r.ctx.SetStrokeWidth(width)
}
// SetStrokeDashArray sets the stroke dash array.
func (r *GoChart) SetStrokeDashArray(dashArray []float64) {
r.ctx.SetDashes(0.0, dashArray...)
}
// MoveTo moves the cursor to a given point.
func (r *GoChart) MoveTo(x, y int) {
r.ctx.MoveTo(float64(x), r.height-float64(y))
}
// LineTo both starts a shape and draws a line to a given point
// from the previous point.
func (r *GoChart) LineTo(x, y int) {
r.ctx.LineTo(float64(x), r.height-float64(y))
}
// QuadCurveTo draws a quad curve.
// cx and cy represent the bezier "control points".
func (r *GoChart) QuadCurveTo(cx, cy, x, y int) {
r.ctx.QuadTo(float64(cx), r.height-float64(cy), float64(x), r.height-float64(y))
}
// ArcTo draws an arc with a given center (cx,cy)
// a given set of radii (rx,ry), a startAngle and delta (in radians).
func (r *GoChart) ArcTo(cx, cy int, rx, ry, startAngle, delta float64) {
startAngle *= 180.0 / math.Pi
delta *= 180.0 / math.Pi
start := ellipsePos(rx, -ry, 0.0, float64(cx), r.height-float64(cy), startAngle)
if r.c.Empty() {
r.ctx.MoveTo(start.X, r.height-start.Y)
} else {
r.ctx.LineTo(start.X, r.height-start.Y)
}
r.ctx.Arc(rx, ry, 0.0, startAngle, startAngle+delta)
}
// Close finalizes a shape as drawn by LineTo.
func (r *GoChart) Close() {
r.ctx.Close()
r.ctx.MoveTo(0.0, 0.0)
}
// Stroke strokes the path.
func (r *GoChart) Stroke() {
r.ctx.Stroke()
}
// Fill fills the path, but does not stroke.
func (r *GoChart) Fill() {
r.ctx.Fill()
}
// FillStroke fills and strokes a path.
func (r *GoChart) FillStroke() {
r.ctx.FillStroke()
}
// Circle draws a circle at the given coords with a given radius.
func (r *GoChart) Circle(radius float64, x, y int) {
r.ctx.DrawPath(float64(x), r.height-float64(y), Circle(radius))
}
// SetFont sets a font for a text field.
func (r *GoChart) SetFont(font *truetype.Font) {
// TODO
}
// SetFontColor sets a font's color
func (r *GoChart) SetFontColor(col drawing.Color) {
r.fontColor = col
}
// SetFontSize sets the font size for a text field.
func (r *GoChart) SetFontSize(size float64) {
r.fontSize = size
}
// Text draws a text blob.
func (r *GoChart) Text(body string, x, y int) {
face := r.font.Face(r.fontSize*ptPerMm*r.dpi/72.0, r.fontColor, FontRegular, FontNormal)
r.ctx.Push()
r.ctx.SetFillColor(r.fontColor)
r.ctx.ComposeView(Identity.Rotate(-r.textRotation * 180.0 / math.Pi))
r.ctx.DrawText(float64(x), r.height-float64(y), NewTextLine(face, body, Left))
r.ctx.Pop()
}
// MeasureText measures text.
func (r *GoChart) MeasureText(body string) chart.Box {
p, _ := r.font.Face(r.fontSize*ptPerMm*r.dpi/72.0, r.fontColor, FontRegular, FontNormal).ToPath(body)
bounds := p.Bounds()
bounds = bounds.Transform(Identity.Rotate(-r.textRotation * 180.0 / math.Pi))
return chart.Box{Left: int(bounds.X + 0.5), Top: int(bounds.Y + 0.5), Right: int((bounds.W + bounds.X) + 0.5), Bottom: int((bounds.H + bounds.Y) + 0.5)}
}
// SetTextRotation sets a rotation for drawing elements.
func (r *GoChart) SetTextRotation(radian float64) {
r.textRotation = radian
}
// ClearTextRotation clears rotation.
func (r *GoChart) ClearTextRotation() {
r.textRotation = 0.0
}
// Save writes the image to the given writer.
func (r *GoChart) Save(w io.Writer) error {
return r.writer(w, r.c)
}