- for(i=0;i<im->gdes_c;i++){
- switch(im->gdes[i].gf){
- case GF_CDEF:
- case GF_VDEF:
- case GF_DEF:
- case GF_PRINT:
- case GF_GPRINT:
- case GF_COMMENT:
- case GF_HRULE:
- case GF_VRULE:
- case GF_XPORT:
- case GF_SHIFT:
- break;
- case GF_TICK:
- for (ii = 0; ii < im->xsize; ii++)
- {
- if (!isnan(im->gdes[i].p_data[ii]) &&
- im->gdes[i].p_data[ii] > 0.0)
- {
- /* generate a tick */
- gfx_new_line(im->canvas, im -> xorigin + ii,
- im -> yorigin - (im -> gdes[i].yrule * im -> ysize),
- im -> xorigin + ii,
- im -> yorigin,
- 1.0,
- im -> gdes[i].col );
- }
- }
- break;
- case GF_LINE:
- case GF_AREA:
- stack_gf = im->gdes[i].gf;
- case GF_STACK:
- /* fix data points at oo and -oo */
- for(ii=0;ii<im->xsize;ii++){
- if (isinf(im->gdes[i].p_data[ii])){
- if (im->gdes[i].p_data[ii] > 0) {
- im->gdes[i].p_data[ii] = im->maxval ;
- } else {
- im->gdes[i].p_data[ii] = im->minval ;
- }
-
- }
- } /* for */
-
- /* *******************************************************
- ___
- | | ___
- ____| | | |
- | |___|
- -------|---------------------------------------
-
- if we know the value of y at time t was a then
- we draw a square from t-1 to t with the value a.
-
- ********************************************************* */
- if (im->gdes[i].col != 0x0){
- /* GF_LINE and friend */
- if(stack_gf == GF_LINE ){
- node = NULL;
- for(ii=1;ii<im->xsize;ii++){
- if (isnan(im->gdes[i].p_data[ii])){
- node = NULL;
- continue;
- }
- if ( node == NULL ) {
- node = gfx_new_line(im->canvas,
- ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
- ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
- im->gdes[i].linewidth,
- im->gdes[i].col);
- } else {
- gfx_add_point(node,ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
- gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
- };
-
- }
- } else {
- for(ii=1;ii<im->xsize;ii++){
- /* keep things simple for now, just draw these bars
- do not try to build a big and complex area */
- float ybase,ytop;
- if ( isnan(im->gdes[i].p_data[ii]) ) {
- continue;
- }
- ytop = ytr(im,im->gdes[i].p_data[ii]);
- if ( im->gdes[i].stack ) {
- ybase = ytr(im,lastgdes->p_data[ii]);
- } else {
- ybase = ytr(im,areazero);
- }
- if ( ybase == ytop ){
- continue;
- }
- node = gfx_new_area(im->canvas,
- ii-1+im->xorigin,ybase,
- ii-1+im->xorigin,ytop,
- ii+im->xorigin,ytop,
- im->gdes[i].col
- );
- gfx_add_point(node,ii+im->xorigin,ybase);
- }
- } /* else GF_LINE */
- } /* if color != 0x0 */
- /* make sure we do not run into trouble when stacking on NaN */
- for(ii=0;ii<im->xsize;ii++){
- if (isnan(im->gdes[i].p_data[ii])) {
- if (lastgdes && (im->gdes[i].stack)) {
- im->gdes[i].p_data[ii] = lastgdes->p_data[ii];
- } else {
- im->gdes[i].p_data[ii] = ytr(im,areazero);
- }
- }
- }
- lastgdes = &(im->gdes[i]);
- break;
-#ifdef WITH_PIECHART
- case GF_PART:
- if(isnan(im->gdes[i].yrule)) /* fetch variable */
- im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
-
- if (finite(im->gdes[i].yrule)) { /* even the fetched var can be NaN */
- pie_part(im,im->gdes[i].col,
- im->pie_x,im->pie_y,im->piesize*0.4,
- M_PI*2.0*PieStart/100.0,
- M_PI*2.0*(PieStart+im->gdes[i].yrule)/100.0);
- PieStart += im->gdes[i].yrule;
- }
- break;
-#endif
-
- } /* switch */
- }
-#ifdef WITH_PIECHART
- if (piechart==2) {
- im->draw_x_grid=0;
- im->draw_y_grid=0;
- }
-#endif
+ im->xOriginLegendY = 0;
+ im->yOriginLegendY = Ytitle + (Ymain / 2);
+
+ im->xorigin = Xvertical + Xylabel;
+ im->yorigin = Ytitle + Ymain;
+
+ im->xOriginLegendY2 = Xvertical + Xylabel + Xmain;
+ if (im->second_axis_scale != 0){
+ im->xOriginLegendY2 += Xylabel;
+ }
+ im->yOriginLegendY2 = Ytitle + (Ymain / 2);
+
+ break;
+
+ case EAST:
+ im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->yOriginTitle = 0;
+
+ im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
+ if (im->second_axis_scale != 0){
+ im->xOriginLegend += Xylabel;
+ }
+ im->yOriginLegend = Ytitle;
+
+ im->xOriginLegendY = 0;
+ im->yOriginLegendY = Ytitle + (Ymain / 2);
+
+ im->xorigin = Xvertical + Xylabel;
+ im->yorigin = Ytitle + Ymain;
+
+ im->xOriginLegendY2 = Xvertical + Xylabel + Xmain;
+ if (im->second_axis_scale != 0){
+ im->xOriginLegendY2 += Xylabel;
+ }
+ im->yOriginLegendY2 = Ytitle + (Ymain / 2);
+
+ if (!(im->extra_flags & NO_RRDTOOL_TAG)){
+ im->xOriginTitle += Xspacing;
+ im->xOriginLegend += Xspacing;
+ im->xOriginLegendY += Xspacing;
+ im->xorigin += Xspacing;
+ im->xOriginLegendY2 += Xspacing;
+ }
+ break;
+ }
+
+ xtr(im, 0);
+ ytr(im, DNAN);
+ return 0;
+}
+
+static cairo_status_t cairo_output(
+ void *closure,
+ const unsigned char
+ *data,
+ unsigned int length)
+{
+ image_desc_t *im = (image_desc_t*)closure;
+
+ im->rendered_image =
+ (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);
+ im->rendered_image_size += length;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* draw that picture thing ... */
+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;
+
+// PangoFontMap *font_map = pango_cairo_font_map_get_default();
+
+ /* pull the data from the rrd files ... */
+ if (data_fetch(im) == -1)
+ return -1;
+ /* evaluate VDEF and CDEF operations ... */
+ if (data_calc(im) == -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 (i==0) we stop here ...
+ * if we are lazy, try to quit ...
+ */
+ i = print_calc(im);
+ if (i < 0)
+ return -1;
+
+ /* if we want and can be lazy ... quit now */
+ if (i == 0)
+ return 0;
+
+/**************************************************************
+ *** Calculating sizes and locations became a bit confusing ***
+ *** so I moved this into a separate function. ***
+ **************************************************************/
+ if (graph_size_location(im, i) == -1)
+ return -1;
+
+ info.u_cnt = im->xorigin;
+ grinfo_push(im, sprintf_alloc("graph_left"), RD_I_CNT, info);
+ info.u_cnt = im->yorigin - im->ysize;
+ grinfo_push(im, sprintf_alloc("graph_top"), RD_I_CNT, info);
+ info.u_cnt = im->xsize;
+ grinfo_push(im, sprintf_alloc("graph_width"), RD_I_CNT, info);
+ info.u_cnt = im->ysize;
+ grinfo_push(im, sprintf_alloc("graph_height"), RD_I_CNT, info);
+ 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);
+ info.u_cnt = im->start;
+ grinfo_push(im, sprintf_alloc("graph_start"), RD_I_CNT, info);
+ info.u_cnt = im->end;
+ grinfo_push(im, sprintf_alloc("graph_end"), RD_I_CNT, info);
+
+ /* if we want and can be lazy ... quit now */
+ if (lazy)
+ return 0;
+
+ /* get actual drawing data and find min and max values */
+ if (data_proc(im) == -1)
+ return -1;
+ if (!im->logarithmic) {
+ si_unit(im);
+ }
+
+ /* identify si magnitude Kilo, Mega Giga ? */
+ if (!im->rigid && !im->logarithmic)
+ expand_range(im); /* make sure the upper and lower limit are
+ sensible values */
+
+ info.u_val = im->minval;
+ grinfo_push(im, sprintf_alloc("value_min"), RD_I_VAL, info);
+ info.u_val = im->maxval;
+ grinfo_push(im, sprintf_alloc("value_max"), RD_I_VAL, info);
+
+
+ if (!calc_horizontal_grid(im))
+ return -1;
+ /* reset precalc */
+ 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);
+ if (im->minval > 0.0)
+ areazero = im->minval;
+ if (im->maxval < 0.0)
+ areazero = im->maxval;
+ for (i = 0; i < im->gdes_c; i++) {
+ switch (im->gdes[i].gf) {
+ case GF_CDEF:
+ case GF_VDEF:
+ case GF_DEF:
+ case GF_PRINT:
+ case GF_GPRINT:
+ case GF_COMMENT:
+ case GF_TEXTALIGN:
+ case GF_HRULE:
+ case GF_VRULE:
+ case GF_XPORT:
+ case GF_SHIFT:
+ break;
+ case GF_TICK:
+ for (ii = 0; ii < im->xsize; ii++) {
+ if (!isnan(im->gdes[i].p_data[ii])
+ && im->gdes[i].p_data[ii] != 0.0) {
+ if (im->gdes[i].yrule > 0) {
+ gfx_line(im,
+ im->xorigin + ii,
+ im->yorigin + 1.0,
+ im->xorigin + ii,
+ im->yorigin -
+ im->gdes[i].yrule *
+ im->ysize, 1.0, im->gdes[i].col);
+ } else if (im->gdes[i].yrule < 0) {
+ gfx_line(im,
+ im->xorigin + ii,
+ im->yorigin - im->ysize - 1.0,
+ im->xorigin + ii,
+ im->yorigin - im->ysize -
+ im->gdes[i].
+ yrule *
+ im->ysize, 1.0, im->gdes[i].col);
+ }
+ }
+ }
+ break;
+ case GF_LINE:
+ case GF_AREA:
+ /* fix data points at oo and -oo */
+ for (ii = 0; ii < im->xsize; ii++) {
+ if (isinf(im->gdes[i].p_data[ii])) {
+ if (im->gdes[i].p_data[ii] > 0) {
+ im->gdes[i].p_data[ii] = im->maxval;
+ } else {
+ im->gdes[i].p_data[ii] = im->minval;
+ }
+
+ }
+ } /* for */
+
+ /* *******************************************************
+ a ___. (a,t)
+ | | ___
+ ____| | | |
+ | |___|
+ -------|--t-1--t--------------------------------
+
+ if we know the value at time t was a then
+ we draw a square from t-1 to t with the value a.
+
+ ********************************************************* */
+ if (im->gdes[i].col.alpha != 0.0) {
+ /* GF_LINE and friend */
+ if (im->gdes[i].gf == GF_LINE) {
+ double last_y = 0.0;
+ int draw_on = 0;
+
+ cairo_save(im->cr);
+ cairo_new_path(im->cr);
+ cairo_set_line_width(im->cr, im->gdes[i].linewidth);
+ if (im->gdes[i].dash) {
+ cairo_set_dash(im->cr,
+ im->gdes[i].p_dashes,
+ im->gdes[i].ndash, im->gdes[i].offset);
+ }