* rrd__graph.c make creates ne rrds
****************************************************************************/
-#if 0
-#include "rrd_tool.h"
-#endif
#include <sys/stat.h>
+
+#include "rrd_tool.h"
+
#ifdef WIN32
#include <io.h>
#include <fcntl.h>
#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
#include "rrd_graph.h"
#include "rrd_graph_helper.h"
#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"
/* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/Arial.ttf" */
#endif
+#endif
text_prop_t text_prop[] = {
}
/* translate data values into y coordinates */
-int
+double
ytr(image_desc_t *im, double value){
static double pixie;
double yval;
pixie = (double) im->ysize / (log10(im->maxval) - log10(im->minval));
yval = im->yorigin;
} else if(!im->logarithmic) {
- yval = im->yorigin - pixie * (value - im->minval) + 0.5;
+ yval = im->yorigin - pixie * (value - im->minval);
} else {
if (value < im->minval) {
yval = im->yorigin;
} else {
- yval = im->yorigin - pixie * (log10(value) - log10(im->minval)) + 0.5;
+ 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) {
- return (int)yval;
- } else if ((int)yval > im->yorigin) {
- return im->yorigin+2;
- } else if ((int) yval < im->yorigin - im->ysize){
- return im->yorigin - im->ysize - 2;
- } else {
- return (int)yval;
+ /* keep yval as-is */
+ } else if (yval > im->yorigin) {
+ yval = im->yorigin+2;
+ } else if (yval < im->yorigin - im->ysize){
+ yval = im->yorigin - im->ysize - 2;
}
+ return yval;
}
conv_if(CDEF,GF_CDEF)
conv_if(VDEF,GF_VDEF)
conv_if(PART,GF_PART)
+ conv_if(XPORT,GF_XPORT)
return (-1);
}
conv_if(PNG,IF_PNG)
conv_if(SVG,IF_SVG)
+ conv_if(EPS,IF_EPS)
+ conv_if(PDF,IF_PDF)
return (-1);
}
#endif
}
-
+void
+apply_gridfit(image_desc_t *im)
+{
+ if (isnan(im->minval) || isnan(im->maxval))
+ return;
+ ytr(im,DNAN);
+ if (im->logarithmic) {
+ double ya, yb, ypix, ypixfrac;
+ double log10_range = log10(im->maxval) - log10(im->minval);
+ ya = pow((double)10, floor(log10(im->minval)));
+ while (ya < im->minval)
+ ya *= 10;
+ if (ya > im->maxval)
+ return; /* don't have y=10^x gridline */
+ yb = ya * 10;
+ if (yb <= im->maxval) {
+ /* we have at least 2 y=10^x gridlines.
+ Make sure distance between them in pixels
+ are an integer by expanding im->maxval */
+ double y_pixel_delta = ytr(im, ya) - ytr(im, yb);
+ double factor = y_pixel_delta / floor(y_pixel_delta);
+ double new_log10_range = factor * log10_range;
+ double new_ymax_log10 = log10(im->minval) + new_log10_range;
+ im->maxval = pow(10, new_ymax_log10);
+ ytr(im, DNAN); /* reset precalc */
+ log10_range = log10(im->maxval) - log10(im->minval);
+ }
+ /* make sure first y=10^x gridline is located on
+ integer pixel position by moving scale slightly
+ downwards (sub-pixel movement) */
+ ypix = ytr(im, ya) + im->ysize; /* add im->ysize so it always is positive */
+ ypixfrac = ypix - floor(ypix);
+ if (ypixfrac > 0 && ypixfrac < 1) {
+ double yfrac = ypixfrac / im->ysize;
+ im->minval = pow(10, log10(im->minval) - yfrac * log10_range);
+ im->maxval = pow(10, log10(im->maxval) - yfrac * log10_range);
+ ytr(im, DNAN); /* reset precalc */
+ }
+ } else {
+ /* Make sure we have an integer pixel distance between
+ each minor gridline */
+ double ypos1 = ytr(im, im->minval);
+ double ypos2 = ytr(im, im->minval + im->ygrid_scale.gridstep);
+ double y_pixel_delta = ypos1 - ypos2;
+ double factor = y_pixel_delta / floor(y_pixel_delta);
+ double new_range = factor * (im->maxval - im->minval);
+ double gridstep = im->ygrid_scale.gridstep;
+ double minor_y, minor_y_px, minor_y_px_frac;
+ im->maxval = im->minval + new_range;
+ ytr(im, DNAN); /* reset precalc */
+ /* make sure first minor gridline is on integer pixel y coord */
+ minor_y = gridstep * floor(im->minval / gridstep);
+ while (minor_y < im->minval)
+ minor_y += gridstep;
+ minor_y_px = ytr(im, minor_y) + im->ysize; /* ensure > 0 by adding ysize */
+ minor_y_px_frac = minor_y_px - floor(minor_y_px);
+ if (minor_y_px_frac > 0 && minor_y_px_frac < 1) {
+ double yfrac = minor_y_px_frac / im->ysize;
+ double range = im->maxval - im->minval;
+ im->minval = im->minval - yfrac * range;
+ im->maxval = im->maxval - yfrac * range;
+ ytr(im, DNAN); /* reset precalc */
+ }
+ calc_horizontal_grid(im); /* recalc with changed im->maxval */
+ }
+}
+
/* reduce data reimplementation by Alex */
void
* so CDEFs can use VDEFs and vice versa
*/
switch (im->gdes[gdi].gf) {
+ case GF_XPORT:
+ 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.
case GF_CDEF:
case GF_VDEF:
case GF_PART:
+ case GF_XPORT:
break;
}
}
}
}
break;
- case GF_COMMENT:
case GF_LINE:
case GF_AREA:
case GF_TICK:
case GF_VRULE:
graphelement = 1;
break;
+ case GF_COMMENT:
case GF_DEF:
case GF_CDEF:
case GF_VDEF:
case GF_PART:
+ case GF_XPORT:
break;
}
}
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->ygif;
+ int leg_x = border, leg_y = im->yimg;
int leg_cc;
int glue = 0;
int i,ii, mark = 0;
if (i == im->gdes_c -1 ) prt_fctn ='l';
/* is it time to place the legends ? */
- if (fill > im->xgif - 2*border){
+ if (fill > im->ximg - 2*border){
if (leg_c > 1) {
/* go back one */
i--;
if (prt_fctn != '\0'){
leg_x = border;
if (leg_c >= 2 && prt_fctn == 'j') {
- glue = (im->xgif - fill - 2* border) / (leg_c-1);
+ glue = (im->ximg - fill - 2* border) / (leg_c-1);
} else {
glue = 0;
}
- if (prt_fctn =='c') leg_x = (im->xgif - fill) / 2.0;
- if (prt_fctn =='r') leg_x = im->xgif - fill - border;
+ 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')
mark = ii;
}
}
- im->ygif = leg_y;
+ im->yimg = leg_y;
free(legspace);
}
return 0;
int
-horizontal_grid(image_desc_t *im)
+calc_horizontal_grid(image_desc_t *im)
{
double range;
double scaledrange;
int pixel,i;
- int sgrid,egrid;
- double gridstep;
- double scaledstep;
- char graph_label[100];
- double x0,x1,y0;
- int labfact,gridind;
+ int gridind;
int decimals, fractionals;
- char labfmt[64];
- labfact=2;
+ im->ygrid_scale.labfact=2;
gridind=-1;
range = im->maxval - im->minval;
scaledrange = range / im->magfact;
fractionals = floor(log10(range));
if(fractionals < 0) /* small amplitude. */
- sprintf(labfmt, "%%%d.%df", decimals - fractionals + 1, -fractionals + 1);
+ sprintf(im->ygrid_scale.labfmt, "%%%d.%df", decimals - fractionals + 1, -fractionals + 1);
else
- sprintf(labfmt, "%%%d.1f", decimals + 1);
- gridstep = pow((double)10, (double)fractionals);
- if(gridstep == 0) /* range is one -> 0.1 is reasonable scale */
- gridstep = 0.1;
+ sprintf(im->ygrid_scale.labfmt, "%%%d.1f", decimals + 1);
+ 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;
/* should have at least 5 lines but no more then 15 */
- if(range/gridstep < 5)
- gridstep /= 10;
- if(range/gridstep > 15)
- gridstep *= 10;
- if(range/gridstep > 5) {
- labfact = 1;
- if(range/gridstep > 8)
- labfact = 2;
+ if(range/im->ygrid_scale.gridstep < 5)
+ 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.labfact = 2;
}
else {
- gridstep /= 5;
- labfact = 5;
+ im->ygrid_scale.gridstep /= 5;
+ im->ygrid_scale.labfact = 5;
}
}
else {
for(i=0; i<4;i++) {
if (pixel * ylab[gridind].lfac[i] >= 2 * im->text_prop[TEXT_PROP_AXIS].size) {
- labfact = ylab[gridind].lfac[i];
+ im->ygrid_scale.labfact = ylab[gridind].lfac[i];
break;
}
}
- gridstep = ylab[gridind].grid * im->magfact;
+ im->ygrid_scale.gridstep = ylab[gridind].grid * im->magfact;
}
} else {
- gridstep = im->ygridstep;
- labfact = im->ylabfact;
+ im->ygrid_scale.gridstep = im->ygridstep;
+ im->ygrid_scale.labfact = im->ylabfact;
}
-
- x0=im->xorigin;
- x1=im->xorigin+im->xsize;
+ return 1;
+}
+
+int draw_horizontal_grid(image_desc_t *im)
+{
+ int i;
+ double scaledstep;
+ char graph_label[100];
+ double X0=im->xorigin;
+ double X1=im->xorigin+im->xsize;
- sgrid = (int)( im->minval / gridstep - 1);
- egrid = (int)( im->maxval / gridstep + 1);
- scaledstep = gridstep/im->magfact;
+ int sgrid = (int)( im->minval / im->ygrid_scale.gridstep - 1);
+ int egrid = (int)( im->maxval / im->ygrid_scale.gridstep + 1);
+ scaledstep = im->ygrid_scale.gridstep/im->magfact;
for (i = sgrid; i <= egrid; i++){
- y0=ytr(im,gridstep*i);
- if ( y0 >= im->yorigin-im->ysize
- && y0 <= im->yorigin){
- if(i % labfact == 0){
+ double Y0=ytr(im,im->ygrid_scale.gridstep*i);
+ if ( Y0 >= im->yorigin-im->ysize
+ && Y0 <= im->yorigin){
+ if(i % im->ygrid_scale.labfact == 0){
if (i==0 || im->symbol == ' ') {
if(scaledstep < 1){
if(im->extra_flags & ALTYGRID) {
- sprintf(graph_label,labfmt,scaledstep*i);
+ sprintf(graph_label,im->ygrid_scale.labfmt,scaledstep*i);
}
else {
sprintf(graph_label,"%4.1f",scaledstep*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/1.5, Y0,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size,
im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER,
graph_label );
- gfx_new_line ( im->canvas,
- x0-2,y0,
- x1+2,y0,
- MGRIDWIDTH, im->graph_col[GRC_MGRID] );
+ gfx_new_dashed_line ( im->canvas,
+ X0-2,Y0,
+ X1+2,Y0,
+ MGRIDWIDTH, im->graph_col[GRC_MGRID],
+ im->grid_dash_on, im->grid_dash_off);
} else {
- gfx_new_line ( im->canvas,
- x0-1,y0,
- x1+1,y0,
- GRIDWIDTH, im->graph_col[GRC_GRID] );
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
}
}
int ii,i;
int minoridx=0, majoridx=0;
char graph_label[100];
- double x0,x1,y0;
+ double X0,X1,Y0;
double value, pixperstep, minstep;
/* find grid spaceing */
if(pixperstep > 2 * im->text_prop[TEXT_PROP_LEGEND].size){majoridx = i;}
}
- x0=im->xorigin;
- x1=im->xorigin+im->xsize;
+ X0=im->xorigin;
+ X1=im->xorigin+im->xsize;
/* paint minor grid */
for (value = pow((double)10, log10(im->minval)
- fmod(log10(im->minval),log10(yloglab[minoridx][0])));
if (value < im->minval) continue;
i=0;
while(yloglab[minoridx][++i] > 0){
- y0 = ytr(im,value * yloglab[minoridx][i]);
- if (y0 <= im->yorigin - im->ysize) break;
- gfx_new_line ( im->canvas,
- x0-1,y0,
- x1+1,y0,
- GRIDWIDTH, im->graph_col[GRC_GRID] );
+ Y0 = ytr(im,value * yloglab[minoridx][i]);
+ if (Y0 <= im->yorigin - im->ysize) break;
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
}
}
if (value < im->minval) continue;
i=0;
while(yloglab[majoridx][++i] > 0){
- y0 = ytr(im,value * yloglab[majoridx][i]);
- if (y0 <= im->yorigin - im->ysize) break;
- gfx_new_line ( im->canvas,
- x0-2,y0,
- x1+2,y0,
- MGRIDWIDTH, im->graph_col[GRC_MGRID] );
+ Y0 = ytr(im,value * yloglab[majoridx][i]);
+ if (Y0 <= im->yorigin - im->ysize) break;
+ gfx_new_dashed_line ( im->canvas,
+ X0-2,Y0,
+ X1+2,Y0,
+ MGRIDWIDTH, im->graph_col[GRC_MGRID],
+ im->grid_dash_on, im->grid_dash_off);
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/1.5, Y0,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size,
image_desc_t *im )
{
int xlab_sel; /* which sort of label and grid ? */
- time_t ti, tilab;
+ time_t ti, tilab, timajor;
long factor;
char graph_label[100];
- double x0,y0,y1; /* points for filled graph and more*/
+ double X0,Y0,Y1; /* points for filled graph and more*/
/* the type of time grid is determined by finding
}
/* y coords are the same for every line ... */
- y0 = im->yorigin;
- y1 = im->yorigin-im->ysize;
+ Y0 = im->yorigin;
+ Y1 = im->yorigin-im->ysize;
/* paint the minor grid */
for(ti = find_first_time(im->start,
im->xlab_user.gridtm,
- im->xlab_user.gridst);
+ im->xlab_user.gridst),
+ timajor = find_first_time(im->start,
+ im->xlab_user.mgridtm,
+ im->xlab_user.mgridst);
ti < im->end;
ti = find_next_time(ti,im->xlab_user.gridtm,im->xlab_user.gridst)
){
/* are we inside the graph ? */
if (ti < im->start || ti > im->end) continue;
- x0 = xtr(im,ti);
- gfx_new_line(im->canvas,x0,y0+1, x0,y1-1,GRIDWIDTH, im->graph_col[GRC_GRID]);
+ while (timajor < ti) {
+ timajor = find_next_time(timajor,
+ im->xlab_user.mgridtm, im->xlab_user.mgridst);
+ }
+ if (ti == timajor) continue; /* skip as falls on major grid line */
+ X0 = xtr(im,ti);
+ gfx_new_dashed_line(im->canvas,X0,Y0+1, X0,Y1-1,GRIDWIDTH,
+ im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
}
){
/* are we inside the graph ? */
if (ti < im->start || ti > im->end) continue;
- x0 = xtr(im,ti);
- gfx_new_line(im->canvas,x0,y0+2, x0,y1-2,MGRIDWIDTH, im->graph_col[GRC_MGRID]);
+ X0 = xtr(im,ti);
+ gfx_new_dashed_line(im->canvas,X0,Y0+3, X0,Y1-2,MGRIDWIDTH,
+ im->graph_col[GRC_MGRID],
+ im->grid_dash_on, im->grid_dash_off);
}
/* paint the labels below the graph */
# 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/1.5,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size,
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+8, im->yorigin+0.5, /* LINEOFFSET */
im->graph_col[GRC_ARROW]);
{
long i;
int res=0;
- double x0,y0; /* points for filled graph and more*/
+ double X0,Y0; /* points for filled graph and more*/
gfx_node_t *node;
/* draw 3d border */
- node = gfx_new_area (im->canvas, 0,im->ygif,
- 2,im->ygif-2,
+ node = gfx_new_area (im->canvas, 0,im->yimg,
+ 2,im->yimg-2,
2,2,im->graph_col[GRC_SHADEA]);
- gfx_add_point( node , im->xgif - 2, 2 );
- gfx_add_point( node , im->xgif, 0 );
+ gfx_add_point( node , im->ximg - 2, 2 );
+ gfx_add_point( node , im->ximg, 0 );
gfx_add_point( node , 0,0 );
-/* gfx_add_point( node , 0,im->ygif ); */
+/* gfx_add_point( node , 0,im->yimg ); */
- node = gfx_new_area (im->canvas, 2,im->ygif-2,
- im->xgif-2,im->ygif-2,
- im->xgif - 2, 2,
+ node = gfx_new_area (im->canvas, 2,im->yimg-2,
+ im->ximg-2,im->yimg-2,
+ im->ximg - 2, 2,
im->graph_col[GRC_SHADEB]);
- gfx_add_point( node , im->xgif,0);
- gfx_add_point( node , im->xgif,im->ygif);
- gfx_add_point( node , 0,im->ygif);
-/* gfx_add_point( node , 0,im->ygif ); */
+ gfx_add_point( node , im->ximg,0);
+ gfx_add_point( node , im->ximg,im->yimg);
+ gfx_add_point( node , 0,im->yimg);
+/* gfx_add_point( node , 0,im->yimg ); */
if (im->draw_x_grid == 1 )
if(im->logarithmic){
res = horizontal_log_grid(im);
} else {
- res = horizontal_grid(im);
+ res = draw_horizontal_grid(im);
}
/* dont draw horizontal grid if there is no min and max val */
if (! res ) {
char *nodata = "No Data found";
- gfx_new_text(im->canvas,im->xgif/2, (2*im->yorigin-im->ysize) / 2,
+ gfx_new_text(im->canvas,im->ximg/2, (2*im->yorigin-im->ysize) / 2,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size,
/* graph title */
gfx_new_text( im->canvas,
- im->xgif/2, im->text_prop[TEXT_PROP_TITLE].size,
+ im->ximg/2, im->text_prop[TEXT_PROP_TITLE].size,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_TITLE].font,
im->text_prop[TEXT_PROP_TITLE].size, im->tabwidth, 0.0,
continue;
/* im->gdes[i].leg_y is the bottom of the legend */
- x0 = im->gdes[i].leg_x;
- y0 = im->gdes[i].leg_y;
+ X0 = im->gdes[i].leg_x;
+ Y0 = im->gdes[i].leg_y;
/* Box needed? */
if ( im->gdes[i].gf != GF_GPRINT
&& im->gdes[i].gf != GF_COMMENT) {
boxV = boxH;
node = gfx_new_area(im->canvas,
- x0,y0-boxV,
- x0,y0,
- x0+boxH,y0,
+ X0,Y0-boxV,
+ X0,Y0,
+ X0+boxH,Y0,
im->gdes[i].col);
- gfx_add_point ( node, x0+boxH, y0-boxV );
+ gfx_add_point ( node, X0+boxH, Y0-boxV );
node = gfx_new_line(im->canvas,
- x0,y0-boxV, x0,y0,
+ X0,Y0-boxV, X0,Y0,
1,0x000000FF);
- gfx_add_point(node,x0+boxH,y0);
- gfx_add_point(node,x0+boxH,y0-boxV);
+ gfx_add_point(node,X0+boxH,Y0);
+ gfx_add_point(node,X0+boxH,Y0-boxV);
gfx_close_path(node);
- x0 += boxH / 1.25 * 2;
+ X0 += boxH / 1.25 * 2;
}
- gfx_new_text ( im->canvas, x0, y0,
+ gfx_new_text ( im->canvas, X0, Y0,
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size,
int lazy_check(image_desc_t *im){
FILE *fd = NULL;
int size = 1;
- struct stat gifstat;
+ struct stat imgstat;
if (im->lazy == 0) return 0; /* no lazy option */
- if (stat(im->graphfile,&gifstat) != 0)
+ if (stat(im->graphfile,&imgstat) != 0)
return 0; /* can't stat */
/* one pixel in the existing graph is more then what we would
change here ... */
- if (time(NULL) - gifstat.st_mtime >
+ if (time(NULL) - imgstat.st_mtime >
(im->end - im->start) / im->xsize)
return 0;
if ((fd = fopen(im->graphfile,"rb")) == NULL)
return 0; /* the file does not exist */
switch (im->canvas->imgformat) {
case IF_PNG:
- size = PngSize(fd,&(im->xgif),&(im->ygif));
+ size = PngSize(fd,&(im->ximg),&(im->yimg));
break;
default:
size = 1;
Xmain =0, Ymain =0,
Xpie =0, Ypie =0,
Xxlabel =0, Yxlabel =0,
+#if 0
Xlegend =0, Ylegend =0,
+#endif
Xspacing =10, Yspacing =10;
if (im->ylegend[0] != '\0') {
** forget about it at all; the legend will have to fit in the
** size already allocated.
*/
- im->xgif = Xylabel + Xmain + Xpie + Xspacing;
- if (Xmain) im->xgif += Xspacing;
- if (Xpie) im->xgif += Xspacing;
+ im->ximg = Xylabel + Xmain + Xpie + Xspacing;
+ if (Xmain) im->ximg += Xspacing;
+ if (Xpie) im->ximg += Xspacing;
im->xorigin = Xspacing + Xylabel;
- if (Xtitle > im->xgif) im->xgif = Xtitle;
+ if (Xtitle > im->ximg) im->ximg = Xtitle;
if (Xvertical) {
- im->xgif += Xvertical;
+ im->ximg += Xvertical;
im->xorigin += Xvertical;
}
xtr(im,0);
*/
/* reserve space for main and/or pie */
- im->ygif = Ymain + Yxlabel;
- if (im->ygif < Ypie) im->ygif = Ypie;
- im->yorigin = im->ygif - Yxlabel;
+ im->yimg = Ymain + Yxlabel;
+ if (im->yimg < Ypie) im->yimg = Ypie;
+ im->yorigin = im->yimg - Yxlabel;
/* reserve space for the title *or* some padding above the graph */
if (Ytitle) {
- im->ygif += Ytitle;
+ im->yimg += Ytitle;
im->yorigin += Ytitle;
} else {
- im->ygif += Yspacing;
+ im->yimg += Yspacing;
im->yorigin += Yspacing;
}
/* reserve space for padding below the graph */
- im->ygif += Yspacing;
+ im->yimg += Yspacing;
ytr(im,DNAN);
/* Determine where to place the legends onto the image.
- ** Adjust im->ygif to match the space requirements.
+ ** Adjust im->yimg to match the space requirements.
*/
if(leg_place(im)==-1)
return -1;
/* last of three steps: check total height of image */
- if (im->ygif < Yvertical) im->ygif = Yvertical;
+ if (im->yimg < Yvertical) im->yimg = Yvertical;
#if 0
- if (Xlegend > im->xgif) {
- im->xgif = Xlegend;
+ if (Xlegend > im->ximg) {
+ im->ximg = Xlegend;
/* reposition Pie */
#endif
** padding.
*/
if (elements) {
- im->pie_x = im->xgif - Xspacing - Xpie/2;
+ im->pie_x = im->ximg - Xspacing - Xpie/2;
im->pie_y = im->yorigin-Ymain+Ypie/2;
} else {
- im->pie_x = im->xgif/2;
+ im->pie_x = im->ximg/2;
im->pie_y = im->yorigin-Ypie/2;
}
expand_range(im); /* make sure the upper and lower limit are
sensible values */
+ 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. ***
node=gfx_new_area ( im->canvas,
0, 0,
- im->xgif, 0,
- im->xgif, im->ygif,
+ im->ximg, 0,
+ im->ximg, im->yimg,
im->graph_col[GRC_BACK]);
- gfx_add_point(node,0, im->ygif);
+ gfx_add_point(node,0, im->yimg);
if (piechart != 2) {
node=gfx_new_area ( im->canvas,
case GF_COMMENT:
case GF_HRULE:
case GF_VRULE:
+ case GF_XPORT:
break;
case GF_TICK:
for (ii = 0; ii < im->xsize; ii++)
return (-1);
}
}
- gfx_render (im->canvas,im->xgif,im->ygif,0x0,fo);
+ gfx_render (im->canvas,im->ximg,im->yimg,0x0,fo);
if (strcmp(im->graphfile,"-") != 0)
fclose(fo);
return 0;
{
image_desc_t im;
+#ifdef HAVE_TZSET
+ tzset();
+#endif
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_TIME,"");
+#endif
+
+
rrd_graph_init(&im);
rrd_graph_options(argc,argv,&im);
** Also, if needed, print a line with information about the image.
*/
- *xsize=im.xgif;
- *ysize=im.ygif;
+ *xsize=im.ximg;
+ *ysize=im.yimg;
if (im.imginfo) {
char *filename;
if (!(*prdata)) {
filename--;
}
- sprintf((*prdata)[0],im.imginfo,filename,(long)(im.canvas->zoom*im.xgif),(long)(im.canvas->zoom*im.ygif));
+ sprintf((*prdata)[0],im.imginfo,filename,(long)(im.canvas->zoom*im.ximg),(long)(im.canvas->zoom*im.yimg));
}
im_free(&im);
return 0;
int i;
im->xlab_user.minsec = -1;
- im->xgif=0;
- im->ygif=0;
+ im->ximg=0;
+ im->yimg=0;
im->xsize = 400;
im->ysize = 100;
im->step = 0;
im->unitsexponent= 9999;
im->extra_flags= 0;
im->rigid = 0;
+ im->gridfit = 1;
im->imginfo = NULL;
im->lazy = 0;
im->logarithmic = 0;
im->gdes_c = 0;
im->gdes = NULL;
im->canvas = gfx_new_canvas();
+ im->grid_dash_on = 1;
+ im->grid_dash_off = 1;
for(i=0;i<DIM(graph_col);i++)
im->graph_col[i]=graph_col[i];
{"alt-autoscale-max", no_argument, 0, 259 },
{"units-exponent",required_argument, 0, 260},
{"step", required_argument, 0, 261},
+ {"no-gridfit", no_argument, 0, 262},
{0,0,0,0}};
int option_index = 0;
int opt;
case 261:
im->step = atoi(optarg);
break;
+ case 262:
+ im->gridfit = 0;
+ break;
case 's':
if ((parsetime_error = parsetime(optarg, &start_tv))) {
rrd_set_error( "start time: %s", parsetime_error );
/* If the error string is set, we exit at the end of the switch */
switch (gdp->gf) {
+ case GF_XPORT:
+ break;
case GF_COMMENT:
if (rrd_graph_legend(gdp,&line[argstart])==0)
rrd_set_error("Cannot parse comment in line: %s",line);
int bad_format(char *fmt) {
- char *ptr;
- int n=0;
-
- ptr = fmt;
- while (*ptr != '\0') {
- if (*ptr == '%') {ptr++;
- if (*ptr == '\0') return 1;
- while ((*ptr >= '0' && *ptr <= '9') || *ptr == '.') {
- ptr++;
- }
- if (*ptr == '\0') return 1;
- if (*ptr == 'l') {
- ptr++;
- n++;
- if (*ptr == '\0') return 1;
- if (*ptr == 'e' || *ptr == 'f') {
- ptr++;
- } else { return 1; }
- }
- else if (*ptr == 's' || *ptr == 'S' || *ptr == '%') { ++ptr; }
- else { return 1; }
- } else {
- ++ptr;
- }
- }
- return (n!=1);
+ char *ptr;
+ int n=0;
+ ptr = fmt;
+ while (*ptr != '\0')
+ if (*ptr++ == '%') {
+
+ /* line cannot end with percent char */
+ if (*ptr == '\0') return 1;
+
+ /* '%s', '%S' and '%%' are allowed */
+ if (*ptr == 's' || *ptr == 'S' || *ptr == '%') ptr++;
+
+ /* or else '% 6.2lf' and such are allowed */
+ else {
+
+ /* optional padding character */
+ if (*ptr == ' ' || *ptr == '+' || *ptr == '-') ptr++;
+
+ /* This should take care of 'm.n' with all three optional */
+ while (*ptr >= '0' && *ptr <= '9') ptr++;
+ if (*ptr == '.') ptr++;
+ while (*ptr >= '0' && *ptr <= '9') ptr++;
+
+ /* Either 'le' or 'lf' must follow here */
+ if (*ptr++ != 'l') return 1;
+ if (*ptr == 'e' || *ptr == 'f') ptr++;
+ else return 1;
+ n++;
+ }
+ }
+
+ return (n!=1);
}
+
+
int
vdef_parse(gdes,str)
struct graph_desc_t *gdes;
};
return 0;
}
+
+
int
vdef_calc(im,gdi)
image_desc_t *im;