2 * Copyright (C) 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
27 #include <libswfdec/swfdec_bits.h>
28 #include <libswfdec/swfdec_debug.h>
29 #include <libswfdec/swfdec_script_internal.h>
30 #include <libswfdec/swfdec_tag.h>
31 #include "swfedit_tag.h"
32 #include "swfdec_out.h"
33 #include "swfedit_file.h"
34 #include "swfedit_list.h"
39 swfedit_object_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
43 g_assert (SWFEDIT_IS_TOKEN (data
));
44 buffer
= swfedit_tag_write (data
);
45 swfdec_out_put_buffer (out
, buffer
);
46 swfdec_buffer_unref (buffer
);
50 swfedit_object_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
52 return swfedit_list_new_read (token
, bits
, hint
);
56 swfedit_binary_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
58 swfdec_out_put_buffer (out
, data
);
62 swfedit_binary_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
64 SwfdecBuffer
*buffer
= swfdec_bits_get_buffer (bits
, -1);
66 buffer
= swfdec_buffer_new ();
71 swfedit_bit_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
73 swfdec_out_put_bit (out
, data
? TRUE
: FALSE
);
77 swfedit_bit_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
79 return GUINT_TO_POINTER (swfdec_bits_getbit (bits
) ? 1 : 0);
83 swfedit_u8_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
85 swfdec_out_put_u8 (out
, GPOINTER_TO_UINT (data
));
89 swfedit_u8_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
91 return GUINT_TO_POINTER ((gulong
) swfdec_bits_get_u8 (bits
));
95 swfedit_u16_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
97 swfdec_out_put_u16 (out
, GPOINTER_TO_UINT (data
));
101 swfedit_u16_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
103 return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits
));
107 swfedit_u32_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
109 swfdec_out_put_u32 (out
, GPOINTER_TO_UINT (data
));
113 swfedit_u32_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
115 return GUINT_TO_POINTER (swfdec_bits_get_u32 (bits
));
119 swfedit_rect_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
121 swfdec_out_put_rect (out
, data
);
125 swfedit_rect_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
127 SwfdecRect
*rect
= g_new (SwfdecRect
, 1);
128 swfdec_bits_get_rect (bits
, rect
);
129 swfdec_bits_syncbits (bits
);
134 swfedit_string_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
136 swfdec_out_put_string (out
, data
);
140 swfedit_string_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
143 s
= swfdec_bits_get_string (bits
, 7);
150 swfedit_rgb_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
152 swfdec_out_put_rgb (out
, GPOINTER_TO_UINT (data
));
156 swfedit_rgb_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
158 return GUINT_TO_POINTER (swfdec_bits_get_color (bits
));
162 swfedit_rgba_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
164 swfdec_out_put_rgba (out
, GPOINTER_TO_UINT (data
));
168 swfedit_rgba_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
170 return GUINT_TO_POINTER (swfdec_bits_get_rgba (bits
));
174 swfedit_matrix_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
176 swfdec_out_put_matrix (out
, data
);
180 swfedit_matrix_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
182 cairo_matrix_t
*matrix
= g_new (cairo_matrix_t
, 1);
184 swfdec_bits_get_matrix (bits
, matrix
, NULL
);
185 swfdec_bits_syncbits (bits
);
190 swfedit_ctrans_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
192 swfdec_out_put_color_transform (out
, data
);
196 swfedit_ctrans_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
198 SwfdecColorTransform
*ctrans
= g_new (SwfdecColorTransform
, 1);
200 swfdec_bits_get_color_transform (bits
, ctrans
);
201 swfdec_bits_syncbits (bits
);
206 swfedit_script_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
208 SwfdecScript
*script
= data
;
210 swfdec_out_put_buffer (out
, script
->buffer
);
214 swfedit_script_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
216 while (token
->parent
)
217 token
= token
->parent
;
218 if (!SWFEDIT_IS_FILE (token
))
220 return swfdec_script_new_from_bits (bits
, "original script", swfedit_file_get_version (SWFEDIT_FILE (token
)));
224 swfedit_clipeventflags_write (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
)
226 while (token
->parent
)
227 token
= token
->parent
;
228 g_assert (SWFEDIT_IS_FILE (token
));
229 if (swfedit_file_get_version (SWFEDIT_FILE (token
)) >= 6)
230 swfdec_out_put_u32 (out
, GPOINTER_TO_UINT (data
));
232 swfdec_out_put_u16 (out
, GPOINTER_TO_UINT (data
));
236 swfedit_clipeventflags_read (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
)
238 while (token
->parent
)
239 token
= token
->parent
;
240 g_assert (SWFEDIT_IS_FILE (token
));
241 if (swfedit_file_get_version (SWFEDIT_FILE (token
)) >= 6)
242 return GUINT_TO_POINTER (swfdec_bits_get_u32 (bits
));
244 return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits
));
248 void (* write
) (SwfeditToken
*token
, gpointer data
, SwfdecOut
*out
, gconstpointer hint
);
249 gpointer (* read
) (SwfeditToken
*token
, SwfdecBits
*bits
, gconstpointer hint
);
250 } operations
[SWFEDIT_N_TOKENS
] = {
251 { swfedit_object_write
, swfedit_object_read
},
252 { swfedit_binary_write
, swfedit_binary_read
},
253 { swfedit_bit_write
, swfedit_bit_read
},
254 { swfedit_u8_write
, swfedit_u8_read
},
255 { swfedit_u16_write
, swfedit_u16_read
},
256 { swfedit_u32_write
, swfedit_u32_read
},
257 { swfedit_string_write
, swfedit_string_read
},
258 { swfedit_rect_write
, swfedit_rect_read
},
259 { swfedit_rgb_write
, swfedit_rgb_read
},
260 { swfedit_rgba_write
, swfedit_rgba_read
},
261 { swfedit_matrix_write
, swfedit_matrix_read
},
262 { swfedit_ctrans_write
, swfedit_ctrans_read
},
263 { swfedit_script_write
, swfedit_script_read
},
264 { swfedit_clipeventflags_write
, swfedit_clipeventflags_read
},
268 swfedit_tag_write_token (SwfeditToken
*token
, SwfdecOut
*out
, guint i
)
270 SwfeditTokenEntry
*entry
;
272 g_return_if_fail (SWFEDIT_IS_TOKEN (token
));
273 g_return_if_fail (i
< token
->tokens
->len
);
275 entry
= &g_array_index (token
->tokens
,
276 SwfeditTokenEntry
, i
);
277 g_assert (operations
[entry
->type
].write
!= NULL
);
278 operations
[entry
->type
].write (token
, entry
->value
, out
, NULL
);
282 swfedit_tag_write (SwfeditToken
*token
)
287 g_return_val_if_fail (SWFEDIT_IS_TOKEN (token
), NULL
);
289 out
= swfdec_out_open ();
290 for (i
= 0; i
< token
->tokens
->len
; i
++) {
291 SwfeditTokenEntry
*entry
= &g_array_index (token
->tokens
,
292 SwfeditTokenEntry
, i
);
294 swfedit_tag_write_token (token
, out
, i
);
296 return swfdec_out_close (out
);
300 swfedit_tag_read_token (SwfeditToken
*token
, SwfdecBits
*bits
,
301 const char *name
, SwfeditTokenType type
, gconstpointer hint
)
305 g_return_if_fail (SWFEDIT_IS_TOKEN (token
));
306 g_return_if_fail (name
!= NULL
);
308 g_assert (operations
[type
].read
!= NULL
);
309 data
= operations
[type
].read (token
, bits
, hint
);
310 swfedit_token_add (token
, name
, type
, data
);
315 static const SwfeditTagDefinition ShowFrame
[] = { { NULL
, 0, 0, NULL
} };
316 static const SwfeditTagDefinition SetBackgroundColor
[] = { { "color", SWFEDIT_TOKEN_RGB
, 0, NULL
}, { NULL
, 0, 0, NULL
} };
317 static const SwfeditTagDefinition PlaceObject2Action
[] = {
318 { "flags", SWFEDIT_TOKEN_CLIPEVENTFLAGS
, 0, NULL
},
319 { "size", SWFEDIT_TOKEN_UINT32
, 0, NULL
},
320 //{ "key code", SWFEDIT_TOKEN_UINT8, 0, NULL }, /* only if flag foo is set */
321 { "script", SWFEDIT_TOKEN_SCRIPT
, 2, NULL
},
324 static const SwfeditTagDefinition PlaceObject2
[] = {
325 { "has clip actions", SWFEDIT_TOKEN_BIT
, 0, NULL
},
326 { "has clip depth", SWFEDIT_TOKEN_BIT
, 0, NULL
},
327 { "has name", SWFEDIT_TOKEN_BIT
, 0, NULL
},
328 { "has ratio", SWFEDIT_TOKEN_BIT
, 0, NULL
},
329 { "has color transform", SWFEDIT_TOKEN_BIT
, 0, NULL
},
330 { "has matrix", SWFEDIT_TOKEN_BIT
, 0, NULL
},
331 { "has character", SWFEDIT_TOKEN_BIT
, 0, NULL
},
332 { "move", SWFEDIT_TOKEN_BIT
, 0, NULL
},
333 { "depth", SWFEDIT_TOKEN_UINT16
, 0, NULL
},
334 { "character", SWFEDIT_TOKEN_UINT16
, 7, NULL
},
335 { "matrix", SWFEDIT_TOKEN_MATRIX
, 6, NULL
},
336 { "color transform", SWFEDIT_TOKEN_CTRANS
, 5, NULL
},
337 { "ratio", SWFEDIT_TOKEN_UINT16
, 4, NULL
},
338 { "name", SWFEDIT_TOKEN_STRING
, 3, NULL
},
339 { "clip depth", SWFEDIT_TOKEN_UINT16
, 2, NULL
},
340 { "reserved", SWFEDIT_TOKEN_UINT16
, 1, NULL
},
341 { "all flags", SWFEDIT_TOKEN_CLIPEVENTFLAGS
, 1, NULL
},
342 { "actions", SWFEDIT_TOKEN_OBJECT
, 1, PlaceObject2Action
},
345 static const SwfeditTagDefinition DoAction
[] = {
346 { "action", SWFEDIT_TOKEN_SCRIPT
, 0, NULL
},
349 static const SwfeditTagDefinition DoInitAction
[] = {
350 { "character", SWFEDIT_TOKEN_UINT16
, 0, NULL
},
351 { "action", SWFEDIT_TOKEN_SCRIPT
, 0, NULL
},
355 static const SwfeditTagDefinition
*tags
[] = {
356 [SWFDEC_TAG_SHOWFRAME
] = ShowFrame
,
357 [SWFDEC_TAG_SETBACKGROUNDCOLOR
] = SetBackgroundColor
,
358 [SWFDEC_TAG_PLACEOBJECT2
] = PlaceObject2
,
359 [SWFDEC_TAG_DOACTION
] = DoAction
,
360 [SWFDEC_TAG_DOINITACTION
] = DoInitAction
,
363 static const SwfeditTagDefinition
*
364 swfedit_tag_get_definition (guint tag
)
366 if (tag
>= G_N_ELEMENTS (tags
))
371 /*** SWFEDIT_TAG ***/
373 G_DEFINE_TYPE (SwfeditTag
, swfedit_tag
, SWFEDIT_TYPE_TOKEN
)
376 swfedit_tag_dispose (GObject
*object
)
378 //SwfeditTag *tag = SWFEDIT_TAG (object);
380 G_OBJECT_CLASS (swfedit_tag_parent_class
)->dispose (object
);
384 swfedit_tag_changed (SwfeditToken
*token
, guint i
)
387 SwfeditTag
*tag
= SWFEDIT_TAG (token
);
388 SwfeditTokenEntry
*entry
= &g_array_index (token
->tokens
, SwfeditTokenEntry
, i
);
389 const SwfeditTagDefinition
*def
= swfedit_tag_get_definition (tag
->tag
);
394 for (j
= i
+ 1; def
[j
].name
; j
++) {
395 if (def
[j
].n_items
== i
+ 1) {
396 swfedit_token_set_visible (token
, j
, entry
->value
!= NULL
);
399 if (def
[i
].n_items
!= 0) {
400 entry
= &g_array_index (token
->tokens
,
401 SwfeditTokenEntry
, def
[i
].n_items
- 1);
402 if (entry
->type
== SWFEDIT_TOKEN_UINT32
) {
403 SwfdecOut
*out
= swfdec_out_open ();
404 SwfdecBuffer
*buffer
;
405 swfedit_tag_write_token (token
, out
, def
[i
].n_items
- 1);
406 buffer
= swfdec_out_close (out
);
407 if (entry
->value
!= GUINT_TO_POINTER (buffer
->length
)) {
408 swfedit_token_set (token
, def
[i
].n_items
- 1,
409 GUINT_TO_POINTER (buffer
->length
));
411 swfdec_buffer_unref (buffer
);
417 swfedit_tag_class_init (SwfeditTagClass
*klass
)
419 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
420 SwfeditTokenClass
*token_class
= SWFEDIT_TOKEN_CLASS (klass
);
422 object_class
->dispose
= swfedit_tag_dispose
;
424 token_class
->changed
= swfedit_tag_changed
;
428 swfedit_tag_init (SwfeditTag
*tag
)
433 swfedit_tag_add_token (SwfeditToken
*token
, const char *name
, SwfeditTokenType type
,
438 if (type
== SWFEDIT_TOKEN_OBJECT
) {
439 data
= swfedit_list_new (hint
);
440 SWFEDIT_TOKEN (data
)->parent
= token
;
442 data
= swfedit_token_new_token (type
);
444 swfedit_token_add (token
, name
, type
, data
);
448 swfedit_tag_read_tag (SwfeditToken
*token
, SwfdecBits
*bits
,
449 const SwfeditTagDefinition
*def
)
451 g_return_if_fail (SWFEDIT_IS_TOKEN (token
));
452 g_return_if_fail (bits
!= NULL
);
453 g_return_if_fail (def
!= NULL
);
455 if (def
->n_items
!= 0) {
456 SwfeditTokenEntry
*entry
= &g_array_index (token
->tokens
,
457 SwfeditTokenEntry
, def
->n_items
- 1);
458 if (GPOINTER_TO_UINT (entry
->value
) == 0) {
459 swfedit_tag_add_token (token
, def
->name
, def
->type
, def
->hint
);
460 swfedit_token_set_visible (token
, token
->tokens
->len
- 1, FALSE
);
461 } else if (entry
->type
== SWFEDIT_TOKEN_BIT
) {
462 swfedit_tag_read_token (token
, bits
, def
->name
, def
->type
, def
->hint
);
464 guint length
= GPOINTER_TO_UINT (entry
->value
);
465 SwfdecBuffer
*buffer
= swfdec_bits_get_buffer (bits
, length
);
466 if (buffer
== NULL
) {
467 swfedit_tag_add_token (token
, def
->name
, def
->type
, def
->hint
);
470 swfdec_bits_init (&bits2
, buffer
);
471 swfedit_tag_read_token (token
, &bits2
, def
->name
, def
->type
, def
->hint
);
472 swfdec_buffer_unref (buffer
);
476 swfedit_tag_read_token (token
, bits
, def
->name
, def
->type
, def
->hint
);
481 swfedit_tag_new (SwfeditToken
*parent
, guint tag
, SwfdecBuffer
*buffer
)
484 const SwfeditTagDefinition
*def
;
486 g_return_val_if_fail (SWFEDIT_IS_TOKEN (parent
), NULL
);
488 item
= g_object_new (SWFEDIT_TYPE_TAG
, NULL
);
490 SWFEDIT_TOKEN (item
)->parent
= parent
;
491 def
= swfedit_tag_get_definition (tag
);
494 swfdec_bits_init (&bits
, buffer
);
495 for (;def
->name
!= NULL
; def
++) {
496 swfedit_tag_read_tag (SWFEDIT_TOKEN (item
), &bits
, def
);
498 if (swfdec_bits_left (&bits
)) {
499 SWFDEC_WARNING ("%u bytes %u bits left unparsed",
500 swfdec_bits_left (&bits
) / 8, swfdec_bits_left (&bits
) % 8);
503 swfedit_token_add (SWFEDIT_TOKEN (item
), "contents", SWFEDIT_TOKEN_BINARY
, buffer
);