From f5b46b2a8532bb9832673f8fbb4934d5b0a65061 Mon Sep 17 00:00:00 2001 From: oetiker Date: Sun, 31 Aug 2008 22:53:49 +0000 Subject: [PATCH] Improve performance by keeping multiple pango font descriptions. For the first invocation we are about 20% times as fast for the second one about 4-5 times faster ... git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1475 a5681a0c-68f1-0310-ab6d-d61299d08faa --- src/rrd_gfx.c | 65 ++++-------------- src/rrd_graph.c | 179 ++++++++++++++++++++++++++----------------------- src/rrd_graph.h | 16 ++--- src/rrd_graph_helper.c | 16 ++--- 4 files changed, 121 insertions(+), 155 deletions(-) diff --git a/src/rrd_gfx.c b/src/rrd_gfx.c index 6f04135..be536c5 100644 --- a/src/rrd_gfx.c +++ b/src/rrd_gfx.c @@ -119,19 +119,17 @@ static PangoLayout *gfx_prep_text( image_desc_t *im, double x, gfx_color_t color, - char *font, - double size, + PangoFontDescription *font_desc, double tabwidth, const char *text) { - static PangoLayout *layout = NULL; - static PangoContext *pango_context = NULL; - static PangoFontMap *pango_fontmap = NULL; - static char* last_font = NULL; - static double last_size = -1; + PangoLayout *layout = im->layout; + PangoFontDescription *pfd; + cairo_t *cr = im->cr; + static double last_tabwidth = -1; - cairo_t *cr = im->cr; + /* for performance reasons we might want todo that only once ... tabs will always @@ -143,25 +141,6 @@ static PangoLayout *gfx_prep_text( gchar *utf8_text; - /* initialize pango only once ... */ - if (!pango_fontmap){ - pango_fontmap = pango_cairo_font_map_get_default (); - } - if (!pango_context){ - // fprintf(stderr,"c"); - pango_context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) (pango_fontmap)); - pango_cairo_context_set_resolution(pango_context, 100); - } - if (!layout){ - // fprintf(stderr,"l"); - layout = pango_layout_new (pango_context); - } - - pango_cairo_context_set_font_options(pango_context, im->font_options); - - pango_cairo_update_context (cr, pango_context); - - if (last_tabwidth < 0 || last_tabwidth != tabwidth){ PangoTabArray *tab_array; // fprintf(stderr,"t"); @@ -175,27 +154,13 @@ static PangoLayout *gfx_prep_text( pango_layout_set_tabs(layout, tab_array); pango_tab_array_free(tab_array); } - - if (last_font == NULL || strcmp(font,last_font) != 0){ - PangoFontDescription *font_desc; - // fprintf(stderr,"f:%s",font); - if (last_font) - free(last_font); - last_font = strdup(font); - font_desc = pango_font_description_from_string(font); + pfd = pango_layout_get_font_description(layout); + if (pfd && pango_font_description_equal (pfd,font_desc)){ pango_layout_set_font_description(layout, font_desc); - pango_font_description_free(font_desc); } - if (last_size < 0 || last_size != size ){ - PangoFontDescription *font_desc; - font_desc = pango_layout_get_font_description (layout); - pango_font_description_set_size(font_desc, size * PANGO_SCALE); - pango_layout_set_font_description(layout, font_desc); - } - - cairo_new_path(cr); - cairo_set_source_rgba(cr, color.red, color.green, color.blue, + cairo_new_path(cr); + cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); /* layout = pango_cairo_create_layout(cr); */ @@ -224,15 +189,14 @@ static PangoLayout *gfx_prep_text( double gfx_get_text_width( image_desc_t *im, double start, - char *font, - double size, + PangoFontDescription *font_desc, double tabwidth, char *text) { PangoLayout *layout; PangoRectangle log_rect; gfx_color_t color = { 0, 0, 0, 0 }; - layout = gfx_prep_text(im, start, color, font, size, tabwidth, text); + layout = gfx_prep_text(im, start, color, font_desc, tabwidth, text); pango_layout_get_pixel_extents(layout, NULL, &log_rect); /* g_object_unref(layout); */ return log_rect.width; @@ -243,8 +207,7 @@ void gfx_text( double x, double y, gfx_color_t color, - char *font, - double size, + PangoFontDescription *font_desc, double tabwidth, double angle, enum gfx_h_align_en h_align, @@ -261,7 +224,7 @@ 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(im, x, color, font, size, tabwidth, text); + layout = gfx_prep_text(im, x, color, font_desc, tabwidth, text); pango_layout_get_pixel_extents(layout, NULL, &log_rect); cairo_rotate(cr, -angle * G_PI / 180.0); sx = log_rect.x; diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 6f1a1ac..36dbddf 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -37,15 +37,17 @@ #endif text_prop_t text_prop[] = { - {8.0, RRD_DEFAULT_FONT} + {8.0, RRD_DEFAULT_FONT,NULL} , /* default */ - {9.0, RRD_DEFAULT_FONT} + {9.0, RRD_DEFAULT_FONT,NULL} , /* title */ - {7.0, RRD_DEFAULT_FONT} + {7.0, RRD_DEFAULT_FONT,NULL} , /* axis */ - {8.0, RRD_DEFAULT_FONT} + {8.0, RRD_DEFAULT_FONT,NULL} , /* unit */ - {8.0, RRD_DEFAULT_FONT} /* legend */ + {8.0, RRD_DEFAULT_FONT,NULL} /* legend */ + , + {5.5, RRD_DEFAULT_FONT,NULL} /* watermark */ }; xlab_t xlab[] = { @@ -288,6 +290,7 @@ enum text_prop_en text_prop_conv( conv_if(AXIS, TEXT_PROP_AXIS); conv_if(UNIT, TEXT_PROP_UNIT); conv_if(LEGEND, TEXT_PROP_LEGEND); + conv_if(WATERMARK, TEXT_PROP_WATERMARK); return -1; } @@ -330,12 +333,18 @@ int im_free( if (im->rendered_image) { free(im->rendered_image); } + + if (im->layout) { + g_object_unref (im->layout); + } + if (im->surface) cairo_surface_destroy(im->surface); + if (status) fprintf(stderr, "OOPS: Cairo has issues it can't even die: %s\n", cairo_status_to_string(status)); - + return 0; } @@ -1701,11 +1710,7 @@ int leg_place( im-> text_prop [TEXT_PROP_LEGEND]. - font, - im-> - text_prop - [TEXT_PROP_LEGEND]. - size, + font_desc, im->tabwidth, im->gdes[i].legend); leg_c++; } else { @@ -1770,11 +1775,7 @@ int leg_place( im-> text_prop [TEXT_PROP_LEGEND]. - font, - im-> - text_prop - [TEXT_PROP_LEGEND]. - size, + font_desc, im->tabwidth, im->gdes[ii].legend) + legspace[ii] + glue; @@ -1990,10 +1991,8 @@ int draw_horizontal_grid( im->graph_col[GRC_FONT], im-> text_prop[TEXT_PROP_AXIS]. - font, - im-> - text_prop[TEXT_PROP_AXIS]. - size, im->tabwidth, 0.0, + font_desc, + 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]); @@ -2171,10 +2170,8 @@ int horizontal_log_grid( im->graph_col[GRC_FONT], im-> text_prop[TEXT_PROP_AXIS]. - font, - im-> - text_prop[TEXT_PROP_AXIS]. - size, im->tabwidth, 0.0, + font_desc, + im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER, graph_label); /* minor grid */ if (mid < 4 && exfrac == 1) { @@ -2442,10 +2439,8 @@ void vertical_grid( im->graph_col[GRC_FONT], im-> text_prop[TEXT_PROP_AXIS]. - font, - im-> - text_prop[TEXT_PROP_AXIS]. - size, im->tabwidth, 0.0, + font_desc, + im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_TOP, graph_label); } @@ -2523,10 +2518,8 @@ void grid_paint( im->graph_col[GRC_FONT], im-> text_prop[TEXT_PROP_AXIS]. - font, - im-> - text_prop[TEXT_PROP_AXIS]. - size, im->tabwidth, 0.0, + font_desc, + im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_CENTER, nodata); } } @@ -2539,10 +2532,8 @@ void grid_paint( im->graph_col[GRC_FONT], im-> text_prop[TEXT_PROP_UNIT]. - font, - im-> - text_prop[TEXT_PROP_UNIT]. - size, im->tabwidth, + font_desc, + im->tabwidth, RRDGRAPH_YLEGEND_ANGLE, GFX_H_CENTER, GFX_V_CENTER, im->ylegend); /* graph title */ gfx_text(im, @@ -2550,18 +2541,16 @@ void grid_paint( 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); + font_desc, + im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_TOP, im->title); /* rrdtool 'logo' */ 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, + text_prop[TEXT_PROP_WATERMARK]. + font_desc, im->tabwidth, -90, GFX_H_LEFT, GFX_V_TOP, "RRDTOOL / TOBI OETIKER"); /* graph watermark */ if (im->watermark[0] != '\0') { @@ -2569,8 +2558,8 @@ void grid_paint( im->ximg / 2, im->yimg - 6, water_color, im-> - text_prop[TEXT_PROP_AXIS]. - font, 5.5, im->tabwidth, 0, + text_prop[TEXT_PROP_WATERMARK]. + font_desc, im->tabwidth, 0, GFX_H_CENTER, GFX_V_BOTTOM, im->watermark); } @@ -2586,10 +2575,7 @@ void grid_paint( im->graph_col[GRC_FONT], im-> text_prop - [TEXT_PROP_LEGEND].font, - im-> - text_prop - [TEXT_PROP_LEGEND].size, + [TEXT_PROP_LEGEND].font_desc, im->tabwidth, 0.0, GFX_H_LEFT, GFX_V_BOTTOM, im->gdes[i].legend); /* The legend for GRAPH items starts with "M " to have @@ -2603,11 +2589,8 @@ void grid_paint( im-> text_prop [TEXT_PROP_LEGEND]. - font, - im-> - text_prop - [TEXT_PROP_LEGEND]. - size, im->tabwidth, "o") * 1.2; + font_desc, + im->tabwidth, "o") * 1.2; boxV = boxH; /* shift the box up a bit */ Y0 -= boxV * 0.4; @@ -2763,11 +2746,8 @@ int graph_size_location( im-> text_prop [TEXT_PROP_AXIS]. - font, - im-> - text_prop - [TEXT_PROP_AXIS]. - size, im->tabwidth, "0") * im->unitslength; + font_desc, + im->tabwidth, "0") * im->unitslength; } } @@ -2948,7 +2928,8 @@ int graph_paint( double areazero = 0.0; graph_desc_t *lastgdes = NULL; rrd_infoval_t info; - PangoFontMap *font_map = pango_cairo_font_map_get_default(); + +// PangoFontMap *font_map = pango_cairo_font_map_get_default(); /* if we want and can be lazy ... quit now */ if (lazy) { @@ -3063,7 +3044,7 @@ int graph_paint( 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); +// 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); @@ -3613,11 +3594,9 @@ rrd_info_t *rrd_graph_v( { image_desc_t im; rrd_info_t *grinfo; - 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); + rrd_graph_options(argc, argv, &im); if (rrd_test_error()) { rrd_info_free(im.grinfo); @@ -3696,11 +3675,39 @@ rrd_info_t *rrd_graph_v( return grinfo; } +static void +rrd_set_font_desc ( + image_desc_t *im,int prop,char *font, double size ){ + static text_prop_t tp_cache[] = { {-1,"",NULL}, {-1,"",NULL}, {-1,"",NULL}, {-1,"",NULL}, {-1,"",NULL}, {-1,"",NULL}}; + + if (tp_cache[prop].font_desc == NULL){ + tp_cache[prop].font_desc = pango_font_description_new(); + im->text_prop[prop].font_desc = pango_font_description_copy (tp_cache[prop].font_desc); + } + + if (font != NULL && strcmp(tp_cache[prop].font,font) != 0){ + pango_font_description_free(tp_cache[prop].font_desc); + pango_font_description_free(im->text_prop[prop].font_desc); + tp_cache[prop].font_desc = pango_font_description_from_string( font ); + im->text_prop[prop].font_desc = pango_font_description_copy( tp_cache[prop].font_desc ); + strncpy(tp_cache[prop].font, font, sizeof(text_prop[prop].font) - 1); + tp_cache[prop].font[sizeof(text_prop[prop].font) - 1] = '\0'; + strcpy(im->text_prop[prop].font,tp_cache[prop].font); + } + if (size != 0 && size != (tp_cache[prop].size)){ + pango_font_description_set_size(tp_cache[prop].font_desc, size * PANGO_SCALE); + pango_font_description_set_size(im->text_prop[prop].font_desc, size * PANGO_SCALE); + im->text_prop[prop].size = size; + tp_cache[prop].size = size; + } +} + void rrd_graph_init( image_desc_t *im) { unsigned int i; + char *deffont = getenv("RRD_DEFAULT_FONT"); #ifdef HAVE_TZSET tzset(); @@ -3712,7 +3719,6 @@ void rrd_graph_init( #endif #endif im->base = 1000; - im->cr = NULL; im->draw_x_grid = 1; im->draw_y_grid = 1; im->extra_flags = 0; @@ -3739,7 +3745,6 @@ void rrd_graph_init( im->rendered_image = NULL; im->slopemode = 0; im->step = 0; - im->surface = NULL; im->symbol = ' '; im->tabwidth = 40.0; im->title[0] = '\0'; @@ -3758,31 +3763,32 @@ void rrd_graph_init( im->yorigin = 0; im->ysize = 100; im->zoom = 1; + + im->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); + im->cr = cairo_create(im->surface); + + for (i = 0; i < DIM(text_prop); i++) { + rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size); + } + + im->layout = pango_cairo_create_layout(im->cr); + pango_cairo_context_set_resolution(pango_layout_get_context(im->layout), 100); + 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]; - { - char *deffont; - - deffont = getenv("RRD_DEFAULT_FONT"); - if (deffont != NULL) { - for (i = 0; i < DIM(text_prop); i++) { - strncpy(text_prop[i].font, deffont, - sizeof(text_prop[i].font) - 1); - text_prop[i].font[sizeof(text_prop[i].font) - 1] = '\0'; - } - } - } - for (i = 0; i < DIM(text_prop); i++) { - im->text_prop[i].size = text_prop[i].size; - strcpy(im->text_prop[i].font, text_prop[i].font); - } + + } + void rrd_graph_options( int argc, char *argv[], @@ -4123,13 +4129,11 @@ void rrd_graph_options( for (propidx = sindex; propidx < TEXT_PROP_LAST; propidx++) { if (size > 0) { - im->text_prop[propidx].size = size; + rrd_set_font_desc(im,propidx,NULL,size); } if ((int) strlen(optarg) > end) { if (optarg[end] == ':') { - strncpy(im->text_prop[propidx].font, - optarg + end + 1, 255); - im->text_prop[propidx].font[255] = '\0'; + rrd_set_font_desc(im,propidx,optarg + end + 1,0); } else { rrd_set_error ("expected : after font size in '%s'", @@ -4212,6 +4216,11 @@ void rrd_graph_options( return; } } + + pango_cairo_context_set_font_options(pango_layout_get_context(im->layout), im->font_options); + pango_layout_context_changed(im->layout); + + if (im->logarithmic && im->minval <= 0) { rrd_set_error diff --git a/src/rrd_graph.h b/src/rrd_graph.h index 2b1c05b..fefa982 100644 --- a/src/rrd_graph.h +++ b/src/rrd_graph.h @@ -65,7 +65,8 @@ enum text_prop_en { TEXT_PROP_DEFAULT = 0, /* default settings */ TEXT_PROP_TITLE, /* properties for the title */ TEXT_PROP_AXIS, /* for the numbers next to the axis */ TEXT_PROP_UNIT, /* for the vertical unit description */ - TEXT_PROP_LEGEND, /* fot the legend below the graph */ + TEXT_PROP_LEGEND, /* for the legend below the graph */ + TEXT_PROP_WATERMARK, /* for the little text to the side of the graph */ TEXT_PROP_LAST }; @@ -87,6 +88,7 @@ typedef struct gfx_color_t { typedef struct text_prop_t { double size; char font[1024]; + PangoFontDescription *font_desc; } text_prop_t; @@ -243,7 +245,7 @@ typedef struct image_desc_t { cairo_t *cr; /* drawin context */ cairo_font_options_t *font_options; /* cairo font options */ cairo_antialias_t graph_antialias; /* antialiasing for the graph */ - + PangoLayout *layout; /* the pango layout we use for writing fonts */ rrd_info_t *grinfo; /* root pointer to extra graph info */ rrd_info_t *grinfo_current; /* pointing to current entry */ } image_desc_t; @@ -338,6 +340,7 @@ int scan_for_col( char *const); void rrd_graph_init( image_desc_t *); + void rrd_graph_options( int, char **, @@ -417,8 +420,7 @@ void gfx_text( double x, double y, gfx_color_t color, - char *font, - double size, + PangoFontDescription *font_desc, double tabwidth, double angle, enum gfx_h_align_en h_align, @@ -429,8 +431,7 @@ void gfx_text( double gfx_get_text_width( image_desc_t *im, double start, - char *font, - double size, + PangoFontDescription *font_desc, double tabwidth, char *text); @@ -454,5 +455,4 @@ void gfx_area_fit( void grinfo_push( image_desc_t *im, char *key, - rrd_info_type_t type, - rrd_infoval_t value); + rrd_info_type_t type, rrd_infoval_t value); diff --git a/src/rrd_graph_helper.c b/src/rrd_graph_helper.c index d570e58..be85b9f 100644 --- a/src/rrd_graph_helper.c +++ b/src/rrd_graph_helper.c @@ -516,10 +516,10 @@ int rrd_parse_textalign( } -/* Parsing of PART, VRULE, HRULE, LINE, AREA, STACK and TICK +/* Parsing of VRULE, HRULE, LINE, AREA, STACK and TICK ** is done in one function. ** -** Stacking PART, VRULE, HRULE or TICK is not allowed. +** Stacking VRULE, HRULE or TICK is not allowed. ** ** If a number (which is valid to enter) is more than a ** certain amount of characters, it is caught as an error. @@ -541,18 +541,12 @@ int rrd_parse_PVHLAST( float one_space = gfx_get_text_width(im, 0, im-> text_prop[TEXT_PROP_LEGEND]. - font, - im-> - text_prop[TEXT_PROP_LEGEND]. - size, + font_desc, im->tabwidth, " ") / 4.0; float target_space = gfx_get_text_width(im, 0, im-> text_prop - [TEXT_PROP_LEGEND].font, - im-> - text_prop - [TEXT_PROP_LEGEND].size, + [TEXT_PROP_LEGEND].font_desc, im->tabwidth, "oo"); spacecnt = target_space / one_space; @@ -739,7 +733,7 @@ int rrd_parse_PVHLAST( } (*eaten)++; /* after colon */ - /* PART, HRULE, VRULE and TICK cannot be stacked. */ + /* HRULE, VRULE and TICK cannot be stacked. */ if ((gdp->gf != GF_HRULE) && (gdp->gf != GF_VRULE) && (gdp->gf != GF_TICK)) { -- 2.11.0