[librsvg] tests: test pixbuf contents



commit 77f94b2933b6994c4fbd7dfd458014fb6984987d
Author: Paolo Borelli <pborelli gnome org>
Date:   Wed Dec 26 09:48:52 2018 +0100

    tests: test pixbuf contents
    
    Compare the content returned by the pixbuf api with
    the one rendered with the cairo api. Since we do not
    want to depend on GDK, we copy an utility function from
    gdkcairo.c.

 tests/api.c        |  68 +++++++++++++++++++++-----------
 tests/test-utils.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-utils.h |   3 ++
 3 files changed, 160 insertions(+), 22 deletions(-)
---
diff --git a/tests/api.c b/tests/api.c
index 1f6690ee..e501eefe 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -425,7 +425,7 @@ handle_has_sub (void)
 }
 
 static void
-handle_get_pixbuf (void)
+test_get_pixbuf (gboolean sub)
 {
     char *filename = get_test_filename ("example.svg");
     GError *error = NULL;
@@ -436,39 +436,63 @@ handle_get_pixbuf (void)
     g_assert (handle != NULL);
     g_assert (error == NULL);
 
-    GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf (handle);
+    GdkPixbuf *pixbuf;
+    if (sub) {
+        pixbuf = rsvg_handle_get_pixbuf_sub (handle, EXAMPLE_ONE_ID);
+    } else {
+        pixbuf = rsvg_handle_get_pixbuf (handle);
+    }
+
     g_assert (pixbuf != NULL);
 
+    /* Note that rsvg_handle_get_pixbuf_sub() creates a surface the size of the
+     * whole SVG, not just the size of the sub-element.
+     */
     g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), ==, EXAMPLE_WIDTH);
     g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), ==, EXAMPLE_HEIGHT);
 
+    cairo_surface_t *surface_a = test_utils_cairo_surface_from_pixbuf (pixbuf);
+    cairo_surface_t *surface_b = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, EXAMPLE_WIDTH, 
EXAMPLE_HEIGHT);
+    cairo_surface_t *surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, EXAMPLE_WIDTH, 
EXAMPLE_HEIGHT);
+
     g_object_unref (pixbuf);
-    g_object_unref (handle);
-}
 
-static void
-handle_get_pixbuf_sub (void)
-{
-    char *filename = get_test_filename ("example.svg");
-    GError *error = NULL;
+    g_assert (surface_a != NULL);
+    g_assert (surface_b != NULL);
+    g_assert (surface_diff != NULL);
 
-    RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
-    g_free (filename);
+    cairo_t *cr = cairo_create (surface_b);
+    if (sub) {
+        g_assert (rsvg_handle_render_cairo_sub (handle, cr, EXAMPLE_ONE_ID));
+    } else {
+        g_assert (rsvg_handle_render_cairo (handle, cr));
+    }
+    cairo_destroy (cr);
 
-    g_assert (handle != NULL);
-    g_assert (error == NULL);
+    g_object_unref (handle);
 
-    GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf_sub (handle, EXAMPLE_ONE_ID);
-    g_assert (pixbuf != NULL);
+    TestUtilsBufferDiffResult result = {0, 0};
+    test_utils_compare_surfaces (surface_a, surface_b, surface_diff, &result);
 
-    /* Note that rsvg_handle_get_pixbuf_sub() creates a surface the size of the
-     * whole SVG, not just the size of the sub-element.
-     */
-    g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), ==, EXAMPLE_WIDTH);
-    g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), ==, EXAMPLE_HEIGHT);
+    if (result.pixels_changed && result.max_diff > 0) {
+        g_test_fail ();
+    }
 
-    g_object_unref (pixbuf);
-    g_object_unref (handle);
+    cairo_surface_destroy (surface_a);
+    cairo_surface_destroy (surface_b);
+    cairo_surface_destroy (surface_diff);
+}
+
+static void
+handle_get_pixbuf (void)
+{
+    test_get_pixbuf (FALSE);
+}
+
+static void
+handle_get_pixbuf_sub (void)
+{
+    test_get_pixbuf (TRUE);
 }
 
 static void
diff --git a/tests/test-utils.c b/tests/test-utils.c
index faa4a56d..5b637ad0 100644
--- a/tests/test-utils.c
+++ b/tests/test-utils.c
@@ -100,6 +100,117 @@ test_utils_compare_surfaces (cairo_surface_t           *surface_a,
                     result->pixels_changed, result->max_diff);
 }
 
+/* Copied from gdk_cairo_surface_paint_pixbuf in gdkcairo.c,
+ * we do not want to depend on GDK
+ */
+static void
+test_utils_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
+                                       const GdkPixbuf *pixbuf)
+{
+  gint width, height;
+  guchar *gdk_pixels, *cairo_pixels;
+  int gdk_rowstride, cairo_stride;
+  int n_channels;
+  int j;
+
+  if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+    return;
+
+  /* This function can't just copy any pixbuf to any surface, be
+   * sure to read the invariants here before calling it */
+
+  g_assert (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
+  g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_RGB24 ||
+            cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32);
+  g_assert (cairo_image_surface_get_width (surface) == gdk_pixbuf_get_width (pixbuf));
+  g_assert (cairo_image_surface_get_height (surface) == gdk_pixbuf_get_height (pixbuf));
+
+  cairo_surface_flush (surface);
+
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+  gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+  gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  cairo_stride = cairo_image_surface_get_stride (surface);
+  cairo_pixels = cairo_image_surface_get_data (surface);
+
+  for (j = height; j; j--)
+    {
+      guchar *p = gdk_pixels;
+      guchar *q = cairo_pixels;
+
+      if (n_channels == 3)
+        {
+          guchar *end = p + 3 * width;
+
+          while (p < end)
+            {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+              q[0] = p[2];
+              q[1] = p[1];
+              q[2] = p[0];
+#else
+              q[1] = p[0];
+              q[2] = p[1];
+              q[3] = p[2];
+#endif
+              p += 3;
+              q += 4;
+            }
+        }
+      else
+        {
+          guchar *end = p + 4 * width;
+          guint t1,t2,t3;
+
+#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
+          while (p < end)
+            {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+              MULT(q[0], p[2], p[3], t1);
+              MULT(q[1], p[1], p[3], t2);
+              MULT(q[2], p[0], p[3], t3);
+              q[3] = p[3];
+#else
+              q[0] = p[3];
+              MULT(q[1], p[0], p[3], t1);
+              MULT(q[2], p[1], p[3], t2);
+              MULT(q[3], p[2], p[3], t3);
+#endif
+
+              p += 4;
+              q += 4;
+            }
+
+#undef MULT
+        }
+
+      gdk_pixels += gdk_rowstride;
+      cairo_pixels += cairo_stride;
+    }
+
+  cairo_surface_mark_dirty (surface);
+}
+
+cairo_surface_t *
+test_utils_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf)
+{
+  cairo_surface_t *surface;
+
+  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
+  g_return_val_if_fail (gdk_pixbuf_get_n_channels (pixbuf) == 4, NULL);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        gdk_pixbuf_get_width (pixbuf),
+                                        gdk_pixbuf_get_height (pixbuf));
+
+  test_utils_cairo_surface_paint_pixbuf (surface, pixbuf);
+
+  return surface;
+}
+
 static gchar *data_path = NULL;
 
 const gchar *
diff --git a/tests/test-utils.h b/tests/test-utils.h
index 68819956..fdbf3b66 100644
--- a/tests/test-utils.h
+++ b/tests/test-utils.h
@@ -6,6 +6,7 @@
 
 #include <cairo.h>
 #include <gio/gio.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 
 G_BEGIN_DECLS
 
@@ -19,6 +20,8 @@ void test_utils_compare_surfaces (cairo_surface_t           *surface_a,
                                   cairo_surface_t           *surface_diff,
                                   TestUtilsBufferDiffResult *result);
 
+cairo_surface_t *test_utils_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf);
+
 typedef gboolean (* AddTestFunc) (GFile *file);
 
 const gchar *test_utils_get_test_data_path      (void);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]