fix build for --disable-gtk-doc
[swfdec.git] / swfdec / swfdec_button.c
blob5eaee0e270a1c6c1b64e8240d734913cd5796e14
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
25 #include "swfdec_button.h"
27 #include <string.h>
29 #include "swfdec_button_movie.h"
30 #include "swfdec_debug.h"
31 #include "swfdec_filter.h"
32 #include "swfdec_sound.h"
33 #include "swfdec_sprite.h"
36 G_DEFINE_TYPE (SwfdecButton, swfdec_button, SWFDEC_TYPE_GRAPHIC)
38 static void
39 swfdec_button_init (SwfdecButton * button)
43 static void
44 swfdec_button_dispose (GObject *object)
46 guint i;
47 SwfdecButton *button = SWFDEC_BUTTON (object);
49 g_slist_foreach (button->records, (GFunc) swfdec_buffer_unref, NULL);
50 g_slist_free (button->records);
51 button->records = NULL;
52 if (button->events != NULL) {
53 swfdec_event_list_free (button->events);
54 button->events = NULL;
56 for (i = 0; i < 4; i++) {
57 if (button->sounds[i]) {
58 swfdec_sound_chunk_free (button->sounds[i]);
59 button->sounds[i] = NULL;
63 G_OBJECT_CLASS (swfdec_button_parent_class)->dispose (G_OBJECT (button));
66 static void
67 swfdec_button_class_init (SwfdecButtonClass * g_class)
69 GObjectClass *object_class = G_OBJECT_CLASS (g_class);
70 SwfdecGraphicClass *graphic_class = SWFDEC_GRAPHIC_CLASS (g_class);
72 object_class->dispose = swfdec_button_dispose;
74 graphic_class->movie_type = SWFDEC_TYPE_BUTTON_MOVIE;
77 static guint
78 swfdec_button_translate_conditions (guint conditions, gboolean menu)
80 static const guint events[][2] = {
81 /* idle => over up */ { 1 << SWFDEC_EVENT_ROLL_OVER, 1 << SWFDEC_EVENT_ROLL_OVER },
82 /* over up => idle */ { 1 << SWFDEC_EVENT_ROLL_OUT, 1 << SWFDEC_EVENT_ROLL_OUT },
83 /* over up => over down */ { 1 << SWFDEC_EVENT_PRESS, 1 << SWFDEC_EVENT_PRESS },
84 /* over down => over up */ { 1 << SWFDEC_EVENT_RELEASE, 1 << SWFDEC_EVENT_RELEASE },
85 /* over down => out down */ { 1 << SWFDEC_EVENT_DRAG_OUT, 0 },
86 /* out down => over down */ { 1 << SWFDEC_EVENT_DRAG_OVER, 0 },
87 /* out down => idle */ { 1 << SWFDEC_EVENT_RELEASE_OUTSIDE, 1 << SWFDEC_EVENT_RELEASE_OUTSIDE },
88 /* idle => over down */ { 0, 1 << SWFDEC_EVENT_DRAG_OVER },
89 /* over down => idle */ { 0, 1 << SWFDEC_EVENT_DRAG_OUT }
91 guint i, ret;
93 ret = 0;
94 for (i = 0; i < G_N_ELEMENTS (events); i++) {
95 if (conditions & (1 << i))
96 ret |= events[i][menu ? 1 : 0];
98 return ret;
102 tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
104 SwfdecBits bits;
105 int id, reserved;
106 guint length;
107 SwfdecButton *button;
108 char *script_name;
110 id = swfdec_bits_get_u16 (&s->b);
111 button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
112 if (!button)
113 return SWFDEC_STATUS_OK;
115 SWFDEC_LOG (" ID: %d", id);
117 reserved = swfdec_bits_getbits (&s->b, 7);
118 button->menubutton = swfdec_bits_getbit (&s->b) ? TRUE : FALSE;
119 length = swfdec_bits_get_u16 (&s->b);
121 SWFDEC_LOG (" reserved = %d", reserved);
122 SWFDEC_LOG (" menu = %d", button->menubutton);
123 SWFDEC_LOG (" length of region = %d", length);
125 if (length)
126 swfdec_bits_init_bits (&bits, &s->b, length > 2 ? length - 2 : 0);
127 else
128 swfdec_bits_init_bits (&bits, &s->b, swfdec_bits_left (&s->b) / 8);
129 while (swfdec_bits_peek_u8 (&bits)) {
130 SwfdecBits tmp;
131 SwfdecBuffer *buffer;
132 cairo_matrix_t trans;
133 SwfdecColorTransform ctrans;
134 guint states, gid;
135 gboolean has_blend_mode, has_filters;
137 /* we parse the placement info into buffers each containing one placement */
138 tmp = bits;
140 if (s->version >= 8) {
141 reserved = swfdec_bits_getbits (&bits, 2);
142 has_blend_mode = swfdec_bits_getbit (&bits);
143 has_filters = swfdec_bits_getbit (&bits);
144 SWFDEC_LOG (" reserved = %d", reserved);
145 SWFDEC_LOG (" has_blend_mode = %d", has_blend_mode);
146 SWFDEC_LOG (" has_filters = %d", has_filters);
147 } else {
148 reserved = swfdec_bits_getbits (&bits, 4);
149 has_blend_mode = 0;
150 has_filters = 0;
151 SWFDEC_LOG (" reserved = %d", reserved);
153 states = swfdec_bits_getbits (&bits, 4);
154 gid = swfdec_bits_get_u16 (&bits);
155 swfdec_bits_get_u16 (&bits);
157 SWFDEC_LOG (" states: %s%s%s%s",
158 states & (1 << SWFDEC_BUTTON_HIT) ? "HIT " : "",
159 states & (1 << SWFDEC_BUTTON_DOWN) ? "DOWN " : "",
160 states & (1 << SWFDEC_BUTTON_OVER) ? "OVER " : "",
161 states & (1 << SWFDEC_BUTTON_UP) ? "UP " : "");
163 swfdec_bits_get_matrix (&bits, &trans, NULL);
164 SWFDEC_LOG ("matrix: %g %g %g %g %g %g",
165 trans.xx, trans.yy,
166 trans.xy, trans.yx,
167 trans.x0, trans.y0);
168 swfdec_bits_get_color_transform (&bits, &ctrans);
170 if (has_filters)
171 swfdec_filter_skip (&bits);
172 if (has_blend_mode) {
173 G_GNUC_UNUSED guint blend_mode = swfdec_bits_get_u8 (&bits);
174 SWFDEC_LOG (" blend mode = %u", blend_mode);
176 buffer = swfdec_bits_get_buffer (&tmp, (swfdec_bits_left (&tmp) - swfdec_bits_left (&bits)) / 8);
177 if (buffer == NULL)
178 break;
179 button->records = g_slist_prepend (button->records, buffer);
180 /* add hit state movies to button's extents */
181 if (states & (1 << SWFDEC_BUTTON_HIT)) {
182 SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
183 if (SWFDEC_IS_GRAPHIC (graphic)) {
184 SwfdecRect rect;
185 swfdec_rect_transform (&rect, &graphic->extents, &trans);
186 swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
187 } else {
188 SWFDEC_ERROR ("graphic for id %u not found", gid);
192 swfdec_bits_get_u8 (&bits);
193 if (swfdec_bits_left (&bits)) {
194 SWFDEC_WARNING ("%u bytes left when parsing button records", swfdec_bits_left (&bits) / 8);
196 button->records = g_slist_reverse (button->records);
198 script_name = g_strdup_printf ("Button%u", SWFDEC_CHARACTER (button)->id);
199 while (length != 0) {
200 guint condition, key;
202 length = swfdec_bits_get_u16 (&s->b);
203 if (length)
204 swfdec_bits_init_bits (&bits, &s->b, length > 2 ? length - 2 : 0);
205 else
206 swfdec_bits_init_bits (&bits, &s->b, swfdec_bits_left (&s->b) / 8);
207 condition = swfdec_bits_get_u16 (&bits);
208 key = condition >> 9;
209 condition &= 0x1FF;
210 condition = swfdec_button_translate_conditions (condition, button->menubutton);
211 if (key)
212 condition |= 1 << SWFDEC_EVENT_KEY_DOWN;
214 SWFDEC_LOG (" length = %d", length);
216 if (button->events == NULL)
217 button->events = swfdec_event_list_new ();
218 SWFDEC_LOG (" new event for condition %u (key %u)", condition, key);
219 swfdec_event_list_parse (button->events, &bits, s->version, condition, key,
220 script_name);
221 if (swfdec_bits_left (&bits)) {
222 SWFDEC_WARNING ("%u bytes left after parsing script", swfdec_bits_left (&bits) / 8);
225 g_free (script_name);
227 return SWFDEC_STATUS_OK;
231 tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
233 guint id, flags;
234 SwfdecButton *button;
236 id = swfdec_bits_get_u16 (&s->b);
237 button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
238 if (!button)
239 return SWFDEC_STATUS_OK;
241 SWFDEC_LOG (" ID: %d", id);
243 while (swfdec_bits_peek_u8 (&s->b)) {
244 SwfdecBits tmp;
245 SwfdecBuffer *buffer;
246 cairo_matrix_t matrix;
247 guint gid;
249 tmp = s->b;
250 flags = swfdec_bits_get_u8 (&tmp);
251 gid = swfdec_bits_get_u16 (&tmp);
252 swfdec_bits_get_u16 (&tmp);
253 swfdec_bits_get_matrix (&tmp, &matrix, NULL);
254 buffer = swfdec_bits_get_buffer (&s->b, (swfdec_bits_left (&s->b) - swfdec_bits_left (&tmp)) / 8);
255 if (buffer == NULL)
256 break;
257 button->records = g_slist_prepend (button->records, buffer);
258 /* add hit state movies to button's extents */
259 if (flags & (1 << SWFDEC_BUTTON_HIT)) {
260 SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
261 if (SWFDEC_IS_GRAPHIC (graphic)) {
262 SwfdecRect rect;
263 swfdec_rect_transform (&rect, &graphic->extents, &matrix);
264 swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
265 } else {
266 SWFDEC_ERROR ("graphic for id %u not found", gid);
271 swfdec_bits_get_u8 (&s->b);
272 button->records = g_slist_reverse (button->records);
274 if (swfdec_bits_peek_u8 (&s->b)) {
275 char *script_name = g_strdup_printf ("Button%u", id);
276 button->events = swfdec_event_list_new ();
277 SWFDEC_LOG (" event for button press");
278 swfdec_event_list_parse (button->events, &s->b, s->version, 1 << SWFDEC_EVENT_RELEASE,
279 0, script_name);
280 g_free (script_name);
281 } else {
282 swfdec_bits_get_u8 (&s->b);
284 if (swfdec_bits_left (&s->b)) {
285 SWFDEC_WARNING ("%u bytes left after parsing script", swfdec_bits_left (&s->b) / 8);
288 return SWFDEC_STATUS_OK;