]> granicus.if.org Git - graphviz/commitdiff
Add support for color namespaces; add Brewer color data
authorerg <devnull@localhost>
Mon, 21 Nov 2005 21:25:40 +0000 (21:25 +0000)
committererg <devnull@localhost>
Mon, 21 Nov 2005 21:25:40 +0000 (21:25 +0000)
lib/common/colorprocs.h
lib/common/colxlate.c
lib/common/emit.c

index 68f9f163dd699cc3ba7558193471b01d7526e486..468098daa04e27faee956335743d79d733bb256d 100644 (file)
@@ -21,6 +21,7 @@
 extern "C" {
 #endif
 
+extern void setColorScheme (char* s);
 extern int colorxlate(char *str, gvcolor_t * color, color_type_t target_type);
 extern char *canontoken(char *str);
 
index d08b9a990fa5d0be39d908908392647186b5a0c8..10e5b50a1b080afafbed3062fba2431a0d58b393 100644 (file)
@@ -22,6 +22,9 @@
 #include "color.h"
 #include "colorprocs.h"
 #include "colortbl.h"
+#include "memory.h"
+
+static char* colorscheme;
 
 static void hsv2rgb(double h, double s, double v,
                        double *r, double *g, double *b)
@@ -143,14 +146,14 @@ char *canontoken(char *str)
     len = strlen(str);
     if (len >= allocated) {
        allocated = len + 1 + 10;
-       canon = realloc(canon, allocated);
+       canon = grealloc(canon, allocated);
        if (!canon)
            return NULL;
     }
     q = (unsigned char *) canon;
     while ((c = *p++)) {
-       if (isalnum(c) == FALSE)
-           continue;
+       /* if (isalnum(c) == FALSE) */
+           /* continue; */
        if (isupper(c))
            c = tolower(c);
        *q++ = c;
@@ -159,6 +162,79 @@ char *canontoken(char *str)
     return (char*)canon;
 }
 
+/* fullColor:
+ * Return "/prefix/str"
+ */
+static char* fullColor (char* prefix, char* str)
+{
+    static char *fulls;
+    static int allocated;
+    int len = strlen (prefix) + strlen (str) + 3;
+
+    if (len >= allocated) {
+       allocated = len + 10;
+       fulls = grealloc(fulls, allocated);
+    }
+    sprintf (fulls, "/%s/%s", prefix, str);
+    return fulls;
+}
+
+/* resolveColor:
+ * Resolve input color str allowing color scheme namespaces.
+ *  1) No initial / => 
+ *          if colorscheme is defined and no "X11", return /colorscheme/str
+ *          else return str
+ *  2) One initial / => return str+1
+ *  3) Two initial /'s =>
+ *       a) If colorscheme is defined and not "X11", return /colorscheme/(str+2)
+ *       b) else return (str+2)
+ *  4) Two /'s, not both initial => return str.
+ *
+ * Note that 1), 2), and 3b) allow the default X11 color scheme. 
+ *
+ * In other words,
+ *   xxx => /colorscheme/xxx     if colorscheme is defined and not "X11"
+ *   xxx => xxx                  otherwise
+ *   /xxx => xxx
+ *   /X11/yyy => yyy
+ *   /xxx/yyy => /xxx/yyy
+ *   //yyy => /colorscheme/yyy   if colorscheme is defined and not "X11"
+ *   //yyy => yyy                otherwise
+ * 
+ * At present, no other error checking is done. For example, 
+ * yyy could be "". This will be caught later.
+ */
+
+#define DFLT_SCHEME "X11/"      /* Must have final '/' */
+#define DFLT_SCHEME_LEN ((sizeof(DFLT_SCHEME)-1)/sizeof(char))
+#define ISNONDFLT(s) ((s) && *(s) && strncasecmp(DFLT_SCHEME, s, DFLT_SCHEME_LEN-1))
+
+static char* resolveColor (char* str)
+{
+    char* s;
+    char* ss;   /* second slash */
+    char* c2;   /* second char */
+
+    if (*str == '/') {   /* if begins with '/' */
+       c2 = str+1;
+        if ((ss = strchr(c2, '/'))) {  /* if has second '/' */
+           if (*c2 == '/') {    /* if second '/' is second character */
+                   /* Do not compare against final '/' */
+               if (ISNONDFLT(colorscheme))
+                   s = fullColor (colorscheme, c2+1);
+               else
+                   s = c2+1;
+           }
+           else if (strncasecmp(DFLT_SCHEME, c2, DFLT_SCHEME_LEN)) s = str;
+           else s = ss + 1;
+       }
+       else s = c2;
+    }
+    else if (ISNONDFLT(colorscheme)) s = fullColor (colorscheme, str);
+    else s = str;
+    return canontoken(s);
+}
+
 int colorxlate(char *str, gvcolor_t * color, color_type_t target_type)
 {
     static hsbcolor_t *last;
@@ -234,7 +310,7 @@ int colorxlate(char *str, gvcolor_t * color, color_type_t target_type)
        len = strlen((char*)p);
        if (len >= allocated) {
            allocated = len + 1 + 10;
-           canon = realloc(canon, allocated);
+           canon = grealloc(canon, allocated);
            if (! canon) {
                rc = COLOR_MALLOC_FAIL;
                return rc;
@@ -298,7 +374,7 @@ int colorxlate(char *str, gvcolor_t * color, color_type_t target_type)
     }
 
     /* test for known color name (generic, not renderer specific known names) */
-    fake.name = canontoken(str);
+    fake.name = resolveColor(str);
     if (!fake.name)
        return COLOR_MALLOC_FAIL;
     if ((last == NULL)
@@ -396,3 +472,11 @@ int colorxlate(char *str, gvcolor_t * color, color_type_t target_type)
     }
     return rc;
 }
+
+/* setColorScheme:
+ * Set current color scheme for resolving names.
+ */
+void setColorScheme (char* s)
+{
+    colorscheme = s;
+}
index 9bd39fea3f02b14052a86355792398d81f84f61a..34d9ad2b2a41ea1efc955fd26ff9dbf760712fa9 100644 (file)
@@ -614,6 +614,7 @@ static void emit_node(GVJ_t * job, node_t * n)
        if (url || explicit_tooltip)
            gvrender_begin_anchor(job, url, tooltip, target);
 
+       setColorScheme (agget (n, "colorscheme"));
        gvrender_begin_context(job);
        ND_shape(n)->fns->codefn(job, n);
        ND_state(n) = gvc->viewNum;
@@ -765,6 +766,7 @@ void emit_edge_graphics(GVJ_t * job, edge_t * e)
                return;
        }
     }
+    setColorScheme (agget (e, "colorscheme"));
     if (ED_spl(e)) {
        scale = late_double(e, E_arrowsz, 1.0, 0.0);
        color = late_string(e, E_color, "");
@@ -1298,6 +1300,7 @@ void emit_graph(GVJ_t * job, graph_t * g)
 
        /* iterate pages */
        for (firstpage(job); validpage(job); nextpage(job)) {
+           setColorScheme (agget (g, "colorscheme"));
            setup_page(job, g);
            if (boxf_overlap(job->clip, job->pageBox))
                emit_view(job,g,flags);
@@ -1433,6 +1436,7 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
        if (url || explicit_tooltip)
            gvrender_begin_anchor(job, url, tooltip, target);
 
+       setColorScheme (agget (sg, "colorscheme"));
        gvrender_begin_context(job);
        filled = FALSE;
        istyle = 0;