- 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 */
-
- /* *******************************************************
- 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 != 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]) || (im->slopemode==1 && isnan(im->gdes[i].p_data[ii-1]))){
- node = NULL;
- continue;
- }
- if ( node == NULL ) {
- if ( im->slopemode == 0 ){
- 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 {
- node = gfx_new_line(im->canvas,
- ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]),
- ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
- im->gdes[i].linewidth,
- im->gdes[i].col);
- }
- } else {
- if ( im->slopemode==0 ){
- 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 {
- int idxI=-1;
- double *foreY=malloc(sizeof(double)*im->xsize*2);
- double *foreX=malloc(sizeof(double)*im->xsize*2);
- double *backY=malloc(sizeof(double)*im->xsize*2);
- double *backX=malloc(sizeof(double)*im->xsize*2);
- int drawem = 0;
- for(ii=0;ii<=im->xsize;ii++){
- double ybase,ytop;
- if ( idxI > 0 && ( drawem != 0 || ii==im->xsize)){
- int cntI=1;
- int lastI=0;
- while (cntI < idxI && foreY[lastI] == foreY[cntI] && foreY[lastI] == foreY[cntI+1]){cntI++;}
- node = gfx_new_area(im->canvas,
- backX[0],backY[0],
- foreX[0],foreY[0],
- foreX[cntI],foreY[cntI], im->gdes[i].col);
- while (cntI < idxI) {
- lastI = cntI;
- cntI++;
- while ( cntI < idxI && foreY[lastI] == foreY[cntI] && foreY[lastI] == foreY[cntI+1]){cntI++;}
- gfx_add_point(node,foreX[cntI],foreY[cntI]);
+ 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 = 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:
+ case GF_GRAD: {
+ rrd_value_t diffval = im->maxval - im->minval;
+ rrd_value_t maxlimit = im->maxval + 9 * diffval;
+ rrd_value_t minlimit = im->minval - 9 * diffval;
+ for (ii = 0; ii < im->xsize; ii++) {
+ /* fix data points at oo and -oo */
+ 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;
+ }
+ }
+ /* some versions of cairo go unstable when trying
+ to draw way out of the canvas ... lets not even try */
+ if (im->gdes[i].p_data[ii] > maxlimit) {
+ im->gdes[i].p_data[ii] = maxlimit;