mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
now just uses meta_gradient_add_alpha (draw_op_as_pixbuf): implement alpha
2002-05-31 Havoc Pennington <hp@redhat.com> * src/theme.c (multiply_alpha): now just uses meta_gradient_add_alpha (draw_op_as_pixbuf): implement alpha gradients for tint, gradient, and image draw ops, so I can implement garrett's stuff. * src/gradient.c (meta_gradient_add_alpha): new function to multiply the alpha channel of a pixbuf by an alpha gradient
This commit is contained in:
parent
8da3b943a9
commit
d4b91dc654
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
2002-05-31 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* src/theme.c (multiply_alpha): now just uses
|
||||
meta_gradient_add_alpha
|
||||
(draw_op_as_pixbuf): implement alpha gradients for tint, gradient,
|
||||
and image draw ops, so I can implement garrett's stuff.
|
||||
|
||||
* src/gradient.c (meta_gradient_add_alpha): new function to
|
||||
multiply the alpha channel of a pixbuf by an alpha gradient
|
||||
|
||||
2002-05-30 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* src/main.c (main): verbose-log on startup whether we were
|
||||
|
173
src/gradient.c
173
src/gradient.c
@ -730,3 +730,176 @@ meta_gradient_create_multi_diagonal (int width, int height,
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
simple_multiply_alpha (GdkPixbuf *pixbuf,
|
||||
guchar alpha)
|
||||
{
|
||||
guchar *pixels;
|
||||
int rowstride;
|
||||
int height;
|
||||
int row;
|
||||
|
||||
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
|
||||
|
||||
if (alpha == 255)
|
||||
return;
|
||||
|
||||
g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
row = 0;
|
||||
while (row < height)
|
||||
{
|
||||
guchar *p;
|
||||
guchar *end;
|
||||
|
||||
p = pixels + row * rowstride;
|
||||
end = p + rowstride;
|
||||
|
||||
while (p != end)
|
||||
{
|
||||
p += 3; /* skip RGB */
|
||||
|
||||
/* multiply the two alpha channels. not sure this is right.
|
||||
* but some end cases are that if the pixbuf contains 255,
|
||||
* then it should be modified to contain "alpha"; if the
|
||||
* pixbuf contains 0, it should remain 0.
|
||||
*/
|
||||
/* ((*p / 255.0) * (alpha / 255.0)) * 255; */
|
||||
*p = (guchar) (((int) *p * (int) alpha) / (int) 255);
|
||||
|
||||
++p; /* skip A */
|
||||
}
|
||||
|
||||
++row;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gradient_add_alpha_horizontal (GdkPixbuf *pixbuf,
|
||||
const unsigned char *alphas,
|
||||
int n_alphas)
|
||||
{
|
||||
int i, j;
|
||||
long a, da;
|
||||
unsigned char *p;
|
||||
unsigned char *pixels;
|
||||
int width2;
|
||||
int rowstride;
|
||||
int width, height;
|
||||
unsigned char *gradient;
|
||||
unsigned char *gradient_p;
|
||||
unsigned char *gradient_end;
|
||||
|
||||
g_return_if_fail (n_alphas > 0);
|
||||
|
||||
if (n_alphas == 1)
|
||||
{
|
||||
/* Optimize this */
|
||||
simple_multiply_alpha (pixbuf, alphas[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
gradient = g_new (unsigned char, width);
|
||||
gradient_end = gradient + width;
|
||||
|
||||
if (n_alphas > width)
|
||||
n_alphas = width;
|
||||
|
||||
if (n_alphas > 1)
|
||||
width2 = width / (n_alphas - 1);
|
||||
else
|
||||
width2 = width;
|
||||
|
||||
a = alphas[0] << 8;
|
||||
gradient_p = gradient;
|
||||
|
||||
/* render the gradient into an array */
|
||||
for (i = 1; i < n_alphas; i++)
|
||||
{
|
||||
da = (((int)(alphas[i] - (int) alphas[i-1])) << 8) / (int) width2;
|
||||
|
||||
for (j = 0; j < width2; j++)
|
||||
{
|
||||
*gradient_p++ = (a >> 8);
|
||||
|
||||
a += da;
|
||||
}
|
||||
|
||||
a = alphas[i] << 8;
|
||||
}
|
||||
|
||||
/* get leftover pixels */
|
||||
while (gradient_p != gradient_end)
|
||||
{
|
||||
*gradient_p++ = a >> 8;
|
||||
}
|
||||
|
||||
/* Now for each line of the pixbuf, fill in with the gradient */
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
p = pixels;
|
||||
i = 0;
|
||||
while (i < height)
|
||||
{
|
||||
unsigned char *row_end = p + rowstride;
|
||||
gradient_p = gradient;
|
||||
|
||||
p += 3;
|
||||
while (gradient_p != gradient_end)
|
||||
{
|
||||
/* multiply the two alpha channels. not sure this is right.
|
||||
* but some end cases are that if the pixbuf contains 255,
|
||||
* then it should be modified to contain "alpha"; if the
|
||||
* pixbuf contains 0, it should remain 0.
|
||||
*/
|
||||
/* ((*p / 255.0) * (alpha / 255.0)) * 255; */
|
||||
*p = (guchar) (((int) *p * (int) *gradient_p) / (int) 255);
|
||||
|
||||
p += 4;
|
||||
++gradient_p;
|
||||
}
|
||||
|
||||
p = row_end;
|
||||
++i;
|
||||
}
|
||||
|
||||
g_free (gradient);
|
||||
}
|
||||
|
||||
void
|
||||
meta_gradient_add_alpha (GdkPixbuf *pixbuf,
|
||||
const guchar *alphas,
|
||||
int n_alphas,
|
||||
MetaGradientType type)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
|
||||
g_return_if_fail (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
g_return_if_fail (n_alphas > 0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case META_GRADIENT_HORIZONTAL:
|
||||
meta_gradient_add_alpha_horizontal (pixbuf, alphas, n_alphas);
|
||||
break;
|
||||
|
||||
case META_GRADIENT_VERTICAL:
|
||||
g_printerr ("metacity: vertical alpha channel gradient not implemented yet\n");
|
||||
break;
|
||||
|
||||
case META_GRADIENT_DIAGONAL:
|
||||
g_printerr ("metacity: diagonal alpha channel gradient not implemented yet\n");
|
||||
break;
|
||||
|
||||
case META_GRADIENT_LAST:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -51,4 +51,13 @@ GdkPixbuf* meta_gradient_create_interwoven (int width,
|
||||
int thickness2);
|
||||
|
||||
|
||||
/* Generate an alpha gradient and multiply it with the existing alpha
|
||||
* channel of the given pixbuf
|
||||
*/
|
||||
void meta_gradient_add_alpha (GdkPixbuf *pixbuf,
|
||||
const guchar *alphas,
|
||||
int n_alphas,
|
||||
MetaGradientType type);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -26,15 +26,82 @@ typedef void (* RenderGradientFunc) (GdkDrawable *drawable,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void
|
||||
draw_checkerboard (GdkDrawable *drawable,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gint i, j, xcount, ycount;
|
||||
GdkGC *gc1, *gc2;
|
||||
GdkColor color;
|
||||
|
||||
#define CHECK_SIZE 10
|
||||
#define SPACING 2
|
||||
|
||||
/* It would be a bit more efficient to keep these
|
||||
* GC's around instead of recreating on each expose, but
|
||||
* this is the lazy/slow way.
|
||||
*/
|
||||
gc1 = gdk_gc_new (drawable);
|
||||
color.red = 30000;
|
||||
color.green = 30000;
|
||||
color.blue = 30000;
|
||||
gdk_gc_set_rgb_fg_color (gc1, &color);
|
||||
|
||||
gc2 = gdk_gc_new (drawable);
|
||||
color.red = 50000;
|
||||
color.green = 50000;
|
||||
color.blue = 50000;
|
||||
gdk_gc_set_rgb_fg_color (gc2, &color);
|
||||
|
||||
xcount = 0;
|
||||
i = SPACING;
|
||||
while (i < width)
|
||||
{
|
||||
j = SPACING;
|
||||
ycount = xcount % 2; /* start with even/odd depending on row */
|
||||
while (j < height)
|
||||
{
|
||||
GdkGC *gc;
|
||||
|
||||
if (ycount % 2)
|
||||
gc = gc1;
|
||||
else
|
||||
gc = gc2;
|
||||
|
||||
/* If we're outside event->area, this will do nothing.
|
||||
* It might be mildly more efficient if we handled
|
||||
* the clipping ourselves, but again we're feeling lazy.
|
||||
*/
|
||||
gdk_draw_rectangle (drawable,
|
||||
gc,
|
||||
TRUE,
|
||||
i, j,
|
||||
CHECK_SIZE,
|
||||
CHECK_SIZE);
|
||||
|
||||
j += CHECK_SIZE + SPACING;
|
||||
++ycount;
|
||||
}
|
||||
|
||||
i += CHECK_SIZE + SPACING;
|
||||
++xcount;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (gc1));
|
||||
g_object_unref (G_OBJECT (gc2));
|
||||
}
|
||||
|
||||
static void
|
||||
render_simple (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
int width, int height,
|
||||
MetaGradientType type)
|
||||
MetaGradientType type,
|
||||
gboolean with_alpha)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkColor from, to;
|
||||
|
||||
|
||||
gdk_color_parse ("blue", &from);
|
||||
gdk_color_parse ("green", &to);
|
||||
|
||||
@ -42,6 +109,26 @@ render_simple (GdkDrawable *drawable,
|
||||
&from, &to,
|
||||
type);
|
||||
|
||||
if (with_alpha)
|
||||
{
|
||||
const unsigned char alphas[] = { 0xff, 0xaa, 0x2f, 0x0, 0xcc, 0xff, 0xff };
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
GdkPixbuf *new_pixbuf;
|
||||
|
||||
new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
pixbuf = new_pixbuf;
|
||||
}
|
||||
|
||||
meta_gradient_add_alpha (pixbuf,
|
||||
alphas, G_N_ELEMENTS (alphas),
|
||||
META_GRADIENT_HORIZONTAL);
|
||||
|
||||
draw_checkerboard (drawable, width, height);
|
||||
}
|
||||
|
||||
gdk_pixbuf_render_to_drawable (pixbuf,
|
||||
drawable,
|
||||
gc,
|
||||
@ -58,7 +145,7 @@ render_vertical_func (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL);
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -66,7 +153,7 @@ render_horizontal_func (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL);
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -74,7 +161,15 @@ render_diagonal_func (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL);
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
render_diagonal_alpha_func (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -230,6 +325,10 @@ meta_gradient_test (void)
|
||||
|
||||
window = create_gradient_window ("Interwoven",
|
||||
render_interwoven_func);
|
||||
|
||||
window = create_gradient_window ("Simple diagonal with horizontal multi alpha",
|
||||
render_diagonal_alpha_func);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -577,22 +577,81 @@ parse_angle (const char *str,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_alpha (const char *str,
|
||||
double *val,
|
||||
GMarkupParseContext *context,
|
||||
GError **error)
|
||||
parse_alpha (const char *str,
|
||||
MetaAlphaGradientSpec **spec_ret,
|
||||
GMarkupParseContext *context,
|
||||
GError **error)
|
||||
{
|
||||
if (!parse_double (str, val, context, error))
|
||||
return FALSE;
|
||||
char **split;
|
||||
int i;
|
||||
int n_alphas;
|
||||
MetaAlphaGradientSpec *spec;
|
||||
|
||||
if (*val < (0.0 - 1e6) || *val > (1.0 + 1e6))
|
||||
*spec_ret = NULL;
|
||||
|
||||
split = g_strsplit (str, ":", -1);
|
||||
|
||||
i = 0;
|
||||
while (split[i])
|
||||
++i;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
||||
_("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"),
|
||||
*val);
|
||||
_("Could not parse \"%s\" as a floating point number"),
|
||||
str);
|
||||
|
||||
g_strfreev (split);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
n_alphas = i;
|
||||
|
||||
/* FIXME allow specifying horizontal/vertical/diagonal in theme format,
|
||||
* once we implement vertical/diagonal in gradient.c
|
||||
*/
|
||||
spec = meta_alpha_gradient_spec_new (META_GRADIENT_HORIZONTAL,
|
||||
n_alphas);
|
||||
|
||||
i = 0;
|
||||
while (i < n_alphas)
|
||||
{
|
||||
double v;
|
||||
|
||||
if (!parse_double (split[i], &v, context, error))
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
||||
_("Could not parse \"%s\" as a floating point number"),
|
||||
split[i]);
|
||||
|
||||
g_strfreev (split);
|
||||
meta_alpha_gradient_spec_free (spec);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (v < (0.0 - 1e6) || v > (1.0 + 1e6))
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
||||
_("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"),
|
||||
v);
|
||||
|
||||
g_strfreev (split);
|
||||
meta_alpha_gradient_spec_free (spec);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
spec->alphas[i] = (unsigned char) (v * 255);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
g_strfreev (split);
|
||||
|
||||
*spec_ret = spec;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1886,7 +1945,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
const char *width;
|
||||
const char *height;
|
||||
const char *alpha;
|
||||
double alpha_val;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
MetaColorSpec *color_spec;
|
||||
|
||||
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
|
||||
@ -1952,7 +2011,8 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
if (!check_expression (height, FALSE, info->theme, context, error))
|
||||
return;
|
||||
|
||||
if (!parse_alpha (alpha, &alpha_val, context, error))
|
||||
alpha_spec = NULL;
|
||||
if (!parse_alpha (alpha, &alpha_spec, context, error))
|
||||
return;
|
||||
|
||||
/* Check last so we don't have to free it when other
|
||||
@ -1961,6 +2021,9 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
color_spec = meta_color_spec_new_from_string (color, error);
|
||||
if (color_spec == NULL)
|
||||
{
|
||||
if (alpha_spec)
|
||||
meta_alpha_gradient_spec_free (alpha_spec);
|
||||
|
||||
add_context_to_error (error, context);
|
||||
return;
|
||||
}
|
||||
@ -1968,11 +2031,11 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
op = meta_draw_op_new (META_DRAW_TINT);
|
||||
|
||||
op->data.tint.color_spec = color_spec;
|
||||
op->data.tint.alpha_spec = alpha_spec;
|
||||
op->data.tint.x = optimize_expression (info->theme, x);
|
||||
op->data.tint.y = optimize_expression (info->theme, y);
|
||||
op->data.tint.width = optimize_expression (info->theme, width);
|
||||
op->data.tint.height = optimize_expression (info->theme, height);
|
||||
op->data.tint.alpha = alpha_val;
|
||||
|
||||
g_assert (info->op_list);
|
||||
|
||||
@ -1988,7 +2051,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
const char *height;
|
||||
const char *type;
|
||||
const char *alpha;
|
||||
double alpha_val;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
MetaGradientType type_val;
|
||||
|
||||
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
|
||||
@ -2046,10 +2109,6 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
|
||||
if (!check_expression (height, FALSE, info->theme, context, error))
|
||||
return;
|
||||
|
||||
alpha_val = 1.0;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_val, context, error))
|
||||
return;
|
||||
|
||||
type_val = meta_gradient_type_from_string (type);
|
||||
if (type_val == META_GRADIENT_LAST)
|
||||
@ -2060,6 +2119,10 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
return;
|
||||
}
|
||||
|
||||
alpha_spec = NULL;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
|
||||
return;
|
||||
|
||||
g_assert (info->op == NULL);
|
||||
info->op = meta_draw_op_new (META_DRAW_GRADIENT);
|
||||
|
||||
@ -2068,10 +2131,9 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
info->op->data.gradient.width = optimize_expression (info->theme, width);
|
||||
info->op->data.gradient.height = optimize_expression (info->theme, height);
|
||||
|
||||
info->op->data.gradient.gradient_spec =
|
||||
meta_gradient_spec_new (type_val);
|
||||
info->op->data.gradient.gradient_spec = meta_gradient_spec_new (type_val);
|
||||
|
||||
info->op->data.gradient.alpha = alpha_val;
|
||||
info->op->data.gradient.alpha_spec = alpha_spec;
|
||||
|
||||
push_state (info, STATE_GRADIENT);
|
||||
|
||||
@ -2087,7 +2149,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
const char *height;
|
||||
const char *alpha;
|
||||
const char *colorize;
|
||||
double alpha_val;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
GdkPixbuf *pixbuf;
|
||||
MetaColorSpec *colorize_spec = NULL;
|
||||
|
||||
@ -2147,9 +2209,6 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
if (!check_expression (height, TRUE, info->theme, context, error))
|
||||
return;
|
||||
|
||||
alpha_val = 1.0;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_val, context, error))
|
||||
return;
|
||||
|
||||
/* Check last so we don't have to free it when other
|
||||
* stuff fails
|
||||
@ -2173,6 +2232,13 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
alpha_spec = NULL;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
|
||||
{
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
return;
|
||||
}
|
||||
|
||||
op = meta_draw_op_new (META_DRAW_IMAGE);
|
||||
|
||||
@ -2182,7 +2248,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
op->data.image.y = optimize_expression (info->theme, y);
|
||||
op->data.image.width = optimize_expression (info->theme, width);
|
||||
op->data.image.height = optimize_expression (info->theme, height);
|
||||
op->data.image.alpha = alpha_val;
|
||||
op->data.image.alpha_spec = alpha_spec;
|
||||
|
||||
g_assert (info->op_list);
|
||||
|
||||
@ -2523,7 +2589,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
const char *width;
|
||||
const char *height;
|
||||
const char *alpha;
|
||||
double alpha_val;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
|
||||
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
|
||||
error,
|
||||
@ -2573,8 +2639,8 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
if (!check_expression (height, FALSE, info->theme, context, error))
|
||||
return;
|
||||
|
||||
alpha_val = 1.0;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_val, context, error))
|
||||
alpha_spec = NULL;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
|
||||
return;
|
||||
|
||||
op = meta_draw_op_new (META_DRAW_ICON);
|
||||
@ -2583,7 +2649,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
op->data.icon.y = optimize_expression (info->theme, y);
|
||||
op->data.icon.width = optimize_expression (info->theme, width);
|
||||
op->data.icon.height = optimize_expression (info->theme, height);
|
||||
op->data.icon.alpha = alpha_val;
|
||||
op->data.icon.alpha_spec = alpha_spec;
|
||||
|
||||
g_assert (info->op_list);
|
||||
|
||||
|
161
src/theme.c
161
src/theme.c
@ -753,6 +753,32 @@ meta_gradient_spec_validate (MetaGradientSpec *spec,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MetaAlphaGradientSpec*
|
||||
meta_alpha_gradient_spec_new (MetaGradientType type,
|
||||
int n_alphas)
|
||||
{
|
||||
MetaAlphaGradientSpec *spec;
|
||||
|
||||
g_return_val_if_fail (n_alphas > 0, NULL);
|
||||
|
||||
spec = g_new0 (MetaAlphaGradientSpec, 1);
|
||||
|
||||
spec->type = type;
|
||||
spec->alphas = g_new0 (unsigned char, n_alphas);
|
||||
spec->n_alphas = n_alphas;
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
void
|
||||
meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
|
||||
{
|
||||
g_return_if_fail (spec != NULL);
|
||||
|
||||
g_free (spec->alphas);
|
||||
g_free (spec);
|
||||
}
|
||||
|
||||
MetaColorSpec*
|
||||
meta_color_spec_new (MetaColorSpecType type)
|
||||
{
|
||||
@ -2347,6 +2373,8 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
case META_DRAW_TINT:
|
||||
if (op->data.tint.color_spec)
|
||||
meta_color_spec_free (op->data.tint.color_spec);
|
||||
if (op->data.tint.alpha_spec)
|
||||
meta_alpha_gradient_spec_free (op->data.tint.alpha_spec);
|
||||
g_free (op->data.tint.x);
|
||||
g_free (op->data.tint.y);
|
||||
g_free (op->data.tint.width);
|
||||
@ -2356,6 +2384,8 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
case META_DRAW_GRADIENT:
|
||||
if (op->data.gradient.gradient_spec)
|
||||
meta_gradient_spec_free (op->data.gradient.gradient_spec);
|
||||
if (op->data.gradient.alpha_spec)
|
||||
meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec);
|
||||
g_free (op->data.gradient.x);
|
||||
g_free (op->data.gradient.y);
|
||||
g_free (op->data.gradient.width);
|
||||
@ -2363,6 +2393,8 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
break;
|
||||
|
||||
case META_DRAW_IMAGE:
|
||||
if (op->data.image.alpha_spec)
|
||||
meta_alpha_gradient_spec_free (op->data.image.alpha_spec);
|
||||
if (op->data.image.pixbuf)
|
||||
g_object_unref (G_OBJECT (op->data.image.pixbuf));
|
||||
if (op->data.image.colorize_spec)
|
||||
@ -2375,7 +2407,6 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
g_free (op->data.image.height);
|
||||
break;
|
||||
|
||||
|
||||
case META_DRAW_GTK_ARROW:
|
||||
g_free (op->data.gtk_arrow.x);
|
||||
g_free (op->data.gtk_arrow.y);
|
||||
@ -2397,6 +2428,8 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
break;
|
||||
|
||||
case META_DRAW_ICON:
|
||||
if (op->data.icon.alpha_spec)
|
||||
meta_alpha_gradient_spec_free (op->data.icon.alpha_spec);
|
||||
g_free (op->data.icon.x);
|
||||
g_free (op->data.icon.y);
|
||||
g_free (op->data.icon.width);
|
||||
@ -2464,21 +2497,21 @@ get_gc_for_primitive (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
multiply_alpha (GdkPixbuf *pixbuf,
|
||||
guchar alpha,
|
||||
gboolean force_copy)
|
||||
apply_alpha (GdkPixbuf *pixbuf,
|
||||
MetaAlphaGradientSpec *spec,
|
||||
gboolean force_copy)
|
||||
{
|
||||
GdkPixbuf *new_pixbuf;
|
||||
guchar *pixels;
|
||||
int rowstride;
|
||||
int height;
|
||||
int row;
|
||||
|
||||
gboolean needs_alpha;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
if (alpha == 255)
|
||||
return pixbuf;
|
||||
needs_alpha = spec && (spec->n_alphas > 1 ||
|
||||
spec->alphas[0] != 0xff);
|
||||
|
||||
if (!needs_alpha)
|
||||
return pixbuf;
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
@ -2493,38 +2526,9 @@ multiply_alpha (GdkPixbuf *pixbuf,
|
||||
}
|
||||
|
||||
g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
|
||||
meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type);
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
row = 0;
|
||||
while (row < height)
|
||||
{
|
||||
guchar *p;
|
||||
guchar *end;
|
||||
|
||||
p = pixels + row * rowstride;
|
||||
end = p + rowstride;
|
||||
|
||||
while (p != end)
|
||||
{
|
||||
p += 3; /* skip RGB */
|
||||
|
||||
/* multiply the two alpha channels. not sure this is right.
|
||||
* but some end cases are that if the pixbuf contains 255,
|
||||
* then it should be modified to contain "alpha"; if the
|
||||
* pixbuf contains 0, it should remain 0.
|
||||
*/
|
||||
/* ((*p / 255.0) * (alpha / 255.0)) * 255; */
|
||||
*p = (guchar) (((int) *p * (int) alpha) / (int) 255);
|
||||
|
||||
++p; /* skip A */
|
||||
}
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
@ -2578,10 +2582,10 @@ render_pixbuf (GdkDrawable *drawable,
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
scale_and_alpha_pixbuf (GdkPixbuf *src,
|
||||
double alpha,
|
||||
int width,
|
||||
int height)
|
||||
scale_and_alpha_pixbuf (GdkPixbuf *src,
|
||||
MetaAlphaGradientSpec *alpha_spec,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
@ -2611,9 +2615,7 @@ scale_and_alpha_pixbuf (GdkPixbuf *src,
|
||||
}
|
||||
|
||||
if (pixbuf)
|
||||
pixbuf = multiply_alpha (pixbuf,
|
||||
ALPHA_TO_UCHAR (alpha),
|
||||
pixbuf == src);
|
||||
pixbuf = apply_alpha (pixbuf, alpha_spec, pixbuf == src);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
@ -2665,20 +2667,46 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
{
|
||||
GdkColor color;
|
||||
guint32 rgba;
|
||||
gboolean has_alpha;
|
||||
|
||||
meta_color_spec_render (op->data.rectangle.color_spec,
|
||||
widget,
|
||||
&color);
|
||||
|
||||
has_alpha =
|
||||
op->data.tint.alpha_spec &&
|
||||
(op->data.tint.alpha_spec->n_alphas > 1 ||
|
||||
op->data.tint.alpha_spec->alphas[0] != 0xff);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
ALPHA_TO_UCHAR (op->data.tint.alpha) < 255,
|
||||
has_alpha,
|
||||
8, width, height);
|
||||
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
rgba &= ~0xff;
|
||||
rgba |= ALPHA_TO_UCHAR (op->data.tint.alpha);
|
||||
if (!has_alpha)
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
}
|
||||
else if (op->data.tint.alpha_spec->n_alphas == 1)
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
rgba &= ~0xff;
|
||||
rgba |= op->data.tint.alpha_spec->alphas[0];
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
meta_gradient_add_alpha (pixbuf,
|
||||
op->data.tint.alpha_spec->alphas,
|
||||
op->data.tint.alpha_spec->n_alphas,
|
||||
op->data.tint.alpha_spec->type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2687,9 +2715,9 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec,
|
||||
widget, width, height);
|
||||
|
||||
pixbuf = multiply_alpha (pixbuf,
|
||||
ALPHA_TO_UCHAR (op->data.gradient.alpha),
|
||||
FALSE);
|
||||
pixbuf = apply_alpha (pixbuf,
|
||||
op->data.gradient.alpha_spec,
|
||||
FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2720,17 +2748,17 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
if (op->data.image.colorize_cache_pixbuf)
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf,
|
||||
op->data.image.alpha,
|
||||
op->data.image.alpha_spec,
|
||||
width, height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
|
||||
op->data.image.alpha,
|
||||
op->data.image.alpha_spec,
|
||||
width, height);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
case META_DRAW_GTK_ARROW:
|
||||
@ -2743,11 +2771,11 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
width <= gdk_pixbuf_get_width (info->mini_icon) &&
|
||||
height <= gdk_pixbuf_get_height (info->mini_icon))
|
||||
pixbuf = scale_and_alpha_pixbuf (info->mini_icon,
|
||||
op->data.icon.alpha,
|
||||
op->data.icon.alpha_spec,
|
||||
width, height);
|
||||
else if (info->icon)
|
||||
pixbuf = scale_and_alpha_pixbuf (info->icon,
|
||||
op->data.icon.alpha,
|
||||
op->data.icon.alpha_spec,
|
||||
width, height);
|
||||
break;
|
||||
|
||||
@ -2902,13 +2930,18 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
case META_DRAW_TINT:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
|
||||
gboolean needs_alpha;
|
||||
|
||||
needs_alpha = op->data.tint.alpha_spec &&
|
||||
(op->data.tint.alpha_spec->n_alphas > 1 ||
|
||||
op->data.tint.alpha_spec->alphas[0] != 0xff);
|
||||
|
||||
rx = parse_x_position_unchecked (op->data.tint.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.tint.y, env);
|
||||
rwidth = parse_size_unchecked (op->data.tint.width, env);
|
||||
rheight = parse_size_unchecked (op->data.tint.height, env);
|
||||
|
||||
if (ALPHA_TO_UCHAR (op->data.tint.alpha) == 255)
|
||||
if (!needs_alpha)
|
||||
{
|
||||
gc = get_gc_for_primitive (widget, drawable,
|
||||
op->data.tint.color_spec,
|
||||
|
19
src/theme.h
19
src/theme.h
@ -31,6 +31,7 @@ typedef struct _MetaFrameStyleSet MetaFrameStyleSet;
|
||||
typedef struct _MetaDrawOp MetaDrawOp;
|
||||
typedef struct _MetaDrawOpList MetaDrawOpList;
|
||||
typedef struct _MetaGradientSpec MetaGradientSpec;
|
||||
typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
|
||||
typedef struct _MetaColorSpec MetaColorSpec;
|
||||
typedef struct _MetaFrameLayout MetaFrameLayout;
|
||||
typedef struct _MetaFrameGeometry MetaFrameGeometry;
|
||||
@ -169,6 +170,13 @@ struct _MetaGradientSpec
|
||||
GSList *color_specs;
|
||||
};
|
||||
|
||||
struct _MetaAlphaGradientSpec
|
||||
{
|
||||
MetaGradientType type;
|
||||
unsigned char *alphas;
|
||||
int n_alphas;
|
||||
};
|
||||
|
||||
struct _MetaDrawInfo
|
||||
{
|
||||
GdkPixbuf *mini_icon;
|
||||
@ -256,7 +264,7 @@ struct _MetaDrawOp
|
||||
|
||||
struct {
|
||||
MetaColorSpec *color_spec;
|
||||
double alpha;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
char *x;
|
||||
char *y;
|
||||
char *width;
|
||||
@ -265,7 +273,7 @@ struct _MetaDrawOp
|
||||
|
||||
struct {
|
||||
MetaGradientSpec *gradient_spec;
|
||||
double alpha;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
char *x;
|
||||
char *y;
|
||||
char *width;
|
||||
@ -274,6 +282,7 @@ struct _MetaDrawOp
|
||||
|
||||
struct {
|
||||
MetaColorSpec *colorize_spec;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
GdkPixbuf *pixbuf;
|
||||
double alpha;
|
||||
char *x;
|
||||
@ -312,7 +321,7 @@ struct _MetaDrawOp
|
||||
} gtk_vline;
|
||||
|
||||
struct {
|
||||
double alpha;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
char *x;
|
||||
char *y;
|
||||
char *width;
|
||||
@ -618,6 +627,10 @@ GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
|
||||
gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
|
||||
GError **error);
|
||||
|
||||
MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type,
|
||||
int n_alphas);
|
||||
void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec);
|
||||
|
||||
|
||||
MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent);
|
||||
void meta_frame_style_ref (MetaFrameStyle *style);
|
||||
|
Loading…
Reference in New Issue
Block a user