add swfdec_gradient_pattern_new()
[swfdec.git] / libswfdec / swfdec_pattern.c
blobd64155635ec2f7ae8cf2c8bff8cae2c2aef99338
1 /* Swfdec
2 * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <math.h>
26 #include "swfdec_pattern.h"
27 #include "swfdec_bits.h"
28 #include "swfdec_color.h"
29 #include "swfdec_debug.h"
30 #include "swfdec_decoder.h"
31 #include "swfdec_gradient_pattern.h"
32 #include "swfdec_image.h"
33 #include "swfdec_path.h"
34 #include "swfdec_stroke.h"
36 /*** PATTERN ***/
38 G_DEFINE_ABSTRACT_TYPE (SwfdecPattern, swfdec_pattern, SWFDEC_TYPE_DRAW);
40 static void
41 swfdec_pattern_compute_extents (SwfdecDraw *draw)
43 swfdec_path_get_extents (&draw->path, &draw->extents);
46 static void
47 swfdec_pattern_paint (SwfdecDraw *draw, cairo_t *cr, const SwfdecColorTransform *trans)
49 cairo_pattern_t *pattern;
51 pattern = swfdec_pattern_get_pattern (SWFDEC_PATTERN (draw), trans);
52 if (pattern == NULL)
53 return;
54 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
55 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
56 cairo_append_path (cr, &draw->path);
57 cairo_set_source (cr, pattern);
58 cairo_pattern_destroy (pattern);
59 cairo_fill (cr);
62 static void
63 swfdec_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio)
65 SwfdecPattern *dpattern = SWFDEC_PATTERN (dest);
66 SwfdecPattern *spattern = SWFDEC_PATTERN (source);
68 swfdec_matrix_morph (&dpattern->start_transform,
69 &spattern->start_transform, &spattern->end_transform, ratio);
70 dpattern->transform = dpattern->start_transform;
71 if (cairo_matrix_invert (&dpattern->transform)) {
72 SWFDEC_ERROR ("morphed paint transform matrix not invertible, using default");
73 dpattern->transform = spattern->transform;
76 SWFDEC_DRAW_CLASS (swfdec_pattern_parent_class)->morph (dest, source, ratio);
79 static gboolean
80 swfdec_pattern_contains (SwfdecDraw *draw, cairo_t *cr, double x, double y)
82 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
83 cairo_append_path (cr, &draw->path);
84 return cairo_in_fill (cr, x, y);
87 static void
88 swfdec_pattern_class_init (SwfdecPatternClass *klass)
90 SwfdecDrawClass *draw_class = SWFDEC_DRAW_CLASS (klass);
92 draw_class->morph = swfdec_pattern_morph;
93 draw_class->paint = swfdec_pattern_paint;
94 draw_class->compute_extents = swfdec_pattern_compute_extents;
95 draw_class->contains = swfdec_pattern_contains;
98 static void
99 swfdec_pattern_init (SwfdecPattern *pattern)
101 cairo_matrix_init_identity (&pattern->transform);
102 cairo_matrix_init_identity (&pattern->start_transform);
103 cairo_matrix_init_identity (&pattern->end_transform);
106 /*** COLOR PATTERN ***/
108 typedef struct _SwfdecColorPattern SwfdecColorPattern;
109 typedef struct _SwfdecColorPatternClass SwfdecColorPatternClass;
111 #define SWFDEC_TYPE_COLOR_PATTERN (swfdec_color_pattern_get_type())
112 #define SWFDEC_IS_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_COLOR_PATTERN))
113 #define SWFDEC_IS_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_COLOR_PATTERN))
114 #define SWFDEC_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPattern))
115 #define SWFDEC_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))
116 #define SWFDEC_COLOR_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))
118 struct _SwfdecColorPattern
120 SwfdecPattern pattern;
122 SwfdecColor start_color; /* color to paint with at the beginning */
123 SwfdecColor end_color; /* color to paint with in the end */
126 struct _SwfdecColorPatternClass
128 SwfdecPatternClass pattern_class;
131 GType swfdec_color_pattern_get_type (void);
132 G_DEFINE_TYPE (SwfdecColorPattern, swfdec_color_pattern, SWFDEC_TYPE_PATTERN);
134 static void
135 swfdec_color_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio)
137 SwfdecColorPattern *dpattern = SWFDEC_COLOR_PATTERN (dest);
138 SwfdecColorPattern *spattern = SWFDEC_COLOR_PATTERN (source);
140 dpattern->start_color = swfdec_color_apply_morph (spattern->start_color, spattern->end_color, ratio);
142 SWFDEC_DRAW_CLASS (swfdec_color_pattern_parent_class)->morph (dest, source, ratio);
145 static cairo_pattern_t *
146 swfdec_color_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans)
148 SwfdecColor color = SWFDEC_COLOR_PATTERN (pat)->start_color;
150 color = swfdec_color_apply_transform (color, trans);
151 return cairo_pattern_create_rgba (
152 SWFDEC_COLOR_R (color) / 255.0, SWFDEC_COLOR_G (color) / 255.0,
153 SWFDEC_COLOR_B (color) / 255.0, SWFDEC_COLOR_A (color) / 255.0);
156 static void
157 swfdec_color_pattern_class_init (SwfdecColorPatternClass *klass)
159 SWFDEC_DRAW_CLASS (klass)->morph = swfdec_color_pattern_morph;
161 SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_color_pattern_get_pattern;
164 static void
165 swfdec_color_pattern_init (SwfdecColorPattern *pattern)
169 /*** IMAGE PATTERN ***/
171 typedef struct _SwfdecImagePattern SwfdecImagePattern;
172 typedef struct _SwfdecImagePatternClass SwfdecImagePatternClass;
174 #define SWFDEC_TYPE_IMAGE_PATTERN (swfdec_image_pattern_get_type())
175 #define SWFDEC_IS_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_IMAGE_PATTERN))
176 #define SWFDEC_IS_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_IMAGE_PATTERN))
177 #define SWFDEC_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePattern))
178 #define SWFDEC_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))
179 #define SWFDEC_IMAGE_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))
181 struct _SwfdecImagePattern
183 SwfdecPattern pattern;
185 SwfdecImage * image; /* image to paint */
186 cairo_extend_t extend;
187 cairo_filter_t filter;
190 struct _SwfdecImagePatternClass
192 SwfdecPatternClass pattern_class;
195 GType swfdec_image_pattern_get_type (void);
196 G_DEFINE_TYPE (SwfdecImagePattern, swfdec_image_pattern, SWFDEC_TYPE_PATTERN);
198 static void
199 swfdec_image_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio)
201 SwfdecImagePattern *dpattern = SWFDEC_IMAGE_PATTERN (dest);
202 SwfdecImagePattern *spattern = SWFDEC_IMAGE_PATTERN (source);
204 dpattern->image = g_object_ref (spattern->image);
205 dpattern->extend = spattern->extend;
206 dpattern->filter = spattern->filter;
208 SWFDEC_DRAW_CLASS (swfdec_image_pattern_parent_class)->morph (dest, source, ratio);
211 static cairo_pattern_t *
212 swfdec_image_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans)
214 SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pat);
215 cairo_pattern_t *pattern;
216 cairo_surface_t *surface;
218 surface = swfdec_image_create_surface_transformed (image->image, trans);
219 if (surface == NULL)
220 return NULL;
221 pattern = cairo_pattern_create_for_surface (surface);
222 cairo_surface_destroy (surface);
223 cairo_pattern_set_matrix (pattern, &pat->transform);
224 cairo_pattern_set_extend (pattern, image->extend);
225 cairo_pattern_set_filter (pattern, image->filter);
226 return pattern;
229 static void
230 swfdec_image_pattern_class_init (SwfdecImagePatternClass *klass)
232 SWFDEC_DRAW_CLASS (klass)->morph = swfdec_image_pattern_morph;
234 SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_image_pattern_get_pattern;
237 static void
238 swfdec_image_pattern_init (SwfdecImagePattern *pattern)
242 /*** EXPORTED API ***/
244 static SwfdecDraw *
245 swfdec_pattern_do_parse (SwfdecBits *bits, SwfdecSwfDecoder *dec, gboolean rgba)
247 guint paint_style_type;
248 SwfdecPattern *pattern;
250 paint_style_type = swfdec_bits_get_u8 (bits);
251 SWFDEC_LOG (" type 0x%02x", paint_style_type);
253 if (paint_style_type == 0x00) {
254 pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
255 if (rgba) {
256 SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_rgba (bits);
257 } else {
258 SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_color (bits);
260 SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
261 SWFDEC_LOG (" color %08x", SWFDEC_COLOR_PATTERN (pattern)->start_color);
262 } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) {
263 SwfdecGradientPattern *gradient;
264 guint i, interpolation;
265 pattern = SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
266 gradient = SWFDEC_GRADIENT_PATTERN (pattern);
267 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
268 pattern->end_transform = pattern->start_transform;
269 switch (swfdec_bits_getbits (bits, 2)) {
270 case 0:
271 gradient->extend = CAIRO_EXTEND_PAD;
272 break;
273 case 1:
274 gradient->extend = CAIRO_EXTEND_REFLECT;
275 break;
276 case 2:
277 gradient->extend = CAIRO_EXTEND_REPEAT;
278 break;
279 case 3:
280 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
281 gradient->extend = CAIRO_EXTEND_PAD;
282 break;
283 default:
284 g_assert_not_reached ();
286 interpolation = swfdec_bits_getbits (bits, 2);
287 if (interpolation) {
288 SWFDEC_FIXME ("only normal interpolation is implemented, mode %u is not", interpolation);
290 gradient->n_gradients = swfdec_bits_getbits (bits, 4);
291 for (i = 0; i < gradient->n_gradients; i++) {
292 gradient->gradient[i].ratio = swfdec_bits_get_u8 (bits);
293 if (rgba)
294 gradient->gradient[i].color = swfdec_bits_get_rgba (bits);
295 else
296 gradient->gradient[i].color = swfdec_bits_get_color (bits);
298 gradient->radial = (paint_style_type != 0x10);
299 /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */
300 if (paint_style_type == 0x13) {
301 gradient->focus = swfdec_bits_get_s16 (bits) / 256.0;
303 } else if (paint_style_type >= 0x40 && paint_style_type <= 0x43) {
304 guint paint_id = swfdec_bits_get_u16 (bits);
305 SWFDEC_LOG (" background paint id = %d (type 0x%02x)",
306 paint_id, paint_style_type);
307 if (paint_id == 65535) {
308 /* FIXME: someone explain this magic paint id here */
309 pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
310 SWFDEC_COLOR_PATTERN (pattern)->start_color = SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
311 SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
312 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
313 pattern->end_transform = pattern->start_transform;
314 } else {
315 pattern = g_object_new (SWFDEC_TYPE_IMAGE_PATTERN, NULL);
316 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
317 pattern->end_transform = pattern->start_transform;
318 SWFDEC_IMAGE_PATTERN (pattern)->image = swfdec_swf_decoder_get_character (dec, paint_id);
319 if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern)->image)) {
320 g_object_unref (pattern);
321 SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id);
322 return NULL;
324 if (paint_style_type == 0x40 || paint_style_type == 0x42) {
325 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_REPEAT;
326 } else {
327 #if 0
328 /* not implemented yet in cairo */
329 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_PAD;
330 #else
331 SWFDEC_FIXME ("CAIRO_EXTEND_PAD is not yet implemented");
332 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_NONE;
333 #endif
335 if (paint_style_type == 0x40 || paint_style_type == 0x41) {
336 SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_BILINEAR;
337 } else {
338 SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_NEAREST;
341 } else {
342 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type);
343 return NULL;
345 pattern->transform = pattern->start_transform;
346 if (cairo_matrix_invert (&pattern->transform)) {
347 SWFDEC_ERROR ("paint transform matrix not invertible, resetting");
348 cairo_matrix_init_identity (&pattern->transform);
350 swfdec_bits_syncbits (bits);
351 return SWFDEC_DRAW (pattern);
355 * swfdec_pattern_parse:
356 * @bits: the bits to parse from
357 * @dec: a #SwfdecDecoder to take context from
358 * @rgba: TRUE if colors are RGBA, FALSE if they're just RGB
360 * Continues parsing @dec into a new #SwfdecPattern
362 * Returns: a new #SwfdecPattern or NULL on error
364 SwfdecDraw *
365 swfdec_pattern_parse (SwfdecBits *bits, SwfdecSwfDecoder *dec)
367 g_return_val_if_fail (bits != NULL, NULL);
368 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);
370 return swfdec_pattern_do_parse (bits, dec, FALSE);
373 SwfdecDraw *
374 swfdec_pattern_parse_rgba (SwfdecBits *bits, SwfdecSwfDecoder *dec)
376 g_return_val_if_fail (bits != NULL, NULL);
377 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);
379 return swfdec_pattern_do_parse (bits, dec, TRUE);
383 * swfdec_pattern_parse_morph:
384 * @dec: a #SwfdecDecoder to parse from
386 * Continues parsing @dec into a new #SwfdecPattern. This function is used by
387 * morph shapes.
389 * Returns: a new #SwfdecPattern or NULL on error
391 SwfdecDraw *
392 swfdec_pattern_parse_morph (SwfdecBits *bits, SwfdecSwfDecoder *dec)
394 guint paint_style_type;
395 SwfdecPattern *pattern;
397 g_return_val_if_fail (bits != NULL, NULL);
398 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);
400 paint_style_type = swfdec_bits_get_u8 (bits);
401 SWFDEC_LOG (" type 0x%02x", paint_style_type);
403 if (paint_style_type == 0x00) {
404 pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
405 SWFDEC_COLOR_PATTERN (pattern)->start_color = swfdec_bits_get_rgba (bits);
406 SWFDEC_COLOR_PATTERN (pattern)->end_color = swfdec_bits_get_rgba (bits);
407 SWFDEC_LOG (" color %08x => %08x", SWFDEC_COLOR_PATTERN (pattern)->start_color,
408 SWFDEC_COLOR_PATTERN (pattern)->end_color);
409 } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) {
410 SwfdecGradientPattern *gradient;
411 guint i, interpolation;
412 pattern = SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
413 gradient = SWFDEC_GRADIENT_PATTERN (pattern);
414 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
415 swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL);
416 switch (swfdec_bits_getbits (bits, 2)) {
417 case 0:
418 gradient->extend = CAIRO_EXTEND_PAD;
419 break;
420 case 1:
421 gradient->extend = CAIRO_EXTEND_REFLECT;
422 break;
423 case 2:
424 gradient->extend = CAIRO_EXTEND_REPEAT;
425 break;
426 case 3:
427 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
428 gradient->extend = CAIRO_EXTEND_PAD;
429 break;
430 default:
431 g_assert_not_reached ();
433 interpolation = swfdec_bits_getbits (bits, 2);
434 if (interpolation) {
435 SWFDEC_FIXME ("only normal interpolation is implemented, mode %u is not", interpolation);
437 gradient->n_gradients = swfdec_bits_getbits (bits, 4);
438 for (i = 0; i < gradient->n_gradients; i++) {
439 gradient->gradient[i].ratio = swfdec_bits_get_u8 (bits);
440 gradient->gradient[i].color = swfdec_bits_get_rgba (bits);
441 gradient->end_gradient[i].ratio = swfdec_bits_get_u8 (bits);
442 gradient->end_gradient[i].color = swfdec_bits_get_rgba (bits);
444 gradient->radial = (paint_style_type != 0x10);
445 /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */
446 if (paint_style_type == 0x13) {
447 gradient->focus = swfdec_bits_get_s16 (bits) / 256.0;
449 } else if (paint_style_type >= 0x40 && paint_style_type <= 0x43) {
450 guint paint_id = swfdec_bits_get_u16 (bits);
451 SWFDEC_LOG (" background paint id = %d (type 0x%02x)",
452 paint_id, paint_style_type);
453 if (paint_id == 65535) {
454 /* FIXME: someone explain this magic paint id here */
455 pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
456 SWFDEC_COLOR_PATTERN (pattern)->start_color = SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
457 SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
458 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
459 swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL);
460 } else {
461 pattern = g_object_new (SWFDEC_TYPE_IMAGE_PATTERN, NULL);
462 swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
463 swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL);
464 SWFDEC_IMAGE_PATTERN (pattern)->image = swfdec_swf_decoder_get_character (dec, paint_id);
465 if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern)->image)) {
466 g_object_unref (pattern);
467 SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id);
468 return NULL;
470 if (paint_style_type == 0x40 || paint_style_type == 0x42) {
471 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_REPEAT;
472 } else {
473 #if 0
474 /* not implemented yet in cairo */
475 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_PAD;
476 #else
477 SWFDEC_FIXME ("CAIRO_EXTEND_PAD is not yet implemented");
478 SWFDEC_IMAGE_PATTERN (pattern)->extend = CAIRO_EXTEND_NONE;
479 #endif
481 if (paint_style_type == 0x40 || paint_style_type == 0x41) {
482 SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_BILINEAR;
483 } else {
484 SWFDEC_IMAGE_PATTERN (pattern)->filter = CAIRO_FILTER_NEAREST;
487 } else {
488 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type);
489 return NULL;
491 pattern->transform = pattern->start_transform;
492 if (cairo_matrix_invert (&pattern->transform)) {
493 SWFDEC_ERROR ("paint transform matrix not invertible, resetting");
494 cairo_matrix_init_identity (&pattern->transform);
496 swfdec_bits_syncbits (bits);
497 return SWFDEC_DRAW (pattern);
501 * swfdec_pattern_new_color:
502 * @color: color to paint in
504 * Creates a new pattern to paint with the given color
506 * Returns: a new @SwfdecPattern to paint with
508 SwfdecPattern *
509 swfdec_pattern_new_color (SwfdecColor color)
511 SwfdecPattern *pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
513 SWFDEC_COLOR_PATTERN (pattern)->start_color = color;
514 SWFDEC_COLOR_PATTERN (pattern)->end_color = color;
516 return pattern;
519 char *
520 swfdec_pattern_to_string (SwfdecPattern *pattern)
522 g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern), NULL);
524 if (SWFDEC_IS_IMAGE_PATTERN (pattern)) {
525 SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pattern);
526 if (image->image->width == 0)
527 cairo_surface_destroy (swfdec_image_create_surface (image->image));
528 return g_strdup_printf ("%ux%u image %u (%s, %s)", image->image->width,
529 image->image->height, SWFDEC_CHARACTER (image->image)->id,
530 image->extend == CAIRO_EXTEND_REPEAT ? "repeat" : "no repeat",
531 image->filter == CAIRO_FILTER_BILINEAR ? "bilinear" : "nearest");
532 } else if (SWFDEC_IS_COLOR_PATTERN (pattern)) {
533 if (SWFDEC_COLOR_PATTERN (pattern)->start_color == SWFDEC_COLOR_PATTERN (pattern)->end_color)
534 return g_strdup_printf ("color #%08X", SWFDEC_COLOR_PATTERN (pattern)->start_color);
535 else
536 return g_strdup_printf ("color #%08X => #%08X", SWFDEC_COLOR_PATTERN (pattern)->start_color,
537 SWFDEC_COLOR_PATTERN (pattern)->end_color);
538 } else if (SWFDEC_IS_GRADIENT_PATTERN (pattern)) {
539 SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pattern);
540 return g_strdup_printf ("%s gradient (%u colors)", gradient->radial ? "radial" : "linear",
541 gradient->n_gradients);
542 } else {
543 return g_strdup_printf ("%s", G_OBJECT_TYPE_NAME (pattern));
547 cairo_pattern_t *
548 swfdec_pattern_get_pattern (SwfdecPattern *pattern, const SwfdecColorTransform *trans)
550 SwfdecPatternClass *klass;
552 g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern), NULL);
553 g_return_val_if_fail (trans != NULL, NULL);
555 klass = SWFDEC_PATTERN_GET_CLASS (pattern);
556 g_assert (klass->get_pattern);
557 return klass->get_pattern (pattern, trans);