X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Frrd_graph.c;h=db9a8c70b724722304582431abd553a944d3179b;hb=daf8e7ff715a59e1f9827080d1b785ffb3c5a4b1;hp=0f84b8085bfe3b4fdc736c1b88b6cb9800a50871;hpb=ea8c705cc27ef33dee2cc6561ed51e16ddc5d0a9;p=rrdtool.git diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 0f84b80..db9a8c7 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -1,5 +1,5 @@ /**************************************************************************** - * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007 + * RRDtool 1.3rc7 Copyright by Tobi Oetiker, 1997-2008 **************************************************************************** * rrd__graph.c produce graphs from data in rrdfiles ****************************************************************************/ @@ -201,16 +201,6 @@ double ytr( yval = im->yorigin - pixie * (log10(value) - log10(im->minval)); } } - /* make sure we don't return anything too unreasonable. GD lib can - get terribly slow when drawing lines outside its scope. This is - especially problematic in connection with the rigid option */ - if (!im->rigid) { - /* keep yval as-is */ - } else if (yval > im->yorigin) { - yval = im->yorigin + 0.00001; - } else if (yval < im->yorigin - im->ysize) { - yval = im->yorigin - im->ysize - 0.00001; - } return yval; } @@ -1122,6 +1112,10 @@ int data_calc( return 0; } +/* from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */ +/* yes we are loosing precision by doing tos with floats instead of doubles + but it seems more stable this way. */ + static int AlmostEqual2sComplement( float A, float B, @@ -1255,24 +1249,29 @@ int data_proc( lets set these to dummy values then ... */ if (im->logarithmic) { - if (isnan(minval)) - minval = 0.2; - if (isnan(maxval)) + if (isnan(minval) || isnan(maxval) || maxval <= 0) { + minval = 0.0; /* catching this right away below */ maxval = 5.1; + } + /* in logarithm mode, where minval is smaller or equal + to 0 make the beast just way smaller than maxval */ + if (minval <= 0) { + minval = maxval / 10e8; + } } else { - if (isnan(minval)) + if (isnan(minval) || isnan(maxval)) { minval = 0.0; - if (isnan(maxval)) maxval = 1.0; + } } - /* adjust min and max values */ + /* adjust min and max values given by the user */ /* for logscale we add something on top */ if (isnan(im->minval) || ((!im->rigid) && im->minval > minval) ) { if (im->logarithmic) - im->minval = minval * 0.5; + im->minval = minval / 2.0; else im->minval = minval; } @@ -1613,7 +1612,8 @@ int leg_place( int border = im->text_prop[TEXT_PROP_LEGEND].size * 2.0; int fill = 0, fill_last; int leg_c = 0; - int leg_x = border, leg_y = im->yimg; + int leg_x = border; + int leg_y = im->yimg; int leg_y_prev = im->yimg; int leg_cc; int glue = 0; @@ -1621,6 +1621,7 @@ int leg_place( char prt_fctn; /*special printfunctions */ char default_txtalign = TXA_JUSTIFIED; /*default line orientation */ int *legspace; + char *tab; if (!(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH)) { if ((legspace = malloc(im->gdes_c * sizeof(int))) == NULL) { @@ -1649,13 +1650,16 @@ int leg_place( im->gdes[i].legend[0] = '\0'; } + /* turn \\t into tab */ + while ((tab = strstr(im->gdes[i].legend, "\\t"))) { + memmove(tab, tab + 1, strlen(tab)); + tab[0] = (char) 9; + } leg_cc = strlen(im->gdes[i].legend); /* is there a controle code ant the end of the legend string ? */ - /* and it is not a tab \\t */ if (leg_cc >= 2 && im->gdes[i].legend[leg_cc - - 2] == '\\' - && im->gdes[i].legend[leg_cc - 1] != 't') { + 2] == '\\' ) { prt_fctn = im->gdes[i].legend[leg_cc - 1]; leg_cc -= 2; im->gdes[i].legend[leg_cc] = '\0'; @@ -1668,7 +1672,7 @@ int leg_place( prt_fctn != 'j' && prt_fctn != 'c' && prt_fctn != 's' && - prt_fctn != 't' && prt_fctn != '\0' && prt_fctn != 'g') { + prt_fctn != '\0' && prt_fctn != 'g') { free(legspace); rrd_set_error ("Unknown control code at the end of '%s\\%c'", @@ -1804,10 +1808,7 @@ int leg_place( leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8; } } else { - im->yimg = leg_y_prev; - /* if we did place some legends we have to add vertical space */ - if (leg_y != im->yimg) - im->yimg += im->text_prop[TEXT_PROP_LEGEND].size * 1.8; + im->yimg = leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 + border * 0.6; } free(legspace); } @@ -1820,8 +1821,6 @@ int leg_place( /* the xaxis labels are determined from the number of seconds per pixel in the requested graph */ - - int calc_horizontal_grid( image_desc_t *im) @@ -1859,13 +1858,13 @@ int calc_horizontal_grid( 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) + 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) { + if (range / im->ygrid_scale.gridstep > 5 ) { im->ygrid_scale.labfact = 1; - if (range / im->ygrid_scale.gridstep > 8) + 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; @@ -1892,17 +1891,17 @@ int calc_horizontal_grid( sprintf(im->ygrid_scale.labfmt, "%%%d.0f%s", len, (im->symbol != ' ' ? " %c" : "")); } - } else { + } else { /* classic rrd grid */ for (i = 0; ylab[i].grid > 0; i++) { pixel = im->ysize / (scaledrange / ylab[i].grid); gridind = i; - if (pixel > 7) + if (pixel >= 5) break; } for (i = 0; i < 4; i++) { if (pixel * ylab[gridind].lfac[i] >= - 2.5 * im->text_prop[TEXT_PROP_AXIS].size) { + 1.8 * im->text_prop[TEXT_PROP_AXIS].size) { im->ygrid_scale.labfact = ylab[gridind].lfac[i]; break; } @@ -2044,10 +2043,6 @@ double frexp10( return mnt; } -/* from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */ -/* yes we are loosing precision by doing tos with floats instead of doubles - but it seems more stable this way. */ - /* logaritmic horizontal grid */ int horizontal_log_grid( @@ -2650,7 +2645,7 @@ void grid_paint( [GRC_FRAME]. blue, im->graph_col[GRC_FRAME].alpha); if (im->gdes[i].dash) { - // make box borders in legend dashed if the graph is dashed + /* make box borders in legend dashed if the graph is dashed */ double dashes[] = { 3.0 }; @@ -2713,7 +2708,6 @@ int graph_size_location( int Xvertical = 0, Ytitle = 0, Xylabel = 0, Xmain = 0, Ymain = 0, Yxlabel = 0, Xspacing = 15, Yspacing = 15, Ywatermark = 4; - infoval info; if (im->extra_flags & ONLY_GRAPH) { im->xorigin = 0; @@ -2923,18 +2917,6 @@ int graph_size_location( } ytr(im, DNAN); - info.u_cnt = im->xorigin; - grinfo_push(im, sprintf_alloc("graph_left"), RD_I_CNT, info); - info.u_cnt = im->yorigin - Ymain; - grinfo_push(im, sprintf_alloc("graph_top"), RD_I_CNT, info); - info.u_cnt = im->xsize; - grinfo_push(im, sprintf_alloc("graph_width"), RD_I_CNT, info); - info.u_cnt = im->ysize; - grinfo_push(im, sprintf_alloc("graph_height"), RD_I_CNT, info); - info.u_cnt = im->ximg; - grinfo_push(im, sprintf_alloc("image_width"), RD_I_CNT, info); - info.u_cnt = im->yimg; - grinfo_push(im, sprintf_alloc("image_height"), RD_I_CNT, info); return 0; } @@ -2991,6 +2973,20 @@ int graph_paint( **************************************************************/ if (graph_size_location(im, i) == -1) return -1; + + info.u_cnt = im->xorigin; + grinfo_push(im, sprintf_alloc("graph_left"), RD_I_CNT, info); + info.u_cnt = im->yorigin - im->ysize; + grinfo_push(im, sprintf_alloc("graph_top"), RD_I_CNT, info); + info.u_cnt = im->xsize; + grinfo_push(im, sprintf_alloc("graph_width"), RD_I_CNT, info); + info.u_cnt = im->ysize; + grinfo_push(im, sprintf_alloc("graph_height"), RD_I_CNT, info); + info.u_cnt = im->ximg; + grinfo_push(im, sprintf_alloc("image_width"), RD_I_CNT, info); + info.u_cnt = im->yimg; + grinfo_push(im, sprintf_alloc("image_height"), RD_I_CNT, info); + /* get actual drawing data and find min and max values */ if (data_proc(im) == -1) return -1; @@ -3027,31 +3023,29 @@ int graph_paint( case IF_PDF: im->gridfit = 0; im->surface = strlen(im->graphfile) - ? - cairo_pdf_surface_create_for_stream - (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom) - : cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom, - im->yimg * im->zoom); + ? cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom) + : cairo_pdf_surface_create_for_stream + (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom); break; case IF_EPS: im->gridfit = 0; im->surface = strlen(im->graphfile) ? - cairo_ps_surface_create_for_stream - (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom) - : cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom, - im->yimg * im->zoom); + cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom) + : cairo_ps_surface_create_for_stream + (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom); break; case IF_SVG: im->gridfit = 0; im->surface = strlen(im->graphfile) ? - cairo_svg_surface_create_for_stream - (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom) - : cairo_svg_surface_create(im-> - graphfile, - im-> - ximg * im->zoom, im->yimg * im->zoom); + cairo_svg_surface_create(im-> + graphfile, + im->ximg * im->zoom, im->yimg * im->zoom) + : cairo_svg_surface_create_for_stream + (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom); cairo_svg_surface_restrict_to_version (im->surface, CAIRO_SVG_VERSION_1_1); break; @@ -3072,7 +3066,9 @@ int graph_paint( im->xsize, im->yorigin - im->ysize, im->graph_col[GRC_CANVAS]); gfx_add_point(im, im->xorigin, im->yorigin - im->ysize); - gfx_close_path(im); + gfx_close_path(im); + cairo_rectangle(im->cr, im->xorigin, im->yorigin-im->ysize-1.0, im->xsize,im->ysize+2.0); + cairo_clip(im->cr); if (im->minval > 0.0) areazero = im->minval; if (im->maxval < 0.0) @@ -3360,6 +3356,7 @@ int graph_paint( break; } /* switch */ } + cairo_reset_clip(im->cr); /* grid_paint also does the text */ if (!(im->extra_flags & ONLY_GRAPH)) @@ -3427,8 +3424,8 @@ int graph_paint( rrd_set_error("Could not save png to '%s'", im->graphfile); return 1; } - } break; + } default: if (strlen(im->graphfile)) { cairo_show_page(im->cr); @@ -3565,7 +3562,7 @@ int rrd_graph( *ymin = walker->value.u_val; } else if (strcmp(walker->key, "value_max") == 0) { *ymax = walker->value.u_val; - } else if (strncmp(walker->key, "print", 6) == 0) { /* keys are prdate[0..] */ + } else if (strncmp(walker->key, "print", 5) == 0) { /* keys are prdate[0..] */ prlines++; if (((*prdata) = rrd_realloc((*prdata), @@ -3578,7 +3575,8 @@ int rrd_graph( (*prdata)[prlines] = NULL; strcpy((*prdata)[prlines - 1], walker->value.u_str); } else if (strcmp(walker->key, "image") == 0) { - fwrite(walker->value.u_blo.ptr, walker->value.u_blo.size, 1, (stream ? stream : stdout)); + fwrite(walker->value.u_blo.ptr, walker->value.u_blo.size, 1, + (stream ? stream : stdout)); } /* skip anything else */ walker = walker->next; @@ -3594,12 +3592,13 @@ int rrd_graph( ** - options parsing now in rrd_graph_options() ** - script parsing now in rrd_graph_script() */ -info_t * rrd_graph_v( +info_t *rrd_graph_v( int argc, char **argv) { image_desc_t im; - info_t *grinfo; + info_t *grinfo; + rrd_graph_init(&im); /* a dummy surface so that we can measure text sizes for placements */ im.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); @@ -3665,6 +3664,7 @@ info_t * rrd_graph_v( } if (im.rendered_image) { infoval img; + img.u_blo.size = im.rendered_image_size; img.u_blo.ptr = im.rendered_image; grinfo_push(&im, sprintf_alloc("image"), RD_I_BLO, img); @@ -4273,7 +4273,7 @@ void rrd_graph_options( } } - if (im->logarithmic == 1 && im->minval <= 0) { + if (im->logarithmic && im->minval <= 0) { rrd_set_error ("for a logarithmic yaxis you must specify a lower-limit > 0"); return; @@ -4510,15 +4510,18 @@ int vdef_calc( graph_desc_t *src, *dst; rrd_value_t *data; long step, steps; + unsigned long end; dst = &im->gdes[gdi]; src = &im->gdes[dst->vidx]; data = src->data + src->ds; - steps = (src->end - src->start) / src->step; + end = src->end_orig % src->step == 0 ? src->end_orig : (src->end_orig + src->step - src->end_orig % src->step); + + steps = (end - src->start) / src->step; #if 0 printf ("DEBUG: start == %lu, end == %lu, %lu steps\n", - src->start, src->end, steps); + src->start, src->end_orig, steps); #endif switch (dst->vf.op) { case VDEF_PERCENT:{