summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2012-12-24 07:07:34 +0000
committerJabiertxo Arraiza Cenoz <jtx@jtx.marker.es>2012-12-24 07:07:34 +0000
commit151539ee2fdfdc417a691ba1d51e129036687cff (patch)
tree6be4d0f9f0516f99083506feede6a0806c2b8537 /src/display
parentGoing to merge (diff)
parentextensions. function plotter. patch by ~suv for clip rectangle (Bug 492103) (diff)
downloadinkscape-151539ee2fdfdc417a691ba1d51e129036687cff.tar.gz
inkscape-151539ee2fdfdc417a691ba1d51e129036687cff.zip
Merge from branch
(bzr r11950.1.6)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/cairo-utils.cpp125
-rw-r--r--src/display/cairo-utils.h15
-rw-r--r--src/display/nr-filter-blend.cpp14
-rw-r--r--src/display/nr-filter-colormatrix.cpp12
-rw-r--r--src/display/nr-filter-component-transfer.cpp11
-rw-r--r--src/display/nr-filter-composite.cpp11
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp13
-rw-r--r--src/display/nr-filter-diffuselighting.cpp7
-rw-r--r--src/display/nr-filter-displacement-map.cpp11
-rw-r--r--src/display/nr-filter-flood.cpp6
-rw-r--r--src/display/nr-filter-gaussian.cpp13
-rw-r--r--src/display/nr-filter-image.cpp6
-rw-r--r--src/display/nr-filter-merge.cpp8
-rw-r--r--src/display/nr-filter-morphology.cpp4
-rw-r--r--src/display/nr-filter-offset.cpp3
-rw-r--r--src/display/nr-filter-primitive.cpp14
-rw-r--r--src/display/nr-filter-primitive.h9
-rw-r--r--src/display/nr-filter-slot.cpp8
-rw-r--r--src/display/nr-filter-specularlighting.cpp7
-rw-r--r--src/display/nr-filter-turbulence.cpp5
-rw-r--r--src/display/nr-filter.cpp5
-rw-r--r--src/display/nr-svgfonts.cpp2
22 files changed, 303 insertions, 6 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 2e2eb42dd..692e31837 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -24,6 +24,7 @@
#include <2geom/transforms.h>
#include <2geom/sbasis-to-bezier.h>
#include "color.h"
+#include "style.h"
#include "helper/geom-curves.h"
namespace Inkscape {
@@ -276,6 +277,43 @@ feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv)
}
}
+SPColorInterpolation
+get_cairo_surface_ci(cairo_surface_t *surface) {
+ void* data = cairo_surface_get_user_data( surface, &ci_key );
+ if( data != NULL ) {
+ return (SPColorInterpolation)GPOINTER_TO_INT( data );
+ } else {
+ return SP_CSS_COLOR_INTERPOLATION_AUTO;
+ }
+}
+
+/** Set the color_interpolation_value for a Cairo surface.
+ * Transform the surface between sRGB and linearRGB if necessary. */
+void
+set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation ci) {
+
+ if( cairo_surface_get_content( surface ) != CAIRO_CONTENT_ALPHA ) {
+
+ SPColorInterpolation ci_in = get_cairo_surface_ci( surface );
+
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ ink_cairo_surface_srgb_to_linear( surface );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ ink_cairo_surface_linear_to_srgb( surface );
+ }
+
+ cairo_surface_set_user_data(surface, &ci_key, GINT_TO_POINTER (ci), NULL);
+ }
+}
+
+void
+copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out) {
+ cairo_surface_set_user_data(out, &ci_key, cairo_surface_get_user_data(in, &ci_key), NULL);
+}
+
void
ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba)
{
@@ -395,6 +433,7 @@ cairo_surface_t *
ink_cairo_surface_create_identical(cairo_surface_t *s)
{
cairo_surface_t *ns = ink_cairo_surface_create_same_size(s, cairo_surface_get_content(s));
+ cairo_surface_set_user_data(ns, &ci_key, cairo_surface_get_user_data(s, &ci_key), NULL);
return ns;
}
@@ -547,6 +586,92 @@ void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r,
a = CLAMP(a, 0.0, 1.0);
}
+void srgb_to_linear( guint32* c, guint32 a ) {
+
+ *c = unpremul_alpha( *c, a );
+
+ double cc = *c/255.0;
+
+ if( cc < 0.04045 ) {
+ cc /= 12.92;
+ } else {
+ cc = pow( (cc+0.055)/1.055, 2.4 );
+ }
+ cc *= 255.0;
+
+ *c = (int)cc;
+
+ *c = premul_alpha( *c, a );
+}
+
+void linear_to_srgb( guint32* c, guint32 a ) {
+
+ *c = unpremul_alpha( *c, a );
+
+ double cc = *c/255.0;
+
+ if( cc < 0.0031308 ) {
+ cc *= 12.92;
+ } else {
+ cc = pow( cc, 1.0/2.4 )*1.055-0.055;
+ }
+ cc *= 255.0;
+
+ *c = (int)cc;
+
+ *c = premul_alpha( *c, a );
+}
+
+int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface)
+{
+ cairo_surface_flush(surface);
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ int stride = cairo_image_surface_get_stride(surface);
+ unsigned char *data = cairo_image_surface_get_data(surface);
+
+ /* TODO convert this to OpenMP somehow */
+ for (int y = 0; y < height; ++y, data += stride) {
+ for (int x = 0; x < width; ++x) {
+ guint32 px = *reinterpret_cast<guint32*>(data + 4*x);
+ EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting
+ if( a != 0 ) {
+ srgb_to_linear( &r, a );
+ srgb_to_linear( &g, a );
+ srgb_to_linear( &b, a );
+ }
+ ASSEMBLE_ARGB32(px2, a,r,g,b);
+ *reinterpret_cast<guint32*>(data + 4*x) = px2;
+ }
+ }
+ return width * height;
+}
+
+int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface)
+{
+ cairo_surface_flush(surface);
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ int stride = cairo_image_surface_get_stride(surface);
+ unsigned char *data = cairo_image_surface_get_data(surface);
+
+ /* TODO convert this to OpenMP somehow */
+ for (int y = 0; y < height; ++y, data += stride) {
+ for (int x = 0; x < width; ++x) {
+ guint32 px = *reinterpret_cast<guint32*>(data + 4*x);
+ EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting
+ if( a != 0 ) {
+ linear_to_srgb( &r, a );
+ linear_to_srgb( &g, a );
+ linear_to_srgb( &b, a );
+ }
+ ASSEMBLE_ARGB32(px2, a,r,g,b);
+ *reinterpret_cast<guint32*>(data + 4*x) = px2;
+ }
+ }
+ return width * height;
+}
+
cairo_pattern_t *
ink_cairo_pattern_create_checkerboard()
{
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index e67872891..d240545eb 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -15,6 +15,7 @@
#include <glib.h>
#include <cairomm/cairomm.h>
#include <2geom/forward.h>
+#include "style.h"
struct SPColor;
struct _GdkPixbuf;
@@ -81,6 +82,17 @@ public:
} // namespace Inkscape
+/**
+ * Key for cairo_surface_t to keep track of current color interpolation value
+ * Only the address of the structure is used, it is never initialized. See:
+ * http://www.cairographics.org/manual/cairo-Types.html#cairo-user-data-key-t
+ */
+static cairo_user_data_key_t ci_key;
+SPColorInterpolation get_cairo_surface_ci(cairo_surface_t *surface);
+void set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation cif);
+void copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out);
+void convert_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation cif);
+
void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacity);
void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m);
@@ -102,6 +114,9 @@ guint32 ink_cairo_surface_average_color(cairo_surface_t *surface);
void ink_cairo_surface_average_color(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
+int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface);
+int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface);
+
cairo_pattern_t *ink_cairo_pattern_create_checkerboard();
void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs);
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
index 267883b4b..a08191f67 100644
--- a/src/display/nr-filter-blend.cpp
+++ b/src/display/nr-filter-blend.cpp
@@ -146,13 +146,23 @@ void FilterBlend::render_cairo(FilterSlot &slot)
cairo_surface_t *input1 = slot.getcairo(_input);
cairo_surface_t *input2 = slot.getcairo(_input2);
- cairo_content_t ct1 = cairo_surface_get_content(input1);
- cairo_content_t ct2 = cairo_surface_get_content(input2);
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci( input1, ci_fp );
+ set_cairo_surface_ci( input2, ci_fp );
// input2 is the "background" image
// out should be ARGB32 if any of the inputs is ARGB32
cairo_surface_t *out = ink_cairo_surface_create_output(input1, input2);
+ set_cairo_surface_ci( out, ci_fp );
+ cairo_content_t ct1 = cairo_surface_get_content(input1);
+ cairo_content_t ct2 = cairo_surface_get_content(input2);
if ((ct1 == CAIRO_CONTENT_ALPHA && ct2 == CAIRO_CONTENT_ALPHA)
|| _blend_mode == BLEND_NORMAL)
{
diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp
index fad6215ff..77873d523 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -152,10 +152,22 @@ void FilterColorMatrix::render_cairo(FilterSlot &slot)
{
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = NULL;
+
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci( input, ci_fp );
+
if (type == COLORMATRIX_LUMINANCETOALPHA) {
out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_ALPHA);
} else {
out = ink_cairo_surface_create_identical(input);
+ // Set ci to that used for computation
+ set_cairo_surface_ci(out, ci_fp);
}
switch (type) {
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 226a73cef..3bc00d2d7 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -238,6 +238,17 @@ void FilterComponentTransfer::render_cairo(FilterSlot &slot)
{
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ set_cairo_surface_ci(out, ci_fp );
+ }
+ set_cairo_surface_ci( input, ci_fp );
+
//cairo_surface_t *outtemp = ink_cairo_surface_create_identical(out);
ink_cairo_surface_blit(input, out);
diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp
index 040424cb3..f6decad0d 100644
--- a/src/display/nr-filter-composite.cpp
+++ b/src/display/nr-filter-composite.cpp
@@ -66,7 +66,18 @@ void FilterComposite::render_cairo(FilterSlot &slot)
cairo_surface_t *input1 = slot.getcairo(_input);
cairo_surface_t *input2 = slot.getcairo(_input2);
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci( input1, ci_fp );
+ set_cairo_surface_ci( input2, ci_fp );
+
cairo_surface_t *out = ink_cairo_surface_create_output(input1, input2);
+ set_cairo_surface_ci(out, ci_fp );
if (op == COMPOSITE_ARITHMETIC) {
ink_cairo_surface_blend(input1, input2, out, ComposeArithmetic(k1, k2, k3, k4));
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
index 5469aff88..2aad528a6 100644
--- a/src/display/nr-filter-convolve-matrix.cpp
+++ b/src/display/nr-filter-convolve-matrix.cpp
@@ -104,8 +104,6 @@ void FilterConvolveMatrix::render_cairo(FilterSlot &slot)
static bool bias_warning = false;
static bool edge_warning = false;
- cairo_surface_t *input = slot.getcairo(_input);
-
if (orderX<=0 || orderY<=0) {
g_warning("Empty kernel!");
return;
@@ -119,8 +117,19 @@ void FilterConvolveMatrix::render_cairo(FilterSlot &slot)
return;
}
+ cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ set_cairo_surface_ci(out, ci_fp);
+ }
+ set_cairo_surface_ci( input, ci_fp );
+
if (bias!=0 && !bias_warning) {
g_warning("It is unknown whether Inkscape's implementation of bias in feConvolveMatrix "
"is correct!");
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index fcc986189..faf56a4ca 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -126,6 +126,13 @@ void FilterDiffuseLighting::render_cairo(FilterSlot &slot)
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ // Only alpha channel of input is used, no need to check input color_interpolation_filter value.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci(out, ci_fp );
+
Geom::Rect slot_area = slot.get_slot_area();
Geom::Point p = slot_area.min();
Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index 9b44c2302..1b979fa6c 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -74,6 +74,17 @@ void FilterDisplacementMap::render_cairo(FilterSlot &slot)
cairo_surface_t *texture = slot.getcairo(_input);
cairo_surface_t *map = slot.getcairo(_input2);
cairo_surface_t *out = ink_cairo_surface_create_identical(texture);
+ // color_interpolation_filters for out same as texture. See spec.
+ copy_cairo_surface_ci( texture, out );
+
+ // We may need to transform map surface to correct color interpolation space. The map surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the map before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci( map, ci_fp );
Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
double scalex = scale * trans.expansionX();
diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp
index 56a27ecd7..7117e0343 100644
--- a/src/display/nr-filter-flood.cpp
+++ b/src/display/nr-filter-flood.cpp
@@ -45,6 +45,8 @@ void FilterFlood::render_cairo(FilterSlot &slot)
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ // DOES THIS REALLY BELONG HERE? SHOULDN'T ICC BE APPLIED AFTER ALL COMPOSITING?
+ // What if color_interpolation_filter is set to linear RGB?
if (icc) {
guchar ru, gu, bu;
icc_color_to_sRGB(icc, &ru, &gu, &bu);
@@ -55,6 +57,10 @@ void FilterFlood::render_cairo(FilterSlot &slot)
#endif
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ // color_interpolation_filter is determined by CSS value (see spec. Turbulence).
+ if( _style ) {
+ set_cairo_surface_ci(out, (SPColorInterpolation)_style->color_interpolation_filters.computed );
+ }
// Get filter primitive area in user units
Geom::Rect fp = filter_primitive_area( slot.get_units() );
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index 6ef321992..9d7c32585 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -553,6 +553,15 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
cairo_surface_t *in = slot.getcairo(_input);
if (!in) return;
+ // We may need to transform input surface to correct color interpolation space. The input surface
+ // might be used as input to another primitive but it is likely that all the primitives in a given
+ // filter use the same color interpolation space so we don't copy the input before converting.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci( in, ci_fp );
+
// zero deviation = no change in output
if (_deviation_x <= 0 && _deviation_y <= 0) {
cairo_surface_t *cp = ink_cairo_surface_copy(in);
@@ -660,10 +669,14 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
cairo_paint(ct);
cairo_destroy(ct);
+ set_cairo_surface_ci( upsampled, ci_fp );
+
slot.set(_output, upsampled);
cairo_surface_destroy(upsampled);
cairo_surface_destroy(downsampled);
} else {
+ set_cairo_surface_ci( downsampled, ci_fp );
+
slot.set(_output, downsampled);
cairo_surface_destroy(downsampled);
}
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index bc18cbcc6..fca8fdba3 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -120,6 +120,9 @@ void FilterImage::render_cairo(FilterSlot &slot)
drawing.render(ct, render_rect);
SVGElem->invoke_hide(key);
+ // For the moment, we'll assume that any image is in sRGB color space
+ set_cairo_surface_ci(out, SP_CSS_COLOR_INTERPOLATION_SRGB);
+
slot.set(_output, out);
cairo_surface_destroy(out);
return;
@@ -185,6 +188,9 @@ void FilterImage::render_cairo(FilterSlot &slot)
cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
sa.width(), sa.height());
+ // For the moment, we'll assume that any image is in sRGB color space
+ set_cairo_surface_ci(out, SP_CSS_COLOR_INTERPOLATION_SRGB);
+
cairo_t *ct = cairo_create(out);
cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]);
diff --git a/src/display/nr-filter-merge.cpp b/src/display/nr-filter-merge.cpp
index 759d7d6d1..2b9a24f25 100644
--- a/src/display/nr-filter-merge.cpp
+++ b/src/display/nr-filter-merge.cpp
@@ -33,6 +33,11 @@ void FilterMerge::render_cairo(FilterSlot &slot)
{
if (_input_image.empty()) return;
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+
// output is RGBA if at least one input is RGBA
bool rgba32 = false;
cairo_surface_t *out = NULL;
@@ -40,6 +45,7 @@ void FilterMerge::render_cairo(FilterSlot &slot)
cairo_surface_t *in = slot.getcairo(*i);
if (cairo_surface_get_content(in) == CAIRO_CONTENT_COLOR_ALPHA) {
out = ink_cairo_surface_create_identical(in);
+ set_cairo_surface_ci( out, ci_fp );
rgba32 = true;
break;
}
@@ -52,6 +58,8 @@ void FilterMerge::render_cairo(FilterSlot &slot)
for (std::vector<int>::iterator i = _input_image.begin(); i != _input_image.end(); ++i) {
cairo_surface_t *in = slot.getcairo(*i);
+
+ set_cairo_surface_ci( in, ci_fp );
cairo_set_source_surface(out_ct, in, 0, 0);
cairo_paint(out_ct);
}
diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp
index 18f99cdcd..b058307cf 100644
--- a/src/display/nr-filter-morphology.cpp
+++ b/src/display/nr-filter-morphology.cpp
@@ -164,6 +164,7 @@ void FilterMorphology::render_cairo(FilterSlot &slot)
if (xradius == 0.0 || yradius == 0.0) {
// output is transparent black
cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+ copy_cairo_surface_ci(input, out);
slot.set(_output, out);
cairo_surface_destroy(out);
return;
@@ -192,6 +193,9 @@ void FilterMorphology::render_cairo(FilterSlot &slot)
cairo_surface_t *out = ink_cairo_surface_create_identical(interm);
+ // color_interpolation_filters for out same as input. See spec (DisplacementMap).
+ copy_cairo_surface_ci(input, out);
+
if (Operator == MORPHOLOGY_OPERATOR_DILATE) {
if (bpp == 1) {
morphologicalFilter1D< std::greater<unsigned char>, Geom::Y, 1 >(interm, out, yr);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
index 833f6ecc9..01d6ffe56 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -35,6 +35,9 @@ void FilterOffset::render_cairo(FilterSlot &slot)
{
cairo_surface_t *in = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_identical(in);
+ // color_interpolation_filters for out same as in. See spec (DisplacementMap).
+ copy_cairo_surface_ci(in, out);
+
cairo_t *ct = cairo_create(out);
Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index ce562668a..fca82c810 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -20,6 +20,7 @@
#include "desktop-handles.h"
#include "document.h"
#include "sp-root.h"
+#include "style.h"
namespace Inkscape {
namespace Filters {
@@ -45,11 +46,14 @@ FilterPrimitive::FilterPrimitive()
_subregion_y.unset(SVGLength::PERCENT, 0, 0);
_subregion_width.unset(SVGLength::PERCENT, 1, 0);
_subregion_height.unset(SVGLength::PERCENT, 1, 0);
+
+ _style = NULL;
}
FilterPrimitive::~FilterPrimitive()
{
- // Nothing to do here
+ if(_style)
+ sp_style_unref(_style);
}
void FilterPrimitive::render_cairo(FilterSlot &slot)
@@ -179,6 +183,14 @@ Geom::Rect FilterPrimitive::filter_primitive_area(FilterUnits const &units)
return area;
}
+void FilterPrimitive::setStyle(SPStyle *style)
+{
+ if (style) sp_style_ref(style);
+ if (_style) sp_style_unref(_style);
+ _style = style;
+}
+
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h
index da2097156..214b2cfc5 100644
--- a/src/display/nr-filter-primitive.h
+++ b/src/display/nr-filter-primitive.h
@@ -16,6 +16,8 @@
#include "display/nr-filter-types.h"
#include "svg/svg-length.h"
+class SPStyle;
+
namespace Inkscape {
namespace Filters {
@@ -113,6 +115,11 @@ public:
*/
virtual bool can_handle_affine(Geom::Affine const &) { return false; }
+ /**
+ * Sets style for access to properties used by filter primitives.
+ */
+ void setStyle(SPStyle *style);
+
protected:
int _input;
int _output;
@@ -122,6 +129,8 @@ protected:
SVGLength _subregion_y;
SVGLength _subregion_width;
SVGLength _subregion_height;
+
+ SPStyle *_style;
};
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 4f7a8849e..fe67972d6 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -129,6 +129,9 @@ cairo_surface_t *FilterSlot::_get_transformed_source_graphic()
if (trans.isTranslation()) {
cairo_surface_reference(_source_graphic);
+
+ // Assume all source graphics are sRGB
+ set_cairo_surface_ci( _source_graphic, SP_CSS_COLOR_INTERPOLATION_SRGB );
return _source_graphic;
}
@@ -145,6 +148,8 @@ cairo_surface_t *FilterSlot::_get_transformed_source_graphic()
cairo_paint(tsg_ct);
cairo_destroy(tsg_ct);
+ // Assume all source graphics are sRGB
+ set_cairo_surface_ci( tsg, SP_CSS_COLOR_INTERPOLATION_SRGB );
return tsg;
}
@@ -172,6 +177,9 @@ cairo_surface_t *FilterSlot::_get_transformed_background()
tbg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, _slot_w, _slot_h);
}
+ // Assume all source graphics are sRGB
+ set_cairo_surface_ci( tbg, SP_CSS_COLOR_INTERPOLATION_SRGB );
+
return tbg;
}
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
index 0242754eb..50f1b48c5 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -139,6 +139,13 @@ void FilterSpecularLighting::render_cairo(FilterSlot &slot)
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ // Only alpha channel of input is used, no need to check input color_interpolation_filter value.
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ set_cairo_surface_ci(out, ci_fp );
+
Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
Geom::Point p = slot.get_slot_area().min();
double x0 = p[Geom::X];
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index bce532f21..76b877fbc 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -375,6 +375,11 @@ void FilterTurbulence::render_cairo(FilterSlot &slot)
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ // color_interpolation_filter is determined by CSS value (see spec. Turbulence).
+ if( _style ) {
+ set_cairo_surface_ci(out, (SPColorInterpolation)_style->color_interpolation_filters.computed );
+ }
+
if (!gen->ready()) {
Geom::Point ta(fTileX, fTileY);
Geom::Point tb(fTileX + fTileWidth, fTileY + fTileHeight);
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index f580a5044..eeba94d7c 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -38,6 +38,7 @@
#include "display/nr-filter-tile.h"
#include "display/nr-filter-turbulence.h"
+#include "display/cairo-utils.h"
#include "display/drawing.h"
#include "display/drawing-item.h"
#include "display/drawing-context.h"
@@ -159,6 +160,10 @@ int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, D
Geom::Point origin = graphic.targetLogicalBounds().min();
cairo_surface_t *result = slot.get_result(_output_slot);
+
+ // Assume for the moment that we paint the filter in sRGB
+ set_cairo_surface_ci( result, SP_CSS_COLOR_INTERPOLATION_SRGB );
+
graphic.setSource(result, origin[Geom::X], origin[Geom::Y]);
graphic.setOperator(CAIRO_OPERATOR_SOURCE);
graphic.paint();
diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp
index d0c6d2d56..0d1b56d54 100644
--- a/src/display/nr-svgfonts.cpp
+++ b/src/display/nr-svgfonts.cpp
@@ -16,7 +16,7 @@
#include <2geom/transforms.h>
#include <cairo.h>
#include <vector>
-#include "style.h"
+#include "sp-object.h"
#include "svg/svg.h"
#include "display/cairo-utils.h"
#include "display/nr-svgfonts.h"