diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index d166f073cbf55408f2cd99b742c9ace7c4d4d16b..8935d4ee4277adadb936484e813f75fc3f44639e 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
{5.5, RRD_DEFAULT_FONT,NULL} /* watermark */
};
+char week_fmt[128] = "Week %V";
+
xlab_t xlab[] = {
{0, 0, TMT_SECOND, 30, TMT_MINUTE, 5, TMT_MINUTE, 5, 0, "%H:%M"}
,
,
{2400, 0, TMT_HOUR, 12, TMT_DAY, 1, TMT_DAY, 2, 24 * 3600, "%a"}
,
- {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, "Week %V"}
+ {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, week_fmt}
,
- {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600,
- "Week %V"}
+ {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600, week_fmt}
,
{6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
"%b"}
conv_if(SVG, IF_SVG);
conv_if(EPS, IF_EPS);
conv_if(PDF, IF_PDF);
+ conv_if(XML, IF_XML);
+ conv_if(XMLENUM, IF_XMLENUM);
+ conv_if(CSV, IF_CSV);
+ conv_if(TSV, IF_TSV);
+ conv_if(SSV, IF_SSV);
+ conv_if(JSON, IF_JSON);
+ conv_if(JSONTIME, IF_JSONTIME);
return (enum gfx_if_en)(-1);
}
+enum gfx_type_en type_conv(
+ char *string)
+{
+ conv_if(TIME , GTYPE_TIME);
+ conv_if(XY, GTYPE_XY);
+ return (enum gfx_type_en)(-1);
+}
+
enum tmt_en tmt_conv(
char *string)
{
}
}
+/* power prefixes */
static char si_symbol[] = {
+ 'y', /* 10e-24 Yocto */
+ 'z', /* 10e-21 Zepto */
'a', /* 10e-18 Atto */
'f', /* 10e-15 Femto */
'p', /* 10e-12 Pico */
'T', /* 10e12 Tera */
'P', /* 10e15 Peta */
'E', /* 10e18 Exa */
+ 'Z', /* 10e21 Zeta */
+ 'Y' /* 10e24 Yotta */
};
-static const int si_symbcenter = 6;
+static const int si_symbcenter = 8;
/* find SI magnitude symbol for the numbers on the y-axis*/
void si_unit(
&im->gdes[i].ds_cnt,
&im->gdes[i].ds_namv,
&im->gdes[i].data)) == -1) {
- return -1;
- }
+ return -1;
+ }
}
im->gdes[i].data_first = 1;
+ /* must reduce to at least im->step
+ otherwhise we end up with more data than we can handle in the
+ chart and visibility of data will be random */
+ im->gdes[i].step = max(im->gdes[i].step,im->step);
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
ft_step,
struct tm tm;
localtime_r(&start, &tm);
+ /* let mktime figure this dst on its own */
+ tm.tm_isdst = -1;
switch (baseint) {
case TMT_SECOND:
time_t madetime;
localtime_r(¤t, &tm);
+ /* let mktime figure this dst on its own */
+ tm.tm_isdst = -1;
int limit = 2;
switch (baseint) {
("STACK should already be turned into LINE or AREA here");
return -1;
break;
+ case GF_XAXIS:
+ case GF_YAXIS:
+ break;
}
}
return graphelement;
prt_fctn != 'j' &&
prt_fctn != 'c' &&
prt_fctn != 'u' &&
+ prt_fctn != '.' &&
prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
free(legspace);
rrd_set_error
if (prt_fctn == 'n') {
prt_fctn = 'l';
}
+ /* \. is a null operation to allow strings ending in \x */
+ if (prt_fctn == '.') {
+ prt_fctn = '\0';
+ }
/* remove exess space from the end of the legend for \g */
while (prt_fctn == 'g' &&
glue = 0;
}
if (prt_fctn == 'c')
- leg_x = (double)(legendwidth - fill) / 2.0;
+ leg_x = border + (double)(legendwidth - fill) / 2.0;
if (prt_fctn == 'r')
leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
im->ximg = im->xsize;
im->yimg = im->ysize;
im->yorigin = im->ysize;
+ xtr(im, 0);
ytr(im, DNAN);
return 0;
}
if (im->second_axis_legend[0] != '\0') {
Xvertical2 = im->text_prop[TEXT_PROP_UNIT].size * 2;
}
+ else{
+ Xvertical2 = Xspacing;
+ }
if (im->title[0] != '\0') {
/* The title is placed "inbetween" two text lines so it
}
else{
// we have no title; get a little clearing from the top
- Ytitle = 1.5 * Yspacing;
+ Ytitle = Yspacing;
}
if (elements) {
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- Ymain -= Yspacing;
+ Ymain -= 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
}
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- im->yimg += Yspacing;
+ im->yimg += 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
*/
switch(im->legendposition){
case NORTH:
- im->xOriginTitle = Xvertical + Xylabel + (im->xsize / 2);
+ im->xOriginTitle = (im->ximg / 2);
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case WEST:
- im->xOriginTitle = im->legendwidth + Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->legendwidth + im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case SOUTH:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->ximg / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case EAST:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
int graph_paint(
image_desc_t *im)
{
- int i, ii;
int lazy = lazy_check(im);
- double areazero = 0.0;
- graph_desc_t *lastgdes = NULL;
- rrd_infoval_t info;
+ int cnt;
-// PangoFontMap *font_map = pango_cairo_font_map_get_default();
+ /* imgformat XML or higher dispatch to xport
+ * output format there is selected via graph_type
+ */
+ if (im->imgformat >= IF_XML) {
+ return rrd_graph_xport(im);
+ }
/* pull the data from the rrd files ... */
if (data_fetch(im) == -1)
* 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)
+ cnt = print_calc(im);
+ if (cnt < 0)
return -1;
/* if we want and can be lazy ... quit now */
- if (i == 0)
+ if (cnt == 0)
return 0;
+ /* otherwise call graph_paint_timestring */
+ switch (im->graph_type) {
+ case GTYPE_TIME:
+ return graph_paint_timestring(im,lazy,cnt);
+ break;
+ case GTYPE_XY:
+ return graph_paint_xy(im,lazy,cnt);
+ break;
+ }
+ /* final return with error*/
+ rrd_set_error("Graph type %i is not implemented",im->graph_type);
+ return -1;
+}
+
+int graph_paint_timestring(
+ image_desc_t *im, int lazy, int cnt)
+{
+ int i,ii;
+ double areazero = 0.0;
+ graph_desc_t *lastgdes = NULL;
+ rrd_infoval_t info;
+
/**************************************************************
*** Calculating sizes and locations became a bit confusing ***
*** so I moved this into a separate function. ***
**************************************************************/
- if (graph_size_location(im, i) == -1)
+ if (graph_size_location(im, cnt) == -1)
return -1;
info.u_cnt = im->xorigin;
ytr(im, DNAN);
/* if (im->gridfit)
apply_gridfit(im); */
- /* the actual graph is created by going through the individual
- graph elements and then drawing them */
- cairo_surface_destroy(im->surface);
- switch (im->imgformat) {
- case IF_PNG:
- im->surface =
- cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- im->ximg * im->zoom,
- im->yimg * im->zoom);
- break;
- case IF_PDF:
- im->gridfit = 0;
- im->surface = strlen(im->graphfile)
- ? 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(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(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);
- 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);
- gfx_close_path(im);
- gfx_new_area(im, im->xorigin,
- im->yorigin,
- im->xorigin +
- im->xsize, im->yorigin,
- im->xorigin +
- im->xsize,
- 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);
+
+ /* set up cairo */
+ if (graph_cairo_setup(im)) { return -1; }
+
+ /* other stuff */
if (im->minval > 0.0)
areazero = im->minval;
if (im->maxval < 0.0)
case GF_VRULE:
case GF_XPORT:
case GF_SHIFT:
+ case GF_XAXIS:
+ case GF_YAXIS:
break;
case GF_TICK:
for (ii = 0; ii < im->xsize; ii++) {
break;
}
}
+ /* close the graph via cairo*/
+ return graph_cairo_finish(im);
+}
+int graph_cairo_setup (image_desc_t *im)
+{
+ /* the actual graph is created by going through the individual
+ graph elements and then drawing them */
+ cairo_surface_destroy(im->surface);
+ switch (im->imgformat) {
+ case IF_PNG:
+ im->surface =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ im->ximg * im->zoom,
+ im->yimg * im->zoom);
+ break;
+ case IF_PDF:
+ im->gridfit = 0;
+ im->surface = strlen(im->graphfile)
+ ? 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(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(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;
+ case IF_XML:
+ case IF_XMLENUM:
+ case IF_CSV:
+ case IF_TSV:
+ case IF_SSV:
+ case IF_JSON:
+ case IF_JSONTIME:
+ 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);
+ 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);
+ gfx_close_path(im);
+ gfx_new_area(im, im->xorigin,
+ im->yorigin,
+ im->xorigin +
+ im->xsize, im->yorigin,
+ im->xorigin +
+ im->xsize,
+ 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);
+ return 0;
+}
+
+int graph_cairo_finish (image_desc_t *im)
+{
switch (im->imgformat) {
case IF_PNG:
}
break;
}
+ case IF_XML:
+ case IF_XMLENUM:
+ case IF_CSV:
+ case IF_TSV:
+ case IF_SSV:
+ case IF_JSON:
+ case IF_JSONTIME:
+ break;
default:
if (strlen(im->graphfile)) {
cairo_show_page(im->cr);
return 0;
}
+int graph_paint_xy(
+ image_desc_t *im, int lazy, int cnt)
+{
+ /* to stop compiler warnings for now */
+ lazy=cnt=(int)im->gdes_c;
+ rrd_set_error("XY diagramm not implemented");
+ return -1;
+}
/*****************************************************
* graph stuff
return -1;
}
+ /* set to zero */
+ memset(&(im->gdes[im->gdes_c - 1]),0,sizeof(graph_desc_t));
im->gdes[im->gdes_c - 1].step = im->step;
im->gdes[im->gdes_c - 1].step_orig = im->step;
** - options parsing now in rrd_graph_options()
** - script parsing now in rrd_graph_script()
*/
+
rrd_info_t *rrd_graph_v(
int argc,
char **argv)
im_free(&im);
return NULL;
}
-
+
/* Everything is now read and the actual work can start */
-
if (graph_paint(&im) == -1) {
- rrd_info_free(im.grinfo);
- im_free(&im);
- return NULL;
+ rrd_info_free(im.grinfo);
+ im_free(&im);
+ return NULL;
}
-
/* The image is generated and needs to be output.
** Also, if needed, print a line with information about the image.
*/
static PangoFontMap *fontmap = NULL;
PangoContext *context;
+ /* zero the whole structure first */
+ memset(im,0,sizeof(image_desc_t));
+
#ifdef HAVE_TZSET
tzset();
#endif
-
+ im->graph_type = GTYPE_TIME;
im->base = 1000;
im->daemon_addr = NULL;
im->draw_x_grid = 1;
im->maxval = DNAN;
im->minval = 0;
im->minval = DNAN;
+ im->magfact = 1;
im->prt_c = 0;
im->rigid = 0;
im->rendered_image_size = 0;
{ "border", required_argument, 0, 1007},
{ "grid-dash", required_argument, 0, 1008},
{ "dynamic-labels", no_argument, 0, 1009},
+ { "week-fmt", required_argument, 0, 1010},
+ { "graph-type", required_argument, 0, 1011},
{ 0, 0, 0, 0}
};
/* *INDENT-ON* */
case 1009: /* enable dynamic labels */
im->dynamic_labels = 1;
break;
+ case 1010:
+ strncpy(week_fmt,optarg,sizeof week_fmt);
+ week_fmt[(sizeof week_fmt)-1]='\0';
+ break;
case 1002: /* right y axis */
if(sscanf(optarg,
return;
}
break;
+ case 1011:
+ if ((int)
+ (im->graph_type = type_conv(optarg)) == -1) {
+ rrd_set_error("unsupported graphics type '%s'", optarg);
+ return;
+ }
+ break;
case 'z':
im->lazy = 1;
break;