summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-01-21 19:02:03 +0000
committerRichard Hughes <richard@hughsie.com>2016-01-21 19:02:03 +0000
commit69e4f135a7332221b32096beaba063d5de072b67 (patch)
tree229c72df34cb68a94f56119b7cb9b862955067f7
parent3460ddc196fafcaa1bb0f973c8db62462545c877 (diff)
downloadappstream-glib-69e4f135a7332221b32096beaba063d5de072b67.tar.gz
Add as_image_load_filename_full()
This makes it possible to resize icons from libappstream-glib
-rw-r--r--libappstream-builder/plugins/asb-plugin-desktop.c105
-rw-r--r--libappstream-glib/as-image.c176
-rw-r--r--libappstream-glib/as-image.h24
3 files changed, 188 insertions, 117 deletions
diff --git a/libappstream-builder/plugins/asb-plugin-desktop.c b/libappstream-builder/plugins/asb-plugin-desktop.c
index 0af900a..ff0382d 100644
--- a/libappstream-builder/plugins/asb-plugin-desktop.c
+++ b/libappstream-builder/plugins/asb-plugin-desktop.c
@@ -63,105 +63,24 @@ asb_app_load_icon (AsbApp *app,
guint min_icon_size,
GError **error)
{
- GdkPixbuf *pixbuf = NULL;
- guint pixbuf_height;
- guint pixbuf_width;
- guint tmp_height;
- guint tmp_width;
- g_autoptr(GdkPixbuf) pixbuf_src = NULL;
- g_autoptr(GdkPixbuf) pixbuf_tmp = NULL;
+ g_autoptr(AsImage) im = NULL;
+ g_autoptr(GError) error_local = NULL;
- /* open file in native size */
- if (g_str_has_suffix (filename, ".svg")) {
- pixbuf_src = gdk_pixbuf_new_from_file_at_scale (filename,
- icon_size,
- icon_size,
- TRUE, error);
- } else {
- pixbuf_src = gdk_pixbuf_new_from_file (filename, error);
- }
- if (pixbuf_src == NULL)
- return NULL;
-
- /* check size */
- if (gdk_pixbuf_get_width (pixbuf_src) < (gint) min_icon_size &&
- gdk_pixbuf_get_height (pixbuf_src) < (gint) min_icon_size) {
+ im = as_image_new ();
+ if (!as_image_load_filename_full (im,
+ filename,
+ icon_size,
+ min_icon_size,
+ AS_IMAGE_LOAD_FLAG_NONE,
+ &error_local)) {
g_set_error (error,
ASB_PLUGIN_ERROR,
ASB_PLUGIN_ERROR_FAILED,
- "icon %s was too small %ix%i",
- logfn,
- gdk_pixbuf_get_width (pixbuf_src),
- gdk_pixbuf_get_height (pixbuf_src));
+ "%s: %s",
+ error_local->message, logfn);
return NULL;
}
-
- /* does the icon not have an alpha channel */
- if (!gdk_pixbuf_get_has_alpha (pixbuf_src)) {
- asb_package_log (asb_app_get_package (app),
- ASB_PACKAGE_LOG_LEVEL_INFO,
- "icon %s does not have an alpha channel",
- logfn);
- }
-
- /* don't do anything to an icon with the perfect size */
- pixbuf_width = gdk_pixbuf_get_width (pixbuf_src);
- pixbuf_height = gdk_pixbuf_get_height (pixbuf_src);
- if (pixbuf_width == icon_size && pixbuf_height == icon_size)
- return g_object_ref (pixbuf_src);
-
- /* never scale up, just pad */
- if (pixbuf_width < icon_size && pixbuf_height < icon_size) {
- g_autofree gchar *size_str = NULL;
- size_str = g_strdup_printf ("%ix%i",
- pixbuf_width,
- pixbuf_height);
- asb_package_log (asb_app_get_package (app),
- ASB_PACKAGE_LOG_LEVEL_INFO,
- "icon %s padded to %ix%i as size %s",
- logfn, icon_size, icon_size, size_str);
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- icon_size, icon_size);
- gdk_pixbuf_fill (pixbuf, 0x00000000);
- gdk_pixbuf_copy_area (pixbuf_src,
- 0, 0, /* of src */
- pixbuf_width, pixbuf_height,
- pixbuf,
- (icon_size - pixbuf_width) / 2,
- (icon_size - pixbuf_height) / 2);
- return pixbuf;
- }
-
- /* is the aspect ratio perfectly square */
- if (pixbuf_width == pixbuf_height) {
- pixbuf = gdk_pixbuf_scale_simple (pixbuf_src,
- icon_size, icon_size,
- GDK_INTERP_HYPER);
- as_pixbuf_sharpen (pixbuf, 1, -0.5);
- return pixbuf;
- }
-
- /* create new square pixbuf with alpha padding */
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- icon_size, icon_size);
- gdk_pixbuf_fill (pixbuf, 0x00000000);
- if (pixbuf_width > pixbuf_height) {
- tmp_width = icon_size;
- tmp_height = icon_size * pixbuf_height / pixbuf_width;
- } else {
- tmp_width = icon_size * pixbuf_width / pixbuf_height;
- tmp_height = icon_size;
- }
- pixbuf_tmp = gdk_pixbuf_scale_simple (pixbuf_src, tmp_width, tmp_height,
- GDK_INTERP_HYPER);
- as_pixbuf_sharpen (pixbuf_tmp, 1, -0.5);
- gdk_pixbuf_copy_area (pixbuf_tmp,
- 0, 0, /* of src */
- tmp_width, tmp_height,
- pixbuf,
- (icon_size - tmp_width) / 2,
- (icon_size - tmp_height) / 2);
- return pixbuf;
+ return g_object_ref (as_image_get_pixbuf (im));
}
/**
diff --git a/libappstream-glib/as-image.c b/libappstream-glib/as-image.c
index bc008e6..10e1032 100644
--- a/libappstream-glib/as-image.c
+++ b/libappstream-glib/as-image.c
@@ -472,52 +472,180 @@ as_image_node_parse_dep11 (AsImage *im, GNode *node,
}
/**
- * as_image_load_filename:
+ * as_image_load_filename_full:
* @image: a #AsImage instance.
* @filename: filename to read from
+ * @dest_size: The size of the constructed pixbuf, or 0 for the native size
+ * @src_size_min: The smallest source size allowed, or 0 for none
+ * @flags: a #AsImageLoadFlags, e.g. %AS_IMAGE_LOAD_FLAG_NONE
* @error: A #GError or %NULL.
*
- * Reads a pixbuf from a file.
- *
- * NOTE: This function also sets the suggested filename which can be retrieved
- * using as_image_get_basename(). This can be overridden if required.
+ * Reads an image from a file.
*
* Returns: %TRUE for success
*
- * Since: 0.1.6
+ * Since: 0.5.6
**/
gboolean
-as_image_load_filename (AsImage *image,
- const gchar *filename,
- GError **error)
+as_image_load_filename_full (AsImage *image,
+ const gchar *filename,
+ guint dest_size,
+ guint src_size_min,
+ AsImageLoadFlags flags,
+ GError **error)
{
AsImagePrivate *priv = GET_PRIVATE (image);
- gsize len;
- g_autofree gchar *basename = NULL;
- g_autofree gchar *data = NULL;
+ guint pixbuf_height;
+ guint pixbuf_width;
+ guint tmp_height;
+ guint tmp_width;
g_autoptr(GdkPixbuf) pixbuf = NULL;
+ g_autoptr(GdkPixbuf) pixbuf_src = NULL;
+ g_autoptr(GdkPixbuf) pixbuf_tmp = NULL;
- /* get the contents so we can hash the predictable file data,
- * rather than the unpredicatable (for JPEG) pixel data */
- if (!g_file_get_contents (filename, &data, &len, error))
+ /* update basename */
+ if (flags & AS_IMAGE_LOAD_FLAG_SET_BASENAME) {
+ g_autofree gchar *basename = NULL;
+ basename = g_path_get_basename (filename);
+ as_image_set_basename (image, basename);
+ }
+
+ /* update checksum */
+ if (flags & AS_IMAGE_LOAD_FLAG_SET_CHECKSUM) {
+ gsize len;
+ g_autofree gchar *data = NULL;
+
+ /* get the contents so we can hash the predictable file data,
+ * rather than the unpredicatable (for JPEG) pixel data */
+ if (!g_file_get_contents (filename, &data, &len, error))
+ return FALSE;
+ g_free (priv->md5);
+ priv->md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
+ (guchar * )data, len);
+ }
+
+ /* load the image of the native size */
+ if (dest_size == 0) {
+ pixbuf = gdk_pixbuf_new_from_file (filename, error);
+ if (pixbuf == NULL)
+ return FALSE;
+ as_image_set_pixbuf (image, pixbuf);
+ return TRUE;
+ }
+
+ /* open file in native size */
+ if (g_str_has_suffix (filename, ".svg")) {
+ pixbuf_src = gdk_pixbuf_new_from_file_at_scale (filename,
+ dest_size,
+ dest_size,
+ TRUE, error);
+ } else {
+ pixbuf_src = gdk_pixbuf_new_from_file (filename, error);
+ }
+ if (pixbuf_src == NULL)
return FALSE;
- g_free (priv->md5);
- priv->md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
- (guchar * )data, len);
- /* load the image */
- pixbuf = gdk_pixbuf_new_from_file (filename, error);
- if (pixbuf == NULL)
+ /* check size */
+ if (gdk_pixbuf_get_width (pixbuf_src) < (gint) src_size_min &&
+ gdk_pixbuf_get_height (pixbuf_src) < (gint) src_size_min) {
+ g_set_error (error,
+ AS_UTILS_ERROR,
+ AS_UTILS_ERROR_FAILED,
+ "icon was too small %ix%i",
+ gdk_pixbuf_get_width (pixbuf_src),
+ gdk_pixbuf_get_height (pixbuf_src));
return FALSE;
+ }
+
+ /* don't do anything to an icon with the perfect size */
+ pixbuf_width = gdk_pixbuf_get_width (pixbuf_src);
+ pixbuf_height = gdk_pixbuf_get_height (pixbuf_src);
+ if (pixbuf_width == dest_size && pixbuf_height == dest_size) {
+ as_image_set_pixbuf (image, pixbuf_src);
+ return TRUE;
+ }
- /* set */
- basename = g_path_get_basename (filename);
- as_image_set_basename (image, basename);
+ /* never scale up, just pad */
+ if (pixbuf_width < dest_size && pixbuf_height < dest_size) {
+ g_debug ("icon padded to %ix%i as size %ix%i",
+ dest_size, dest_size,
+ pixbuf_width, pixbuf_height);
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ dest_size, dest_size);
+ gdk_pixbuf_fill (pixbuf, 0x00000000);
+ gdk_pixbuf_copy_area (pixbuf_src,
+ 0, 0, /* of src */
+ pixbuf_width, pixbuf_height,
+ pixbuf,
+ (dest_size - pixbuf_width) / 2,
+ (dest_size - pixbuf_height) / 2);
+ as_image_set_pixbuf (image, pixbuf);
+ return TRUE;
+ }
+
+ /* is the aspect ratio perfectly square */
+ if (pixbuf_width == pixbuf_height) {
+ pixbuf = gdk_pixbuf_scale_simple (pixbuf_src,
+ dest_size, dest_size,
+ GDK_INTERP_HYPER);
+ as_image_set_pixbuf (image, pixbuf);
+ return TRUE;
+ }
+
+ /* create new square pixbuf with alpha padding */
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ dest_size, dest_size);
+ gdk_pixbuf_fill (pixbuf, 0x00000000);
+ if (pixbuf_width > pixbuf_height) {
+ tmp_width = dest_size;
+ tmp_height = dest_size * pixbuf_height / pixbuf_width;
+ } else {
+ tmp_width = dest_size * pixbuf_width / pixbuf_height;
+ tmp_height = dest_size;
+ }
+ pixbuf_tmp = gdk_pixbuf_scale_simple (pixbuf_src, tmp_width, tmp_height,
+ GDK_INTERP_HYPER);
+ if (flags & AS_IMAGE_LOAD_FLAG_SHARPEN)
+ as_pixbuf_sharpen (pixbuf_tmp, 1, -0.5);
+ gdk_pixbuf_copy_area (pixbuf_tmp,
+ 0, 0, /* of src */
+ tmp_width, tmp_height,
+ pixbuf,
+ (dest_size - tmp_width) / 2,
+ (dest_size - tmp_height) / 2);
as_image_set_pixbuf (image, pixbuf);
return TRUE;
}
/**
+ * as_image_load_filename:
+ * @image: a #AsImage instance.
+ * @filename: filename to read from
+ * @error: A #GError or %NULL.
+ *
+ * Reads a pixbuf from a file.
+ *
+ * NOTE: This function also sets the suggested filename which can be retrieved
+ * using as_image_get_basename(). This can be overridden if required.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.1.6
+ **/
+gboolean
+as_image_load_filename (AsImage *image,
+ const gchar *filename,
+ GError **error)
+{
+ return as_image_load_filename_full (image,
+ filename,
+ 0, 0,
+ AS_IMAGE_LOAD_FLAG_SET_BASENAME |
+ AS_IMAGE_LOAD_FLAG_SET_CHECKSUM,
+ error);
+}
+
+/**
* as_image_save_pixbuf:
* @image: a #AsImage instance.
* @width: target width, or 0 for default
diff --git a/libappstream-glib/as-image.h b/libappstream-glib/as-image.h
index 03e7bb5..fb5fa07 100644
--- a/libappstream-glib/as-image.h
+++ b/libappstream-glib/as-image.h
@@ -83,6 +83,24 @@ typedef enum {
} AsImageSaveFlags;
/**
+ * AsImageLoadFlags:
+ * @AS_IMAGE_LOAD_FLAG_NONE: No special flags set
+ * @AS_IMAGE_LOAD_FLAG_SHARPEN: Sharpen the resulting image
+ * @AS_IMAGE_LOAD_FLAG_SET_BASENAME: Set the image basename
+ * @AS_IMAGE_LOAD_FLAG_SET_CHECKSUM: Set the image checksum
+ *
+ * The flags used for loading images.
+ **/
+typedef enum {
+ AS_IMAGE_LOAD_FLAG_NONE = 0, /* Since: 0.5.6 */
+ AS_IMAGE_LOAD_FLAG_SHARPEN = 1, /* Since: 0.5.6 */
+ AS_IMAGE_LOAD_FLAG_SET_BASENAME = 2, /* Since: 0.5.6 */
+ AS_IMAGE_LOAD_FLAG_SET_CHECKSUM = 4, /* Since: 0.5.6 */
+ /*< private >*/
+ AS_IMAGE_LOAD_FLAG_LAST
+} AsImageLoadFlags;
+
+/**
* AsImageAlphaFlags:
* @AS_IMAGE_ALPHA_FLAG_NONE: No padding detected
* @AS_IMAGE_ALPHA_FLAG_TOP: Padding detected at the image top
@@ -146,6 +164,12 @@ AsImageAlphaFlags as_image_get_alpha_flags (AsImage *image);
gboolean as_image_load_filename (AsImage *image,
const gchar *filename,
GError **error);
+gboolean as_image_load_filename_full (AsImage *image,
+ const gchar *filename,
+ guint dest_size,
+ guint src_size_min,
+ AsImageLoadFlags flags,
+ GError **error);
GdkPixbuf *as_image_save_pixbuf (AsImage *image,
guint width,
guint height,