X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcssimageurl.c;h=0a7c4f3eef2dfb84de5f1cc77f0e57c8b6e61178;hb=e1edc998a2e9c557030d207533932b3120e13fe5;hp=2f1cca9a4743170c8b09136d56ce55e2ce2bc263;hpb=9ad78370eb3cd29613b7491bb363f6d395f155d0;p=~andy%2Fgtk diff --git a/gtk/gtkcssimageurl.c b/gtk/gtkcssimageurl.c index 2f1cca9a4..0a7c4f3ee 100644 --- a/gtk/gtkcssimageurl.c +++ b/gtk/gtkcssimageurl.c @@ -12,26 +12,81 @@ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * License along with this library. If not, see . * * Authors: Benjamin Otte */ #include "config.h" -#include "gtkcssimageurlprivate.h" +#include -#include "gtkcssprovider.h" +#include "gtkcssimageurlprivate.h" +#include "gtkcssimagesurfaceprivate.h" G_DEFINE_TYPE (GtkCssImageUrl, _gtk_css_image_url, GTK_TYPE_CSS_IMAGE) +static GtkCssImage * +gtk_css_image_url_load_image (GtkCssImageUrl *url) +{ + GdkPixbuf *pixbuf; + GError *error = NULL; + GFileInputStream *input; + + if (url->loaded_image) + return url->loaded_image; + + /* We special case resources here so we can use + gdk_pixbuf_new_from_resource, which in turn has some special casing + for GdkPixdata files to avoid duplicating the memory for the pixbufs */ + if (g_file_has_uri_scheme (url->file, "resource")) + { + char *uri = g_file_get_uri (url->file); + char *resource_path = g_uri_unescape_string (uri + strlen ("resource://"), NULL); + + pixbuf = gdk_pixbuf_new_from_resource (resource_path, &error); + g_free (resource_path); + g_free (uri); + } + else + { + input = g_file_read (url->file, NULL, &error); + if (input != NULL) + { + pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (input), NULL, &error); + g_object_unref (input); + } + else + { + pixbuf = NULL; + } + } + + if (pixbuf == NULL) + { + cairo_surface_t *empty = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); + + /* XXX: Can we get the error somehow sent to the CssProvider? + * I don't like just dumping it to stderr or losing it completely. */ + g_warning ("Error loading image: %s", error->message); + g_error_free (error); + url->loaded_image = _gtk_css_image_surface_new (empty); + cairo_surface_destroy (empty); + return url->loaded_image; + } + + url->loaded_image = _gtk_css_image_surface_new_for_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return url->loaded_image; +} + static int gtk_css_image_url_get_width (GtkCssImage *image) { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); - return cairo_image_surface_get_width (url->surface); + return _gtk_css_image_get_width (gtk_css_image_url_load_image (url)); } static int @@ -39,7 +94,15 @@ gtk_css_image_url_get_height (GtkCssImage *image) { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); - return cairo_image_surface_get_height (url->surface); + return _gtk_css_image_get_height (gtk_css_image_url_load_image (url)); +} + +static double +gtk_css_image_url_get_aspect_ratio (GtkCssImage *image) +{ + GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); + + return _gtk_css_image_get_aspect_ratio (gtk_css_image_url_load_image (url)); } static void @@ -50,86 +113,42 @@ gtk_css_image_url_draw (GtkCssImage *image, { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); - cairo_rectangle (cr, 0, 0, width, height); - cairo_scale (cr, - width / cairo_image_surface_get_width (url->surface), - height / cairo_image_surface_get_height (url->surface)); - cairo_set_source_surface (cr, url->surface, 0, 0); - cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD); - cairo_fill (cr); + _gtk_css_image_draw (gtk_css_image_url_load_image (url), cr, width, height); +} + +static GtkCssImage * +gtk_css_image_url_compute (GtkCssImage *image, + guint property_id, + GtkStyleProviderPrivate *provider, + GtkCssComputedValues *values, + GtkCssComputedValues *parent_values, + GtkCssDependencies *dependencies) +{ + GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); + + return g_object_ref (gtk_css_image_url_load_image (url)); } static gboolean gtk_css_image_url_parse (GtkCssImage *image, - GtkCssParser *parser, - GFile *base) + GtkCssParser *parser) { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); - GdkPixbuf *pixbuf; - GFile *file; - char *path; - cairo_t *cr; - GError *error = NULL; - file = _gtk_css_parser_read_url (parser, base); - if (file == NULL) + url->file = _gtk_css_parser_read_url (parser); + if (url->file == NULL) return FALSE; - path = g_file_get_path (file); - g_object_unref (file); - - pixbuf = gdk_pixbuf_new_from_file (path, &error); - g_free (path); - if (pixbuf == NULL) - { - _gtk_css_parser_take_error (parser, error); - return FALSE; - } - - url->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - cr = cairo_create (url->surface); - gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); - cairo_paint (cr); - cairo_destroy (cr); - g_object_unref (pixbuf); - return TRUE; } -static cairo_status_t -surface_write (void *closure, - const unsigned char *data, - unsigned int length) -{ - g_byte_array_append (closure, data, length); - - return CAIRO_STATUS_SUCCESS; -} - static void gtk_css_image_url_print (GtkCssImage *image, GString *string) { -#if CAIRO_HAS_PNG_FUNCTIONS GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); - GByteArray *array; - char *base64; - - array = g_byte_array_new (); - cairo_surface_write_to_png_stream (url->surface, surface_write, array); - base64 = g_base64_encode (array->data, array->len); - g_byte_array_free (array, TRUE); - - g_string_append (string, "url(\"data:image/png;base64,"); - g_string_append (string, base64); - g_string_append (string, "\")"); - - g_free (base64); -#else - g_string_append (string, "none /* you need cairo png functions enabled to make this work */"); -#endif + + _gtk_css_image_print (gtk_css_image_url_load_image (url), string); } static void @@ -137,11 +156,8 @@ gtk_css_image_url_dispose (GObject *object) { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (object); - if (url->surface) - { - cairo_surface_destroy (url->surface); - url->surface = NULL; - } + g_clear_object (&url->file); + g_clear_object (&url->loaded_image); G_OBJECT_CLASS (_gtk_css_image_url_parent_class)->dispose (object); } @@ -154,6 +170,8 @@ _gtk_css_image_url_class_init (GtkCssImageUrlClass *klass) image_class->get_width = gtk_css_image_url_get_width; image_class->get_height = gtk_css_image_url_get_height; + image_class->get_aspect_ratio = gtk_css_image_url_get_aspect_ratio; + image_class->compute = gtk_css_image_url_compute; image_class->draw = gtk_css_image_url_draw; image_class->parse = gtk_css_image_url_parse; image_class->print = gtk_css_image_url_print;