1 | /* GTK - The GIMP Toolkit |
2 | * Copyright (C) 2019 Benjamin Otte <otte@gnome.org> |
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 | #ifndef __GTK_CSS_BOXES_IMPL_PRIVATE_H__ |
19 | #define __GTK_CSS_BOXES_IMPL_PRIVATE_H__ |
20 | |
21 | #include "gtkcssboxesprivate.h" |
22 | |
23 | #include "gtkcsscornervalueprivate.h" |
24 | #include "gtkcssnodeprivate.h" |
25 | #include "gtkcssnumbervalueprivate.h" |
26 | #include "gtkcssdimensionvalueprivate.h" |
27 | #include "gtkwidgetprivate.h" |
28 | |
29 | /* This file is included from gtkcssboxesprivate.h */ |
30 | |
31 | static inline void |
32 | gtk_css_boxes_init (GtkCssBoxes *boxes, |
33 | GtkWidget *widget) |
34 | { |
35 | GtkWidgetPrivate *priv = widget->priv; |
36 | |
37 | gtk_css_boxes_init_content_box (boxes, |
38 | style: gtk_css_node_get_style (cssnode: priv->cssnode), |
39 | x: 0, y: 0, |
40 | width: priv->width, |
41 | height: priv->height); |
42 | } |
43 | |
44 | static inline void |
45 | gtk_css_boxes_init_content_box (GtkCssBoxes *boxes, |
46 | GtkCssStyle *style, |
47 | double x, |
48 | double y, |
49 | double width, |
50 | double height) |
51 | { |
52 | memset (s: boxes, c: 0, n: sizeof (GtkCssBoxes)); |
53 | |
54 | boxes->style = style; |
55 | boxes->box[GTK_CSS_AREA_CONTENT_BOX].bounds = GRAPHENE_RECT_INIT (x, y, width, height); |
56 | boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX] = TRUE; |
57 | } |
58 | |
59 | static inline void |
60 | gtk_css_boxes_init_border_box (GtkCssBoxes *boxes, |
61 | GtkCssStyle *style, |
62 | double x, |
63 | double y, |
64 | double width, |
65 | double height) |
66 | { |
67 | memset (s: boxes, c: 0, n: sizeof (GtkCssBoxes)); |
68 | |
69 | boxes->style = style; |
70 | boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds = GRAPHENE_RECT_INIT (x, y, width, height); |
71 | boxes->has_rect[GTK_CSS_AREA_BORDER_BOX] = TRUE; |
72 | } |
73 | |
74 | static inline void |
75 | gtk_css_boxes_rect_grow (GskRoundedRect *dest, |
76 | GskRoundedRect *src, |
77 | GtkCssValue *top, |
78 | GtkCssValue *right, |
79 | GtkCssValue *bottom, |
80 | GtkCssValue *left) |
81 | { |
82 | if (gtk_css_dimension_value_is_zero (value: left)) |
83 | { |
84 | dest->bounds.origin.x = src->bounds.origin.x; |
85 | if (gtk_css_dimension_value_is_zero (value: right)) |
86 | dest->bounds.size.width = src->bounds.size.width; |
87 | else |
88 | dest->bounds.size.width = src->bounds.size.width + _gtk_css_number_value_get (number: right, one_hundred_percent: 100); |
89 | } |
90 | else |
91 | { |
92 | const double left_value = _gtk_css_number_value_get (number: left, one_hundred_percent: 100); |
93 | |
94 | dest->bounds.origin.x = src->bounds.origin.x - left_value; |
95 | if (gtk_css_dimension_value_is_zero (value: right)) |
96 | dest->bounds.size.width = src->bounds.size.width + left_value; |
97 | else |
98 | dest->bounds.size.width = src->bounds.size.width + left_value + _gtk_css_number_value_get (number: right, one_hundred_percent: 100); |
99 | |
100 | } |
101 | |
102 | |
103 | if (gtk_css_dimension_value_is_zero (value: top)) |
104 | { |
105 | dest->bounds.origin.y = src->bounds.origin.y; |
106 | if (gtk_css_dimension_value_is_zero (value: bottom)) |
107 | dest->bounds.size.height = src->bounds.size.height; |
108 | else |
109 | dest->bounds.size.height = src->bounds.size.height + _gtk_css_number_value_get (number: bottom, one_hundred_percent: 100); |
110 | } |
111 | else |
112 | { |
113 | const double top_value = _gtk_css_number_value_get (number: top, one_hundred_percent: 100); |
114 | |
115 | dest->bounds.origin.y = src->bounds.origin.y - top_value; |
116 | if (gtk_css_dimension_value_is_zero (value: bottom)) |
117 | dest->bounds.size.height = src->bounds.size.height + top_value; |
118 | else |
119 | dest->bounds.size.height = src->bounds.size.height + top_value + _gtk_css_number_value_get (number: bottom, one_hundred_percent: 100); |
120 | } |
121 | } |
122 | |
123 | static inline void |
124 | gtk_css_boxes_rect_shrink (GskRoundedRect *dest, |
125 | GskRoundedRect *src, |
126 | GtkCssValue *top_value, |
127 | GtkCssValue *right_value, |
128 | GtkCssValue *bottom_value, |
129 | GtkCssValue *left_value) |
130 | { |
131 | double top = _gtk_css_number_value_get (number: top_value, one_hundred_percent: 100); |
132 | double right = _gtk_css_number_value_get (number: right_value, one_hundred_percent: 100); |
133 | double bottom = _gtk_css_number_value_get (number: bottom_value, one_hundred_percent: 100); |
134 | double left = _gtk_css_number_value_get (number: left_value, one_hundred_percent: 100); |
135 | |
136 | /* FIXME: Do we need underflow checks here? */ |
137 | dest->bounds.origin.x = src->bounds.origin.x + left; |
138 | dest->bounds.origin.y = src->bounds.origin.y + top; |
139 | dest->bounds.size.width = src->bounds.size.width - left - right; |
140 | dest->bounds.size.height = src->bounds.size.height - top - bottom; |
141 | } |
142 | |
143 | static inline void gtk_css_boxes_compute_padding_rect (GtkCssBoxes *boxes); |
144 | |
145 | static inline const graphene_rect_t * |
146 | gtk_css_boxes_get_rect (GtkCssBoxes *boxes, |
147 | GtkCssArea area) |
148 | { |
149 | switch (area) |
150 | { |
151 | case GTK_CSS_AREA_BORDER_BOX: |
152 | return gtk_css_boxes_get_border_rect (boxes); |
153 | case GTK_CSS_AREA_PADDING_BOX: |
154 | return gtk_css_boxes_get_padding_rect (boxes); |
155 | case GTK_CSS_AREA_CONTENT_BOX: |
156 | return gtk_css_boxes_get_content_rect (boxes); |
157 | default: |
158 | g_assert_not_reached (); |
159 | return NULL; |
160 | } |
161 | } |
162 | |
163 | static inline void |
164 | gtk_css_boxes_compute_border_rect (GtkCssBoxes *boxes) |
165 | { |
166 | if (boxes->has_rect[GTK_CSS_AREA_BORDER_BOX]) |
167 | return; |
168 | |
169 | gtk_css_boxes_compute_padding_rect (boxes); |
170 | |
171 | gtk_css_boxes_rect_grow (dest: &boxes->box[GTK_CSS_AREA_BORDER_BOX], |
172 | src: &boxes->box[GTK_CSS_AREA_PADDING_BOX], |
173 | top: boxes->style->border->border_top_width, |
174 | right: boxes->style->border->border_right_width, |
175 | bottom: boxes->style->border->border_bottom_width, |
176 | left: boxes->style->border->border_left_width); |
177 | |
178 | boxes->has_rect[GTK_CSS_AREA_BORDER_BOX] = TRUE; |
179 | } |
180 | |
181 | static inline void |
182 | gtk_css_boxes_compute_padding_rect (GtkCssBoxes *boxes) |
183 | { |
184 | if (boxes->has_rect[GTK_CSS_AREA_PADDING_BOX]) |
185 | return; |
186 | |
187 | if (boxes->has_rect[GTK_CSS_AREA_BORDER_BOX]) |
188 | { |
189 | gtk_css_boxes_rect_shrink (dest: &boxes->box[GTK_CSS_AREA_PADDING_BOX], |
190 | src: &boxes->box[GTK_CSS_AREA_BORDER_BOX], |
191 | top_value: boxes->style->border->border_top_width, |
192 | right_value: boxes->style->border->border_right_width, |
193 | bottom_value: boxes->style->border->border_bottom_width, |
194 | left_value: boxes->style->border->border_left_width); |
195 | } |
196 | else |
197 | { |
198 | gtk_css_boxes_rect_grow (dest: &boxes->box[GTK_CSS_AREA_PADDING_BOX], |
199 | src: &boxes->box[GTK_CSS_AREA_CONTENT_BOX], |
200 | top: boxes->style->size->padding_top, |
201 | right: boxes->style->size->padding_right, |
202 | bottom: boxes->style->size->padding_bottom, |
203 | left: boxes->style->size->padding_left); |
204 | } |
205 | |
206 | boxes->has_rect[GTK_CSS_AREA_PADDING_BOX] = TRUE; |
207 | } |
208 | |
209 | static inline void |
210 | gtk_css_boxes_compute_content_rect (GtkCssBoxes *boxes) |
211 | { |
212 | if (boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX]) |
213 | return; |
214 | |
215 | gtk_css_boxes_compute_padding_rect (boxes); |
216 | |
217 | gtk_css_boxes_rect_shrink (dest: &boxes->box[GTK_CSS_AREA_CONTENT_BOX], |
218 | src: &boxes->box[GTK_CSS_AREA_PADDING_BOX], |
219 | top_value: boxes->style->size->padding_top, |
220 | right_value: boxes->style->size->padding_right, |
221 | bottom_value: boxes->style->size->padding_bottom, |
222 | left_value: boxes->style->size->padding_left); |
223 | |
224 | boxes->has_rect[GTK_CSS_AREA_CONTENT_BOX] = TRUE; |
225 | } |
226 | |
227 | static inline void |
228 | gtk_css_boxes_compute_margin_rect (GtkCssBoxes *boxes) |
229 | { |
230 | if (boxes->has_rect[GTK_CSS_AREA_MARGIN_BOX]) |
231 | return; |
232 | |
233 | gtk_css_boxes_compute_border_rect (boxes); |
234 | |
235 | gtk_css_boxes_rect_grow (dest: &boxes->box[GTK_CSS_AREA_MARGIN_BOX], |
236 | src: &boxes->box[GTK_CSS_AREA_BORDER_BOX], |
237 | top: boxes->style->size->margin_top, |
238 | right: boxes->style->size->margin_right, |
239 | bottom: boxes->style->size->margin_bottom, |
240 | left: boxes->style->size->margin_left); |
241 | |
242 | boxes->has_rect[GTK_CSS_AREA_MARGIN_BOX] = TRUE; |
243 | } |
244 | |
245 | static inline void |
246 | gtk_css_boxes_compute_outline_rect (GtkCssBoxes *boxes) |
247 | { |
248 | graphene_rect_t *dest, *src; |
249 | double d; |
250 | |
251 | if (boxes->has_rect[GTK_CSS_AREA_OUTLINE_BOX]) |
252 | return; |
253 | |
254 | gtk_css_boxes_compute_border_rect (boxes); |
255 | |
256 | dest = &boxes->box[GTK_CSS_AREA_OUTLINE_BOX].bounds; |
257 | src = &boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds; |
258 | |
259 | d = _gtk_css_number_value_get (number: boxes->style->outline->outline_offset, one_hundred_percent: 100) + |
260 | _gtk_css_number_value_get (number: boxes->style->outline->outline_width, one_hundred_percent: 100); |
261 | |
262 | dest->origin.x = src->origin.x - d; |
263 | dest->origin.y = src->origin.y - d; |
264 | dest->size.width = src->size.width + d + d; |
265 | dest->size.height = src->size.height + d + d; |
266 | |
267 | boxes->has_rect[GTK_CSS_AREA_OUTLINE_BOX] = TRUE; |
268 | } |
269 | |
270 | static inline const graphene_rect_t * |
271 | gtk_css_boxes_get_margin_rect (GtkCssBoxes *boxes) |
272 | { |
273 | gtk_css_boxes_compute_margin_rect (boxes); |
274 | |
275 | return &boxes->box[GTK_CSS_AREA_MARGIN_BOX].bounds; |
276 | } |
277 | |
278 | static inline const graphene_rect_t * |
279 | gtk_css_boxes_get_border_rect (GtkCssBoxes *boxes) |
280 | { |
281 | gtk_css_boxes_compute_border_rect (boxes); |
282 | |
283 | return &boxes->box[GTK_CSS_AREA_BORDER_BOX].bounds; |
284 | } |
285 | |
286 | static inline const graphene_rect_t * |
287 | gtk_css_boxes_get_padding_rect (GtkCssBoxes *boxes) |
288 | { |
289 | gtk_css_boxes_compute_padding_rect (boxes); |
290 | |
291 | return &boxes->box[GTK_CSS_AREA_PADDING_BOX].bounds; |
292 | } |
293 | |
294 | static inline const graphene_rect_t * |
295 | gtk_css_boxes_get_content_rect (GtkCssBoxes *boxes) |
296 | { |
297 | gtk_css_boxes_compute_content_rect (boxes); |
298 | |
299 | return &boxes->box[GTK_CSS_AREA_CONTENT_BOX].bounds; |
300 | } |
301 | |
302 | static inline const graphene_rect_t * |
303 | gtk_css_boxes_get_outline_rect (GtkCssBoxes *boxes) |
304 | { |
305 | gtk_css_boxes_compute_outline_rect (boxes); |
306 | |
307 | return &boxes->box[GTK_CSS_AREA_OUTLINE_BOX].bounds; |
308 | } |
309 | |
310 | /* clamp border radius, following CSS specs */ |
311 | static inline void |
312 | gtk_css_boxes_clamp_border_radius (GskRoundedRect *box) |
313 | { |
314 | double factor = 1.0; |
315 | double corners; |
316 | |
317 | corners = box->corner[GSK_CORNER_TOP_LEFT].width + box->corner[GSK_CORNER_TOP_RIGHT].width; |
318 | if (corners != 0) |
319 | factor = MIN (factor, box->bounds.size.width / corners); |
320 | |
321 | corners = box->corner[GSK_CORNER_TOP_RIGHT].height + box->corner[GSK_CORNER_BOTTOM_RIGHT].height; |
322 | if (corners != 0) |
323 | factor = MIN (factor, box->bounds.size.height / corners); |
324 | |
325 | corners = box->corner[GSK_CORNER_BOTTOM_RIGHT].width + box->corner[GSK_CORNER_BOTTOM_LEFT].width; |
326 | if (corners != 0) |
327 | factor = MIN (factor, box->bounds.size.width / corners); |
328 | |
329 | corners = box->corner[GSK_CORNER_TOP_LEFT].height + box->corner[GSK_CORNER_BOTTOM_LEFT].height; |
330 | if (corners != 0) |
331 | factor = MIN (factor, box->bounds.size.height / corners); |
332 | |
333 | box->corner[GSK_CORNER_TOP_LEFT].width *= factor; |
334 | box->corner[GSK_CORNER_TOP_LEFT].height *= factor; |
335 | box->corner[GSK_CORNER_TOP_RIGHT].width *= factor; |
336 | box->corner[GSK_CORNER_TOP_RIGHT].height *= factor; |
337 | box->corner[GSK_CORNER_BOTTOM_RIGHT].width *= factor; |
338 | box->corner[GSK_CORNER_BOTTOM_RIGHT].height *= factor; |
339 | box->corner[GSK_CORNER_BOTTOM_LEFT].width *= factor; |
340 | box->corner[GSK_CORNER_BOTTOM_LEFT].height *= factor; |
341 | } |
342 | |
343 | static inline void |
344 | gtk_css_boxes_apply_border_radius (GskRoundedRect *box, |
345 | const GtkCssValue *top_left, |
346 | const GtkCssValue *top_right, |
347 | const GtkCssValue *bottom_right, |
348 | const GtkCssValue *bottom_left) |
349 | { |
350 | gboolean has_border_radius = FALSE; |
351 | |
352 | if (!gtk_css_corner_value_is_zero (corner: top_left)) |
353 | { |
354 | box->corner[GSK_CORNER_TOP_LEFT].width = _gtk_css_corner_value_get_x (corner: top_left, one_hundred_percent: box->bounds.size.width); |
355 | box->corner[GSK_CORNER_TOP_LEFT].height = _gtk_css_corner_value_get_y (corner: top_left, one_hundred_percent: box->bounds.size.height); |
356 | has_border_radius = TRUE; |
357 | } |
358 | |
359 | if (!gtk_css_corner_value_is_zero (corner: top_right)) |
360 | { |
361 | box->corner[GSK_CORNER_TOP_RIGHT].width = _gtk_css_corner_value_get_x (corner: top_right, one_hundred_percent: box->bounds.size.width); |
362 | box->corner[GSK_CORNER_TOP_RIGHT].height = _gtk_css_corner_value_get_y (corner: top_right, one_hundred_percent: box->bounds.size.height); |
363 | has_border_radius = TRUE; |
364 | } |
365 | |
366 | if (!gtk_css_corner_value_is_zero (corner: bottom_right)) |
367 | { |
368 | box->corner[GSK_CORNER_BOTTOM_RIGHT].width = _gtk_css_corner_value_get_x (corner: bottom_right, one_hundred_percent: box->bounds.size.width); |
369 | box->corner[GSK_CORNER_BOTTOM_RIGHT].height = _gtk_css_corner_value_get_y (corner: bottom_right, one_hundred_percent: box->bounds.size.height); |
370 | has_border_radius = TRUE; |
371 | } |
372 | |
373 | if (!gtk_css_corner_value_is_zero (corner: bottom_left)) |
374 | { |
375 | box->corner[GSK_CORNER_BOTTOM_LEFT].width = _gtk_css_corner_value_get_x (corner: bottom_left, one_hundred_percent: box->bounds.size.width); |
376 | box->corner[GSK_CORNER_BOTTOM_LEFT].height = _gtk_css_corner_value_get_y (corner: bottom_left, one_hundred_percent: box->bounds.size.height); |
377 | has_border_radius = TRUE; |
378 | } |
379 | |
380 | if (has_border_radius) |
381 | gtk_css_boxes_clamp_border_radius (box); |
382 | } |
383 | |
384 | /* NB: width and height must be >= 0 */ |
385 | static inline void |
386 | gtk_css_boxes_shrink_border_radius (graphene_size_t *dest, |
387 | const graphene_size_t *src, |
388 | double width, |
389 | double height) |
390 | { |
391 | dest->width = src->width - width; |
392 | dest->height = src->height - height; |
393 | |
394 | if (dest->width <= 0 || dest->height <= 0) |
395 | { |
396 | dest->width = 0; |
397 | dest->height = 0; |
398 | } |
399 | } |
400 | |
401 | static inline void |
402 | gtk_css_boxes_shrink_corners (GskRoundedRect *dest, |
403 | const GskRoundedRect *src) |
404 | { |
405 | double top = dest->bounds.origin.y - src->bounds.origin.y; |
406 | double right = src->bounds.origin.x + src->bounds.size.width - dest->bounds.origin.x - dest->bounds.size.width; |
407 | double bottom = src->bounds.origin.y + src->bounds.size.height - dest->bounds.origin.y - dest->bounds.size.height; |
408 | double left = dest->bounds.origin.x - src->bounds.origin.x; |
409 | |
410 | gtk_css_boxes_shrink_border_radius (dest: &dest->corner[GSK_CORNER_TOP_LEFT], |
411 | src: &src->corner[GSK_CORNER_TOP_LEFT], |
412 | width: top, height: left); |
413 | gtk_css_boxes_shrink_border_radius (dest: &dest->corner[GSK_CORNER_TOP_RIGHT], |
414 | src: &src->corner[GSK_CORNER_TOP_RIGHT], |
415 | width: top, height: right); |
416 | gtk_css_boxes_shrink_border_radius (dest: &dest->corner[GSK_CORNER_BOTTOM_RIGHT], |
417 | src: &src->corner[GSK_CORNER_BOTTOM_RIGHT], |
418 | width: bottom, height: right); |
419 | gtk_css_boxes_shrink_border_radius (dest: &dest->corner[GSK_CORNER_BOTTOM_LEFT], |
420 | src: &src->corner[GSK_CORNER_BOTTOM_LEFT], |
421 | width: bottom, height: left); |
422 | } |
423 | |
424 | static inline void |
425 | gtk_css_boxes_compute_border_box (GtkCssBoxes *boxes) |
426 | { |
427 | if (boxes->has_box[GTK_CSS_AREA_BORDER_BOX]) |
428 | return; |
429 | |
430 | gtk_css_boxes_compute_border_rect (boxes); |
431 | |
432 | gtk_css_boxes_apply_border_radius (box: &boxes->box[GTK_CSS_AREA_BORDER_BOX], |
433 | top_left: boxes->style->border->border_top_left_radius, |
434 | top_right: boxes->style->border->border_top_right_radius, |
435 | bottom_right: boxes->style->border->border_bottom_right_radius, |
436 | bottom_left: boxes->style->border->border_bottom_left_radius); |
437 | |
438 | boxes->has_box[GTK_CSS_AREA_BORDER_BOX] = TRUE; |
439 | } |
440 | |
441 | static inline void |
442 | gtk_css_boxes_compute_padding_box (GtkCssBoxes *boxes) |
443 | { |
444 | if (boxes->has_box[GTK_CSS_AREA_PADDING_BOX]) |
445 | return; |
446 | |
447 | gtk_css_boxes_compute_border_box (boxes); |
448 | gtk_css_boxes_compute_padding_rect (boxes); |
449 | |
450 | gtk_css_boxes_shrink_corners (dest: &boxes->box[GTK_CSS_AREA_PADDING_BOX], |
451 | src: &boxes->box[GTK_CSS_AREA_BORDER_BOX]); |
452 | |
453 | boxes->has_box[GTK_CSS_AREA_PADDING_BOX] = TRUE; |
454 | } |
455 | |
456 | static inline void |
457 | gtk_css_boxes_compute_content_box (GtkCssBoxes *boxes) |
458 | { |
459 | if (boxes->has_box[GTK_CSS_AREA_CONTENT_BOX]) |
460 | return; |
461 | |
462 | gtk_css_boxes_compute_padding_box (boxes); |
463 | gtk_css_boxes_compute_content_rect (boxes); |
464 | |
465 | gtk_css_boxes_shrink_corners (dest: &boxes->box[GTK_CSS_AREA_CONTENT_BOX], |
466 | src: &boxes->box[GTK_CSS_AREA_PADDING_BOX]); |
467 | |
468 | boxes->has_box[GTK_CSS_AREA_CONTENT_BOX] = TRUE; |
469 | } |
470 | |
471 | static inline void |
472 | gtk_css_boxes_compute_outline_box (GtkCssBoxes *boxes) |
473 | { |
474 | const GskRoundedRect *src; |
475 | GskRoundedRect *dest; |
476 | double d; |
477 | int i; |
478 | |
479 | if (boxes->has_box[GTK_CSS_AREA_OUTLINE_BOX]) |
480 | return; |
481 | |
482 | gtk_css_boxes_compute_border_box (boxes); |
483 | |
484 | src = &boxes->box[GTK_CSS_AREA_BORDER_BOX]; |
485 | dest = &boxes->box[GTK_CSS_AREA_OUTLINE_BOX]; |
486 | |
487 | d = _gtk_css_number_value_get (number: boxes->style->outline->outline_offset, one_hundred_percent: 100) + |
488 | _gtk_css_number_value_get (number: boxes->style->outline->outline_width, one_hundred_percent: 100); |
489 | |
490 | /* Grow border rect into outline rect */ |
491 | dest->bounds.origin.x = src->bounds.origin.x - d; |
492 | dest->bounds.origin.y = src->bounds.origin.y - d; |
493 | dest->bounds.size.width = src->bounds.size.width + d + d; |
494 | dest->bounds.size.height = src->bounds.size.height + d + d; |
495 | |
496 | /* Grow corner radii of border rect */ |
497 | for (i = 0; i < 4; i ++) |
498 | { |
499 | if (src->corner[i].width > 0) dest->corner[i].width = src->corner[i].width + d; |
500 | if (src->corner[i].height > 0) dest->corner[i].height = src->corner[i].height + d; |
501 | |
502 | if (dest->corner[i].width <= 0 || dest->corner[i].height <= 0) |
503 | { |
504 | dest->corner[i].width = 0; |
505 | dest->corner[i].height = 0; |
506 | } |
507 | else |
508 | { |
509 | dest->corner[i].width = MIN (dest->corner[i].width, dest->bounds.size.width); |
510 | dest->corner[i].height = MIN (dest->corner[i].height, dest->bounds.size.height); |
511 | } |
512 | } |
513 | |
514 | boxes->has_box[GTK_CSS_AREA_OUTLINE_BOX] = TRUE; |
515 | } |
516 | |
517 | static inline const GskRoundedRect * |
518 | gtk_css_boxes_get_box (GtkCssBoxes *boxes, |
519 | GtkCssArea area) |
520 | { |
521 | switch (area) |
522 | { |
523 | case GTK_CSS_AREA_BORDER_BOX: |
524 | return gtk_css_boxes_get_border_box (boxes); |
525 | case GTK_CSS_AREA_PADDING_BOX: |
526 | return gtk_css_boxes_get_padding_box (boxes); |
527 | case GTK_CSS_AREA_CONTENT_BOX: |
528 | return gtk_css_boxes_get_content_box (boxes); |
529 | default: |
530 | g_assert_not_reached (); |
531 | return NULL; |
532 | } |
533 | } |
534 | |
535 | static inline const GskRoundedRect * |
536 | gtk_css_boxes_get_border_box (GtkCssBoxes *boxes) |
537 | { |
538 | gtk_css_boxes_compute_border_box (boxes); |
539 | |
540 | return &boxes->box[GTK_CSS_AREA_BORDER_BOX]; |
541 | } |
542 | |
543 | static inline const GskRoundedRect * |
544 | gtk_css_boxes_get_padding_box (GtkCssBoxes *boxes) |
545 | { |
546 | gtk_css_boxes_compute_padding_box (boxes); |
547 | |
548 | return &boxes->box[GTK_CSS_AREA_PADDING_BOX]; |
549 | } |
550 | |
551 | static inline const GskRoundedRect * |
552 | gtk_css_boxes_get_content_box (GtkCssBoxes *boxes) |
553 | { |
554 | gtk_css_boxes_compute_content_box (boxes); |
555 | |
556 | return &boxes->box[GTK_CSS_AREA_CONTENT_BOX]; |
557 | } |
558 | |
559 | static inline const GskRoundedRect * |
560 | gtk_css_boxes_get_outline_box (GtkCssBoxes *boxes) |
561 | { |
562 | gtk_css_boxes_compute_outline_box (boxes); |
563 | |
564 | return &boxes->box[GTK_CSS_AREA_OUTLINE_BOX]; |
565 | } |
566 | |
567 | #endif /* __GTK_CSS_BOXES_IMPL_PRIVATE_H__ */ |
568 | |