mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
actor: Allow querying the paint volume
An actor has an implicit "paint volume", that is the volume in 3D space occupied when painting itself. The paint volume is defined as a cuboid with the origin placed at the top-left corner of the actor; the size of the cuboid is given by three vectors: width, height and depth. ClutterActor provides API to convert the paint volume into a 2D box in screen coordinates, to compute the on-screen area that an actor will occupy when painted. Actors can override the default implementation of the get_paint_volume() virtual function to provide a different volume.
This commit is contained in:
parent
27aebb5c9d
commit
94ce747f83
@ -312,6 +312,37 @@ typedef struct _AnchorCoord AnchorCoord;
|
|||||||
#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
|
#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterPaintVolume:
|
||||||
|
*
|
||||||
|
* <structname>ClutterPaintVolume</structname> is an opaque structure whose
|
||||||
|
* members cannot be directly accessed
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
struct _ClutterPaintVolume
|
||||||
|
{
|
||||||
|
ClutterActor *actor;
|
||||||
|
|
||||||
|
/* cuboid for the volume:
|
||||||
|
*
|
||||||
|
* 0: origin ┐
|
||||||
|
* 1: width │→ plane[0], Z value = 0
|
||||||
|
* 2: height ┘
|
||||||
|
*
|
||||||
|
* 3. depth → X = 0, Y = 0, Z = @actor:depth
|
||||||
|
*
|
||||||
|
* 4: anti-origin ┐
|
||||||
|
* 5: width │→ plane[1], Z value = @actor:depth
|
||||||
|
* 6: height ┘
|
||||||
|
*
|
||||||
|
* 7: depth → X = anti-origin.x, Y = anti-origin.y, Z = @actor:depth
|
||||||
|
*
|
||||||
|
* the first four elements are filled in by the PaintVolume setters
|
||||||
|
*/
|
||||||
|
ClutterVertex vertices[8];
|
||||||
|
};
|
||||||
|
|
||||||
/* Internal helper struct to represent a point that can be stored in
|
/* Internal helper struct to represent a point that can be stored in
|
||||||
either direct pixel coordinates or as a fraction of the actor's
|
either direct pixel coordinates or as a fraction of the actor's
|
||||||
size. It is used for the anchor point, scale center and rotation
|
size. It is used for the anchor point, scale center and rotation
|
||||||
@ -3223,6 +3254,19 @@ atk_implementor_iface_init (AtkImplementorIface *iface)
|
|||||||
iface->ref_accessible = _clutter_actor_ref_accessible;
|
iface->ref_accessible = _clutter_actor_ref_accessible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_actor_real_get_paint_volume (ClutterActor *self,
|
||||||
|
ClutterPaintVolume *volume)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
/* the default origin is set to { 0, 0, 0 } */
|
||||||
|
|
||||||
|
clutter_paint_volume_set_width (volume, priv->allocation.x2 - priv->allocation.x1);
|
||||||
|
clutter_paint_volume_set_height (volume, priv->allocation.y2 - priv->allocation.y1);
|
||||||
|
clutter_paint_volume_set_depth (volume, priv->z);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_actor_class_init (ClutterActorClass *klass)
|
clutter_actor_class_init (ClutterActorClass *klass)
|
||||||
{
|
{
|
||||||
@ -4633,6 +4677,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
klass->queue_relayout = clutter_actor_real_queue_relayout;
|
klass->queue_relayout = clutter_actor_real_queue_relayout;
|
||||||
klass->apply_transform = clutter_actor_real_apply_transform;
|
klass->apply_transform = clutter_actor_real_apply_transform;
|
||||||
klass->get_accessible = clutter_actor_real_get_accessible;
|
klass->get_accessible = clutter_actor_real_get_accessible;
|
||||||
|
klass->get_paint_volume = clutter_actor_real_get_paint_volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -11438,3 +11483,227 @@ clutter_actor_has_key_focus (ClutterActor *self)
|
|||||||
|
|
||||||
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self;
|
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
clutter_paint_volume_get_type (void)
|
||||||
|
{
|
||||||
|
static GType our_type = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (our_type == 0))
|
||||||
|
our_type =
|
||||||
|
g_boxed_type_register_static (I_("ClutterPaintVolume"),
|
||||||
|
(GBoxedCopyFunc) clutter_paint_volume_copy,
|
||||||
|
(GBoxedFreeFunc) clutter_paint_volume_free);
|
||||||
|
|
||||||
|
return our_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterPaintVolume *
|
||||||
|
_clutter_paint_volume_new (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterPaintVolume *pv;
|
||||||
|
|
||||||
|
pv = g_slice_new (ClutterPaintVolume);
|
||||||
|
pv->actor = (actor != NULL) ? g_object_ref (actor) : NULL;
|
||||||
|
|
||||||
|
memset (pv->vertices, 0, 8 * sizeof (ClutterVertex));
|
||||||
|
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterPaintVolume *
|
||||||
|
clutter_paint_volume_copy (const ClutterPaintVolume *pv)
|
||||||
|
{
|
||||||
|
ClutterPaintVolume *copy;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (pv == NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
copy = g_slice_dup (ClutterPaintVolume, pv);
|
||||||
|
copy->actor = g_object_ref (pv->actor);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_free (ClutterPaintVolume *pv)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (pv == NULL))
|
||||||
|
{
|
||||||
|
if (pv->actor != NULL)
|
||||||
|
g_object_unref (pv->actor);
|
||||||
|
|
||||||
|
g_slice_free (ClutterPaintVolume, pv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
|
||||||
|
const ClutterVertex *origin)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
|
||||||
|
pv->vertices[0] = *origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_get_origin (const ClutterPaintVolume *pv,
|
||||||
|
ClutterVertex *vertex)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
g_return_if_fail (vertex != NULL);
|
||||||
|
|
||||||
|
*vertex = pv->vertices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_set_width (ClutterPaintVolume *pv,
|
||||||
|
gfloat width)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
g_return_if_fail (width >= 0.0f);
|
||||||
|
|
||||||
|
pv->vertices[1].x = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfloat
|
||||||
|
clutter_paint_volume_get_width (const ClutterPaintVolume *pv)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (pv != NULL, 0.0);
|
||||||
|
|
||||||
|
return pv->vertices[1].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_set_height (ClutterPaintVolume *pv,
|
||||||
|
gfloat height)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
g_return_if_fail (height >= 0.0f);
|
||||||
|
|
||||||
|
pv->vertices[2].y = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfloat
|
||||||
|
clutter_paint_volume_get_height (const ClutterPaintVolume *pv)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (pv != NULL, 0.0);
|
||||||
|
|
||||||
|
return pv->vertices[2].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_paint_volume_set_depth (ClutterPaintVolume *pv,
|
||||||
|
gfloat depth)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
|
||||||
|
pv->vertices[3].z = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfloat
|
||||||
|
clutter_paint_volume_get_depth (const ClutterPaintVolume *pv)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (pv != NULL, 0.0);
|
||||||
|
|
||||||
|
return pv->vertices[3].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_paint_volume_get_box (ClutterPaintVolume *pv,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
ClutterVertex screen_v[8];
|
||||||
|
gfloat x_min, y_min, x_max, y_max;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_if_fail (pv != NULL);
|
||||||
|
g_return_if_fail (box != NULL);
|
||||||
|
|
||||||
|
if (pv->actor == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("Paint volume created without a reference actor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* anti-origin */
|
||||||
|
pv->vertices[4].x = pv->vertices[1].x;
|
||||||
|
pv->vertices[4].y = pv->vertices[2].y;
|
||||||
|
pv->vertices[4].z = 0.0f;
|
||||||
|
|
||||||
|
if (pv->vertices[3].z < 0.00001 || pv->vertices[3].z > 0.00001)
|
||||||
|
{
|
||||||
|
pv->vertices[5].x = pv->vertices[1].x;
|
||||||
|
pv->vertices[5].y = pv->vertices[0].y;
|
||||||
|
pv->vertices[5].z = pv->vertices[3].z;
|
||||||
|
|
||||||
|
pv->vertices[6].x = pv->vertices[0].x;
|
||||||
|
pv->vertices[6].y = pv->vertices[2].y;
|
||||||
|
pv->vertices[6].z = pv->vertices[3].z;
|
||||||
|
|
||||||
|
pv->vertices[7].x = pv->vertices[1].x;
|
||||||
|
pv->vertices[7].y = pv->vertices[2].y;
|
||||||
|
pv->vertices[7].z = pv->vertices[3].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_clutter_actor_fully_transform_vertices (pv->actor,
|
||||||
|
pv->vertices,
|
||||||
|
screen_v,
|
||||||
|
G_N_ELEMENTS (screen_v)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
box->x1 = box->y1 = box->x2 = box->y2 = 0.0f;
|
||||||
|
|
||||||
|
x_min = y_min = G_MAXFLOAT;
|
||||||
|
x_max = y_max = -G_MAXFLOAT;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (screen_v); i++)
|
||||||
|
{
|
||||||
|
if (screen_v[i].x < x_min)
|
||||||
|
x_min = screen_v[i].x;
|
||||||
|
|
||||||
|
if (screen_v[i].x > x_max)
|
||||||
|
x_max = screen_v[i].x;
|
||||||
|
|
||||||
|
if (screen_v[i].y < y_min)
|
||||||
|
y_min = screen_v[i].y;
|
||||||
|
|
||||||
|
if (screen_v[i].y > y_max)
|
||||||
|
y_max = screen_v[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
box->x1 = x_min;
|
||||||
|
box->y1 = y_min;
|
||||||
|
box->x2 = x_max;
|
||||||
|
box->y2 = y_max;
|
||||||
|
clutter_actor_box_clamp_to_pixel (box);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterPaintVolume *
|
||||||
|
clutter_actor_get_paint_volume (ClutterActor *self)
|
||||||
|
{
|
||||||
|
ClutterPaintVolume *pv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||||
|
|
||||||
|
pv = _clutter_paint_volume_new (self);
|
||||||
|
CLUTTER_ACTOR_GET_CLASS (self)->get_paint_volume (self, pv);
|
||||||
|
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_actor_get_paint_box (ClutterActor *self,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
ClutterPaintVolume *pv;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||||
|
g_return_if_fail (box != NULL);
|
||||||
|
|
||||||
|
pv = clutter_actor_get_paint_volume (self);
|
||||||
|
|
||||||
|
_clutter_paint_volume_get_box (pv, box);
|
||||||
|
|
||||||
|
clutter_paint_volume_free (pv);
|
||||||
|
}
|
||||||
|
@ -306,9 +306,12 @@ struct _ClutterActorClass
|
|||||||
/* accessibility support */
|
/* accessibility support */
|
||||||
AtkObject * (* get_accessible) (ClutterActor *actor);
|
AtkObject * (* get_accessible) (ClutterActor *actor);
|
||||||
|
|
||||||
|
void (* get_paint_volume) (ClutterActor *actor,
|
||||||
|
ClutterPaintVolume *volume);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding for future expansion */
|
/* padding for future expansion */
|
||||||
gpointer _padding_dummy[30];
|
gpointer _padding_dummy[29];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
||||||
@ -586,6 +589,9 @@ gboolean clutter_actor_has_allocation (ClutterActor *sel
|
|||||||
AtkObject * clutter_actor_get_accessible (ClutterActor *self);
|
AtkObject * clutter_actor_get_accessible (ClutterActor *self);
|
||||||
|
|
||||||
gboolean clutter_actor_has_key_focus (ClutterActor *self);
|
gboolean clutter_actor_has_key_focus (ClutterActor *self);
|
||||||
|
ClutterPaintVolume *clutter_actor_get_paint_volume (ClutterActor *self);
|
||||||
|
void clutter_actor_get_paint_box (ClutterActor *self,
|
||||||
|
ClutterActorBox *box);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -409,6 +409,10 @@ gpointer _clutter_event_get_platform_data (const ClutterEvent *event);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ClutterPaintVolume *_clutter_paint_volume_new (ClutterActor *actor);
|
||||||
|
void _clutter_paint_volume_get_box (ClutterPaintVolume *pv,
|
||||||
|
ClutterActorBox *box);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
||||||
|
@ -33,10 +33,11 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_ACTOR_BOX (clutter_actor_box_get_type ())
|
#define CLUTTER_TYPE_ACTOR_BOX (clutter_actor_box_get_type ())
|
||||||
#define CLUTTER_TYPE_GEOMETRY (clutter_geometry_get_type ())
|
#define CLUTTER_TYPE_GEOMETRY (clutter_geometry_get_type ())
|
||||||
#define CLUTTER_TYPE_KNOT (clutter_knot_get_type ())
|
#define CLUTTER_TYPE_KNOT (clutter_knot_get_type ())
|
||||||
#define CLUTTER_TYPE_VERTEX (clutter_vertex_get_type ())
|
#define CLUTTER_TYPE_PAINT_VOLUME (clutter_paint_volume_get_type ())
|
||||||
|
#define CLUTTER_TYPE_VERTEX (clutter_vertex_get_type ())
|
||||||
|
|
||||||
/* Forward delarations to avoid header catch 22's */
|
/* Forward delarations to avoid header catch 22's */
|
||||||
typedef struct _ClutterActor ClutterActor;
|
typedef struct _ClutterActor ClutterActor;
|
||||||
@ -90,6 +91,7 @@ typedef struct _ClutterActorBox ClutterActorBox;
|
|||||||
typedef struct _ClutterGeometry ClutterGeometry;
|
typedef struct _ClutterGeometry ClutterGeometry;
|
||||||
typedef struct _ClutterKnot ClutterKnot;
|
typedef struct _ClutterKnot ClutterKnot;
|
||||||
typedef struct _ClutterVertex ClutterVertex;
|
typedef struct _ClutterVertex ClutterVertex;
|
||||||
|
typedef struct _ClutterPaintVolume ClutterPaintVolume;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterVertex:
|
* ClutterVertex:
|
||||||
@ -433,6 +435,25 @@ typedef enum {
|
|||||||
CLUTTER_FRAGMENT_SHADER
|
CLUTTER_FRAGMENT_SHADER
|
||||||
} ClutterShaderType;
|
} ClutterShaderType;
|
||||||
|
|
||||||
|
GType clutter_paint_volume_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ClutterPaintVolume *clutter_paint_volume_copy (const ClutterPaintVolume *pv);
|
||||||
|
void clutter_paint_volume_free (ClutterPaintVolume *pv);
|
||||||
|
|
||||||
|
void clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
|
||||||
|
const ClutterVertex *origin);
|
||||||
|
void clutter_paint_volume_get_origin (const ClutterPaintVolume *pv,
|
||||||
|
ClutterVertex *vertex);
|
||||||
|
void clutter_paint_volume_set_width (ClutterPaintVolume *pv,
|
||||||
|
gfloat width);
|
||||||
|
gfloat clutter_paint_volume_get_width (const ClutterPaintVolume *pv);
|
||||||
|
void clutter_paint_volume_set_height (ClutterPaintVolume *pv,
|
||||||
|
gfloat height);
|
||||||
|
gfloat clutter_paint_volume_get_height (const ClutterPaintVolume *pv);
|
||||||
|
void clutter_paint_volume_set_depth (ClutterPaintVolume *pv,
|
||||||
|
gfloat depth);
|
||||||
|
gfloat clutter_paint_volume_get_depth (const ClutterPaintVolume *pv);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_TYPES_H__ */
|
#endif /* __CLUTTER_TYPES_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user