[gtk/path-work-rebased: 47/105] path: Deal with non-uniformness of progress parameter




commit bbac8c03b5f1502b9bb9342d953011d38b253743
Author: Benjamin Otte <otte redhat com>
Date:   Wed Dec 9 21:42:55 2020 +0100

    path: Deal with non-uniformness of progress parameter
    
    The progress is non-uniform, so simple translation of progress doesn't work.
    So check if larger and smaller values inch closer towards minimal distance.

 gsk/gskcontour.c | 67 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 24 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index 472efc2f36..3ba57337c7 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -1109,23 +1109,6 @@ gsk_standard_contour_find_measure (gconstpointer m,
     return 0;
 }
 
-static void
-gsk_standard_contour_measure_get_point (GskStandardContour        *self,
-                                        gsize                      op,
-                                        float                      progress,
-                                        graphene_point_t          *pos,
-                                        graphene_vec2_t           *tangent)
-{
-  GskCurve curve;
-
-  gsk_curve_init (&curve, self->ops[op]);
-
-  if (pos)
-    gsk_curve_get_point (&curve, progress, pos);
-  if (tangent)
-    gsk_curve_get_tangent (&curve, progress, tangent);
-}
-
 static void
 gsk_standard_contour_get_point (const GskContour *contour,
                                 gpointer          measure_data,
@@ -1138,6 +1121,7 @@ gsk_standard_contour_get_point (const GskContour *contour,
   guint index;
   float progress;
   GskStandardContourMeasure *measure;
+  GskCurve curve;
 
   if (array->len == 0)
     {
@@ -1157,7 +1141,12 @@ gsk_standard_contour_get_point (const GskContour *contour,
   progress = measure->start_progress + (measure->end_progress - measure->start_progress) * progress;
   g_assert (progress >= 0 && progress <= 1);
 
-  gsk_standard_contour_measure_get_point (self, measure->op, progress, pos, tangent);
+  gsk_curve_init (&curve, self->ops[measure->op]);
+
+  if (pos)
+    gsk_curve_get_point (&curve, progress, pos);
+  if (tangent)
+    gsk_curve_get_tangent (&curve, progress, tangent);
 }
 
 static gboolean
@@ -1220,15 +1209,45 @@ gsk_standard_contour_get_closest_point (const GskContour       *contour,
       //g_print ("%zu: (%g-%g) dist %g\n", i, measure->start, measure->end, dist);
       if (dist <= threshold + 1.0f)
         {
-          graphene_vec2_t t;
-          float found_progress;
+          GskCurve curve;
+          graphene_point_t p2;
+          float found_progress, test_progress, test_dist;
+          const float step = 1/1024.f;
 
-          found_progress = measure->start_progress + (measure->end_progress - measure->start_progress) * 
progress;
+          gsk_curve_init (&curve, self->ops[measure->op]);
 
-          gsk_standard_contour_measure_get_point (self, measure->op, found_progress, &p, out_tangent ? &t : 
NULL);
+          found_progress = measure->start_progress + (measure->end_progress - measure->start_progress) * 
progress;
+          gsk_curve_get_point (&curve, found_progress, &p);
           dist = graphene_point_distance (point, &p, NULL, NULL);
+          //g_print ("!!! %zu: (%g-%g @ %g) dist %g\n", i, measure->start_progress, measure->end_progress, 
progress, dist);
+
+          /* The progress is non-uniform, so simple translation of progress doesn't work.
+           * Check if larger values inch closer towards minimal distance. */
+          while (progress + step < 1.0f) {
+            test_progress = measure->start_progress + (measure->end_progress - measure->start_progress) * 
(progress + step);
+            gsk_curve_get_point (&curve, test_progress, &p2);
+            test_dist = graphene_point_distance (point, &p2, NULL, NULL);
+            if (test_dist > dist)
+              break;
+            progress += step;
+            p = p2;
+            found_progress = test_progress;
+            dist = test_dist;
+          }
+          /* Also check smaller ones */
+          while (progress - step > 0.0f) {
+            test_progress = measure->start_progress + (measure->end_progress - measure->start_progress) * 
(progress - step);
+            gsk_curve_get_point (&curve, test_progress, &p2);
+            test_dist = graphene_point_distance (point, &p2, NULL, NULL);
+            if (test_dist > dist)
+              break;
+            progress -= step;
+            p = p2;
+            found_progress = test_progress;
+            dist = test_dist;
+          }
+          //g_print ("!!! %zu: (%g-%g @ %g) dist %g\n", i, measure->start_progress, measure->end_progress, 
progress, dist);
           /* double check that the point actually is closer */
-          //g_print ("!!! %zu: (%g-%g) dist %g\n", i, measure->start, measure->end, dist);
           if (dist <= threshold)
             {
               if (out_distance)
@@ -1238,7 +1257,7 @@ gsk_standard_contour_get_closest_point (const GskContour       *contour,
               if (out_offset)
                 *out_offset = measure->start + (measure->end - measure->start) * progress;
               if (out_tangent)
-                *out_tangent = t;
+                gsk_curve_get_tangent (&curve, found_progress, out_tangent);
               result = TRUE;
               if (tolerance >= dist)
                   return TRUE;


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