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
26 #include "swfdec_button.h"
27 #include "swfdec_button_movie.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_filter.h"
30 #include "swfdec_sound.h"
31 #include "swfdec_sprite.h"
34 G_DEFINE_TYPE (SwfdecButton
, swfdec_button
, SWFDEC_TYPE_GRAPHIC
)
37 swfdec_button_init (SwfdecButton
* button
)
42 swfdec_button_dispose (GObject
*object
)
45 SwfdecButton
*button
= SWFDEC_BUTTON (object
);
47 g_slist_foreach (button
->records
, (GFunc
) swfdec_buffer_unref
, NULL
);
48 g_slist_free (button
->records
);
49 button
->records
= NULL
;
50 if (button
->events
!= NULL
) {
51 swfdec_event_list_free (button
->events
);
52 button
->events
= NULL
;
54 for (i
= 0; i
< 4; i
++) {
55 if (button
->sounds
[i
]) {
56 swfdec_sound_chunk_free (button
->sounds
[i
]);
57 button
->sounds
[i
] = NULL
;
61 G_OBJECT_CLASS (swfdec_button_parent_class
)->dispose (G_OBJECT (button
));
65 swfdec_button_create_movie (SwfdecGraphic
*graphic
, gsize
*size
)
67 SwfdecButton
*button
= SWFDEC_BUTTON (graphic
);
68 SwfdecButtonMovie
*movie
= g_object_new (SWFDEC_TYPE_BUTTON_MOVIE
, NULL
);
70 movie
->button
= g_object_ref (button
);
71 *size
= sizeof (SwfdecButtonMovie
);
73 SWFDEC_MOVIE (movie
)->events
= swfdec_event_list_copy (button
->events
);
75 return SWFDEC_MOVIE (movie
);
79 swfdec_button_class_init (SwfdecButtonClass
* g_class
)
81 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
82 SwfdecGraphicClass
*graphic_class
= SWFDEC_GRAPHIC_CLASS (g_class
);
84 object_class
->dispose
= swfdec_button_dispose
;
86 graphic_class
->create_movie
= swfdec_button_create_movie
;
90 swfdec_button_translate_conditions (guint conditions
, gboolean menu
)
92 static const guint events
[][2] = {
93 /* idle => over up */ { 1 << SWFDEC_EVENT_ROLL_OVER
, 1 << SWFDEC_EVENT_ROLL_OVER
},
94 /* over up => idle */ { 1 << SWFDEC_EVENT_ROLL_OUT
, 1 << SWFDEC_EVENT_ROLL_OUT
},
95 /* over up => over down */ { 1 << SWFDEC_EVENT_PRESS
, 1 << SWFDEC_EVENT_PRESS
},
96 /* over down => over up */ { 1 << SWFDEC_EVENT_RELEASE
, 1 << SWFDEC_EVENT_RELEASE
},
97 /* over down => out down */ { 1 << SWFDEC_EVENT_DRAG_OUT
, 0 },
98 /* out down => over down */ { 1 << SWFDEC_EVENT_DRAG_OVER
, 0 },
99 /* out down => idle */ { 1 << SWFDEC_EVENT_RELEASE_OUTSIDE
, 1 << SWFDEC_EVENT_RELEASE_OUTSIDE
},
100 /* idle => over down */ { 0, 1 << SWFDEC_EVENT_DRAG_OVER
},
101 /* over down => idle */ { 0, 1 << SWFDEC_EVENT_DRAG_OUT
}
106 for (i
= 0; i
<= G_N_ELEMENTS (events
); i
++) {
107 if (conditions
& (1 << i
))
108 ret
|= events
[i
][menu
? 1 : 0];
114 tag_func_define_button_2 (SwfdecSwfDecoder
* s
, guint tag
)
119 SwfdecButton
*button
;
122 id
= swfdec_bits_get_u16 (&s
->b
);
123 button
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_BUTTON
);
125 return SWFDEC_STATUS_OK
;
127 SWFDEC_LOG (" ID: %d", id
);
129 reserved
= swfdec_bits_getbits (&s
->b
, 7);
130 button
->menubutton
= swfdec_bits_getbit (&s
->b
) ? TRUE
: FALSE
;
131 length
= swfdec_bits_get_u16 (&s
->b
);
133 SWFDEC_LOG (" reserved = %d", reserved
);
134 SWFDEC_LOG (" menu = %d", button
->menubutton
);
135 SWFDEC_LOG (" length of region = %d", length
);
138 swfdec_bits_init_bits (&bits
, &s
->b
, length
> 2 ? length
- 2 : 0);
140 swfdec_bits_init_bits (&bits
, &s
->b
, swfdec_bits_left (&s
->b
) / 8);
141 while (swfdec_bits_peek_u8 (&bits
)) {
143 SwfdecBuffer
*buffer
;
144 cairo_matrix_t trans
;
145 SwfdecColorTransform ctrans
;
147 gboolean has_blend_mode
, has_filters
;
149 /* we parse the placement info into buffers each containing one palcement */
152 if (s
->version
>= 8) {
153 reserved
= swfdec_bits_getbits (&bits
, 2);
154 has_blend_mode
= swfdec_bits_getbit (&bits
);
155 has_filters
= swfdec_bits_getbit (&bits
);
156 SWFDEC_LOG (" reserved = %d", reserved
);
157 SWFDEC_LOG (" has_blend_mode = %d", has_blend_mode
);
158 SWFDEC_LOG (" has_filters = %d", has_filters
);
160 reserved
= swfdec_bits_getbits (&bits
, 4);
163 SWFDEC_LOG (" reserved = %d", reserved
);
165 states
= swfdec_bits_getbits (&bits
, 4);
166 swfdec_bits_skip_bytes (&bits
, 4);
168 SWFDEC_LOG (" states: %s%s%s%s",
169 states
& (1 << SWFDEC_BUTTON_HIT
) ? "HIT " : "",
170 states
& (1 << SWFDEC_BUTTON_DOWN
) ? "DOWN " : "",
171 states
& (1 << SWFDEC_BUTTON_OVER
) ? "OVER " : "",
172 states
& (1 << SWFDEC_BUTTON_UP
) ? "UP " : "");
174 swfdec_bits_get_matrix (&bits
, &trans
, NULL
);
175 SWFDEC_LOG ("matrix: %g %g %g %g %g %g",
179 swfdec_bits_get_color_transform (&bits
, &ctrans
);
182 GSList
*list
= swfdec_filter_parse (SWFDEC_DECODER (s
)->player
, &bits
);
185 if (has_blend_mode
) {
186 guint blend_mode
= swfdec_bits_get_u8 (&bits
);
187 SWFDEC_LOG (" blend mode = %u", blend_mode
);
189 buffer
= swfdec_bits_get_buffer (&tmp
, (swfdec_bits_left (&tmp
) - swfdec_bits_left (&bits
)) / 8);
191 button
->records
= g_slist_prepend (button
->records
, buffer
);
193 swfdec_bits_get_u8 (&bits
);
194 if (swfdec_bits_left (&bits
)) {
195 SWFDEC_WARNING ("%u bytes left when parsing button records", swfdec_bits_left (&bits
) / 8);
197 button
->records
= g_slist_reverse (button
->records
);
199 script_name
= g_strdup_printf ("Button%u", SWFDEC_CHARACTER (button
)->id
);
200 while (length
!= 0) {
201 guint condition
, key
;
203 length
= swfdec_bits_get_u16 (&s
->b
);
205 swfdec_bits_init_bits (&bits
, &s
->b
, length
> 2 ? length
- 2 : 0);
207 swfdec_bits_init_bits (&bits
, &s
->b
, swfdec_bits_left (&s
->b
) / 8);
208 condition
= swfdec_bits_get_u16 (&bits
);
209 key
= condition
>> 9;
211 condition
= swfdec_button_translate_conditions (condition
, button
->menubutton
);
213 SWFDEC_LOG (" length = %d", length
);
215 if (button
->events
== NULL
)
216 button
->events
= swfdec_event_list_new (SWFDEC_DECODER (s
)->player
);
217 SWFDEC_LOG (" new event for condition %u (key %u)", condition
, key
);
218 swfdec_event_list_parse (button
->events
, &bits
, s
->version
, condition
, key
,
220 if (swfdec_bits_left (&bits
)) {
221 SWFDEC_WARNING ("%u bytes left after parsing script", swfdec_bits_left (&bits
) / 8);
224 g_free (script_name
);
226 return SWFDEC_STATUS_OK
;
230 tag_func_define_button (SwfdecSwfDecoder
* s
, guint tag
)
232 SWFDEC_ERROR ("implement DefineButton again");
234 return SWFDEC_STATUS_OK
;