X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_graph.c;h=6648d9ccd9fdcd7aaa6fb94e638de13a1fad2584;hp=191404e2d0eab670b5f3fc093feb9c3890df38db;hb=04ed1c285ff739ad2cd1384e6cfe24aea82cfa7e;hpb=dd86fdf1b4d99437b9aa19934e02230c090cc1d5 diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 191404e..6648d9c 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -140,16 +140,17 @@ ylab_t ylab[] = { gfx_color_t graph_col[] = /* default colors */ -{ 0xFFFFFFFF, /* canvas */ - 0xF0F0F0FF, /* background */ - 0xD0D0D0FF, /* shade A */ - 0xA0A0A0FF, /* shade B */ - 0x90909080, /* grid */ - 0xE0505080, /* major grid */ - 0x000000FF, /* font */ - 0x802020FF, /* arrow */ - 0x202020FF, /* axis */ - 0x000000FF /* frame */ +{ + {1.00, 1.00, 1.00, 1.00}, /* canvas */ + {0.95, 0.95, 0.95, 1.00}, /* background */ + {0.81, 0.81, 0.81, 1.00}, /* shade A */ + {0.62, 0.62, 0.62, 1.00}, /* shade B */ + {0.56, 0.56, 0.56, 0.75}, /* grid */ + {0.87, 0.31, 0.31, 0.60}, /* major grid */ + {0.00, 0.00, 0.00, 1.00}, /* font */ + {0.50, 0.12, 0.12, 1.00}, /* arrow */ + {0.12, 0.12, 0.12, 1.00}, /* axis */ + {0.00, 0.00, 0.00, 1.00} /* frame */ }; @@ -225,81 +226,78 @@ enum gf_en gf_conv( char *string) { - conv_if(PRINT, GF_PRINT) - conv_if(GPRINT, GF_GPRINT) - conv_if(COMMENT, GF_COMMENT) - conv_if(HRULE, GF_HRULE) - conv_if(VRULE, GF_VRULE) - conv_if(LINE, GF_LINE) - conv_if(AREA, GF_AREA) - conv_if(STACK, GF_STACK) - conv_if(TICK, GF_TICK) - conv_if(DEF, GF_DEF) - conv_if(CDEF, GF_CDEF) - conv_if(VDEF, GF_VDEF) -#ifdef WITH_PIECHART - conv_if(PART, GF_PART) -#endif - conv_if(XPORT, GF_XPORT) - conv_if(SHIFT, GF_SHIFT) - - return (-1); + conv_if(PRINT, GF_PRINT); + conv_if(GPRINT, GF_GPRINT); + conv_if(COMMENT, GF_COMMENT); + conv_if(HRULE, GF_HRULE); + conv_if(VRULE, GF_VRULE); + conv_if(LINE, GF_LINE); + conv_if(AREA, GF_AREA); + conv_if(STACK, GF_STACK); + conv_if(TICK, GF_TICK); + conv_if(DEF, GF_DEF); + conv_if(CDEF, GF_CDEF); + conv_if(VDEF, GF_VDEF); + conv_if(XPORT, GF_XPORT); + conv_if(SHIFT, GF_SHIFT); + + return (-1); } enum gfx_if_en if_conv( char *string) { - conv_if(PNG, IF_PNG) - conv_if(SVG, IF_SVG) - conv_if(EPS, IF_EPS) - conv_if(PDF, IF_PDF) + conv_if(PNG, IF_PNG); + conv_if(SVG, IF_SVG); + conv_if(EPS, IF_EPS); + conv_if(PDF, IF_PDF); - return (-1); + return (-1); } enum tmt_en tmt_conv( char *string) { - conv_if(SECOND, TMT_SECOND) - conv_if(MINUTE, TMT_MINUTE) - conv_if(HOUR, TMT_HOUR) - conv_if(DAY, TMT_DAY) - conv_if(WEEK, TMT_WEEK) - conv_if(MONTH, TMT_MONTH) - conv_if(YEAR, TMT_YEAR) - return (-1); + conv_if(SECOND, TMT_SECOND); + conv_if(MINUTE, TMT_MINUTE); + conv_if(HOUR, TMT_HOUR); + conv_if(DAY, TMT_DAY); + conv_if(WEEK, TMT_WEEK); + conv_if(MONTH, TMT_MONTH); + conv_if(YEAR, TMT_YEAR); + return (-1); } enum grc_en grc_conv( char *string) { - conv_if(BACK, GRC_BACK) - conv_if(CANVAS, GRC_CANVAS) - conv_if(SHADEA, GRC_SHADEA) - conv_if(SHADEB, GRC_SHADEB) - conv_if(GRID, GRC_GRID) - conv_if(MGRID, GRC_MGRID) - conv_if(FONT, GRC_FONT) - conv_if(ARROW, GRC_ARROW) - conv_if(AXIS, GRC_AXIS) - conv_if(FRAME, GRC_FRAME) + conv_if(BACK, GRC_BACK); + conv_if(CANVAS, GRC_CANVAS); + conv_if(SHADEA, GRC_SHADEA); + conv_if(SHADEB, GRC_SHADEB); + conv_if(GRID, GRC_GRID); + conv_if(MGRID, GRC_MGRID); + conv_if(FONT, GRC_FONT); + conv_if(ARROW, GRC_ARROW); + conv_if(AXIS, GRC_AXIS); + conv_if(FRAME, GRC_FRAME); - return -1; + return -1; } enum text_prop_en text_prop_conv( char *string) { - conv_if(DEFAULT, TEXT_PROP_DEFAULT) - conv_if(TITLE, TEXT_PROP_TITLE) - conv_if(AXIS, TEXT_PROP_AXIS) - conv_if(UNIT, TEXT_PROP_UNIT) - conv_if(LEGEND, TEXT_PROP_LEGEND) - return -1; + conv_if(DEFAULT, TEXT_PROP_DEFAULT); + conv_if(TITLE, TEXT_PROP_TITLE); + conv_if(AXIS, TEXT_PROP_AXIS); + conv_if(UNIT, TEXT_PROP_UNIT); + conv_if(LEGEND, TEXT_PROP_LEGEND); + return -1; } @@ -326,7 +324,10 @@ int im_free( free(im->gdes[i].rpnp); } free(im->gdes); - gfx_destroy(im->canvas); + if (im->surface) + cairo_surface_destroy(im->surface); + if (im->font_options) + cairo_font_options_destroy(im->font_options); return 0; } @@ -520,6 +521,7 @@ void expand_range( #endif } + void apply_gridfit( image_desc_t *im) { @@ -1638,12 +1640,12 @@ int leg_place( /* no interleg space if string ends in \g */ fill += legspace[i]; } - fill += gfx_get_text_width(im->canvas, fill + border, + fill += gfx_get_text_width(im, fill + border, im->text_prop[TEXT_PROP_LEGEND]. font, im->text_prop[TEXT_PROP_LEGEND]. size, im->tabwidth, - im->gdes[i].legend, 0); + im->gdes[i].legend); leg_c++; } else { legspace[i] = 0; @@ -1690,12 +1692,12 @@ int leg_place( im->gdes[ii].leg_x = leg_x; im->gdes[ii].leg_y = leg_y; leg_x += - gfx_get_text_width(im->canvas, leg_x, + gfx_get_text_width(im, leg_x, im->text_prop[TEXT_PROP_LEGEND]. font, im->text_prop[TEXT_PROP_LEGEND]. size, im->tabwidth, - im->gdes[ii].legend, 0) + im->gdes[ii].legend) + legspace[ii] + glue; } @@ -1900,25 +1902,37 @@ int draw_horizontal_grid( } nlabels++; - gfx_new_text(im->canvas, - X0 - im->text_prop[TEXT_PROP_AXIS].size, Y0, - im->graph_col[GRC_FONT], - im->text_prop[TEXT_PROP_AXIS].font, - im->text_prop[TEXT_PROP_AXIS].size, - im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER, - graph_label); - gfx_new_dashed_line(im->canvas, - X0 - 2, Y0, - X1 + 2, Y0, - MGRIDWIDTH, im->graph_col[GRC_MGRID], - im->grid_dash_on, im->grid_dash_off); + gfx_text(im, + X0 - im->text_prop[TEXT_PROP_AXIS].size, Y0, + im->graph_col[GRC_FONT], + im->text_prop[TEXT_PROP_AXIS].font, + im->text_prop[TEXT_PROP_AXIS].size, + 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]); + gfx_line(im, + X1, Y0, + X1 + 2, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); + gfx_dashed_line(im, + X0 - 2, Y0, + X1 + 2, Y0, + MGRIDWIDTH, im->graph_col[GRC_MGRID], + im->grid_dash_on, im->grid_dash_off); } else if (!(im->extra_flags & NOMINOR)) { - gfx_new_dashed_line(im->canvas, - X0 - 1, Y0, - X1 + 1, Y0, - GRIDWIDTH, im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, + X0 - 2, Y0, + X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_line(im, + X1, Y0, + X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_dashed_line(im, + X0 - 1, Y0, + X1 + 1, Y0, + GRIDWIDTH, im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } @@ -2056,11 +2070,18 @@ int horizontal_log_grid( break; /* major grid line */ - gfx_new_dashed_line(im->canvas, - X0 - 2, Y0, - X1 + 2, Y0, - MGRIDWIDTH, im->graph_col[GRC_MGRID], - im->grid_dash_on, im->grid_dash_off); + + gfx_line(im, + X0 - 2, Y0, X0, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); + gfx_line(im, + X1, Y0, X1 + 2, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); + + + gfx_dashed_line(im, + X0 - 2, Y0, + X1 + 2, Y0, + MGRIDWIDTH, im->graph_col[GRC_MGRID], + im->grid_dash_on, im->grid_dash_off); /* label */ if (im->extra_flags & FORCE_UNITS_SI) { @@ -2084,13 +2105,12 @@ int horizontal_log_grid( sprintf(graph_label, "%3.0f %c", pvalue, symbol); } else sprintf(graph_label, "%3.0e", value); - gfx_new_text(im->canvas, - X0 - im->text_prop[TEXT_PROP_AXIS].size, Y0, - im->graph_col[GRC_FONT], - im->text_prop[TEXT_PROP_AXIS].font, - im->text_prop[TEXT_PROP_AXIS].size, - im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER, - graph_label); + gfx_text(im, + X0 - im->text_prop[TEXT_PROP_AXIS].size, Y0, + im->graph_col[GRC_FONT], + im->text_prop[TEXT_PROP_AXIS].font, + im->text_prop[TEXT_PROP_AXIS].size, + im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER, graph_label); /* minor grid */ if (mid < 4 && exfrac == 1) { @@ -2119,11 +2139,17 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_new_dashed_line(im->canvas, - X0 - 1, Y0, - X1 + 1, Y0, - GRIDWIDTH, im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, + X0 - 2, Y0, + X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_line(im, + X1, Y0, + X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_dashed_line(im, + X0 - 1, Y0, + X1 + 1, Y0, + GRIDWIDTH, im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } else if (exfrac > 1) { for (i = val_exp - exfrac / 3 * 2; i < val_exp; i += exfrac / 3) { @@ -2136,11 +2162,17 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_new_dashed_line(im->canvas, - X0 - 1, Y0, - X1 + 1, Y0, - GRIDWIDTH, im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, + X0 - 2, Y0, + X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_line(im, + X1, Y0, + X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_dashed_line(im, + X0 - 1, Y0, + X1 + 1, Y0, + GRIDWIDTH, im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } @@ -2178,11 +2210,15 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_new_dashed_line(im->canvas, - X0 - 1, Y0, - X1 + 1, Y0, - GRIDWIDTH, im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, + X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_line(im, + X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_dashed_line(im, + X0 - 1, Y0, + X1 + 1, Y0, + GRIDWIDTH, im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } /* fancy minor gridlines */ @@ -2197,11 +2233,15 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_new_dashed_line(im->canvas, - X0 - 1, Y0, - X1 + 1, Y0, - GRIDWIDTH, im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, + X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_line(im, + X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); + gfx_dashed_line(im, + X0 - 1, Y0, + X1 + 1, Y0, + GRIDWIDTH, im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } @@ -2272,9 +2312,13 @@ void vertical_grid( if (ti == timajor) continue; /* skip as falls on major grid line */ X0 = xtr(im, ti); - gfx_new_dashed_line(im->canvas, X0, Y0 + 1, X0, Y1 - 1, GRIDWIDTH, - im->graph_col[GRC_GRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, X0, Y1 - 2, X0, Y1, GRIDWIDTH, + im->graph_col[GRC_GRID]); + gfx_line(im, X0, Y0, X0, Y0 + 2, GRIDWIDTH, + im->graph_col[GRC_GRID]); + gfx_dashed_line(im, X0, Y0 + 1, X0, Y1 - 1, GRIDWIDTH, + im->graph_col[GRC_GRID], + im->grid_dash_on, im->grid_dash_off); } } @@ -2290,9 +2334,13 @@ void vertical_grid( if (ti < im->start || ti > im->end) continue; X0 = xtr(im, ti); - gfx_new_dashed_line(im->canvas, X0, Y0 + 3, X0, Y1 - 2, MGRIDWIDTH, - im->graph_col[GRC_MGRID], - im->grid_dash_on, im->grid_dash_off); + gfx_line(im, X0, Y1 - 2, X0, Y1, MGRIDWIDTH, + im->graph_col[GRC_MGRID]); + gfx_line(im, X0, Y0, X0, Y0 + 3, MGRIDWIDTH, + im->graph_col[GRC_MGRID]); + gfx_dashed_line(im, X0, Y0 + 3, X0, Y1 - 2, MGRIDWIDTH, + im->graph_col[GRC_MGRID], + im->grid_dash_on, im->grid_dash_off); } /* paint the labels below the graph */ @@ -2313,13 +2361,13 @@ void vertical_grid( #else # error "your libc has no strftime I guess we'll abort the exercise here." #endif - gfx_new_text(im->canvas, - xtr(im, tilab), - Y0 + im->text_prop[TEXT_PROP_AXIS].size * 1.4 + 5, - im->graph_col[GRC_FONT], - im->text_prop[TEXT_PROP_AXIS].font, - im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 0.0, - GFX_H_CENTER, GFX_V_BOTTOM, graph_label); + gfx_text(im, + xtr(im, tilab), + Y0 + 3, + im->graph_col[GRC_FONT], + im->text_prop[TEXT_PROP_AXIS].font, + im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 0.0, + GFX_H_CENTER, GFX_V_TOP, graph_label); } @@ -2330,29 +2378,32 @@ void axis_paint( image_desc_t *im) { /* draw x and y axis */ - /* gfx_new_line ( im->canvas, im->xorigin+im->xsize,im->yorigin, + /* gfx_line ( im->canvas, im->xorigin+im->xsize,im->yorigin, im->xorigin+im->xsize,im->yorigin-im->ysize, GRIDWIDTH, im->graph_col[GRC_AXIS]); - gfx_new_line ( im->canvas, im->xorigin,im->yorigin-im->ysize, + gfx_line ( im->canvas, im->xorigin,im->yorigin-im->ysize, im->xorigin+im->xsize,im->yorigin-im->ysize, GRIDWIDTH, im->graph_col[GRC_AXIS]); */ - gfx_new_line(im->canvas, im->xorigin - 4, im->yorigin, - im->xorigin + im->xsize + 4, im->yorigin, - MGRIDWIDTH, im->graph_col[GRC_AXIS]); + gfx_line(im, im->xorigin - 4, im->yorigin, + im->xorigin + im->xsize + 4, im->yorigin, + MGRIDWIDTH, im->graph_col[GRC_AXIS]); - gfx_new_line(im->canvas, im->xorigin, im->yorigin + 4, - im->xorigin, im->yorigin - im->ysize - 4, - MGRIDWIDTH, im->graph_col[GRC_AXIS]); + gfx_line(im, im->xorigin, im->yorigin + 4, + im->xorigin, im->yorigin - im->ysize - 4, + MGRIDWIDTH, im->graph_col[GRC_AXIS]); /* arrow for X and Y axis direction */ - gfx_new_area(im->canvas, im->xorigin + im->xsize + 2, im->yorigin - 2, im->xorigin + im->xsize + 2, im->yorigin + 3, im->xorigin + im->xsize + 7, im->yorigin + 0.5, /* LINEOFFSET */ + gfx_new_area(im, im->xorigin + im->xsize + 2, im->yorigin - 2, im->xorigin + im->xsize + 2, im->yorigin + 3, im->xorigin + im->xsize + 7, im->yorigin + 0.5, /* LINEOFFSET */ im->graph_col[GRC_ARROW]); + gfx_close_path(im); - gfx_new_area(im->canvas, im->xorigin - 2, im->yorigin - im->ysize - 2, im->xorigin + 3, im->yorigin - im->ysize - 2, im->xorigin + 0.5, im->yorigin - im->ysize - 7, /* LINEOFFSET */ + gfx_new_area(im, im->xorigin - 2, im->yorigin - im->ysize - 2, im->xorigin + 3, im->yorigin - im->ysize - 2, im->xorigin + 0.5, im->yorigin - im->ysize - 7, /* LINEOFFSET */ im->graph_col[GRC_ARROW]); + gfx_close_path(im); + } @@ -2362,23 +2413,23 @@ void grid_paint( long i; int res = 0; double X0, Y0; /* points for filled graph and more */ - gfx_node_t *node; + struct gfx_color_t water_color; /* draw 3d border */ - node = gfx_new_area(im->canvas, 0, im->yimg, - 2, im->yimg - 2, 2, 2, im->graph_col[GRC_SHADEA]); - gfx_add_point(node, im->ximg - 2, 2); - gfx_add_point(node, im->ximg, 0); - gfx_add_point(node, 0, 0); -/* gfx_add_point( node , 0,im->yimg ); */ - - node = gfx_new_area(im->canvas, 2, im->yimg - 2, - im->ximg - 2, im->yimg - 2, - im->ximg - 2, 2, im->graph_col[GRC_SHADEB]); - gfx_add_point(node, im->ximg, 0); - gfx_add_point(node, im->ximg, im->yimg); - gfx_add_point(node, 0, im->yimg); -/* gfx_add_point( node , 0,im->yimg ); */ + gfx_new_area(im, 0, im->yimg, + 2, im->yimg - 2, 2, 2, im->graph_col[GRC_SHADEA]); + gfx_add_point(im, im->ximg - 2, 2); + gfx_add_point(im, im->ximg, 0); + gfx_add_point(im, 0, 0); + gfx_close_path(im); + + gfx_new_area(im, 2, im->yimg - 2, + im->ximg - 2, im->yimg - 2, + im->ximg - 2, 2, im->graph_col[GRC_SHADEB]); + gfx_add_point(im, im->ximg, 0); + gfx_add_point(im, im->ximg, im->yimg); + gfx_add_point(im, 0, im->yimg); + gfx_close_path(im); if (im->draw_x_grid == 1) @@ -2395,47 +2446,48 @@ void grid_paint( if (!res) { char *nodata = "No Data found"; - gfx_new_text(im->canvas, im->ximg / 2, - (2 * im->yorigin - im->ysize) / 2, - im->graph_col[GRC_FONT], - im->text_prop[TEXT_PROP_AXIS].font, - im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, - 0.0, GFX_H_CENTER, GFX_V_CENTER, nodata); + gfx_text(im, im->ximg / 2, + (2 * im->yorigin - im->ysize) / 2, + im->graph_col[GRC_FONT], + im->text_prop[TEXT_PROP_AXIS].font, + im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, + 0.0, GFX_H_CENTER, GFX_V_CENTER, nodata); } } /* yaxis unit description */ - gfx_new_text(im->canvas, - 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_LEFT, GFX_V_CENTER, im->ylegend); + 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); /* graph title */ - gfx_new_text(im->canvas, - im->ximg / 2, im->text_prop[TEXT_PROP_TITLE].size * 1.3 + 4, - 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_CENTER, im->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); /* rrdtool 'logo' */ - gfx_new_text(im->canvas, - im->ximg - 7, 7, - (im->graph_col[GRC_FONT] & 0xffffff00) | 0x00000044, - im->text_prop[TEXT_PROP_AXIS].font, - 5.5, im->tabwidth, 270, - GFX_H_RIGHT, GFX_V_TOP, "RRDTOOL / TOBI OETIKER"); + 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"); /* graph watermark */ if (im->watermark[0] != '\0') { - gfx_new_text(im->canvas, - im->ximg / 2, im->yimg - 6, - (im->graph_col[GRC_FONT] & 0xffffff00) | 0x00000044, - im->text_prop[TEXT_PROP_AXIS].font, - 5.5, im->tabwidth, 0, - GFX_H_CENTER, GFX_V_BOTTOM, im->watermark); + gfx_text(im, + im->ximg / 2, im->yimg - 6, + water_color, + im->text_prop[TEXT_PROP_AXIS].font, + 5.5, im->tabwidth, 0, + GFX_H_CENTER, GFX_V_BOTTOM, im->watermark); } /* graph labels */ @@ -2447,42 +2499,62 @@ void grid_paint( /* im->gdes[i].leg_y is the bottom of the legend */ X0 = im->gdes[i].leg_x; Y0 = im->gdes[i].leg_y; - gfx_new_text(im->canvas, X0, Y0, - im->graph_col[GRC_FONT], - im->text_prop[TEXT_PROP_LEGEND].font, - im->text_prop[TEXT_PROP_LEGEND].size, - im->tabwidth, 0.0, GFX_H_LEFT, GFX_V_BOTTOM, - im->gdes[i].legend); + gfx_text(im, X0, Y0, + im->graph_col[GRC_FONT], + im->text_prop[TEXT_PROP_LEGEND].font, + im->text_prop[TEXT_PROP_LEGEND].size, + im->tabwidth, 0.0, GFX_H_LEFT, GFX_V_BOTTOM, + im->gdes[i].legend); /* The legend for GRAPH items starts with "M " to have enough space for the box */ if (im->gdes[i].gf != GF_PRINT && im->gdes[i].gf != GF_GPRINT && im->gdes[i].gf != GF_COMMENT) { - int boxH, boxV; + double boxH, boxV; + double X1, Y1; - boxH = gfx_get_text_width(im->canvas, 0, + + boxH = gfx_get_text_width(im, 0, im->text_prop[TEXT_PROP_LEGEND]. font, im->text_prop[TEXT_PROP_LEGEND]. - size, im->tabwidth, "o", 0) * 1.2; - boxV = boxH * 1.1; + size, im->tabwidth, "o") * 1.2; + boxV = boxH; + + /* shift the box up a bit */ + Y0 -= boxV * 0.4; /* make sure transparent colors show up the same way as in the graph */ - node = gfx_new_area(im->canvas, - X0, Y0 - boxV, - X0, Y0, - X0 + boxH, Y0, im->graph_col[GRC_BACK]); - gfx_add_point(node, X0 + boxH, Y0 - boxV); - - node = gfx_new_area(im->canvas, - X0, Y0 - boxV, - X0, Y0, X0 + boxH, Y0, im->gdes[i].col); - gfx_add_point(node, X0 + boxH, Y0 - boxV); - node = gfx_new_line(im->canvas, - X0, Y0 - boxV, - X0, Y0, 1.0, im->graph_col[GRC_FRAME]); - gfx_add_point(node, X0 + boxH, Y0); - gfx_add_point(node, X0 + boxH, Y0 - boxV); - gfx_close_path(node); + + gfx_new_area(im, + X0, Y0 - boxV, + X0, Y0, X0 + boxH, Y0, im->graph_col[GRC_BACK]); + gfx_add_point(im, X0 + boxH, Y0 - boxV); + gfx_close_path(im); + + gfx_new_area(im, + X0, Y0 - boxV, + X0, Y0, X0 + boxH, Y0, im->gdes[i].col); + gfx_add_point(im, X0 + boxH, Y0 - boxV); + gfx_close_path(im); + + cairo_save(im->cr); + cairo_new_path(im->cr); + cairo_set_line_width(im->cr, 1.0); + X1 = X0 + boxH; + Y1 = Y0 - boxV; + gfx_line_fit(im, &X0, &Y0); + gfx_line_fit(im, &X1, &Y1); + cairo_move_to(im->cr, X0, Y0); + cairo_line_to(im->cr, X1, Y0); + cairo_line_to(im->cr, X1, Y1); + cairo_line_to(im->cr, X0, Y1); + cairo_close_path(im->cr); + cairo_set_source_rgba(im->cr, im->graph_col[GRC_FRAME].red, + im->graph_col[GRC_FRAME].green, + im->graph_col[GRC_FRAME].blue, + im->graph_col[GRC_FRAME].alpha); + cairo_stroke(im->cr); + cairo_restore(im->cr); } } } @@ -2510,7 +2582,7 @@ int lazy_check( return 0; if ((fd = fopen(im->graphfile, "rb")) == NULL) return 0; /* the file does not exist */ - switch (im->canvas->imgformat) { + switch (im->imgformat) { case IF_PNG: size = PngSize(fd, &(im->ximg), &(im->yimg)); break; @@ -2521,67 +2593,10 @@ int lazy_check( return size; } -#ifdef WITH_PIECHART -void pie_part( - image_desc_t *im, - gfx_color_t color, - double PieCenterX, - double PieCenterY, - double Radius, - double startangle, - double endangle) -{ - gfx_node_t *node; - double angle; - double step = M_PI / 50; /* Number of iterations for the circle; - ** 10 is definitely too low, more than - ** 50 seems to be overkill - */ - - /* Strange but true: we have to work clockwise or else - ** anti aliasing nor transparency don't work. - ** - ** This test is here to make sure we do it right, also - ** this makes the for...next loop more easy to implement. - ** The return will occur if the user enters a negative number - ** (which shouldn't be done according to the specs) or if the - ** programmers do something wrong (which, as we all know, never - ** happens anyway :) - */ - if (endangle < startangle) - return; - - /* Hidden feature: Radius decreases each full circle */ - angle = startangle; - while (angle >= 2 * M_PI) { - angle -= 2 * M_PI; - Radius *= 0.8; - } - - node = gfx_new_area(im->canvas, - PieCenterX + sin(startangle) * Radius, - PieCenterY - cos(startangle) * Radius, - PieCenterX, - PieCenterY, - PieCenterX + sin(endangle) * Radius, - PieCenterY - cos(endangle) * Radius, color); - for (angle = endangle; angle - startangle >= step; angle -= step) { - gfx_add_point(node, - PieCenterX + sin(angle) * Radius, - PieCenterY - cos(angle) * Radius); - } -} - -#endif int graph_size_location( image_desc_t *im, - int elements -#ifdef WITH_PIECHART - , - int piechart -#endif - ) + int elements) { /* The actual size of the image to draw is determined from ** several sources. The size given on the command line is @@ -2590,14 +2605,7 @@ int graph_size_location( */ int Xvertical = 0, Ytitle = 0, Xylabel = 0, Xmain = 0, Ymain = 0, -#ifdef WITH_PIECHART - Xpie = 0, Ypie = 0, -#endif - Yxlabel = 0, -#if 0 - Xlegend = 0, Ylegend = 0, -#endif - Xspacing = 15, Yspacing = 15, Ywatermark = 4; + Yxlabel = 0, Xspacing = 15, Yspacing = 15, Ywatermark = 4; if (im->extra_flags & ONLY_GRAPH) { im->xorigin = 0; @@ -2646,11 +2654,10 @@ int graph_size_location( Yxlabel = im->text_prop[TEXT_PROP_AXIS].size * 2.5; } if (im->draw_y_grid || im->forceleftspace) { - Xylabel = gfx_get_text_width(im->canvas, 0, + Xylabel = gfx_get_text_width(im, 0, im->text_prop[TEXT_PROP_AXIS].font, im->text_prop[TEXT_PROP_AXIS].size, - im->tabwidth, - "0", 0) * im->unitslength; + im->tabwidth, "0") * im->unitslength; } } @@ -2668,14 +2675,6 @@ int graph_size_location( im->yorigin += Ytitle; -#ifdef WITH_PIECHART - if (piechart) { - im->piesize = im->xsize < im->ysize ? im->xsize : im->ysize; - Xpie = im->piesize; - Ypie = im->piesize; - } -#endif - /* 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 @@ -2687,12 +2686,6 @@ int graph_size_location( if (Xmain) Xmain -= Xspacing; /* put space between main graph area and right edge */ -#ifdef WITH_PIECHART - Xmain -= Xpie; /* remove pie width from main graph area */ - if (Xpie) - Xmain -= Xspacing; /* put space between pie and main graph area */ -#endif - im->xorigin = Xspacing + Xylabel; /* the length of the title should not influence with width of the graph @@ -2710,15 +2703,20 @@ int graph_size_location( ** of the legend and the axis labels. */ - /* Determine where to place the legends onto the image. - ** Set Ymain and adjust im->yorigin to match the space requirements. - */ - if (leg_place(im, &Ymain) == -1) - return -1; + if (im->extra_flags & NOLEGEND) { + /* set dimensions correctly if using full size mode with no legend */ + im->yorigin = + im->yimg - im->text_prop[TEXT_PROP_AXIS].size * 2.5 - + Yspacing; + Ymain = im->yorigin; + } else { + /* Determine where to place the legends onto the image. + ** Set Ymain and adjust im->yorigin to match the space requirements. + */ + if (leg_place(im, &Ymain) == -1) + return -1; + } -#ifdef WITH_PIECHART - /* if (im->yimg < Ypie) im->yimg = Ypie; * not sure what do about this */ -#endif /* remove title space *or* some padding above the graph from the main graph area */ if (Ytitle) { @@ -2765,14 +2763,6 @@ int graph_size_location( Xmain = im->xsize; Ymain = im->ysize; } -#ifdef WITH_PIECHART - if (piechart) { - im->piesize = im->xsize < im->ysize ? im->xsize : im->ysize; - Xpie = im->piesize; - Ypie = im->piesize; - } -#endif - /* 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 @@ -2786,16 +2776,8 @@ int graph_size_location( */ im->ximg = Xylabel + Xmain + 2 * Xspacing; -#ifdef WITH_PIECHART - im->ximg += Xpie; -#endif - if (Xmain) im->ximg += Xspacing; -#ifdef WITH_PIECHART - if (Xpie) - im->ximg += Xspacing; -#endif im->xorigin = Xspacing + Xylabel; @@ -2822,10 +2804,6 @@ int graph_size_location( im->yimg = Ymain + Yxlabel; -#ifdef WITH_PIECHART - if (im->yimg < Ypie) - im->yimg = Ypie; -#endif im->yorigin = im->yimg - Yxlabel; @@ -2851,27 +2829,6 @@ int graph_size_location( } } -#if 0 - if (Xlegend > im->ximg) { - im->ximg = Xlegend; - /* reposition Pie */ - } -#endif - -#ifdef WITH_PIECHART - /* The pie is placed in the upper right hand corner, - ** just below the title (if any) and with sufficient - ** padding. - */ - if (elements) { - im->pie_x = im->ximg - Xspacing - Xpie / 2; - im->pie_y = im->yorigin - Ymain + Ypie / 2; - } else { - im->pie_x = im->ximg / 2; - im->pie_y = im->yorigin - Ypie / 2; - } -#endif - ytr(im, DNAN); return 0; } @@ -2889,16 +2846,12 @@ int graph_paint( int i, ii; int lazy = lazy_check(im); -#ifdef WITH_PIECHART - int piechart = 0; - double PieStart = 0.0; -#endif - FILE *fo; - gfx_node_t *node; - double areazero = 0.0; graph_desc_t *lastgdes = NULL; + PangoFontMap *font_map = pango_cairo_font_map_get_default(); + + /* if we are lazy and there is nothing to PRINT ... quit now */ if (lazy && im->prt_c == 0) return 0; @@ -2912,15 +2865,6 @@ int graph_paint( if (data_calc(im) == -1) return -1; -#ifdef WITH_PIECHART - /* check if we need to draw a piechart */ - for (i = 0; i < im->gdes_c; i++) { - if (im->gdes[i].gf == GF_PART) { - piechart = 1; - break; - } - } -#endif /* calculate and PRINT and GPRINT definitions. We have to do it at * this point because it will affect the length of the legends @@ -2930,28 +2874,14 @@ int graph_paint( i = print_calc(im, calcpr); if (i < 0) return -1; - if (((i == 0) -#ifdef WITH_PIECHART - && (piechart == 0) -#endif - ) || lazy) + if ((i == 0) || lazy) return 0; -#ifdef WITH_PIECHART - /* If there's only the pie chart to draw, signal this */ - if (i == 0) - piechart = 2; -#endif - /************************************************************** *** Calculating sizes and locations became a bit confusing *** *** so I moved this into a separate function. *** **************************************************************/ - if (graph_size_location(im, i -#ifdef WITH_PIECHART - , piechart -#endif - ) == -1) + if (graph_size_location(im, i) == -1) return -1; /* get actual drawing data and find min and max values */ @@ -2969,44 +2899,67 @@ int graph_paint( if (!calc_horizontal_grid(im)) return -1; - if (im->gridfit) - apply_gridfit(im); + /* 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->surface = + cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom); + break; + case IF_EPS: + im->surface = + cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom); + break; + case IF_SVG: + im->surface = + cairo_svg_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom); + cairo_svg_surface_restrict_to_version(im->surface, + CAIRO_SVG_VERSION_1_1); + break; + }; + im->cr = cairo_create(im->surface); + pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(font_map), 100); + cairo_set_antialias(im->cr, im->graph_antialias); + cairo_scale(im->cr, im->zoom, im->zoom); - node = gfx_new_area(im->canvas, - 0, 0, - 0, im->yimg, - im->ximg, im->yimg, im->graph_col[GRC_BACK]); + gfx_new_area(im, + 0, 0, + 0, im->yimg, im->ximg, im->yimg, im->graph_col[GRC_BACK]); - gfx_add_point(node, im->ximg, 0); + gfx_add_point(im, im->ximg, 0); + gfx_close_path(im); -#ifdef WITH_PIECHART - if (piechart != 2) { -#endif - node = gfx_new_area(im->canvas, - 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(node, im->xorigin, im->yorigin - im->ysize); - - if (im->minval > 0.0) - areazero = im->minval; - if (im->maxval < 0.0) - areazero = im->maxval; -#ifdef WITH_PIECHART - } -#endif + 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]); -#ifdef WITH_PIECHART - if (piechart) { - pie_part(im, im->graph_col[GRC_CANVAS], im->pie_x, im->pie_y, - im->piesize * 0.5, 0, 2 * M_PI); - } -#endif + gfx_add_point(im, im->xorigin, im->yorigin - im->ysize); + gfx_close_path(im); + + 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) { @@ -3026,20 +2979,20 @@ int graph_paint( if (!isnan(im->gdes[i].p_data[ii]) && im->gdes[i].p_data[ii] != 0.0) { if (im->gdes[i].yrule > 0) { - gfx_new_line(im->canvas, - im->xorigin + ii, im->yorigin, - im->xorigin + ii, - im->yorigin - - im->gdes[i].yrule * im->ysize, 1.0, - im->gdes[i].col); + gfx_line(im, + im->xorigin + ii, im->yorigin, + 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_new_line(im->canvas, - im->xorigin + ii, - im->yorigin - im->ysize, - im->xorigin + ii, - im->yorigin - (1 - - im->gdes[i].yrule) * - im->ysize, 1.0, im->gdes[i].col); + gfx_line(im, + im->xorigin + ii, + im->yorigin - im->ysize, + im->xorigin + ii, + im->yorigin - (1 - + im->gdes[i].yrule) * + im->ysize, 1.0, im->gdes[i].col); } } @@ -3070,52 +3023,74 @@ int graph_paint( we draw a square from t-1 to t with the value a. ********************************************************* */ - if (im->gdes[i].col != 0x0) { + 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; - node = NULL; + cairo_save(im->cr); + cairo_new_path(im->cr); + + cairo_set_line_width(im->cr, im->gdes[i].linewidth); 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; + draw_on = 0; continue; } - if (node == NULL) { + if (draw_on == 0) { last_y = ytr(im, im->gdes[i].p_data[ii]); if (im->slopemode == 0) { - node = gfx_new_line(im->canvas, - ii - 1 + im->xorigin, - last_y, ii + im->xorigin, - last_y, - im->gdes[i].linewidth, - im->gdes[i].col); + double x = ii - 1 + im->xorigin; + double y = last_y; + + gfx_line_fit(im, &x, &y); + cairo_move_to(im->cr, x, y); + x = ii + im->xorigin; + y = last_y; + gfx_line_fit(im, &x, &y); + cairo_line_to(im->cr, x, y); } else { - node = gfx_new_line(im->canvas, - ii - 1 + im->xorigin, - ytr(im, - im->gdes[i]. - p_data[ii - 1]), - ii + im->xorigin, last_y, - im->gdes[i].linewidth, - im->gdes[i].col); + double x = ii - 1 + im->xorigin; + double y = ytr(im, + im->gdes[i].p_data[ii - 1]); + + gfx_line_fit(im, &x, &y); + cairo_move_to(im->cr, x, y); + x = ii + im->xorigin; + y = last_y; + gfx_line_fit(im, &x, &y); + cairo_line_to(im->cr, x, y); } + draw_on = 1; } else { - double new_y = ytr(im, im->gdes[i].p_data[ii]); + double x1 = ii + im->xorigin; + double y1 = ytr(im, im->gdes[i].p_data[ii]); if (im->slopemode == 0 - && !AlmostEqual2sComplement(new_y, last_y, - 4)) { - gfx_add_point(node, ii - 1 + im->xorigin, - new_y); + && !AlmostEqual2sComplement(y1, last_y, 4)) { + double x = ii - 1 + im->xorigin; + double y = y1; + + gfx_line_fit(im, &x, &y); + cairo_line_to(im->cr, x, y); }; - last_y = new_y; - gfx_add_point(node, ii + im->xorigin, new_y); + last_y = y1; + gfx_line_fit(im, &x1, &y1); + cairo_line_to(im->cr, x1, y1); }; } + cairo_set_source_rgba(im->cr, im->gdes[i].col.red, + im->gdes[i].col.green, + im->gdes[i].col.blue, + im->gdes[i].col.alpha); + cairo_set_line_cap(im->cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_join(im->cr, CAIRO_LINE_JOIN_ROUND); + cairo_stroke(im->cr); + cairo_restore(im->cr); } else { int idxI = -1; double *foreY = malloc(sizeof(double) * im->xsize * 2); @@ -3139,11 +3114,11 @@ int graph_paint( 4)) { cntI++; } - node = gfx_new_area(im->canvas, - backX[0], backY[0], - foreX[0], foreY[0], - foreX[cntI], foreY[cntI], - im->gdes[i].col); + gfx_new_area(im, + backX[0], backY[0], + foreX[0], foreY[0], + foreX[cntI], foreY[cntI], + im->gdes[i].col); while (cntI < idxI) { lastI = cntI; cntI++; @@ -3157,9 +3132,9 @@ int graph_paint( 1], 4)) { cntI++; } - gfx_add_point(node, foreX[cntI], foreY[cntI]); + gfx_add_point(im, foreX[cntI], foreY[cntI]); } - gfx_add_point(node, backX[idxI], backY[idxI]); + gfx_add_point(im, backX[idxI], backY[idxI]); while (idxI > 1) { lastI = idxI; idxI--; @@ -3173,10 +3148,11 @@ int graph_paint( 1], 4)) { idxI--; } - gfx_add_point(node, backX[idxI], backY[idxI]); + gfx_add_point(im, backX[idxI], backY[idxI]); } idxI = -1; drawem = 0; + gfx_close_path(im); } if (drawem != 0) { drawem = 0; @@ -3185,10 +3161,6 @@ int graph_paint( if (ii == im->xsize) break; - /* keep things simple for now, just draw these bars - do not try to build a big and complex area */ - - if (im->slopemode == 0 && ii == 0) { continue; } @@ -3206,8 +3178,7 @@ int graph_paint( drawem = 1; continue; } - /* every area has to be wound clock-wise, - so we have to make sur base remains base */ + if (ybase > ytop) { double extra = ytop; @@ -3245,20 +3216,6 @@ int graph_paint( } 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 case GF_STACK: rrd_set_error ("STACK should already be turned into LINE or AREA here"); @@ -3267,13 +3224,6 @@ int graph_paint( } /* switch */ } -#ifdef WITH_PIECHART - if (piechart == 2) { - im->draw_x_grid = 0; - im->draw_y_grid = 0; - } -#endif - /* grid_paint also does the text */ if (!(im->extra_flags & ONLY_GRAPH)) @@ -3290,19 +3240,19 @@ int graph_paint( case GF_HRULE: if (im->gdes[i].yrule >= im->minval && im->gdes[i].yrule <= im->maxval) - gfx_new_line(im->canvas, - im->xorigin, ytr(im, im->gdes[i].yrule), - im->xorigin + im->xsize, ytr(im, - im->gdes[i].yrule), - 1.0, im->gdes[i].col); + gfx_line(im, + im->xorigin, ytr(im, im->gdes[i].yrule), + im->xorigin + im->xsize, ytr(im, + im->gdes[i].yrule), + 1.0, im->gdes[i].col); break; case GF_VRULE: if (im->gdes[i].xrule >= im->start && im->gdes[i].xrule <= im->end) - gfx_new_line(im->canvas, - xtr(im, im->gdes[i].xrule), im->yorigin, - xtr(im, im->gdes[i].xrule), - im->yorigin - im->ysize, 1.0, im->gdes[i].col); + gfx_line(im, + xtr(im, im->gdes[i].xrule), im->yorigin, + xtr(im, im->gdes[i].xrule), + im->yorigin - im->ysize, 1.0, im->gdes[i].col); break; default: break; @@ -3310,22 +3260,18 @@ int graph_paint( } - if (strcmp(im->graphfile, "-") == 0) { - fo = im->graphhandle ? im->graphhandle : stdout; -#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) - /* Change translation mode for stdout to BINARY */ - _setmode(_fileno(fo), O_BINARY); -#endif - } else { - if ((fo = fopen(im->graphfile, "wb")) == NULL) { - rrd_set_error("Opening '%s' for write: %s", im->graphfile, - rrd_strerror(errno)); - return (-1); + 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; } + break; + default: + cairo_show_page(im->cr); + break; } - gfx_render(im->canvas, im->ximg, im->yimg, 0x00000000, fo); - if (strcmp(im->graphfile, "-") != 0) - fclose(fo); return 0; } @@ -3362,8 +3308,11 @@ int gdes_alloc( im->gdes[im->gdes_c - 1].data_first = 0; im->gdes[im->gdes_c - 1].p_data = NULL; im->gdes[im->gdes_c - 1].rpnp = NULL; - im->gdes[im->gdes_c - 1].shift = 0; - im->gdes[im->gdes_c - 1].col = 0x0; + im->gdes[im->gdes_c - 1].shift = 0.0; + im->gdes[im->gdes_c - 1].col.red = 0.0; + im->gdes[im->gdes_c - 1].col.green = 0.0; + im->gdes[im->gdes_c - 1].col.blue = 0.0; + im->gdes[im->gdes_c - 1].col.alpha = 0.0; im->gdes[im->gdes_c - 1].legend[0] = '\0'; im->gdes[im->gdes_c - 1].format[0] = '\0'; im->gdes[im->gdes_c - 1].strftm = 0; @@ -3418,6 +3367,13 @@ int rrd_graph( image_desc_t im; 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); + + + /* not currently using this ... */ im.graphhandle = stream; rrd_graph_options(argc, argv, &im); @@ -3481,8 +3437,7 @@ int rrd_graph( } sprintf((*prdata)[0], im.imginfo, filename, - (long) (im.canvas->zoom * im.ximg), - (long) (im.canvas->zoom * im.yimg)); + (long) (im.zoom * im.ximg), (long) (im.zoom * im.yimg)); } im_free(&im); return 0; @@ -3521,6 +3476,9 @@ void rrd_graph_init( im->forceleftspace = 0; im->symbol = ' '; im->viewfactor = 1.0; + im->imgformat = IF_PNG; + im->cr = NULL; + im->surface = NULL; im->extra_flags = 0; im->rigid = 0; im->gridfit = 1; @@ -3535,10 +3493,19 @@ void rrd_graph_init( im->prt_c = 0; im->gdes_c = 0; im->gdes = NULL; - im->canvas = gfx_new_canvas(); im->grid_dash_on = 1; im->grid_dash_off = 1; im->tabwidth = 40.0; + im->zoom = 1; + im->font_options = cairo_font_options_create(); + im->graph_antialias = CAIRO_ANTIALIAS_GRAY; + + 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]; @@ -3592,7 +3559,7 @@ void rrd_graph_options( time_t start_tmp = 0, end_tmp = 0; long long_tmp; struct rrd_time_value start_tv, end_tv; - gfx_color_t color; + long unsigned int color; optind = 0; opterr = 0; /* initialize getopt */ @@ -3643,6 +3610,7 @@ void rrd_graph_options( {"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 */ @@ -3819,7 +3787,7 @@ void rrd_graph_options( im->extra_flags |= FULL_SIZE_MODE; break; case 'i': - im->canvas->interlaced = 1; + /* interlaced png not supported at the moment */ break; case 'r': im->rigid = 1; @@ -3828,7 +3796,7 @@ void rrd_graph_options( im->imginfo = optarg; break; case 'a': - if ((int) (im->canvas->imgformat = if_conv(optarg)) == -1) { + if ((int) (im->imgformat = if_conv(optarg)) == -1) { rrd_set_error("unsupported graphics format '%s'", optarg); return; } @@ -3873,7 +3841,7 @@ void rrd_graph_options( return; } if ((ci = grc_conv(col_nam)) != -1) { - im->graph_col[ci] = color; + im->graph_col[ci] = gfx_hex_to_col(color); } else { rrd_set_error("invalid color name '%s'", col_nam); return; @@ -3914,8 +3882,8 @@ void rrd_graph_options( break; } case 'm': - im->canvas->zoom = atof(optarg); - if (im->canvas->zoom <= 0.0) { + im->zoom = atof(optarg); + if (im->zoom <= 0.0) { rrd_set_error("zoom factor must be > 0"); return; } @@ -3926,20 +3894,38 @@ void rrd_graph_options( break; case 'R': + if (strcmp(optarg, "normal") == 0) { + cairo_font_options_set_antialias(im->font_options, + CAIRO_ANTIALIAS_GRAY); + cairo_font_options_set_hint_style(im->font_options, + CAIRO_HINT_STYLE_FULL); + } else if (strcmp(optarg, "light") == 0) { + cairo_font_options_set_antialias(im->font_options, + CAIRO_ANTIALIAS_GRAY); + cairo_font_options_set_hint_style(im->font_options, + CAIRO_HINT_STYLE_SLIGHT); + } else if (strcmp(optarg, "mono") == 0) { + cairo_font_options_set_antialias(im->font_options, + CAIRO_ANTIALIAS_NONE); + cairo_font_options_set_hint_style(im->font_options, + CAIRO_HINT_STYLE_FULL); + } else { + rrd_set_error("unknown font-render-mode '%s'", optarg); + return; + } + break; + case 'G': if (strcmp(optarg, "normal") == 0) - im->canvas->aa_type = AA_NORMAL; - else if (strcmp(optarg, "light") == 0) - im->canvas->aa_type = AA_LIGHT; + im->graph_antialias = CAIRO_ANTIALIAS_GRAY; else if (strcmp(optarg, "mono") == 0) - im->canvas->aa_type = AA_NONE; + im->graph_antialias = CAIRO_ANTIALIAS_NONE; else { - rrd_set_error("unknown font-render-mode '%s'", optarg); + rrd_set_error("unknown graph-render-mode '%s'", optarg); return; } break; - case 'B': - im->canvas->font_aa_threshold = atof(optarg); + /* not supported curently */ break; case 'W': @@ -4008,7 +3994,7 @@ int rrd_graph_color( } else { int n = 0; char *rest; - gfx_color_t col; + long unsigned int col; rest = strstr(color, ":"); if (rest != NULL) @@ -4032,7 +4018,7 @@ int rrd_graph_color( } if (rrd_test_error()) return 0; - gdp->col = col; + gdp->col = gfx_hex_to_col(col); return n; } }