diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index eeff31c41ca33db51c06eb9737ac97a7ca156c9c..d783a358609d68465555b4e31ff6a10485a9ab21 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
/****************************************************************************
/****************************************************************************
- * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010
+ * RRDtool 1.4.8 Copyright by Tobi Oetiker, 1997-2013
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
,
{3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, "Week %V"}
,
,
{3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, "Week %V"}
,
- {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600,
- "Week %V"}
+ {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600, "Week %V"}
,
{6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
"%b"}
,
{6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
"%b"}
if (im->daemon_addr != NULL)
free(im->daemon_addr);
if (im->daemon_addr != NULL)
free(im->daemon_addr);
+ if (im->gdef_map){
+ g_hash_table_destroy(im->gdef_map);
+ }
+
+ if (im->rrd_map){
+ g_hash_table_destroy(im->rrd_map);
+ }
+
for (i = 0; i < (unsigned) im->gdes_c; i++) {
if (im->gdes[i].data_first) {
/* careful here, because a single pointer can occur several times */
for (i = 0; i < (unsigned) im->gdes_c; i++) {
if (im->gdes[i].data_first) {
/* careful here, because a single pointer can occur several times */
free(im->gdes[i].rpnp);
}
free(im->gdes);
free(im->gdes[i].rpnp);
}
free(im->gdes);
+
+ for (i = 0; i < DIM(text_prop);i++){
+ pango_font_description_free(im->text_prop[i].font_desc);
+ im->text_prop[i].font_desc = NULL;
+ }
+
if (im->font_options)
cairo_font_options_destroy(im->font_options);
if (im->font_options)
cairo_font_options_destroy(im->font_options);
status = cairo_status(im->cr);
cairo_destroy(im->cr);
}
status = cairo_status(im->cr);
cairo_destroy(im->cr);
}
+
+
if (im->rendered_image) {
free(im->rendered_image);
}
if (im->rendered_image) {
free(im->rendered_image);
}
}
}
}
}
+/* power prefixes */
static char si_symbol[] = {
static char si_symbol[] = {
+ 'y', /* 10e-24 Yocto */
+ 'z', /* 10e-21 Zepto */
'a', /* 10e-18 Atto */
'f', /* 10e-15 Femto */
'p', /* 10e-12 Pico */
'a', /* 10e-18 Atto */
'f', /* 10e-15 Femto */
'p', /* 10e-12 Pico */
'T', /* 10e12 Tera */
'P', /* 10e15 Peta */
'E', /* 10e18 Exa */
'T', /* 10e12 Tera */
'P', /* 10e15 Peta */
'E', /* 10e18 Exa */
+ 'Z', /* 10e21 Zeta */
+ 'Y' /* 10e24 Yotta */
};
};
-static const int si_symbcenter = 6;
+static const int si_symbcenter = 8;
/* find SI magnitude symbol for the numbers on the y-axis*/
void si_unit(
/* find SI magnitude symbol for the numbers on the y-axis*/
void si_unit(
image_desc_t *im)
{
int i, ii;
image_desc_t *im)
{
int i, ii;
- int skip;
/* pull the data from the rrd files ... */
for (i = 0; i < (int) im->gdes_c; i++) {
/* pull the data from the rrd files ... */
for (i = 0; i < (int) im->gdes_c; i++) {
if (im->gdes[i].gf != GF_DEF)
continue;
if (im->gdes[i].gf != GF_DEF)
continue;
- skip = 0;
/* do we have it already ? */
/* do we have it already ? */
- for (ii = 0; ii < i; ii++) {
- if (im->gdes[ii].gf != GF_DEF)
- continue;
- if ((strcmp(im->gdes[i].rrd, im->gdes[ii].rrd) == 0)
- && (im->gdes[i].cf == im->gdes[ii].cf)
- && (im->gdes[i].cf_reduce == im->gdes[ii].cf_reduce)
- && (im->gdes[i].start_orig == im->gdes[ii].start_orig)
- && (im->gdes[i].end_orig == im->gdes[ii].end_orig)
- && (im->gdes[i].step_orig == im->gdes[ii].step_orig)) {
- /* OK, the data is already there.
- ** Just copy the header portion
- */
- im->gdes[i].start = im->gdes[ii].start;
- im->gdes[i].end = im->gdes[ii].end;
- im->gdes[i].step = im->gdes[ii].step;
- im->gdes[i].ds_cnt = im->gdes[ii].ds_cnt;
- im->gdes[i].ds_namv = im->gdes[ii].ds_namv;
- im->gdes[i].data = im->gdes[ii].data;
- im->gdes[i].data_first = 0;
- skip = 1;
- }
- if (skip)
- break;
- }
- if (!skip) {
+ gpointer value;
+ char *key = gdes_fetch_key(im->gdes[i]);
+ gboolean ok = g_hash_table_lookup_extended(im->rrd_map,key,NULL,&value);
+ free(key);
+ if (ok){
+ ii = GPOINTER_TO_INT(value);
+ im->gdes[i].start = im->gdes[ii].start;
+ im->gdes[i].end = im->gdes[ii].end;
+ im->gdes[i].step = im->gdes[ii].step;
+ im->gdes[i].ds_cnt = im->gdes[ii].ds_cnt;
+ im->gdes[i].ds_namv = im->gdes[ii].ds_namv;
+ im->gdes[i].data = im->gdes[ii].data;
+ im->gdes[i].data_first = 0;
+ } else {
unsigned long ft_step = im->gdes[i].step; /* ft_step will record what we got from fetch */
/* Flush the file if
unsigned long ft_step = im->gdes[i].step; /* ft_step will record what we got from fetch */
/* Flush the file if
}
im->gdes[i].data_first = 1;
}
im->gdes[i].data_first = 1;
+ /* must reduce to at least im->step
+ otherwhise we end up with more data than we can handle in the
+ chart and visibility of data will be random */
+ im->gdes[i].step = max(im->gdes[i].step,im->step);
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
ft_step,
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
ft_step,
image_desc_t *im,
char *key)
{
image_desc_t *im,
char *key)
{
- long ii;
-
- for (ii = 0; ii < im->gdes_c - 1; ii++) {
- if ((im->gdes[ii].gf == GF_DEF
- || im->gdes[ii].gf == GF_VDEF || im->gdes[ii].gf == GF_CDEF)
- && (strcmp(im->gdes[ii].vname, key) == 0)) {
- return ii;
- }
+ long match = -1;
+ gpointer value;
+ gboolean ok = g_hash_table_lookup_extended(im->gdef_map,key,NULL,&value);
+ if (ok){
+ match = GPOINTER_TO_INT(value);
}
}
- return -1;
+
+ /* printf("%s -> %ld\n",key,match); */
+
+ return match;
}
/* find the greatest common divisor for all the numbers
}
/* find the greatest common divisor for all the numbers
/* GF_TICK: the data values are not
** relevant for min and max
*/
/* GF_TICK: the data values are not
** relevant for min and max
*/
- if (finite(paintval) && im->gdes[ii].gf != GF_TICK) {
+ if (finite(paintval) && im->gdes[ii].gf != GF_TICK && !im->gdes[ii].skipscale) {
if ((isnan(minval) || paintval < minval) &&
!(im->logarithmic && paintval <= 0.0))
minval = paintval;
if ((isnan(minval) || paintval < minval) &&
!(im->logarithmic && paintval <= 0.0))
minval = paintval;
if (first_weekday == -1){
#ifdef HAVE__NL_TIME_WEEK_1STDAY
/* according to http://sourceware.org/ml/libc-locales/2009-q1/msg00011.html */
if (first_weekday == -1){
#ifdef HAVE__NL_TIME_WEEK_1STDAY
/* according to http://sourceware.org/ml/libc-locales/2009-q1/msg00011.html */
+ /* See correct way here http://pasky.or.cz/dev/glibc/first_weekday.c */
+ first_weekday = nl_langinfo (_NL_TIME_FIRST_WEEKDAY)[0];
+ int week_1stday;
long week_1stday_l = (long) nl_langinfo (_NL_TIME_WEEK_1STDAY);
long week_1stday_l = (long) nl_langinfo (_NL_TIME_WEEK_1STDAY);
- if (week_1stday_l == 19971130) first_weekday = 0; /* Sun */
- else if (week_1stday_l == 19971201) first_weekday = 1; /* Mon */
- else first_weekday = 1; /* we go for a monday default */
+ if (week_1stday_l == 19971130) week_1stday = 0; /* Sun */
+ else if (week_1stday_l == 19971201) week_1stday = 1; /* Mon */
+ else
+ {
+ first_weekday = 1;
+ return first_weekday; /* we go for a monday default */
+ }
+ first_weekday=(week_1stday + first_weekday - 1) % 7;
#else
first_weekday = 1;
#endif
#else
first_weekday = 1;
#endif
struct tm tm;
localtime_r(&start, &tm);
struct tm tm;
localtime_r(&start, &tm);
+ /* let mktime figure this dst on its own */
+ tm.tm_isdst = -1;
switch (baseint) {
case TMT_SECOND:
switch (baseint) {
case TMT_SECOND:
time_t madetime;
localtime_r(¤t, &tm);
time_t madetime;
localtime_r(¤t, &tm);
+ /* let mktime figure this dst on its own */
+ tm.tm_isdst = -1;
+ int limit = 2;
+ switch (baseint) {
+ case TMT_SECOND: limit = 7200; break;
+ case TMT_MINUTE: limit = 120; break;
+ case TMT_HOUR: limit = 2; break;
+ default: limit = 2; break;
+ }
do {
switch (baseint) {
case TMT_SECOND:
do {
switch (baseint) {
case TMT_SECOND:
tm. tm_year += basestep;
}
madetime = mktime(&tm);
tm. tm_year += basestep;
}
madetime = mktime(&tm);
- } while (madetime == -1); /* this is necessary to skip impssible times
+ } while (madetime == -1 && limit-- >= 0); /* this is necessary to skip impossible times
like the daylight saving time skips */
return madetime;
like the daylight saving time skips */
return madetime;
}
} /* prepare printval */
}
} /* prepare printval */
- if ((percent_s = strstr(im->gdes[i].format, "%S")) != NULL) {
+ if (!im->gdes[i].strftm && (percent_s = strstr(im->gdes[i].format, "%S")) != NULL) {
/* Magfact is set to -1 upon entry to print_calc. If it
* is still less than 0, then we need to run auto_scale.
* Otherwise, put the value into the correct units. If
/* Magfact is set to -1 upon entry to print_calc. If it
* is still less than 0, then we need to run auto_scale.
* Otherwise, put the value into the correct units. If
printval /= magfact;
}
*(++percent_s) = 's';
printval /= magfact;
}
*(++percent_s) = 's';
- } else if (strstr(im->gdes[i].format, "%s") != NULL) {
+ } else if (!im->gdes[i].strftm && strstr(im->gdes[i].format, "%s") != NULL) {
auto_scale(im, &printval, &si_symb, &magfact);
}
auto_scale(im, &printval, &si_symb, &magfact);
}
int leg_c = 0;
double leg_x = border;
int leg_y = 0; //im->yimg;
int leg_c = 0;
double leg_x = border;
int leg_y = 0; //im->yimg;
- int leg_y_prev = 0; // im->yimg;
int leg_cc;
double glue = 0;
int i, ii, mark = 0;
int leg_cc;
double glue = 0;
int i, ii, mark = 0;
prt_fctn != 'j' &&
prt_fctn != 'c' &&
prt_fctn != 'u' &&
prt_fctn != 'j' &&
prt_fctn != 'c' &&
prt_fctn != 'u' &&
+ prt_fctn != '.' &&
prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
free(legspace);
rrd_set_error
prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
free(legspace);
rrd_set_error
if (prt_fctn == 'n') {
prt_fctn = 'l';
}
if (prt_fctn == 'n') {
prt_fctn = 'l';
}
+ /* \. is a null operation to allow strings ending in \x */
+ if (prt_fctn == '.') {
+ prt_fctn = '\0';
+ }
/* remove exess space from the end of the legend for \g */
while (prt_fctn == 'g' &&
/* remove exess space from the end of the legend for \g */
while (prt_fctn == 'g' &&
glue = 0;
}
if (prt_fctn == 'c')
glue = 0;
}
if (prt_fctn == 'c')
- leg_x = (double)(legendwidth - fill) / 2.0;
+ leg_x = border + (double)(legendwidth - fill) / 2.0;
if (prt_fctn == 'r')
leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
if (prt_fctn == 'r')
leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
+(double)legspace[ii]
+ glue;
}
+(double)legspace[ii]
+ glue;
}
- leg_y_prev = leg_y;
if (leg_x > border || prt_fctn == 's')
leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
if (prt_fctn == 's')
if (leg_x > border || prt_fctn == 's')
leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
if (prt_fctn == 's')
}
}
else {
}
}
else {
- sprintf(graph_label_right,im->second_axis_format,sval);
+ sprintf(graph_label_right,im->second_axis_format,sval,"");
}
gfx_text ( im,
X1+7, Y0,
}
gfx_text ( im,
X1+7, Y0,
}
}
else {
}
}
else {
- sprintf(graph_label_right,im->second_axis_format,sval);
+ sprintf(graph_label_right,im->second_axis_format,sval,"");
}
gfx_text ( im,
}
gfx_text ( im,
mgridtm,
im->xlab_user.
mgridst);
mgridtm,
im->xlab_user.
mgridst);
- ti < im->end;
+ ti < im->end && ti != -1;
ti =
find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst)
) {
/* are we inside the graph ? */
if (ti < im->start || ti > im->end)
continue;
ti =
find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst)
) {
/* are we inside the graph ? */
if (ti < im->start || ti > im->end)
continue;
- while (timajor < ti) {
+ while (timajor < ti && timajor != -1) {
timajor = find_next_time(timajor,
im->
xlab_user.
mgridtm, im->xlab_user.mgridst);
}
timajor = find_next_time(timajor,
im->
xlab_user.
mgridtm, im->xlab_user.mgridst);
}
+ if (timajor == -1) break; /* fail in case of problems with time increments */
if (ti == timajor)
continue; /* skip as falls on major grid line */
X0 = xtr(im, ti);
if (ti == timajor)
continue; /* skip as falls on major grid line */
X0 = xtr(im, ti);
im->
xlab_user.
mgridst);
im->
xlab_user.
mgridst);
- ti < im->end;
+ ti < im->end && ti != -1;
ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst)
) {
/* are we inside the graph ? */
ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst)
) {
/* are we inside the graph ? */
labtm,
im->xlab_user.
labst);
labtm,
im->xlab_user.
labst);
- ti <=
+ (ti <=
im->end -
im->end -
- im->xlab_user.precis / 2;
+ im->xlab_user.precis / 2) && ti != -1;
ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst)
) {
tilab = ti + im->xlab_user.precis / 2; /* correct time for the label */
ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst)
) {
tilab = ti + im->xlab_user.precis / 2; /* correct time for the label */
im->ximg = im->xsize;
im->yimg = im->ysize;
im->yorigin = im->ysize;
im->ximg = im->xsize;
im->yimg = im->ysize;
im->yorigin = im->ysize;
+ xtr(im, 0);
ytr(im, DNAN);
return 0;
}
ytr(im, DNAN);
return 0;
}
}
else{
// we have no title; get a little clearing from the top
}
else{
// we have no title; get a little clearing from the top
- Ytitle = 1.5 * Yspacing;
+ Ytitle = Yspacing;
}
if (elements) {
}
if (elements) {
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- Ymain -= Yspacing;
+ Ymain -= 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
}
if (im->watermark[0] != '\0') {
}
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
}
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- im->yimg += Yspacing;
+ im->yimg += 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
}
if (im->watermark[0] != '\0') {
*/
switch(im->legendposition){
case NORTH:
*/
switch(im->legendposition){
case NORTH:
- im->xOriginTitle = Xvertical + Xylabel + (im->xsize / 2);
+ im->xOriginTitle = (im->ximg / 2);
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case WEST:
break;
case WEST:
- im->xOriginTitle = im->legendwidth + Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->legendwidth + im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case SOUTH:
break;
case SOUTH:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->ximg / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case EAST:
break;
case EAST:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
im->yOriginTitle = 0;
im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
}
break;
case GF_LINE:
}
break;
case GF_LINE:
- case GF_AREA:
- /* fix data points at oo and -oo */
+ case GF_AREA: {
+ rrd_value_t diffval = im->maxval - im->minval;
+ rrd_value_t maxlimit = im->maxval + 9 * diffval;
+ rrd_value_t minlimit = im->minval - 9 * diffval;
for (ii = 0; ii < im->xsize; ii++) {
for (ii = 0; ii < im->xsize; ii++) {
+ /* fix data points at oo and -oo */
if (isinf(im->gdes[i].p_data[ii])) {
if (im->gdes[i].p_data[ii] > 0) {
im->gdes[i].p_data[ii] = im->maxval;
} else {
im->gdes[i].p_data[ii] = im->minval;
}
if (isinf(im->gdes[i].p_data[ii])) {
if (im->gdes[i].p_data[ii] > 0) {
im->gdes[i].p_data[ii] = im->maxval;
} else {
im->gdes[i].p_data[ii] = im->minval;
}
-
+ }
+ /* some versions of cairo go unstable when trying
+ to draw way out of the canvas ... lets not even try */
+ if (im->gdes[i].p_data[ii] > maxlimit) {
+ im->gdes[i].p_data[ii] = maxlimit;
+ }
+ if (im->gdes[i].p_data[ii] < minlimit) {
+ im->gdes[i].p_data[ii] = minlimit;
}
} /* for */
}
} /* for */
}
lastgdes = &(im->gdes[i]);
break;
}
lastgdes = &(im->gdes[i]);
break;
+ } /* GF_AREA, GF_LINE, GF_GRAD */
case GF_STACK:
rrd_set_error
("STACK should already be turned into LINE or AREA here");
case GF_STACK:
rrd_set_error
("STACK should already be turned into LINE or AREA here");
im->gdes[im->gdes_c - 1].step = im->step;
im->gdes[im->gdes_c - 1].step_orig = im->step;
im->gdes[im->gdes_c - 1].stack = 0;
im->gdes[im->gdes_c - 1].step = im->step;
im->gdes[im->gdes_c - 1].step_orig = im->step;
im->gdes[im->gdes_c - 1].stack = 0;
+ im->gdes[im->gdes_c - 1].skipscale = 0;
im->gdes[im->gdes_c - 1].linewidth = 0;
im->gdes[im->gdes_c - 1].debug = 0;
im->gdes[im->gdes_c - 1].start = im->start;
im->gdes[im->gdes_c - 1].linewidth = 0;
im->gdes[im->gdes_c - 1].debug = 0;
im->gdes[im->gdes_c - 1].start = im->start;
char *old_locale;
rrd_graph_init(&im);
/* a dummy surface so that we can measure text sizes for placements */
char *old_locale;
rrd_graph_init(&im);
/* a dummy surface so that we can measure text sizes for placements */
- old_locale = setlocale(LC_NUMERIC, "C");
+ old_locale = setlocale(LC_NUMERIC, NULL);
+ setlocale(LC_NUMERIC, "C");
rrd_graph_options(argc, argv, &im);
if (rrd_test_error()) {
rrd_info_free(im.grinfo);
rrd_graph_options(argc, argv, &im);
if (rrd_test_error()) {
rrd_info_free(im.grinfo);
if (font){
strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1);
im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0';
if (font){
strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1);
im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0';
+ /* if we already got one, drop it first */
+ pango_font_description_free(im->text_prop[prop].font_desc);
im->text_prop[prop].font_desc = pango_font_description_from_string( font );
};
if (size > 0){
im->text_prop[prop].font_desc = pango_font_description_from_string( font );
};
if (size > 0){
#ifdef HAVE_TZSET
tzset();
#endif
#ifdef HAVE_TZSET
tzset();
#endif
-
+ im->gdef_map = g_hash_table_new_full(g_str_hash, g_str_equal,g_free,NULL);
+ im->rrd_map = g_hash_table_new_full(g_str_hash, g_str_equal,g_free,NULL);
im->base = 1000;
im->daemon_addr = NULL;
im->draw_x_grid = 1;
im->base = 1000;
im->daemon_addr = NULL;
im->draw_x_grid = 1;
im->maxval = DNAN;
im->minval = 0;
im->minval = DNAN;
im->maxval = DNAN;
im->minval = 0;
im->minval = DNAN;
+ im->magfact = 1;
im->prt_c = 0;
im->rigid = 0;
im->rendered_image_size = 0;
im->prt_c = 0;
im->rigid = 0;
im->rendered_image_size = 0;
for (i = 0; i < DIM(text_prop); i++) {
im->text_prop[i].size = -1;
for (i = 0; i < DIM(text_prop); i++) {
im->text_prop[i].size = -1;
+ im->text_prop[i].font_desc = NULL;
rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size);
}
rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size);
}
pango_cairo_update_context(im->cr,context);
im->layout = pango_layout_new(context);
pango_cairo_update_context(im->cr,context);
im->layout = pango_layout_new(context);
+ g_object_unref (context);
// im->layout = pango_cairo_create_layout(im->cr);
// im->layout = pango_cairo_create_layout(im->cr);