Signed-off-by: Tiago Vignatti <tiago.vigna...@nokia.com>
---

This patch is a WIP to remove gdk-pixbuf dependency and use libpng instead.
It is unfinished though and only compositor with simple-client works.

In principle, gdk-pixbuf is a bit bloated and brings a big package dependency
in some platforms which makes harder to try Wayland. On the other hand,
gdk-pixbuf has several modules to convert a bunch of image formats in pixel
data, whereas libpng has only one, obviously. This is the drawback on using
lipng. However, I guess compositor and clients could live happy with libpng
only given they are made for demonstration purposes (well, at least at the
moment).

I won't be playing with this on the next days, but I'd love to help anyone
with this work in the case I got a positive feedback here. Then, the short
TODO on my mind:

- fix command line parsing in compositor.c
- apply analogue changes for other clients and screenshooter


Thanks!

      Tiago

 clients/dnd.c              |    2 +
 clients/image.c            |    6 +++
 clients/window.c           |    6 +++
 compositor/compositor.c    |   92 +++++++++++++++++++++++++++++++++-----------
 compositor/screenshooter.c |    8 ++++
 configure.ac               |    4 +-
 6 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/clients/dnd.c b/clients/dnd.c
index 1625ffd..48d8dc0 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -30,7 +30,9 @@
 #include <sys/time.h>
 #include <cairo.h>
 #include <glib.h>
+#ifdef GDK_STUFF
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
 
 #include "wayland-client.h"
 #include "wayland-glib.h"
diff --git a/clients/image.c b/clients/image.c
index 3eada1e..ca144e4 100644
--- a/clients/image.c
+++ b/clients/image.c
@@ -31,7 +31,9 @@
 #include <time.h>
 #include <cairo.h>
 #include <glib.h>
+#ifdef GDK_STUFF
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
 
 #include "wayland-client.h"
 #include "wayland-glib.h"
@@ -45,6 +47,7 @@ struct image {
        gchar *filename;
 };
 
+#ifdef GDK_STUFF
 static void
 set_source_pixbuf(cairo_t         *cr,
                  const GdkPixbuf *pixbuf,
@@ -133,10 +136,12 @@ set_source_pixbuf(cairo_t         *cr,
                                 src_y + .5 * (src_height - height));
        cairo_surface_destroy(surface);
 }
+#endif
 
 static void
 image_draw(struct image *image)
 {
+#ifdef GDK_STUFF
        struct rectangle allocation;
        GdkPixbuf *pb;
        cairo_t *cr;
@@ -179,6 +184,7 @@ image_draw(struct image *image)
 
        window_flush(image->window);
        cairo_surface_destroy(surface);
+#endif
 }
 
 static void
diff --git a/clients/window.c b/clients/window.c
index b802518..9fa523e 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -33,7 +33,9 @@
 #include <cairo.h>
 #include <glib.h>
 #include <glib-object.h>
+#ifdef GDK_STUFF
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
 #include <sys/mman.h>
 
 #define EGL_EGLEXT_PROTOTYPES 1
@@ -281,6 +283,7 @@ display_create_egl_image_surface_from_file(struct display 
*display,
                                           const char *filename,
                                           struct rectangle *rect)
 {
+#ifdef GDK_STUFF
        cairo_surface_t *surface;
        GdkPixbuf *pixbuf;
        GError *error = NULL;
@@ -335,6 +338,7 @@ display_create_egl_image_surface_from_file(struct display 
*display,
        g_object_unref(pixbuf);
 
        return surface;
+#endif
 }
 
 #endif
@@ -429,6 +433,7 @@ display_create_shm_surface_from_file(struct display 
*display,
                                     const char *filename,
                                     struct rectangle *rect)
 {
+#ifdef GDK_STUFF
        cairo_surface_t *surface;
        GdkPixbuf *pixbuf;
        GError *error = NULL;
@@ -481,6 +486,7 @@ display_create_shm_surface_from_file(struct display 
*display,
        g_object_unref(pixbuf);
 
        return surface;
+#endif
 }
 
 static int
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 535b3f1..8bbe387 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -28,7 +28,8 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <png.h>
+#include <signal.h> /* SIGTERM and SIGINT */
 #include <math.h>
 #include <linux/input.h>
 
@@ -45,10 +46,11 @@ struct wlsc_switcher {
  * advertise that through a service on the session dbus.
  */
 static const char *option_socket_name = NULL;
-static const char *option_background = "background.jpg";
+static const char *option_background = "background.png";
 static const char *option_geometry = "1024x640";
 static int option_connector = 0;
 
+#ifdef GDK_STUFF
 static const GOptionEntry option_entries[] = {
        { "background", 'b', 0, G_OPTION_ARG_STRING,
          &option_background, "Background image" },
@@ -60,6 +62,7 @@ static const GOptionEntry option_entries[] = {
          &option_socket_name, "Socket Name" },
        { NULL }
 };
+#endif
 
 static void
 wlsc_matrix_init(struct wlsc_matrix *matrix)
@@ -198,33 +201,76 @@ destroy_surface(struct wl_resource *resource, struct 
wl_client *client)
 uint32_t *
 wlsc_load_image(const char *filename, int width, int height)
 {
-       GdkPixbuf *pixbuf;
-       GError *error = NULL;
        int stride, i, n_channels;
-       unsigned char *pixels, *end, *argb_pixels, *s, *d;
-
-       pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
-                                                  width, height,
-                                                  FALSE, &error);
-       if (error != NULL) {
-               fprintf(stderr, "failed to load image: %s\n", error->message);
-               g_error_free(error);
+       unsigned char *end, *argb_pixels, *s, *d;
+
+       int y;
+       png_byte bit_depth;
+       png_structp png_ptr;
+       png_infop info_ptr;
+       int number_of_passes;
+       png_bytep * row_pointers;
+
+       char header[8];    // 8 is the maximum size that can be checked
+
+       /* open file and test for it being a png */
+       FILE *fp = fopen(filename, "rb");
+       if (!fp)
+               fprintf(stderr, "file %s could not be opened for reading", 
filename);
+
+       fread(header, 1, 8, fp);
+
+       if (png_sig_cmp((png_bytep) header, 0, 8)) {
+               fprintf(stderr, "file %s is not recognized as a PNG file", 
filename);
                return NULL;
        }
 
-       stride = gdk_pixbuf_get_rowstride(pixbuf);
-       pixels = gdk_pixbuf_get_pixels(pixbuf);
-       n_channels = gdk_pixbuf_get_n_channels(pixbuf);
+       /* initialize stuff */
+       png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 
NULL);
+       if (!png_ptr)
+               fprintf(stderr, "png_create_read_struct failed");
 
-       argb_pixels = malloc (height * width * 4);
-       if (argb_pixels == NULL) {
-               g_object_unref(pixbuf);
+       info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr)
+               fprintf(stderr, "png_create_info_struct failed");
+
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               fprintf(stderr, "error during init_io");
                return NULL;
        }
 
+       png_init_io(png_ptr, fp);
+       png_set_sig_bytes(png_ptr, 8);
+       png_set_swap_alpha(png_ptr);
+       png_read_info(png_ptr, info_ptr);
+
+       bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+       n_channels = png_get_channels(png_ptr, info_ptr);
+       stride = width * bit_depth * n_channels / 8;
+
+       number_of_passes = png_set_interlace_handling(png_ptr);
+       png_read_update_info(png_ptr, info_ptr);
+
+       /* read file */
+       if (setjmp(png_jmpbuf(png_ptr)))
+               fprintf(stderr, "error during read_image");
+
+       row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
+       for (y=0; y < height; y++)
+               row_pointers[y] = malloc(png_get_rowbytes(png_ptr, info_ptr));
+
+       png_read_image(png_ptr, row_pointers);
+       fclose(fp);
+
+       /* TODO: implement color type checking */
+
+       argb_pixels = malloc (height * width * 4);
+       if (argb_pixels == NULL)
+               return NULL;
+
        if (n_channels == 4) {
                for (i = 0; i < height; i++) {
-                       s = pixels + i * stride;
+                       s = (unsigned char *)row_pointers[i];
                        end = s + width * 4;
                        d = argb_pixels + i * width * 4;
                        while (s < end) {
@@ -243,7 +289,7 @@ wlsc_load_image(const char *filename, int width, int height)
                }
        } else if (n_channels == 3) {
                for (i = 0; i < height; i++) {
-                       s = pixels + i * stride;
+                       s = (unsigned char *)row_pointers[i];
                        end = s + width * 3;
                        d = argb_pixels + i * width * 4;
                        while (s < end) {
@@ -257,8 +303,6 @@ wlsc_load_image(const char *filename, int width, int height)
                }
        }
 
-       g_object_unref(pixbuf);
-
        return (uint32_t *) argb_pixels;
 }
 
@@ -1283,9 +1327,10 @@ int main(int argc, char *argv[])
        struct wl_display *display;
        struct wlsc_compositor *ec;
        struct wl_event_loop *loop;
+       int width, height;
+#ifdef GDK_STUFF
        GError *error = NULL;
        GOptionContext *context;
-       int width, height;
 
        g_type_init(); /* GdkPixbuf needs this, it seems. */
 
@@ -1295,6 +1340,7 @@ int main(int argc, char *argv[])
                fprintf(stderr, "option parsing failed: %s\n", error->message);
                exit(EXIT_FAILURE);
        }
+#endif
        if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) {
                fprintf(stderr, "invalid geometry option: %s \n",
                        option_geometry);
diff --git a/compositor/screenshooter.c b/compositor/screenshooter.c
index 53ed931..a5cece3 100644
--- a/compositor/screenshooter.c
+++ b/compositor/screenshooter.c
@@ -18,7 +18,11 @@
 
 #include <stdlib.h>
 #include <GLES2/gl2.h>
+#ifdef GDK_STUFF
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#else
+#include <stdio.h>
+#endif
 
 #include "compositor.h"
 #include "screenshooter-server-protocol.h"
@@ -34,8 +38,10 @@ screenshooter_shoot(struct wl_client *client, struct 
wl_screenshooter *shooter)
        struct wlsc_compositor *ec = shooter->ec;
        struct wlsc_output *output;
        char buffer[256];
+#ifdef GDK_STUFF
        GdkPixbuf *pixbuf;
        GError *error = NULL;
+#endif
        unsigned char *data;
        int i, j;
 
@@ -56,11 +62,13 @@ screenshooter_shoot(struct wl_client *client, struct 
wl_screenshooter *shooter)
                for (j = 3; j < output->width * output->height * 4; j += 4)
                        data[j] = 0xff;
 
+#ifdef GDK_STUFF
                pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, 
TRUE,
                                                  8, output->width, 
output->height, output->width * 4,
                                                  NULL, NULL);
                gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL);
                g_object_unref(pixbuf);
+#endif
                free(data);
        }
 }
diff --git a/configure.ac b/configure.ac
index 868ebb8..38e4ab5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,9 +23,9 @@ PKG_PROG_PKG_CONFIG()
 PKG_CHECK_MODULES(FFI, [libffi])
 
 PKG_CHECK_MODULES(COMPOSITOR,
-                 [egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 
2.4.23] xcb-dri2 xcb-xfixes)
+                 [egl >= 7.10 glesv2 libudev >= 136 libdrm >= 2.4.23] libpng 
xcb-dri2 xcb-xfixes)
 PKG_CHECK_MODULES(GLES2, [egl >= 7.10 glesv2 libdrm >= 2.4.23])
-PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 
glib-2.0 gobject-2.0 xkbcommon libdrm >= 2.4.23])
+PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 libpng glib-2.0 
gobject-2.0 xkbcommon libdrm >= 2.4.23])
 PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0],
                           [have_poppler=yes], [have_poppler=no])
 AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes")
-- 
1.7.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to