X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_graph.c;h=79a23be482ec8da82040afdd217fc30a6a391e66;hp=0279d49d524cbee22831a1546e6528b5195e8fea;hb=990fcfb7eec407edfe504f42760bae204e1c074d;hpb=99b9b7fd0cad0edea57c08fdf939d368c4c0ec45 diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 0279d49..79a23be 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -1,5 +1,5 @@ /**************************************************************************** - * RRDtool 1.2rc2 Copyright by Tobi Oetiker, 1997-2005 + * RRDtool 1.2rc9 Copyright by Tobi Oetiker, 1997-2005 **************************************************************************** * rrd__graph.c produce graphs from data in rrdfiles ****************************************************************************/ @@ -9,7 +9,7 @@ #include "rrd_tool.h" -#ifdef WIN32 +#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) #include #include #endif @@ -27,9 +27,6 @@ /* some constant definitions */ -#ifdef WIN32 -char rrd_win_default_font[80]; -#endif #ifndef RRD_DEFAULT_FONT /* there is special code later to pick Cour.ttf when running on windows */ @@ -37,11 +34,11 @@ char rrd_win_default_font[80]; #endif text_prop_t text_prop[] = { - { 9.0, RRD_DEFAULT_FONT }, /* default */ - { 11.0, RRD_DEFAULT_FONT }, /* title */ - { 8.0, RRD_DEFAULT_FONT }, /* axis */ - { 9.0, RRD_DEFAULT_FONT }, /* unit */ - { 9.0, RRD_DEFAULT_FONT } /* legend */ + { 8.0, RRD_DEFAULT_FONT }, /* default */ + { 9.0, RRD_DEFAULT_FONT }, /* title */ + { 7.0, RRD_DEFAULT_FONT }, /* axis */ + { 8.0, RRD_DEFAULT_FONT }, /* unit */ + { 8.0, RRD_DEFAULT_FONT } /* legend */ }; xlab_t xlab[] = { @@ -102,8 +99,8 @@ gfx_color_t graph_col[] = /* default colors */ 0x90909080, /* grid */ 0xE0505080, /* major grid */ 0x000000FF, /* font */ - 0xFF0000FF, /* arrow */ - 0x404040FF /* axis */ + 0x802020FF, /* arrow */ + 0x202020FF /* axis */ }; @@ -332,25 +329,32 @@ si_unit( 'E'};/* 10e18 Exa */ int symbcenter = 6; - double digits; + double digits,viewdigits=0; + digits = floor( log( max( fabs(im->minval),fabs(im->maxval)))/log((double)im->base)); + if (im->unitsexponent != 9999) { /* unitsexponent = 9, 6, 3, 0, -3, -6, -9, etc */ - digits = floor(im->unitsexponent / 3); + viewdigits = floor(im->unitsexponent / 3); } else { - digits = floor( log( max( fabs(im->minval),fabs(im->maxval)))/log((double)im->base)); + viewdigits = digits; } - im->magfact = pow((double)im->base , digits); + im->magfact = pow((double)im->base , digits); + #ifdef DEBUG printf("digits %6.3f im->magfact %6.3f\n",digits,im->magfact); #endif - if ( ((digits+symbcenter) < sizeof(symbol)) && - ((digits+symbcenter) >= 0) ) - im->symbol = symbol[(int)digits+symbcenter]; + im->viewfactor = im->magfact / pow((double)im->base , viewdigits); + + pow((double)im->base , viewdigits); + + if ( ((viewdigits+symbcenter) < sizeof(symbol)) && + ((viewdigits+symbcenter) >= 0) ) + im->symbol = symbol[(int)viewdigits+symbcenter]; else - im->symbol = ' '; + im->symbol = '?'; } /* move min and max values around to become sensible */ @@ -426,6 +430,10 @@ expand_range(image_desc_t *im) -sensiblevalues[i] >=scaled_max) im->maxval = -sensiblevalues[i]*(im->magfact); } + /* no sensiblevalues found. we switch to ALTYGRID mode */ + if (sensiblevalues[i] == 0){ + im->extra_flags |= ALTYGRID; + } } } else { /* adjust min and max to the grid definition if there is one */ @@ -1288,14 +1296,16 @@ print_calc(image_desc_t *im, char ***prdata) if (!strcmp(im->gdes[i].format,"%c")) { /* VDEF time print */ char ctime_buf[128]; /* PS: for ctime_r, must be >= 26 chars */ + int iii=0; + ctime_r(&printtime,ctime_buf); + while(isprint(ctime_buf[iii])){iii++;} + ctime_buf[iii]='\0'; if (im->gdes[i].gf == GF_PRINT){ (*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char)); - sprintf((*prdata)[prlines-2],"%s (%lu)", - ctime_r(&printtime,ctime_buf),printtime); + sprintf((*prdata)[prlines-2],"%s (%lu)",ctime_buf,printtime); (*prdata)[prlines-1] = NULL; } else { - sprintf(im->gdes[i].legend,"%s (%lu)", - ctime_r(&printtime,ctime_buf),printtime); + sprintf(im->gdes[i].legend,"%s (%lu)",ctime_buf,printtime); graphelement = 1; } } else { @@ -1487,7 +1497,7 @@ leg_place(image_desc_t *im) + legspace[ii] + glue; } - leg_y += im->text_prop[TEXT_PROP_LEGEND].size*1.7; + 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; @@ -1538,10 +1548,15 @@ calc_horizontal_grid(image_desc_t *im) decimals = 1; fractionals = floor(log10(range)); - if(fractionals < 0) /* small amplitude. */ - sprintf(im->ygrid_scale.labfmt, "%%%d.%df", decimals - fractionals + 1, -fractionals + 1); - else - sprintf(im->ygrid_scale.labfmt, "%%%d.1f", decimals + 1); + if(fractionals < 0) { /* small amplitude. */ + int len = decimals - fractionals + 1; + if (im->unitslength < len) im->unitslength = len; + sprintf(im->ygrid_scale.labfmt, "%%%d.%df", len, -fractionals + 1); + } else { + int len = decimals + 1; + if (im->unitslength < len) im->unitslength = len; + sprintf(im->ygrid_scale.labfmt, "%%%d.1f", len); + } im->ygrid_scale.gridstep = pow((double)10, (double)fractionals); if(im->ygrid_scale.gridstep == 0) /* range is one -> 0.1 is reasonable scale */ im->ygrid_scale.gridstep = 0.1; @@ -1563,7 +1578,7 @@ calc_horizontal_grid(image_desc_t *im) else { for(i=0;ylab[i].grid > 0;i++){ pixel = im->ysize / (scaledrange / ylab[i].grid); - if (gridind == -1 && pixel > 5) { + if (pixel > 5) { gridind = i; break; } @@ -1604,24 +1619,24 @@ int draw_horizontal_grid(image_desc_t *im) if (i==0 || im->symbol == ' ') { if(scaledstep < 1){ if(im->extra_flags & ALTYGRID) { - sprintf(graph_label,im->ygrid_scale.labfmt,scaledstep*i); + sprintf(graph_label,im->ygrid_scale.labfmt,scaledstep*im->viewfactor*i); } else { - sprintf(graph_label,"%4.1f",scaledstep*i); + sprintf(graph_label,"%4.1f",scaledstep*im->viewfactor*i); } } else { - sprintf(graph_label,"%4.0f",scaledstep*i); + sprintf(graph_label,"%4.0f",scaledstep*im->viewfactor*i); } }else { if(scaledstep < 1){ - sprintf(graph_label,"%4.1f %c",scaledstep*i, im->symbol); + sprintf(graph_label,"%4.1f %c",scaledstep*im->viewfactor*i, im->symbol); } else { - sprintf(graph_label,"%4.0f %c",scaledstep*i, im->symbol); + sprintf(graph_label,"%4.0f %c",scaledstep*im->viewfactor*i, im->symbol); } } gfx_new_text ( im->canvas, - X0-im->text_prop[TEXT_PROP_AXIS].size/1.5, Y0, + X0-im->text_prop[TEXT_PROP_AXIS].size, Y0, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, @@ -1715,7 +1730,7 @@ horizontal_log_grid(image_desc_t *im) sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]); gfx_new_text ( im->canvas, - X0-im->text_prop[TEXT_PROP_AXIS].size/1.5, Y0, + X0-im->text_prop[TEXT_PROP_AXIS].size, Y0, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, @@ -1822,7 +1837,7 @@ vertical_grid( # error "your libc has no strftime I guess we'll abort the exercise here." #endif gfx_new_text ( im->canvas, - xtr(im,tilab), Y0+im->text_prop[TEXT_PROP_AXIS].size/1.5, + xtr(im,tilab), Y0+im->text_prop[TEXT_PROP_AXIS].size, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, @@ -1857,11 +1872,17 @@ axis_paint( MGRIDWIDTH, im->graph_col[GRC_AXIS]); - /* arrow for X axis direction */ + /* arrow for X and Y axis direction */ gfx_new_area ( im->canvas, - im->xorigin+im->xsize+3, im->yorigin-3, - im->xorigin+im->xsize+3, im->yorigin+4, - im->xorigin+im->xsize+8, im->yorigin+0.5, /* LINEOFFSET */ + im->xorigin+im->xsize+2, im->yorigin-2, + im->xorigin+im->xsize+2, im->yorigin+3, + im->xorigin+im->xsize+7, im->yorigin+0.5, /* LINEOFFSET */ + im->graph_col[GRC_ARROW]); + + gfx_new_area ( im->canvas, + im->xorigin-2, im->yorigin-im->ysize-2, + im->xorigin+3, im->yorigin-im->ysize-2, + im->xorigin+0.5, im->yorigin-im->ysize-7, /* LINEOFFSET */ im->graph_col[GRC_ARROW]); } @@ -2098,28 +2119,34 @@ graph_size_location(image_desc_t *im, int elements */ int Xvertical=0, Yvertical=0, Xtitle =0, Ytitle =0, - Xylabel =0, Yylabel =0, + Xylabel =0, Xmain =0, Ymain =0, +#ifdef WITH_PIECHART Xpie =0, Ypie =0, - Xxlabel =0, Yxlabel =0, +#endif + Yxlabel =0, #if 0 Xlegend =0, Ylegend =0, #endif - Xspacing =10, Yspacing =10; + Xspacing =15, Yspacing =15; if (im->extra_flags & ONLY_GRAPH) { - Xspacing =0; - Yspacing =0; - } else { - if (im->ylegend[0] != '\0') { + im->xorigin =0; + im->ximg = im->xsize; + im->yimg = im->ysize; + im->yorigin = im->ysize; + return 0; + } + + if (im->ylegend[0] != '\0' ) { Xvertical = im->text_prop[TEXT_PROP_UNIT].size *2; Yvertical = gfx_get_text_width(im->canvas, 0, im->text_prop[TEXT_PROP_UNIT].font, im->text_prop[TEXT_PROP_UNIT].size, im->tabwidth,im->ylegend, 0); - } } + if (im->title[0] != '\0') { /* The title is placed "inbetween" two text lines so it ** automatically has some vertical spacing. The horizontal @@ -2137,12 +2164,14 @@ graph_size_location(image_desc_t *im, int elements Xmain=im->xsize; Ymain=im->ysize; if (im->draw_x_grid) { - Xxlabel=Xmain; Yxlabel=im->text_prop[TEXT_PROP_AXIS].size *2.5; } if (im->draw_y_grid) { - Xylabel=im->text_prop[TEXT_PROP_AXIS].size *6; - Yylabel=Ymain; + Xylabel=gfx_get_text_width(im->canvas, 0, + im->text_prop[TEXT_PROP_AXIS].font, + im->text_prop[TEXT_PROP_AXIS].size, + im->tabwidth, + "0", 0) * im->unitslength + im->text_prop[TEXT_PROP_AXIS].size * 2; } } @@ -2165,23 +2194,22 @@ graph_size_location(image_desc_t *im, int elements ** forget about it at all; the legend will have to fit in the ** size already allocated. */ - im->ximg = Xmain; + im->ximg = Xylabel + Xmain + 2 * Xspacing; - if ( !(im->extra_flags & ONLY_GRAPH) ) { - im->ximg = Xylabel + Xmain + Xpie + 2 * Xspacing; - } +#ifdef WITH_PIECHART + im->ximg += Xpie; +#endif if (Xmain) im->ximg += Xspacing; +#ifdef WITH_PIECHART if (Xpie) im->ximg += Xspacing; +#endif - if (im->extra_flags & ONLY_GRAPH) { - im->xorigin = 0; - } else { - im->xorigin = Xspacing + Xylabel; - } + im->xorigin = Xspacing + Xylabel; if (Xtitle > im->ximg) im->ximg = Xtitle; - if (Xvertical) { + + if (Xvertical) { /* unit description */ im->ximg += Xvertical; im->xorigin += Xvertical; } @@ -2198,19 +2226,13 @@ graph_size_location(image_desc_t *im, int elements /* reserve space for main and/or pie */ - if (im->extra_flags & ONLY_GRAPH) { - im->yimg = Ymain; - } else { - im->yimg = Ymain + Yxlabel; - } + im->yimg = Ymain + Yxlabel; +#ifdef WITH_PIECHART if (im->yimg < Ypie) im->yimg = Ypie; +#endif - if (im->extra_flags & ONLY_GRAPH) { - im->yorigin = im->yimg; - } else { - im->yorigin = im->yimg - Yxlabel; - } + im->yorigin = im->yimg - Yxlabel; /* reserve space for the title *or* some padding above the graph */ if (Ytitle) { @@ -2422,81 +2444,70 @@ graph_paint(image_desc_t *im, char ***calcpr) } } /* for */ - - if (im->gdes[i].col != 0x0){ + + /* ******************************************************* + ___ + | | ___ + ____| | | | + | |___| + -------|--------------------------------------- + + if we know the value of y at time t was a then + we draw a square from t-1 to t with the value a. + + ********************************************************* */ + if (im->gdes[i].col != 0x0){ /* GF_LINE and friend */ if(stack_gf == GF_LINE ){ node = NULL; for(ii=1;iixsize;ii++){ - if ( ! isnan(im->gdes[i].p_data[ii-1]) - && ! isnan(im->gdes[i].p_data[ii])){ - if (node == NULL){ - node = gfx_new_line(im->canvas, - ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]), + if (isnan(im->gdes[i].p_data[ii])){ + node = NULL; + continue; + } + if ( node == NULL ) { + node = gfx_new_line(im->canvas, + ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii]), ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]), im->gdes[i].linewidth, im->gdes[i].col); - } else { - gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii])); - } - } else { - node = NULL; - } + } else { + gfx_add_point(node,ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii])); + gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii])); + }; + } } else { - int area_start=-1; - node = NULL; for(ii=1;iixsize;ii++){ - /* open an area */ - if ( ! isnan(im->gdes[i].p_data[ii-1]) - && ! isnan(im->gdes[i].p_data[ii])){ - if (node == NULL){ - float ybase = 0.0; -/* - if (im->gdes[i].gf == GF_STACK) { -*/ - if ( (im->gdes[i].gf == GF_STACK) - || (im->gdes[i].stack) ) { - - ybase = ytr(im,lastgdes->p_data[ii-1]); - } else { - ybase = ytr(im,areazero); - } - area_start = ii-1; - node = gfx_new_area(im->canvas, - ii-1+im->xorigin,ybase, - ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]), - ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]), - im->gdes[i].col - ); - } else { - gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii])); - } + /* keep things simple for now, just draw these bars + do not try to build a big and complex area */ + float ybase,ytop; + if ( isnan(im->gdes[i].p_data[ii]) ) { + continue; + } + ytop = ytr(im,im->gdes[i].p_data[ii]); + if ( im->gdes[i].stack ) { + ybase = ytr(im,lastgdes->p_data[ii]); + } else { + ybase = ytr(im,areazero); } - - if ( node != NULL && (ii+1==im->xsize || isnan(im->gdes[i].p_data[ii]) )){ - /* GF_AREA STACK type*/ -/* - if (im->gdes[i].gf == GF_STACK ) { -*/ - if ( (im->gdes[i].gf == GF_STACK) - || (im->gdes[i].stack) ) { - int iii; - for (iii=ii-1;iii>area_start;iii--){ - gfx_add_point(node,iii+im->xorigin,ytr(im,lastgdes->p_data[iii])); - } - } else { - gfx_add_point(node,ii+im->xorigin,ytr(im,areazero)); - }; - node=NULL; - }; + if ( ybase == ytop ){ + continue; + } + node = gfx_new_area(im->canvas, + ii-1+im->xorigin,ybase, + ii-1+im->xorigin,ytop, + ii+im->xorigin,ytop, + im->gdes[i].col + ); + gfx_add_point(node,ii+im->xorigin,ybase); } } /* else GF_LINE */ } /* if color != 0x0 */ /* make sure we do not run into trouble when stacking on NaN */ for(ii=0;iixsize;ii++){ if (isnan(im->gdes[i].p_data[ii])) { - if (lastgdes && (im->gdes[i].gf == GF_STACK)) { + if (lastgdes && (im->gdes[i].stack)) { im->gdes[i].p_data[ii] = lastgdes->p_data[ii]; } else { im->gdes[i].p_data[ii] = ytr(im,areazero); @@ -2529,12 +2540,14 @@ graph_paint(image_desc_t *im, char ***calcpr) } #endif - if( !(im->extra_flags & ONLY_GRAPH) ) - axis_paint(im); /* grid_paint also does the text */ if( !(im->extra_flags & ONLY_GRAPH) ) grid_paint(im); + + + if( !(im->extra_flags & ONLY_GRAPH) ) + axis_paint(im); /* the RULES are the last thing to paint ... */ for(i=0;igdes_c;i++){ @@ -2570,7 +2583,7 @@ graph_paint(image_desc_t *im, char ***calcpr) if (strcmp(im->graphfile,"-")==0) { fo = im->graphhandle ? im->graphhandle : stdout; -#ifdef WIN32 +#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) /* Change translation mode for stdout to BINARY */ _setmode( _fileno( fo ), O_BINARY ); #endif @@ -2737,7 +2750,9 @@ rrd_graph_init(image_desc_t *im) #ifdef HAVE_SETLOCALE setlocale(LC_TIME,""); #endif - + im->yorigin=0; + im->xorigin=0; + im->minval=0; im->xlab_user.minsec = -1; im->ximg=0; im->yimg=0; @@ -2749,6 +2764,9 @@ rrd_graph_init(image_desc_t *im) im->minval = DNAN; im->maxval = DNAN; im->unitsexponent= 9999; + im->unitslength= 6; + im->symbol = ' '; + im->viewfactor = 1.0; im->extra_flags= 0; im->rigid = 0; im->gridfit = 1; @@ -2769,19 +2787,34 @@ rrd_graph_init(image_desc_t *im) for(i=0;igraph_col[i]=graph_col[i]; -#ifdef WIN32 + +#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) { char *windir; + char rrd_win_default_font[1000]; windir = getenv("windir"); /* %windir% is something like D:\windows or C:\winnt */ if (windir != NULL) { - strcpy(rrd_win_default_font,windir); + strncpy(rrd_win_default_font,windir,999); + rrd_win_default_font[999] = '\0'; strcat(rrd_win_default_font,"\\fonts\\cour.ttf"); - for(i=0;itext_prop[i].size = text_prop[i].size; strcpy(im->text_prop[i].font,text_prop[i].font); @@ -2832,17 +2865,18 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) {"no-minor", no_argument, 0, 'I'}, {"alt-autoscale", no_argument, 0, 'A'}, {"alt-autoscale-max", no_argument, 0, 'M'}, + {"no-gridfit", no_argument, 0, 'N'}, {"units-exponent",required_argument, 0, 'X'}, + {"units-length",required_argument, 0, 'L'}, {"step", required_argument, 0, 'S'}, {"tabwidth", required_argument, 0, 'T'}, - {"no-gridfit", no_argument, 0, 'N'}, {0,0,0,0}}; int option_index = 0; int opt; - + int col_start,col_end; opt = getopt_long(argc, argv, - "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMX:S:NT:", + "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMX:L:S:T:N", long_options, &option_index); if (opt == EOF) @@ -2873,13 +2907,16 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) case 'X': im->unitsexponent = atoi(optarg); break; + case 'L': + im->unitslength = atoi(optarg); + break; case 'T': im->tabwidth = atof(optarg); break; case 'S': im->step = atoi(optarg); break; - case 262: + case 'N': im->gridfit = 0; break; case 's': @@ -2911,6 +2948,7 @@ 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); + im->xlab_form[sizeof(im->xlab_form)-1] = '\0'; if((int)(im->xlab_user.gridtm = tmt_conv(scan_gtm)) == -1){ rrd_set_error("unknown keyword %s",scan_gtm); return; @@ -3009,13 +3047,25 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) break; case 'c': if(sscanf(optarg, - "%10[A-Z]#%8lx", - col_nam,&color) == 2){ + "%10[A-Z]#%n%8lx%n", + col_nam,&col_start,&color,&col_end) == 2){ int ci; + int col_len = col_end - col_start; + switch (col_len){ + case 6: + color = (color << 8) + 0xff /* shift left by 8 */; + break; + case 8: + break; + default: + rrd_set_error("the color format is #RRGGBB[AA]"); + return; + } if((ci=grc_conv(col_nam)) != -1){ im->graph_col[ci]=color; } else { rrd_set_error("invalid color name '%s'",col_nam); + return; } } else { rrd_set_error("invalid color def format");