2006-08-29 Matthew Allum <mallum@openedhand.com>
authorMatthew Allum <mallum@openedhand.com>
Tue, 29 Aug 2006 19:09:43 +0000 (19:09 +0000)
committerMatthew Allum <mallum@openedhand.com>
Tue, 29 Aug 2006 19:09:43 +0000 (19:09 +0000)
        * 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.

ChangeLog
clutter/Makefile.am
clutter/clutter-actor.c
clutter/clutter-actor.h
clutter/clutter-fixed.h [new file with mode: 0644]
clutter/clutter-group.c
clutter/clutter-stage.c
clutter/clutter-texture.c
examples/super-oh.c

index 510c18b..d89d0e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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),
index dc21a96..b88ff8e 100644 (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         \
index fadaac9..192ef1e 100644 (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;
@@ -957,6 +957,57 @@ clutter_actor_get_abs_position (ClutterActor *self,
 }
 
 /**
+ * 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
  *
@@ -1037,6 +1088,87 @@ clutter_actor_get_y (ClutterActor *self)
 }
 
 /**
+ * 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
  * @opacity: New opacity value for actor.
index 1fb2ff2..d4c3070 100644 (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
 
diff --git a/clutter/clutter-fixed.h b/clutter/clutter-fixed.h
new file mode 100644 (file)
index 0000000..3a1c5a9
--- /dev/null
@@ -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
index a230c9b..ce15a62 100644 (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);
index 984a9bf..952b18a 100644 (file)
@@ -501,6 +501,7 @@ clutter_stage_request_coords (ClutterActor    *self,
                 priv->xwin,
                 box->x1,
                 box->y1);
+
 }
 
 static void 
index e6bffe3..348e5c2 100644 (file)
@@ -241,8 +241,6 @@ texture_render_to_gl_quad (ClutterTexture *texture,
 
   priv = texture->priv;
 
-
-
   qwidth  = x2-x1;
   qheight = y2-y1;
 
index daebc17..955a86a 100644 (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));