[gnome-shell] st-private: add cairo code for drawing shadow



commit 03757c1fcb9b9f27d44cc4cc8665aa59fcc3d409
Author: Ray Strode <rstrode redhat com>
Date:   Wed Jan 12 19:45:28 2011 -0500

    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

 src/st/st-private.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/st/st-private.h |    4 ++
 2 files changed, 101 insertions(+), 0 deletions(-)
---
diff --git a/src/st/st-private.c b/src/st/st-private.c
index 757f1e4..54d9a4b 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -636,6 +636,103 @@ _st_create_shadow_material_from_actor (StShadow     *shadow_spec,
   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
 _st_paint_shadow_with_opacity (StShadow        *shadow_spec,
                                CoglHandle       shadow_material,
diff --git a/src/st/st-private.h b/src/st/st-private.h
index f958842..4954757 100644
--- a/src/st/st-private.h
+++ b/src/st/st-private.h
@@ -24,6 +24,7 @@
 #define __ST_PRIVATE_H__
 
 #include <glib.h>
+#include <cairo.h>
 #include "st-widget.h"
 #include "st-bin.h"
 #include "st-shadow.h"
@@ -79,6 +80,9 @@ CoglHandle _st_create_shadow_material (StShadow   *shadow_spec,
                                        CoglHandle  src_texture);
 CoglHandle _st_create_shadow_material_from_actor (StShadow     *shadow_spec,
                                                   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,
                                     CoglHandle       shadow_material,
                                     ClutterActorBox *box,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]