summaryrefslogtreecommitdiffstats
path: root/src/display/cairo-utils.cpp
diff options
context:
space:
mode:
authorsu_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
commit0b3b386881da011ac7ee60dd20bd610fd9670677 (patch)
tree59d08dfb788ebbe333fa21140fcd8203faadc356 /src/display/cairo-utils.cpp
parentmerge from trunk (r11952) (diff)
parentclip path visual bbox refresh, second try (Bug 1005085) (diff)
downloadinkscape-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.cpp125
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()
{