diff -ur gdk-pixbuf-2.34.0.orig/gdk-pixbuf/io-ico.c gdk-pixbuf-2.34.0/gdk-pixbuf/io-ico.c
--- gdk-pixbuf-2.34.0.orig/gdk-pixbuf/io-ico.c	2016-10-21 15:41:38.000000000 -0400
+++ gdk-pixbuf-2.34.0/gdk-pixbuf/io-ico.c	2016-10-21 15:54:16.947099120 -0400
@@ -5,6 +5,7 @@
  *
  * Authors: Arjan van de Ven <arjan@fenrus.demon.nl>
  *          Federico Mena-Quintero <federico@gimp.org>
+ *          Pat Suwalski <pat@suwalski.net>
  *
  * Based on io-bmp.c
  *
@@ -44,7 +45,10 @@
 #include <errno.h>
 #include "gdk-pixbuf-private.h"
 
-
+/* Required for PNG loader */
+#include "gdk-pixbuf-loader.h"
+
+#define INFOHEADER_SIZE 40
 
 /* 
 
@@ -130,6 +134,7 @@
         gint width;
         gint height;
 	gint DIBoffset;
+	gint length;
 	gint x_hot;
 	gint y_hot;
 };
@@ -162,6 +167,8 @@
         gint x_hot;
         gint y_hot;
 
+	GdkPixbufLoader *pngloader;	/* Used for possible PNG loader */
+
 	struct headerpair Header;	/* Decoded (BE->CPU) header */
 	GList *entries;
 	gint			DIBoffset;
@@ -190,6 +197,9 @@
 	if (context->pixbuf)
 		g_object_unref (context->pixbuf);
 
+	if (context->pngloader)
+		g_object_unref (context->pngloader);
+
 	g_free (context);
 }
 
@@ -204,6 +214,70 @@
 	return ib->ImageScore - ia->ImageScore;
 }
 
+/* Callback passed to PNG loader on "area_prepared" signal */
+static void
+png_prepared_callback (GdkPixbufLoader* loader, gpointer data)
+{
+	struct ico_progressive_state *context = (struct ico_progressive_state*)data;
+	context->pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+
+	if (!context->pixbuf) {
+		/* Not ready just yet */
+		return;
+	}
+
+	if (context->prepared_func != NULL) {
+		(*context->prepared_func) (context->pixbuf, NULL, context->user_data);
+	}
+}
+
+/* Callback passed to PNG loader on "area_updated" signal */
+static void
+png_updated_callback (GdkPixbufLoader* loader, gint x, gint y, gint width, gint height, gpointer data)
+{
+	struct ico_progressive_state *context = (struct ico_progressive_state*)data;
+
+	GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+
+	if (context->updated_func) {
+		(* context->updated_func) (pixbuf, x, y, width, height, context->user_data);
+	}
+}
+
+/* Creates a PNG pixbuf loader */
+static void
+png_pixbuf_create (struct ico_progressive_state *context, GError **error) {
+	GError *loader_error = NULL;
+
+	context->pngloader = gdk_pixbuf_loader_new_with_type("png", &loader_error);
+
+	if (loader_error)
+	{
+		g_propagate_error(error, loader_error);
+		return;
+	}
+
+	g_signal_connect(context->pngloader, "area_prepared", G_CALLBACK(png_prepared_callback), context);
+	g_signal_connect(context->pngloader, "area_updated", G_CALLBACK(png_updated_callback), context);
+}
+
+/* Writes bytes to the PNG pixbuf loader */
+static gboolean
+png_pixbuf_write (GdkPixbufLoader* loader, const guchar* buf, guint bytes, GError **error)
+{
+	GError *loader_error = NULL;
+
+	if (!gdk_pixbuf_loader_write(loader, buf, bytes, &loader_error))
+	{
+		g_propagate_error(error, loader_error);
+		gdk_pixbuf_loader_close(loader, NULL);
+		g_object_unref(loader);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void DecodeHeader(guchar *Data, gint Bytes,
 			 struct ico_progressive_state *State,
 			 GError **error)
@@ -220,6 +294,8 @@
 	guint16 imgtype; /* 1 = icon, 2 = cursor */
 	GList *l;
 
+	gint width, height, depth;
+
  	/* Step 1: The ICO header */
 
 	/* First word should be 0 according to specs */
@@ -281,11 +357,28 @@
 
                 width = Ptr[0];
                 height = Ptr[1];
+		depth = Ptr[2];
 		x_hot = (Ptr[5] << 8) + Ptr[4];
 		y_hot = (Ptr[7] << 8) + Ptr[6];
+
+		if (width == 0)
+			width = 256;
+
+		if (height == 0)
+			height = 256;
+
+		if (depth == 0)
+			depth = 32;
+		else if (depth <= 2)
+			depth = 1;
+		else if (depth <= 16)
+			depth = 4;
+		else if (depth <= 256)
+			depth = 8;
+
                 data_size = (Ptr[11] << 24) + (Ptr[10] << 16) + (Ptr[9] << 8) + (Ptr[8]);
 		data_offset = (Ptr[15] << 24) + (Ptr[14] << 16) + (Ptr[13] << 8) + (Ptr[12]);
-                DEBUG(g_print ("Image %d: %d x %d\n\tPalette: %d\n", I, width, height, Ptr[2]);
+                DEBUG(g_print ("Image %d: %d x %d\n\tPalette: %d\n", I, width, height, depth);
                 if (imgtype == 2)
                   g_print ("\tHotspot: %d x %d\n", x_hot, y_hot);
                 else
@@ -293,7 +386,7 @@
                 g_print ("\tSize: %d\n\tOffset: %d\n", data_size, data_offset);)
 
 		entry = g_new0 (struct ico_direntry_data, 1);
-		entry->ImageScore = data_size;
+		entry->ImageScore = width * height * depth;
 
                 entry->width = width ? width : 256;
                 entry->height = height ? height : 256;
@@ -318,7 +411,7 @@
 		}
 
 		/* We know how many bytes are in the "header" part. */
-		State->HeaderSize = entry->DIBoffset + 40; /* 40 = sizeof(InfoHeader) */
+		State->HeaderSize = entry->DIBoffset + INFOHEADER_SIZE; /* 40 = sizeof(InfoHeader) */
 
 		if (State->HeaderSize < 0) {
 			g_set_error (error,
@@ -345,13 +438,8 @@
 
 		BIH = Data+entry->DIBoffset;
 
-		/* A compressed icon, try the next one */
-		if ((BIH[16] != 0) || (BIH[17] != 0) || (BIH[18] != 0)
-		    || (BIH[19] != 0))
-			continue;
-
 		/* If we made it to here then we have selected a BIH structure
-		 * in a format that we can parse */
+		 * in a format that we can parse, or a PNG. */
 		break;
 	}
 
@@ -360,7 +448,20 @@
 		g_set_error_literal (error,
 		                     GDK_PIXBUF_ERROR,
 		                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
-		                     _("Compressed icons are not supported"));
+		                     _("No supported icon formats found"));
+		return;
+	}
+
+	/* Check for PNG header */
+	if (BIH[0] == 0x89 && BIH[1] == 'P' && BIH[2] == 'N' && BIH[3] == 'G') {
+		/* Create a PNG pixbuf data can be passed on to */
+		png_pixbuf_create(State, error);
+
+		/* We already have 40 bytes of the possible bitmap InfoHeader.
+		   Pass this on to the PNG pixbuf loader. */
+		png_pixbuf_write(State->pngloader, Data+entry->DIBoffset, INFOHEADER_SIZE, error);
+
+		/* The rest of this function applies only to bitmaps. */
 		return;
 	}
 
@@ -547,7 +648,7 @@
 	context->user_data = user_data;
 
 	context->HeaderSize = 54;
-	context->HeaderBuf = g_try_malloc(14 + 40 + 4*256 + 512);
+	context->HeaderBuf = g_try_malloc(14 + INFOHEADER_SIZE + 4*256 + 512);
 	if (!context->HeaderBuf) {
 		g_free (context);
 		g_set_error_literal (error,
@@ -557,7 +658,7 @@
 		return NULL;
 	}
 	/* 4*256 for the colormap */
-	context->BytesInHeaderBuf = 14 + 40 + 4*256 + 512 ;
+	context->BytesInHeaderBuf = 14 + INFOHEADER_SIZE + 4*256 + 512 ;
 	context->HeaderDone = 0;
 
 	context->LineWidth = 0;
@@ -886,6 +987,11 @@
 	gint BytesToCopy;
 
 	while (size > 0) {
+		/* If the PNG loader is present, use it. */
+		if (context->pngloader) {
+			return png_pixbuf_write(context->pngloader, buf, size, error);
+		}
+
 		g_assert(context->LineDone >= 0);
 		if (context->HeaderDone < context->HeaderSize) {	/* We still 
 									   have headerbytes to do */
@@ -1152,7 +1258,7 @@
 
 	for (entry = entries; entry; entry = entry->next) {
 		icon = (IconEntry *)entry->data;
-		size = 40 + icon->height * (icon->and_rowstride + icon->xor_rowstride);
+		size = INFOHEADER_SIZE + icon->height * (icon->and_rowstride + icon->xor_rowstride);
 		
 		/* directory entry */
 		if (icon->width == 256)
@@ -1186,7 +1292,7 @@
 		icon = (IconEntry *)entry->data;
 
 		/* bitmap header */
-		dwords[0] = 40;
+		dwords[0] = INFOHEADER_SIZE;
 		dwords[1] = icon->width;
 		dwords[2] = icon->height * 2;
 		write32 (f, dwords, 3);
@@ -1306,7 +1412,3 @@
 	info->flags = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
 	info->license = "LGPL";
 }
-
-
-
-
Only in gdk-pixbuf-2.34.0/gdk-pixbuf: io-ico.c.orig
Only in gdk-pixbuf-2.34.0/gdk-pixbuf: io-ico.c.rej
Only in gdk-pixbuf-2.34.0/gdk-pixbuf: .io-ico.c.rej.swp
