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_renderer_internal.h"
35 #include "swfdec_stroke.h"
39 G_DEFINE_ABSTRACT_TYPE (SwfdecPattern
, swfdec_pattern
, SWFDEC_TYPE_DRAW
);
42 swfdec_pattern_compute_extents (SwfdecDraw
*draw
)
44 swfdec_path_get_extents (&draw
->path
, &draw
->extents
);
48 swfdec_pattern_paint (SwfdecDraw
*draw
, cairo_t
*cr
, const SwfdecColorTransform
*trans
)
50 cairo_pattern_t
*pattern
;
52 pattern
= swfdec_pattern_get_pattern (SWFDEC_PATTERN (draw
), swfdec_renderer_get (cr
),
56 cairo_set_operator (cr
, CAIRO_OPERATOR_OVER
);
57 cairo_set_fill_rule (cr
, CAIRO_FILL_RULE_EVEN_ODD
);
58 cairo_append_path (cr
, &draw
->path
);
59 cairo_set_source (cr
, pattern
);
60 cairo_pattern_destroy (pattern
);
65 swfdec_pattern_morph (SwfdecDraw
*dest
, SwfdecDraw
*source
, guint ratio
)
67 SwfdecPattern
*dpattern
= SWFDEC_PATTERN (dest
);
68 SwfdecPattern
*spattern
= SWFDEC_PATTERN (source
);
70 swfdec_matrix_morph (&dpattern
->start_transform
,
71 &spattern
->start_transform
, &spattern
->end_transform
, ratio
);
72 dpattern
->end_transform
= dpattern
->start_transform
;
73 dpattern
->transform
= dpattern
->start_transform
;
74 if (cairo_matrix_invert (&dpattern
->transform
)) {
75 SWFDEC_ERROR ("morphed paint transform matrix not invertible, using default");
76 dpattern
->transform
= spattern
->transform
;
79 SWFDEC_DRAW_CLASS (swfdec_pattern_parent_class
)->morph (dest
, source
, ratio
);
83 swfdec_pattern_contains (SwfdecDraw
*draw
, cairo_t
*cr
, double x
, double y
)
85 cairo_set_fill_rule (cr
, CAIRO_FILL_RULE_EVEN_ODD
);
86 cairo_append_path (cr
, &draw
->path
);
87 return cairo_in_fill (cr
, x
, y
);
91 swfdec_pattern_class_init (SwfdecPatternClass
*klass
)
93 SwfdecDrawClass
*draw_class
= SWFDEC_DRAW_CLASS (klass
);
95 draw_class
->morph
= swfdec_pattern_morph
;
96 draw_class
->paint
= swfdec_pattern_paint
;
97 draw_class
->compute_extents
= swfdec_pattern_compute_extents
;
98 draw_class
->contains
= swfdec_pattern_contains
;
102 swfdec_pattern_init (SwfdecPattern
*pattern
)
104 cairo_matrix_init_identity (&pattern
->transform
);
105 cairo_matrix_init_identity (&pattern
->start_transform
);
106 cairo_matrix_init_identity (&pattern
->end_transform
);
109 /*** COLOR PATTERN ***/
111 typedef struct _SwfdecColorPattern SwfdecColorPattern
;
112 typedef struct _SwfdecColorPatternClass SwfdecColorPatternClass
;
114 #define SWFDEC_TYPE_COLOR_PATTERN (swfdec_color_pattern_get_type())
115 #define SWFDEC_IS_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_COLOR_PATTERN))
116 #define SWFDEC_IS_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_COLOR_PATTERN))
117 #define SWFDEC_COLOR_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPattern))
118 #define SWFDEC_COLOR_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))
119 #define SWFDEC_COLOR_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_COLOR_PATTERN, SwfdecColorPatternClass))
121 struct _SwfdecColorPattern
123 SwfdecPattern pattern
;
125 SwfdecColor start_color
; /* color to paint with at the beginning */
126 SwfdecColor end_color
; /* color to paint with in the end */
129 struct _SwfdecColorPatternClass
131 SwfdecPatternClass pattern_class
;
134 GType
swfdec_color_pattern_get_type (void);
135 G_DEFINE_TYPE (SwfdecColorPattern
, swfdec_color_pattern
, SWFDEC_TYPE_PATTERN
);
138 swfdec_color_pattern_morph (SwfdecDraw
*dest
, SwfdecDraw
*source
, guint ratio
)
140 SwfdecColorPattern
*dpattern
= SWFDEC_COLOR_PATTERN (dest
);
141 SwfdecColorPattern
*spattern
= SWFDEC_COLOR_PATTERN (source
);
143 dpattern
->start_color
= swfdec_color_apply_morph (spattern
->start_color
, spattern
->end_color
, ratio
);
144 dpattern
->end_color
= dpattern
->start_color
;
146 SWFDEC_DRAW_CLASS (swfdec_color_pattern_parent_class
)->morph (dest
, source
, ratio
);
149 static cairo_pattern_t
*
150 swfdec_color_pattern_get_pattern (SwfdecPattern
*pat
, SwfdecRenderer
*renderer
,
151 const SwfdecColorTransform
*trans
)
153 SwfdecColor color
= SWFDEC_COLOR_PATTERN (pat
)->start_color
;
155 color
= swfdec_color_apply_transform (color
, trans
);
156 return cairo_pattern_create_rgba (
157 SWFDEC_COLOR_RED (color
) / 255.0, SWFDEC_COLOR_GREEN (color
) / 255.0,
158 SWFDEC_COLOR_BLUE (color
) / 255.0, SWFDEC_COLOR_ALPHA (color
) / 255.0);
162 swfdec_color_pattern_class_init (SwfdecColorPatternClass
*klass
)
164 SWFDEC_DRAW_CLASS (klass
)->morph
= swfdec_color_pattern_morph
;
166 SWFDEC_PATTERN_CLASS (klass
)->get_pattern
= swfdec_color_pattern_get_pattern
;
170 swfdec_color_pattern_init (SwfdecColorPattern
*pattern
)
174 /*** IMAGE PATTERN ***/
176 typedef struct _SwfdecImagePattern SwfdecImagePattern
;
177 typedef struct _SwfdecImagePatternClass SwfdecImagePatternClass
;
179 #define SWFDEC_TYPE_IMAGE_PATTERN (swfdec_image_pattern_get_type())
180 #define SWFDEC_IS_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_IMAGE_PATTERN))
181 #define SWFDEC_IS_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_IMAGE_PATTERN))
182 #define SWFDEC_IMAGE_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePattern))
183 #define SWFDEC_IMAGE_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))
184 #define SWFDEC_IMAGE_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_IMAGE_PATTERN, SwfdecImagePatternClass))
186 struct _SwfdecImagePattern
188 SwfdecPattern pattern
;
190 SwfdecImage
* image
; /* image to paint */
191 cairo_extend_t extend
;
192 cairo_filter_t filter
;
195 struct _SwfdecImagePatternClass
197 SwfdecPatternClass pattern_class
;
200 GType
swfdec_image_pattern_get_type (void);
201 G_DEFINE_TYPE (SwfdecImagePattern
, swfdec_image_pattern
, SWFDEC_TYPE_PATTERN
);
204 swfdec_image_pattern_morph (SwfdecDraw
*dest
, SwfdecDraw
*source
, guint ratio
)
206 SwfdecImagePattern
*dpattern
= SWFDEC_IMAGE_PATTERN (dest
);
207 SwfdecImagePattern
*spattern
= SWFDEC_IMAGE_PATTERN (source
);
209 dpattern
->image
= g_object_ref (spattern
->image
);
210 dpattern
->extend
= spattern
->extend
;
211 dpattern
->filter
= spattern
->filter
;
213 SWFDEC_DRAW_CLASS (swfdec_image_pattern_parent_class
)->morph (dest
, source
, ratio
);
217 swfdec_image_pattern_paint (SwfdecDraw
*draw
, cairo_t
*cr
, const SwfdecColorTransform
*trans
)
219 cairo_pattern_t
*pattern
;
221 if (swfdec_color_transform_is_alpha (trans
)) {
222 SwfdecColorTransform identity
;
223 swfdec_color_transform_init_identity (&identity
);
224 pattern
= swfdec_pattern_get_pattern (SWFDEC_PATTERN (draw
),
225 swfdec_renderer_get (cr
), &identity
);
229 cairo_set_operator (cr
, CAIRO_OPERATOR_OVER
);
230 cairo_set_fill_rule (cr
, CAIRO_FILL_RULE_EVEN_ODD
);
231 cairo_append_path (cr
, &draw
->path
);
233 cairo_set_source (cr
, pattern
);
234 cairo_pattern_destroy (pattern
);
235 cairo_paint_with_alpha (cr
, trans
->aa
/ 256.0);
238 SWFDEC_DRAW_CLASS (swfdec_image_pattern_parent_class
)->paint (draw
, cr
, trans
);
242 static cairo_pattern_t
*
243 swfdec_image_pattern_get_pattern (SwfdecPattern
*pat
, SwfdecRenderer
*renderer
,
244 const SwfdecColorTransform
*trans
)
246 SwfdecImagePattern
*image
= SWFDEC_IMAGE_PATTERN (pat
);
247 cairo_pattern_t
*pattern
;
248 cairo_surface_t
*surface
;
250 if (swfdec_color_transform_is_mask (trans
))
251 return cairo_pattern_create_rgb (0, 0, 0);
252 surface
= swfdec_image_create_surface_transformed (image
->image
, renderer
, trans
);
255 pattern
= cairo_pattern_create_for_surface (surface
);
256 cairo_surface_destroy (surface
);
257 cairo_pattern_set_matrix (pattern
, &pat
->transform
);
258 cairo_pattern_set_extend (pattern
, image
->extend
);
259 cairo_pattern_set_filter (pattern
, image
->filter
);
264 swfdec_image_pattern_class_init (SwfdecImagePatternClass
*klass
)
266 SWFDEC_DRAW_CLASS (klass
)->morph
= swfdec_image_pattern_morph
;
267 SWFDEC_DRAW_CLASS (klass
)->paint
= swfdec_image_pattern_paint
;
269 SWFDEC_PATTERN_CLASS (klass
)->get_pattern
= swfdec_image_pattern_get_pattern
;
273 swfdec_image_pattern_init (SwfdecImagePattern
*pattern
)
277 /*** EXPORTED API ***/
280 swfdec_pattern_do_parse (SwfdecBits
*bits
, SwfdecSwfDecoder
*dec
, gboolean rgba
)
282 guint paint_style_type
;
283 SwfdecPattern
*pattern
;
285 paint_style_type
= swfdec_bits_get_u8 (bits
);
286 SWFDEC_LOG (" type 0x%02x", paint_style_type
);
288 if (paint_style_type
== 0x00) {
289 pattern
= g_object_new (SWFDEC_TYPE_COLOR_PATTERN
, NULL
);
291 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= swfdec_bits_get_rgba (bits
);
293 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= swfdec_bits_get_color (bits
);
295 SWFDEC_COLOR_PATTERN (pattern
)->end_color
= SWFDEC_COLOR_PATTERN (pattern
)->start_color
;
296 SWFDEC_LOG (" color %08x", SWFDEC_COLOR_PATTERN (pattern
)->start_color
);
297 } else if (paint_style_type
== 0x10 || paint_style_type
== 0x12 || paint_style_type
== 0x13) {
298 SwfdecGradientPattern
*gradient
;
299 guint i
, interpolation
;
300 pattern
= SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
301 gradient
= SWFDEC_GRADIENT_PATTERN (pattern
);
302 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
303 pattern
->end_transform
= pattern
->start_transform
;
304 switch (swfdec_bits_getbits (bits
, 2)) {
306 gradient
->extend
= CAIRO_EXTEND_PAD
;
309 gradient
->extend
= CAIRO_EXTEND_REFLECT
;
312 gradient
->extend
= CAIRO_EXTEND_REPEAT
;
315 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
316 gradient
->extend
= CAIRO_EXTEND_PAD
;
319 g_assert_not_reached ();
321 interpolation
= swfdec_bits_getbits (bits
, 2);
323 SWFDEC_FIXME ("only normal interpolation is implemented, mode %u is not", interpolation
);
325 gradient
->n_gradients
= swfdec_bits_getbits (bits
, 4);
326 for (i
= 0; i
< gradient
->n_gradients
; i
++) {
327 gradient
->gradient
[i
].ratio
= swfdec_bits_get_u8 (bits
);
329 gradient
->gradient
[i
].color
= swfdec_bits_get_rgba (bits
);
331 gradient
->gradient
[i
].color
= swfdec_bits_get_color (bits
);
333 gradient
->radial
= (paint_style_type
!= 0x10);
334 /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */
335 if (paint_style_type
== 0x13) {
336 gradient
->focus
= swfdec_bits_get_s16 (bits
) / 256.0;
338 } else if (paint_style_type
>= 0x40 && paint_style_type
<= 0x43) {
339 guint paint_id
= swfdec_bits_get_u16 (bits
);
340 SWFDEC_LOG (" background paint id = %d (type 0x%02x)",
341 paint_id
, paint_style_type
);
342 if (paint_id
== 65535) {
343 /* FIXME: someone explain this magic paint id here */
344 pattern
= g_object_new (SWFDEC_TYPE_COLOR_PATTERN
, NULL
);
345 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
346 SWFDEC_COLOR_PATTERN (pattern
)->end_color
= SWFDEC_COLOR_PATTERN (pattern
)->start_color
;
347 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
348 pattern
->end_transform
= pattern
->start_transform
;
350 pattern
= g_object_new (SWFDEC_TYPE_IMAGE_PATTERN
, NULL
);
351 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
352 pattern
->end_transform
= pattern
->start_transform
;
353 SWFDEC_IMAGE_PATTERN (pattern
)->image
= swfdec_swf_decoder_get_character (dec
, paint_id
);
354 if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern
)->image
)) {
355 g_object_unref (pattern
);
356 SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id
);
359 if (paint_style_type
== 0x40 || paint_style_type
== 0x42) {
360 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_REPEAT
;
362 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_PAD
;
364 if (paint_style_type
== 0x40 || paint_style_type
== 0x41) {
365 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_BILINEAR
;
367 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_NEAREST
;
371 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type
);
374 pattern
->transform
= pattern
->start_transform
;
375 if (cairo_matrix_invert (&pattern
->transform
)) {
376 SWFDEC_ERROR ("paint transform matrix not invertible, resetting");
377 cairo_matrix_init_identity (&pattern
->transform
);
379 swfdec_bits_syncbits (bits
);
380 return SWFDEC_DRAW (pattern
);
384 * swfdec_pattern_parse:
385 * @bits: the bits to parse from
386 * @dec: a #SwfdecDecoder to take context from
387 * @rgba: TRUE if colors are RGBA, FALSE if they're just RGB
389 * Continues parsing @dec into a new #SwfdecPattern
391 * Returns: a new #SwfdecPattern or NULL on error
394 swfdec_pattern_parse (SwfdecBits
*bits
, SwfdecSwfDecoder
*dec
)
396 g_return_val_if_fail (bits
!= NULL
, NULL
);
397 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec
), NULL
);
399 return swfdec_pattern_do_parse (bits
, dec
, FALSE
);
403 swfdec_pattern_parse_rgba (SwfdecBits
*bits
, SwfdecSwfDecoder
*dec
)
405 g_return_val_if_fail (bits
!= NULL
, NULL
);
406 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec
), NULL
);
408 return swfdec_pattern_do_parse (bits
, dec
, TRUE
);
412 * swfdec_pattern_parse_morph:
413 * @dec: a #SwfdecDecoder to parse from
415 * Continues parsing @dec into a new #SwfdecPattern. This function is used by
418 * Returns: a new #SwfdecPattern or NULL on error
421 swfdec_pattern_parse_morph (SwfdecBits
*bits
, SwfdecSwfDecoder
*dec
)
423 guint paint_style_type
;
424 SwfdecPattern
*pattern
;
426 g_return_val_if_fail (bits
!= NULL
, NULL
);
427 g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec
), NULL
);
429 paint_style_type
= swfdec_bits_get_u8 (bits
);
430 SWFDEC_LOG (" type 0x%02x", paint_style_type
);
432 if (paint_style_type
== 0x00) {
433 pattern
= g_object_new (SWFDEC_TYPE_COLOR_PATTERN
, NULL
);
434 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= swfdec_bits_get_rgba (bits
);
435 SWFDEC_COLOR_PATTERN (pattern
)->end_color
= swfdec_bits_get_rgba (bits
);
436 SWFDEC_LOG (" color %08x => %08x", SWFDEC_COLOR_PATTERN (pattern
)->start_color
,
437 SWFDEC_COLOR_PATTERN (pattern
)->end_color
);
438 } else if (paint_style_type
== 0x10 || paint_style_type
== 0x12 || paint_style_type
== 0x13) {
439 SwfdecGradientPattern
*gradient
;
440 guint i
, interpolation
;
441 pattern
= SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
442 gradient
= SWFDEC_GRADIENT_PATTERN (pattern
);
443 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
444 swfdec_bits_get_matrix (bits
, &pattern
->end_transform
, NULL
);
445 switch (swfdec_bits_getbits (bits
, 2)) {
447 gradient
->extend
= CAIRO_EXTEND_PAD
;
450 gradient
->extend
= CAIRO_EXTEND_REFLECT
;
453 gradient
->extend
= CAIRO_EXTEND_REPEAT
;
456 SWFDEC_ERROR ("spread mode 3 is undefined for gradients");
457 gradient
->extend
= CAIRO_EXTEND_PAD
;
460 g_assert_not_reached ();
462 interpolation
= swfdec_bits_getbits (bits
, 2);
464 SWFDEC_FIXME ("only normal interpolation is implemented, mode %u is not", interpolation
);
466 gradient
->n_gradients
= swfdec_bits_getbits (bits
, 4);
467 for (i
= 0; i
< gradient
->n_gradients
; i
++) {
468 gradient
->gradient
[i
].ratio
= swfdec_bits_get_u8 (bits
);
469 gradient
->gradient
[i
].color
= swfdec_bits_get_rgba (bits
);
470 gradient
->end_gradient
[i
].ratio
= swfdec_bits_get_u8 (bits
);
471 gradient
->end_gradient
[i
].color
= swfdec_bits_get_rgba (bits
);
473 gradient
->radial
= (paint_style_type
!= 0x10);
474 /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */
475 if (paint_style_type
== 0x13) {
476 gradient
->focus
= swfdec_bits_get_s16 (bits
) / 256.0;
478 } else if (paint_style_type
>= 0x40 && paint_style_type
<= 0x43) {
479 guint paint_id
= swfdec_bits_get_u16 (bits
);
480 SWFDEC_LOG (" background paint id = %d (type 0x%02x)",
481 paint_id
, paint_style_type
);
482 if (paint_id
== 65535) {
483 /* FIXME: someone explain this magic paint id here */
484 pattern
= g_object_new (SWFDEC_TYPE_COLOR_PATTERN
, NULL
);
485 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
486 SWFDEC_COLOR_PATTERN (pattern
)->end_color
= SWFDEC_COLOR_PATTERN (pattern
)->start_color
;
487 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
488 swfdec_bits_get_matrix (bits
, &pattern
->end_transform
, NULL
);
490 pattern
= g_object_new (SWFDEC_TYPE_IMAGE_PATTERN
, NULL
);
491 swfdec_bits_get_matrix (bits
, &pattern
->start_transform
, NULL
);
492 swfdec_bits_get_matrix (bits
, &pattern
->end_transform
, NULL
);
493 SWFDEC_IMAGE_PATTERN (pattern
)->image
= swfdec_swf_decoder_get_character (dec
, paint_id
);
494 if (!SWFDEC_IS_IMAGE (SWFDEC_IMAGE_PATTERN (pattern
)->image
)) {
495 g_object_unref (pattern
);
496 SWFDEC_ERROR ("could not find image with id %u for pattern", paint_id
);
499 if (paint_style_type
== 0x40 || paint_style_type
== 0x42) {
500 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_REPEAT
;
502 SWFDEC_IMAGE_PATTERN (pattern
)->extend
= CAIRO_EXTEND_PAD
;
504 if (paint_style_type
== 0x40 || paint_style_type
== 0x41) {
505 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_BILINEAR
;
507 SWFDEC_IMAGE_PATTERN (pattern
)->filter
= CAIRO_FILTER_NEAREST
;
511 SWFDEC_ERROR ("unknown paint style type 0x%02x", paint_style_type
);
514 pattern
->transform
= pattern
->start_transform
;
515 if (cairo_matrix_invert (&pattern
->transform
)) {
516 SWFDEC_ERROR ("paint transform matrix not invertible, resetting");
517 cairo_matrix_init_identity (&pattern
->transform
);
519 swfdec_bits_syncbits (bits
);
520 return SWFDEC_DRAW (pattern
);
524 * swfdec_pattern_new_color:
525 * @color: color to paint in
527 * Creates a new pattern to paint with the given color
529 * Returns: a new @SwfdecPattern to paint with
532 swfdec_pattern_new_color (SwfdecColor color
)
534 SwfdecPattern
*pattern
= g_object_new (SWFDEC_TYPE_COLOR_PATTERN
, NULL
);
536 SWFDEC_COLOR_PATTERN (pattern
)->start_color
= color
;
537 SWFDEC_COLOR_PATTERN (pattern
)->end_color
= color
;
543 swfdec_pattern_to_string (SwfdecPattern
*pattern
)
545 g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern
), NULL
);
547 if (SWFDEC_IS_IMAGE_PATTERN (pattern
)) {
548 SwfdecImagePattern
*image
= SWFDEC_IMAGE_PATTERN (pattern
);
549 if (image
->image
->width
== 0)
550 cairo_surface_destroy (swfdec_image_create_surface (image
->image
, NULL
));
551 return g_strdup_printf ("%ux%u image %u (%s, %s)", image
->image
->width
,
552 image
->image
->height
, SWFDEC_CHARACTER (image
->image
)->id
,
553 image
->extend
== CAIRO_EXTEND_REPEAT
? "repeat" : "no repeat",
554 image
->filter
== CAIRO_FILTER_BILINEAR
? "bilinear" : "nearest");
555 } else if (SWFDEC_IS_COLOR_PATTERN (pattern
)) {
556 if (SWFDEC_COLOR_PATTERN (pattern
)->start_color
== SWFDEC_COLOR_PATTERN (pattern
)->end_color
)
557 return g_strdup_printf ("color #%08X", SWFDEC_COLOR_PATTERN (pattern
)->start_color
);
559 return g_strdup_printf ("color #%08X => #%08X", SWFDEC_COLOR_PATTERN (pattern
)->start_color
,
560 SWFDEC_COLOR_PATTERN (pattern
)->end_color
);
561 } else if (SWFDEC_IS_GRADIENT_PATTERN (pattern
)) {
562 SwfdecGradientPattern
*gradient
= SWFDEC_GRADIENT_PATTERN (pattern
);
563 return g_strdup_printf ("%s gradient (%u colors)", gradient
->radial
? "radial" : "linear",
564 gradient
->n_gradients
);
566 return g_strdup_printf ("%s", G_OBJECT_TYPE_NAME (pattern
));
571 swfdec_pattern_get_pattern (SwfdecPattern
*pattern
, SwfdecRenderer
*renderer
,
572 const SwfdecColorTransform
*trans
)
574 SwfdecPatternClass
*klass
;
576 g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern
), NULL
);
577 g_return_val_if_fail (SWFDEC_IS_RENDERER (renderer
), NULL
);
578 g_return_val_if_fail (trans
!= NULL
, NULL
);
580 klass
= SWFDEC_PATTERN_GET_CLASS (pattern
);
581 g_assert (klass
->get_pattern
);
582 return klass
->get_pattern (pattern
, renderer
, trans
);