]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssimagesurface.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkcssimagesurface.c
1 /*
2  * Copyright © 2011 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authors: Benjamin Otte <otte@gnome.org>
18  */
19
20 #include "config.h"
21
22 #include "gtkcssimagesurfaceprivate.h"
23
24 G_DEFINE_TYPE (GtkCssImageSurface, _gtk_css_image_surface, GTK_TYPE_CSS_IMAGE)
25
26 static int
27 gtk_css_image_surface_get_width (GtkCssImage *image)
28 {
29   GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image);
30
31   return cairo_image_surface_get_width (surface->surface);
32 }
33
34 static int
35 gtk_css_image_surface_get_height (GtkCssImage *image)
36 {
37   GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image);
38
39   return cairo_image_surface_get_height (surface->surface);
40 }
41
42 static void
43 gtk_css_image_surface_draw (GtkCssImage *image,
44                             cairo_t     *cr,
45                             double       width,
46                             double       height)
47 {
48   GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image);
49
50   cairo_rectangle (cr, 0, 0, width, height);
51   cairo_scale (cr,
52                width / cairo_image_surface_get_width (surface->surface),
53                height / cairo_image_surface_get_height (surface->surface));
54   cairo_set_source_surface (cr, surface->surface, 0, 0);
55   cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
56   cairo_fill (cr);
57 }
58
59 static cairo_status_t
60 surface_write (void                *closure,
61                const unsigned char *data,
62                unsigned int         length)
63 {
64   g_byte_array_append (closure, data, length);
65
66   return CAIRO_STATUS_SUCCESS;
67 }
68
69 static void
70 gtk_css_image_surface_print (GtkCssImage *image,
71                              GString     *string)
72 {
73 #if CAIRO_HAS_PNG_FUNCTIONS
74   GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image);
75   GByteArray *array;
76   char *base64;
77   
78   array = g_byte_array_new ();
79   cairo_surface_write_to_png_stream (surface->surface, surface_write, array);
80   base64 = g_base64_encode (array->data, array->len);
81   g_byte_array_free (array, TRUE);
82
83   g_string_append (string, "url(\"data:image/png;base64,");
84   g_string_append (string, base64);
85   g_string_append (string, "\")");
86
87   g_free (base64);
88 #else
89   g_string_append (string, "none /* you need cairo png functions enabled to make this work */");
90 #endif
91 }
92
93 static void
94 gtk_css_image_surface_dispose (GObject *object)
95 {
96   GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (object);
97
98   if (surface->surface)
99     {
100       cairo_surface_destroy (surface->surface);
101       surface->surface = NULL;
102     }
103
104   G_OBJECT_CLASS (_gtk_css_image_surface_parent_class)->dispose (object);
105 }
106
107 static void
108 _gtk_css_image_surface_class_init (GtkCssImageSurfaceClass *klass)
109 {
110   GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
111   GObjectClass *object_class = G_OBJECT_CLASS (klass);
112
113   image_class->get_width = gtk_css_image_surface_get_width;
114   image_class->get_height = gtk_css_image_surface_get_height;
115   image_class->draw = gtk_css_image_surface_draw;
116   image_class->print = gtk_css_image_surface_print;
117
118   object_class->dispose = gtk_css_image_surface_dispose;
119 }
120
121 static void
122 _gtk_css_image_surface_init (GtkCssImageSurface *image_surface)
123 {
124 }
125
126 GtkCssImage *
127 _gtk_css_image_surface_new (cairo_surface_t *surface)
128 {
129   GtkCssImage *image;
130
131   g_return_val_if_fail (surface != NULL, NULL);
132
133   image = g_object_new (GTK_TYPE_CSS_IMAGE_SURFACE, NULL);
134   
135   GTK_CSS_IMAGE_SURFACE (image)->surface = cairo_surface_reference (surface);
136
137   return image;
138 }
139
140 GtkCssImage *
141 _gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf)
142 {
143   GtkCssImage *image;
144   cairo_surface_t *surface;
145   cairo_t *cr;
146
147   g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
148
149   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
150                                         gdk_pixbuf_get_width (pixbuf),
151                                         gdk_pixbuf_get_height (pixbuf));
152   cr = cairo_create (surface);
153   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
154   cairo_paint (cr);
155   cairo_destroy (cr);
156
157   image = _gtk_css_image_surface_new (surface);
158
159   cairo_surface_destroy (surface);
160
161   return image;
162 }
163