From: Benjamin Otte Date: Fri, 1 Feb 2013 22:15:27 +0000 (+0100) Subject: css: Split out GtkCssImageSurface X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=18ca907c4cb37c234868ef13797f1a563fe01502;p=~andy%2Fgtk css: Split out GtkCssImageSurface This is essentially a GtkCssImage for a cairo_surface_t and is a pretty much straight up copy of GtkCssImageUrl. But we want to implement lazy loading and animations, so GtkCssImageUrl is going to gain new features... https://bugzilla.gnome.org/show_bug.cgi?id=692934 --- diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 19c8e10ff..e47670670 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -447,6 +447,7 @@ gtk_private_h_sources = \ gtkcssimagegradientprivate.h \ gtkcssimagelinearprivate.h \ gtkcssimageprivate.h \ + gtkcssimagesurfaceprivate.h \ gtkcssimageurlprivate.h \ gtkcssimagevalueprivate.h \ gtkcssimagewin32private.h \ @@ -672,6 +673,7 @@ gtk_base_c_sources = \ gtkcssimagecrossfade.c \ gtkcssimagegradient.c \ gtkcssimagelinear.c \ + gtkcssimagesurface.c \ gtkcssimageurl.c \ gtkcssimagevalue.c \ gtkcssimagewin32.c \ diff --git a/gtk/gtkcssimagesurface.c b/gtk/gtkcssimagesurface.c new file mode 100644 index 000000000..f2b6704e4 --- /dev/null +++ b/gtk/gtkcssimagesurface.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2011 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.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, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkcssimagesurfaceprivate.h" + +G_DEFINE_TYPE (GtkCssImageSurface, _gtk_css_image_surface, GTK_TYPE_CSS_IMAGE) + +static int +gtk_css_image_surface_get_width (GtkCssImage *image) +{ + GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image); + + return cairo_image_surface_get_width (surface->surface); +} + +static int +gtk_css_image_surface_get_height (GtkCssImage *image) +{ + GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image); + + return cairo_image_surface_get_height (surface->surface); +} + +static void +gtk_css_image_surface_draw (GtkCssImage *image, + cairo_t *cr, + double width, + double height) +{ + GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image); + + cairo_rectangle (cr, 0, 0, width, height); + cairo_scale (cr, + width / cairo_image_surface_get_width (surface->surface), + height / cairo_image_surface_get_height (surface->surface)); + cairo_set_source_surface (cr, surface->surface, 0, 0); + cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD); + cairo_fill (cr); +} + +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_surface_print (GtkCssImage *image, + GString *string) +{ +#if CAIRO_HAS_PNG_FUNCTIONS + GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image); + GByteArray *array; + char *base64; + + array = g_byte_array_new (); + cairo_surface_write_to_png_stream (surface->surface, surface_write, array); + base64 = g_base64_encode (array->data, array->len); + g_byte_array_free (array, TRUE); + + g_string_append (string, "surface(\"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 +} + +static void +gtk_css_image_surface_dispose (GObject *object) +{ + GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (object); + + if (surface->surface) + { + cairo_surface_destroy (surface->surface); + surface->surface = NULL; + } + + G_OBJECT_CLASS (_gtk_css_image_surface_parent_class)->dispose (object); +} + +static void +_gtk_css_image_surface_class_init (GtkCssImageSurfaceClass *klass) +{ + GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + image_class->get_width = gtk_css_image_surface_get_width; + image_class->get_height = gtk_css_image_surface_get_height; + image_class->draw = gtk_css_image_surface_draw; + image_class->print = gtk_css_image_surface_print; + + object_class->dispose = gtk_css_image_surface_dispose; +} + +static void +_gtk_css_image_surface_init (GtkCssImageSurface *image_surface) +{ +} + +GtkCssImage * +_gtk_css_image_surface_new (cairo_surface_t *surface) +{ + GtkCssImage *image; + + g_return_val_if_fail (surface != NULL, NULL); + + image = g_object_new (GTK_TYPE_CSS_IMAGE_SURFACE, NULL); + + GTK_CSS_IMAGE_SURFACE (image)->surface = cairo_surface_reference (surface); + + return image; +} + +GtkCssImage * +_gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf) +{ + GtkCssImage *image; + cairo_surface_t *surface; + cairo_t *cr; + + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + cr = cairo_create (surface); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + + image = _gtk_css_image_surface_new (surface); + + cairo_surface_destroy (surface); + + return image; +} + diff --git a/gtk/gtkcssimagesurfaceprivate.h b/gtk/gtkcssimagesurfaceprivate.h new file mode 100644 index 000000000..87baab288 --- /dev/null +++ b/gtk/gtkcssimagesurfaceprivate.h @@ -0,0 +1,56 @@ +/* + * Copyright © 2011 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.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, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_CSS_IMAGE_SURFACE_PRIVATE_H__ +#define __GTK_CSS_IMAGE_SURFACE_PRIVATE_H__ + +#include "gtk/gtkcssimageprivate.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_CSS_IMAGE_SURFACE (_gtk_css_image_surface_get_type ()) +#define GTK_CSS_IMAGE_SURFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_SURFACE, GtkCssImageSurface)) +#define GTK_CSS_IMAGE_SURFACE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_SURFACE, GtkCssImageSurfaceClass)) +#define GTK_IS_CSS_IMAGE_SURFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_SURFACE)) +#define GTK_IS_CSS_IMAGE_SURFACE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_SURFACE)) +#define GTK_CSS_IMAGE_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_SURFACE, GtkCssImageSurfaceClass)) + +typedef struct _GtkCssImageSurface GtkCssImageSurface; +typedef struct _GtkCssImageSurfaceClass GtkCssImageSurfaceClass; + +struct _GtkCssImageSurface +{ + GtkCssImage parent; + + cairo_surface_t *surface; /* the surface we render - guaranteed to be an image surface */ +}; + +struct _GtkCssImageSurfaceClass +{ + GtkCssImageClass parent_class; +}; + +GType _gtk_css_image_surface_get_type (void) G_GNUC_CONST; + +GtkCssImage * _gtk_css_image_surface_new (cairo_surface_t *surface); +GtkCssImage * _gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf); + +G_END_DECLS + +#endif /* __GTK_CSS_IMAGE_SURFACE_PRIVATE_H__ */ diff --git a/gtk/gtkcssimageurl.c b/gtk/gtkcssimageurl.c index 2c6dc898e..746289572 100644 --- a/gtk/gtkcssimageurl.c +++ b/gtk/gtkcssimageurl.c @@ -22,8 +22,7 @@ #include #include "gtkcssimageurlprivate.h" - -#include "gtkcssprovider.h" +#include "gtkcssimagesurfaceprivate.h" G_DEFINE_TYPE (GtkCssImageUrl, _gtk_css_image_url, GTK_TYPE_CSS_IMAGE) @@ -32,7 +31,7 @@ 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 (url->loaded_image); } static int @@ -40,7 +39,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 (url->loaded_image); +} + +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 (url->loaded_image); } static void @@ -51,13 +58,7 @@ 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 (url->loaded_image, cr, width, height); } static gboolean @@ -66,7 +67,6 @@ gtk_css_image_url_parse (GtkCssImage *image, { GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image); GdkPixbuf *pixbuf; - cairo_t *cr; GError *error = NULL; GFileInputStream *input; @@ -105,50 +105,19 @@ gtk_css_image_url_parse (GtkCssImage *image, 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); + url->loaded_image = _gtk_css_image_surface_new_for_pixbuf (pixbuf); 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 (url->loaded_image, string); } static void @@ -157,12 +126,7 @@ gtk_css_image_url_dispose (GObject *object) GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (object); g_clear_object (&url->file); - - if (url->surface) - { - cairo_surface_destroy (url->surface); - url->surface = NULL; - } + g_clear_object (&url->loaded_image); G_OBJECT_CLASS (_gtk_css_image_url_parent_class)->dispose (object); } @@ -175,6 +139,7 @@ _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->draw = gtk_css_image_url_draw; image_class->parse = gtk_css_image_url_parse; image_class->print = gtk_css_image_url_print; diff --git a/gtk/gtkcssimageurlprivate.h b/gtk/gtkcssimageurlprivate.h index e2df7f1c7..f2d91d146 100644 --- a/gtk/gtkcssimageurlprivate.h +++ b/gtk/gtkcssimageurlprivate.h @@ -39,7 +39,7 @@ struct _GtkCssImageUrl GtkCssImage parent; GFile *file; /* the file we're loading from */ - cairo_surface_t *surface; /* the surface we render - guaranteed to be an image surface */ + GtkCssImage *loaded_image; /* the actual image we render */ }; struct _GtkCssImageUrlClass