X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fdisplay%2Fnr-arena-item.cpp;h=ddde4102e60eea8f309dae65048e6d69c6127ed4;hb=9857ba6e1d24d9769ef3454fb6826934dc83349b;hp=d4e237104ea0c66acd5283cb9470556f3c8ff44b;hpb=2f95b6ec60b75dcab7588ac0cd73dea9d62cf74e;p=inkscape.git diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index d4e237104..ddde4102e 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -259,10 +259,15 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, if (item->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,7 +294,7 @@ 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); @@ -314,10 +319,38 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, 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)); + 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 */ @@ -363,8 +396,8 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL const *area, /* 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) || item->background_new || (item->parent && item->parent->background_pb)) { /* Setup and render item buffer */ @@ -374,19 +407,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) { + 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,7 +436,7 @@ 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) { item->filter->render (item, &ipb); } @@ -436,7 +474,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 +527,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,17 +544,20 @@ 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 { - /* Opacity only */ - nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity); + if (item->render_opacity) { // opacity was already rendered in, just copy to dpb here + nr_blit_pixblock_pixblock(dpb, &ipb); + } else { // copy while multiplying by opacity + nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity); + } } 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) @@ -789,6 +830,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) @@ -803,7 +853,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);