X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsvg%2Fsvg-color.cpp;h=7d43b68eef18d75c2e82c6f7d4e967ceb1f2ee95;hb=dedcb6c735b9199a15b5895b96e091a344dff187;hp=6bbcdd8846c7db93a4bd0e15d3fdcd0f185dbfed;hpb=c87d0307348fcfdc65b6b4ab6999a3cb0de2431f;p=inkscape.git diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp index 6bbcdd884..7d43b68ee 100644 --- a/src/svg/svg-color.cpp +++ b/src/svg/svg-color.cpp @@ -17,18 +17,35 @@ # include "config.h" #endif -#include "svg-color.h" -#include "svg-icc-color.h" +#include +#include // sprintf +#include +#include #include #include #include +#include // g_assert #include #include #include #include -#include // sprintf #include + #include "strneq.h" +#include "preferences.h" +#include "svg-color.h" +#include "svg-icc-color.h" +#include "svg-device-color.h" + +#if ENABLE_LCMS +#include +#include "color.h" +#include "color-profile.h" +#include "document.h" +#include "inkscape.h" +#include "profile-manager.h" +#endif // ENABLE_LCMS + using std::sprintf; struct SPSVGColor { @@ -240,17 +257,17 @@ internal_sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def) gdouble r, g, b; s = (gchar *) str + 4; - hasp = FALSE; - hasd = FALSE; + hasp = false; + hasd = false; r = g_ascii_strtod(s, &e); if (s == e) return def; s = e; if (*s == '%') { - hasp = TRUE; + hasp = true; s += 1; } else { - hasd = TRUE; + hasd = true; } while (*s && g_ascii_isspace(*s)) s += 1; if (*s != ',') return def; @@ -260,10 +277,10 @@ internal_sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def) if (s == e) return def; s = e; if (*s == '%') { - hasp = TRUE; + hasp = true; s += 1; } else { - hasd = TRUE; + hasd = true; } while (*s && g_ascii_isspace(*s)) s += 1; if (*s != ',') return def; @@ -273,10 +290,10 @@ internal_sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def) if (s == e) return def; s = e; if (*s == '%') { - hasp = TRUE; + hasp = true; s += 1; } else { - hasd = TRUE; + hasd = true; } while(*s && g_ascii_isspace(*s)) s += 1; if (*s != ')') { @@ -334,9 +351,9 @@ sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 dfl) * this check wrapper. */ gchar const *end = str; guint32 const ret = internal_sp_svg_read_color(str, &end, dfl); - assert(ret == dfl && end == str + assert(((ret == dfl) && (end == str)) || (((ret & 0xff) == 0) - && str < end)); + && (str < end))); if (str < end) { gchar *buf = (gchar *) g_malloc(end + 1 - str); memcpy(buf, str, end - str); @@ -409,7 +426,7 @@ rgb24_to_css(char *const buf, unsigned const rgb24) strcpy(buf, src); } - assert(sp_svg_read_color(buf, 0xff) == (rgb24 << 8)); + // assert(sp_svg_read_color(buf, 0xff) == (rgb24 << 8)); } /** @@ -424,8 +441,13 @@ sp_svg_write_color(gchar *buf, unsigned const buflen, guint32 const rgba32) { g_assert(8 <= buflen); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned const rgb24 = rgba32 >> 8; - rgb24_to_css(buf, rgb24); + if (prefs->getBool("/options/svgoutput/usenamedcolors")) { + rgb24_to_css(buf, rgb24); + } else { + g_snprintf(buf, buflen, "#%06x", rgb24); + } } static GHashTable * @@ -442,7 +464,47 @@ sp_svg_create_color_hash() return colors; } +#if ENABLE_LCMS +//helper function borrowed from src/widgets/sp-color-icc-selector.cpp: +void getThings( DWORD space, gchar const**& namers, gchar const**& tippies, guint const*& scalies ); + +void icc_color_to_sRGB(SVGICCColor* icc, guchar* r, guchar* g, guchar* b){ + guchar color_out[4]; + guchar color_in[4]; + if (icc){ +g_message("profile name: %s", icc->colorProfile.c_str()); + Inkscape::ColorProfile* prof = SP_ACTIVE_DOCUMENT->profileManager->find(icc->colorProfile.c_str()); + if ( prof ) { + cmsHTRANSFORM trans = prof->getTransfToSRGB8(); + if ( trans ) { + gchar const** names = 0; + gchar const** tips = 0; + guint const* scales = 0; + getThings( prof->getColorSpace(), names, tips, scales ); + + guint count = _cmsChannelsOf( prof->getColorSpace() ); + if (count>4) count=4; //do we need it? Should we allow an arbitrary number of color values? Or should we limit to a maximum? (max==4?) + for (guint i=0;icolors[i])*256.0) * (gdouble)scales[i]); +g_message("input[%d]: %d",i, color_in[i]); + } + + cmsDoTransform( trans, color_in, color_out, 1 ); +g_message("transform to sRGB done"); + } + *r = color_out[0]; + *g = color_out[1]; + *b = color_out[2]; + } + } +} +#endif //ENABLE_LCMS +/* + * Some discussion at http://markmail.org/message/bhfvdfptt25kgtmj + * Allowed ASCII first characters: ':', 'A'-'Z', '_', 'a'-'z' + * Allowed ASCII remaining chars add: '-', '.', '0'-'9', + */ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor* dest ) { bool good = true; @@ -472,11 +534,14 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor } if ( !g_ascii_isalpha(*str) - && ( !(0x080 & *str) ) ) { + && ( !(0x080 & *str) ) + && (*str != '_') + && (*str != ':') ) { // Name must start with a certain type of character good = false; } else { - while ( g_ascii_isdigit(*str) || g_ascii_islower(*str) || (*str == '-') ) { + while ( g_ascii_isdigit(*str) || g_ascii_isalpha(*str) + || (*str == '-') || (*str == ':') || (*str == '_') || (*str == '.') ) { if ( dest ) { dest->colorProfile += *str; } @@ -517,7 +582,7 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor while ( g_ascii_isspace(*str) ) { str++; } - good &= *str == ')'; + good &= (*str == ')'); } } @@ -535,6 +600,117 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor return good; } + +bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest ) +{ + return sp_svg_read_icc_color(str, NULL, dest); +} + +bool sp_svg_read_device_color( gchar const *str, gchar const **end_ptr, SVGDeviceColor* dest) +{ + bool good = true; + unsigned int max_colors; + + if ( end_ptr ) { + *end_ptr = str; + } + if ( dest ) { + dest->colors.clear(); + } + + if ( !str ) { + // invalid input + good = false; + } else { + while ( g_ascii_isspace(*str) ) { + str++; + } + + dest->type = DEVICE_COLOR_INVALID; + if (strneq( str, "device-gray(", 12 )){ + dest->type = DEVICE_GRAY; + max_colors=1; + str += 12; + } + + if (strneq( str, "device-rgb(", 11 )){ + dest->type = DEVICE_RGB; + max_colors=3; + str += 11; + } + + if (strneq( str, "device-cmyk(", 12 )){ + dest->type = DEVICE_CMYK; + max_colors=4; + str += 12; + } + + if (strneq( str, "device-nchannel(", 16 )){ + dest->type = DEVICE_NCHANNEL; + max_colors=0; + str += 16; + } + + if ( dest->type != DEVICE_COLOR_INVALID ) { + while ( g_ascii_isspace(*str) ) { + str++; + } + + while ( *str && *str != ')' ) { + if ( g_ascii_isdigit(*str) || *str == '.' || *str == '-' || *str == '+') { + gchar* endPtr = 0; + gdouble dbl = g_ascii_strtod( str, &endPtr ); + if ( !errno ) { + if ( dest ) { + dest->colors.push_back( dbl ); + } + str = endPtr; + } else { + good = false; + break; + } + + while ( g_ascii_isspace(*str) || *str == ',' ) { + str++; + } + } else { + break; + } + } + } + + // We need to have ended on a closing parenthesis + if ( good ) { + while ( g_ascii_isspace(*str) ) { + str++; + } + good &= (*str == ')'); + } + } + + if ( dest->colors.size() == 0) good=false; + if ( dest->type != DEVICE_NCHANNEL && (dest->colors.size() != max_colors)) good=false; + + if ( good ) { + if ( end_ptr ) { + *end_ptr = str; + } + } else { + if ( dest ) { + dest->type = DEVICE_COLOR_INVALID; + dest->colors.clear(); + } + } + + return good; +} + + +bool sp_svg_read_device_color( gchar const *str, SVGDeviceColor* dest) +{ + return sp_svg_read_device_color(str, NULL, dest); +} + /* Local Variables: mode:c++