revamped drawing routines to be less complex and more stable. be kind to libart
[rrdtool.git] / src / rrd_graph.c
index 8391349..67fce90 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * RRDtool 1.2rc4  Copyright by Tobi Oetiker, 1997-2005
+ * RRDtool 1.2rc5  Copyright by Tobi Oetiker, 1997-2005
  ****************************************************************************
  * rrd__graph.c  produce graphs from data in rrdfiles
  ****************************************************************************/
@@ -2097,7 +2097,9 @@ graph_size_location(image_desc_t *im, int elements
        Xtitle   =0,    Ytitle   =0,
        Xylabel  =0,    Yylabel  =0,
        Xmain    =0,    Ymain    =0,
+#ifdef WITH_PIECHART
        Xpie     =0,    Ypie     =0,
+#endif
        Xxlabel  =0,    Yxlabel  =0,
 #if 0
        Xlegend  =0,    Ylegend  =0,
@@ -2105,18 +2107,22 @@ graph_size_location(image_desc_t *im, int elements
         Xspacing =10,  Yspacing =10;
 
     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
@@ -2162,23 +2168,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;
     }
@@ -2195,19 +2200,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) {
@@ -2419,81 +2418,69 @@ 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;ii<im->xsize;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;ii<im->xsize;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;
+           if ( isnan(im->gdes[i].p_data[ii]) ) {
+               continue;
+           }
+           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 == im->gdes[i].p_data[ii] ){
+               continue;
+           }
+            node = gfx_new_area(im->canvas,
+                                ii-1+im->xorigin,ybase,
+                                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].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;ii<im->xsize;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);
@@ -2851,7 +2838,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
            {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:",
@@ -3022,13 +3009,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");