xrchart_geometry_init (cairo_t *cr, struct xrchart_geometry *geom,
double width, double length)
{
- /* Set default chartetry. */
+ /* Set default chart geometry. */
geom->axis[SCALE_ORDINATE].data_max = 0.900 * length;
- geom->axis[SCALE_ABSCISSA].data_max = 0.800 * width;
geom->axis[SCALE_ORDINATE].data_min = 0.120 * length;
+
geom->axis[SCALE_ABSCISSA].data_min = 0.150 * width;
- geom->abscissa_top = 0.070 * length;
- geom->ordinate_right = 0.120 * width;
+ geom->axis[SCALE_ABSCISSA].data_max = 0.800 * width;
+ geom->abscissa_bottom = 0.070 * length;
+ geom->ordinate_left = 0.050 * width;
geom->title_bottom = 0.920 * length;
geom->legend_left = 0.810 * width;
geom->legend_right = width;
}
/* Draw a tick mark at position
- If label is non zero, then print it at the tick mark
+ If label is non null, then print it at the tick mark
*/
+static void
+draw_tick_internal (cairo_t *cr, const struct xrchart_geometry *geom,
+ enum tick_orientation orientation,
+ double position,
+ const char *s);
+
void
draw_tick (cairo_t *cr, const struct xrchart_geometry *geom,
enum tick_orientation orientation,
double position,
const char *label, ...)
+{
+ va_list ap;
+ char *s;
+ va_start (ap, label);
+ s = xvasprintf (label, ap);
+
+ if (fabs (position) < DBL_EPSILON)
+ position = 0;
+
+ draw_tick_internal (cr, geom, orientation, position, s);
+ free (s);
+ va_end (ap);
+}
+
+
+static void
+draw_tick_internal (cairo_t *cr, const struct xrchart_geometry *geom,
+ enum tick_orientation orientation,
+ double position,
+ const char *s)
{
const int tickSize = 10;
double x, y;
cairo_stroke (cr);
- if (label != NULL)
+ if (s != NULL)
{
- va_list ap;
- char *s;
-
cairo_move_to (cr, x, y);
- va_start (ap, label);
- s = xvasprintf (label, ap);
if (orientation == SCALE_ABSCISSA)
xrchart_label (cr, 'c', 't', geom->font_size, s);
else if (orientation == SCALE_ORDINATE)
cairo_rel_move_to (cr, 0, 10);
xrchart_label (cr, 'r', 'c', geom->font_size, s);
}
- free (s);
- va_end (ap);
}
}
xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom,
double smin, double smax, int ticks, enum tick_orientation orient)
{
- double y;
+ int s;
const double tick_interval =
chart_rounded_tick ((smax - smin) / (double) ticks);
- geom->axis[orient].max = ceil (smax / tick_interval) * tick_interval;
- geom->axis[orient].min = floor (smin / tick_interval) * tick_interval;
+ int upper = ceil (smax / tick_interval);
+ int lower = floor (smin / tick_interval);
- geom->axis[orient].scale = (fabs (geom->axis[orient].data_max - geom->axis[orient].data_min)
- / fabs (geom->axis[orient].max - geom->axis[orient].min));
+ geom->axis[orient].max = tick_interval * upper;
+ geom->axis[orient].min = tick_interval * lower;
- /*
- geom->axis[orient].scale = (fabs (geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min)
+ geom->axis[orient].scale = (fabs (geom->axis[orient].data_max - geom->axis[orient].data_min)
/ fabs (geom->axis[orient].max - geom->axis[orient].min));
- */
-
- for (y = geom->axis[orient].min; y <= geom->axis[orient].max; y += tick_interval)
- draw_tick (cr, geom, orient,
- (y - geom->axis[orient].min) * geom->axis[orient].scale, "%g", y);
+ for (s = 0 ; s < upper - lower; ++s)
+ {
+ double pos = (s + lower) * tick_interval;
+ draw_tick (cr, geom, orient,
+ s * tick_interval * geom->axis[orient].scale, "%g", pos);
+ }
}
void
xrchart_write_xlabel (cairo_t *cr, const struct xrchart_geometry *geom,
const char *label)
{
- cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->abscissa_top);
+ cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->abscissa_bottom);
xrchart_label (cr, 'l', 't', geom->font_size, label);
}
const char *label)
{
cairo_save (cr);
- cairo_translate (cr, -geom->axis[SCALE_ORDINATE].data_min, -geom->ordinate_right);
- cairo_move_to (cr, 0, 0);
+ cairo_translate (cr, geom->ordinate_left, geom->axis[SCALE_ORDINATE].data_min);
cairo_rotate (cr, M_PI / 2.0);
+
xrchart_label (cr, 'l', 'x', geom->font_size, label);
cairo_restore (cr);
}