1
2
3
4
5
6 package raster
7
8 import (
9 "fmt"
10 "math"
11
12 "golang.org/x/image/math/fixed"
13 )
14
15
16 func maxAbs(a, b fixed.Int26_6) fixed.Int26_6 {
17 if a < 0 {
18 a = -a
19 }
20 if b < 0 {
21 b = -b
22 }
23 if a < b {
24 return b
25 }
26 return a
27 }
28
29
30 func pNeg(p fixed.Point26_6) fixed.Point26_6 {
31 return fixed.Point26_6{-p.X, -p.Y}
32 }
33
34
35 func pDot(p fixed.Point26_6, q fixed.Point26_6) fixed.Int52_12 {
36 px, py := int64(p.X), int64(p.Y)
37 qx, qy := int64(q.X), int64(q.Y)
38 return fixed.Int52_12(px*qx + py*qy)
39 }
40
41
42 func pLen(p fixed.Point26_6) fixed.Int26_6 {
43
44 x := float64(p.X)
45 y := float64(p.Y)
46 return fixed.Int26_6(math.Sqrt(x*x + y*y))
47 }
48
49
50
51 func pNorm(p fixed.Point26_6, length fixed.Int26_6) fixed.Point26_6 {
52 d := pLen(p)
53 if d == 0 {
54 return fixed.Point26_6{}
55 }
56 s, t := int64(length), int64(d)
57 x := int64(p.X) * s / t
58 y := int64(p.Y) * s / t
59 return fixed.Point26_6{fixed.Int26_6(x), fixed.Int26_6(y)}
60 }
61
62
63
64
65 func pRot45CW(p fixed.Point26_6) fixed.Point26_6 {
66
67 px, py := int64(p.X), int64(p.Y)
68 qx := (+px - py) * 181 / 256
69 qy := (+px + py) * 181 / 256
70 return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)}
71 }
72
73
74
75
76 func pRot90CW(p fixed.Point26_6) fixed.Point26_6 {
77 return fixed.Point26_6{-p.Y, p.X}
78 }
79
80
81
82
83 func pRot135CW(p fixed.Point26_6) fixed.Point26_6 {
84
85 px, py := int64(p.X), int64(p.Y)
86 qx := (-px - py) * 181 / 256
87 qy := (+px - py) * 181 / 256
88 return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)}
89 }
90
91
92
93
94 func pRot45CCW(p fixed.Point26_6) fixed.Point26_6 {
95
96 px, py := int64(p.X), int64(p.Y)
97 qx := (+px + py) * 181 / 256
98 qy := (-px + py) * 181 / 256
99 return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)}
100 }
101
102
103
104
105 func pRot90CCW(p fixed.Point26_6) fixed.Point26_6 {
106 return fixed.Point26_6{p.Y, -p.X}
107 }
108
109
110
111
112 func pRot135CCW(p fixed.Point26_6) fixed.Point26_6 {
113
114 px, py := int64(p.X), int64(p.Y)
115 qx := (-px + py) * 181 / 256
116 qy := (-px - py) * 181 / 256
117 return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)}
118 }
119
120
121 type Adder interface {
122
123 Start(a fixed.Point26_6)
124
125 Add1(b fixed.Point26_6)
126
127 Add2(b, c fixed.Point26_6)
128
129 Add3(b, c, d fixed.Point26_6)
130 }
131
132
133
134 type Path []fixed.Int26_6
135
136
137 func (p Path) String() string {
138 s := ""
139 for i := 0; i < len(p); {
140 if i != 0 {
141 s += " "
142 }
143 switch p[i] {
144 case 0:
145 s += "S0" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+3]))
146 i += 4
147 case 1:
148 s += "A1" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+3]))
149 i += 4
150 case 2:
151 s += "A2" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+5]))
152 i += 6
153 case 3:
154 s += "A3" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+7]))
155 i += 8
156 default:
157 panic("freetype/raster: bad path")
158 }
159 }
160 return s
161 }
162
163
164 func (p *Path) Clear() {
165 *p = (*p)[:0]
166 }
167
168
169 func (p *Path) Start(a fixed.Point26_6) {
170 *p = append(*p, 0, a.X, a.Y, 0)
171 }
172
173
174 func (p *Path) Add1(b fixed.Point26_6) {
175 *p = append(*p, 1, b.X, b.Y, 1)
176 }
177
178
179 func (p *Path) Add2(b, c fixed.Point26_6) {
180 *p = append(*p, 2, b.X, b.Y, c.X, c.Y, 2)
181 }
182
183
184 func (p *Path) Add3(b, c, d fixed.Point26_6) {
185 *p = append(*p, 3, b.X, b.Y, c.X, c.Y, d.X, d.Y, 3)
186 }
187
188
189 func (p *Path) AddPath(q Path) {
190 *p = append(*p, q...)
191 }
192
193
194 func (p *Path) AddStroke(q Path, width fixed.Int26_6, cr Capper, jr Joiner) {
195 Stroke(p, q, width, cr, jr)
196 }
197
198
199 func (p Path) firstPoint() fixed.Point26_6 {
200 return fixed.Point26_6{p[1], p[2]}
201 }
202
203
204 func (p Path) lastPoint() fixed.Point26_6 {
205 return fixed.Point26_6{p[len(p)-3], p[len(p)-2]}
206 }
207
208
209
210
211
212
213
214 func addPathReversed(p Adder, q Path) {
215 if len(q) == 0 {
216 return
217 }
218 i := len(q) - 1
219 for {
220 switch q[i] {
221 case 0:
222 return
223 case 1:
224 i -= 4
225 p.Add1(
226 fixed.Point26_6{q[i-2], q[i-1]},
227 )
228 case 2:
229 i -= 6
230 p.Add2(
231 fixed.Point26_6{q[i+2], q[i+3]},
232 fixed.Point26_6{q[i-2], q[i-1]},
233 )
234 case 3:
235 i -= 8
236 p.Add3(
237 fixed.Point26_6{q[i+4], q[i+5]},
238 fixed.Point26_6{q[i+2], q[i+3]},
239 fixed.Point26_6{q[i-2], q[i-1]},
240 )
241 default:
242 panic("freetype/raster: bad path")
243 }
244 }
245 }
246
View as plain text