Code

Add a version of the reader that indicates the end of the color specification.
authorpjrm <pjrm@users.sourceforge.net>
Mon, 3 Apr 2006 05:11:59 +0000 (05:11 +0000)
committerpjrm <pjrm@users.sourceforge.net>
Mon, 3 Apr 2006 05:11:59 +0000 (05:11 +0000)
src/svg/svg-color.cpp
src/svg/svg-color.h

index b81cb2660c78e307937a4b6555f022c0f8d2d0c3..33b73f0d4c44ed9e51ab91dc1e3a285a3edcee5e 100644 (file)
@@ -20,6 +20,7 @@
 #include "svg-color.h"
 #include <cassert>
 #include <math.h>
+#include <glib/gmem.h>
 #include <glib/gmessages.h>
 #include <glib/gstrfuncs.h>
 #include <glib/ghash.h>
@@ -189,10 +190,15 @@ static SPSVGColor const sp_svg_color_named[] = {
 static GHashTable *sp_svg_create_color_hash();
 
 guint32
-sp_svg_read_color(gchar const *str, guint32 def)
+sp_svg_read_color(gchar const *str, guint32 const dfl)
+{
+    return sp_svg_read_color(str, NULL, dfl);
+}
+
+static guint32
+internal_sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def)
 {
     static GHashTable *colors = NULL;
-    gchar c[32];
     guint32 val = 0;
 
     if (str == NULL) return def;
@@ -223,6 +229,9 @@ sp_svg_read_color(gchar const *str, guint32 def)
             /* must be either 3 or 6 digits. */
             return def;
         }
+        if (end_ptr) {
+            *end_ptr = str + i;
+        }
     } else if (strneq(str, "rgb(", 4)) {
         gboolean hasp, hasd;
         gchar *s, *e;
@@ -266,6 +275,11 @@ sp_svg_read_color(gchar const *str, guint32 def)
         } else {
             hasd = TRUE;
         }
+        while(*s && g_ascii_isspace(*s)) s += 1;
+        if (*s != ')') {
+            return def;
+        }
+        ++s;
         if (hasp && hasd) return def;
         if (hasp) {
             val = (guint) floor(CLAMP(r, 0.0, 100.0) * 2.559999) << 24;
@@ -276,14 +290,18 @@ sp_svg_read_color(gchar const *str, guint32 def)
             val |= ((guint) CLAMP(g, 0, 255) << 16);
             val |= ((guint) CLAMP(b, 0, 255) << 8);
         }
+        if (end_ptr) {
+            *end_ptr = s;
+        }
         return val;
     } else {
         gint i;
         if (!colors) {
             colors = sp_svg_create_color_hash();
         }
+        gchar c[32];
         for (i = 0; i < 31; i++) {
-            if (str[i] == ';') {
+            if (str[i] == ';' || g_ascii_isspace(str[i])) {
                 c[i] = '\0';
                 break;
             }
@@ -298,11 +316,38 @@ sp_svg_read_color(gchar const *str, guint32 def)
         } else {
             return def;
         }
+        if (end_ptr) {
+            *end_ptr = str + i;
+        }
     }
 
     return (val << 8);
 }
 
+guint32
+sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 dfl)
+{
+    /* I've been rather hurried in editing the above to add support for end_ptr, so I'm adding
+     * this check wrapper. */
+    gchar const *end = str;
+    guint32 const ret = internal_sp_svg_read_color(str, &end, dfl);
+    assert(ret == dfl && end == str
+           || (((ret & 0xff) == 0)
+               && str < end));
+    if (str < end) {
+        gchar *buf = (gchar *) g_malloc(end + 1 - str);
+        memcpy(buf, str, end - str);
+        buf[end - str] = '\0';
+        gchar const *buf_end = buf;
+        guint32 const check = internal_sp_svg_read_color(buf, &buf_end, 1);
+        assert(check == ret
+               && buf_end - buf == end - str);
+        g_free(buf);
+    }
+    return ret;
+}
+
+
 /**
  * Converts an RGB colour expressed in form 0x00rrggbb to a CSS/SVG representation of that colour.
  * The result is valid even in SVG Tiny or non-SVG CSS.
index beab1a50cb6a3288b1a415abdaf87e29841fd1f1..1c48b87de187015c3316a4d384c21c7dce63f390 100644 (file)
@@ -3,7 +3,8 @@
 
 #include <glib/gtypes.h>
 
-unsigned int sp_svg_read_color(gchar const *str, unsigned int dfl);
+guint32 sp_svg_read_color(gchar const *str, unsigned int dfl);
+guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def);
 void sp_svg_write_color(char *buf, unsigned int buflen, unsigned int rgba32);