diff options
| author | su_v <suv-sf@users.sourceforge.net> | 2013-01-01 18:24:47 +0000 |
|---|---|---|
| committer | ~suv <suv-sf@users.sourceforge.net> | 2013-01-01 18:24:47 +0000 |
| commit | 0b3b386881da011ac7ee60dd20bd610fd9670677 (patch) | |
| tree | 59d08dfb788ebbe333fa21140fcd8203faadc356 /src/display/cairo-utils.cpp | |
| parent | merge from trunk (r11952) (diff) | |
| parent | clip path visual bbox refresh, second try (Bug 1005085) (diff) | |
| download | inkscape-0b3b386881da011ac7ee60dd20bd610fd9670677.tar.gz inkscape-0b3b386881da011ac7ee60dd20bd610fd9670677.zip | |
merge from trunk (r12005)
(bzr r11668.1.47)
Diffstat (limited to 'src/display/cairo-utils.cpp')
| -rw-r--r-- | src/display/cairo-utils.cpp | 125 |
1 files changed, 125 insertions, 0 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() { |
