diff --git a/ChangeLog b/ChangeLog index e7b437367..e2d13a809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2008-02-20 Emmanuele Bassi + + * clutter/clutter-actor.h: + * clutter/clutter-actor.c: + (clutter_actor_get_abs_opacity): Add function that does what + get_opacity() does now... + + (clutter_actor_get_opacity): ... and make get_opacity() do what + it's supposed to be doing. The original get_opacity() returned + a composited value, and there's no way to actually extract the + real opacity value set with set_opacity(). + + * clutter/clutter-clone-texture.c: + * clutter/clutter-rectangle.c: + * clutter/clutter-texture.c: Update to use get_abs_opacity(). + + * clutter/clutter-entry.c: + * clutter/clutter-label.c: Ditto. Also, never change the stored + alpha value. (#804) + + * tests/Makefile.am: + * tests/test-opacity.c: Test suite for the get_opacity() and + get_abs_opacity() API, and correct opacity handling. + + * README: Add note about the change in get_opacity(). + 2008-02-19 Chris Lord * clutter/clutter-model.c: (clutter_model_resort): diff --git a/README b/README index 9303e473f..70e92575f 100644 --- a/README +++ b/README @@ -140,7 +140,7 @@ RELEASE NOTES Relevant information for developers with existing Clutter applications wanting to port to newer releases (See NEWS for general new feature info). -Release Notes for Clutter 0.6.0 +Release Notes for Clutter 0.6 ------------------------------- * Now that every actor has events, the class signal handlers have been @@ -229,6 +229,17 @@ Release Notes for Clutter 0.6.0 clutter_entry_set_cursor_position() and clutter_entry_get_cursor_position() respectively. +* The behaviour of clutter_actor_get_opacity() has been slightly changed; + instead of returning the composited opacity of the entire parents chain + of an actor, clutter_actor_get_opacity() does what you mean, and returns + the opacity set with clutter_actor_set_opacity(). The composited + opacity value is now returned by clutter_actor_get_abs_opacity(). + +* Until 0.6.0, clutter_label_get_color() would have returned a ClutterColor + with the alpha component equal to the composited opacity of the label. + Now, clutter_label_get_color() returns a copy of the exact color set + with clutter_label_set_color(). + Release Notes for Clutter 0.4.0 ------------------------------- diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index fe4e837e5..95e2b9885 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -3345,25 +3345,61 @@ clutter_actor_set_opacity (ClutterActor *self, } /** - * clutter_actor_get_opacity: + * clutter_actor_get_abs_opacity: * @self: A #ClutterActor * - * Retrieves the actor's opacity. + * Retrieves the absolute opacity of the actor, as it appears on the stage. + * + * This function traverses the hierarchy chain and composites the opacity of + * the actor with that of its parents. + * + * This function is intended for subclasses to use in the paint virtual + * function, to paint themselves with the correct opacity. * * Return value: The actor opacity value. + * + * Since: 0.6 */ guint8 -clutter_actor_get_opacity (ClutterActor *self) +clutter_actor_get_abs_opacity (ClutterActor *self) { + ClutterActorPrivate *priv; ClutterActor *parent; g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); - parent = self->priv->parent_actor; + priv = self->priv; + + parent = priv->parent_actor; /* Factor in the actual actors opacity with parents */ - if (parent && clutter_actor_get_opacity (parent) != 0xff) - return (clutter_actor_get_opacity(parent) * self->priv->opacity) / 0xff; + if (G_LIKELY (parent)) + { + guint8 opacity = clutter_actor_get_abs_opacity (parent); + + if (opacity != 0xff) + return (opacity * priv->opacity) / 0xff; + } + + return clutter_actor_get_opacity (self); +} + +/** + * clutter_actor_get_opacity: + * @self: a #ClutterActor + * + * Retrieves the opacity value of an actor, as set by + * clutter_actor_set_opacity(). + * + * For retrieving the absolute opacity of the actor inside a paint + * virtual function, see clutter_actor_get_abs_opacity(). + * + * Return value: the opacity of the actor + */ +guint8 +clutter_actor_get_opacity (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); return self->priv->opacity; } diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index f71ddc3cf..1ad5b541e 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -360,6 +360,7 @@ ClutterFixed clutter_actor_get_rotationx (ClutterActor void clutter_actor_set_opacity (ClutterActor *self, guint8 opacity); guint8 clutter_actor_get_opacity (ClutterActor *self); +guint8 clutter_actor_get_abs_opacity (ClutterActor *self); void clutter_actor_set_name (ClutterActor *self, const gchar *name); G_CONST_RETURN gchar *clutter_actor_get_name (ClutterActor *self); diff --git a/clutter/clutter-clone-texture.c b/clutter/clutter-clone-texture.c index 6643dcac1..7a1de598a 100644 --- a/clutter/clutter-clone-texture.c +++ b/clutter/clutter-clone-texture.c @@ -213,7 +213,7 @@ clutter_clone_texture_paint (ClutterActor *self) cogl_enable (CGL_ENABLE_TEXTURE_2D|CGL_ENABLE_BLEND); } - col.alpha = clutter_actor_get_opacity (self); + col.alpha = clutter_actor_get_abs_opacity (self); cogl_color (&col); clutter_actor_get_coords (self, &x_1, &y_1, &x_2, &y_2); diff --git a/clutter/clutter-entry.c b/clutter/clutter-entry.c index a9671265f..f73fa7268 100644 --- a/clutter/clutter-entry.c +++ b/clutter/clutter-entry.c @@ -396,6 +396,7 @@ clutter_entry_paint (ClutterActor *self) gint width, actor_width; gint text_width; gint cursor_x; + ClutterColor color = { 0, }; entry = CLUTTER_ENTRY(self); priv = entry->priv; @@ -465,10 +466,12 @@ clutter_entry_paint (ClutterActor *self) priv->cursor_pos.x += priv->entry_padding; } - priv->fgcol.alpha = clutter_actor_get_opacity (self); + memcpy (&color, &priv->fgcol, sizeof (ClutterColor)); + color.alpha = clutter_actor_get_abs_opacity (self); + pango_clutter_render_layout (priv->layout, priv->text_x + priv->entry_padding, 0, - &priv->fgcol, 0); + &color, 0); if (CLUTTER_ENTRY_GET_CLASS (entry)->paint_cursor) CLUTTER_ENTRY_GET_CLASS (entry)->paint_cursor (entry); diff --git a/clutter/clutter-label.c b/clutter/clutter-label.c index 11de65aed..15c492923 100644 --- a/clutter/clutter-label.c +++ b/clutter/clutter-label.c @@ -288,6 +288,7 @@ clutter_label_paint (ClutterActor *self) { ClutterLabel *label = CLUTTER_LABEL (self); ClutterLabelPrivate *priv = label->priv; + ClutterColor color = { 0, }; if (priv->font_desc == NULL || priv->text == NULL) { @@ -302,9 +303,10 @@ clutter_label_paint (ClutterActor *self) clutter_label_ensure_layout (label); - priv->fgcol.alpha = clutter_actor_get_opacity (self); + memcpy (&color, &priv->fgcol, sizeof (ClutterColor)); + color.alpha = clutter_actor_get_abs_opacity (self); - pango_clutter_render_layout (priv->layout, 0, 0, &priv->fgcol, 0); + pango_clutter_render_layout (priv->layout, 0, 0, &color, 0); } static void diff --git a/clutter/clutter-rectangle.c b/clutter/clutter-rectangle.c index 950dc1700..e7d9833ad 100644 --- a/clutter/clutter-rectangle.c +++ b/clutter/clutter-rectangle.c @@ -96,7 +96,7 @@ clutter_rectangle_paint (ClutterActor *self) tmp_col.red = priv->border_color.red; tmp_col.green = priv->border_color.green; tmp_col.blue = priv->border_color.blue; - tmp_col.alpha = clutter_actor_get_opacity (self); + tmp_col.alpha = clutter_actor_get_abs_opacity (self); cogl_color (&tmp_col); @@ -134,7 +134,7 @@ clutter_rectangle_paint (ClutterActor *self) tmp_col.red = priv->color.red; tmp_col.green = priv->color.green; tmp_col.blue = priv->color.blue; - tmp_col.alpha = clutter_actor_get_opacity (self); + tmp_col.alpha = clutter_actor_get_abs_opacity (self); cogl_color (&tmp_col); @@ -392,8 +392,7 @@ clutter_rectangle_set_color (ClutterRectangle *rectangle, priv->color.blue = color->blue; priv->color.alpha = color->alpha; - clutter_actor_set_opacity (CLUTTER_ACTOR (rectangle), - priv->color.alpha); + clutter_actor_set_opacity (CLUTTER_ACTOR (rectangle), priv->color.alpha); #if 0 /* FIXME - appears to be causing border to always get drawn */ @@ -403,7 +402,7 @@ clutter_rectangle_set_color (ClutterRectangle *rectangle, priv->has_border = TRUE; #endif - if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (rectangle))) + if (CLUTTER_ACTOR_IS_VISIBLE (rectangle)) clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); g_object_notify (G_OBJECT (rectangle), "color"); diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index f1c35d09e..fc28e9607 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -847,8 +847,7 @@ clutter_texture_paint (ClutterActor *self) break; } - col.alpha = clutter_actor_get_opacity (self); - + col.alpha = clutter_actor_get_abs_opacity (self); cogl_color (&col); clutter_actor_get_coords (self, &x_1, &y_1, &x_2, &y_2); diff --git a/tests/Makefile.am b/tests/Makefile.am index e6f869841..d529f3e6f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,7 +3,8 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \ test-perspective test-rotate test-depth \ test-threads test-timeline test-score test-script \ test-model test-grab test-effects test-fullscreen \ - test-shader test-unproject test-viewport test-fbo + test-shader test-unproject test-viewport test-fbo \ + test-opacity INCLUDES = -I$(top_srcdir)/ LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la @@ -33,6 +34,7 @@ test_model_SOURCES = test-model.c test_effects_SOURCES = test-effects.c test_fullscreen_SOURCES = test-fullscreen.c test_viewport_SOURCES = test-viewport.c -test_fbo_SOURCES = test-fbo.c +test_fbo_SOURCES = test-fbo.c +test_opacity_SOURCES = test-opacity.c EXTRA_DIST = redhand.png test-script.json diff --git a/tests/test-opacity.c b/tests/test-opacity.c new file mode 100644 index 000000000..6fac2ffaf --- /dev/null +++ b/tests/test-opacity.c @@ -0,0 +1,115 @@ +#include +#include + +#include + +#include + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *group1, *group2, *label, *rect; + ClutterColor label_color = { 255, 0, 0, 128 }; + ClutterColor rect_color = { 0, 0, 255, 255 }; + ClutterColor color_check = { 0, }; + + clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); + + label = clutter_label_new_with_text ("Sans 18px", "Label, 50% opacity"); + clutter_label_set_color (CLUTTER_LABEL (label), &label_color); + + g_print ("label 50%%.get_color()/1\n"); + clutter_label_get_color (CLUTTER_LABEL (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (stage), label, NULL); + clutter_actor_set_position (label, 10, 10); + + g_print ("label 50%%.get_color()/2\n"); + clutter_label_get_color (CLUTTER_LABEL (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + g_print ("label 50%%.get_abs_opacity() = %d\n", + clutter_actor_get_abs_opacity (label)); + g_assert (clutter_actor_get_abs_opacity (label) == 128); + + clutter_actor_show (label); + + group1 = clutter_group_new (); + clutter_actor_set_opacity (group1, 128); + clutter_container_add (CLUTTER_CONTAINER (stage), group1, NULL); + clutter_actor_set_position (group1, 10, 30); + clutter_actor_show (group1); + + label = clutter_label_new_with_text ("Sans 18px", "Label+Group, 25% opacity"); + + clutter_label_set_color (CLUTTER_LABEL (label), &label_color); + + g_print ("label 50%% + group 50%%.get_color()/1\n"); + clutter_label_get_color (CLUTTER_LABEL (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (group1), label, NULL); + + g_print ("label 50%% + group 50%%.get_color()/2\n"); + clutter_label_get_color (CLUTTER_LABEL (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + g_print ("label 50%% + group 50%%.get_abs_opacity() = %d\n", + clutter_actor_get_abs_opacity (label)); + g_assert (clutter_actor_get_abs_opacity (label) == 64); + + clutter_actor_show (label); + + group2 = clutter_group_new (); + clutter_container_add (CLUTTER_CONTAINER (group1), group2, NULL); + clutter_actor_set_position (group2, 10, 60); + clutter_actor_show (group2); + + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_size (rect, 128, 128); + + g_print ("rect 100%% + group 100%% + group 50%%.get_color()/1\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (group2), rect, NULL); + + g_print ("rect 100%% + group 100%% + group 50%%.get_color()/2\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + g_print ("rect 100%%.get_abs_opacity() = %d\n", + clutter_actor_get_abs_opacity (rect)); + g_assert (clutter_actor_get_abs_opacity (rect) == 128); + + clutter_actor_show (rect); + + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_size (rect, 128, 128); + clutter_actor_set_position (rect, 150, 90); + + g_print ("rect 100%%.get_color()/1\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (stage), rect, NULL); + + g_print ("rect 100%%.get_color()/2\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + g_print ("rect 100%%.get_abs_opacity() = %d\n", + clutter_actor_get_abs_opacity (rect)); + g_assert (clutter_actor_get_abs_opacity (rect) == 255); + + clutter_actor_show (rect); + + clutter_actor_show_all (stage); + + clutter_main (); + + return EXIT_SUCCESS; +}