From 7215dbf9d7ba8c147c66f16f23c0d6481491c76b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 22 Dec 2012 17:40:01 +0100 Subject: Add utilities to tag a cairo surface with color interpolation value. (bzr r11971) --- src/display/cairo-utils.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) (limited to 'src/display/cairo-utils.cpp') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 2e2eb42dd..92303fed8 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,26 @@ 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; + } +} + +void +set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation ci) { + 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 +416,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 +569,94 @@ 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(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(data + 4*x) = px2; + } + } + set_cairo_surface_ci( surface, SP_CSS_COLOR_INTERPOLATION_LINEARRGB ); + 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(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(data + 4*x) = px2; + } + } + set_cairo_surface_ci( surface, SP_CSS_COLOR_INTERPOLATION_SRGB ); + return width * height; +} + cairo_pattern_t * ink_cairo_pattern_create_checkerboard() { -- cgit v1.2.3 From d1e043d27a35b00c9e49a2deef1c2ee5bc8b2cc5 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 23 Dec 2012 10:55:50 +0100 Subject: Move some code from filter primitives to cairo-utils.cpp. Fix bug in lighting primitives. (bzr r11976) --- src/display/cairo-utils.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src/display/cairo-utils.cpp') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 92303fed8..692e31837 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -287,9 +287,26 @@ get_cairo_surface_ci(cairo_surface_t *surface) { } } +/** 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) { - cairo_surface_set_user_data(surface, &ci_key, GINT_TO_POINTER (ci), NULL); + + 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 @@ -627,7 +644,6 @@ int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface) *reinterpret_cast(data + 4*x) = px2; } } - set_cairo_surface_ci( surface, SP_CSS_COLOR_INTERPOLATION_LINEARRGB ); return width * height; } @@ -653,7 +669,6 @@ int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface) *reinterpret_cast(data + 4*x) = px2; } } - set_cairo_surface_ci( surface, SP_CSS_COLOR_INTERPOLATION_SRGB ); return width * height; } -- cgit v1.2.3