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:
parent
1faee65a68
commit
03757c1fcb
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user