make swfdec_as_object_mark() only mark if not marked yet
[swfdec.git] / swfdec / swfdec_filter.c
blob6fa26d0653b65dd49fd0485ad779639fd866c9cb
1 /* Swfdec
2 * Copyright (C) 2007-2008 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 "swfdec_filter.h"
26 #include "swfdec_blur_filter.h"
27 #include "swfdec_color_matrix_filter.h"
28 #include "swfdec_debug.h"
30 G_DEFINE_ABSTRACT_TYPE (SwfdecFilter, swfdec_filter, SWFDEC_TYPE_AS_RELAY)
32 static void
33 swfdec_filter_class_init (SwfdecFilterClass *klass)
37 static void
38 swfdec_filter_init (SwfdecFilter *array)
42 SwfdecFilter *
43 swfdec_filter_clone (SwfdecFilter *filter)
45 SwfdecFilter *clone;
46 SwfdecFilterClass *klass;
48 g_return_val_if_fail (SWFDEC_IS_FILTER (filter), NULL);
50 klass = SWFDEC_FILTER_GET_CLASS (filter);
51 clone = g_object_new (G_OBJECT_CLASS_TYPE (klass), "context",
52 swfdec_gc_object_get_context (filter), NULL);
53 klass->clone (clone, filter);
55 return clone;
58 cairo_pattern_t *
59 swfdec_filter_apply (SwfdecFilter *filter, cairo_pattern_t *pattern,
60 double xscale, double yscale, const SwfdecRectangle *rect)
62 SwfdecFilterClass *klass;
63 cairo_pattern_t *ret;
65 g_return_val_if_fail (SWFDEC_IS_FILTER (filter), NULL);
66 g_return_val_if_fail (pattern != NULL, NULL);
67 g_return_val_if_fail (rect != NULL, NULL);
69 klass = SWFDEC_FILTER_GET_CLASS (filter);
70 g_assert (klass->apply);
72 ret = klass->apply (filter, pattern, xscale, yscale, rect);
73 cairo_pattern_destroy (pattern);
74 return ret;
77 GSList *
78 swfdec_filter_parse (SwfdecPlayer *player, SwfdecBits *bits)
80 GSList *filters = NULL;
81 guint i, n_filters, filter_id;
83 g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
84 g_return_val_if_fail (bits != NULL, NULL);
86 n_filters = swfdec_bits_get_u8 (bits);
87 SWFDEC_LOG (" filters: %u", n_filters);
88 for (i = 0; i < n_filters && swfdec_bits_left (bits); i++) {
89 filter_id = swfdec_bits_get_u8 (bits);
90 switch (filter_id) {
91 case 0:
92 SWFDEC_WARNING (" drop shadow");
93 swfdec_bits_skip_bytes (bits, 16);
94 break;
95 case 1:
97 SwfdecBlurFilter *filter;
99 filter = g_object_new (SWFDEC_TYPE_BLUR_FILTER,
100 "context", player, NULL);
101 SWFDEC_LOG (" blur");
102 filter->x = swfdec_bits_get_u32 (bits) / 65536.0;
103 filter->y = swfdec_bits_get_u32 (bits) / 65536.0;
104 filter->quality = swfdec_bits_getbits (bits, 5);
105 SWFDEC_LOG (" x = %g", filter->x);
106 SWFDEC_LOG (" y = %g", filter->x);
107 SWFDEC_LOG (" quality = %u", filter->quality);
108 swfdec_bits_getbits (bits, 3);
109 filters = g_slist_prepend (filters, filter);
111 break;
112 case 2:
113 SWFDEC_WARNING (" glow");
114 swfdec_bits_skip_bytes (bits, 15);
115 break;
116 case 3:
117 SWFDEC_WARNING (" bevel");
118 swfdec_bits_skip_bytes (bits, 27);
119 break;
120 case 4:
122 guint n;
123 n = swfdec_bits_get_u8 (bits);
124 SWFDEC_WARNING (" gradient glow");
125 swfdec_bits_skip_bytes (bits, n * 5 + 19);
127 break;
128 case 5:
130 guint x, y;
131 x = swfdec_bits_get_u8 (bits);
132 y = swfdec_bits_get_u8 (bits);
133 SWFDEC_WARNING (" %u x %u convolution", x, y);
134 swfdec_bits_skip_bytes (bits, (x + y) * 4 + 13);
136 break;
137 case 6:
139 SwfdecColorMatrixFilter *filter;
140 guint j;
142 filter = g_object_new (SWFDEC_TYPE_COLOR_MATRIX_FILTER,
143 "context", player, NULL);
144 SWFDEC_LOG (" color matrix");
145 for (j = 0; j < 20; j++) {
146 filter->matrix[j] = swfdec_bits_get_float (bits);
148 filters = g_slist_prepend (filters, filter);
150 break;
151 case 7:
153 guint n;
154 n = swfdec_bits_get_u8 (bits);
155 SWFDEC_WARNING (" gradient bevel");
156 swfdec_bits_skip_bytes (bits, n * 5 + 19);
158 break;
159 default:
160 SWFDEC_ERROR ("unknown filter id %u", filter_id);
161 break;
165 filters = g_slist_reverse (filters);
166 return filters;
169 void
170 swfdec_filter_skip (SwfdecBits *bits)
172 guint i, n_filters, filter_id;
174 g_return_if_fail (bits != NULL);
176 n_filters = swfdec_bits_get_u8 (bits);
177 for (i = 0; i < n_filters && swfdec_bits_left (bits); i++) {
178 filter_id = swfdec_bits_get_u8 (bits);
179 switch (filter_id) {
180 case 0:
181 swfdec_bits_skip_bytes (bits, 16);
182 break;
183 case 1:
184 swfdec_bits_skip_bytes (bits, 9);
185 break;
186 case 2:
187 swfdec_bits_skip_bytes (bits, 15);
188 break;
189 case 3:
190 swfdec_bits_skip_bytes (bits, 27);
191 break;
192 case 4:
194 guint n;
195 n = swfdec_bits_get_u8 (bits);
196 swfdec_bits_skip_bytes (bits, n * 5 + 19);
198 break;
199 case 5:
201 guint x, y;
202 x = swfdec_bits_get_u8 (bits);
203 y = swfdec_bits_get_u8 (bits);
204 swfdec_bits_skip_bytes (bits, (x + y) * 4 + 13);
206 break;
207 case 6:
208 swfdec_bits_skip_bytes (bits, 20 * 4);
209 break;
210 case 7:
212 guint n;
213 n = swfdec_bits_get_u8 (bits);
214 swfdec_bits_skip_bytes (bits, n * 5 + 19);
216 break;
217 default:
218 SWFDEC_ERROR ("unknown filter id %u", filter_id);
219 break;
224 void
225 swfdec_filter_get_rectangle (SwfdecFilter *filter, SwfdecRectangle *dest,
226 double xscale, double yscale, const SwfdecRectangle *source)
228 SwfdecFilterClass *klass;
230 g_return_if_fail (SWFDEC_IS_FILTER (filter));
231 g_return_if_fail (dest != NULL);
232 g_return_if_fail (source != NULL);
234 klass = SWFDEC_FILTER_GET_CLASS (filter);
235 klass->get_rectangle (filter, dest, xscale, yscale, source);