blob: 15372de07652fa8b55d29d188e7d6a3fce63f6cb [file] [log] [blame]
Allan MacKinnon4359d522018-06-19 13:57:04 -07001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can
5 * be found in the LICENSE file.
6 *
7 */
8
9//
10//
11//
12
13#include "path_builder.h"
14#include "context.h"
15
16//
17//
18//
19
20skc_err
21skc_path_builder_retain(skc_path_builder_t path_builder)
22{
23 ++path_builder->refcount;
24
25 return SKC_ERR_SUCCESS;
26}
27
28skc_err
29skc_path_builder_release(skc_path_builder_t path_builder)
30{
31 SKC_ASSERT_STATE_ASSERT(SKC_PATH_BUILDER_STATE_READY,path_builder);
32
33 path_builder->release(path_builder->impl);
34
35 return SKC_ERR_SUCCESS;
36}
37
38//
39// PATH BODY
40//
41
42skc_err
43skc_path_begin(skc_path_builder_t path_builder)
44{
45 SKC_ASSERT_STATE_TRANSITION(SKC_PATH_BUILDER_STATE_READY,
46 SKC_PATH_BUILDER_STATE_BUILDING,
47 path_builder);
48
49 // init path builder counters
50 path_builder->line .rem = 0;
51 path_builder->quad .rem = 0;
52 path_builder->cubic.rem = 0;
53
54 // begin the path
55 path_builder->begin(path_builder->impl);
56
57 return SKC_ERR_SUCCESS;
58}
59
60skc_err
61skc_path_end(skc_path_builder_t path_builder, skc_path_t * path)
62{
63 SKC_ASSERT_STATE_TRANSITION(SKC_PATH_BUILDER_STATE_BUILDING,
64 SKC_PATH_BUILDER_STATE_READY,
65 path_builder);
66
67 // update path header with proper counts
68 path_builder->end(path_builder->impl,path);
69
70 return SKC_ERR_SUCCESS;
71}
72
73//
74// PATH SEGMENT OPS
75//
76
77static
78void
79skc_path_move_to_1(skc_path_builder_t path_builder,
80 float x0, float y0)
81{
82 path_builder->curr[0].x = x0;
83 path_builder->curr[0].y = y0;
84 path_builder->curr[1].x = x0;
85 path_builder->curr[1].y = y0;
86}
87
88static
89void
90skc_path_move_to_2(skc_path_builder_t path_builder,
91 float x0, float y0,
92 float x1, float y1)
93{
94 path_builder->curr[0].x = x0;
95 path_builder->curr[0].y = y0;
96 path_builder->curr[1].x = x1;
97 path_builder->curr[1].y = y1;
98}
99
100skc_err
101skc_path_move_to(skc_path_builder_t path_builder,
102 float x0, float y0)
103{
104 skc_path_move_to_1(path_builder,x0,y0);
105
106 return SKC_ERR_SUCCESS;
107}
108
109skc_err
110skc_path_close(skc_path_builder_t path_builder)
111{
112 //
113 // FIXME -- CLARIFY WHY SUBTLE AUTO-CLOSE BEHAVIORS _DON'T BELONG_
114 // IN THE SKIA COMPUTE LAYER
115 //
116 // OR, BETTER YET, GET RID OF THIS FUNC ENTIRELY
117 //
118 return SKC_ERR_NOT_IMPLEMENTED;
119}
120
121skc_err
122skc_path_line_to(skc_path_builder_t path_builder,
123 float x1, float y1)
124{
125 if (path_builder->line.rem == 0) {
126 path_builder->new_line(path_builder->impl);
127 }
128
129 --path_builder->line.rem;
130
131 *path_builder->line.coords[0]++ = path_builder->curr[0].x;
132 *path_builder->line.coords[1]++ = path_builder->curr[0].y;
133 *path_builder->line.coords[2]++ = x1;
134 *path_builder->line.coords[3]++ = y1;
135
136 skc_path_move_to_1(path_builder,x1,y1);
137
138 return SKC_ERR_SUCCESS;
139}
140
141skc_err
142skc_path_quad_to(skc_path_builder_t path_builder,
143 float x1, float y1,
144 float x2, float y2)
145{
146 if (path_builder->quad.rem == 0) {
147 path_builder->new_quad(path_builder->impl);
148 }
149
150 --path_builder->quad.rem;
151
152 *path_builder->quad.coords[0]++ = path_builder->curr[0].x;
153 *path_builder->quad.coords[1]++ = path_builder->curr[0].y;
154 *path_builder->quad.coords[2]++ = x1;
155 *path_builder->quad.coords[3]++ = y1;
156 *path_builder->quad.coords[4]++ = x2;
157 *path_builder->quad.coords[5]++ = y2;
158
159 skc_path_move_to_2(path_builder,x2,y2,x1,y1);
160
161 return SKC_ERR_SUCCESS;
162}
163
164skc_err
165skc_path_quad_smooth_to(skc_path_builder_t path_builder,
166 float x2, float y2)
167{
168 float const x1 = path_builder->curr[0].x * 2.0f - path_builder->curr[1].x;
169 float const y1 = path_builder->curr[0].y * 2.0f - path_builder->curr[1].y;
170
171 return skc_path_quad_to(path_builder,x1,y1,x2,y2);
172}
173
174skc_err
175skc_path_cubic_to(skc_path_builder_t path_builder,
176 float x1, float y1,
177 float x2, float y2,
178 float x3, float y3)
179{
180 if (path_builder->cubic.rem == 0) {
181 path_builder->new_cubic(path_builder->impl);
182 }
183
184 --path_builder->cubic.rem;
185
186 *path_builder->cubic.coords[0]++ = path_builder->curr[0].x;
187 *path_builder->cubic.coords[1]++ = path_builder->curr[0].y;
188 *path_builder->cubic.coords[2]++ = x1;
189 *path_builder->cubic.coords[3]++ = y1;
190 *path_builder->cubic.coords[4]++ = x2;
191 *path_builder->cubic.coords[5]++ = y2;
192 *path_builder->cubic.coords[6]++ = x3;
193 *path_builder->cubic.coords[7]++ = y3;
194
195 skc_path_move_to_2(path_builder,x3,y3,x2,y2);
196
197 return SKC_ERR_SUCCESS;
198}
199
200skc_err
201skc_path_cubic_smooth_to(skc_path_builder_t path_builder,
202 float x2, float y2,
203 float x3, float y3)
204{
205 float const x1 = path_builder->curr[0].x * 2.0f - path_builder->curr[1].x;
206 float const y1 = path_builder->curr[0].y * 2.0f - path_builder->curr[1].y;
207
208 return skc_path_cubic_to(path_builder,x1,y1,x2,y2,x3,y3);
209}
210
211//
212// FIXME -- add rational quad and cubic support and move primitives
213// like ellipse into an adapter. They do *not* belong in the core API.
214//
215
216skc_err
217skc_path_ellipse(skc_path_builder_t path_builder,
218 float cx, float cy,
219 float rx, float ry)
220{
221 //
222 // FIXME -- we can implement this with rationals later...
223 //
224
225 //
226 // Approximate a circle with 4 cubics:
227 //
228 // http://en.wikipedia.org/wiki/B%C3%A9zier_spline#Approximating_circular_arcs
229 //
230 skc_path_move_to_1(path_builder, cx, cy + ry);
231
232#define KAPPA_FLOAT 0.55228474983079339840f // moar digits!
233
234 float const kx = rx * KAPPA_FLOAT;
235 float const ky = ry * KAPPA_FLOAT;
236
237 skc_err err;
238
239 err = skc_path_cubic_to(path_builder,
240 cx + kx, cy + ry,
241 cx + rx, cy + ky,
242 cx + rx, cy);
243
244 if (err)
245 return err;
246
247 err = skc_path_cubic_to(path_builder,
248 cx + rx, cy - ky,
249 cx + kx, cy - ry,
250 cx, cy - ry);
251
252 if (err)
253 return err;
254
255 err = skc_path_cubic_to(path_builder,
256 cx - kx, cy - ry,
257 cx - rx, cy - ky,
258 cx - rx, cy);
259
260 if (err)
261 return err;
262
263 err = skc_path_cubic_to(path_builder,
264 cx - rx, cy + ky,
265 cx - kx, cy + ry,
266 cx, cy + ry);
267 return err;
268}
269
270//
271//
272//