add another test for gradients
[swfdec.git] / test / swfedit_tag.c
blob4a4bf67e6fce969f9edf159327055015274c05ef
1 /* Swfedit
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.
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 <stdlib.h>
25 #include <gtk/gtk.h>
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"
36 /*** LOAD/SAVE ***/
38 static void
39 swfedit_object_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
41 SwfdecBuffer *buffer;
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);
49 static gpointer
50 swfedit_object_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
52 return swfedit_list_new_read (token, bits, hint);
55 static void
56 swfedit_binary_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
58 swfdec_out_put_buffer (out, data);
61 static gpointer
62 swfedit_binary_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
64 SwfdecBuffer *buffer = swfdec_bits_get_buffer (bits, -1);
65 if (buffer == NULL)
66 buffer = swfdec_buffer_new ();
67 return buffer;
70 static void
71 swfedit_bit_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
73 swfdec_out_put_bit (out, data ? TRUE : FALSE);
76 static gpointer
77 swfedit_bit_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
79 return GUINT_TO_POINTER (swfdec_bits_getbit (bits) ? 1 : 0);
82 static void
83 swfedit_u8_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
85 swfdec_out_put_u8 (out, GPOINTER_TO_UINT (data));
88 static gpointer
89 swfedit_u8_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
91 return GUINT_TO_POINTER ((gulong) swfdec_bits_get_u8 (bits));
94 static void
95 swfedit_u16_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
97 swfdec_out_put_u16 (out, GPOINTER_TO_UINT (data));
100 static gpointer
101 swfedit_u16_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
103 return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits));
106 static void
107 swfedit_u32_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
109 swfdec_out_put_u32 (out, GPOINTER_TO_UINT (data));
112 static gpointer
113 swfedit_u32_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
115 return GUINT_TO_POINTER (swfdec_bits_get_u32 (bits));
118 static void
119 swfedit_rect_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
121 swfdec_out_put_rect (out, data);
124 static gpointer
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);
130 return rect;
133 static void
134 swfedit_string_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
136 swfdec_out_put_string (out, data);
139 static gpointer
140 swfedit_string_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
142 char *s;
143 s = swfdec_bits_get_string (bits, 7);
144 if (s == NULL)
145 s = g_strdup ("");
146 return s;
149 static void
150 swfedit_rgb_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
152 swfdec_out_put_rgb (out, GPOINTER_TO_UINT (data));
155 static gpointer
156 swfedit_rgb_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
158 return GUINT_TO_POINTER (swfdec_bits_get_color (bits));
161 static void
162 swfedit_rgba_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
164 swfdec_out_put_rgba (out, GPOINTER_TO_UINT (data));
167 static gpointer
168 swfedit_rgba_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
170 return GUINT_TO_POINTER (swfdec_bits_get_rgba (bits));
173 static void
174 swfedit_matrix_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
176 swfdec_out_put_matrix (out, data);
179 static gpointer
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);
186 return matrix;
189 static void
190 swfedit_ctrans_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
192 swfdec_out_put_color_transform (out, data);
195 static gpointer
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);
202 return ctrans;
205 static void
206 swfedit_script_write (SwfeditToken *token, gpointer data, SwfdecOut *out, gconstpointer hint)
208 SwfdecScript *script = data;
210 swfdec_out_put_buffer (out, script->buffer);
213 static gpointer
214 swfedit_script_read (SwfeditToken *token, SwfdecBits *bits, gconstpointer hint)
216 while (token->parent)
217 token = token->parent;
218 if (!SWFEDIT_IS_FILE (token))
219 return NULL;
220 return swfdec_script_new_from_bits (bits, "original script", swfedit_file_get_version (SWFEDIT_FILE (token)));
223 static void
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));
231 else
232 swfdec_out_put_u16 (out, GPOINTER_TO_UINT (data));
235 static gpointer
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));
243 else
244 return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits));
247 struct {
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 },
267 void
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);
281 SwfdecBuffer *
282 swfedit_tag_write (SwfeditToken *token)
284 guint i;
285 SwfdecOut *out;
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);
293 if (entry->visible)
294 swfedit_tag_write_token (token, out, i);
296 return swfdec_out_close (out);
299 void
300 swfedit_tag_read_token (SwfeditToken *token, SwfdecBits *bits,
301 const char *name, SwfeditTokenType type, gconstpointer hint)
303 gpointer data;
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);
313 /*** TAGS ***/
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 },
322 { NULL, 0, 0, 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 },
343 { NULL, 0, 0, NULL }
345 static const SwfeditTagDefinition DoAction[] = {
346 { "action", SWFEDIT_TOKEN_SCRIPT, 0, NULL },
347 { NULL, 0, 0, NULL }
349 static const SwfeditTagDefinition DoInitAction[] = {
350 { "character", SWFEDIT_TOKEN_UINT16, 0, NULL },
351 { "action", SWFEDIT_TOKEN_SCRIPT, 0, NULL },
352 { NULL, 0, 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))
367 return NULL;
368 return tags[tag];
371 /*** SWFEDIT_TAG ***/
373 G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN)
375 static void
376 swfedit_tag_dispose (GObject *object)
378 //SwfeditTag *tag = SWFEDIT_TAG (object);
380 G_OBJECT_CLASS (swfedit_tag_parent_class)->dispose (object);
383 static void
384 swfedit_tag_changed (SwfeditToken *token, guint i)
386 guint j;
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);
391 if (def == NULL)
392 return;
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);
416 static void
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;
427 static void
428 swfedit_tag_init (SwfeditTag *tag)
432 void
433 swfedit_tag_add_token (SwfeditToken *token, const char *name, SwfeditTokenType type,
434 gconstpointer hint)
436 gpointer data;
438 if (type == SWFEDIT_TOKEN_OBJECT) {
439 data = swfedit_list_new (hint);
440 SWFEDIT_TOKEN (data)->parent = token;
441 } else {
442 data = swfedit_token_new_token (type);
444 swfedit_token_add (token, name, type, data);
447 void
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);
463 } else {
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);
468 } else {
469 SwfdecBits bits2;
470 swfdec_bits_init (&bits2, buffer);
471 swfedit_tag_read_token (token, &bits2, def->name, def->type, def->hint);
472 swfdec_buffer_unref (buffer);
475 } else {
476 swfedit_tag_read_token (token, bits, def->name, def->type, def->hint);
480 SwfeditTag *
481 swfedit_tag_new (SwfeditToken *parent, guint tag, SwfdecBuffer *buffer)
483 SwfeditTag *item;
484 const SwfeditTagDefinition *def;
486 g_return_val_if_fail (SWFEDIT_IS_TOKEN (parent), NULL);
488 item = g_object_new (SWFEDIT_TYPE_TAG, NULL);
489 item->tag = tag;
490 SWFEDIT_TOKEN (item)->parent = parent;
491 def = swfedit_tag_get_definition (tag);
492 if (def) {
493 SwfdecBits bits;
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);
502 } else {
503 swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
505 return item;