From 0c39890e0f89a4edc283f5930306d9502d8ae4a9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 18 Aug 2023 09:49:51 -0400 Subject: [PATCH] contour: Optimize bounds Cache the bounds in the contour, and compute the stroke bounds based on it as well. --- gsk/gskcontour.c | 76 +++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 53 deletions(-) diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c index fd79e28c71..47e5786eea 100644 --- a/gsk/gskcontour.c +++ b/gsk/gskcontour.c @@ -119,6 +119,8 @@ struct _GskStandardContour GskPathFlags flags; + GskBoundingBox bounds; + gsize n_ops; gsize n_points; graphene_point_t *points; @@ -254,7 +256,7 @@ gsk_standard_contour_print (const GskContour *contour, const graphene_point_t *pt = gsk_pathop_points (self->ops[i]); switch (gsk_pathop_op (self->ops[i])) - { + { case GSK_PATH_MOVE: g_string_append (string, "M "); _g_string_append_point (string, &pt[0]); @@ -288,7 +290,7 @@ gsk_standard_contour_print (const GskContour *contour, default: g_assert_not_reached(); return; - } + } } } @@ -297,68 +299,32 @@ gsk_standard_contour_get_bounds (const GskContour *contour, GskBoundingBox *bounds) { const GskStandardContour *self = (const GskStandardContour *) contour; - gsize i; if (self->n_points == 0) return FALSE; - gsk_bounding_box_init (bounds, &self->points[0], &self->points[0]); - for (i = 1; i < self->n_points; i ++) - gsk_bounding_box_expand (bounds, &self->points[i]); + *bounds = self->bounds; return bounds->max.x > bounds->min.x && bounds->max.y > bounds->min.y; } -static gboolean -add_stroke_bounds (GskPathOperation op, - const graphene_point_t *pts, - gsize n_pts, - gpointer user_data) -{ - struct { - GskBoundingBox *bounds; - float lw; - float mw; - } *data = user_data; - GskBoundingBox bounds; - - for (int i = 1; i < n_pts - 1; i++) - { - gsk_bounding_box_init (&bounds, - &GRAPHENE_POINT_INIT (pts[i].x - data->lw/2, pts[i].y - data->lw/2), - &GRAPHENE_POINT_INIT (pts[i].x + data->lw/2, pts[i].y + data->lw/2)); - gsk_bounding_box_union (&bounds, data->bounds, data->bounds); - } - - gsk_bounding_box_init (&bounds, - &GRAPHENE_POINT_INIT (pts[n_pts - 1].x - data->mw/2, pts[n_pts - 1].y - data->mw/2), - &GRAPHENE_POINT_INIT (pts[n_pts - 1].x + data->mw/2, pts[n_pts - 1].y + data->mw/2)); - gsk_bounding_box_union (&bounds, data->bounds, data->bounds); - - return TRUE; -} - static gboolean gsk_standard_contour_get_stroke_bounds (const GskContour *contour, const GskStroke *stroke, GskBoundingBox *bounds) { GskStandardContour *self = (GskStandardContour *) contour; - struct { - GskBoundingBox *bounds; - float lw; - float mw; - } data; + float extra; - data.bounds = bounds; - data.lw = stroke->line_width; - data.mw = gsk_stroke_get_join_width (stroke); + if (self->n_points == 0) + return FALSE; - gsk_bounding_box_init (bounds, - &GRAPHENE_POINT_INIT (self->points[0].x - data.mw/2, self->points[0].y - data.mw/2), - &GRAPHENE_POINT_INIT (self->points[0].x + data.mw/2, self->points[0].y + data.mw/2)); + extra = MAX (stroke->line_width / 2, gsk_stroke_get_join_width (stroke) / 2); - gsk_standard_contour_foreach (contour, GSK_PATH_TOLERANCE_DEFAULT, add_stroke_bounds, &data); + gsk_bounding_box_init (bounds, &GRAPHENE_POINT_INIT (self->bounds.min.x - extra, + self->bounds.min.y - extra), + &GRAPHENE_POINT_INIT (self->bounds.max.x + extra, + self->bounds.max.y + extra)); return TRUE; } @@ -384,6 +350,9 @@ gsk_standard_contour_get_winding (const GskContour *contour, GskStandardContour *self = (GskStandardContour *) contour; int winding = 0; + if (!gsk_bounding_box_contains_point (&self->bounds, point)) + return 0; + for (gsize i = 0; i < self->n_ops; i ++) { GskCurve c; @@ -669,7 +638,6 @@ gsk_standard_contour_init (GskContour *contour, { GskStandardContour *self = (GskStandardContour *) contour; - gsize i; self->contour.klass = &GSK_STANDARD_CONTOUR_CLASS; @@ -680,11 +648,13 @@ gsk_standard_contour_init (GskContour *contour, memcpy (self->points, points, sizeof (graphene_point_t) * n_points); offset += self->points - points; - for (i = 0; i < n_ops; i++) - { - self->ops[i] = gsk_pathop_encode (gsk_pathop_op (ops[i]), - gsk_pathop_points (ops[i]) + offset); - } + for (gsize i = 0; i < n_ops; i++) + self->ops[i] = gsk_pathop_encode (gsk_pathop_op (ops[i]), + gsk_pathop_points (ops[i]) + offset); + + gsk_bounding_box_init (&self->bounds, &self->points[0], &self->points[0]); + for (gsize i = 1; i < self->n_points; i ++) + gsk_bounding_box_expand (&self->bounds, &self->points[i]); } GskContour *