<commit_before>/*
 * Clutter.
 *
 * An OpenGL based 'interactive canvas' library.
 *
 * Authored By <NAME>  <<EMAIL>>
 *
 * 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.
 */

/**
 * SECTION:clutter-actor
 * @short_description: Base abstract class for all visual stage actors. 
 * 
 * #ClutterActor is a base abstract class for all visual elements. 
 */

#include "config.h"

#include "clutter-actor.h"
#include "clutter-group.h"
#include "clutter-main.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-debug.h"

#include <GL/gl.h>

G_DEFINE_ABSTRACT_TYPE (ClutterActor,
			clutter_actor,
			G_TYPE_INITIALLY_UNOWNED);

static guint32 __id = 0;


#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))

struct _ClutterActorPrivate
{
  ClutterActorBox coords;

  ClutterGeometry clip;
  guint has_clip : 1;

  gfloat rxang, ryang, rzang; /* Rotation foo. */
  gint rzx, rzy, rxy, rxz, ryx, ryz;
  gint z; /* to actor box ? */

  guint8 opacity;
  
  ClutterActor *parent_actor; /* This should always be a group */
  
  gchar *name;

  ClutterFixed   scale_x, scale_y;

  guint32 id; /* Unique ID */
};

enum
{
  PROP_0,
  PROP_X,
  PROP_Y,
  PROP_WIDTH,
  PROP_HEIGHT,
  PROP_CLIP,
  PROP_HAS_CLIP,
  PROP_OPACITY,
  PROP_NAME,
  PROP_VISIBLE
};

enum
{
  SHOW,
  HIDE,
  DESTROY,
  PARENT_SET,

  LAST_SIGNAL
};

static guint actor_signals[LAST_SIGNAL] = { 0, };

static gboolean
redraw_update_idle (gpointer data)
{
  ClutterMainContext *ctx = CLUTTER_CONTEXT();

  if (ctx->update_idle)
    {
      g_source_remove (ctx->update_idle);
      ctx->update_idle = 0;
    }

  clutter_redraw ();

  return FALSE;
}

static void
clutter_actor_real_show (ClutterActor *self)
{
  if (!CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      if (!CLUTTER_ACTOR_IS_REALIZED (self))
        clutter_actor_realize (self);

      CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);

      if (CLUTTER_ACTOR_IS_VISIBLE (self))
        clutter_actor_queue_redraw (self);
    }
}

/**
 * clutter_actor_show
 * @self: A #ClutterActor
 *
 * Flags a clutter actor to be displayed. An actor not shown will not 
 * appear on the display.
 **/
void
clutter_actor_show (ClutterActor *self)
{
  if (!CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      g_object_ref (self);
      
      g_signal_emit (self, actor_signals[SHOW], 0);
      g_object_notify (G_OBJECT (self), "visible");

      g_object_unref (self);
    }
}

/**
 * clutter_actor_show_all:
 * @self: a #ClutterActor
 *
 * Recursively show an actor, and any child actor if @self has
 * child actors.
 *
 * Since: 0.2
 */
void
clutter_actor_show_all (ClutterActor *self)
{
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));

  klass = CLUTTER_ACTOR_GET_CLASS (self);
  if (klass->show_all)
    klass->show_all (self);
}

void
clutter_actor_real_hide (ClutterActor *self)
{
  if (CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
      clutter_actor_queue_redraw (self);
    }
}

/**
 * clutter_actor_hide
 * @self: A #ClutterActor
 *
 * Flags a clutter actor to be hidden. An actor not shown will not 
 * appear on the display.
 **/
void
clutter_actor_hide (ClutterActor *self)
{
  if (CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      g_object_ref (self);

      g_signal_emit (self, actor_signals[HIDE], 0);
      g_object_notify (G_OBJECT (self), "visible");

      g_object_unref (self);
    }
}

/**
 * clutter_actor_hide_all:
 * @self: a #ClutterActor
 *
 * Recursively hides an actor, and any child actor if @self
 * has child actors.
 *
 * Since: 0.2
 */
void
clutter_actor_hide_all (ClutterActor *self)
{
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));

  klass = CLUTTER_ACTOR_GET_CLASS (self);
  if (klass->hide_all)
    klass->hide_all (self);
}

/**
 * clutter_actor_realize
 * @self: A #ClutterActor
 *
 * Creates any underlying graphics resources needed by the actor to be
 * displayed.  
 **/
void
clutter_actor_realize (ClutterActor *self)
{
  ClutterActorClass *klass;

  if (CLUTTER_ACTOR_IS_REALIZED (self))
    return;

  CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->realize)
    (klass->realize) (self);
}

/**
 * clutter_actor_unrealize
 * @self: A #ClutterActor
 *
 * Frees up any underlying graphics resources needed by the actor to be
 * displayed.  
 **/
void
clutter_actor_unrealize (ClutterActor *self)
{
  ClutterActorClass *klass;

  if (!CLUTTER_ACTOR_IS_REALIZED (self))
    return;

  CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->unrealize)
    (klass->unrealize) (self);
}

/**
 * clutter_actor_paint:
 * @self: A #ClutterActor
 *
 * Renders the actor to display.
 *
 * This function should not be called directly by applications instead 
 * #clutter_actor_queue_redraw should be used to queue paints. 
 **/
void
clutter_actor_paint (ClutterActor *self)
{
  ClutterActorPrivate *priv;
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));
  priv = self->priv;

  if (!CLUTTER_ACTOR_IS_REALIZED (self))
    {
      CLUTTER_NOTE (PAINT, "Attempting realize via paint()");
      clutter_actor_realize(self);

      if (!CLUTTER_ACTOR_IS_REALIZED (self))
	{
	  CLUTTER_NOTE (PAINT, "Attempt failed, aborting paint");
	  return;
	}
    }

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  glPushMatrix();

  glLoadName (clutter_actor_get_id (self));

  if (clutter_actor_get_parent (self) != NULL)
    {
      glTranslatef((float) (priv->coords.x1), 
		   (float) (priv->coords.y1), 
		   0.0);
    }

  if (self->priv->rzang)
    {
      glTranslatef (priv->rzx,
		    priv->rzy,
		    0.0);

      glRotatef (priv->rzang, 0.0f, 0.0f, 1.0f);

      glTranslatef (-1. * priv->rzx,
		    -1. * priv->rzy,
		     0.0);
    }

  if (self->priv->ryang)
    {
      glTranslatef (priv->ryx,
		    0.0,
		    (float) (priv->z) + priv->ryz);

      glRotatef (priv->ryang, 0.0f, 1.0f, 0.0f);

      glTranslatef ((float) - priv->ryx,
		    0.0,
		    (float) (-1. * priv->z) - priv->ryz);
    }

  if (self->priv->rxang)
    {
      glTranslatef (0.0,
		    (float) priv->rxy,
		    (float) (priv->z) + priv->rxz);

      glRotatef (priv->rxang, 1.0f, 0.0f, 0.0f);

      glTranslatef (0.0,
		    -1. * priv->rxy,
		    -1. * priv->z - priv->rxz);
    }

  if (self->priv->z)
    glTranslatef (0.0, 0.0, (float) priv->z);

  if (self->priv->scale_x != CFX_ONE ||
      self->priv->scale_y != CFX_ONE)
    {
      glScaled (CLUTTER_FIXED_TO_DOUBLE (priv->scale_x),
		CLUTTER_FIXED_TO_DOUBLE (priv->scale_y),
		1.0);
    }

  if (priv->has_clip)
    {
      ClutterGeometry *clip = &(priv->clip);

      glEnable (GL_STENCIL_TEST);

      glClearStencil (0.0f);
      glClear (GL_STENCIL_BUFFER_BIT);

      glStencilFunc (GL_NEVER, 0x1, 0x1);
      glStencilOp (GL_INCR, GL_INCR, GL_INCR);

      glColor3f (1.0f, 1.0f, 1.0f);

      glRecti (clip->x, 
	       clip->y,
	       clip->x + clip->width,
	       clip->y + clip->height);

      glStencilFunc (GL_EQUAL, 0x1, 0x1);
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
    }

  if (klass->paint)
    (klass->paint) (self);

  if (priv->has_clip)
    glDisable (GL_STENCIL_TEST);

  if (priv->scale_x != CFX_ONE || priv->scale_y != CFX_ONE)
    glScaled (1.0, 1.0, 1.0);

  glPopMatrix();
}

/**
 * clutter_actor_request_coords:
 * @self: A #ClutterActor
 * @box: A #ClutterActorBox with requested new co-ordinates.
 *
 * Requests new co-ordinates for the #ClutterActor ralative to any parent.
 *
 * This function should not be called directly by applications instead 
 * the various position/geometry methods should be used.
 **/
void
clutter_actor_request_coords (ClutterActor    *self,
			      ClutterActorBox *box)
{
  ClutterActorClass *klass;
  gboolean x_change, y_change, width_change, height_change;

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->request_coords)
    klass->request_coords (self, box);

  x_change     = (self->priv->coords.x1 != box->x1);
  y_change     = (self->priv->coords.y1 != box->y1);
  width_change = (self->priv->coords.x2 - self->priv->coords.x1 
		            != box->x2 - box->x1);
  height_change = (self->priv->coords.y2 - self->priv->coords.y1 
		            != box->y2 - box->y1);

  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");
    }
}

/**
 * clutter_actor_allocate_coords:
 * @self: A #ClutterActor
 * @box: A location to store the actors #ClutterActorBox co-ordinates
 *
 * Requests the allocated co-ordinates for the #ClutterActor relative 
 * to any parent.
 *
 * This function should not be called directly by applications instead 
 * the various position/geometry methods should be used.
 **/
void
clutter_actor_allocate_coords (ClutterActor    *self,
			       ClutterActorBox *box)
{
  ClutterActorClass *klass;

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  box->x1 = self->priv->coords.x1;
  box->y1 = self->priv->coords.y1;
  box->x2 = self->priv->coords.x2;
  box->y2 = self->priv->coords.y2;<commit_msg>Freeze notification queue when changing multiple properties.<commit_after>/*
 * Clutter.
 *
 * An OpenGL based 'interactive canvas' library.
 *
 * Authored By <NAME>  <<EMAIL>>
 *
 * 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.
 */

/**
 * SECTION:clutter-actor
 * @short_description: Base abstract class for all visual stage actors. 
 * 
 * #ClutterActor is a base abstract class for all visual elements. 
 */

#include "config.h"

#include "clutter-actor.h"
#include "clutter-group.h"
#include "clutter-main.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-debug.h"

#include <GL/gl.h>

G_DEFINE_ABSTRACT_TYPE (ClutterActor,
			clutter_actor,
			G_TYPE_INITIALLY_UNOWNED);

static guint32 __id = 0;


#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))

struct _ClutterActorPrivate
{
  ClutterActorBox coords;

  ClutterGeometry clip;
  guint has_clip : 1;

  gfloat rxang, ryang, rzang; /* Rotation foo. */
  gint rzx, rzy, rxy, rxz, ryx, ryz;
  gint z; /* to actor box ? */

  guint8 opacity;
  
  ClutterActor *parent_actor; /* This should always be a group */
  
  gchar *name;

  ClutterFixed   scale_x, scale_y;

  guint32 id; /* Unique ID */
};

enum
{
  PROP_0,
  PROP_X,
  PROP_Y,
  PROP_WIDTH,
  PROP_HEIGHT,
  PROP_CLIP,
  PROP_HAS_CLIP,
  PROP_OPACITY,
  PROP_NAME,
  PROP_VISIBLE
};

enum
{
  SHOW,
  HIDE,
  DESTROY,
  PARENT_SET,

  LAST_SIGNAL
};

static guint actor_signals[LAST_SIGNAL] = { 0, };

static gboolean
redraw_update_idle (gpointer data)
{
  ClutterMainContext *ctx = CLUTTER_CONTEXT();

  if (ctx->update_idle)
    {
      g_source_remove (ctx->update_idle);
      ctx->update_idle = 0;
    }

  clutter_redraw ();

  return FALSE;
}

static void
clutter_actor_real_show (ClutterActor *self)
{
  if (!CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      if (!CLUTTER_ACTOR_IS_REALIZED (self))
        clutter_actor_realize (self);

      CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);

      if (CLUTTER_ACTOR_IS_VISIBLE (self))
        clutter_actor_queue_redraw (self);
    }
}

/**
 * clutter_actor_show
 * @self: A #ClutterActor
 *
 * Flags a clutter actor to be displayed. An actor not shown will not 
 * appear on the display.
 **/
void
clutter_actor_show (ClutterActor *self)
{
  if (!CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      g_object_ref (self);
      
      g_signal_emit (self, actor_signals[SHOW], 0);
      g_object_notify (G_OBJECT (self), "visible");

      g_object_unref (self);
    }
}

/**
 * clutter_actor_show_all:
 * @self: a #ClutterActor
 *
 * Recursively show an actor, and any child actor if @self has
 * child actors.
 *
 * Since: 0.2
 */
void
clutter_actor_show_all (ClutterActor *self)
{
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));

  klass = CLUTTER_ACTOR_GET_CLASS (self);
  if (klass->show_all)
    klass->show_all (self);
}

void
clutter_actor_real_hide (ClutterActor *self)
{
  if (CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
      clutter_actor_queue_redraw (self);
    }
}

/**
 * clutter_actor_hide
 * @self: A #ClutterActor
 *
 * Flags a clutter actor to be hidden. An actor not shown will not 
 * appear on the display.
 **/
void
clutter_actor_hide (ClutterActor *self)
{
  if (CLUTTER_ACTOR_IS_VISIBLE (self))
    {
      g_object_ref (self);

      g_signal_emit (self, actor_signals[HIDE], 0);
      g_object_notify (G_OBJECT (self), "visible");

      g_object_unref (self);
    }
}

/**
 * clutter_actor_hide_all:
 * @self: a #ClutterActor
 *
 * Recursively hides an actor, and any child actor if @self
 * has child actors.
 *
 * Since: 0.2
 */
void
clutter_actor_hide_all (ClutterActor *self)
{
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));

  klass = CLUTTER_ACTOR_GET_CLASS (self);
  if (klass->hide_all)
    klass->hide_all (self);
}

/**
 * clutter_actor_realize
 * @self: A #ClutterActor
 *
 * Creates any underlying graphics resources needed by the actor to be
 * displayed.  
 **/
void
clutter_actor_realize (ClutterActor *self)
{
  ClutterActorClass *klass;

  if (CLUTTER_ACTOR_IS_REALIZED (self))
    return;

  CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->realize)
    (klass->realize) (self);
}

/**
 * clutter_actor_unrealize
 * @self: A #ClutterActor
 *
 * Frees up any underlying graphics resources needed by the actor to be
 * displayed.  
 **/
void
clutter_actor_unrealize (ClutterActor *self)
{
  ClutterActorClass *klass;

  if (!CLUTTER_ACTOR_IS_REALIZED (self))
    return;

  CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->unrealize)
    (klass->unrealize) (self);
}

/**
 * clutter_actor_paint:
 * @self: A #ClutterActor
 *
 * Renders the actor to display.
 *
 * This function should not be called directly by applications instead 
 * #clutter_actor_queue_redraw should be used to queue paints. 
 **/
void
clutter_actor_paint (ClutterActor *self)
{
  ClutterActorPrivate *priv;
  ClutterActorClass *klass;

  g_return_if_fail (CLUTTER_IS_ACTOR (self));
  priv = self->priv;

  if (!CLUTTER_ACTOR_IS_REALIZED (self))
    {
      CLUTTER_NOTE (PAINT, "Attempting realize via paint()");
      clutter_actor_realize(self);

      if (!CLUTTER_ACTOR_IS_REALIZED (self))
	{
	  CLUTTER_NOTE (PAINT, "Attempt failed, aborting paint");
	  return;
	}
    }

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  glPushMatrix();

  glLoadName (clutter_actor_get_id (self));

  if (clutter_actor_get_parent (self) != NULL)
    {
      glTranslatef((float) (priv->coords.x1), 
		   (float) (priv->coords.y1), 
		   0.0);
    }

  if (self->priv->rzang)
    {
      glTranslatef (priv->rzx,
		    priv->rzy,
		    0.0);

      glRotatef (priv->rzang, 0.0f, 0.0f, 1.0f);

      glTranslatef (-1. * priv->rzx,
		    -1. * priv->rzy,
		     0.0);
    }

  if (self->priv->ryang)
    {
      glTranslatef (priv->ryx,
		    0.0,
		    (float) (priv->z) + priv->ryz);

      glRotatef (priv->ryang, 0.0f, 1.0f, 0.0f);

      glTranslatef ((float) - priv->ryx,
		    0.0,
		    (float) (-1. * priv->z) - priv->ryz);
    }

  if (self->priv->rxang)
    {
      glTranslatef (0.0,
		    (float) priv->rxy,
		    (float) (priv->z) + priv->rxz);

      glRotatef (priv->rxang, 1.0f, 0.0f, 0.0f);

      glTranslatef (0.0,
		    -1. * priv->rxy,
		    -1. * priv->z - priv->rxz);
    }

  if (self->priv->z)
    glTranslatef (0.0, 0.0, (float) priv->z);

  if (self->priv->scale_x != CFX_ONE ||
      self->priv->scale_y != CFX_ONE)
    {
      glScaled (CLUTTER_FIXED_TO_DOUBLE (priv->scale_x),
		CLUTTER_FIXED_TO_DOUBLE (priv->scale_y),
		1.0);
    }

  if (priv->has_clip)
    {
      ClutterGeometry *clip = &(priv->clip);

      glEnable (GL_STENCIL_TEST);

      glClearStencil (0.0f);
      glClear (GL_STENCIL_BUFFER_BIT);

      glStencilFunc (GL_NEVER, 0x1, 0x1);
      glStencilOp (GL_INCR, GL_INCR, GL_INCR);

      glColor3f (1.0f, 1.0f, 1.0f);

      glRecti (clip->x, 
	       clip->y,
	       clip->x + clip->width,
	       clip->y + clip->height);

      glStencilFunc (GL_EQUAL, 0x1, 0x1);
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
    }

  if (klass->paint)
    (klass->paint) (self);

  if (priv->has_clip)
    glDisable (GL_STENCIL_TEST);

  if (priv->scale_x != CFX_ONE || priv->scale_y != CFX_ONE)
    glScaled (1.0, 1.0, 1.0);

  glPopMatrix();
}

/**
 * clutter_actor_request_coords:
 * @self: A #ClutterActor
 * @box: A #ClutterActorBox with requested new co-ordinates.
 *
 * Requests new co-ordinates for the #ClutterActor ralative to any parent.
 *
 * This function should not be called directly by applications instead 
 * the various position/geometry methods should be used.
 **/
void
clutter_actor_request_coords (ClutterActor    *self,
			      ClutterActorBox *box)
{
  ClutterActorClass *klass;
  gboolean x_change, y_change, width_change, height_change;

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  if (klass->request_coords)
    klass->request_coords (self, box);

  x_change     = (self->priv->coords.x1 != box->x1);
  y_change     = (self->priv->coords.y1 != box->y1);
  width_change = (self->priv->coords.x2 - self->priv->coords.x1 
		            != box->x2 - box->x1);
  height_change = (self->priv->coords.y2 - self->priv->coords.y1 
		            != box->y2 - box->y1);

  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);

      g_object_ref (self);
      g_object_freeze_notify (G_OBJECT (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");

      g_object_thaw_notify (G_OBJECT (self));
      g_object_unref (self);
    }
}

/**
 * clutter_actor_allocate_coords:
 * @self: A #ClutterActor
 * @box: A location to store the actors #ClutterActorBox co-ordinates
 *
 * Requests the allocated co-ordinates for the #ClutterActor relative 
 * to any parent.
 *
 * This function should not be called directly by applications instead 
 * the various position/geometry methods should be used.
 **/
void
clutter_actor_allocate_coords (ClutterActor    *self,
			       ClutterActorBox *box)
{
  ClutterActorClass *klass;

  klass = CLUTTER_ACTOR_GET_CLASS (self);

  box->x1 = self->priv->coords.x1;
  box->y1 = self->priv->coords.y1;
  box->x2 = self->priv->coords.x2;
  box->y2 = self->priv->coords.y2;
{'fraction_non_alphanumeric': 0.12422212721485915, 'fraction_numerical': 0.012445964562253574, 'mean_word_length': 3.2324085243264977, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 221, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7022217', 'n_tokens_mistral': 8273, 'n_tokens_neox': 7931, 'n_words': 1833}