summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-blend.cpp44
-rw-r--r--src/display/nr-filter-colormatrix.cpp29
-rw-r--r--src/display/nr-filter-component-transfer.cpp27
-rw-r--r--src/display/nr-filter-composite.cpp41
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp29
-rw-r--r--src/display/nr-filter-diffuselighting.cpp12
-rw-r--r--src/display/nr-filter-displacement-map.cpp28
-rw-r--r--src/display/nr-filter-flood.cpp9
-rw-r--r--src/display/nr-filter-gaussian.cpp34
-rw-r--r--src/display/nr-filter-image.cpp10
-rw-r--r--src/display/nr-filter-merge.cpp19
-rw-r--r--src/display/nr-filter-morphology.cpp6
-rw-r--r--src/display/nr-filter-offset.cpp6
-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.cpp10
-rw-r--r--src/display/nr-filter-specularlighting.cpp12
-rw-r--r--src/display/nr-filter-turbulence.cpp7
-rw-r--r--src/display/nr-filter.cpp11
-rw-r--r--src/filter-chemistry.cpp5
-rw-r--r--src/sp-filter-primitive.cpp15
-rw-r--r--src/sp-filter.cpp28
22 files changed, 372 insertions, 33 deletions
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
index 267883b4b..2ada36949 100644
--- a/src/display/nr-filter-blend.cpp
+++ b/src/display/nr-filter-blend.cpp
@@ -146,13 +146,53 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ // Note: an alpha only surface should not have ci set.
+ SPColorInterpolation ci_in1 = get_cairo_surface_ci(input1);
+ SPColorInterpolation ci_in2 = get_cairo_surface_ci(input2);
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ if( ci_in1 == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterColorBlend: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input1 );
+ }
+ if( ci_in1 == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterColorBlend: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input1 );
+ }
+ if( ci_in2 == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterColorBlend: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input2 );
+ }
+ if( ci_in2 == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterColorBlend: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input2 );
+ }
// 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);
+ if( cairo_surface_get_content( out ) == CAIRO_CONTENT_COLOR_ALPHA ) {
+ set_cairo_surface_ci(out, ci_fp );
+ }
+
+ // std::cout << "FilterBlend: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input1)
+ // << " in2: " << get_cairo_surface_ci(input2)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+ 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..5d3cf6a9e 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -152,12 +152,41 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ // Note: an alpha only surface should not have ci set.
+ SPColorInterpolation ci_in = get_cairo_surface_ci(input);
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterColorMatrix: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterColorMatrix: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input );
+ }
+
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);
}
+ // std::cout << "FilterColorMatrix: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+
switch (type) {
case COLORMATRIX_MATRIX:
ink_cairo_surface_filter(input, out, FilterColorMatrix::ColorMatrixMatrix(values));
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 226a73cef..8efcc9c4d 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -238,6 +238,33 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ SPColorInterpolation ci_in = get_cairo_surface_ci(input);
+ 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 );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterComponentTransfer: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterComponentTransfer: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input );
+ }
+
+ // std::cout << "FilterComponentTransfer: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+
//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..f5ec94a46 100644
--- a/src/display/nr-filter-composite.cpp
+++ b/src/display/nr-filter-composite.cpp
@@ -66,7 +66,48 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ // Note: an alpha only surface should not have ci set.
+ SPColorInterpolation ci_in1 = get_cairo_surface_ci(input1);
+ SPColorInterpolation ci_in2 = get_cairo_surface_ci(input2);
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ if( ci_in1 == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterColorComposite: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input1 );
+ }
+ if( ci_in1 == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterColorComposite: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input1 );
+ }
+ if( ci_in2 == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ std::cout << "FilterColorComposite: srgb -> linear" << std::endl;
+ //ink_cairo_surface_srgb_to_linear( input2 );
+ }
+ if( ci_in2 == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterColorComposite: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input2 );
+ }
+
cairo_surface_t *out = ink_cairo_surface_create_output(input1, input2);
+ if( cairo_surface_get_content( out ) == CAIRO_CONTENT_COLOR_ALPHA ) {
+ set_cairo_surface_ci(out, ci_fp );
+ }
+
+ // std::cout << "FilterComposite: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input1)
+ // << " in2: " << get_cairo_surface_ci(input2)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
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..6ee67d126 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,35 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ SPColorInterpolation ci_in = get_cairo_surface_ci(input);
+ 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);
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterConvolveMatrix: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( input );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterConvolveMatrix: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( input );
+ }
+
+ // std::cout << "FilterConvolveMatrix: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+
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..bd473eb76 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -126,6 +126,18 @@ 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 ) {
+ set_cairo_surface_ci(out, (SPColorInterpolation)_style->color_interpolation_filters.computed );
+ set_cairo_surface_ci(out, ci_fp );
+ }
+
+ // std::cout << "FilterDiffuseLighting: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+
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..909e11f50 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -74,6 +74,34 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ SPColorInterpolation ci_map = get_cairo_surface_ci(map);
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ if( ci_map == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterDisplacementMap: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( map );
+ }
+ if( ci_map == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterDisplacementMap: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( map );
+ }
+
+ // std::cout << "FilterDisplacementMap: ci data: "
+ // << " texture: " << get_cairo_surface_ci(texture)
+ // << " map: " << get_cairo_surface_ci(map)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
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..649d4609f 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,13 @@ 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 );
+ }
+
+ // std::cout << "FilterFlood: ci data: out: "
+ // << get_cairo_surface_ci(out) << std::endl;
// 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..3b29e825d 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -553,6 +553,30 @@ 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.
+ // The converting function tags surface with the proper ci value.
+ // Note: an alpha only surface should not have ci set.
+ SPColorInterpolation ci_in = get_cairo_surface_ci(in);
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
+ if( _style ) {
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterGaussian: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( in );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterGaussian: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( in );
+ }
+
+ // std::cout << "FilterGaussian: ci data: in: "
+ // << get_cairo_surface_ci( in ) << std::endl;
+
// zero deviation = no change in output
if (_deviation_x <= 0 && _deviation_y <= 0) {
cairo_surface_t *cp = ink_cairo_surface_copy(in);
@@ -660,10 +684,20 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
cairo_paint(ct);
cairo_destroy(ct);
+ if( cairo_surface_get_content( upsampled ) == CAIRO_CONTENT_COLOR_ALPHA ) {
+ set_cairo_surface_ci( upsampled, ci_fp );
+ }
+ // std::cout << "FilterGaussian: ci data: resampled: "
+ // << get_cairo_surface_ci(upsampled) << std::endl;
slot.set(_output, upsampled);
cairo_surface_destroy(upsampled);
cairo_surface_destroy(downsampled);
} else {
+ if( cairo_surface_get_content( downsampled ) == CAIRO_CONTENT_COLOR_ALPHA ) {
+ set_cairo_surface_ci( downsampled, ci_fp );
+ }
+ // std::cout << "FilterGaussian: ci data: downsampled: "
+ // << get_cairo_surface_ci(downsampled) << std::endl;
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..8aae29cbe 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -120,6 +120,11 @@ 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);
+ // std::cout << "FilterImage: ci set to: "
+ // << get_cairo_surface_ci(out) << std::endl;
+
slot.set(_output, out);
cairo_surface_destroy(out);
return;
@@ -185,6 +190,11 @@ 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);
+ // std::cout << "FilterImage: ci set to: "
+ // << get_cairo_surface_ci(out) << std::endl;
+
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..4d3862a33 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,19 @@ 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);
+
+ SPColorInterpolation ci_in = get_cairo_surface_ci(in);
+ //std::cout << "FilterMerge: slot: ci: " << ci_in << std::endl;
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_SRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "FilterMerge: srgb -> linear" << std::endl;
+ ink_cairo_surface_srgb_to_linear( in );
+ }
+ if( ci_in == SP_CSS_COLOR_INTERPOLATION_LINEARRGB &&
+ ci_fp == SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ //std::cout << "FilterMerge: linear -> srgb" << std::endl;
+ ink_cairo_surface_linear_to_srgb( in );
+ }
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..7447b76fe 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,11 @@ 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);
+ // std::cout << "FilterMorphology: ci set to: "
+ // << get_cairo_surface_ci(out) << std::endl;
+
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..3543de6df 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -35,6 +35,12 @@ 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);
+
+ // std::cout << "FilterOffset: ci data: out: "
+ // << get_cairo_surface_ci(out) << std::endl;
+
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..64c5143ff 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -84,11 +84,13 @@ cairo_surface_t *FilterSlot::getcairo(int slot_nr)
case NR_FILTER_SOURCEGRAPHIC: {
cairo_surface_t *tr = _get_transformed_source_graphic();
_set_internal(NR_FILTER_SOURCEGRAPHIC, tr);
+ //std::cout << "Source Graphic: ci data: " << get_cairo_surface_ci( tr ) << std::endl;
cairo_surface_destroy(tr);
} break;
case NR_FILTER_BACKGROUNDIMAGE: {
cairo_surface_t *bg = _get_transformed_background();
_set_internal(NR_FILTER_BACKGROUNDIMAGE, bg);
+ //std::cout << "Background Image: ci data: " << get_cairo_surface_ci( bg ) << std::endl;
cairo_surface_destroy(bg);
} break;
case NR_FILTER_SOURCEALPHA: {
@@ -129,6 +131,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 +150,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 +179,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..4cf8f319d 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -139,6 +139,18 @@ 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 ) {
+ set_cairo_surface_ci(out, (SPColorInterpolation)_style->color_interpolation_filters.computed );
+ set_cairo_surface_ci(out, ci_fp );
+ }
+
+ // std::cout << "FilterSpecularLighting: ci data: "
+ // << " in1: " << get_cairo_surface_ci(input)
+ // << " out: " << get_cairo_surface_ci(out)
+ // << std::endl;
+
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..e2b52a1d4 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -375,6 +375,13 @@ 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 );
+ }
+ // std::cout << "FilterTurbulance: ci data: out: "
+ // << get_cairo_surface_ci(out) << std::endl;
+
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..a29ac551a 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,16 @@ 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);
+
+ // std::cout << "Filter: result: ci data: "
+ // << get_cairo_surface_ci(result) << std::endl;
+
+ // Assume for the moment that we paint the filter in sRGB
+ if( get_cairo_surface_ci(result) == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ //std::cout << "Filter: result: linear -> sRGB" << std::endl;
+ ink_cairo_surface_linear_to_srgb( result );
+ }
+
graphic.setSource(result, origin[Geom::X], origin[Geom::Y]);
graphic.setOperator(CAIRO_OPERATOR_SOURCE);
graphic.paint();
diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp
index fc74ee8a2..14bd00057 100644
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
@@ -98,7 +98,10 @@ SPFilter *new_filter(SPDocument *document)
Inkscape::XML::Node *repr;
repr = xml_doc->createElement("svg:filter");
- // Inkscape only supports sRGB. See note in sp-filter.cpp.
+ // Inkscape now supports both sRGB and linear color-interpolation-filters.
+ // But, for the moment, keep sRGB as default value for new filters
+ // (historically set to sRGB and doesn't require conversion between
+ // filter cairo surfaces and other types of cairo surfaces).
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_set_property(css, "color-interpolation-filters", "sRGB");
sp_repr_css_change(repr, css, "style");
diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp
index b63a05b4b..7ddf3b065 100644
--- a/src/sp-filter-primitive.cpp
+++ b/src/sp-filter-primitive.cpp
@@ -20,6 +20,7 @@
#include <string.h>
#include "attributes.h"
+#include "style.h"
#include "sp-filter-primitive.h"
#include "xml/repr.h"
#include "sp-filter.h"
@@ -100,16 +101,17 @@ static void sp_filter_primitive_init(SPFilterPrimitive *filter_primitive)
static void
sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
- if ((static_cast<SPObjectClass *>(filter_primitive_parent_class))->build) {
- (static_cast<SPObjectClass *>(filter_primitive_parent_class))->build(object, document, repr);
- }
-
+ object->readAttr( "style" ); // struct not derived from SPItem, we need to do this ourselves.
object->readAttr( "in" );
object->readAttr( "result" );
object->readAttr( "x" );
object->readAttr( "y" );
object->readAttr( "width" );
object->readAttr( "height" );
+
+ if ((static_cast<SPObjectClass *>(filter_primitive_parent_class))->build) {
+ (static_cast<SPObjectClass *>(filter_primitive_parent_class))->build(object, document, repr);
+ }
}
/**
@@ -188,7 +190,9 @@ sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags)
{
//SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);
+ // Is this required?
if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ object->readAttr( "style" );
object->readAttr( "in" );
object->readAttr( "result" );
object->readAttr( "x" );
@@ -311,6 +315,9 @@ void sp_filter_primitive_renderer_common(SPFilterPrimitive *sp_prim, Inkscape::F
/* TODO: place here code to handle input images, filter area etc. */
nr_prim->set_subregion( sp_prim->x, sp_prim->y, sp_prim->width, sp_prim->height );
+
+ // Give renderer access to filter properties
+ nr_prim->setStyle( sp_prim->style );
}
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index a20856f53..c7dce3850 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -130,11 +130,8 @@ sp_filter_init(SPFilter *filter)
static void
sp_filter_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
- if (((SPObjectClass *) filter_parent_class)->build) {
- ((SPObjectClass *) filter_parent_class)->build(object, document, repr);
- }
-
//Read values of key attributes from XML nodes into object.
+ object->readAttr( "style" ); // struct not derived from SPItem, we need to do this ourselves.
object->readAttr( "filterUnits" );
object->readAttr( "primitiveUnits" );
object->readAttr( "x" );
@@ -144,6 +141,10 @@ sp_filter_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
object->readAttr( "filterRes" );
object->readAttr( "xlink:href" );
+ if (((SPObjectClass *) filter_parent_class)->build) {
+ ((SPObjectClass *) filter_parent_class)->build(object, document, repr);
+ }
+
//is this necessary?
document->addResource("filter", object);
}
@@ -366,25 +367,6 @@ sp_filter_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::N
g_free(uri_string);
}
- // TODO: This is evil, correctly implement support for color-interpolation-filters!!!
- // The color-interpolation-filters attribute is initially set to linearRGB according to the SVG standard.
- // However, Inkscape completely ignores it and implicitly assumes that it is sRGB (like color-interpolation).
- // This results in a discrepancy between Inkscape and other renderers in how they render filters.
- // To mitigate this problem I've (Jasper van de Gronde,th.v.d.gronde@hccnet.nl) added this to ensure that at least
- // any filters written by Inkscape will henceforth be rendered the same in other renderers.
- // In the future Inkscape should have proper support for the color-interpolation properties and this should be changed.
-
- // repr->setAttribute("color-interpolation-filters", "sRGB");
-
- // Actually, the above line is not correct as the attribute is only allowed on filter
- // primitives and not <filter> objects. However, it is allowed as a property in a style
- // attribute. Note, this property must also be set in sp-filter-chemistry, filter_new() as the
- // code here is not necessarily called when a new filter is created. 29 Aug 2011 Tav.
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "color-interpolation-filters", "sRGB");
- sp_repr_css_change(repr, css, "style");
- sp_repr_css_attr_unref(css);
-
if (((SPObjectClass *) filter_parent_class)->write) {
((SPObjectClass *) filter_parent_class)->write(object, doc, repr, flags);
}