]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcssshadowvalue.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkcssshadowvalue.c
index a2389f4e37f27e7d1693ee6e83f65b35ed7f7c74..618288807af8d3b7e9571d013c632880a9f7f67a 100644 (file)
 
 #include "gtkcssshadowvalueprivate.h"
 
+#include "gtkcairoblurprivate.h"
+#include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnumbervalueprivate.h"
 #include "gtkcssrgbavalueprivate.h"
 #include "gtkstylecontextprivate.h"
-#include "gtksymboliccolorprivate.h"
 #include "gtkthemingengineprivate.h"
 #include "gtkpango.h"
 
@@ -59,6 +60,40 @@ gtk_css_value_shadow_free (GtkCssValue *shadow)
   g_slice_free (GtkCssValue, shadow);
 }
 
+static GtkCssValue *
+gtk_css_value_shadow_compute (GtkCssValue             *shadow,
+                              guint                    property_id,
+                              GtkStyleProviderPrivate *provider,
+                              GtkCssComputedValues    *values,
+                              GtkCssComputedValues    *parent_values,
+                              GtkCssDependencies      *dependencies)
+{
+  GtkCssValue *hoffset, *voffset, *radius, *spread, *color;
+  GtkCssDependencies child_deps;
+
+  child_deps = 0;
+  hoffset = _gtk_css_value_compute (shadow->hoffset, property_id, provider, values, parent_values, &child_deps);
+  *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+
+  child_deps = 0;
+  voffset = _gtk_css_value_compute (shadow->voffset, property_id, provider, values, parent_values, &child_deps);
+  *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+
+  child_deps = 0;
+  radius = _gtk_css_value_compute (shadow->radius, property_id, provider, values, parent_values, &child_deps);
+  *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+
+  child_deps = 0;
+  spread = _gtk_css_value_compute (shadow->spread, property_id, provider, values, parent_values, &child_deps),
+  *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+
+  child_deps = 0;
+  color = _gtk_css_value_compute (shadow->color, property_id, provider, values, parent_values, &child_deps);
+  *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+
+  return gtk_css_shadow_value_new (hoffset, voffset, radius, spread, shadow->inset, color);
+}
+
 static gboolean
 gtk_css_value_shadow_equal (const GtkCssValue *shadow1,
                             const GtkCssValue *shadow2)
@@ -74,17 +109,18 @@ gtk_css_value_shadow_equal (const GtkCssValue *shadow1,
 static GtkCssValue *
 gtk_css_value_shadow_transition (GtkCssValue *start,
                                  GtkCssValue *end,
+                                 guint        property_id,
                                  double       progress)
 {
   if (start->inset != end->inset)
     return NULL;
 
-  return gtk_css_shadow_value_new (_gtk_css_value_transition (start->hoffset, end->hoffset, progress),
-                                   _gtk_css_value_transition (start->voffset, end->voffset, progress),
-                                   _gtk_css_value_transition (start->radius, end->radius, progress),
-                                   _gtk_css_value_transition (start->spread, end->spread, progress),
+  return gtk_css_shadow_value_new (_gtk_css_value_transition (start->hoffset, end->hoffset, property_id, progress),
+                                   _gtk_css_value_transition (start->voffset, end->voffset, property_id, progress),
+                                   _gtk_css_value_transition (start->radius, end->radius, property_id, progress),
+                                   _gtk_css_value_transition (start->spread, end->spread, property_id, progress),
                                    start->inset,
-                                   _gtk_css_value_transition (start->color, end->color, progress));
+                                   _gtk_css_value_transition (start->color, end->color, property_id, progress));
 }
 
 static void
@@ -117,6 +153,7 @@ gtk_css_value_shadow_print (const GtkCssValue *shadow,
 
 static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = {
   gtk_css_value_shadow_free,
+  gtk_css_value_shadow_compute,
   gtk_css_value_shadow_equal,
   gtk_css_value_shadow_transition,
   gtk_css_value_shadow_print
@@ -234,7 +271,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser)
       }
     else if (values[COLOR] == NULL)
       {
-        values[COLOR] = _gtk_css_symbolic_value_new (parser);
+        values[COLOR] = _gtk_css_color_value_parse (parser);
 
         if (values[COLOR] == NULL)
           goto fail;
@@ -250,9 +287,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser)
   while (values[HOFFSET] == NULL || !value_is_done_parsing (parser));
 
   if (values[COLOR] == NULL)
-    values[COLOR] = _gtk_css_symbolic_value_new_take_symbolic_color (
-                      gtk_symbolic_color_ref (
-                        _gtk_symbolic_color_get_current_color ()));
+    values[COLOR] = _gtk_css_color_value_new_current_color ();
 
   return gtk_css_shadow_value_new (values[HOFFSET], values[VOFFSET],
                                    values[RADIUS], values[SPREAD],
@@ -268,25 +303,67 @@ fail:
   return NULL;
 }
 
-GtkCssValue *
-_gtk_css_shadow_value_compute (GtkCssValue     *shadow,
-                               GtkStyleContext *context)
+static const cairo_user_data_key_t shadow_key;
+
+static cairo_t *
+gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow,
+                                    cairo_t           *cr)
 {
-  GdkRGBA transparent = { 0, 0, 0, 0 };
-  GtkCssValue *color;
+  cairo_rectangle_int_t clip_rect;
+  cairo_surface_t *surface;
+  cairo_t *blur_cr;
+  gdouble radius;
+
+  radius = _gtk_css_number_value_get (shadow->radius, 0);
+  if (radius == 0.0)
+    return cr;
+
+  gdk_cairo_get_clip_rectangle (cr, &clip_rect);
+
+  /* Create a larger surface to center the blur. */
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        clip_rect.width + 2 * radius,
+                                        clip_rect.height + 2 * radius);
+  cairo_surface_set_device_offset (surface, radius - clip_rect.x, radius - clip_rect.y);
+  blur_cr = cairo_create (surface);
+  cairo_set_user_data (blur_cr, &shadow_key, cairo_reference (cr), (cairo_destroy_func_t) cairo_destroy);
+
+  if (cairo_has_current_point (cr))
+    {
+      double x, y;
+      
+      cairo_get_current_point (cr, &x, &y);
+      cairo_move_to (blur_cr, x, y);
+    }
+
+  return blur_cr;
+}
+
+static cairo_t *
+gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow,
+                                     cairo_t           *cr)
+{
+  gdouble radius;
+  cairo_t *original_cr;
+  cairo_surface_t *surface;
+
+  radius = _gtk_css_number_value_get (shadow->radius, 0);
+  if (radius == 0.0)
+    return cr;
+
+  surface = cairo_get_target (cr);
+  original_cr = cairo_get_user_data (cr, &shadow_key);
+
+  /* Blur the surface. */
+  _gtk_cairo_blur_surface (surface, radius);
+
+  cairo_set_source_surface (original_cr, surface, 0, 0);
+  cairo_paint (original_cr);
 
-  color = _gtk_css_rgba_value_compute_from_symbolic (shadow->color,
-                                                     _gtk_css_symbolic_value_new_take_symbolic_color (
-                                                       gtk_symbolic_color_new_literal (&transparent)),
-                                                     context,
-                                                     FALSE);
-
-  return gtk_css_shadow_value_new (_gtk_css_number_value_compute (shadow->hoffset, context),
-                                   _gtk_css_number_value_compute (shadow->voffset, context),
-                                   _gtk_css_number_value_compute (shadow->radius, context),
-                                   _gtk_css_number_value_compute (shadow->spread, context),
-                                   shadow->inset,
-                                   color);
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface);
+
+  return original_cr;
 }
 
 void
@@ -304,9 +381,14 @@ _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
   cairo_rel_move_to (cr, 
                      _gtk_css_number_value_get (shadow->hoffset, 0),
                      _gtk_css_number_value_get (shadow->voffset, 0));
+
+  cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+
   gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
   _gtk_pango_fill_layout (cr, layout);
 
+  cr = gtk_css_shadow_value_finish_drawing (shadow, cr);
+
   cairo_rel_move_to (cr,
                      - _gtk_css_number_value_get (shadow->hoffset, 0),
                      - _gtk_css_number_value_get (shadow->voffset, 0));
@@ -323,6 +405,9 @@ _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
 
   cairo_save (cr);
   pattern = cairo_pattern_reference (cairo_get_source (cr));
+
+  cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+
   gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
 
   cairo_translate (cr,
@@ -330,6 +415,8 @@ _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
                    _gtk_css_number_value_get (shadow->voffset, 0));
   cairo_mask (cr, pattern);
 
+  cr = gtk_css_shadow_value_finish_drawing (shadow, cr);
+
   cairo_restore (cr);
   cairo_pattern_destroy (pattern);
 }
@@ -344,6 +431,8 @@ _gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
 
   cairo_save (cr);
 
+  cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+
   cairo_translate (cr,
                    _gtk_css_number_value_get (shadow->hoffset, 0),
                    _gtk_css_number_value_get (shadow->voffset, 0));
@@ -351,6 +440,8 @@ _gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
                                      radius, progress,
                                      _gtk_css_rgba_value_get_rgba (shadow->color));
 
+  cr = gtk_css_shadow_value_finish_drawing (shadow, cr);
+
   cairo_restore (cr);
 }
 
@@ -359,13 +450,12 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue   *shadow,
                                  cairo_t             *cr,
                                  const GtkRoundedBox *padding_box)
 {
-  GtkRoundedBox box;
-  double spread;
+  GtkRoundedBox box, clip_box;
+  double spread, radius;
 
   g_return_if_fail (shadow->class == &GTK_CSS_VALUE_SHADOW);
 
   cairo_save (cr);
-  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
 
   _gtk_rounded_box_path (padding_box, cr);
   cairo_clip (cr);
@@ -377,11 +467,20 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue   *shadow,
   spread = _gtk_css_number_value_get (shadow->spread, 0);
   _gtk_rounded_box_shrink (&box, spread, spread, spread, spread);
 
+  clip_box = *padding_box;
+  radius = _gtk_css_number_value_get (shadow->radius, 0);
+  _gtk_rounded_box_shrink (&clip_box, -radius, -radius, -radius, -radius);
+
+  cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+
+  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
   _gtk_rounded_box_path (&box, cr);
-  _gtk_rounded_box_clip_path (padding_box, cr);
+  _gtk_rounded_box_clip_path (&clip_box, cr);
 
   gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
   cairo_fill (cr);
 
+  cr = gtk_css_shadow_value_finish_drawing (shadow, cr);
+
   cairo_restore (cr);
 }