diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-08-05 01:18:22 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-08-05 01:18:22 +0000 |
| commit | 1b0dd0634095b71205407ec9e85ab39d7607cca5 (patch) | |
| tree | b2b0323a776b8696519a06c76e54b8fee7702f07 /src | |
| parent | Wholesale cruft removal part 4; fix crash when rendering guides (diff) | |
| download | inkscape-1b0dd0634095b71205407ec9e85ab39d7607cca5.tar.gz inkscape-1b0dd0634095b71205407ec9e85ab39d7607cca5.zip | |
Fix mask rendering to use luminance-to-alpha
(bzr r9508.1.49)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/cairo-templates.h | 41 | ||||
| -rw-r--r-- | src/display/nr-arena-item.cpp | 12 | ||||
| -rw-r--r-- | src/display/nr-filter-colormatrix.cpp | 15 |
3 files changed, 48 insertions, 20 deletions
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h index 78fdff664..3c8a6fea3 100644 --- a/src/display/cairo-templates.h +++ b/src/display/cairo-templates.h @@ -24,6 +24,7 @@ static const int OPENMP_THRESHOLD = 2048; #include <glib.h> #include <math.h> #include "display/nr-3dutils.h" +#include "display/cairo-utils.h" /** * @brief Blend two surfaces using the supplied functor. @@ -200,6 +201,30 @@ void ink_cairo_surface_filter(cairo_surface_t *in, cairo_surface_t *out, Filter int num_threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256); #endif + // this is provided just in case, to avoid problems with strict aliasing rules + if (in == out) { + if (bppin == 4) { + #if HAVE_OPENMP + #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads) + #endif + for (int i = 0; i < limit; ++i) { + *(in_data + i) = filter(*(in_data + i)); + } + } else { + #if HAVE_OPENMP + #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads) + #endif + for (int i = 0; i < limit; ++i) { + guint8 *in_p = reinterpret_cast<guint8*>(in_data) + i; + guint32 in_px = *in_p; in_px <<= 24; + guint32 out_px = filter(in_px); + *in_p = out_px >> 24; + } + } + cairo_surface_mark_dirty(out); + return; + } + if (bppin == 4) { if (bppout == 4) { // bppin == 4, bppout == 4 @@ -661,6 +686,22 @@ pxclamp(gint32 v, gint32 low, gint32 high) { #define ASSEMBLE_ARGB32(px,a,r,g,b) \ guint32 px = (a << 24) | (r << 16) | (g << 8) | b; +// this is also used for masks, so it resides in this header +struct ColorMatrixLuminanceToAlpha { + guint32 operator()(guint32 in) { + // original computation in double: r*0.2125 + g*0.7154 + b*0.0721 + EXTRACT_ARGB32(in, a, r, g, b) + // unpremultiply color values + if (a != 0) { + r = unpremul_alpha(r, a); + g = unpremul_alpha(g, a); + b = unpremul_alpha(b, a); + } + guint32 ao = r*54 + g*182 + b*18; + return ((ao + 127) / 255) << 24; + } +}; + #endif /* Local Variables: diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index 0bdbd12ae..9b76c4ff7 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -20,6 +20,7 @@ #include <cairomm/cairomm.h> #include "display/cairo-utils.h" +#include "display/cairo-templates.h" #include "nr-arena.h" #include "nr-arena-item.h" #include "gc-core.h" @@ -433,7 +434,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area // render mask on the intermediate context and store it if (item->mask) { - maskgroup.push_with_content(CAIRO_CONTENT_ALPHA); + maskgroup.push_with_content(CAIRO_CONTENT_COLOR_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) { @@ -449,12 +450,13 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area cct.paint_with_alpha(opacity); } mask = maskgroup.popmm(); + // convert luminance to alpha + cairo_pattern_t *p = mask->cobj(); + cairo_surface_t *s; + cairo_pattern_get_surface(p, &s); + ink_cairo_surface_filter(s, s, ColorMatrixLuminanceToAlpha()); } - /*if (mask) { - drawgroup.push(); - }*/ - // render the object (possibly to the intermediate surface) state = NR_ARENA_ITEM_VIRTUAL (item, render) (this_ct, item, this_area, pb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp index 7ab606182..d77898180 100644 --- a/src/display/nr-filter-colormatrix.cpp +++ b/src/display/nr-filter-colormatrix.cpp @@ -135,21 +135,6 @@ private: gint32 _v[9]; }; -struct ColorMatrixLuminanceToAlpha { - guint32 operator()(guint32 in) { - // original computation in double: r*0.2125 + g*0.7154 + b*0.0721 - EXTRACT_ARGB32(in, a, r, g, b) - // unpremultiply color values - if (a != 0) { - r = unpremul_alpha(r, a); - g = unpremul_alpha(g, a); - b = unpremul_alpha(b, a); - } - guint32 ao = r*54 + g*182 + b*18; - return ((ao + 127) / 255) << 24; - } -}; - void FilterColorMatrix::render_cairo(FilterSlot &slot) { cairo_surface_t *input = slot.getcairo(_input); |
