X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdisplay%2Fnr-arena-item.cpp;h=195dba2f073c530a70c66f3220a291f48112ada1;hb=61a8e3bd39889c3795adbfdf368c7a40e46292a5;hp=0657144eddbacdc17ceb4274e9d8c6d56c580eaa;hpb=a1dd38d30990bd7b1ceb96b95454d86f5ba27d60;p=inkscape.git diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index 0657144ed..195dba2f0 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -15,9 +15,13 @@ #define noNR_ARENA_ITEM_VERBOSE #define noNR_ARENA_ITEM_DEBUG_CASCADE +#include +#include #include #include +#include +#include #include "nr-arena.h" #include "nr-arena-item.h" #include "gc-core.h" @@ -203,6 +207,7 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, 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), @@ -243,8 +248,7 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, /* 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; @@ -256,13 +260,18 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, if (item->state & NR_ARENA_ITEM_STATE_INVALID) return item->state; /* Enlarge the bounding box to contain filter effects */ - if (item->filter) { + if (item->filter && filter) { item->filter->bbox_enlarge (item->bbox); } + // 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) /* Clipping */ if (item->clip) { - unsigned int newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset); + // FIXME: since here we only need bbox, consider passing + // ((state & !(NR_ARENA_ITEM_STATE_RENDER)) | NR_ARENA_ITEM_STATE_BBOX) + // instead of state, so it does not have to create rendering structures in nr_arena_shape_update + unsigned int newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset); if (newstate & NR_ARENA_ITEM_STATE_INVALID) { item->state |= NR_ARENA_ITEM_STATE_INVALID; return item->state; @@ -289,10 +298,11 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, */ unsigned int -nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, +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_NORMAL); nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID); nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), @@ -313,11 +323,39 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, nr_rect_l_intersect (&carea, area, &item->bbox); if (nr_rect_l_test_empty (&carea)) return item->state | NR_ARENA_ITEM_STATE_RENDER; - if (item->filter && !outline) { - nr_rect_l_enlarge (&carea, item->filter->get_enlarge (item->ctm)); + if (item->filter && filter) { + item->filter->area_enlarge (carea, item->ctm); nr_rect_l_intersect (&carea, &carea, &item->bbox); } + if (outline) { + // No caching in outline mode for now; investigate if it really gives any advantage with cairo. + // Also no attempts to clip anything; just render everything: item, clip, mask + // First, render the object itself + unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags); + if (state & NR_ARENA_ITEM_STATE_INVALID) { + /* Clean up and return error */ + item->state |= NR_ARENA_ITEM_STATE_INVALID; + return item->state; + } + + // 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 + if (item->clip) { + item->arena->outlinecolor = prefs_get_int_attribute("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 + NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags); + } + item->arena->outlinecolor = saved_rgba; // restore outline color + + return item->state | NR_ARENA_ITEM_STATE_RENDER; + } + NRPixBlock cpb; if (item->px) { /* Has cache pixblock, render this and return */ @@ -359,12 +397,12 @@ nr_arena_item_invoke_render (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 && !outline) - || (item->filter && !outline) || item->background_new + || ((item->opacity != 255) && !item->render_opacity) + || (item->filter && filter) || item->background_new || (item->parent && item->parent->background_pb)) { /* Setup and render item buffer */ @@ -374,19 +412,24 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, TRUE); // if memory allocation failed, abort render - if (ipb.data.px == NULL) { + if (ipb.size != NR_PIXBLOCK_SIZE_TINY && ipb.data.px == NULL) { nr_pixblock_release (&ipb); return (item->state); } /* 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->parent && item->parent->background_pb)) { item->background_pb = &ipb; } + ipb.visible_area = pb->visible_area; - unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags); + if (item->filter && filter) { + item->filter->area_enlarge (ipb.visible_area, item->ctm); + } + + 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 */ nr_pixblock_release (&ipb); @@ -398,11 +441,11 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, ipb.empty = FALSE; /* Run filtering, if a filter is set for this object */ - if (item->filter && !outline) { + if (item->filter && filter) { item->filter->render (item, &ipb); } - if ((item->clip || item->mask) && !outline) { + if (item->clip || item->mask) { /* Setup mask pixblock */ NRPixBlock mpb; nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, @@ -436,7 +479,7 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, if (tpb.data.px != NULL) { // if memory allocation was successful tpb.visible_area = pb->visible_area; - unsigned int state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, &tpb, flags); + unsigned int state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, &tpb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ nr_pixblock_release (&tpb); @@ -489,7 +532,7 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, } /* Multiply with opacity if needed */ if ((item->opacity != 255) && !item->render_opacity - && !outline) { + ) { int x, y; unsigned int a; a = item->opacity; @@ -506,35 +549,6 @@ nr_arena_item_invoke_render (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->clip || item->mask) && outline) { - // Render clipped or masked object in outline mode: - - // First, render the object itself - unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, dpb, flags); - if (state & NR_ARENA_ITEM_STATE_INVALID) { - /* Clean up and return error */ - if (dpb != pb) - nr_pixblock_release (dpb); - item->state |= NR_ARENA_ITEM_STATE_INVALID; - return item->state; - } - - guint32 saved_rgba = item->arena->outlinecolor; // save current outline color - // render clippath as an object, using a different color - if (item->clip) { - item->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "clips", 0x00ff00ff); // green clips - NR_ARENA_ITEM_VIRTUAL (item->clip, render) (item->clip, &carea, dpb, 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 - NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, dpb, flags); - } - item->arena->outlinecolor = saved_rgba; // restore outline color - } else { if (item->render_opacity) { // opacity was already rendered in, just copy to dpb here nr_blit_pixblock_pixblock(dpb, &ipb); @@ -544,9 +558,11 @@ nr_arena_item_invoke_render (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) (item, &carea, dpb, flags); + unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, dpb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ if (dpb != pb) @@ -697,12 +713,12 @@ nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child) void nr_arena_item_set_transform (NRArenaItem *item, NR::Matrix const &transform) { - NRMatrix const t (transform); + NR::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, NR::Matrix const *transform) { nr_return_if_fail (item != NULL); nr_return_if_fail (NR_IS_ARENA_ITEM (item)); @@ -710,17 +726,17 @@ nr_arena_item_set_transform (NRArenaItem *item, NRMatrix const *transform) if (!transform && !item->transform) return; - const NRMatrix *md = (item->transform) ? item->transform : &NR_MATRIX_IDENTITY; - const NRMatrix *ms = (transform) ? transform : &NR_MATRIX_IDENTITY; + const NR::Matrix *md = (item->transform) ? item->transform : &NR_MATRIX_IDENTITY; + const NR::Matrix *ms = (transform) ? transform : &NR_MATRIX_IDENTITY; - if (!NR_MATRIX_DF_TEST_CLOSE (md, ms, NR_EPSILON)) { + if (!NR::matrix_equalp(*md, *ms, NR_EPSILON)) { nr_arena_item_request_render (item); - if (!transform || nr_matrix_test_identity (transform, NR_EPSILON)) { + if (!transform || transform->test_identity()) { /* Set to identity affine */ item->transform = NULL; } else { if (!item->transform) - item->transform = new (GC::ATOMIC) NRMatrix (); + item->transform = new (GC::ATOMIC) NR::Matrix (); *item->transform = *transform; } nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE); @@ -819,6 +835,15 @@ nr_arena_item_set_order (NRArenaItem *item, int order) nr_arena_item_set_child_position (item->parent, item, ref); } +void +nr_arena_item_set_item_bbox (NRArenaItem *item, NR::Maybe &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) @@ -833,7 +858,7 @@ nr_arena_item_get_background (NRArenaItem const *item, int depth) item->background_pb->area.y0, item->background_pb->area.x1, item->background_pb->area.y1, true); - if (pb->data.px == NULL) // allocation failed + if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) // allocation failed return NULL; } else if (item->parent) { pb = nr_arena_item_get_background (item->parent, depth + 1);