add test for frames and bytes properties of empty movies
[swfdec.git] / test / swfdec_out.c
blobecf5a830a10885a75f9c0345fe68deb5390006e5
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_out.h"
28 SwfdecOut *
29 swfdec_out_open (void)
31 SwfdecOut *out = g_new0 (SwfdecOut, 1);
33 out->data = g_malloc (SWFDEC_OUT_INITIAL);
34 out->ptr = out->data;
35 out->end = out->data + SWFDEC_OUT_INITIAL;
37 return out;
40 static void
41 swfdec_out_syncbits (SwfdecOut *out)
43 g_return_if_fail (out != NULL);
45 if (out->idx > 0) {
46 out->ptr++;
47 out->idx = 0;
51 SwfdecBuffer *
52 swfdec_out_close (SwfdecOut *out)
54 SwfdecBuffer *buffer;
56 g_return_val_if_fail (out != NULL, NULL);
58 swfdec_out_syncbits (out);
60 buffer = swfdec_buffer_new ();
61 buffer->data = out->data;
62 buffer->length = out->ptr - out->data;
64 g_free (out);
66 return buffer;
69 unsigned int
70 swfdec_out_get_bits (SwfdecOut *out)
72 g_return_val_if_fail (out != NULL, 0);
74 return (out->ptr - out->data) * 8 + out->idx;
77 unsigned int
78 swfdec_out_left (SwfdecOut *out)
80 g_return_val_if_fail (out != NULL, 0);
82 return (out->end - out->ptr) * 8 - out->idx;
85 void
86 swfdec_out_ensure_bits (SwfdecOut *out, unsigned int bits)
88 unsigned int current, taken, needed;
90 g_return_if_fail (out != NULL);
92 current = swfdec_out_left (out);
93 if (current >= bits)
94 return;
95 taken = out->ptr - out->data;
96 needed = (bits - current + 7) / 8;
97 needed += SWFDEC_OUT_STEP;
98 needed -= needed % SWFDEC_OUT_STEP;
99 needed += out->end - out->data;
100 out->data = g_realloc (out->data, needed);
101 out->ptr = out->data + taken;
102 out->end = out->data + needed;
105 void
106 swfdec_out_prepare_bytes (SwfdecOut *out, unsigned int bytes)
108 g_return_if_fail (out != NULL);
110 swfdec_out_syncbits (out);
111 swfdec_out_ensure_bits (out, bytes * 8);
114 void
115 swfdec_out_put_data (SwfdecOut *out, const guint8 *data, guint length)
117 g_return_if_fail (out != NULL);
119 swfdec_out_prepare_bytes (out, length);
120 memcpy (out->ptr, data, length);
121 out->ptr += length;
124 void
125 swfdec_out_put_buffer (SwfdecOut *out, SwfdecBuffer *buffer)
127 g_return_if_fail (out != NULL);
129 swfdec_out_prepare_bytes (out, buffer->length);
130 memcpy (out->ptr, buffer->data, buffer->length);
131 out->ptr += buffer->length;
134 void
135 swfdec_out_put_u8 (SwfdecOut *out, guint i)
137 g_return_if_fail (i <= G_MAXUINT8);
139 swfdec_out_prepare_bytes (out, 1);
140 *out->ptr = i;
141 out->ptr++;
144 void
145 swfdec_out_put_u16 (SwfdecOut *out, guint i)
147 g_return_if_fail (i <= G_MAXUINT16);
149 swfdec_out_prepare_bytes (out, 2);
150 *(guint16 *)out->ptr = GUINT16_TO_LE (i);
151 out->ptr += 2;
154 void
155 swfdec_out_put_u32 (SwfdecOut *out, guint i)
157 g_return_if_fail (i <= G_MAXUINT32);
159 swfdec_out_prepare_bytes (out, 4);
160 *(guint32 *)out->ptr = GUINT32_TO_LE (i);
161 out->ptr += 4;
164 void
165 swfdec_out_put_bit (SwfdecOut *out, gboolean bit)
167 g_return_if_fail (out != NULL);
169 swfdec_out_put_bits (out, bit ? 1 : 0, 1);
172 void
173 swfdec_out_put_bits (SwfdecOut *out, guint bits, guint n_bits)
175 g_return_if_fail (out != NULL);
177 swfdec_out_ensure_bits (out, n_bits);
179 /* FIXME: implement this less braindead */
180 while (n_bits) {
181 guint bits_now = MIN (n_bits, 8 - out->idx);
182 guint value = bits >> (n_bits - bits_now);
184 /* clear data if necessary */
185 if (out->idx == 0)
186 *out->ptr = 0;
187 value &= (1 << bits_now) - 1;
188 value <<= 8 - out->idx - bits_now;
189 *out->ptr |= value;
190 out->idx += bits_now;
191 g_assert (out->idx <= 8);
192 if (out->idx == 8) {
193 out->ptr ++;
194 out->idx = 0;
196 n_bits -= bits_now;
200 void
201 swfdec_out_put_sbits (SwfdecOut *out, int bits, guint n_bits)
203 g_return_if_fail (out != NULL);
204 swfdec_out_put_bits (out, bits, n_bits);
207 void
208 swfdec_out_put_string (SwfdecOut *out, const char *s)
210 guint len;
212 g_return_if_fail (out != NULL);
213 g_return_if_fail (s != NULL);
215 len = strlen (s) + 1;
217 swfdec_out_prepare_bytes (out, len);
218 memcpy (out->ptr, s, len);
219 out->ptr += len;
222 static guint
223 swfdec_out_bits_required (guint x)
225 guint ret = 0;
227 while (x > 0) {
228 x >>= 1;
229 ret++;
231 return ret;
234 static guint
235 swfdec_out_sbits_required (int x)
237 if (x < 0)
238 x = !x;
239 return swfdec_out_bits_required (x) + 1;
242 void
243 swfdec_out_put_rect (SwfdecOut *out, const SwfdecRect *rect)
245 int x0, x1, y0, y1;
246 guint req, tmp;
248 g_return_if_fail (out != NULL);
249 g_return_if_fail (rect != NULL);
251 x0 = rect->x0;
252 y0 = rect->y0;
253 x1 = rect->x1;
254 y1 = rect->y1;
255 req = swfdec_out_sbits_required (x0);
256 tmp = swfdec_out_sbits_required (y0);
257 req = MAX (req, tmp);
258 tmp = swfdec_out_sbits_required (x1);
259 req = MAX (req, tmp);
260 tmp = swfdec_out_sbits_required (y1);
261 req = MAX (req, tmp);
262 swfdec_out_syncbits (out);
263 swfdec_out_put_bits (out, req, 5);
264 swfdec_out_put_sbits (out, x0, req);
265 swfdec_out_put_sbits (out, x1, req);
266 swfdec_out_put_sbits (out, y0, req);
267 swfdec_out_put_sbits (out, y1, req);
268 swfdec_out_syncbits (out);
271 void
272 swfdec_out_put_matrix (SwfdecOut *out, const cairo_matrix_t *matrix)
274 int x, y;
275 unsigned int xbits, ybits;
277 if (matrix->xx != 1.0 || matrix->yy != 1.0) {
278 swfdec_out_put_bit (out, 1);
279 x = SWFDEC_DOUBLE_TO_FIXED (matrix->xx);
280 y = SWFDEC_DOUBLE_TO_FIXED (matrix->yy);
281 xbits = swfdec_out_sbits_required (x);
282 ybits = swfdec_out_sbits_required (y);
283 xbits = MAX (xbits, ybits);
284 swfdec_out_put_bits (out, xbits, 5);
285 swfdec_out_put_sbits (out, x, xbits);
286 swfdec_out_put_sbits (out, y, xbits);
287 } else {
288 swfdec_out_put_bit (out, 0);
290 if (matrix->xy != 0.0 || matrix->yx != 0.0) {
291 swfdec_out_put_bit (out, 1);
292 x = SWFDEC_DOUBLE_TO_FIXED (matrix->yx);
293 y = SWFDEC_DOUBLE_TO_FIXED (matrix->xy);
294 xbits = swfdec_out_sbits_required (x);
295 ybits = swfdec_out_sbits_required (y);
296 xbits = MAX (xbits, ybits);
297 swfdec_out_put_bits (out, xbits, 5);
298 swfdec_out_put_sbits (out, x, xbits);
299 swfdec_out_put_sbits (out, y, xbits);
300 } else {
301 swfdec_out_put_bit (out, 0);
303 x = matrix->x0;
304 y = matrix->y0;
305 xbits = swfdec_out_sbits_required (x);
306 ybits = swfdec_out_sbits_required (y);
307 xbits = MAX (xbits, ybits);
308 swfdec_out_put_bits (out, xbits, 5);
309 swfdec_out_put_sbits (out, x, xbits);
310 swfdec_out_put_sbits (out, y, xbits);
311 swfdec_out_syncbits (out);
314 void
315 swfdec_out_put_color_transform (SwfdecOut *out, const SwfdecColorTransform *trans)
317 gboolean has_add, has_mult;
318 unsigned int n_bits, tmp;
320 has_mult = trans->ra != 256 || trans->ga != 256 || trans->ba != 256 || trans->aa != 256;
321 has_add = trans->rb != 0 || trans->gb != 0 || trans->bb != 0 || trans->ab != 0;
322 if (has_mult) {
323 n_bits = swfdec_out_sbits_required (trans->ra);
324 tmp = swfdec_out_sbits_required (trans->ga);
325 n_bits = MAX (tmp, n_bits);
326 tmp = swfdec_out_sbits_required (trans->ba);
327 n_bits = MAX (tmp, n_bits);
328 tmp = swfdec_out_sbits_required (trans->aa);
329 n_bits = MAX (tmp, n_bits);
330 } else {
331 n_bits = 0;
333 if (has_add) {
334 tmp = swfdec_out_sbits_required (trans->rb);
335 n_bits = MAX (tmp, n_bits);
336 tmp = swfdec_out_sbits_required (trans->gb);
337 n_bits = MAX (tmp, n_bits);
338 tmp = swfdec_out_sbits_required (trans->bb);
339 n_bits = MAX (tmp, n_bits);
340 tmp = swfdec_out_sbits_required (trans->ab);
341 n_bits = MAX (tmp, n_bits);
343 if (n_bits >= (1 << 4))
344 n_bits = (1 << 4) - 1;
345 swfdec_out_put_bit (out, has_add);
346 swfdec_out_put_bit (out, has_mult);
347 swfdec_out_put_bits (out, n_bits, 4);
348 if (has_mult) {
349 swfdec_out_put_sbits (out, trans->ra, n_bits);
350 swfdec_out_put_sbits (out, trans->ga, n_bits);
351 swfdec_out_put_sbits (out, trans->ba, n_bits);
352 swfdec_out_put_sbits (out, trans->aa, n_bits);
354 if (has_add) {
355 swfdec_out_put_sbits (out, trans->rb, n_bits);
356 swfdec_out_put_sbits (out, trans->gb, n_bits);
357 swfdec_out_put_sbits (out, trans->bb, n_bits);
358 swfdec_out_put_sbits (out, trans->ab, n_bits);
360 swfdec_out_syncbits (out);
363 void
364 swfdec_out_put_rgb (SwfdecOut *out, SwfdecColor color)
366 g_return_if_fail (out != NULL);
368 swfdec_out_put_u8 (out, SWFDEC_COLOR_R (color));
369 swfdec_out_put_u8 (out, SWFDEC_COLOR_G (color));
370 swfdec_out_put_u8 (out, SWFDEC_COLOR_B (color));
373 void
374 swfdec_out_put_rgba (SwfdecOut *out, SwfdecColor color)
376 g_return_if_fail (out != NULL);
378 swfdec_out_put_u8 (out, SWFDEC_COLOR_R (color));
379 swfdec_out_put_u8 (out, SWFDEC_COLOR_G (color));
380 swfdec_out_put_u8 (out, SWFDEC_COLOR_B (color));
381 swfdec_out_put_u8 (out, SWFDEC_COLOR_A (color));