Code

prepare for the release of rrdtool-1.2.30
[rrdtool-all.git] / program / src / rrd_graph.c
index 3ee158254aec58c97e5890322d03fd2a9b92b2e4..ee44c77e3481cbb47aca15ba50f79194489f8e30 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * RRDtool 1.2.27  Copyright by Tobi Oetiker, 1997-2008
+ * RRDtool 1.2.30  Copyright by Tobi Oetiker, 1997-2009
  ****************************************************************************
  * rrd__graph.c  produce graphs from data in rrdfiles
  ****************************************************************************/
@@ -1710,6 +1710,8 @@ int draw_horizontal_grid(image_desc_t *im)
     int sgrid = (int)( im->minval / im->ygrid_scale.gridstep - 1);
     int egrid = (int)( im->maxval / im->ygrid_scale.gridstep + 1);
     double MaxY;
+    double second_axis_magfact = 0;
+    char *second_axis_symb = "";
     scaledstep = im->ygrid_scale.gridstep/(double)im->magfact*(double)im->viewfactor;
     MaxY = scaledstep*(double)egrid;
     for (i = sgrid; i <= egrid; i++){
@@ -1744,6 +1746,33 @@ int draw_horizontal_grid(image_desc_t *im)
                     }
                 }
                 nlabels++;
+                if (im->second_axis_scale != 0){
+                        char graph_label_right[100];
+                        double sval = im->ygrid_scale.gridstep*(double)i*im->second_axis_scale+im->second_axis_shift;
+                        if (im->second_axis_format[0] == '\0'){
+                            if (!second_axis_magfact){
+                                double dummy = im->ygrid_scale.gridstep*(double)(sgrid+egrid)/2.0*im->second_axis_scale+im->second_axis_shift;
+                                auto_scale(im,&dummy,&second_axis_symb,&second_axis_magfact);
+                            }
+                            sval /= second_axis_magfact;
+                            if(MaxY < 10) { 
+                                sprintf(graph_label_right,"%5.1f %s",sval,second_axis_symb);
+                            } else {
+                                sprintf(graph_label_right,"%5.0f %s",sval,second_axis_symb);
+                            }
+                        }
+                        else {
+                           sprintf(graph_label_right,im->second_axis_format,sval);
+                        }        
+                        gfx_new_text ( im->canvas,
+                               X1+7, 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_CENTER,
+                               graph_label_right );
+                }
 
                gfx_new_text ( im->canvas,
                               X0-im->text_prop[TEXT_PROP_AXIS].size, Y0,
@@ -1787,7 +1816,6 @@ double frexp10(double x, double *e) {
     return mnt;
 }
 
-
 /* logaritmic horizontal grid */
 int
 horizontal_log_grid(image_desc_t   *im)   
@@ -1877,16 +1905,44 @@ horizontal_log_grid(image_desc_t   *im)
             else
                 symbol = '?';
 
-                sprintf(graph_label,"%3.0f %c", pvalue, symbol);
-        } else
+            sprintf(graph_label,"%3.0f %c", pvalue, symbol);
+        } else {
             sprintf(graph_label,"%3.0e", value);
+        }
+        if (im->second_axis_scale != 0){
+                char graph_label_right[100];
+                double sval = value*im->second_axis_scale+im->second_axis_shift;
+                if (im->second_axis_format[0] == '\0'){
+                        if (im->extra_flags & FORCE_UNITS_SI) {
+                                double mfac = 1;
+                                char   *symb = "";
+                                auto_scale(im,&sval,&symb,&mfac);
+                                sprintf(graph_label_right,"%4.0f %s", sval,symb);
+                        }
+                        else {        
+                                sprintf(graph_label_right,"%3.0e", sval);
+                        }
+                }
+                else {
+                      sprintf(graph_label_right,im->second_axis_format,sval);
+                }    
+    
+                gfx_new_text ( im->canvas,
+                               X1+7, 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_CENTER,
+                               graph_label_right );
+        }
+            
         gfx_new_text ( im->canvas,
-            X0-im->text_prop[TEXT_PROP_AXIS].size, 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 );
+                       X0-im->text_prop[TEXT_PROP_AXIS].size, 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 );
 
         /* minor grid */
         if(mid < 4 && exfrac == 1) {
@@ -2145,6 +2201,16 @@ axis_paint(
                    im->xorigin+0.5,    im->yorigin-im->ysize-7, /* LINEOFFSET */
                    im->graph_col[GRC_ARROW]);
 
+    if (im->second_axis_scale != 0){
+       gfx_new_line ( im->canvas, im->xorigin+im->xsize,im->yorigin+4,
+                         im->xorigin+im->xsize,im->yorigin-im->ysize-4,
+                         MGRIDWIDTH, im->graph_col[GRC_AXIS]);
+       gfx_new_area ( im->canvas, 
+                   im->xorigin+im->xsize-2,  im->yorigin-im->ysize-2,
+                   im->xorigin+im->xsize+3,  im->yorigin-im->ysize-2,
+                   im->xorigin+im->xsize+0.5,    im->yorigin-im->ysize-7, /* LINEOFFSET */
+                   im->graph_col[GRC_ARROW]);
+    }
 }
 
 void
@@ -2197,7 +2263,8 @@ grid_paint(image_desc_t   *im)
     }
 
     /* yaxis unit description */
-    gfx_new_text( im->canvas,
+    if (im->ylegend[0] != '\0'){
+            gfx_new_text( im->canvas,
                   10, (im->yorigin - im->ysize/2),
                   im->graph_col[GRC_FONT],
                   im->text_prop[TEXT_PROP_UNIT].font,
@@ -2205,7 +2272,23 @@ grid_paint(image_desc_t   *im)
                   RRDGRAPH_YLEGEND_ANGLE,
                   GFX_H_LEFT, GFX_V_CENTER,
                   im->ylegend);
-
+    }
+    if (im->second_axis_legend[0] != '\0'){
+            double Xylabel=gfx_get_text_width(im->canvas, 0,
+                        im->text_prop[TEXT_PROP_AXIS].font,
+                        im->text_prop[TEXT_PROP_AXIS].size,
+                        im->tabwidth,
+                        "0", 0) * im->unitslength
+                    + im->text_prop[TEXT_PROP_UNIT].size *2;
+            gfx_new_text( im->canvas,
+                  im->xorigin+im->xsize+Xylabel+4, (im->yorigin - im->ysize/2),
+                  im->graph_col[GRC_FONT],
+                  im->text_prop[TEXT_PROP_UNIT].font,
+                  im->text_prop[TEXT_PROP_UNIT].size, im->tabwidth, 
+                  RRDGRAPH_YLEGEND_ANGLE,
+                  GFX_H_LEFT, GFX_V_CENTER,
+                  im->second_axis_legend);
+    }        
     /* graph title */
     gfx_new_text( im->canvas,
                   im->ximg/2, im->text_prop[TEXT_PROP_TITLE].size*1.3+4,
@@ -2215,14 +2298,15 @@ grid_paint(image_desc_t   *im)
                   GFX_H_CENTER, GFX_V_CENTER,
                   im->title);
     /* rrdtool 'logo' */
-    gfx_new_text( im->canvas,
+    if (!(im->extra_flags & NO_RRDTOOL_TAG)){
+            gfx_new_text( im->canvas,
                   im->ximg-7, 7,
                   ( im->graph_col[GRC_FONT] & 0xffffff00 ) | 0x00000044,
                   im->text_prop[TEXT_PROP_AXIS].font,
                   5.5, im->tabwidth, 270,
                   GFX_H_RIGHT, GFX_V_TOP,
                   "RRDTOOL / TOBI OETIKER");
-
+    }
     /* graph watermark */
     if(im->watermark[0] != '\0') {
         gfx_new_text( im->canvas,
@@ -2478,6 +2562,13 @@ graph_size_location(image_desc_t *im, int elements
     */
     im->ximg = Xylabel + Xmain + 2 * Xspacing;
 
+    if (im->second_axis_scale != 0){
+        im->ximg += Xylabel + Xspacing;
+    }
+    if (im->extra_flags & NO_RRDTOOL_TAG){
+        im->ximg -= Xspacing;
+    }
+
 #ifdef WITH_PIECHART
     im->ximg  += Xpie;
 #endif
@@ -2496,6 +2587,10 @@ graph_size_location(image_desc_t *im, int elements
         im->ximg += Xvertical;
         im->xorigin += Xvertical;
     }
+    if (im->second_axis_legend[0] != '\0' ) {
+        im->ximg += Xvertical;
+    }
+
     xtr(im,0);
 
     /* The vertical size is interesting... we need to compare
@@ -2716,8 +2811,8 @@ graph_paint(image_desc_t *im, char ***calcpr)
                                    im -> gdes[i].col );
               } else if ( im -> gdes[i].yrule < 0 ) {
                       gfx_new_line(im->canvas,
-                                   im -> xorigin + ii, im->yorigin - im -> ysize,
-                                   im -> xorigin + ii, im->yorigin - ( 1 - im -> gdes[i].yrule ) * im -> ysize,
+                                   im -> xorigin + ii, im->yorigin - im->ysize,
+                                   im -> xorigin + ii, im->yorigin - im->ysize - im->gdes[i].yrule * im->ysize,
                                    1.0,
                                    im -> gdes[i].col );
               
@@ -3085,6 +3180,7 @@ rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize, FILE *s
     *ymax=im.maxval;
     if (im.imginfo) {
         char *filename;
+        char *path;
         if (!(*prdata)) {
             /* maybe prdata is not allocated yet ... lets do it now */
             if ((*prdata = calloc(2,sizeof(char *)))==NULL) {
@@ -3097,13 +3193,10 @@ rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize, FILE *s
             rrd_set_error("malloc imginfo");
             return -1;
         }
-        filename=im.graphfile+strlen(im.graphfile);
-        while(filename > im.graphfile) {
-            if (*(filename-1)=='/' || *(filename-1)=='\\' ) break;
-            filename--;
-        }
-
+        path = strdup(im.graphfile);
+        filename = basename(path);
         sprintf((*prdata)[0],im.imginfo,filename,(long)(im.canvas->zoom*im.ximg),(long)(im.canvas->zoom*im.yimg));
+        free(path);
     }
     im_free(&im);
     return 0;
@@ -3133,6 +3226,10 @@ rrd_graph_init(image_desc_t *im)
     im->ysize = 100;
     im->step = 0;
     im->ylegend[0] = '\0';
+    im->second_axis_scale = 0; /* 0 disables it */
+    im->second_axis_shift = 0; /* no shift by default */
+    im->second_axis_legend[0] = '\0';
+    im->second_axis_format[0] = '\0';
     im->title[0] = '\0';
     im->watermark[0] = '\0';
     im->minval = DNAN;
@@ -3259,6 +3356,10 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
             {"font-smoothing-threshold", required_argument, 0, 'B'},
             {"watermark",  required_argument, 0,  'W'},
             {"alt-y-mrtg", no_argument,       0,  1000}, /* this has no effect it is just here to save old apps from crashing when they use it */
+            {"disable-rrdtool-tag", no_argument,  0,  1001},
+            {"right-axis", required_argument,  0,  1002},
+            {"right-axis-label", required_argument,  0,  1003},
+            {"right-axis-format", required_argument,  0,  1004},
             {0,0,0,0}};
         int option_index = 0;
         int opt;
@@ -3296,6 +3397,9 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
         case 'F':
             im->extra_flags |= FORCE_RULES_LEGEND;
             break;
+        case 1001:
+            im->extra_flags |= NO_RRDTOOL_TAG;
+            break;
         case LONGOPT_UNITS_SI:
             if(im->extra_flags & FORCE_UNITS) {
                 rrd_set_error("--units can only be used once!");
@@ -3394,6 +3498,33 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
                 return;
             }
             break;
+        case 1002: /* right y axis */
+
+            if(sscanf(optarg,
+                      "%lf:%lf",
+                      &im->second_axis_scale,
+                      &im->second_axis_shift) == 2) {
+                if(im->second_axis_scale==0){
+                    rrd_set_error("the second_axis_scale  must not be 0");
+                    return;
+                }
+            } else {
+                rrd_set_error("invalid right-axis format expected scale:shift");
+                return;
+            }
+            break;
+        case 1003:
+            strncpy(im->second_axis_legend,optarg,150);
+            im->second_axis_legend[150]='\0';
+            break;
+        case 1004:
+            if (bad_format(optarg)){
+                rrd_set_error("use either %le or %lf formats");
+                return;
+            }
+            strncpy(im->second_axis_format,optarg,150);
+            im->second_axis_format[150]='\0';
+            break;
         case 'v':
             strncpy(im->ylegend,optarg,150);
             im->ylegend[150]='\0';
@@ -3508,15 +3639,17 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
                         if (size > 0){
                               im->text_prop[propidx].size=size;              
                       }        
-                       if (strlen(prop) > end){
-                          if (prop[end] == ':'){
-                             strncpy(im->text_prop[propidx].font,prop+end+1,255);
+                        if ((int)strlen(optarg) > end+2){
+                          if (optarg[end] == ':'){
+                             strncpy(im->text_prop[propidx].font,optarg+end+1,255);
                              im->text_prop[propidx].font[255] = '\0';
                           } else {
-                             rrd_set_error("expected after font size in '%s'",prop);
+                             rrd_set_error("expected : after font size in '%s'",optarg);
                             return;
                           }
                       }
+                      /* only run the for loop for DEFAULT (0) for
+                         all others, we break here. woodo programming */
                       if (propidx==sindex && sindex != 0) break;
                   }
                 } else {
@@ -3789,17 +3922,16 @@ int gdi;
 {
     graph_desc_t        *src,*dst;
     rrd_value_t                *data;
-    long                step,steps,end;
+    long                step,steps;
 
     dst = &im->gdes[gdi];
     src = &im->gdes[dst->vidx];
     data = src->data + src->ds;
-    end = (src->end_orig % src->step) == 0 ? src->end_orig : (src->end_orig + src->step - src->end_orig % src->step);
-    steps = (end - src->start) / src->step;
+    steps = (src->end - src->start) / src->step;
 #if 0
 printf("DEBUG: start == %lu, end == %lu, %lu steps\n"
     ,src->start
-    ,src->end_orig
+    ,src->end
     ,steps
     );
 #endif