1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <math.h>
6
7 #include "clutter-types.h"
8 #include "clutter-interval.h"
9 #include "clutter-private.h"
10
11 /**
12 * clutter_actor_box_new:
13 * @x_1: X coordinate of the top left point
14 * @y_1: Y coordinate of the top left point
15 * @x_2: X coordinate of the bottom right point
16 * @y_2: Y coordinate of the bottom right point
17 *
18 * Allocates a new #ClutterActorBox using the passed coordinates
19 * for the top left and bottom right points.
20 *
21 * This function is the logical equivalent of:
22 *
23 * |[
24 * clutter_actor_box_init (clutter_actor_box_alloc (),
25 * x_1, y_1,
26 * x_2, y_2);
27 * ]|
28 *
29 * Return value: (transfer full): the newly allocated #ClutterActorBox.
30 * Use clutter_actor_box_free() to free the resources
31 *
32 * Since: 1.0
33 */
34 ClutterActorBox *
clutter_actor_box_new(gfloat x_1,gfloat y_1,gfloat x_2,gfloat y_2)35 clutter_actor_box_new (gfloat x_1,
36 gfloat y_1,
37 gfloat x_2,
38 gfloat y_2)
39 {
40 return clutter_actor_box_init (clutter_actor_box_alloc (),
41 x_1, y_1,
42 x_2, y_2);
43 }
44
45 /**
46 * clutter_actor_box_alloc:
47 *
48 * Allocates a new #ClutterActorBox.
49 *
50 * Return value: (transfer full): the newly allocated #ClutterActorBox.
51 * Use clutter_actor_box_free() to free its resources
52 *
53 * Since: 1.12
54 */
55 ClutterActorBox *
clutter_actor_box_alloc(void)56 clutter_actor_box_alloc (void)
57 {
58 return g_slice_new0 (ClutterActorBox);
59 }
60
61 /**
62 * clutter_actor_box_init:
63 * @box: a #ClutterActorBox
64 * @x_1: X coordinate of the top left point
65 * @y_1: Y coordinate of the top left point
66 * @x_2: X coordinate of the bottom right point
67 * @y_2: Y coordinate of the bottom right point
68 *
69 * Initializes @box with the given coordinates.
70 *
71 * Return value: (transfer none): the initialized #ClutterActorBox
72 *
73 * Since: 1.10
74 */
75 ClutterActorBox *
clutter_actor_box_init(ClutterActorBox * box,gfloat x_1,gfloat y_1,gfloat x_2,gfloat y_2)76 clutter_actor_box_init (ClutterActorBox *box,
77 gfloat x_1,
78 gfloat y_1,
79 gfloat x_2,
80 gfloat y_2)
81 {
82 g_return_val_if_fail (box != NULL, NULL);
83
84 box->x1 = x_1;
85 box->y1 = y_1;
86 box->x2 = x_2;
87 box->y2 = y_2;
88
89 return box;
90 }
91
92 /**
93 * clutter_actor_box_init_rect:
94 * @box: a #ClutterActorBox
95 * @x: X coordinate of the origin
96 * @y: Y coordinate of the origin
97 * @width: width of the box
98 * @height: height of the box
99 *
100 * Initializes @box with the given origin and size.
101 *
102 * Since: 1.10
103 */
104 void
clutter_actor_box_init_rect(ClutterActorBox * box,gfloat x,gfloat y,gfloat width,gfloat height)105 clutter_actor_box_init_rect (ClutterActorBox *box,
106 gfloat x,
107 gfloat y,
108 gfloat width,
109 gfloat height)
110 {
111 g_return_if_fail (box != NULL);
112
113 box->x1 = x;
114 box->y1 = y;
115 box->x2 = box->x1 + width;
116 box->y2 = box->y1 + height;
117 }
118
119 /**
120 * clutter_actor_box_copy:
121 * @box: a #ClutterActorBox
122 *
123 * Copies @box
124 *
125 * Return value: a newly allocated copy of #ClutterActorBox. Use
126 * clutter_actor_box_free() to free the allocated resources
127 *
128 * Since: 1.0
129 */
130 ClutterActorBox *
clutter_actor_box_copy(const ClutterActorBox * box)131 clutter_actor_box_copy (const ClutterActorBox *box)
132 {
133 if (G_LIKELY (box != NULL))
134 return g_slice_dup (ClutterActorBox, box);
135
136 return NULL;
137 }
138
139 /**
140 * clutter_actor_box_free:
141 * @box: a #ClutterActorBox
142 *
143 * Frees a #ClutterActorBox allocated using clutter_actor_box_new()
144 * or clutter_actor_box_copy()
145 *
146 * Since: 1.0
147 */
148 void
clutter_actor_box_free(ClutterActorBox * box)149 clutter_actor_box_free (ClutterActorBox *box)
150 {
151 if (G_LIKELY (box != NULL))
152 g_slice_free (ClutterActorBox, box);
153 }
154
155 /**
156 * clutter_actor_box_equal:
157 * @box_a: a #ClutterActorBox
158 * @box_b: a #ClutterActorBox
159 *
160 * Checks @box_a and @box_b for equality
161 *
162 * Return value: %TRUE if the passed #ClutterActorBox are equal
163 *
164 * Since: 1.0
165 */
166 gboolean
clutter_actor_box_equal(const ClutterActorBox * box_a,const ClutterActorBox * box_b)167 clutter_actor_box_equal (const ClutterActorBox *box_a,
168 const ClutterActorBox *box_b)
169 {
170 g_return_val_if_fail (box_a != NULL && box_b != NULL, FALSE);
171
172 if (box_a == box_b)
173 return TRUE;
174
175 return box_a->x1 == box_b->x1 && box_a->y1 == box_b->y1 &&
176 box_a->x2 == box_b->x2 && box_a->y2 == box_b->y2;
177 }
178
179 /**
180 * clutter_actor_box_get_x:
181 * @box: a #ClutterActorBox
182 *
183 * Retrieves the X coordinate of the origin of @box
184 *
185 * Return value: the X coordinate of the origin
186 *
187 * Since: 1.0
188 */
189 gfloat
clutter_actor_box_get_x(const ClutterActorBox * box)190 clutter_actor_box_get_x (const ClutterActorBox *box)
191 {
192 g_return_val_if_fail (box != NULL, 0.);
193
194 return box->x1;
195 }
196
197 /**
198 * clutter_actor_box_get_y:
199 * @box: a #ClutterActorBox
200 *
201 * Retrieves the Y coordinate of the origin of @box
202 *
203 * Return value: the Y coordinate of the origin
204 *
205 * Since: 1.0
206 */
207 gfloat
clutter_actor_box_get_y(const ClutterActorBox * box)208 clutter_actor_box_get_y (const ClutterActorBox *box)
209 {
210 g_return_val_if_fail (box != NULL, 0.);
211
212 return box->y1;
213 }
214
215 /**
216 * clutter_actor_box_get_width:
217 * @box: a #ClutterActorBox
218 *
219 * Retrieves the width of the @box
220 *
221 * Return value: the width of the box
222 *
223 * Since: 1.0
224 */
225 gfloat
clutter_actor_box_get_width(const ClutterActorBox * box)226 clutter_actor_box_get_width (const ClutterActorBox *box)
227 {
228 g_return_val_if_fail (box != NULL, 0.);
229
230 return box->x2 - box->x1;
231 }
232
233 /**
234 * clutter_actor_box_get_height:
235 * @box: a #ClutterActorBox
236 *
237 * Retrieves the height of the @box
238 *
239 * Return value: the height of the box
240 *
241 * Since: 1.0
242 */
243 gfloat
clutter_actor_box_get_height(const ClutterActorBox * box)244 clutter_actor_box_get_height (const ClutterActorBox *box)
245 {
246 g_return_val_if_fail (box != NULL, 0.);
247
248 return box->y2 - box->y1;
249 }
250
251 /**
252 * clutter_actor_box_get_origin:
253 * @box: a #ClutterActorBox
254 * @x: (out) (allow-none): return location for the X coordinate, or %NULL
255 * @y: (out) (allow-none): return location for the Y coordinate, or %NULL
256 *
257 * Retrieves the origin of @box
258 *
259 * Since: 1.0
260 */
261 void
clutter_actor_box_get_origin(const ClutterActorBox * box,gfloat * x,gfloat * y)262 clutter_actor_box_get_origin (const ClutterActorBox *box,
263 gfloat *x,
264 gfloat *y)
265 {
266 g_return_if_fail (box != NULL);
267
268 if (x)
269 *x = box->x1;
270
271 if (y)
272 *y = box->y1;
273 }
274
275 /**
276 * clutter_actor_box_get_size:
277 * @box: a #ClutterActorBox
278 * @width: (out) (allow-none): return location for the width, or %NULL
279 * @height: (out) (allow-none): return location for the height, or %NULL
280 *
281 * Retrieves the size of @box
282 *
283 * Since: 1.0
284 */
285 void
clutter_actor_box_get_size(const ClutterActorBox * box,gfloat * width,gfloat * height)286 clutter_actor_box_get_size (const ClutterActorBox *box,
287 gfloat *width,
288 gfloat *height)
289 {
290 g_return_if_fail (box != NULL);
291
292 if (width)
293 *width = box->x2 - box->x1;
294
295 if (height)
296 *height = box->y2 - box->y1;
297 }
298
299 /**
300 * clutter_actor_box_get_area:
301 * @box: a #ClutterActorBox
302 *
303 * Retrieves the area of @box
304 *
305 * Return value: the area of a #ClutterActorBox, in pixels
306 *
307 * Since: 1.0
308 */
309 gfloat
clutter_actor_box_get_area(const ClutterActorBox * box)310 clutter_actor_box_get_area (const ClutterActorBox *box)
311 {
312 g_return_val_if_fail (box != NULL, 0.);
313
314 return (box->x2 - box->x1) * (box->y2 - box->y1);
315 }
316
317 /**
318 * clutter_actor_box_contains:
319 * @box: a #ClutterActorBox
320 * @x: X coordinate of the point
321 * @y: Y coordinate of the point
322 *
323 * Checks whether a point with @x, @y coordinates is contained
324 * withing @box
325 *
326 * Return value: %TRUE if the point is contained by the #ClutterActorBox
327 *
328 * Since: 1.0
329 */
330 gboolean
clutter_actor_box_contains(const ClutterActorBox * box,gfloat x,gfloat y)331 clutter_actor_box_contains (const ClutterActorBox *box,
332 gfloat x,
333 gfloat y)
334 {
335 g_return_val_if_fail (box != NULL, FALSE);
336
337 return (x > box->x1 && x < box->x2) &&
338 (y > box->y1 && y < box->y2);
339 }
340
341 /**
342 * clutter_actor_box_from_vertices:
343 * @box: a #ClutterActorBox
344 * @verts: (array fixed-size=4): array of four #ClutterVertex
345 *
346 * Calculates the bounding box represented by the four vertices; for details
347 * of the vertex array see clutter_actor_get_abs_allocation_vertices().
348 *
349 * Since: 1.0
350 */
351 void
clutter_actor_box_from_vertices(ClutterActorBox * box,const ClutterVertex verts[])352 clutter_actor_box_from_vertices (ClutterActorBox *box,
353 const ClutterVertex verts[])
354 {
355 gfloat x_1, x_2, y_1, y_2;
356
357 g_return_if_fail (box != NULL);
358 g_return_if_fail (verts != NULL);
359
360 /* 4-way min/max */
361 x_1 = verts[0].x;
362 y_1 = verts[0].y;
363
364 if (verts[1].x < x_1)
365 x_1 = verts[1].x;
366
367 if (verts[2].x < x_1)
368 x_1 = verts[2].x;
369
370 if (verts[3].x < x_1)
371 x_1 = verts[3].x;
372
373 if (verts[1].y < y_1)
374 y_1 = verts[1].y;
375
376 if (verts[2].y < y_1)
377 y_1 = verts[2].y;
378
379 if (verts[3].y < y_1)
380 y_1 = verts[3].y;
381
382 x_2 = verts[0].x;
383 y_2 = verts[0].y;
384
385 if (verts[1].x > x_2)
386 x_2 = verts[1].x;
387
388 if (verts[2].x > x_2)
389 x_2 = verts[2].x;
390
391 if (verts[3].x > x_2)
392 x_2 = verts[3].x;
393
394 if (verts[1].y > y_2)
395 y_2 = verts[1].y;
396
397 if (verts[2].y > y_2)
398 y_2 = verts[2].y;
399
400 if (verts[3].y > y_2)
401 y_2 = verts[3].y;
402
403 box->x1 = x_1;
404 box->x2 = x_2;
405 box->y1 = y_1;
406 box->y2 = y_2;
407 }
408
409 /**
410 * clutter_actor_box_interpolate:
411 * @initial: the initial #ClutterActorBox
412 * @final: the final #ClutterActorBox
413 * @progress: the interpolation progress
414 * @result: (out): return location for the interpolation
415 *
416 * Interpolates between @initial and @final #ClutterActorBox<!-- -->es
417 * using @progress
418 *
419 * Since: 1.2
420 */
421 void
clutter_actor_box_interpolate(const ClutterActorBox * initial,const ClutterActorBox * final,gdouble progress,ClutterActorBox * result)422 clutter_actor_box_interpolate (const ClutterActorBox *initial,
423 const ClutterActorBox *final,
424 gdouble progress,
425 ClutterActorBox *result)
426 {
427 g_return_if_fail (initial != NULL);
428 g_return_if_fail (final != NULL);
429 g_return_if_fail (result != NULL);
430
431 result->x1 = initial->x1 + (final->x1 - initial->x1) * progress;
432 result->y1 = initial->y1 + (final->y1 - initial->y1) * progress;
433 result->x2 = initial->x2 + (final->x2 - initial->x2) * progress;
434 result->y2 = initial->y2 + (final->y2 - initial->y2) * progress;
435 }
436
437 /**
438 * clutter_actor_box_clamp_to_pixel:
439 * @box: (inout): the #ClutterActorBox to clamp
440 *
441 * Clamps the components of @box to the nearest integer
442 *
443 * Since: 1.2
444 */
445 void
clutter_actor_box_clamp_to_pixel(ClutterActorBox * box)446 clutter_actor_box_clamp_to_pixel (ClutterActorBox *box)
447 {
448 g_return_if_fail (box != NULL);
449
450 box->x1 = floorf (box->x1);
451 box->y1 = floorf (box->y1);
452 box->x2 = ceilf (box->x2);
453 box->y2 = ceilf (box->y2);
454 }
455
456 /**
457 * clutter_actor_box_union:
458 * @a: (in): the first #ClutterActorBox
459 * @b: (in): the second #ClutterActorBox
460 * @result: (out): the #ClutterActorBox representing a union
461 * of @a and @b
462 *
463 * Unions the two boxes @a and @b and stores the result in @result.
464 *
465 * Since: 1.4
466 */
467 void
clutter_actor_box_union(const ClutterActorBox * a,const ClutterActorBox * b,ClutterActorBox * result)468 clutter_actor_box_union (const ClutterActorBox *a,
469 const ClutterActorBox *b,
470 ClutterActorBox *result)
471 {
472 g_return_if_fail (a != NULL);
473 g_return_if_fail (b != NULL);
474 g_return_if_fail (result != NULL);
475
476 result->x1 = MIN (a->x1, b->x1);
477 result->y1 = MIN (a->y1, b->y1);
478
479 result->x2 = MAX (a->x2, b->x2);
480 result->y2 = MAX (a->y2, b->y2);
481 }
482
483 static gboolean
clutter_actor_box_progress(const GValue * a,const GValue * b,gdouble factor,GValue * retval)484 clutter_actor_box_progress (const GValue *a,
485 const GValue *b,
486 gdouble factor,
487 GValue *retval)
488 {
489 ClutterActorBox res = { 0, };
490
491 clutter_actor_box_interpolate (g_value_get_boxed (a),
492 g_value_get_boxed (b),
493 factor,
494 &res);
495
496 g_value_set_boxed (retval, &res);
497
498 return TRUE;
499 }
500
501 /**
502 * clutter_actor_box_set_origin:
503 * @box: a #ClutterActorBox
504 * @x: the X coordinate of the new origin
505 * @y: the Y coordinate of the new origin
506 *
507 * Changes the origin of @box, maintaining the size of the #ClutterActorBox.
508 *
509 * Since: 1.6
510 */
511 void
clutter_actor_box_set_origin(ClutterActorBox * box,gfloat x,gfloat y)512 clutter_actor_box_set_origin (ClutterActorBox *box,
513 gfloat x,
514 gfloat y)
515 {
516 gfloat width, height;
517
518 g_return_if_fail (box != NULL);
519
520 width = box->x2 - box->x1;
521 height = box->y2 - box->y1;
522
523 clutter_actor_box_init_rect (box, x, y, width, height);
524 }
525
526 /**
527 * clutter_actor_box_set_size:
528 * @box: a #ClutterActorBox
529 * @width: the new width
530 * @height: the new height
531 *
532 * Sets the size of @box, maintaining the origin of the #ClutterActorBox.
533 *
534 * Since: 1.6
535 */
536 void
clutter_actor_box_set_size(ClutterActorBox * box,gfloat width,gfloat height)537 clutter_actor_box_set_size (ClutterActorBox *box,
538 gfloat width,
539 gfloat height)
540 {
541 g_return_if_fail (box != NULL);
542
543 box->x2 = box->x1 + width;
544 box->y2 = box->y1 + height;
545 }
546
547 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
548 clutter_actor_box_copy,
549 clutter_actor_box_free,
550 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_actor_box_progress));
551