fix alignment problems
[swfdec.git] / swfdec / swfdec_bots.c
blobeda1b7a9a292d43fc8a44665821b1fa2165cf009
1 /* Swfdec
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 <string.h>
26 #include "swfdec_bots.h"
28 SwfdecBots *
29 swfdec_bots_open (void)
31 SwfdecBots *bots = g_new0 (SwfdecBots, 1);
33 bots->data = g_malloc (SWFDEC_OUT_INITIAL);
34 bots->ptr = bots->data;
35 bots->end = bots->data + SWFDEC_OUT_INITIAL;
37 return bots;
40 static void
41 swfdec_bots_syncbits (SwfdecBots *bots)
43 g_return_if_fail (bots != NULL);
45 if (bots->idx > 0) {
46 bots->ptr++;
47 bots->idx = 0;
51 SwfdecBuffer *
52 swfdec_bots_close (SwfdecBots *bots)
54 SwfdecBuffer *buffer;
56 g_return_val_if_fail (bots != NULL, NULL);
58 swfdec_bots_syncbits (bots);
60 buffer = swfdec_buffer_new_for_data (bots->data, bots->ptr - bots->data);
62 g_free (bots);
64 return buffer;
67 void
68 swfdec_bots_free (SwfdecBots *bots)
70 g_return_if_fail (bots != NULL);
72 g_free (bots->data);
73 g_free (bots);
76 gsize
77 swfdec_bots_get_bits (SwfdecBots *bots)
79 g_return_val_if_fail (bots != NULL, 0);
81 return (bots->ptr - bots->data) * 8 + bots->idx;
84 gsize
85 swfdec_bots_get_bytes (SwfdecBots *bots)
87 g_return_val_if_fail (bots != NULL, 0);
89 g_assert (bots->idx == 0);
91 return swfdec_bots_get_bits (bots) / 8;
94 gsize
95 swfdec_bots_left (SwfdecBots *bots)
97 g_return_val_if_fail (bots != NULL, 0);
99 return (bots->end - bots->ptr) * 8 - bots->idx;
102 void
103 swfdec_bots_ensure_bits (SwfdecBots *bots, unsigned int bits)
105 unsigned int current, taken, needed;
107 g_return_if_fail (bots != NULL);
109 current = swfdec_bots_left (bots);
110 if (current >= bits)
111 return;
112 taken = bots->ptr - bots->data;
113 needed = (bits - current + 7) / 8;
114 needed += SWFDEC_OUT_STEP;
115 needed -= needed % SWFDEC_OUT_STEP;
116 needed += bots->end - bots->data;
117 bots->data = g_realloc (bots->data, needed);
118 bots->ptr = bots->data + taken;
119 bots->end = bots->data + needed;
122 void
123 swfdec_bots_prepare_bytes (SwfdecBots *bots, unsigned int bytes)
125 g_return_if_fail (bots != NULL);
127 swfdec_bots_syncbits (bots);
128 swfdec_bots_ensure_bits (bots, bytes * 8);
131 void
132 swfdec_bots_put_data (SwfdecBots *bots, const guint8 *data, guint length)
134 g_return_if_fail (bots != NULL);
136 swfdec_bots_prepare_bytes (bots, length);
137 memcpy (bots->ptr, data, length);
138 bots->ptr += length;
141 void
142 swfdec_bots_put_buffer (SwfdecBots *bots, SwfdecBuffer *buffer)
144 g_return_if_fail (bots != NULL);
146 swfdec_bots_prepare_bytes (bots, buffer->length);
147 memcpy (bots->ptr, buffer->data, buffer->length);
148 bots->ptr += buffer->length;
151 void
152 swfdec_bots_put_bots (SwfdecBots *bots, SwfdecBots *other)
154 gsize bytes;
156 g_return_if_fail (bots != NULL);
157 g_return_if_fail (other != NULL);
159 bytes = swfdec_bots_get_bytes (other);
160 swfdec_bots_prepare_bytes (bots, bytes);
161 memcpy (bots->ptr, other->data, bytes);
162 bots->ptr += bytes;
165 void
166 swfdec_bots_put_u8 (SwfdecBots *bots, guint i)
168 g_return_if_fail (i <= G_MAXUINT8);
170 swfdec_bots_prepare_bytes (bots, 1);
171 *bots->ptr = i;
172 bots->ptr++;
175 void
176 swfdec_bots_put_u16 (SwfdecBots *bots, guint i)
178 g_return_if_fail (i <= G_MAXUINT16);
180 swfdec_bots_prepare_bytes (bots, 2);
181 bots->ptr[0] = i;
182 bots->ptr[1] = i >> 8;
183 bots->ptr += 2;
186 void
187 swfdec_bots_put_s16 (SwfdecBots *bots, int i)
189 g_return_if_fail (i >= G_MININT16 && i <= G_MAXINT16);
191 swfdec_bots_prepare_bytes (bots, 2);
192 bots->ptr[0] = i;
193 bots->ptr[1] = i >> 8;
194 bots->ptr += 2;
197 void
198 swfdec_bots_put_u32 (SwfdecBots *bots, guint i)
200 g_return_if_fail (i <= G_MAXUINT32);
202 swfdec_bots_prepare_bytes (bots, 4);
203 bots->ptr[0] = i;
204 bots->ptr[1] = i >> 8;
205 bots->ptr[2] = i >> 16;
206 bots->ptr[3] = i >> 24;
207 bots->ptr += 4;
210 void
211 swfdec_bots_put_bit (SwfdecBots *bots, gboolean bit)
213 g_return_if_fail (bots != NULL);
215 swfdec_bots_put_bits (bots, bit ? 1 : 0, 1);
218 void
219 swfdec_bots_put_bits (SwfdecBots *bots, guint bits, guint n_bits)
221 g_return_if_fail (bots != NULL);
223 swfdec_bots_ensure_bits (bots, n_bits);
225 /* FIXME: implement this less braindead */
226 while (n_bits) {
227 guint bits_now = MIN (n_bits, 8 - bots->idx);
228 guint value = bits >> (n_bits - bits_now);
230 /* clear data if necessary */
231 if (bots->idx == 0)
232 *bots->ptr = 0;
233 value &= (1 << bits_now) - 1;
234 value <<= 8 - bots->idx - bits_now;
235 *bots->ptr |= value;
236 bots->idx += bits_now;
237 g_assert (bots->idx <= 8);
238 if (bots->idx == 8) {
239 bots->ptr ++;
240 bots->idx = 0;
242 n_bits -= bits_now;
246 void
247 swfdec_bots_put_sbits (SwfdecBots *bots, int bits, guint n_bits)
249 g_return_if_fail (bots != NULL);
251 swfdec_bots_put_bits (bots, bits, n_bits);
254 void
255 swfdec_bots_put_string (SwfdecBots *bots, const char *s)
257 guint len;
259 g_return_if_fail (bots != NULL);
260 g_return_if_fail (s != NULL);
262 len = strlen (s) + 1;
264 swfdec_bots_prepare_bytes (bots, len);
265 memcpy (bots->ptr, s, len);
266 bots->ptr += len;
269 void
270 swfdec_bots_put_float (SwfdecBots *bots, float f)
272 union {
273 guint32 i;
274 float f;
275 } conv;
277 g_return_if_fail (bots != NULL);
279 conv.f = f;
280 swfdec_bots_put_u32 (bots, conv.i);
283 /* If little endian x86 byte order is 0 1 2 3 4 5 6 7 and PPC32 byte order is
284 * 7 6 5 4 3 2 1 0, then Flash uses 4 5 6 7 0 1 2 3. */
285 void
286 swfdec_bots_put_double (SwfdecBots *bots, double value)
288 union {
289 guint32 i[2];
290 double d;
291 } conv;
293 swfdec_bots_ensure_bits (bots, 8);
295 conv.d = value;
297 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
298 swfdec_bots_put_u32 (bots, conv.i[1]);
299 swfdec_bots_put_u32 (bots, conv.i[0]);
300 #else
301 swfdec_bots_put_u32 (bots, GUINT32_TO_LE (conv.i[0]));
302 swfdec_bots_put_u32 (bots, GUINT32_TO_LE (conv.i[1]));
303 #endif
306 static guint
307 swfdec_bit_sstorage (long x)
309 if (x < 0)
310 x = ~x;
311 return g_bit_storage (x) + 1;
314 void
315 swfdec_bots_put_rect (SwfdecBots *bots, const SwfdecRect *rect)
317 int x0, x1, y0, y1;
318 guint req, tmp;
320 g_return_if_fail (bots != NULL);
321 g_return_if_fail (rect != NULL);
323 x0 = rect->x0;
324 y0 = rect->y0;
325 x1 = rect->x1;
326 y1 = rect->y1;
327 req = swfdec_bit_sstorage (x0);
328 tmp = swfdec_bit_sstorage (y0);
329 req = MAX (req, tmp);
330 tmp = swfdec_bit_sstorage (x1);
331 req = MAX (req, tmp);
332 tmp = swfdec_bit_sstorage (y1);
333 req = MAX (req, tmp);
334 swfdec_bots_syncbits (bots);
335 swfdec_bots_put_bits (bots, req, 5);
336 swfdec_bots_put_sbits (bots, x0, req);
337 swfdec_bots_put_sbits (bots, x1, req);
338 swfdec_bots_put_sbits (bots, y0, req);
339 swfdec_bots_put_sbits (bots, y1, req);
340 swfdec_bots_syncbits (bots);
343 void
344 swfdec_bots_put_matrix (SwfdecBots *bots, const cairo_matrix_t *matrix)
346 int x, y;
347 unsigned int xbits, ybits;
349 if (matrix->xx != 1.0 || matrix->yy != 1.0) {
350 swfdec_bots_put_bit (bots, 1);
351 x = SWFDEC_DOUBLE_TO_FIXED (matrix->xx);
352 y = SWFDEC_DOUBLE_TO_FIXED (matrix->yy);
353 xbits = swfdec_bit_sstorage (x);
354 ybits = swfdec_bit_sstorage (y);
355 xbits = MAX (xbits, ybits);
356 swfdec_bots_put_bits (bots, xbits, 5);
357 swfdec_bots_put_sbits (bots, x, xbits);
358 swfdec_bots_put_sbits (bots, y, xbits);
359 } else {
360 swfdec_bots_put_bit (bots, 0);
362 if (matrix->xy != 0.0 || matrix->yx != 0.0) {
363 swfdec_bots_put_bit (bots, 1);
364 x = SWFDEC_DOUBLE_TO_FIXED (matrix->yx);
365 y = SWFDEC_DOUBLE_TO_FIXED (matrix->xy);
366 xbits = swfdec_bit_sstorage (x);
367 ybits = swfdec_bit_sstorage (y);
368 xbits = MAX (xbits, ybits);
369 swfdec_bots_put_bits (bots, xbits, 5);
370 swfdec_bots_put_sbits (bots, x, xbits);
371 swfdec_bots_put_sbits (bots, y, xbits);
372 } else {
373 swfdec_bots_put_bit (bots, 0);
375 x = matrix->x0;
376 y = matrix->y0;
377 xbits = swfdec_bit_sstorage (x);
378 ybits = swfdec_bit_sstorage (y);
379 xbits = MAX (xbits, ybits);
380 swfdec_bots_put_bits (bots, xbits, 5);
381 swfdec_bots_put_sbits (bots, x, xbits);
382 swfdec_bots_put_sbits (bots, y, xbits);
383 swfdec_bots_syncbits (bots);
386 void
387 swfdec_bots_put_color_transform (SwfdecBots *bots, const SwfdecColorTransform *trans)
389 gboolean has_add, has_mult;
390 unsigned int n_bits, tmp;
392 has_mult = trans->ra != 256 || trans->ga != 256 || trans->ba != 256 || trans->aa != 256;
393 has_add = trans->rb != 0 || trans->gb != 0 || trans->bb != 0 || trans->ab != 0;
394 if (has_mult) {
395 n_bits = swfdec_bit_sstorage (trans->ra);
396 tmp = swfdec_bit_sstorage (trans->ga);
397 n_bits = MAX (tmp, n_bits);
398 tmp = swfdec_bit_sstorage (trans->ba);
399 n_bits = MAX (tmp, n_bits);
400 tmp = swfdec_bit_sstorage (trans->aa);
401 n_bits = MAX (tmp, n_bits);
402 } else {
403 n_bits = 0;
405 if (has_add) {
406 tmp = swfdec_bit_sstorage (trans->rb);
407 n_bits = MAX (tmp, n_bits);
408 tmp = swfdec_bit_sstorage (trans->gb);
409 n_bits = MAX (tmp, n_bits);
410 tmp = swfdec_bit_sstorage (trans->bb);
411 n_bits = MAX (tmp, n_bits);
412 tmp = swfdec_bit_sstorage (trans->ab);
413 n_bits = MAX (tmp, n_bits);
415 if (n_bits >= (1 << 4))
416 n_bits = (1 << 4) - 1;
417 swfdec_bots_put_bit (bots, has_add);
418 swfdec_bots_put_bit (bots, has_mult);
419 swfdec_bots_put_bits (bots, n_bits, 4);
420 if (has_mult) {
421 swfdec_bots_put_sbits (bots, trans->ra, n_bits);
422 swfdec_bots_put_sbits (bots, trans->ga, n_bits);
423 swfdec_bots_put_sbits (bots, trans->ba, n_bits);
424 swfdec_bots_put_sbits (bots, trans->aa, n_bits);
426 if (has_add) {
427 swfdec_bots_put_sbits (bots, trans->rb, n_bits);
428 swfdec_bots_put_sbits (bots, trans->gb, n_bits);
429 swfdec_bots_put_sbits (bots, trans->bb, n_bits);
430 swfdec_bots_put_sbits (bots, trans->ab, n_bits);
432 swfdec_bots_syncbits (bots);
435 void
436 swfdec_bots_put_rgb (SwfdecBots *bots, SwfdecColor color)
438 g_return_if_fail (bots != NULL);
440 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_RED (color));
441 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_GREEN (color));
442 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_BLUE (color));
445 void
446 swfdec_bots_put_rgba (SwfdecBots *bots, SwfdecColor color)
448 g_return_if_fail (bots != NULL);
450 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_RED (color));
451 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_GREEN (color));
452 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_BLUE (color));
453 swfdec_bots_put_u8 (bots, SWFDEC_COLOR_ALPHA (color));