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, see <http://www.gnu.org/licenses/>.
17 * Authors: Benjamin Otte <otte@gnome.org>
22 #include "gtkcssimagegradientprivate.h"
24 #include "gtkcssprovider.h"
26 G_DEFINE_TYPE (GtkCssImageGradient, _gtk_css_image_gradient, GTK_TYPE_CSS_IMAGE)
29 gtk_css_image_gradient_compute (GtkCssImage *image,
30 GtkStyleContext *context)
32 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
33 GtkCssImageGradient *copy;
35 if (gradient->pattern)
36 return g_object_ref (gradient);
38 copy = g_object_new (GTK_TYPE_CSS_IMAGE_GRADIENT, NULL);
39 copy->gradient = gtk_gradient_ref (gradient->gradient);
40 copy->pattern = gtk_gradient_resolve_for_context (copy->gradient, context);
42 return GTK_CSS_IMAGE (copy);
46 gtk_css_image_gradient_draw (GtkCssImage *image,
51 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
53 if (!gradient->pattern)
55 g_warning ("trying to paint unresolved gradient");
59 cairo_scale (cr, width, height);
61 cairo_rectangle (cr, 0, 0, 1, 1);
62 cairo_set_source (cr, gradient->pattern);
67 gtk_css_image_gradient_parse (GtkCssImage *image,
71 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
73 gradient->gradient = _gtk_gradient_parse (parser);
75 return gradient->gradient != NULL;
79 gtk_css_image_gradient_print (GtkCssImage *image,
82 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
85 s = gtk_gradient_to_string (gradient->gradient);
86 g_string_append (string, s);
91 gtk_css_image_gradient_dispose (GObject *object)
93 GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (object);
95 if (gradient->gradient)
97 gtk_gradient_unref (gradient->gradient);
98 gradient->gradient = NULL;
100 if (gradient->pattern)
102 cairo_pattern_destroy (gradient->pattern);
103 gradient->pattern = NULL;
106 G_OBJECT_CLASS (_gtk_css_image_gradient_parent_class)->dispose (object);
110 _gtk_css_image_gradient_class_init (GtkCssImageGradientClass *klass)
112 GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
113 GObjectClass *object_class = G_OBJECT_CLASS (klass);
115 image_class->compute = gtk_css_image_gradient_compute;
116 image_class->draw = gtk_css_image_gradient_draw;
117 image_class->parse = gtk_css_image_gradient_parse;
118 image_class->print = gtk_css_image_gradient_print;
120 object_class->dispose = gtk_css_image_gradient_dispose;
124 _gtk_css_image_gradient_init (GtkCssImageGradient *image_gradient)
129 _gtk_gradient_parse (GtkCssParser *parser)
131 GtkGradient *gradient;
132 cairo_pattern_type_t type;
136 g_return_val_if_fail (parser != NULL, NULL);
138 if (!_gtk_css_parser_try (parser, "-gtk-gradient", TRUE))
140 _gtk_css_parser_error (parser,
141 "Expected '-gtk-gradient'");
145 if (!_gtk_css_parser_try (parser, "(", TRUE))
147 _gtk_css_parser_error (parser,
148 "Expected '(' after '-gtk-gradient'");
152 /* Parse gradient type */
153 if (_gtk_css_parser_try (parser, "linear", TRUE))
154 type = CAIRO_PATTERN_TYPE_LINEAR;
155 else if (_gtk_css_parser_try (parser, "radial", TRUE))
156 type = CAIRO_PATTERN_TYPE_RADIAL;
159 _gtk_css_parser_error (parser,
160 "Gradient type must be 'radial' or 'linear'");
164 /* Parse start/stop position parameters */
165 for (i = 0; i < 2; i++)
167 if (! _gtk_css_parser_try (parser, ",", TRUE))
169 _gtk_css_parser_error (parser,
174 if (_gtk_css_parser_try (parser, "left", TRUE))
176 else if (_gtk_css_parser_try (parser, "right", TRUE))
178 else if (_gtk_css_parser_try (parser, "center", TRUE))
180 else if (!_gtk_css_parser_try_double (parser, &coords[i * 3]))
182 _gtk_css_parser_error (parser,
183 "Expected a valid X coordinate");
187 if (_gtk_css_parser_try (parser, "top", TRUE))
188 coords[i * 3 + 1] = 0;
189 else if (_gtk_css_parser_try (parser, "bottom", TRUE))
190 coords[i * 3 + 1] = 1;
191 else if (_gtk_css_parser_try (parser, "center", TRUE))
192 coords[i * 3 + 1] = 0.5;
193 else if (!_gtk_css_parser_try_double (parser, &coords[i * 3 + 1]))
195 _gtk_css_parser_error (parser,
196 "Expected a valid Y coordinate");
200 if (type == CAIRO_PATTERN_TYPE_RADIAL)
203 if (! _gtk_css_parser_try (parser, ",", TRUE))
205 _gtk_css_parser_error (parser,
210 if (! _gtk_css_parser_try_double (parser, &coords[(i * 3) + 2]))
212 _gtk_css_parser_error (parser,
213 "Expected a numer for the radius");
219 if (type == CAIRO_PATTERN_TYPE_LINEAR)
220 gradient = gtk_gradient_new_linear (coords[0], coords[1], coords[3], coords[4]);
222 gradient = gtk_gradient_new_radial (coords[0], coords[1], coords[2],
223 coords[3], coords[4], coords[5]);
225 while (_gtk_css_parser_try (parser, ",", TRUE))
227 GtkSymbolicColor *color;
230 if (_gtk_css_parser_try (parser, "from", TRUE))
234 if (!_gtk_css_parser_try (parser, "(", TRUE))
236 gtk_gradient_unref (gradient);
237 _gtk_css_parser_error (parser,
243 else if (_gtk_css_parser_try (parser, "to", TRUE))
247 if (!_gtk_css_parser_try (parser, "(", TRUE))
249 gtk_gradient_unref (gradient);
250 _gtk_css_parser_error (parser,
256 else if (_gtk_css_parser_try (parser, "color-stop", TRUE))
258 if (!_gtk_css_parser_try (parser, "(", TRUE))
260 gtk_gradient_unref (gradient);
261 _gtk_css_parser_error (parser,
266 if (!_gtk_css_parser_try_double (parser, &position))
268 gtk_gradient_unref (gradient);
269 _gtk_css_parser_error (parser,
270 "Expected a valid number");
274 if (!_gtk_css_parser_try (parser, ",", TRUE))
276 gtk_gradient_unref (gradient);
277 _gtk_css_parser_error (parser,
284 gtk_gradient_unref (gradient);
285 _gtk_css_parser_error (parser,
286 "Not a valid color-stop definition");
290 color = _gtk_css_parser_read_symbolic_color (parser);
293 gtk_gradient_unref (gradient);
297 gtk_gradient_add_color_stop (gradient, position, color);
298 gtk_symbolic_color_unref (color);
300 if (!_gtk_css_parser_try (parser, ")", TRUE))
302 gtk_gradient_unref (gradient);
303 _gtk_css_parser_error (parser,
309 if (!_gtk_css_parser_try (parser, ")", TRUE))
311 gtk_gradient_unref (gradient);
312 _gtk_css_parser_error (parser,