,
{60, 0, TMT_MINUTE, 30, TMT_HOUR, 2, TMT_HOUR, 2, 0, "%H:%M"}
,
- {60, 24 * 3600, TMT_MINUTE, 30, TMT_HOUR, 2, TMT_HOUR, 4, 0, "%a %H:%M"}
+ {60, 24 * 3600, TMT_MINUTE, 30, TMT_HOUR, 2, TMT_HOUR, 6, 0, "%a %H:%M"}
,
{180, 0, TMT_HOUR, 1, TMT_HOUR, 6, TMT_HOUR, 6, 0, "%H:%M"}
,
free(im->gdes[i].ds_namv);
}
}
+ /* free allocated memory used for dashed lines */
+ if (im->gdes[i].p_dashes != NULL)
+ free(im->gdes[i].p_dashes);
+
free(im->gdes[i].p_data);
free(im->gdes[i].rpnp);
}
if (im->surface)
cairo_surface_destroy(im->surface);
if (status)
- fprintf(stderr, "OOPS: Cairo has issuesm it can't even die: %s\n",
+ fprintf(stderr, "OOPS: Cairo has issues it can't even die: %s\n",
cairo_status_to_string(status));
return 0;
return 0;
}
+static int AlmostEqual2sComplement(
+ float A,
+ float B,
+ int maxUlps)
+{
+
+ int aInt = *(int *) &A;
+ int bInt = *(int *) &B;
+ int intDiff;
+
+ /* Make sure maxUlps is non-negative and small enough that the
+ default NAN won't compare as equal to anything. */
+
+ /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
+
+ /* Make aInt lexicographically ordered as a twos-complement int */
+
+ if (aInt < 0)
+ aInt = 0x80000000l - aInt;
+
+ /* Make bInt lexicographically ordered as a twos-complement int */
+
+ if (bInt < 0)
+ bInt = 0x80000000l - bInt;
+
+ intDiff = abs(aInt - bInt);
+
+ if (intDiff <= maxUlps)
+ return 1;
+
+ return 0;
+}
+
/* massage data so, that we get one value for each x coordinate in the graph */
int data_proc(
image_desc_t *im)
}
/* adjust min and max values */
+ /* for logscale we add something on top */
if (isnan(im->minval)
- /* don't adjust low-end with log scale *//* why not? */
|| ((!im->rigid) && im->minval > minval)
) {
if (im->logarithmic)
else
im->maxval = maxval;
}
+
/* make sure min is smaller than max */
if (im->minval > im->maxval) {
- im->minval = 0.99 * im->maxval;
+ if (im->minval > 0)
+ im->minval = 0.99 * im->maxval;
+ else
+ im->minval = 1.01 * im->maxval;
}
/* make sure min and max are not equal */
- if (im->minval == im->maxval) {
- im->maxval *= 1.01;
- if (!im->logarithmic) {
- im->minval *= 0.99;
- }
+ if (AlmostEqual2sComplement(im->minval, im->maxval, 4)) {
+ if (im->maxval > 0)
+ im->maxval *= 1.01;
+ else
+ im->maxval *= 0.99;
+
/* make sure min and max are not both zero */
- if (im->maxval == 0.0) {
+ if (AlmostEqual2sComplement(im->maxval, 0, 4)) {
im->maxval = 1.0;
}
}
/* yes we are loosing precision by doing tos with floats instead of doubles
but it seems more stable this way. */
-static int AlmostEqual2sComplement(
- float A,
- float B,
- int maxUlps)
-{
-
- int aInt = *(int *) &A;
- int bInt = *(int *) &B;
- int intDiff;
-
- /* Make sure maxUlps is non-negative and small enough that the
- default NAN won't compare as equal to anything. */
-
- /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
-
- /* Make aInt lexicographically ordered as a twos-complement int */
-
- if (aInt < 0)
- aInt = 0x80000000l - aInt;
-
- /* Make bInt lexicographically ordered as a twos-complement int */
-
- if (bInt < 0)
- bInt = 0x80000000l - bInt;
-
- intDiff = abs(aInt - bInt);
-
- if (intDiff <= maxUlps)
- return 1;
-
- return 0;
-}
/* logaritmic horizontal grid */
int horizontal_log_grid(
im->graph_col[GRC_FRAME].green,
im->graph_col[GRC_FRAME].blue,
im->graph_col[GRC_FRAME].alpha);
+ if (im->gdes[i].dash) {
+ // make box borders in legend dashed if the graph is dashed
+ double dashes[] = { 3.0 };
+ cairo_set_dash(im->cr, dashes, 1, 0.0);
+ }
cairo_stroke(im->cr);
cairo_restore(im->cr);
}
break;
};
im->cr = cairo_create(im->surface);
- pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(font_map), 100);
cairo_set_antialias(im->cr, im->graph_antialias);
cairo_scale(im->cr, im->zoom, im->zoom);
+ pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(font_map), 100);
gfx_new_area(im,
0, 0,
cairo_new_path(im->cr);
cairo_set_line_width(im->cr, im->gdes[i].linewidth);
+
+ if (im->gdes[i].dash) {
+ cairo_set_dash(im->cr, im->gdes[i].p_dashes,
+ im->gdes[i].ndash, im->gdes[i].offset);
+ }
+
for (ii = 1; ii < im->xsize; ii++) {
if (isnan(im->gdes[i].p_data[ii])
|| (im->slopemode == 1
cairo_restore(im->cr);
} else {
int idxI = -1;
- double *foreY = malloc(sizeof(double) * im->xsize * 2);
- double *foreX = malloc(sizeof(double) * im->xsize * 2);
- double *backY = malloc(sizeof(double) * im->xsize * 2);
- double *backX = malloc(sizeof(double) * im->xsize * 2);
+ double *foreY =
+ (double *) malloc(sizeof(double) * im->xsize * 2);
+ double *foreX =
+ (double *) malloc(sizeof(double) * im->xsize * 2);
+ double *backY =
+ (double *) malloc(sizeof(double) * im->xsize * 2);
+ double *backX =
+ (double *) malloc(sizeof(double) * im->xsize * 2);
int drawem = 0;
for (ii = 0; ii <= im->xsize; ii++) {
case GF_HRULE:
if (im->gdes[i].yrule >= im->minval
&& im->gdes[i].yrule <= im->maxval)
- gfx_line(im,
- im->xorigin, ytr(im, im->gdes[i].yrule),
- im->xorigin + im->xsize, ytr(im,
- im->gdes[i].yrule),
- 1.0, im->gdes[i].col);
+ cairo_save(im->cr);
+ if (im->gdes[i].dash) {
+ cairo_set_dash(im->cr, im->gdes[i].p_dashes,
+ im->gdes[i].ndash, im->gdes[i].offset);
+ }
+ gfx_line(im,
+ im->xorigin, ytr(im, im->gdes[i].yrule),
+ im->xorigin + im->xsize, ytr(im,
+ im->gdes[i].yrule),
+ 1.0, im->gdes[i].col);
+ cairo_stroke(im->cr);
+ cairo_restore(im->cr);
break;
case GF_VRULE:
if (im->gdes[i].xrule >= im->start
&& im->gdes[i].xrule <= im->end)
- 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);
+ cairo_save(im->cr);
+ if (im->gdes[i].dash) {
+ cairo_set_dash(im->cr, im->gdes[i].p_dashes,
+ im->gdes[i].ndash, im->gdes[i].offset);
+ }
+ 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);
+ cairo_stroke(im->cr);
+ cairo_restore(im->cr);
break;
default:
break;
im->gdes[im->gdes_c - 1].data_first = 0;
im->gdes[im->gdes_c - 1].p_data = NULL;
im->gdes[im->gdes_c - 1].rpnp = NULL;
+ im->gdes[im->gdes_c - 1].p_dashes = NULL;
im->gdes[im->gdes_c - 1].shift = 0.0;
+ im->gdes[im->gdes_c - 1].dash = 0;
+ im->gdes[im->gdes_c - 1].ndash = 0;
+ im->gdes[im->gdes_c - 1].offset = 0;
im->gdes[im->gdes_c - 1].col.red = 0.0;
im->gdes[im->gdes_c - 1].col.green = 0.0;
im->gdes[im->gdes_c - 1].col.blue = 0.0;
im->gdes[im->gdes_c - 1].ds = -1;
im->gdes[im->gdes_c - 1].cf_reduce = CF_AVERAGE;
im->gdes[im->gdes_c - 1].cf = CF_AVERAGE;
- im->gdes[im->gdes_c - 1].p_data = NULL;
im->gdes[im->gdes_c - 1].yrule = DNAN;
im->gdes[im->gdes_c - 1].xrule = 0;
return 0;
case 'n':{
char prop[15];
double size = 1;
- char font[1024] = "";
+ int end;
old_locale = setlocale(LC_NUMERIC, "C");
- if (sscanf(optarg, "%10[A-Z]:%lf:%1000s", prop, &size, font) >= 2) {
+ if (sscanf(optarg, "%10[A-Z]:%lf%n", prop, &size, &end) >= 2) {
int sindex, propidx;
setlocale(LC_NUMERIC, old_locale);
if (size > 0) {
im->text_prop[propidx].size = size;
}
- if (strlen(font) > 0) {
- strcpy(im->text_prop[propidx].font, font);
+ if (strlen(prop) > end) {
+ if (prop[end] == ':') {
+ strncpy(im->text_prop[propidx].font,
+ prop + end + 1, 255);
+ im->text_prop[propidx].font[255] = '\0';
+ } else {
+ rrd_set_error
+ ("expected after font size in '%s'",
+ prop);
+ return;
+ }
}
if (propidx == sindex && sindex != 0)
break;
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum * src->step;
dst->vf.when = 0; /* no time component */
- } else if (dst->vf.op == VDEF_AVERAGE){
+ } else if (dst->vf.op == VDEF_AVERAGE) {
dst->vf.val = sum / cnt;
dst->vf.when = 0; /* no time component */
} else {
average = sum / cnt;
sum = 0.0;
- for (step=0;step<steps;step++) {
- if (finite(data[step*src->ds_cnt])) {
- sum += pow((data[step*src->ds_cnt] - average),2.0);
+ for (step = 0; step < steps; step++) {
+ if (finite(data[step * src->ds_cnt])) {
+ sum += pow((data[step * src->ds_cnt] - average), 2.0);
};
}
- dst->vf.val = pow(sum / cnt,0.5);
- dst->vf.when = 0; /* no time component */
+ dst->vf.val = pow(sum / cnt, 0.5);
+ dst->vf.when = 0; /* no time component */
};
} else {
dst->vf.val = DNAN;