index d4e237104ea0c66acd5283cb9470556f3c8ff44b..ddde4102e60eea8f309dae65048e6d69c6127ed4 100644 (file)
if (item->filter) {
item->filter->bbox_enlarge (item->bbox);
}
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) {
/* 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;
if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
*/
unsigned int
*/
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);
NRPixBlock *pb, unsigned int flags)
{
bool outline = (item->arena->rendermode == RENDERMODE_OUTLINE);
if (nr_rect_l_test_empty (&carea))
return item->state | NR_ARENA_ITEM_STATE_RENDER;
if (item->filter && !outline) {
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);
}
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 */
NRPixBlock cpb;
if (item->px) {
/* Has cache pixblock, render this and return */
/* Determine, whether we need temporary buffer */
if (item->clip || item->mask
/* 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 */
|| (item->parent && item->parent->background_pb)) {
/* Setup and render item buffer */
TRUE);
// if memory allocation failed, abort render
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 */
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;
}
item->background_pb = &ipb;
}
+
ipb.visible_area = pb->visible_area;
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);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
nr_pixblock_release (&ipb);
ipb.empty = FALSE;
/* Run filtering, if a filter is set for this object */
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);
}
item->filter->render (item, &ipb);
}
if (tpb.data.px != NULL) { // if memory allocation was successful
tpb.visible_area = pb->visible_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);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
nr_pixblock_release (&tpb);
}
/* Multiply with opacity if needed */
if ((item->opacity != 255) && !item->render_opacity
}
/* Multiply with opacity if needed */
if ((item->opacity != 255) && !item->render_opacity
- && !outline) {
+ ) {
int x, y;
unsigned int a;
a = item->opacity;
int x, y;
unsigned int a;
a = item->opacity;
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
}
nr_pixblock_release (&mpb);
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 {
} 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;
}
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 */
} 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)
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
if (dpb != pb)
nr_arena_item_set_child_position (item->parent, item, ref);
}
nr_arena_item_set_child_position (item->parent, item, ref);
}
+void
+nr_arena_item_set_item_bbox (NRArenaItem *item, NR::Maybe<NR::Rect> &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)
/** Returns a background image for use with filter effects. */
NRPixBlock *
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);
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);
return NULL;
} else if (item->parent) {
pb = nr_arena_item_get_background (item->parent, depth + 1);