/****************************************************************************
- * RRDtool 1.0.33 Copyright Tobias Oetiker, 1997 - 2000
+ * RRDtool 1.1.x Copyright Tobias Oetiker, 1997 - 2002
****************************************************************************
* rrd__graph.c make creates ne rrds
****************************************************************************/
#ifndef RRD_DEFAULT_FONT
-#define RRD_DEFAULT_FONT "/usr/openwin/lib/X11/fonts/TrueType/Arial.ttf"
+#define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/openoffice/ariosor.ttf"
/* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/Arial.ttf" */
#endif
/*{300, TMT_HOUR,3, TMT_HOUR,12, TMT_HOUR,12, 12*3600,"%a %p"}, this looks silly*/
{600, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%a"},
{1800, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a"},
- {3600, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %W"},
- {3*3600, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %W"},
+ {3600, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %V"},
+ {3*3600, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %V"},
{6*3600, TMT_MONTH,1, TMT_MONTH,1, TMT_MONTH,1, 30*24*3600,"%b"},
{48*3600, TMT_MONTH,1, TMT_MONTH,3, TMT_MONTH,3, 30*24*3600,"%b"},
{10*24*3600, TMT_YEAR,1, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%y"},
conv_if(DEF,GF_DEF)
conv_if(CDEF,GF_CDEF)
conv_if(VDEF,GF_VDEF)
+ conv_if(PART,GF_PART)
return (-1);
}
* further save step size and data source
* count of this rra
*/
- im->gdes[gdi].rpnp[rpi].data = im->gdes[ptr].data;
+ im->gdes[gdi].rpnp[rpi].data = im->gdes[ptr].data + im->gdes[ptr].ds;
im->gdes[gdi].rpnp[rpi].step = im->gdes[ptr].step;
im->gdes[gdi].rpnp[rpi].ds_cnt = im->gdes[ptr].ds_cnt;
case GF_DEF:
case GF_CDEF:
case GF_VDEF:
+ case GF_PART:
break;
}
}
case GF_LINE:
case GF_AREA:
case GF_TICK:
+ case GF_PART:
case GF_STACK:
case GF_HRULE:
case GF_VRULE:
gfx_get_text_width(leg_x,im->text_prop[TEXT_PROP_LEGEND].font,
im->text_prop[TEXT_PROP_LEGEND].size,
im->tabwidth,
- im->gdes[i].legend)
+ im->gdes[ii].legend)
+ legspace[ii]
+ glue;
if (im->gdes[ii].gf != GF_GPRINT &&
return size;
}
+void
+pie_part(gfx_canvas_t *canvas, gfx_color_t color,
+ double PieCenterX, double PieCenterY, double Radius,
+ double startangle, double endangle)
+{
+ gfx_node_t *node;
+ double angle;
+ double step=M_PI/50; /* Number of iterations for the circle;
+ ** 10 is definitely too low, more than
+ ** 50 seems to be overkill
+ */
+
+ /* Strange but true: we have to work clockwise or else
+ ** anti aliasing nor transparency don't work.
+ **
+ ** This test is here to make sure we do it right, also
+ ** this makes the for...next loop more easy to implement.
+ ** The return will occur if the user enters a negative number
+ ** (which shouldn't be done according to the specs) or if the
+ ** programmers do something wrong (which, as we all know, never
+ ** happens anyway :)
+ */
+ if (endangle<startangle) return;
+
+ /* Hidden feature: Radius decreases each full circle */
+ angle=startangle;
+ while (angle>=2*M_PI) {
+ angle -= 2*M_PI;
+ Radius *= 0.8;
+ }
+
+ node=gfx_new_area(canvas,
+ PieCenterX+sin(startangle)*Radius,
+ PieCenterY-cos(startangle)*Radius,
+ PieCenterX,
+ PieCenterY,
+ PieCenterX+sin(endangle)*Radius,
+ PieCenterY-cos(endangle)*Radius,
+ color);
+ for (angle=endangle;angle-startangle>=step;angle-=step) {
+ gfx_add_point(node,
+ PieCenterX+sin(angle)*Radius,
+ PieCenterY-cos(angle)*Radius );
+ }
+}
/* draw that picture thing ... */
int
{
int i,ii;
int lazy = lazy_check(im);
+ int piechart = 0;
+ double PieStart=0.0, PieSize=0.0, PieCenterX=0.0, PieCenterY=0.0;
FILE *fo;
gfx_canvas_t *canvas;
gfx_node_t *node;
if(im->title[0] != '\0')
im->yorigin += im->text_prop[TEXT_PROP_TITLE].size*3+4;
- im->xgif=20+im->xsize + im->xorigin;
+ 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)
canvas=gfx_new_canvas();
+
/* the actual graph is created by going through the individual
graph elements and then drawing them */
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);
+ }
+
+#endif
+
+ if (piechart) {
+ pie_part(canvas,im->graph_col[GRC_CANVAS],PieCenterX,PieCenterY,PieSize*0.6,0,2*M_PI);
+ }
+
if (im->minval > 0.0)
areazero = im->minval;
if (im->maxval < 0.0)
axis_paint(im,canvas);
- for(i=0;i<im->gdes_c;i++){
+ for(i=0;i<im->gdes_c;i++){
switch(im->gdes[i].gf){
case GF_CDEF:
case GF_VDEF:
}
lastgdes = &(im->gdes[i]);
break;
+ case GF_PART:
+ if(isnan(im->gdes[i].yrule)) /* fetch variable */
+ 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,
+ 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);
switch(im->gdes[i].gf){
case GF_HRULE:
- printf("DEBUG: HRULE at %f\n",im->gdes[i].yrule);
if(isnan(im->gdes[i].yrule)) { /* fetch variable */
im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
};
}
break;
case 'n':{
- char *prop = "";
- double size = 1;
- char *font = "dummy";
-
- if(sscanf(optarg,
- "%10[A-Z]:%lf:%s",
- prop,&size,font) == 3){
- int sindex;
- if((sindex=text_prop_conv(prop)) != -1){
- im->text_prop[sindex].size=size;
- im->text_prop[sindex].font=font;
-
- } else {
- rrd_set_error("invalid color name '%s'",col_nam);
- }
- } else {
- rrd_set_error("invalid text property format");
- return;
- }
- break;
- }
+ /* originally this used char *prop = "" and
+ ** char *font = "dummy" however this results
+ ** in a SEG fault, at least on RH7.1
+ **
+ ** The current implementation isn't proper
+ ** either, font is never freed and prop uses
+ ** a fixed width string
+ */
+ char prop[100];
+ double size = 1;
+ char *font;
+
+ font=malloc(255);
+ if(sscanf(optarg,
+ "%10[A-Z]:%lf:%s",
+ prop,&size,font) == 3){
+ int sindex;
+ if((sindex=text_prop_conv(prop)) != -1){
+ im->text_prop[sindex].size=size;
+ im->text_prop[sindex].font=font;
+ if (sindex==0) { /* the default */
+ im->text_prop[TEXT_PROP_TITLE].size=size;
+ im->text_prop[TEXT_PROP_TITLE].font=font;
+ im->text_prop[TEXT_PROP_AXIS].size=size;
+ im->text_prop[TEXT_PROP_AXIS].font=font;
+ im->text_prop[TEXT_PROP_UNIT].size=size;
+ im->text_prop[TEXT_PROP_UNIT].font=font;
+ im->text_prop[TEXT_PROP_LEGEND].size=size;
+ im->text_prop[TEXT_PROP_LEGEND].font=font;
+ }
+ } else {
+ rrd_set_error("invalid fonttag '%s'",prop);
+ return;
+ }
+ } else {
+ rrd_set_error("invalid text property format");
+ return;
+ }
+ break;
+ }
case 'm':
im->zoom= atof(optarg);
if (im->zoom <= 0.0) {
/* function:newvname=string[:ds-name:CF] for xDEF
** function:vname[#color[:string]] for LINEx,AREA,STACK
** function:vname#color[:num[:string]] for TICK
- ** function:vname-or-num#color[:string] for xRULE
+ ** function:vname-or-num#color[:string] for xRULE,PART
** function:vname:CF:string for xPRINT
** function:string for COMMENT
*/
if (rrd_graph_legend(gdp,&line[argstart])==0)
rrd_set_error("Cannot parse comment in line: %s",line);
break;
+ case GF_PART:
case GF_VRULE:
case GF_HRULE:
j=k=l=m=0;