From: Carl Worth Date: Tue, 3 Feb 2009 16:00:17 +0000 (-0800) Subject: Select N colors from HSV color space. X-Git-Url: https://git.cworth.org/git?p=acre;a=commitdiff_plain;h=b58094819fb79d0d7e30ff57ddfdb7c3926302c5 Select N colors from HSV color space. This is as opposed to the three hard-coded RGB primaries which we had before. --- diff --git a/acre.c b/acre.c index 35d0541..bda8e81 100644 --- a/acre.c +++ b/acre.c @@ -47,6 +47,12 @@ typedef struct _acre_axis { double max; } acre_axis_t; +typedef struct _acre_color { + double red; + double green; + double blue; +} acre_color_t; + struct _acre { char *title; acre_axis_t x_axis; @@ -59,7 +65,8 @@ struct _acre { /* Data for drawing. */ cairo_t *cr; PangoFontDescription *font; - struct { double r; double g; double b;} colors[3]; + acre_color_t *colors; + int colors_size; int num_colors; /* Total size including labels. */ @@ -92,6 +99,14 @@ acre_create (void) acre->data_size = 0; acre->num_data = 0; + acre->cr = NULL; + acre->font = NULL; + acre->colors = NULL; + acre->num_colors = 0; + + acre->width = 0; + acre->height = 0; + acre->chart.x = 0; acre->chart.y = 0; acre->chart.width = 0; @@ -115,6 +130,8 @@ acre_destroy (acre_t *acre) free (acre->data); + free (acre->colors); + free (acre); } @@ -500,24 +517,76 @@ _compute_axis_ranges (acre_t *acre) cairo_restore (cr); } +static void +_acre_color_from_hsv (acre_color_t *color, + double hue, + double saturation, + double value) +{ + double f, p, q, t; + int hmod6; + + hmod6 = (int) floor (hue / 60) % 6; + f = hue / 60 - floor (hue / 60); + p = value * (1 - saturation); + q = value * (1 - f * saturation); + t = value * (1 - (1 - f) * saturation); + + switch (hmod6) { + case 0: + color->red = value; + color->green = t; + color->blue = p; + break; + case 1: + color->red = q; + color->green = value; + color->blue = p; + break; + case 2: + color->red = p; + color->green = value; + color->blue = t; + break; + case 3: + color->red = p; + color->green = q; + color->blue = value; + break; + case 4: + color->red = t; + color->green = p; + color->blue = value; + break; + case 5: + color->red = value; + color->green = p; + color->blue = q; + break; + } +} + static void _choose_colors (acre_t *acre) { - /* XXX: Should choose N, equally-spaced colors from a perceptually - * linear space here. */ - acre->num_colors = 3; + double hue, saturation, value; + int i; - acre->colors[0].r = 1; - acre->colors[0].g = 0; - acre->colors[0].b = 0; + acre->num_colors = acre->num_data; - acre->colors[1].r = 0; - acre->colors[1].g = 1; - acre->colors[1].b = 0; + if (acre->num_colors > acre->colors_size) { + acre->colors_size = acre->num_colors; + acre->colors = xrealloc (acre->colors, + acre->colors_size * sizeof (acre_color_t)); + } - acre->colors[2].r = 0; - acre->colors[2].g = 0; - acre->colors[2].b = 1; + saturation = 1.0; + value = 0.7; + for (i = 0; i < acre->num_colors; i++) { + hue = 360 * (double) i / acre->num_colors; + _acre_color_from_hsv (&acre->colors[i], + hue, saturation, value); + } } static void @@ -536,9 +605,9 @@ _draw_data (acre_t *acre) for (d = 0; d < acre->num_data; d++) { int color = d % acre->num_colors; cairo_set_source_rgb (cr, - acre->colors[color].r, - acre->colors[color].g, - acre->colors[color].b); + acre->colors[color].red, + acre->colors[color].green, + acre->colors[color].blue); data = acre->data[d]; cairo_new_path (cr); for (i = 0; i < data->num_points; i++) { @@ -680,13 +749,14 @@ _draw_legend (acre_t *acre) cairo_translate (cr, ACRE_LEGEND_PAD, ACRE_LEGEND_PAD); for (i = 0; i < acre->num_data; i++) { - cairo_move_to (cr, 0, ACRE_FONT_SIZE / 2 + 0.5); - cairo_rel_line_to (cr, ACRE_LEGEND_LINE_SIZE, 0); + cairo_rectangle (cr, + 0, ACRE_LEGEND_LINE_SIZE / 2, + ACRE_LEGEND_LINE_SIZE, ACRE_LEGEND_LINE_SIZE / 2); cairo_set_source_rgb (cr, - acre->colors[i % acre->num_colors].r, - acre->colors[i % acre->num_colors].g, - acre->colors[i % acre->num_colors].b); - cairo_stroke (cr); + acre->colors[i % acre->num_colors].red, + acre->colors[i % acre->num_colors].green, + acre->colors[i % acre->num_colors].blue); + cairo_fill (cr); layout = _create_layout (acre, acre->data[i]->name); cairo_move_to (cr, ACRE_LEGEND_LINE_SIZE + ACRE_LEGEND_PAD, 0);