added TEXTALIGN command to change the default text alignment
[rrdtool.git] / src / rrd_graph.c
index aeea5dd..542c3b8 100644 (file)
@@ -235,6 +235,7 @@ enum gf_en gf_conv(
     conv_if(AREA, GF_AREA);
     conv_if(STACK, GF_STACK);
     conv_if(TICK, GF_TICK);
+    conv_if(TEXTALIGN, GF_TEXTALIGN);
     conv_if(DEF, GF_DEF);
     conv_if(CDEF, GF_CDEF);
     conv_if(VDEF, GF_VDEF);
@@ -327,16 +328,16 @@ int im_free(
     free(im->gdes);
     if (im->font_options)
         cairo_font_options_destroy(im->font_options);
-    
-    status = cairo_status (im->cr);
+
+    status = cairo_status(im->cr);
 
     if (im->cr)
         cairo_destroy(im->cr);
     if (im->surface)
         cairo_surface_destroy(im->surface);
     if (status)
-        fprintf(stderr,"OOPS: Cairo has issuesm it can't even die: %s\n",
-                         cairo_status_to_string (status));
+        fprintf(stderr, "OOPS: Cairo has issuesm it can't even die: %s\n",
+                cairo_status_to_string(status));
 
     return 0;
 }
@@ -1542,6 +1543,7 @@ int print_calc(
             graphelement = 1;
             break;
         case GF_COMMENT:
+        case GF_TEXTALIGN:
         case GF_DEF:
         case GF_CDEF:
         case GF_VDEF:
@@ -1578,6 +1580,7 @@ int leg_place(
     int       glue = 0;
     int       i, ii, mark = 0;
     char      prt_fctn; /*special printfunctions */
+    char      default_txtalign = TXA_JUSTIFIED; /*default line orientation*/
     int      *legspace;
 
     if (!(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH)) {
@@ -1595,6 +1598,10 @@ int leg_place(
 
             /* hide legends for rules which are not displayed */
 
+            if (im->gdes[i].gf == GF_TEXTALIGN){
+                default_txtalign = im->gdes[i].txtalign;
+            }
+
             if (!(im->extra_flags & FORCE_RULES_LEGEND)) {
                 if (im->gdes[i].gf == GF_HRULE &&
                     (im->gdes[i].yrule < im->minval
@@ -1632,22 +1639,24 @@ int leg_place(
                 return -1;
 
             }
-
-            /* remove exess space */
+            /* \n -> \l */
             if (prt_fctn == 'n') {
                 prt_fctn = 'l';
             }
 
+            /* remove exess space from the end of the legend for \g*/            
             while (prt_fctn == 'g' &&
                    leg_cc > 0 && im->gdes[i].legend[leg_cc - 1] == ' ') {
                 leg_cc--;
                 im->gdes[i].legend[leg_cc] = '\0';
             }
+
             if (leg_cc != 0) {
+
+                /* no interleg space if string ends in \g */
                 legspace[i] = (prt_fctn == 'g' ? 0 : interleg);
 
                 if (fill > 0) {
-                    /* no interleg space if string ends in \g */
                     fill += legspace[i];
                 }
                 fill += gfx_get_text_width(im, fill + border,
@@ -1664,10 +1673,25 @@ int leg_place(
             if (prt_fctn == 'g') {
                 prt_fctn = '\0';
             }
-            if (prt_fctn == '\0') {
-                if (i == im->gdes_c - 1)
-                    prt_fctn = 'l';
 
+            if (prt_fctn == '\0') {
+                if (i == im->gdes_c - 1 || fill > im->ximg - 2 * border) {
+                    /* just one legend item is left right or center */
+                    switch (default_txtalign){
+                    case TXA_RIGHT:
+                         prt_fctn = 'r';
+                         break;
+                    case TXA_CENTER:
+                         prt_fctn = 'c';
+                         break;
+                    case TXA_JUSTIFIED:
+                         prt_fctn = 'j';
+                         break;
+                    default:
+                         prt_fctn = 'l';
+                         break;
+                    }
+                }
                 /* is it time to place the legends ? */
                 if (fill > im->ximg - 2 * border) {
                     if (leg_c > 1) {
@@ -1675,11 +1699,10 @@ int leg_place(
                         i--;
                         fill = fill_last;
                         leg_c--;
-                        prt_fctn = 'j';
-                    } else {
-                        prt_fctn = 'l';
                     }
-
+                }
+                if (leg_c == 1 && prt_fctn == 'j'){
+                    prt_fctn = 'l';
                 }
             }
 
@@ -1971,6 +1994,10 @@ double frexp10(
     return mnt;
 }
 
+/* from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */
+/* yes we are loosing precision by doing tos with floats instead of doubles
+   but it seems more stable this way. */
+
 static int AlmostEqual2sComplement(
     float A,
     float B,
@@ -2407,11 +2434,11 @@ void axis_paint(
 
     /* arrow for X and Y axis direction */
 
-    gfx_new_area(im, im->xorigin + im->xsize + 2, im->yorigin - 3, im->xorigin + im->xsize + 2, im->yorigin + 3, im->xorigin + im->xsize + 7, im->yorigin,    /* horyzontal */
+    gfx_new_area(im, im->xorigin + im->xsize + 2, im->yorigin - 3, im->xorigin + im->xsize + 2, im->yorigin + 3, im->xorigin + im->xsize + 7, im->yorigin,  /* horyzontal */
                  im->graph_col[GRC_ARROW]);
     gfx_close_path(im);
 
-    gfx_new_area(im, im->xorigin - 3, im->yorigin - im->ysize - 2, im->xorigin + 3, im->yorigin - im->ysize - 2, im->xorigin, im->yorigin - im->ysize - 7,    /* vertical */
+    gfx_new_area(im, im->xorigin - 3, im->yorigin - im->ysize - 2, im->xorigin + 3, im->yorigin - im->ysize - 2, im->xorigin, im->yorigin - im->ysize - 7,  /* vertical */
                  im->graph_col[GRC_ARROW]);
     gfx_close_path(im);
 
@@ -2844,9 +2871,17 @@ int graph_size_location(
     return 0;
 }
 
-/* from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */
-/* yes we are loosing precision by doing tos with floats instead of doubles
-   but it seems more stable this way. */
+
+
+static cairo_status_t cairo_write_func_file(
+       void *closure,
+       const unsigned char *data,
+       unsigned int length)
+{
+       if (fwrite(data, length, 1, closure) != 1)
+               return CAIRO_STATUS_WRITE_ERROR;
+       return CAIRO_STATUS_SUCCESS;
+}
 
 
 /* draw that picture thing ... */
@@ -2983,6 +3018,7 @@ int graph_paint(
         case GF_PRINT:
         case GF_GPRINT:
         case GF_COMMENT:
+        case GF_TEXTALIGN:
         case GF_HRULE:
         case GF_VRULE:
         case GF_XPORT:
@@ -3276,11 +3312,20 @@ int graph_paint(
 
     switch (im->imgformat) {
     case IF_PNG:
-        if (cairo_surface_write_to_png(im->surface, im->graphfile) !=
-            CAIRO_STATUS_SUCCESS) {
-            rrd_set_error("Could not save png to '%s'", im->graphfile);
-            return 1;
-        }
+               {
+                       cairo_status_t status;
+               
+                       if (strcmp(im->graphfile, "-") == 0) {
+               status = cairo_surface_write_to_png_stream(im->surface, &cairo_write_func_file, (void*)stdout);
+                       } else {
+               status = cairo_surface_write_to_png(im->surface, im->graphfile);
+                       }
+               
+               if (status != CAIRO_STATUS_SUCCESS) {
+               rrd_set_error("Could not save png to '%s'", im->graphfile);
+                   return 1;
+               }
+               }
         break;
     default:
         cairo_show_page(im->cr);