[gtk] gl renderer: Fix blurred outset shadow slicing



commit 1aa86d23f4b25f23f434f8c0f0ec90e6d255da08
Author: Timm Bäder <mail baedert org>
Date:   Wed May 20 08:01:48 2020 +0200

    gl renderer: Fix blurred outset shadow slicing
    
    Take 23.
    
    Fixes #2759

 gsk/gl/glutilsprivate.h | 287 ++++++++++++++++++++++++++++++++++++++++++++++++
 gsk/gl/gskglrenderer.c  | 232 ++++++++++++++++++--------------------
 2 files changed, 396 insertions(+), 123 deletions(-)
---
diff --git a/gsk/gl/glutilsprivate.h b/gsk/gl/glutilsprivate.h
new file mode 100644
index 0000000000..fb2c67d11b
--- /dev/null
+++ b/gsk/gl/glutilsprivate.h
@@ -0,0 +1,287 @@
+
+#pragma once
+
+#define SANITY_CHECKS 0
+
+
+enum {
+  NINE_SLICE_TOP_LEFT      = 0,
+  NINE_SLICE_TOP_CENTER    = 1,
+  NINE_SLICE_TOP_RIGHT     = 2,
+  NINE_SLICE_LEFT_CENTER   = 3,
+  NINE_SLICE_CENTER        = 4,
+  NINE_SLICE_RIGHT_CENTER  = 5,
+  NINE_SLICE_BOTTOM_LEFT   = 6,
+  NINE_SLICE_BOTTOM_CENTER = 7,
+  NINE_SLICE_BOTTOM_RIGHT  = 8,
+};
+#define NINE_SLICE_SIZE 9 /* Hah. */
+
+typedef struct
+{
+  int texture_id;
+  float x;
+  float y;
+  float x2;
+  float y2;
+} TextureRegion;
+
+static inline bool G_GNUC_PURE
+slice_is_visible (const cairo_rectangle_int_t *r)
+{
+  return (r->width > 0 && r->height > 0);
+}
+
+static inline void
+nine_slice_rounded_rect (const GskRoundedRect  *rect,
+                         cairo_rectangle_int_t *out_rects)
+{
+  const graphene_point_t *origin = &rect->bounds.origin;
+  const graphene_size_t *size = &rect->bounds.size;
+  const int top_height = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].height,
+                                     rect->corner[GSK_CORNER_TOP_RIGHT].height));
+  const int bottom_height = ceilf (MAX (rect->corner[GSK_CORNER_BOTTOM_LEFT].height,
+                                        rect->corner[GSK_CORNER_BOTTOM_RIGHT].height));
+  const int right_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_RIGHT].width,
+                                      rect->corner[GSK_CORNER_BOTTOM_RIGHT].width));
+  const int left_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].width,
+                                     rect->corner[GSK_CORNER_BOTTOM_LEFT].width));
+
+  /* Top left */
+  out_rects[0] = (cairo_rectangle_int_t) {
+                   origin->x, origin->y,
+                   left_width, top_height,
+                 };
+
+  /* Top center */
+  out_rects[1] = (cairo_rectangle_int_t) {
+                   origin->x + size->width / 2.0 - 1, origin->y,
+                   1, top_height,
+                 };
+
+  /* Top right */
+  out_rects[2] = (cairo_rectangle_int_t) {
+                   origin->x + size->width - right_width, origin->y,
+                   right_width, top_height
+                 };
+
+  /* Left center */
+  out_rects[3] = (cairo_rectangle_int_t) {
+                   origin->x, origin->y + size->height / 2,
+                   left_width, 1,
+                 };
+
+  /* center */
+  out_rects[4] = (cairo_rectangle_int_t) {
+                   origin->x + size->width / 2.0,
+                   origin->y + size->height / 2.0,
+                   1, 1
+                 };
+
+  /* Right center */
+  out_rects[5] = (cairo_rectangle_int_t) {
+                   origin->x + size->width - right_width,
+                   origin->y + (size->height / 2.0),
+                   right_width,
+                   1,
+                 };
+
+  /* Bottom Left */
+  out_rects[6] = (cairo_rectangle_int_t) {
+                   origin->x, origin->y + size->height - bottom_height,
+                   left_width, bottom_height,
+                 };
+
+  /* Bottom center */
+  out_rects[7] = (cairo_rectangle_int_t) {
+                   origin->x + (size->width / 2.0), origin->y + size->height - bottom_height,
+                   1, bottom_height,
+                 };
+
+  /* Bottom right */
+  out_rects[8] = (cairo_rectangle_int_t) {
+                   origin->x + size->width - right_width,
+                   origin->y + size->height - bottom_height,
+                   right_width, bottom_height,
+                 };
+
+#if SANITY_CHECKS
+  g_assert_cmpfloat (size->width, >=, left_width + right_width);
+  g_assert_cmpfloat (size->height, >=, top_height + bottom_height);
+#endif
+}
+
+static inline void
+nine_slice_grow (cairo_rectangle_int_t *slices,
+                 const int              amount)
+{
+  /* top left */
+  slices[0].x -= amount;
+  slices[0].y -= amount;
+  if (amount > slices[0].width)
+    slices[0].width += amount * 2;
+  else
+    slices[0].width += amount;
+
+  if (amount > slices[0].height)
+    slices[0].height += amount * 2;
+  else
+    slices[0].height += amount;
+
+
+  /* Top center */
+  slices[1].y -= amount;
+  if (amount > slices[1].height)
+    slices[1].height += amount * 2;
+  else
+    slices[1].height += amount;
+
+
+  /* top right */
+  slices[2].y -= amount;
+  if (amount > slices[2].width)
+    {
+      slices[2].x -= amount;
+      slices[2].width += amount * 2;
+    }
+  else
+    {
+     slices[2].width += amount;
+    }
+
+  if (amount > slices[2].height)
+    slices[2].height += amount * 2;
+  else
+    slices[2].height += amount;
+
+
+
+  slices[3].x -= amount;
+  if (amount > slices[3].width)
+    slices[3].width += amount * 2;
+  else
+    slices[3].width += amount;
+
+  /* Leave Britney^Wcenter alone */
+
+  if (amount > slices[5].width)
+    {
+      slices[5].x -= amount;
+      slices[5].width += amount * 2;
+    }
+  else
+    {
+      slices[5].width += amount;
+    }
+
+
+  /* Bottom left */
+  slices[6].x -= amount;
+  if (amount > slices[6].width)
+    {
+      slices[6].width += amount * 2;
+    }
+  else
+    {
+      slices[6].width += amount;
+    }
+
+  if (amount > slices[6].height)
+    {
+      slices[6].y -= amount;
+      slices[6].height += amount * 2;
+    }
+  else
+    {
+      slices[6].height += amount;
+    }
+
+
+  /* Bottom center */
+  if (amount > slices[7].height)
+    {
+      slices[7].y -= amount;
+      slices[7].height += amount * 2;
+    }
+  else
+    {
+      slices[7].height += amount;
+    }
+
+  if (amount > slices[8].width)
+    {
+      slices[8].x -= amount;
+      slices[8].width += amount * 2;
+    }
+  else
+    {
+      slices[8].width += amount;
+    }
+
+  if (amount > slices[8].height)
+    {
+      slices[8].y -= amount;
+      slices[8].height += amount * 2;
+    }
+  else
+    {
+      slices[8].height += amount;
+    }
+
+#if SANITY_CHECKS
+  {
+    for (int i = 0; i < 9; i ++)
+      {
+        g_assert_cmpint (slices[i].x, >=, 0);
+        g_assert_cmpint (slices[i].y, >=, 0);
+        g_assert_cmpint (slices[i].width, >=, 0);
+        g_assert_cmpint (slices[i].height, >=, 0);
+      }
+
+    /* Rows don't overlap */
+    for (int i = 0; i < 3; i++)
+      {
+        g_assert_cmpint (slices[i * 3 + 0].x + slices[i * 3 + 0].width, <, slices[i * 3 + 1].x);
+      }
+  }
+#endif
+
+}
+
+static inline void
+nine_slice_to_texture_coords (const cairo_rectangle_int_t *slices,
+                              const int                    texture_width,
+                              const int                    texture_height,
+                              TextureRegion               *out_regions)
+{
+  const float fw = (float)texture_width;
+  const float fh = (float)texture_height;
+  int i;
+
+  for (i = 0; i < 9; i++)
+    {
+      out_regions[i] = (TextureRegion) {
+        0, /* Texture id */
+        slices[i].x / fw,
+        1.0 - ((slices[i].y + slices[i].height) / fh),
+        (slices[i].x + slices[i].width)  / fw,
+        1.0 - (slices[i].y / fh),
+      };
+    }
+
+#if SANITY_CHECKS
+  {
+    for (i = 0; i < 9; i++)
+      {
+        const TextureRegion *r = &out_regions[i];
+        g_assert_cmpfloat (r->x, >=, 0);
+        g_assert_cmpfloat (r->x, <=, 1);
+        g_assert_cmpfloat (r->y, >=, 0);
+        g_assert_cmpfloat (r->y, <=, 1);
+
+        g_assert_cmpfloat (r->x, <, r->x2);
+        g_assert_cmpfloat (r->y, <, r->y2);
+      }
+  }
+#endif
+}
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 2061a12fec..288a015524 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -18,6 +18,7 @@
 #include "gskglshadowcacheprivate.h"
 #include "gskglnodesampleprivate.h"
 #include "gsktransform.h"
+#include "glutilsprivate.h"
 
 #include "gskprivate.h"
 
@@ -73,15 +74,6 @@ typedef enum
   NO_CACHE_PLZ     = 1 << 5,
 } OffscreenFlags;
 
-typedef struct
-{
-  int texture_id;
-  float x;
-  float y;
-  float x2;
-  float y2;
-} TextureRegion;
-
 static inline void
 init_full_texture_region (TextureRegion *r,
                           int            texture_id)
@@ -1712,6 +1704,8 @@ render_unblurred_outset_shadow_node (GskGLRenderer   *self,
   load_vertex_data (ops_draw (builder, NULL), node, builder);
 }
 
+
+
 static GdkRGBA COLOR_WHITE = { 1, 1, 1, 1 };
 static inline void
 render_outset_shadow_node (GskGLRenderer   *self,
@@ -1727,8 +1721,7 @@ render_outset_shadow_node (GskGLRenderer   *self,
   const float dx = gsk_outset_shadow_node_get_dx (node);
   const float dy = gsk_outset_shadow_node_get_dy (node);
   GskRoundedRect scaled_outline;
-  GskRoundedRect unscaled_outline;
-  float texture_width, texture_height;
+  int texture_width, texture_height;
   OpShadow *shadow;
   int blurred_texture_id;
   int cached_tid;
@@ -1740,15 +1733,14 @@ render_outset_shadow_node (GskGLRenderer   *self,
   gsk_rounded_rect_shrink_to_minimum (&scaled_outline);
   /* Increase by the spread */
   gsk_rounded_rect_shrink (&scaled_outline, -spread, -spread, -spread, -spread);
+  /* Grow bounds but don't grow corners */
+  graphene_rect_inset (&scaled_outline.bounds, - blur_extra / 2.0 * scale, - blur_extra / 2.0 * scale);
   /* For the center part, we add a few pixels */
   scaled_outline.bounds.size.width += SHADOW_EXTRA_SIZE;
   scaled_outline.bounds.size.height += SHADOW_EXTRA_SIZE;
 
-  texture_width  = ceil ((scaled_outline.bounds.size.width  + (blur_extra)) * scale);
-  texture_height = ceil ((scaled_outline.bounds.size.height + (blur_extra)) * scale);
-
-  /* Preserve this for usage later */
-  unscaled_outline = scaled_outline;
+  texture_width  = (int)ceil ((scaled_outline.bounds.size.width  + blur_extra) * scale);
+  texture_height = (int)ceil ((scaled_outline.bounds.size.height + blur_extra) * scale);
 
   scaled_outline.bounds.origin.x = blur_extra / 2.0 * scale;
   scaled_outline.bounds.origin.y = blur_extra / 2.0 * scale;
@@ -1782,6 +1774,7 @@ render_outset_shadow_node (GskGLRenderer   *self,
       gdk_gl_context_label_object_printf  (self->gl_context, GL_FRAMEBUFFER, render_target,
                                            "Outset Shadow FB Temp %d", render_target);
 
+      ops_set_program (builder, &self->programs->color_program);
       graphene_matrix_init_ortho (&item_proj,
                                   0, texture_width, 0, texture_height,
                                   ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
@@ -1794,7 +1787,6 @@ render_outset_shadow_node (GskGLRenderer   *self,
       prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
 
       /* Draw outline */
-      ops_set_program (builder, &self->programs->color_program);
       ops_push_clip (builder, &scaled_outline);
       ops_set_color (builder, &COLOR_WHITE);
       ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
@@ -1843,42 +1835,30 @@ render_outset_shadow_node (GskGLRenderer   *self,
     const float min_y = builder->dy + outline->bounds.origin.y - spread - (blur_extra / 2.0) + dy;
     const float max_x = min_x + outline->bounds.size.width  + (spread + (blur_extra / 2.0)) * 2;
     const float max_y = min_y + outline->bounds.size.height + (spread + (blur_extra / 2.0)) * 2;
-    const float left_width = MAX (MAX (unscaled_outline.corner[GSK_CORNER_TOP_LEFT].width,
-                                       unscaled_outline.corner[GSK_CORNER_BOTTOM_LEFT].width),
-                                  blur_extra / 2.0);
-    const float top_height = MAX (MAX (unscaled_outline.corner[GSK_CORNER_TOP_LEFT].height,
-                                       unscaled_outline.corner[GSK_CORNER_TOP_RIGHT].height),
-                                  blur_extra / 2.0);
-    const float right_width = MAX (MAX (unscaled_outline.corner[GSK_CORNER_TOP_RIGHT].width,
-                                        unscaled_outline.corner[GSK_CORNER_BOTTOM_RIGHT].width),
-                                   blur_extra / 2.0);
-    const float bottom_height = MAX (MAX (unscaled_outline.corner[GSK_CORNER_BOTTOM_LEFT].height,
-                                          unscaled_outline.corner[GSK_CORNER_BOTTOM_RIGHT].height),
-                                     blur_extra / 2.0);
-    const float center_width = (max_x - min_x) - left_width - right_width;
-    const float center_height = (max_y - min_y) - top_height - bottom_height;
     float x1, x2, y1, y2, tx1, tx2, ty1, ty2;
+    cairo_rectangle_int_t slices[9];
+    TextureRegion tregs[9];
+
+    /* TODO: The slicing never changes and could just go into the cache */
+    nine_slice_rounded_rect (&scaled_outline, slices);
+    nine_slice_grow (slices, blur_extra / 2.0 * scale);
+    nine_slice_to_texture_coords (slices, texture_width, texture_height, tregs);
 
     /* Our texture coordinates MUST be scaled, while the actual vertex coords
      * MUST NOT be scaled. */
 
     /* Top left */
-    if (top_height > 0 && left_width > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_TOP_LEFT]))
       {
         x1 = min_x;
-        x2 = min_x + left_width;
+        x2 = min_x + (slices[NINE_SLICE_TOP_LEFT].width / scale);
         y1 = min_y;
-        y2 = min_y + top_height;
+        y2 = min_y + (slices[NINE_SLICE_TOP_LEFT].height / scale);
 
-        tx1 = 0;
-        tx2 = (left_width * scale) / texture_width;
-        ty1 = 1 - (top_height * scale / texture_height);
-        ty2 = 1;
-
-        g_assert_cmpfloat (x1, <=, x2);
-        g_assert_cmpfloat (y1, <=, y2);
-        g_assert_cmpfloat (tx1, <=, tx2);
-        g_assert_cmpfloat (ty1, <=, ty2);
+        tx1 = tregs[NINE_SLICE_TOP_LEFT].x;
+        tx2 = tregs[NINE_SLICE_TOP_LEFT].x2;
+        ty1 = tregs[NINE_SLICE_TOP_LEFT].y;
+        ty2 = tregs[NINE_SLICE_TOP_LEFT].y2;
 
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
@@ -1891,23 +1871,18 @@ render_outset_shadow_node (GskGLRenderer   *self,
         });
       }
 
-    /* Top side */
-    if (top_height > 0 && center_width > 0)
+    /* Top center */
+    if (slice_is_visible (&slices[NINE_SLICE_TOP_CENTER]))
       {
-        x1 = min_x + left_width;
-        x2 = x1 + center_width;
+        x1 = min_x + (slices[NINE_SLICE_TOP_LEFT].width / scale);
+        x2 = max_x - (slices[NINE_SLICE_TOP_RIGHT].width / scale);
         y1 = min_y;
-        y2 = min_y + top_height;
-
-        tx1 = left_width * scale / texture_width;
-        tx2 = 1.0 - (right_width * scale / texture_width);
-        ty1 = 1 - (top_height * scale / texture_height);
-        ty2 = 1;
+        y2 = min_y + (slices[NINE_SLICE_TOP_CENTER].height / scale);
 
-        g_assert_cmpfloat (x1, <=, x2);
-        g_assert_cmpfloat (y1, <=, y2);
-        g_assert_cmpfloat (tx1, <=, tx2);
-        g_assert_cmpfloat (ty1, <=, ty2);
+        tx1 = tregs[NINE_SLICE_TOP_CENTER].x;
+        tx2 = tregs[NINE_SLICE_TOP_CENTER].x2;
+        ty1 = tregs[NINE_SLICE_TOP_CENTER].y;
+        ty2 = tregs[NINE_SLICE_TOP_CENTER].y2;
 
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
@@ -1921,20 +1896,23 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Top right */
-    if (top_height > 0 && right_width > 0)
-    {
-      x1 = max_x - right_width;
-      x2 = max_x;
-      y1 = min_y;
-      y2 = min_y + top_height;
-      tx1 = 1 - (right_width * scale / texture_width);
-      tx2 = 1;
-      ty1 = 1 - (top_height * scale / texture_height);
-      ty2 = 1;
-      ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
-        { { x1, y1 }, { tx1, ty2 }, },
-        { { x1, y2 }, { tx1, ty1 }, },
-        { { x2, y1 }, { tx2, ty2 }, },
+    if (slice_is_visible (&slices[NINE_SLICE_TOP_RIGHT]))
+      {
+        x1 = max_x - (slices[NINE_SLICE_TOP_RIGHT].width / scale);
+        x2 = max_x;
+        y1 = min_y;
+        y2 = min_y + (slices[NINE_SLICE_TOP_RIGHT].height / scale);
+
+        tx1 = tregs[NINE_SLICE_TOP_RIGHT].x;
+        tx2 = tregs[NINE_SLICE_TOP_RIGHT].x2;
+
+        ty1 = tregs[NINE_SLICE_TOP_RIGHT].y;
+        ty2 = tregs[NINE_SLICE_TOP_RIGHT].y2;
+
+        ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
+          { { x1, y1 }, { tx1, ty2 }, },
+          { { x1, y2 }, { tx1, ty1 }, },
+          { { x2, y1 }, { tx2, ty2 }, },
 
           { { x2, y2 }, { tx2, ty1 }, },
           { { x1, y2 }, { tx1, ty1 }, },
@@ -1943,16 +1921,17 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Bottom right */
-    if (bottom_height > 0 && left_width > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_BOTTOM_RIGHT]))
       {
-        x1 = max_x - right_width;
+        x1 = max_x - (slices[NINE_SLICE_BOTTOM_RIGHT].width / scale);
         x2 = max_x;
-        y1 = max_y - bottom_height;
+        y1 = max_y - (slices[NINE_SLICE_BOTTOM_RIGHT].height / scale);
         y2 = max_y;
-        tx1 = 1 - (right_width * scale / texture_width);
-        tx2 = 1;
-        ty1 = 0;
-        ty2 = (bottom_height * scale / texture_height);
+        tx1 = tregs[NINE_SLICE_BOTTOM_RIGHT].x;
+        tx2 = tregs[NINE_SLICE_BOTTOM_RIGHT].x2;
+        ty1 = tregs[NINE_SLICE_BOTTOM_RIGHT].y;
+        ty2 = tregs[NINE_SLICE_BOTTOM_RIGHT].y2;
+
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
           { { x1, y2 }, { tx1, ty1 }, },
@@ -1965,16 +1944,18 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Bottom left */
-    if (bottom_height > 0 && left_width > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_BOTTOM_LEFT]))
       {
         x1 = min_x;
-        x2 = min_x + left_width;
-        y1 = max_y - bottom_height;
+        x2 = min_x + (slices[NINE_SLICE_BOTTOM_LEFT].width / scale);
+        y1 = max_y - (slices[NINE_SLICE_BOTTOM_LEFT].height / scale);
         y2 = max_y;
-        tx1 = 0;
-        tx2 = left_width * scale / texture_width;
-        ty1 = 0;
-        ty2 = bottom_height * scale / texture_height;
+
+        tx1 = tregs[NINE_SLICE_BOTTOM_LEFT].x;
+        tx2 = tregs[NINE_SLICE_BOTTOM_LEFT].x2;
+        ty1 = tregs[NINE_SLICE_BOTTOM_LEFT].y;
+        ty2 = tregs[NINE_SLICE_BOTTOM_LEFT].y2;
+
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
           { { x1, y2 }, { tx1, ty1 }, },
@@ -1987,21 +1968,16 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Left side */
-    if (left_width > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_LEFT_CENTER]))
       {
         x1 = min_x;
-        x2 = min_x + left_width;
-        y1 = min_y + top_height;
-        y2 = y1 + center_height;
-        tx1 = 0;
-        tx2 = left_width * scale / texture_width;
-        ty1 = top_height * scale / texture_height;
-        ty2 = 1.0 - (bottom_height * scale / texture_height);
-
-        g_assert_cmpfloat (x1, <=, x2);
-        g_assert_cmpfloat (y1, <=, y2);
-        g_assert_cmpfloat (tx1, <=, tx2);
-        g_assert_cmpfloat (ty1, <=, ty2);
+        x2 = min_x + (slices[NINE_SLICE_LEFT_CENTER].width / scale);
+        y1 = min_y + (slices[NINE_SLICE_TOP_LEFT].height / scale);
+        y2 = max_y - (slices[NINE_SLICE_BOTTOM_LEFT].height / scale);
+        tx1 = tregs[NINE_SLICE_LEFT_CENTER].x;
+        tx2 = tregs[NINE_SLICE_LEFT_CENTER].x2;
+        ty1 = tregs[NINE_SLICE_LEFT_CENTER].y;
+        ty2 = tregs[NINE_SLICE_LEFT_CENTER].y2;
 
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
@@ -2015,16 +1991,19 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Right side */
-    if (right_width > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_RIGHT_CENTER]))
       {
-        x1 = max_x - right_width;
+        x1 = max_x - (slices[NINE_SLICE_RIGHT_CENTER].width / scale);
         x2 = max_x;
-        y1 = min_y + top_height;
-        y2 = y1 + center_height;
-        tx1 = 1 - (right_width * scale / texture_width);
-        tx2 = 1;
-        ty1 = top_height * scale / texture_height;
-        ty2 = 1.0 - (bottom_height * scale / texture_height);
+        y1 = min_y + (slices[NINE_SLICE_TOP_RIGHT].height / scale);
+        y2 = max_y - (slices[NINE_SLICE_BOTTOM_RIGHT].height / scale);
+
+        tx1 = tregs[NINE_SLICE_RIGHT_CENTER].x;
+        tx2 = tregs[NINE_SLICE_RIGHT_CENTER].x2;
+
+        ty1 = tregs[NINE_SLICE_RIGHT_CENTER].y;
+        ty2 = tregs[NINE_SLICE_RIGHT_CENTER].y2;
+
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
           { { x1, y2 }, { tx1, ty1 }, },
@@ -2037,16 +2016,20 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Bottom side */
-    if (bottom_height > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_BOTTOM_CENTER]))
       {
-        x1 = min_x + left_width;
-        x2 = max_x - right_width;
-        y1 = max_y - bottom_height;
+        x1 = min_x + (slices[NINE_SLICE_BOTTOM_LEFT].width / scale);
+        x2 = max_x - (slices[NINE_SLICE_BOTTOM_RIGHT].width / scale);
+        y1 = max_y - (slices[NINE_SLICE_BOTTOM_CENTER].height / scale);
         y2 = max_y;
-        tx1 = left_width * scale / texture_width;
-        tx2 = 1.0 - (right_width * scale / texture_width);
-        ty1 = 0;
-        ty2 = bottom_height * scale / texture_height;
+
+        tx1 = tregs[NINE_SLICE_BOTTOM_CENTER].x;
+        tx2 = tregs[NINE_SLICE_BOTTOM_CENTER].x2;
+
+        ty1 = tregs[NINE_SLICE_BOTTOM_CENTER].y;
+        ty2 = tregs[NINE_SLICE_BOTTOM_CENTER].y2;
+
+
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
           { { x1, y2 }, { tx1, ty1 }, },
@@ -2059,16 +2042,19 @@ render_outset_shadow_node (GskGLRenderer   *self,
       }
 
     /* Middle */
-    if (center_width > 0 && center_height > 0)
+    if (slice_is_visible (&slices[NINE_SLICE_CENTER]))
       {
-        x1 = min_x + left_width;
-        x2 = max_x - right_width;
-        y1 = min_y + top_height;
-        y2 = max_y - bottom_height;
-        tx1 = left_width * scale / texture_width;
-        tx2 = 1.0 - (right_width * scale / texture_width);
-        ty1 = top_height * scale / texture_height;
-        ty2 = 1.0 - (bottom_height * scale / texture_height);
+        x1 = min_x + (slices[NINE_SLICE_LEFT_CENTER].width / scale);
+        x2 = max_x - (slices[NINE_SLICE_RIGHT_CENTER].width / scale);
+        y1 = min_y + (slices[NINE_SLICE_TOP_CENTER].height / scale);
+        y2 = max_y - (slices[NINE_SLICE_BOTTOM_CENTER].height / scale);
+
+        tx1 = tregs[NINE_SLICE_CENTER].x;
+        tx2 = tregs[NINE_SLICE_CENTER].x2;
+
+        ty1 = tregs[NINE_SLICE_CENTER].y;
+        ty2 = tregs[NINE_SLICE_CENTER].y2;
+
         ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
           { { x1, y1 }, { tx1, ty2 }, },
           { { x1, y2 }, { tx1, ty1 }, },


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