From 5f248c9adc1d11b174e685ec02bbc2269fbfcb9e Mon Sep 17 00:00:00 2001 From: oetiker Date: Mon, 11 Jun 2007 15:11:10 +0000 Subject: [PATCH] --font-render-mode is back, and there is also --graph-render-mode now. It allows to enable mono graphs that look strikingly like rrdtool 1.0.x --tobi git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk@1107 a5681a0c-68f1-0310-ab6d-d61299d08faa --- program/NEWS | 5 +- program/configure.ac | 4 +- program/doc/rrdgraph.pod | 32 ++-- program/src/Makefile.am | 1 - program/src/rrd_gfx.c | 69 ++++++--- program/src/rrd_gfx.h | 111 -------------- program/src/rrd_graph.c | 271 ++++++++++++++++++++------------- program/src/rrd_graph.h | 132 +++++++++++++--- program/src/rrd_graph_helper.c | 4 +- 9 files changed, 341 insertions(+), 288 deletions(-) delete mode 100644 program/src/rrd_gfx.h diff --git a/program/NEWS b/program/NEWS index 32ee7d42..28b801cb 100644 --- a/program/NEWS +++ b/program/NEWS @@ -14,7 +14,10 @@ Graphing -------- * libart has been replaced by cairo/pango * pango markup is supported -* full gridfitting +* full gridfitting +* --graph-render-mode=mono for non antialiased graphing +* --font-render-mode=mono for non antialiased fonts + RRDTOOL NEWS ============ diff --git a/program/configure.ac b/program/configure.ac index b27a3e77..e88f287a 100644 --- a/program/configure.ac +++ b/program/configure.ac @@ -605,9 +605,9 @@ dnl EX_CHECK_ALL(z, zlibVersion, zlib.h, dnl EX_CHECK_ALL(png, png_access_version_number, png.h, libpng, 1.2.10, http://prdownloads.sourceforge.net/libpng/, "") dnl EX_CHECK_ALL(freetype, FT_Init_FreeType, ft2build.h, freetype2, 2.1.10, http://prdownloads.sourceforge.net/freetype/, /usr/include/freetype2) dnl EX_CHECK_ALL(fontconfig, FcInit, fontconfig.h, fontconfig, 2.3.1, http://fontconfig.org/release/, /usr/include) -EX_CHECK_ALL(cairo, cairo_version, cairo.h, cairo-png, 1.4.6, http://cairographics.org/releases/, "") +EX_CHECK_ALL(cairo, cairo_font_options_create, cairo.h, cairo-png, 1.4.6, http://cairographics.org/releases/, "") dnl EX_CHECK_ALL(glib-2.0, glib_check_version, glib.h, glib-2.0, 2.12.12, ftp://ftp.gtk.org/pub/glib/2.12/, "") -EX_CHECK_ALL(pango-1.0, pango_version_check, pango/pango.h, pangocairo, 1.17, http://ftp.gnome.org/pub/GNOME/sources/pango/1.17, "") +EX_CHECK_ALL(pango-1.0, pango_cairo_context_set_font_options, pango/pango.h, pangocairo, 1.17, http://ftp.gnome.org/pub/GNOME/sources/pango/1.17, "") if test "$EX_CHECK_ALL_ERR" = "YES"; then AC_MSG_ERROR([Please fix the library issues listed above and try again.]) diff --git a/program/doc/rrdgraph.pod b/program/doc/rrdgraph.pod index 812b2478..84856750 100644 --- a/program/doc/rrdgraph.pod +++ b/program/doc/rrdgraph.pod @@ -146,13 +146,10 @@ and thus the throughput may be higher than the WAN line speed. [B<-N>|B<--no-gridfit>] -In order to avoid anti-aliasing effects gridlines are placed on -integer pixel values. This is by default done by extending -the scale so that gridlines happens to be spaced using an -integer number of pixels and also start on an integer pixel value. -This might extend the scale too much for some logarithmic scales -and for linear scales where B<--alt-autoscale> is needed. -Using B<--no-gridfit> disables modification of the scale. +In order to avoid anti-aliasing blurring effects rrdtool snaps +points to device resolution pixels, this results in a crisper +aperance. If this is not to your liking, you can use this switch +to turn this behaviour off. =item Grid @@ -320,13 +317,16 @@ gravity, and I is a decimal number (size in points) or optionally followed by the unit modifier "px" for absolute size. Any one of the options may be absent. -[B<-R>|B<--font-render-mode> {I,I,I}] +[B<-R>|B<--font-render-mode> {B,B,B}] -(this gets ignored in 1.3 for now!) +There are 3 font render modes: + +B: Full Hinting and Antialiasing (default) + +B: Slight Hinting and Antialiasing + +B: Full Hinting and NO Antialiasing -This lets you customize the strength of the font smoothing, -or disable it entirely using I. By default, I -font smoothing is used. [B<-B>|B<--font-smoothing-threshold> I] @@ -336,6 +336,14 @@ This specifies the largest font size which will be rendered bitmapped, that is, without any font smoothing. By default, no text is rendered bitmapped. +[B<-G>|B<--graph-render-mode> {B,B}] + +There are 2 render modes: + +B: Graphs are fully Antialiased (default) + +B: No Antialiasing + [B<-E>|B<--slope-mode>] RRDtool graphs are composed of stair case curves by default. This is in line with diff --git a/program/src/Makefile.am b/program/src/Makefile.am index 43f7ce40..68780689 100644 --- a/program/src/Makefile.am +++ b/program/src/Makefile.am @@ -49,7 +49,6 @@ RRD_C_FILES = \ noinst_HEADERS = \ unused.h \ - rrd_gfx.h \ rrd_getopt.h parsetime.h \ rrd_format.h rrd_tool.h rrd_xport.h rrd.h rrd_hw.h rrd_rpncalc.h \ rrd_nan_inf.h fnv.h rrd_graph.h \ diff --git a/program/src/rrd_gfx.c b/program/src/rrd_gfx.c index ec6a574b..8a18ce42 100644 --- a/program/src/rrd_gfx.c +++ b/program/src/rrd_gfx.c @@ -18,12 +18,12 @@ #endif /* _MSC_VER */ #include "rrd_tool.h" -#include "rrd_gfx.h" +#include "rrd_graph.h" /* create a new line */ void gfx_line( - cairo_t * cr, + image_desc_t *im, double X0, double Y0, double X1, @@ -31,11 +31,11 @@ void gfx_line( double width, gfx_color_t color) { - gfx_dashed_line(cr, X0, Y0, X1, Y1, width, color, 0, 0); + gfx_dashed_line(im, X0, Y0, X1, Y1, width, color, 0, 0); } void gfx_dashed_line( - cairo_t * cr, + image_desc_t *im, double X0, double Y0, double X1, @@ -45,6 +45,7 @@ void gfx_dashed_line( double dash_on, double dash_off) { + cairo_t *cr = im->cr; double dashes[] = { dash_on, dash_off }; double x = 0; double y = 0; @@ -52,10 +53,10 @@ void gfx_dashed_line( cairo_save(cr); cairo_new_path(cr); cairo_set_line_width(cr, width); - gfx_line_fit(cr, &x, &y); - gfx_line_fit(cr, &X0, &Y0); + gfx_line_fit(im, &x, &y); + gfx_line_fit(im, &X0, &Y0); cairo_move_to(cr, X0, Y0); - gfx_line_fit(cr, &X1, &Y1); + gfx_line_fit(im, &X1, &Y1); cairo_line_to(cr, X1, Y1); if (dash_on > 0 || dash_off > 0) cairo_set_dash(cr, dashes, 2, x); @@ -67,7 +68,7 @@ void gfx_dashed_line( /* create a new area */ void gfx_new_area( - cairo_t * cr, + image_desc_t *im, double X0, double Y0, double X1, @@ -76,12 +77,14 @@ void gfx_new_area( double Y2, gfx_color_t color) { + cairo_t *cr = im->cr; + cairo_new_path(cr); - gfx_area_fit(cr, &X0, &Y0); + gfx_area_fit(im, &X0, &Y0); cairo_move_to(cr, X0, Y0); - gfx_area_fit(cr, &X1, &Y1); + gfx_area_fit(im, &X1, &Y1); cairo_line_to(cr, X1, Y1); - gfx_area_fit(cr, &X2, &Y2); + gfx_area_fit(im, &X2, &Y2); cairo_line_to(cr, X2, Y2); cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); @@ -89,24 +92,28 @@ void gfx_new_area( /* add a point to a line or to an area */ void gfx_add_point( - cairo_t * cr, + image_desc_t *im, double x, double y) { - gfx_area_fit(cr, &x, &y); + cairo_t *cr = im->cr; + + gfx_area_fit(im, &x, &y); cairo_line_to(cr, x, y); } void gfx_close_path( - cairo_t * cr) + image_desc_t *im) { + cairo_t *cr = im->cr; + cairo_close_path(cr); cairo_fill(cr); } /* create a text node */ static PangoLayout *gfx_prep_text( - cairo_t * cr, + image_desc_t *im, double x, gfx_color_t color, char *font, @@ -116,6 +123,7 @@ static PangoLayout *gfx_prep_text( { PangoLayout *layout; PangoFontDescription *font_desc; + cairo_t *cr = im->cr; /* for performance reasons we might want todo that only once ... tabs will always @@ -125,6 +133,7 @@ static PangoLayout *gfx_prep_text( long tab_shift = fmod(x, tabwidth); PangoTabArray *tab_array; + PangoContext *pango_context; tab_array = pango_tab_array_new(tab_count, (gboolean) (1)); for (i = 1; i <= tab_count; i++) { @@ -135,6 +144,9 @@ static PangoLayout *gfx_prep_text( cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); layout = pango_cairo_create_layout(cr); + pango_context = pango_layout_get_context(layout); + pango_cairo_context_set_font_options(pango_context, im->font_options); + pango_cairo_update_context(cr, pango_context); pango_layout_set_tabs(layout, tab_array); font_desc = pango_font_description_from_string(font); @@ -146,7 +158,7 @@ static PangoLayout *gfx_prep_text( /* Size Text Node */ double gfx_get_text_width( - cairo_t * cr, + image_desc_t *im, double start, char *font, double size, @@ -159,11 +171,11 @@ double gfx_get_text_width( char *tab; /* turn \\t into tab */ - while (tab = strstr(text, "\\t")) { + while ((tab = strstr(text, "\\t"))) { memmove(tab + 1, tab + 2, strlen(tab + 2)); tab[0] = (char) 9; } - layout = gfx_prep_text(cr, start, color, font, size, tabwidth, text); + layout = gfx_prep_text(im, start, color, font, size, tabwidth, text); pango_layout_get_pixel_extents(layout, NULL, &log_rect); pango_tab_array_free(pango_layout_get_tabs(layout)); g_object_unref(layout); @@ -171,7 +183,7 @@ double gfx_get_text_width( } void gfx_text( - cairo_t * cr, + image_desc_t *im, double x, double y, gfx_color_t color, @@ -186,6 +198,7 @@ void gfx_text( PangoLayout *layout; PangoRectangle log_rect; PangoRectangle ink_rect; + cairo_t *cr = im->cr; double sx = 0; double sy = 0; @@ -193,11 +206,10 @@ void gfx_text( cairo_translate(cr, x, y); /* gfx_line(cr,-2,0,2,0,1,color); gfx_line(cr,0,-2,0,2,1,color); */ - layout = gfx_prep_text(cr, x, color, font, size, tabwidth, text); + layout = gfx_prep_text(im, x, color, font, size, tabwidth, text); pango_layout_get_pixel_extents(layout, &ink_rect, &log_rect); cairo_rotate(cr, -angle * G_PI / 180.0); sx = log_rect.x; - sy = ink_rect.y; switch (h_align) { case GFX_H_RIGHT: sx -= log_rect.width; @@ -210,7 +222,7 @@ void gfx_text( case GFX_H_NULL: break; } - sy += log_rect.y; + sy = log_rect.y; switch (v_align) { case GFX_V_TOP: break; @@ -248,20 +260,23 @@ struct gfx_color_t gfx_hex_to_col( /* gridfit_lines */ void gfx_line_fit( - cairo_t * cr, + image_desc_t *im, double *x, double *y) { + cairo_t *cr = im->cr; double line_width; double line_height; + if (!im->gridfit) + return; cairo_user_to_device(cr, x, y); line_width = cairo_get_line_width(cr); line_height = line_width; cairo_user_to_device_distance(cr, &line_width, &line_height); line_width = line_width / 2.0 - (long) (line_width / 2.0); line_height = line_height / 2.0 - (long) (line_height / 2.0); - *x = (double) ((long) (*x + 0.5)) + line_width; + *x = (double) ((long) (*x + 0.5)) - line_width; *y = (double) ((long) (*y + 0.5)) + line_height; cairo_device_to_user(cr, x, y); } @@ -269,10 +284,14 @@ void gfx_line_fit( /* gridfit_areas */ void gfx_area_fit( - cairo_t * cr, + image_desc_t *im, double *x, double *y) { + cairo_t *cr = im->cr; + + if (!im->gridfit) + return; cairo_user_to_device(cr, x, y); *x = (double) ((long) (*x + 0.5)); *y = (double) ((long) (*y + 0.5)); diff --git a/program/src/rrd_gfx.h b/program/src/rrd_gfx.h deleted file mode 100644 index c3cd1e39..00000000 --- a/program/src/rrd_gfx.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** - * RRDtool 1.2.23 Copyright by Tobi Oetiker, 1997-2007 - **************************************************************************** - * rrd_gfx.h generic graphics adapter library - ****************************************************************************/ - -#ifndef RRD_GFX_H -#define RRD_GFX_H - -#define y0 cairo_y0 -#define y1 cairo_y1 -#define index cairo_index - -#include -#include -#include -#include - -enum gfx_if_en { IF_PNG = 0, IF_SVG, IF_EPS, IF_PDF }; -enum gfx_en { GFX_LINE = 0, GFX_AREA, GFX_TEXT }; -enum gfx_h_align_en { GFX_H_NULL = 0, GFX_H_LEFT, GFX_H_RIGHT, GFX_H_CENTER }; -enum gfx_v_align_en { GFX_V_NULL = 0, GFX_V_TOP, GFX_V_BOTTOM, GFX_V_CENTER }; - -/* cairo color components */ -typedef struct gfx_color_t { - double red; - double green; - double blue; - double alpha; -} gfx_color_t; - - -/* create a new line */ -void gfx_line( - cairo_t * cr, - double X0, - double Y0, - double X1, - double Y1, - double width, - gfx_color_t color); - -void gfx_dashed_line( - cairo_t * cr, - double X0, - double Y0, - double X1, - double Y1, - double width, - gfx_color_t color, - double dash_on, - double dash_off); - -/* create a new area */ -void gfx_new_area( - cairo_t * cr, - double X0, - double Y0, - double X1, - double Y1, - double X2, - double Y2, - gfx_color_t color); - -/* add a point to a line or to an area */ -void gfx_add_point( - cairo_t * cr, - double x, - double y); - -/* close current path so it ends at the same point as it started */ -void gfx_close_path( - cairo_t * cr); - - -/* create a text node */ -void gfx_text( - cairo_t * cr, - double x, - double y, - gfx_color_t color, - char *font, - double size, - double tabwidth, - double angle, - enum gfx_h_align_en h_align, - enum gfx_v_align_en v_align, - const char *text); - -/* measure width of a text string */ -double gfx_get_text_width( - cairo_t * cr, - double start, - char *font, - double size, - double tabwidth, - char *text); - - -/* convert color */ -gfx_color_t gfx_hex_to_col( - long unsigned int); -void gfx_line_fit( - cairo_t *, - double *, - double *); -void gfx_area_fit( - cairo_t *, - double *, - double *); -#endif diff --git a/program/src/rrd_graph.c b/program/src/rrd_graph.c index d23d0716..6648d9cc 100644 --- a/program/src/rrd_graph.c +++ b/program/src/rrd_graph.c @@ -326,6 +326,8 @@ int im_free( free(im->gdes); if (im->surface) cairo_surface_destroy(im->surface); + if (im->font_options) + cairo_font_options_destroy(im->font_options); return 0; } @@ -1638,7 +1640,7 @@ int leg_place( /* no interleg space if string ends in \g */ fill += legspace[i]; } - fill += gfx_get_text_width(im->cr, fill + border, + fill += gfx_get_text_width(im, fill + border, im->text_prop[TEXT_PROP_LEGEND]. font, im->text_prop[TEXT_PROP_LEGEND]. @@ -1690,7 +1692,7 @@ int leg_place( im->gdes[ii].leg_x = leg_x; im->gdes[ii].leg_y = leg_y; leg_x += - gfx_get_text_width(im->cr, leg_x, + gfx_get_text_width(im, leg_x, im->text_prop[TEXT_PROP_LEGEND]. font, im->text_prop[TEXT_PROP_LEGEND]. @@ -1900,33 +1902,33 @@ int draw_horizontal_grid( } nlabels++; - gfx_text(im->cr, + 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->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_dashed_line(im->cr, + 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_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 1, Y0, X1 + 1, Y0, GRIDWIDTH, im->graph_col[GRC_GRID], @@ -2069,13 +2071,13 @@ int horizontal_log_grid( /* major grid line */ - gfx_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 2, Y0, X1 + 2, Y0, MGRIDWIDTH, im->graph_col[GRC_MGRID], @@ -2103,7 +2105,7 @@ int horizontal_log_grid( sprintf(graph_label, "%3.0f %c", pvalue, symbol); } else sprintf(graph_label, "%3.0e", value); - gfx_text(im->cr, + gfx_text(im, X0 - im->text_prop[TEXT_PROP_AXIS].size, Y0, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, @@ -2137,13 +2139,13 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 1, Y0, X1 + 1, Y0, GRIDWIDTH, im->graph_col[GRC_GRID], @@ -2160,13 +2162,13 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 1, Y0, X1 + 1, Y0, GRIDWIDTH, im->graph_col[GRC_GRID], @@ -2208,11 +2210,11 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 1, Y0, X1 + 1, Y0, GRIDWIDTH, im->graph_col[GRC_GRID], @@ -2231,11 +2233,11 @@ int horizontal_log_grid( break; /* draw lines */ - gfx_line(im->cr, + gfx_line(im, X0 - 2, Y0, X0, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, + gfx_line(im, X1, Y0, X1 + 2, Y0, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, + gfx_dashed_line(im, X0 - 1, Y0, X1 + 1, Y0, GRIDWIDTH, im->graph_col[GRC_GRID], @@ -2310,11 +2312,11 @@ void vertical_grid( if (ti == timajor) continue; /* skip as falls on major grid line */ X0 = xtr(im, ti); - gfx_line(im->cr, X0, Y1 - 2, X0, Y1, GRIDWIDTH, + gfx_line(im, X0, Y1 - 2, X0, Y1, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_line(im->cr, X0, Y0, X0, Y0 + 2, GRIDWIDTH, + gfx_line(im, X0, Y0, X0, Y0 + 2, GRIDWIDTH, im->graph_col[GRC_GRID]); - gfx_dashed_line(im->cr, X0, Y1 - 1, X0, Y0 + 1, GRIDWIDTH, + gfx_dashed_line(im, X0, Y0 + 1, X0, Y1 - 1, GRIDWIDTH, im->graph_col[GRC_GRID], im->grid_dash_on, im->grid_dash_off); @@ -2332,11 +2334,11 @@ void vertical_grid( if (ti < im->start || ti > im->end) continue; X0 = xtr(im, ti); - gfx_line(im->cr, X0, Y1 - 2, X0, Y1, MGRIDWIDTH, + gfx_line(im, X0, Y1 - 2, X0, Y1, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_line(im->cr, X0, Y0, X0, Y0 + 3, MGRIDWIDTH, + gfx_line(im, X0, Y0, X0, Y0 + 3, MGRIDWIDTH, im->graph_col[GRC_MGRID]); - gfx_dashed_line(im->cr, X0, Y1 - 2, X0, Y0 + 3, MGRIDWIDTH, + gfx_dashed_line(im, X0, Y0 + 3, X0, Y1 - 2, MGRIDWIDTH, im->graph_col[GRC_MGRID], im->grid_dash_on, im->grid_dash_off); @@ -2359,9 +2361,9 @@ void vertical_grid( #else # error "your libc has no strftime I guess we'll abort the exercise here." #endif - gfx_text(im->cr, + gfx_text(im, xtr(im, tilab), - Y0 + 1, + 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, @@ -2384,23 +2386,23 @@ void axis_paint( im->xorigin+im->xsize,im->yorigin-im->ysize, GRIDWIDTH, im->graph_col[GRC_AXIS]); */ - gfx_line(im->cr, im->xorigin - 4, im->yorigin, + gfx_line(im, im->xorigin - 4, im->yorigin, im->xorigin + im->xsize + 4, im->yorigin, MGRIDWIDTH, im->graph_col[GRC_AXIS]); - gfx_line(im->cr, im->xorigin, im->yorigin + 4, + 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->cr, 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->cr); + gfx_close_path(im); - gfx_new_area(im->cr, 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->cr); + gfx_close_path(im); } @@ -2414,20 +2416,20 @@ void grid_paint( struct gfx_color_t water_color; /* draw 3d border */ - gfx_new_area(im->cr, 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->cr, im->ximg - 2, 2); - gfx_add_point(im->cr, im->ximg, 0); - gfx_add_point(im->cr, 0, 0); - gfx_close_path(im->cr); + 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->cr, 2, im->yimg - 2, + 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->cr, im->ximg, 0); - gfx_add_point(im->cr, im->ximg, im->yimg); - gfx_add_point(im->cr, 0, im->yimg); - gfx_close_path(im->cr); + 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) @@ -2444,7 +2446,7 @@ void grid_paint( if (!res) { char *nodata = "No Data found"; - gfx_text(im->cr, im->ximg / 2, + gfx_text(im, im->ximg / 2, (2 * im->yorigin - im->ysize) / 2, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_AXIS].font, @@ -2454,7 +2456,7 @@ void grid_paint( } /* yaxis unit description */ - gfx_text(im->cr, + gfx_text(im, 10, (im->yorigin - im->ysize / 2), im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_UNIT].font, @@ -2462,8 +2464,8 @@ void grid_paint( RRDGRAPH_YLEGEND_ANGLE, GFX_H_CENTER, GFX_V_CENTER, im->ylegend); /* graph title */ - gfx_text(im->cr, - im->ximg / 2, 4, + 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, @@ -2471,8 +2473,8 @@ void grid_paint( /* rrdtool 'logo' */ water_color = im->graph_col[GRC_FONT]; water_color.alpha = 0.3; - gfx_text(im->cr, - im->ximg - 4, 7, + gfx_text(im, + im->ximg - 4, 5, water_color, im->text_prop[TEXT_PROP_AXIS].font, 5.5, im->tabwidth, -90, @@ -2480,7 +2482,7 @@ void grid_paint( /* graph watermark */ if (im->watermark[0] != '\0') { - gfx_text(im->cr, + gfx_text(im, im->ximg / 2, im->yimg - 6, water_color, im->text_prop[TEXT_PROP_AXIS].font, @@ -2497,7 +2499,7 @@ 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_text(im->cr, X0, Y0, + gfx_text(im, X0, Y0, im->graph_col[GRC_FONT], im->text_prop[TEXT_PROP_LEGEND].font, im->text_prop[TEXT_PROP_LEGEND].size, @@ -2507,44 +2509,52 @@ void grid_paint( 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->cr, 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") * 1.2; - boxV = boxH * 1.1; + boxV = boxH; /* shift the box up a bit */ - Y0 -= boxV * 0.3; + Y0 -= boxV * 0.4; /* make sure transparent colors show up the same way as in the graph */ - gfx_new_area(im->cr, + gfx_new_area(im, X0, Y0 - boxV, X0, Y0, X0 + boxH, Y0, im->graph_col[GRC_BACK]); - gfx_add_point(im->cr, X0 + boxH, Y0 - boxV); - gfx_close_path(im->cr); + gfx_add_point(im, X0 + boxH, Y0 - boxV); + gfx_close_path(im); - gfx_new_area(im->cr, + gfx_new_area(im, X0, Y0 - boxV, X0, Y0, X0 + boxH, Y0, im->gdes[i].col); - gfx_add_point(im->cr, X0 + boxH, Y0 - boxV); - gfx_close_path(im->cr); - - gfx_line(im->cr, - X0, Y0 - boxV, - X0, Y0, 1.0, im->graph_col[GRC_FRAME]); - gfx_line(im->cr, - X0, Y0, - X0 + boxH, Y0, 1.0, im->graph_col[GRC_FRAME]); - gfx_line(im->cr, - X0 + boxH, Y0, - X0 + boxH, Y0 - boxV, 1.0, im->graph_col[GRC_FRAME]); - gfx_line(im->cr, - X0 + boxH, Y0 - boxV, - X0, Y0 - boxV, 1.0, im->graph_col[GRC_FRAME]); + 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); } } } @@ -2644,7 +2654,7 @@ 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->cr, 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") * im->unitslength; @@ -2837,9 +2847,10 @@ int graph_paint( int lazy = lazy_check(im); double areazero = 0.0; + graph_desc_t *lastgdes = NULL; + PangoFontMap *font_map = pango_cairo_font_map_get_default(); - graph_desc_t *lastgdes = NULL; /* if we are lazy and there is nothing to PRINT ... quit now */ if (lazy && im->prt_c == 0) @@ -2888,8 +2899,12 @@ 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 */ @@ -2921,24 +2936,25 @@ int graph_paint( break; }; im->cr = cairo_create(im->surface); - pango_cairo_font_map_set_resolution(font_map, 100); + 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); - gfx_new_area(im->cr, + gfx_new_area(im, 0, 0, 0, im->yimg, im->ximg, im->yimg, im->graph_col[GRC_BACK]); - gfx_add_point(im->cr, im->ximg, 0); - gfx_close_path(im->cr); + gfx_add_point(im, im->ximg, 0); + gfx_close_path(im); - gfx_new_area(im->cr, + 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->cr, im->xorigin, im->yorigin - im->ysize); - gfx_close_path(im->cr); + gfx_add_point(im, im->xorigin, im->yorigin - im->ysize); + gfx_close_path(im); if (im->minval > 0.0) areazero = im->minval; @@ -2963,14 +2979,14 @@ 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_line(im->cr, + 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_line(im->cr, + gfx_line(im, im->xorigin + ii, im->yorigin - im->ysize, im->xorigin + ii, @@ -3030,22 +3046,22 @@ int graph_paint( double x = ii - 1 + im->xorigin; double y = last_y; - gfx_line_fit(im->cr, &x, &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->cr, &x, &y); + gfx_line_fit(im, &x, &y); cairo_line_to(im->cr, x, y); } else { double x = ii - 1 + im->xorigin; double y = ytr(im, im->gdes[i].p_data[ii - 1]); - gfx_line_fit(im->cr, &x, &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->cr, &x, &y); + gfx_line_fit(im, &x, &y); cairo_line_to(im->cr, x, y); } draw_on = 1; @@ -3058,11 +3074,11 @@ int graph_paint( double x = ii - 1 + im->xorigin; double y = y1; - gfx_line_fit(im->cr, &x, &y); + gfx_line_fit(im, &x, &y); cairo_line_to(im->cr, x, y); }; last_y = y1; - gfx_line_fit(im->cr, &x1, &y1); + gfx_line_fit(im, &x1, &y1); cairo_line_to(im->cr, x1, y1); }; @@ -3098,7 +3114,7 @@ int graph_paint( 4)) { cntI++; } - gfx_new_area(im->cr, + gfx_new_area(im, backX[0], backY[0], foreX[0], foreY[0], foreX[cntI], foreY[cntI], @@ -3116,10 +3132,9 @@ int graph_paint( 1], 4)) { cntI++; } - gfx_add_point(im->cr, foreX[cntI], - foreY[cntI]); + gfx_add_point(im, foreX[cntI], foreY[cntI]); } - gfx_add_point(im->cr, backX[idxI], backY[idxI]); + gfx_add_point(im, backX[idxI], backY[idxI]); while (idxI > 1) { lastI = idxI; idxI--; @@ -3133,12 +3148,11 @@ int graph_paint( 1], 4)) { idxI--; } - gfx_add_point(im->cr, backX[idxI], - backY[idxI]); + gfx_add_point(im, backX[idxI], backY[idxI]); } idxI = -1; drawem = 0; - gfx_close_path(im->cr); + gfx_close_path(im); } if (drawem != 0) { drawem = 0; @@ -3226,7 +3240,7 @@ int graph_paint( case GF_HRULE: if (im->gdes[i].yrule >= im->minval && im->gdes[i].yrule <= im->maxval) - gfx_line(im->cr, + gfx_line(im, im->xorigin, ytr(im, im->gdes[i].yrule), im->xorigin + im->xsize, ytr(im, im->gdes[i].yrule), @@ -3235,7 +3249,7 @@ int graph_paint( case GF_VRULE: if (im->gdes[i].xrule >= im->start && im->gdes[i].xrule <= im->end) - gfx_line(im->cr, + 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); @@ -3483,6 +3497,15 @@ void rrd_graph_init( 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]; @@ -3587,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 */ @@ -3870,9 +3894,36 @@ void rrd_graph_options( break; case 'R': - /* not supported curently */ + 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->graph_antialias = CAIRO_ANTIALIAS_GRAY; + else if (strcmp(optarg, "mono") == 0) + im->graph_antialias = CAIRO_ANTIALIAS_NONE; + else { + rrd_set_error("unknown graph-render-mode '%s'", optarg); + return; + } break; - case 'B': /* not supported curently */ break; diff --git a/program/src/rrd_graph.h b/program/src/rrd_graph.h index dd036151..502fefe1 100644 --- a/program/src/rrd_graph.h +++ b/program/src/rrd_graph.h @@ -1,9 +1,17 @@ #ifndef _RRD_GRAPH_H #define _RRD_GRAPH_H +#define y0 cairo_y0 +#define y1 cairo_y1 +#define index cairo_index + +#include +#include +#include +#include + #include "rrd_tool.h" #include "rrd_rpncalc.h" -#include "rrd_gfx.h" #define MAX_VNAME_LEN 255 #define DEF_NAM_FMT "%255[-_A-Za-z0-9]" @@ -36,9 +44,6 @@ enum grc_en { GRC_CANVAS = 0, GRC_BACK, GRC_SHADEA, GRC_SHADEB, enum gf_en { GF_PRINT = 0, GF_GPRINT, GF_COMMENT, GF_HRULE, GF_VRULE, GF_LINE, GF_AREA, GF_STACK, GF_TICK, GF_DEF, GF_CDEF, GF_VDEF, GF_SHIFT, -#ifdef WITH_PIECHART - GF_PART, -#endif GF_XPORT }; @@ -62,6 +67,21 @@ enum text_prop_en { TEXT_PROP_DEFAULT = 0, /* default settings */ TEXT_PROP_LAST }; + +enum gfx_if_en { IF_PNG = 0, IF_SVG, IF_EPS, IF_PDF }; +enum gfx_en { GFX_LINE = 0, GFX_AREA, GFX_TEXT }; +enum gfx_h_align_en { GFX_H_NULL = 0, GFX_H_LEFT, GFX_H_RIGHT, GFX_H_CENTER }; +enum gfx_v_align_en { GFX_V_NULL = 0, GFX_V_TOP, GFX_V_BOTTOM, GFX_V_CENTER }; + +/* cairo color components */ +typedef struct gfx_color_t { + double red; + double green; + double blue; + double alpha; +} gfx_color_t; + + typedef struct text_prop_t { double size; char font[1024]; @@ -156,9 +176,6 @@ typedef struct image_desc_t { char graphfile[MAXPATH]; /* filename for graphic */ FILE *graphhandle; /* FILE to use if filename is "-" */ long xsize, ysize; /* graph area size in pixels */ -#ifdef WITH_PIECHART - long piesize; /* size of the piechart */ -#endif struct gfx_color_t graph_col[__GRC_END__]; /* real colors for the graph */ text_prop_t text_prop[TEXT_PROP_LAST]; /* text properties */ char ylegend[210]; /* legend along the yaxis */ @@ -193,9 +210,6 @@ typedef struct image_desc_t { /* status information */ long xorigin, yorigin; /* where is (0,0) of the graph */ -#ifdef WITH_PIECHART - long pie_x, pie_y; /* where is the centerpoint */ -#endif long ximg, yimg; /* total size of the image */ double zoom; double magfact; /* numerical magnitude */ @@ -214,6 +228,8 @@ typedef struct image_desc_t { graph_desc_t *gdes; /* points to an array of graph elements */ cairo_surface_t *surface; /* graphics library */ cairo_t *cr; /* drawin context */ + cairo_font_options_t *font_options; /* cairo font options */ + cairo_antialias_t graph_antialias; /* antialiasing for the graph */ } image_desc_t; /* Prototypes */ @@ -300,16 +316,6 @@ int graph_paint( image_desc_t *, char ***); -#ifdef WITH_PIECHART -void pie_part( - image_desc_t *, - gfx_color_t, - double, - double, - double, - double, - double); -#endif int gdes_alloc( image_desc_t *); int scan_for_col( @@ -355,10 +361,88 @@ int vdef_percent_compar( int graph_size_location( image_desc_t *, int -#ifdef WITH_PIECHART - , - int -#endif ); + +/* create a new line */ +void gfx_line( + image_desc_t *im, + double X0, + double Y0, + double X1, + double Y1, + double width, + gfx_color_t color); + +void gfx_dashed_line( + image_desc_t *im, + double X0, + double Y0, + double X1, + double Y1, + double width, + gfx_color_t color, + double dash_on, + double dash_off); + +/* create a new area */ +void gfx_new_area( + image_desc_t *im, + double X0, + double Y0, + double X1, + double Y1, + double X2, + double Y2, + gfx_color_t color); + +/* add a point to a line or to an area */ +void gfx_add_point( + image_desc_t *im, + double x, + double y); + +/* close current path so it ends at the same point as it started */ +void gfx_close_path( + image_desc_t *im); + + +/* create a text node */ +void gfx_text( + image_desc_t *im, + double x, + double y, + gfx_color_t color, + char *font, + double size, + double tabwidth, + double angle, + enum gfx_h_align_en h_align, + enum gfx_v_align_en v_align, + const char *text); + +/* measure width of a text string */ +double gfx_get_text_width( + image_desc_t *im, + double start, + char *font, + double size, + double tabwidth, + char *text); + + +/* convert color */ +gfx_color_t gfx_hex_to_col( + long unsigned int); + +void gfx_line_fit( + image_desc_t *im, + double *x, + double *y); + +void gfx_area_fit( + image_desc_t *im, + double *x, + double *y); + #endif diff --git a/program/src/rrd_graph_helper.c b/program/src/rrd_graph_helper.c index 0991b3b8..708c2232 100644 --- a/program/src/rrd_graph_helper.c +++ b/program/src/rrd_graph_helper.c @@ -497,7 +497,7 @@ int rrd_parse_PVHLAST( static int spacecnt = 0; if (spacecnt == 0) { - float one_space = gfx_get_text_width(im->cr, 0, + float one_space = gfx_get_text_width(im, 0, im-> text_prop[TEXT_PROP_LEGEND]. font, @@ -505,7 +505,7 @@ int rrd_parse_PVHLAST( text_prop[TEXT_PROP_LEGEND]. size, im->tabwidth, " ") / 4.0; - float target_space = gfx_get_text_width(im->cr, 0, + float target_space = gfx_get_text_width(im, 0, im-> text_prop [TEXT_PROP_LEGEND].font, -- 2.30.2