Fix few bugs in SwfdecGtkSocket that made it unusable
[swfdec.git] / swfdec / swfdec_shape_parser.c
blob453dc60cad01408fd7bcd7fb24dd508279d9e412
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 "swfdec_shape_parser.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_path.h"
29 #include "swfdec_stroke.h"
31 /*** PATH CONSTRUCTION ***/
33 typedef enum {
34 SWFDEC_SHAPE_TYPE_END = 0,
35 SWFDEC_SHAPE_TYPE_CHANGE,
36 SWFDEC_SHAPE_TYPE_LINE,
37 SWFDEC_SHAPE_TYPE_CURVE
38 } SwfdecShapeType;
40 static SwfdecShapeType
41 swfdec_shape_peek_type (SwfdecBits *bits)
43 guint ret = swfdec_bits_peekbits (bits, 6);
45 if (ret == 0)
46 return SWFDEC_SHAPE_TYPE_END;
47 if ((ret & 0x20) == 0)
48 return SWFDEC_SHAPE_TYPE_CHANGE;
49 if ((ret & 0x10) == 0)
50 return SWFDEC_SHAPE_TYPE_CURVE;
51 return SWFDEC_SHAPE_TYPE_LINE;
54 typedef struct {
55 int x_start, y_start;
56 int x_end, y_end;
57 cairo_path_t path;
58 } SwfdecSubPath;
60 static gboolean
61 swfdec_sub_path_match (SwfdecSubPath *from, SwfdecSubPath *to)
63 return from->x_end == to->x_start && from->y_end == to->y_start;
66 typedef struct {
67 SwfdecDraw * draw; /* drawing operation that should take the subpaths or NULL on parsing error */
68 GSList * subpaths; /* indexes into SubPath array */
69 } SwfdecStyle;
71 struct _SwfdecShapeParser {
72 /* state */
73 GSList * draws; /* completely accumulated drawing commands */
74 SwfdecParseDrawFunc parse_fill; /* function to call to parse a fill style */
75 SwfdecParseDrawFunc parse_line; /* function to call to parse a line style */
76 gpointer data; /* data to pass to parse functions */
77 /* used while parsing */
78 GArray * fillstyles; /* SwfdecStyle objects */
79 GArray * linestyles; /* SwfdecStyle objects */
80 GArray * subpaths; /* SwfdecSubPath partial paths */
81 guint fill0style;
82 guint fill1style;
83 guint linestyle;
84 guint n_fill_bits;
85 guint n_line_bits;
86 /* for morph styles */
87 GArray * subpaths2; /* SwfdecSubPath partial paths */
88 guint fill0style2;
89 guint fill1style2;
90 guint linestyle2;
91 guint n_fill_bits2;
92 guint n_line_bits2;
95 static void
96 swfdec_shape_parser_new_styles (SwfdecShapeParser *parser, SwfdecBits *bits)
98 guint i, n_fill_styles, n_line_styles;
100 swfdec_bits_syncbits (bits);
101 if (parser->parse_fill) {
102 n_fill_styles = swfdec_bits_get_u8 (bits);
103 if (n_fill_styles == 0xff) {
104 n_fill_styles = swfdec_bits_get_u16 (bits);
106 SWFDEC_LOG (" n_fill_styles %d", n_fill_styles);
107 g_array_set_size (parser->fillstyles, n_fill_styles);
108 for (i = 0; i < n_fill_styles && swfdec_bits_left (bits); i++) {
109 g_array_index (parser->fillstyles, SwfdecStyle, i).draw =
110 parser->parse_fill (bits, parser->data);
113 n_line_styles = swfdec_bits_get_u8 (bits);
114 if (n_line_styles == 0xff) {
115 n_line_styles = swfdec_bits_get_u16 (bits);
117 SWFDEC_LOG (" n_line_styles %d", n_line_styles);
118 g_array_set_size (parser->linestyles, n_line_styles);
119 for (i = 0; i < n_line_styles && swfdec_bits_left (bits); i++) {
120 g_array_index (parser->linestyles, SwfdecStyle, i).draw =
121 parser->parse_line (bits, parser->data);
123 } else {
124 /* This is the magic part for DefineFont */
125 g_array_set_size (parser->fillstyles, 1);
126 g_array_index (parser->fillstyles, SwfdecStyle, 0).draw =
127 SWFDEC_DRAW (swfdec_pattern_new_color (0xFFFFFFFF));
129 parser->n_fill_bits = swfdec_bits_getbits (bits, 4);
130 parser->n_line_bits = swfdec_bits_getbits (bits, 4);
134 SwfdecShapeParser *
135 swfdec_shape_parser_new (SwfdecParseDrawFunc parse_fill,
136 SwfdecParseDrawFunc parse_line, gpointer data)
138 SwfdecShapeParser *list;
140 list = g_slice_new0 (SwfdecShapeParser);
141 list->parse_fill = parse_fill;
142 list->parse_line = parse_line;
143 list->data = data;
144 list->fillstyles = g_array_new (FALSE, TRUE, sizeof (SwfdecStyle));
145 list->linestyles = g_array_new (FALSE, TRUE, sizeof (SwfdecStyle));
146 list->subpaths = g_array_new (FALSE, TRUE, sizeof (SwfdecSubPath));
147 list->subpaths2 = g_array_new (FALSE, TRUE, sizeof (SwfdecSubPath));
149 return list;
152 static void
153 swfdec_shape_parser_clear_one (GArray *array)
155 guint i;
157 for (i = 0; i < array->len; i++) {
158 SwfdecStyle *style = &g_array_index (array, SwfdecStyle, i);
159 if (style->draw)
160 g_object_unref (style->draw);
161 g_slist_free (style->subpaths);
163 g_array_set_size (array, 0);
166 static void
167 swfdec_shape_parser_clear (SwfdecShapeParser *list)
169 guint i;
171 swfdec_shape_parser_clear_one (list->fillstyles);
172 swfdec_shape_parser_clear_one (list->linestyles);
174 for (i = 0; i < list->subpaths->len; i++) {
175 SwfdecSubPath *path = &g_array_index (list->subpaths, SwfdecSubPath, i);
176 swfdec_path_reset (&path->path);
178 g_array_set_size (list->subpaths, 0);
179 for (i = 0; i < list->subpaths2->len; i++) {
180 SwfdecSubPath *path = &g_array_index (list->subpaths2, SwfdecSubPath, i);
181 swfdec_path_reset (&path->path);
183 g_array_set_size (list->subpaths2, 0);
186 GSList *
187 swfdec_shape_parser_reset (SwfdecShapeParser *parser)
189 GSList *draws = parser->draws;
191 parser->draws = NULL;
192 return draws;
195 GSList *
196 swfdec_shape_parser_free (SwfdecShapeParser *parser)
198 GSList *draws = parser->draws;
200 swfdec_shape_parser_clear (parser);
201 g_array_free (parser->fillstyles, TRUE);
202 g_array_free (parser->linestyles, TRUE);
203 g_array_free (parser->subpaths, TRUE);
204 g_array_free (parser->subpaths2, TRUE);
205 g_slice_free (SwfdecShapeParser, parser);
207 draws = g_slist_reverse (draws);
208 return draws;
211 /* NB: assumes all fill paths are closed */
212 static void
213 swfdec_style_finish (SwfdecStyle *style, SwfdecSubPath *paths, SwfdecSubPath *paths2, gboolean line)
215 GSList *walk;
217 /* checked before calling this function */
218 g_assert (style->draw);
220 /* accumulate paths one by one */
221 while (style->subpaths) {
222 SwfdecSubPath *start, *last;
223 SwfdecSubPath *start2 = NULL, *last2 = NULL;
225 last = start = &paths[GPOINTER_TO_UINT (style->subpaths->data)];
226 swfdec_path_move_to (&style->draw->path, start->x_start, start->y_start);
227 swfdec_path_append (&style->draw->path, &start->path);
228 if (paths2) {
229 last2 = start2 = &paths2[GPOINTER_TO_UINT (style->subpaths->data)];
230 swfdec_path_move_to (&style->draw->end_path, start2->x_start, start2->y_start);
231 swfdec_path_append (&style->draw->end_path, &start2->path);
233 style->subpaths = g_slist_delete_link (style->subpaths, style->subpaths);
234 while (!swfdec_sub_path_match (last, start) ||
235 (paths2 != NULL && !swfdec_sub_path_match (last2, start2))) {
236 for (walk = style->subpaths; walk; walk = walk->next) {
237 SwfdecSubPath *cur = &paths[GPOINTER_TO_UINT (walk->data)];
238 if (swfdec_sub_path_match (last, cur)) {
239 if (paths2) {
240 SwfdecSubPath *cur2 = &paths2[GPOINTER_TO_UINT (walk->data)];
241 if (!swfdec_sub_path_match (last2, cur2))
242 continue;
243 swfdec_path_append (&style->draw->end_path, &cur2->path);
244 last2 = cur2;
246 swfdec_path_append (&style->draw->path, &cur->path);
247 last = cur;
248 break;
251 if (walk) {
252 style->subpaths = g_slist_delete_link (style->subpaths, walk);
253 } else {
254 if (!line) {
255 SWFDEC_ERROR ("fill path not closed");
257 break;
261 swfdec_draw_recompute (style->draw);
264 /* merge subpaths into draws, then reset */
265 static void
266 swfdec_shape_parser_finish (SwfdecShapeParser *parser)
268 guint i;
269 for (i = 0; i < parser->fillstyles->len; i++) {
270 SwfdecStyle *style = &g_array_index (parser->fillstyles, SwfdecStyle, i);
271 if (style->draw == NULL)
272 continue;
273 if (style->subpaths) {
274 swfdec_style_finish (style, (SwfdecSubPath *) (void *) parser->subpaths->data,
275 parser->subpaths2->len ? (SwfdecSubPath *) (void *) parser->subpaths2->data : NULL, FALSE);
276 parser->draws = g_slist_prepend (parser->draws, g_object_ref (style->draw));
277 } else {
278 SWFDEC_INFO ("fillstyle %u has no path", i);
281 for (i = 0; i < parser->linestyles->len; i++) {
282 SwfdecStyle *style = &g_array_index (parser->linestyles, SwfdecStyle, i);
283 if (style->draw == NULL)
284 continue;
285 if (style->subpaths) {
286 swfdec_style_finish (style, (SwfdecSubPath *) (void *) parser->subpaths->data,
287 parser->subpaths2->len ? (SwfdecSubPath *) (void *) parser->subpaths2->data : NULL, TRUE);
288 parser->draws = g_slist_prepend (parser->draws, g_object_ref (style->draw));
289 } else {
290 SWFDEC_WARNING ("linestyle %u has no path", i);
293 swfdec_shape_parser_clear (parser);
296 static void
297 swfdec_shape_parser_end_path (SwfdecShapeParser *parser, SwfdecSubPath *path1, SwfdecSubPath *path2,
298 int x1, int y1, int x2, int y2)
300 if (path1 == NULL)
301 return;
302 if (path1->path.num_data == 0) {
303 SWFDEC_INFO ("ignoring empty path");
304 return;
307 path1->x_end = x1;
308 path1->y_end = y1;
310 if (path2) {
311 path2->x_end = x2;
312 path2->y_end = y2;
313 /* check our assumptions about morph styles */
314 if ((parser->fill0style != parser->fill0style2 &&
315 parser->fill0style != parser->fill1style2) ||
316 (parser->fill1style != parser->fill0style2 &&
317 parser->fill1style != parser->fill1style2)) {
318 SWFDEC_ERROR ("fillstyle assumptions don't hold for %u %u vs %u %u",
319 parser->fill0style, parser->fill1style, parser->fill0style2,
320 parser->fill1style2);
321 return;
323 if (parser->linestyle != parser->linestyle2) {
324 SWFDEC_ERROR ("linestyle change from %u to %u", parser->linestyle,
325 parser->linestyle2);
326 return;
330 /* add the path to their styles */
331 if (parser->fill0style) {
332 if (parser->fill0style > parser->fillstyles->len) {
333 SWFDEC_ERROR ("fillstyle too big (%u > %u)", parser->fill0style,
334 parser->fillstyles->len);
335 } else {
336 SwfdecStyle *style = &g_array_index (parser->fillstyles,
337 SwfdecStyle, parser->fill0style - 1);
338 style->subpaths = g_slist_prepend (style->subpaths,
339 GUINT_TO_POINTER (parser->subpaths->len - 1));
342 if (parser->fill1style) {
343 if (parser->fill1style > parser->fillstyles->len) {
344 SWFDEC_ERROR ("fillstyle too big (%u > %u)", parser->fill1style,
345 parser->fillstyles->len);
346 } else {
347 SwfdecStyle *style = &g_array_index (parser->fillstyles,
348 SwfdecStyle, parser->fill1style - 1);
350 if (swfdec_sub_path_match (path1, path1) &&
351 (path2 == NULL || swfdec_sub_path_match (path2, path2))) {
352 style->subpaths = g_slist_prepend (style->subpaths,
353 GUINT_TO_POINTER (parser->subpaths->len - 1));
354 } else {
355 SwfdecSubPath reverse;
356 SWFDEC_LOG ("reversing path from %d %d to %d %d", path1->x_start, path1->y_start,
357 path1->x_end, path1->y_end);
358 reverse.x_start = path1->x_end;
359 reverse.y_start = path1->y_end;
360 reverse.x_end = path1->x_start;
361 reverse.y_end = path1->y_start;
362 swfdec_path_init (&reverse.path);
363 swfdec_path_append_reverse (&reverse.path, &path1->path, reverse.x_end, reverse.y_end);
364 style->subpaths = g_slist_prepend (style->subpaths,
365 GUINT_TO_POINTER (parser->subpaths->len));
366 g_array_append_val (parser->subpaths, reverse);
367 if (path2) {
368 reverse.x_start = path2->x_end;
369 reverse.y_start = path2->y_end;
370 reverse.x_end = path2->x_start;
371 reverse.y_end = path2->y_start;
372 swfdec_path_init (&reverse.path);
373 swfdec_path_append_reverse (&reverse.path, &path2->path, reverse.x_end, reverse.y_end);
374 g_array_append_val (parser->subpaths2, reverse);
379 if (parser->linestyle) {
380 if (parser->linestyle > parser->linestyles->len) {
381 SWFDEC_ERROR ("linestyle too big (%u > %u)", parser->linestyle,
382 parser->linestyles->len);
383 } else {
384 SwfdecStyle *style = &g_array_index (parser->linestyles,
385 SwfdecStyle, parser->linestyle - 1);
386 style->subpaths = g_slist_prepend (style->subpaths,
387 GUINT_TO_POINTER (parser->subpaths->len - 1));
392 static SwfdecSubPath *
393 swfdec_sub_path_create (GArray *array, int x, int y)
395 SwfdecSubPath *path;
397 g_array_set_size (array, array->len + 1);
398 path = &g_array_index (array, SwfdecSubPath, array->len - 1);
399 swfdec_path_init (&path->path);
400 path->x_start = x;
401 path->y_start = y;
403 return path;
406 static SwfdecSubPath *
407 swfdec_shape_parser_parse_change (SwfdecShapeParser *parser, SwfdecBits *bits, int *x, int *y)
409 int state_new_styles, state_line_styles, state_fill_styles1, state_fill_styles0, state_moveto;
410 SwfdecSubPath *path;
412 if (swfdec_bits_getbit (bits) != 0) {
413 g_assert_not_reached ();
416 state_new_styles = swfdec_bits_getbit (bits);
417 state_line_styles = swfdec_bits_getbit (bits);
418 state_fill_styles1 = swfdec_bits_getbit (bits);
419 state_fill_styles0 = swfdec_bits_getbit (bits);
420 state_moveto = swfdec_bits_getbit (bits);
422 if (state_moveto) {
423 int n_bits = swfdec_bits_getbits (bits, 5);
424 *x = swfdec_bits_getsbits (bits, n_bits);
425 *y = swfdec_bits_getsbits (bits, n_bits);
427 SWFDEC_LOG (" moveto %d,%d", *x, *y);
429 if (state_fill_styles0) {
430 parser->fill0style = swfdec_bits_getbits (bits, parser->n_fill_bits);
431 SWFDEC_LOG (" * fill0style = %d", parser->fill0style);
432 } else {
433 SWFDEC_LOG (" * not changing fill0style");
435 if (state_fill_styles1) {
436 parser->fill1style = swfdec_bits_getbits (bits, parser->n_fill_bits);
437 SWFDEC_LOG (" * fill1style = %d", parser->fill1style);
438 } else {
439 SWFDEC_LOG (" * not changing fill1style");
441 if (state_line_styles) {
442 parser->linestyle = swfdec_bits_getbits (bits, parser->n_line_bits);
443 SWFDEC_LOG (" * linestyle = %d", parser->linestyle);
444 } else {
445 SWFDEC_LOG (" * not changing linestyle");
447 if (state_new_styles) {
448 SWFDEC_LOG (" * new styles");
449 swfdec_shape_parser_finish (parser);
450 swfdec_shape_parser_new_styles (parser, bits);
452 path = swfdec_sub_path_create (parser->subpaths, *x, *y);
453 return path;
456 static void
457 swfdec_shape_parser_parse_curve (SwfdecBits *bits, SwfdecSubPath *path,
458 int *x, int *y)
460 int n_bits;
461 int cur_x, cur_y;
462 int control_x, control_y;
464 if (swfdec_bits_getbits (bits, 2) != 2) {
465 g_assert_not_reached ();
468 n_bits = swfdec_bits_getbits (bits, 4) + 2;
470 cur_x = *x;
471 cur_y = *y;
473 control_x = cur_x + swfdec_bits_getsbits (bits, n_bits);
474 control_y = cur_y + swfdec_bits_getsbits (bits, n_bits);
475 SWFDEC_LOG (" control %d,%d", control_x, control_y);
477 *x = control_x + swfdec_bits_getsbits (bits, n_bits);
478 *y = control_y + swfdec_bits_getsbits (bits, n_bits);
479 SWFDEC_LOG (" anchor %d,%d", *x, *y);
480 if (path) {
481 swfdec_path_curve_to (&path->path,
482 cur_x, cur_y,
483 control_x, control_y,
484 *x, *y);
485 } else {
486 SWFDEC_ERROR ("no path to curve in");
490 static void
491 swfdec_shape_parser_parse_line (SwfdecBits *bits, SwfdecSubPath *path,
492 int *x, int *y, gboolean add_as_curve)
494 int n_bits;
495 int general_line_flag;
496 int cur_x, cur_y;
498 if (swfdec_bits_getbits (bits, 2) != 3) {
499 g_assert_not_reached ();
502 cur_x = *x;
503 cur_y = *y;
504 n_bits = swfdec_bits_getbits (bits, 4) + 2;
505 general_line_flag = swfdec_bits_getbit (bits);
506 if (general_line_flag == 1) {
507 *x += swfdec_bits_getsbits (bits, n_bits);
508 *y += swfdec_bits_getsbits (bits, n_bits);
509 } else {
510 int vert_line_flag = swfdec_bits_getbit (bits);
511 if (vert_line_flag == 0) {
512 *x += swfdec_bits_getsbits (bits, n_bits);
513 } else {
514 *y += swfdec_bits_getsbits (bits, n_bits);
517 SWFDEC_LOG (" line to %d,%d", *x, *y);
518 if (path) {
519 if (add_as_curve)
520 swfdec_path_curve_to (&path->path, cur_x, cur_y,
521 (cur_x + *x) / 2, (cur_y + *y) / 2, *x, *y);
522 else
523 swfdec_path_line_to (&path->path, *x, *y);
524 } else {
525 SWFDEC_ERROR ("no path to line in");
529 void
530 swfdec_shape_parser_parse (SwfdecShapeParser *parser, SwfdecBits *bits)
532 int x = 0, y = 0;
533 SwfdecSubPath *path = NULL;
534 SwfdecShapeType type;
536 swfdec_shape_parser_new_styles (parser, bits);
538 while ((type = swfdec_shape_peek_type (bits))) {
539 switch (type) {
540 case SWFDEC_SHAPE_TYPE_CHANGE:
541 swfdec_shape_parser_end_path (parser, path, NULL, x, y, 0, 0);
542 path = swfdec_shape_parser_parse_change (parser, bits, &x, &y);
543 break;
544 case SWFDEC_SHAPE_TYPE_LINE:
545 swfdec_shape_parser_parse_line (bits, path, &x, &y, FALSE);
546 break;
547 case SWFDEC_SHAPE_TYPE_CURVE:
548 swfdec_shape_parser_parse_curve (bits, path, &x, &y);
549 break;
550 case SWFDEC_SHAPE_TYPE_END:
551 default:
552 g_assert_not_reached ();
553 break;
556 swfdec_shape_parser_end_path (parser, path, NULL, x, y, 0, 0);
557 swfdec_bits_getbits (bits, 6);
558 swfdec_bits_syncbits (bits);
560 swfdec_shape_parser_finish (parser);
563 static SwfdecSubPath *
564 swfdec_shape_parser_parse_morph_change (SwfdecShapeParser *parser,
565 SwfdecBits *bits, int *x, int *y)
567 SwfdecSubPath *path;
568 int state_line_styles, state_fill_styles1, state_fill_styles0, state_moveto;
570 if (swfdec_bits_getbit (bits) != 0) {
571 g_assert_not_reached ();
573 if (swfdec_bits_getbit (bits)) {
574 SWFDEC_ERROR ("new styles aren't allowed in end edges, ignoring");
576 state_line_styles = swfdec_bits_getbit (bits);
577 state_fill_styles1 = swfdec_bits_getbit (bits);
578 state_fill_styles0 = swfdec_bits_getbit (bits);
579 state_moveto = swfdec_bits_getbit (bits);
580 if (state_moveto) {
581 int n_bits = swfdec_bits_getbits (bits, 5);
582 *x = swfdec_bits_getsbits (bits, n_bits);
583 *y = swfdec_bits_getsbits (bits, n_bits);
585 SWFDEC_LOG (" moveto %d,%d", *x, *y);
587 path = swfdec_sub_path_create (parser->subpaths2, *x, *y);
588 if (state_fill_styles0) {
589 parser->fill0style2 = swfdec_bits_getbits (bits, parser->n_fill_bits2);
591 if (state_fill_styles1) {
592 parser->fill1style2 = swfdec_bits_getbits (bits, parser->n_fill_bits2);
594 if (state_line_styles) {
595 parser->linestyle2 = swfdec_bits_getbits (bits, parser->n_line_bits2);
598 return path;
601 void
602 swfdec_shape_parser_parse_morph (SwfdecShapeParser *parser, SwfdecBits *bits1, SwfdecBits *bits2)
604 int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
605 SwfdecSubPath *path1 = NULL, *path2 = NULL;
606 SwfdecShapeType type1, type2;
608 swfdec_shape_parser_new_styles (parser, bits1);
609 parser->n_fill_bits2 = swfdec_bits_getbits (bits2, 4);
610 parser->n_line_bits2 = swfdec_bits_getbits (bits2, 4);
611 parser->fill0style2 = parser->fill0style;
612 parser->fill1style2 = parser->fill1style;
613 parser->linestyle2 = parser->linestyle;
614 SWFDEC_LOG ("%u fill bits, %u line bits in end shape", parser->n_fill_bits2, parser->n_line_bits2);
616 while ((type1 = swfdec_shape_peek_type (bits1))) {
617 type2 = swfdec_shape_peek_type (bits2);
618 if (type2 == SWFDEC_SHAPE_TYPE_CHANGE || type1 == SWFDEC_SHAPE_TYPE_CHANGE) {
619 swfdec_shape_parser_end_path (parser, path1, path2, x1, y1, x2, y2);
620 if (type1 == SWFDEC_SHAPE_TYPE_CHANGE) {
621 path1 = swfdec_shape_parser_parse_change (parser, bits1, &x1, &y1);
622 parser->fill0style2 = parser->fill0style;
623 parser->fill1style2 = parser->fill1style;
624 parser->linestyle2 = parser->linestyle;
625 } else {
626 path1 = swfdec_sub_path_create (parser->subpaths, x1, y1);
628 if (type2 == SWFDEC_SHAPE_TYPE_CHANGE) {
629 path2 = swfdec_shape_parser_parse_morph_change (parser, bits2, &x2, &y2);
630 } else {
631 path2 = swfdec_sub_path_create (parser->subpaths2, x2, y2);
633 continue;
635 switch (type2) {
636 case SWFDEC_SHAPE_TYPE_LINE:
637 swfdec_shape_parser_parse_line (bits2, path2, &x2, &y2, type1 != SWFDEC_SHAPE_TYPE_LINE);
638 break;
639 case SWFDEC_SHAPE_TYPE_CURVE:
640 swfdec_shape_parser_parse_curve (bits2, path2, &x2, &y2);
641 break;
642 case SWFDEC_SHAPE_TYPE_END:
643 SWFDEC_ERROR ("morph shape ends too early, aborting");
644 goto out;
645 case SWFDEC_SHAPE_TYPE_CHANGE:
646 default:
647 g_assert_not_reached ();
648 break;
650 switch (type1) {
651 case SWFDEC_SHAPE_TYPE_LINE:
652 swfdec_shape_parser_parse_line (bits1, path1, &x1, &y1, type2 != SWFDEC_SHAPE_TYPE_LINE);
653 break;
654 case SWFDEC_SHAPE_TYPE_CURVE:
655 swfdec_shape_parser_parse_curve (bits1, path1, &x1, &y1);
656 break;
657 case SWFDEC_SHAPE_TYPE_CHANGE:
658 case SWFDEC_SHAPE_TYPE_END:
659 default:
660 g_assert_not_reached ();
661 break;
664 out:
665 swfdec_shape_parser_end_path (parser, path1, path2, x1, y1, x2, y2);
666 swfdec_bits_getbits (bits1, 6);
667 swfdec_bits_syncbits (bits1);
668 if (swfdec_bits_getbits (bits2, 6) != 0) {
669 SWFDEC_ERROR ("end shapes are not finished when start shapes are");
671 swfdec_bits_syncbits (bits2);
673 swfdec_shape_parser_finish (parser);