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.
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
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"
38 G_DEFINE_ABSTRACT_TYPE (SwfdecPattern
, swfdec_pattern
, SWFDEC_TYPE_DRAW
);
41 swfdec_pattern_compute_extents (SwfdecDraw
*draw
)
43 swfdec_path_get_extents (&draw
->path
, &draw
->extents
);
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
);
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
);
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
);
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
);
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
;
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
);
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);
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
;
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
);
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
);
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
);
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
;
238 swfdec_image_pattern_init (SwfdecImagePattern
*pattern
)
242 /*** EXPORTED API ***/
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
);
256 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= swfdec_bits_get_rgba (bits
);
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)) {
271 gradient
->extend
= CAIRO_EXTEND_PAD
;
274 gradient
->extend
= CAIRO_EXTEND_REFLECT
;
277 gradient
->extend
= CAIRO_EXTEND_REPEAT
;
280 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
281 gradient
->extend
= CAIRO_EXTEND_PAD
;
284 g_assert_not_reached ();
286 interpolation
= swfdec_bits_getbits (bits
, 2);
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
);
294 gradient
->gradient
[i
].color
= swfdec_bits_get_rgba (bits
);
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
;
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
);
324 if (paint_style_type
== 0x40 || paint_style_type
== 0x42) {
325 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_REPEAT
;
328 /* not implemented yet in cairo */
329 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_PAD
;
331 SWFDEC_FIXME ("CAIRO_EXTEND_PAD is not yet implemented");
332 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_NONE
;
335 if (paint_style_type
== 0x40 || paint_style_type
== 0x41) {
336 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_BILINEAR
;
338 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_NEAREST
;
342 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type
);
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
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
);
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
389 * Returns: a new #SwfdecPattern or NULL on error
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)) {
418 gradient
->extend
= CAIRO_EXTEND_PAD
;
421 gradient
->extend
= CAIRO_EXTEND_REFLECT
;
424 gradient
->extend
= CAIRO_EXTEND_REPEAT
;
427 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
428 gradient
->extend
= CAIRO_EXTEND_PAD
;
431 g_assert_not_reached ();
433 interpolation
= swfdec_bits_getbits (bits
, 2);
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
);
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
);
470 if (paint_style_type
== 0x40 || paint_style_type
== 0x42) {
471 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_REPEAT
;
474 /* not implemented yet in cairo */
475 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_PAD
;
477 SWFDEC_FIXME ("CAIRO_EXTEND_PAD is not yet implemented");
478 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_NONE
;
481 if (paint_style_type
== 0x40 || paint_style_type
== 0x41) {
482 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_BILINEAR
;
484 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_NEAREST
;
488 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type
);
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
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
;
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
);
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
);
543 return g_strdup_printf ("%s", G_OBJECT_TYPE_NAME (pattern
));
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
);