2006-08-29 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-fixed.h:
        Add basic fixed point utility defines and type.

        * clutter/Makefile.am:
        * clutter/clutter-actor.c:
        * clutter/clutter-actor.h:
        * clutter/clutter-group.c:
        * clutter/clutter-stage.c:
        * examples/super-oh.c: (main):
        Add scale API and functionality.
        Rework group sizing. Now group size requests have no effect
        but can be scaled.
This commit is contained in:
Matthew Allum 2006-08-29 19:09:43 +00:00
parent 9f81571737
commit 3afb377c3e
9 changed files with 337 additions and 126 deletions

View File

@ -1,3 +1,18 @@
2006-08-29 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-fixed.h:
Add basic fixed point utility defines and type.
* clutter/Makefile.am:
* clutter/clutter-actor.c:
* clutter/clutter-actor.h:
* clutter/clutter-group.c:
* clutter/clutter-stage.c:
* examples/super-oh.c: (main):
Add scale API and functionality.
Rework group sizing. Now group size requests have no effect
but can be scaled.
2006-08-29 Jorn Baayen <jorn@openedhand.com>
* clutter/clutter-behaviour.c: (_clutter_behaviour_finalize),

View File

@ -8,6 +8,7 @@ BUILT_SOURCES = $(MARSHALFILES) $(ENUMFILES)
source_h = \
$(srcdir)/clutter-keysyms.h \
$(srcdir)/clutter-util.h \
$(srcdir)/clutter-fixed.h \
$(srcdir)/clutter-media.h \
$(srcdir)/clutter-event.h \
$(srcdir)/clutter-color.h \

View File

@ -64,7 +64,9 @@ struct _ClutterActorPrivate
ClutterActor *parent_actor; /* This should always be a group */
gchar *name;
ClutterFixed scale_x, scale_y;
guint32 id; /* Unique ID */
};
@ -253,37 +255,10 @@ clutter_actor_paint (ClutterActor *self)
klass = CLUTTER_ACTOR_GET_CLASS (self);
#if 0
if (self->priv->has_clip)
{
ClutterGeometry *clip = &(self->priv->clip);
gint absx, absy;
ClutterActor *stage = clutter_stage_get_default ();
clutter_actor_get_abs_position (self, &absx, &absy);
CLUTTER_DBG("clip +%i+%i, %ix%i\n",
absx + clip->x,
clutter_actor_get_height (stage)
- (absy + clip->y) - clip->height,
clip->width,
clip->height);
glEnable (GL_SCISSOR_TEST);
glScissor (absx + clip->x,
clutter_actor_get_height (stage)
- (absy + clip->y) - clip->height,
clip->width,
clip->height);
}
#endif
glPushMatrix();
glLoadName (clutter_actor_get_id (self));
/* FIXME: Less clunky ? */
if (self->priv->rzang)
{
@ -327,6 +302,13 @@ clutter_actor_paint (ClutterActor *self)
if (self->priv->z)
glTranslatef ( 0.0, 0.0, (float)self->priv->z);
if (self->priv->scale_x != CFX_ONE || self->priv->scale_y != CFX_ONE)
{
glScaled (CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_x),
CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_y),
1.0);
}
if (self->priv->has_clip)
{
ClutterGeometry *clip = &(self->priv->clip);
@ -381,7 +363,6 @@ clutter_actor_request_coords (ClutterActor *self,
klass = CLUTTER_ACTOR_GET_CLASS (self);
/* FIXME: Kludgy see allocate co-ords */
if (klass->request_coords)
klass->request_coords (self, box);
@ -392,27 +373,28 @@ clutter_actor_request_coords (ClutterActor *self,
height_change = (self->priv->coords.y2 - self->priv->coords.y1
!= box->y2 - box->y1);
self->priv->coords.x1 = box->x1;
self->priv->coords.y1 = box->y1;
self->priv->coords.x2 = box->x2;
self->priv->coords.y2 = box->y2;
if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self);
/* FIXME: Below really needed ? If so should add to other _set calls.
*/
if (x_change)
g_object_notify (G_OBJECT (self), "x");
if (y_change)
g_object_notify (G_OBJECT (self), "y");
if (width_change)
g_object_notify (G_OBJECT (self), "width");
if (height_change)
g_object_notify (G_OBJECT (self), "height");
if (x_change || y_change || width_change || height_change)
{
self->priv->coords.x1 = box->x1;
self->priv->coords.y1 = box->y1;
self->priv->coords.x2 = box->x2;
self->priv->coords.y2 = box->y2;
if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self);
if (x_change)
g_object_notify (G_OBJECT (self), "x");
if (y_change)
g_object_notify (G_OBJECT (self), "y");
if (width_change)
g_object_notify (G_OBJECT (self), "width");
if (height_change)
g_object_notify (G_OBJECT (self), "height");
}
}
/**
@ -740,6 +722,8 @@ clutter_actor_init (ClutterActor *self)
self->priv->has_clip = FALSE;
self->priv->opacity = 0xff;
self->priv->id = __id++;
self->priv->scale_x = CFX_ONE;
self->priv->scale_y = CFX_ONE;
clutter_actor_set_position (self, 0, 0);
clutter_actor_set_size (self, 0, 0);
@ -849,10 +833,10 @@ clutter_actor_get_geometry (ClutterActor *self,
*/
void
clutter_actor_get_coords (ClutterActor *self,
gint *x1,
gint *y1,
gint *x2,
gint *y2)
gint *x1,
gint *y1,
gint *x2,
gint *y2)
{
ClutterActorBox box;
@ -877,8 +861,8 @@ clutter_actor_get_coords (ClutterActor *self,
*/
void
clutter_actor_set_position (ClutterActor *self,
gint x,
gint y)
gint x,
gint y)
{
ClutterActorBox box;
@ -906,8 +890,8 @@ clutter_actor_set_position (ClutterActor *self,
*/
void
clutter_actor_set_size (ClutterActor *self,
gint width,
gint height)
gint width,
gint height)
{
ClutterActorBox box;
@ -932,8 +916,8 @@ clutter_actor_set_size (ClutterActor *self,
*/
void
clutter_actor_get_abs_position (ClutterActor *self,
gint *x,
gint *y)
gint *x,
gint *y)
{
ClutterActorBox box;
ClutterActor *parent;
@ -946,8 +930,24 @@ clutter_actor_get_abs_position (ClutterActor *self,
parent = self->priv->parent_actor;
/* FIXME: must be nicer way to get 0,0 for stage ? */
if (parent && !CLUTTER_IS_STAGE (parent))
clutter_actor_get_abs_position (parent, &px, &py);
if (parent)
{
ClutterFixed parent_scale_x, parent_scale_y, fx, fy;
clutter_actor_get_scalex(parent, &parent_scale_x, &parent_scale_y);
if (parent_scale_x != CFX_ONE || parent_scale_y != CFX_ONE)
{
fx = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(box.x1),parent_scale_x);
fy = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(box.y1),parent_scale_y);
box.x1 = CLUTTER_FIXED_INT(fx);
box.y1 = CLUTTER_FIXED_INT(fy);
}
if (!CLUTTER_IS_STAGE (parent))
clutter_actor_get_abs_position (parent, &px, &py);
}
if (x)
*x = px + box.x1;
@ -956,6 +956,57 @@ clutter_actor_get_abs_position (ClutterActor *self,
*y = py + box.y1;
}
/**
* clutter_actor_get_abs_size
* @self: A #ClutterActor
* @x: Location to store width if non NULL.
* @y: Location to store height if non NULL.
*
* Gets the absolute size of an actor taking into account
* an scaling factors
*/
void
clutter_actor_get_abs_size (ClutterActor *self,
guint *width,
guint *height)
{
ClutterActorBox box;
ClutterActor *parent;
clutter_actor_allocate_coords (self, &box);
if (width)
*width = box.x2 - box.x1;
if (height)
*height = box.y2 - box.y1;
parent = self;
do
{
if (parent->priv->scale_x != CFX_ONE || parent->priv->scale_y != CFX_ONE)
{
ClutterFixed fx, fy;
if (width)
{
fx = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(*width),
parent->priv->scale_x);
*width = CLUTTER_FIXED_INT(fx);
}
if (height)
{
fy = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(*height),
parent->priv->scale_x);
*height = CLUTTER_FIXED_INT(fy);
}
}
}
while ((parent = clutter_actor_get_parent(parent)) != NULL);
}
/**
* clutter_actor_get_width
* @self: A #ClutterActor
@ -1036,6 +1087,87 @@ clutter_actor_get_y (ClutterActor *self)
return box.y1;
}
/**
* clutter_actor_set_scalex:
* @self: A #ClutterActor
* @scale_x: #ClutterFixed factor to scale actor by horizontally.
* @scale_y: #ClutterFixed factor to scale actor by vertically.
*
* Scale an actor.
*/
void
clutter_actor_set_scalex (ClutterActor *self,
ClutterFixed scale_x,
ClutterFixed scale_y)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
self->priv->scale_x = scale_x;
self->priv->scale_y = scale_y;
if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self);
}
/**
* clutter_actor_set_scale:
* @self: A #ClutterActor
* @scale_x: double
* @scale_y: double
*/
void
clutter_actor_set_scale (ClutterActor *self,
double scale_x,
double scale_y)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_actor_set_scalex (self,
CLUTTER_FLOAT_TO_FIXED (scale_x),
CLUTTER_FLOAT_TO_FIXED (scale_y));
}
/**
* clutter_actor_get_scalex
* @self: A #ClutterActor
* @scale_x: FIXME
* @scale_y: FIXME
*
* FIXME
*/
void
clutter_actor_get_scalex (ClutterActor *self,
ClutterFixed *scale_x,
ClutterFixed *scale_y)
{
if (scale_x)
*scale_x = self->priv->scale_x;
if (scale_y)
*scale_y = self->priv->scale_y;
}
/**
* clutter_actor_get_scale
* @self: A #ClutterActor
* @scale_x: FIXME
* @scale_y: FIXME
*
* FIXME
*/
void
clutter_actor_get_scale (ClutterActor *self,
double *scale_x,
double *scale_y)
{
if (scale_x)
*scale_x = CLUTTER_FIXED_TO_FLOAT(self->priv->scale_x);
if (scale_y)
*scale_y = CLUTTER_FIXED_TO_FLOAT(self->priv->scale_y);
}
/**
* clutter_actor_set_opacity:
* @self: A #ClutterActor

View File

@ -30,6 +30,8 @@
#include <glib-object.h>
#include "clutter-fixed.h"
G_BEGIN_DECLS
#define CLUTTER_TYPE_GEOMETRY (clutter_geometry_get_type ())
@ -66,7 +68,11 @@ typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data);
#define CLUTTER_CALLBACK(f) ((ClutterCallback) (f))
struct _ClutterGeometry
{
{
/* FIXME:
* It is likely gonna save a load of pain if we make
* x,y unsigned...
*/
gint x;
gint y;
guint width;
@ -206,6 +212,30 @@ void clutter_actor_set_depth (ClutterActor *sel
gint depth);
gint clutter_actor_get_depth (ClutterActor *self);
void
clutter_actor_set_scalex (ClutterActor *self,
ClutterFixed scale_x,
ClutterFixed scale_y);
void
clutter_actor_set_scale (ClutterActor *self,
double scale_x,
double scale_y);
void
clutter_actor_get_scalex (ClutterActor *self,
ClutterFixed *scale_x,
ClutterFixed *scale_y);
void
clutter_actor_get_scale (ClutterActor *self,
double *scale_x,
double *scale_y);
void
clutter_actor_get_abs_size (ClutterActor *self,
guint *width,
guint *height);
G_END_DECLS

66
clutter/clutter-fixed.h Normal file
View File

@ -0,0 +1,66 @@
/*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _HAVE_CLUTTER_FIXED_H
#define _HAVE_CLUTTER_FIXED_H
#include <glib.h>
G_BEGIN_DECLS
typedef gint32 ClutterFixed;
#define CFX_Q 16 /* Decimal part size in bits */
#define CFX_ONE (1 << CFX_Q) /* 1 */
#define CFX_MAX 0x7fffffff
#define CFX_MIN 0x80000000
#define CLUTTER_FIXED_TO_FLOAT(x) ((float)((x)/65536.0))
#define CLUTTER_FIXED_TO_DOUBLE(x) ((double)((x)/65536.0))
#define CLUTTER_FLOAT_TO_FIXED(x) \
( (ABS(x) > 32767.0) ? \
(((x)/(x))*0x7fffffff) \
: ((long)((x) * 65536.0 + ((x) < 0 ? -0.5 : 0.5))) )
#define CLUTTER_INT_TO_FIXED(x) ((x) << CFX_Q)
#define CLUTTER_FIXED_INT(x) ((x) >> CFX_Q)
#define CLUTTER_FIXED_FRACTION(x) ((x) & ((1 << CFX_Q) - 1))
#define CLUTTER_FIXED_FLOOR(x) \
(((x) >= 0) ? ((x) >> CFX_Q) : ~((~(x)) >> CFX_Q))
#define CLUTTER_FIXED_CEIL(x) CLUTTER_FIXED_FLOOR(x + 0xffff)
#define CLUTTER_FIXED_MUL(x,y) ((x) >> 8) * ((y) >> 8)
#define CLUTTER_FIXED_DIV(x,y) ((((x) << 8)/(y)) << 8)
G_END_DECLS
#endif

View File

@ -99,60 +99,15 @@ static void
clutter_group_request_coords (ClutterActor *self,
ClutterActorBox *box)
{
ClutterGroup *group = CLUTTER_GROUP(self);
guint cwidth, cheight, width ,height;
ClutterActorBox cbox;
clutter_actor_allocate_coords (self, &cbox);
cwidth = cbox.x2 - cbox.x1;
cheight = cbox.y2 - cbox.y1;
/* g_print("cbox x2: %i x1 %i\n", cbox.x2, cbox.x1); */
width = box->x2 - box->x1;
height = box->y2 - box->y1;
/* FIXME: below needs work */
if (cwidth != width || cheight != height)
{
GList *child_item;
for (child_item = group->priv->children;
child_item != NULL;
child_item = child_item->next)
{
ClutterActor *child = child_item->data;
ClutterActorBox tbox;
gint nx, ny;
gint twidth, theight, nwidth, nheight;
g_assert (child != NULL);
clutter_actor_allocate_coords (child, &tbox);
twidth = tbox.x2 - tbox.x1;
theight = tbox.y2 - tbox.y1;
/* g_print("getting ps %ix%i\n", tbox.x1, tbox.y1); */
nwidth = ( width * twidth ) / cwidth;
nheight = ( height * theight ) / cheight;
nx = ( nwidth * tbox.x1 ) / twidth ;
/* g_print("n: %i t %i x1: %i\n", nwidth, twidth, tbox.x1); */
ny = ( nheight * tbox.y1 ) / theight;
/* g_print("n: %i t %i x1: %i\n", nheight, theight, tbox.y1); */
clutter_actor_set_position (child, nx, ny);
clutter_actor_set_size (child, nwidth, height);
/* g_print("size to +%i+%x %ix%i\n", nx, ny, nwidth, nheight); */
}
}
/* Sizing requests fail, use scale() instead */
box->x1 = cbox.x1;
box->y1 = cbox.y1;
box->x2 = cbox.x2;
box->y2 = cbox.y2;
}
static void
@ -172,19 +127,15 @@ clutter_group_allocate_coords (ClutterActor *self,
{
ClutterActor *child = CLUTTER_ACTOR(child_item->data);
/* if (CLUTTER_ACTOR_IS_VISIBLE (child)) */
if (CLUTTER_ACTOR_IS_VISIBLE (child))
{
ClutterActorBox cbox;
clutter_actor_allocate_coords (child, &cbox);
/*
if (box->x1 == 0 || cbox.x1 < box->x1)
box->x1 = cbox.x1;
if (box->y1 == 0 || cbox.y1 < box->y1)
box->y1 = cbox.y1;
*/
/* Ignore any children with offscreen ( negaive )
* positions
*/
if (box->x2 == 0 || cbox.x2 > box->x2)
box->x2 = cbox.x2;
@ -374,6 +325,8 @@ clutter_group_add (ClutterGroup *self,
ClutterActor *actor)
{
ClutterActor *parent;
/* FIXME: add() needs to be somehow overidden */
g_return_if_fail (CLUTTER_IS_GROUP (self));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
@ -397,6 +350,8 @@ clutter_group_add (ClutterGroup *self,
clutter_group_sort_depth_order (self);
/* If were scaled, we scale the actor too */
g_signal_emit (self, group_signals[ADD], 0, actor);
g_object_unref (actor);

View File

@ -501,6 +501,7 @@ clutter_stage_request_coords (ClutterActor *self,
priv->xwin,
box->x1,
box->y1);
}
static void

View File

@ -241,8 +241,6 @@ texture_render_to_gl_quad (ClutterTexture *texture,
priv = texture->priv;
qwidth = x2-x1;
qheight = y2-y1;

View File

@ -167,9 +167,9 @@ main (int argc, char *argv[])
/* Create a texture from pixbuf, then clone in to same resources */
if (i == 0)
oh->hand[i] = clutter_texture_new_from_pixbuf (pixbuf);
else
oh->hand[i] = clutter_clone_texture_new (CLUTTER_TEXTURE(oh->hand[0]));
oh->hand[i] = clutter_texture_new_from_pixbuf (pixbuf);
else
oh->hand[i] = clutter_clone_texture_new (CLUTTER_TEXTURE(oh->hand[0]));
/* Place around a circle */
w = clutter_actor_get_width (oh->hand[0]);
@ -186,6 +186,19 @@ main (int argc, char *argv[])
clutter_group_add (CLUTTER_GROUP (oh->group), oh->hand[i]);
}
clutter_actor_set_scale (oh->group, .1, 0.1);
#if 0
{
guint w, h;
clutter_actor_get_abs_size (CLUTTER_ACTOR(oh->hand[0]), &w, &h);
g_print ("%ix%i\n", w, h);
g_print ("%ix%i\n",
clutter_actor_get_width(oh->hand[0]),
clutter_actor_get_height(oh->hand[0]));
}
#endif
/* Add the group to the stage */
clutter_group_add (CLUTTER_GROUP (stage), CLUTTER_ACTOR(oh->group));