Move rendering into st-theme-node-drawing.c
The idea behind this move is that we have a lot more control over rendering if StWidget isn't a big pile of actors, and things are more efficient. https://bugzilla.gnome.org/show_bug.cgi?id=607500
This commit is contained in:
parent
a8fa8a498a
commit
5060081db5
@ -83,13 +83,11 @@ st_source_h = \
|
|||||||
st/st-scrollable.h \
|
st/st-scrollable.h \
|
||||||
st/st-scroll-bar.h \
|
st/st-scroll-bar.h \
|
||||||
st/st-scroll-view.h \
|
st/st-scroll-view.h \
|
||||||
st/st-shadow-texture.h \
|
|
||||||
st/st-shadow.h \
|
st/st-shadow.h \
|
||||||
st/st-subtexture.h \
|
st/st-subtexture.h \
|
||||||
st/st-table.h \
|
st/st-table.h \
|
||||||
st/st-table-child.h \
|
st/st-table-child.h \
|
||||||
st/st-texture-cache.h \
|
st/st-texture-cache.h \
|
||||||
st/st-texture-frame.h \
|
|
||||||
st/st-theme.h \
|
st/st-theme.h \
|
||||||
st/st-theme-context.h \
|
st/st-theme-context.h \
|
||||||
st/st-theme-node.h \
|
st/st-theme-node.h \
|
||||||
@ -109,7 +107,8 @@ BUILT_SOURCES += st.h
|
|||||||
st_source_private_h = \
|
st_source_private_h = \
|
||||||
st/st-private.h \
|
st/st-private.h \
|
||||||
st/st-table-private.h \
|
st/st-table-private.h \
|
||||||
st/st-theme-private.h
|
st/st-theme-private.h \
|
||||||
|
st/st-theme-node-private.h
|
||||||
|
|
||||||
# please, keep this sorted alphabetically
|
# please, keep this sorted alphabetically
|
||||||
st_source_c = \
|
st_source_c = \
|
||||||
@ -130,16 +129,15 @@ st_source_c = \
|
|||||||
st/st-scrollable.c \
|
st/st-scrollable.c \
|
||||||
st/st-scroll-bar.c \
|
st/st-scroll-bar.c \
|
||||||
st/st-scroll-view.c \
|
st/st-scroll-view.c \
|
||||||
st/st-shadow-texture.c \
|
|
||||||
st/st-shadow.c \
|
st/st-shadow.c \
|
||||||
st/st-subtexture.c \
|
st/st-subtexture.c \
|
||||||
st/st-table.c \
|
st/st-table.c \
|
||||||
st/st-table-child.c \
|
st/st-table-child.c \
|
||||||
st/st-texture-cache.c \
|
st/st-texture-cache.c \
|
||||||
st/st-texture-frame.c \
|
|
||||||
st/st-theme.c \
|
st/st-theme.c \
|
||||||
st/st-theme-context.c \
|
st/st-theme-context.c \
|
||||||
st/st-theme-node.c \
|
st/st-theme-node.c \
|
||||||
|
st/st-theme-node-drawing.c \
|
||||||
st/st-tooltip.c \
|
st/st-tooltip.c \
|
||||||
st/st-widget.c \
|
st/st-widget.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
#include "st-button.h"
|
#include "st-button.h"
|
||||||
|
|
||||||
#include "st-marshal.h"
|
#include "st-marshal.h"
|
||||||
#include "st-texture-frame.h"
|
|
||||||
#include "st-texture-cache.h"
|
#include "st-texture-cache.h"
|
||||||
#include "st-private.h"
|
#include "st-private.h"
|
||||||
|
|
||||||
|
@ -1,273 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "st-shadow-texture.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION: st-shadow-texture
|
|
||||||
* @short_description: a class for creating soft shadow textures
|
|
||||||
*
|
|
||||||
* #StShadowTexture is a #ClutterTexture holding a soft shadow texture for
|
|
||||||
* another #ClutterActor.
|
|
||||||
* It is used to implement the box-shadow property in StWidget and should
|
|
||||||
* not be used stand-alone.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct _StShadowTexture {
|
|
||||||
ClutterTexture parent;
|
|
||||||
|
|
||||||
CoglColor color;
|
|
||||||
gdouble sigma;
|
|
||||||
gdouble blur_radius;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _StShadowTextureClass {
|
|
||||||
ClutterTextureClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (StShadowTexture, st_shadow_texture, CLUTTER_TYPE_TEXTURE);
|
|
||||||
|
|
||||||
static gdouble *
|
|
||||||
calculate_gaussian_kernel (gdouble sigma, guint n_values)
|
|
||||||
{
|
|
||||||
gdouble *ret, sum;
|
|
||||||
gdouble exp_divisor;
|
|
||||||
gint half, i;
|
|
||||||
|
|
||||||
g_return_val_if_fail ((int) sigma > 0, NULL);
|
|
||||||
|
|
||||||
half = n_values / 2;
|
|
||||||
|
|
||||||
ret = g_malloc (n_values * sizeof (gdouble));
|
|
||||||
sum = 0.0;
|
|
||||||
|
|
||||||
exp_divisor = 2 * sigma * sigma;
|
|
||||||
|
|
||||||
/* n_values of 1D Gauss function */
|
|
||||||
for (i = 0; i < n_values; i++)
|
|
||||||
{
|
|
||||||
ret[i] = exp (-(i - half) * (i - half) / exp_divisor);
|
|
||||||
sum += ret[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* normalize */
|
|
||||||
for (i = 0; i < n_values; i++)
|
|
||||||
ret[i] /= sum;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_shadow_texture_create_shadow (StShadowTexture *st,
|
|
||||||
ClutterActor *actor)
|
|
||||||
{
|
|
||||||
CoglHandle texture, material;
|
|
||||||
guchar *pixels_in, *pixels_out;
|
|
||||||
gint width_in, height_in, rowstride_in;
|
|
||||||
gint width_out, height_out, rowstride_out;
|
|
||||||
|
|
||||||
g_return_if_fail (ST_IS_SHADOW_TEXTURE (st));
|
|
||||||
|
|
||||||
/* Right now we only deal with actors of type ClutterTexture.
|
|
||||||
It would be nice to extend this to generic actors with some
|
|
||||||
clutter_texture_new_from_actor magic in the future */
|
|
||||||
g_return_if_fail (CLUTTER_IS_TEXTURE (actor));
|
|
||||||
|
|
||||||
texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
|
|
||||||
if (texture == COGL_INVALID_HANDLE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
width_in = cogl_texture_get_width (texture);
|
|
||||||
height_in = cogl_texture_get_height (texture);
|
|
||||||
rowstride_in = (width_in + 3) & ~3;
|
|
||||||
|
|
||||||
pixels_in = g_malloc0 (rowstride_in * height_in);
|
|
||||||
|
|
||||||
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_A_8,
|
|
||||||
rowstride_in, pixels_in);
|
|
||||||
|
|
||||||
if ((guint) st->blur_radius == 0)
|
|
||||||
{
|
|
||||||
width_out = width_in;
|
|
||||||
height_out = height_in;
|
|
||||||
rowstride_out = rowstride_in;
|
|
||||||
pixels_out = g_memdup (pixels_in, rowstride_out * height_out);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdouble *kernel;
|
|
||||||
guchar *line;
|
|
||||||
gint n_values, half;
|
|
||||||
gint x_in, y_in, x_out, y_out, i;
|
|
||||||
|
|
||||||
n_values = (gint) 5 * st->sigma;
|
|
||||||
half = n_values / 2;
|
|
||||||
|
|
||||||
width_out = width_in + 2 * half;
|
|
||||||
height_out = height_in + 2 * half;
|
|
||||||
rowstride_out = (width_out + 3) & ~3;
|
|
||||||
|
|
||||||
pixels_out = g_malloc0 (rowstride_out * height_out);
|
|
||||||
line = g_malloc0 (rowstride_out);
|
|
||||||
|
|
||||||
kernel = calculate_gaussian_kernel (st->sigma, n_values);
|
|
||||||
|
|
||||||
/* vertical blur */
|
|
||||||
for (x_in = 0; x_in < width_in; x_in++)
|
|
||||||
for (y_out = 0; y_out < height_out; y_out++)
|
|
||||||
{
|
|
||||||
guchar *pixel_in, *pixel_out;
|
|
||||||
gint i0, i1;
|
|
||||||
|
|
||||||
y_in = y_out - half;
|
|
||||||
|
|
||||||
/* We read from the source at 'y = y_in + i - half'; clamp the
|
|
||||||
* full i range [0, n_values) so that y is in [0, height_in).
|
|
||||||
*/
|
|
||||||
i0 = MAX (half - y_in, 0);
|
|
||||||
i1 = MIN (height_in + half - y_in, n_values);
|
|
||||||
|
|
||||||
pixel_in = pixels_in + (y_in + i0 - half) * rowstride_in + x_in;
|
|
||||||
pixel_out = pixels_out + y_out * rowstride_out + (x_in + half);
|
|
||||||
|
|
||||||
for (i = i0; i < i1; i++)
|
|
||||||
{
|
|
||||||
*pixel_out += *pixel_in * kernel[i];
|
|
||||||
pixel_in += rowstride_in;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* horizontal blur */
|
|
||||||
for (y_out = 0; y_out < height_out; y_out++)
|
|
||||||
{
|
|
||||||
memcpy (line, pixels_out + y_out * rowstride_out, rowstride_out);
|
|
||||||
|
|
||||||
for (x_out = 0; x_out < width_out; x_out++)
|
|
||||||
{
|
|
||||||
gint i0, i1;
|
|
||||||
guchar *pixel_out, *pixel_in;
|
|
||||||
|
|
||||||
/* We read from the source at 'x = x_out + i - half'; clamp the
|
|
||||||
* full i range [0, n_values) so that x is in [0, width_out).
|
|
||||||
*/
|
|
||||||
i0 = MAX (half - x_out, 0);
|
|
||||||
i1 = MIN (width_out + half - x_out, n_values);
|
|
||||||
|
|
||||||
pixel_in = line + x_out + i0 - half;
|
|
||||||
pixel_out = pixels_out + rowstride_out * y_out + x_out;
|
|
||||||
|
|
||||||
*pixel_out = 0;
|
|
||||||
for (i = i0; i < i1; i++)
|
|
||||||
{
|
|
||||||
*pixel_out += *pixel_in * kernel[i];
|
|
||||||
pixel_in++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_free (kernel);
|
|
||||||
g_free (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
material = cogl_material_new ();
|
|
||||||
texture = cogl_texture_new_from_data (width_out,
|
|
||||||
height_out,
|
|
||||||
COGL_TEXTURE_NONE,
|
|
||||||
COGL_PIXEL_FORMAT_A_8,
|
|
||||||
COGL_PIXEL_FORMAT_A_8,
|
|
||||||
rowstride_out,
|
|
||||||
pixels_out);
|
|
||||||
|
|
||||||
cogl_material_set_layer_combine_constant (material, 0, &st->color);
|
|
||||||
cogl_material_set_layer (material, 0, texture);
|
|
||||||
|
|
||||||
/* We ignore the material color, which encodes the overall opacity of the
|
|
||||||
* actor, so setting an ancestor of the shadow to partially opaque won't
|
|
||||||
* work. The easiest way to fix this would be to override paint(). */
|
|
||||||
|
|
||||||
cogl_material_set_layer_combine (material, 0,
|
|
||||||
"RGBA = MODULATE (CONSTANT, TEXTURE[A])",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
clutter_texture_set_cogl_material (CLUTTER_TEXTURE (st), material);
|
|
||||||
|
|
||||||
cogl_handle_unref (texture);
|
|
||||||
cogl_handle_unref (material);
|
|
||||||
|
|
||||||
g_free (pixels_in);
|
|
||||||
g_free (pixels_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_shadow_texture_adjust_allocation:
|
|
||||||
* @shadow: a #StShadowTexture
|
|
||||||
* @allocation: the original allocation of @shadow
|
|
||||||
*
|
|
||||||
* Adjust @allocation to account for size change caused by blurrimg
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
st_shadow_texture_adjust_allocation (StShadowTexture *shadow,
|
|
||||||
ClutterActorBox *allocation)
|
|
||||||
{
|
|
||||||
g_return_if_fail (ST_IS_SHADOW_TEXTURE (shadow));
|
|
||||||
g_return_if_fail (allocation != NULL);
|
|
||||||
|
|
||||||
allocation->x1 -= shadow->blur_radius;
|
|
||||||
allocation->y1 -= shadow->blur_radius;
|
|
||||||
allocation->x2 += shadow->blur_radius;
|
|
||||||
allocation->y2 += shadow->blur_radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_shadow_texture_new:
|
|
||||||
* @actor: the original actor
|
|
||||||
* @color: (allow-none): the shadow color
|
|
||||||
* @blur: the shadow's blur radius
|
|
||||||
*
|
|
||||||
* Create a shadow texture for @actor. When %NULL is passed for @color, it
|
|
||||||
* defaults to fully opaque black.
|
|
||||||
*
|
|
||||||
* Returns: a new #ClutterActor holding a shadow texture for @actor
|
|
||||||
*/
|
|
||||||
ClutterActor *
|
|
||||||
st_shadow_texture_new (ClutterActor *actor,
|
|
||||||
ClutterColor *color,
|
|
||||||
gdouble blur)
|
|
||||||
{
|
|
||||||
StShadowTexture *st = g_object_new (ST_TYPE_SHADOW_TEXTURE, NULL);
|
|
||||||
|
|
||||||
if (color)
|
|
||||||
{
|
|
||||||
cogl_color_set_from_4ub (&st->color,
|
|
||||||
color->red, color->green,
|
|
||||||
color->blue, color->alpha);
|
|
||||||
cogl_color_premultiply (&st->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
st->blur_radius = blur;
|
|
||||||
/* we use an approximation of the sigma - blur radius relationship used
|
|
||||||
in Firefox for doing SVG blurs; see
|
|
||||||
http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/src/gfxBlur.cpp#280
|
|
||||||
*/
|
|
||||||
st->sigma = blur / 1.9;
|
|
||||||
|
|
||||||
st_shadow_texture_create_shadow (st, actor);
|
|
||||||
|
|
||||||
return CLUTTER_ACTOR (st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_shadow_texture_init (StShadowTexture *st)
|
|
||||||
{
|
|
||||||
st->sigma = 0.0;
|
|
||||||
st->blur_radius = 0.0;
|
|
||||||
|
|
||||||
cogl_color_set_from_4ub (&st->color, 0x0, 0x0, 0x0, 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_shadow_texture_class_init (StShadowTextureClass *klass)
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
#ifndef __ST_SHADOW_TEXTURE__
|
|
||||||
#define __ST_SHADOW_TEXTURE__
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
typedef struct _StShadowTexture StShadowTexture;
|
|
||||||
typedef struct _StShadowTextureClass StShadowTextureClass;
|
|
||||||
|
|
||||||
#define ST_TYPE_SHADOW_TEXTURE (st_shadow_texture_get_type ())
|
|
||||||
#define ST_SHADOW_TEXTURE(object) (G_TYPE_CHECK_INSTANCE_CAST((object),ST_TYPE_SHADOW_TEXTURE, StShadowTexture))
|
|
||||||
#define ST_IS_SHADOW_TEXTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),ST_TYPE_SHADOW_TEXTURE))
|
|
||||||
#define ST_SHADOW_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ST_TYPE_SHADOW_TEXTURE, StShadowTextureClass))
|
|
||||||
#define ST_IS_SHADOW_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ST_TYPE_SHADOW_TEXTURE))
|
|
||||||
#define ST_SHADOW_TEXTURE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), ST_TYPE_SHADOW_TEXTURE, StShadowTextureClass))
|
|
||||||
|
|
||||||
GType st_shadow_texture_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ClutterActor *st_shadow_texture_new (ClutterActor *actor,
|
|
||||||
ClutterColor *color,
|
|
||||||
gdouble blur_radius);
|
|
||||||
|
|
||||||
void st_shadow_texture_adjust_allocation (StShadowTexture *shadow,
|
|
||||||
ClutterActorBox *allocation);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __ST_SHADOW_TEXTURE__ */
|
|
@ -1,621 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
/*
|
|
||||||
* st-texture-frame.h: Expandible texture actor
|
|
||||||
*
|
|
||||||
* Copyright 2007 OpenedHand
|
|
||||||
* Copyright 2009 Intel Corporation.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU Lesser General Public License,
|
|
||||||
* version 2.1, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:st-texture-frame
|
|
||||||
* @short_description: Stretch a texture to fit the entire allocation
|
|
||||||
*
|
|
||||||
* #StTextureFrame
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cogl/cogl.h>
|
|
||||||
|
|
||||||
#include "st-texture-frame.h"
|
|
||||||
#include "st-private.h"
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_PARENT_TEXTURE,
|
|
||||||
|
|
||||||
PROP_TOP,
|
|
||||||
PROP_RIGHT,
|
|
||||||
PROP_BOTTOM,
|
|
||||||
PROP_LEFT
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (StTextureFrame, st_texture_frame, CLUTTER_TYPE_ACTOR);
|
|
||||||
|
|
||||||
#define ST_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFramePrivate))
|
|
||||||
|
|
||||||
struct _StTextureFramePrivate
|
|
||||||
{
|
|
||||||
ClutterTexture *parent_texture;
|
|
||||||
|
|
||||||
gfloat top;
|
|
||||||
gfloat right;
|
|
||||||
gfloat bottom;
|
|
||||||
gfloat left;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_get_preferred_width (ClutterActor *self,
|
|
||||||
gfloat for_height,
|
|
||||||
gfloat *min_width_p,
|
|
||||||
gfloat *natural_width_p)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = ST_TEXTURE_FRAME (self)->priv;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
|
||||||
{
|
|
||||||
if (min_width_p)
|
|
||||||
*min_width_p = 0;
|
|
||||||
|
|
||||||
if (natural_width_p)
|
|
||||||
*natural_width_p = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ClutterActorClass *klass;
|
|
||||||
|
|
||||||
/* by directly querying the parent texture's class implementation
|
|
||||||
* we are going around any override mechanism the parent texture
|
|
||||||
* might have in place, and we ask directly for the original
|
|
||||||
* preferred width
|
|
||||||
*/
|
|
||||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
|
||||||
klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture),
|
|
||||||
for_height,
|
|
||||||
min_width_p,
|
|
||||||
natural_width_p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_get_preferred_height (ClutterActor *self,
|
|
||||||
gfloat for_width,
|
|
||||||
gfloat *min_height_p,
|
|
||||||
gfloat *natural_height_p)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = ST_TEXTURE_FRAME (self)->priv;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
|
||||||
{
|
|
||||||
if (min_height_p)
|
|
||||||
*min_height_p = 0;
|
|
||||||
|
|
||||||
if (natural_height_p)
|
|
||||||
*natural_height_p = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ClutterActorClass *klass;
|
|
||||||
|
|
||||||
/* by directly querying the parent texture's class implementation
|
|
||||||
* we are going around any override mechanism the parent texture
|
|
||||||
* might have in place, and we ask directly for the original
|
|
||||||
* preferred height
|
|
||||||
*/
|
|
||||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
|
||||||
klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture),
|
|
||||||
for_width,
|
|
||||||
min_height_p,
|
|
||||||
natural_height_p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_paint (ClutterActor *self)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = ST_TEXTURE_FRAME (self)->priv;
|
|
||||||
CoglHandle cogl_texture = COGL_INVALID_HANDLE;
|
|
||||||
CoglHandle cogl_material = COGL_INVALID_HANDLE;
|
|
||||||
ClutterActorBox box = { 0, };
|
|
||||||
gfloat width, height;
|
|
||||||
gfloat tex_width, tex_height;
|
|
||||||
gfloat ex, ey;
|
|
||||||
gfloat tx1, ty1, tx2, ty2;
|
|
||||||
guint8 opacity;
|
|
||||||
|
|
||||||
/* no need to paint stuff if we don't have a texture */
|
|
||||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* parent texture may have been hidden, so need to make sure it gets
|
|
||||||
* realized
|
|
||||||
*/
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture))
|
|
||||||
clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture));
|
|
||||||
|
|
||||||
cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture);
|
|
||||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
|
||||||
return;
|
|
||||||
cogl_material = clutter_texture_get_cogl_material (priv->parent_texture);
|
|
||||||
if (cogl_material == COGL_INVALID_HANDLE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tex_width = cogl_texture_get_width (cogl_texture);
|
|
||||||
tex_height = cogl_texture_get_height (cogl_texture);
|
|
||||||
|
|
||||||
clutter_actor_get_allocation_box (self, &box);
|
|
||||||
width = box.x2 - box.x1;
|
|
||||||
height = box.y2 - box.y1;
|
|
||||||
|
|
||||||
tx1 = priv->left / tex_width;
|
|
||||||
tx2 = (tex_width - priv->right) / tex_width;
|
|
||||||
ty1 = priv->top / tex_height;
|
|
||||||
ty2 = (tex_height - priv->bottom) / tex_height;
|
|
||||||
|
|
||||||
ex = width - priv->right;
|
|
||||||
if (ex < 0)
|
|
||||||
ex = priv->right; /* FIXME ? */
|
|
||||||
|
|
||||||
ey = height - priv->bottom;
|
|
||||||
if (ey < 0)
|
|
||||||
ey = priv->bottom; /* FIXME ? */
|
|
||||||
|
|
||||||
opacity = clutter_actor_get_paint_opacity (self);
|
|
||||||
|
|
||||||
/* Paint using the parent texture's material. It should already have
|
|
||||||
the cogl texture set as the first layer */
|
|
||||||
/* NB: for correct blending we need set a preumultiplied color here: */
|
|
||||||
cogl_material_set_color4ub (cogl_material,
|
|
||||||
opacity, opacity, opacity, opacity);
|
|
||||||
cogl_set_source (cogl_material);
|
|
||||||
|
|
||||||
{
|
|
||||||
GLfloat rectangles[] =
|
|
||||||
{
|
|
||||||
/* top left corner */
|
|
||||||
0, 0, priv->left, priv->top,
|
|
||||||
0.0, 0.0,
|
|
||||||
tx1, ty1,
|
|
||||||
|
|
||||||
/* top middle */
|
|
||||||
priv->left, 0, ex, priv->top,
|
|
||||||
tx1, 0.0,
|
|
||||||
tx2, ty1,
|
|
||||||
|
|
||||||
/* top right */
|
|
||||||
ex, 0, width, priv->top,
|
|
||||||
tx2, 0.0,
|
|
||||||
1.0, ty1,
|
|
||||||
|
|
||||||
/* mid left */
|
|
||||||
0, priv->top, priv->left, ey,
|
|
||||||
0.0, ty1,
|
|
||||||
tx1, ty2,
|
|
||||||
|
|
||||||
/* center */
|
|
||||||
priv->left, priv->top, ex, ey,
|
|
||||||
tx1, ty1,
|
|
||||||
tx2, ty2,
|
|
||||||
|
|
||||||
/* mid right */
|
|
||||||
ex, priv->top, width, ey,
|
|
||||||
tx2, ty1,
|
|
||||||
1.0, ty2,
|
|
||||||
|
|
||||||
/* bottom left */
|
|
||||||
0, ey, priv->left, height,
|
|
||||||
0.0, ty2,
|
|
||||||
tx1, 1.0,
|
|
||||||
|
|
||||||
/* bottom center */
|
|
||||||
priv->left, ey, ex, height,
|
|
||||||
tx1, ty2,
|
|
||||||
tx2, 1.0,
|
|
||||||
|
|
||||||
/* bottom right */
|
|
||||||
ex, ey, width, height,
|
|
||||||
tx2, ty2,
|
|
||||||
1.0, 1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
cogl_rectangles_with_texture_coords (rectangles, 9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
st_texture_frame_set_frame_internal (StTextureFrame *frame,
|
|
||||||
gfloat top,
|
|
||||||
gfloat right,
|
|
||||||
gfloat bottom,
|
|
||||||
gfloat left)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = frame->priv;
|
|
||||||
GObject *gobject = G_OBJECT (frame);
|
|
||||||
gboolean changed = FALSE;
|
|
||||||
|
|
||||||
g_object_freeze_notify (gobject);
|
|
||||||
|
|
||||||
if (priv->top != top)
|
|
||||||
{
|
|
||||||
priv->top = top;
|
|
||||||
g_object_notify (gobject, "top");
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->right != right)
|
|
||||||
{
|
|
||||||
priv->right = right;
|
|
||||||
g_object_notify (gobject, "right");
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->bottom != bottom)
|
|
||||||
{
|
|
||||||
priv->bottom = bottom;
|
|
||||||
g_object_notify (gobject, "bottom");
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->left != left)
|
|
||||||
{
|
|
||||||
priv->left = left;
|
|
||||||
g_object_notify (gobject, "left");
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame))
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (frame));
|
|
||||||
|
|
||||||
g_object_thaw_notify (gobject);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_set_property (GObject *gobject,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
StTextureFrame *frame = ST_TEXTURE_FRAME (gobject);
|
|
||||||
StTextureFramePrivate *priv = frame->priv;
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_PARENT_TEXTURE:
|
|
||||||
st_texture_frame_set_parent_texture (frame,
|
|
||||||
g_value_get_object (value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_TOP:
|
|
||||||
st_texture_frame_set_frame_internal (frame,
|
|
||||||
g_value_get_float (value),
|
|
||||||
priv->right,
|
|
||||||
priv->bottom,
|
|
||||||
priv->left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_RIGHT:
|
|
||||||
st_texture_frame_set_frame_internal (frame,
|
|
||||||
priv->top,
|
|
||||||
g_value_get_float (value),
|
|
||||||
priv->bottom,
|
|
||||||
priv->left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BOTTOM:
|
|
||||||
st_texture_frame_set_frame_internal (frame,
|
|
||||||
priv->top,
|
|
||||||
priv->right,
|
|
||||||
g_value_get_float (value),
|
|
||||||
priv->left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_LEFT:
|
|
||||||
st_texture_frame_set_frame_internal (frame,
|
|
||||||
priv->top,
|
|
||||||
priv->right,
|
|
||||||
priv->bottom,
|
|
||||||
g_value_get_float (value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_get_property (GObject *gobject,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = ST_TEXTURE_FRAME (gobject)->priv;
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_PARENT_TEXTURE:
|
|
||||||
g_value_set_object (value, priv->parent_texture);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_LEFT:
|
|
||||||
g_value_set_float (value, priv->left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_TOP:
|
|
||||||
g_value_set_float (value, priv->top);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_RIGHT:
|
|
||||||
g_value_set_float (value, priv->right);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BOTTOM:
|
|
||||||
g_value_set_float (value, priv->bottom);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_dispose (GObject *gobject)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv = ST_TEXTURE_FRAME (gobject)->priv;
|
|
||||||
|
|
||||||
if (priv->parent_texture)
|
|
||||||
{
|
|
||||||
g_object_unref (priv->parent_texture);
|
|
||||||
priv->parent_texture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (st_texture_frame_parent_class)->dispose (gobject);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_class_init (StTextureFrameClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
GParamSpec *pspec;
|
|
||||||
|
|
||||||
g_type_class_add_private (gobject_class, sizeof (StTextureFramePrivate));
|
|
||||||
|
|
||||||
actor_class->get_preferred_width =
|
|
||||||
st_texture_frame_get_preferred_width;
|
|
||||||
actor_class->get_preferred_height =
|
|
||||||
st_texture_frame_get_preferred_height;
|
|
||||||
actor_class->paint = st_texture_frame_paint;
|
|
||||||
|
|
||||||
gobject_class->set_property = st_texture_frame_set_property;
|
|
||||||
gobject_class->get_property = st_texture_frame_get_property;
|
|
||||||
gobject_class->dispose = st_texture_frame_dispose;
|
|
||||||
|
|
||||||
pspec = g_param_spec_object ("parent-texture",
|
|
||||||
"Parent Texture",
|
|
||||||
"The parent ClutterTexture",
|
|
||||||
CLUTTER_TYPE_TEXTURE,
|
|
||||||
ST_PARAM_READWRITE |
|
|
||||||
G_PARAM_CONSTRUCT);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec);
|
|
||||||
|
|
||||||
pspec = g_param_spec_float ("left",
|
|
||||||
"Left",
|
|
||||||
"Left offset",
|
|
||||||
0, G_MAXFLOAT,
|
|
||||||
0,
|
|
||||||
ST_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LEFT, pspec);
|
|
||||||
|
|
||||||
pspec = g_param_spec_float ("top",
|
|
||||||
"Top",
|
|
||||||
"Top offset",
|
|
||||||
0, G_MAXFLOAT,
|
|
||||||
0,
|
|
||||||
ST_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_TOP, pspec);
|
|
||||||
|
|
||||||
pspec = g_param_spec_float ("bottom",
|
|
||||||
"Bottom",
|
|
||||||
"Bottom offset",
|
|
||||||
0, G_MAXFLOAT,
|
|
||||||
0,
|
|
||||||
ST_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec);
|
|
||||||
|
|
||||||
pspec = g_param_spec_float ("right",
|
|
||||||
"Right",
|
|
||||||
"Right offset",
|
|
||||||
0, G_MAXFLOAT,
|
|
||||||
0,
|
|
||||||
ST_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_RIGHT, pspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_texture_frame_init (StTextureFrame *self)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv;
|
|
||||||
|
|
||||||
self->priv = priv = ST_TEXTURE_FRAME_GET_PRIVATE (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_texture_frame_new:
|
|
||||||
* @texture: a #ClutterTexture or %NULL
|
|
||||||
* @left: left margin preserving its content
|
|
||||||
* @top: top margin preserving its content
|
|
||||||
* @right: right margin preserving its content
|
|
||||||
* @bottom: bottom margin preserving its content
|
|
||||||
*
|
|
||||||
* A #StTextureFrame is a specialized texture that efficiently clones
|
|
||||||
* an area of the given @texture while keeping preserving portions of the
|
|
||||||
* same texture.
|
|
||||||
*
|
|
||||||
* A #StTextureFrame can be used to make a rectangular texture fit a
|
|
||||||
* given size without stretching its borders.
|
|
||||||
*
|
|
||||||
* Return value: the newly created #StTextureFrame
|
|
||||||
*/
|
|
||||||
ClutterActor*
|
|
||||||
st_texture_frame_new (ClutterTexture *texture,
|
|
||||||
gfloat top,
|
|
||||||
gfloat right,
|
|
||||||
gfloat bottom,
|
|
||||||
gfloat left)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
|
|
||||||
|
|
||||||
return g_object_new (ST_TYPE_TEXTURE_FRAME,
|
|
||||||
"parent-texture", texture,
|
|
||||||
"top", top,
|
|
||||||
"right", right,
|
|
||||||
"bottom", bottom,
|
|
||||||
"left", left,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_texture_frame_get_parent_texture:
|
|
||||||
* @frame: A #StTextureFrame
|
|
||||||
*
|
|
||||||
* Return the texture used by the #StTextureFrame
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): a #ClutterTexture owned by the #StTextureFrame
|
|
||||||
*/
|
|
||||||
ClutterTexture *
|
|
||||||
st_texture_frame_get_parent_texture (StTextureFrame *frame)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (ST_IS_TEXTURE_FRAME (frame), NULL);
|
|
||||||
|
|
||||||
return frame->priv->parent_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_texture_frame_set_parent_texture:
|
|
||||||
* @frame: A #StTextureFrame
|
|
||||||
* @texture: A #ClutterTexture
|
|
||||||
*
|
|
||||||
* Set the #ClutterTexture used by this #StTextureFrame
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
st_texture_frame_set_parent_texture (StTextureFrame *frame,
|
|
||||||
ClutterTexture *texture)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv;
|
|
||||||
gboolean was_visible;
|
|
||||||
|
|
||||||
g_return_if_fail (ST_IS_TEXTURE_FRAME (frame));
|
|
||||||
g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture));
|
|
||||||
|
|
||||||
priv = frame->priv;
|
|
||||||
|
|
||||||
was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame);
|
|
||||||
|
|
||||||
if (priv->parent_texture == texture)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (priv->parent_texture)
|
|
||||||
{
|
|
||||||
g_object_unref (priv->parent_texture);
|
|
||||||
priv->parent_texture = NULL;
|
|
||||||
|
|
||||||
if (was_visible)
|
|
||||||
clutter_actor_hide (CLUTTER_ACTOR (frame));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture)
|
|
||||||
{
|
|
||||||
priv->parent_texture = g_object_ref_sink (texture);
|
|
||||||
|
|
||||||
if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture))
|
|
||||||
clutter_actor_show (CLUTTER_ACTOR (frame));
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (frame), "parent-texture");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_texture_frame_set_frame:
|
|
||||||
* @frame: A #StTextureFrame
|
|
||||||
* @top: width of the top slice
|
|
||||||
* @right: width of the right slice
|
|
||||||
* @bottom: width of the bottom slice
|
|
||||||
* @left: width of the left slice
|
|
||||||
*
|
|
||||||
* Set the slice lines of the specified frame. The slices are calculated as
|
|
||||||
* widths from the edge of the frame.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
st_texture_frame_set_frame (StTextureFrame *frame,
|
|
||||||
gfloat top,
|
|
||||||
gfloat right,
|
|
||||||
gfloat bottom,
|
|
||||||
gfloat left)
|
|
||||||
{
|
|
||||||
g_return_if_fail (ST_IS_TEXTURE_FRAME (frame));
|
|
||||||
|
|
||||||
st_texture_frame_set_frame_internal (frame, top, right, bottom, left);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* st_texture_frame_get_frame:
|
|
||||||
* @frame: A #StTextureFrame
|
|
||||||
* @top: width of the top slice
|
|
||||||
* @right: width of the right slice
|
|
||||||
* @bottom: width of the bottom slice
|
|
||||||
* @left: width of the left slice
|
|
||||||
*
|
|
||||||
* Retrieve the current slice lines from the specified frame.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
st_texture_frame_get_frame (StTextureFrame *frame,
|
|
||||||
gfloat *top,
|
|
||||||
gfloat *right,
|
|
||||||
gfloat *bottom,
|
|
||||||
gfloat *left)
|
|
||||||
{
|
|
||||||
StTextureFramePrivate *priv;
|
|
||||||
|
|
||||||
g_return_if_fail (ST_IS_TEXTURE_FRAME (frame));
|
|
||||||
|
|
||||||
priv = frame->priv;
|
|
||||||
|
|
||||||
if (top)
|
|
||||||
*top = priv->top;
|
|
||||||
|
|
||||||
if (right)
|
|
||||||
*right = priv->right;
|
|
||||||
|
|
||||||
if (bottom)
|
|
||||||
*bottom = priv->bottom;
|
|
||||||
|
|
||||||
if (left)
|
|
||||||
*left = priv->left;
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
/*
|
|
||||||
* st-texture-frame.h: Expandible texture actor
|
|
||||||
*
|
|
||||||
* Copyright 2007, 2008 OpenedHand Ltd
|
|
||||||
* Copyright 2009 Intel Corporation.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU Lesser General Public License,
|
|
||||||
* version 2.1, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
|
||||||
#error "Only <st/st.h> can be included directly.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __ST_TEXTURE_FRAME_H__
|
|
||||||
#define __ST_TEXTURE_FRAME_H__
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define ST_TYPE_TEXTURE_FRAME (st_texture_frame_get_type ())
|
|
||||||
#define ST_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFrame))
|
|
||||||
#define ST_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_TEXTURE_FRAME, StTextureFrameClass))
|
|
||||||
#define ST_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_TEXTURE_FRAME))
|
|
||||||
#define ST_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_TEXTURE_FRAME))
|
|
||||||
#define ST_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFrameClass))
|
|
||||||
|
|
||||||
typedef struct _StTextureFrame StTextureFrame;
|
|
||||||
typedef struct _StTextureFramePrivate StTextureFramePrivate;
|
|
||||||
typedef struct _StTextureFrameClass StTextureFrameClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* StTextureFrame:
|
|
||||||
*
|
|
||||||
* The contents of this structure are private and should only be accessed
|
|
||||||
* through the public API.
|
|
||||||
*/
|
|
||||||
struct _StTextureFrame
|
|
||||||
{
|
|
||||||
/*< private >*/
|
|
||||||
ClutterActor parent_instance;
|
|
||||||
|
|
||||||
StTextureFramePrivate *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _StTextureFrameClass
|
|
||||||
{
|
|
||||||
ClutterActorClass parent_class;
|
|
||||||
|
|
||||||
/* padding for future expansion */
|
|
||||||
void (*_clutter_box_1) (void);
|
|
||||||
void (*_clutter_box_2) (void);
|
|
||||||
void (*_clutter_box_3) (void);
|
|
||||||
void (*_clutter_box_4) (void);
|
|
||||||
};
|
|
||||||
|
|
||||||
GType st_texture_frame_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ClutterActor * st_texture_frame_new (ClutterTexture *texture,
|
|
||||||
gfloat top,
|
|
||||||
gfloat right,
|
|
||||||
gfloat bottom,
|
|
||||||
gfloat left);
|
|
||||||
void st_texture_frame_set_parent_texture (StTextureFrame *frame,
|
|
||||||
ClutterTexture *texture);
|
|
||||||
ClutterTexture *st_texture_frame_get_parent_texture (StTextureFrame *frame);
|
|
||||||
void st_texture_frame_set_frame (StTextureFrame *frame,
|
|
||||||
gfloat top,
|
|
||||||
gfloat right,
|
|
||||||
gfloat bottom,
|
|
||||||
gfloat left);
|
|
||||||
void st_texture_frame_get_frame (StTextureFrame *frame,
|
|
||||||
gfloat *top,
|
|
||||||
gfloat *right,
|
|
||||||
gfloat *bottom,
|
|
||||||
gfloat *left);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __ST_TEXTURE_FRAME_H__ */
|
|
1097
src/st/st-theme-node-drawing.c
Normal file
1097
src/st/st-theme-node-drawing.c
Normal file
File diff suppressed because it is too large
Load Diff
86
src/st/st-theme-node-private.h
Normal file
86
src/st/st-theme-node-private.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
#ifndef __ST_THEME_NODE_PRIVATE_H__
|
||||||
|
#define __ST_THEME_NODE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
|
#include "st-theme-node.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
struct _StThemeNode {
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
StThemeContext *context;
|
||||||
|
StThemeNode *parent_node;
|
||||||
|
StTheme *theme;
|
||||||
|
|
||||||
|
PangoFontDescription *font_desc;
|
||||||
|
|
||||||
|
ClutterColor background_color;
|
||||||
|
/* If gradient is set, then background_color is the gradient start */
|
||||||
|
StGradientType background_gradient_type;
|
||||||
|
ClutterColor background_gradient_end;
|
||||||
|
|
||||||
|
ClutterColor foreground_color;
|
||||||
|
ClutterColor border_color[4];
|
||||||
|
|
||||||
|
int border_width[4];
|
||||||
|
int border_radius[4];
|
||||||
|
guint padding[4];
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int min_width;
|
||||||
|
int min_height;
|
||||||
|
int max_width;
|
||||||
|
int max_height;
|
||||||
|
|
||||||
|
char *background_image;
|
||||||
|
StBorderImage *border_image;
|
||||||
|
StShadow *shadow;
|
||||||
|
|
||||||
|
GType element_type;
|
||||||
|
char *element_id;
|
||||||
|
char *element_class;
|
||||||
|
char *pseudo_class;
|
||||||
|
char *inline_style;
|
||||||
|
|
||||||
|
CRDeclaration **properties;
|
||||||
|
int n_properties;
|
||||||
|
|
||||||
|
/* We hold onto these separately so we can destroy them on finalize */
|
||||||
|
CRDeclaration *inline_properties;
|
||||||
|
|
||||||
|
guint properties_computed : 1;
|
||||||
|
guint geometry_computed : 1;
|
||||||
|
guint background_computed : 1;
|
||||||
|
guint foreground_computed : 1;
|
||||||
|
guint border_image_computed : 1;
|
||||||
|
guint shadow_computed : 1;
|
||||||
|
guint link_type : 2;
|
||||||
|
|
||||||
|
/* Graphics state */
|
||||||
|
float alloc_width;
|
||||||
|
float alloc_height;
|
||||||
|
|
||||||
|
CoglHandle shadow_material;
|
||||||
|
CoglHandle background_texture;
|
||||||
|
CoglHandle border_texture;
|
||||||
|
CoglHandle corner_texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StThemeNodeClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void _st_theme_node_ensure_background (StThemeNode *node);
|
||||||
|
void _st_theme_node_ensure_geometry (StThemeNode *node);
|
||||||
|
|
||||||
|
void _st_theme_node_init_drawing_state (StThemeNode *node);
|
||||||
|
void _st_theme_node_free_drawing_state (StThemeNode *node);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_THEME_NODE_PRIVATE_H__ */
|
@ -5,70 +5,12 @@
|
|||||||
|
|
||||||
#include "st-theme-private.h"
|
#include "st-theme-private.h"
|
||||||
#include "st-theme-context.h"
|
#include "st-theme-context.h"
|
||||||
#include "st-theme-node.h"
|
#include "st-theme-node-private.h"
|
||||||
|
|
||||||
static void st_theme_node_init (StThemeNode *node);
|
static void st_theme_node_init (StThemeNode *node);
|
||||||
static void st_theme_node_class_init (StThemeNodeClass *klass);
|
static void st_theme_node_class_init (StThemeNodeClass *klass);
|
||||||
static void st_theme_node_finalize (GObject *object);
|
static void st_theme_node_finalize (GObject *object);
|
||||||
|
|
||||||
struct _StThemeNode {
|
|
||||||
GObject parent;
|
|
||||||
|
|
||||||
StThemeContext *context;
|
|
||||||
StThemeNode *parent_node;
|
|
||||||
StTheme *theme;
|
|
||||||
|
|
||||||
PangoFontDescription *font_desc;
|
|
||||||
|
|
||||||
ClutterColor background_color;
|
|
||||||
/* If gradient is set, then background_color is the gradient start */
|
|
||||||
StGradientType background_gradient_type;
|
|
||||||
ClutterColor background_gradient_end;
|
|
||||||
|
|
||||||
ClutterColor foreground_color;
|
|
||||||
ClutterColor border_color[4];
|
|
||||||
|
|
||||||
int border_width[4];
|
|
||||||
int border_radius[4];
|
|
||||||
guint padding[4];
|
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int min_width;
|
|
||||||
int min_height;
|
|
||||||
int max_width;
|
|
||||||
int max_height;
|
|
||||||
|
|
||||||
char *background_image;
|
|
||||||
StBorderImage *border_image;
|
|
||||||
StShadow *shadow;
|
|
||||||
|
|
||||||
GType element_type;
|
|
||||||
char *element_id;
|
|
||||||
char *element_class;
|
|
||||||
char *pseudo_class;
|
|
||||||
char *inline_style;
|
|
||||||
|
|
||||||
CRDeclaration **properties;
|
|
||||||
int n_properties;
|
|
||||||
|
|
||||||
/* We hold onto these separately so we can destroy them on finalize */
|
|
||||||
CRDeclaration *inline_properties;
|
|
||||||
|
|
||||||
guint properties_computed : 1;
|
|
||||||
guint geometry_computed : 1;
|
|
||||||
guint background_computed : 1;
|
|
||||||
guint foreground_computed : 1;
|
|
||||||
guint border_image_computed : 1;
|
|
||||||
guint shadow_computed : 1;
|
|
||||||
guint link_type : 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _StThemeNodeClass {
|
|
||||||
GObjectClass parent_class;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static const ClutterColor BLACK_COLOR = { 0, 0, 0, 0xff };
|
static const ClutterColor BLACK_COLOR = { 0, 0, 0, 0xff };
|
||||||
static const ClutterColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
|
static const ClutterColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
@ -77,6 +19,7 @@ G_DEFINE_TYPE (StThemeNode, st_theme_node, G_TYPE_OBJECT)
|
|||||||
static void
|
static void
|
||||||
st_theme_node_init (StThemeNode *node)
|
st_theme_node_init (StThemeNode *node)
|
||||||
{
|
{
|
||||||
|
_st_theme_node_init_drawing_state (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -131,6 +74,8 @@ st_theme_node_finalize (GObject *object)
|
|||||||
if (node->background_image)
|
if (node->background_image)
|
||||||
g_free (node->background_image);
|
g_free (node->background_image);
|
||||||
|
|
||||||
|
_st_theme_node_free_drawing_state (node);
|
||||||
|
|
||||||
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
|
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +204,7 @@ st_theme_node_get_pseudo_class (StThemeNode *node)
|
|||||||
return node->pseudo_class;
|
return node->pseudo_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
ensure_properties (StThemeNode *node)
|
ensure_properties (StThemeNode *node)
|
||||||
{
|
{
|
||||||
if (!node->properties_computed)
|
if (!node->properties_computed)
|
||||||
@ -1108,8 +1053,8 @@ do_size_property (StThemeNode *node,
|
|||||||
get_length_from_term_int (node, decl->value, FALSE, node_value);
|
get_length_from_term_int (node, decl->value, FALSE, node_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
ensure_geometry (StThemeNode *node)
|
_st_theme_node_ensure_geometry (StThemeNode *node)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@ -1192,7 +1137,7 @@ st_theme_node_get_border_width (StThemeNode *node,
|
|||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
||||||
g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
|
g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
return node->border_width[side];
|
return node->border_width[side];
|
||||||
}
|
}
|
||||||
@ -1204,7 +1149,7 @@ st_theme_node_get_border_radius (StThemeNode *node,
|
|||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
||||||
g_return_val_if_fail (corner >= ST_CORNER_TOPLEFT && corner <= ST_CORNER_BOTTOMLEFT, 0.);
|
g_return_val_if_fail (corner >= ST_CORNER_TOPLEFT && corner <= ST_CORNER_BOTTOMLEFT, 0.);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
return node->border_radius[corner];
|
return node->border_radius[corner];
|
||||||
}
|
}
|
||||||
@ -1214,7 +1159,7 @@ st_theme_node_get_width (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->width;
|
return node->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1223,7 +1168,7 @@ st_theme_node_get_height (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->height;
|
return node->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,7 +1177,7 @@ st_theme_node_get_min_width (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->min_width;
|
return node->min_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1241,7 +1186,7 @@ st_theme_node_get_min_height (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->min_height;
|
return node->min_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1250,7 +1195,7 @@ st_theme_node_get_max_width (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->max_width;
|
return node->max_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,7 +1204,7 @@ st_theme_node_get_max_height (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
return node->max_height;
|
return node->max_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,8 +1226,8 @@ get_background_color_from_term (StThemeNode *node,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
ensure_background (StThemeNode *node)
|
_st_theme_node_ensure_background (StThemeNode *node)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1429,7 +1374,7 @@ st_theme_node_get_background_color (StThemeNode *node,
|
|||||||
{
|
{
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
|
|
||||||
ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
|
|
||||||
*color = node->background_color;
|
*color = node->background_color;
|
||||||
}
|
}
|
||||||
@ -1439,7 +1384,7 @@ st_theme_node_get_background_image (StThemeNode *node)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
|
|
||||||
return node->background_image;
|
return node->background_image;
|
||||||
}
|
}
|
||||||
@ -1500,7 +1445,7 @@ st_theme_node_get_background_gradient (StThemeNode *node,
|
|||||||
{
|
{
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
|
|
||||||
ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
|
|
||||||
*type = node->background_gradient_type;
|
*type = node->background_gradient_type;
|
||||||
if (*type != ST_GRADIENT_NONE)
|
if (*type != ST_GRADIENT_NONE)
|
||||||
@ -1518,7 +1463,7 @@ st_theme_node_get_border_color (StThemeNode *node,
|
|||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
g_return_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT);
|
g_return_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
*color = node->border_color[side];
|
*color = node->border_color[side];
|
||||||
}
|
}
|
||||||
@ -1530,7 +1475,7 @@ st_theme_node_get_padding (StThemeNode *node,
|
|||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
|
||||||
g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
|
g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
return node->padding[side];
|
return node->padding[side];
|
||||||
}
|
}
|
||||||
@ -2353,7 +2298,7 @@ st_theme_node_adjust_preferred_width (StThemeNode *node,
|
|||||||
|
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
width_inc = get_width_inc (node);
|
width_inc = get_width_inc (node);
|
||||||
|
|
||||||
@ -2420,7 +2365,7 @@ st_theme_node_adjust_preferred_height (StThemeNode *node,
|
|||||||
|
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
height_inc = get_height_inc (node);
|
height_inc = get_height_inc (node);
|
||||||
|
|
||||||
@ -2461,7 +2406,7 @@ st_theme_node_get_content_box (StThemeNode *node,
|
|||||||
|
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
|
|
||||||
avail_width = allocation->x2 - allocation->x1;
|
avail_width = allocation->x2 - allocation->x1;
|
||||||
avail_height = allocation->y2 - allocation->y1;
|
avail_height = allocation->y2 - allocation->y1;
|
||||||
@ -2501,8 +2446,8 @@ st_theme_node_geometry_equal (StThemeNode *node,
|
|||||||
{
|
{
|
||||||
StSide side;
|
StSide side;
|
||||||
|
|
||||||
ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
ensure_geometry (other);
|
_st_theme_node_ensure_geometry (other);
|
||||||
|
|
||||||
for (side = ST_SIDE_TOP; side <= ST_SIDE_LEFT; side++)
|
for (side = ST_SIDE_TOP; side <= ST_SIDE_LEFT; side++)
|
||||||
{
|
{
|
||||||
|
@ -171,6 +171,11 @@ void st_theme_node_get_content_box (StThemeNode *node,
|
|||||||
gboolean st_theme_node_geometry_equal (StThemeNode *node,
|
gboolean st_theme_node_geometry_equal (StThemeNode *node,
|
||||||
StThemeNode *other);
|
StThemeNode *other);
|
||||||
|
|
||||||
|
void st_theme_node_paint (StThemeNode *node,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
guint8 paint_opacity);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __ST_THEME_NODE_H__ */
|
#endif /* __ST_THEME_NODE_H__ */
|
||||||
|
@ -38,9 +38,7 @@
|
|||||||
|
|
||||||
#include "st-marshal.h"
|
#include "st-marshal.h"
|
||||||
#include "st-private.h"
|
#include "st-private.h"
|
||||||
#include "st-shadow-texture.h"
|
|
||||||
#include "st-texture-cache.h"
|
#include "st-texture-cache.h"
|
||||||
#include "st-texture-frame.h"
|
|
||||||
#include "st-theme-context.h"
|
#include "st-theme-context.h"
|
||||||
#include "st-tooltip.h"
|
#include "st-tooltip.h"
|
||||||
|
|
||||||
@ -59,7 +57,6 @@ struct _StWidgetPrivate
|
|||||||
|
|
||||||
ClutterActor *border_image;
|
ClutterActor *border_image;
|
||||||
ClutterActor *background_image;
|
ClutterActor *background_image;
|
||||||
ClutterActor *background_image_shadow;
|
|
||||||
ClutterColor bg_color;
|
ClutterColor bg_color;
|
||||||
|
|
||||||
guint border_width;
|
guint border_width;
|
||||||
@ -68,6 +65,7 @@ struct _StWidgetPrivate
|
|||||||
StGradientType bg_gradient_type;
|
StGradientType bg_gradient_type;
|
||||||
ClutterColor bg_gradient_end;
|
ClutterColor bg_gradient_end;
|
||||||
|
|
||||||
|
ClutterActorBox background_allocation;
|
||||||
gdouble shadow_xoffset;
|
gdouble shadow_xoffset;
|
||||||
gdouble shadow_yoffset;
|
gdouble shadow_yoffset;
|
||||||
|
|
||||||
@ -125,7 +123,6 @@ G_DEFINE_ABSTRACT_TYPE (StWidget, st_widget, CLUTTER_TYPE_ACTOR);
|
|||||||
|
|
||||||
static void st_widget_recompute_style (StWidget *widget,
|
static void st_widget_recompute_style (StWidget *widget,
|
||||||
StThemeNode *old_theme_node);
|
StThemeNode *old_theme_node);
|
||||||
static void st_widget_redraw_gradient (StWidget *widget);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_widget_set_property (GObject *gobject,
|
st_widget_set_property (GObject *gobject,
|
||||||
@ -254,12 +251,6 @@ st_widget_dispose (GObject *gobject)
|
|||||||
priv->border_image = NULL;
|
priv->border_image = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->background_image_shadow)
|
|
||||||
{
|
|
||||||
clutter_actor_unparent (priv->background_image_shadow);
|
|
||||||
priv->background_image_shadow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->theme_node)
|
if (priv->theme_node)
|
||||||
{
|
{
|
||||||
g_object_unref (priv->theme_node);
|
g_object_unref (priv->theme_node);
|
||||||
@ -295,18 +286,20 @@ st_widget_finalize (GObject *gobject)
|
|||||||
G_OBJECT_CLASS (st_widget_parent_class)->finalize (gobject);
|
G_OBJECT_CLASS (st_widget_parent_class)->finalize (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_widget_allocate (ClutterActor *actor,
|
st_widget_allocate (ClutterActor *actor,
|
||||||
const ClutterActorBox *box,
|
const ClutterActorBox *box,
|
||||||
ClutterAllocationFlags flags)
|
ClutterAllocationFlags flags)
|
||||||
{
|
{
|
||||||
StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
|
StWidget *self = ST_WIDGET (actor);
|
||||||
|
StWidgetPrivate *priv = self->priv;
|
||||||
StThemeNode *theme_node;
|
StThemeNode *theme_node;
|
||||||
ClutterActorClass *klass;
|
ClutterActorClass *klass;
|
||||||
ClutterGeometry area;
|
ClutterGeometry area;
|
||||||
ClutterVertex in_v, out_v;
|
ClutterVertex in_v, out_v;
|
||||||
|
|
||||||
theme_node = st_widget_get_theme_node ((StWidget*) actor);
|
theme_node = st_widget_get_theme_node (self);
|
||||||
|
|
||||||
klass = CLUTTER_ACTOR_CLASS (st_widget_parent_class);
|
klass = CLUTTER_ACTOR_CLASS (st_widget_parent_class);
|
||||||
klass->allocate (actor, box, flags);
|
klass->allocate (actor, box, flags);
|
||||||
@ -327,249 +320,20 @@ st_widget_allocate (ClutterActor *actor,
|
|||||||
|
|
||||||
st_tooltip_set_tip_area (priv->tooltip, &area);
|
st_tooltip_set_tip_area (priv->tooltip, &area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (priv->border_image && priv->bg_gradient_type == ST_GRADIENT_NONE)
|
|
||||||
{
|
|
||||||
ClutterActorBox frame_box;
|
|
||||||
|
|
||||||
frame_box.x1 = frame_box.y1 = 0;
|
|
||||||
frame_box.x2 = box->x2 - box->x1;
|
|
||||||
frame_box.y2 = box->y2 - box->y1;
|
|
||||||
|
|
||||||
clutter_actor_allocate (CLUTTER_ACTOR (priv->border_image),
|
|
||||||
&frame_box,
|
|
||||||
flags);
|
|
||||||
}
|
|
||||||
else if (priv->bg_gradient_type != ST_GRADIENT_NONE)
|
|
||||||
{
|
|
||||||
guint width, old_width,
|
|
||||||
height, old_height;
|
|
||||||
ClutterActorBox frame_box;
|
|
||||||
|
|
||||||
frame_box.x1 = frame_box.y1 = 0;
|
|
||||||
frame_box.x2 = box->x2 - box->x1;
|
|
||||||
frame_box.y2 = box->y2 - box->y1;
|
|
||||||
|
|
||||||
width = (guint)(0.5 + frame_box.x2);
|
|
||||||
height = (guint)(0.5 + frame_box.y2);
|
|
||||||
|
|
||||||
clutter_cairo_texture_get_surface_size (CLUTTER_CAIRO_TEXTURE (priv->border_image),
|
|
||||||
&old_width, &old_height);
|
|
||||||
|
|
||||||
if (width > 0 && height > 0 &&
|
|
||||||
(old_width != width || old_height != height))
|
|
||||||
{
|
|
||||||
|
|
||||||
clutter_cairo_texture_set_surface_size (CLUTTER_CAIRO_TEXTURE (priv->border_image),
|
|
||||||
width, height);
|
|
||||||
st_widget_redraw_gradient ((StWidget*) actor);
|
|
||||||
}
|
|
||||||
clutter_actor_allocate (CLUTTER_ACTOR (priv->border_image),
|
|
||||||
&frame_box,
|
|
||||||
flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->background_image)
|
|
||||||
{
|
|
||||||
ClutterActorBox frame_box;
|
|
||||||
gfloat w, h;
|
|
||||||
|
|
||||||
frame_box.x1 = frame_box.y1 = 0;
|
|
||||||
frame_box.x2 = box->x2 - box->x1;
|
|
||||||
frame_box.y2 = box->y2 - box->y1;
|
|
||||||
|
|
||||||
clutter_actor_get_size (CLUTTER_ACTOR (priv->background_image), &w, &h);
|
|
||||||
|
|
||||||
/* scale the background into the allocated bounds */
|
|
||||||
if (w > frame_box.x2 || h > frame_box.y2)
|
|
||||||
{
|
|
||||||
gint new_h, new_w, offset;
|
|
||||||
gint box_w, box_h;
|
|
||||||
|
|
||||||
box_w = (int) frame_box.x2;
|
|
||||||
box_h = (int) frame_box.y2;
|
|
||||||
|
|
||||||
/* scale to fit */
|
|
||||||
new_h = (int)((h / w) * ((gfloat) box_w));
|
|
||||||
new_w = (int)((w / h) * ((gfloat) box_h));
|
|
||||||
|
|
||||||
if (new_h > box_h)
|
|
||||||
{
|
|
||||||
/* center for new width */
|
|
||||||
offset = ((box_w) - new_w) * 0.5;
|
|
||||||
frame_box.x1 = offset;
|
|
||||||
frame_box.x2 = offset + new_w;
|
|
||||||
|
|
||||||
frame_box.y2 = box_h;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* center for new height */
|
|
||||||
offset = ((box_h) - new_h) * 0.5;
|
|
||||||
frame_box.y1 = offset;
|
|
||||||
frame_box.y2 = offset + new_h;
|
|
||||||
|
|
||||||
frame_box.x2 = box_w;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* center the background on the widget */
|
|
||||||
frame_box.x1 = (int)(((box->x2 - box->x1) / 2) - (w / 2));
|
|
||||||
frame_box.y1 = (int)(((box->y2 - box->y1) / 2) - (h / 2));
|
|
||||||
frame_box.x2 = frame_box.x1 + w;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_widget_real_draw_background (StWidget *self)
|
st_widget_paint (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
StWidgetPrivate *priv = self->priv;
|
StWidget *self = ST_WIDGET (actor);
|
||||||
ClutterActor *actor = CLUTTER_ACTOR (self);
|
StThemeNode *theme_node;
|
||||||
ClutterActorBox allocation = { 0, };
|
ClutterActorBox allocation;
|
||||||
gfloat w, h;
|
|
||||||
guint8 opacity;
|
theme_node = st_widget_get_theme_node (self);
|
||||||
|
|
||||||
clutter_actor_get_allocation_box (actor, &allocation);
|
clutter_actor_get_allocation_box (actor, &allocation);
|
||||||
w = allocation.x2 - allocation.x1;
|
|
||||||
h = allocation.y2 - allocation.y1;
|
|
||||||
|
|
||||||
opacity = clutter_actor_get_paint_opacity (actor);
|
st_theme_node_paint (theme_node, &allocation, clutter_actor_get_paint_opacity (actor));
|
||||||
|
|
||||||
/* Default implementation just draws the background
|
|
||||||
* colour and the image on top
|
|
||||||
*/
|
|
||||||
if (priv->draw_bg_color)
|
|
||||||
{
|
|
||||||
ClutterColor bg_color = priv->bg_color;
|
|
||||||
|
|
||||||
bg_color.alpha = opacity * bg_color.alpha / 255;
|
|
||||||
|
|
||||||
cogl_set_source_color4ub (bg_color.red,
|
|
||||||
bg_color.green,
|
|
||||||
bg_color.blue,
|
|
||||||
bg_color.alpha);
|
|
||||||
cogl_rectangle (0, 0, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->draw_border_internal)
|
|
||||||
{
|
|
||||||
StThemeNode *node = st_widget_get_theme_node (self);
|
|
||||||
int side;
|
|
||||||
double border_top, border_right, border_bottom, border_left;
|
|
||||||
|
|
||||||
border_top = st_theme_node_get_border_width (node, ST_SIDE_TOP);
|
|
||||||
border_right = st_theme_node_get_border_width (node, ST_SIDE_RIGHT);
|
|
||||||
border_bottom = st_theme_node_get_border_width (node, ST_SIDE_BOTTOM);
|
|
||||||
border_left = st_theme_node_get_border_width (node, ST_SIDE_LEFT);
|
|
||||||
|
|
||||||
for (side = 0; side < 4; side++)
|
|
||||||
{
|
|
||||||
ClutterColor color;
|
|
||||||
|
|
||||||
switch (side)
|
|
||||||
{
|
|
||||||
case ST_SIDE_TOP:
|
|
||||||
if (border_top <= 0)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case ST_SIDE_RIGHT:
|
|
||||||
if (border_right <= 0)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case ST_SIDE_BOTTOM:
|
|
||||||
if (border_bottom <= 0)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case ST_SIDE_LEFT:
|
|
||||||
if (border_left <= 0)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
st_theme_node_get_border_color (node, side, &color);
|
|
||||||
|
|
||||||
color.alpha = (color.alpha * opacity) / 0xff;
|
|
||||||
|
|
||||||
cogl_set_source_color4ub (color.red,
|
|
||||||
color.green,
|
|
||||||
color.blue,
|
|
||||||
color.alpha);
|
|
||||||
|
|
||||||
/* Note top and bottom extend to the ends, left/right
|
|
||||||
* are constrained by them. See comment above about CSS
|
|
||||||
* conformance.
|
|
||||||
*/
|
|
||||||
switch (side)
|
|
||||||
{
|
|
||||||
case ST_SIDE_TOP:
|
|
||||||
cogl_rectangle (0, 0,
|
|
||||||
w, border_top);
|
|
||||||
break;
|
|
||||||
case ST_SIDE_RIGHT:
|
|
||||||
cogl_rectangle (w - border_right, border_top,
|
|
||||||
w, h - border_bottom);
|
|
||||||
break;
|
|
||||||
case ST_SIDE_BOTTOM:
|
|
||||||
cogl_rectangle (0, h - border_bottom,
|
|
||||||
w, h);
|
|
||||||
break;
|
|
||||||
case ST_SIDE_LEFT:
|
|
||||||
cogl_rectangle (0, border_top,
|
|
||||||
border_left, h - border_bottom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->border_image)
|
|
||||||
clutter_actor_paint (priv->border_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
st_widget_paint (ClutterActor *self)
|
|
||||||
{
|
|
||||||
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
|
|
||||||
|
|
||||||
st_widget_real_draw_background (ST_WIDGET (self));
|
|
||||||
|
|
||||||
if (priv->background_image != NULL)
|
|
||||||
{
|
|
||||||
if (priv->background_image_shadow)
|
|
||||||
clutter_actor_paint (priv->background_image_shadow);
|
|
||||||
clutter_actor_paint (priv->background_image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -599,9 +363,6 @@ st_widget_map (ClutterActor *actor)
|
|||||||
|
|
||||||
st_widget_ensure_style ((StWidget*) actor);
|
st_widget_ensure_style ((StWidget*) actor);
|
||||||
|
|
||||||
if (priv->background_image_shadow)
|
|
||||||
clutter_actor_map (priv->background_image_shadow);
|
|
||||||
|
|
||||||
if (priv->border_image)
|
if (priv->border_image)
|
||||||
clutter_actor_map (priv->border_image);
|
clutter_actor_map (priv->border_image);
|
||||||
|
|
||||||
@ -619,9 +380,6 @@ st_widget_unmap (ClutterActor *actor)
|
|||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (st_widget_parent_class)->unmap (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)
|
if (priv->border_image)
|
||||||
clutter_actor_unmap (priv->border_image);
|
clutter_actor_unmap (priv->border_image);
|
||||||
|
|
||||||
@ -632,125 +390,6 @@ st_widget_unmap (ClutterActor *actor)
|
|||||||
clutter_actor_unmap ((ClutterActor *) priv->tooltip);
|
clutter_actor_unmap ((ClutterActor *) priv->tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
st_widget_redraw_gradient (StWidget *widget)
|
|
||||||
{
|
|
||||||
ClutterCairoTexture *texture;
|
|
||||||
ClutterColor *start, *end;
|
|
||||||
StWidgetPrivate *priv;
|
|
||||||
guint width, height;
|
|
||||||
guint radius[4], i;
|
|
||||||
cairo_t *cr;
|
|
||||||
cairo_pattern_t *pattern;
|
|
||||||
gboolean round_border = FALSE;
|
|
||||||
|
|
||||||
if (widget->priv->bg_gradient_type == ST_GRADIENT_NONE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
texture = CLUTTER_CAIRO_TEXTURE (widget->priv->border_image);
|
|
||||||
priv = widget->priv;
|
|
||||||
start = &widget->priv->bg_color;
|
|
||||||
end = &widget->priv->bg_gradient_end;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
radius[i] = st_theme_node_get_border_radius (priv->theme_node, i);
|
|
||||||
if (radius[i] > 0)
|
|
||||||
round_border = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
|
||||||
clutter_cairo_texture_clear (texture);
|
|
||||||
cr = clutter_cairo_texture_create (texture);
|
|
||||||
|
|
||||||
if (priv->bg_gradient_type == ST_GRADIENT_VERTICAL)
|
|
||||||
pattern = cairo_pattern_create_linear (0, 0, 0, height);
|
|
||||||
else if (priv->bg_gradient_type == ST_GRADIENT_HORIZONTAL)
|
|
||||||
pattern = cairo_pattern_create_linear (0, 0, width, 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdouble cx, cy;
|
|
||||||
|
|
||||||
cx = width / 2.;
|
|
||||||
cy = height / 2.;
|
|
||||||
pattern = cairo_pattern_create_radial (cx, cy, 0, cx, cy, MIN (cx, cy));
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_pattern_add_color_stop_rgba (pattern, 0,
|
|
||||||
start->red / 255.,
|
|
||||||
start->green / 255.,
|
|
||||||
start->blue / 255.,
|
|
||||||
start->alpha / 255.);
|
|
||||||
cairo_pattern_add_color_stop_rgba (pattern, 1,
|
|
||||||
end->red / 255.,
|
|
||||||
end->green / 255.,
|
|
||||||
end->blue / 255.,
|
|
||||||
end->alpha / 255.);
|
|
||||||
|
|
||||||
if (round_border)
|
|
||||||
{
|
|
||||||
if (radius[ST_CORNER_TOPLEFT] > 0)
|
|
||||||
cairo_arc (cr,
|
|
||||||
radius[ST_CORNER_TOPLEFT],
|
|
||||||
radius[ST_CORNER_TOPLEFT],
|
|
||||||
radius[ST_CORNER_TOPLEFT], M_PI, 3 * M_PI / 2);
|
|
||||||
else
|
|
||||||
cairo_move_to (cr, 0, 0);
|
|
||||||
cairo_line_to (cr, width - radius[ST_CORNER_TOPRIGHT], 0);
|
|
||||||
if (radius[ST_CORNER_TOPRIGHT] > 0)
|
|
||||||
cairo_arc (cr,
|
|
||||||
width - radius[ST_CORNER_TOPRIGHT],
|
|
||||||
radius[ST_CORNER_TOPRIGHT],
|
|
||||||
radius[ST_CORNER_TOPRIGHT], 3 * M_PI / 2, 2 * M_PI);
|
|
||||||
cairo_line_to (cr, width, height - radius[ST_CORNER_BOTTOMRIGHT]);
|
|
||||||
if (radius[ST_CORNER_BOTTOMRIGHT])
|
|
||||||
cairo_arc (cr,
|
|
||||||
width - radius[ST_CORNER_BOTTOMRIGHT],
|
|
||||||
height - radius[ST_CORNER_BOTTOMRIGHT],
|
|
||||||
radius[ST_CORNER_BOTTOMRIGHT], 0, M_PI / 2);
|
|
||||||
cairo_line_to (cr, radius[ST_CORNER_BOTTOMLEFT], height);
|
|
||||||
if (radius[ST_CORNER_BOTTOMLEFT])
|
|
||||||
cairo_arc (cr,
|
|
||||||
radius[ST_CORNER_BOTTOMLEFT],
|
|
||||||
height - radius[ST_CORNER_BOTTOMLEFT],
|
|
||||||
radius[ST_CORNER_BOTTOMLEFT], M_PI / 2, M_PI);
|
|
||||||
cairo_close_path (cr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cairo_rectangle (cr, 0, 0, width, height);
|
|
||||||
|
|
||||||
if (priv->border_width > 0)
|
|
||||||
{
|
|
||||||
guint8 opacity;
|
|
||||||
gdouble effective_alpha;
|
|
||||||
cairo_path_t *path;
|
|
||||||
|
|
||||||
path = cairo_copy_path (cr);
|
|
||||||
opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (widget));
|
|
||||||
effective_alpha = priv->border_color.alpha * opacity / (255. * 255.);
|
|
||||||
|
|
||||||
cairo_set_source_rgba (cr,
|
|
||||||
priv->border_color.red / 255.,
|
|
||||||
priv->border_color.green / 255.,
|
|
||||||
priv->border_color.blue / 255.,
|
|
||||||
effective_alpha);
|
|
||||||
cairo_fill (cr);
|
|
||||||
|
|
||||||
cairo_translate (cr, priv->border_width, priv->border_width);
|
|
||||||
cairo_scale (cr,
|
|
||||||
(gdouble)(width - 2 * priv->border_width) / width,
|
|
||||||
(gdouble)(height - 2 * priv->border_width) / height);
|
|
||||||
cairo_append_path (cr, path);
|
|
||||||
cairo_path_destroy (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_set_source (cr, pattern);
|
|
||||||
cairo_fill (cr);
|
|
||||||
|
|
||||||
cairo_pattern_destroy (pattern);
|
|
||||||
cairo_destroy (cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void notify_children_of_style_change (ClutterContainer *container);
|
static void notify_children_of_style_change (ClutterContainer *container);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -776,270 +415,12 @@ static void
|
|||||||
st_widget_real_style_changed (StWidget *self)
|
st_widget_real_style_changed (StWidget *self)
|
||||||
{
|
{
|
||||||
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
|
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
|
||||||
StThemeNode *theme_node;
|
|
||||||
StBorderImage *border_image;
|
|
||||||
StShadow *shadow;
|
|
||||||
StTextureCache *texture_cache;
|
|
||||||
ClutterTexture *texture;
|
|
||||||
const char *bg_file = NULL;
|
|
||||||
gboolean relayout_needed = FALSE;
|
|
||||||
gboolean has_changed = FALSE;
|
|
||||||
ClutterColor color;
|
|
||||||
guint border_radius = 0;
|
|
||||||
StGradientType gradient;
|
|
||||||
ClutterColor gradient_end;
|
|
||||||
StSide side;
|
|
||||||
StCorner corner;
|
|
||||||
gboolean uniform_border_width;
|
|
||||||
|
|
||||||
/* application has request this widget is not stylable */
|
/* application has request this widget is not stylable */
|
||||||
if (!priv->is_stylable)
|
if (!priv->is_stylable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
theme_node = st_widget_get_theme_node (self);
|
|
||||||
|
|
||||||
st_theme_node_get_background_gradient (theme_node, &gradient, &color, &gradient_end);
|
|
||||||
|
|
||||||
if (gradient == ST_GRADIENT_NONE)
|
|
||||||
{
|
|
||||||
st_theme_node_get_background_color (theme_node, &color);
|
|
||||||
if (gradient != priv->bg_gradient_type ||
|
|
||||||
!clutter_color_equal (&color, &priv->bg_color))
|
|
||||||
{
|
|
||||||
priv->bg_gradient_type = gradient;
|
|
||||||
priv->bg_color = color;
|
|
||||||
priv->draw_bg_color = color.alpha != 0;
|
|
||||||
has_changed = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (gradient != priv->bg_gradient_type ||
|
|
||||||
!clutter_color_equal (&color, &priv->bg_color) ||
|
|
||||||
!clutter_color_equal (&gradient_end, &priv->bg_gradient_end))
|
|
||||||
{
|
|
||||||
priv->bg_gradient_type = gradient;
|
|
||||||
priv->bg_color = color;
|
|
||||||
priv->bg_gradient_end = gradient_end;
|
|
||||||
priv->draw_bg_color = TRUE;
|
|
||||||
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);
|
|
||||||
priv->border_image = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->background_image)
|
|
||||||
{
|
|
||||||
clutter_actor_unparent (priv->background_image);
|
|
||||||
priv->background_image = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture_cache = st_texture_cache_get_default ();
|
|
||||||
|
|
||||||
|
|
||||||
/* Rough notes about the relationship of borders and backgrounds in CSS3;
|
|
||||||
* see http://www.w3.org/TR/css3-background/ for more accurate details.
|
|
||||||
*
|
|
||||||
* - Things are drawn in 4 layers, from the bottom:
|
|
||||||
* Background color
|
|
||||||
* Background image
|
|
||||||
* Border color or border image
|
|
||||||
* Content
|
|
||||||
* - The background color, gradient and image extend to and are clipped by
|
|
||||||
* the edge of the border area, so will be rounded if the border is
|
|
||||||
* rounded. (CSS3 background-clip property modifies this)
|
|
||||||
* - The border image replaces what would normally be drawn by the border
|
|
||||||
* - The border image is not clipped by a rounded border-radius
|
|
||||||
* - The border radius rounds the background even if the border is
|
|
||||||
* zero width or a border image is being used.
|
|
||||||
*
|
|
||||||
* Deviations from the above as implemented here:
|
|
||||||
* - Nonuniform border widths combined with a non-zero border radius result
|
|
||||||
* in the border radius being ignored
|
|
||||||
* - The combination of border image and a non-zero border radius is
|
|
||||||
* not supported; the background color will be drawn with square
|
|
||||||
* corners.
|
|
||||||
* - The combination of border image and a background gradient is not
|
|
||||||
* supported; the background will be drawn as a solid color
|
|
||||||
* - The background image is drawn above the border color or image,
|
|
||||||
* not below it.
|
|
||||||
* - We don't clip the background image to the (rounded) border area.
|
|
||||||
*
|
|
||||||
* The first three allow us to always draw with no more than a single
|
|
||||||
* border_image and a single background image above it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check whether all border widths are the same. Also, acquire the
|
|
||||||
* first nonzero border width as well as the border color.
|
|
||||||
*/
|
|
||||||
uniform_border_width = TRUE;
|
|
||||||
priv->border_width = st_theme_node_get_border_width (theme_node,
|
|
||||||
ST_SIDE_TOP);
|
|
||||||
if (priv->border_width > 0.5)
|
|
||||||
priv->border_width = (int)(0.5 + priv->border_width);
|
|
||||||
for (side = 0; side < 4; side++)
|
|
||||||
{
|
|
||||||
double width = st_theme_node_get_border_width (theme_node, side);
|
|
||||||
if (width > 0.5)
|
|
||||||
width = (int)(0.5 + width);
|
|
||||||
if (width > 0)
|
|
||||||
{
|
|
||||||
priv->border_width = width;
|
|
||||||
st_theme_node_get_border_color (theme_node,
|
|
||||||
side, &priv->border_color);
|
|
||||||
}
|
|
||||||
if ((int)width != priv->border_width)
|
|
||||||
{
|
|
||||||
uniform_border_width = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pick the first nonzero border radius, but only if we have a uniform border. */
|
|
||||||
if (uniform_border_width)
|
|
||||||
{
|
|
||||||
for (corner = 0; corner < 4; corner++)
|
|
||||||
{
|
|
||||||
double radius = st_theme_node_get_border_radius (theme_node, corner);
|
|
||||||
if (radius > 0.5)
|
|
||||||
{
|
|
||||||
border_radius = (int)(0.5 + radius);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
border_image = st_theme_node_get_border_image (theme_node);
|
|
||||||
if (border_image)
|
|
||||||
{
|
|
||||||
const char *filename;
|
|
||||||
gint border_left, border_right, border_top, border_bottom;
|
|
||||||
gint width, height;
|
|
||||||
|
|
||||||
filename = st_border_image_get_filename (border_image);
|
|
||||||
|
|
||||||
/* `border-image' takes precedence over `background-image'.
|
|
||||||
* Firefox lets the background-image shine thru when border-image has
|
|
||||||
* alpha an channel, maybe that would be an option for the future. */
|
|
||||||
texture = (ClutterTexture*) st_texture_cache_load_file_simple (texture_cache,
|
|
||||||
filename);
|
|
||||||
|
|
||||||
clutter_texture_get_base_size (CLUTTER_TEXTURE (texture),
|
|
||||||
&width, &height);
|
|
||||||
|
|
||||||
st_border_image_get_borders (border_image,
|
|
||||||
&border_left, &border_right, &border_top, &border_bottom);
|
|
||||||
|
|
||||||
priv->border_image = st_texture_frame_new (texture,
|
|
||||||
border_top,
|
|
||||||
border_right,
|
|
||||||
border_bottom,
|
|
||||||
border_left);
|
|
||||||
clutter_actor_set_parent (priv->border_image, CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
else if (priv->bg_gradient_type != ST_GRADIENT_NONE)
|
|
||||||
{
|
|
||||||
priv->draw_border_internal = FALSE;
|
|
||||||
priv->draw_bg_color = FALSE;
|
|
||||||
texture = g_object_new (CLUTTER_TYPE_CAIRO_TEXTURE, NULL);
|
|
||||||
priv->border_image = CLUTTER_ACTOR (texture);
|
|
||||||
clutter_actor_set_parent (priv->border_image, CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
else if (border_radius > 0)
|
|
||||||
{
|
|
||||||
priv->draw_border_internal = FALSE;
|
|
||||||
priv->draw_bg_color = FALSE;
|
|
||||||
priv->border_image = g_object_new (BIG_TYPE_RECTANGLE,
|
|
||||||
"color", &priv->bg_color,
|
|
||||||
"border-width", priv->border_width,
|
|
||||||
"border-color", &priv->border_color,
|
|
||||||
"corner-radius", border_radius,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
clutter_actor_set_parent (priv->border_image, CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
else if (priv->border_width > 0 && priv->border_color.alpha != 0)
|
|
||||||
{
|
|
||||||
priv->draw_bg_color = TRUE;
|
|
||||||
priv->draw_border_internal = TRUE;
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
else if (priv->draw_border_internal)
|
|
||||||
{
|
|
||||||
priv->draw_border_internal = FALSE;
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bg_file = st_theme_node_get_background_image (theme_node);
|
|
||||||
if (bg_file != NULL)
|
|
||||||
{
|
|
||||||
priv->background_image = st_texture_cache_load_file_simple (texture_cache, bg_file);
|
|
||||||
clutter_actor_set_parent (priv->background_image, CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
has_changed = TRUE;
|
|
||||||
relayout_needed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
if (relayout_needed)
|
|
||||||
clutter_actor_queue_relayout ((ClutterActor *) self);
|
|
||||||
else
|
|
||||||
clutter_actor_queue_redraw ((ClutterActor *) self);
|
clutter_actor_queue_redraw ((ClutterActor *) self);
|
||||||
}
|
|
||||||
|
|
||||||
if (CLUTTER_IS_CONTAINER (self))
|
if (CLUTTER_IS_CONTAINER (self))
|
||||||
notify_children_of_style_change ((ClutterContainer *)self);
|
notify_children_of_style_change ((ClutterContainer *)self);
|
||||||
|
Loading…
Reference in New Issue
Block a user