[gtk/fix-rect-closest-point: 58/58] Fix get_closest_point for rectangles




commit 137eef6465dc275fad1b3548ded9fa4aa6c30acb
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 5 02:56:55 2020 -0500

    Fix get_closest_point for rectangles
    
    This was still returning wrong offsets for one of the four
    sides. Add a testcase for rectangles and circles to prevent
    this happening again in the future.

 gsk/gskcontour.c                   |  9 +++++--
 testsuite/gsk/path-special-cases.c | 51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index c7c74e9cff..8d47b456a4 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -359,8 +359,13 @@ gsk_rect_contour_get_closest_point (const GskContour       *contour,
     *out_pos = p;
 
   if (out_offset)
-    *out_offset = (t.x == 0.0 && self->width > 0 ? 2 - t.y : t.y) * ABS (self->height) + 
-                  (t.y == 1.0 ? 2 - t.x : t.x) * ABS (self->width);
+    {
+      if (t.x == 0.0 && t.y == 0.0)
+        *out_offset = 0.0;
+      else
+        *out_offset = (t.x == 0.0 && self->width > 0 ? 2 - t.y : t.y) * ABS (self->height) +
+                      (t.y > 0 ? 2 - t.x : t.x) * ABS (self->width);
+    }
 
   if (out_tangent)
     {
diff --git a/testsuite/gsk/path-special-cases.c b/testsuite/gsk/path-special-cases.c
index 04a575ac1f..3f65556064 100644
--- a/testsuite/gsk/path-special-cases.c
+++ b/testsuite/gsk/path-special-cases.c
@@ -306,6 +306,56 @@ test_serialize_custom_contours (void)
   gsk_path_unref (path1);
 }
 
+/* Test that get_closest_point works for rectangles and circles */
+static void
+test_closest_point_custom_contours (void)
+{
+  static const float tolerance = 0.5;
+  GskPathBuilder *builder;
+  GskPath *path;
+  GskPathMeasure *measure;
+  float length, offset, closest_offset, distance;
+  graphene_point_t point, closest_point;
+  guint i, j;
+
+  for (i = 0; i < 2; i++)
+    {
+      builder = gsk_path_builder_new ();
+      if (i == 0)
+        gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (100, 100, 200, 200));
+      else
+        gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (100, 100), 200);
+
+      path = gsk_path_builder_free_to_path (builder);
+
+      measure = gsk_path_measure_new_with_tolerance (path, tolerance);
+      length = gsk_path_measure_get_length (measure);
+
+      for (j = 0; j < 100; j++)
+        {
+          offset = g_test_rand_double_range (0, length);
+
+          gsk_path_measure_get_point (measure,
+                                      offset,
+                                      &point,
+                                      NULL);
+          g_assert_true (gsk_path_measure_get_closest_point_full (measure,
+                                                                  &point,
+                                                                  tolerance,
+                                                                  &distance,
+                                                                  &closest_point,
+                                                                  &closest_offset,
+                                                                  NULL));
+          g_assert_cmpfloat (distance, <=, tolerance);
+          g_assert_cmpfloat (graphene_point_distance (&point, &closest_point, NULL, NULL), <=, tolerance);
+          g_assert_cmpfloat_with_epsilon (closest_offset, offset, tolerance);
+        }
+
+      gsk_path_measure_unref (measure);
+      gsk_path_unref (path);
+    }
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -314,6 +364,7 @@ main (int   argc,
 
   g_test_add_func ("/path/rsvg-parse", test_rsvg_parse);
   g_test_add_func ("/path/serialize-custom-contours", test_serialize_custom_contours);
+  g_test_add_func ("/path/closest-point-custom-contours", test_closest_point_custom_contours);
 
   return g_test_run ();
 }


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