st-private: add cairo code for drawing shadow

This does the same thing as the cogl equivalent
code, but for handling fallbacks.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
This commit is contained in:
Ray Strode 2011-01-12 19:45:28 -05:00
parent 1faee65a68
commit 03757c1fcb
2 changed files with 101 additions and 0 deletions

View File

@ -636,6 +636,103 @@ _st_create_shadow_material_from_actor (StShadow *shadow_spec,
return shadow_material; return shadow_material;
} }
cairo_pattern_t *
_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
cairo_pattern_t *src_pattern)
{
cairo_t *cr;
cairo_surface_t *src_surface;
cairo_surface_t *surface_in;
cairo_surface_t *surface_out;
cairo_pattern_t *dst_pattern;
guchar *pixels_in, *pixels_out;
gint width_in, height_in, rowstride_in;
gint width_out, height_out, rowstride_out;
cairo_matrix_t shadow_matrix;
g_return_val_if_fail (shadow_spec != NULL, NULL);
g_return_val_if_fail (src_pattern != NULL, NULL);
cairo_pattern_get_surface (src_pattern, &src_surface);
width_in = cairo_image_surface_get_width (src_surface);
height_in = cairo_image_surface_get_height (src_surface);
/* We want the output to be a color agnostic alpha mask,
* so we need to strip the color channels from the input
*/
if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8)
{
surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8,
width_in, height_in);
cr = cairo_create (surface_in);
cairo_set_source_surface (cr, src_surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
else
{
surface_in = cairo_surface_reference (src_surface);
}
pixels_in = cairo_image_surface_get_data (surface_in);
rowstride_in = cairo_image_surface_get_stride (surface_in);
pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
shadow_spec->blur,
&width_out, &height_out, &rowstride_out);
cairo_surface_destroy (surface_in);
surface_out = cairo_image_surface_create_for_data (pixels_out,
CAIRO_FORMAT_A8,
width_out,
height_out,
rowstride_out);
dst_pattern = cairo_pattern_create_for_surface (surface_out);
cairo_surface_destroy (surface_out);
cairo_pattern_get_matrix (src_pattern, &shadow_matrix);
/* Read all the code from the cairo_pattern_set_matrix call
* at the end of this function to here from bottom to top,
* because each new affine transformation is applied in
* front of all the previous ones */
/* 6. Invert the matrix back */
cairo_matrix_invert (&shadow_matrix);
/* 5. Adjust based on specified offsets */
cairo_matrix_translate (&shadow_matrix,
shadow_spec->xoffset,
shadow_spec->yoffset);
/* 4. Recenter the newly scaled image */
cairo_matrix_translate (&shadow_matrix,
- shadow_spec->spread,
- shadow_spec->spread);
/* 3. Scale up the blurred image to fill the spread */
cairo_matrix_scale (&shadow_matrix,
(width_in + 2.0 * shadow_spec->spread) / width_in,
(height_in + 2.0 * shadow_spec->spread) / height_in);
/* 2. Shift the blurred image left, so that it aligns centered
* under the unblurred one */
cairo_matrix_translate (&shadow_matrix,
- (width_out - width_in) / 2.0,
- (height_out - height_in) / 2.0);
/* 1. Invert the matrix so we can work with it in pattern space
*/
cairo_matrix_invert (&shadow_matrix);
cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);
return dst_pattern;
}
void void
_st_paint_shadow_with_opacity (StShadow *shadow_spec, _st_paint_shadow_with_opacity (StShadow *shadow_spec,
CoglHandle shadow_material, CoglHandle shadow_material,

View File

@ -24,6 +24,7 @@
#define __ST_PRIVATE_H__ #define __ST_PRIVATE_H__
#include <glib.h> #include <glib.h>
#include <cairo.h>
#include "st-widget.h" #include "st-widget.h"
#include "st-bin.h" #include "st-bin.h"
#include "st-shadow.h" #include "st-shadow.h"
@ -79,6 +80,9 @@ CoglHandle _st_create_shadow_material (StShadow *shadow_spec,
CoglHandle src_texture); CoglHandle src_texture);
CoglHandle _st_create_shadow_material_from_actor (StShadow *shadow_spec, CoglHandle _st_create_shadow_material_from_actor (StShadow *shadow_spec,
ClutterActor *actor); ClutterActor *actor);
cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
cairo_pattern_t *src_pattern);
void _st_paint_shadow_with_opacity (StShadow *shadow_spec, void _st_paint_shadow_with_opacity (StShadow *shadow_spec,
CoglHandle shadow_material, CoglHandle shadow_material,
ClutterActorBox *box, ClutterActorBox *box,