summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbulia byak <buliabyak@gmail.com>2009-03-09 01:13:55 +0000
committerbuliabyak <buliabyak@users.sourceforge.net>2009-03-09 01:13:55 +0000
commit121ae8a9b836417ac548b84dbf0af7a77a3ae9f8 (patch)
tree9b0e093824f7aa8dfa4816bf7512f01168e79b06 /src
parentonly request redraw of those parts of the rect sides that actually moved (diff)
downloadinkscape-121ae8a9b836417ac548b84dbf0af7a77a3ae9f8.tar.gz
inkscape-121ae8a9b836417ac548b84dbf0af7a77a3ae9f8.zip
separate bbox (calculated by subclasses) and drawbox, which includes filters margin and clip/mask cropping; this fixes runaway enlargement when dragging a blurred group. also, move request to dirty canvas rectangle from subclasses to NRArenaItem, which uses drawbox for this, fixing numerous rendering glitches with filters
(bzr r7451)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-arena-glyphs.cpp1
-rw-r--r--src/display/nr-arena-group.cpp2
-rw-r--r--src/display/nr-arena-image.cpp5
-rw-r--r--src/display/nr-arena-item.cpp56
-rw-r--r--src/display/nr-arena-item.h2
-rw-r--r--src/display/nr-arena-shape.cpp1
6 files changed, 38 insertions, 29 deletions
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
index 802fe448c..429f1ed32 100644
--- a/src/display/nr-arena-glyphs.cpp
+++ b/src/display/nr-arena-glyphs.cpp
@@ -215,7 +215,6 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s
item->bbox.y0 = (gint32)(bbox.y0 - 1.0);
item->bbox.x1 = (gint32)(bbox.x1 + 1.0);
item->bbox.y1 = (gint32)(bbox.y1 + 1.0);
- nr_arena_request_render_rect(item->arena, &item->bbox);
return NR_ARENA_ITEM_STATE_ALL;
}
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index d73a0ecbf..38d37c233 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -181,7 +181,7 @@ nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int
nr_rect_l_set_empty (&item->bbox);
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
if (child->visible)
- nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
+ nr_rect_l_union (&item->bbox, &item->bbox, &child->drawbox);
}
}
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index da2f5ce7e..07533aadc 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -111,9 +111,6 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned
NRArenaImage *image = NR_ARENA_IMAGE (item);
- /* Request render old */
- nr_arena_item_request_render (item);
-
/* Copy affine */
grid2px = gc->transform.inverse();
double hscale, vscale; // todo: replace with Geom::Scale
@@ -162,8 +159,6 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned
item->bbox.y1 = item->bbox.y0 - 1;
}
- nr_arena_item_request_render (item);
-
return NR_ARENA_ITEM_STATE_ALL;
}
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 04b814cfb..bdab5b479 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -81,6 +81,7 @@ nr_arena_item_init (NRArenaItem *item)
item->visible = TRUE;
memset (&item->bbox, 0, sizeof (item->bbox));
+ memset (&item->drawbox, 0, sizeof (item->drawbox));
item->transform = NULL;
item->opacity = 255;
item->render_opacity = FALSE;
@@ -234,7 +235,7 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
return item->state;
/* Test whether to return immediately */
if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
- if (!nr_rect_l_test_intersect_ptr(area, &item->bbox))
+ if (!nr_rect_l_test_intersect_ptr(area, &item->drawbox))
return item->state;
}
@@ -252,12 +253,17 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
item->ctm = childgc.transform;
/* Invoke the real method */
+ // that will update bbox
item->state = NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state, reset);
if (item->state & NR_ARENA_ITEM_STATE_INVALID)
return item->state;
- /* Enlarge the bounding box to contain filter effects */
+
+ // get a copy of bbox
+ memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
+
+ /* Enlarge the drawbox to contain filter effects */
if (item->filter && filter) {
- item->filter->bbox_enlarge (item->bbox);
+ item->filter->bbox_enlarge (item->drawbox);
}
// fixme: to fix the display glitches, in outline mode bbox must be a combination of
// full item bbox and its clip and mask (after we have the API to get these)
@@ -272,7 +278,8 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- nr_rect_l_intersect (&item->bbox, &item->bbox, &item->clip->bbox);
+ // for clipping, we need geometric bbox
+ nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->clip->bbox);
}
/* Masking */
if (item->mask) {
@@ -281,7 +288,14 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- nr_rect_l_intersect (&item->bbox, &item->bbox, &item->mask->bbox);
+ // for masking, we need full drawbox of mask
+ nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->mask->drawbox);
+ }
+
+ // now that we know drawbox, dirty the corresponding rect on canvas:
+ if (!NR_IS_ARENA_GROUP(item) || (item->filter && filter)) {
+ // unless filtered, groups do not need to render by themselves, only their members
+ nr_arena_item_request_render (item);
}
return item->state;
@@ -311,17 +325,17 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
area->x1, area->y1);
#endif
- /* If we are outside bbox just return successfully */
+ /* If we are invisible, just return successfully */
if (!item->visible)
return item->state | NR_ARENA_ITEM_STATE_RENDER;
NRRectL carea;
- nr_rect_l_intersect (&carea, area, &item->bbox);
+ nr_rect_l_intersect (&carea, area, &item->drawbox);
if (nr_rect_l_test_empty(carea))
return item->state | NR_ARENA_ITEM_STATE_RENDER;
if (item->filter && filter) {
item->filter->area_enlarge (carea, item);
- nr_rect_l_intersect (&carea, &carea, &item->bbox);
+ nr_rect_l_intersect (&carea, &carea, &item->drawbox);
}
if (outline) {
@@ -360,10 +374,10 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
/* fixme: This probably cannot overflow, because we render only if visible */
/* fixme: and pixel cache is there only for small items */
/* fixme: But this still needs extra check (Lauris) */
- item->bbox.x0, item->bbox.y0,
- item->bbox.x1, item->bbox.y1,
+ item->drawbox.x0, item->drawbox.y0,
+ item->drawbox.x1, item->drawbox.y1,
item->px,
- 4 * (item->bbox.x1 - item->bbox.x0), FALSE,
+ 4 * (item->drawbox.x1 - item->drawbox.x0), FALSE,
FALSE);
nr_blit_pixblock_pixblock (pb, &cpb);
nr_pixblock_release (&cpb);
@@ -375,15 +389,15 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
/* Setup cache if we can */
if ((!(flags & NR_ARENA_ITEM_RENDER_NO_CACHE)) &&
- (carea.x0 <= item->bbox.x0) && (carea.y0 <= item->bbox.y0) &&
- (carea.x1 >= item->bbox.x1) && (carea.y1 >= item->bbox.y1) &&
- (((item->bbox.x1 - item->bbox.x0) * (item->bbox.y1 -
- item->bbox.y0)) <= 4096)) {
- // Item bbox is fully in renderable area and size is acceptable
- carea.x0 = item->bbox.x0;
- carea.y0 = item->bbox.y0;
- carea.x1 = item->bbox.x1;
- carea.y1 = item->bbox.y1;
+ (carea.x0 <= item->drawbox.x0) && (carea.y0 <= item->drawbox.y0) &&
+ (carea.x1 >= item->drawbox.x1) && (carea.y1 >= item->drawbox.y1) &&
+ (((item->drawbox.x1 - item->drawbox.x0) * (item->drawbox.y1 -
+ item->drawbox.y0)) <= 4096)) {
+ // Item drawbox is fully in renderable area and size is acceptable
+ carea.x0 = item->drawbox.x0;
+ carea.y0 = item->drawbox.y0;
+ carea.x1 = item->drawbox.x1;
+ carea.y1 = item->drawbox.y1;
item->px =
new (GC::ATOMIC) unsigned char[4 * (carea.x1 - carea.x0) *
(carea.y1 - carea.y0)];
@@ -672,7 +686,7 @@ nr_arena_item_request_render (NRArenaItem *item)
nr_return_if_fail (item != NULL);
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_arena_request_render_rect (item->arena, &item->bbox);
+ nr_arena_request_render_rect (item->arena, &item->drawbox);
}
/* Public */
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index 17a223b31..2faa7d2d0 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -89,6 +89,8 @@ struct NRArenaItem : public NRObject {
/* BBox in grid coordinates */
NRRectL bbox;
+ /* Redraw area in grid coordinates = bbox filter-enlarged and clipped/masked */
+ NRRectL drawbox;
/* BBox in item coordinates - this should be a bounding box as
* specified in SVG standard. Required by filters. */
Geom::OptRect item_bbox;
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index aafdc37d6..96ea76cbe 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -365,7 +365,6 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
item->bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F);
item->bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.0F);
item->bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.0F);
- nr_arena_request_render_rect(item->arena, &item->bbox);
item->render_opacity = TRUE;
if ( shape->_fill.paint.type() == NRArenaShape::Paint::SERVER ) {