From bdcec99e706ccb2af0600bce67b7ade6e0abf348 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 26 Jan 2009 23:17:42 -0800 Subject: [PATCH] Finish adjustment of tick positions for pixel-snapping. This is the final step of adjusting the axis ranges so that the ticks aligne nicely with integer pixel boundaries. Notably we don't round the ticks at all while drawing them---instead we only adjust the axis ranges so that when we draw the ticks at their numerical positions they will look good. --- acre.c | 64 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/acre.c b/acre.c index 6a4728b..6d1262a 100644 --- a/acre.c +++ b/acre.c @@ -17,6 +17,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#define _ISOC99_SOURCE /* for round() */ +#define _XOPEN_SOURCE 500 + #include "acre.h" #include "xmalloc.h" @@ -304,13 +307,31 @@ _expand_range (double data_range, int pixel_size) return data_range * pixel_step / floor (pixel_step); } +/* Setup a transformation in acre->cr such that data values plotted + * will appear where they should within the chart. + */ +static void +_set_transform_to_data_space (acre_t *acre) +{ + cairo_t *cr = acre->cr; + + cairo_translate (cr, + acre->chart.x, + acre->chart.y + acre->chart.height); + cairo_scale (cr, + acre->chart.width / (acre->x_axis.max - acre->x_axis.min), + - acre->chart.height /(acre->y_axis.max - acre->y_axis.min)); + cairo_translate (cr, -acre->x_axis.min, -acre->y_axis.min); +} + static void _compute_axis_ranges (acre_t *acre) { unsigned int d, i; acre_data_t *data; - double x_range, new_x_range; - double y_range, new_y_range; + double x_range, new_x_range, x_adjust; + double y_range, new_y_range, y_adjust; + cairo_t *cr = acre->cr; /* First, simply find the extrema of the data. */ for (d = 0; d < acre->num_data; d++) { @@ -343,23 +364,28 @@ _compute_axis_ranges (acre_t *acre) acre->y_axis.min -= (new_y_range - y_range) / 2.0; acre->y_axis.max += (new_y_range - y_range) / 2.0; -} -/* Setup a transformation in acre->cr such that data values plotted - * will appear where they should within the chart. - */ -static void -_set_transform_to_data_space (acre_t *acre) -{ - cairo_t *cr = acre->cr; + /* Finally, we also translate the axis ranges slightly so that the + * ticks land on half-integer device-pixel positions. + */ + cairo_save (cr); + { + _set_transform_to_data_space (acre); - cairo_translate (cr, - acre->chart.x, - acre->chart.y + acre->chart.height); - cairo_scale (cr, - acre->chart.width / (acre->x_axis.max - acre->x_axis.min), - - acre->chart.height /(acre->y_axis.max - acre->y_axis.min)); - cairo_translate (cr, -acre->x_axis.min, -acre->y_axis.min); + x_adjust = 0.0; + y_adjust = 0.0; + cairo_user_to_device (cr, &x_adjust, &y_adjust); + x_adjust = (round (x_adjust + 0.5) - 0.5) - x_adjust; + y_adjust = (round (y_adjust + 0.5) - 0.5) - y_adjust; + cairo_device_to_user_distance (cr, &x_adjust, &y_adjust); + + acre->x_axis.min -= x_adjust; + acre->x_axis.max -= x_adjust; + + acre->y_axis.min -= y_adjust; + acre->y_axis.max -= y_adjust; + } + cairo_restore (cr); } static void @@ -418,7 +444,7 @@ _draw_frame_and_ticks (acre_t *acre) { cairo_identity_matrix (cr); cairo_rel_line_to (cr, 0, 0.5); - cairo_rel_line_to (cr, 0, -ACRE_TICK_SIZE); + cairo_rel_line_to (cr, 0, -ACRE_TICK_SIZE-0.5); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); } @@ -434,7 +460,7 @@ _draw_frame_and_ticks (acre_t *acre) { cairo_identity_matrix (cr); cairo_rel_line_to (cr, -0.5, 0); - cairo_rel_line_to (cr, ACRE_TICK_SIZE, 0); + cairo_rel_line_to (cr, ACRE_TICK_SIZE+0.5, 0); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); } -- 2.43.0