+ if (prt_fctn == '\0') {
+ if (i == im->gdes_c - 1 || fill > im->ximg - 2 * border) {
+ /* just one legend item is left right or center */
+ switch (default_txtalign) {
+ case TXA_RIGHT:
+ prt_fctn = 'r';
+ break;
+ case TXA_CENTER:
+ prt_fctn = 'c';
+ break;
+ case TXA_JUSTIFIED:
+ prt_fctn = 'j';
+ break;
+ default:
+ prt_fctn = 'l';
+ break;
+ }
+ }
+ /* is it time to place the legends ? */
+ if (fill > im->ximg - 2 * border) {
+ if (leg_c > 1) {
+ /* go back one */
+ i--;
+ fill = fill_last;
+ leg_c--;
+ }
+ }
+ if (leg_c == 1 && prt_fctn == 'j') {
+ prt_fctn = 'l';
+ }
+ }
+
+
+ if (prt_fctn != '\0') {
+ leg_x = border;
+ if (leg_c >= 2 && prt_fctn == 'j') {
+ glue = (im->ximg - fill - 2 * border) / (leg_c - 1);
+ } else {
+ glue = 0;
+ }
+ if (prt_fctn == 'c')
+ leg_x = (im->ximg - fill) / 2.0;
+ if (prt_fctn == 'r')
+ leg_x = im->ximg - fill - border;
+ for (ii = mark; ii <= i; ii++) {
+ if (im->gdes[ii].legend[0] == '\0')
+ continue; /* skip empty legends */
+ im->gdes[ii].leg_x = leg_x;
+ im->gdes[ii].leg_y = leg_y;
+ leg_x +=
+ gfx_get_text_width(im, leg_x,
+ im->
+ text_prop
+ [TEXT_PROP_LEGEND].
+ font,
+ im->
+ text_prop
+ [TEXT_PROP_LEGEND].
+ size,
+ im->tabwidth, im->gdes[ii].legend)
+ + legspace[ii]
+ + glue;
+ }
+ leg_y_prev = leg_y;
+ if (im->extra_flags & FULL_SIZE_MODE) {
+ /* only add y space if there was text on the line */
+ if (leg_x > border || prt_fctn == 's')
+ leg_y -= im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ if (prt_fctn == 's')
+ leg_y += im->text_prop[TEXT_PROP_LEGEND].size;
+ } else {
+ if (leg_x > border || prt_fctn == 's')
+ leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ if (prt_fctn == 's')
+ leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
+ }
+ fill = 0;
+ leg_c = 0;
+ mark = ii;
+ }
+ }
+
+ if (im->extra_flags & FULL_SIZE_MODE) {
+ if (leg_y != leg_y_prev) {
+ *gY = leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ im->yorigin =
+ leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ }
+ } else {
+ im->yimg = leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 + border * 0.6;
+ }
+ free(legspace);
+ }
+ return 0;
+}
+
+/* create a grid on the graph. it determines what to do
+ from the values of xsize, start and end */
+
+/* the xaxis labels are determined from the number of seconds per pixel
+ in the requested graph */
+
+int calc_horizontal_grid(
+ image_desc_t
+ *im)
+{
+ double range;
+ double scaledrange;
+ int pixel, i;
+ int gridind = 0;
+ int decimals, fractionals;
+
+ im->ygrid_scale.labfact = 2;
+ range = im->maxval - im->minval;
+ scaledrange = range / im->magfact;
+ /* does the scale of this graph make it impossible to put lines
+ on it? If so, give up. */
+ if (isnan(scaledrange)) {
+ return 0;
+ }
+
+ /* find grid spaceing */
+ pixel = 1;
+ if (isnan(im->ygridstep)) {
+ if (im->extra_flags & ALTYGRID) {
+ /* find the value with max number of digits. Get number of digits */
+ decimals =
+ ceil(log10
+ (max(fabs(im->maxval), fabs(im->minval)) *
+ im->viewfactor / im->magfact));
+ if (decimals <= 0) /* everything is small. make place for zero */
+ decimals = 1;
+ im->ygrid_scale.gridstep =
+ pow((double) 10,
+ floor(log10(range * im->viewfactor / im->magfact))) /
+ im->viewfactor * im->magfact;
+ if (im->ygrid_scale.gridstep == 0) /* range is one -> 0.1 is reasonable scale */
+ im->ygrid_scale.gridstep = 0.1;
+ /* should have at least 5 lines but no more then 15 */
+ if (range / im->ygrid_scale.gridstep < 5 && im->ygrid_scale.gridstep >= 30 )
+ im->ygrid_scale.gridstep /= 10;
+ if (range / im->ygrid_scale.gridstep > 15)
+ im->ygrid_scale.gridstep *= 10;
+ if (range / im->ygrid_scale.gridstep > 5 ) {
+ im->ygrid_scale.labfact = 1;
+ if (range / im->ygrid_scale.gridstep > 8 || im->ygrid_scale.gridstep < 1.8 * im->text_prop[TEXT_PROP_AXIS].size )
+ im->ygrid_scale.labfact = 2;
+ } else {
+ im->ygrid_scale.gridstep /= 5;
+ im->ygrid_scale.labfact = 5;
+ }
+ fractionals =
+ floor(log10
+ (im->ygrid_scale.gridstep *
+ (double) im->ygrid_scale.labfact * im->viewfactor /
+ im->magfact));
+ if (fractionals < 0) { /* small amplitude. */
+ int len = decimals - fractionals + 1;
+
+ if (im->unitslength < len + 2)
+ im->unitslength = len + 2;
+ sprintf(im->ygrid_scale.labfmt,
+ "%%%d.%df%s", len,
+ -fractionals, (im->symbol != ' ' ? " %c" : ""));
+ } else {
+ int len = decimals + 1;
+
+ if (im->unitslength < len + 2)
+ im->unitslength = len + 2;
+ sprintf(im->ygrid_scale.labfmt,
+ "%%%d.0f%s", len, (im->symbol != ' ' ? " %c" : ""));
+ }
+ } else { /* classic rrd grid */
+ for (i = 0; ylab[i].grid > 0; i++) {
+ pixel = im->ysize / (scaledrange / ylab[i].grid);
+ gridind = i;
+ if (pixel >= 5)
+ break;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (pixel * ylab[gridind].lfac[i] >=
+ 1.8 * im->text_prop[TEXT_PROP_AXIS].size) {
+ im->ygrid_scale.labfact = ylab[gridind].lfac[i];
+ break;
+ }
+ }
+
+ im->ygrid_scale.gridstep = ylab[gridind].grid * im->magfact;
+ }
+ } else {
+ im->ygrid_scale.gridstep = im->ygridstep;
+ im->ygrid_scale.labfact = im->ylabfact;
+ }
+ return 1;
+}
+
+int draw_horizontal_grid(
+ image_desc_t
+ *im)
+{
+ int i;
+ double scaledstep;
+ char graph_label[100];
+ int nlabels = 0;
+ double X0 = im->xorigin;
+ double X1 = im->xorigin + im->xsize;
+ int sgrid = (int) (im->minval / im->ygrid_scale.gridstep - 1);
+ int egrid = (int) (im->maxval / im->ygrid_scale.gridstep + 1);
+ double MaxY;
+
+ scaledstep =
+ im->ygrid_scale.gridstep /
+ (double) im->magfact * (double) im->viewfactor;
+ MaxY = scaledstep * (double) egrid;
+ for (i = sgrid; i <= egrid; i++) {
+ double Y0 = ytr(im,
+ im->ygrid_scale.gridstep * i);
+ double YN = ytr(im,
+ im->ygrid_scale.gridstep * (i + 1));
+
+ if (floor(Y0 + 0.5) >=
+ im->yorigin - im->ysize && floor(Y0 + 0.5) <= im->yorigin) {
+ /* Make sure at least 2 grid labels are shown, even if it doesn't agree
+ with the chosen settings. Add a label if required by settings, or if
+ there is only one label so far and the next grid line is out of bounds. */
+ if (i % im->ygrid_scale.labfact == 0
+ || (nlabels == 1
+ && (YN < im->yorigin - im->ysize || YN > im->yorigin))) {
+ if (im->symbol == ' ') {
+ if (im->extra_flags & ALTYGRID) {
+ sprintf(graph_label,
+ im->ygrid_scale.labfmt,
+ scaledstep * (double) i);