4 * An OpenGL based 'interactive canvas' library.
6 * Authored By Matthew Allum <mallum@openedhand.com>
8 * Copyright (C) 2006 OpenedHand
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
25 * SECTION:clutter-geometric-types
26 * @Title: Base geometric types
27 * @Short_Description: Common geometric data types used by Clutter
29 * Clutter defines a set of geometric data structures that are commonly used
30 * across the whole API.
37 #include "clutter-types.h"
38 #include "clutter-private.h"
42 #define FLOAT_EPSILON (1e-15)
50 static ClutterGeometry*
51 clutter_geometry_copy (const ClutterGeometry *geometry)
53 return g_slice_dup (ClutterGeometry, geometry);
57 clutter_geometry_free (ClutterGeometry *geometry)
59 if (G_LIKELY (geometry != NULL))
60 g_slice_free (ClutterGeometry, geometry);
64 * clutter_geometry_union:
65 * @geometry_a: a #ClutterGeometry
66 * @geometry_b: another #ClutterGeometry
67 * @result: (out): location to store the result
69 * Find the union of two rectangles represented as #ClutterGeometry.
74 clutter_geometry_union (const ClutterGeometry *geometry_a,
75 const ClutterGeometry *geometry_b,
76 ClutterGeometry *result)
78 /* We don't try to handle rectangles that can't be represented
79 * as a signed integer box */
80 gint x_1 = MIN (geometry_a->x, geometry_b->x);
81 gint y_1 = MIN (geometry_a->y, geometry_b->y);
82 gint x_2 = MAX (geometry_a->x + (gint)geometry_a->width,
83 geometry_b->x + (gint)geometry_b->width);
84 gint y_2 = MAX (geometry_a->y + (gint)geometry_a->height,
85 geometry_b->y + (gint)geometry_b->height);
88 result->width = x_2 - x_1;
89 result->height = y_2 - y_1;
93 * clutter_geometry_intersects:
94 * @geometry0: The first geometry to test
95 * @geometry1: The second geometry to test
97 * Determines if @geometry0 and geometry1 intersect returning %TRUE if
98 * they do else %FALSE.
100 * Return value: %TRUE of @geometry0 and geometry1 intersect else
106 clutter_geometry_intersects (const ClutterGeometry *geometry0,
107 const ClutterGeometry *geometry1)
109 if (geometry1->x >= (geometry0->x + (gint)geometry0->width) ||
110 geometry1->y >= (geometry0->y + (gint)geometry0->height) ||
111 (geometry1->x + (gint)geometry1->width) <= geometry0->x ||
112 (geometry1->y + (gint)geometry1->height) <= geometry0->y)
119 clutter_geometry_progress (const GValue *a,
124 const ClutterGeometry *a_geom = g_value_get_boxed (a);
125 const ClutterGeometry *b_geom = g_value_get_boxed (b);
126 ClutterGeometry res = { 0, };
127 gint a_width = a_geom->width;
128 gint b_width = b_geom->width;
129 gint a_height = a_geom->height;
130 gint b_height = b_geom->height;
132 res.x = a_geom->x + (b_geom->x - a_geom->x) * progress;
133 res.y = a_geom->y + (b_geom->y - a_geom->y) * progress;
135 res.width = a_width + (b_width - a_width) * progress;
136 res.height = a_height + (b_height - a_height) * progress;
138 g_value_set_boxed (retval, &res);
143 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterGeometry, clutter_geometry,
144 clutter_geometry_copy,
145 clutter_geometry_free,
146 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_geometry_progress));
155 * clutter_vertex_new:
160 * Creates a new #ClutterVertex for the point in 3D space
161 * identified by the 3 coordinates @x, @y, @z.
163 * This function is the logical equivalent of:
166 * clutter_vertex_init (clutter_vertex_alloc (), x, y, z);
169 * Return value: (transfer full): the newly allocated #ClutterVertex.
170 * Use clutter_vertex_free() to free the resources
175 clutter_vertex_new (gfloat x,
179 return clutter_vertex_init (clutter_vertex_alloc (), x, y, z);
183 * clutter_vertex_alloc:
185 * Allocates a new, empty #ClutterVertex.
187 * Return value: (transfer full): the newly allocated #ClutterVertex.
188 * Use clutter_vertex_free() to free its resources
193 clutter_vertex_alloc (void)
195 return g_slice_new0 (ClutterVertex);
199 * clutter_vertex_init:
200 * @vertex: a #ClutterVertex
205 * Initializes @vertex with the given coordinates.
207 * Return value: (transfer none): the initialized #ClutterVertex
212 clutter_vertex_init (ClutterVertex *vertex,
217 g_return_val_if_fail (vertex != NULL, NULL);
227 * clutter_vertex_copy:
228 * @vertex: a #ClutterVertex
232 * Return value: (transfer full): a newly allocated copy of #ClutterVertex.
233 * Use clutter_vertex_free() to free the allocated resources
238 clutter_vertex_copy (const ClutterVertex *vertex)
240 if (G_LIKELY (vertex != NULL))
241 return g_slice_dup (ClutterVertex, vertex);
247 * clutter_vertex_free:
248 * @vertex: a #ClutterVertex
250 * Frees a #ClutterVertex allocated using clutter_vertex_alloc() or
251 * clutter_vertex_copy().
256 clutter_vertex_free (ClutterVertex *vertex)
258 if (G_UNLIKELY (vertex != NULL))
259 g_slice_free (ClutterVertex, vertex);
263 * clutter_vertex_equal:
264 * @vertex_a: a #ClutterVertex
265 * @vertex_b: a #ClutterVertex
267 * Compares @vertex_a and @vertex_b for equality
269 * Return value: %TRUE if the passed #ClutterVertex are equal
274 clutter_vertex_equal (const ClutterVertex *vertex_a,
275 const ClutterVertex *vertex_b)
277 g_return_val_if_fail (vertex_a != NULL && vertex_b != NULL, FALSE);
279 if (vertex_a == vertex_b)
282 return fabsf (vertex_a->x - vertex_b->x) < FLOAT_EPSILON &&
283 fabsf (vertex_a->y - vertex_b->y) < FLOAT_EPSILON &&
284 fabsf (vertex_a->z - vertex_b->z) < FLOAT_EPSILON;
288 clutter_vertex_progress (const GValue *a,
293 const ClutterVertex *av = g_value_get_boxed (a);
294 const ClutterVertex *bv = g_value_get_boxed (b);
297 res.x = av->x + (bv->x - av->x) * progress;
298 res.y = av->y + (bv->y - av->y) * progress;
299 res.z = av->z + (bv->z - av->z) * progress;
301 g_value_set_boxed (retval, &res);
306 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterVertex, clutter_vertex,
309 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_vertex_progress));
318 * clutter_margin_new:
320 * Creates a new #ClutterMargin.
322 * Return value: (transfer full): a newly allocated #ClutterMargin. Use
323 * clutter_margin_free() to free the resources associated with it when
329 clutter_margin_new (void)
331 return g_slice_new0 (ClutterMargin);
335 * clutter_margin_copy:
336 * @margin_: a #ClutterMargin
338 * Creates a new #ClutterMargin and copies the contents of @margin_ into
339 * the newly created structure.
341 * Return value: (transfer full): a copy of the #ClutterMargin.
346 clutter_margin_copy (const ClutterMargin *margin_)
348 if (G_LIKELY (margin_ != NULL))
349 return g_slice_dup (ClutterMargin, margin_);
355 * clutter_margin_free:
356 * @margin_: a #ClutterMargin
358 * Frees the resources allocated by clutter_margin_new() and
359 * clutter_margin_copy().
364 clutter_margin_free (ClutterMargin *margin_)
366 if (G_LIKELY (margin_ != NULL))
367 g_slice_free (ClutterMargin, margin_);
370 G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin,
380 static const ClutterPoint _clutter_point_zero = CLUTTER_POINT_INIT_ZERO;
383 * clutter_point_zero:
385 * A point centered at (0, 0).
387 * The returned value can be used as a guard.
389 * Return value: a point centered in (0, 0); the returned #ClutterPoint
390 * is owned by Clutter and it should not be modified or freed.
395 clutter_point_zero (void)
397 return &_clutter_point_zero;
401 * clutter_point_alloc:
403 * Allocates a new #ClutterPoint.
405 * Return value: (transfer full): the newly allocated #ClutterPoint.
406 * Use clutter_point_free() to free its resources.
411 clutter_point_alloc (void)
413 return g_slice_new0 (ClutterPoint);
417 * clutter_point_init:
418 * @point: a #ClutterPoint
419 * @x: the X coordinate of the point
420 * @y: the Y coordinate of the point
422 * Initializes @point with the given coordinates.
424 * Return value: (transfer none): the initialized #ClutterPoint
429 clutter_point_init (ClutterPoint *point,
433 g_return_val_if_fail (point != NULL, NULL);
442 * clutter_point_copy:
443 * @point: a #ClutterPoint
445 * Creates a new #ClutterPoint with the same coordinates of @point.
447 * Return value: (transfer full): a newly allocated #ClutterPoint.
448 * Use clutter_point_free() to free its resources.
453 clutter_point_copy (const ClutterPoint *point)
455 return g_slice_dup (ClutterPoint, point);
459 * clutter_point_free:
460 * @point: a #ClutterPoint
462 * Frees the resources allocated for @point.
467 clutter_point_free (ClutterPoint *point)
470 g_slice_free (ClutterPoint, point);
474 * clutter_point_equals:
475 * @a: the first #ClutterPoint to compare
476 * @b: the second #ClutterPoint to compare
478 * Compares two #ClutterPoint for equality.
480 * Return value: %TRUE if the #ClutterPoints are equal
485 clutter_point_equals (const ClutterPoint *a,
486 const ClutterPoint *b)
491 if (a == NULL || b == NULL)
494 return fabsf (a->x - b->x) < FLOAT_EPSILON &&
495 fabsf (a->y - b->y) < FLOAT_EPSILON;
499 * clutter_point_distance:
500 * @a: a #ClutterPoint
501 * @b: a #ClutterPoint
502 * @x_distance: (out) (allow-none): return location for the horizontal
503 * distance between the points
504 * @y_distance: (out) (allow-none): return location for the vertical
505 * distance between the points
507 * Computes the distance between two #ClutterPoint.
509 * Return value: the distance between the points.
514 clutter_point_distance (const ClutterPoint *a,
515 const ClutterPoint *b,
521 g_return_val_if_fail (a != NULL, 0.f);
522 g_return_val_if_fail (b != NULL, 0.f);
524 if (clutter_point_equals (a, b))
530 if (x_distance != NULL)
531 *x_distance = fabsf (x_d);
533 if (y_distance != NULL)
534 *y_distance = fabsf (y_d);
536 return sqrt ((x_d * x_d) + (y_d * y_d));
540 clutter_point_progress (const GValue *a,
545 const ClutterPoint *ap = g_value_get_boxed (a);
546 const ClutterPoint *bp = g_value_get_boxed (b);
547 ClutterPoint res = CLUTTER_POINT_INIT (0, 0);
549 res.x = ap->x + (bp->x - ap->x) * progress;
550 res.y = ap->y + (bp->y - ap->y) * progress;
552 g_value_set_boxed (retval, &res);
557 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterPoint, clutter_point,
560 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_point_progress))
569 * clutter_size_alloc:
571 * Allocates a new #ClutterSize.
573 * Return value: (transfer full): the newly allocated #ClutterSize.
574 * Use clutter_size_free() to free its resources.
579 clutter_size_alloc (void)
581 return g_slice_new0 (ClutterSize);
586 * @size: a #ClutterSize
588 * @height: the height
590 * Initializes a #ClutterSize with the given dimensions.
592 * Return value: (transfer none): the initialized #ClutterSize
597 clutter_size_init (ClutterSize *size,
601 g_return_val_if_fail (size != NULL, NULL);
604 size->height = height;
611 * @size: a #ClutterSize
613 * Creates a new #ClutterSize and duplicates @size.
615 * Return value: (transfer full): the newly allocated #ClutterSize.
616 * Use clutter_size_free() to free its resources.
621 clutter_size_copy (const ClutterSize *size)
623 return g_slice_dup (ClutterSize, size);
628 * @size: a #ClutterSize
630 * Frees the resources allocated for @size.
635 clutter_size_free (ClutterSize *size)
638 g_slice_free (ClutterSize, size);
642 * clutter_size_equals:
643 * @a: a #ClutterSize to compare
644 * @b: a #ClutterSize to compare
646 * Compares two #ClutterSize for equality.
648 * Return value: %TRUE if the two #ClutterSize are equal
653 clutter_size_equals (const ClutterSize *a,
654 const ClutterSize *b)
659 if (a == NULL || b == NULL)
662 return fabsf (a->width - b->width) < FLOAT_EPSILON &&
663 fabsf (a->height - b->height) < FLOAT_EPSILON;
667 clutter_size_progress (const GValue *a,
672 const ClutterSize *as = g_value_get_boxed (a);
673 const ClutterSize *bs = g_value_get_boxed (b);
674 ClutterSize res = CLUTTER_SIZE_INIT (0, 0);
676 res.width = as->width + (bs->width - as->width) * progress;
677 res.height = as->height + (bs->height - as->height) * progress;
679 g_value_set_boxed (retval, &res);
684 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterSize, clutter_size,
687 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_size_progress))
695 static const ClutterRect _clutter_rect_zero = CLUTTER_RECT_INIT_ZERO;
697 static gboolean clutter_rect_progress (const GValue *a,
702 G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterRect, clutter_rect,
705 CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_rect_progress))
708 clutter_rect_normalize_internal (ClutterRect *rect)
710 if (rect->size.width >= 0.f && rect->size.height >= 0.f)
713 if (rect->size.width < 0.f)
715 float size = fabsf (rect->size.width);
717 rect->origin.x -= size;
718 rect->size.width = size;
721 if (rect->size.height < 0.f)
723 float size = fabsf (rect->size.height);
725 rect->origin.y -= size;
726 rect->size.height = size;
733 * A #ClutterRect with #ClutterRect.origin set at (0, 0) and a size
736 * The returned value can be used as a guard.
738 * Return value: a rectangle with origin in (0, 0) and a size of 0.
739 * The returned #ClutterRect is owned by Clutter and it should not
740 * be modified or freed.
745 clutter_rect_zero (void)
747 return &_clutter_rect_zero;
751 * clutter_rect_alloc:
753 * Creates a new, empty #ClutterRect.
755 * You can use clutter_rect_init() to initialize the returned rectangle,
759 * rect = clutter_rect_init (clutter_rect_alloc (), x, y, width, height);
762 * Return value: (transfer full): the newly allocated #ClutterRect.
763 * Use clutter_rect_free() to free its resources
768 clutter_rect_alloc (void)
770 return g_slice_new0 (ClutterRect);
775 * @rect: a #ClutterRect
776 * @x: X coordinate of the origin
777 * @y: Y coordinate of the origin
778 * @width: width of the rectangle
779 * @height: height of the rectangle
781 * Initializes a #ClutterRect with the given origin and size.
783 * Return value: (transfer none): the updated rectangle
788 clutter_rect_init (ClutterRect *rect,
794 g_return_val_if_fail (rect != NULL, NULL);
799 rect->size.width = width;
800 rect->size.height = height;
807 * @rect: a #ClutterRect
809 * Copies @rect into a new #ClutterRect instance.
811 * Return value: (transfer full): the newly allocate copy of @rect.
812 * Use clutter_rect_free() to free the associated resources
817 clutter_rect_copy (const ClutterRect *rect)
823 res = g_slice_dup (ClutterRect, rect);
824 clutter_rect_normalize_internal (res);
834 * @rect: a #ClutterRect
836 * Frees the resources allocated by @rect.
841 clutter_rect_free (ClutterRect *rect)
844 g_slice_free (ClutterRect, rect);
848 * clutter_rect_equals:
852 * Checks whether @a and @b are equals.
854 * This function will normalize both @a and @b before comparing
855 * their origin and size.
857 * Return value: %TRUE if the rectangles match in origin and size.
862 clutter_rect_equals (ClutterRect *a,
868 if (a == NULL || b == NULL)
871 clutter_rect_normalize_internal (a);
872 clutter_rect_normalize_internal (b);
874 return clutter_point_equals (&a->origin, &b->origin) &&
875 clutter_size_equals (&a->size, &b->size);
879 * clutter_rect_normalize:
880 * @rect: a #ClutterRect
882 * Normalizes a #ClutterRect.
884 * A #ClutterRect is defined by the area covered by its size; this means
885 * that a #ClutterRect with #ClutterRect.origin in [ 0, 0 ] and a
886 * #ClutterRect.size of [ 10, 10 ] is equivalent to a #ClutterRect with
887 * #ClutterRect.origin in [ 10, 10 ] and a #ClutterRect.size of [ -10, -10 ].
889 * This function is useful to ensure that a rectangle has positive width
890 * and height; it will modify the passed @rect and normalize its size.
895 clutter_rect_normalize (ClutterRect *rect)
897 g_return_val_if_fail (rect != NULL, NULL);
899 clutter_rect_normalize_internal (rect);
905 * clutter_rect_get_center:
906 * @rect: a #ClutterRect
907 * @center: (out caller-allocates): a #ClutterPoint
909 * Retrieves the center of @rect, after normalizing the rectangle,
910 * and updates @center with the correct coordinates.
915 clutter_rect_get_center (ClutterRect *rect,
916 ClutterPoint *center)
918 g_return_if_fail (rect != NULL);
919 g_return_if_fail (center != NULL);
921 clutter_rect_normalize_internal (rect);
923 center->x = rect->origin.x + (rect->size.width / 2.0f);
924 center->y = rect->origin.y + (rect->size.height / 2.0f);
928 * clutter_rect_contains_point:
929 * @rect: a #ClutterRect
930 * @point: the point to check
932 * Checks whether @point is contained by @rect, after normalizing the
935 * Return value: %TRUE if the @point is contained by @rect.
940 clutter_rect_contains_point (ClutterRect *rect,
943 g_return_val_if_fail (rect != NULL, FALSE);
944 g_return_val_if_fail (point != NULL, FALSE);
946 clutter_rect_normalize_internal (rect);
948 return (point->x >= rect->origin.x) &&
949 (point->y >= rect->origin.y) &&
950 (point->x <= (rect->origin.x + rect->size.width)) &&
951 (point->y <= (rect->origin.y + rect->size.height));
955 * clutter_rect_contains_rect:
959 * Checks whether @a contains @b.
961 * The first rectangle contains the second if the union of the
962 * two #ClutterRect is equal to the first rectangle.
964 * Return value: %TRUE if the first rectangle contains the second.
969 clutter_rect_contains_rect (ClutterRect *a,
974 g_return_val_if_fail (a != NULL, FALSE);
975 g_return_val_if_fail (b != NULL, FALSE);
977 clutter_rect_union (a, b, &res);
979 return clutter_rect_equals (a, &res);
983 * clutter_rect_union:
986 * @res: (out caller-allocates): a #ClutterRect
988 * Computes the smallest possible rectangle capable of fully containing
989 * both @a and @b, and places it into @res.
991 * This function will normalize both @a and @b prior to computing their
997 clutter_rect_union (ClutterRect *a,
1001 g_return_if_fail (a != NULL);
1002 g_return_if_fail (b != NULL);
1003 g_return_if_fail (res != NULL);
1005 clutter_rect_normalize_internal (a);
1006 clutter_rect_normalize_internal (b);
1008 res->origin.x = MIN (a->origin.x, b->origin.x);
1009 res->origin.y = MIN (a->origin.y, b->origin.y);
1011 res->size.width = MAX (a->size.width, b->size.width);
1012 res->size.height = MAX (a->size.height, b->size.height);
1016 * clutter_rect_intersection:
1017 * @a: a #ClutterRect
1018 * @b: a #ClutterRect
1019 * @res: (out caller-allocates) (allow-none): a #ClutterRect, or %NULL
1021 * Computes the intersection of @a and @b, and places it in @res, if @res
1024 * This function will normalize both @a and @b prior to computing their
1027 * This function can be used to simply check if the intersection of @a and @b
1028 * is not empty, by using %NULL for @res.
1030 * Return value: %TRUE if the intersection of @a and @b is not empty
1035 clutter_rect_intersection (ClutterRect *a,
1039 float x_1, y_1, x_2, y_2;
1041 g_return_val_if_fail (a != NULL, FALSE);
1042 g_return_val_if_fail (b != NULL, FALSE);
1044 clutter_rect_normalize_internal (a);
1045 clutter_rect_normalize_internal (b);
1047 x_1 = MAX (a->origin.x, b->origin.y);
1048 y_1 = MAX (a->origin.y, b->origin.y);
1049 x_2 = MIN (a->origin.x + a->size.width, b->origin.x + b->size.width);
1050 y_2 = MIN (a->origin.y + a->size.height, b->origin.y + b->size.height);
1052 if (x_1 >= x_2 || y_1 >= y_2)
1055 clutter_rect_init (res, 0.f, 0.f, 0.f, 0.f);
1061 clutter_rect_init (res, x_1, y_1, x_2 - x_1, y_2 - y_1);
1067 * clutter_rect_offset:
1068 * @rect: a #ClutterRect
1069 * @d_x: the horizontal offset value
1070 * @d_y: the vertical offset value
1072 * Offsets the origin of @rect by the given values, after normalizing
1078 clutter_rect_offset (ClutterRect *rect,
1082 g_return_if_fail (rect != NULL);
1084 clutter_rect_normalize_internal (rect);
1086 rect->origin.x += d_x;
1087 rect->origin.y += d_y;
1091 * clutter_rect_inset:
1092 * @rect: a #ClutterRect
1093 * @d_x: an horizontal value; a positive @d_x will create an inset rectangle,
1094 * and a negative value will create a larger rectangle
1095 * @d_y: a vertical value; a positive @d_x will create an inset rectangle,
1096 * and a negative value will create a larger rectangle
1098 * Normalizes the @rect and offsets its origin by the @d_x and @d_y values;
1099 * the size is adjusted by (2 * @d_x, 2 * @d_y).
1101 * If @d_x and @d_y are positive the size of the rectangle is decreased; if
1102 * the values are negative, the size of the rectangle is increased.
1104 * If the resulting rectangle has a negative width or height, the size is
1110 clutter_rect_inset (ClutterRect *rect,
1114 g_return_if_fail (rect != NULL);
1116 clutter_rect_normalize_internal (rect);
1118 rect->origin.x += d_x;
1119 rect->origin.y += d_y;
1122 rect->size.width -= (d_x * 2.f);
1124 rect->size.width += (d_x * -2.f);
1127 rect->size.height -= (d_y * 2.f);
1129 rect->size.height += (d_y * -2.f);
1131 if (rect->size.width < 0.f)
1132 rect->size.width = 0.f;
1134 if (rect->size.height < 0.f)
1135 rect->size.height = 0.f;
1139 * clutter_rect_clamp_to_pixel:
1140 * @rect: a #ClutterRect
1142 * Rounds the origin of @rect downwards to the nearest integer, and rounds
1143 * the size of @rect upwards to the nearest integer, so that @rect is
1144 * updated to the smallest rectangle capable of fully containing the
1145 * original, fractional rectangle.
1150 clutter_rect_clamp_to_pixel (ClutterRect *rect)
1152 g_return_if_fail (rect != NULL);
1154 clutter_rect_normalize_internal (rect);
1156 rect->origin.x = floorf (rect->origin.x);
1157 rect->origin.y = floorf (rect->origin.y);
1159 rect->size.width = ceilf (rect->size.width);
1160 rect->size.height = ceilf (rect->size.height);
1164 * clutter_rect_get_x:
1165 * @rect: a #ClutterRect
1167 * Retrieves the X coordinate of the origin of @rect.
1169 * Return value: the X coordinate of the origin of the rectangle
1174 clutter_rect_get_x (ClutterRect *rect)
1176 g_return_val_if_fail (rect != NULL, 0.f);
1178 clutter_rect_normalize_internal (rect);
1180 return rect->origin.x;
1184 * clutter_rect_get_y:
1185 * @rect: a #ClutterRect
1187 * Retrieves the Y coordinate of the origin of @rect.
1189 * Return value: the Y coordinate of the origin of the rectangle
1194 clutter_rect_get_y (ClutterRect *rect)
1196 g_return_val_if_fail (rect != NULL, 0.f);
1198 clutter_rect_normalize_internal (rect);
1200 return rect->origin.y;
1204 * clutter_rect_get_width:
1205 * @rect: a #ClutterRect
1207 * Retrieves the width of @rect.
1209 * Return value: the width of the rectangle
1214 clutter_rect_get_width (ClutterRect *rect)
1216 g_return_val_if_fail (rect != NULL, 0.f);
1218 clutter_rect_normalize_internal (rect);
1220 return rect->size.width;
1224 * clutter_rect_get_height:
1225 * @rect: a #ClutterRect
1227 * Retrieves the height of @rect.
1229 * Return value: the height of the rectangle
1234 clutter_rect_get_height (ClutterRect *rect)
1236 g_return_val_if_fail (rect != NULL, 0.f);
1238 clutter_rect_normalize_internal (rect);
1240 return rect->size.height;
1244 clutter_rect_progress (const GValue *a,
1249 const ClutterRect *rect_a = g_value_get_boxed (a);
1250 const ClutterRect *rect_b = g_value_get_boxed (b);
1251 ClutterRect res = CLUTTER_RECT_INIT_ZERO;
1253 #define INTERPOLATE(r_a,r_b,member,field,factor) ((r_a)->member.field + (((r_b)->member.field - ((r_b)->member.field)) * (factor)))
1255 res.origin.x = INTERPOLATE (rect_a, rect_b, origin, x, progress);
1256 res.origin.y = INTERPOLATE (rect_a, rect_b, origin, y, progress);
1258 res.size.width = INTERPOLATE (rect_a, rect_b, size, width, progress);
1259 res.size.height = INTERPOLATE (rect_a, rect_b, size, height, progress);
1263 clutter_rect_normalize_internal (&res);
1265 g_value_set_boxed (retval, &res);