Implement -st-shadow for StWidget

Add support for a new -st-shadow property, which is based loosely
on the CSS3 box-shadow property:
http://www.css3.info/preview/box-shadow/

It defers from the specification as follows:

 * no multiple shadows
 * the optional color argument may be placed anywhere
 * the shape is not determined by the widget's bounding box,
   but by the background-image property

https://bugzilla.gnome.org/show_bug.cgi?id=603691
This commit is contained in:
Florian Müllner
2009-11-21 04:19:56 +01:00
parent a2cae50e0e
commit 2dfe113a42
8 changed files with 614 additions and 2 deletions

View File

@ -37,6 +37,7 @@
#include "st-marshal.h"
#include "st-private.h"
#include "st-shadow-texture.h"
#include "st-texture-cache.h"
#include "st-texture-frame.h"
#include "st-theme-context.h"
@ -57,11 +58,15 @@ struct _StWidgetPrivate
ClutterActor *border_image;
ClutterActor *background_image;
ClutterActor *background_image_shadow;
ClutterColor bg_color;
StGradientType bg_gradient_type;
ClutterColor bg_gradient_end;
gdouble shadow_xoffset;
gdouble shadow_yoffset;
gboolean is_stylable : 1;
gboolean has_tooltip : 1;
gboolean is_style_dirty : 1;
@ -227,6 +232,12 @@ st_widget_dispose (GObject *gobject)
priv->border_image = NULL;
}
if (priv->background_image_shadow)
{
clutter_actor_unparent (priv->background_image_shadow);
priv->background_image_shadow = NULL;
}
if (priv->tooltip)
{
ClutterContainer *parent;
@ -356,6 +367,28 @@ st_widget_allocate (ClutterActor *actor,
frame_box.y2 = frame_box.y1 + h;
}
if (priv->background_image_shadow)
{
StShadowTexture *shadow;
ClutterActorBox shadow_box;
shadow_box.x1 = frame_box.x1 + priv->shadow_xoffset;
shadow_box.y1 = frame_box.y1 + priv->shadow_yoffset;
shadow_box.x2 = frame_box.x2 + priv->shadow_xoffset;
shadow_box.y2 = frame_box.y2 + priv->shadow_yoffset;
/* The shadow texture is larger than the original image due
to blurring, so we let it adjust its size.
When the original image has been scaled, this will change
the effective blur radius - we ignore this for now. */
shadow = ST_SHADOW_TEXTURE (priv->background_image_shadow);
st_shadow_texture_adjust_allocation (shadow, &shadow_box);
clutter_actor_allocate (priv->background_image_shadow,
&shadow_box, flags);
}
clutter_actor_allocate (CLUTTER_ACTOR (priv->background_image),
&frame_box,
flags);
@ -497,7 +530,11 @@ st_widget_paint (ClutterActor *self)
klass->draw_background (ST_WIDGET (self));
if (priv->background_image != NULL)
clutter_actor_paint (priv->background_image);
{
if (priv->background_image_shadow)
clutter_actor_paint (priv->background_image_shadow);
clutter_actor_paint (priv->background_image);
}
}
static void
@ -527,6 +564,9 @@ st_widget_map (ClutterActor *actor)
st_widget_ensure_style ((StWidget*) actor);
if (priv->background_image_shadow)
clutter_actor_map (priv->background_image_shadow);
if (priv->border_image)
clutter_actor_map (priv->border_image);
@ -544,6 +584,9 @@ st_widget_unmap (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (st_widget_parent_class)->unmap (actor);
if (priv->background_image_shadow)
clutter_actor_unmap (priv->background_image_shadow);
if (priv->border_image)
clutter_actor_unmap (priv->border_image);
@ -659,6 +702,7 @@ st_widget_real_style_changed (StWidget *self)
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
StThemeNode *theme_node;
StBorderImage *border_image;
StShadow *shadow;
StTextureCache *texture_cache;
ClutterTexture *texture;
const char *bg_file = NULL;
@ -706,6 +750,12 @@ st_widget_real_style_changed (StWidget *self)
has_changed = TRUE;
}
if (priv->background_image_shadow)
{
clutter_actor_unparent (priv->background_image_shadow);
priv->background_image_shadow = NULL;
}
if (priv->border_image)
{
clutter_actor_unparent (priv->border_image);
@ -877,7 +927,39 @@ st_widget_real_style_changed (StWidget *self)
relayout_needed = TRUE;
}
/* If there are any properties above that need to cause a relayout thay
/* CSS based drop shadows
*
* Drop shadows in ST are modelled after the CSS3 box-shadow property;
* see http://www.css3.info/preview/box-shadow/ for a detailed description.
*
* While the syntax of the property is mostly identical - we do not support
* multiple shadows and allow for a more liberal placement of the color
* parameter - its interpretation defers significantly in that the shadow's
* shape is not determined by the bounding box, but by the CSS background
* image (we could exend this in the future to take other CSS properties
* like boder and background color into account).
*/
shadow = st_theme_node_get_shadow (theme_node);
if (shadow != NULL)
{
priv->shadow_xoffset = shadow->xoffset;
priv->shadow_yoffset = shadow->yoffset;
if (priv->background_image)
{
priv->background_image_shadow =
st_shadow_texture_new (priv->background_image,
&shadow->color,
shadow->blur);
clutter_actor_set_parent (priv->background_image_shadow,
CLUTTER_ACTOR (self));
has_changed = TRUE;
relayout_needed = TRUE;
}
}
/* If there are any properties above that need to cause a relayout they
* should set this flag.
*/
if (has_changed)