From: Matthias Klumpp <matthias@tenstral.net>
Date: Fri, 29 Apr 2016 06:02:31 +0200

This makes the parser read new-style cached icons, local and remote
icons when they are present in DEP-11 YAML.

The version in Ubuntu Xenial doesn't handle stock icons to work around
a bug in GNOME Software.
Based on asglib commit 628e3cfb1c62c3177d6decd86102217f2546e0a2
---
 data/tests/usr/share/app-info/yaml/aequorea.yml |  5 ++-
 libappstream-glib/as-app.c                      | 55 ++++++++++++++++++++++--
 libappstream-glib/as-icon.c                     | 56 +++++++++++++++++++++----
 libappstream-glib/as-self-test.c                |  7 +++-
 4 files changed, 109 insertions(+), 14 deletions(-)

--- a/data/tests/usr/share/app-info/yaml/aequorea.yml
+++ b/data/tests/usr/share/app-info/yaml/aequorea.yml
@@ -9,7 +9,10 @@
   C: Iceweasel
 Package: iceweasel
 Icon:
-  cached: iceweasel.png
+  cached:
+      - name: iceweasel.png
+        width: 64
+        height: 64
 Keywords:
   C:
     - browser
--- a/libappstream-glib/as-app.c
+++ b/libappstream-glib/as-app.c
@@ -4139,10 +4139,52 @@
 	guint size;
 	g_autoptr(AsIcon) ic_tmp = NULL;
 
-	/* YAML files only specify one icon for various sizes */
-	ic_tmp = as_icon_new ();
-	if (!as_icon_node_parse_dep11 (ic_tmp, node, ctx, error))
-		return FALSE;
+	if (g_strcmp0 (as_yaml_node_get_key (node), "cached") == 0) {
+		if (node->children == NULL) {
+			/* legacy compatibility */
+			ic_tmp = as_icon_new ();
+			as_icon_set_kind (ic_tmp, AS_ICON_KIND_CACHED);
+			as_icon_set_name (ic_tmp, as_yaml_node_get_value (node));
+		} else {
+			GNode *sn;
+			/* we have a modern YAML file */
+			for (sn = node->children; sn != NULL; sn = sn->next) {
+				g_autoptr(AsIcon) icon = NULL;
+				icon = as_icon_new ();
+				as_icon_set_kind (icon, AS_ICON_KIND_CACHED);
+				as_icon_set_prefix (icon, priv->icon_path);
+				if (!as_icon_node_parse_dep11 (icon, sn, ctx, error))
+					return FALSE;
+				as_app_add_icon (app, icon);
+			}
+		}
+	} else {
+		GNode *sn;
+		AsIconKind ikind;
+
+		if (g_strcmp0 (as_yaml_node_get_key (node), "remote") == 0) {
+			ikind = AS_ICON_KIND_REMOTE;
+		} else if (g_strcmp0 (as_yaml_node_get_key (node), "local") == 0) {
+			ikind = AS_ICON_KIND_REMOTE;
+		} else {
+			/* We have an unknown icon type, and just ignore that here */
+			return TRUE;
+		}
+
+		for (sn = node->children; sn != NULL; sn = sn->next) {
+			g_autoptr(AsIcon) icon = NULL;
+			icon = as_icon_new ();
+			as_icon_set_kind (icon, ikind);
+			if (!as_icon_node_parse_dep11 (icon, sn, ctx, error))
+				return FALSE;
+			as_app_add_icon (app, icon);
+		}
+	}
+
+	if (ic_tmp == NULL) {
+		/* we have no icon which we need to probe sizes for */
+		return TRUE;
+	}
 
 	/* find each size */
 	for (i = 0; sizes[i] != NULL; i++) {
--- a/libappstream-glib/as-icon.c
+++ b/libappstream-glib/as-icon.c
@@ -700,16 +700,58 @@
  * Since: 0.3.1
  **/
 gboolean
-as_icon_node_parse_dep11 (AsIcon *im, GNode *node,
+as_icon_node_parse_dep11 (AsIcon *icon, GNode *node,
 			  AsNodeContext *ctx, GError **error)
 {
-	if (g_strcmp0 (as_yaml_node_get_key (node), "cached") == 0) {
-		as_icon_set_name (im, as_yaml_node_get_value (node));
-		as_icon_set_kind (im, AS_ICON_KIND_CACHED);
-	} else if (g_strcmp0 (as_yaml_node_get_key (node), "stock") == 0) {
-		as_icon_set_name (im, as_yaml_node_get_value (node));
-		as_icon_set_kind (im, AS_ICON_KIND_STOCK);
+	GNode *n;
+	AsIconPrivate *priv = GET_PRIVATE (icon);
+
+	for (n = node->children; n != NULL; n = n->next) {
+		const gchar *key;
+		gint size;
+
+		key = as_yaml_node_get_key (n);
+		if (g_strcmp0 (key, "width") == 0) {
+			size = as_yaml_node_get_value_as_int (n);
+			if (size == G_MAXINT)
+				size = 64;
+			priv->width = size;
+		} else if (g_strcmp0 (key, "height") == 0) {
+			size = as_yaml_node_get_value_as_int (n);
+			if (size == G_MAXINT)
+				size = 64;
+			priv->height = size;
+		} else {
+			if (priv->kind == AS_ICON_KIND_REMOTE) {
+				if (g_strcmp0 (key, "url") == 0) {
+					const gchar *media_baseurl;
+					media_baseurl = as_node_context_get_media_base_url (ctx);
+					if (media_baseurl == NULL) {
+						/* no baseurl, we can just set the value as URL */
+						as_icon_set_url (icon, as_yaml_node_get_value (n));
+					} else {
+						/* handle the media baseurl */
+						g_autofree gchar *url = NULL;
+						url = g_build_filename (media_baseurl,
+									as_yaml_node_get_value (n),
+									NULL);
+						as_icon_set_url (icon, url);
+					}
+				}
+			} else {
+				if (g_strcmp0 (key, "name") == 0) {
+					const gchar *icon_name;
+					icon_name = as_yaml_node_get_value (n);
+
+					if (g_str_has_prefix (icon_name, "/"))
+						as_icon_set_filename (icon, icon_name);
+					else
+						as_icon_set_name (icon, icon_name);
+				}
+			}
+		}
 	}
+
 	return TRUE;
 }
 
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -4155,7 +4155,11 @@
 		"  [KVL]C=Iceweasel\n"
 		" [KVL]Package=iceweasel\n"
 		" [MAP]Icon\n"
-		"  [KVL]cached=iceweasel.png\n"
+		"  [SEQ]cached\n"
+		"   [MAP]{\n"
+		"    [KVL]name=iceweasel.png\n"
+		"    [KVL]width=64\n"
+		"    [KVL]height=64\n"
 		" [MAP]Keywords\n"
 		"  [SEQ]C\n"
 		"   [KEY]browser\n"
@@ -4181,7 +4185,6 @@
 	g_assert (ret);
 	g_string_free (str, TRUE);
 	as_yaml_unref (node);
-
 }
 
 static void
