char *title;
char *xtitle;
char *ytitle;
- int xdim, ydim;
+ unsigned int xdim, ydim;
struct graph_label *labels;
struct graph_label *tail;
int per_label_limit;
+ const char *font;
};
-struct graph *graph_new(int xdim, int ydim)
+void graph_set_size(struct graph *g, unsigned int xdim, unsigned int ydim)
+{
+ g->xdim = xdim;
+ g->ydim = ydim;
+}
+
+struct graph *graph_new(unsigned int xdim, unsigned int ydim, const char *font)
{
struct graph *g;
g = calloc(1, sizeof(*g));
- g->xdim = xdim;
- g->ydim = ydim;
+ graph_set_size(g, xdim, ydim);
g->per_label_limit = -1;
+ g->font = font;
+ if (!g->font)
+ g->font = "Sans";
return g;
}
}
}
-static void draw_centered_text(cairo_t *cr, double x, double y,
- double fontsize, const char *text)
+static void draw_aligned_text(struct graph *g, cairo_t *cr, double x, double y,
+ double fontsize, const char *text, int alignment)
{
+#define CENTERED 0
+#define LEFT_JUSTIFIED 1
+#define RIGHT_JUSTIFIED 2
+
+ double factor, direction;
cairo_text_extents_t extents;
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
+ switch(alignment) {
+ case CENTERED:
+ direction = -1.0;
+ factor = 0.5;
+ break;
+ case RIGHT_JUSTIFIED:
+ direction = -1.0;
+ factor = 1.0;
+ break;
+ case LEFT_JUSTIFIED:
+ default:
+ direction = 1.0;
+ factor = 1.0;
+ break;
+ }
+ cairo_select_font_face (cr, g->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, fontsize);
cairo_text_extents(cr, text, &extents);
- x = x - (extents.width / 2 + extents.x_bearing);
+ x = x + direction * (factor * extents.width + extents.x_bearing);
y = y - (extents.height / 2 + extents.y_bearing);
cairo_move_to(cr, x, y);
cairo_show_text(cr, text);
}
-static void draw_vertical_centered_text(cairo_t *cr, double x, double y,
- double fontsize, const char *text)
+static inline void draw_centered_text(struct graph *g, cairo_t *cr, double x, double y,
+ double fontsize, const char *text)
+{
+ draw_aligned_text(g, cr, x, y, fontsize, text, CENTERED);
+}
+
+static inline void draw_right_justified_text(struct graph *g, cairo_t *cr,
+ double x, double y,
+ double fontsize, const char *text)
+{
+ draw_aligned_text(g, cr, x, y, fontsize, text, RIGHT_JUSTIFIED);
+}
+
+static inline void draw_left_justified_text(struct graph *g, cairo_t *cr,
+ double x, double y,
+ double fontsize, const char *text)
+{
+ draw_aligned_text(g, cr, x, y, fontsize, text, LEFT_JUSTIFIED);
+}
+
+static void draw_vertical_centered_text(struct graph *g, cairo_t *cr, double x,
+ double y, double fontsize,
+ const char *text)
{
double sx, sy;
cairo_text_extents_t extents;
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_select_font_face(cr, g->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, fontsize);
cairo_text_extents(cr, text, &extents);
double *x1, double *y1, double *x2, double *y2)
{
cairo_set_source_rgb(cr, 0, 0, 0);
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, 0.8);
- cairo_move_to(cr, 0, 0);
- cairo_line_to(cr, 0, g->ydim);
- cairo_line_to(cr, g->xdim, g->ydim);
- cairo_line_to(cr, g->xdim, 0);
- cairo_line_to(cr, 0, 0);
-
- /* for now just set margins at 10% of width. This is not very good. */
- *x1 = g->xdim / 10.0;
- *x2 = 9.0 * *x1;
- *y1 = g->ydim / 10.0;
- *y2 = 9.0 * *y1;
+ *x1 = 0.15 * g->xdim;
+ *x2 = 0.95 * g->xdim;
+ *y1 = 0.10 * g->ydim;
+ *y2 = 0.90 * g->ydim;
cairo_move_to(cr, *x1, *y1);
cairo_line_to(cr, *x1, *y2);
cairo_line_to(cr, *x1, *y1);
cairo_stroke(cr);
- draw_centered_text(cr, g->xdim / 2, g->ydim / 20, 20.0, g->title);
- draw_centered_text(cr, g->xdim / 2, g->ydim * 0.97, 14.0, g->xtitle);
- draw_vertical_centered_text(cr, g->xdim * 0.02, g->ydim / 2, 14.0, g->ytitle);
+ draw_centered_text(g, cr, g->xdim / 2, g->ydim / 20, 20.0, g->title);
+ draw_centered_text(g, cr, g->xdim / 2, g->ydim * 0.97, 14.0, g->xtitle);
+ draw_vertical_centered_text(g, cr, g->xdim * 0.02, g->ydim / 2, 14.0, g->ytitle);
cairo_stroke(cr);
}
continue;
/* Draw tick mark */
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, 0.8);
cairo_move_to(cr, tx, y2);
cairo_line_to(cr, tx, y2 + (y2 - y1) * 0.03);
cairo_stroke(cr);
cairo_restore(cr);
/* draw tickmark label */
- draw_centered_text(cr, tx, y2 * 1.04, 12.0, tm[i].string);
+ draw_centered_text(g, cr, tx, y2 * 1.04, 12.0, tm[i].string);
cairo_stroke(cr);
}
cairo_restore(cr);
/* draw tickmark label */
- draw_centered_text(cr, x1 - (x2 - x1) * 0.04, ty, 12.0, tm[i].string);
+ draw_right_justified_text(g, cr, x1 - (x2 - x1) * 0.025, ty, 12.0, tm[i].string);
cairo_stroke(cr);
}
}
maxdata = find_max_data(bg->labels);
if (fabs(maxdata - mindata) < 1e-20) {
- draw_centered_text(cr,
+ draw_centered_text(bg, cr,
x1 + (x2 - x1) / 2.0,
y1 + (y2 - y1) / 2.0, 20.0, "No good data");
return;
label_offset = bg->xdim * 0.1 + space_per_label * (double) i + space_per_label * 0.1;
draw_bars(bg, cr, lb, label_offset, bar_width, mindata, maxdata);
// draw_centered_text(cr, label_offset + (bar_width / 2.0 + bar_width * 0.1), bg->ydim * 0.93,
- draw_centered_text(cr, x1 + space_per_label * (i + 0.5), bg->ydim * 0.93,
+ draw_centered_text(bg, cr, x1 + space_per_label * (i + 0.5), bg->ydim * 0.93,
12.0, lb->label);
i++;
}
double tmp, answer = 0.0;
struct graph_label *i;
struct graph_value *j;
+ int first = 1;
for (i = g->labels; i; i = i->next)
for (j = i->values; j; j = j->next) {
tmp = getvalue(j);
+ if (first) {
+ first = 0;
+ answer = tmp;
+ }
answer = cmp(tmp, answer);
}
return answer;
double tx, ty;
struct graph_label *i;
struct graph_value *j;
- int first = 1;
+ int good_data = 1, first = 1;
cairo_save(cr);
graph_draw_common(g, cr, &x1, &y1, &x2, &y2);
maxy = find_xy_value(g, gety, maxdouble);
if (fabs(maxx - minx) < 1e-20 || fabs(maxy - miny) < 1e-20) {
- draw_centered_text(cr,
- x1 + (x2 - x1) / 2.0,
- y1 + (y2 - y1) / 2.0, 20.0, "No good Data");
- return;
+ good_data = 0;
+ minx = 0.0;
+ miny = 0.0;
+ maxx = 10.0;
+ maxy = 100.0;
}
graph_draw_x_ticks(g, cr, x1, y1, x2, y2, minx, maxx, 10);
graph_draw_y_ticks(g, cr, x1, y1, x2, y2, miny, maxy, 10);
- cairo_set_line_width(cr, 2.5);
+ if (!good_data)
+ goto skip_data;
+
+ cairo_set_line_width(cr, 1.5);
for (i = g->labels; i; i = i->next) {
first = 1;
+ if (i->r < 0) /* invisible data */
+ continue;
cairo_set_source_rgb(cr, i->r, i->g, i->b);
for (j = i->values; j; j = j->next) {
tx = ((getx(j) - minx) / (maxx - minx)) * (x2 - x1) + x1;
}
cairo_stroke(cr);
}
+
+skip_data:
cairo_restore(cr);
+
}
static void gfree(void *f)
struct graph_label *i;
double r, g, b;
- r = fabs(red);
- g = fabs(green);
- b = fabs(blue);
-
- if (r > 1.0)
- r = 1.0;
- if (g > 1.0)
- g = 1.0;
- if (b > 1.0)
- b =1.0;
+ if (red < 0.0) { /* invisible color */
+ r = -1.0;
+ g = -1.0;
+ b = -1.0;
+ } else {
+ r = fabs(red);
+ g = fabs(green);
+ b = fabs(blue);
+
+ if (r > 1.0)
+ r = 1.0;
+ if (g > 1.0)
+ g = 1.0;
+ if (b > 1.0)
+ b =1.0;
+ }
for (i = gr->labels; i; i = i->next)
if (strcmp(i->label, label) == 0) {