Improve performance by keeping multiple pango font descriptions. For the first invoca...
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 31 Aug 2008 22:53:49 +0000 (22:53 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 31 Aug 2008 22:53:49 +0000 (22:53 +0000)
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
src/rrd_graph.c
src/rrd_graph.h
src/rrd_graph_helper.c

index 6f04135..be536c5 100644 (file)
@@ -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;
index 6f1a1ac..36dbddf 100644 (file)
 #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
index 2b1c05b..fefa982 100644 (file)
@@ -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);
index d570e58..be85b9f 100644 (file)
@@ -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)) {