2 * Copyright © 2011 Red Hat Inc.
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Benjamin Otte <otte@gnome.org>
23 #include "gtkcssimagegradientprivate.h"
25 #include "gtkcssprovider.h"
27 G_DEFINE_TYPE (GtkCssImageGradient, _gtk_css_image_gradient, GTK_TYPE_CSS_IMAGE)
30 gtk_css_image_gradient_compute (GtkCssImage *image,
31 GtkStyleContext *context)
33 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
34 GtkCssImageGradient *copy;
36 if (gradient->pattern)
37 return g_object_ref (gradient);
39 copy = g_object_new (GTK_TYPE_CSS_IMAGE_GRADIENT, NULL);
40 copy->gradient = gtk_gradient_ref (gradient->gradient);
41 copy->pattern = gtk_gradient_resolve_for_context (copy->gradient, context);
43 return GTK_CSS_IMAGE (copy);
47 gtk_css_image_gradient_draw (GtkCssImage *image,
52 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
54 if (!gradient->pattern)
56 g_warning ("trying to paint unresolved gradient");
60 cairo_scale (cr, width, height);
62 cairo_rectangle (cr, 0, 0, 1, 1);
63 cairo_set_source (cr, gradient->pattern);
68 gtk_css_image_gradient_parse (GtkCssImage *image,
72 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
74 gradient->gradient = _gtk_gradient_parse (parser);
76 return gradient->gradient != NULL;
80 gtk_css_image_gradient_print (GtkCssImage *image,
83 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
86 s = gtk_gradient_to_string (gradient->gradient);
87 g_string_append (string, s);
92 gtk_css_image_gradient_dispose (GObject *object)
94 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (object);
96 if (gradient->gradient)
98 gtk_gradient_unref (gradient->gradient);
99 gradient->gradient = NULL;
101 if (gradient->pattern)
103 cairo_pattern_destroy (gradient->pattern);
104 gradient->pattern = NULL;
107 G_OBJECT_CLASS (_gtk_css_image_gradient_parent_class)->dispose (object);
111 _gtk_css_image_gradient_class_init (GtkCssImageGradientClass *klass)
113 GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
114 GObjectClass *object_class = G_OBJECT_CLASS (klass);
116 image_class->compute = gtk_css_image_gradient_compute;
117 image_class->draw = gtk_css_image_gradient_draw;
118 image_class->parse = gtk_css_image_gradient_parse;
119 image_class->print = gtk_css_image_gradient_print;
121 object_class->dispose = gtk_css_image_gradient_dispose;
125 _gtk_css_image_gradient_init (GtkCssImageGradient *image_gradient)
130 _gtk_gradient_parse (GtkCssParser *parser)
132 GtkGradient *gradient;
133 cairo_pattern_type_t type;
137 g_return_val_if_fail (parser != NULL, NULL);
139 if (!_gtk_css_parser_try (parser, "-gtk-gradient", TRUE))
141 _gtk_css_parser_error (parser,
142 "Expected '-gtk-gradient'");
146 if (!_gtk_css_parser_try (parser, "(", TRUE))
148 _gtk_css_parser_error (parser,
149 "Expected '(' after '-gtk-gradient'");
153 /* Parse gradient type */
154 if (_gtk_css_parser_try (parser, "linear", TRUE))
155 type = CAIRO_PATTERN_TYPE_LINEAR;
156 else if (_gtk_css_parser_try (parser, "radial", TRUE))
157 type = CAIRO_PATTERN_TYPE_RADIAL;
160 _gtk_css_parser_error (parser,
161 "Gradient type must be 'radial' or 'linear'");
165 /* Parse start/stop position parameters */
166 for (i = 0; i < 2; i++)
168 if (! _gtk_css_parser_try (parser, ",", TRUE))
170 _gtk_css_parser_error (parser,
175 if (_gtk_css_parser_try (parser, "left", TRUE))
177 else if (_gtk_css_parser_try (parser, "right", TRUE))
179 else if (_gtk_css_parser_try (parser, "center", TRUE))
181 else if (!_gtk_css_parser_try_double (parser, &coords[i * 3]))
183 _gtk_css_parser_error (parser,
184 "Expected a valid X coordinate");
188 if (_gtk_css_parser_try (parser, "top", TRUE))
189 coords[i * 3 + 1] = 0;
190 else if (_gtk_css_parser_try (parser, "bottom", TRUE))
191 coords[i * 3 + 1] = 1;
192 else if (_gtk_css_parser_try (parser, "center", TRUE))
193 coords[i * 3 + 1] = 0.5;
194 else if (!_gtk_css_parser_try_double (parser, &coords[i * 3 + 1]))
196 _gtk_css_parser_error (parser,
197 "Expected a valid Y coordinate");
201 if (type == CAIRO_PATTERN_TYPE_RADIAL)
204 if (! _gtk_css_parser_try (parser, ",", TRUE))
206 _gtk_css_parser_error (parser,
211 if (! _gtk_css_parser_try_double (parser, &coords[(i * 3) + 2]))
213 _gtk_css_parser_error (parser,
214 "Expected a numer for the radius");
220 if (type == CAIRO_PATTERN_TYPE_LINEAR)
221 gradient = gtk_gradient_new_linear (coords[0], coords[1], coords[3], coords[4]);
223 gradient = gtk_gradient_new_radial (coords[0], coords[1], coords[2],
224 coords[3], coords[4], coords[5]);
226 while (_gtk_css_parser_try (parser, ",", TRUE))
228 GtkSymbolicColor *color;
231 if (_gtk_css_parser_try (parser, "from", TRUE))
235 if (!_gtk_css_parser_try (parser, "(", TRUE))
237 gtk_gradient_unref (gradient);
238 _gtk_css_parser_error (parser,
244 else if (_gtk_css_parser_try (parser, "to", TRUE))
248 if (!_gtk_css_parser_try (parser, "(", TRUE))
250 gtk_gradient_unref (gradient);
251 _gtk_css_parser_error (parser,
257 else if (_gtk_css_parser_try (parser, "color-stop", TRUE))
259 if (!_gtk_css_parser_try (parser, "(", TRUE))
261 gtk_gradient_unref (gradient);
262 _gtk_css_parser_error (parser,
267 if (!_gtk_css_parser_try_double (parser, &position))
269 gtk_gradient_unref (gradient);
270 _gtk_css_parser_error (parser,
271 "Expected a valid number");
275 if (!_gtk_css_parser_try (parser, ",", TRUE))
277 gtk_gradient_unref (gradient);
278 _gtk_css_parser_error (parser,
285 gtk_gradient_unref (gradient);
286 _gtk_css_parser_error (parser,
287 "Not a valid color-stop definition");
291 color = _gtk_css_parser_read_symbolic_color (parser);
294 gtk_gradient_unref (gradient);
298 gtk_gradient_add_color_stop (gradient, position, color);
299 gtk_symbolic_color_unref (color);
301 if (!_gtk_css_parser_try (parser, ")", TRUE))
303 gtk_gradient_unref (gradient);
304 _gtk_css_parser_error (parser,
310 if (!_gtk_css_parser_try (parser, ")", TRUE))
312 gtk_gradient_unref (gradient);
313 _gtk_css_parser_error (parser,