diff options
-rw-r--r-- | gdk-pixbuf/pixops/pixops.c | 55 | ||||
-rw-r--r-- | tests/pixbuf-composite.c | 92 |
2 files changed, 132 insertions, 15 deletions
diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c index 6a4a09629..11ff2415a 100644 --- a/gdk-pixbuf/pixops/pixops.c +++ b/gdk-pixbuf/pixops/pixops.c @@ -437,21 +437,51 @@ pixops_composite_nearest_noscale (guchar *dest_buf, gboolean src_has_alpha, int overall_alpha) { - int i, j; - int x; + gint64 i; + gint64 x; + gint64 xmax, xstart, xstop, y_pos; + const guchar *p; + unsigned int a0; + +#define INNER_LOOP_NOSCALE(SRC_CHANNELS,DEST_CHANNELS,ASSIGN_PIXEL) \ + xmax = x + (render_x1 - render_x0); \ + xstart = MIN (0, xmax); \ + xstop = MIN (src_width, xmax); \ + p = src + CLAMP (x, xstart, xstop) * SRC_CHANNELS; \ + while (x < xstart) \ + { \ + ASSIGN_PIXEL; \ + dest += DEST_CHANNELS; \ + x++; \ + } \ + p = src + x * SRC_CHANNELS; \ + while (x < xstop) \ + { \ + ASSIGN_PIXEL; \ + dest += DEST_CHANNELS; \ + x++; \ + p += SRC_CHANNELS; \ + } \ + p = src + CLAMP (x, 0, src_width - 1) * SRC_CHANNELS; \ + while (x < xmax) \ + { \ + ASSIGN_PIXEL; \ + dest += DEST_CHANNELS; \ + x++; \ + } for (i = 0; i < (render_y1 - render_y0); i++) { - const guchar *src = src_buf + (gsize)(i + render_y0) * src_rowstride; - guchar *dest = dest_buf + (gsize)i * dest_rowstride; - - x = render_x0 * src_channels; + const guchar *src; + guchar *dest; + y_pos = i + render_y0; + y_pos = CLAMP (y_pos, 0, src_height - 1); + src = src_buf + (gsize)y_pos * src_rowstride; + dest = dest_buf + (gsize)i * dest_rowstride; - for (j=0; j < (render_x1 - render_x0); j++) - { - const guchar *p = src + x; - unsigned int a0; + x = render_x0; + INNER_LOOP_NOSCALE(src_channels, dest_channels, if (src_has_alpha) a0 = (p[3] * overall_alpha) / 0xff; else @@ -494,11 +524,10 @@ pixops_composite_nearest_noscale (guchar *dest_buf, } break; } - dest += dest_channels; - x += src_channels; - } + ); } } +#undef INNER_LOOP_NOSCALE static void pixops_composite_color_nearest (guchar *dest_buf, diff --git a/tests/pixbuf-composite.c b/tests/pixbuf-composite.c index e8b70fd93..3bd201fab 100644 --- a/tests/pixbuf-composite.c +++ b/tests/pixbuf-composite.c @@ -22,7 +22,7 @@ #include "test-common.h" static void -test_composite (void) +test_composite1 (void) { GdkPixbuf *red, *green, *out, *ref, *sub; @@ -54,12 +54,100 @@ test_composite (void) g_object_unref (sub); } +/* + * Test for Bug 766842 + * https://bugzilla.gnome.org/show_bug.cgi?id=766842 + */ +static void +test_composite2 (void) +{ + GdkPixbuf *src, *dest; + guchar *pixels, *p; + + src = gdk_pixbuf_new_from_file ("test-image.png", NULL); + + { + GdkPixbuf *tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + gdk_pixbuf_get_bits_per_sample (src), + gdk_pixbuf_get_width (src), + gdk_pixbuf_get_height (src)); + gdk_pixbuf_fill (tmp, 0x00ccccff); + gdk_pixbuf_composite (src, tmp, + 0, 0, gdk_pixbuf_get_width (tmp), gdk_pixbuf_get_height (tmp), + 0., 0., 1., 1., + GDK_INTERP_NEAREST, 255); + g_object_unref (src); + src = tmp; + } + + pixels = gdk_pixbuf_get_pixels (src); + p = pixels; + p[0] = 0xff; + p[1] = 0x00; + p[2] = 0xff; + p = pixels + (gsize)((gdk_pixbuf_get_height (src) - 1) * gdk_pixbuf_get_rowstride (src)) + (gsize)((gdk_pixbuf_get_width (src) - 1) * gdk_pixbuf_get_n_channels (src)); + p[0] = 0xff; + p[1] = 0xff; + p[2] = 0x00; + + dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + gdk_pixbuf_get_bits_per_sample (src), + gdk_pixbuf_get_width (src) + 80, + gdk_pixbuf_get_height (src) + 80); + gdk_pixbuf_fill (dest, 0xffffffff); + gdk_pixbuf_composite (src, dest, + 0, 0, gdk_pixbuf_get_width (dest), gdk_pixbuf_get_height (dest), + 10.0, 10.0, 1.0, 1.0, + GDK_INTERP_NEAREST, 255); + + pixels = gdk_pixbuf_get_pixels (dest); + p = pixels; + g_assert_cmpint (p[0], ==, 0xff); + g_assert_cmpint (p[1], ==, 0x00); + g_assert_cmpint (p[2], ==, 0xff); + p = pixels + (gsize)((gdk_pixbuf_get_height (dest) - 1) * gdk_pixbuf_get_rowstride (dest)) + (gsize)((gdk_pixbuf_get_width (dest) - 1) * gdk_pixbuf_get_n_channels (dest)); + g_assert_cmpint (p[0], ==, 0xff); + g_assert_cmpint (p[1], ==, 0xff); + g_assert_cmpint (p[2], ==, 0x00); + + g_object_unref (dest); + + /* now try compositing into a pixbuf that is 1px less in width and height */ + dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + gdk_pixbuf_get_bits_per_sample (src), + gdk_pixbuf_get_width (src) - 1, + gdk_pixbuf_get_height (src) - 1); + gdk_pixbuf_fill (dest, 0xffffffff); + gdk_pixbuf_composite (src, dest, + 0, 0, gdk_pixbuf_get_width (dest), gdk_pixbuf_get_height (dest), + -1.0, -2.0, 1.0, 1.0, + GDK_INTERP_NEAREST, 255); + + pixels = gdk_pixbuf_get_pixels (dest); + p = pixels + (gsize)((gdk_pixbuf_get_height (dest) - 2) * gdk_pixbuf_get_rowstride (dest)) + (gsize)((gdk_pixbuf_get_width (dest) - 1) * gdk_pixbuf_get_n_channels (dest)); + g_assert_cmpint (p[0], ==, 0xff); + g_assert_cmpint (p[1], ==, 0xff); + g_assert_cmpint (p[2], ==, 0x00); + p = pixels + (gsize)((gdk_pixbuf_get_height (dest) - 1) * gdk_pixbuf_get_rowstride (dest)) + (gsize)((gdk_pixbuf_get_width (dest) - 1) * gdk_pixbuf_get_n_channels (dest)); + g_assert_cmpint (p[0], ==, 0xff); + g_assert_cmpint (p[1], ==, 0xff); + g_assert_cmpint (p[2], ==, 0x00); + + g_object_unref (dest); + + g_object_unref (src); +} + int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_add_func ("/pixbuf/composite", test_composite); + g_test_add_func ("/pixbuf/composite1", test_composite1); + g_test_add_func ("/pixbuf/composite2", test_composite2); return g_test_run (); } |