summaryrefslogtreecommitdiffstats
path: root/src/display/nr-arena-item.cpp
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-07-07 18:08:47 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-07-07 18:08:47 +0000
commitb80e2b5bb72ebb814745bd58ccf10bfa617dd7e9 (patch)
tree23b5587685ddf4f15b9a1d3a65a066e49a779455 /src/display/nr-arena-item.cpp
parentSwitch to nearest neighbor filtering when image is larger than original (diff)
downloadinkscape-b80e2b5bb72ebb814745bd58ccf10bfa617dd7e9.tar.gz
inkscape-b80e2b5bb72ebb814745bd58ccf10bfa617dd7e9.zip
Fix group opacity
(bzr r9508.1.13)
Diffstat (limited to 'src/display/nr-arena-item.cpp')
-rw-r--r--src/display/nr-arena-item.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 338940fb6..f5731c0e3 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -571,10 +571,14 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
bool needs_intermediate_rendering = false;
bool &nir = needs_intermediate_rendering;
+ bool needs_opacity = (item->opacity != 255);
// this item needs an intermediate rendering if:
nir |= (item->mask != NULL); // 1. it has a mask
nir |= (item->filter != NULL && filter); // 2. it has a filter
+ nir |= needs_opacity; // 3. it is non-opaque
+
+ double opacity = static_cast<double>(item->opacity) / 255.0;
if (needs_intermediate_rendering) {
cairo_surface_t *intermediate = cairo_surface_create_similar(
@@ -590,6 +594,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
CairoSave clipsave(this_ct); // RAII for save / restore
CairoGroup maskgroup(this_ct); // RAII for push_group / pop_group
CairoGroup drawgroup(this_ct);
+ CairoGroup maskopacitygroup(this_ct);
if (item->clip && !(item->filter && filter)) {
clipsave.save();
@@ -603,12 +608,20 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
if (item->mask) {
maskgroup.push_with_content(CAIRO_CONTENT_ALPHA);
-
+ // handle opacity of a masked object by composing it with the mask
+ // this uses 1/4 the memory of composing it with full rendering
+ if (needs_opacity) {
+ maskopacitygroup.push();
+ }
state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (this_ct, item->mask, this_area, pb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
+ if (needs_opacity) {
+ maskopacitygroup.pop_to_source();
+ cct.paint_with_alpha(opacity);
+ }
mask = maskgroup.popmm();
}
@@ -632,8 +645,14 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
cairo_matrix_translate(&m, area->x0 - carea.x0, area->y0 - carea.y0);
cairo_pattern_set_matrix(cmask, &m);
cairo_mask(ct, cmask);
+ // opacity of masked objects is handled by premultiplying the mask
} else {
- cairo_paint(ct);
+ // opacity of non-masked objects must be rendered explicitly
+ if (needs_opacity) {
+ cairo_paint_with_alpha(ct, opacity);
+ } else {
+ cairo_paint(ct);
+ }
}
cairo_set_source_rgba(ct,0,0,0,0);
cairo_destroy(this_ct);