mutter/clutter/clutter-fixed.c
Emmanuele Bassi 911b395c8a 2008-10-30 Emmanuele Bassi <ebassi@linux.intel.com>
Bug 1209 - Move fixed point API in COGL

	* clutter/cogl/cogl-fixed.h:
	* clutter/cogl/cogl.h.in:
	* clutter/cogl/common/Makefile.am:
	* clutter/cogl/common/cogl-fixed.c: Add fixed point API, modelled
	after the ClutterFixed. The CoglFixed API supercedes the ClutterFixed
	one and avoids the dependency of COGL on Clutter's own API.

	* clutter/cogl/common/cogl-clip-stack.c:
	* clutter/cogl/common/cogl-primitives.c:
	* clutter/cogl/common/cogl-primitives.h: Update internal usage of
	ClutterFixed to CoglFixed.

	* clutter/cogl/gl/Makefile.am:
	* clutter/cogl/gl/cogl-primitives.c:
	* clutter/cogl/gl/cogl-texture.c:
	* clutter/cogl/gl/cogl.c: Ditto, in the GL implementation of the
	COGL API.

	* clutter/cogl/gles/Makefile.am:
	* clutter/cogl/gles/cogl-fbo.c:
	* clutter/cogl/gles/cogl-gles2-wrapper.c:
	* clutter/cogl/gles/cogl-primitives.c:
	* clutter/cogl/gles/cogl-texture.c:
	* clutter/cogl/gles/cogl.c: Ditto, in the GLES implementation of
	the COGL API.

	* clutter/pango/pangoclutter-glyph-cache.c:
	* clutter/pango/pangoclutter-glyph-cache.h: Ditto, in the Pango
	renderer glyphs cache.

	* clutter/clutter-fixed.c:
	* clutter/clutter-fixed.h: ClutterFixed and related API becomes
	a simple transition API for bindings and public Clutter API.

	* clutter/clutter-actor.c:
	* clutter/clutter-alpha.c:
	* clutter/clutter-backend.c:
	* clutter/clutter-behaviour-depth.c:
	* clutter/clutter-behaviour-ellipse.c:
	* clutter/clutter-behaviour-path.c:
	* clutter/clutter-behaviour-rotate.c:
	* clutter/clutter-behaviour-scale.c:
	* clutter/clutter-clone-texture.c:
	* clutter/clutter-color.c:
	* clutter/clutter-entry.c:
	* clutter/clutter-stage.c:
	* clutter/clutter-texture.c:
	* clutter/clutter-timeline.c:
	* clutter/clutter-units.h: Move from the internal usage of
	ClutterFixed to CoglFixed.

	* doc/reference/clutter/clutter-sections.txt:
	* doc/reference/cogl/cogl-docs.sgml:
	* doc/reference/cogl/cogl-sections.txt: Update the documentation.

	* tests/test-cogl-tex-tile.c:
	* tests/test-project.c: Fix tests after the API change

	* README: Add release notes.
2008-10-30 16:37:55 +00:00

369 lines
9.9 KiB
C

/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Tomas Frydrych <tf@openedhand.com>
*
* Copyright (C) 2006, 2007 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#define G_IMPLEMENT_INLINES
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#include "clutter-fixed.h"
#include "clutter-private.h"
/**
* SECTION:clutter-fixed
* @short_description: Fixed Point API
*
* Clutter has a fixed point API targeted at platforms without a
* floating point unit, such as embedded devices. On such platforms
* this API should be preferred to the floating point one as it does
* not trigger the slow path of software emulation, relying on integer
* math for fixed-to-floating and floating-to-fixed conversion.
*
* It is no recommened for use on platforms with a floating point unit
* (eg desktop systems) nor for use in bindings.
*
* Basic rules of Fixed Point arithmethic:
*
* <itemizedlist>
* <listitem>
* <para>Two fixed point numbers can be directly added,
* subtracted and have their modulus taken.</para>
* </listitem>
* <listitem>
* <para>To add other numerical type to a fixed point number it has to
* be first converted to fixed point.</para>
* </listitem>
* <listitem>
* <para>A fixed point number can be directly multiplied or divided by
* an integer.</para>
* </listitem>
* <listitem>
* <para>Two fixed point numbers can only be multiplied and divided by the
* provided %CLUTTER_FIXED_MUL and %CLUTTER_FIXED_DIV macros.</para>
* </listitem>
* </itemizedlist>
*/
static GTypeInfo _info = {
0,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL,
NULL,
};
static GTypeFundamentalInfo _finfo = { 0, };
static void
clutter_value_init_fixed (GValue *value)
{
value->data[0].v_int = 0;
}
static void
clutter_value_copy_fixed (const GValue *src,
GValue *dest)
{
dest->data[0].v_int = src->data[0].v_int;
}
static gchar *
clutter_value_collect_fixed (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
value->data[0].v_int = collect_values[0].v_int;
return NULL;
}
static gchar *
clutter_value_lcopy_fixed (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint32 *fixed_p = collect_values[0].v_pointer;
if (!fixed_p)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
*fixed_p = value->data[0].v_int;
return NULL;
}
static void
clutter_value_transform_fixed_int (const GValue *src,
GValue *dest)
{
dest->data[0].v_int = COGL_FIXED_TO_INT (src->data[0].v_int);
}
static void
clutter_value_transform_fixed_double (const GValue *src,
GValue *dest)
{
dest->data[0].v_double = COGL_FIXED_TO_DOUBLE (src->data[0].v_int);
}
static void
clutter_value_transform_fixed_float (const GValue *src,
GValue *dest)
{
dest->data[0].v_float = COGL_FIXED_TO_FLOAT (src->data[0].v_int);
}
static void
clutter_value_transform_int_fixed (const GValue *src,
GValue *dest)
{
dest->data[0].v_int = COGL_FIXED_FROM_INT (src->data[0].v_int);
}
static void
clutter_value_transform_double_fixed (const GValue *src,
GValue *dest)
{
dest->data[0].v_int = COGL_FIXED_FROM_FLOAT (src->data[0].v_double);
}
static void
clutter_value_transform_float_fixed (const GValue *src,
GValue *dest)
{
dest->data[0].v_int = COGL_FIXED_FROM_FLOAT (src->data[0].v_float);
}
static const GTypeValueTable _clutter_fixed_value_table = {
clutter_value_init_fixed,
NULL,
clutter_value_copy_fixed,
NULL,
"i",
clutter_value_collect_fixed,
"p",
clutter_value_lcopy_fixed
};
GType
clutter_fixed_get_type (void)
{
static GType _clutter_fixed_type = 0;
if (G_UNLIKELY (_clutter_fixed_type == 0))
{
_info.value_table = & _clutter_fixed_value_table;
_clutter_fixed_type =
g_type_register_fundamental (g_type_fundamental_next (),
I_("ClutterFixed"),
&_info, &_finfo, 0);
g_value_register_transform_func (_clutter_fixed_type, G_TYPE_INT,
clutter_value_transform_fixed_int);
g_value_register_transform_func (G_TYPE_INT, _clutter_fixed_type,
clutter_value_transform_int_fixed);
g_value_register_transform_func (_clutter_fixed_type, G_TYPE_FLOAT,
clutter_value_transform_fixed_float);
g_value_register_transform_func (G_TYPE_FLOAT, _clutter_fixed_type,
clutter_value_transform_float_fixed);
g_value_register_transform_func (_clutter_fixed_type, G_TYPE_DOUBLE,
clutter_value_transform_fixed_double);
g_value_register_transform_func (G_TYPE_DOUBLE, _clutter_fixed_type,
clutter_value_transform_double_fixed);
}
return _clutter_fixed_type;
}
/**
* clutter_value_set_fixed:
* @value: a #GValue initialized to #CLUTTER_TYPE_FIXED
* @fixed_: the fixed point value to set
*
* Sets @value to @fixed_.
*
* Since: 0.8
*/
void
clutter_value_set_fixed (GValue *value,
ClutterFixed fixed_)
{
g_return_if_fail (CLUTTER_VALUE_HOLDS_FIXED (value));
value->data[0].v_int = fixed_;
}
/**
* clutter_value_get_fixed:
* @value: a #GValue initialized to #CLUTTER_TYPE_FIXED
*
* Gets the fixed point value stored inside @value.
*
* Return value: the value inside the passed #GValue
*
* Since: 0.8
*/
ClutterFixed
clutter_value_get_fixed (const GValue *value)
{
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_FIXED (value), 0);
return value->data[0].v_int;
}
static void
param_fixed_init (GParamSpec *pspec)
{
ClutterParamSpecFixed *fspec = CLUTTER_PARAM_SPEC_FIXED (pspec);
fspec->minimum = COGL_FIXED_MIN;
fspec->maximum = COGL_FIXED_MAX;
fspec->default_value = 0;
}
static void
param_fixed_set_default (GParamSpec *pspec,
GValue *value)
{
value->data[0].v_int = CLUTTER_PARAM_SPEC_FIXED (pspec)->default_value;
}
static gboolean
param_fixed_validate (GParamSpec *pspec,
GValue *value)
{
ClutterParamSpecFixed *fspec = CLUTTER_PARAM_SPEC_FIXED (pspec);
gint oval = COGL_FIXED_TO_INT (value->data[0].v_int);
gint min, max, val;
g_assert (CLUTTER_IS_PARAM_SPEC_FIXED (pspec));
/* we compare the integer part of the value because the minimum
* and maximum values cover just that part of the representation
*/
min = fspec->minimum;
max = fspec->maximum;
val = COGL_FIXED_TO_INT (value->data[0].v_int);
val = CLAMP (val, min, max);
if (val != oval)
{
value->data[0].v_int = val;
return TRUE;
}
return FALSE;
}
static gint
param_fixed_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2)
{
if (value1->data[0].v_int < value2->data[0].v_int)
return -1;
else
return value1->data[0].v_int > value2->data[0].v_int;
}
GType
clutter_param_fixed_get_type (void)
{
static GType pspec_type = 0;
if (G_UNLIKELY (pspec_type == 0))
{
const GParamSpecTypeInfo pspec_info = {
sizeof (ClutterParamSpecFixed),
16,
param_fixed_init,
CLUTTER_TYPE_FIXED,
NULL,
param_fixed_set_default,
param_fixed_validate,
param_fixed_values_cmp,
};
pspec_type = g_param_type_register_static (I_("ClutterParamSpecFixed"),
&pspec_info);
}
return pspec_type;
}
/**
* clutter_param_spec_fixed:
* @name: name of the property
* @nick: short name
* @blurb: description (can be translatable)
* @minimum: lower boundary
* @maximum: higher boundary
* @default_value: default value
* @flags: flags for the param spec
*
* Creates a #GParamSpec for properties using #ClutterFixed values
*
* Return value: the newly created #GParamSpec
*
* Since: 0.8
*/
GParamSpec *
clutter_param_spec_fixed (const gchar *name,
const gchar *nick,
const gchar *blurb,
ClutterUnit minimum,
ClutterUnit maximum,
ClutterUnit default_value,
GParamFlags flags)
{
ClutterParamSpecFixed *fspec;
g_return_val_if_fail (default_value >= minimum && default_value <= maximum,
NULL);
fspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_FIXED,
name, nick, blurb,
flags);
fspec->minimum = minimum;
fspec->maximum = maximum;
fspec->default_value = default_value;
return G_PARAM_SPEC (fspec);
}