diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2013-01-29 14:23:22 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2013-01-29 14:23:22 +0000 |
| commit | 7900b2459ca0a6f6e11a367443046582c4852752 (patch) | |
| tree | 5326fff6c6b1457f22d56b4f50dceac3c9744f28 /src | |
| parent | Path::OutlineJoin. remove redundant nodes which are causing glitches (Bug 820... (diff) | |
| download | inkscape-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.cpp | 9 | ||||
| -rw-r--r-- | src/display/cairo-utils.h | 1 | ||||
| -rw-r--r-- | src/display/nr-filter-diffuselighting.cpp | 37 | ||||
| -rw-r--r-- | src/display/nr-filter-diffuselighting.h | 3 | ||||
| -rw-r--r-- | src/display/nr-filter-flood.cpp | 17 | ||||
| -rw-r--r-- | src/display/nr-filter-specularlighting.cpp | 37 | ||||
| -rw-r--r-- | src/display/nr-filter-specularlighting.h | 3 | ||||
| -rw-r--r-- | src/filters/diffuselighting.cpp | 17 | ||||
| -rw-r--r-- | src/filters/diffuselighting.h | 8 | ||||
| -rw-r--r-- | src/filters/specularlighting.cpp | 17 | ||||
| -rw-r--r-- | src/filters/specularlighting.h | 3 |
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; }; |
