index b7ff825d28a98f61778a8eda13b63c3697ff8090..9b3a6214cf1877ae7e092d211e459b3ffc392bcd 100644 (file)
#define noNR_ARENA_ITEM_VERBOSE
#define noNR_ARENA_ITEM_DEBUG_CASCADE
+#include <cstring>
+#include <string>
#include <libnr/nr-blit.h>
#include <libnr/nr-pixops.h>
#include "nr-arena.h"
#include "nr-arena-item.h"
#include "gc-core.h"
+#include "helper/geom.h"
#include "nr-filter.h"
-#include "libnr/nr-rect.h"
#include "nr-arena-group.h"
-#include "prefs-utils.h"
+#include "preferences.h"
namespace GC = Inkscape::GC;
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;
unsigned int state, unsigned int reset)
{
NRGC childgc (gc);
+ bool filter = (item->arena->rendermode == Inkscape::RENDERMODE_NORMAL);
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
return item->state;
/* Test whether to return immediately */
if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
- if (!nr_rect_l_test_intersect (area, &item->bbox))
+ if (!nr_rect_l_test_intersect_ptr(area, &item->drawbox))
return item->state;
}
/* Set up local gc */
childgc = *gc;
if (item->transform) {
- nr_matrix_multiply (&childgc.transform, item->transform,
- &childgc.transform);
+ childgc.transform = (*item->transform) * childgc.transform;
}
/* Remember the transformation matrix */
item->ctm = childgc.transform;
/* Invoke the real method */
- item->state =
- NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state,
- reset);
+ // 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 */
- if (item->filter) {
- item->filter->bbox_enlarge (item->bbox);
+
+ // 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->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)
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) {
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;
nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area,
NRPixBlock *pb, unsigned int flags)
{
- bool outline = (item->arena->rendermode == RENDERMODE_OUTLINE);
+ bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
+ bool filter = (item->arena->rendermode != Inkscape::RENDERMODE_OUTLINE &&
+ item->arena->rendermode != Inkscape::RENDERMODE_NO_FILTERS);
+ bool print_colors = (item->arena->rendermode == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW);
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
@@ -306,21 +323,24 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
item->state);
#ifdef NR_ARENA_ITEM_VERBOSE
- printf ("Invoke render %p: %d %d - %d %d\n", item, area->x0, area->y0,
- area->x1, area->y1);
+ g_message ("Invoke render %p on %p: %d %d - %d %d, %d %d - %d %d", item, pb,
+ area->x0, area->y0,
+ area->x1, area->y1,
+ item->drawbox.x0, item->drawbox.y0,
+ item->drawbox.x1, item->drawbox.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);
- if (nr_rect_l_test_empty (&carea))
+ 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 && !outline) {
- item->filter->area_enlarge (carea, item->ctm);
- nr_rect_l_intersect (&carea, &carea, &item->bbox);
+ if (item->filter && filter) {
+ item->filter->area_enlarge (carea, item);
+ nr_rect_l_intersect (&carea, &carea, &item->drawbox);
}
if (outline) {
@@ -337,13 +357,14 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
// render clip and mask, if any
guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
// render clippath as an object, using a different color
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (item->clip) {
- item->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "clips", 0x00ff00ff); // green clips
+ item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, &carea, pb, flags);
}
// render mask as an object, using a different color
if (item->mask) {
- item->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "masks", 0x0000ffff); // blue masks
+ item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags);
}
item->arena->outlinecolor = saved_rgba; // restore outline color
@@ -358,10 +379,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);
@@ -373,15 +394,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)];
@@ -392,13 +413,12 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
dpb = &cpb;
// Set nocache flag for downstream rendering
flags |= NR_ARENA_ITEM_RENDER_NO_CACHE;
- }
+ }
/* Determine, whether we need temporary buffer */
if (item->clip || item->mask
|| ((item->opacity != 255) && !item->render_opacity)
- || (item->filter) || item->background_new
- || (item->parent && item->parent->background_pb)) {
+ || (item->filter && filter) || item->background_new) {
/* Setup and render item buffer */
NRPixBlock ipb;
@@ -414,11 +434,15 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
/* If background access is used, save the pixblock address.
* This address is set to NULL at the end of this block */
- if (item->background_new
- || (item->parent && item->parent->background_pb)) {
+ if (item->background_new) {
item->background_pb = &ipb;
}
+
ipb.visible_area = pb->visible_area;
+ if (item->filter && filter) {
+ item->filter->area_enlarge (ipb.visible_area, item);
+ }
+
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, &ipb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
@@ -431,7 +455,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
ipb.empty = FALSE;
/* Run filtering, if a filter is set for this object */
- if (item->filter) {
+ if (item->filter && filter) {
item->filter->render (item, &ipb);
}
@@ -539,9 +563,6 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
}
nr_pixblock_release (&mpb);
- /* This pointer wouldn't be valid outside this block, so clear it */
- item->background_pb = NULL;
-
} else {
if (item->render_opacity) { // opacity was already rendered in, just copy to dpb here
nr_blit_pixblock_pixblock(dpb, &ipb);
@@ -551,6 +572,8 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
}
nr_pixblock_release (&ipb);
dpb->empty = FALSE;
+ /* This pointer wouldn't be valid outside this block, so clear it */
+ item->background_pb = NULL;
} else {
/* Just render */
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, dpb, flags);
(&item->bbox)->y0, (&item->bbox)->x1, (&item->bbox)->y1);
#endif
- if (item->visible && nr_rect_l_test_intersect (area, &item->bbox)) {
+ if (item->visible && nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
/* Need render that item */
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip) {
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
}
NRArenaItem *
-nr_arena_item_invoke_pick (NRArenaItem *item, NR::Point p, double delta,
+nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta,
unsigned int sticky)
{
nr_return_val_if_fail (item != NULL, NULL);
if (!sticky && !(item->visible && item->sensitive))
return NULL;
- // TODO: rewrite using NR::Rect
- const double x = p[NR::X];
- const double y = p[NR::Y];
+ // TODO: rewrite using Geom::Rect
+ const double x = p[Geom::X];
+ const double y = p[Geom::Y];
if (((x + delta) >= item->bbox.x0) &&
((x - delta) < item->bbox.x1) &&
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 */
}
void
-nr_arena_item_set_transform (NRArenaItem *item, NR::Matrix const &transform)
+nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const &transform)
{
- NRMatrix const t (transform);
+ Geom::Matrix const t (transform);
nr_arena_item_set_transform (item, &t);
}
void
-nr_arena_item_set_transform (NRArenaItem *item, NRMatrix const *transform)
+nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform)
{
nr_return_if_fail (item != NULL);
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
if (!transform && !item->transform)
return;
- const NRMatrix *md = (item->transform) ? item->transform : &NR_MATRIX_IDENTITY;
- const NRMatrix *ms = (transform) ? transform : &NR_MATRIX_IDENTITY;
+ const Geom::Matrix *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY;
+ const Geom::Matrix *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY;
- if (!NR_MATRIX_DF_TEST_CLOSE (md, ms, NR_EPSILON)) {
+ if (!Geom::matrix_equalp(*md, *ms, NR_EPSILON)) {
nr_arena_item_request_render (item);
- if (!transform || nr_matrix_test_identity (transform, NR_EPSILON)) {
+ if (!transform || transform->isIdentity()) {
/* Set to identity affine */
item->transform = NULL;
} else {
if (!item->transform)
- item->transform = new (GC::ATOMIC) NRMatrix ();
+ item->transform = new (GC::ATOMIC) Geom::Matrix ();
*item->transform = *transform;
}
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
nr_arena_item_set_child_position (item->parent, item, ref);
}
+void
+nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox)
+{
+ nr_return_if_fail(item != NULL);
+ nr_return_if_fail(NR_IS_ARENA_ITEM(item));
+
+ item->item_bbox = bbox;
+}
+
/** Returns a background image for use with filter effects. */
NRPixBlock *
-nr_arena_item_get_background (NRArenaItem const *item, int depth)
+nr_arena_item_get_background (NRArenaItem const *item)
{
- NRPixBlock *pb;
- if (!item->background_pb)
- return NULL;
if (item->background_new) {
- pb = new NRPixBlock ();
- nr_pixblock_setup_fast (pb, item->background_pb->mode,
- item->background_pb->area.x0,
- item->background_pb->area.y0,
- item->background_pb->area.x1,
- item->background_pb->area.y1, true);
- if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) // allocation failed
- return NULL;
+ return item->background_pb;
} else if (item->parent) {
- pb = nr_arena_item_get_background (item->parent, depth + 1);
- } else
+ return nr_arena_item_get_background (item->parent);
+ } else {
return NULL;
-
- if (depth > 0)
- nr_blit_pixblock_pixblock (pb, item->background_pb);
-
- return pb;
+ }
}
/* Helpers */
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :