summaryrefslogtreecommitdiff
path: root/libappstream-builder/plugins/asb-plugin-icon.c
diff options
context:
space:
mode:
Diffstat (limited to 'libappstream-builder/plugins/asb-plugin-icon.c')
-rw-r--r--libappstream-builder/plugins/asb-plugin-icon.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/libappstream-builder/plugins/asb-plugin-icon.c b/libappstream-builder/plugins/asb-plugin-icon.c
new file mode 100644
index 0000000..1cf9ad3
--- /dev/null
+++ b/libappstream-builder/plugins/asb-plugin-icon.c
@@ -0,0 +1,205 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014-2018 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU Lesser General Public License Version 2.1
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <asb-plugin.h>
+
+#define __APPSTREAM_GLIB_PRIVATE_H
+#include <as-utils-private.h>
+#include <as-app-private.h>
+
+const gchar *
+asb_plugin_get_name (void)
+{
+ return "icon";
+}
+
+void
+asb_plugin_add_globs (AsbPlugin *plugin, GPtrArray *globs)
+{
+ asb_plugin_add_glob (globs, "/usr/share/pixmaps/*");
+ asb_plugin_add_glob (globs, "/usr/share/icons/*");
+ asb_plugin_add_glob (globs, "/usr/share/*/icons/*");
+}
+
+static GdkPixbuf *
+asb_app_load_icon (AsbPlugin *plugin,
+ const gchar *filename,
+ const gchar *logfn,
+ guint icon_size,
+ guint min_icon_size,
+ GError **error)
+{
+ g_autoptr(AsImage) im = NULL;
+ g_autoptr(GError) error_local = NULL;
+ AsImageLoadFlags load_flags = AS_IMAGE_LOAD_FLAG_ALWAYS_RESIZE;
+
+ /* is icon in a unsupported format */
+ if (!asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_IGNORE_LEGACY_ICONS))
+ load_flags |= AS_IMAGE_LOAD_FLAG_ONLY_SUPPORTED;
+
+ im = as_image_new ();
+ if (!as_image_load_filename_full (im,
+ filename,
+ icon_size,
+ min_icon_size,
+ load_flags,
+ &error_local)) {
+ g_set_error (error,
+ ASB_PLUGIN_ERROR,
+ ASB_PLUGIN_ERROR_FAILED,
+ "%s: %s",
+ error_local->message, logfn);
+ return NULL;
+ }
+ return g_object_ref (as_image_get_pixbuf (im));
+}
+
+static gboolean
+asb_plugin_icon_convert_cached (AsbPlugin *plugin,
+ AsbApp *app,
+ const gchar *tmpdir,
+ const gchar *key,
+ GError **error)
+{
+ guint min_icon_size;
+ g_autofree gchar *fn_hidpi = NULL;
+ g_autofree gchar *fn = NULL;
+ g_autofree gchar *name_hidpi = NULL;
+ g_autofree gchar *name = NULL;
+ g_autoptr(AsIcon) icon_hidpi = NULL;
+ g_autoptr(AsIcon) icon = NULL;
+ g_autoptr(GdkPixbuf) pixbuf_hidpi = NULL;
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ /* find 64x64 icon */
+ fn = as_utils_find_icon_filename_full (tmpdir, key,
+ AS_UTILS_FIND_ICON_NONE,
+ error);
+ if (fn == NULL) {
+ g_prefix_error (error, "Failed to find icon: ");
+ return FALSE;
+ }
+
+ /* load the icon */
+ min_icon_size = asb_context_get_min_icon_size (plugin->ctx);
+ pixbuf = asb_app_load_icon (plugin, fn, fn + strlen (tmpdir),
+ 64, min_icon_size, error);
+ if (pixbuf == NULL) {
+ g_prefix_error (error, "Failed to load icon: ");
+ return FALSE;
+ }
+
+ /* save in target directory */
+ if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)) {
+ name = g_strdup_printf ("%ix%i/%s.png",
+ 64, 64,
+ as_app_get_id_filename (AS_APP (app)));
+ } else {
+ name = g_strdup_printf ("%s.png",
+ as_app_get_id_filename (AS_APP (app)));
+ }
+ icon = as_icon_new ();
+ as_icon_set_pixbuf (icon, pixbuf);
+ as_icon_set_name (icon, name);
+ as_icon_set_kind (icon, AS_ICON_KIND_CACHED);
+ as_icon_set_prefix (icon, as_app_get_icon_path (AS_APP (app)));
+ as_app_add_icon (AS_APP (app), icon);
+
+ /* is HiDPI disabled */
+ if (!asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS))
+ return TRUE;
+
+ /* try to get a HiDPI icon */
+ fn_hidpi = as_utils_find_icon_filename_full (tmpdir, key,
+ AS_UTILS_FIND_ICON_HI_DPI,
+ NULL);
+ if (fn_hidpi == NULL)
+ return TRUE;
+
+ /* load the HiDPI icon */
+ pixbuf_hidpi = asb_app_load_icon (plugin, fn_hidpi,
+ fn_hidpi + strlen (tmpdir),
+ 128, 128, NULL);
+ if (pixbuf_hidpi == NULL)
+ return TRUE;
+ if (gdk_pixbuf_get_width (pixbuf_hidpi) <= gdk_pixbuf_get_width (pixbuf) ||
+ gdk_pixbuf_get_height (pixbuf_hidpi) <= gdk_pixbuf_get_height (pixbuf))
+ return TRUE;
+ as_app_add_kudo_kind (AS_APP (app), AS_KUDO_KIND_HI_DPI_ICON);
+
+ /* save icon */
+ name_hidpi = g_strdup_printf ("%ix%i/%s.png",
+ 128, 128,
+ as_app_get_id_filename (AS_APP (app)));
+ icon_hidpi = as_icon_new ();
+ as_icon_set_pixbuf (icon_hidpi, pixbuf_hidpi);
+ as_icon_set_name (icon_hidpi, name_hidpi);
+ as_icon_set_kind (icon_hidpi, AS_ICON_KIND_CACHED);
+ as_icon_set_prefix (icon_hidpi, as_app_get_icon_path (AS_APP (app)));
+ as_app_add_icon (AS_APP (app), icon_hidpi);
+ return TRUE;
+}
+
+gboolean
+asb_plugin_process_app (AsbPlugin *plugin,
+ AsbPackage *pkg,
+ AsbApp *app,
+ const gchar *tmpdir,
+ GError **error)
+{
+ AsIcon *icon;
+ g_autofree gchar *key = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ /* no icon defined */
+ icon = as_app_get_icon_default (AS_APP (app));
+ if (icon == NULL)
+ return TRUE;
+
+ /* is the icon a stock-icon-name? */
+ if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) {
+ asb_package_log (pkg,
+ ASB_PACKAGE_LOG_LEVEL_DEBUG,
+ "using stock icon %s",
+ as_icon_get_name (icon));
+ return TRUE;
+ }
+
+ /* convert to cached */
+ switch (as_icon_get_kind (icon)) {
+ case AS_ICON_KIND_LOCAL:
+ key = g_strdup (as_icon_get_filename (icon));
+ break;
+ default:
+ key = g_strdup (as_icon_get_name (icon));
+ break;
+ }
+ g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0);
+ if (!asb_plugin_icon_convert_cached (plugin, app, tmpdir, key, &error_local))
+ as_app_add_veto (AS_APP (app), "%s", error_local->message);
+
+ return TRUE;
+}