diff mbox

[i-g-t,13/16] plot: Add axis titles

Message ID 1436186144-19665-14-git-send-email-damien.lespiau@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lespiau, Damien July 6, 2015, 12:35 p.m. UTC
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(-)
diff mbox

Patch

diff --git a/lib/igt_plot.c b/lib/igt_plot.c
index 763c000..b3d4bc7 100644
--- a/lib/igt_plot.c
+++ b/lib/igt_plot.c
@@ -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);
+}
diff --git a/lib/igt_plot.h b/lib/igt_plot.h
index 49d5819..dce21e7 100644
--- a/lib/igt_plot.h
+++ b/lib/igt_plot.h
@@ -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__ */
diff --git a/lib/tests/igt_plot.c b/lib/tests/igt_plot.c
index 81946f3..a178fbf 100644
--- a/lib/tests/igt_plot.c
+++ b/lib/tests/igt_plot.c
@@ -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");