From 847739aed7cf6f6cf5f745fdef0a976980089ea9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 16 May 2023 21:53:55 -0400 Subject: Reduce pixbuf helpers Concentrate pixbuf handling in gdkpixbufutils.c. --- gtk/gdkpixbufutils.c | 188 ++++++++++++++++++++++++++++++++------------ gtk/gdkpixbufutilsprivate.h | 38 +++++---- gtk/gtkcssimagerecolor.c | 4 +- gtk/gtkicontheme.c | 52 +++--------- tools/encodesymbolic.c | 6 +- 5 files changed, 173 insertions(+), 115 deletions(-) diff --git a/gtk/gdkpixbufutils.c b/gtk/gdkpixbufutils.c index c60335e228..b96282c94d 100644 --- a/gtk/gdkpixbufutils.c +++ b/gtk/gdkpixbufutils.c @@ -22,6 +22,8 @@ #include "gdk/gdktextureprivate.h" +/* {{{ Pixbuf helpers */ + static GdkPixbuf * load_from_stream (GdkPixbufLoader *loader, GInputStream *stream, @@ -145,7 +147,7 @@ size_prepared_cb2 (GdkPixbufLoader *loader, gdk_pixbuf_loader_set_size (loader, width, height); } -GdkPixbuf * +static GdkPixbuf * _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream, int width, int height, @@ -172,15 +174,7 @@ _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream, return pixbuf; } -GdkPixbuf * -_gdk_pixbuf_new_from_stream (GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - return _gdk_pixbuf_new_from_stream_scaled (stream, 0, cancellable, error); -} - -GdkPixbuf * +static GdkPixbuf * _gdk_pixbuf_new_from_resource_at_scale (const char *resource_path, int width, int height, @@ -198,9 +192,11 @@ _gdk_pixbuf_new_from_resource_at_scale (const char *resource_path, g_object_unref (stream); return pixbuf; - } +/* }}} */ +/* {{{ Symbolic processing */ + static GdkPixbuf * load_symbolic_svg (const char *escaped_file_data, int width, @@ -306,19 +302,17 @@ gtk_make_symbolic_pixbuf_from_data (const char *file_data, char *escaped_file_data; /* Fetch size from the original icon */ - { - GInputStream *stream = g_memory_input_stream_new_from_data (file_data, file_len, NULL); - GdkPixbuf *reference = gdk_pixbuf_new_from_stream (stream, NULL, error); + GInputStream *stream = g_memory_input_stream_new_from_data (file_data, file_len, NULL); + GdkPixbuf *reference = gdk_pixbuf_new_from_stream (stream, NULL, error); - g_object_unref (stream); + g_object_unref (stream); - if (!reference) - return NULL; + if (!reference) + return NULL; - icon_width = gdk_pixbuf_get_width (reference); - icon_height = gdk_pixbuf_get_height (reference); - g_object_unref (reference); - } + icon_width = gdk_pixbuf_get_width (reference); + icon_height = gdk_pixbuf_get_height (reference); + g_object_unref (reference); escaped_file_data = g_base64_encode ((guchar *) file_data, file_len); icon_width_str = g_strdup_printf ("%d", icon_width); @@ -389,12 +383,12 @@ out: return pixbuf; } -GdkPixbuf * -gtk_make_symbolic_pixbuf_from_resource (const char *path, - int width, - int height, - double scale, - GError **error) +static GdkPixbuf * +make_symbolic_pixbuf_from_resource (const char *path, + int width, + int height, + double scale, + GError **error) { GBytes *bytes; const char *data; @@ -414,12 +408,12 @@ gtk_make_symbolic_pixbuf_from_resource (const char *path, return pixbuf; } -GdkPixbuf * -gtk_make_symbolic_pixbuf_from_path (const char *path, - int width, - int height, - double scale, - GError **error) +static GdkPixbuf * +make_symbolic_pixbuf_from_path (const char *path, + int width, + int height, + double scale, + GError **error) { char *data; gsize size; @@ -436,11 +430,11 @@ gtk_make_symbolic_pixbuf_from_path (const char *path, } static GdkPixbuf * -gtk_make_symbolic_pixbuf_from_file (GFile *file, - int width, - int height, - double scale, - GError **error) +make_symbolic_pixbuf_from_file (GFile *file, + int width, + int height, + double scale, + GError **error) { char *data; gsize size; @@ -456,6 +450,91 @@ gtk_make_symbolic_pixbuf_from_file (GFile *file, return pixbuf; } +/* }}} */ +/* {{{ Texture API */ + +GdkTexture * +gdk_texture_new_from_stream_at_scale (GInputStream *stream, + int width, + int height, + gboolean aspect, + GCancellable *cancellable, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, aspect, cancellable, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gdk_texture_new_from_stream (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, 0, cancellable, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gdk_texture_new_from_resource_at_scale (const char *path, + int width, + int height, + gboolean preserve_aspect, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_resource_at_scale (path, width, height, preserve_aspect, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +/* }}} */ +/* {{{ Symbolic texture API */ + +GdkTexture * +gdk_texture_new_from_path_symbolic (const char *path, + int width, + int height, + double scale, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = make_symbolic_pixbuf_from_path (path, width, height, scale, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + GdkTexture * gtk_load_symbolic_texture_from_resource (const char *path) { @@ -463,16 +542,16 @@ gtk_load_symbolic_texture_from_resource (const char *path) } GdkTexture * -gtk_make_symbolic_texture_from_resource (const char *path, - int width, - int height, - double scale, - GError **error) +gdk_texture_new_from_resource_symbolic (const char *path, + int width, + int height, + double scale, + GError **error) { GdkPixbuf *pixbuf; GdkTexture *texture = NULL; - pixbuf = gtk_make_symbolic_pixbuf_from_resource (path, width, height, scale, error); + pixbuf = make_symbolic_pixbuf_from_resource (path, width, height, scale, error); if (pixbuf) { texture = gdk_texture_new_for_pixbuf (pixbuf); @@ -493,7 +572,7 @@ gtk_load_symbolic_texture_from_file (GFile *file) if (stream == NULL) return NULL; - pixbuf = _gdk_pixbuf_new_from_stream (stream, NULL, NULL); + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); g_object_unref (stream); if (pixbuf == NULL) return NULL; @@ -505,22 +584,25 @@ gtk_load_symbolic_texture_from_file (GFile *file) } GdkTexture * -gtk_make_symbolic_texture_from_file (GFile *file, - int width, - int height, - double scale, - GError **error) +gdk_texture_new_from_file_symbolic (GFile *file, + int width, + int height, + double scale, + GError **error) { GdkPixbuf *pixbuf; GdkTexture *texture; - pixbuf = gtk_make_symbolic_pixbuf_from_file (file, width, height, scale, error); + pixbuf = make_symbolic_pixbuf_from_file (file, width, height, scale, error); texture = gdk_texture_new_for_pixbuf (pixbuf); g_object_unref (pixbuf); return texture; } +/* }}} */ +/* {{{ Scaled paintable API */ + typedef struct { int scale_factor; } LoaderData; @@ -651,3 +733,7 @@ gdk_paintable_new_from_file_scaled (GFile *file, return paintable; } + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/gtk/gdkpixbufutilsprivate.h b/gtk/gdkpixbufutilsprivate.h index 10801722e4..77e21a4c75 100644 --- a/gtk/gdkpixbufutilsprivate.h +++ b/gtk/gdkpixbufutilsprivate.h @@ -21,49 +21,48 @@ G_BEGIN_DECLS -GdkPixbuf *_gdk_pixbuf_new_from_stream (GInputStream *stream, +GdkPixbuf *gtk_make_symbolic_pixbuf_from_data (const char *data, + gsize len, + int width, + int height, + double scale, + const char *debug_output_to, + GError **error); + +GdkTexture *gdk_texture_new_from_stream (GInputStream *stream, GCancellable *cancellable, GError **error); -GdkPixbuf *_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream, +GdkTexture *gdk_texture_new_from_stream_at_scale (GInputStream *stream, int width, int height, gboolean aspect, GCancellable *cancellable, GError **error); -GdkPixbuf *_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path, +GdkTexture *gdk_texture_new_from_resource_at_scale (const char *path, int width, int height, - gboolean preserve_aspect, + gboolean aspect, GError **error); -GdkPixbuf *gtk_make_symbolic_pixbuf_from_data (const char *data, - gsize len, + +GdkTexture *gdk_texture_new_from_path_symbolic (const char *path, int width, int height, double scale, - const char *debug_output_to, GError **error); -GdkPixbuf *gtk_make_symbolic_pixbuf_from_path (const char *path, +GdkTexture *gdk_texture_new_from_file_symbolic (GFile *file, int width, int height, double scale, GError **error); -GdkPixbuf *gtk_make_symbolic_pixbuf_from_resource (const char *path, +GdkTexture *gdk_texture_new_from_resource_symbolic (const char *path, int width, int height, double scale, GError **error); + GdkTexture *gtk_load_symbolic_texture_from_file (GFile *file); -GdkTexture *gtk_make_symbolic_texture_from_file (GFile *file, - int width, - int height, - double scale, - GError **error); GdkTexture *gtk_load_symbolic_texture_from_resource (const char *data); -GdkTexture *gtk_make_symbolic_texture_from_resource (const char *path, - int width, - int height, - double scale, - GError **error); + GdkPaintable *gdk_paintable_new_from_path_scaled (const char *path, int scale_factor); GdkPaintable *gdk_paintable_new_from_resource_scaled (const char *path, @@ -72,4 +71,3 @@ GdkPaintable *gdk_paintable_new_from_file_scaled (GFile *file, int scale_factor); G_END_DECLS - diff --git a/gtk/gtkcssimagerecolor.c b/gtk/gtkcssimagerecolor.c index 62ca62790c..b9760aff4b 100644 --- a/gtk/gtkcssimagerecolor.c +++ b/gtk/gtkcssimagerecolor.c @@ -110,7 +110,7 @@ gtk_css_image_recolor_load_texture (GtkCssImageRecolor *recolor, if (g_str_has_suffix (uri, ".symbolic.png")) recolor->texture = gtk_load_symbolic_texture_from_resource (resource_path); else - recolor->texture = gtk_make_symbolic_texture_from_resource (resource_path, 0, 0, 1.0, NULL); + recolor->texture = gdk_texture_new_from_resource_symbolic (resource_path, 0, 0, 1.0, NULL); g_free (resource_path); } @@ -119,7 +119,7 @@ gtk_css_image_recolor_load_texture (GtkCssImageRecolor *recolor, if (g_str_has_suffix (uri, ".symbolic.png")) recolor->texture = gtk_load_symbolic_texture_from_file (recolor->file); else - recolor->texture = gtk_make_symbolic_texture_from_file (recolor->file, 0, 0, 1.0, NULL); + recolor->texture = gdk_texture_new_from_file_symbolic (recolor->file, 0, 0, 1.0, NULL); } g_free (uri); diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index b073133401..7b19810ebf 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -3747,22 +3747,15 @@ icon_ensure_texture__locked (GtkIconPaintable *icon, { if (icon->is_svg) { - GdkPixbuf *source_pixbuf; - if (gtk_icon_paintable_is_symbolic (icon)) - source_pixbuf = gtk_make_symbolic_pixbuf_from_resource (icon->filename, + icon->texture = gdk_texture_new_from_resource_symbolic (icon->filename, pixel_size, pixel_size, icon->desired_scale, &load_error); else - source_pixbuf = _gdk_pixbuf_new_from_resource_at_scale (icon->filename, + icon->texture = gdk_texture_new_from_resource_at_scale (icon->filename, pixel_size, pixel_size, TRUE, &load_error); - if (source_pixbuf) - { - icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf); - g_object_unref (source_pixbuf); - } } else icon->texture = gdk_texture_new_from_resource (icon->filename); @@ -3771,10 +3764,8 @@ icon_ensure_texture__locked (GtkIconPaintable *icon, { if (icon->is_svg) { - GdkPixbuf *source_pixbuf; - if (gtk_icon_paintable_is_symbolic (icon)) - source_pixbuf = gtk_make_symbolic_pixbuf_from_path (icon->filename, + icon->texture = gdk_texture_new_from_path_symbolic (icon->filename, pixel_size, pixel_size, icon->desired_scale, &load_error); @@ -3783,22 +3774,16 @@ icon_ensure_texture__locked (GtkIconPaintable *icon, GFile *file = g_file_new_for_path (icon->filename); GInputStream *stream = G_INPUT_STREAM (g_file_read (file, NULL, &load_error)); - g_object_unref (file); if (stream) { - source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, + icon->texture = gdk_texture_new_from_stream_at_scale (stream, pixel_size, pixel_size, TRUE, NULL, &load_error); g_object_unref (stream); } - else - source_pixbuf = NULL; - } - if (source_pixbuf) - { - icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf); - g_object_unref (source_pixbuf); + + g_object_unref (file); } } else @@ -3809,35 +3794,24 @@ icon_ensure_texture__locked (GtkIconPaintable *icon, else { GInputStream *stream; - GdkPixbuf *source_pixbuf; g_assert (icon->loadable); - stream = g_loadable_icon_load (icon->loadable, - pixel_size, - NULL, NULL, - &load_error); + stream = g_loadable_icon_load (icon->loadable, pixel_size, NULL, NULL, &load_error); if (stream) { /* SVG icons are a special case - we just immediately scale them * to the desired size */ if (icon->is_svg) - { - source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, - pixel_size, pixel_size, - TRUE, NULL, - &load_error); - } + icon->texture = gdk_texture_new_from_stream_at_scale (stream, + pixel_size, pixel_size, + TRUE, NULL, + &load_error); else - source_pixbuf = _gdk_pixbuf_new_from_stream (stream, - NULL, &load_error); + icon->texture = gdk_texture_new_from_stream (stream, NULL, &load_error); + g_object_unref (stream); - if (source_pixbuf) - { - icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf); - g_object_unref (source_pixbuf); - } } } diff --git a/tools/encodesymbolic.c b/tools/encodesymbolic.c index 90887f3365..bfe96005b8 100644 --- a/tools/encodesymbolic.c +++ b/tools/encodesymbolic.c @@ -133,9 +133,9 @@ main (int argc, char **argv) out = g_file_replace (dest, - NULL, FALSE, - G_FILE_CREATE_REPLACE_DESTINATION, - NULL, &error); + NULL, FALSE, + G_FILE_CREATE_REPLACE_DESTINATION, + NULL, &error); if (out == NULL) { g_printerr (_("Can’t save file %s: %s\n"), pngpath, error->message); -- cgit v1.2.1 From c2ba1d69a1b1bd04571db0e0813e85c4ee6a14ef Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 16 May 2023 22:00:08 -0400 Subject: Rename pixbuf utils to texture utils That is what this is now. --- gtk/gdkpixbufutils.c | 739 ------------------------------------------- gtk/gdkpixbufutilsprivate.h | 73 ----- gtk/gdktextureutils.c | 739 +++++++++++++++++++++++++++++++++++++++++++ gtk/gdktextureutilsprivate.h | 73 +++++ gtk/gtkcssimagerecolor.c | 2 +- gtk/gtkicontheme.c | 2 +- gtk/gtkimage.c | 2 +- gtk/gtkpicture.c | 2 +- gtk/meson.build | 2 +- tools/encodesymbolic.c | 2 +- 10 files changed, 818 insertions(+), 818 deletions(-) delete mode 100644 gtk/gdkpixbufutils.c delete mode 100644 gtk/gdkpixbufutilsprivate.h create mode 100644 gtk/gdktextureutils.c create mode 100644 gtk/gdktextureutilsprivate.h diff --git a/gtk/gdkpixbufutils.c b/gtk/gdkpixbufutils.c deleted file mode 100644 index b96282c94d..0000000000 --- a/gtk/gdkpixbufutils.c +++ /dev/null @@ -1,739 +0,0 @@ -/* Copyright (C) 2016 Red Hat, Inc. - * - * 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 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, see . - */ - -#include "config.h" - -#include -#include "gdkpixbufutilsprivate.h" -#include "gtkscalerprivate.h" - -#include "gdk/gdktextureprivate.h" - -/* {{{ Pixbuf helpers */ - -static GdkPixbuf * -load_from_stream (GdkPixbufLoader *loader, - GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - GdkPixbuf *pixbuf; - gssize n_read; - guchar buffer[65536]; - gboolean res; - - res = TRUE; - while (1) - { - n_read = g_input_stream_read (stream, buffer, sizeof (buffer), cancellable, error); - if (n_read < 0) - { - res = FALSE; - error = NULL; /* Ignore further errors */ - break; - } - - if (n_read == 0) - break; - - if (!gdk_pixbuf_loader_write (loader, buffer, n_read, error)) - { - res = FALSE; - error = NULL; - break; - } - } - - if (!gdk_pixbuf_loader_close (loader, error)) - { - res = FALSE; - error = NULL; - } - - pixbuf = NULL; - - if (res) - { - pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - if (pixbuf) - g_object_ref (pixbuf); - } - - return pixbuf; -} - -static void -size_prepared_cb (GdkPixbufLoader *loader, - int width, - int height, - gpointer data) -{ - double *scale = data; - - width = MAX (*scale * width, 1); - height = MAX (*scale * height, 1); - - gdk_pixbuf_loader_set_size (loader, width, height); -} - -/* Like gdk_pixbuf_new_from_stream_at_scale, but - * load the image at its original size times the - * given scale. - */ -static GdkPixbuf * -_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream, - double scale, - GCancellable *cancellable, - GError **error) -{ - GdkPixbufLoader *loader; - GdkPixbuf *pixbuf; - - loader = gdk_pixbuf_loader_new (); - - if (scale != 0) - g_signal_connect (loader, "size-prepared", - G_CALLBACK (size_prepared_cb), &scale); - - pixbuf = load_from_stream (loader, stream, cancellable, error); - - g_object_unref (loader); - - return pixbuf; -} - -static void -size_prepared_cb2 (GdkPixbufLoader *loader, - int width, - int height, - gpointer data) -{ - int *scales = data; - - if (scales[2]) /* keep same aspect ratio as original, while fitting in given size */ - { - double aspect = (double) height / width; - - /* First use given width and calculate size */ - width = scales[0]; - height = scales[0] * aspect; - - /* Check if it fits given height, otherwise scale down */ - if (height > scales[1]) - { - width *= (double) scales[1] / height; - height = scales[1]; - } - } - else - { - width = scales[0]; - height = scales[1]; - } - - gdk_pixbuf_loader_set_size (loader, width, height); -} - -static GdkPixbuf * -_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream, - int width, - int height, - gboolean aspect, - GCancellable *cancellable, - GError **error) -{ - GdkPixbufLoader *loader; - GdkPixbuf *pixbuf; - int scales[3]; - - loader = gdk_pixbuf_loader_new (); - - scales[0] = width; - scales[1] = height; - scales[2] = aspect; - g_signal_connect (loader, "size-prepared", - G_CALLBACK (size_prepared_cb2), scales); - - pixbuf = load_from_stream (loader, stream, cancellable, error); - - g_object_unref (loader); - - return pixbuf; -} - -static GdkPixbuf * -_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path, - int width, - int height, - gboolean preserve_aspect, - GError **error) -{ - GInputStream *stream; - GdkPixbuf *pixbuf; - - stream = g_resources_open_stream (resource_path, 0, error); - if (stream == NULL) - return NULL; - - pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, preserve_aspect, NULL, error); - g_object_unref (stream); - - return pixbuf; -} - -/* }}} */ -/* {{{ Symbolic processing */ - -static GdkPixbuf * -load_symbolic_svg (const char *escaped_file_data, - int width, - int height, - const char *icon_width_str, - const char *icon_height_str, - const char *fg_string, - const char *success_color_string, - const char *warning_color_string, - const char *error_color_string, - GError **error) -{ - GInputStream *stream; - GdkPixbuf *pixbuf; - char *data; - - data = g_strconcat ("\n" - "\n" - " \n" - " \n" - "", - NULL); - - stream = g_memory_input_stream_new_from_data (data, -1, g_free); - pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, width, height, TRUE, NULL, error); - g_object_unref (stream); - - return pixbuf; -} - -static void -extract_plane (GdkPixbuf *src, - GdkPixbuf *dst, - int from_plane, - int to_plane) -{ - guchar *src_data, *dst_data; - int width, height; - gsize src_stride, dst_stride; - guchar *src_row, *dst_row; - int x, y; - - width = gdk_pixbuf_get_width (src); - height = gdk_pixbuf_get_height (src); - - g_assert (width <= gdk_pixbuf_get_width (dst)); - g_assert (height <= gdk_pixbuf_get_height (dst)); - - src_stride = gdk_pixbuf_get_rowstride (src); - src_data = gdk_pixbuf_get_pixels (src); - - dst_data = gdk_pixbuf_get_pixels (dst); - dst_stride = gdk_pixbuf_get_rowstride (dst); - - for (y = 0; y < height; y++) - { - src_row = src_data + src_stride * y; - dst_row = dst_data + dst_stride * y; - for (x = 0; x < width; x++) - { - dst_row[to_plane] = src_row[from_plane]; - src_row += 4; - dst_row += 4; - } - } -} - -GdkPixbuf * -gtk_make_symbolic_pixbuf_from_data (const char *file_data, - gsize file_len, - int width, - int height, - double scale, - const char *debug_output_basename, - GError **error) - -{ - const char *r_string = "rgb(255,0,0)"; - const char *g_string = "rgb(0,255,0)"; - char *icon_width_str; - char *icon_height_str; - GdkPixbuf *loaded; - GdkPixbuf *pixbuf = NULL; - int plane; - int icon_width, icon_height; - char *escaped_file_data; - - /* Fetch size from the original icon */ - GInputStream *stream = g_memory_input_stream_new_from_data (file_data, file_len, NULL); - GdkPixbuf *reference = gdk_pixbuf_new_from_stream (stream, NULL, error); - - g_object_unref (stream); - - if (!reference) - return NULL; - - icon_width = gdk_pixbuf_get_width (reference); - icon_height = gdk_pixbuf_get_height (reference); - g_object_unref (reference); - - escaped_file_data = g_base64_encode ((guchar *) file_data, file_len); - icon_width_str = g_strdup_printf ("%d", icon_width); - icon_height_str = g_strdup_printf ("%d", icon_height); - - if (width == 0) - width = icon_width * scale; - if (height == 0) - height = icon_height * scale; - - for (plane = 0; plane < 3; plane++) - { - /* Here we render the svg with all colors solid, this should - * always make the alpha channel the same and it should match - * the final alpha channel for all possible renderings. We - * Just use it as-is for final alpha. - * - * For the 3 non-fg colors, we render once each with that - * color as red, and every other color as green. The resulting - * red will describe the amount of that color is in the - * opaque part of the color. We store these as the rgb - * channels, with the color of the fg being implicitly - * the "rest", as all color fractions should add up to 1. - */ - loaded = load_symbolic_svg (escaped_file_data, width, height, - icon_width_str, - icon_height_str, - g_string, - plane == 0 ? r_string : g_string, - plane == 1 ? r_string : g_string, - plane == 2 ? r_string : g_string, - error); - if (loaded == NULL) - goto out; - - if (debug_output_basename) - { - char *filename; - - filename = g_strdup_printf ("%s.debug%d.png", debug_output_basename, plane); - g_print ("Writing %s\n", filename); - gdk_pixbuf_save (loaded, filename, "png", NULL, NULL); - g_free (filename); - } - - if (pixbuf == NULL) - { - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, - gdk_pixbuf_get_width (loaded), - gdk_pixbuf_get_height (loaded)); - gdk_pixbuf_fill (pixbuf, 0); - } - - if (plane == 0) - extract_plane (loaded, pixbuf, 3, 3); - - extract_plane (loaded, pixbuf, 0, plane); - - g_object_unref (loaded); - } - - g_free (escaped_file_data); - -out: - g_free (icon_width_str); - g_free (icon_height_str); - - return pixbuf; -} - -static GdkPixbuf * -make_symbolic_pixbuf_from_resource (const char *path, - int width, - int height, - double scale, - GError **error) -{ - GBytes *bytes; - const char *data; - gsize size; - GdkPixbuf *pixbuf; - - bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); - if (bytes == NULL) - return NULL; - - data = g_bytes_get_data (bytes, &size); - - pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); - - g_bytes_unref (bytes); - - return pixbuf; -} - -static GdkPixbuf * -make_symbolic_pixbuf_from_path (const char *path, - int width, - int height, - double scale, - GError **error) -{ - char *data; - gsize size; - GdkPixbuf *pixbuf; - - if (!g_file_get_contents (path, &data, &size, error)) - return NULL; - - pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); - - g_free (data); - - return pixbuf; -} - -static GdkPixbuf * -make_symbolic_pixbuf_from_file (GFile *file, - int width, - int height, - double scale, - GError **error) -{ - char *data; - gsize size; - GdkPixbuf *pixbuf; - - if (!g_file_load_contents (file, NULL, &data, &size, NULL, error)) - return NULL; - - pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); - - g_free (data); - - return pixbuf; -} - -/* }}} */ -/* {{{ Texture API */ - -GdkTexture * -gdk_texture_new_from_stream_at_scale (GInputStream *stream, - int width, - int height, - gboolean aspect, - GCancellable *cancellable, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture = NULL; - - pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, aspect, cancellable, error); - if (pixbuf) - { - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - } - - return texture; -} - -GdkTexture * -gdk_texture_new_from_stream (GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture = NULL; - - pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, 0, cancellable, error); - if (pixbuf) - { - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - } - - return texture; -} - -GdkTexture * -gdk_texture_new_from_resource_at_scale (const char *path, - int width, - int height, - gboolean preserve_aspect, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture = NULL; - - pixbuf = _gdk_pixbuf_new_from_resource_at_scale (path, width, height, preserve_aspect, error); - if (pixbuf) - { - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - } - - return texture; -} - -/* }}} */ -/* {{{ Symbolic texture API */ - -GdkTexture * -gdk_texture_new_from_path_symbolic (const char *path, - int width, - int height, - double scale, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture = NULL; - - pixbuf = make_symbolic_pixbuf_from_path (path, width, height, scale, error); - if (pixbuf) - { - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - } - - return texture; -} - -GdkTexture * -gtk_load_symbolic_texture_from_resource (const char *path) -{ - return gdk_texture_new_from_resource (path); -} - -GdkTexture * -gdk_texture_new_from_resource_symbolic (const char *path, - int width, - int height, - double scale, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture = NULL; - - pixbuf = make_symbolic_pixbuf_from_resource (path, width, height, scale, error); - if (pixbuf) - { - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - } - - return texture; -} - -GdkTexture * -gtk_load_symbolic_texture_from_file (GFile *file) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture; - GInputStream *stream; - - stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL)); - if (stream == NULL) - return NULL; - - pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); - g_object_unref (stream); - if (pixbuf == NULL) - return NULL; - - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - - return texture; -} - -GdkTexture * -gdk_texture_new_from_file_symbolic (GFile *file, - int width, - int height, - double scale, - GError **error) -{ - GdkPixbuf *pixbuf; - GdkTexture *texture; - - pixbuf = make_symbolic_pixbuf_from_file (file, width, height, scale, error); - texture = gdk_texture_new_for_pixbuf (pixbuf); - g_object_unref (pixbuf); - - return texture; -} - -/* }}} */ -/* {{{ Scaled paintable API */ - -typedef struct { - int scale_factor; -} LoaderData; - -static void -on_loader_size_prepared (GdkPixbufLoader *loader, - int width, - int height, - gpointer user_data) -{ - LoaderData *loader_data = user_data; - GdkPixbufFormat *format; - - /* Let the regular icon helper code path handle non-scalable images */ - format = gdk_pixbuf_loader_get_format (loader); - if (!gdk_pixbuf_format_is_scalable (format)) - { - loader_data->scale_factor = 1; - return; - } - - gdk_pixbuf_loader_set_size (loader, - width * loader_data->scale_factor, - height * loader_data->scale_factor); -} - -static GdkPaintable * -gdk_paintable_new_from_bytes_scaled (GBytes *bytes, - int scale_factor) -{ - LoaderData loader_data; - GdkTexture *texture; - GdkPaintable *paintable; - - loader_data.scale_factor = scale_factor; - - if (gdk_texture_can_load (bytes)) - { - texture = gdk_texture_new_from_bytes (bytes, NULL); - if (texture == NULL) - return NULL; - - /* We know these formats can't be scaled */ - paintable = GDK_PAINTABLE (texture); - } - else - { - GdkPixbufLoader *loader; - gboolean success; - - loader = gdk_pixbuf_loader_new (); - g_signal_connect (loader, "size-prepared", - G_CALLBACK (on_loader_size_prepared), &loader_data); - - success = gdk_pixbuf_loader_write_bytes (loader, bytes, NULL); - /* close even when writing failed */ - success &= gdk_pixbuf_loader_close (loader, NULL); - - if (!success) - return NULL; - - texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader)); - g_object_unref (loader); - - if (loader_data.scale_factor != 1) - paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor); - else - paintable = g_object_ref (GDK_PAINTABLE (texture)); - - g_object_unref (texture); - } - - return paintable; -} - -GdkPaintable * -gdk_paintable_new_from_path_scaled (const char *path, - int scale_factor) -{ - char *contents; - gsize length; - GBytes *bytes; - GdkPaintable *paintable; - - if (!g_file_get_contents (path, &contents, &length, NULL)) - return NULL; - - bytes = g_bytes_new_take (contents, length); - - paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); - - g_bytes_unref (bytes); - - return paintable; -} - -GdkPaintable * -gdk_paintable_new_from_resource_scaled (const char *path, - int scale_factor) -{ - GBytes *bytes; - GdkPaintable *paintable; - - bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); - if (!bytes) - return NULL; - - paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); - g_bytes_unref (bytes); - - return paintable; -} - -GdkPaintable * -gdk_paintable_new_from_file_scaled (GFile *file, - int scale_factor) -{ - GBytes *bytes; - GdkPaintable *paintable; - - bytes = g_file_load_bytes (file, NULL, NULL, NULL); - if (!bytes) - return NULL; - - paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); - - g_bytes_unref (bytes); - - return paintable; -} - -/* }}} */ - -/* vim:set foldmethod=marker expandtab: */ diff --git a/gtk/gdkpixbufutilsprivate.h b/gtk/gdkpixbufutilsprivate.h deleted file mode 100644 index 77e21a4c75..0000000000 --- a/gtk/gdkpixbufutilsprivate.h +++ /dev/null @@ -1,73 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 2016 Red Hat, Inc. - * - * 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 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, see . - */ - -#pragma once - -#include - -G_BEGIN_DECLS - -GdkPixbuf *gtk_make_symbolic_pixbuf_from_data (const char *data, - gsize len, - int width, - int height, - double scale, - const char *debug_output_to, - GError **error); - -GdkTexture *gdk_texture_new_from_stream (GInputStream *stream, - GCancellable *cancellable, - GError **error); -GdkTexture *gdk_texture_new_from_stream_at_scale (GInputStream *stream, - int width, - int height, - gboolean aspect, - GCancellable *cancellable, - GError **error); -GdkTexture *gdk_texture_new_from_resource_at_scale (const char *path, - int width, - int height, - gboolean aspect, - GError **error); - -GdkTexture *gdk_texture_new_from_path_symbolic (const char *path, - int width, - int height, - double scale, - GError **error); -GdkTexture *gdk_texture_new_from_file_symbolic (GFile *file, - int width, - int height, - double scale, - GError **error); -GdkTexture *gdk_texture_new_from_resource_symbolic (const char *path, - int width, - int height, - double scale, - GError **error); - -GdkTexture *gtk_load_symbolic_texture_from_file (GFile *file); -GdkTexture *gtk_load_symbolic_texture_from_resource (const char *data); - -GdkPaintable *gdk_paintable_new_from_path_scaled (const char *path, - int scale_factor); -GdkPaintable *gdk_paintable_new_from_resource_scaled (const char *path, - int scale_factor); -GdkPaintable *gdk_paintable_new_from_file_scaled (GFile *file, - int scale_factor); - -G_END_DECLS diff --git a/gtk/gdktextureutils.c b/gtk/gdktextureutils.c new file mode 100644 index 0000000000..96aed7133c --- /dev/null +++ b/gtk/gdktextureutils.c @@ -0,0 +1,739 @@ +/* Copyright (C) 2016 Red Hat, Inc. + * + * 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 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, see . + */ + +#include "config.h" + +#include +#include "gdktextureutilsprivate.h" +#include "gtkscalerprivate.h" + +#include "gdk/gdktextureprivate.h" + +/* {{{ Pixbuf helpers */ + +static GdkPixbuf * +load_from_stream (GdkPixbufLoader *loader, + GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GdkPixbuf *pixbuf; + gssize n_read; + guchar buffer[65536]; + gboolean res; + + res = TRUE; + while (1) + { + n_read = g_input_stream_read (stream, buffer, sizeof (buffer), cancellable, error); + if (n_read < 0) + { + res = FALSE; + error = NULL; /* Ignore further errors */ + break; + } + + if (n_read == 0) + break; + + if (!gdk_pixbuf_loader_write (loader, buffer, n_read, error)) + { + res = FALSE; + error = NULL; + break; + } + } + + if (!gdk_pixbuf_loader_close (loader, error)) + { + res = FALSE; + error = NULL; + } + + pixbuf = NULL; + + if (res) + { + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + if (pixbuf) + g_object_ref (pixbuf); + } + + return pixbuf; +} + +static void +size_prepared_cb (GdkPixbufLoader *loader, + int width, + int height, + gpointer data) +{ + double *scale = data; + + width = MAX (*scale * width, 1); + height = MAX (*scale * height, 1); + + gdk_pixbuf_loader_set_size (loader, width, height); +} + +/* Like gdk_pixbuf_new_from_stream_at_scale, but + * load the image at its original size times the + * given scale. + */ +static GdkPixbuf * +_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream, + double scale, + GCancellable *cancellable, + GError **error) +{ + GdkPixbufLoader *loader; + GdkPixbuf *pixbuf; + + loader = gdk_pixbuf_loader_new (); + + if (scale != 0) + g_signal_connect (loader, "size-prepared", + G_CALLBACK (size_prepared_cb), &scale); + + pixbuf = load_from_stream (loader, stream, cancellable, error); + + g_object_unref (loader); + + return pixbuf; +} + +static void +size_prepared_cb2 (GdkPixbufLoader *loader, + int width, + int height, + gpointer data) +{ + int *scales = data; + + if (scales[2]) /* keep same aspect ratio as original, while fitting in given size */ + { + double aspect = (double) height / width; + + /* First use given width and calculate size */ + width = scales[0]; + height = scales[0] * aspect; + + /* Check if it fits given height, otherwise scale down */ + if (height > scales[1]) + { + width *= (double) scales[1] / height; + height = scales[1]; + } + } + else + { + width = scales[0]; + height = scales[1]; + } + + gdk_pixbuf_loader_set_size (loader, width, height); +} + +static GdkPixbuf * +_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream, + int width, + int height, + gboolean aspect, + GCancellable *cancellable, + GError **error) +{ + GdkPixbufLoader *loader; + GdkPixbuf *pixbuf; + int scales[3]; + + loader = gdk_pixbuf_loader_new (); + + scales[0] = width; + scales[1] = height; + scales[2] = aspect; + g_signal_connect (loader, "size-prepared", + G_CALLBACK (size_prepared_cb2), scales); + + pixbuf = load_from_stream (loader, stream, cancellable, error); + + g_object_unref (loader); + + return pixbuf; +} + +static GdkPixbuf * +_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path, + int width, + int height, + gboolean preserve_aspect, + GError **error) +{ + GInputStream *stream; + GdkPixbuf *pixbuf; + + stream = g_resources_open_stream (resource_path, 0, error); + if (stream == NULL) + return NULL; + + pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, preserve_aspect, NULL, error); + g_object_unref (stream); + + return pixbuf; +} + +/* }}} */ +/* {{{ Symbolic processing */ + +static GdkPixbuf * +load_symbolic_svg (const char *escaped_file_data, + int width, + int height, + const char *icon_width_str, + const char *icon_height_str, + const char *fg_string, + const char *success_color_string, + const char *warning_color_string, + const char *error_color_string, + GError **error) +{ + GInputStream *stream; + GdkPixbuf *pixbuf; + char *data; + + data = g_strconcat ("\n" + "\n" + " \n" + " \n" + "", + NULL); + + stream = g_memory_input_stream_new_from_data (data, -1, g_free); + pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, width, height, TRUE, NULL, error); + g_object_unref (stream); + + return pixbuf; +} + +static void +extract_plane (GdkPixbuf *src, + GdkPixbuf *dst, + int from_plane, + int to_plane) +{ + guchar *src_data, *dst_data; + int width, height; + gsize src_stride, dst_stride; + guchar *src_row, *dst_row; + int x, y; + + width = gdk_pixbuf_get_width (src); + height = gdk_pixbuf_get_height (src); + + g_assert (width <= gdk_pixbuf_get_width (dst)); + g_assert (height <= gdk_pixbuf_get_height (dst)); + + src_stride = gdk_pixbuf_get_rowstride (src); + src_data = gdk_pixbuf_get_pixels (src); + + dst_data = gdk_pixbuf_get_pixels (dst); + dst_stride = gdk_pixbuf_get_rowstride (dst); + + for (y = 0; y < height; y++) + { + src_row = src_data + src_stride * y; + dst_row = dst_data + dst_stride * y; + for (x = 0; x < width; x++) + { + dst_row[to_plane] = src_row[from_plane]; + src_row += 4; + dst_row += 4; + } + } +} + +GdkPixbuf * +gtk_make_symbolic_pixbuf_from_data (const char *file_data, + gsize file_len, + int width, + int height, + double scale, + const char *debug_output_basename, + GError **error) + +{ + const char *r_string = "rgb(255,0,0)"; + const char *g_string = "rgb(0,255,0)"; + char *icon_width_str; + char *icon_height_str; + GdkPixbuf *loaded; + GdkPixbuf *pixbuf = NULL; + int plane; + int icon_width, icon_height; + char *escaped_file_data; + + /* Fetch size from the original icon */ + GInputStream *stream = g_memory_input_stream_new_from_data (file_data, file_len, NULL); + GdkPixbuf *reference = gdk_pixbuf_new_from_stream (stream, NULL, error); + + g_object_unref (stream); + + if (!reference) + return NULL; + + icon_width = gdk_pixbuf_get_width (reference); + icon_height = gdk_pixbuf_get_height (reference); + g_object_unref (reference); + + escaped_file_data = g_base64_encode ((guchar *) file_data, file_len); + icon_width_str = g_strdup_printf ("%d", icon_width); + icon_height_str = g_strdup_printf ("%d", icon_height); + + if (width == 0) + width = icon_width * scale; + if (height == 0) + height = icon_height * scale; + + for (plane = 0; plane < 3; plane++) + { + /* Here we render the svg with all colors solid, this should + * always make the alpha channel the same and it should match + * the final alpha channel for all possible renderings. We + * Just use it as-is for final alpha. + * + * For the 3 non-fg colors, we render once each with that + * color as red, and every other color as green. The resulting + * red will describe the amount of that color is in the + * opaque part of the color. We store these as the rgb + * channels, with the color of the fg being implicitly + * the "rest", as all color fractions should add up to 1. + */ + loaded = load_symbolic_svg (escaped_file_data, width, height, + icon_width_str, + icon_height_str, + g_string, + plane == 0 ? r_string : g_string, + plane == 1 ? r_string : g_string, + plane == 2 ? r_string : g_string, + error); + if (loaded == NULL) + goto out; + + if (debug_output_basename) + { + char *filename; + + filename = g_strdup_printf ("%s.debug%d.png", debug_output_basename, plane); + g_print ("Writing %s\n", filename); + gdk_pixbuf_save (loaded, filename, "png", NULL, NULL); + g_free (filename); + } + + if (pixbuf == NULL) + { + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, + gdk_pixbuf_get_width (loaded), + gdk_pixbuf_get_height (loaded)); + gdk_pixbuf_fill (pixbuf, 0); + } + + if (plane == 0) + extract_plane (loaded, pixbuf, 3, 3); + + extract_plane (loaded, pixbuf, 0, plane); + + g_object_unref (loaded); + } + + g_free (escaped_file_data); + +out: + g_free (icon_width_str); + g_free (icon_height_str); + + return pixbuf; +} + +static GdkPixbuf * +make_symbolic_pixbuf_from_resource (const char *path, + int width, + int height, + double scale, + GError **error) +{ + GBytes *bytes; + const char *data; + gsize size; + GdkPixbuf *pixbuf; + + bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); + if (bytes == NULL) + return NULL; + + data = g_bytes_get_data (bytes, &size); + + pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); + + g_bytes_unref (bytes); + + return pixbuf; +} + +static GdkPixbuf * +make_symbolic_pixbuf_from_path (const char *path, + int width, + int height, + double scale, + GError **error) +{ + char *data; + gsize size; + GdkPixbuf *pixbuf; + + if (!g_file_get_contents (path, &data, &size, error)) + return NULL; + + pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); + + g_free (data); + + return pixbuf; +} + +static GdkPixbuf * +make_symbolic_pixbuf_from_file (GFile *file, + int width, + int height, + double scale, + GError **error) +{ + char *data; + gsize size; + GdkPixbuf *pixbuf; + + if (!g_file_load_contents (file, NULL, &data, &size, NULL, error)) + return NULL; + + pixbuf = gtk_make_symbolic_pixbuf_from_data (data, size, width, height, scale, NULL, error); + + g_free (data); + + return pixbuf; +} + +/* }}} */ +/* {{{ Texture API */ + +GdkTexture * +gdk_texture_new_from_stream_at_scale (GInputStream *stream, + int width, + int height, + gboolean aspect, + GCancellable *cancellable, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, aspect, cancellable, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gdk_texture_new_from_stream (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, 0, cancellable, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gdk_texture_new_from_resource_at_scale (const char *path, + int width, + int height, + gboolean preserve_aspect, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = _gdk_pixbuf_new_from_resource_at_scale (path, width, height, preserve_aspect, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +/* }}} */ +/* {{{ Symbolic texture API */ + +GdkTexture * +gdk_texture_new_from_path_symbolic (const char *path, + int width, + int height, + double scale, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = make_symbolic_pixbuf_from_path (path, width, height, scale, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gtk_load_symbolic_texture_from_resource (const char *path) +{ + return gdk_texture_new_from_resource (path); +} + +GdkTexture * +gdk_texture_new_from_resource_symbolic (const char *path, + int width, + int height, + double scale, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture = NULL; + + pixbuf = make_symbolic_pixbuf_from_resource (path, width, height, scale, error); + if (pixbuf) + { + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + } + + return texture; +} + +GdkTexture * +gtk_load_symbolic_texture_from_file (GFile *file) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture; + GInputStream *stream; + + stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL)); + if (stream == NULL) + return NULL; + + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); + g_object_unref (stream); + if (pixbuf == NULL) + return NULL; + + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return texture; +} + +GdkTexture * +gdk_texture_new_from_file_symbolic (GFile *file, + int width, + int height, + double scale, + GError **error) +{ + GdkPixbuf *pixbuf; + GdkTexture *texture; + + pixbuf = make_symbolic_pixbuf_from_file (file, width, height, scale, error); + texture = gdk_texture_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return texture; +} + +/* }}} */ +/* {{{ Scaled paintable API */ + +typedef struct { + int scale_factor; +} LoaderData; + +static void +on_loader_size_prepared (GdkPixbufLoader *loader, + int width, + int height, + gpointer user_data) +{ + LoaderData *loader_data = user_data; + GdkPixbufFormat *format; + + /* Let the regular icon helper code path handle non-scalable images */ + format = gdk_pixbuf_loader_get_format (loader); + if (!gdk_pixbuf_format_is_scalable (format)) + { + loader_data->scale_factor = 1; + return; + } + + gdk_pixbuf_loader_set_size (loader, + width * loader_data->scale_factor, + height * loader_data->scale_factor); +} + +static GdkPaintable * +gdk_paintable_new_from_bytes_scaled (GBytes *bytes, + int scale_factor) +{ + LoaderData loader_data; + GdkTexture *texture; + GdkPaintable *paintable; + + loader_data.scale_factor = scale_factor; + + if (gdk_texture_can_load (bytes)) + { + texture = gdk_texture_new_from_bytes (bytes, NULL); + if (texture == NULL) + return NULL; + + /* We know these formats can't be scaled */ + paintable = GDK_PAINTABLE (texture); + } + else + { + GdkPixbufLoader *loader; + gboolean success; + + loader = gdk_pixbuf_loader_new (); + g_signal_connect (loader, "size-prepared", + G_CALLBACK (on_loader_size_prepared), &loader_data); + + success = gdk_pixbuf_loader_write_bytes (loader, bytes, NULL); + /* close even when writing failed */ + success &= gdk_pixbuf_loader_close (loader, NULL); + + if (!success) + return NULL; + + texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader)); + g_object_unref (loader); + + if (loader_data.scale_factor != 1) + paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor); + else + paintable = g_object_ref (GDK_PAINTABLE (texture)); + + g_object_unref (texture); + } + + return paintable; +} + +GdkPaintable * +gdk_paintable_new_from_path_scaled (const char *path, + int scale_factor) +{ + char *contents; + gsize length; + GBytes *bytes; + GdkPaintable *paintable; + + if (!g_file_get_contents (path, &contents, &length, NULL)) + return NULL; + + bytes = g_bytes_new_take (contents, length); + + paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); + + g_bytes_unref (bytes); + + return paintable; +} + +GdkPaintable * +gdk_paintable_new_from_resource_scaled (const char *path, + int scale_factor) +{ + GBytes *bytes; + GdkPaintable *paintable; + + bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); + if (!bytes) + return NULL; + + paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); + g_bytes_unref (bytes); + + return paintable; +} + +GdkPaintable * +gdk_paintable_new_from_file_scaled (GFile *file, + int scale_factor) +{ + GBytes *bytes; + GdkPaintable *paintable; + + bytes = g_file_load_bytes (file, NULL, NULL, NULL); + if (!bytes) + return NULL; + + paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor); + + g_bytes_unref (bytes); + + return paintable; +} + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/gtk/gdktextureutilsprivate.h b/gtk/gdktextureutilsprivate.h new file mode 100644 index 0000000000..77e21a4c75 --- /dev/null +++ b/gtk/gdktextureutilsprivate.h @@ -0,0 +1,73 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2016 Red Hat, Inc. + * + * 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 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, see . + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +GdkPixbuf *gtk_make_symbolic_pixbuf_from_data (const char *data, + gsize len, + int width, + int height, + double scale, + const char *debug_output_to, + GError **error); + +GdkTexture *gdk_texture_new_from_stream (GInputStream *stream, + GCancellable *cancellable, + GError **error); +GdkTexture *gdk_texture_new_from_stream_at_scale (GInputStream *stream, + int width, + int height, + gboolean aspect, + GCancellable *cancellable, + GError **error); +GdkTexture *gdk_texture_new_from_resource_at_scale (const char *path, + int width, + int height, + gboolean aspect, + GError **error); + +GdkTexture *gdk_texture_new_from_path_symbolic (const char *path, + int width, + int height, + double scale, + GError **error); +GdkTexture *gdk_texture_new_from_file_symbolic (GFile *file, + int width, + int height, + double scale, + GError **error); +GdkTexture *gdk_texture_new_from_resource_symbolic (const char *path, + int width, + int height, + double scale, + GError **error); + +GdkTexture *gtk_load_symbolic_texture_from_file (GFile *file); +GdkTexture *gtk_load_symbolic_texture_from_resource (const char *data); + +GdkPaintable *gdk_paintable_new_from_path_scaled (const char *path, + int scale_factor); +GdkPaintable *gdk_paintable_new_from_resource_scaled (const char *path, + int scale_factor); +GdkPaintable *gdk_paintable_new_from_file_scaled (GFile *file, + int scale_factor); + +G_END_DECLS diff --git a/gtk/gtkcssimagerecolor.c b/gtk/gtkcssimagerecolor.c index b9760aff4b..ab566b3e24 100644 --- a/gtk/gtkcssimagerecolor.c +++ b/gtk/gtkcssimagerecolor.c @@ -23,7 +23,7 @@ #include "gtkcssimageprivate.h" #include "gtkcsspalettevalueprivate.h" #include "gtkcsscolorvalueprivate.h" -#include "gdkpixbufutilsprivate.h" +#include "gdktextureutilsprivate.h" #include "gtkstyleproviderprivate.h" diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index 7b19810ebf..6641df003d 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -51,7 +51,7 @@ #include "gtkstyleproviderprivate.h" #include "gtksymbolicpaintable.h" #include "gtkwidgetprivate.h" -#include "gdkpixbufutilsprivate.h" +#include "gdktextureutilsprivate.h" #include "gdk/gdktextureprivate.h" #include "gdk/gdkprofilerprivate.h" diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 33c2841ef4..7945886bf0 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -31,7 +31,7 @@ #include "gtksnapshot.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" -#include "gdkpixbufutilsprivate.h" +#include "gdktextureutilsprivate.h" #include #include diff --git a/gtk/gtkpicture.c b/gtk/gtkpicture.c index dadd2b4b6e..9f0665d7f5 100644 --- a/gtk/gtkpicture.c +++ b/gtk/gtkpicture.c @@ -28,7 +28,7 @@ #include "gtksnapshot.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" -#include "gdkpixbufutilsprivate.h" +#include "gdktextureutilsprivate.h" /** * GtkPicture: diff --git a/gtk/meson.build b/gtk/meson.build index bf04d21095..201c8c9fd0 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -15,7 +15,7 @@ gtk_cargs = [ # introspected gtk_private_sources = files([ 'fnmatch.c', - 'gdkpixbufutils.c', + 'gdktextureutils.c', 'gsettings-mapping.c', 'gtkaccessibleattributeset.c', 'gtkaccessiblevalue.c', diff --git a/tools/encodesymbolic.c b/tools/encodesymbolic.c index bfe96005b8..d471394544 100644 --- a/tools/encodesymbolic.c +++ b/tools/encodesymbolic.c @@ -31,7 +31,7 @@ #include #include -#include "gdkpixbufutilsprivate.h" +#include "gdktextureutilsprivate.h" static char *output_dir = NULL; -- cgit v1.2.1