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.
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
24 #include "swfdec_test_image.h"
25 #include "swfdec_test_function.h"
26 #include "swfdec_test_utils.h"
28 #define SWFDEC_TEST_IMAGE_IS_VALID(image) ((image)->surface && \
29 cairo_surface_status ((image)->surface) == CAIRO_STATUS_SUCCESS)
32 swfdec_test_image_new (SwfdecAsContext
*context
, guint width
, guint height
)
35 SwfdecAsObject
*object
;
37 ret
= g_object_new (SWFDEC_TYPE_TEST_IMAGE
, "context", context
, NULL
);
38 ret
->surface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
, width
, height
);
40 object
= swfdec_as_object_new (context
, NULL
);
41 swfdec_as_object_set_constructor_by_name (object
,
42 swfdec_as_context_get_string (context
, "Image"), NULL
);
43 swfdec_as_object_set_relay (object
, SWFDEC_AS_RELAY (ret
));
48 /*** SWFDEC_TEST_IMAGE ***/
50 G_DEFINE_TYPE (SwfdecTestImage
, swfdec_test_image
, SWFDEC_TYPE_AS_RELAY
)
53 swfdec_test_image_dispose (GObject
*object
)
55 SwfdecTestImage
*image
= SWFDEC_TEST_IMAGE (object
);
58 cairo_surface_destroy (image
->surface
);
59 image
->surface
= NULL
;
62 G_OBJECT_CLASS (swfdec_test_image_parent_class
)->dispose (object
);
66 swfdec_test_image_class_init (SwfdecTestImageClass
*klass
)
68 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
70 object_class
->dispose
= swfdec_test_image_dispose
;
74 swfdec_test_image_init (SwfdecTestImage
*this)
80 /* Compare two buffers, returning the number of pixels that are
81 * different and the maximum difference of any single color channel in
84 * This function should be rewritten to compare all formats supported by
85 * cairo_format_t instead of taking a mask as a parameter.
88 buffer_diff_core (unsigned char *buf_a
,
90 unsigned char *buf_diff
,
98 gboolean result
= TRUE
;
99 guint32
*row_a
, *row_b
, *row
;
101 for (y
= 0; y
< height
; y
++) {
102 row_a
= (guint32
*) (buf_a
+ y
* stride_a
);
103 row_b
= (guint32
*) (buf_b
+ y
* stride_b
);
104 row
= (guint32
*) (buf_diff
+ y
* stride_diff
);
105 for (x
= 0; x
< width
; x
++) {
106 /* check if the pixels are the same */
107 if (row_a
[x
] != row_b
[x
]) {
109 static const unsigned int threshold
= 3;
110 guint32 diff_pixel
= 0;
112 /* calculate a difference value for all 4 channels */
113 for (channel
= 0; channel
< 4; channel
++) {
114 int value_a
= (row_a
[x
] >> (channel
*8)) & 0xff;
115 int value_b
= (row_b
[x
] >> (channel
*8)) & 0xff;
117 diff
= ABS (value_a
- value_b
);
118 if (diff
<= threshold
)
120 diff
*= 4; /* emphasize */
121 diff
+= 128; /* make sure it's visible */
124 diff_pixel
|= diff
<< (channel
*8);
133 row
[x
] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
139 SWFDEC_TEST_FUNCTION ("Image_compare", swfdec_test_image_compare
)
141 swfdec_test_image_compare (SwfdecAsContext
*cx
, SwfdecAsObject
*object
, guint argc
,
142 SwfdecAsValue
*argv
, SwfdecAsValue
*retval
)
144 SwfdecTestImage
*image
, *compare
, *diff
;
148 SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_IMAGE
, &image
, "o", &o
);
150 if (!SWFDEC_IS_TEST_IMAGE (o
->relay
))
152 compare
= SWFDEC_TEST_IMAGE (o
->relay
);
154 SWFDEC_AS_VALUE_SET_OBJECT (retval
, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (image
)));
155 if (!SWFDEC_TEST_IMAGE_IS_VALID (image
) ||
156 !SWFDEC_TEST_IMAGE_IS_VALID (compare
))
159 g_assert (cairo_surface_get_type (image
->surface
) == CAIRO_SURFACE_TYPE_IMAGE
);
160 g_assert (cairo_surface_get_type (compare
->surface
) == CAIRO_SURFACE_TYPE_IMAGE
);
162 w
= cairo_image_surface_get_width (image
->surface
);
163 if (w
!= cairo_image_surface_get_width (compare
->surface
))
165 h
= cairo_image_surface_get_height (image
->surface
);
166 if (h
!= cairo_image_surface_get_height (compare
->surface
))
168 diff
= SWFDEC_TEST_IMAGE (swfdec_test_image_new (cx
, w
, h
));
170 if (!buffer_diff_core (cairo_image_surface_get_data (image
->surface
),
171 cairo_image_surface_get_data (compare
->surface
),
172 cairo_image_surface_get_data (diff
->surface
),
174 cairo_image_surface_get_stride (image
->surface
),
175 cairo_image_surface_get_stride (compare
->surface
),
176 cairo_image_surface_get_stride (diff
->surface
)) != 0) {
177 SWFDEC_AS_VALUE_SET_OBJECT (retval
,
178 swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (diff
)));
180 SWFDEC_AS_VALUE_SET_NULL (retval
);
184 SWFDEC_TEST_FUNCTION ("Image_save", swfdec_test_image_save
)
186 swfdec_test_image_save (SwfdecAsContext
*cx
, SwfdecAsObject
*object
, guint argc
,
187 SwfdecAsValue
*argv
, SwfdecAsValue
*retval
)
189 SwfdecTestImage
*image
;
190 const char *filename
;
191 cairo_status_t status
;
193 SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_IMAGE
, &image
, "s", &filename
);
195 SWFDEC_AS_VALUE_SET_BOOLEAN (retval
, FALSE
);
196 if (!SWFDEC_TEST_IMAGE_IS_VALID (image
))
199 status
= cairo_surface_write_to_png (image
->surface
, filename
);
200 if (status
!= CAIRO_STATUS_SUCCESS
) {
201 swfdec_test_throw (cx
, "Couldn't save to %s: %s", filename
, cairo_status_to_string (status
));
204 SWFDEC_AS_VALUE_SET_BOOLEAN (retval
, TRUE
);
207 SWFDEC_TEST_FUNCTION ("Image", swfdec_test_image_create
)
209 swfdec_test_image_create (SwfdecAsContext
*cx
, SwfdecAsObject
*object
, guint argc
,
210 SwfdecAsValue
*argv
, SwfdecAsValue
*retval
)
212 SwfdecTestImage
*image
;
213 const char *filename
;
215 if (!swfdec_as_context_is_constructing (cx
))
218 SWFDEC_AS_CHECK (0, NULL
, "s", &filename
);
220 image
= g_object_new (SWFDEC_TYPE_TEST_IMAGE
, "context", cx
, NULL
);
221 image
->surface
= cairo_image_surface_create_from_png (filename
);
223 swfdec_as_object_set_relay (object
, SWFDEC_AS_RELAY (image
));
224 SWFDEC_AS_VALUE_SET_OBJECT (retval
, object
);