/****************************************************************************
- * RRDtool 1.3rc2 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"
+#include "plbasename.h"
#endif
+
#include "rrd_tool.h"
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
#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[] = {
yval = im->yorigin - pixie * (log10(value) - log10(im->minval));
}
}
- /* make sure we don't return anything too unreasonable. GD lib can
- get terribly slow when drawing lines outside its scope. This is
- especially problematic in connection with the rigid option */
- if (!im->rigid) {
- /* keep yval as-is */
- } else if (yval > im->yorigin) {
- yval = im->yorigin + 0.00001;
- } else if (yval < im->yorigin - im->ysize) {
- yval = im->yorigin - im->ysize - 0.00001;
- }
return yval;
}
conv_if(XPORT, GF_XPORT);
conv_if(SHIFT, GF_SHIFT);
- return (-1);
+ return (enum gf_en)(-1);
}
enum gfx_if_en if_conv(
conv_if(EPS, IF_EPS);
conv_if(PDF, IF_PDF);
- return (-1);
+ return (enum gfx_if_en)(-1);
}
enum tmt_en tmt_conv(
conv_if(WEEK, TMT_WEEK);
conv_if(MONTH, TMT_MONTH);
conv_if(YEAR, TMT_YEAR);
- return (-1);
+ return (enum tmt_en)(-1);
}
enum grc_en grc_conv(
conv_if(AXIS, GRC_AXIS);
conv_if(FRAME, GRC_FRAME);
- return -1;
+ return (enum grc_en)(-1);
}
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);
- return -1;
+ conv_if(WATERMARK, TEXT_PROP_WATERMARK);
+ return (enum text_prop_en)(-1);
}
image_desc_t *im)
{
unsigned long i, ii;
- cairo_status_t status = 0;
+ cairo_status_t status = (cairo_status_t) 0;
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 */
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;
}
if (im->unitsexponent != 9999) {
/* unitsexponent = 9, 6, 3, 0, -3, -6, -9, etc */
- viewdigits = floor(im->unitsexponent / 3);
+ viewdigits = floor((double)(im->unitsexponent / 3));
} else {
viewdigits = digits;
}
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,
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)
/* add one entry to the array that keeps track of the step sizes of the
* data sources going into the CDEF. */
if ((steparray =
- rrd_realloc(steparray,
+ (long*)rrd_realloc(steparray,
(++stepcnt +
1) * sizeof(*steparray))) == NULL) {
rrd_set_error("realloc steparray");
*/
im->gdes[gdi].step = lcd(steparray);
free(steparray);
- if ((im->gdes[gdi].data = malloc(((im->gdes[gdi].end -
+ if ((im->gdes[gdi].data = (rrd_value_t*)malloc(((im->gdes[gdi].end -
im->gdes[gdi].start)
/ im->gdes[gdi].step)
* sizeof(double))) == NULL) {
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 int AlmostEqual2sComplement(
float A,
float B,
for (i = 0; i < im->gdes_c; i++) {
if ((im->gdes[i].gf == GF_LINE) ||
(im->gdes[i].gf == GF_AREA) || (im->gdes[i].gf == GF_TICK)) {
- if ((im->gdes[i].p_data = malloc((im->xsize + 1)
+ if ((im->gdes[i].p_data = (rrd_value_t*)malloc((im->xsize + 1)
* sizeof(rrd_value_t))) == NULL) {
rrd_set_error("malloc data_proc");
return -1;
if (im->logarithmic) {
if (isnan(minval) || isnan(maxval) || maxval <= 0) {
- minval = 0.0; /* catching this right away below */
+ minval = 0.0; /* catching this right away below */
maxval = 5.1;
}
/* in logarithm mode, where minval is smaller or equal
}
}
- /* adjust min and max values given by the user*/
+ /* adjust min and max values given by the user */
/* for logscale we add something on top */
if (isnan(im->minval)
|| ((!im->rigid) && im->minval > minval)
}
if (im->gdes[i].gf == GF_PRINT) {
- infoval prline;
+ rrd_infoval_t prline;
if (im->gdes[i].strftm) {
- prline.u_str = malloc((FMT_LEG_LEN + 2) * sizeof(char));
+ prline.u_str = (char*)malloc((FMT_LEG_LEN + 2) * sizeof(char));
strftime(prline.u_str,
FMT_LEG_LEN, im->gdes[i].format, &tmvdef);
} else if (bad_format(im->gdes[i].format)) {
int border = im->text_prop[TEXT_PROP_LEGEND].size * 2.0;
int fill = 0, fill_last;
int leg_c = 0;
- int leg_x = border, leg_y = im->yimg;
+ 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 */
int *legspace;
+ char *tab;
if (!(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH)) {
- if ((legspace = malloc(im->gdes_c * sizeof(int))) == NULL) {
+ if ((legspace = (int*)malloc(im->gdes_c * sizeof(int))) == NULL) {
rrd_set_error("malloc for legspace");
return -1;
}
- if (im->extra_flags & FULL_SIZE_MODE)
- leg_y = leg_y_prev =
- leg_y - (int) (im->text_prop[TEXT_PROP_LEGEND].size * 1.8);
for (i = 0; i < im->gdes_c; i++) {
+ char prt_fctn; /*special printfunctions */
fill_last = fill;
/* hide legends for rules which are not displayed */
if (im->gdes[i].gf == GF_TEXTALIGN) {
im->gdes[i].legend[0] = '\0';
}
+ /* turn \\t into tab */
+ while ((tab = strstr(im->gdes[i].legend, "\\t"))) {
+ memmove(tab, tab + 1, strlen(tab));
+ tab[0] = (char) 9;
+ }
leg_cc = strlen(im->gdes[i].legend);
- /* is there a controle code ant the end of the legend string ? */
- /* and it is not a tab \\t */
- if (leg_cc >= 2
- && im->gdes[i].legend[leg_cc -
- 2] == '\\'
- && im->gdes[i].legend[leg_cc - 1] != 't') {
+ /* is there a controle code at the end of the legend string ? */
+ if (leg_cc >= 2 && im->gdes[i].legend[leg_cc - 2] == '\\') {
prt_fctn = im->gdes[i].legend[leg_cc - 1];
leg_cc -= 2;
im->gdes[i].legend[leg_cc] = '\0';
prt_fctn != 'r' &&
prt_fctn != 'j' &&
prt_fctn != 'c' &&
- prt_fctn != 's' &&
- prt_fctn != 't' && prt_fctn != '\0' && prt_fctn != 'g') {
+ prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
free(legspace);
rrd_set_error
("Unknown control code at the end of '%s\\%c'",
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 {
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++) {
im->gdes[ii].leg_x = leg_x;
im->gdes[ii].leg_y = leg_y;
leg_x +=
- gfx_get_text_width(im, leg_x,
+ (double)gfx_get_text_width(im, leg_x,
im->
text_prop
[TEXT_PROP_LEGEND].
- font,
- 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;
- if (im->extra_flags & FULL_SIZE_MODE) {
- /* only add y space if there was text on the line */
- if (leg_x > border || prt_fctn == 's')
- leg_y -= im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
- if (prt_fctn == 's')
- leg_y += im->text_prop[TEXT_PROP_LEGEND].size;
- } else {
- if (leg_x > border || prt_fctn == 's')
- leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
- if (prt_fctn == 's')
- leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
- }
+ if (leg_x > border || prt_fctn == 's')
+ leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ if (prt_fctn == 's')
+ leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
fill = 0;
leg_c = 0;
mark = ii;
}
if (im->extra_flags & FULL_SIZE_MODE) {
- if (leg_y != leg_y_prev) {
- *gY = leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
- im->yorigin =
- leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ /* now for some backpaddeling. We have to shift up all the
+ legend items into the graph and tell the caller about the
+ space we used up. */
+ long shift_up = leg_y - im->yimg - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 + border * 0.7;
+ for (i = 0; i < im->gdes_c; i++) {
+ im->gdes[i].leg_y -= shift_up;
}
+ im->yorigin = im->yorigin - leg_y + im->yimg - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 - border;
+ *gY = im->yorigin;
} else {
- im->yimg = leg_y_prev;
- /* if we did place some legends we have to add vertical space */
- if (leg_y != im->yimg)
- im->yimg += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
+ im->yimg =
+ leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 +
+ border * 0.6;
}
free(legspace);
}
/* the xaxis labels are determined from the number of seconds per pixel
in the requested graph */
-
-
int calc_horizontal_grid(
image_desc_t
*im)
if (im->ygrid_scale.gridstep == 0) /* range is one -> 0.1 is reasonable scale */
im->ygrid_scale.gridstep = 0.1;
/* should have at least 5 lines but no more then 15 */
- if (range / im->ygrid_scale.gridstep < 5)
+ if (range / im->ygrid_scale.gridstep < 5
+ && im->ygrid_scale.gridstep >= 30)
im->ygrid_scale.gridstep /= 10;
if (range / im->ygrid_scale.gridstep > 15)
im->ygrid_scale.gridstep *= 10;
if (range / im->ygrid_scale.gridstep > 5) {
im->ygrid_scale.labfact = 1;
- if (range / im->ygrid_scale.gridstep > 8)
+ if (range / im->ygrid_scale.gridstep > 8
+ || im->ygrid_scale.gridstep <
+ 1.8 * im->text_prop[TEXT_PROP_AXIS].size)
im->ygrid_scale.labfact = 2;
} else {
im->ygrid_scale.gridstep /= 5;
sprintf(im->ygrid_scale.labfmt,
"%%%d.0f%s", len, (im->symbol != ' ' ? " %c" : ""));
}
- } else {
+ } else { /* classic rrd grid */
for (i = 0; ylab[i].grid > 0; i++) {
pixel = im->ysize / (scaledrange / ylab[i].grid);
gridind = i;
- if (pixel > 7)
+ if (pixel >= 5)
break;
}
for (i = 0; i < 4; i++) {
if (pixel * ylab[gridind].lfac[i] >=
- 2.5 * im->text_prop[TEXT_PROP_AXIS].size) {
+ 1.8 * im->text_prop[TEXT_PROP_AXIS].size) {
im->ygrid_scale.labfact = ylab[gridind].lfac[i];
break;
}
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;
}
}
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_text ( im,
+ X1+7, Y0,
+ im->graph_col[GRC_FONT],
+ im->text_prop[TEXT_PROP_AXIS].font_desc,
+ im->tabwidth,0.0, GFX_H_LEFT, GFX_V_CENTER,
+ graph_label_right );
+ }
+
gfx_text(im,
X0 -
im->
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]);
double mnt;
int iexp;
- iexp = floor(log(fabs(x)) / log(10));
+ iexp = floor(log((double)fabs(x)) / log((double)10));
mnt = x / pow(10.0, iexp);
if (mnt >= 10.0) {
iexp++;
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. */
-
/* logaritmic horizontal grid */
int horizontal_log_grid(
else
symbol = '?';
sprintf(graph_label, "%3.0f %c", pvalue, symbol);
- } else
+ } 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_text ( im,
+ X1+7, Y0,
+ im->graph_col[GRC_FONT],
+ im->text_prop[TEXT_PROP_AXIS].font_desc,
+ im->tabwidth,0.0, GFX_H_LEFT, GFX_V_CENTER,
+ graph_label_right );
+ }
+
gfx_text(im,
X0 -
im->
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) {
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);
}
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);
+ if (im->second_axis_scale != 0){
+ gfx_line ( im, 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,
+ im->xorigin+im->xsize-2, im->yorigin-im->ysize-2,
+ im->xorigin+im->xsize+3, im->yorigin-im->ysize-2,
+ im->xorigin+im->xsize, im->yorigin-im->ysize-7, /* LINEOFFSET */
+ im->graph_col[GRC_ARROW]);
+ gfx_close_path(im);
+ }
+
}
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);
}
}
/* yaxis unit description */
- gfx_text(im,
- 10,
- (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_CENTER, GFX_V_CENTER, im->ylegend);
+ if (im->ylegend[0] != '\0'){
+ gfx_text(im,
+ 10,
+ (im->yorigin -
+ im->ysize / 2),
+ im->graph_col[GRC_FONT],
+ im->
+ text_prop[TEXT_PROP_UNIT].
+ font_desc,
+ im->tabwidth,
+ RRDGRAPH_YLEGEND_ANGLE, GFX_H_CENTER, GFX_V_CENTER, im->ylegend);
+ }
+ if (im->second_axis_legend[0] != '\0'){
+ double Xylabel=gfx_get_text_width(im, 0,
+ im->text_prop[TEXT_PROP_AXIS].font_desc,
+ im->tabwidth,
+ "0") * im->unitslength
+ + im->text_prop[TEXT_PROP_UNIT].size *2;
+ gfx_text( im,
+ im->xorigin+im->xsize+Xylabel+8, (im->yorigin - im->ysize/2),
+ im->graph_col[GRC_FONT],
+ im->text_prop[TEXT_PROP_UNIT].font_desc,
+ im->tabwidth,
+ RRDGRAPH_YLEGEND_ANGLE,
+ GFX_H_CENTER, GFX_V_CENTER,
+ im->second_axis_legend);
+ }
+
/* graph title */
gfx_text(im,
im->ximg / 2, 6,
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,
- -90, GFX_H_LEFT, GFX_V_TOP, "RRDTOOL / TOBI OETIKER");
+ if (!(im->extra_flags & NO_RRDTOOL_TAG)){
+ 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_WATERMARK].
+ font_desc, im->tabwidth,
+ -90, GFX_H_LEFT, GFX_V_TOP, "RRDTOOL / TOBI OETIKER");
+ }
/* graph watermark */
if (im->watermark[0] != '\0') {
gfx_text(im,
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);
}
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
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;
return 0;
}
- /** +---+--------------------------------------------+
- ** | y |...............graph title..................|
- ** | +---+-------------------------------+--------+
- ** | a | y | | |
- ** | x | | | |
- ** | i | a | | pie |
- ** | s | x | main graph area | chart |
- ** | | i | | area |
- ** | t | s | | |
- ** | i | | | |
- ** | t | l | | |
- ** | l | b +-------------------------------+--------+
- ** | e | l | x axis labels | |
- ** +---+---+-------------------------------+--------+
- ** |....................legends.....................|
- ** +------------------------------------------------+
- ** | watermark |
- ** +------------------------------------------------+
+ /** +---+-----------------------------------+
+ ** | y |...............graph title.........|
+ ** | +---+-------------------------------+
+ ** | a | y | |
+ ** | x | | |
+ ** | i | a | |
+ ** | s | x | main graph area |
+ ** | | i | |
+ ** | t | s | |
+ ** | i | | |
+ ** | t | l | |
+ ** | l | b +-------------------------------+
+ ** | e | l | x axis labels |
+ ** +---+---+-------------------------------+
+ ** |....................legends............|
+ ** +---------------------------------------+
+ ** | watermark |
+ ** +---------------------------------------+
*/
if (im->ylegend[0] != '\0') {
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;
}
}
if (im->extra_flags & FULL_SIZE_MODE) {
/* The actual size of the image to draw has been determined by the user.
** The graph area is the space remaining after accounting for the legend,
- ** the watermark, the pie chart, the axis labels, and the title.
+ ** the watermark, the axis labels, and the title.
*/
im->xorigin = 0;
im->ximg = im->xsize;
im->yorigin = im->ysize;
Xmain = im->ximg;
Ymain = im->yimg;
- im->yorigin += Ytitle;
/* Now calculate the total size. Insert some spacing where
desired. im->xorigin and im->yorigin need to correspond
with the lower left corner of the main graph area or, if
this one is not set, the imaginary box surrounding the
pie chart area. */
/* Initial size calculation for the main graph area */
- Xmain = im->ximg - (Xylabel + 2 * Xspacing);
- if (Xmain)
- Xmain -= Xspacing; /* put space between main graph area and right edge */
+ Xmain = im->ximg - Xylabel - 3 * Xspacing;
+
im->xorigin = Xspacing + Xylabel;
- /* the length of the title should not influence with width of the graph
- if (Xtitle > im->ximg) im->ximg = Xtitle; */
+
if (Xvertical) { /* unit description */
Xmain -= Xvertical;
im->xorigin += Xvertical;
}
+
+ /* adjust space for second axis */
+ if (im->second_axis_scale != 0){
+ Xmain -= Xylabel + Xspacing;
+ }
+ if (im->extra_flags & NO_RRDTOOL_TAG){
+ Xmain += Xspacing;
+ }
+ if (im->second_axis_legend[0] != '\0' ) {
+ Xmain -= im->text_prop[TEXT_PROP_UNIT].size * 1.5;
+ }
+
im->xsize = Xmain;
+
xtr(im, 0);
/* The vertical size of the image is known in advance. The main graph area
** (Ymain) and im->yorigin must be set according to the space requirements
** of the legend and the axis labels.
*/
if (im->extra_flags & NOLEGEND) {
- /* set dimensions correctly if using full size mode with no legend */
- im->yorigin =
- im->yimg -
+ im->yorigin = im->yimg -
im->text_prop[TEXT_PROP_AXIS].size * 2.5 - Yspacing;
Ymain = im->yorigin;
- } else {
+ }
+ else {
/* Determine where to place the legends onto the image.
** Set Ymain and adjust im->yorigin to match the space requirements.
*/
*/
/* don't care for the with of the title
Xtitle = gfx_get_text_width(im->canvas, 0,
- im->text_prop[TEXT_PROP_TITLE].font,
- im->text_prop[TEXT_PROP_TITLE].size,
+ im->text_prop[TEXT_PROP_TITLE].font_desc,
im->tabwidth,
im->title, 0) + 2*Xspacing; */
Ytitle = im->text_prop[TEXT_PROP_TITLE].size * 2.6 + 10;
** size already allocated.
*/
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;
+ }
+
if (Xmain)
im->ximg += Xspacing;
im->xorigin = Xspacing + Xylabel;
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
** the sum of {Ytitle, Ymain, Yxlabel, Ylegend, Ywatermark} with
*data,
unsigned int length)
{
- image_desc_t *im = closure;
+ image_desc_t *im = (image_desc_t*)closure;
im->rendered_image =
- realloc(im->rendered_image, im->rendered_image_size + length);
+ (unsigned char*)realloc(im->rendered_image, im->rendered_image_size + length);
if (im->rendered_image == NULL)
return CAIRO_STATUS_WRITE_ERROR;
memcpy(im->rendered_image + im->rendered_image_size, data, length);
int lazy = lazy_check(im);
double areazero = 0.0;
graph_desc_t *lastgdes = NULL;
- infoval info;
- PangoFontMap *font_map = pango_cairo_font_map_get_default();
+ rrd_infoval_t info;
- /* 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;
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. ***
case IF_PDF:
im->gridfit = 0;
im->surface = strlen(im->graphfile)
- ?
- cairo_pdf_surface_create_for_stream
- (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom)
- : cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom,
- im->yimg * im->zoom);
+ ? cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom,
+ im->yimg * im->zoom)
+ : cairo_pdf_surface_create_for_stream
+ (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom);
break;
case IF_EPS:
im->gridfit = 0;
im->surface = strlen(im->graphfile)
?
- cairo_ps_surface_create_for_stream
- (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom)
- : cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom,
- im->yimg * im->zoom);
+ cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom,
+ im->yimg * im->zoom)
+ : cairo_ps_surface_create_for_stream
+ (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom);
break;
case IF_SVG:
im->gridfit = 0;
im->surface = strlen(im->graphfile)
?
- cairo_svg_surface_create_for_stream
- (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom)
- : cairo_svg_surface_create(im->
- graphfile,
- im->
- ximg * im->zoom, im->yimg * im->zoom);
+ cairo_svg_surface_create(im->
+ graphfile,
+ im->ximg * im->zoom, im->yimg * im->zoom)
+ : cairo_svg_surface_create_for_stream
+ (&cairo_output, im, im->ximg * im->zoom, im->yimg * im->zoom);
cairo_svg_surface_restrict_to_version
(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);
im->yorigin - im->ysize, im->graph_col[GRC_CANVAS]);
gfx_add_point(im, im->xorigin, im->yorigin - im->ysize);
gfx_close_path(im);
+ cairo_rectangle(im->cr, im->xorigin, im->yorigin - im->ysize - 1.0,
+ im->xsize, im->ysize + 2.0);
+ cairo_clip(im->cr);
if (im->minval > 0.0)
areazero = im->minval;
if (im->maxval < 0.0)
if (im->gdes[i].yrule > 0) {
gfx_line(im,
im->xorigin + ii,
- im->yorigin,
+ im->yorigin + 1.0,
im->xorigin + ii,
im->yorigin -
im->gdes[i].yrule *
} else if (im->gdes[i].yrule < 0) {
gfx_line(im,
im->xorigin + ii,
- im->yorigin - im->ysize,
+ im->yorigin - im->ysize - 1.0,
im->xorigin + ii,
- im->yorigin - (1 -
+ im->yorigin - im->ysize -
im->gdes[i].
- yrule) *
+ yrule *
im->ysize, 1.0, im->gdes[i].col);
}
}
break;
} /* switch */
}
+ cairo_reset_clip(im->cr);
/* grid_paint also does the text */
if (!(im->extra_flags & ONLY_GRAPH))
rrd_set_error("Could not save png to '%s'", im->graphfile);
return 1;
}
- }
break;
+ }
default:
if (strlen(im->graphfile)) {
cairo_show_page(im->cr);
double *ymax)
{
int prlines = 0;
- info_t *grinfo = NULL;
- info_t *walker;
+ rrd_info_t *grinfo = NULL;
+ rrd_info_t *walker;
grinfo = rrd_graph_v(argc, argv);
if (grinfo == NULL)
if (strcmp(walker->key, "image_info") == 0) {
prlines++;
if (((*prdata) =
- rrd_realloc((*prdata),
+ (char**)rrd_realloc((*prdata),
(prlines + 1) * sizeof(char *))) == NULL) {
rrd_set_error("realloc prdata");
return 0;
}
/* imginfo goes to position 0 in the prdata array */
- (*prdata)[prlines - 1] = malloc((strlen(walker->value.u_str)
+ (*prdata)[prlines - 1] = (char*)malloc((strlen(walker->value.u_str)
+ 2) * sizeof(char));
strcpy((*prdata)[prlines - 1], walker->value.u_str);
(*prdata)[prlines] = NULL;
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;
+ *xsize = walker->value.u_cnt;
} else if (strcmp(walker->key, "image_height") == 0) {
- *ysize = walker->value.u_int;
+ *ysize = walker->value.u_cnt;
} else if (strcmp(walker->key, "value_min") == 0) {
*ymin = walker->value.u_val;
} else if (strcmp(walker->key, "value_max") == 0) {
*ymax = walker->value.u_val;
- } else if (strncmp(walker->key, "print", 6) == 0) { /* keys are prdate[0..] */
+ } else if (strncmp(walker->key, "print", 5) == 0) { /* keys are prdate[0..] */
prlines++;
if (((*prdata) =
- rrd_realloc((*prdata),
+ (char**)rrd_realloc((*prdata),
(prlines + 1) * sizeof(char *))) == NULL) {
rrd_set_error("realloc prdata");
return 0;
}
- (*prdata)[prlines - 1] = malloc((strlen(walker->value.u_str)
+ (*prdata)[prlines - 1] = (char*)malloc((strlen(walker->value.u_str)
+ 2) * sizeof(char));
(*prdata)[prlines] = NULL;
strcpy((*prdata)[prlines - 1], walker->value.u_str);
/* skip anything else */
walker = walker->next;
}
- info_free(grinfo);
+ rrd_info_free(grinfo);
return 0;
}
** - options parsing now in rrd_graph_options()
** - script parsing now in rrd_graph_script()
*/
-info_t *rrd_graph_v(
+rrd_info_t *rrd_graph_v(
int argc,
char **argv)
{
image_desc_t im;
- 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()) {
- info_free(im.grinfo);
+ rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
if (optind >= argc) {
- info_free(im.grinfo);
+ rrd_info_free(im.grinfo);
im_free(&im);
rrd_set_error("missing filename");
return NULL;
if (strlen(argv[optind]) >= MAXPATH) {
rrd_set_error("filename (including path) too long");
- info_free(im.grinfo);
+ rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
rrd_graph_script(argc, argv, &im, 1);
if (rrd_test_error()) {
- info_free(im.grinfo);
+ rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
/* Everything is now read and the actual work can start */
if (graph_paint(&im) == -1) {
- info_free(im.grinfo);
+ rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
*/
if (im.imginfo) {
- infoval info;
+ 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) {
- infoval img;
+ rrd_infoval_t img;
img.u_blo.size = im.rendered_image_size;
img.u_blo.ptr = im.rendered_image;
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();
#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;
im->grid_dash_off = 1;
im->grid_dash_on = 1;
im->gridfit = 1;
- im->grinfo = (info_t *) NULL;
- im->grinfo_current = (info_t *) NULL;
+ im->grinfo = (rrd_info_t *) NULL;
+ im->grinfo_current = (rrd_info_t *) NULL;
im->imgformat = IF_PNG;
im->imginfo = NULL;
im->lazy = 0;
im->rendered_image = NULL;
im->slopemode = 0;
im->step = 0;
- im->surface = NULL;
im->symbol = ' ';
im->tabwidth = 40.0;
im->title[0] = '\0';
im->unitslength = 6;
im->viewfactor = 1.0;
im->watermark[0] = '\0';
+ im->with_markup = 0;
im->ximg = 0;
im->xlab_user.minsec = -1;
im->xorigin = 0;
im->ygridstep = DNAN;
im->yimg = 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->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[],
char scan_gtm[12], scan_mtm[12], scan_ltm[12], col_nam[12];
time_t start_tmp = 0, end_tmp = 0;
long long_tmp;
- struct rrd_time_value start_tv, end_tv;
+ rrd_time_value_t start_tv, end_tv;
long unsigned int color;
char *old_locale = "";
/* defines for long options without a short equivalent. should be bytes,
and may not collide with (the ASCII value of) short options */
#define LONGOPT_UNITS_SI 255
+
+/* *INDENT-OFF* */
struct option long_options[] = {
- {
- "start", required_argument, 0, 's'}, {
- "end", required_argument, 0,
- 'e'}, {
- "x-grid",
- required_argument, 0,
- 'x'}, {
- "y-grid",
- required_argument,
- 0, 'y'}, {
- "vertical-label",
- required_argument,
- 0,
- 'v'}, {
- "width",
- required_argument,
- 0,
- 'w'},
- {
- "height", required_argument, 0, 'h'}, {
- "full-size-mode", no_argument,
- 0, 'D'}, {
- "interlaced",
- no_argument, 0,
- 'i'}, {
- "upper-limit",
- required_argument,
- 0,
- 'u'}, {
- "lower-limit",
- required_argument,
- 0,
- 'l'}, {
- "rigid",
- no_argument,
- 0,
- 'r'},
- {
- "base", required_argument, 0, 'b'}, {
- "logarithmic", no_argument, 0,
- 'o'}, {
- "color",
- required_argument, 0,
- 'c'}, {
- "font",
- required_argument,
- 0, 'n'}, {
- "title",
- required_argument,
- 0, 't'},
- {
- "imginfo", required_argument, 0, 'f'}, {
- "imgformat",
- required_argument, 0, 'a'}, {
- "lazy",
- no_argument,
- 0,
- 'z'},
- {
- "zoom", required_argument, 0, 'm'}, {
- "no-legend", no_argument, 0,
- 'g'}, {
- "force-rules-legend",
- no_argument,
- 0, 'F'}, {
- "only-graph",
- no_argument, 0,
- 'j'}, {
- "alt-y-grid",
- no_argument,
- 0, 'Y'},
- {
- "no-minor", no_argument, 0, 'I'}, {
- "slope-mode", no_argument, 0,
- 'E'}, {
- "alt-autoscale",
- no_argument, 0, 'A'}, {
- "alt-autoscale-min",
- no_argument,
- 0,
- 'J'}, {
- "alt-autoscale-max",
- no_argument,
- 0,
- 'M'}, {
- "no-gridfit",
- no_argument,
- 0,
- 'N'},
- {
- "units-exponent", required_argument,
- 0, 'X'}, {
- "units-length", required_argument,
- 0, 'L'}, {
- "units", required_argument, 0,
- LONGOPT_UNITS_SI}, {
- "step", required_argument, 0,
- 'S'}, {
- "tabwidth",
- required_argument, 0,
- 'T'}, {
- "font-render-mode",
- required_argument,
- 0, 'R'}, {
- "graph-render-mode",
- required_argument,
- 0,
- 'G'},
- {
- "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 */
- {
- 0, 0, 0, 0}
- };
+ { "start", required_argument, 0, 's'},
+ { "end", required_argument, 0, 'e'},
+ { "x-grid", required_argument, 0, 'x'},
+ { "y-grid", required_argument, 0, 'y'},
+ { "vertical-label", required_argument, 0, 'v'},
+ { "width", required_argument, 0, 'w'},
+ { "height", required_argument, 0, 'h'},
+ { "full-size-mode", no_argument, 0, 'D'},
+ { "interlaced", no_argument, 0, 'i'},
+ { "upper-limit", required_argument, 0, 'u'},
+ { "lower-limit", required_argument, 0, 'l'},
+ { "rigid", no_argument, 0, 'r'},
+ { "base", required_argument, 0, 'b'},
+ { "logarithmic", no_argument, 0, 'o'},
+ { "color", required_argument, 0, 'c'},
+ { "font", required_argument, 0, 'n'},
+ { "title", required_argument, 0, 't'},
+ { "imginfo", required_argument, 0, 'f'},
+ { "imgformat", required_argument, 0, 'a'},
+ { "lazy", no_argument, 0, 'z'},
+ { "zoom", required_argument, 0, 'm'},
+ { "no-legend", no_argument, 0, 'g'},
+ { "force-rules-legend", no_argument, 0, 'F'},
+ { "only-graph", no_argument, 0, 'j'},
+ { "alt-y-grid", no_argument, 0, 'Y'},
+ {"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},
+ { "no-minor", no_argument, 0, 'I'},
+ { "slope-mode", no_argument, 0, 'E'},
+ { "alt-autoscale", no_argument, 0, 'A'},
+ { "alt-autoscale-min", no_argument, 0, 'J'},
+ { "alt-autoscale-max", no_argument, 0, 'M'},
+ { "no-gridfit", no_argument, 0, 'N'},
+ { "units-exponent", required_argument, 0, 'X'},
+ { "units-length", required_argument, 0, 'L'},
+ { "units", required_argument, 0, LONGOPT_UNITS_SI},
+ { "step", required_argument, 0, 'S'},
+ { "tabwidth", required_argument, 0, 'T'},
+ { "font-render-mode", required_argument, 0, 'R'},
+ { "graph-render-mode", required_argument, 0, 'G'},
+ { "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 */
+ { "pango-markup", no_argument, 0, 'P'},
+ { "daemon", required_argument, 0, 'd'},
+ { 0, 0, 0, 0}
+};
+/* *INDENT-ON* */
+
optind = 0;
opterr = 0; /* initialize getopt */
- parsetime("end-24h", &start_tv);
- parsetime("now", &end_tv);
+ rrd_parsetime("end-24h", &start_tv);
+ rrd_parsetime("now", &end_tv);
while (1) {
int option_index = 0;
int opt;
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:k",
+ "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;
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!");
case 'N':
im->gridfit = 0;
break;
+ case 'P':
+ im->with_markup = 1;
+ break;
case 's':
- if ((parsetime_error = parsetime(optarg, &start_tv))) {
+ if ((parsetime_error = rrd_parsetime(optarg, &start_tv))) {
rrd_set_error("start time: %s", parsetime_error);
return;
}
break;
case 'e':
- if ((parsetime_error = parsetime(optarg, &end_tv))) {
+ if ((parsetime_error = rrd_parsetime(optarg, &end_tv))) {
rrd_set_error("end time: %s", parsetime_error);
return;
}
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';
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(prop) > end) {
- if (prop[end] == ':') {
- strncpy(im->text_prop[propidx].font,
- prop + end + 1, 255);
- im->text_prop[propidx].font[255] = '\0';
+ if ((int) strlen(optarg) > end+2) {
+ if (optarg[end] == ':') {
+ rrd_set_font_desc(im,propidx,optarg + end + 1,0);
} else {
rrd_set_error
- ("expected after font size in '%s'",
- prop);
+ ("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;
}
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);
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
return;
}
- if (proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
- /* error string is set in parsetime.c */
+ if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
+ /* error string is set in rrd_parsetime.c */
return;
}
}
if (!strcmp("PERCENT", func))
gdes->vf.op = VDEF_PERCENT;
+ else if (!strcmp("PERCENTNAN", func))
+ gdes->vf.op = VDEF_PERCENTNAN;
else if (!strcmp("MAXIMUM", func))
gdes->vf.op = VDEF_MAXIMUM;
else if (!strcmp("AVERAGE", func))
};
switch (gdes->vf.op) {
case VDEF_PERCENT:
+ case VDEF_PERCENTNAN:
if (isnan(param)) { /* no parameter given */
rrd_set_error
("Function '%s' needs parameter in VDEF '%s'\n",
dst = &im->gdes[gdi];
src = &im->gdes[dst->vidx];
data = src->data + src->ds;
+
steps = (src->end - src->start) / src->step;
#if 0
printf
case VDEF_PERCENT:{
rrd_value_t *array;
int field;
- if ((array = malloc(steps * sizeof(double))) == NULL) {
+ if ((array = (rrd_value_t*)malloc(steps * sizeof(double))) == NULL) {
rrd_set_error("malloc VDEV_PERCENT");
return -1;
}
#endif
}
break;
+ case VDEF_PERCENTNAN:{
+ rrd_value_t *array;
+ int field;
+ /* count number of "valid" values */
+ int nancount=0;
+ for (step = 0; step < steps; step++) {
+ if (!isnan(data[step * src->ds_cnt])) { nancount++; }
+ }
+ /* and allocate it */
+ if ((array = (rrd_value_t*)malloc(nancount * sizeof(double))) == NULL) {
+ rrd_set_error("malloc VDEV_PERCENT");
+ return -1;
+ }
+ /* and fill it in */
+ field=0;
+ for (step = 0; step < steps; step++) {
+ if (!isnan(data[step * src->ds_cnt])) {
+ array[field] = data[step * src->ds_cnt];
+ field++;
+ }
+ }
+ qsort(array, nancount, sizeof(double), vdef_percent_compar);
+ field = (nancount - 1) * dst->vf.param / 100;
+ dst->vf.val = array[field];
+ dst->vf.when = 0; /* no time component */
+ free(array);
+ }
+ break;
case VDEF_MAXIMUM:
step = 0;
while (step != steps && isnan(data[step * src->ds_cnt]))
void grinfo_push(
image_desc_t *im,
char *key,
- enum info_type type,
- infoval value)
+ rrd_info_type_t type,
+ rrd_infoval_t value)
{
- im->grinfo_current = info_push(im->grinfo_current, key, type, value);
+ im->grinfo_current = rrd_info_push(im->grinfo_current, key, type, value);
if (im->grinfo == NULL) {
im->grinfo = im->grinfo_current;
}