* rrd__graph.c make creates ne rrds
****************************************************************************/
-#if 0
-#include "rrd_tool.h"
-#endif
#include <sys/stat.h>
#ifdef WIN32
#include <fcntl.h>
#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include "rrd_tool.h"
+
#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;
}
return (-1);
}
-enum if_en if_conv(char *string){
+enum gfx_if_en if_conv(char *string){
conv_if(PNG,IF_PNG)
+ conv_if(SVG,IF_SVG)
+ conv_if(EPS,IF_EPS)
return (-1);
}
free (im->gdes[i].rpnp);
}
free(im->gdes);
+ gfx_destroy(im->canvas);
return 0;
}
#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
}
}
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:
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;
im->gdes[i].gf != GF_COMMENT) {
fill += box;
}
- fill += gfx_get_text_width(fill+border,im->text_prop[TEXT_PROP_LEGEND].font,
+ fill += gfx_get_text_width(im->canvas, fill+border,
+ im->text_prop[TEXT_PROP_LEGEND].font,
im->text_prop[TEXT_PROP_LEGEND].size,
im->tabwidth,
im->gdes[i].legend);
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')
im->gdes[ii].leg_x = leg_x;
im->gdes[ii].leg_y = leg_y;
leg_x +=
- gfx_get_text_width(leg_x,im->text_prop[TEXT_PROP_LEGEND].font,
+ gfx_get_text_width(im->canvas, leg_x,
+ im->text_prop[TEXT_PROP_LEGEND].font,
im->text_prop[TEXT_PROP_LEGEND].size,
im->tabwidth,
im->gdes[ii].legend)
mark = ii;
}
}
- im->ygif = leg_y;
+ im->yimg = leg_y;
free(legspace);
}
return 0;
int
-horizontal_grid(gfx_canvas_t *canvas, 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,y1;
- 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 ( canvas,
- x0-im->text_prop[TEXT_PROP_AXIS].size/1.5, y0,
+ gfx_new_text ( im->canvas,
+ 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 ( canvas,
- x0-2,y0,
- x1+2,y0,
+ gfx_new_line ( im->canvas,
+ X0-2,Y0,
+ X1+2,Y0,
MGRIDWIDTH, im->graph_col[GRC_MGRID] );
} else {
- gfx_new_line ( canvas,
- x0-1,y0,
- x1+1,y0,
+ gfx_new_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
GRIDWIDTH, im->graph_col[GRC_GRID] );
}
/* logaritmic horizontal grid */
int
-horizontal_log_grid(gfx_canvas_t *canvas, image_desc_t *im)
+horizontal_log_grid(image_desc_t *im)
{
double pixpex;
int ii,i;
int minoridx=0, majoridx=0;
char graph_label[100];
- double x0,x1,y0,y1;
+ 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 ( canvas,
- x0-1,y0,
- x1+1,y0,
+ 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] );
}
}
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 ( canvas,
- x0-2,y0,
- x1+2,y0,
+ 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] );
sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
- gfx_new_text ( canvas,
- x0-im->text_prop[TEXT_PROP_AXIS].size/1.5, y0,
+ gfx_new_text ( im->canvas,
+ 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,
void
vertical_grid(
- gfx_canvas_t *canvas,
image_desc_t *im )
{
int xlab_sel; /* which sort of label and grid ? */
time_t ti, tilab;
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 */
){
/* are we inside the graph ? */
if (ti < im->start || ti > im->end) continue;
- x0 = xtr(im,ti);
- gfx_new_line(canvas,x0,y0+1, x0,y1-1,GRIDWIDTH, im->graph_col[GRC_GRID]);
+ X0 = xtr(im,ti);
+ gfx_new_line(im->canvas,X0,Y0+1, X0,Y1-1,GRIDWIDTH, im->graph_col[GRC_GRID]);
}
){
/* are we inside the graph ? */
if (ti < im->start || ti > im->end) continue;
- x0 = xtr(im,ti);
- gfx_new_line(canvas,x0,y0+2, x0,y1-2,MGRIDWIDTH, im->graph_col[GRC_MGRID]);
+ X0 = xtr(im,ti);
+ gfx_new_line(im->canvas,X0,Y0+2, X0,Y1-2,MGRIDWIDTH, im->graph_col[GRC_MGRID]);
}
/* paint the labels below the graph */
#else
# error "your libc has no strftime I guess we'll abort the exercise here."
#endif
- gfx_new_text ( canvas,
- xtr(im,tilab), y0+im->text_prop[TEXT_PROP_AXIS].size/1.5,
+ gfx_new_text ( im->canvas,
+ 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,
void
axis_paint(
- image_desc_t *im,
- gfx_canvas_t *canvas
+ image_desc_t *im
)
{
/* draw x and y axis */
- gfx_new_line ( canvas, im->xorigin+im->xsize,im->yorigin,
+ gfx_new_line ( im->canvas, im->xorigin+im->xsize,im->yorigin,
im->xorigin+im->xsize,im->yorigin-im->ysize,
GRIDWIDTH, im->graph_col[GRC_GRID]);
- gfx_new_line ( canvas, im->xorigin,im->yorigin-im->ysize,
+ gfx_new_line ( im->canvas, im->xorigin,im->yorigin-im->ysize,
im->xorigin+im->xsize,im->yorigin-im->ysize,
GRIDWIDTH, im->graph_col[GRC_GRID]);
- gfx_new_line ( canvas, im->xorigin-4,im->yorigin,
+ gfx_new_line ( im->canvas, im->xorigin-4,im->yorigin,
im->xorigin+im->xsize+4,im->yorigin,
MGRIDWIDTH, im->graph_col[GRC_GRID]);
- gfx_new_line ( canvas, im->xorigin,im->yorigin+4,
+ gfx_new_line ( im->canvas, im->xorigin,im->yorigin+4,
im->xorigin,im->yorigin-im->ysize-4,
MGRIDWIDTH, im->graph_col[GRC_GRID]);
/* arrow for X axis direction */
- gfx_new_area ( canvas,
- im->xorigin+im->xsize+4, im->yorigin-3,
- im->xorigin+im->xsize+4, im->yorigin+3,
- im->xorigin+im->xsize+9, im->yorigin,
+ 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->graph_col[GRC_ARROW]);
}
void
-grid_paint(
- image_desc_t *im,
- gfx_canvas_t *canvas
-
- )
+grid_paint(image_desc_t *im)
{
long i;
int res=0;
- double x0,x1,x2,x3,y0,y1,y2,y3; /* 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 (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 (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 )
- vertical_grid(canvas, im);
+ vertical_grid(im);
if (im->draw_y_grid == 1){
if(im->logarithmic){
- res = horizontal_log_grid(canvas,im);
+ res = horizontal_log_grid(im);
} else {
- res = horizontal_grid(canvas,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(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,
}
/* yaxis description */
- #if 0
- gfx_new_text( canvas,
+ if (im->canvas->imgformat != IF_PNG) {
+ 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->ylegend);
- #else
+ } else {
/* horrible hack until we can actually print vertically */
{
int n;
for (n=0;n<strlen(im->ylegend);n++) {
s[0]=im->ylegend[n];
s[1]='\0';
- gfx_new_text(canvas,7,im->text_prop[TEXT_PROP_AXIS].size*(l-n),
+ gfx_new_text(im->canvas,7,im->text_prop[TEXT_PROP_AXIS].size*(l-n),
im->graph_col[GRC_FONT],
im->text_prop[TEXT_PROP_AXIS].font,
im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 270.0,
s);
}
}
- #endif
+ }
/* graph title */
- gfx_new_text( canvas,
- im->xgif/2, im->text_prop[TEXT_PROP_TITLE].size,
+ gfx_new_text( im->canvas,
+ 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) {
int boxH, boxV;
- boxH = gfx_get_text_width(0,
+ 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;
boxV = boxH;
- node = gfx_new_area(canvas,
- x0,y0-boxV,
- x0,y0,
- x0+boxH,y0,
+ node = gfx_new_area(im->canvas,
+ X0,Y0-boxV,
+ X0,Y0,
+ X0+boxH,Y0,
im->gdes[i].col);
- gfx_add_point ( node, x0+boxH, y0-boxV );
- node = gfx_new_line(canvas,
- x0,y0-boxV, x0,y0,
+ gfx_add_point ( node, X0+boxH, Y0-boxV );
+ node = gfx_new_line(im->canvas,
+ 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,y0-boxV);
- x0 += boxH / 1.25 * 2;
+ gfx_add_point(node,X0+boxH,Y0);
+ gfx_add_point(node,X0+boxH,Y0-boxV);
+ gfx_close_path(node);
+ X0 += boxH / 1.25 * 2;
}
- gfx_new_text ( 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->imgformat) {
+ 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;
}
fclose(fd);
return size;
}
void
-pie_part(gfx_canvas_t *canvas, gfx_color_t color,
+pie_part(image_desc_t *im, gfx_color_t color,
double PieCenterX, double PieCenterY, double Radius,
double startangle, double endangle)
{
Radius *= 0.8;
}
- node=gfx_new_area(canvas,
+ node=gfx_new_area(im->canvas,
PieCenterX+sin(startangle)*Radius,
PieCenterY-cos(startangle)*Radius,
PieCenterX,
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') {
** automatically has some vertical spacing. The horizontal
** spacing is added here, on each side.
*/
- Xtitle = gfx_get_text_width(0,
+ Xtitle = gfx_get_text_width(im->canvas, 0,
im->text_prop[TEXT_PROP_TITLE].font,
im->text_prop[TEXT_PROP_TITLE].size,
im->tabwidth,
** 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;
}
int piechart = 0;
double PieStart=0.0;
FILE *fo;
- gfx_canvas_t *canvas;
gfx_node_t *node;
double areazero = 0.0;
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. ***
if(graph_size_location(im,i,piechart)==-1)
return -1;
- canvas=gfx_new_canvas();
-
/* the actual graph is created by going through the individual
graph elements and then drawing them */
- node=gfx_new_area ( canvas,
+ 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 ( canvas,
+ node=gfx_new_area ( im->canvas,
im->xorigin, im->yorigin,
im->xorigin + im->xsize, im->yorigin,
im->xorigin + im->xsize, im->yorigin-im->ysize,
if (im->maxval < 0.0)
areazero = im->maxval;
- axis_paint(im,canvas);
+ axis_paint(im);
}
if (piechart) {
- pie_part(canvas,im->graph_col[GRC_CANVAS],im->pie_x,im->pie_y,im->piesize*0.5,0,2*M_PI);
+ pie_part(im,im->graph_col[GRC_CANVAS],im->pie_x,im->pie_y,im->piesize*0.5,0,2*M_PI);
}
for(i=0;i<im->gdes_c;i++){
im->gdes[i].p_data[ii] > 0.0)
{
/* generate a tick */
- gfx_new_line(canvas, im -> xorigin + ii,
+ gfx_new_line(im->canvas, im -> xorigin + ii,
im -> yorigin - (im -> gdes[i].yrule * im -> ysize),
im -> xorigin + ii,
im -> yorigin,
if ( ! isnan(im->gdes[i].p_data[ii-1])
&& ! isnan(im->gdes[i].p_data[ii])){
if (node == NULL){
- node = gfx_new_line(canvas,
+ node = gfx_new_line(im->canvas,
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].linewidth,
ybase = ytr(im,areazero);
}
area_start = ii-1;
- node = gfx_new_area(canvas,
+ 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].yrule = im->gdes[im->gdes[i].vidx].vf.val;
if (finite(im->gdes[i].yrule)) { /* even the fetched var can be NaN */
- pie_part(canvas,im->gdes[i].col,
+ pie_part(im,im->gdes[i].col,
im->pie_x,im->pie_y,im->piesize*0.4,
M_PI*2.0*PieStart/100.0,
M_PI*2.0*(PieStart+im->gdes[i].yrule)/100.0);
im->draw_y_grid=0;
}
/* grid_paint also does the text */
- grid_paint(im,canvas);
+ grid_paint(im);
/* the RULES are the last thing to paint ... */
for(i=0;i<im->gdes_c;i++){
};
if(im->gdes[i].yrule >= im->minval
&& im->gdes[i].yrule <= im->maxval)
- gfx_new_line(canvas,
+ gfx_new_line(im->canvas,
im->xorigin,ytr(im,im->gdes[i].yrule),
im->xorigin+im->xsize,ytr(im,im->gdes[i].yrule),
1.0,im->gdes[i].col);
};
if(im->gdes[i].xrule >= im->start
&& im->gdes[i].xrule <= im->end)
- gfx_new_line(canvas,
+ gfx_new_line(im->canvas,
xtr(im,im->gdes[i].xrule),im->yorigin,
xtr(im,im->gdes[i].xrule),im->yorigin-im->ysize,
1.0,im->gdes[i].col);
return (-1);
}
}
- switch (im->imgformat) {
- case IF_PNG:
- gfx_render_png (canvas,im->xgif,im->ygif,im->zoom,0x0,fo);
- break;
- }
+ gfx_render (im->canvas,im->ximg,im->yimg,0x0,fo);
if (strcmp(im->graphfile,"-") != 0)
fclose(fo);
-
- gfx_destroy(canvas);
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.zoom*im.xgif),(long)(im.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->title[0] = '\0';
im->minval = DNAN;
im->maxval = DNAN;
- im->interlaced = 0;
im->unitsexponent= 9999;
im->extra_flags= 0;
im->rigid = 0;
+ im->gridfit = 1;
im->imginfo = NULL;
im->lazy = 0;
im->logarithmic = 0;
im->prt_c = 0;
im->gdes_c = 0;
im->gdes = NULL;
- im->zoom = 1.0;
- im->imgformat = IF_PNG; /* we default to PNG output */
+ im->canvas = gfx_new_canvas();
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 );
im->ysize = long_tmp;
break;
case 'i':
- im->interlaced = 1;
+ im->canvas->interlaced = 1;
break;
case 'r':
im->rigid = 1;
im->imginfo = optarg;
break;
case 'a':
- if((im->imgformat = if_conv(optarg)) == -1) {
+ if((im->canvas->imgformat = if_conv(optarg)) == -1) {
rrd_set_error("unsupported graphics format '%s'",optarg);
return;
}
break;
case 'c':
if(sscanf(optarg,
- "%10[A-Z]#%8x",
+ "%10[A-Z]#%8lx",
col_nam,&color) == 2){
int ci;
if((ci=grc_conv(col_nam)) != -1){
}
} else {
rrd_set_error("invalid color def format");
- return -1;
+ return;
}
break;
case 'n':{
break;
}
case 'm':
- im->zoom= atof(optarg);
- if (im->zoom <= 0.0) {
+ im->canvas->zoom = atof(optarg);
+ if (im->canvas->zoom <= 0.0) {
rrd_set_error("zoom factor must be > 0");
return;
}
switch (n) {
case 7:
- sscanf(color,"#%6x%n",&col,&n);
+ sscanf(color,"#%6lx%n",&col,&n);
col = (col << 8) + 0xff /* shift left by 8 */;
if (n!=7) rrd_set_error("Color problem in %s",err);
break;
case 9:
- sscanf(color,"#%8x%n",&col,&n);
+ sscanf(color,"#%8lx%n",&col,&n);
if (n==9) break;
default:
rrd_set_error("Color problem in %s",err);