@@ -422,6 +422,7 @@ typedef struct {
char *text;
cairo_text_extents_t extents;
igt_align_t halign, valign;
+ double rotation;
} igt_label_t;
typedef struct {
@@ -430,9 +431,10 @@ typedef struct {
double title_font_size;
double tick_label_font_size;
igt_box_t plot_area;
- igt_label_t title;
+ igt_label_t title, x_title, y_title;
igt_label_t *x_tick_labels;
igt_label_t *y_tick_labels;
+ double y_tick_width, x_tick_height;
} flush_t;
static double plot_length(igt_plot_t *plot, double percent)
@@ -476,15 +478,22 @@ igt_plot_draw_text(igt_plot_t *plot, double x, double y, igt_label_t *label)
if (plot->debug) {
cairo_set_source_rgb(plot->cr, 1.0, 0.0, 0.0);
- cairo_move_to(plot->cr, x, y);
- cairo_rectangle(plot->cr, x, y,
+ cairo_translate(plot->cr, x, y);
+ if (label->rotation)
+ cairo_rotate(plot->cr, label->rotation);
+ cairo_rectangle(plot->cr, 0, 0,
label->extents.width, -label->extents.height);
cairo_stroke(plot->cr);
+ cairo_identity_matrix(plot->cr);
}
cairo_set_source_rgb(plot->cr, 0.0, 0.0, 0.0);
cairo_move_to(plot->cr, x, y);
+ if (label->rotation)
+ cairo_rotate(plot->cr, label->rotation);
cairo_show_text(plot->cr, label->text);
+ if (label->rotation)
+ cairo_identity_matrix(plot->cr);
}
static void igt_plot_draw_background(igt_plot_t *plot, flush_t *flush)
@@ -521,6 +530,30 @@ static void igt_plot_draw_title(igt_plot_t *plot, flush_t *flush)
igt_plot_draw_text(plot, SNAP(x), SNAP(y), &flush->title);
}
+static void igt_plot_draw_axis_title(igt_plot_t *plot, igt_plot_axis_t *axis,
+ igt_label_t *label, flush_t *flush)
+{
+ igt_box_t *area = &flush->plot_area;
+ double x, y;
+
+ if (!plot->title)
+ return;
+
+ cairo_set_font_size(plot->cr, flush->title_font_size);
+ cairo_set_source_rgb(plot->cr, 0.0, 0.0, 0.0);
+
+ if (axis->side == IGT_SIDE_BOTTOM) {
+ x = area->x1 + (area->x2 - area->x1 ) / 2.0;
+ y = area->y2 + flush->x_tick_height + flush->inner_padding;
+ igt_plot_draw_text(plot, SNAP(x), SNAP(y), label);
+ } else {
+ x = area->x1 - 2 * flush->tick_label_padding -
+ flush->y_tick_width;
+ y = area->y1 + (area->y2 - area->y1) / 2.0;
+ igt_plot_draw_text(plot, SNAP(x), SNAP(y), label);
+ }
+}
+
static void igt_plot_draw_grid(igt_plot_t *plot, flush_t *flush)
{
unsigned int i, n_ticks;
@@ -661,6 +694,9 @@ static void igt_plot_draw_axis(igt_plot_t *plot, flush_t *flush)
igt_box_t *area = &flush->plot_area;
const double tick_length = plot_length(plot, 0.01);
+ igt_plot_draw_axis_title(plot, &plot->x_axis, &flush->x_title, flush);
+ igt_plot_draw_axis_title(plot, &plot->y_axis, &flush->y_title, flush);
+
igt_plot_draw_grid(plot, flush);
/* X-axis */
@@ -695,6 +731,33 @@ static void igt_plot_layout_title(igt_plot_t *plot, flush_t *flush)
label->valign = IGT_ALIGN_BOTTOM;
cairo_set_font_size(plot->cr, flush->title_font_size);
cairo_text_extents(plot->cr, label->text, &label->extents);
+
+ flush->plot_area.y1 += flush->title.extents.height +
+ flush->inner_padding;
+}
+
+static void igt_plot_layout_axis_title(igt_plot_t *plot, igt_plot_axis_t *axis,
+ igt_label_t *label, flush_t *flush)
+{
+ if (!axis->title)
+ return;
+
+ label->text = axis->title;
+ cairo_set_font_size(plot->cr, flush->title_font_size);
+ cairo_text_extents(plot->cr, label->text, &label->extents);
+
+ if (axis->side == IGT_SIDE_BOTTOM) {
+ label->halign = IGT_ALIGN_CENTER;
+ label->valign = IGT_ALIGN_TOP;
+ flush->plot_area.y2 -= flush->x_title.extents.height +
+ flush->inner_padding;
+ } else {
+ label->halign = IGT_ALIGN_LEFT;
+ label->valign = IGT_ALIGN_CENTER;
+ label->rotation = -M_PI / 2;
+ flush->plot_area.x1 += flush->y_title.extents.height +
+ flush->inner_padding;
+ }
}
static void igt_plot_layout_tick_labels(igt_plot_t *plot,
@@ -731,7 +794,6 @@ static void igt_plot_layout_tick_labels(igt_plot_t *plot,
static void igt_plot_layout(igt_plot_t *plot, flush_t *flush)
{
const double outer_padding = 0.10;
- double max_width, max_height;
flush->inner_padding = plot_length(plot, 0.05);
flush->tick_label_padding = plot_length(plot, 0.02);
@@ -746,17 +808,19 @@ static void igt_plot_layout(igt_plot_t *plot, flush_t *flush)
/* plot title */
igt_plot_layout_title(plot, flush);
- flush->plot_area.y1 += flush->title.extents.height +
- flush->inner_padding;
+
+ /* axis titles */
+ igt_plot_layout_axis_title(plot, &plot->x_axis, &flush->x_title, flush);
+ igt_plot_layout_axis_title(plot, &plot->y_axis, &flush->y_title, flush);
/* measure tick labels and adjust the plot area */
cairo_set_font_size(plot->cr, flush->tick_label_font_size);
igt_plot_layout_tick_labels(plot, &plot->x_axis, flush->x_tick_labels,
- &max_height);
- flush->plot_area.y2 -= max_height - flush->tick_label_padding;
+ &flush->x_tick_height);
+ flush->plot_area.y2 -= flush->x_tick_height - flush->tick_label_padding;
igt_plot_layout_tick_labels(plot, &plot->y_axis, flush->y_tick_labels,
- &max_width);
- flush->plot_area.x1 += max_width + flush->tick_label_padding;
+ &flush->y_tick_width);
+ flush->plot_area.x1 += flush->y_tick_width + flush->tick_label_padding;
}
static void igt_plot_flush_init(igt_plot_t *plot, flush_t *flush)
@@ -801,3 +865,19 @@ void igt_plot_write(igt_plot_t *plot, const char *filename)
igt_plot_flush_fini(plot, &flush);
}
+
+/**
+ * igt_plot_axis_set_title:
+ * @axis: An #igt_plot_axis_t instance
+ * @title: An UTF-8 string
+ *
+ * Set a title for the plot.
+ */
+void igt_plot_axis_set_title(igt_plot_axis_t *axis, const char *title)
+{
+ free(axis->title);
+ axis->title = NULL;
+ if (!title)
+ return;
+ axis->title = strndup(title, 64);
+}
@@ -75,6 +75,7 @@ typedef struct {
/*< private >*/
igt_orientation_t orientation;
igt_side_t side;
+ char *title;
unsigned int n_ticks;
double min, max; /* range of the values on this axis */
} igt_plot_axis_t;
@@ -91,6 +92,8 @@ typedef struct {
/**
* igt_plot_t:
+ * @x_axis: X axis
+ * @y_axis: Y axis
*
* Draw nice plots!
*/
@@ -106,9 +109,12 @@ typedef struct {
unsigned int width, height;
char *title;
igt_trbl_t margin;
- igt_plot_axis_t x_axis, y_axis;
igt_plot_axis_t x_axis_top, y_axis_right;
+ /*< public >*/
+ igt_plot_axis_t x_axis, y_axis;
+
+ /*< private >*/
/* per draw command contexts */
igt_plot_ctx_t contexts[IGT_PLOT_MAX_PLOTS + 1];
unsigned int n_valid_contexts;
@@ -135,5 +141,6 @@ void igt_plot_set_color(igt_plot_t *plot,
void igt_plot_set_line_width(igt_plot_t *plot, double width);
void igt_plot_draw(igt_plot_t *plot, igt_vector_t *x, igt_vector_t *y);
void igt_plot_write(igt_plot_t *plot, const char *filename);
+void igt_plot_axis_set_title(igt_plot_axis_t *axis, const char *title);
#endif /* __IGT_PLOT_H__ */
@@ -84,6 +84,8 @@ static void test_simple_plot(void)
igt_plot_init(&plot, 800, 600);
igt_plot_set_title(&plot, "f(x) = sin(2?x)");
+ igt_plot_axis_set_title(&plot.x_axis, "x");
+ igt_plot_axis_set_title(&plot.y_axis, "f(x)");
igt_plot_set_color(&plot, 0.0, 0.0, 1.0, 1.0);
igt_plot_draw(&plot, x, y);
igt_plot_write(&plot, "test_simple_plot.png");
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> --- lib/igt_plot.c | 100 +++++++++++++++++++++++++++++++++++++++++++++------ lib/igt_plot.h | 9 ++++- lib/tests/igt_plot.c | 2 ++ 3 files changed, 100 insertions(+), 11 deletions(-)