summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorbulia byak <buliabyak@gmail.com>2007-03-18 21:07:21 +0000
committerbuliabyak <buliabyak@users.sourceforge.net>2007-03-18 21:07:21 +0000
commit91ced2280b8586bc345820dd464dfdaa2d60ee6a (patch)
treed69397c6cb60aadf9a2a0497c2912a51d9c7e501 /src/display
parentadd growBy and constructors from NRRect(L) (diff)
downloadinkscape-91ced2280b8586bc345820dd464dfdaa2d60ee6a.tar.gz
inkscape-91ced2280b8586bc345820dd464dfdaa2d60ee6a.zip
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
(bzr r2700)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/inkscape-cairo.cpp51
-rw-r--r--src/display/inkscape-cairo.h2
-rw-r--r--src/display/nr-arena-glyphs.cpp2
-rw-r--r--src/display/nr-arena-shape.cpp15
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 {