]> granicus.if.org Git - graphviz/commitdiff
canonicalize input color strings
authorellson <devnull@localhost>
Fri, 26 Sep 2008 17:41:05 +0000 (17:41 +0000)
committerellson <devnull@localhost>
Fri, 26 Sep 2008 17:41:05 +0000 (17:41 +0000)
lib/inkpot/inkpot.h
lib/inkpot/inkpot_scheme.c
lib/inkpot/inkpot_structs.h
lib/inkpot/test.c

index 6076b3fb4c73f4d1271ae126555c65fb81a86ede..8961501537b5aa63a5759b17bd5d51c623a11d6d 100644 (file)
@@ -30,55 +30,42 @@ typedef enum {
     INKPOT_FAIL
 } inkpot_status_t;
 
-/* opaque inkpot struct */
 typedef struct inkpot_s inkpot_t;
 
-/* writer discipline */
 typedef struct inkpot_disc_s {
     size_t (*out_writer) (void *out_closure, const char *data, size_t length);
     size_t (*err_writer) (void *err_closure, const char *data, size_t length);
 } inkpot_disc_t;
 
-/* malloc an inkpot. */
-extern inkpot_t *inkpot_init                 ( void );
 
-/* Discplines default to stdout, stderr.  Use this to provide other writers */
+
+extern inkpot_t *      inkpot_init           ( void );
+extern void            inkpot_destroy        ( inkpot_t *inkpot );
+
 extern inkpot_status_t inkpot_disciplines     ( inkpot_t *inkpot, inkpot_disc_t disc, void *out_closure, void *err_closure );
 
-/* The list of schemes for color input interpretation, NULL scheme terminates */
 extern inkpot_status_t inkpot_schemes        ( inkpot_t *inkpot, const char *scheme, ... );
-/* The scheme for color output representation, */
 extern inkpot_status_t inkpot_translate       ( inkpot_t *inkpot, const char *scheme );
 
-/* set inkpot color by name as interpeted by the current schemes */
 extern inkpot_status_t inkpot_set            ( inkpot_t *inkpot, const char *color );
-/* set inkpot color to the default (from the first scheme specified) */
 extern inkpot_status_t inkpot_set_default     ( inkpot_t *inkpot );
-/* set inkpot color by value, which may or may not have a name in the current or any schemes */
 extern inkpot_status_t inkpot_set_rgba       ( inkpot_t *inkpot, double rgba[4] );
 extern inkpot_status_t inkpot_set_hsva       ( inkpot_t *inkpot, double hsva[4] );
 
-/* get inkpot color name in the translation scheme, or for colors without a name in the translated scheme,
- * set NULL and return INKPOT_COLOR_NONAME */
 extern inkpot_status_t inkpot_get            ( inkpot_t *inkpot, const char **color );
-
-/* get inkpot color value in various formats */
+extern inkpot_status_t inkpot_get_rgba_i      ( inkpot_t *inkpot, unsigned int rgba[4] );
 extern inkpot_status_t inkpot_get_rgba       ( inkpot_t *inkpot, double rgba[4] );
 extern inkpot_status_t inkpot_get_hsva       ( inkpot_t *inkpot, double hsva[4] );
 extern inkpot_status_t inkpot_get_cmyk       ( inkpot_t *inkpot, double cmyk[4] );
 extern inkpot_status_t inkpot_get_index              ( inkpot_t *inkpot, unsigned int *index );
 
-/* output the current color to out_writer (default stdout) */
-/* returns INKPOT_COLOR_NONAME if it converted the color to a hex numeric string value */
 extern inkpot_status_t inkpot_write          ( inkpot_t *inkpot );
 
-/* debugging and error functions that oput to the err_writer (default stderr) */
 extern inkpot_status_t inkpot_debug_schemes   ( inkpot_t *inkpot );
 extern inkpot_status_t inkpot_debug_names     ( inkpot_t *inkpot );
-extern inkpot_status_t inkpot_debug_names_out ( inkpot_t *inkpot );
+extern inkpot_status_t inkpot_debug_out_names ( inkpot_t *inkpot );
 extern inkpot_status_t inkpot_debug_values    ( inkpot_t *inkpot );
 
-/* write the most recent inkpot status to the err writer */
 extern inkpot_status_t inkpot_error          ( inkpot_t *inkpot );
 
 #ifdef __cplusplus
index 6b79821726243e8c5fa47c3de45c0928580ebda1..fa55a0374aaee96eb329940749a964b9ad5cc50d 100644 (file)
@@ -49,15 +49,25 @@ inkpot_t *inkpot_init ( void )
    
     inkpot = malloc(sizeof(inkpot_t));
     if (inkpot) {
+       inkpot->canon = NULL;
+       inkpot->canon_alloc = 0;
+
        inkpot->disc = inkpot_default_disc;
        inkpot->out_closure = stdout;
        inkpot->err_closure = stderr;
+
        rc = inkpot_clear ( inkpot );
         assert ( rc == INKPOT_SUCCESS );
     }
     return inkpot;
 }
 
+void inkpot_destroy ( inkpot_t *inkpot )
+{
+    free(inkpot->canon);
+    free(inkpot);
+}
+
 inkpot_status_t inkpot_disciplines ( inkpot_t *inkpot, inkpot_disc_t disc, void *out_closure, void *err_closure )
 {
     inkpot->disc = disc;
@@ -67,6 +77,7 @@ inkpot_status_t inkpot_disciplines ( inkpot_t *inkpot, inkpot_disc_t disc, void
     return ((inkpot->status = INKPOT_SUCCESS));
 }
 
+/* FIXME - this needs to work with UTF-8 strings */
 static int string_cmpf (const char *k, const char *b)
 {
     for ( ; *k && *b; k++, b++) {
@@ -414,57 +425,69 @@ inkpot_status_t inkpot_set_hsva ( inkpot_t *inkpot, double hsva[4] )
 
 inkpot_status_t inkpot_set( inkpot_t *inkpot, const char *color )
 {
-    static char *canon;
-    static int allocated;
-    char *q, c;
+    char *q;
     const char *p;
     int len, index;
-    unsigned int rgba;
+    unsigned int rgba, c;
     double hsva[4];
     inkpot_status_t rc = INKPOT_COLOR_UNKNOWN;
 
     if (!color)
         return ((inkpot->status = INKPOT_COLOR_UNKNOWN));
 
-    if (*color == '#') {
-        if (sscanf(color, "#%8x", &rgba))
+    len = strlen(color);
+    if (len >= inkpot->canon_alloc) {
+       inkpot->canon_alloc = len + 1 + 20;
+       inkpot->canon = realloc(inkpot->canon, inkpot->canon_alloc);
+       if (! inkpot->canon)
+            return ((inkpot->status = INKPOT_MALLOC_FAIL));
+    }
+
+    /* canonicalize input string */
+    for (p = color, q = inkpot->canon;
+               (c = *p) && ( c == ' ' || c == '\t' );
+               p++) { }; /* remove leading ws */
+
+    /* change ',' to ' ' */
+    /* FIXME - is this UTF-8 safe ? */
+    while ((c = *p++)) {
+       if (c == ',')
+           c = ' ';
+       *q++ = c;
+    }
+    *q = '\0';
+
+    if (*inkpot->canon == '#') {
+        if (sscanf(inkpot->canon, "#%8x", &rgba))
            rc = inkpot_set_RGBA(inkpot, &rgba);
 
         if (rc != INKPOT_SUCCESS) {
-            if (sscanf(color, "#%6x", &rgba)) {
+            if (sscanf(inkpot->canon, "#%6x", &rgba)) {
                rgba = (rgba << SZB_RED) | MAX_RED;
                rc = inkpot_set_RGBA(inkpot, &rgba);
             }
        } 
     }
 
-    if ((rc != INKPOT_SUCCESS) || ((c = *color) == '.') || isdigit(c)) {
-       len = strlen(color);
-       if (len >= allocated) {
-           allocated = len + 1 + 10;
-           canon = realloc(canon, allocated);
-           if (! canon)
-                return ((inkpot->status = INKPOT_MALLOC_FAIL));
-        }
-       p = color;
-        q = canon;
-        while ((c = *p++)) {
-           if (c == ',')
-               c = ' ';
-           *q++ = c;
-        }
-        *q = '\0';
+    if ((rc != INKPOT_SUCCESS) || ((c = *inkpot->canon) == '.') || isdigit(c)) {
        hsva[3] = 1.0;
-        if (sscanf(canon, "%lf%lf%lf%lf", &hsva[0], &hsva[1], &hsva[2], &hsva[3]) >= 3)
+        if (sscanf(inkpot->canon, "%lf%lf%lf%lf", &hsva[0], &hsva[1], &hsva[2], &hsva[3]) >= 3)
            rc = inkpot_set_hsva(inkpot, hsva);
     }
 
     if (rc != INKPOT_SUCCESS)
-        if (sscanf(color, "%d", &index) == 1)
+        if (sscanf(inkpot->canon, "%d", &index) == 1)
             rc = inkpot_set_index(inkpot, index);
 
-    if (rc != INKPOT_SUCCESS)
-        rc = inkpot_set_name(inkpot, color);
+    if (rc != INKPOT_SUCCESS) {
+       /* remove embedded ws and convert to lower case*/
+        for (p = q = inkpot->canon;
+               (c = *p) && ! ( c == ' ' || c == '\t' ); p++) {
+           *q++ = tolower(c);
+       };
+       *q = '\0';
+        rc = inkpot_set_name(inkpot, inkpot->canon);
+    }
 
     return rc;
 }
@@ -528,6 +551,21 @@ static inkpot_status_t inkpot_get_RGBA ( inkpot_t *inkpot, RGBA *rgba )
     return ((inkpot->status = INKPOT_SUCCESS));
 }
 
+inkpot_status_t inkpot_get_rgba_i ( inkpot_t *inkpot, unsigned int rgba[4] )
+{
+    inkpot_status_t rc;
+    RGBA myrgba;
+
+    rc = inkpot_get_RGBA( inkpot, &myrgba );
+    if (rc == INKPOT_SUCCESS) {
+        rgba[3] = myrgba & MSK_RED; myrgba >>= SZB_RED;
+        rgba[2] = myrgba & MSK_RED; myrgba >>= SZB_RED;
+        rgba[1] = myrgba & MSK_RED; myrgba >>= SZB_RED;
+        rgba[0] = myrgba & MSK_RED;
+    }
+    return rc;
+}
+
 inkpot_status_t inkpot_get_rgba ( inkpot_t *inkpot, double rgba[4] )
 {
     inkpot_status_t rc;
@@ -543,6 +581,7 @@ inkpot_status_t inkpot_get_rgba ( inkpot_t *inkpot, double rgba[4] )
     }
     return rc;
 }
+
 inkpot_status_t inkpot_get_hsva ( inkpot_t *inkpot, double hsva[4] )
 {
     inkpot_status_t rc;
@@ -713,7 +752,7 @@ inkpot_status_t inkpot_debug_names( inkpot_t *inkpot )
     return inkpot_debug_names_schemes(inkpot, scheme_bits, scheme_index);
 }
 
-inkpot_status_t inkpot_debug_names_out( inkpot_t *inkpot )
+inkpot_status_t inkpot_debug_out_names( inkpot_t *inkpot )
 {
     MSK_SCHEMES_NAME scheme_bits = inkpot->out_scheme_bit;
     inkpot_scheme_index_t *scheme_index = inkpot->out_scheme_index;
index 691204c2bbb2bed6be65067d0764d09e73f8a5f3..7a701c00c84fe92773d29a5f8af83adabaf28670 100644 (file)
@@ -132,6 +132,9 @@ struct inkpot_s {           /* The Ink Pot */
            *name,              /* The current input name, or NULL. */
            *out_name;          /* The current output name, or NULL. */
 
+       char *canon;            /* malloc'ed buffer for canonicalizing input color */
+       int canon_alloc;
+
        inkpot_disc_t disc;     /* writers and closures for out and err */
        void *out_closure, *err_closure;
 
index f34710a89dc63d71530abdd697243a0adfd71183..7b1119a3f5b2caf2356b092f2ba2d6b832e6e822 100644 (file)
@@ -64,25 +64,26 @@ int main (int argc, char *argv[])
         }
     }
 
-/* ------------- */
+#if 0
 
     inkpot_debug_schemes(inkpot);
     
     inkpot_debug_names(inkpot);
 
-    inkpot_debug_names_out(inkpot);
+    inkpot_debug_out_names(inkpot);
 
     inkpot_debug_values(inkpot);
 
-/* ------------- */
+#endif
 
-    fprintf(stdout, "%s ", color);
+    fprintf(stdout, "%s ", color); /* ' ' after %s so it doesn't crash on NULL */
     rc = inkpot_set(inkpot, color);
     if (rc == INKPOT_COLOR_UNKNOWN) {
-        fprintf(stdout, "(unknown)\n text: ");
+        fprintf(stdout, "(unknown)");
        rc = inkpot_set_default(inkpot);
        assert (rc == INKPOT_SUCCESS);
     }
+    fprintf(stdout, "\n text: ");
 
     rc = inkpot_write(inkpot);
     assert (rc == INKPOT_SUCCESS || rc == INKPOT_COLOR_NONAME);
@@ -102,5 +103,6 @@ int main (int argc, char *argv[])
     fprintf(stdout, " cmyk: %.3f,%.3f,%.3f,%.3f\n",
                cmyk[0], cmyk[1], cmyk[2], cmyk[3]);
 
+    inkpot_destroy(inkpot);
     return 0;
 }