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
28 #include "swfdec_path.h"
29 #include "swfdec_debug.h"
32 swfdec_path_init (cairo_path_t
*path
)
34 path
->status
= CAIRO_STATUS_SUCCESS
;
40 swfdec_path_reset (cairo_path_t
*path
)
42 path
->status
= CAIRO_STATUS_SUCCESS
;
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
;
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
)
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
);
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
++];
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
++];
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
;
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
;
135 swfdec_path_append_reverse (cairo_path_t
*path
, const cairo_path_t
*append
,
138 cairo_path_data_t
*out
, *in
;
141 swfdec_path_require_size (path
, append
->num_data
);
142 path
->num_data
+= append
->num_data
;
143 out
= &path
->data
[path
->num_data
- 1];
145 for (i
= 0; i
< append
->num_data
; i
++) {
146 switch (in
[i
].header
.type
) {
147 case CAIRO_PATH_LINE_TO
:
150 out
[-i
- 1].header
= in
[i
].header
;
153 case CAIRO_PATH_CURVE_TO
:
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
;
161 case CAIRO_PATH_CLOSE_PATH
:
162 case CAIRO_PATH_MOVE_TO
:
163 /* these two don't exist in our code */
165 g_assert_not_reached ();
173 swfdec_path_get_extents (const cairo_path_t
*path
, SwfdecRect
*extents
)
175 cairo_path_data_t
*data
= path
->data
;
178 gboolean need_current
= TRUE
;
179 gboolean start
= TRUE
;
180 #define ADD_POINT(extents, x, y) G_STMT_START { \
181 if (x < extents->x0) \
183 else if (x > extents->x1) \
185 if (y < extents->y0) \
187 else if (y > extents->y1) \
190 for (i
= 0; i
< path
->num_data
; i
++) {
191 switch (data
[i
].header
.type
) {
192 case CAIRO_PATH_CURVE_TO
:
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
);
210 case CAIRO_PATH_LINE_TO
:
219 ADD_POINT (extents
, x
, y
);
221 need_current
= FALSE
;
223 ADD_POINT (extents
, data
[i
+1].point
.x
, data
[i
+1].point
.y
);
226 case CAIRO_PATH_CLOSE_PATH
:
231 case CAIRO_PATH_MOVE_TO
:
232 x
= data
[i
+1].point
.x
;
233 y
= data
[i
+1].point
.y
;
238 g_assert_not_reached ();
245 swfdec_path_merge (cairo_path_t
*dest
, const cairo_path_t
*start
,
246 const cairo_path_t
*end
, double ratio
)
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
;
260 for (i
= 0; i
< dest
->num_data
; i
++) {
261 g_assert (sdata
[i
].header
.type
== edata
[i
].header
.type
);
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
;
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
;
275 case CAIRO_PATH_CLOSE_PATH
:
278 g_assert_not_reached ();