Code

separate bbox (calculated by subclasses) and drawbox, which includes filters margin...
authorbuliabyak <buliabyak@users.sourceforge.net>
Mon, 9 Mar 2009 01:13:55 +0000 (01:13 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Mon, 9 Mar 2009 01:13:55 +0000 (01:13 +0000)
src/display/nr-arena-glyphs.cpp
src/display/nr-arena-group.cpp
src/display/nr-arena-image.cpp
src/display/nr-arena-item.cpp
src/display/nr-arena-item.h
src/display/nr-arena-shape.cpp

index 802fe448c75a952bdc844360436cff7f96d01888..429f1ed32c186c7f61481eccf68a731ab6ff2b91 100644 (file)
@@ -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;
 }
index d73a0ecbf69aa9202a46ee1fbd59b85d13bdf5b4..38d37c233421cfede8c4bea486028a6ad77a620e 100644 (file)
@@ -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);
         }
     }
 
index da2f5ce7eb4564e24095249ede96473a64880ba0..07533aadcc17a02f60466736080c0011ec07f83c 100644 (file)
@@ -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;
 }
 
index 04b814cfbff52ae2b835075796f68fb8b52c3f84..bdab5b479507d8dc9305063a87ab6305d00a039e 100644 (file)
@@ -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 */
index 17a223b31afe796d17fc0ede73b3969963f1991d..2faa7d2d05557de7ccb2413a0b30388b235a86c5 100644 (file)
@@ -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;
index aafdc37d69a34cd879b813dcd02cadee06f0da4a..96ea76cbef83f14dc6d97c96d437e43dacab1fac 100644 (file)
@@ -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 ) {