use the correct matrix
[swfdec.git] / swfdec / swfdec_bitmap_data.c
blob5c3ed4547bc0f09e9b7d906fe33168c4eaa0d45b
1 /* Swfdec
2 * Copyright (C) 2007 Pekka Lampila <pekka.lampila@iki.fi>
3 * 2008 Benjamin Otte <otte@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "swfdec_bitmap_data.h"
27 #include <math.h>
29 #include "swfdec_as_context.h"
30 #include "swfdec_as_frame_internal.h"
31 #include "swfdec_as_internal.h"
32 #include "swfdec_as_native_function.h"
33 #include "swfdec_as_strings.h"
34 #include "swfdec_color.h"
35 #include "swfdec_color_transform_as.h"
36 #include "swfdec_debug.h"
37 #include "swfdec_image.h"
38 #include "swfdec_player_internal.h"
39 #include "swfdec_rectangle.h"
40 #include "swfdec_renderer_internal.h"
41 #include "swfdec_resource.h"
42 #include "swfdec_utils.h"
44 enum {
45 INVALIDATE,
46 LAST_SIGNAL
49 static guint signals[LAST_SIGNAL];
50 G_DEFINE_TYPE (SwfdecBitmapData, swfdec_bitmap_data, SWFDEC_TYPE_AS_OBJECT)
52 static void
53 swfdec_bitmap_data_invalidate (SwfdecBitmapData *bitmap, guint x, guint y, guint w, guint h)
55 SwfdecRectangle rect = { x, y, w, h };
57 g_return_if_fail (w > 0);
58 g_return_if_fail (h > 0);
60 g_signal_emit (bitmap, signals[INVALIDATE], 0, &rect);
63 static void
64 swfdec_bitmap_data_clear (SwfdecBitmapData *bitmap)
66 int w, h;
68 if (bitmap->surface == NULL)
69 return;
71 w = cairo_image_surface_get_width (bitmap->surface);
72 h = cairo_image_surface_get_height (bitmap->surface);
73 swfdec_bitmap_data_invalidate (bitmap, 0, 0, w, h);
74 swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (bitmap), 4 * w * h);
75 cairo_surface_destroy (bitmap->surface);
76 bitmap->surface = NULL;
79 static void
80 swfdec_bitmap_data_dispose (GObject *object)
82 SwfdecBitmapData *bitmap = SWFDEC_BITMAP_DATA (object);
84 swfdec_bitmap_data_clear (bitmap);
86 G_OBJECT_CLASS (swfdec_bitmap_data_parent_class)->dispose (object);
89 static void
90 swfdec_bitmap_data_class_init (SwfdecBitmapDataClass *klass)
92 GObjectClass *object_class = G_OBJECT_CLASS (klass);
94 object_class->dispose = swfdec_bitmap_data_dispose;
96 signals[INVALIDATE] = g_signal_new ("invalidate", G_TYPE_FROM_CLASS (klass),
97 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED,
98 G_TYPE_NONE, 1, SWFDEC_TYPE_RECTANGLE);
101 static void
102 swfdec_bitmap_data_init (SwfdecBitmapData *transform)
106 SwfdecBitmapData *
107 swfdec_bitmap_data_new (SwfdecAsContext *context, gboolean transparent, guint width, guint height)
109 SwfdecBitmapData *bitmap;
111 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
112 g_return_val_if_fail (width > 0, NULL);
113 g_return_val_if_fail (height > 0, NULL);
115 if (!swfdec_as_context_try_use_mem (context, width * height * 4))
116 return NULL;
118 bitmap = g_object_new (SWFDEC_TYPE_BITMAP_DATA, "context", context, NULL);
119 bitmap->surface = cairo_image_surface_create (
120 transparent ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height);
122 swfdec_as_object_set_constructor_by_name (SWFDEC_AS_OBJECT (bitmap),
123 SWFDEC_AS_STR_flash, SWFDEC_AS_STR_display, SWFDEC_AS_STR_BitmapData, NULL);
125 return bitmap;
128 #define swfdec_surface_has_alpha(surface) (cairo_surface_get_content (surface) & CAIRO_CONTENT_ALPHA)
130 SWFDEC_AS_NATIVE (1100, 40, swfdec_bitmap_data_loadBitmap)
131 void
132 swfdec_bitmap_data_loadBitmap (SwfdecAsContext *cx, SwfdecAsObject *object,
133 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
135 SwfdecBitmapData *bitmap;
136 SwfdecImage *image;
137 const char *name;
138 cairo_surface_t *isurface;
139 cairo_t *cr;
141 SWFDEC_AS_CHECK (0, NULL, "s", &name);
143 g_assert (SWFDEC_IS_MOVIE (cx->frame->target));
144 image = swfdec_resource_get_export (SWFDEC_MOVIE (cx->frame->target)->resource, name);
145 if (!SWFDEC_IS_IMAGE (image)) {
146 SWFDEC_ERROR ("loadBitmap cannot find image with name %s", name);
147 return;
150 /* FIXME: improve this to not create an image if there is one cached */
151 isurface = swfdec_image_create_surface (image, NULL);
152 if (isurface == NULL)
153 return;
155 /* FIXME: use image directly instead of doing a copy and then deleting it */
156 bitmap = swfdec_bitmap_data_new (cx,
157 swfdec_surface_has_alpha (isurface),
158 cairo_image_surface_get_width (isurface),
159 cairo_image_surface_get_height (isurface));
160 if (bitmap == NULL)
161 return;
163 cr = cairo_create (bitmap->surface);
164 cairo_set_source_surface (cr, isurface, 0, 0);
165 cairo_paint (cr);
166 cairo_destroy (cr);
167 cairo_surface_destroy (isurface);
168 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (bitmap));
171 // properties
172 SWFDEC_AS_NATIVE (1100, 100, swfdec_bitmap_data_get_width)
173 void
174 swfdec_bitmap_data_get_width (SwfdecAsContext *cx, SwfdecAsObject *object,
175 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
177 SwfdecBitmapData *bitmap;
179 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
181 SWFDEC_AS_VALUE_SET_INT (ret, bitmap->surface ?
182 cairo_image_surface_get_width (bitmap->surface) : -1);
185 SWFDEC_AS_NATIVE (1100, 101, swfdec_bitmap_data_set_width)
186 void
187 swfdec_bitmap_data_set_width (SwfdecAsContext *cx, SwfdecAsObject *object,
188 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
190 SWFDEC_STUB ("BitmapData.width (set)");
193 SWFDEC_AS_NATIVE (1100, 102, swfdec_bitmap_data_get_height)
194 void
195 swfdec_bitmap_data_get_height (SwfdecAsContext *cx, SwfdecAsObject *object,
196 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
198 SwfdecBitmapData *bitmap;
200 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
202 SWFDEC_AS_VALUE_SET_INT (ret, bitmap->surface ?
203 cairo_image_surface_get_height (bitmap->surface) : -1);
206 SWFDEC_AS_NATIVE (1100, 103, swfdec_bitmap_data_set_height)
207 void
208 swfdec_bitmap_data_set_height (SwfdecAsContext *cx, SwfdecAsObject *object,
209 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
211 SWFDEC_STUB ("BitmapData.height (set)");
214 SWFDEC_AS_NATIVE (1100, 104, swfdec_bitmap_data_get_rectangle)
215 void
216 swfdec_bitmap_data_get_rectangle (SwfdecAsContext *cx, SwfdecAsObject *object,
217 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
219 SwfdecBitmapData *bitmap;
220 SwfdecAsObject *o;
221 SwfdecAsValue args[4];
223 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
225 SWFDEC_AS_VALUE_SET_INT (ret, -1);
226 if (bitmap->surface == NULL)
227 return;
229 swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_flash, args);
230 if (!SWFDEC_AS_VALUE_IS_OBJECT (args))
231 return;
232 o = SWFDEC_AS_VALUE_GET_OBJECT (args);
233 swfdec_as_object_get_variable (o, SWFDEC_AS_STR_geom, args);
234 if (!SWFDEC_AS_VALUE_IS_OBJECT (args))
235 return;
236 o = SWFDEC_AS_VALUE_GET_OBJECT (args);
237 swfdec_as_object_get_variable (o, SWFDEC_AS_STR_Rectangle, args);
238 if (!SWFDEC_AS_VALUE_IS_OBJECT (args))
239 return;
240 o = SWFDEC_AS_VALUE_GET_OBJECT (args);
241 if (!SWFDEC_IS_AS_FUNCTION (o))
242 return;
244 SWFDEC_AS_VALUE_SET_INT (&args[0], 0);
245 SWFDEC_AS_VALUE_SET_INT (&args[1], 0);
246 SWFDEC_AS_VALUE_SET_INT (&args[2], cairo_image_surface_get_width (bitmap->surface));
247 SWFDEC_AS_VALUE_SET_INT (&args[3], cairo_image_surface_get_width (bitmap->surface));
248 swfdec_as_object_create (SWFDEC_AS_FUNCTION (o), 4, args, ret);
251 SWFDEC_AS_NATIVE (1100, 105, swfdec_bitmap_data_set_rectangle)
252 void
253 swfdec_bitmap_data_set_rectangle (SwfdecAsContext *cx, SwfdecAsObject *object,
254 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
256 SWFDEC_STUB ("BitmapData.rectangle (set)");
259 SWFDEC_AS_NATIVE (1100, 106, swfdec_bitmap_data_get_transparent)
260 void
261 swfdec_bitmap_data_get_transparent (SwfdecAsContext *cx,
262 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
263 SwfdecAsValue *ret)
265 SwfdecBitmapData *bitmap;
267 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
269 if (bitmap->surface) {
270 SWFDEC_AS_VALUE_SET_BOOLEAN (ret,
271 swfdec_surface_has_alpha (bitmap->surface) ? TRUE : FALSE);
272 } else {
273 SWFDEC_AS_VALUE_SET_INT (ret, -1);
277 SWFDEC_AS_NATIVE (1100, 107, swfdec_bitmap_data_set_transparent)
278 void
279 swfdec_bitmap_data_set_transparent (SwfdecAsContext *cx,
280 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
281 SwfdecAsValue *ret)
283 SWFDEC_STUB ("BitmapData.transparent (set)");
286 #define SWFDEC_COLOR_MULTIPLY(color) SWFDEC_COLOR_COMBINE ( \
287 (SWFDEC_COLOR_ALPHA (color) * SWFDEC_COLOR_RED (color) + 128) / 255, \
288 (SWFDEC_COLOR_ALPHA (color) * SWFDEC_COLOR_GREEN (color) + 128) / 255, \
289 (SWFDEC_COLOR_ALPHA (color) * SWFDEC_COLOR_BLUE (color) + 128) / 255, \
290 SWFDEC_COLOR_ALPHA (color))
292 /* FIXME: This algorithm rounds wrong, no idea how though */
293 #define SWFDEC_COLOR_UNMULTIPLY(color) (SWFDEC_COLOR_ALPHA (color) ? (\
294 SWFDEC_COLOR_ALPHA (color) == 0xFF ? color : SWFDEC_COLOR_COMBINE ( \
295 (SWFDEC_COLOR_RED (color) * 255 + SWFDEC_COLOR_ALPHA (color) / 2) / SWFDEC_COLOR_ALPHA (color), \
296 (SWFDEC_COLOR_GREEN (color) * 255 + SWFDEC_COLOR_ALPHA (color) / 2) / SWFDEC_COLOR_ALPHA (color), \
297 (SWFDEC_COLOR_BLUE (color) * 255 + SWFDEC_COLOR_ALPHA (color) / 2) / SWFDEC_COLOR_ALPHA (color), \
298 SWFDEC_COLOR_ALPHA (color))) : 0)
300 SWFDEC_AS_NATIVE (1100, 1, swfdec_bitmap_data_getPixel)
301 void
302 swfdec_bitmap_data_getPixel (SwfdecAsContext *cx, SwfdecAsObject *object,
303 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
305 SwfdecBitmapData *bitmap;
306 guint x, y, color;
307 guint8 *addr;
309 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "ii", &x, &y);
311 if (bitmap->surface == NULL ||
312 x >= (guint) cairo_image_surface_get_width (bitmap->surface) ||
313 y >= (guint) cairo_image_surface_get_height (bitmap->surface))
314 return;
316 addr = cairo_image_surface_get_data (bitmap->surface);
317 addr += cairo_image_surface_get_stride (bitmap->surface) * y;
318 addr += 4 * x;
319 color = *(SwfdecColor *) addr;
320 color = SWFDEC_COLOR_UNMULTIPLY (color);
321 color &= SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0);
322 SWFDEC_AS_VALUE_SET_INT (ret, color);
325 SWFDEC_AS_NATIVE (1100, 2, swfdec_bitmap_data_setPixel)
326 void
327 swfdec_bitmap_data_setPixel (SwfdecAsContext *cx, SwfdecAsObject *object,
328 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
330 SwfdecBitmapData *bitmap;
331 guint x, y, color;
332 SwfdecColor old;
333 guint8 *addr;
335 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "iii", &x, &y, &color);
337 if (bitmap->surface == NULL ||
338 x >= (guint) cairo_image_surface_get_width (bitmap->surface) ||
339 y >= (guint) cairo_image_surface_get_height (bitmap->surface))
340 return;
342 addr = cairo_image_surface_get_data (bitmap->surface);
343 addr += cairo_image_surface_get_stride (bitmap->surface) * y;
344 addr += 4 * x;
345 old = *(SwfdecColor *) addr;
346 old |= SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0);
347 color = old & SWFDEC_COLOR_OPAQUE (color);
348 *(SwfdecColor *) addr = SWFDEC_COLOR_MULTIPLY (color);
349 cairo_surface_mark_dirty_rectangle (bitmap->surface, x, y, 1, 1);
350 swfdec_bitmap_data_invalidate (bitmap, x, y, 1, 1);
353 SWFDEC_AS_NATIVE (1100, 3, swfdec_bitmap_data_fillRect)
354 void
355 swfdec_bitmap_data_fillRect (SwfdecAsContext *cx, SwfdecAsObject *object,
356 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
358 SWFDEC_STUB ("BitmapData.fillRect");
361 static gboolean
362 swfdec_rectangle_from_as_object (SwfdecRectangle *rect, SwfdecAsObject *object)
364 SwfdecAsValue *val;
365 SwfdecAsContext *cx = swfdec_gc_object_get_context (object);
367 /* FIXME: This function is untested */
368 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_x);
369 rect->x = swfdec_as_value_to_integer (cx, val);
370 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_y);
371 rect->y = swfdec_as_value_to_integer (cx, val);
372 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_width);
373 rect->width = swfdec_as_value_to_integer (cx, val);
374 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_height);
375 rect->height = swfdec_as_value_to_integer (cx, val);
376 return rect->width > 0 && rect->height > 0;
379 static void
380 swfdec_point_from_as_object (int *x, int *y, SwfdecAsObject *object)
382 SwfdecAsValue *val;
383 SwfdecAsContext *cx = swfdec_gc_object_get_context (object);
385 /* FIXME: This function is untested */
386 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_x);
387 *x = swfdec_as_value_to_integer (cx, val);
388 val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_y);
389 *y = swfdec_as_value_to_integer (cx, val);
392 SWFDEC_AS_NATIVE (1100, 4, swfdec_bitmap_data_copyPixels)
393 void
394 swfdec_bitmap_data_copyPixels (SwfdecAsContext *cx, SwfdecAsObject *object,
395 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
397 SwfdecBitmapData *bitmap, *source, *alpha = NULL;
398 SwfdecAsObject *recto, *pt, *apt = NULL;
399 SwfdecRectangle rect;
400 gboolean copy_alpha = FALSE;
401 cairo_t *cr;
402 int x, y;
404 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "ooo|OOb", &source, &recto, &pt,
405 &alpha, &apt, &copy_alpha);
407 if (bitmap->surface == NULL ||
408 !SWFDEC_IS_BITMAP_DATA (source) ||
409 source->surface == NULL ||
410 (argc > 3 && (!SWFDEC_IS_BITMAP_DATA (alpha) || alpha->surface == NULL)) ||
411 !swfdec_rectangle_from_as_object (&rect, recto))
412 return;
414 x = rect.x;
415 y = rect.y;
416 swfdec_point_from_as_object (&rect.x, &rect.y, pt);
417 cr = cairo_create (bitmap->surface);
418 if (bitmap == source) {
419 cairo_surface_t *copy = cairo_surface_create_similar (source->surface,
420 cairo_surface_get_content (source->surface),
421 rect.width, rect.height);
422 cairo_t *cr2 = cairo_create (copy);
423 cairo_set_source_surface (cr2, source->surface, x, y);
424 cairo_paint (cr2);
425 cairo_destroy (cr2);
426 cairo_set_source_surface (cr, copy, rect.x, rect.y);
427 cairo_surface_destroy (copy);
428 } else {
429 cairo_set_source_surface (cr, source->surface, rect.x - x, rect.y - y);
432 if (swfdec_surface_has_alpha (bitmap->surface) && !copy_alpha) {
433 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
436 cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
437 if (alpha) {
438 cairo_surface_t *mask = cairo_surface_create_similar (alpha->surface,
439 CAIRO_CONTENT_COLOR_ALPHA, rect.width, rect.height);
440 cairo_t *cr2 = cairo_create (mask);
442 cairo_surface_set_device_offset (mask, -rect.x, -rect.y);
443 cairo_set_source (cr2, cairo_get_source (cr));
444 if (apt) {
445 swfdec_point_from_as_object (&x, &y, apt);
446 } else {
447 x = y = 0;
449 cairo_mask_surface (cr2, alpha->surface, rect.x - x, rect.y - y);
450 cairo_destroy (cr2);
451 cairo_set_source_surface (cr, mask, 0, 0);
452 cairo_surface_destroy (mask);
454 cairo_fill (cr);
455 cairo_destroy (cr);
456 cairo_surface_mark_dirty_rectangle (bitmap->surface, rect.x, rect.y,
457 rect.width, rect.height);
460 SWFDEC_AS_NATIVE (1100, 5, swfdec_bitmap_data_applyFilter)
461 void
462 swfdec_bitmap_data_applyFilter (SwfdecAsContext *cx, SwfdecAsObject *object,
463 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
465 SWFDEC_STUB ("BitmapData.applyFilter");
468 SWFDEC_AS_NATIVE (1100, 6, swfdec_bitmap_data_scroll)
469 void
470 swfdec_bitmap_data_scroll (SwfdecAsContext *cx, SwfdecAsObject *object,
471 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
473 SWFDEC_STUB ("BitmapData.scroll");
476 SWFDEC_AS_NATIVE (1100, 7, swfdec_bitmap_data_threshold)
477 void
478 swfdec_bitmap_data_threshold (SwfdecAsContext *cx, SwfdecAsObject *object,
479 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
481 SWFDEC_STUB ("BitmapData.threshold");
484 SWFDEC_AS_NATIVE (1100, 8, swfdec_bitmap_data_draw)
485 void
486 swfdec_bitmap_data_draw (SwfdecAsContext *cx, SwfdecAsObject *object,
487 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
489 SwfdecAsObject *o, *matrix = NULL, *trans = NULL;
490 cairo_t *cr;
491 SwfdecColorTransform ctrans;
492 SwfdecBitmapData *bitmap;
493 SwfdecRenderer *renderer;
494 cairo_matrix_t mat;
496 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "o|OO", &o, &matrix, &trans);
498 if (argc >= 2) {
499 if (matrix == NULL || !swfdec_matrix_from_as_object (&mat, matrix))
500 return;
501 } else {
502 cairo_matrix_init_identity (&mat);
504 if (SWFDEC_IS_COLOR_TRANSFORM_AS (trans)) {
505 swfdec_color_transform_get_transform (SWFDEC_COLOR_TRANSFORM_AS (trans), &ctrans);
506 } else {
507 swfdec_color_transform_init_identity (&ctrans);
510 if (argc > 3) {
511 SWFDEC_FIXME ("only the first 3 arguments to Bitmap.draw() are implemented");
514 cr = cairo_create (bitmap->surface);
515 /* FIXME: Do we have a better renderer? */
516 renderer = SWFDEC_PLAYER (cx)->priv->renderer;
517 swfdec_renderer_attach (renderer, cr);
518 cairo_transform (cr, &mat);
520 if (SWFDEC_IS_BITMAP_DATA (o)) {
521 SwfdecBitmapData *src = SWFDEC_BITMAP_DATA (o);
522 if (src->surface) {
523 if (swfdec_color_transform_is_identity (&ctrans)) {
524 cairo_set_source_surface (cr, SWFDEC_BITMAP_DATA (o)->surface, 0, 0);
525 } else {
526 cairo_surface_t *transformed = swfdec_renderer_transform (renderer,
527 SWFDEC_BITMAP_DATA (o)->surface, &ctrans);
528 SWFDEC_FIXME ("unmodified pixels will be treated as -1, not as 0 as in our "
529 "transform code, but we don't know if a pixel is unmodified.");
530 cairo_set_source_surface (cr, transformed, 0, 0);
531 cairo_surface_destroy (transformed);
533 cairo_paint (cr);
535 } else if (SWFDEC_IS_MOVIE (o)) {
536 SwfdecMovie *movie = SWFDEC_MOVIE (o);
537 swfdec_movie_update (movie);
538 cairo_scale (cr, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR);
539 cairo_transform (cr, &movie->inverse_matrix);
540 swfdec_movie_render (movie, cr, &ctrans);
541 } else {
542 SWFDEC_FIXME ("BitmapData.draw() with a %s?", G_OBJECT_TYPE_NAME (o));
545 cairo_destroy (cr);
548 SWFDEC_AS_NATIVE (1100, 9, swfdec_bitmap_data_pixelDissolve)
549 void
550 swfdec_bitmap_data_pixelDissolve (SwfdecAsContext *cx, SwfdecAsObject *object,
551 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
553 SWFDEC_STUB ("BitmapData.pixelDissolve");
556 SWFDEC_AS_NATIVE (1100, 10, swfdec_bitmap_data_getPixel32)
557 void
558 swfdec_bitmap_data_getPixel32 (SwfdecAsContext *cx, SwfdecAsObject *object,
559 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
561 SwfdecBitmapData *bitmap;
562 guint x, y, color;
563 guint8 *addr;
565 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "ii", &x, &y);
567 if (bitmap->surface == NULL ||
568 x >= (guint) cairo_image_surface_get_width (bitmap->surface) ||
569 y >= (guint) cairo_image_surface_get_height (bitmap->surface))
570 return;
572 addr = cairo_image_surface_get_data (bitmap->surface);
573 addr += cairo_image_surface_get_stride (bitmap->surface) * y;
574 addr += 4 * x;
575 color = *(SwfdecColor *) addr;
576 color = SWFDEC_COLOR_UNMULTIPLY (color);
577 SWFDEC_AS_VALUE_SET_INT (ret, color);
580 SWFDEC_AS_NATIVE (1100, 11, swfdec_bitmap_data_setPixel32)
581 void
582 swfdec_bitmap_data_setPixel32 (SwfdecAsContext *cx, SwfdecAsObject *object,
583 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
585 SwfdecBitmapData *bitmap;
586 guint x, y, color;
587 guint8 *addr;
589 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "iii", &x, &y, &color);
591 if (bitmap->surface == NULL ||
592 x >= (guint) cairo_image_surface_get_width (bitmap->surface) ||
593 y >= (guint) cairo_image_surface_get_height (bitmap->surface))
594 return;
596 addr = cairo_image_surface_get_data (bitmap->surface);
597 addr += cairo_image_surface_get_stride (bitmap->surface) * y;
598 addr += 4 * x;
599 if (swfdec_surface_has_alpha (bitmap->surface)) {
600 *(SwfdecColor *) addr = SWFDEC_COLOR_MULTIPLY ((SwfdecColor) color);
601 } else {
602 *(SwfdecColor *) addr = SWFDEC_COLOR_OPAQUE ((SwfdecColor) color);
604 cairo_surface_mark_dirty_rectangle (bitmap->surface, x, y, 1, 1);
605 swfdec_bitmap_data_invalidate (bitmap, x, y, 1, 1);
608 SWFDEC_AS_NATIVE (1100, 12, swfdec_bitmap_data_floodFill)
609 void
610 swfdec_bitmap_data_floodFill (SwfdecAsContext *cx, SwfdecAsObject *object,
611 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
613 SWFDEC_STUB ("BitmapData.floodFill");
616 SWFDEC_AS_NATIVE (1100, 13, swfdec_bitmap_data_getColorBoundsRect)
617 void
618 swfdec_bitmap_data_getColorBoundsRect (SwfdecAsContext *cx,
619 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
620 SwfdecAsValue *ret)
622 SWFDEC_STUB ("BitmapData.getColorBoundsRect");
625 SWFDEC_AS_NATIVE (1100, 14, swfdec_bitmap_data_perlinNoise)
626 void
627 swfdec_bitmap_data_perlinNoise (SwfdecAsContext *cx, SwfdecAsObject *object,
628 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
630 SWFDEC_STUB ("BitmapData.perlinNoise");
633 SWFDEC_AS_NATIVE (1100, 15, swfdec_bitmap_data_colorTransform)
634 void
635 swfdec_bitmap_data_colorTransform (SwfdecAsContext *cx, SwfdecAsObject *object,
636 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
638 SWFDEC_STUB ("BitmapData.colorTransform");
641 SWFDEC_AS_NATIVE (1100, 16, swfdec_bitmap_data_hitTest)
642 void
643 swfdec_bitmap_data_hitTest (SwfdecAsContext *cx, SwfdecAsObject *object,
644 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
646 SWFDEC_STUB ("BitmapData.hitTest");
649 SWFDEC_AS_NATIVE (1100, 17, swfdec_bitmap_data_paletteMap)
650 void
651 swfdec_bitmap_data_paletteMap (SwfdecAsContext *cx, SwfdecAsObject *object,
652 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
654 SWFDEC_STUB ("BitmapData.paletteMap");
657 SWFDEC_AS_NATIVE (1100, 18, swfdec_bitmap_data_merge)
658 void
659 swfdec_bitmap_data_merge (SwfdecAsContext *cx, SwfdecAsObject *object,
660 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
662 SWFDEC_STUB ("BitmapData.merge");
665 SWFDEC_AS_NATIVE (1100, 19, swfdec_bitmap_data_noise)
666 void
667 swfdec_bitmap_data_noise (SwfdecAsContext *cx, SwfdecAsObject *object,
668 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
670 SWFDEC_STUB ("BitmapData.noise");
673 SWFDEC_AS_NATIVE (1100, 20, swfdec_bitmap_data_copyChannel)
674 void
675 swfdec_bitmap_data_copyChannel (SwfdecAsContext *cx, SwfdecAsObject *object,
676 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
678 SWFDEC_STUB ("BitmapData.copyChannel");
681 SWFDEC_AS_NATIVE (1100, 21, swfdec_bitmap_data_clone)
682 void
683 swfdec_bitmap_data_clone (SwfdecAsContext *cx, SwfdecAsObject *object,
684 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
686 SwfdecBitmapData *bitmap, *clone;
687 cairo_t *cr;
689 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
691 if (bitmap->surface == NULL)
692 return;
694 clone = swfdec_bitmap_data_new (cx,
695 swfdec_surface_has_alpha (bitmap->surface),
696 cairo_image_surface_get_width (bitmap->surface),
697 cairo_image_surface_get_height (bitmap->surface));
698 if (clone == NULL)
699 return;
701 cr = cairo_create (clone->surface);
702 cairo_set_source_surface (cr, bitmap->surface, 0, 0);
703 cairo_paint (cr);
704 cairo_destroy (cr);
705 SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (clone));
708 SWFDEC_AS_NATIVE (1100, 22, swfdec_bitmap_data_do_dispose)
709 void
710 swfdec_bitmap_data_do_dispose (SwfdecAsContext *cx, SwfdecAsObject *object,
711 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
713 SwfdecBitmapData *bitmap;
715 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
717 swfdec_bitmap_data_clear (bitmap);
720 SWFDEC_AS_NATIVE (1100, 23, swfdec_bitmap_data_generateFilterRect)
721 void
722 swfdec_bitmap_data_generateFilterRect (SwfdecAsContext *cx,
723 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
724 SwfdecAsValue *ret)
726 SWFDEC_STUB ("BitmapData.generateFilterRect");
729 SWFDEC_AS_NATIVE (1100, 24, swfdec_bitmap_data_compare)
730 void
731 swfdec_bitmap_data_compare (SwfdecAsContext *cx,
732 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
733 SwfdecAsValue *ret)
735 SWFDEC_STUB ("BitmapData.compare");
738 SWFDEC_AS_CONSTRUCTOR (1100, 0, swfdec_bitmap_data_construct, swfdec_bitmap_data_get_type)
739 void
740 swfdec_bitmap_data_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
741 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
743 SwfdecBitmapData *bitmap;
744 int w, h;
745 gboolean transparent = TRUE;
746 guint color = 0;
748 if (!swfdec_as_context_is_constructing (cx))
749 return;
751 SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "ii|bi",
752 &w, &h, &transparent, &color);
754 if (w > 2880 || w <= 0 || h > 2880 || h <= 0) {
755 SWFDEC_FIXME ("the constructor should return undefined here");
756 return;
759 if (!swfdec_as_context_try_use_mem (cx, w * h * 4))
760 return;
761 bitmap->surface = cairo_image_surface_create (
762 transparent ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, w, h);
764 if (color) {
765 cairo_t *cr = cairo_create (bitmap->surface);
766 swfdec_color_set_source (cr, transparent ? color : SWFDEC_COLOR_OPAQUE (color));
767 cairo_paint (cr);
768 cairo_destroy (cr);