1/*
2 * Copyright © 2015 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: Matthias Clasen <mclasen@redhat.com>
18 */
19
20#include "config.h"
21
22#include "gtkcssimageradialprivate.h"
23
24#include <math.h>
25
26#include "gtkcsscolorvalueprivate.h"
27#include "gtkcssnumbervalueprivate.h"
28#include "gtkcsspositionvalueprivate.h"
29#include "gtkcsscolorvalueprivate.h"
30#include "gtkcssprovider.h"
31
32G_DEFINE_TYPE (GtkCssImageRadial, _gtk_css_image_radial, GTK_TYPE_CSS_IMAGE)
33
34static void
35gtk_css_image_radial_get_start_end (GtkCssImageRadial *radial,
36 double radius,
37 double *start,
38 double *end)
39{
40 const GtkCssImageRadialColorStop *stop;
41 double pos;
42 guint i;
43
44 if (radial->repeating)
45 {
46 stop = &radial->color_stops[0];
47 if (stop->offset == NULL)
48 *start = 0;
49 else
50 *start = _gtk_css_number_value_get (number: stop->offset, one_hundred_percent: radius) / radius;
51
52 *end = *start;
53
54 for (i = 0; i < radial->n_stops; i++)
55 {
56 stop = &radial->color_stops[i];
57
58 if (stop->offset == NULL)
59 continue;
60
61 pos = _gtk_css_number_value_get (number: stop->offset, one_hundred_percent: radius) / radius;
62
63 *end = MAX (pos, *end);
64 }
65
66 if (stop->offset == NULL)
67 *end = MAX (*end, 1.0);
68 }
69 else
70 {
71 *start = 0;
72 *end = 1;
73 }
74}
75
76static void
77gtk_css_image_radial_snapshot (GtkCssImage *image,
78 GtkSnapshot *snapshot,
79 double width,
80 double height)
81{
82 GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
83 GskColorStop *stops;
84 double x, y;
85 double hradius, vradius;
86 double start, end;
87 double r1, r2, r3, r4, r;
88 double offset;
89 int i, last;
90
91 x = _gtk_css_position_value_get_x (position: radial->position, one_hundred_percent: width);
92 y = _gtk_css_position_value_get_y (position: radial->position, one_hundred_percent: height);
93
94 if (radial->circle)
95 {
96 switch (radial->size)
97 {
98 case GTK_CSS_EXPLICIT_SIZE:
99 hradius = _gtk_css_number_value_get (number: radial->sizes[0], one_hundred_percent: width);
100 break;
101 case GTK_CSS_CLOSEST_SIDE:
102 hradius = MIN (MIN (x, width - x), MIN (y, height - y));
103 break;
104 case GTK_CSS_FARTHEST_SIDE:
105 hradius = MAX (MAX (x, width - x), MAX (y, height - y));
106 break;
107 case GTK_CSS_CLOSEST_CORNER:
108 case GTK_CSS_FARTHEST_CORNER:
109 r1 = x*x + y*y;
110 r2 = x*x + (height - y)*(height - y);
111 r3 = (width - x)*(width - x) + y*y;
112 r4 = (width - x)*(width - x) + (height - y)*(height - y);
113 if (radial->size == GTK_CSS_CLOSEST_CORNER)
114 r = MIN ( MIN (r1, r2), MIN (r3, r4));
115 else
116 r = MAX ( MAX (r1, r2), MAX (r3, r4));
117 hradius = sqrt (x: r);
118 break;
119 default:
120 g_assert_not_reached ();
121 }
122
123 hradius = MAX (1.0, hradius);
124 vradius = hradius;
125 }
126 else
127 {
128 switch (radial->size)
129 {
130 case GTK_CSS_EXPLICIT_SIZE:
131 hradius = _gtk_css_number_value_get (number: radial->sizes[0], one_hundred_percent: width);
132 vradius = _gtk_css_number_value_get (number: radial->sizes[1], one_hundred_percent: height);
133 break;
134 case GTK_CSS_CLOSEST_SIDE:
135 hradius = MIN (x, width - x);
136 vradius = MIN (y, height - y);
137 break;
138 case GTK_CSS_FARTHEST_SIDE:
139 hradius = MAX (x, width - x);
140 vradius = MAX (y, height - y);
141 break;
142 case GTK_CSS_CLOSEST_CORNER:
143 hradius = M_SQRT2 * MIN (x, width - x);
144 vradius = M_SQRT2 * MIN (y, height - y);
145 break;
146 case GTK_CSS_FARTHEST_CORNER:
147 hradius = M_SQRT2 * MAX (x, width - x);
148 vradius = M_SQRT2 * MAX (y, height - y);
149 break;
150 default:
151 g_assert_not_reached ();
152 }
153
154 hradius = MAX (1.0, hradius);
155 vradius = MAX (1.0, vradius);
156 }
157
158 gtk_css_image_radial_get_start_end (radial, radius: hradius, start: &start, end: &end);
159
160 offset = start;
161 last = -1;
162 stops = g_newa (GskColorStop, radial->n_stops);
163
164 for (i = 0; i < radial->n_stops; i++)
165 {
166 const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
167 double pos, step;
168
169 if (stop->offset == NULL)
170 {
171 if (i == 0)
172 pos = 0.0;
173 else if (i + 1 == radial->n_stops)
174 pos = 1.0;
175 else
176 continue;
177 }
178 else
179 pos = MIN (1.0, _gtk_css_number_value_get (stop->offset, hradius) / hradius);
180
181 pos = MAX (pos, offset);
182 step = (pos - offset) / (i - last);
183 for (last = last + 1; last <= i; last++)
184 {
185 stop = &radial->color_stops[last];
186
187 offset += step;
188
189 stops[last].offset = (offset - start) / (end - start);
190 stops[last].color = *gtk_css_color_value_get_rgba (color: stop->color);
191 }
192
193 offset = pos;
194 last = i;
195 }
196
197 if (radial->repeating)
198 gtk_snapshot_append_repeating_radial_gradient (snapshot,
199 bounds: &GRAPHENE_RECT_INIT (0, 0, width, height),
200 center: &GRAPHENE_POINT_INIT (x, y),
201 hradius,
202 vradius,
203 start,
204 end,
205 stops,
206 n_stops: radial->n_stops);
207 else
208 gtk_snapshot_append_radial_gradient (snapshot,
209 bounds: &GRAPHENE_RECT_INIT (0, 0, width, height),
210 center: &GRAPHENE_POINT_INIT (x, y),
211 hradius,
212 vradius,
213 start,
214 end,
215 stops,
216 n_stops: radial->n_stops);
217}
218
219static guint
220gtk_css_image_radial_parse_color_stop (GtkCssImageRadial *radial,
221 GtkCssParser *parser,
222 GArray *stop_array)
223{
224 GtkCssImageRadialColorStop stop;
225
226 stop.color = _gtk_css_color_value_parse (parser);
227 if (stop.color == NULL)
228 return 0;
229
230 if (gtk_css_number_value_can_parse (parser))
231 {
232 stop.offset = _gtk_css_number_value_parse (parser,
233 flags: GTK_CSS_PARSE_PERCENT
234 | GTK_CSS_PARSE_LENGTH);
235 if (stop.offset == NULL)
236 {
237 _gtk_css_value_unref (value: stop.color);
238 return 0;
239 }
240 }
241 else
242 {
243 stop.offset = NULL;
244 }
245
246 g_array_append_val (stop_array, stop);
247
248 return 1;
249}
250
251static guint
252gtk_css_image_radial_parse_first_arg (GtkCssImageRadial *radial,
253 GtkCssParser *parser,
254 GArray *stop_array)
255{
256 gboolean has_shape = FALSE;
257 gboolean has_size = FALSE;
258 gboolean found_one = FALSE;
259 guint i;
260 static struct {
261 const char *name;
262 guint value;
263 } names[] = {
264 { "closest-side", GTK_CSS_CLOSEST_SIDE },
265 { "farthest-side", GTK_CSS_FARTHEST_SIDE },
266 { "closest-corner", GTK_CSS_CLOSEST_CORNER },
267 { "farthest-corner", GTK_CSS_FARTHEST_CORNER }
268 };
269
270 found_one = FALSE;
271
272 do {
273 if (!has_shape && gtk_css_parser_try_ident (self: parser, ident: "circle"))
274 {
275 radial->circle = TRUE;
276 found_one = has_shape = TRUE;
277 }
278 else if (!has_shape && gtk_css_parser_try_ident (self: parser, ident: "ellipse"))
279 {
280 radial->circle = FALSE;
281 found_one = has_shape = TRUE;
282 }
283 else if (!has_size)
284 {
285 for (i = 0; i < G_N_ELEMENTS (names); i++)
286 {
287 if (gtk_css_parser_try_ident (self: parser, ident: names[i].name))
288 {
289 found_one = has_size = TRUE;
290 radial->size = names[i].value;
291 break;
292 }
293 }
294
295 if (!has_size && gtk_css_number_value_can_parse (parser))
296 {
297 radial->sizes[0] = _gtk_css_number_value_parse (parser, flags: GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
298 if (radial->sizes[0] == NULL)
299 return 0;
300 if (gtk_css_number_value_can_parse (parser))
301 {
302 radial->sizes[1] = _gtk_css_number_value_parse (parser, flags: GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
303 if (radial->sizes[1] == NULL)
304 return 0;
305 }
306 found_one = has_size = TRUE;
307 }
308 if (!has_size)
309 break;
310 }
311 else
312 {
313 break;
314 }
315 } while (!(has_shape && has_size));
316
317 if (gtk_css_parser_try_ident (self: parser, ident: "at"))
318 {
319 radial->position = _gtk_css_position_value_parse (parser);
320 if (!radial->position)
321 return 0;
322 found_one = TRUE;
323 }
324 else
325 {
326 radial->position = _gtk_css_position_value_new (x: _gtk_css_number_value_new (value: 50, unit: GTK_CSS_PERCENT),
327 y: _gtk_css_number_value_new (value: 50, unit: GTK_CSS_PERCENT));
328 }
329
330 if (!has_size)
331 {
332 radial->size = GTK_CSS_FARTHEST_CORNER;
333 }
334
335 if (!has_shape)
336 {
337 if (radial->sizes[0] && !radial->sizes[1])
338 radial->circle = TRUE;
339 else
340 radial->circle = FALSE;
341 }
342
343 if (has_shape && radial->circle)
344 {
345 if (radial->sizes[0] && radial->sizes[1])
346 {
347 gtk_css_parser_error_syntax (self: parser, format: "Circular gradient can only have one size");
348 return 0;
349 }
350
351 if (radial->sizes[0] && gtk_css_number_value_has_percent (value: radial->sizes[0]))
352 {
353 gtk_css_parser_error_syntax (self: parser, format: "Circular gradient cannot have percentage as size");
354 return 0;
355 }
356 }
357
358 if (has_size && !radial->circle)
359 {
360 if (radial->sizes[0] && !radial->sizes[1])
361 radial->sizes[1] = _gtk_css_value_ref (value: radial->sizes[0]);
362 }
363
364 if (found_one)
365 return 1;
366
367 if (!gtk_css_image_radial_parse_color_stop (radial, parser, stop_array))
368 return 0;
369
370 return 2;
371}
372
373typedef struct
374{
375 GtkCssImageRadial *self;
376 GArray *stop_array;
377} ParseData;
378
379static guint
380gtk_css_image_radial_parse_arg (GtkCssParser *parser,
381 guint arg,
382 gpointer user_data)
383{
384 ParseData *parse_data = user_data;
385 GtkCssImageRadial *self = parse_data->self;
386
387 if (arg == 0)
388 return gtk_css_image_radial_parse_first_arg (radial: self, parser, stop_array: parse_data->stop_array);
389 else
390 return gtk_css_image_radial_parse_color_stop (radial: self, parser, stop_array: parse_data->stop_array);
391
392}
393
394static gboolean
395gtk_css_image_radial_parse (GtkCssImage *image,
396 GtkCssParser *parser)
397{
398 GtkCssImageRadial *self = GTK_CSS_IMAGE_RADIAL (image);
399 ParseData parse_data;
400 gboolean success;
401
402 if (gtk_css_parser_has_function (self: parser, name: "repeating-radial-gradient"))
403 self->repeating = TRUE;
404 else if (gtk_css_parser_has_function (self: parser, name: "radial-gradient"))
405 self->repeating = FALSE;
406 else
407 {
408 gtk_css_parser_error_syntax (self: parser, format: "Not a radial gradient");
409 return FALSE;
410 }
411
412 parse_data.self = self;
413 parse_data.stop_array = g_array_new (TRUE, FALSE, element_size: sizeof (GtkCssImageRadialColorStop));
414
415 success = gtk_css_parser_consume_function (self: parser, min_args: 3, G_MAXUINT, parse_func: gtk_css_image_radial_parse_arg, data: &parse_data);
416
417 if (!success)
418 {
419 g_array_free (array: parse_data.stop_array, TRUE);
420 }
421 else
422 {
423 self->n_stops = parse_data.stop_array->len;
424 self->color_stops = (GtkCssImageRadialColorStop *)g_array_free (array: parse_data.stop_array, FALSE);
425 }
426
427 return success;
428}
429
430static void
431gtk_css_image_radial_print (GtkCssImage *image,
432 GString *string)
433{
434 GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
435 guint i;
436 const char *names[] = {
437 NULL,
438 "closest-side",
439 "farthest-side",
440 "closest-corner",
441 "farthest-corner"
442 };
443
444 if (radial->repeating)
445 g_string_append (string, val: "repeating-radial-gradient(");
446 else
447 g_string_append (string, val: "radial-gradient(");
448
449 if (radial->circle)
450 g_string_append (string, val: "circle ");
451 else
452 g_string_append (string, val: "ellipse ");
453
454 if (radial->size != 0)
455 g_string_append (string, val: names[radial->size]);
456 else
457 {
458 if (radial->sizes[0])
459 _gtk_css_value_print (value: radial->sizes[0], string);
460 if (radial->sizes[1])
461 {
462 g_string_append (string, val: " ");
463 _gtk_css_value_print (value: radial->sizes[1], string);
464 }
465 }
466
467 g_string_append (string, val: " at ");
468 _gtk_css_value_print (value: radial->position, string);
469
470 g_string_append (string, val: ", ");
471
472 for (i = 0; i < radial->n_stops; i++)
473 {
474 const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
475
476 if (i > 0)
477 g_string_append (string, val: ", ");
478
479 _gtk_css_value_print (value: stop->color, string);
480
481 if (stop->offset)
482 {
483 g_string_append (string, val: " ");
484 _gtk_css_value_print (value: stop->offset, string);
485 }
486 }
487
488 g_string_append (string, val: ")");
489}
490
491static GtkCssImage *
492gtk_css_image_radial_compute (GtkCssImage *image,
493 guint property_id,
494 GtkStyleProvider *provider,
495 GtkCssStyle *style,
496 GtkCssStyle *parent_style)
497{
498 GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
499 GtkCssImageRadial *copy;
500 guint i;
501
502 copy = g_object_new (GTK_TYPE_CSS_IMAGE_RADIAL, NULL);
503 copy->repeating = radial->repeating;
504 copy->circle = radial->circle;
505 copy->size = radial->size;
506
507 copy->position = _gtk_css_value_compute (value: radial->position, property_id, provider, style, parent_style);
508
509 if (radial->sizes[0])
510 copy->sizes[0] = _gtk_css_value_compute (value: radial->sizes[0], property_id, provider, style, parent_style);
511
512 if (radial->sizes[1])
513 copy->sizes[1] = _gtk_css_value_compute (value: radial->sizes[1], property_id, provider, style, parent_style);
514
515 copy->n_stops = radial->n_stops;
516 copy->color_stops = g_malloc (n_bytes: sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
517 for (i = 0; i < radial->n_stops; i++)
518 {
519 const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
520 GtkCssImageRadialColorStop *scopy = &copy->color_stops[i];
521
522 scopy->color = _gtk_css_value_compute (value: stop->color, property_id, provider, style, parent_style);
523
524 if (stop->offset)
525 {
526 scopy->offset = _gtk_css_value_compute (value: stop->offset, property_id, provider, style, parent_style);
527 }
528 else
529 {
530 scopy->offset = NULL;
531 }
532 }
533
534 return GTK_CSS_IMAGE (copy);
535}
536
537static GtkCssImage *
538gtk_css_image_radial_transition (GtkCssImage *start_image,
539 GtkCssImage *end_image,
540 guint property_id,
541 double progress)
542{
543 GtkCssImageRadial *start, *end, *result;
544 guint i;
545
546 start = GTK_CSS_IMAGE_RADIAL (start_image);
547
548 if (end_image == NULL)
549 return GTK_CSS_IMAGE_CLASS (_gtk_css_image_radial_parent_class)->transition (start_image, end_image, property_id, progress);
550
551 if (!GTK_IS_CSS_IMAGE_RADIAL (end_image))
552 return GTK_CSS_IMAGE_CLASS (_gtk_css_image_radial_parent_class)->transition (start_image, end_image, property_id, progress);
553
554 end = GTK_CSS_IMAGE_RADIAL (end_image);
555
556 if (start->repeating != end->repeating ||
557 start->n_stops != end->n_stops ||
558 start->size != end->size ||
559 start->circle != end->circle)
560 return GTK_CSS_IMAGE_CLASS (_gtk_css_image_radial_parent_class)->transition (start_image, end_image, property_id, progress);
561
562 result = g_object_new (GTK_TYPE_CSS_IMAGE_RADIAL, NULL);
563 result->repeating = start->repeating;
564 result->circle = start->circle;
565 result->size = start->size;
566
567 result->position = _gtk_css_value_transition (start: start->position, end: end->position, property_id, progress);
568 if (result->position == NULL)
569 goto fail;
570
571 if (start->sizes[0] && end->sizes[0])
572 {
573 result->sizes[0] = _gtk_css_value_transition (start: start->sizes[0], end: end->sizes[0], property_id, progress);
574 if (result->sizes[0] == NULL)
575 goto fail;
576 }
577 else
578 result->sizes[0] = 0;
579
580 if (start->sizes[1] && end->sizes[1])
581 {
582 result->sizes[1] = _gtk_css_value_transition (start: start->sizes[1], end: end->sizes[1], property_id, progress);
583 if (result->sizes[1] == NULL)
584 goto fail;
585 }
586 else
587 result->sizes[1] = 0;
588
589 result->color_stops = g_malloc (n_bytes: sizeof (GtkCssImageRadialColorStop) * start->n_stops);
590 result->n_stops = 0;
591 for (i = 0; i < start->n_stops; i++)
592 {
593 const GtkCssImageRadialColorStop *start_stop = &start->color_stops[i];
594 const GtkCssImageRadialColorStop *end_stop = &end->color_stops[i];
595 GtkCssImageRadialColorStop *stop = &result->color_stops[i];
596
597 if ((start_stop->offset != NULL) != (end_stop->offset != NULL))
598 goto fail;
599
600 if (start_stop->offset == NULL)
601 {
602 stop->offset = NULL;
603 }
604 else
605 {
606 stop->offset = _gtk_css_value_transition (start: start_stop->offset,
607 end: end_stop->offset,
608 property_id,
609 progress);
610 if (stop->offset == NULL)
611 goto fail;
612 }
613
614 stop->color = _gtk_css_value_transition (start: start_stop->color,
615 end: end_stop->color,
616 property_id,
617 progress);
618 if (stop->color == NULL)
619 {
620 if (stop->offset)
621 _gtk_css_value_unref (value: stop->offset);
622 goto fail;
623 }
624
625 result->n_stops++;
626 }
627
628 return GTK_CSS_IMAGE (result);
629
630fail:
631 g_object_unref (object: result);
632 return GTK_CSS_IMAGE_CLASS (_gtk_css_image_radial_parent_class)->transition (start_image, end_image, property_id, progress);
633}
634
635static gboolean
636gtk_css_image_radial_equal (GtkCssImage *image1,
637 GtkCssImage *image2)
638{
639 GtkCssImageRadial *radial1 = (GtkCssImageRadial *) image1;
640 GtkCssImageRadial *radial2 = (GtkCssImageRadial *) image2;
641 guint i;
642
643 if (radial1->repeating != radial2->repeating ||
644 radial1->size != radial2->size ||
645 !_gtk_css_value_equal (value1: radial1->position, value2: radial2->position) ||
646 ((radial1->sizes[0] == NULL) != (radial2->sizes[0] == NULL)) ||
647 (radial1->sizes[0] && radial2->sizes[0] && !_gtk_css_value_equal (value1: radial1->sizes[0], value2: radial2->sizes[0])) ||
648 ((radial1->sizes[1] == NULL) != (radial2->sizes[1] == NULL)) ||
649 (radial1->sizes[1] && radial2->sizes[1] && !_gtk_css_value_equal (value1: radial1->sizes[1], value2: radial2->sizes[1])) ||
650 radial1->n_stops != radial2->n_stops)
651 return FALSE;
652
653 for (i = 0; i < radial1->n_stops; i++)
654 {
655 const GtkCssImageRadialColorStop *stop1 = &radial1->color_stops[i];
656 const GtkCssImageRadialColorStop *stop2 = &radial2->color_stops[i];
657
658 if (!_gtk_css_value_equal0 (value1: stop1->offset, value2: stop2->offset) ||
659 !_gtk_css_value_equal (value1: stop1->color, value2: stop2->color))
660 return FALSE;
661 }
662
663 return TRUE;
664}
665
666static void
667gtk_css_image_radial_dispose (GObject *object)
668{
669 GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (object);
670 guint i;
671
672 for (i = 0; i < radial->n_stops; i ++)
673 {
674 GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
675
676 _gtk_css_value_unref (value: stop->color);
677 if (stop->offset)
678 _gtk_css_value_unref (value: stop->offset);
679 }
680 g_free (mem: radial->color_stops);
681
682 if (radial->position)
683 {
684 _gtk_css_value_unref (value: radial->position);
685 radial->position = NULL;
686 }
687
688 for (i = 0; i < 2; i++)
689 if (radial->sizes[i])
690 {
691 _gtk_css_value_unref (value: radial->sizes[i]);
692 radial->sizes[i] = NULL;
693 }
694
695 G_OBJECT_CLASS (_gtk_css_image_radial_parent_class)->dispose (object);
696}
697
698static gboolean
699gtk_css_image_radial_is_computed (GtkCssImage *image)
700{
701 GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
702 guint i;
703 gboolean computed = TRUE;
704
705 computed = computed && (!radial->position || gtk_css_value_is_computed (value: radial->position));
706 computed = computed && (!radial->sizes[0] || gtk_css_value_is_computed (value: radial->sizes[0]));
707 computed = computed && (!radial->sizes[1] || gtk_css_value_is_computed (value: radial->sizes[1]));
708
709 if (computed)
710 for (i = 0; i < radial->n_stops; i ++)
711 {
712 const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
713
714 if (stop->offset && !gtk_css_value_is_computed (value: stop->offset))
715 {
716 computed = FALSE;
717 break;
718 }
719
720 if (!gtk_css_value_is_computed (value: stop->color))
721 {
722 computed = FALSE;
723 break;
724 }
725 }
726
727 return computed;
728}
729static void
730_gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass)
731{
732 GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
733 GObjectClass *object_class = G_OBJECT_CLASS (klass);
734
735 image_class->snapshot = gtk_css_image_radial_snapshot;
736 image_class->parse = gtk_css_image_radial_parse;
737 image_class->print = gtk_css_image_radial_print;
738 image_class->compute = gtk_css_image_radial_compute;
739 image_class->transition = gtk_css_image_radial_transition;
740 image_class->equal = gtk_css_image_radial_equal;
741 image_class->is_computed = gtk_css_image_radial_is_computed;
742
743 object_class->dispose = gtk_css_image_radial_dispose;
744}
745
746static void
747_gtk_css_image_radial_init (GtkCssImageRadial *radial)
748{
749}
750
751

source code of gtk/gtk/gtkcssimageradial.c