add blend mode tests
[swfdec.git] / swfdec / swfdec_as_gcable.c
blob3a02d7ce87aceef7ebe34f8fad173cbbfc3cd9a1
1 /* Swfdec
2 * Copyright (C) 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_as_gcable.h"
26 #include "swfdec_as_context.h"
28 gpointer
29 swfdec_as_gcable_alloc (SwfdecAsContext *context, gsize size)
31 SwfdecAsGcable *mem;
32 guint8 diff;
34 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
35 g_return_val_if_fail (size > sizeof (SwfdecAsGcable), NULL);
37 swfdec_as_context_use_mem (context, size);
38 mem = g_slice_alloc0 (size);
39 if (G_LIKELY ((GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK) == 0))
40 return mem;
42 g_slice_free1 (size, mem);
43 mem = g_slice_alloc0 (size + SWFDEC_AS_GC_FLAG_MASK);
44 diff = GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK;
45 if (diff == 0)
46 return mem;
48 diff = SWFDEC_AS_GC_FLAG_MASK + 1 - diff;
49 mem += diff;
50 g_assert ((GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK) == 0);
51 SWFDEC_AS_GCABLE_SET_FLAG (mem, SWFDEC_AS_GC_ALIGN);
52 ((guint8 *) mem)[-1] = diff;
54 return mem;
57 void
58 swfdec_as_gcable_free (SwfdecAsContext *context, gpointer mem, gsize size)
60 SwfdecAsGcable *gc;
62 g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
63 g_return_if_fail (mem != NULL);
64 g_return_if_fail (size > sizeof (SwfdecAsGcable));
66 gc = mem;
67 swfdec_as_context_unuse_mem (context, size);
68 if (G_UNLIKELY (SWFDEC_AS_GCABLE_FLAG_IS_SET (gc, SWFDEC_AS_GC_ALIGN))) {
69 mem = ((guint8 *) mem) - ((guint8 *) mem)[-1];
70 size += SWFDEC_AS_GC_FLAG_MASK;
72 g_slice_free1 (size, mem);
75 SwfdecAsGcable *
76 swfdec_as_gcable_collect (SwfdecAsContext *context, SwfdecAsGcable *gc,
77 SwfdecAsGcableDestroyNotify notify)
79 SwfdecAsGcable *prev, *cur, *tmp;
81 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
83 prev = NULL;
84 cur = gc;
85 for (;;) {
86 while (cur) {
87 if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK | SWFDEC_AS_GC_ROOT)) {
88 if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK))
89 SWFDEC_AS_GCABLE_UNSET_FLAG (cur, SWFDEC_AS_GC_MARK);
90 break;
92 tmp = SWFDEC_AS_GCABLE_NEXT (cur);
93 notify (context, cur);
94 cur = tmp;
96 if (prev)
97 SWFDEC_AS_GCABLE_SET_NEXT (prev, cur);
98 else
99 gc = cur;
100 prev = cur;
101 if (prev == NULL)
102 break;
103 cur = SWFDEC_AS_GCABLE_NEXT (cur);
106 return gc;