From daa122e632b9c06a0b6fb8971a41b2886d0e99cc Mon Sep 17 00:00:00 2001 From: buliabyak Date: Sun, 18 Mar 2007 21:07:21 +0000 Subject: [PATCH] optimize cairo paths by not drawing segments that are outside of view (for stroke only); increase tolerance for picking, not calculate wind when it's not needed --- src/display/inkscape-cairo.cpp | 51 ++++++++++++++++++++++++--------- src/display/inkscape-cairo.h | 2 +- src/display/nr-arena-glyphs.cpp | 2 +- src/display/nr-arena-shape.cpp | 15 +++++----- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp index 39cd90ed6..9a8500885 100644 --- a/src/display/inkscape-cairo.cpp +++ b/src/display/inkscape-cairo.cpp @@ -46,9 +46,13 @@ nr_create_cairo_context (NRRectL *area, NRPixBlock *pb) /** Feeds path-creating calls to the cairo context translating them from the SPCurve, with the given transform and shift */ void -feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point shift) +feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Rect area, bool optimize_stroke, double stroke_width) { - NR::Point lastX(0,0); + NR::Point next(0,0), last(0,0); + NR::Point shift = area.min(); + NR::Rect view = area; + view.growBy (stroke_width); + NR::Rect swept; bool closed = false; for (int i = 0; bpath[i].code != NR_END; i++) { switch (bpath[i].code) { @@ -56,19 +60,30 @@ feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point case NR_MOVETO: if (closed) cairo_close_path(ct); closed = (bpath[i].code == NR_MOVETO); - lastX[NR::X] = bpath[i].x3; - lastX[NR::Y] = bpath[i].y3; - lastX *= trans; - lastX -= shift; - cairo_move_to(ct, lastX[NR::X], lastX[NR::Y]); + next[NR::X] = bpath[i].x3; + next[NR::Y] = bpath[i].y3; + next *= trans; + last = next; + next -= shift; + cairo_move_to(ct, next[NR::X], next[NR::Y]); break; case NR_LINETO: - lastX[NR::X] = bpath[i].x3; - lastX[NR::Y] = bpath[i].y3; - lastX *= trans; - lastX -= shift; - cairo_line_to(ct, lastX[NR::X], lastX[NR::Y]); + next[NR::X] = bpath[i].x3; + next[NR::Y] = bpath[i].y3; + next *= trans; + if (optimize_stroke) { + swept = NR::Rect(last, next); + //std::cout << "swept: " << swept; + //std::cout << "view: " << view; + //std::cout << "intersects? " << (swept.intersects(view)? "YES" : "NO") << "\n"; + } + last = next; + next -= shift; + if (!optimize_stroke || swept.intersects(view)) + cairo_line_to(ct, next[NR::X], next[NR::Y]); + else + cairo_move_to(ct, next[NR::X], next[NR::Y]); break; case NR_CURVETO: { @@ -82,10 +97,20 @@ feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point tm1 *= trans; tm2 *= trans; tm3 *= trans; + if (optimize_stroke) { + swept = NR::Rect(last, last); + swept.expandTo(tm1); + swept.expandTo(tm2); + swept.expandTo(tm3); + } + last = tm3; tm1 -= shift; tm2 -= shift; tm3 -= shift; - cairo_curve_to (ct, tm1[NR::X], tm1[NR::Y], tm2[NR::X], tm2[NR::Y], tm3[NR::X], tm3[NR::Y]); + if (!optimize_stroke || swept.intersects(view)) + cairo_curve_to (ct, tm1[NR::X], tm1[NR::Y], tm2[NR::X], tm2[NR::Y], tm3[NR::X], tm3[NR::Y]); + else + cairo_move_to(ct, tm3[NR::X], tm3[NR::Y]); break; } diff --git a/src/display/inkscape-cairo.h b/src/display/inkscape-cairo.h index 0692a0d06..4b9f50e76 100644 --- a/src/display/inkscape-cairo.h +++ b/src/display/inkscape-cairo.h @@ -11,7 +11,7 @@ */ cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb); -void feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point shift); +void feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Rect area, bool optimize_stroke, double stroke_width); #endif /* diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index c8e51a19c..b6f0e5d60 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -458,7 +458,7 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi cairo_new_path(ct); NR::Matrix g_t(g->g_transform); - feed_curve_to_cairo (ct, bpath, g_t * group->ctm, NR::Point(pb->area.x0, pb->area.y0)); + feed_curve_to_cairo (ct, bpath, g_t * group->ctm, NR::Rect(&pb->area), false, 0); cairo_fill(ct); pb->empty = FALSE; } diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 6aa259ba6..259c6fb45 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -728,7 +728,7 @@ nr_arena_shape_add_bboxes(NRArenaShape* shape, NRRect &bbox) // cairo outline rendering: static unsigned int -cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, NR::Point shift) +cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, NR::Rect area) { NRArenaShape *shape = NR_ARENA_SHAPE(item); @@ -744,7 +744,7 @@ cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, NR::Point shift cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode cairo_new_path(ct); - feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), shift); + feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), area, true, 0); cairo_stroke(ct); @@ -827,7 +827,7 @@ cairo_arena_shape_render_stroke(NRArenaItem *item, NRRectL *area, NRPixBlock *pb cairo_set_tolerance(ct, 0.1); cairo_new_path(ct); - feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0)); + feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Rect(area), true, style_width); cairo_stroke(ct); @@ -856,7 +856,7 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock if (outline) { // cairo outline rendering pb->empty = FALSE; - unsigned int ret = cairo_arena_shape_render_outline (ct, item, NR::Point(pb->area.x0, pb->area.y0)); + unsigned int ret = cairo_arena_shape_render_outline (ct, item, NR::Rect(&pb->area)); if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret; } else { @@ -1004,7 +1004,7 @@ cairo_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb) cairo_new_path(ct); - feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0)); + feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Rect(area), false, 0); cairo_fill(ct); @@ -1091,10 +1091,11 @@ nr_arena_shape_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int / bp.path = SP_CURVE_BPATH(shape->curve); double dist = NR_HUGE; int wind = 0; - nr_path_matrix_point_bbox_wind_distance(&bp, shape->ctm, p, NULL, &wind, &dist, NR_EPSILON); + bool needfill = (shape->_fill.paint.type() != NRArenaShape::Paint::NONE && !outline); + nr_path_matrix_point_bbox_wind_distance(&bp, shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5); // pick fill - if (shape->_fill.paint.type() != NRArenaShape::Paint::NONE && !outline) { + if (needfill) { if (!shape->style->fill_rule.computed) { if (wind != 0) return item; } else { -- 2.30.2