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_ensure_size (cairo_path_t
*path
, int size
)
51 #define SWFDEC_PATH_STEPS 32
52 /* round up to next multiple of SWFDEC_PATH_STEPS */
53 int current_size
= path
->num_data
- path
->num_data
% SWFDEC_PATH_STEPS
;
54 if (path
->num_data
% SWFDEC_PATH_STEPS
)
55 current_size
+= SWFDEC_PATH_STEPS
;
57 if (size
% SWFDEC_PATH_STEPS
)
58 size
+= SWFDEC_PATH_STEPS
- size
% SWFDEC_PATH_STEPS
;
59 g_assert (current_size
% SWFDEC_PATH_STEPS
== 0);
60 g_assert (size
% SWFDEC_PATH_STEPS
== 0);
61 while (size
<= current_size
)
63 SWFDEC_LOG ("extending size of %p from %u to %u", path
, current_size
, size
);
64 path
->data
= g_renew (cairo_path_data_t
, path
->data
, size
);
68 swfdec_path_move_to (cairo_path_t
*path
, double x
, double y
)
70 cairo_path_data_t
*cur
;
72 swfdec_path_require_size (path
, 2);
73 cur
= &path
->data
[path
->num_data
++];
74 cur
->header
.type
= CAIRO_PATH_MOVE_TO
;
75 cur
->header
.length
= 2;
76 cur
= &path
->data
[path
->num_data
++];
82 swfdec_path_line_to (cairo_path_t
*path
, double x
, double y
)
84 cairo_path_data_t
*cur
;
86 swfdec_path_require_size (path
, 2);
87 cur
= &path
->data
[path
->num_data
++];
88 cur
->header
.type
= CAIRO_PATH_LINE_TO
;
89 cur
->header
.length
= 2;
90 cur
= &path
->data
[path
->num_data
++];
96 swfdec_path_curve_to (cairo_path_t
*path
, double start_x
, double start_y
,
97 double control_x
, double control_y
, double end_x
, double end_y
)
99 cairo_path_data_t
*cur
;
101 swfdec_path_require_size (path
, 4);
102 cur
= &path
->data
[path
->num_data
++];
103 cur
->header
.type
= CAIRO_PATH_CURVE_TO
;
104 cur
->header
.length
= 4;
105 #define WEIGHT (2.0/3.0)
106 cur
= &path
->data
[path
->num_data
++];
107 cur
->point
.x
= control_x
* WEIGHT
+ (1-WEIGHT
) * start_x
;
108 cur
->point
.y
= control_y
* WEIGHT
+ (1-WEIGHT
) * start_y
;
109 cur
= &path
->data
[path
->num_data
++];
110 cur
->point
.x
= control_x
* WEIGHT
+ (1-WEIGHT
) * end_x
;
111 cur
->point
.y
= control_y
* WEIGHT
+ (1-WEIGHT
) * end_y
;
112 cur
= &path
->data
[path
->num_data
++];
113 cur
->point
.x
= end_x
;
114 cur
->point
.y
= end_y
;
118 swfdec_path_append (cairo_path_t
*path
, const cairo_path_t
*append
)
120 swfdec_path_require_size (path
, append
->num_data
);
121 memcpy (&path
->data
[path
->num_data
], append
->data
, sizeof (cairo_path_data_t
) * append
->num_data
);
122 path
->num_data
+= append
->num_data
;
126 swfdec_path_append_reverse (cairo_path_t
*path
, const cairo_path_t
*append
,
129 cairo_path_data_t
*out
, *in
;
132 swfdec_path_require_size (path
, append
->num_data
);
133 path
->num_data
+= append
->num_data
;
134 out
= &path
->data
[path
->num_data
- 1];
136 for (i
= 0; i
< append
->num_data
; i
++) {
137 switch (in
[i
].header
.type
) {
138 case CAIRO_PATH_LINE_TO
:
141 out
[-i
- 1].header
= in
[i
].header
;
144 case CAIRO_PATH_CURVE_TO
:
147 out
[-i
- 3].header
= in
[i
].header
;
148 out
[-i
- 1].point
= in
[i
+ 1].point
;
149 out
[-i
- 2].point
= in
[i
+ 2].point
;
152 case CAIRO_PATH_CLOSE_PATH
:
153 case CAIRO_PATH_MOVE_TO
:
154 /* these two don't exist in our code */
156 g_assert_not_reached ();
164 swfdec_path_get_extents (const cairo_path_t
*path
, SwfdecRect
*extents
)
166 cairo_path_data_t
*data
= path
->data
;
169 gboolean need_current
= TRUE
;
170 gboolean start
= TRUE
;
171 #define ADD_POINT(extents, x, y) G_STMT_START { \
172 if (x < extents->x0) \
174 else if (x > extents->x1) \
176 if (y < extents->y0) \
178 else if (y > extents->y1) \
181 for (i
= 0; i
< path
->num_data
; i
++) {
182 switch (data
[i
].header
.type
) {
183 case CAIRO_PATH_CURVE_TO
:
192 ADD_POINT (extents
, x
, y
);
194 need_current
= FALSE
;
196 ADD_POINT (extents
, data
[i
+1].point
.x
, data
[i
+1].point
.y
);
197 ADD_POINT (extents
, data
[i
+2].point
.x
, data
[i
+2].point
.y
);
198 ADD_POINT (extents
, data
[i
+3].point
.x
, data
[i
+3].point
.y
);
201 case CAIRO_PATH_LINE_TO
:
210 ADD_POINT (extents
, x
, y
);
212 need_current
= FALSE
;
214 ADD_POINT (extents
, data
[i
+1].point
.x
, data
[i
+1].point
.y
);
217 case CAIRO_PATH_CLOSE_PATH
:
222 case CAIRO_PATH_MOVE_TO
:
223 x
= data
[i
+1].point
.x
;
224 y
= data
[i
+1].point
.y
;
229 g_assert_not_reached ();
236 swfdec_path_merge (cairo_path_t
*dest
, const cairo_path_t
*start
,
237 const cairo_path_t
*end
, double ratio
)
240 cairo_path_data_t
*ddata
, *sdata
, *edata
;
241 double inv
= 1.0 - ratio
;
243 g_assert (start
->num_data
== end
->num_data
);
245 swfdec_path_reset (dest
);
246 swfdec_path_ensure_size (dest
, start
->num_data
);
247 dest
->num_data
= start
->num_data
;
251 for (i
= 0; i
< dest
->num_data
; i
++) {
252 g_assert (sdata
[i
].header
.type
== edata
[i
].header
.type
);
254 switch (sdata
[i
].header
.type
) {
255 case CAIRO_PATH_CURVE_TO
:
256 ddata
[i
+1].point
.x
= sdata
[i
+1].point
.x
* inv
+ edata
[i
+1].point
.x
* ratio
;
257 ddata
[i
+1].point
.y
= sdata
[i
+1].point
.y
* inv
+ edata
[i
+1].point
.y
* ratio
;
258 ddata
[i
+2].point
.x
= sdata
[i
+2].point
.x
* inv
+ edata
[i
+2].point
.x
* ratio
;
259 ddata
[i
+2].point
.y
= sdata
[i
+2].point
.y
* inv
+ edata
[i
+2].point
.y
* ratio
;
261 case CAIRO_PATH_MOVE_TO
:
262 case CAIRO_PATH_LINE_TO
:
263 ddata
[i
+1].point
.x
= sdata
[i
+1].point
.x
* inv
+ edata
[i
+1].point
.x
* ratio
;
264 ddata
[i
+1].point
.y
= sdata
[i
+1].point
.y
* inv
+ edata
[i
+1].point
.y
* ratio
;
266 case CAIRO_PATH_CLOSE_PATH
:
269 g_assert_not_reached ();