summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2013-01-29 14:23:22 +0000
committertavmjong-free <tavmjong@free.fr>2013-01-29 14:23:22 +0000
commit7900b2459ca0a6f6e11a367443046582c4852752 (patch)
tree5326fff6c6b1457f22d56b4f50dceac3c9744f28 /src
parentPath::OutlineJoin. remove redundant nodes which are causing glitches (Bug 820... (diff)
downloadinkscape-7900b2459ca0a6f6e11a367443046582c4852752.tar.gz
inkscape-7900b2459ca0a6f6e11a367443046582c4852752.zip
Filter color values always defined as sRGB (or ICC).
(bzr r12070)
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp9
-rw-r--r--src/display/cairo-utils.h1
-rw-r--r--src/display/nr-filter-diffuselighting.cpp37
-rw-r--r--src/display/nr-filter-diffuselighting.h3
-rw-r--r--src/display/nr-filter-flood.cpp17
-rw-r--r--src/display/nr-filter-specularlighting.cpp37
-rw-r--r--src/display/nr-filter-specularlighting.h3
-rw-r--r--src/filters/diffuselighting.cpp17
-rw-r--r--src/filters/diffuselighting.h8
-rw-r--r--src/filters/specularlighting.cpp17
-rw-r--r--src/filters/specularlighting.h3
11 files changed, 137 insertions, 15 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 9655fc194..831b37899 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -597,6 +597,15 @@ void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r,
a = CLAMP(a, 0.0, 1.0);
}
+void srgb_to_linear( double* c ) {
+
+ if( *c < 0.04045 ) {
+ *c /= 12.92;
+ } else {
+ *c = pow( (*c+0.055)/1.055, 2.4 );
+ }
+}
+
void srgb_to_linear( guint32* c, guint32 a ) {
*c = unpremul_alpha( *c, a );
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index af4727c01..04d6c6810 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -108,6 +108,7 @@ 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);
+void srgb_to_linear( double *c);
int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface);
int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface);
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index faf56a4ca..22e6731c3 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -21,6 +21,8 @@
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "display/nr-light.h"
+#include "svg/svg-icc-color.h"
+#include "svg/svg-color.h"
namespace Inkscape {
namespace Filters {
@@ -126,12 +128,37 @@ 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);
+ double r = SP_RGBA32_R_F(lighting_color);
+ double g = SP_RGBA32_G_F(lighting_color);
+ double b = SP_RGBA32_B_F(lighting_color);
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+ if (icc) {
+ guchar ru, gu, bu;
+ icc_color_to_sRGB(icc, &ru, &gu, &bu);
+ r = SP_COLOR_U_TO_F(ru);
+ g = SP_COLOR_U_TO_F(gu);
+ b = SP_COLOR_U_TO_F(bu);
+ }
+#endif
+
// 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;
+
+ // Lighting color is always defined in terms of sRGB, preconvert to linearRGB
+ // if color_interpolation_filters set to linearRGB (for efficiency assuming
+ // next filter primitive has same value of cif).
+ if( ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ srgb_to_linear( &r );
+ srgb_to_linear( &g );
+ srgb_to_linear( &b );
+ }
}
set_cairo_surface_ci(out, ci_fp );
+ guint32 color = SP_RGBA32_F_COMPOSE( r, g, b, 1.0 );
Geom::Rect slot_area = slot.get_slot_area();
Geom::Point p = slot_area.min();
@@ -142,15 +169,15 @@ void FilterDiffuseLighting::render_cairo(FilterSlot &slot)
switch (light_type) {
case DISTANT_LIGHT:
ink_cairo_surface_synthesize(out,
- DiffuseDistantLight(input, light.distant, lighting_color, scale, diffuseConstant));
+ DiffuseDistantLight(input, light.distant, color, scale, diffuseConstant));
break;
case POINT_LIGHT:
ink_cairo_surface_synthesize(out,
- DiffusePointLight(input, light.point, lighting_color, trans, scale, diffuseConstant, x0, y0));
+ DiffusePointLight(input, light.point, color, trans, scale, diffuseConstant, x0, y0));
break;
case SPOT_LIGHT:
ink_cairo_surface_synthesize(out,
- DiffuseSpotLight(input, light.spot, lighting_color, trans, scale, diffuseConstant, x0, y0));
+ DiffuseSpotLight(input, light.spot, color, trans, scale, diffuseConstant, x0, y0));
break;
default: {
cairo_t *ct = cairo_create(out);
@@ -165,6 +192,10 @@ void FilterDiffuseLighting::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
+void FilterDiffuseLighting::set_icc(SVGICCColor *icc_color) {
+ icc = icc_color;
+}
+
void FilterDiffuseLighting::area_enlarge(Geom::IntRect &area, Geom::Affine const & /*trans*/)
{
// TODO: support kernelUnitLength
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
index 0da6cc218..315bf9f48 100644
--- a/src/display/nr-filter-diffuselighting.h
+++ b/src/display/nr-filter-diffuselighting.h
@@ -22,6 +22,7 @@
class SPFeDistantLight;
class SPFePointLight;
class SPFeSpotLight;
+class SVGICCColor;
namespace Inkscape {
namespace Filters {
@@ -32,6 +33,7 @@ public:
static FilterPrimitive *create();
virtual ~FilterDiffuseLighting();
virtual void render_cairo(FilterSlot &slot);
+ virtual void set_icc(SVGICCColor *icc_color);
virtual void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans);
virtual double complexity(Geom::Affine const &ctm);
@@ -46,6 +48,7 @@ public:
guint32 lighting_color;
private:
+ SVGICCColor *icc;
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp
index 7117e0343..0c581762d 100644
--- a/src/display/nr-filter-flood.cpp
+++ b/src/display/nr-filter-flood.cpp
@@ -45,8 +45,6 @@ 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);
@@ -57,10 +55,21 @@ 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).
+
+ SPColorInterpolation ci_fp = SP_CSS_COLOR_INTERPOLATION_AUTO;
if( _style ) {
- set_cairo_surface_ci(out, (SPColorInterpolation)_style->color_interpolation_filters.computed );
+ ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;
+
+ // Flood color is always defined in terms of sRGB, preconvert to linearRGB
+ // if color_interpolation_filters set to linearRGB (for efficiency assuming
+ // next filter primitive has same value of cif).
+ if( ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ srgb_to_linear( &r );
+ srgb_to_linear( &g );
+ srgb_to_linear( &b );
+ }
}
+ set_cairo_surface_ci(out, ci_fp );
// Get filter primitive area in user units
Geom::Rect fp = filter_primitive_area( slot.get_units() );
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
index 50f1b48c5..535633143 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -21,6 +21,8 @@
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "display/nr-light.h"
+#include "svg/svg-icc-color.h"
+#include "svg/svg-color.h"
namespace Inkscape {
namespace Filters {
@@ -139,12 +141,37 @@ 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);
+ double r = SP_RGBA32_R_F(lighting_color);
+ double g = SP_RGBA32_G_F(lighting_color);
+ double b = SP_RGBA32_B_F(lighting_color);
+
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
+ if (icc) {
+ guchar ru, gu, bu;
+ icc_color_to_sRGB(icc, &ru, &gu, &bu);
+ r = SP_COLOR_U_TO_F(ru);
+ g = SP_COLOR_U_TO_F(gu);
+ b = SP_COLOR_U_TO_F(bu);
+ }
+#endif
+
// 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;
+
+ // Lighting color is always defined in terms of sRGB, preconvert to linearRGB
+ // if color_interpolation_filters set to linearRGB (for efficiency assuming
+ // next filter primitive has same value of cif).
+ if( ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
+ srgb_to_linear( &r );
+ srgb_to_linear( &g );
+ srgb_to_linear( &b );
+ }
}
set_cairo_surface_ci(out, ci_fp );
+ guint32 color = SP_RGBA32_F_COMPOSE( r, g, b, 1.0 );
Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
Geom::Point p = slot.get_slot_area().min();
@@ -157,15 +184,15 @@ void FilterSpecularLighting::render_cairo(FilterSlot &slot)
switch (light_type) {
case DISTANT_LIGHT:
ink_cairo_surface_synthesize(out,
- SpecularDistantLight(input, light.distant, lighting_color, scale, ks, se));
+ SpecularDistantLight(input, light.distant, color, scale, ks, se));
break;
case POINT_LIGHT:
ink_cairo_surface_synthesize(out,
- SpecularPointLight(input, light.point, lighting_color, trans, scale, ks, se, x0, y0));
+ SpecularPointLight(input, light.point, color, trans, scale, ks, se, x0, y0));
break;
case SPOT_LIGHT:
ink_cairo_surface_synthesize(out,
- SpecularSpotLight(input, light.spot, lighting_color, trans, scale, ks, se, x0, y0));
+ SpecularSpotLight(input, light.spot, color, trans, scale, ks, se, x0, y0));
break;
default: {
cairo_t *ct = cairo_create(out);
@@ -180,6 +207,10 @@ void FilterSpecularLighting::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
+void FilterSpecularLighting::set_icc(SVGICCColor *icc_color) {
+ icc = icc_color;
+}
+
void FilterSpecularLighting::area_enlarge(Geom::IntRect &area, Geom::Affine const & /*trans*/)
{
// TODO: support kernelUnitLength
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
index 33ea17a87..4f8c2d112 100644
--- a/src/display/nr-filter-specularlighting.h
+++ b/src/display/nr-filter-specularlighting.h
@@ -20,6 +20,7 @@
class SPFeDistantLight;
class SPFePointLight;
class SPFeSpotLight;
+class SVGICCColor;
namespace Inkscape {
namespace Filters {
@@ -33,6 +34,7 @@ public:
virtual ~FilterSpecularLighting();
virtual void render_cairo(FilterSlot &slot);
+ virtual void set_icc(SVGICCColor *icc_color);
virtual void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans);
virtual double complexity(Geom::Affine const &ctm);
@@ -48,6 +50,7 @@ public:
guint32 lighting_color;
private:
+ SVGICCColor *icc;
};
} /* namespace Filters */
diff --git a/src/filters/diffuselighting.cpp b/src/filters/diffuselighting.cpp
index 2e69f7555..66dd825f6 100644
--- a/src/filters/diffuselighting.cpp
+++ b/src/filters/diffuselighting.cpp
@@ -18,10 +18,13 @@
# include "config.h"
#endif
+#include "strneq.h"
+
#include "attributes.h"
#include "svg/svg.h"
#include "sp-object.h"
#include "svg/svg-color.h"
+#include "svg/svg-icc-color.h"
#include "filters/diffuselighting.h"
#include "filters/distantlight.h"
#include "filters/pointlight.h"
@@ -74,6 +77,8 @@ sp_feDiffuseLighting_init(SPFeDiffuseLighting *feDiffuseLighting)
feDiffuseLighting->surfaceScale = 1;
feDiffuseLighting->diffuseConstant = 1;
feDiffuseLighting->lighting_color = 0xffffffff;
+ feDiffuseLighting->icc = NULL;
+
//TODO kernelUnit
feDiffuseLighting->renderer = NULL;
@@ -176,6 +181,16 @@ sp_feDiffuseLighting_set(SPObject *object, unsigned int key, gchar const *value)
feDiffuseLighting->lighting_color = sp_svg_read_color(value, &cend_ptr, 0xffffffff);
//if a value was read
if (cend_ptr) {
+ while (g_ascii_isspace(*cend_ptr)) {
+ ++cend_ptr;
+ }
+ if (strneq(cend_ptr, "icc-color(", 10)) {
+ if (!feDiffuseLighting->icc) feDiffuseLighting->icc = new SVGICCColor();
+ if ( ! sp_svg_read_icc_color( cend_ptr, feDiffuseLighting->icc ) ) {
+ delete feDiffuseLighting->icc;
+ feDiffuseLighting->icc = NULL;
+ }
+ }
feDiffuseLighting->lighting_color_set = TRUE;
} else {
//lighting_color already contains the default value
@@ -328,6 +343,8 @@ static void sp_feDiffuseLighting_build_renderer(SPFilterPrimitive *primitive, In
nr_diffuselighting->diffuseConstant = sp_diffuselighting->diffuseConstant;
nr_diffuselighting->surfaceScale = sp_diffuselighting->surfaceScale;
nr_diffuselighting->lighting_color = sp_diffuselighting->lighting_color;
+ nr_diffuselighting->set_icc(sp_diffuselighting->icc);
+
//We assume there is at most one child
nr_diffuselighting->light_type = Inkscape::Filters::NO_LIGHT;
if (SP_IS_FEDISTANTLIGHT(primitive->children)) {
diff --git a/src/filters/diffuselighting.h b/src/filters/diffuselighting.h
index a23346622..99dccb394 100644
--- a/src/filters/diffuselighting.h
+++ b/src/filters/diffuselighting.h
@@ -15,17 +15,14 @@
#include "sp-filter-primitive.h"
#include "number-opt-number.h"
-namespace Inkscape {
-namespace Filters {
-class FilterDiffuseLighting;
-} }
-
#define SP_TYPE_FEDIFFUSELIGHTING (sp_feDiffuseLighting_get_type())
#define SP_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLighting))
#define SP_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLightingClass))
#define SP_IS_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDIFFUSELIGHTING))
#define SP_IS_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDIFFUSELIGHTING))
+class SVGICCColor;
+
namespace Inkscape {
namespace Filters {
class FilterDiffuseLighting;
@@ -42,6 +39,7 @@ struct SPFeDiffuseLighting : public SPFilterPrimitive {
guint32 lighting_color;
guint lighting_color_set : 1;
Inkscape::Filters::FilterDiffuseLighting *renderer;
+ SVGICCColor *icc;
};
struct SPFeDiffuseLightingClass {
diff --git a/src/filters/specularlighting.cpp b/src/filters/specularlighting.cpp
index 44eeff35a..a7a19e11d 100644
--- a/src/filters/specularlighting.cpp
+++ b/src/filters/specularlighting.cpp
@@ -18,10 +18,13 @@
# include "config.h"
#endif
+#include "strneq.h"
+
#include "attributes.h"
#include "svg/svg.h"
#include "sp-object.h"
#include "svg/svg-color.h"
+#include "svg/svg-icc-color.h"
#include "filters/specularlighting.h"
#include "filters/distantlight.h"
#include "filters/pointlight.h"
@@ -75,6 +78,8 @@ sp_feSpecularLighting_init(SPFeSpecularLighting *feSpecularLighting)
feSpecularLighting->specularConstant = 1;
feSpecularLighting->specularExponent = 1;
feSpecularLighting->lighting_color = 0xffffffff;
+ feSpecularLighting->icc = NULL;
+
//TODO kernelUnit
feSpecularLighting->renderer = NULL;
@@ -202,6 +207,16 @@ sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value
feSpecularLighting->lighting_color = sp_svg_read_color(value, &cend_ptr, 0xffffffff);
//if a value was read
if (cend_ptr) {
+ while (g_ascii_isspace(*cend_ptr)) {
+ ++cend_ptr;
+ }
+ if (strneq(cend_ptr, "icc-color(", 10)) {
+ if (!feSpecularLighting->icc) feSpecularLighting->icc = new SVGICCColor();
+ if ( ! sp_svg_read_icc_color( cend_ptr, feSpecularLighting->icc ) ) {
+ delete feSpecularLighting->icc;
+ feSpecularLighting->icc = NULL;
+ }
+ }
feSpecularLighting->lighting_color_set = TRUE;
} else {
//lighting_color already contains the default value
@@ -352,6 +367,8 @@ static void sp_feSpecularLighting_build_renderer(SPFilterPrimitive *primitive, I
nr_specularlighting->specularExponent = sp_specularlighting->specularExponent;
nr_specularlighting->surfaceScale = sp_specularlighting->surfaceScale;
nr_specularlighting->lighting_color = sp_specularlighting->lighting_color;
+ nr_specularlighting->set_icc(sp_specularlighting->icc);
+
//We assume there is at most one child
nr_specularlighting->light_type = Inkscape::Filters::NO_LIGHT;
if (SP_IS_FEDISTANTLIGHT(primitive->children)) {
diff --git a/src/filters/specularlighting.h b/src/filters/specularlighting.h
index 90d1f9f62..44bd98c6c 100644
--- a/src/filters/specularlighting.h
+++ b/src/filters/specularlighting.h
@@ -23,6 +23,8 @@
#define SP_IS_FESPECULARLIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FESPECULARLIGHTING))
#define SP_IS_FESPECULARLIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FESPECULARLIGHTING))
+class SVGICCColor;
+
namespace Inkscape {
namespace Filters {
class FilterSpecularLighting;
@@ -41,6 +43,7 @@ struct SPFeSpecularLighting : public SPFilterPrimitive {
NumberOptNumber kernelUnitLength;
guint32 lighting_color;
guint lighting_color_set : 1;
+ SVGICCColor *icc;
Inkscape::Filters::FilterSpecularLighting *renderer;
};