[gtk/wip/otte/no-clip-on-draw: 1/8] roundedrect: Fix gsk_rounded_rect_intersects_rect()



commit 45c45d63461c41ea41d476ab1de734321d1de86e
Author: Benjamin Otte <otte redhat com>
Date:   Thu Feb 13 05:21:49 2020 +0100

    roundedrect: Fix gsk_rounded_rect_intersects_rect()
    
    The previous code would return FALSE for
      gsk_rounded_rect_intersects_rect (&rounded, &rounded.bounds);
    if rounded was indeed rounded.

 gsk/gskroundedrect.c | 65 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 42 insertions(+), 23 deletions(-)
---
diff --git a/gsk/gskroundedrect.c b/gsk/gskroundedrect.c
index bde6078b4e..a82f8831d9 100644
--- a/gsk/gskroundedrect.c
+++ b/gsk/gskroundedrect.c
@@ -324,25 +324,25 @@ ellipsis_contains_point (const graphene_size_t *ellipsis,
        + (point->y * point->y) / (ellipsis->height * ellipsis->height) <= 1;
 }
 
-/**
- * gsk_rounded_rect_contains_point:
- * @self: a #GskRoundedRect
- * @point: the point to check
- *
- * Checks if the given @point is inside the rounded rectangle. This function
- * returns %FALSE if the point is in the rounded corner areas.
- *
- * Returns: %TRUE if the @point is inside the rounded rectangle
- **/
-gboolean
-gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
-                                 const graphene_point_t *point)
+typedef enum
+{
+  INSIDE,
+  OUTSIDE_TOP_LEFT,
+  OUTSIDE_TOP_RIGHT,
+  OUTSIDE_BOTTOM_LEFT,
+  OUTSIDE_BOTTOM_RIGHT,
+  OUTSIDE
+} Location;
+
+static Location
+gsk_rounded_rect_locate_point (const GskRoundedRect   *self,
+                               const graphene_point_t *point)
 {
   if (point->x < self->bounds.origin.x ||
       point->y < self->bounds.origin.y ||
       point->x >= self->bounds.origin.x + self->bounds.size.width ||
       point->y >= self->bounds.origin.y + self->bounds.size.height)
-    return FALSE;
+    return OUTSIDE;
 
   if (self->bounds.origin.x + self->corner[GSK_CORNER_TOP_LEFT].width > point->x &&
       self->bounds.origin.y + self->corner[GSK_CORNER_TOP_LEFT].height > point->y &&
@@ -351,7 +351,7 @@ gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
                                     self->bounds.origin.x + self->corner[GSK_CORNER_TOP_LEFT].width - 
point->x,
                                     self->bounds.origin.y + self->corner[GSK_CORNER_TOP_LEFT].height- 
point->y
                                 )))
-    return FALSE;
+    return OUTSIDE_TOP_LEFT;
 
   if (self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_TOP_RIGHT].width < point->x 
&&
       self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height > point->y &&
@@ -360,7 +360,7 @@ gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
                                     self->bounds.origin.x + self->bounds.size.width - 
self->corner[GSK_CORNER_TOP_RIGHT].width - point->x,
                                     self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height- 
point->y
                                 )))
-    return FALSE;
+    return OUTSIDE_TOP_RIGHT;
 
   if (self->bounds.origin.x + self->corner[GSK_CORNER_BOTTOM_LEFT].width > point->x &&
       self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_LEFT].height < 
point->y &&
@@ -369,7 +369,7 @@ gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
                                     self->bounds.origin.x + self->corner[GSK_CORNER_BOTTOM_LEFT].width - 
point->x,
                                     self->bounds.origin.y + self->bounds.size.height - 
self->corner[GSK_CORNER_BOTTOM_LEFT].height- point->y
                                 )))
-    return FALSE;
+    return OUTSIDE_BOTTOM_LEFT;
 
   if (self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_BOTTOM_RIGHT].width < 
point->x &&
       self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_RIGHT].height < 
point->y &&
@@ -378,9 +378,26 @@ gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
                                     self->bounds.origin.x + self->bounds.size.width - 
self->corner[GSK_CORNER_BOTTOM_RIGHT].width - point->x,
                                     self->bounds.origin.y + self->bounds.size.height - 
self->corner[GSK_CORNER_BOTTOM_RIGHT].height- point->y
                                 )))
-    return FALSE;
+    return OUTSIDE_BOTTOM_RIGHT;
 
-  return TRUE;
+  return INSIDE;
+}
+
+/**
+ * gsk_rounded_rect_contains_point:
+ * @self: a #GskRoundedRect
+ * @point: the point to check
+ *
+ * Checks if the given @point is inside the rounded rectangle. This function
+ * returns %FALSE if the point is in the rounded corner areas.
+ *
+ * Returns: %TRUE if the @point is inside the rounded rectangle
+ **/
+gboolean
+gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
+                                 const graphene_point_t *point)
+{
+  return gsk_rounded_rect_locate_point (self, point) != INSIDE;
 }
 
 /**
@@ -431,10 +448,12 @@ gsk_rounded_rect_intersects_rect (const GskRoundedRect  *self,
   if (!graphene_rect_intersection (&self->bounds, rect, NULL))
     return FALSE;
 
-  if (!gsk_rounded_rect_contains_point (self, &rect->origin) &&
-      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, 
rect->origin.y)) &&
-      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + 
rect->size.height)) &&
-      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, 
rect->origin.y + rect->size.height)))
+  /* If the bounding boxes intersect but the rectangles don't, one of the rect's corners
+   * must be in the opposite corner's outside region */
+  if (gsk_rounded_rect_locate_point (self, &rect->origin) == OUTSIDE_BOTTOM_RIGHT ||
+      gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, 
rect->origin.y)) == OUTSIDE_BOTTOM_LEFT ||
+      gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + 
rect->size.height)) == OUTSIDE_TOP_RIGHT ||
+      gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, 
rect->origin.y + rect->size.height)) == OUTSIDE_TOP_LEFT)
     return FALSE;
 
   return TRUE;


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