diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp
index 51d68717e96d083f1106ad112a9e0bc1e9ca500b..7d43b68eef18d75c2e82c6f7d4e967ceb1f2ee95 100644 (file)
--- a/src/svg/svg-color.cpp
+++ b/src/svg/svg-color.cpp
# include "config.h"
#endif
-#include "svg-color.h"
-#include "svg-icc-color.h"
+#include <cstdlib>
+#include <cstdio> // sprintf
+#include <cstring>
+#include <string>
#include <cassert>
#include <math.h>
#include <glib/gmem.h>
+#include <glib.h> // g_assert
#include <glib/gmessages.h>
#include <glib/gstrfuncs.h>
#include <glib/ghash.h>
#include <glib/gutils.h>
-#include <cstdio> // sprintf
#include <errno.h>
+
#include "strneq.h"
+#include "preferences.h"
+#include "svg-color.h"
+#include "svg-icc-color.h"
+#include "svg-device-color.h"
+
+#if ENABLE_LCMS
+#include <lcms.h>
+#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 {
@@ -235,22 +252,22 @@ internal_sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def)
*end_ptr = str + i;
}
} else if (strneq(str, "rgb(", 4)) {
- gboolean hasp, hasd;
+ bool hasp, hasd;
gchar *s, *e;
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,9 +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 != ')') {
* 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);
strcpy(buf, src);
}
- assert(sp_svg_read_color(buf, 0xff) == (rgb24 << 8));
+ // assert(sp_svg_read_color(buf, 0xff) == (rgb24 << 8));
}
/**
{
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 *
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;i<count; i++){
+ color_in[i] = (guchar) ((((gdouble)icc->colors[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;
@@ -466,48 +529,188 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor
if ( good ) {
str += 10;
-
- while ( *str && !g_ascii_isspace(*str) && *str!= ',' && *str != ')' ) {
- if ( dest ) {
- dest->colorProfile += *str;
- }
+ while ( g_ascii_isspace(*str) ) {
str++;
}
- while ( g_ascii_isspace(*str) || *str == ',' ) {
- str++;
+
+ if ( !g_ascii_isalpha(*str)
+ && ( !(0x080 & *str) )
+ && (*str != '_')
+ && (*str != ':') ) {
+ // Name must start with a certain type of character
+ good = false;
+ } else {
+ while ( g_ascii_isdigit(*str) || g_ascii_isalpha(*str)
+ || (*str == '-') || (*str == ':') || (*str == '_') || (*str == '.') ) {
+ if ( dest ) {
+ dest->colorProfile += *str;
+ }
+ str++;
+ }
+ while ( g_ascii_isspace(*str) || *str == ',' ) {
+ str++;
+ }
}
}
- while ( good && *str && *str != ')' ) {
- if ( g_ascii_isdigit(*str) || *str == '.' ) {
- gchar* endPtr = 0;
- gdouble dbl = g_ascii_strtod( str, &endPtr );
- if ( !errno ) {
- if ( dest ) {
- dest->colors.push_back( dbl );
+ if ( good ) {
+ 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++;
}
- str = endPtr;
} else {
- good = false;
break;
}
+ }
+ }
- while ( good && 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 ( good ) {
+ if ( end_ptr ) {
+ *end_ptr = str;
+ }
+ } else {
+ if ( dest ) {
+ dest->colorProfile.clear();
+ dest->colors.clear();
+ }
+ }
+
+ 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++