make basename work
[rrdtool.git] / src / rrd_graph.c
index 357df07..a24889f 100644 (file)
@@ -1,11 +1,12 @@
 /****************************************************************************
- * RRDtool 1.3rc8  Copyright by Tobi Oetiker, 1997-2008
+ * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2008
  ****************************************************************************
  * rrd__graph.c  produce graphs from data in rrdfiles
  ****************************************************************************/
 
 
 #include <sys/stat.h>
+#include <libgen.h>
 
 #ifdef WIN32
 #include "strftime.h"
@@ -26,6 +27,7 @@
 #endif
 
 #include "rrd_graph.h"
+#include "rrd_client.h"
 
 /* some constant definitions */
 
 #endif
 
 text_prop_t text_prop[] = {
-    {8.0, RRD_DEFAULT_FONT}
+    {8.0, RRD_DEFAULT_FONT,NULL}
     ,                   /* default */
-    {9.0, RRD_DEFAULT_FONT}
+    {9.0, RRD_DEFAULT_FONT,NULL}
     ,                   /* title */
-    {7.0, RRD_DEFAULT_FONT}
+    {7.0, RRD_DEFAULT_FONT,NULL}
     ,                   /* axis */
-    {8.0, RRD_DEFAULT_FONT}
+    {8.0, RRD_DEFAULT_FONT,NULL}
     ,                   /* unit */
-    {8.0, RRD_DEFAULT_FONT} /* legend */
+    {8.0, RRD_DEFAULT_FONT,NULL} /* legend */
+    ,
+    {5.5, RRD_DEFAULT_FONT,NULL} /* watermark */    
 };
 
 xlab_t    xlab[] = {
@@ -288,6 +292,7 @@ enum text_prop_en text_prop_conv(
     conv_if(AXIS, TEXT_PROP_AXIS);
     conv_if(UNIT, TEXT_PROP_UNIT);
     conv_if(LEGEND, TEXT_PROP_LEGEND);
+    conv_if(WATERMARK, TEXT_PROP_WATERMARK);
     return -1;
 }
 
@@ -302,6 +307,10 @@ int im_free(
 
     if (im == NULL)
         return 0;
+
+    if (im->daemon_addr != NULL)
+      free(im->daemon_addr);
+
     for (i = 0; i < (unsigned) im->gdes_c; i++) {
         if (im->gdes[i].data_first) {
             /* careful here, because a single pointer can occur several times */
@@ -330,12 +339,18 @@ int im_free(
     if (im->rendered_image) {
         free(im->rendered_image);
     }
+
+    if (im->layout) {
+        g_object_unref (im->layout);
+    }
+
     if (im->surface)
         cairo_surface_destroy(im->surface);
+
     if (status)
         fprintf(stderr, "OOPS: Cairo has issues it can't even die: %s\n",
                 cairo_status_to_string(status));
-
+        
     return 0;
 }
 
@@ -824,6 +839,36 @@ int data_fetch(
         if (!skip) {
             unsigned long ft_step = im->gdes[i].step;   /* ft_step will record what we got from fetch */
 
+            /* Flush the file if
+             * - a connection to the daemon has been established
+             * - this is the first occurrence of that RRD file
+             */
+            if (rrdc_is_connected(im->daemon_addr))
+            {
+                int status;
+
+                status = 0;
+                for (ii = 0; ii < i; ii++)
+                {
+                    if (strcmp (im->gdes[i].rrd, im->gdes[ii].rrd) == 0)
+                    {
+                        status = 1;
+                        break;
+                    }
+                }
+
+                if (status == 0)
+                {
+                    status = rrdc_flush (im->gdes[i].rrd);
+                    if (status != 0)
+                    {
+                        rrd_set_error ("rrdc_flush (%s) failed with status %i.",
+                                im->gdes[i].rrd, status);
+                        return (-1);
+                    }
+                }
+            } /* if (rrdc_is_connected()) */
+
             if ((rrd_fetch_fn(im->gdes[i].rrd,
                               im->gdes[i].cf,
                               &im->gdes[i].start,
@@ -894,7 +939,7 @@ long find_var(
     return -1;
 }
 
-/* find the largest common denominator for all the numbers
+/* find the greatest common divisor for all the numbers
    in the 0 terminated num array */
 long lcd(
     long *num)
@@ -1612,11 +1657,11 @@ int leg_place(
     int       border = im->text_prop[TEXT_PROP_LEGEND].size * 2.0;
     int       fill = 0, fill_last;
     int       leg_c = 0;
-    int       leg_x = border;
+    double    leg_x = border;
     int       leg_y = im->yimg;
     int       leg_y_prev = im->yimg;
     int       leg_cc;
-    int       glue = 0;
+    double    glue = 0;
     int       i, ii, mark = 0;
     char      prt_fctn; /*special printfunctions */
     char      default_txtalign = TXA_JUSTIFIED; /*default line orientation */
@@ -1701,11 +1746,7 @@ int leg_place(
                                        im->
                                        text_prop
                                        [TEXT_PROP_LEGEND].
-                                       font,
-                                       im->
-                                       text_prop
-                                       [TEXT_PROP_LEGEND].
-                                       size,
+                                       font_desc,
                                        im->tabwidth, im->gdes[i].legend);
                 leg_c++;
             } else {
@@ -1752,12 +1793,12 @@ int leg_place(
             if (prt_fctn != '\0') {
                 leg_x = border;
                 if (leg_c >= 2 && prt_fctn == 'j') {
-                    glue = (im->ximg - fill - 2 * border) / (leg_c - 1);
+                    glue = (double)(im->ximg - fill - 2 * border) / (double)(leg_c - 1);
                 } else {
                     glue = 0;
                 }
                 if (prt_fctn == 'c')
-                    leg_x = (im->ximg - fill) / 2.0;
+                    leg_x = (double)(im->ximg - fill) / 2.0;
                 if (prt_fctn == 'r')
                     leg_x = im->ximg - fill - border;
                 for (ii = mark; ii <= i; ii++) {
@@ -1766,17 +1807,13 @@ int leg_place(
                     im->gdes[ii].leg_x = leg_x;
                     im->gdes[ii].leg_y = leg_y;
                     leg_x +=
-                        gfx_get_text_width(im, leg_x,
-                                           im->
-                                           text_prop
-                                           [TEXT_PROP_LEGEND].
-                                           font,
+                        (double)gfx_get_text_width(im, leg_x,
                                            im->
                                            text_prop
                                            [TEXT_PROP_LEGEND].
-                                           size,
+                                           font_desc,
                                            im->tabwidth, im->gdes[ii].legend)
-                        + legspace[ii]
+                        +(double)legspace[ii]
                         + glue;
                 }
                 leg_y_prev = leg_y;
@@ -1990,10 +2027,8 @@ int draw_horizontal_grid(
                          im->graph_col[GRC_FONT],
                          im->
                          text_prop[TEXT_PROP_AXIS].
-                         font,
-                         im->
-                         text_prop[TEXT_PROP_AXIS].
-                         size, im->tabwidth, 0.0,
+                         font_desc,
+                         im->tabwidth, 0.0,
                          GFX_H_RIGHT, GFX_V_CENTER, graph_label);
                 gfx_line(im, X0 - 2, Y0, X0, Y0,
                          MGRIDWIDTH, im->graph_col[GRC_MGRID]);
@@ -2171,10 +2206,8 @@ int horizontal_log_grid(
                  im->graph_col[GRC_FONT],
                  im->
                  text_prop[TEXT_PROP_AXIS].
-                 font,
-                 im->
-                 text_prop[TEXT_PROP_AXIS].
-                 size, im->tabwidth, 0.0,
+                 font_desc,
+                 im->tabwidth, 0.0,
                  GFX_H_RIGHT, GFX_V_CENTER, graph_label);
         /* minor grid */
         if (mid < 4 && exfrac == 1) {
@@ -2442,10 +2475,8 @@ void vertical_grid(
                  im->graph_col[GRC_FONT],
                  im->
                  text_prop[TEXT_PROP_AXIS].
-                 font,
-                 im->
-                 text_prop[TEXT_PROP_AXIS].
-                 size, im->tabwidth, 0.0,
+                 font_desc,
+                 im->tabwidth, 0.0,
                  GFX_H_CENTER, GFX_V_TOP, graph_label);
     }
 
@@ -2523,10 +2554,8 @@ void grid_paint(
                      im->graph_col[GRC_FONT],
                      im->
                      text_prop[TEXT_PROP_AXIS].
-                     font,
-                     im->
-                     text_prop[TEXT_PROP_AXIS].
-                     size, im->tabwidth, 0.0,
+                     font_desc,
+                     im->tabwidth, 0.0,
                      GFX_H_CENTER, GFX_V_CENTER, nodata);
         }
     }
@@ -2539,10 +2568,8 @@ void grid_paint(
              im->graph_col[GRC_FONT],
              im->
              text_prop[TEXT_PROP_UNIT].
-             font,
-             im->
-             text_prop[TEXT_PROP_UNIT].
-             size, im->tabwidth,
+             font_desc,
+             im->tabwidth,
              RRDGRAPH_YLEGEND_ANGLE, GFX_H_CENTER, GFX_V_CENTER, im->ylegend);
     /* graph title */
     gfx_text(im,
@@ -2550,18 +2577,16 @@ void grid_paint(
              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_TOP, im->title);
+             font_desc,
+             im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_TOP, im->title);
     /* rrdtool 'logo' */
     water_color = im->graph_col[GRC_FONT];
     water_color.alpha = 0.3;
     gfx_text(im, im->ximg - 4, 5,
              water_color,
              im->
-             text_prop[TEXT_PROP_AXIS].
-             font, 5.5, im->tabwidth,
+             text_prop[TEXT_PROP_WATERMARK].
+             font_desc, im->tabwidth,
              -90, GFX_H_LEFT, GFX_V_TOP, "RRDTOOL / TOBI OETIKER");
     /* graph watermark */
     if (im->watermark[0] != '\0') {
@@ -2569,8 +2594,8 @@ void grid_paint(
                  im->ximg / 2, im->yimg - 6,
                  water_color,
                  im->
-                 text_prop[TEXT_PROP_AXIS].
-                 font, 5.5, im->tabwidth, 0,
+                 text_prop[TEXT_PROP_WATERMARK].
+                 font_desc, im->tabwidth, 0,
                  GFX_H_CENTER, GFX_V_BOTTOM, im->watermark);
     }
 
@@ -2586,10 +2611,7 @@ void grid_paint(
                      im->graph_col[GRC_FONT],
                      im->
                      text_prop
-                     [TEXT_PROP_LEGEND].font,
-                     im->
-                     text_prop
-                     [TEXT_PROP_LEGEND].size,
+                     [TEXT_PROP_LEGEND].font_desc,
                      im->tabwidth, 0.0,
                      GFX_H_LEFT, GFX_V_BOTTOM, im->gdes[i].legend);
             /* The legend for GRAPH items starts with "M " to have
@@ -2603,11 +2625,8 @@ void grid_paint(
                                           im->
                                           text_prop
                                           [TEXT_PROP_LEGEND].
-                                          font,
-                                          im->
-                                          text_prop
-                                          [TEXT_PROP_LEGEND].
-                                          size, im->tabwidth, "o") * 1.2;
+                                          font_desc,
+                                          im->tabwidth, "o") * 1.2;
                 boxV = boxH;
                 /* shift the box up a bit */
                 Y0 -= boxV * 0.4;
@@ -2763,11 +2782,8 @@ int graph_size_location(
                                    im->
                                    text_prop
                                    [TEXT_PROP_AXIS].
-                                   font,
-                                   im->
-                                   text_prop
-                                   [TEXT_PROP_AXIS].
-                                   size, im->tabwidth, "0") * im->unitslength;
+                                   font_desc,
+                                   im->tabwidth, "0") * im->unitslength;
         }
     }
 
@@ -2948,11 +2964,17 @@ int graph_paint(
     double    areazero = 0.0;
     graph_desc_t *lastgdes = NULL;
     rrd_infoval_t info;
-    PangoFontMap *font_map = pango_cairo_font_map_get_default();
 
-    /* if we are lazy and there is nothing to PRINT ... quit now */
-    if (lazy && im->prt_c == 0)
+//    PangoFontMap *font_map = pango_cairo_font_map_get_default();
+
+    /* if we want and can be lazy ... quit now */
+    if (lazy) {
+        info.u_cnt = im->ximg;
+        grinfo_push(im, sprintf_alloc("image_width"), RD_I_CNT, info);
+        info.u_cnt = im->yimg;
+        grinfo_push(im, sprintf_alloc("image_height"), RD_I_CNT, info);
         return 0;
+    }
     /* pull the data from the rrd files ... */
     if (data_fetch(im) == -1)
         return -1;
@@ -2961,14 +2983,16 @@ int graph_paint(
         return -1;
     /* 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 ... 
+     * if there are no graph elements (i==0) we stop here ... 
      * if we are lazy, try to quit ... 
      */
     i = print_calc(im);
     if (i < 0)
         return -1;
+
     if ((i == 0) || lazy)
         return 0;
+
 /**************************************************************
  *** Calculating sizes and locations became a bit confusing ***
  *** so I moved this into a separate function.              ***
@@ -3052,10 +3076,11 @@ int graph_paint(
             (im->surface, CAIRO_SVG_VERSION_1_1);
         break;
     };
+    cairo_destroy(im->cr);
     im->cr = cairo_create(im->surface);
     cairo_set_antialias(im->cr, im->graph_antialias);
     cairo_scale(im->cr, im->zoom, im->zoom);
-    pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(font_map), 100);
+//    pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(font_map), 100);
     gfx_new_area(im, 0, 0, 0, im->yimg,
                  im->ximg, im->yimg, im->graph_col[GRC_BACK]);
     gfx_add_point(im, im->ximg, 0);
@@ -3556,6 +3581,10 @@ int rrd_graph(
         walker = walker->next;
     }
     walker = grinfo;
+    *xsize = 0;
+    *ysize = 0;
+    *ymin = 0;
+    *ymax = 0;
     while (walker) {
         if (strcmp(walker->key, "image_width") == 0) {
             *xsize = walker->value.u_int;
@@ -3600,12 +3629,10 @@ rrd_info_t *rrd_graph_v(
     char **argv)
 {
     image_desc_t im;
-    rrd_info_t  *grinfo;
-
+    rrd_info_t *grinfo;
     rrd_graph_init(&im);
     /* a dummy surface so that we can measure text sizes for placements */
-    im.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);
-    im.cr = cairo_create(im.surface);
+    
     rrd_graph_options(argc, argv, &im);
     if (rrd_test_error()) {
         rrd_info_free(im.grinfo);
@@ -3656,14 +3683,19 @@ rrd_info_t *rrd_graph_v(
 
     if (im.imginfo) {
         rrd_infoval_t info;
+        char     *path;
+        char     *filename;
 
+        path = strdup(im.graphfile);
+        filename = basename(path);
         info.u_str =
             sprintf_alloc(im.imginfo,
-                          im.graphfile,
+                          filename,
                           (long) (im.zoom *
                                   im.ximg), (long) (im.zoom * im.yimg));
         grinfo_push(&im, sprintf_alloc("image_info"), RD_I_STR, info);
         free(info.u_str);
+        free(path);
     }
     if (im.rendered_image) {
         rrd_infoval_t img;
@@ -3677,11 +3709,30 @@ rrd_info_t *rrd_graph_v(
     return grinfo;
 }
 
+static void 
+rrd_set_font_desc (
+    image_desc_t *im,int prop,char *font, double size ){
+    if (font){
+        strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1);        
+        im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0';   
+        im->text_prop[prop].font_desc = pango_font_description_from_string( font );        
+    };
+    if (size > 0){  
+        im->text_prop[prop].size = size;
+    };
+    if (im->text_prop[prop].font_desc && im->text_prop[prop].size ){
+        pango_font_description_set_size(im->text_prop[prop].font_desc, im->text_prop[prop].size * PANGO_SCALE);
+    };
+}
+
 void rrd_graph_init(
     image_desc_t
     *im)
 {
     unsigned int i;
+    char     *deffont = getenv("RRD_DEFAULT_FONT");
+    static PangoFontMap *fontmap = NULL;
+    PangoContext *context;
 
 #ifdef HAVE_TZSET
     tzset();
@@ -3693,7 +3744,7 @@ void rrd_graph_init(
 #endif
 #endif
     im->base = 1000;
-    im->cr = NULL;
+    im->daemon_addr = NULL;
     im->draw_x_grid = 1;
     im->draw_y_grid = 1;
     im->extra_flags = 0;
@@ -3720,7 +3771,6 @@ void rrd_graph_init(
     im->rendered_image = NULL;
     im->slopemode = 0;
     im->step = 0;
-    im->surface = NULL;
     im->symbol = ' ';
     im->tabwidth = 40.0;
     im->title[0] = '\0';
@@ -3739,51 +3789,45 @@ void rrd_graph_init(
     im->yorigin = 0;
     im->ysize = 100;
     im->zoom = 1;
+
+    im->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);     
+    im->cr = cairo_create(im->surface);
+
+    for (i = 0; i < DIM(text_prop); i++) {
+        im->text_prop[i].size = -1;
+        rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size);
+    }
+
+    if (fontmap == NULL){
+        fontmap = pango_cairo_font_map_get_default();
+    }
+
+    context =  pango_cairo_font_map_create_context((PangoCairoFontMap*)fontmap);
+
+    pango_cairo_context_set_resolution(context, 100);
+
+    pango_cairo_update_context(im->cr,context);
+
+    im->layout = pango_layout_new(context);
+
+//  im->layout = pango_cairo_create_layout(im->cr);
+
+
     cairo_font_options_set_hint_style
         (im->font_options, CAIRO_HINT_STYLE_FULL);
     cairo_font_options_set_hint_metrics
         (im->font_options, CAIRO_HINT_METRICS_ON);
     cairo_font_options_set_antialias(im->font_options, CAIRO_ANTIALIAS_GRAY);
+
+
+
     for (i = 0; i < DIM(graph_col); i++)
         im->graph_col[i] = graph_col[i];
-#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
-    {
-        char     *windir;
-        char      rrd_win_default_font[1000];
-
-        windir = getenv("windir");
-        /* %windir% is something like D:\windows or C:\winnt */
-        if (windir != NULL) {
-            strncpy(rrd_win_default_font, windir, 500);
-            rrd_win_default_font[500] = '\0';
-            strcat(rrd_win_default_font, "\\fonts\\");
-            strcat(rrd_win_default_font, RRD_DEFAULT_FONT);
-            for (i = 0; i < DIM(text_prop); i++) {
-                strncpy(text_prop[i].font,
-                        rrd_win_default_font, sizeof(text_prop[i].font) - 1);
-                text_prop[i].font[sizeof(text_prop[i].font) - 1] = '\0';
-            }
-        }
-    }
-#endif
-    {
-        char     *deffont;
-
-        deffont = getenv("RRD_DEFAULT_FONT");
-        if (deffont != NULL) {
-            for (i = 0; i < DIM(text_prop); i++) {
-                strncpy(text_prop[i].font, deffont,
-                        sizeof(text_prop[i].font) - 1);
-                text_prop[i].font[sizeof(text_prop[i].font) - 1] = '\0';
-            }
-        }
-    }
-    for (i = 0; i < DIM(text_prop); i++) {
-        im->text_prop[i].size = text_prop[i].size;
-        strcpy(im->text_prop[i].font, text_prop[i].font);
-    }
+
+
 }
 
+
 void rrd_graph_options(
     int argc,
     char *argv[],
@@ -3847,6 +3891,7 @@ void rrd_graph_options(
         { "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 */
         { "pango-markup",       no_argument,       0, 'P'},
+        { "daemon",             required_argument, 0, 'd'},
         {  0, 0, 0, 0}
 };
 /* *INDENT-ON* */
@@ -3861,7 +3906,7 @@ void rrd_graph_options(
         int       col_start, col_end;
 
         opt = getopt_long(argc, argv,
-                          "s:e:x:y:v:w:h:D:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMEX:L:S:T:NR:B:W:kP",
+                          "s:e:x:y:v:w:h:D:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMEX:L:S:T:NR:B:W:kPd:",
                           long_options, &option_index);
         if (opt == EOF)
             break;
@@ -4124,13 +4169,11 @@ void rrd_graph_options(
                     for (propidx = sindex;
                          propidx < TEXT_PROP_LAST; propidx++) {
                         if (size > 0) {
-                            im->text_prop[propidx].size = size;
+                            rrd_set_font_desc(im,propidx,NULL,size);   
                         }
-                        if ((int) strlen(optarg) > end) {
+                        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';
+                                rrd_set_font_desc(im,propidx,optarg + end + 1,0);   
                             } else {
                                 rrd_set_error
                                     ("expected : after font size in '%s'",
@@ -4205,6 +4248,24 @@ void rrd_graph_options(
             strncpy(im->watermark, optarg, 100);
             im->watermark[99] = '\0';
             break;
+        case 'd':
+        {
+            if (im->daemon_addr != NULL)
+            {
+                rrd_set_error ("You cannot specify --daemon "
+                        "more than once.");
+                return;
+            }
+
+            im->daemon_addr = strdup(optarg);
+            if (im->daemon_addr == NULL)
+            {
+              rrd_set_error("strdup failed");
+              return;
+            }
+
+            break;
+        }
         case '?':
             if (optopt != 0)
                 rrd_set_error("unknown option '%c'", optopt);
@@ -4212,7 +4273,17 @@ void rrd_graph_options(
                 rrd_set_error("unknown option '%s'", argv[optind - 1]);
             return;
         }
+    } /* while (1) */
+
+    {   /* try to connect to rrdcached */
+        int status = rrdc_connect(im->daemon_addr);
+        if (status != 0) return;
     }
+    
+    pango_cairo_context_set_font_options(pango_layout_get_context(im->layout), im->font_options);
+    pango_layout_context_changed(im->layout);
+
+
 
     if (im->logarithmic && im->minval <= 0) {
         rrd_set_error
@@ -4451,21 +4522,16 @@ int vdef_calc(
     graph_desc_t *src, *dst;
     rrd_value_t *data;
     long      step, steps;
-    unsigned long end;
 
     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, steps);
+         src->start, src->end, steps);
 #endif
     switch (dst->vf.op) {
     case VDEF_PERCENT:{