remove SWFDEC_IS_AS_VALUE check
[swfdec.git] / swfdec / swfdec_path.c
blobe5af14a5f3a2d768217d213bd533165a39746e97
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <string.h>
28 #include "swfdec_path.h"
29 #include "swfdec_debug.h"
31 void
32 swfdec_path_init (cairo_path_t *path)
34 path->status = CAIRO_STATUS_SUCCESS;
35 path->data = NULL;
36 path->num_data = 0;
39 void
40 swfdec_path_reset (cairo_path_t *path)
42 path->status = CAIRO_STATUS_SUCCESS;
43 g_free (path->data);
44 path->data = NULL;
45 path->num_data = 0;
48 void
49 swfdec_path_copy (cairo_path_t *dest, const cairo_path_t *source)
51 dest->status = source->status;
52 swfdec_path_ensure_size (dest, source->num_data);
53 memcpy (dest->data, source->data, sizeof (cairo_path_data_t) * source->num_data);
54 dest->num_data = source->num_data;
57 void
58 swfdec_path_ensure_size (cairo_path_t *path, int size)
60 #define SWFDEC_PATH_STEPS 32
61 /* round up to next multiple of SWFDEC_PATH_STEPS */
62 int current_size = path->num_data - path->num_data % SWFDEC_PATH_STEPS;
63 if (path->num_data % SWFDEC_PATH_STEPS)
64 current_size += SWFDEC_PATH_STEPS;
66 if (size % SWFDEC_PATH_STEPS)
67 size += SWFDEC_PATH_STEPS - size % SWFDEC_PATH_STEPS;
68 g_assert (current_size % SWFDEC_PATH_STEPS == 0);
69 g_assert (size % SWFDEC_PATH_STEPS == 0);
70 while (size <= current_size)
71 return;
72 SWFDEC_LOG ("extending size of %p from %u to %u", path, current_size, size);
73 path->data = g_renew (cairo_path_data_t, path->data, size);
76 void
77 swfdec_path_move_to (cairo_path_t *path, double x, double y)
79 cairo_path_data_t *cur;
81 swfdec_path_require_size (path, 2);
82 cur = &path->data[path->num_data++];
83 cur->header.type = CAIRO_PATH_MOVE_TO;
84 cur->header.length = 2;
85 cur = &path->data[path->num_data++];
86 cur->point.x = x;
87 cur->point.y = y;
90 void
91 swfdec_path_line_to (cairo_path_t *path, double x, double y)
93 cairo_path_data_t *cur;
95 swfdec_path_require_size (path, 2);
96 cur = &path->data[path->num_data++];
97 cur->header.type = CAIRO_PATH_LINE_TO;
98 cur->header.length = 2;
99 cur = &path->data[path->num_data++];
100 cur->point.x = x;
101 cur->point.y = y;
104 void
105 swfdec_path_curve_to (cairo_path_t *path, double start_x, double start_y,
106 double control_x, double control_y, double end_x, double end_y)
108 cairo_path_data_t *cur;
110 swfdec_path_require_size (path, 4);
111 cur = &path->data[path->num_data++];
112 cur->header.type = CAIRO_PATH_CURVE_TO;
113 cur->header.length = 4;
114 #define WEIGHT (2.0/3.0)
115 cur = &path->data[path->num_data++];
116 cur->point.x = control_x * WEIGHT + (1-WEIGHT) * start_x;
117 cur->point.y = control_y * WEIGHT + (1-WEIGHT) * start_y;
118 cur = &path->data[path->num_data++];
119 cur->point.x = control_x * WEIGHT + (1-WEIGHT) * end_x;
120 cur->point.y = control_y * WEIGHT + (1-WEIGHT) * end_y;
121 cur = &path->data[path->num_data++];
122 cur->point.x = end_x;
123 cur->point.y = end_y;
126 void
127 swfdec_path_append (cairo_path_t *path, const cairo_path_t *append)
129 swfdec_path_require_size (path, append->num_data);
130 memcpy (&path->data[path->num_data], append->data, sizeof (cairo_path_data_t) * append->num_data);
131 path->num_data += append->num_data;
134 void
135 swfdec_path_append_reverse (cairo_path_t *path, const cairo_path_t *append,
136 double x, double y)
138 cairo_path_data_t *out, *in;
139 int i;
141 swfdec_path_require_size (path, append->num_data);
142 path->num_data += append->num_data;
143 out = &path->data[path->num_data - 1];
144 in = append->data;
145 for (i = 0; i < append->num_data; i++) {
146 switch (in[i].header.type) {
147 case CAIRO_PATH_LINE_TO:
148 out[-i].point.x = x;
149 out[-i].point.y = y;
150 out[-i - 1].header = in[i].header;
151 i++;
152 break;
153 case CAIRO_PATH_CURVE_TO:
154 out[-i].point.x = x;
155 out[-i].point.y = y;
156 out[-i - 3].header = in[i].header;
157 out[-i - 1].point = in[i + 1].point;
158 out[-i - 2].point = in[i + 2].point;
159 i += 3;
160 break;
161 case CAIRO_PATH_CLOSE_PATH:
162 case CAIRO_PATH_MOVE_TO:
163 /* these two don't exist in our code */
164 default:
165 g_assert_not_reached ();
167 x = in[i].point.x;
168 y = in[i].point.y;
172 void
173 swfdec_path_get_extents (const cairo_path_t *path, SwfdecRect *extents)
175 cairo_path_data_t *data = path->data;
176 int i;
177 double x = 0, y = 0;
178 gboolean need_current = TRUE;
179 gboolean start = TRUE;
180 #define ADD_POINT(extents, x, y) G_STMT_START { \
181 if (x < extents->x0) \
182 extents->x0 = x; \
183 else if (x > extents->x1) \
184 extents->x1 = x; \
185 if (y < extents->y0) \
186 extents->y0 = y; \
187 else if (y > extents->y1) \
188 extents->y1 = y; \
189 } G_STMT_END
190 for (i = 0; i < path->num_data; i++) {
191 switch (data[i].header.type) {
192 case CAIRO_PATH_CURVE_TO:
193 if (need_current) {
194 if (start) {
195 start = FALSE;
196 extents->x0 = x;
197 extents->x1 = x;
198 extents->y0 = y;
199 extents->y1 = y;
200 } else {
201 ADD_POINT (extents, x, y);
203 need_current = FALSE;
205 ADD_POINT (extents, data[i+1].point.x, data[i+1].point.y);
206 ADD_POINT (extents, data[i+2].point.x, data[i+2].point.y);
207 ADD_POINT (extents, data[i+3].point.x, data[i+3].point.y);
208 i += 3;
209 break;
210 case CAIRO_PATH_LINE_TO:
211 if (need_current) {
212 if (start) {
213 start = FALSE;
214 extents->x0 = x;
215 extents->x1 = x;
216 extents->y0 = y;
217 extents->y1 = y;
218 } else {
219 ADD_POINT (extents, x, y);
221 need_current = FALSE;
223 ADD_POINT (extents, data[i+1].point.x, data[i+1].point.y);
224 i++;
225 break;
226 case CAIRO_PATH_CLOSE_PATH:
227 x = 0;
228 y = 0;
229 need_current = TRUE;
230 break;
231 case CAIRO_PATH_MOVE_TO:
232 x = data[i+1].point.x;
233 y = data[i+1].point.y;
234 need_current = TRUE;
235 i++;
236 break;
237 default:
238 g_assert_not_reached ();
241 #undef ADD_POINT
244 void
245 swfdec_path_merge (cairo_path_t *dest, const cairo_path_t *start,
246 const cairo_path_t *end, double ratio)
248 int i;
249 cairo_path_data_t *ddata, *sdata, *edata;
250 double inv = 1.0 - ratio;
252 g_assert (start->num_data == end->num_data);
254 swfdec_path_reset (dest);
255 swfdec_path_ensure_size (dest, start->num_data);
256 dest->num_data = start->num_data;
257 ddata = dest->data;
258 sdata = start->data;
259 edata = end->data;
260 for (i = 0; i < dest->num_data; i++) {
261 g_assert (sdata[i].header.type == edata[i].header.type);
262 ddata[i] = sdata[i];
263 switch (sdata[i].header.type) {
264 case CAIRO_PATH_CURVE_TO:
265 ddata[i+1].point.x = sdata[i+1].point.x * inv + edata[i+1].point.x * ratio;
266 ddata[i+1].point.y = sdata[i+1].point.y * inv + edata[i+1].point.y * ratio;
267 ddata[i+2].point.x = sdata[i+2].point.x * inv + edata[i+2].point.x * ratio;
268 ddata[i+2].point.y = sdata[i+2].point.y * inv + edata[i+2].point.y * ratio;
269 i += 2;
270 case CAIRO_PATH_MOVE_TO:
271 case CAIRO_PATH_LINE_TO:
272 ddata[i+1].point.x = sdata[i+1].point.x * inv + edata[i+1].point.x * ratio;
273 ddata[i+1].point.y = sdata[i+1].point.y * inv + edata[i+1].point.y * ratio;
274 i++;
275 case CAIRO_PATH_CLOSE_PATH:
276 break;
277 default:
278 g_assert_not_reached ();