From 580cc874c2a6c92d05b6a55b06ea01fccb80e570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= Date: Sun, 10 Jul 2016 11:08:10 +0300 Subject: libmetacity: use cairo to apply alpha --- libmetacity/meta-draw-op.c | 103 ++++++++++++++++++------------- libmetacity/meta-gradient-spec-private.h | 8 +-- libmetacity/meta-gradient-spec.c | 67 ++++++++++---------- 3 files changed, 95 insertions(+), 83 deletions(-) diff --git a/libmetacity/meta-draw-op.c b/libmetacity/meta-draw-op.c index 0e3e6ae4..e88d11c4 100644 --- a/libmetacity/meta-draw-op.c +++ b/libmetacity/meta-draw-op.c @@ -24,12 +24,6 @@ #include "meta-draw-op-private.h" #include "meta-theme-impl-private.h" -#define GDK_COLOR_RGBA(color) \ - ((guint32) (0xff | \ - ((int)((color).red * 255) << 24) | \ - ((int)((color).green * 255) << 16) | \ - ((int)((color).blue * 255) << 8))) - #define GDK_COLOR_RGB(color) \ ((guint32) (((int)((color).red * 255) << 16) | \ ((int)((color).green * 255) << 8) | \ @@ -210,18 +204,15 @@ replicate_cols (GdkPixbuf *src, } static GdkPixbuf* -scale_and_alpha_pixbuf (GdkPixbuf *src, - MetaAlphaGradientSpec *alpha_spec, - MetaImageFillType fill_type, - int width, - int height, - gboolean vertical_stripes, - gboolean horizontal_stripes) +scale_pixbuf (GdkPixbuf *src, + MetaAlphaGradientSpec *alpha_spec, + MetaImageFillType fill_type, + gint width, + gint height, + gboolean vertical_stripes, + gboolean horizontal_stripes) { GdkPixbuf *pixbuf; - GdkPixbuf *temp_pixbuf; - - pixbuf = NULL; pixbuf = src; @@ -238,6 +229,7 @@ scale_and_alpha_pixbuf (GdkPixbuf *src, } else { + GdkPixbuf *temp_pixbuf; int src_h, src_w, dest_h, dest_w; src_h = gdk_pixbuf_get_height (src); src_w = gdk_pixbuf_get_width (src); @@ -294,9 +286,6 @@ scale_and_alpha_pixbuf (GdkPixbuf *src, } } - if (pixbuf) - pixbuf = meta_alpha_gradient_spec_apply_alpha (alpha_spec, pixbuf, pixbuf == src); - return pixbuf; } @@ -438,22 +427,22 @@ 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_spec, - op->data.image.fill_type, - width, height, - op->data.image.vertical_stripes, - op->data.image.horizontal_stripes); + pixbuf = scale_pixbuf (op->data.image.colorize_cache_pixbuf, + op->data.image.alpha_spec, + op->data.image.fill_type, + width, height, + op->data.image.vertical_stripes, + op->data.image.horizontal_stripes); } } else { - pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf, - op->data.image.alpha_spec, - op->data.image.fill_type, - width, height, - op->data.image.vertical_stripes, - op->data.image.horizontal_stripes); + pixbuf = scale_pixbuf (op->data.image.pixbuf, + op->data.image.alpha_spec, + op->data.image.fill_type, + width, height, + op->data.image.vertical_stripes, + op->data.image.horizontal_stripes); } break; } @@ -467,17 +456,13 @@ draw_op_as_pixbuf (const MetaDrawOp *op, if (info->mini_icon && 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_spec, - op->data.icon.fill_type, - width, height, - FALSE, FALSE); + pixbuf = scale_pixbuf (info->mini_icon, op->data.icon.alpha_spec, + op->data.icon.fill_type, width, height, + FALSE, FALSE); else if (info->icon) - pixbuf = scale_and_alpha_pixbuf (info->icon, - op->data.icon.alpha_spec, - op->data.icon.fill_type, - width, height, - FALSE, FALSE); + pixbuf = scale_pixbuf (info->icon, op->data.icon.alpha_spec, + op->data.icon.fill_type, width, height, + FALSE, FALSE); break; case META_DRAW_TITLE: @@ -723,7 +708,23 @@ draw_op_draw_with_env (const MetaDrawOp *op, ry = meta_draw_spec_parse_y_position (op->data.image.y, env); gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); - cairo_paint (cr); + + if (op->data.image.alpha_spec) + { + cairo_pattern_t *pattern; + + cairo_translate (cr, rx, ry); + cairo_scale (cr, rwidth, rheight); + + pattern = meta_alpha_gradient_spec_get_mask (op->data.image.alpha_spec); + cairo_mask (cr, pattern); + + cairo_pattern_destroy (pattern); + } + else + { + cairo_paint (cr); + } g_object_unref (G_OBJECT (pixbuf)); } @@ -811,7 +812,23 @@ draw_op_draw_with_env (const MetaDrawOp *op, ry = meta_draw_spec_parse_y_position (op->data.icon.y, env); gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); - cairo_paint (cr); + + if (op->data.icon.alpha_spec) + { + cairo_pattern_t *pattern; + + cairo_translate (cr, rx, ry); + cairo_scale (cr, rwidth, rheight); + + pattern = meta_alpha_gradient_spec_get_mask (op->data.icon.alpha_spec); + cairo_mask (cr, pattern); + + cairo_pattern_destroy (pattern); + } + else + { + cairo_paint (cr); + } g_object_unref (G_OBJECT (pixbuf)); } diff --git a/libmetacity/meta-gradient-spec-private.h b/libmetacity/meta-gradient-spec-private.h index a07240f1..aaa883b9 100644 --- a/libmetacity/meta-gradient-spec-private.h +++ b/libmetacity/meta-gradient-spec-private.h @@ -68,11 +68,6 @@ G_GNUC_INTERNAL guchar meta_alpha_gradient_spec_get_alpha (MetaAlphaGradientSpec *spec, gint n_alpha); -G_GNUC_INTERNAL -GdkPixbuf *meta_alpha_gradient_spec_apply_alpha (MetaAlphaGradientSpec *spec, - GdkPixbuf *pixbuf, - gboolean force_copy); - G_GNUC_INTERNAL void meta_alpha_gradient_spec_render (MetaAlphaGradientSpec *spec, GdkRGBA color, @@ -82,6 +77,9 @@ void meta_alpha_gradient_spec_render (MetaAlphaGradientSp gint width, gint height); +G_GNUC_INTERNAL +cairo_pattern_t *meta_alpha_gradient_spec_get_mask (const MetaAlphaGradientSpec *spec); + G_END_DECLS #endif diff --git a/libmetacity/meta-gradient-spec.c b/libmetacity/meta-gradient-spec.c index dd4b48e5..cb99a692 100644 --- a/libmetacity/meta-gradient-spec.c +++ b/libmetacity/meta-gradient-spec.c @@ -220,41 +220,6 @@ meta_alpha_gradient_spec_get_alpha (MetaAlphaGradientSpec *spec, return spec->alphas[n_alpha]; } -GdkPixbuf * -meta_alpha_gradient_spec_apply_alpha (MetaAlphaGradientSpec *spec, - GdkPixbuf *pixbuf, - gboolean force_copy) -{ - GdkPixbuf *new_pixbuf; - gboolean needs_alpha; - - g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); - - 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); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - else if (force_copy) - { - new_pixbuf = gdk_pixbuf_copy (pixbuf); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - - g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); - - meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type); - - return pixbuf; -} - void meta_alpha_gradient_spec_render (MetaAlphaGradientSpec *spec, GdkRGBA color, @@ -309,3 +274,35 @@ meta_alpha_gradient_spec_render (MetaAlphaGradientSpec *spec, cairo_restore (cr); } } + +cairo_pattern_t * +meta_alpha_gradient_spec_get_mask (const MetaAlphaGradientSpec *spec) +{ + gint n_alphas; + cairo_pattern_t *pattern; + gint i; + + /* Hardcoded in meta-theme-metacity.c */ + g_assert (spec->type == META_GRADIENT_HORIZONTAL); + + n_alphas = spec->n_alphas; + if (n_alphas == 0) + return NULL; + + if (n_alphas == 1) + return cairo_pattern_create_rgba (0, 0, 0, spec->alphas[0] / 255.0); + + pattern = cairo_pattern_create_linear (0, 0, 1, 0); + + for (i = 0; i < n_alphas; i++) + cairo_pattern_add_color_stop_rgba (pattern, i / (gfloat) (n_alphas - 1), + 0, 0, 0, spec->alphas[i] / 255.0); + + if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS) + { + cairo_pattern_destroy (pattern); + return NULL; + } + + return pattern; +} -- cgit v1.2.1