summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-08-05 01:18:22 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-08-05 01:18:22 +0000
commit1b0dd0634095b71205407ec9e85ab39d7607cca5 (patch)
treeb2b0323a776b8696519a06c76e54b8fee7702f07 /src
parentWholesale cruft removal part 4; fix crash when rendering guides (diff)
downloadinkscape-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.h41
-rw-r--r--src/display/nr-arena-item.cpp12
-rw-r--r--src/display/nr-filter-colormatrix.cpp15
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);