Add support for webp image format
diff --git a/clients/cairo-util.c b/clients/cairo-util.c
index 2f780a7..df2fb1b 100644
--- a/clients/cairo-util.c
+++ b/clients/cairo-util.c
@@ -21,6 +21,8 @@
  * OF THIS SOFTWARE.
  */
 
+#include "../config.h"
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -32,6 +34,10 @@
 #include <jpeglib.h>
 #include <png.h>
 
+#ifdef HAVE_WEBP
+#include <webp/decode.h>
+#endif
+
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 
 void
@@ -514,14 +520,98 @@
 						    width, height, stride);
 }
 
+#ifdef HAVE_WEBP
+
+static cairo_surface_t *
+load_webp(FILE *fp)
+{
+	WebPDecoderConfig config;
+	uint8_t buffer[16 * 1024];
+	int len;
+	VP8StatusCode status;
+	WebPIDecoder *idec;
+
+	if (!WebPInitDecoderConfig(&config)) {
+		fprintf(stderr, "Library version mismatch!\n");
+		return NULL;
+	}
+
+	/* webp decoding api doesn't seem to specify a min size that's
+	   usable for GetFeatures, but 256 works... */
+	len = fread(buffer, 1, 256, fp);
+	status = WebPGetFeatures(buffer, len, &config.input);
+	if (status != VP8_STATUS_OK) {
+		fprintf(stderr, "failed to parse webp header\n");
+		WebPFreeDecBuffer(&config.output);
+		return NULL;
+	}
+
+	config.output.colorspace = MODE_BGRA;
+	config.output.u.RGBA.stride =
+		cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
+					      config.input.width);
+	config.output.u.RGBA.size =
+		config.output.u.RGBA.stride * config.input.height;
+	config.output.u.RGBA.rgba =
+		malloc(config.output.u.RGBA.stride * config.input.height);
+	config.output.is_external_memory = 1;
+	if (!config.output.u.RGBA.rgba) {
+		WebPFreeDecBuffer(&config.output);
+		return NULL;
+	}
+
+	rewind(fp);
+	idec = WebPINewDecoder(&config.output);
+	if (!idec) {
+		WebPFreeDecBuffer(&config.output);
+		return NULL;
+	}
+
+	while (!feof(fp)) {
+		len = fread(buffer, 1, sizeof buffer, fp);
+		status = WebPIAppend(idec, buffer, len);
+		if (status != VP8_STATUS_OK) {
+			fprintf(stderr, "webp decode status %d\n", status);
+			WebPIDelete(idec);
+			WebPFreeDecBuffer(&config.output);
+			return NULL;
+		}
+	}
+
+	WebPIDelete(idec);
+	WebPFreeDecBuffer(&config.output);
+
+	return cairo_image_surface_create_for_data (config.output.u.RGBA.rgba,
+						    CAIRO_FORMAT_RGB24,
+						    config.input.width,
+						    config.input.height,
+						    config.output.u.RGBA.stride);
+}
+
+#endif
+
+
+struct image_loader {
+	char header[4];
+	int header_size;
+	cairo_surface_t *(*load)(FILE *fp);
+};
+
+static const struct image_loader loaders[] = {
+	{ { 0x89, 'P', 'N', 'G' }, 4, load_png },
+	{ { 0xff, 0xd8 }, 2, load_jpeg },
+#ifdef HAVE_WEBP
+	{ { 'R', 'I', 'F', 'F' }, 4, load_webp }
+#endif
+};
+
 cairo_surface_t *
 load_image(const char *filename)
 {
 	cairo_surface_t *surface;
-	static const unsigned char png_header[] = { 0x89, 'P', 'N', 'G' };
-	static const unsigned char jpeg_header[] = { 0xff, 0xd8 };
 	unsigned char header[4];
 	FILE *fp;
+	int i;
 
 	fp = fopen(filename, "rb");
 	if (fp == NULL)
@@ -529,18 +619,22 @@
 
 	fread(header, sizeof header, 1, fp);
 	rewind(fp);
-	if (memcmp(header, png_header, sizeof png_header) == 0)
-		surface = load_png(fp);
-	else if (memcmp(header, jpeg_header, sizeof jpeg_header) == 0)
-		surface = load_jpeg(fp);
-	else {
+	for (i = 0; i < ARRAY_LENGTH(loaders); i++) {
+		if (memcmp(header, loaders[i].header,
+			   loaders[i].header_size) == 0) {
+			surface = loaders[i].load(fp);
+			break;
+		}
+	}
+
+	fclose(fp);
+
+	if (i == ARRAY_LENGTH(loaders)) {
 		fprintf(stderr, "unrecognized file header for %s: "
 			"0x%02x 0x%02x 0x%02x 0x%02x\n",
 			filename, header[0], header[1], header[2], header[3]);
 		surface = NULL;
 	}
 
-	fclose(fp);
-
 	return surface;
 }
diff --git a/configure.ac b/configure.ac
index a2bb537..02f4040 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,11 +123,16 @@
 			     [have_poppler=yes], [have_poppler=no])
   PKG_CHECK_MODULES(CAIRO_EGL, [cairo-egl >= 1.11.3 $cairo_modules],
 		    [have_cairo_egl=yes], [have_cairo_egl=no])
-
   AS_IF([test "x$have_cairo_egl" = "xyes"],
         [AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])],
         [AC_MSG_WARN([Cairo-EGL not found - clients will use cairo image])])
 
+  PKG_CHECK_MODULES(WEBP, [libwebp], [have_webp=yes], [have_webp=no])
+  AS_IF([test "x$have_webp" = "xyes"],
+        [AC_DEFINE([HAVE_WEBP], [1], [Have webp])])
+  CLIENT_LIBS="$CLIENT_LIBS $WEBP_LIBS"
+  CLIENT_CFLAGS="$CLIENT_CFLAGS $WEBP_CFLAGS"
+
   AC_CHECK_LIB([jpeg], [jpeg_CreateDecompress], have_jpeglib=yes)
   if test x$have_jpeglib == xyes; then
     CLIENT_LIBS="$CLIENT_LIBS -ljpeg"