[gtk+] render: Propagate snapshot drawing to box shadows



commit 38f226b5cef1660c7a7f465528befbd65ab944a5
Author: Benjamin Otte <otte redhat com>
Date:   Sat Nov 19 20:38:22 2016 +0100

    render: Propagate snapshot drawing to box shadows
    
    This decouples actual background drawing from shadow drawing in the
    snapshot case.
    
    We also now create seperate nodes for shadows vs for backgrounds.

 gtk/gtkcssshadowsvalue.c        |   36 +++++++++++++++++++++++++
 gtk/gtkcssshadowsvalueprivate.h |    6 ++++
 gtk/gtkcssshadowvalue.c         |   53 ++++++++++++++++++++++++++++++++++++
 gtk/gtkcssshadowvalueprivate.h  |    8 +++++-
 gtk/gtkrenderbackground.c       |   56 +++++++++++++++++++++++++++------------
 5 files changed, 141 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtkcssshadowsvalue.c b/gtk/gtkcssshadowsvalue.c
index e2be207..1838155 100644
--- a/gtk/gtkcssshadowsvalue.c
+++ b/gtk/gtkcssshadowsvalue.c
@@ -316,6 +316,42 @@ _gtk_css_shadows_value_paint_box (const GtkCssValue   *shadows,
 }
 
 void
+gtk_css_shadows_value_snapshot_outset (const GtkCssValue   *shadows,
+                                       GtkSnapshot         *snapshot,
+                                       const GtkRoundedBox *border_box)
+{
+  guint i;
+
+  g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
+
+  for (i = 0; i < shadows->len; i++)
+    {
+      if (_gtk_css_shadow_value_get_inset (shadows->values[i]))
+        continue;
+
+      gtk_css_shadow_value_snapshot_outset (shadows->values[i], snapshot, border_box);
+    }
+}
+
+void
+gtk_css_shadows_value_snapshot_inset (const GtkCssValue   *shadows,
+                                      GtkSnapshot         *snapshot,
+                                      const GtkRoundedBox *padding_box)
+{
+  guint i;
+
+  g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
+
+  for (i = 0; i < shadows->len; i++)
+    {
+      if (!_gtk_css_shadow_value_get_inset (shadows->values[i]))
+        continue;
+
+      gtk_css_shadow_value_snapshot_inset (shadows->values[i], snapshot, padding_box);
+    }
+}
+
+void
 _gtk_css_shadows_value_get_extents (const GtkCssValue *shadows,
                                     GtkBorder         *border)
 {
diff --git a/gtk/gtkcssshadowsvalueprivate.h b/gtk/gtkcssshadowsvalueprivate.h
index 790e8ec..5909740 100644
--- a/gtk/gtkcssshadowsvalueprivate.h
+++ b/gtk/gtkcssshadowsvalueprivate.h
@@ -47,6 +47,12 @@ void            _gtk_css_shadows_value_paint_box      (const GtkCssValue
                                                        cairo_t                  *cr,
                                                        const GtkRoundedBox      *padding_box,
                                                        gboolean                  inset);
+void            gtk_css_shadows_value_snapshot_outset (const GtkCssValue        *shadows,
+                                                       GtkSnapshot              *snapshot,
+                                                       const GtkRoundedBox      *border_box);
+void            gtk_css_shadows_value_snapshot_inset  (const GtkCssValue        *shadows,
+                                                       GtkSnapshot              *snapshot,
+                                                       const GtkRoundedBox      *padding_box);
 
 void            _gtk_css_shadows_value_get_extents    (const GtkCssValue        *shadows,
                                                        GtkBorder                *border);
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index a17b213..3c7aeb9 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -25,6 +25,7 @@
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnumbervalueprivate.h"
 #include "gtkcssrgbavalueprivate.h"
+#include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
 #include "gtkrenderprivate.h"
 #include "gtkpango.h"
@@ -1019,3 +1020,55 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue   *shadow,
 
   cairo_restore (cr);
 }
+
+void
+gtk_css_shadow_value_snapshot_outset (const GtkCssValue   *shadow,
+                                      GtkSnapshot         *snapshot,
+                                      const GtkRoundedBox *border_box)
+{
+  GtkBorder extents;
+  cairo_t *cr;
+
+  g_return_if_fail (shadow->class == &GTK_CSS_VALUE_SHADOW);
+
+  /* We don't need to draw invisible shadows */
+  if (gtk_rgba_is_clear (_gtk_css_rgba_value_get_rgba (shadow->color)))
+    return;
+
+  gtk_css_shadow_value_get_extents (shadow, &extents);
+
+  cr = gtk_snapshot_append_cairo_node (snapshot,
+                                       &(graphene_rect_t) GRAPHENE_RECT_INIT (
+                                          border_box->box.x - extents.left,
+                                          border_box->box.y - extents.top,
+                                          border_box->box.width + extents.left + extents.right,
+                                          border_box->box.height + extents.top + extents.bottom),
+                                       "Outset Shadow");
+  _gtk_css_shadow_value_paint_box (shadow, cr, border_box);
+  cairo_destroy (cr);
+}
+
+void
+gtk_css_shadow_value_snapshot_inset (const GtkCssValue   *shadow,
+                                     GtkSnapshot         *snapshot,
+                                     const GtkRoundedBox *padding_box)
+{
+  cairo_t *cr;
+
+  g_return_if_fail (shadow->class == &GTK_CSS_VALUE_SHADOW);
+
+  /* We don't need to draw invisible shadows */
+  if (gtk_rgba_is_clear (_gtk_css_rgba_value_get_rgba (shadow->color)))
+    return;
+
+  cr = gtk_snapshot_append_cairo_node (snapshot,
+                                       &(graphene_rect_t) GRAPHENE_RECT_INIT (
+                                          padding_box->box.x,
+                                          padding_box->box.y,
+                                          padding_box->box.width,
+                                          padding_box->box.height),
+                                       "Inset Shadow");
+  _gtk_css_shadow_value_paint_box (shadow, cr, padding_box);
+  cairo_destroy (cr);
+}
+
diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h
index 5b89944..7f8c86b 100644
--- a/gtk/gtkcssshadowvalueprivate.h
+++ b/gtk/gtkcssshadowvalueprivate.h
@@ -46,11 +46,17 @@ void            _gtk_css_shadow_value_paint_layout    (const GtkCssValue
 
 void            _gtk_css_shadow_value_paint_icon      (const GtkCssValue        *shadow,
                                                       cairo_t                  *cr);
-
 void            _gtk_css_shadow_value_paint_box       (const GtkCssValue        *shadow,
                                                        cairo_t                  *cr,
                                                        const GtkRoundedBox      *padding_box);
 
+void            gtk_css_shadow_value_snapshot_outset  (const GtkCssValue        *shadow,
+                                                       GtkSnapshot              *snapshot,
+                                                       const GtkRoundedBox      *border_box);
+void            gtk_css_shadow_value_snapshot_inset   (const GtkCssValue        *shadow,
+                                                       GtkSnapshot              *snapshot,
+                                                       const GtkRoundedBox      *padding_box);
+
 G_END_DECLS
 
 #endif /* __GTK_SHADOW_H__ */
diff --git a/gtk/gtkrenderbackground.c b/gtk/gtkrenderbackground.c
index c0a7d75..7def6b0 100644
--- a/gtk/gtkrenderbackground.c
+++ b/gtk/gtkrenderbackground.c
@@ -302,13 +302,16 @@ _gtk_theming_background_paint_layer (GtkThemingBackground *bg,
 }
 
 static void
-_gtk_theming_background_init_style (GtkThemingBackground *bg,
-                                    double                width,
-                                    double                height,
-                                    GtkJunctionSides      junction)
+gtk_theming_background_init (GtkThemingBackground *bg,
+                             GtkCssStyle          *style,
+                             double                width,
+                             double                height,
+                             GtkJunctionSides      junction)
 {
   GtkBorder border, padding;
 
+  bg->style = style;
+
   border.top = _gtk_css_number_value_get (gtk_css_style_get_value (bg->style, 
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
   border.right = _gtk_css_number_value_get (gtk_css_style_get_value (bg->style, 
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
   border.bottom = _gtk_css_number_value_get (gtk_css_style_get_value (bg->style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
@@ -370,8 +373,7 @@ gtk_css_style_render_background (GtkCssStyle      *style,
       _gtk_css_shadows_value_is_none (box_shadow))
     return;
 
-  bg.style = style;
-  _gtk_theming_background_init_style (&bg, width, height, junction);
+  gtk_theming_background_init (&bg, style, width, height, junction);
 
   cairo_save (cr);
   cairo_translate (cr, x, y);
@@ -435,14 +437,17 @@ gtk_css_style_snapshot_background (GtkCssStyle      *style,
                                    gdouble           height,
                                    GtkJunctionSides  junction)
 {
+  GtkThemingBackground bg;
+  gint idx;
   GtkCssValue *background_image;
+  GtkCssValue *blend_modes;
   GtkCssValue *box_shadow;
   const GdkRGBA *bg_color;
-  GtkBorder shadow;
-  graphene_rect_t bounds;
+  gint number_of_layers;
   cairo_t *cr;
 
   background_image = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);
+  blend_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
   bg_color = _gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BACKGROUND_COLOR));
   box_shadow = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BOX_SHADOW);
 
@@ -453,20 +458,37 @@ gtk_css_style_snapshot_background (GtkCssStyle      *style,
       _gtk_css_shadows_value_is_none (box_shadow))
     return;
 
-  _gtk_css_shadows_value_get_extents (box_shadow, &shadow);
+  gtk_theming_background_init (&bg, style, width, height, junction);
 
-  graphene_rect_init (&bounds,
-                      - shadow.left,
-                      - shadow.top,
-                      ceil (width) + shadow.left + shadow.right,
-                      ceil (height) + shadow.top + shadow.bottom);
+  gtk_css_shadows_value_snapshot_outset (box_shadow,
+                                         snapshot,
+                                         &bg.boxes[GTK_CSS_AREA_BORDER_BOX]);
 
+  /*
+   * When we have a blend mode set for the background, we must blend on a transparent
+   * background. GSK can't do that yet.
+   */
   cr = gtk_snapshot_append_cairo_node (snapshot,
-                                       &bounds,
-                                       "Background");
+                                       &(graphene_rect_t)GRAPHENE_RECT_INIT(0, 0, width, height),
+                                       "Background with blend mode");
 
-  gtk_css_style_render_background (style, cr, 0, 0, width, height, junction);
+  _gtk_theming_background_paint_color (&bg, cr, bg_color, background_image);
+
+  number_of_layers = _gtk_css_array_value_get_n_values (background_image);
+
+  for (idx = number_of_layers - 1; idx >= 0; idx--)
+    {
+      GtkCssBlendMode blend_mode;
+
+      blend_mode = _gtk_css_blend_mode_value_get (_gtk_css_array_value_get_nth (blend_modes, idx));
+
+      _gtk_theming_background_paint_layer (&bg, idx, cr, blend_mode);
+    }
 
   cairo_destroy (cr);
+
+  gtk_css_shadows_value_snapshot_inset (box_shadow,
+                                        snapshot,
+                                        &bg.boxes[GTK_CSS_AREA_PADDING_BOX]);
 }
 


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