From a3e3b4a20d1635ea6b16e278d76aca35b9be9016 Mon Sep 17 00:00:00 2001 From: erg Date: Mon, 21 Nov 2005 21:25:40 +0000 Subject: [PATCH] Add support for color namespaces; add Brewer color data --- lib/common/colorprocs.h | 1 + lib/common/colxlate.c | 94 ++++++++++++++++++++++++++++++++++++++--- lib/common/emit.c | 4 ++ 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/lib/common/colorprocs.h b/lib/common/colorprocs.h index 68f9f163d..468098daa 100644 --- a/lib/common/colorprocs.h +++ b/lib/common/colorprocs.h @@ -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); diff --git a/lib/common/colxlate.c b/lib/common/colxlate.c index d08b9a990..10e5b50a1 100644 --- a/lib/common/colxlate.c +++ b/lib/common/colxlate.c @@ -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; +} diff --git a/lib/common/emit.c b/lib/common/emit.c index 9bd39fea3..34d9ad2b2 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -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; -- 2.40.0