return (-1);
}
-enum if_en if_conv(char *string){
+enum gfx_if_en if_conv(char *string){
- conv_if(GIF,IF_GIF)
conv_if(PNG,IF_PNG)
+ conv_if(SVG,IF_SVG)
return (-1);
}
free (im->gdes[i].rpnp);
}
free(im->gdes);
+ gfx_destroy(im->canvas);
return 0;
}
} /* if OP_VARIABLE */
} /* loop through all rpi */
+ /* move the data pointers to the correct period */
+ for(rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){
+ if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE){
+ 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;
+ }
+ }
+ }
+
+
if(steparray == NULL){
rrd_set_error("rpn expressions without DEF"
" or CDEF variables are not supported");
}
}
break;
- case GF_COMMENT:
case GF_LINE:
case GF_AREA:
case GF_TICK:
- case GF_PART:
case GF_STACK:
case GF_HRULE:
case GF_VRULE:
graphelement = 1;
break;
+ case GF_COMMENT:
case GF_DEF:
case GF_CDEF:
case GF_VDEF:
+ case GF_PART:
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;
leg_cc--;
im->gdes[i].legend[leg_cc]='\0';
}
- if (leg_cc != 0 ){
+ if (leg_cc != 0 ){
legspace[i]=(prt_fctn=='g' ? 0 : interleg);
if (fill > 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+6;
+ im->yimg = leg_y;
free(legspace);
}
return 0;
int
-horizontal_grid(gfx_canvas_t *canvas, image_desc_t *im)
+horizontal_grid(image_desc_t *im)
{
double range;
double scaledrange;
double gridstep;
double scaledstep;
char graph_label[100];
- double x0,x1,y0,y1;
+ double X0,X1,Y0;
int labfact,gridind;
int decimals, fractionals;
char labfmt[64];
labfact = im->ylabfact;
}
- x0=im->xorigin;
- x1=im->xorigin+im->xsize;
+ X0=im->xorigin;
+ X1=im->xorigin+im->xsize;
sgrid = (int)( im->minval / gridstep - 1);
egrid = (int)( im->maxval / gridstep + 1);
scaledstep = gridstep/im->magfact;
for (i = sgrid; i <= egrid; i++){
- y0=ytr(im,gridstep*i);
- if ( y0 >= im->yorigin-im->ysize
- && y0 <= im->yorigin){
+ Y0=ytr(im,gridstep*i);
+ if ( Y0 >= im->yorigin-im->ysize
+ && Y0 <= im->yorigin){
if(i % labfact == 0){
if (i==0 || im->symbol == ' ') {
if(scaledstep < 1){
}
}
- 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 */
ti = find_next_time(ti,im->xlab_user.labtm,im->xlab_user.labst)
){
tilab= ti + im->xlab_user.precis/2; /* correct time for the label */
+ /* are we inside the graph ? */
+ if (ti < im->start || ti > im->end) continue;
#if HAVE_STRFTIME
strftime(graph_label,99,im->xlab_user.stst,localtime(&tilab));
#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 boxH=8, boxV=8;
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, 0,0, im->xgif, 0,im->graph_col[GRC_SHADEA]);
- gfx_add_point( node , im->xgif - 2, 2 );
- gfx_add_point( node , 2,2 );
- gfx_add_point( node , 2,im->ygif-2 );
- gfx_add_point( node , 0,im->ygif );
+ 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->ximg - 2, 2 );
+ gfx_add_point( node , im->ximg, 0 );
+ gfx_add_point( node , 0,0 );
+/* gfx_add_point( node , 0,im->yimg ); */
- node = gfx_new_area (canvas, 0,im->ygif, im->xgif,im->ygif, im->xgif,0,im->graph_col[GRC_SHADEB]);
- gfx_add_point( node , im->xgif - 2, 2 );
- gfx_add_point( node , im->xgif-2,im->ygif-2 );
- gfx_add_point( node , 2,im->ygif-2 );
- gfx_add_point( node , 0,im->ygif );
+ 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->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 = 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 */
- gfx_new_text( 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);
+ 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 {
+ /* horrible hack until we can actually print vertically */
+ {
+ int n;
+ int l=strlen(im->ylegend);
+ char s[2];
+ for (n=0;n<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),
+ 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,
+ s);
+ }
+ }
+ }
/* graph title */
- gfx_new_text( canvas,
- im->xgif/2, im->text_prop[TEXT_PROP_TITLE].size*1.5,
+ 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,
GFX_H_CENTER, GFX_V_CENTER,
im->title);
- /* graph labels */
- if( !(im->extra_flags & NOLEGEND) ) {
+ /* graph labels */
+ if( !(im->extra_flags & NOLEGEND) ) {
for(i=0;i<im->gdes_c;i++){
- if(im->gdes[i].legend[0] =='\0')
- continue;
+ if(im->gdes[i].legend[0] =='\0')
+ continue;
- if(im->gdes[i].gf != GF_GPRINT && im->gdes[i].gf != GF_COMMENT){
- x0 = im->gdes[i].leg_x;
- y0 = im->gdes[i].leg_y+1.0;
- x1 = x0+boxH;
- x2 = x0+boxH;
- x3 = x0;
- y1 = y0;
- y2 = y0+boxV;
- y3 = y0+boxV;
- node = gfx_new_area(canvas, x0,y0,x1,y1,x2,y2 ,im->gdes[i].col);
- gfx_add_point ( node, x3, y3 );
- gfx_add_point ( node, x0, y0 );
- node = gfx_new_line(canvas, x0,y0,x1,y1 ,GRIDWIDTH, im->graph_col[GRC_FRAME]);
- gfx_add_point ( node, x2, y2 );
- gfx_add_point ( node, x3, y3 );
- gfx_add_point ( node, x0, y0 );
-
- gfx_new_text ( canvas, x0+boxH+6, (y0+y2) / 2.0,
- 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_LEFT, GFX_V_CENTER,
- im->gdes[i].legend );
-
- } else {
- x0 = im->gdes[i].leg_x;
- y0 = im->gdes[i].leg_y;
-
- gfx_new_text ( canvas, x0, (y0+y2) / 2.0,
- 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_LEFT, GFX_V_BOTTOM,
- im->gdes[i].legend );
-
- }
- }
- }
-}
+ /* im->gdes[i].leg_y is the bottom of the legend */
+ 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(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(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(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_close_path(node);
+ X0 += boxH / 1.25 * 2;
+ }
+ 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,
+ im->tabwidth,0.0, GFX_H_LEFT, GFX_V_BOTTOM,
+ im->gdes[i].legend );
+ }
+ }
+ }
/*****************************************************
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) {
- case IF_GIF:
- size = GifSize(fd,&(im->xgif),&(im->ygif));
- break;
+ 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,
}
}
+int
+graph_size_location(image_desc_t *im, int elements, int piechart )
+{
+ /* The actual size of the image to draw is determined from
+ ** several sources. The size given on the command line is
+ ** the graph area but we need more as we have to draw labels
+ ** and other things outside the graph area
+ */
+
+ /* +-+-------------------------------------------+
+ ** |l|.................title.....................|
+ ** |e+--+-------------------------------+--------+
+ ** |b| b| | |
+ ** |a| a| | pie |
+ ** |l| l| main graph area | chart |
+ ** |.| .| | area |
+ ** |t| y| | |
+ ** |r+--+-------------------------------+--------+
+ ** |e| | x-axis labels | |
+ ** |v+--+-------------------------------+--------+
+ ** | |..............legends......................|
+ ** +-+-------------------------------------------+
+ */
+ int Xvertical=0, Yvertical=0,
+ Xtitle =0, Ytitle =0,
+ Xylabel =0, Yylabel =0,
+ 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') {
+ 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') {
+ /* The title is placed "inbetween" two text lines so it
+ ** automatically has some vertical spacing. The horizontal
+ ** spacing is added here, on each side.
+ */
+ Xtitle = gfx_get_text_width(im->canvas, 0,
+ im->text_prop[TEXT_PROP_TITLE].font,
+ im->text_prop[TEXT_PROP_TITLE].size,
+ im->tabwidth,
+ im->title) + 2*Xspacing;
+ Ytitle = im->text_prop[TEXT_PROP_TITLE].size*2;
+ }
+
+ if (elements) {
+ Xmain=im->xsize;
+ Ymain=im->ysize;
+ if (im->draw_x_grid) {
+ Xxlabel=Xmain;
+ Yxlabel=im->text_prop[TEXT_PROP_LEGEND].size *2;
+ }
+ if (im->draw_y_grid) {
+ Xylabel=im->text_prop[TEXT_PROP_LEGEND].size *6;
+ Yylabel=Ymain;
+ }
+ }
+
+ if (piechart) {
+ im->piesize=im->xsize<im->ysize?im->xsize:im->ysize;
+ Xpie=im->piesize;
+ Ypie=im->piesize;
+ }
+
+ /* Now calculate the total size. Insert some spacing where
+ desired. im->xorigin and im->yorigin need to correspond
+ with the lower left corner of the main graph area or, if
+ this one is not set, the imaginary box surrounding the
+ pie chart area. */
+
+ /* The legend width cannot yet be determined, as a result we
+ ** have problems adjusting the image to it. For now, we just
+ ** forget about it at all; the legend will have to fit in the
+ ** size already allocated.
+ */
+ im->ximg = Xylabel + Xmain + Xpie + Xspacing;
+ if (Xmain) im->ximg += Xspacing;
+ if (Xpie) im->ximg += Xspacing;
+ im->xorigin = Xspacing + Xylabel;
+ if (Xtitle > im->ximg) im->ximg = Xtitle;
+ if (Xvertical) {
+ im->ximg += Xvertical;
+ im->xorigin += Xvertical;
+ }
+ xtr(im,0);
+
+ /* The vertical size is interesting... we need to compare
+ ** the sum of {Ytitle, Ymain, Yxlabel, Ylegend} with Yvertical
+ ** however we need to know {Ytitle+Ymain+Yxlabel} in order to
+ ** start even thinking about Ylegend.
+ **
+ ** Do it in three portions: First calculate the inner part,
+ ** then do the legend, then adjust the total height of the img.
+ */
+
+ /* reserve space for main and/or pie */
+ 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->yimg += Ytitle;
+ im->yorigin += Ytitle;
+ } else {
+ im->yimg += Yspacing;
+ im->yorigin += Yspacing;
+ }
+ /* reserve space for padding below the graph */
+ im->yimg += Yspacing;
+ ytr(im,DNAN);
+
+ /* Determine where to place the legends onto the image.
+ ** 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->yimg < Yvertical) im->yimg = Yvertical;
+
+#if 0
+ if (Xlegend > im->ximg) {
+ im->ximg = Xlegend;
+ /* reposition Pie */
+#endif
+
+ /* The pie is placed in the upper right hand corner,
+ ** just below the title (if any) and with sufficient
+ ** padding.
+ */
+ if (elements) {
+ im->pie_x = im->ximg - Xspacing - Xpie/2;
+ im->pie_y = im->yorigin-Ymain+Ypie/2;
+ } else {
+ im->pie_x = im->ximg/2;
+ im->pie_y = im->yorigin-Ypie/2;
+ }
+
+ return 0;
+}
+
/* draw that picture thing ... */
int
graph_paint(image_desc_t *im, char ***calcpr)
int i,ii;
int lazy = lazy_check(im);
int piechart = 0;
- double PieStart=0.0, PieSize=0.0, PieCenterX=0.0, PieCenterY=0.0;
+ double PieStart=0.0;
FILE *fo;
- gfx_canvas_t *canvas;
gfx_node_t *node;
double areazero = 0.0;
if(data_calc(im)==-1)
return -1;
+ /* check if we need to draw a piechart */
+ for(i=0;i<im->gdes_c;i++){
+ if (im->gdes[i].gf == GF_PART) {
+ piechart=1;
+ break;
+ }
+ }
+
/* calculate and PRINT and GPRINT definitions. We have to do it at
* this point because it will affect the length of the legends
* if there are no graph elements we stop here ...
*/
i=print_calc(im,calcpr);
if(i<0) return -1;
- if(i==0 || lazy) return 0;
+ if(((i==0)&&(piechart==0)) || lazy) return 0;
+
+ /* If there's only the pie chart to draw, signal this */
+ if (i==0) piechart=2;
/* get actual drawing data and find min and max values*/
if(data_proc(im)==-1)
if(!im->rigid && ! im->logarithmic)
expand_range(im); /* make sure the upper and lower limit are
sensible values */
-
- /* init xtr and ytr */
- /* determine the actual size of the gif to draw. The size given
- on the cmdline is the graph area. But we need more as we have
- draw labels and other things outside the graph area */
-
-
- im->xorigin = 10 + 9 * im->text_prop[TEXT_PROP_LEGEND].size;
- xtr(im,0);
-
- im->yorigin = 10 + im->ysize;
-
- ytr(im,DNAN);
-
- if(im->title[0] != '\0')
- im->yorigin += im->text_prop[TEXT_PROP_TITLE].size*3+4;
-
- im->xgif= 20 +im->xsize + im->xorigin;
- im->ygif= im->yorigin+2* im->text_prop[TEXT_PROP_LEGEND].size;
-
- /* check if we need to draw a piechart */
- for(i=0;i<im->gdes_c;i++){
- if (im->gdes[i].gf == GF_PART) {
- piechart=1;
- break;
- }
- }
-
- if (piechart) {
- /* allocate enough space for the piechart itself (PieSize), 20%
- ** more for the background and an additional 50 pixels spacing.
- */
- if (im->xsize < im->ysize)
- PieSize = im->xsize;
- else
- PieSize = im->ysize;
- im->xgif += PieSize*1.2 + 50;
-
- PieCenterX = im->xorigin + im->xsize + 50 + PieSize*0.6;
- PieCenterY = im->yorigin - PieSize*0.5;
- }
-
- /* determine where to place the legends onto the graphics.
- and set im->ygif to match space requirements for text */
- if(leg_place(im)==-1)
+/**************************************************************
+ *** 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);
- node=gfx_new_area ( canvas,
+ if (piechart != 2) {
+ node=gfx_new_area ( im->canvas,
im->xorigin, im->yorigin,
im->xorigin + im->xsize, im->yorigin,
im->xorigin + im->xsize, im->yorigin-im->ysize,
im->graph_col[GRC_CANVAS]);
- gfx_add_point(node,im->xorigin, im->yorigin - im->ysize);
+ gfx_add_point(node,im->xorigin, im->yorigin - im->ysize);
-#if 0
-/******************************************************************
- ** Just to play around. If you see this, I forgot to remove it **
- ******************************************************************/
- im->ygif+=100;
- node=gfx_new_area(canvas,
- 0, im->ygif-100,
- im->xgif, im->ygif-100,
- im->xgif, im->ygif,
- im->graph_col[GRC_CANVAS]);
- gfx_add_point(node,0,im->ygif);
-
- /* Four areas:
- ** top left: current way, solid color
- ** top right: proper way, solid color
- ** bottom left: current way, alpha=0x80, partially overlapping
- ** bottom right: proper way, alpha=0x80, partially overlapping
- */
- {
- double x,y,x1,y1,x2,y2,x3,y3,x4,y4;
-
- x=(im->xgif-40)/6;
- y= (100-40)/6;
- x1= 20; y1=im->ygif-100+20;
- x2=3*x+20; y2=im->ygif-100+20;
- x3= x+20; y3=im->ygif-100+20+2*y;
- x4=4*x+20; y4=im->ygif-100+20+2*y;
-
- node=gfx_new_area(canvas,
- x1,y1,
- x1+3*x,y1,
- x1+3*x,y1+3*y,
- 0xFF0000FF);
- gfx_add_point(node,x1,y1+3*y);
- node=gfx_new_area(canvas,
- x2,y2,
- x2,y2+3*y,
- x2+3*x,y2+3*y,
- 0xFFFF00FF);
- gfx_add_point(node,x2+3*x,y2);
- node=gfx_new_area(canvas,
- x3,y3,
- x3+2*x,y3,
- x3+2*x,y3+3*y,
- 0x00FF007F);
- gfx_add_point(node,x3,y3+3*y);
- node=gfx_new_area(canvas,
- x4,y4,
- x4,y4+3*y,
- x4+2*x,y4+3*y,
- 0x0000FF7F);
- gfx_add_point(node,x4+2*x,y4);
+ if (im->minval > 0.0)
+ areazero = im->minval;
+ if (im->maxval < 0.0)
+ areazero = im->maxval;
+
+ axis_paint(im);
}
-
-#endif
if (piechart) {
- pie_part(canvas,im->graph_col[GRC_CANVAS],PieCenterX,PieCenterY,PieSize*0.6,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);
}
- if (im->minval > 0.0)
- areazero = im->minval;
- if (im->maxval < 0.0)
- areazero = im->maxval;
-
- axis_paint(im,canvas);
-
-
for(i=0;i<im->gdes_c;i++){
switch(im->gdes[i].gf){
case GF_CDEF:
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,
- PieCenterX,PieCenterY,PieSize/2,
+ 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);
PieStart += im->gdes[i].yrule;
break;
} /* switch */
}
- grid_paint(im,canvas);
+ if (piechart==2) {
+ im->draw_x_grid=0;
+ im->draw_y_grid=0;
+ }
+ /* grid_paint also does the text */
+ 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_GIF:
- break;
- 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;
}
** 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->prt_c = 0;
im->gdes_c = 0;
im->gdes = NULL;
- im->zoom = 1.0;
- im->imgformat = IF_GIF; /* we default to GIF output */
+ im->canvas = gfx_new_canvas();
for(i=0;i<DIM(graph_col);i++)
im->graph_col[i]=graph_col[i];
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);