/* Data for drawing. */
cairo_t *cr;
PangoFontDescription *font;
+ struct { double r; double g; double b;} colors[3];
+ int num_colors;
/* Total size including labels. */
int width;
#define ACRE_TICK_MINOR_SIZE 3
#define ACRE_X_TICK_VALUE_PAD 2
#define ACRE_Y_TICK_VALUE_PAD 4
+#define ACRE_LEGEND_PAD 4
+#define ACRE_LEGEND_LINE_SIZE 10
static PangoLayout *
_create_layout (acre_t *acre, const char *text)
cairo_restore (cr);
}
+static void
+_choose_colors (acre_t *acre)
+{
+ /* XXX: Should choose N, equally-spaced colors from a perceptually
+ * linear space here. */
+ acre->num_colors = 3;
+
+ acre->colors[0].r = 1;
+ acre->colors[0].g = 0;
+ acre->colors[0].b = 0;
+
+ acre->colors[1].r = 0;
+ acre->colors[1].g = 1;
+ acre->colors[1].b = 0;
+
+ acre->colors[2].r = 0;
+ acre->colors[2].g = 0;
+ acre->colors[2].b = 1;
+}
+
static void
_draw_data (acre_t *acre)
{
cairo_t *cr = acre->cr;
unsigned int d, i;
acre_data_t *data;
-#define NUM_COLORS 3
- struct {
- double r;
- double g;
- double b;
- } colors [NUM_COLORS] = {
- {1, 0, 0},
- {0, 1, 0},
- {0, 0, 1}
- };
cairo_save (cr);
_set_transform_to_data_space (acre);
for (d = 0; d < acre->num_data; d++) {
- int color = d % NUM_COLORS;
+ int color = d % acre->num_colors;
cairo_set_source_rgb (cr,
- colors[color].r,
- colors[color].g,
- colors[color].b);
+ acre->colors[color].r,
+ acre->colors[color].g,
+ acre->colors[color].b);
data = acre->data[d];
cairo_new_path (cr);
for (i = 0; i < data->num_points; i++) {
cairo_restore (cr);
}
+static void
+_draw_legend (acre_t *acre)
+{
+ PangoLayout *layout;
+ int label_width, max_label_width = 0;
+ int width, height;
+ unsigned int i;
+ cairo_t *cr = acre->cr;
+
+ cairo_save (cr);
+
+ for (i = 0; i < acre->num_data; i++) {
+ layout = _create_layout (acre, acre->data[i]->name);
+ pango_layout_get_pixel_size (layout, &label_width, NULL);
+ _destroy_layout (layout);
+ if (label_width > max_label_width)
+ max_label_width = label_width;
+ }
+
+ width = ACRE_LEGEND_PAD + ACRE_LEGEND_LINE_SIZE + ACRE_LEGEND_PAD +
+ max_label_width + ACRE_LEGEND_PAD;
+ height = ACRE_LEGEND_PAD +
+ acre->num_data * (ACRE_FONT_SIZE + ACRE_LEGEND_PAD);
+
+ cairo_translate (cr, acre->chart.x, acre->chart.y);
+
+ cairo_translate (cr,
+ acre->chart.width - ACRE_LEGEND_PAD - width,
+ ACRE_LEGEND_PAD);
+
+ cairo_rectangle (cr, -0.5, -0.5, width + 1.0, height + 1.0);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+
+ 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_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);
+
+ layout = _create_layout (acre, acre->data[i]->name);
+ cairo_move_to (cr, ACRE_LEGEND_LINE_SIZE + ACRE_LEGEND_PAD, 0);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ _show_layout (cr, layout);
+
+ cairo_translate (cr, 0, ACRE_LEGEND_PAD + ACRE_FONT_SIZE);
+ }
+
+ cairo_restore (cr);
+}
+
static void
_draw_frame_and_ticks (acre_t *acre)
{
cairo_set_source_rgb (cr, 1, 1, 1);
+ _choose_colors (acre);
+
/* We compute the axis ranges before doing label layout so that we
* can account for the width of the y-axis value labels. */
_compute_axis_ranges (acre);
_draw_data (acre);
+ if (acre->num_data > 1)
+ _draw_legend (acre);
+
_draw_frame_and_ticks (acre);
}