X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_graph.c;h=d22c85350a2750d36455411afa08b74308975f6c;hp=451e891490f8fddd3a5f399818113a3db99b4b9b;hb=fcbf2878a231442f4b62ee95fca39e28f04fc8d2;hpb=298b318acaf1147474ab9e97cac37c3608660efd diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 451e891..d22c853 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -27,19 +27,21 @@ /* some constant definitions */ -#ifndef RRD_DEFAULT_FONT #ifdef WIN32 -#define RRD_DEFAULT_FONT "c:/winnt/fonts/COUR.TTF" -#else -#define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/openoffice/ariosor.ttf" +char rrd_win_default_font[80]; +#endif + +#ifndef RRD_DEFAULT_FONT +#ifndef WIN32 +#define RRD_DEFAULT_FONT "VeraMono.ttf" +/* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/openoffice/ariosor.ttf" */ /* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/Arial.ttf" */ #endif #endif - text_prop_t text_prop[] = { { 10.0, RRD_DEFAULT_FONT }, /* default */ - { 12.0, RRD_DEFAULT_FONT }, /* title */ + { 10.0, RRD_DEFAULT_FONT }, /* title */ { 8.0, RRD_DEFAULT_FONT }, /* axis */ { 10.0, RRD_DEFAULT_FONT }, /* unit */ { 10.0, RRD_DEFAULT_FONT } /* legend */ @@ -186,6 +188,7 @@ enum gf_en gf_conv(char *string){ conv_if(VDEF,GF_VDEF) conv_if(PART,GF_PART) conv_if(XPORT,GF_XPORT) + conv_if(SHIFT,GF_SHIFT) return (-1); } @@ -599,7 +602,7 @@ printf("row_cnt after: %lu\n",row_cnt); ** into one interval for the destination. */ - for (dst_row=0;row_cnt>=reduce_factor;dst_row++) { + for (dst_row=0;(long int)row_cnt>=reduce_factor;dst_row++) { for (col=0;col<(*ds_cnt);col++) { rrd_value_t newval=DNAN; unsigned long validval=0; @@ -679,11 +682,11 @@ for (col=0;colgdes_c;i++){ + for (i=0;i< (int)im->gdes_c;i++){ /* only GF_DEF elements fetch data */ if (im->gdes[i].gf != GF_DEF) continue; @@ -695,6 +698,7 @@ data_fetch(image_desc_t *im ) continue; if ((strcmp(im->gdes[i].rrd, im->gdes[ii].rrd) == 0) && (im->gdes[i].cf == im->gdes[ii].cf) + && (im->gdes[i].cf_reduce == im->gdes[ii].cf_reduce) && (im->gdes[i].start == im->gdes[ii].start) && (im->gdes[i].end == im->gdes[ii].end) && (im->gdes[i].step == im->gdes[ii].step)) { @@ -727,9 +731,10 @@ data_fetch(image_desc_t *im ) return -1; } im->gdes[i].data_first = 1; + im->gdes[i].step = im->step; if (ft_step < im->gdes[i].step) { - reduce_data(im->gdes[i].cf, + reduce_data(im->gdes[i].cf_reduce, ft_step, &im->gdes[i].start, &im->gdes[i].end, @@ -741,8 +746,8 @@ data_fetch(image_desc_t *im ) } } - /* lets see if the required data source is realy there */ - for(ii=0;iigdes[i].ds_cnt;ii++){ + /* lets see if the required data source is really there */ + for(ii=0;ii<(int)im->gdes[i].ds_cnt;ii++){ if(strcmp(im->gdes[i].ds_namv[ii],im->gdes[i].ds_nam) == 0){ im->gdes[i].ds=ii; } } @@ -820,6 +825,28 @@ data_calc( image_desc_t *im){ switch (im->gdes[gdi].gf) { case GF_XPORT: break; + case GF_SHIFT: { + graph_desc_t *vdp = &im->gdes[im->gdes[gdi].vidx]; + + /* remove current shift */ + vdp->start -= vdp->shift; + vdp->end -= vdp->shift; + + /* vdef */ + if (im->gdes[gdi].shidx >= 0) + vdp->shift = im->gdes[im->gdes[gdi].shidx].vf.val; + /* constant */ + else + vdp->shift = im->gdes[gdi].shval; + + /* normalize shift to multiple of consolidated step */ + vdp->shift = (vdp->shift / (long)vdp->step) * (long)vdp->step; + + /* apply shift */ + vdp->start += vdp->shift; + vdp->end += vdp->shift; + break; + } case GF_VDEF: /* A VDEF has no DS. This also signals other parts * of rrdtool that this is a VDEF value, not a CDEF. @@ -910,12 +937,12 @@ data_calc( image_desc_t *im){ if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE || im->gdes[gdi].rpnp[rpi].op == OP_PREV_OTHER){ long ptr = im->gdes[gdi].rpnp[rpi].ptr; - if(im->gdes[gdi].start > im->gdes[ptr].start) { - im->gdes[gdi].rpnp[rpi].data += im->gdes[gdi].rpnp[rpi].ds_cnt; - } + long diff = im->gdes[gdi].start - im->gdes[ptr].start; + + if(diff > 0) + im->gdes[gdi].rpnp[rpi].data += (diff / im->gdes[ptr].step) * im->gdes[ptr].ds_cnt; } } - if(steparray == NULL){ rrd_set_error("rpn expressions without DEF" @@ -1013,8 +1040,10 @@ data_proc( image_desc_t *im ){ ** the time of the graph. Beware. */ vidx = im->gdes[ii].vidx; - if ( (gr_time >= im->gdes[vidx].start) && - (gr_time <= im->gdes[vidx].end) ) { + if (im->gdes[vidx].gf == GF_VDEF) { + value = im->gdes[vidx].vf.val; + } else if (((long int)gr_time >= (long int)im->gdes[vidx].start) && + ((long int)gr_time <= (long int)im->gdes[vidx].end) ) { value = im->gdes[vidx].data[ (unsigned long) floor( (double)(gr_time - im->gdes[vidx].start) @@ -1070,6 +1099,11 @@ data_proc( image_desc_t *im ){ else im->maxval = maxval; } + /* make sure min is smaller than max */ + if (im->minval > im->maxval) { + im->minval = 0.99 * im->maxval; + } + /* make sure min and max are not equal */ if (im->minval == im->maxval) { im->maxval *= 1.01; @@ -1325,6 +1359,7 @@ print_calc(image_desc_t *im, char ***prdata) case GF_CDEF: case GF_VDEF: case GF_PART: + case GF_SHIFT: case GF_XPORT: break; } @@ -1350,7 +1385,7 @@ leg_place(image_desc_t *im) char prt_fctn; /*special printfunctions */ int *legspace; - if( !(im->extra_flags & NOLEGEND) ) { + if( !(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH) ) { if ((legspace = malloc(im->gdes_c*sizeof(int)))==NULL){ rrd_set_error("malloc for legspace"); return -1; @@ -1358,6 +1393,16 @@ leg_place(image_desc_t *im) for(i=0;igdes_c;i++){ fill_last = fill; + + /* hid legends for rules which are not displayed */ + + if (im->gdes[i].gf == GF_HRULE && + (im->gdes[i].yrule < im->minval || im->gdes[i].yrule > im->maxval)) + im->gdes[i].legend[0] = '\0'; + + if (im->gdes[i].gf == GF_VRULE && + (im->gdes[i].xrule < im->start || im->gdes[i].xrule > im->end)) + im->gdes[i].legend[0] = '\0'; leg_cc = strlen(im->gdes[i].legend); @@ -1391,7 +1436,7 @@ leg_place(image_desc_t *im) im->text_prop[TEXT_PROP_LEGEND].font, im->text_prop[TEXT_PROP_LEGEND].size, im->tabwidth, - im->gdes[i].legend); + im->gdes[i].legend, 0); leg_c++; } else { legspace[i]=0; @@ -1439,7 +1484,7 @@ leg_place(image_desc_t *im) im->text_prop[TEXT_PROP_LEGEND].font, im->text_prop[TEXT_PROP_LEGEND].size, im->tabwidth, - im->gdes[ii].legend) + im->gdes[ii].legend, 0) + legspace[ii] + glue; if (im->gdes[ii].gf != GF_GPRINT && @@ -1877,24 +1922,25 @@ grid_paint(image_desc_t *im) } /* yaxis description */ - if (im->canvas->imgformat != IF_PNG) { +/* if (im->canvas->imgformat != IF_PNG) {*/ + if (1) { gfx_new_text( im->canvas, 7, (im->yorigin - im->ysize/2), im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, - im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 270.0, - GFX_H_CENTER, GFX_V_CENTER, + im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, + RRDGRAPH_YLEGEND_ANGLE, + GFX_H_LEFT, GFX_V_CENTER, im->ylegend); } else { /* horrible hack until we can actually print vertically */ { int n; - int l=strlen(im->ylegend); char s[2]; - for (n=0;nylegend);n++) { + for (n=0;n< (int)strlen(im->ylegend);n++) { s[0]=im->ylegend[n]; s[1]='\0'; - gfx_new_text(im->canvas,7,im->text_prop[TEXT_PROP_AXIS].size*(l-n), + gfx_new_text(im->canvas,7,im->text_prop[TEXT_PROP_AXIS].size*(n+1), im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 270.0, @@ -1914,7 +1960,7 @@ grid_paint(image_desc_t *im) im->title); /* graph labels */ - if( !(im->extra_flags & NOLEGEND) ) { + if( !(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH) ) { for(i=0;igdes_c;i++){ if(im->gdes[i].legend[0] =='\0') continue; @@ -1930,7 +1976,7 @@ grid_paint(image_desc_t *im) boxH = gfx_get_text_width(im->canvas, 0, im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, - im->tabwidth,"M") * 1.25; + im->tabwidth,"M", 0) * 1.25; boxV = boxH; node = gfx_new_area(im->canvas, @@ -2066,11 +2112,20 @@ graph_size_location(image_desc_t *im, int elements, int piechart ) #if 0 Xlegend =0, Ylegend =0, #endif - Xspacing =10, Yspacing =10; + Xspacing =10, Yspacing =10; - if (im->ylegend[0] != '\0') { - Xvertical = im->text_prop[TEXT_PROP_LEGEND].size *2; - Yvertical = im->text_prop[TEXT_PROP_LEGEND].size * (strlen(im->ylegend)+1); + if (im->extra_flags & ONLY_GRAPH) { + if ( im->ysize > 32 ) { + rrd_set_error("height > 32 is not possible with --only-graph option"); + return -1; + } + Xspacing =0; + Yspacing =0; + } else { + if (im->ylegend[0] != '\0') { + Xvertical = im->text_prop[TEXT_PROP_LEGEND].size *2; + Yvertical = im->text_prop[TEXT_PROP_LEGEND].size * (strlen(im->ylegend)+1); + } } if (im->title[0] != '\0') { @@ -2082,7 +2137,7 @@ graph_size_location(image_desc_t *im, int elements, int piechart ) im->text_prop[TEXT_PROP_TITLE].font, im->text_prop[TEXT_PROP_TITLE].size, im->tabwidth, - im->title) + 2*Xspacing; + im->title, 0) + 2*Xspacing; Ytitle = im->text_prop[TEXT_PROP_TITLE].size*2; } @@ -2116,10 +2171,21 @@ graph_size_location(image_desc_t *im, int elements, int piechart ) ** forget about it at all; the legend will have to fit in the ** size already allocated. */ - im->ximg = Xylabel + Xmain + Xpie + Xspacing; + im->ximg = Xmain; + + if ( !(im->extra_flags & ONLY_GRAPH) ) { + im->ximg = Xylabel + Xmain + Xpie + Xspacing; + } + if (Xmain) im->ximg += Xspacing; if (Xpie) im->ximg += Xspacing; - im->xorigin = Xspacing + Xylabel; + + if (im->extra_flags & ONLY_GRAPH) { + im->xorigin = 0; + } else { + im->xorigin = Xspacing + Xylabel; + } + if (Xtitle > im->ximg) im->ximg = Xtitle; if (Xvertical) { im->ximg += Xvertical; @@ -2137,9 +2203,21 @@ graph_size_location(image_desc_t *im, int elements, int piechart ) */ /* reserve space for main and/or pie */ - im->yimg = Ymain + Yxlabel; + + if (im->extra_flags & ONLY_GRAPH) { + im->yimg = Ymain; + } else { + im->yimg = Ymain + Yxlabel; + } + if (im->yimg < Ypie) im->yimg = Ypie; - im->yorigin = im->yimg - Yxlabel; + + if (im->extra_flags & ONLY_GRAPH) { + im->yorigin = im->yimg; + } else { + im->yorigin = im->yimg - Yxlabel; + } + /* reserve space for the title *or* some padding above the graph */ if (Ytitle) { im->yimg += Ytitle; @@ -2242,9 +2320,11 @@ graph_paint(image_desc_t *im, char ***calcpr) if (!calc_horizontal_grid(im)) return -1; + if (im->gridfit) apply_gridfit(im); + /************************************************************** *** Calculating sizes and locations became a bit confusing *** *** so I moved this into a separate function. *** @@ -2276,8 +2356,8 @@ graph_paint(image_desc_t *im, char ***calcpr) areazero = im->minval; if (im->maxval < 0.0) areazero = im->maxval; - - axis_paint(im); + if( !(im->extra_flags & ONLY_GRAPH) ) + axis_paint(im); } if (piechart) { @@ -2295,6 +2375,7 @@ graph_paint(image_desc_t *im, char ***calcpr) case GF_HRULE: case GF_VRULE: case GF_XPORT: + case GF_SHIFT: break; case GF_TICK: for (ii = 0; ii < im->xsize; ii++) @@ -2429,7 +2510,8 @@ graph_paint(image_desc_t *im, char ***calcpr) im->draw_y_grid=0; } /* grid_paint also does the text */ - grid_paint(im); + if( !(im->extra_flags & ONLY_GRAPH) ) + grid_paint(im); /* the RULES are the last thing to paint ... */ for(i=0;igdes_c;i++){ @@ -2464,11 +2546,11 @@ graph_paint(image_desc_t *im, char ***calcpr) if (strcmp(im->graphfile,"-")==0) { + fo = im->graphhandle ? im->graphhandle : stdout; #ifdef WIN32 /* Change translation mode for stdout to BINARY */ - _setmode( _fileno( stdout ), O_BINARY ); + _setmode( _fileno( fo ), O_BINARY ); #endif - fo = stdout; } else { if ((fo = fopen(im->graphfile,"wb")) == NULL) { rrd_set_error("Opening '%s' for write: %s",im->graphfile, @@ -2490,13 +2572,7 @@ graph_paint(image_desc_t *im, char ***calcpr) int gdes_alloc(image_desc_t *im){ - unsigned long def_step = (im->end-im->start)/im->xsize; - - if (im->step > def_step) /* step can be increassed ... no decreassed */ - def_step = im->step; - im->gdes_c++; - if ((im->gdes = (graph_desc_t *) rrd_realloc(im->gdes, (im->gdes_c) * sizeof(graph_desc_t)))==NULL){ rrd_set_error("realloc graph_descs"); @@ -2504,7 +2580,7 @@ gdes_alloc(image_desc_t *im){ } - im->gdes[im->gdes_c-1].step=def_step; + im->gdes[im->gdes_c-1].step=im->step; im->gdes[im->gdes_c-1].stack=0; im->gdes[im->gdes_c-1].debug=0; im->gdes[im->gdes_c-1].start=im->start; @@ -2515,6 +2591,7 @@ gdes_alloc(image_desc_t *im){ im->gdes[im->gdes_c-1].data_first=0; im->gdes[im->gdes_c-1].p_data=NULL; im->gdes[im->gdes_c-1].rpnp=NULL; + im->gdes[im->gdes_c-1].shift=0; im->gdes[im->gdes_c-1].col = 0x0; im->gdes[im->gdes_c-1].legend[0]='\0'; im->gdes[im->gdes_c-1].rrd[0]='\0'; @@ -2556,12 +2633,13 @@ scan_for_col(char *input, int len, char *output) ** - script parsing now in rrd_graph_script() */ int -rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize) +rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize, FILE *stream) { image_desc_t im; rrd_graph_init(&im); - + im.graphhandle = stream; + rrd_graph_options(argc,argv,&im); if (rrd_test_error()) { im_free(&im); @@ -2576,7 +2654,7 @@ rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize) strncpy(im.graphfile,argv[optind],MAXPATH-1); im.graphfile[MAXPATH-1]='\0'; - rrd_graph_script(argc,argv,&im); + rrd_graph_script(argc,argv,&im,1); if (rrd_test_error()) { im_free(&im); return -1; @@ -2664,7 +2742,19 @@ rrd_graph_init(image_desc_t *im) for(i=0;igraph_col[i]=graph_col[i]; - +#ifdef WIN32 + { + char *windir; + windir = getenv("windir"); + /* %windir% is something like D:\windows or C:\winnt */ + if (windir != NULL) { + strcpy(rrd_win_default_font,windir); + strcat(rrd_win_default_font,"\\fonts\\cour.ttf"); + for(i=0;itext_prop[i].size = text_prop[i].size; im->text_prop[i].font = text_prop[i].font; @@ -2679,7 +2769,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) char scan_gtm[12],scan_mtm[12],scan_ltm[12],col_nam[12]; time_t start_tmp=0,end_tmp=0; long long_tmp; - struct time_value start_tv, end_tv; + struct rrd_time_value start_tv, end_tv; gfx_color_t color; parsetime("end-24h", &start_tv); @@ -2709,6 +2799,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) {"lazy", no_argument, 0, 'z'}, {"zoom", required_argument, 0, 'm'}, {"no-legend", no_argument, 0, 'g'}, + {"only-graph", no_argument, 0, 'j'}, {"alt-y-grid", no_argument, 0, 'Y'}, {"no-minor", no_argument, 0, 'I'}, {"alt-autoscale", no_argument, 0, 'A'}, @@ -2722,7 +2813,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) opt = getopt_long(argc, argv, - "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:I:zgYAMX:S:N", + "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:I:zgjYAMX:S:N", long_options, &option_index); if (opt == EOF) @@ -2741,6 +2832,9 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) case 'M': im->extra_flags |= ALTAUTOSCALE_MAX; break; + case 'j': + im->extra_flags |= ONLY_GRAPH; + break; case 'g': im->extra_flags |= NOLEGEND; break; @@ -2782,13 +2876,13 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) &im->xlab_user.precis, &stroff) == 7 && stroff != 0){ strncpy(im->xlab_form, optarg+stroff, sizeof(im->xlab_form) - 1); - if((im->xlab_user.gridtm = tmt_conv(scan_gtm)) == -1){ + if((int)(im->xlab_user.gridtm = tmt_conv(scan_gtm)) == -1){ rrd_set_error("unknown keyword %s",scan_gtm); return; - } else if ((im->xlab_user.mgridtm = tmt_conv(scan_mtm)) == -1){ + } else if ((int)(im->xlab_user.mgridtm = tmt_conv(scan_mtm)) == -1){ rrd_set_error("unknown keyword %s",scan_mtm); return; - } else if ((im->xlab_user.labtm = tmt_conv(scan_ltm)) == -1){ + } else if ((int)(im->xlab_user.labtm = tmt_conv(scan_ltm)) == -1){ rrd_set_error("unknown keyword %s",scan_ltm); return; } @@ -2865,7 +2959,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) im->imginfo = optarg; break; case 'a': - if((im->canvas->imgformat = if_conv(optarg)) == -1) { + if((int)(im->canvas->imgformat = if_conv(optarg)) == -1) { rrd_set_error("unsupported graphics format '%s'",optarg); return; } @@ -2983,6 +3077,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) im->start = start_tmp; im->end = end_tmp; + im->step = max((long)im->step, (im->end-im->start)/im->xsize); } int @@ -3096,12 +3191,12 @@ char *str; n=0; sscanf(str,"%le,%29[A-Z]%n",¶m,func,&n); - if (n==strlen(str)) { /* matched */ + if (n== (int)strlen(str)) { /* matched */ ; } else { n=0; sscanf(str,"%29[A-Z]%n",func,&n); - if (n==strlen(str)) { /* matched */ + if (n== (int)strlen(str)) { /* matched */ param=DNAN; } else { rrd_set_error("Unknown function string '%s' in VDEF '%s'"