2012-03-30 13:22:04 -04:00
|
|
|
|
/*
|
|
|
|
|
* Clutter.
|
|
|
|
|
*
|
|
|
|
|
* An OpenGL based 'interactive canvas' library.
|
|
|
|
|
*
|
|
|
|
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2006 OpenedHand
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2012-04-19 09:55:08 -04:00
|
|
|
|
* SECTION:clutter-geometric-types
|
|
|
|
|
* @Title: Base geometric types
|
|
|
|
|
* @Short_Description: Common geometric data types used by Clutter
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
2012-04-19 09:55:08 -04:00
|
|
|
|
* Clutter defines a set of geometric data structures that are commonly used
|
|
|
|
|
* across the whole API.
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "clutter-types.h"
|
|
|
|
|
#include "clutter-private.h"
|
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
2012-04-19 07:30:45 -04:00
|
|
|
|
#define FLOAT_EPSILON (1e-15)
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterGeometry
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static ClutterGeometry*
|
|
|
|
|
clutter_geometry_copy (const ClutterGeometry *geometry)
|
|
|
|
|
{
|
|
|
|
|
return g_slice_dup (ClutterGeometry, geometry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
clutter_geometry_free (ClutterGeometry *geometry)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (geometry != NULL))
|
|
|
|
|
g_slice_free (ClutterGeometry, geometry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_geometry_union:
|
|
|
|
|
* @geometry_a: a #ClutterGeometry
|
|
|
|
|
* @geometry_b: another #ClutterGeometry
|
|
|
|
|
* @result: (out): location to store the result
|
|
|
|
|
*
|
|
|
|
|
* Find the union of two rectangles represented as #ClutterGeometry.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.4
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_geometry_union (const ClutterGeometry *geometry_a,
|
|
|
|
|
const ClutterGeometry *geometry_b,
|
|
|
|
|
ClutterGeometry *result)
|
|
|
|
|
{
|
|
|
|
|
/* We don't try to handle rectangles that can't be represented
|
|
|
|
|
* as a signed integer box */
|
|
|
|
|
gint x_1 = MIN (geometry_a->x, geometry_b->x);
|
|
|
|
|
gint y_1 = MIN (geometry_a->y, geometry_b->y);
|
|
|
|
|
gint x_2 = MAX (geometry_a->x + (gint)geometry_a->width,
|
|
|
|
|
geometry_b->x + (gint)geometry_b->width);
|
|
|
|
|
gint y_2 = MAX (geometry_a->y + (gint)geometry_a->height,
|
|
|
|
|
geometry_b->y + (gint)geometry_b->height);
|
|
|
|
|
result->x = x_1;
|
|
|
|
|
result->y = y_1;
|
|
|
|
|
result->width = x_2 - x_1;
|
|
|
|
|
result->height = y_2 - y_1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_geometry_intersects:
|
|
|
|
|
* @geometry0: The first geometry to test
|
|
|
|
|
* @geometry1: The second geometry to test
|
|
|
|
|
*
|
|
|
|
|
* Determines if @geometry0 and geometry1 intersect returning %TRUE if
|
|
|
|
|
* they do else %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE of @geometry0 and geometry1 intersect else
|
|
|
|
|
* %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.4
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_geometry_intersects (const ClutterGeometry *geometry0,
|
|
|
|
|
const ClutterGeometry *geometry1)
|
|
|
|
|
{
|
|
|
|
|
if (geometry1->x >= (geometry0->x + (gint)geometry0->width) ||
|
|
|
|
|
geometry1->y >= (geometry0->y + (gint)geometry0->height) ||
|
|
|
|
|
(geometry1->x + (gint)geometry1->width) <= geometry0->x ||
|
|
|
|
|
(geometry1->y + (gint)geometry1->height) <= geometry0->y)
|
|
|
|
|
return FALSE;
|
|
|
|
|
else
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clutter_geometry_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *retval)
|
|
|
|
|
{
|
|
|
|
|
const ClutterGeometry *a_geom = g_value_get_boxed (a);
|
|
|
|
|
const ClutterGeometry *b_geom = g_value_get_boxed (b);
|
|
|
|
|
ClutterGeometry res = { 0, };
|
|
|
|
|
gint a_width = a_geom->width;
|
|
|
|
|
gint b_width = b_geom->width;
|
|
|
|
|
gint a_height = a_geom->height;
|
|
|
|
|
gint b_height = b_geom->height;
|
|
|
|
|
|
|
|
|
|
res.x = a_geom->x + (b_geom->x - a_geom->x) * progress;
|
|
|
|
|
res.y = a_geom->y + (b_geom->y - a_geom->y) * progress;
|
|
|
|
|
|
|
|
|
|
res.width = a_width + (b_width - a_width) * progress;
|
|
|
|
|
res.height = a_height + (b_height - a_height) * progress;
|
|
|
|
|
|
|
|
|
|
g_value_set_boxed (retval, &res);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterGeometry, clutter_geometry,
|
|
|
|
|
clutter_geometry_copy,
|
|
|
|
|
clutter_geometry_free,
|
|
|
|
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_geometry_progress));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterVertices
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_vertex_new:
|
|
|
|
|
* @x: X coordinate
|
|
|
|
|
* @y: Y coordinate
|
|
|
|
|
* @z: Z coordinate
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #ClutterVertex for the point in 3D space
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* identified by the 3 coordinates @x, @y, @z.
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* This function is the logical equivalent of:
|
|
|
|
|
*
|
|
|
|
|
* |[
|
|
|
|
|
* clutter_vertex_init (clutter_vertex_alloc (), x, y, z);
|
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterVertex.
|
|
|
|
|
* Use clutter_vertex_free() to free the resources
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
|
|
|
|
*/
|
|
|
|
|
ClutterVertex *
|
|
|
|
|
clutter_vertex_new (gfloat x,
|
|
|
|
|
gfloat y,
|
|
|
|
|
gfloat z)
|
|
|
|
|
{
|
2012-04-18 12:31:28 -04:00
|
|
|
|
return clutter_vertex_init (clutter_vertex_alloc (), x, y, z);
|
|
|
|
|
}
|
2012-03-30 13:22:04 -04:00
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
2012-08-10 09:28:48 -04:00
|
|
|
|
* clutter_vertex_alloc: (constructor)
|
2012-04-18 12:31:28 -04:00
|
|
|
|
*
|
|
|
|
|
* Allocates a new, empty #ClutterVertex.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterVertex.
|
|
|
|
|
* Use clutter_vertex_free() to free its resources
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterVertex *
|
|
|
|
|
clutter_vertex_alloc (void)
|
|
|
|
|
{
|
|
|
|
|
return g_slice_new0 (ClutterVertex);
|
2012-03-30 13:22:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_vertex_init:
|
|
|
|
|
* @vertex: a #ClutterVertex
|
|
|
|
|
* @x: X coordinate
|
|
|
|
|
* @y: Y coordinate
|
|
|
|
|
* @z: Z coordinate
|
|
|
|
|
*
|
|
|
|
|
* Initializes @vertex with the given coordinates.
|
|
|
|
|
*
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* Return value: (transfer none): the initialized #ClutterVertex
|
|
|
|
|
*
|
2012-03-30 13:22:04 -04:00
|
|
|
|
* Since: 1.10
|
|
|
|
|
*/
|
2012-04-18 12:31:28 -04:00
|
|
|
|
ClutterVertex *
|
2012-03-30 13:22:04 -04:00
|
|
|
|
clutter_vertex_init (ClutterVertex *vertex,
|
|
|
|
|
gfloat x,
|
|
|
|
|
gfloat y,
|
|
|
|
|
gfloat z)
|
|
|
|
|
{
|
2012-04-18 12:31:28 -04:00
|
|
|
|
g_return_val_if_fail (vertex != NULL, NULL);
|
2012-03-30 13:22:04 -04:00
|
|
|
|
|
|
|
|
|
vertex->x = x;
|
|
|
|
|
vertex->y = y;
|
|
|
|
|
vertex->z = z;
|
2012-04-18 12:31:28 -04:00
|
|
|
|
|
|
|
|
|
return vertex;
|
2012-03-30 13:22:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_vertex_copy:
|
|
|
|
|
* @vertex: a #ClutterVertex
|
|
|
|
|
*
|
|
|
|
|
* Copies @vertex
|
|
|
|
|
*
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* Return value: (transfer full): a newly allocated copy of #ClutterVertex.
|
|
|
|
|
* Use clutter_vertex_free() to free the allocated resources
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
|
|
|
|
*/
|
|
|
|
|
ClutterVertex *
|
|
|
|
|
clutter_vertex_copy (const ClutterVertex *vertex)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (vertex != NULL))
|
|
|
|
|
return g_slice_dup (ClutterVertex, vertex);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_vertex_free:
|
|
|
|
|
* @vertex: a #ClutterVertex
|
|
|
|
|
*
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* Frees a #ClutterVertex allocated using clutter_vertex_alloc() or
|
|
|
|
|
* clutter_vertex_copy().
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_vertex_free (ClutterVertex *vertex)
|
|
|
|
|
{
|
|
|
|
|
if (G_UNLIKELY (vertex != NULL))
|
|
|
|
|
g_slice_free (ClutterVertex, vertex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_vertex_equal:
|
|
|
|
|
* @vertex_a: a #ClutterVertex
|
|
|
|
|
* @vertex_b: a #ClutterVertex
|
|
|
|
|
*
|
|
|
|
|
* Compares @vertex_a and @vertex_b for equality
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the passed #ClutterVertex are equal
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_vertex_equal (const ClutterVertex *vertex_a,
|
|
|
|
|
const ClutterVertex *vertex_b)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (vertex_a != NULL && vertex_b != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (vertex_a == vertex_b)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2012-04-19 07:30:45 -04:00
|
|
|
|
return fabsf (vertex_a->x - vertex_b->x) < FLOAT_EPSILON &&
|
|
|
|
|
fabsf (vertex_a->y - vertex_b->y) < FLOAT_EPSILON &&
|
|
|
|
|
fabsf (vertex_a->z - vertex_b->z) < FLOAT_EPSILON;
|
2012-03-30 13:22:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clutter_vertex_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *retval)
|
|
|
|
|
{
|
|
|
|
|
const ClutterVertex *av = g_value_get_boxed (a);
|
|
|
|
|
const ClutterVertex *bv = g_value_get_boxed (b);
|
2012-04-18 12:31:28 -04:00
|
|
|
|
ClutterVertex res;
|
2012-03-30 13:22:04 -04:00
|
|
|
|
|
|
|
|
|
res.x = av->x + (bv->x - av->x) * progress;
|
|
|
|
|
res.y = av->y + (bv->y - av->y) * progress;
|
|
|
|
|
res.z = av->z + (bv->z - av->z) * progress;
|
|
|
|
|
|
|
|
|
|
g_value_set_boxed (retval, &res);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterVertex, clutter_vertex,
|
|
|
|
|
clutter_vertex_copy,
|
|
|
|
|
clutter_vertex_free,
|
|
|
|
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_vertex_progress));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterMargin
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_margin_new:
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #ClutterMargin.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): a newly allocated #ClutterMargin. Use
|
|
|
|
|
* clutter_margin_free() to free the resources associated with it when
|
|
|
|
|
* done.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.10
|
|
|
|
|
*/
|
|
|
|
|
ClutterMargin *
|
|
|
|
|
clutter_margin_new (void)
|
|
|
|
|
{
|
|
|
|
|
return g_slice_new0 (ClutterMargin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_margin_copy:
|
|
|
|
|
* @margin_: a #ClutterMargin
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #ClutterMargin and copies the contents of @margin_ into
|
|
|
|
|
* the newly created structure.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): a copy of the #ClutterMargin.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.10
|
|
|
|
|
*/
|
|
|
|
|
ClutterMargin *
|
|
|
|
|
clutter_margin_copy (const ClutterMargin *margin_)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (margin_ != NULL))
|
|
|
|
|
return g_slice_dup (ClutterMargin, margin_);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_margin_free:
|
|
|
|
|
* @margin_: a #ClutterMargin
|
|
|
|
|
*
|
|
|
|
|
* Frees the resources allocated by clutter_margin_new() and
|
|
|
|
|
* clutter_margin_copy().
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.10
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_margin_free (ClutterMargin *margin_)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (margin_ != NULL))
|
|
|
|
|
g_slice_free (ClutterMargin, margin_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin,
|
|
|
|
|
clutter_margin_copy,
|
|
|
|
|
clutter_margin_free)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterPoint
|
|
|
|
|
*/
|
|
|
|
|
|
2012-06-09 05:35:56 -04:00
|
|
|
|
static const ClutterPoint _clutter_point_zero = CLUTTER_POINT_INIT_ZERO;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_point_zero:
|
|
|
|
|
*
|
|
|
|
|
* A point centered at (0, 0).
|
|
|
|
|
*
|
|
|
|
|
* The returned value can be used as a guard.
|
|
|
|
|
*
|
|
|
|
|
* Return value: a point centered in (0, 0); the returned #ClutterPoint
|
|
|
|
|
* is owned by Clutter and it should not be modified or freed.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
const ClutterPoint *
|
|
|
|
|
clutter_point_zero (void)
|
|
|
|
|
{
|
|
|
|
|
return &_clutter_point_zero;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
2012-08-10 09:28:48 -04:00
|
|
|
|
* clutter_point_alloc: (constructor)
|
2012-04-18 12:31:28 -04:00
|
|
|
|
*
|
|
|
|
|
* Allocates a new #ClutterPoint.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterPoint.
|
|
|
|
|
* Use clutter_point_free() to free its resources.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterPoint *
|
2012-04-18 12:31:28 -04:00
|
|
|
|
clutter_point_alloc (void)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
{
|
|
|
|
|
return g_slice_new0 (ClutterPoint);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_point_init:
|
|
|
|
|
* @point: a #ClutterPoint
|
|
|
|
|
* @x: the X coordinate of the point
|
|
|
|
|
* @y: the Y coordinate of the point
|
|
|
|
|
*
|
|
|
|
|
* Initializes @point with the given coordinates.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the initialized #ClutterPoint
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterPoint *
|
|
|
|
|
clutter_point_init (ClutterPoint *point,
|
|
|
|
|
float x,
|
|
|
|
|
float y)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (point != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
point->x = x;
|
|
|
|
|
point->y = y;
|
|
|
|
|
|
|
|
|
|
return point;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_point_copy:
|
|
|
|
|
* @point: a #ClutterPoint
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #ClutterPoint with the same coordinates of @point.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): a newly allocated #ClutterPoint.
|
|
|
|
|
* Use clutter_point_free() to free its resources.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterPoint *
|
|
|
|
|
clutter_point_copy (const ClutterPoint *point)
|
|
|
|
|
{
|
|
|
|
|
return g_slice_dup (ClutterPoint, point);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_point_free:
|
|
|
|
|
* @point: a #ClutterPoint
|
|
|
|
|
*
|
|
|
|
|
* Frees the resources allocated for @point.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
void
|
|
|
|
|
clutter_point_free (ClutterPoint *point)
|
|
|
|
|
{
|
2012-06-09 05:38:09 -04:00
|
|
|
|
if (point != NULL && point != &_clutter_point_zero)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
g_slice_free (ClutterPoint, point);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_point_equals:
|
|
|
|
|
* @a: the first #ClutterPoint to compare
|
|
|
|
|
* @b: the second #ClutterPoint to compare
|
|
|
|
|
*
|
|
|
|
|
* Compares two #ClutterPoint for equality.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the #ClutterPoints are equal
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
gboolean
|
|
|
|
|
clutter_point_equals (const ClutterPoint *a,
|
|
|
|
|
const ClutterPoint *b)
|
|
|
|
|
{
|
|
|
|
|
if (a == b)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (a == NULL || b == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-04-19 07:30:45 -04:00
|
|
|
|
return fabsf (a->x - b->x) < FLOAT_EPSILON &&
|
|
|
|
|
fabsf (a->y - b->y) < FLOAT_EPSILON;
|
2012-03-30 13:22:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-19 07:15:17 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_point_distance:
|
|
|
|
|
* @a: a #ClutterPoint
|
|
|
|
|
* @b: a #ClutterPoint
|
|
|
|
|
* @x_distance: (out) (allow-none): return location for the horizontal
|
|
|
|
|
* distance between the points
|
|
|
|
|
* @y_distance: (out) (allow-none): return location for the vertical
|
|
|
|
|
* distance between the points
|
|
|
|
|
*
|
|
|
|
|
* Computes the distance between two #ClutterPoint.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the distance between the points.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
float
|
|
|
|
|
clutter_point_distance (const ClutterPoint *a,
|
|
|
|
|
const ClutterPoint *b,
|
|
|
|
|
float *x_distance,
|
|
|
|
|
float *y_distance)
|
|
|
|
|
{
|
|
|
|
|
float x_d, y_d;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (a != NULL, 0.f);
|
|
|
|
|
g_return_val_if_fail (b != NULL, 0.f);
|
|
|
|
|
|
|
|
|
|
if (clutter_point_equals (a, b))
|
|
|
|
|
return 0.f;
|
|
|
|
|
|
|
|
|
|
x_d = (a->x - b->x);
|
|
|
|
|
y_d = (a->y - b->y);
|
|
|
|
|
|
|
|
|
|
if (x_distance != NULL)
|
|
|
|
|
*x_distance = fabsf (x_d);
|
|
|
|
|
|
|
|
|
|
if (y_distance != NULL)
|
|
|
|
|
*y_distance = fabsf (y_d);
|
|
|
|
|
|
|
|
|
|
return sqrt ((x_d * x_d) + (y_d * y_d));
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
static gboolean
|
|
|
|
|
clutter_point_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *retval)
|
|
|
|
|
{
|
|
|
|
|
const ClutterPoint *ap = g_value_get_boxed (a);
|
|
|
|
|
const ClutterPoint *bp = g_value_get_boxed (b);
|
|
|
|
|
ClutterPoint res = CLUTTER_POINT_INIT (0, 0);
|
|
|
|
|
|
|
|
|
|
res.x = ap->x + (bp->x - ap->x) * progress;
|
|
|
|
|
res.y = ap->y + (bp->y - ap->y) * progress;
|
|
|
|
|
|
|
|
|
|
g_value_set_boxed (retval, &res);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterPoint, clutter_point,
|
|
|
|
|
clutter_point_copy,
|
|
|
|
|
clutter_point_free,
|
|
|
|
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_point_progress))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterSize
|
|
|
|
|
*/
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
2012-08-10 09:28:48 -04:00
|
|
|
|
* clutter_size_alloc: (constructor)
|
2012-04-18 12:31:28 -04:00
|
|
|
|
*
|
|
|
|
|
* Allocates a new #ClutterSize.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterSize.
|
|
|
|
|
* Use clutter_size_free() to free its resources.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterSize *
|
2012-04-18 12:31:28 -04:00
|
|
|
|
clutter_size_alloc (void)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
{
|
|
|
|
|
return g_slice_new0 (ClutterSize);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_size_init:
|
|
|
|
|
* @size: a #ClutterSize
|
|
|
|
|
* @width: the width
|
|
|
|
|
* @height: the height
|
|
|
|
|
*
|
|
|
|
|
* Initializes a #ClutterSize with the given dimensions.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the initialized #ClutterSize
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterSize *
|
|
|
|
|
clutter_size_init (ClutterSize *size,
|
|
|
|
|
float width,
|
|
|
|
|
float height)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (size != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
size->width = width;
|
|
|
|
|
size->height = height;
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_size_copy:
|
|
|
|
|
* @size: a #ClutterSize
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #ClutterSize and duplicates @size.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterSize.
|
|
|
|
|
* Use clutter_size_free() to free its resources.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
ClutterSize *
|
|
|
|
|
clutter_size_copy (const ClutterSize *size)
|
|
|
|
|
{
|
|
|
|
|
return g_slice_dup (ClutterSize, size);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_size_free:
|
|
|
|
|
* @size: a #ClutterSize
|
|
|
|
|
*
|
|
|
|
|
* Frees the resources allocated for @size.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
void
|
|
|
|
|
clutter_size_free (ClutterSize *size)
|
|
|
|
|
{
|
|
|
|
|
if (size != NULL)
|
|
|
|
|
g_slice_free (ClutterSize, size);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_size_equals:
|
|
|
|
|
* @a: a #ClutterSize to compare
|
|
|
|
|
* @b: a #ClutterSize to compare
|
|
|
|
|
*
|
|
|
|
|
* Compares two #ClutterSize for equality.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the two #ClutterSize are equal
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
2012-03-30 13:22:04 -04:00
|
|
|
|
gboolean
|
|
|
|
|
clutter_size_equals (const ClutterSize *a,
|
|
|
|
|
const ClutterSize *b)
|
|
|
|
|
{
|
|
|
|
|
if (a == b)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (a == NULL || b == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-04-19 07:30:45 -04:00
|
|
|
|
return fabsf (a->width - b->width) < FLOAT_EPSILON &&
|
|
|
|
|
fabsf (a->height - b->height) < FLOAT_EPSILON;
|
2012-03-30 13:22:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clutter_size_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *retval)
|
|
|
|
|
{
|
|
|
|
|
const ClutterSize *as = g_value_get_boxed (a);
|
|
|
|
|
const ClutterSize *bs = g_value_get_boxed (b);
|
|
|
|
|
ClutterSize res = CLUTTER_SIZE_INIT (0, 0);
|
|
|
|
|
|
|
|
|
|
res.width = as->width + (bs->width - as->width) * progress;
|
|
|
|
|
res.height = as->height + (bs->height - as->height) * progress;
|
|
|
|
|
|
|
|
|
|
g_value_set_boxed (retval, &res);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterSize, clutter_size,
|
|
|
|
|
clutter_size_copy,
|
|
|
|
|
clutter_size_free,
|
|
|
|
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_size_progress))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ClutterRect
|
|
|
|
|
*/
|
|
|
|
|
|
2012-06-09 05:35:56 -04:00
|
|
|
|
static const ClutterRect _clutter_rect_zero = CLUTTER_RECT_INIT_ZERO;
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
static gboolean clutter_rect_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *res);
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterRect, clutter_rect,
|
|
|
|
|
clutter_rect_copy,
|
|
|
|
|
clutter_rect_free,
|
|
|
|
|
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_rect_progress))
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
clutter_rect_normalize_internal (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
if (rect->size.width >= 0.f && rect->size.height >= 0.f)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (rect->size.width < 0.f)
|
|
|
|
|
{
|
|
|
|
|
float size = fabsf (rect->size.width);
|
|
|
|
|
|
|
|
|
|
rect->origin.x -= size;
|
|
|
|
|
rect->size.width = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rect->size.height < 0.f)
|
|
|
|
|
{
|
|
|
|
|
float size = fabsf (rect->size.height);
|
|
|
|
|
|
|
|
|
|
rect->origin.y -= size;
|
|
|
|
|
rect->size.height = size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-09 05:35:56 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_zero:
|
|
|
|
|
*
|
|
|
|
|
* A #ClutterRect with #ClutterRect.origin set at (0, 0) and a size
|
|
|
|
|
* of 0.
|
|
|
|
|
*
|
|
|
|
|
* The returned value can be used as a guard.
|
|
|
|
|
*
|
|
|
|
|
* Return value: a rectangle with origin in (0, 0) and a size of 0.
|
|
|
|
|
* The returned #ClutterRect is owned by Clutter and it should not
|
|
|
|
|
* be modified or freed.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
const ClutterRect *
|
|
|
|
|
clutter_rect_zero (void)
|
|
|
|
|
{
|
|
|
|
|
return &_clutter_rect_zero;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
/**
|
2012-08-10 09:28:48 -04:00
|
|
|
|
* clutter_rect_alloc: (constructor)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
*
|
|
|
|
|
* Creates a new, empty #ClutterRect.
|
|
|
|
|
*
|
|
|
|
|
* You can use clutter_rect_init() to initialize the returned rectangle,
|
|
|
|
|
* for instance:
|
|
|
|
|
*
|
|
|
|
|
* |[
|
2012-04-18 12:31:28 -04:00
|
|
|
|
* rect = clutter_rect_init (clutter_rect_alloc (), x, y, width, height);
|
2012-03-30 13:22:04 -04:00
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterRect.
|
|
|
|
|
* Use clutter_rect_free() to free its resources
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterRect *
|
2012-04-18 12:31:28 -04:00
|
|
|
|
clutter_rect_alloc (void)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
{
|
|
|
|
|
return g_slice_new0 (ClutterRect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_init:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
* @x: X coordinate of the origin
|
|
|
|
|
* @y: Y coordinate of the origin
|
|
|
|
|
* @width: width of the rectangle
|
|
|
|
|
* @height: height of the rectangle
|
|
|
|
|
*
|
|
|
|
|
* Initializes a #ClutterRect with the given origin and size.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the updated rectangle
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterRect *
|
|
|
|
|
clutter_rect_init (ClutterRect *rect,
|
|
|
|
|
float x,
|
|
|
|
|
float y,
|
|
|
|
|
float width,
|
|
|
|
|
float height)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
rect->origin.x = x;
|
|
|
|
|
rect->origin.y = y;
|
|
|
|
|
|
|
|
|
|
rect->size.width = width;
|
|
|
|
|
rect->size.height = height;
|
|
|
|
|
|
|
|
|
|
return rect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_copy:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Copies @rect into a new #ClutterRect instance.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocate copy of @rect.
|
|
|
|
|
* Use clutter_rect_free() to free the associated resources
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterRect *
|
|
|
|
|
clutter_rect_copy (const ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
if (rect != NULL)
|
|
|
|
|
{
|
|
|
|
|
ClutterRect *res;
|
|
|
|
|
|
|
|
|
|
res = g_slice_dup (ClutterRect, rect);
|
|
|
|
|
clutter_rect_normalize_internal (res);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_free:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Frees the resources allocated by @rect.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_free (ClutterRect *rect)
|
|
|
|
|
{
|
2012-06-09 05:38:09 -04:00
|
|
|
|
if (rect != NULL && rect != &_clutter_rect_zero)
|
2012-03-30 13:22:04 -04:00
|
|
|
|
g_slice_free (ClutterRect, rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_equals:
|
|
|
|
|
* @a: a #ClutterRect
|
|
|
|
|
* @b: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Checks whether @a and @b are equals.
|
|
|
|
|
*
|
|
|
|
|
* This function will normalize both @a and @b before comparing
|
|
|
|
|
* their origin and size.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the rectangles match in origin and size.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_rect_equals (ClutterRect *a,
|
|
|
|
|
ClutterRect *b)
|
|
|
|
|
{
|
|
|
|
|
if (a == b)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (a == NULL || b == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (a);
|
|
|
|
|
clutter_rect_normalize_internal (b);
|
|
|
|
|
|
|
|
|
|
return clutter_point_equals (&a->origin, &b->origin) &&
|
|
|
|
|
clutter_size_equals (&a->size, &b->size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_normalize:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Normalizes a #ClutterRect.
|
|
|
|
|
*
|
|
|
|
|
* A #ClutterRect is defined by the area covered by its size; this means
|
|
|
|
|
* that a #ClutterRect with #ClutterRect.origin in [ 0, 0 ] and a
|
|
|
|
|
* #ClutterRect.size of [ 10, 10 ] is equivalent to a #ClutterRect with
|
|
|
|
|
* #ClutterRect.origin in [ 10, 10 ] and a #ClutterRect.size of [ -10, -10 ].
|
|
|
|
|
*
|
|
|
|
|
* This function is useful to ensure that a rectangle has positive width
|
|
|
|
|
* and height; it will modify the passed @rect and normalize its size.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterRect *
|
|
|
|
|
clutter_rect_normalize (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return rect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_get_center:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
* @center: (out caller-allocates): a #ClutterPoint
|
|
|
|
|
*
|
|
|
|
|
* Retrieves the center of @rect, after normalizing the rectangle,
|
|
|
|
|
* and updates @center with the correct coordinates.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_get_center (ClutterRect *rect,
|
|
|
|
|
ClutterPoint *center)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (rect != NULL);
|
|
|
|
|
g_return_if_fail (center != NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
center->x = rect->origin.x + (rect->size.width / 2.0f);
|
|
|
|
|
center->y = rect->origin.y + (rect->size.height / 2.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_contains_point:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
* @point: the point to check
|
|
|
|
|
*
|
|
|
|
|
* Checks whether @point is contained by @rect, after normalizing the
|
|
|
|
|
* rectangle.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the @point is contained by @rect.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_rect_contains_point (ClutterRect *rect,
|
|
|
|
|
ClutterPoint *point)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (point != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return (point->x >= rect->origin.x) &&
|
|
|
|
|
(point->y >= rect->origin.y) &&
|
|
|
|
|
(point->x <= (rect->origin.x + rect->size.width)) &&
|
|
|
|
|
(point->y <= (rect->origin.y + rect->size.height));
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-19 07:32:07 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_contains_rect:
|
|
|
|
|
* @a: a #ClutterRect
|
|
|
|
|
* @b: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Checks whether @a contains @b.
|
|
|
|
|
*
|
|
|
|
|
* The first rectangle contains the second if the union of the
|
|
|
|
|
* two #ClutterRect is equal to the first rectangle.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the first rectangle contains the second.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_rect_contains_rect (ClutterRect *a,
|
|
|
|
|
ClutterRect *b)
|
|
|
|
|
{
|
|
|
|
|
ClutterRect res;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (a != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (b != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
clutter_rect_union (a, b, &res);
|
|
|
|
|
|
|
|
|
|
return clutter_rect_equals (a, &res);
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_union:
|
|
|
|
|
* @a: a #ClutterRect
|
|
|
|
|
* @b: a #ClutterRect
|
|
|
|
|
* @res: (out caller-allocates): a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Computes the smallest possible rectangle capable of fully containing
|
|
|
|
|
* both @a and @b, and places it into @res.
|
|
|
|
|
*
|
|
|
|
|
* This function will normalize both @a and @b prior to computing their
|
|
|
|
|
* union.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_union (ClutterRect *a,
|
|
|
|
|
ClutterRect *b,
|
|
|
|
|
ClutterRect *res)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (a != NULL);
|
|
|
|
|
g_return_if_fail (b != NULL);
|
|
|
|
|
g_return_if_fail (res != NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (a);
|
|
|
|
|
clutter_rect_normalize_internal (b);
|
|
|
|
|
|
|
|
|
|
res->origin.x = MIN (a->origin.x, b->origin.x);
|
|
|
|
|
res->origin.y = MIN (a->origin.y, b->origin.y);
|
|
|
|
|
|
|
|
|
|
res->size.width = MAX (a->size.width, b->size.width);
|
|
|
|
|
res->size.height = MAX (a->size.height, b->size.height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_intersection:
|
|
|
|
|
* @a: a #ClutterRect
|
|
|
|
|
* @b: a #ClutterRect
|
|
|
|
|
* @res: (out caller-allocates) (allow-none): a #ClutterRect, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Computes the intersection of @a and @b, and places it in @res, if @res
|
|
|
|
|
* is not %NULL.
|
|
|
|
|
*
|
|
|
|
|
* This function will normalize both @a and @b prior to computing their
|
|
|
|
|
* intersection.
|
|
|
|
|
*
|
|
|
|
|
* This function can be used to simply check if the intersection of @a and @b
|
|
|
|
|
* is not empty, by using %NULL for @res.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the intersection of @a and @b is not empty
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
clutter_rect_intersection (ClutterRect *a,
|
|
|
|
|
ClutterRect *b,
|
|
|
|
|
ClutterRect *res)
|
|
|
|
|
{
|
|
|
|
|
float x_1, y_1, x_2, y_2;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (a != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (b != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (a);
|
|
|
|
|
clutter_rect_normalize_internal (b);
|
|
|
|
|
|
|
|
|
|
x_1 = MAX (a->origin.x, b->origin.y);
|
|
|
|
|
y_1 = MAX (a->origin.y, b->origin.y);
|
|
|
|
|
x_2 = MIN (a->origin.x + a->size.width, b->origin.x + b->size.width);
|
|
|
|
|
y_2 = MIN (a->origin.y + a->size.height, b->origin.y + b->size.height);
|
|
|
|
|
|
|
|
|
|
if (x_1 >= x_2 || y_1 >= y_2)
|
|
|
|
|
{
|
|
|
|
|
if (res != NULL)
|
|
|
|
|
clutter_rect_init (res, 0.f, 0.f, 0.f, 0.f);
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res != NULL)
|
|
|
|
|
clutter_rect_init (res, x_1, y_1, x_2 - x_1, y_2 - y_1);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_offset:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
* @d_x: the horizontal offset value
|
|
|
|
|
* @d_y: the vertical offset value
|
|
|
|
|
*
|
|
|
|
|
* Offsets the origin of @rect by the given values, after normalizing
|
|
|
|
|
* the rectangle.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_offset (ClutterRect *rect,
|
|
|
|
|
float d_x,
|
|
|
|
|
float d_y)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (rect != NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
rect->origin.x += d_x;
|
|
|
|
|
rect->origin.y += d_y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_inset:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
* @d_x: an horizontal value; a positive @d_x will create an inset rectangle,
|
|
|
|
|
* and a negative value will create a larger rectangle
|
|
|
|
|
* @d_y: a vertical value; a positive @d_x will create an inset rectangle,
|
|
|
|
|
* and a negative value will create a larger rectangle
|
|
|
|
|
*
|
|
|
|
|
* Normalizes the @rect and offsets its origin by the @d_x and @d_y values;
|
|
|
|
|
* the size is adjusted by (2 * @d_x, 2 * @d_y).
|
|
|
|
|
*
|
|
|
|
|
* If @d_x and @d_y are positive the size of the rectangle is decreased; if
|
|
|
|
|
* the values are negative, the size of the rectangle is increased.
|
|
|
|
|
*
|
|
|
|
|
* If the resulting rectangle has a negative width or height, the size is
|
|
|
|
|
* set to 0.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_inset (ClutterRect *rect,
|
|
|
|
|
float d_x,
|
|
|
|
|
float d_y)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (rect != NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
rect->origin.x += d_x;
|
|
|
|
|
rect->origin.y += d_y;
|
|
|
|
|
|
|
|
|
|
if (d_x >= 0.f)
|
|
|
|
|
rect->size.width -= (d_x * 2.f);
|
|
|
|
|
else
|
|
|
|
|
rect->size.width += (d_x * -2.f);
|
|
|
|
|
|
|
|
|
|
if (d_y >= 0.f)
|
|
|
|
|
rect->size.height -= (d_y * 2.f);
|
|
|
|
|
else
|
|
|
|
|
rect->size.height += (d_y * -2.f);
|
|
|
|
|
|
|
|
|
|
if (rect->size.width < 0.f)
|
|
|
|
|
rect->size.width = 0.f;
|
|
|
|
|
|
|
|
|
|
if (rect->size.height < 0.f)
|
|
|
|
|
rect->size.height = 0.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_clamp_to_pixel:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Rounds the origin of @rect downwards to the nearest integer, and rounds
|
|
|
|
|
* the size of @rect upwards to the nearest integer, so that @rect is
|
|
|
|
|
* updated to the smallest rectangle capable of fully containing the
|
|
|
|
|
* original, fractional rectangle.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_rect_clamp_to_pixel (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (rect != NULL);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
rect->origin.x = floorf (rect->origin.x);
|
|
|
|
|
rect->origin.y = floorf (rect->origin.y);
|
|
|
|
|
|
|
|
|
|
rect->size.width = ceilf (rect->size.width);
|
|
|
|
|
rect->size.height = ceilf (rect->size.height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_get_x:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Retrieves the X coordinate of the origin of @rect.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the X coordinate of the origin of the rectangle
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
float
|
|
|
|
|
clutter_rect_get_x (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, 0.f);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return rect->origin.x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_get_y:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Retrieves the Y coordinate of the origin of @rect.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the Y coordinate of the origin of the rectangle
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
float
|
|
|
|
|
clutter_rect_get_y (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, 0.f);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return rect->origin.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_get_width:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Retrieves the width of @rect.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the width of the rectangle
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
float
|
|
|
|
|
clutter_rect_get_width (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, 0.f);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return rect->size.width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_rect_get_height:
|
|
|
|
|
* @rect: a #ClutterRect
|
|
|
|
|
*
|
|
|
|
|
* Retrieves the height of @rect.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the height of the rectangle
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
float
|
|
|
|
|
clutter_rect_get_height (ClutterRect *rect)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (rect != NULL, 0.f);
|
|
|
|
|
|
|
|
|
|
clutter_rect_normalize_internal (rect);
|
|
|
|
|
|
|
|
|
|
return rect->size.height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clutter_rect_progress (const GValue *a,
|
|
|
|
|
const GValue *b,
|
|
|
|
|
gdouble progress,
|
|
|
|
|
GValue *retval)
|
|
|
|
|
{
|
|
|
|
|
const ClutterRect *rect_a = g_value_get_boxed (a);
|
|
|
|
|
const ClutterRect *rect_b = g_value_get_boxed (b);
|
|
|
|
|
ClutterRect res = CLUTTER_RECT_INIT_ZERO;
|
|
|
|
|
|
|
|
|
|
#define INTERPOLATE(r_a,r_b,member,field,factor) ((r_a)->member.field + (((r_b)->member.field - ((r_b)->member.field)) * (factor)))
|
|
|
|
|
|
|
|
|
|
res.origin.x = INTERPOLATE (rect_a, rect_b, origin, x, progress);
|
|
|
|
|
res.origin.y = INTERPOLATE (rect_a, rect_b, origin, y, progress);
|
|
|
|
|
|
|
|
|
|
res.size.width = INTERPOLATE (rect_a, rect_b, size, width, progress);
|
|
|
|
|
res.size.height = INTERPOLATE (rect_a, rect_b, size, height, progress);
|
|
|
|
|
|
|
|
|
|
#undef INTERPOLATE
|
|
|
|
|
|
2012-04-18 12:31:28 -04:00
|
|
|
|
clutter_rect_normalize_internal (&res);
|
|
|
|
|
|
2012-03-30 13:22:04 -04:00
|
|
|
|
g_value_set_boxed (retval, &res);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-07-21 13:46:47 -04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ClutterMatrix:
|
|
|
|
|
*
|
|
|
|
|
* A type representing a 4x4 matrix.
|
|
|
|
|
*
|
|
|
|
|
* It is identicaly to #CoglMatrix.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static gpointer
|
|
|
|
|
clutter_matrix_copy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
return g_memdup (data, sizeof (ClutterMatrix));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_DEFINE_BOXED_TYPE (ClutterMatrix, clutter_matrix,
|
|
|
|
|
clutter_matrix_copy,
|
|
|
|
|
clutter_matrix_free)
|
|
|
|
|
|
|
|
|
|
/**
|
2012-08-16 06:37:20 -04:00
|
|
|
|
* clutter_matrix_alloc:
|
2012-07-21 13:46:47 -04:00
|
|
|
|
*
|
|
|
|
|
* Allocates enough memory to hold a #ClutterMatrix.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer full): the newly allocated #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterMatrix *
|
|
|
|
|
clutter_matrix_alloc (void)
|
|
|
|
|
{
|
|
|
|
|
return g_new0 (ClutterMatrix, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_matrix_free:
|
|
|
|
|
* @matrix: (allow-none): a #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Frees the memory allocated by clutter_matrix_alloc().
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
clutter_matrix_free (ClutterMatrix *matrix)
|
|
|
|
|
{
|
|
|
|
|
g_free (matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_matrix_init_identity:
|
|
|
|
|
* @matrix: a #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Initializes @matrix with the identity matrix, i.e.:
|
|
|
|
|
*
|
|
|
|
|
* |[
|
|
|
|
|
* .xx = 1.0, .xy = 0.0, .xz = 0.0, .xw = 0.0
|
|
|
|
|
* .yx = 0.0, .yy = 1.0, .yz = 0.0, .yw = 0.0
|
|
|
|
|
* .zx = 0.0, .zy = 0.0, .zz = 1.0, .zw = 0.0
|
|
|
|
|
* .wx = 0.0, .wy = 0.0, .wz = 0.0, .ww = 1.0
|
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the initialized #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterMatrix *
|
|
|
|
|
clutter_matrix_init_identity (ClutterMatrix *matrix)
|
|
|
|
|
{
|
|
|
|
|
cogl_matrix_init_identity (matrix);
|
|
|
|
|
|
|
|
|
|
return matrix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_matrix_init_from_array:
|
|
|
|
|
* @matrix: a #ClutterMatrix
|
|
|
|
|
* @values: (array fixed-size=16): a C array of 16 floating point values,
|
|
|
|
|
* representing a 4x4 matrix, with column-major order
|
|
|
|
|
*
|
|
|
|
|
* Initializes @matrix with the contents of a C array of floating point
|
|
|
|
|
* values.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the initialzed #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterMatrix *
|
|
|
|
|
clutter_matrix_init_from_array (ClutterMatrix *matrix,
|
|
|
|
|
const float values[16])
|
|
|
|
|
{
|
|
|
|
|
cogl_matrix_init_from_array (matrix, values);
|
|
|
|
|
|
|
|
|
|
return matrix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clutter_matrix_init_from_matrix:
|
|
|
|
|
* @a: the #ClutterMatrix to initialize
|
|
|
|
|
* @b: the #ClutterMatrix to copy
|
|
|
|
|
*
|
|
|
|
|
* Initializes the #ClutterMatrix @a with the contents of the
|
|
|
|
|
* #ClutterMatrix @b.
|
|
|
|
|
*
|
|
|
|
|
* Return value: (transfer none): the initialized #ClutterMatrix
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.12
|
|
|
|
|
*/
|
|
|
|
|
ClutterMatrix *
|
2012-08-16 11:13:38 -04:00
|
|
|
|
clutter_matrix_init_from_matrix (ClutterMatrix *a,
|
|
|
|
|
const ClutterMatrix *b)
|
2012-07-21 13:46:47 -04:00
|
|
|
|
{
|
2012-08-16 11:13:38 -04:00
|
|
|
|
return memcpy (a, b, sizeof (ClutterMatrix));
|
2012-07-21 13:46:47 -04:00
|
|
|
|
}
|