mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 21:34:09 +00:00
Migrated internal ClutterBezier to float.
Initial stage of ClutterPath migration to using float. Naive implementation of ClutterBezier, for now the points along the curve doesn't move at a regular speed. It is required a more precise calculation of the length of the curve for that to happen. Anyway the old implementation worked like this.
This commit is contained in:
parent
2be42c333a
commit
7c6d0251dd
@ -6,6 +6,7 @@
|
||||
* Authored By Tomas Frydrych <tf@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2007 OpenedHand
|
||||
* Copyright (C) 2013 Erick Pérez Castellanos <erick.red@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -21,97 +22,105 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include "clutter-bezier.h"
|
||||
#include "clutter-debug.h"
|
||||
|
||||
/*
|
||||
* We have some experimental code here to allow for constant velocity
|
||||
* movement of actors along the bezier path, this macro enables it.
|
||||
*/
|
||||
#undef CBZ_L2T_INTERPOLATION
|
||||
|
||||
/****************************************************************************
|
||||
* ClutterBezier -- represenation of a cubic bezier curve *
|
||||
* ClutterBezier -- representation of a cubic bezier curve *
|
||||
* (private; a building block for the public bspline object) *
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* The t parameter of the bezier is from interval <0,1>, so we can use
|
||||
* 14.18 format and special multiplication functions that preserve
|
||||
* more of the least significant bits but would overflow if the value
|
||||
* is > 1
|
||||
* Constants for sampling of the bezier. Float point.
|
||||
*/
|
||||
#define CBZ_T_Q 18
|
||||
#define CBZ_T_ONE (1 << CBZ_T_Q)
|
||||
#define CBZ_T_MUL(x,y) ((((x) >> 3) * ((y) >> 3)) >> 12)
|
||||
#define CBZ_T_POW2(x) CBZ_T_MUL (x, x)
|
||||
#define CBZ_T_POW3(x) CBZ_T_MUL (CBZ_T_POW2 (x), x)
|
||||
#define CBZ_T_DIV(x,y) ((((x) << 9)/(y)) << 9)
|
||||
|
||||
/*
|
||||
* Constants for sampling of the bezier
|
||||
*/
|
||||
#define CBZ_T_SAMPLES 128
|
||||
#define CBZ_T_STEP (CBZ_T_ONE / CBZ_T_SAMPLES)
|
||||
#define CBZ_L_STEP (CBZ_T_ONE / CBZ_T_SAMPLES)
|
||||
|
||||
typedef gint32 _FixedT;
|
||||
#define CBZ_T_SAMPLES 128.0
|
||||
#define CBZ_T_STEP (1.0 / CBZ_T_SAMPLES)
|
||||
|
||||
/*
|
||||
* This is a private type representing a single cubic bezier
|
||||
*/
|
||||
struct _ClutterBezier
|
||||
{
|
||||
/*
|
||||
* bezier coefficients -- these are calculated using multiplication and
|
||||
* addition from integer input, so these are also integers
|
||||
*/
|
||||
gint ax;
|
||||
gint bx;
|
||||
gint cx;
|
||||
gint dx;
|
||||
/* bezier coefficients */
|
||||
gfloat ax;
|
||||
gfloat bx;
|
||||
gfloat cx;
|
||||
gfloat dx;
|
||||
|
||||
gfloat ay;
|
||||
gfloat by;
|
||||
gfloat cy;
|
||||
gfloat dy;
|
||||
|
||||
gint ay;
|
||||
gint by;
|
||||
gint cy;
|
||||
gint dy;
|
||||
|
||||
/* length of the bezier */
|
||||
guint length;
|
||||
|
||||
#ifdef CBZ_L2T_INTERPOLATION
|
||||
/*
|
||||
* coefficients for the L -> t bezier; these are calculated from fixed
|
||||
* point input, and more specifically numbers that have been normalised
|
||||
* to fit <0,1>, so these are also fixed point, and we can used the
|
||||
* _FixedT type here.
|
||||
*/
|
||||
_FixedT La;
|
||||
_FixedT Lb;
|
||||
_FixedT Lc;
|
||||
/* _FixedT Ld; == 0 */
|
||||
#endif
|
||||
gfloat length;
|
||||
};
|
||||
|
||||
static gfloat
|
||||
_clutter_bezier_t2x (const ClutterBezier *b,
|
||||
gfloat t)
|
||||
{
|
||||
return b->ax * (1 - t) * (1 - t) * (1 - t) +
|
||||
b->bx * (1 - t) * (1 - t) * t +
|
||||
b->cx * (1 - t) * t * t +
|
||||
b->dx * t * t * t;
|
||||
}
|
||||
|
||||
static gfloat
|
||||
_clutter_bezier_t2y (const ClutterBezier *b,
|
||||
gfloat t)
|
||||
{
|
||||
return b->ay * (1 - t) * (1 - t) * (1 - t) +
|
||||
b->by * (1 - t) * (1 - t) * t +
|
||||
b->cy * (1 - t) * t * t +
|
||||
b->dy * t * t * t;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_bezier_new:
|
||||
*
|
||||
* Allocate the bezier
|
||||
*
|
||||
* Return value: The new bezier object.
|
||||
*/
|
||||
ClutterBezier *
|
||||
_clutter_bezier_new (void)
|
||||
{
|
||||
return g_slice_new0 (ClutterBezier);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_bezier_free:
|
||||
* @b: The bezier to free
|
||||
*
|
||||
* Free the object
|
||||
*/
|
||||
void
|
||||
_clutter_bezier_free (ClutterBezier * b)
|
||||
_clutter_bezier_free (ClutterBezier *b)
|
||||
{
|
||||
if (G_LIKELY (b))
|
||||
{
|
||||
g_slice_free (ClutterBezier, b);
|
||||
}
|
||||
g_slice_free (ClutterBezier, b);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_bezier_clone_and_move:
|
||||
* @b: A #ClutterBezier for cloning
|
||||
* @x: The x coordinates of the new end of the bezier
|
||||
* @y: The y coordinates of the new end of the bezier
|
||||
*
|
||||
* Clone the bezier and move th end-point, leaving both control
|
||||
* points in place.
|
||||
*
|
||||
* Return value: The new bezier object.
|
||||
*/
|
||||
ClutterBezier *
|
||||
_clutter_bezier_clone_and_move (const ClutterBezier *b, gint x, gint y)
|
||||
_clutter_bezier_clone_and_move (const ClutterBezier *b,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
{
|
||||
ClutterBezier * b2 = _clutter_bezier_new ();
|
||||
memcpy (b2, b, sizeof (ClutterBezier));
|
||||
@ -122,294 +131,124 @@ _clutter_bezier_clone_and_move (const ClutterBezier *b, gint x, gint y)
|
||||
return b2;
|
||||
}
|
||||
|
||||
#ifdef CBZ_L2T_INTERPOLATION
|
||||
/*
|
||||
* L is relative advance along the bezier curve from interval <0,1>
|
||||
*/
|
||||
static _FixedT
|
||||
_clutter_bezier_L2t (const ClutterBezier *b, _FixedT L)
|
||||
{
|
||||
_FixedT t = CBZ_T_MUL (b->La, CBZ_T_POW3(L))
|
||||
+ CBZ_T_MUL (b->Lb, CBZ_T_POW2(L))
|
||||
+ CBZ_T_MUL (b->Lc, L);
|
||||
|
||||
if (t > CBZ_T_ONE)
|
||||
t = CBZ_T_ONE;
|
||||
else if (t < 0)
|
||||
t = 0;
|
||||
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gint
|
||||
_clutter_bezier_t2x (const ClutterBezier * b, _FixedT t)
|
||||
{
|
||||
/*
|
||||
* NB -- the int coefficients can be at most 8192 for the multiplication
|
||||
* to work in this fashion due to the limits of the 14.18 fixed.
|
||||
*/
|
||||
return ((b->ax*CBZ_T_POW3(t) + b->bx*CBZ_T_POW2(t) + b->cx*t) >> CBZ_T_Q)
|
||||
+ b->dx;
|
||||
}
|
||||
|
||||
static gint
|
||||
_clutter_bezier_t2y (const ClutterBezier * b, _FixedT t)
|
||||
{
|
||||
/*
|
||||
* NB -- the int coefficients can be at most 8192 for the multiplication
|
||||
* to work in this fashion due to the limits of the 14.18 fixed.
|
||||
*/
|
||||
return ((b->ay*CBZ_T_POW3(t) + b->by*CBZ_T_POW2(t) + b->cy*t) >> CBZ_T_Q)
|
||||
+ b->dy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advances along the bezier to relative length L and returns the coordinances
|
||||
* in knot
|
||||
* _clutter_bezier_advance:
|
||||
* @b: A #ClutterBezier
|
||||
* @L: A relative length
|
||||
* @knot: The point whith the calculated position
|
||||
*
|
||||
* Advances along the bezier @b to relative length @L and returns the coordinances
|
||||
* in @knot
|
||||
*/
|
||||
void
|
||||
_clutter_bezier_advance (const ClutterBezier *b, gint L, ClutterKnot * knot)
|
||||
_clutter_bezier_advance (const ClutterBezier *b,
|
||||
gfloat L,
|
||||
ClutterKnot *knot)
|
||||
{
|
||||
#ifdef CBZ_L2T_INTERPOLATION
|
||||
_FixedT t = clutter_bezier_L2t (b, L);
|
||||
#else
|
||||
_FixedT t = L;
|
||||
#endif
|
||||
|
||||
gfloat t;
|
||||
t = L;
|
||||
|
||||
knot->x = _clutter_bezier_t2x (b, t);
|
||||
knot->y = _clutter_bezier_t2y (b, t);
|
||||
|
||||
CLUTTER_NOTE (MISC, "advancing to relative pt %f: t %f, {%d,%d}",
|
||||
(double) L / (double) CBZ_T_ONE,
|
||||
(double) t / (double) CBZ_T_ONE,
|
||||
knot->x, knot->y);
|
||||
|
||||
CLUTTER_NOTE (MISC,
|
||||
"advancing to relative point {%d,%d} by moving a distance equals to: %f, with t: %f",
|
||||
knot->x, knot->y, L, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_bezier_init:
|
||||
* @b: A #ClutterBezier
|
||||
* @x_0: x coordinates of the start point of the cubic bezier
|
||||
* @y_0: y coordinates of the start point of the cubic bezier
|
||||
* @x_1: x coordinates of the first control point
|
||||
* @y_1: y coordinates of the first control point
|
||||
* @x_2: x coordinates of the second control point
|
||||
* @y_2: y coordinates of the second control point
|
||||
* @x_3: x coordinates of the end point of the cubic bezier
|
||||
* @y_3: y coordinates of the end point of the cubic bezier
|
||||
*
|
||||
* Initialize the data of the bezier object @b.
|
||||
*/
|
||||
void
|
||||
_clutter_bezier_init (ClutterBezier *b,
|
||||
gint x_0, gint y_0,
|
||||
gint x_1, gint y_1,
|
||||
gint x_2, gint y_2,
|
||||
gint x_3, gint y_3)
|
||||
gfloat x_0,
|
||||
gfloat y_0,
|
||||
gfloat x_1,
|
||||
gfloat y_1,
|
||||
gfloat x_2,
|
||||
gfloat y_2,
|
||||
gfloat x_3,
|
||||
gfloat y_3)
|
||||
{
|
||||
_FixedT t;
|
||||
int i;
|
||||
int xp = x_0;
|
||||
int yp = y_0;
|
||||
_FixedT length [CBZ_T_SAMPLES + 1];
|
||||
gfloat t;
|
||||
gint i;
|
||||
|
||||
#ifdef CBZ_L2T_INTERPOLATION
|
||||
int j, k;
|
||||
_FixedT L;
|
||||
_FixedT t_equalized [CBZ_T_SAMPLES + 1];
|
||||
#endif
|
||||
gfloat xp;
|
||||
gfloat yp;
|
||||
|
||||
#if 0
|
||||
g_debug ("Initializing bezier at {{%d,%d},{%d,%d},{%d,%d},{%d,%d}}",
|
||||
x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
#endif
|
||||
|
||||
b->dx = x_0;
|
||||
b->dy = y_0;
|
||||
CLUTTER_NOTE (MISC,
|
||||
"Initializing bezier at {{%f,%f},{%f,%f},{%f,%f},{%f,%f}}",
|
||||
x_0, y_0, x_1, y_1, x_2, y_2, x_3, y_3);
|
||||
|
||||
b->cx = 3 * (x_1 - x_0);
|
||||
b->cy = 3 * (y_1 - y_0);
|
||||
b->ax = x_0;
|
||||
b->ay = y_0;
|
||||
b->bx = 3 * x_1;
|
||||
b->by = 3 * y_1;
|
||||
b->cx = 3 * x_2;
|
||||
b->cy = 3 * y_2;
|
||||
b->dx = x_3;
|
||||
b->dy = y_3;
|
||||
b->length = 0.0;
|
||||
|
||||
b->bx = 3 * (x_2 - x_1) - b->cx;
|
||||
b->by = 3 * (y_2 - y_1) - b->cy;
|
||||
CLUTTER_NOTE (MISC,
|
||||
"Coefficients {{%f,%f},{%f,%f},{%f,%f},{%f,%f}}",
|
||||
b->ax, b->ay, b->bx, b->by, b->cx, b->cy, b->dx, b->dy);
|
||||
|
||||
b->ax = x_3 - 3 * x_2 + 3 * x_1 - x_0;
|
||||
b->ay = y_3 - 3 * y_2 + 3 * y_1 - y_0;
|
||||
|
||||
#if 0
|
||||
g_debug ("Cooeficients {{%d,%d},{%d,%d},{%d,%d},{%d,%d}}",
|
||||
b->ax, b->ay, b->bx, b->by, b->cx, b->cy, b->dx, b->dy);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Because of the way we do the multiplication in bezeir_t2x,y
|
||||
* these coefficients need to be at most 0x1fff; this should be the case,
|
||||
* I think, but have added this warning to catch any problems -- if it
|
||||
* triggers, we need to change those two functions a bit.
|
||||
*/
|
||||
if (b->ax > 0x1fff || b->bx > 0x1fff || b->cx > 0x1fff)
|
||||
g_warning ("Calculated coefficents will result in multiplication "
|
||||
"overflow in clutter_bezier_t2x and clutter_bezier_t2y.");
|
||||
|
||||
/*
|
||||
* Sample the bezier with CBZ_T_SAMPLES and calculate length at
|
||||
* each point.
|
||||
*
|
||||
* We are working with integers here, so we use the fast sqrti function.
|
||||
*/
|
||||
length[0] = 0;
|
||||
|
||||
xp = b->ax;
|
||||
yp = b->ay;
|
||||
for (t = CBZ_T_STEP, i = 1; i <= CBZ_T_SAMPLES; ++i, t += CBZ_T_STEP)
|
||||
{
|
||||
int x = _clutter_bezier_t2x (b, t);
|
||||
int y = _clutter_bezier_t2y (b, t);
|
||||
|
||||
guint l = cogl_sqrti ((y - yp)*(y - yp) + (x - xp)*(x - xp));
|
||||
gfloat x = _clutter_bezier_t2x (b, t);
|
||||
gfloat y = _clutter_bezier_t2y (b, t);
|
||||
|
||||
l += length[i-1];
|
||||
|
||||
length[i] = l;
|
||||
b->length += sqrtf ((y - yp)*(y - yp) + (x - xp)*(x - xp));
|
||||
|
||||
xp = x;
|
||||
yp = y;
|
||||
}
|
||||
|
||||
b->length = length[CBZ_T_SAMPLES];
|
||||
|
||||
#if 0
|
||||
g_debug ("length %d", b->length);
|
||||
#endif
|
||||
|
||||
#ifdef CBZ_L2T_INTERPOLATION
|
||||
/*
|
||||
* Now normalize the length values, converting them into _FixedT
|
||||
*/
|
||||
for (i = 0; i <= CBZ_T_SAMPLES; ++i)
|
||||
{
|
||||
length[i] = (length[i] << CBZ_T_Q) / b->length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now generate a L -> t table such that the L will equidistant
|
||||
* over <0,1>
|
||||
*/
|
||||
t_equalized[0] = 0;
|
||||
|
||||
for (i = 1, j = 1, L = CBZ_L_STEP; i < CBZ_T_SAMPLES; ++i, L += CBZ_L_STEP)
|
||||
{
|
||||
_FixedT l1, l2;
|
||||
_FixedT d1, d2, d;
|
||||
_FixedT t1, t2;
|
||||
|
||||
/* find the band for our L */
|
||||
for (k = j; k < CBZ_T_SAMPLES; ++k)
|
||||
{
|
||||
if (L < length[k])
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we know that L is from (length[k-1],length[k]>
|
||||
* We remember k-1 in order not to have to iterate over the
|
||||
* whole length array in the next iteration of the main loop
|
||||
*/
|
||||
j = k - 1;
|
||||
|
||||
/*
|
||||
* Now interpolate equlised t as a weighted average
|
||||
*/
|
||||
l1 = length[k-1];
|
||||
l2 = length[k];
|
||||
d1 = l2 - L;
|
||||
d2 = L - l1;
|
||||
d = l2 - l1;
|
||||
t1 = (k - 1) * CBZ_T_STEP;
|
||||
t2 = k * CBZ_T_STEP;
|
||||
|
||||
t_equalized[i] = (t1*d1 + t2*d2)/d;
|
||||
|
||||
if (t_equalized[i] < t_equalized[i-1])
|
||||
g_debug ("wrong t: L %f, l1 %f, l2 %f, t1 %f, t2 %f",
|
||||
(double) (L)/(double)CBZ_T_ONE,
|
||||
(double) (l1)/(double)CBZ_T_ONE,
|
||||
(double) (l2)/(double)CBZ_T_ONE,
|
||||
(double) (t1)/(double)CBZ_T_ONE,
|
||||
(double) (t2)/(double)CBZ_T_ONE);
|
||||
|
||||
}
|
||||
|
||||
t_equalized[CBZ_T_SAMPLES] = CBZ_T_ONE;
|
||||
|
||||
/* We now fit a bezier -- at this stage, do a single fit through our values
|
||||
* at 0, 1/3, 2/3 and 1
|
||||
*
|
||||
* FIXME -- do we need to use a better fitting approach to choose the best
|
||||
* beziere. The actual curve we acquire this way is not too bad shapwise,
|
||||
* but (probably due to rounding errors) the resulting curve no longer
|
||||
* satisfies the necessary condition that for L2 > L1, t2 > t1, which
|
||||
* causes oscilation.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* These are the control points we use to calculate the curve coefficients
|
||||
* for bezier t(L); these are not needed directly, but are implied in the
|
||||
* calculations below.
|
||||
*
|
||||
* (p0 is 0,0, and p3 is 1,1)
|
||||
*/
|
||||
p1 = (18 * t_equalized[CBZ_T_SAMPLES/3] -
|
||||
9 * t_equalized[2*CBZ_T_SAMPLES/3] +
|
||||
2 << CBZ_T_Q) / 6;
|
||||
|
||||
p2 = (18 * t_equalized[2*CBZ_T_SAMPLES/3] -
|
||||
9 * t_equalized[CBZ_T_SAMPLES/3] -
|
||||
(5 << CBZ_T_Q)) / 6;
|
||||
#endif
|
||||
|
||||
b->Lc = (18 * t_equalized[CBZ_T_SAMPLES/3] -
|
||||
9 * t_equalized[2*CBZ_T_SAMPLES/3] +
|
||||
(2 << CBZ_T_Q)) >> 1;
|
||||
|
||||
b->Lb = (36 * t_equalized[2*CBZ_T_SAMPLES/3] -
|
||||
45 * t_equalized[CBZ_T_SAMPLES/3] -
|
||||
(9 << CBZ_T_Q)) >> 1;
|
||||
|
||||
b->La = ((27 * (t_equalized[CBZ_T_SAMPLES/3] -
|
||||
t_equalized[2*CBZ_T_SAMPLES/3]) +
|
||||
(7 << CBZ_T_Q)) >> 1) + CBZ_T_ONE;
|
||||
|
||||
g_debug ("t(1/3) %f, t(2/3) %f",
|
||||
(double)t_equalized[CBZ_T_SAMPLES/3]/(double)CBZ_T_ONE,
|
||||
(double)t_equalized[2*CBZ_T_SAMPLES/3]/(double)CBZ_T_ONE);
|
||||
|
||||
g_debug ("L -> t coefficients: %f, %f, %f",
|
||||
(double)b->La/(double)CBZ_T_ONE,
|
||||
(double)b->Lb/(double)CBZ_T_ONE,
|
||||
(double)b->Lc/(double)CBZ_T_ONE);
|
||||
|
||||
|
||||
/*
|
||||
* For debugging, you can load these values into a spreadsheet and graph
|
||||
* them to see how well the approximation matches the data
|
||||
*/
|
||||
for (i = 0; i < CBZ_T_SAMPLES; ++i)
|
||||
{
|
||||
g_print ("%f, %f, %f\n",
|
||||
(double)(i*CBZ_T_STEP)/(double)CBZ_T_ONE,
|
||||
(double)(t_equalized[i])/(double)CBZ_T_ONE,
|
||||
(double)(clutter_bezier_L2t(b,i*CBZ_T_STEP))/(double)CBZ_T_ONE);
|
||||
}
|
||||
#endif
|
||||
CLUTTER_NOTE (MISC, "length %f", b->length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves a control point at indx to location represented by knot
|
||||
* _clutter_bezier_adjust:
|
||||
* @b: A #ClutterBezier object
|
||||
* @knot: The new position of the control point
|
||||
@ @indx: The index of the control point you want to move.
|
||||
*
|
||||
* Moves a control point at index @indx to location represented by @knot
|
||||
*/
|
||||
void
|
||||
_clutter_bezier_adjust (ClutterBezier * b, ClutterKnot * knot, guint indx)
|
||||
_clutter_bezier_adjust (ClutterBezier *b,
|
||||
ClutterKnot *knot,
|
||||
guint indx)
|
||||
{
|
||||
guint x[4], y[4];
|
||||
gfloat x[4], y[4];
|
||||
|
||||
g_assert (indx < 4);
|
||||
|
||||
x[0] = b->dx;
|
||||
y[0] = b->dy;
|
||||
|
||||
x[1] = b->cx / 3 + x[0];
|
||||
y[1] = b->cy / 3 + y[0];
|
||||
x[0] = b->ax;
|
||||
y[0] = b->ay;
|
||||
|
||||
x[2] = b->bx / 3 + b->cx + x[1];
|
||||
y[2] = b->by / 3 + b->cy + y[1];
|
||||
x[1] = b->bx;
|
||||
y[1] = b->by;
|
||||
|
||||
x[3] = b->ax + x[0] + b->cx + b->bx;
|
||||
y[3] = b->ay + y[0] + b->cy + b->by;
|
||||
x[2] = b->cx;
|
||||
y[2] = b->cy;
|
||||
|
||||
x[3] = b->dx;
|
||||
y[3] = b->dy;
|
||||
|
||||
x[indx] = knot->x;
|
||||
y[indx] = knot->y;
|
||||
@ -417,7 +256,13 @@ _clutter_bezier_adjust (ClutterBezier * b, ClutterKnot * knot, guint indx)
|
||||
_clutter_bezier_init (b, x[0], y[0], x[1], y[1], x[2], y[2], x[3], y[3]);
|
||||
}
|
||||
|
||||
guint
|
||||
/*
|
||||
* _clutter_bezier_get_length:
|
||||
* @b: A #ClutterBezier
|
||||
*
|
||||
* Return value: Returns the length of the bezier
|
||||
*/
|
||||
gfloat
|
||||
_clutter_bezier_get_length (const ClutterBezier *b)
|
||||
{
|
||||
return b->length;
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Authored By Tomas Frydrych <tf@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006, 2007 OpenedHand
|
||||
* Copyright (C) 2013 Erick Pérez Castellanos <erick.red@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -29,36 +30,35 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* This is used in _clutter_bezier_advance to represent the full
|
||||
length of the bezier curve. Anything less than that represents a
|
||||
fraction of the length */
|
||||
#define CLUTTER_BEZIER_MAX_LENGTH (1 << 18)
|
||||
|
||||
typedef struct _ClutterBezier ClutterBezier;
|
||||
|
||||
ClutterBezier *_clutter_bezier_new ();
|
||||
ClutterBezier *_clutter_bezier_new ();
|
||||
|
||||
void _clutter_bezier_free (ClutterBezier * b);
|
||||
void _clutter_bezier_free (ClutterBezier *b);
|
||||
|
||||
ClutterBezier *_clutter_bezier_clone_and_move (const ClutterBezier *b,
|
||||
gint x,
|
||||
gint y);
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
|
||||
void _clutter_bezier_advance (const ClutterBezier *b,
|
||||
gint L,
|
||||
ClutterKnot *knot);
|
||||
void _clutter_bezier_advance (const ClutterBezier *b,
|
||||
gfloat L,
|
||||
ClutterKnot *knot);
|
||||
|
||||
void _clutter_bezier_init (ClutterBezier *b,
|
||||
gint x_0, gint y_0,
|
||||
gint x_1, gint y_1,
|
||||
gint x_2, gint y_2,
|
||||
gint x_3, gint y_3);
|
||||
void _clutter_bezier_init (ClutterBezier *b,
|
||||
gfloat x_0,
|
||||
gfloat y_0,
|
||||
gfloat x_1,
|
||||
gfloat y_1,
|
||||
gfloat x_2,
|
||||
gfloat y_2,
|
||||
gfloat x_3,
|
||||
gfloat y_3);
|
||||
|
||||
void _clutter_bezier_adjust (ClutterBezier *b,
|
||||
ClutterKnot *knot,
|
||||
guint indx);
|
||||
void _clutter_bezier_adjust (ClutterBezier *b,
|
||||
ClutterKnot *knot,
|
||||
guint indx);
|
||||
|
||||
guint _clutter_bezier_get_length (const ClutterBezier *b);
|
||||
gfloat _clutter_bezier_get_length (const ClutterBezier *b);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -1458,8 +1458,7 @@ clutter_path_get_position (ClutterPath *path,
|
||||
else
|
||||
{
|
||||
_clutter_bezier_advance (node->bezier,
|
||||
point_distance * CLUTTER_BEZIER_MAX_LENGTH
|
||||
/ node->length,
|
||||
(gfloat) point_distance / (gfloat) node->length,
|
||||
position);
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user