diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c index e433d8c508..c7c74e9cff 100644 --- a/gsk/gskcontour.c +++ b/gsk/gskcontour.c @@ -1124,23 +1124,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, @@ -1153,6 +1136,7 @@ gsk_standard_contour_get_point (const GskContour *contour, guint index; float progress; GskStandardContourMeasure *measure; + GskCurve curve; if (array->len == 0) { @@ -1172,7 +1156,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 @@ -1235,15 +1224,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; + + gsk_curve_init (&curve, self->ops[measure->op]); found_progress = measure->start_progress + (measure->end_progress - measure->start_progress) * progress; - - gsk_standard_contour_measure_get_point (self, measure->op, found_progress, &p, out_tangent ? &t : NULL); + 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) @@ -1253,7 +1272,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;