1/* GTK - The GIMP Toolkit
2 * Copyright (C) 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 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
18#include "config.h"
19
20#include "gtkcssrepeatvalueprivate.h"
21
22#include "gtkcssnumbervalueprivate.h"
23
24struct _GtkCssValue {
25 GTK_CSS_VALUE_BASE
26 GtkCssRepeatStyle x;
27 GtkCssRepeatStyle y;
28};
29
30static void
31gtk_css_value_repeat_free (GtkCssValue *value)
32{
33 g_slice_free (GtkCssValue, value);
34}
35
36static GtkCssValue *
37gtk_css_value_repeat_compute (GtkCssValue *value,
38 guint property_id,
39 GtkStyleProvider *provider,
40 GtkCssStyle *style,
41 GtkCssStyle *parent_style)
42{
43 return _gtk_css_value_ref (value);
44}
45
46static gboolean
47gtk_css_value_repeat_equal (const GtkCssValue *repeat1,
48 const GtkCssValue *repeat2)
49{
50 return repeat1->x == repeat2->x
51 && repeat1->y == repeat2->y;
52}
53
54static GtkCssValue *
55gtk_css_value_repeat_transition (GtkCssValue *start,
56 GtkCssValue *end,
57 guint property_id,
58 double progress)
59{
60 return NULL;
61}
62
63static void
64gtk_css_value_background_repeat_print (const GtkCssValue *repeat,
65 GString *string)
66{
67 static const char *names[] = {
68 "no-repeat",
69 "repeat",
70 "round",
71 "space"
72 };
73
74 if (repeat->x == repeat->y)
75 {
76 g_string_append (string, val: names[repeat->x]);
77 }
78 else if (repeat->x == GTK_CSS_REPEAT_STYLE_REPEAT &&
79 repeat->y == GTK_CSS_REPEAT_STYLE_NO_REPEAT)
80 {
81 g_string_append (string, val: "repeat-x");
82 }
83 else if (repeat->x == GTK_CSS_REPEAT_STYLE_NO_REPEAT &&
84 repeat->y == GTK_CSS_REPEAT_STYLE_REPEAT)
85 {
86 g_string_append (string, val: "repeat-y");
87 }
88 else
89 {
90 g_string_append (string, val: names[repeat->x]);
91 g_string_append_c (string, ' ');
92 g_string_append (string, val: names[repeat->y]);
93 }
94}
95
96static void
97gtk_css_value_border_repeat_print (const GtkCssValue *repeat,
98 GString *string)
99{
100 static const char *names[] = {
101 "stretch",
102 "repeat",
103 "round",
104 "space"
105 };
106
107 g_string_append (string, val: names[repeat->x]);
108 if (repeat->x != repeat->y)
109 {
110 g_string_append_c (string, ' ');
111 g_string_append (string, val: names[repeat->y]);
112 }
113}
114
115static const GtkCssValueClass GTK_CSS_VALUE_BACKGROUND_REPEAT = {
116 "GtkCssBackgroundRepeatValue",
117 gtk_css_value_repeat_free,
118 gtk_css_value_repeat_compute,
119 gtk_css_value_repeat_equal,
120 gtk_css_value_repeat_transition,
121 NULL,
122 NULL,
123 gtk_css_value_background_repeat_print
124};
125
126static const GtkCssValueClass GTK_CSS_VALUE_BORDER_REPEAT = {
127 "GtkCssBorderRepeatValue",
128 gtk_css_value_repeat_free,
129 gtk_css_value_repeat_compute,
130 gtk_css_value_repeat_equal,
131 gtk_css_value_repeat_transition,
132 NULL,
133 NULL,
134 gtk_css_value_border_repeat_print
135};
136/* BACKGROUND REPEAT */
137
138static struct {
139 const char *name;
140 GtkCssValue values[4];
141} background_repeat_values[4] = {
142 { "no-repeat",
143 { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
144 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
145 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
146 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
147 } },
148 { "repeat",
149 { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
150 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
151 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
152 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
153 } },
154 { "round",
155 { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
156 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
157 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
158 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
159 } },
160 { "space",
161 { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
162 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
163 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
164 { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
165 } }
166};
167
168GtkCssValue *
169_gtk_css_background_repeat_value_new (GtkCssRepeatStyle x,
170 GtkCssRepeatStyle y)
171{
172 return _gtk_css_value_ref (value: &background_repeat_values[x].values[y]);
173}
174
175static gboolean
176_gtk_css_background_repeat_style_try (GtkCssParser *parser,
177 GtkCssRepeatStyle *result)
178{
179 guint i;
180
181 for (i = 0; i < G_N_ELEMENTS (background_repeat_values); i++)
182 {
183 if (gtk_css_parser_try_ident (self: parser, ident: background_repeat_values[i].name))
184 {
185 *result = i;
186 return TRUE;
187 }
188 }
189
190 return FALSE;
191}
192
193GtkCssValue *
194_gtk_css_background_repeat_value_try_parse (GtkCssParser *parser)
195{
196 GtkCssRepeatStyle x, y;
197
198 g_return_val_if_fail (parser != NULL, NULL);
199
200 if (gtk_css_parser_try_ident (self: parser, ident: "repeat-x"))
201 return _gtk_css_background_repeat_value_new (x: GTK_CSS_REPEAT_STYLE_REPEAT, y: GTK_CSS_REPEAT_STYLE_NO_REPEAT);
202 if (gtk_css_parser_try_ident (self: parser, ident: "repeat-y"))
203 return _gtk_css_background_repeat_value_new (x: GTK_CSS_REPEAT_STYLE_NO_REPEAT, y: GTK_CSS_REPEAT_STYLE_REPEAT);
204
205 if (!_gtk_css_background_repeat_style_try (parser, result: &x))
206 return NULL;
207
208 if (!_gtk_css_background_repeat_style_try (parser, result: &y))
209 y = x;
210
211 return _gtk_css_background_repeat_value_new (x, y);
212}
213
214GtkCssRepeatStyle
215_gtk_css_background_repeat_value_get_x (const GtkCssValue *repeat)
216{
217 g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BACKGROUND_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
218
219 return repeat->x;
220}
221
222GtkCssRepeatStyle
223_gtk_css_background_repeat_value_get_y (const GtkCssValue *repeat)
224{
225 g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BACKGROUND_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
226
227 return repeat->y;
228}
229
230/* BORDER IMAGE REPEAT */
231
232static struct {
233 const char *name;
234 GtkCssValue values[4];
235} border_repeat_values[4] = {
236 { "stretch",
237 { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH },
238 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_REPEAT },
239 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_ROUND },
240 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_SPACE }
241 } },
242 { "repeat",
243 { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH },
244 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
245 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
246 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
247 } },
248 { "round",
249 { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_STRETCH },
250 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
251 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
252 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
253 } },
254 { "space",
255 { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_STRETCH },
256 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
257 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
258 { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
259 } }
260};
261
262GtkCssValue *
263_gtk_css_border_repeat_value_new (GtkCssRepeatStyle x,
264 GtkCssRepeatStyle y)
265{
266 return _gtk_css_value_ref (value: &border_repeat_values[x].values[y]);
267}
268
269static gboolean
270_gtk_css_border_repeat_style_try (GtkCssParser *parser,
271 GtkCssRepeatStyle *result)
272{
273 guint i;
274
275 for (i = 0; i < G_N_ELEMENTS (border_repeat_values); i++)
276 {
277 if (gtk_css_parser_try_ident (self: parser, ident: border_repeat_values[i].name))
278 {
279 *result = i;
280 return TRUE;
281 }
282 }
283
284 return FALSE;
285}
286
287GtkCssValue *
288_gtk_css_border_repeat_value_try_parse (GtkCssParser *parser)
289{
290 GtkCssRepeatStyle x, y;
291
292 g_return_val_if_fail (parser != NULL, NULL);
293
294 if (!_gtk_css_border_repeat_style_try (parser, result: &x))
295 return NULL;
296
297 if (!_gtk_css_border_repeat_style_try (parser, result: &y))
298 y = x;
299
300 return _gtk_css_border_repeat_value_new (x, y);
301}
302
303GtkCssRepeatStyle
304_gtk_css_border_repeat_value_get_x (const GtkCssValue *repeat)
305{
306 g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BORDER_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH);
307
308 return repeat->x;
309}
310
311GtkCssRepeatStyle
312_gtk_css_border_repeat_value_get_y (const GtkCssValue *repeat)
313{
314 g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BORDER_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH);
315
316 return repeat->y;
317}
318
319

source code of gtk/gtk/gtkcssrepeatvalue.c