X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcolor.cpp;h=54af89ae5d5c92665b458a5cf5666d11179a7d5b;hb=HEAD;hp=2a6da863c4fd35bffbe2033dcc1389bfe72ca64c;hpb=f4f507228b30d55fd7e39386ba513f3a0a54bd5d;p=inkscape.git diff --git a/src/color.cpp b/src/color.cpp index 2a6da863c..54af89ae5 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -1,11 +1,12 @@ #define __SP_COLOR_C__ /** \file - * Colors and colorspaces. + * Colors. * * Author: * Lauris Kaplinski * bulia byak + * Jon A. Cruz * * Copyright (C) 2001-2002 Lauris Kaplinski * Copyright (C) 2001 Ximian, Inc. @@ -15,103 +16,121 @@ #include #include "color.h" +#include "svg/svg-icc-color.h" +#include "svg/svg-color.h" -/// A color space is just a name. -struct SPColorSpace { - gchar const *name; -}; +#include "svg/css-ostringstream.h" -static SPColorSpace const RGB = {"RGB"}; -static SPColorSpace const CMYK = {"CMYK"}; +using Inkscape::CSSOStringStream; +using std::vector; -/** - * Returns one of three values depending on if color is valid and if it - * has a valid color space. Likely redundant as soon as this is C++. - */ -SPColorSpaceClass -sp_color_get_colorspace_class(SPColor const *color) -{ - g_return_val_if_fail (color != NULL, SP_COLORSPACE_CLASS_INVALID); +static bool profileMatches( SVGICCColor const* first, SVGICCColor const* second ); - if (color->colorspace == &RGB) return SP_COLORSPACE_CLASS_PROCESS; - if (color->colorspace == &CMYK) return SP_COLORSPACE_CLASS_PROCESS; +#define PROFILE_EPSILON 0.00000001 - return SP_COLORSPACE_CLASS_UNKNOWN; +SPColor::SPColor() : + icc(0) +{ + v.c[0] = 0; + v.c[1] = 0; + v.c[2] = 0; } -/** - * Returns the SPColorSpaceType corresponding to color's color space. - * \todo color->colorspace should simply be a named enum. - */ -SPColorSpaceType -sp_color_get_colorspace_type(SPColor const *color) +SPColor::SPColor( SPColor const& other ) : + icc(0) { - g_return_val_if_fail (color != NULL, SP_COLORSPACE_TYPE_INVALID); + *this = other; +} - if (color->colorspace == &RGB) return SP_COLORSPACE_TYPE_RGB; - if (color->colorspace == &CMYK) return SP_COLORSPACE_TYPE_CMYK; +SPColor::SPColor( float r, float g, float b ) : + icc(0) +{ + set( r, g, b ); +} - return SP_COLORSPACE_TYPE_UNKNOWN; +SPColor::SPColor( guint32 value ) : + icc(0) +{ + set( value ); } -/** - * Shallow copy of color struct with NULL check. - */ -void -sp_color_copy(SPColor *dst, SPColor const *src) +SPColor::~SPColor() { - g_return_if_fail (dst != NULL); - g_return_if_fail (src != NULL); + delete icc; + icc = 0; +} - *dst = *src; + +SPColor& SPColor::operator= (SPColor const& other) +{ + SVGICCColor* tmp_icc = other.icc ? new SVGICCColor(*other.icc) : 0; + + v.c[0] = other.v.c[0]; + v.c[1] = other.v.c[1]; + v.c[2] = other.v.c[2]; + if ( icc ) { + delete icc; + } + icc = tmp_icc; + + return *this; } + /** - * Returns TRUE if c0 or c1 is NULL, or if colors/opacities differ. + * Returns true if colors match. */ -gboolean -sp_color_is_equal (SPColor const *c0, SPColor const *c1) +bool SPColor::operator == (SPColor const& other) const { - g_return_val_if_fail (c0 != NULL, TRUE); - g_return_val_if_fail (c1 != NULL, TRUE); + bool match = (v.c[0] != other.v.c[0]) + && (v.c[1] != other.v.c[1]) + && (v.c[2] != other.v.c[2]); - if (c0->colorspace != c1->colorspace) return FALSE; - if (c0->v.c[0] != c1->v.c[0]) return FALSE; - if (c0->v.c[1] != c1->v.c[1]) return FALSE; - if (c0->v.c[2] != c1->v.c[2]) return FALSE; - if ((c0->colorspace == &CMYK) && (c0->v.c[3] != c1->v.c[3])) return FALSE; + match &= profileMatches( icc, other.icc ); - return TRUE; + return match; } /** - * Returns TRUE if no RGB value differs epsilon or more in both colors, - * with CMYK aditionally comparing opacity, or if c0 or c1 is NULL. - * \note Do we want the latter? + * Returns true if no RGB value differs epsilon or more in both colors, + * false otherwise. */ -gboolean -sp_color_is_close (SPColor const *c0, SPColor const *c1, float epsilon) +bool SPColor::isClose( SPColor const& other, float epsilon ) const { - g_return_val_if_fail (c0 != NULL, TRUE); - g_return_val_if_fail (c1 != NULL, TRUE); + bool match = false; + + match = (fabs((v.c[0]) - (other.v.c[0])) < epsilon) + && (fabs((v.c[1]) - (other.v.c[1])) < epsilon) + && (fabs((v.c[2]) - (other.v.c[2])) < epsilon); - if (c0->colorspace != c1->colorspace) return FALSE; - if (fabs ((c0->v.c[0]) - (c1->v.c[0])) >= epsilon) return FALSE; - if (fabs ((c0->v.c[1]) - (c1->v.c[1])) >= epsilon) return FALSE; - if (fabs ((c0->v.c[2]) - (c1->v.c[2])) >= epsilon) return FALSE; - if ((c0->colorspace == &CMYK) && (fabs ((c0->v.c[3]) - (c1->v.c[3])) >= epsilon)) return FALSE; + match &= profileMatches( icc, other.icc ); - return TRUE; + return match; +} + +static bool profileMatches( SVGICCColor const* first, SVGICCColor const* second ) { + bool match = false; + if ( !first && !second ) { + match = true; + } else { + match = first && second + && (first->colorProfile == second->colorProfile) + && (first->colors.size() == second->colors.size()); + if ( match ) { + for ( guint i = 0; i < first->colors.size(); i++ ) { + match &= (fabs(first->colors[i] - second->colors[i]) < PROFILE_EPSILON); + } + } + } + return match; } /** * Sets RGB values and colorspace in color. - * \pre color != NULL && 0 <={r,g,b}<=1 + * \pre 0 <={r,g,b}<=1 */ -void -sp_color_set_rgb_float(SPColor *color, float r, float g, float b) +void SPColor::set( float r, float g, float b ) { - g_return_if_fail(color != NULL); g_return_if_fail(r >= 0.0); g_return_if_fail(r <= 1.0); g_return_if_fail(g >= 0.0); @@ -119,80 +138,35 @@ sp_color_set_rgb_float(SPColor *color, float r, float g, float b) g_return_if_fail(b >= 0.0); g_return_if_fail(b <= 1.0); - color->colorspace = &RGB; - color->v.c[0] = r; - color->v.c[1] = g; - color->v.c[2] = b; - color->v.c[3] = 0; + // TODO clear icc if set? + v.c[0] = r; + v.c[1] = g; + v.c[2] = b; } /** * Converts 32bit value to RGB floats and sets color. - * \pre color != NULL */ -void -sp_color_set_rgb_rgba32(SPColor *color, guint32 value) +void SPColor::set( guint32 value ) { - g_return_if_fail (color != NULL); - - color->colorspace = &RGB; - color->v.c[0] = (value >> 24) / 255.0F; - color->v.c[1] = ((value >> 16) & 0xff) / 255.0F; - color->v.c[2] = ((value >> 8) & 0xff) / 255.0F; - color->v.c[3] = 0; -} - -/** - * Sets CMYK values and colorspace in color. - * \pre color != NULL && 0 <={c,m,y,k}<=1 - */ -void -sp_color_set_cmyk_float(SPColor *color, float c, float m, float y, float k) -{ - g_return_if_fail(color != NULL); - g_return_if_fail(c >= 0.0); - g_return_if_fail(c <= 1.0); - g_return_if_fail(m >= 0.0); - g_return_if_fail(m <= 1.0); - g_return_if_fail(y >= 0.0); - g_return_if_fail(y <= 1.0); - g_return_if_fail(k >= 0.0); - g_return_if_fail(k <= 1.0); - - color->colorspace = &CMYK; - color->v.c[0] = c; - color->v.c[1] = m; - color->v.c[2] = y; - color->v.c[3] = k; + // TODO clear icc if set? + v.c[0] = (value >> 24) / 255.0F; + v.c[1] = ((value >> 16) & 0xff) / 255.0F; + v.c[2] = ((value >> 8) & 0xff) / 255.0F; } /** * Convert SPColor with integer alpha value to 32bit RGBA value. - * \pre color != NULL && alpha < 256 + * \pre alpha < 256 */ -guint32 -sp_color_get_rgba32_ualpha(SPColor const *color, guint32 alpha) +guint32 SPColor::toRGBA32( gint alpha ) const { - guint32 rgba; - - g_return_val_if_fail (color != NULL, 0x0); g_return_val_if_fail (alpha <= 0xff, 0x0); - if (color->colorspace == &RGB) { - rgba = SP_RGBA32_U_COMPOSE(SP_COLOR_F_TO_U(color->v.c[0]), - SP_COLOR_F_TO_U(color->v.c[1]), - SP_COLOR_F_TO_U(color->v.c[2]), - alpha); - } else { - float rgb[3]; - rgb[0] = rgb[1] = rgb[2] = 0.0; - sp_color_get_rgb_floatv (color, rgb); - rgba = SP_RGBA32_U_COMPOSE(SP_COLOR_F_TO_U(rgb[0]), - SP_COLOR_F_TO_U(rgb[1]), - SP_COLOR_F_TO_U(rgb[2]), - alpha); - } - + guint32 rgba = SP_RGBA32_U_COMPOSE( SP_COLOR_F_TO_U(v.c[0]), + SP_COLOR_F_TO_U(v.c[1]), + SP_COLOR_F_TO_U(v.c[2]), + alpha ); return rgba; } @@ -200,16 +174,41 @@ sp_color_get_rgba32_ualpha(SPColor const *color, guint32 alpha) * Convert SPColor with float alpha value to 32bit RGBA value. * \pre color != NULL && 0 <= alpha <= 1 */ -guint32 -sp_color_get_rgba32_falpha(SPColor const *color, float alpha) +guint32 SPColor::toRGBA32( gdouble alpha ) const { - g_return_val_if_fail(color != NULL, 0x0); g_return_val_if_fail(alpha >= 0.0, 0x0); g_return_val_if_fail(alpha <= 1.0, 0x0); - return sp_color_get_rgba32_ualpha(color, SP_COLOR_F_TO_U(alpha)); + return toRGBA32( static_cast(SP_COLOR_F_TO_U(alpha)) ); } +std::string SPColor::toString() const +{ + CSSOStringStream css; + + std::string result; + char tmp[64] = {0}; + + sp_svg_write_color(tmp, sizeof(tmp), toRGBA32(0x0ff)); + css << tmp; + + if ( icc ) { + if ( !css.str().empty() ) { + css << " "; + } + css << "icc-color(" << icc->colorProfile; + for (vector::const_iterator i(icc->colors.begin()), + iEnd(icc->colors.end()); + i != iEnd; ++i) { + css << ", " << *i; + } + css << ')'; + } + + return css.str(); +} + + /** * Fill rgb float array with values from SPColor. * \pre color != NULL && rgb != NULL && rgb[0-2] is meaningful @@ -220,17 +219,9 @@ sp_color_get_rgb_floatv(SPColor const *color, float *rgb) g_return_if_fail (color != NULL); g_return_if_fail (rgb != NULL); - if (color->colorspace == &RGB) { - rgb[0] = color->v.c[0]; - rgb[1] = color->v.c[1]; - rgb[2] = color->v.c[2]; - } else if (color->colorspace == &CMYK) { - sp_color_cmyk_to_rgb_floatv(rgb, - color->v.c[0], - color->v.c[1], - color->v.c[2], - color->v.c[3]); - } + rgb[0] = color->v.c[0]; + rgb[1] = color->v.c[1]; + rgb[2] = color->v.c[2]; } /** @@ -243,17 +234,10 @@ sp_color_get_cmyk_floatv(SPColor const *color, float *cmyk) g_return_if_fail (color != NULL); g_return_if_fail (cmyk != NULL); - if (color->colorspace == &CMYK) { - cmyk[0] = color->v.c[0]; - cmyk[1] = color->v.c[1]; - cmyk[2] = color->v.c[2]; - cmyk[3] = color->v.c[3]; - } else if (color->colorspace == &RGB) { - sp_color_rgb_to_cmyk_floatv(cmyk, - color->v.c[0], - color->v.c[1], - color->v.c[2]); - } + sp_color_rgb_to_cmyk_floatv( cmyk, + color->v.c[0], + color->v.c[1], + color->v.c[2] ); } /* Plain mode helpers */ @@ -291,7 +275,7 @@ sp_color_rgb_to_hsv_floatv (float *hsv, float r, float g, float b) if (hsv[0] < 0) hsv[0] += 1.0; } - else + else hsv[0] = 0.0; } @@ -468,4 +452,4 @@ sp_color_cmyk_to_rgb_floatv (float *rgb, float c, float m, float y, float k) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :