|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
patch to do vertical gradientsSomebody on the irc channel suggested that I post this patch here. The
patch is against rrdtool 1.3.8. This adds the GRAD element, which acts more or less like an AREA, except you can specify a second color and a height which is used to create a gradient from one color to the next. I also attached an example graph that uses this patch. The gradients in it are generated with these commands: GRAD:ips#4444ff:half\\ firewall\\ states GRAD:Bin#00cc00#0099441f:0:incoming\\ bandwidth The syntax is vname-or-value[#color[#color:gradientheight][:legend]][:STACK] if the second color is missing, it is assumed to be #00000000 and the gradientheight defaults to 50 gradientheight can actually produce 3 kinds of results depending on its value: gradientheight > 0 generates a fixed-height gradient from the data point down. (fire style) gradientheight < 0 generates a fixed-height gradient from the 0 line to the data point. (fixed style) gradientheight == 0 generates a gradient that is stretched from the data point to the 0 line. this is what the example image is using. I would appreciate any comments or suggestions. -- rian [grad.patch] diff -crB rrdtool-1.3.8/src/rrd_gfx.c ../rrdtool-1.3.8/src/rrd_gfx.c *** rrdtool-1.3.8/src/rrd_gfx.c Tue May 19 07:45:05 2009 --- ../rrdtool-1.3.8/src/rrd_gfx.c Thu Nov 5 10:17:01 2009 *************** *** 105,110 **** --- 106,147 ---- cairo_line_to(cr, x, y); } + /* add a point to a line or to an area */ + void gfx_add_rect_fadey( + image_desc_t *im, + double x1,double y1, + double x2,double y2, + double py, + gfx_color_t color1, + gfx_color_t color2, + double height) + { + cairo_t *cr = im->cr; + + cairo_new_path(cr); + gfx_area_fit(im, &x1, &y1); + gfx_area_fit(im, &x2, &y2); + cairo_line_to(cr, x1, y1); + cairo_line_to(cr, x1, y2); + cairo_line_to(cr, x2, y2); + cairo_line_to(cr, x2, y1); + cairo_close_path(cr); + cairo_pattern_t* p; + if (height < 0) { + p = cairo_pattern_create_linear(x1,y1,x2,y1+height); + } else if (height > 0) { + p = cairo_pattern_create_linear(x1,(y2+py)/2+height,x2,(y2+py)/2); + } else { + p = cairo_pattern_create_linear(x1,y1,x2,(y2+py)/2); + } + //cairo_pattern_t* p = cairo_pattern_create_linear(x1,py+50,x2,py); + cairo_pattern_add_color_stop_rgba(p, 1, color1.red,color1.green,color1.blue,color1.alpha); + cairo_pattern_add_color_stop_rgba(p, 0, color2.red,color2.green,color2.blue,color2.alpha); + cairo_set_source(cr, p); + cairo_pattern_destroy(p); + cairo_fill(cr); + } + void gfx_close_path( image_desc_t *im) { diff -crB rrdtool-1.3.8/src/rrd_graph.c ../rrdtool-1.3.8/src/rrd_graph.c *** rrdtool-1.3.8/src/rrd_graph.c Tue May 19 07:45:05 2009 --- ../rrdtool-1.3.8/src/rrd_graph.c Thu Nov 5 10:19:45 2009 *************** *** 227,232 **** --- 227,233 ---- conv_if(VRULE, GF_VRULE); conv_if(LINE, GF_LINE); conv_if(AREA, GF_AREA); + conv_if(GRAD, GF_GRAD); conv_if(STACK, GF_STACK); conv_if(TICK, GF_TICK); conv_if(TEXTALIGN, GF_TEXTALIGN); *************** *** 1176,1182 **** /* memory for the processed data */ for (i = 0; i < im->gdes_c; i++) { if ((im->gdes[i].gf == GF_LINE) || ! (im->gdes[i].gf == GF_AREA) || (im->gdes[i].gf == GF_TICK)) { if ((im->gdes[i].p_data = (rrd_value_t*)(malloc((im->xsize + 1) * sizeof(rrd_value_t)))) == NULL) { rrd_set_error("malloc data_proc"); --- 1177,1185 ---- /* memory for the processed data */ for (i = 0; i < im->gdes_c; i++) { if ((im->gdes[i].gf == GF_LINE) || ! (im->gdes[i].gf == GF_AREA) || ! (im->gdes[i].gf == GF_GRAD) || ! (im->gdes[i].gf == GF_TICK)) { if ((im->gdes[i].p_data = (rrd_value_t*)(malloc((im->xsize + 1) * sizeof(rrd_value_t)))) == NULL) { rrd_set_error("malloc data_proc"); *************** *** 1197,1202 **** --- 1200,1206 ---- switch (im->gdes[ii].gf) { case GF_LINE: case GF_AREA: + case GF_GRAD: case GF_TICK: if (!im->gdes[ii].stack) paintval = 0.0; *************** *** 1576,1581 **** --- 1580,1586 ---- break; case GF_LINE: case GF_AREA: + case GF_GRAD: case GF_TICK: graphelement = 1; break; *************** *** 3208,3213 **** --- 3213,3219 ---- break; case GF_LINE: case GF_AREA: + case GF_GRAD: /* fix data points at oo and -oo */ for (ii = 0; ii < im->xsize; ii++) { if (isinf(im->gdes[i].p_data[ii])) { *************** *** 3306,3311 **** --- 3312,3319 ---- cairo_stroke(im->cr); cairo_restore(im->cr); } else { + double lastx=0; + double lasty=0; int idxI = -1; double *foreY = (double *) malloc(sizeof(double) * im->xsize * 2); *************** *** 3336,3347 **** [cntI + 1], 4)) { cntI++; } ! gfx_new_area(im, ! backX[0], backY[0], ! foreX[0], foreY[0], ! foreX[cntI], ! foreY[cntI], im->gdes[i].col); ! while (cntI < idxI) { lastI = cntI; cntI++; while (cntI < idxI --- 3344,3360 ---- [cntI + 1], 4)) { cntI++; } ! if (im->gdes[i].gf != GF_GRAD) { ! gfx_new_area(im, ! backX[0], backY[0], ! foreX[0], foreY[0], ! foreX[cntI], ! foreY[cntI], im->gdes[i].col); ! } else { ! lastx = foreX[cntI]; ! lasty = foreY[cntI]; ! } ! while (cntI < idxI) { lastI = cntI; cntI++; while (cntI < idxI *************** *** 3357,3365 **** + 1], 4)) { cntI++; } ! gfx_add_point(im, foreX[cntI], foreY[cntI]); } ! gfx_add_point(im, backX[idxI], backY[idxI]); while (idxI > 1) { lastI = idxI; idxI--; --- 3370,3401 ---- + 1], 4)) { cntI++; } ! if (im->gdes[i].gf != GF_GRAD) { ! gfx_add_point(im, foreX[cntI], foreY[cntI]); ! } else { ! gfx_add_rect_fadey(im, ! lastx, foreY[0], ! foreX[cntI], foreY[cntI], lasty, ! im->gdes[i].col, ! im->gdes[i].col2, ! im->gdes[i].gradheight ! ); ! lastx = foreX[cntI]; ! lasty = foreY[cntI]; ! } } ! if (im->gdes[i].gf != GF_GRAD) { ! gfx_add_point(im, backX[idxI], backY[idxI]); ! } else { ! gfx_add_rect_fadey(im, ! lastx, foreY[0], ! backX[idxI], backY[idxI], lasty, ! im->gdes[i].col, ! im->gdes[i].col2, ! im->gdes[i].gradheight); ! lastx = backX[idxI]; ! lasty = backY[idxI]; ! } while (idxI > 1) { lastI = idxI; idxI--; *************** *** 3376,3386 **** - 1], 4)) { idxI--; } ! gfx_add_point(im, backX[idxI], backY[idxI]); } idxI = -1; drawem = 0; ! gfx_close_path(im); } if (drawem != 0) { drawem = 0; --- 3412,3434 ---- - 1], 4)) { idxI--; } ! if (im->gdes[i].gf != GF_GRAD) { ! gfx_add_point(im, backX[idxI], backY[idxI]); ! } else { ! gfx_add_rect_fadey(im, ! lastx, foreY[0], ! backX[idxI], backY[idxI], lasty, ! im->gdes[i].col, ! im->gdes[i].col2, ! im->gdes[i].gradheight); ! lastx = backX[idxI]; ! lasty = backY[idxI]; ! } } idxI = -1; drawem = 0; ! if (im->gdes[i].gf != GF_GRAD) ! gfx_close_path(im); } if (drawem != 0) { drawem = 0; *************** *** 3574,3579 **** --- 3622,3632 ---- 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].col.alpha = 0.0; + im->gdes[im->gdes_c - 1].col2.red = 0.0; + im->gdes[im->gdes_c - 1].col2.green = 0.0; + im->gdes[im->gdes_c - 1].col2.blue = 0.0; + im->gdes[im->gdes_c - 1].col2.alpha = 0.0; + im->gdes[im->gdes_c - 1].gradheight = 50.0; im->gdes[im->gdes_c - 1].legend[0] = '\0'; im->gdes[im->gdes_c - 1].format[0] = '\0'; im->gdes[im->gdes_c - 1].strftm = 0; diff -crB rrdtool-1.3.8/src/rrd_graph.h ../rrdtool-1.3.8/src/rrd_graph.h *** rrdtool-1.3.8/src/rrd_graph.h Fri Dec 26 01:05:03 2008 --- ../rrdtool-1.3.8/src/rrd_graph.h Thu Nov 5 10:36:52 2009 *************** *** 51,57 **** #define GRIDWIDTH 0.4 enum gf_en { GF_PRINT = 0, GF_GPRINT, GF_COMMENT, GF_HRULE, GF_VRULE, GF_LINE, ! GF_AREA, GF_STACK, GF_TICK, GF_TEXTALIGN, GF_DEF, GF_CDEF, GF_VDEF, GF_SHIFT, GF_XPORT }; --- 51,57 ---- #define GRIDWIDTH 0.4 enum gf_en { GF_PRINT = 0, GF_GPRINT, GF_COMMENT, GF_HRULE, GF_VRULE, GF_LINE, ! GF_AREA,GF_GRAD, GF_STACK, GF_TICK, GF_TEXTALIGN, GF_DEF, GF_CDEF, GF_VDEF, GF_SHIFT, GF_XPORT }; *************** *** 156,162 **** long ds; /* data source number */ enum cf_en cf; /* consolidation function */ enum cf_en cf_reduce; /* consolidation function for reduce_data() */ ! struct gfx_color_t col; /* graph color */ char format[FMT_LEG_LEN + 5]; /* format for PRINT AND GPRINT */ char legend[FMT_LEG_LEN + 5]; /* legend */ int strftm; /* should the VDEF legend be formated with strftime */ --- 156,163 ---- long ds; /* data source number */ enum cf_en cf; /* consolidation function */ enum cf_en cf_reduce; /* consolidation function for reduce_data() */ ! struct gfx_color_t col, col2; /* graph color */ ! double gradheight; char format[FMT_LEG_LEN + 5]; /* format for PRINT AND GPRINT */ char legend[FMT_LEG_LEN + 5]; /* legend */ int strftm; /* should the VDEF legend be formated with strftime */ *************** *** 424,429 **** --- 425,449 ---- double x, double y); + /* create a rect that has a gradient from color1 to color2 in height pixels + * height > 0: + * gradient starts at top and goes down a fixed number of pixels (fire style) + * height < 0: + * gradient starts at bottom and goes up a fixed number of pixels (constant style) + * height == 0: + * gradient is stretched between two points + */ + void gfx_add_rect_fadey( + image_desc_t *im, + double x1,double y1, + double x2,double y2, + double py, + gfx_color_t color1, + gfx_color_t color2, + double height); + + + /* close current path so it ends at the same point as it started */ void gfx_close_path( image_desc_t *im); diff -crB rrdtool-1.3.8/src/rrd_graph_helper.c ../rrdtool-1.3.8/src/rrd_graph_helper.c *** rrdtool-1.3.8/src/rrd_graph_helper.c Tue May 19 07:45:05 2009 --- ../rrdtool-1.3.8/src/rrd_graph_helper.c Thu Nov 5 10:38:27 2009 *************** *** 532,538 **** graph_desc_t *const gdp, image_desc_t *const im) { ! int i, j, k; int colorfound = 0; char tmpstr[MAX_VNAME_LEN + 10]; /* vname#RRGGBBAA\0 */ static int spacecnt = 0; --- 532,538 ---- graph_desc_t *const gdp, image_desc_t *const im) { ! int i, j, k, j2; int colorfound = 0; char tmpstr[MAX_VNAME_LEN + 10]; /* vname#RRGGBBAA\0 */ static int spacecnt = 0; *************** *** 567,576 **** rrd_set_error("Cannot parse line '%s'", line); return 1; } ! ! j = i; while (j > 0 && tmpstr[j] != '#') j--; if (j) { tmpstr[j] = '\0'; --- 567,588 ---- rrd_set_error("Cannot parse line '%s'", line); return 1; } ! ! j = i; while (j > 0 && tmpstr[j] != '#') j--; + //see if there is a second color + j2 = j-1; + while (j2 > 0 && tmpstr[j2] != '#') + j2--; + if (j && j2) { //yes, swap j and j2, so that j is first color, j2 is second + int tmp = j; + j = j2; + j2 = tmp; + tmpstr[j2] = '\0'; + } else { + j2 = 0; + } if (j) { tmpstr[j] = '\0'; *************** *** 578,585 **** /* We now have: * tmpstr[0] containing vname * tmpstr[j] if j!=0 then containing color ! * i size of vname + color * j if j!=0 then size of vname */ /* Number or vname ? --- 590,599 ---- /* We now have: * tmpstr[0] containing vname * tmpstr[j] if j!=0 then containing color ! * tmpstr[j2] if j2!=0 then containing second color ! * i size of vname * j if j!=0 then size of vname + * j2 if j2!=0 then size of vname + first color */ /* Number or vname ? *************** *** 644,649 **** --- 658,690 ---- dprintf("- parsed color %0.0f,%0.0f,%0.0f,%0.0f\n", gdp->col.red, gdp->col.green, gdp->col.blue, gdp->col.alpha); colorfound = 1; + if (j2) { //second color? + j2++; + dprintf("- examining second color '%s'\n", &tmpstr[j2]); + //TODO: maybe rrd_parse_color should take a pointer to gdp->col instead of gdp + struct gfx_color_t firstcol = gdp->col; + if (rrd_parse_color(&tmpstr[j2], gdp)) { + rrd_set_error("Could not parse color in '%s'", &tmpstr[j2]); + return 1; + } + dprintf("- parsed color %0.0f,%0.0f,%0.0f,%0.0f\n", gdp->col.red, + gdp->col.green, gdp->col.blue, gdp->col.alpha); + gdp->col2 = gdp->col; + gdp->col = firstcol; + //we now have a mandatory grid height + (*eaten) += i; + if (line[*eaten] != '\0') { + (*eaten)++; + } + dprintf("- examining gradient height\n"); + i = scan_for_col(&line[*eaten], MAX_VNAME_LEN + 9, tmpstr); + sscanf(tmpstr, "%lf%n", &gdp->gradheight, &j); + if (i != j) { + rrd_set_error("Could not parse gradient height in '%s'", tmpstr); + return 1; + } + dprintf("- parsed gradientheight %0.0f\n", gdp->gradheight); + } } else { dprintf("- no color present in '%s'\n", tmpstr); } *************** *** 1113,1118 **** --- 1154,1160 ---- case GF_HRULE: /* value#color[:legend] */ case GF_LINE: /* vname-or-value[#color[:legend]][:STACK] */ case GF_AREA: /* vname-or-value[#color[:legend]][:STACK] */ + case GF_GRAD: /* vname-or-value[#color[:legend][#color[:gradientheight]]][:STACK] */ case GF_TICK: /* vname#color[:num[:legend]] */ if (rrd_parse_PVHLAST(argv[i], &eaten, gdp, im)) return; *************** *** 1122,1128 **** case GF_STACK: /* vname-or-value[#color[:legend]] */ if (rrd_parse_PVHLAST(argv[i], &eaten, gdp, im)) return; ! if (last_gf == GF_LINE || last_gf == GF_AREA) { gdp->gf = last_gf; gdp->linewidth = last_linewidth; } else { --- 1164,1170 ---- case GF_STACK: /* vname-or-value[#color[:legend]] */ if (rrd_parse_PVHLAST(argv[i], &eaten, gdp, im)) return; ! if (last_gf == GF_LINE || last_gf == GF_AREA || last_gf == GF_GRAD) { gdp->gf = last_gf; gdp->linewidth = last_linewidth; } else { _______________________________________________ rrd-developers mailing list rrd-developers@... https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers |
|
|
|
|
|
Re: patch to do vertical gradientsThis time i remembered to attach the patch :D
> thanks for this ... it looks cool ... quersion though, is there > some information carying capability in this feature ? Not really. For the most part, I wanted to add some control over how the AREA's were drawn, especially when you have two of them on the same graph that keep covering one another, it makes it easier for the eye to pick out the two graphs, as opposed to simply using an alpha, which gives a solid color that can be mis-interpreted as another graph. I also wanted the ability to make it so that peak values could be highlighted in a different color if desired, as in a cpu graph going from green through yellow to red. I haven't thought about making it carry information, although it might be neat to show temporal distribution of an average value (ie, turn the dataset on its side, and make it represent color instead of displacement). I don't really know how to get into that, since all I've played with so far is the drawing code. > > can you please also add a patch for the documentation ? Hopefully the attached patch will suffice. -- rian [grad_doc.patch] diff -crB rrdtool-1.3.8/doc/rrdgraph_graph.pod ../rrdtool-1.3.8/doc/rrdgraph_graph.pod *** rrdtool-1.3.8/doc/rrdgraph_graph.pod Sat Feb 21 02:43:58 2009 --- ../rrdtool-1.3.8/doc/rrdgraph_graph.pod Thu Nov 5 12:23:08 2009 *************** *** 262,267 **** --- 262,275 ---- See B<LINE>, however the area between the x-axis and the line will be filled. + =head3 B<GRAD>B<:>I<value>[B<#>I<color1>[B<#>I<color2>B<:>I<height>][B<:>[I<legend>][B<:STACK>]] + + Similar to B<AREA>, except the area between the line and the x-axis will contain a gradient from color1 to color2. + + The I<height> parameter can create three different behaviors. If I<height> > 0, then the gradient is a fixed height, starting at the line going down. If I<height> < 0, then the gradient starts at fixed height above the x-axis, going down to the x-axis. If I<height> == 0, then the gradient goes from the line to x-axis. + + If not present, I<color2> defaults to #00000000 and I<height> defaults to 50. + =head3 B<TICK>B<:>I<vname>B<#>I<rrggbb>[I<aa>][B<:>I<fraction>[B<:>I<legend>]] Plot a tick mark (a vertical line) for each value of I<vname> that is _______________________________________________ rrd-developers mailing list rrd-developers@... https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers |
|
|
Re: patch to do vertical gradientsHi Rian,
Today Rian Shelley wrote: > This time i remembered to attach the patch :D > > > > thanks for this ... it looks cool ... quersion though, is there > > some information carying capability in this feature ? > > Not really. For the most part, I wanted to add some control over how > the AREA's were drawn, especially when you have two of them on the > same graph that keep covering one another, it makes it easier for the > eye to pick out the two graphs, as opposed to simply using an alpha, > which gives a solid color that can be mis-interpreted as another > graph. > > I also wanted the ability to make it so that peak values could be > highlighted in a different color if desired, as in a cpu graph going > from green through yellow to red. > > I haven't thought about making it carry information, although it might > be neat to show temporal distribution of an average value (ie, turn > the dataset on its side, and make it represent color instead of > displacement). I don't really know how to get into that, since all > I've played with so far is the drawing code. > > > > > can you please also add a patch for the documentation ? > > Hopefully the attached patch will suffice. great ... thanks very much tobi > > > -- > rian > -- Tobi Oetiker, OETIKER+PARTNER AG, Aarweg 15 CH-4600 Olten, Switzerland http://it.oetiker.ch tobi@... ++41 62 775 9902 / sb: -9900 _______________________________________________ rrd-developers mailing list rrd-developers@... https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers |
|
|
Re: patch to do vertical gradientsTobias Oetiker wrote:
>>> thanks for this ... it looks cool ... quersion though, is there >>> some information carying capability in this feature ? >>> If it was used to carry information, one that might help would be scale differences. I have had issues in the past where my boss at the time freaked out when a graph spiked and we had to point out that the one he was looking at had spiked from bits to kbits... not from mbits to gbits. ;-) A way to color the scale in the area (logarithmically?) would help when scanning graphs quickly. It wouldn't give the same cool fire effect but "ripples" in the area paint could effectively replace the need for grid lines. I'd also recommend that the default second color be set to the graph background color with the transparency set to 0x20 and not be forced to #000000. Might as well make it do something cool by default no matter what color scheme they use. Also, I'm jealous of Rian because I've been wanting to write this patch for like 5-6 years and never had the time. ;-) It looks even better than I hoped. I'm looking forward to this being in the main build. --mark _______________________________________________ rrd-developers mailing list rrd-developers@... https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers |
|
|
Re: patch to do vertical gradientsOn Fri, Nov 6, 2009 at 7:20 AM, Mark Mills <extremely@...> wrote:
> If it was used to carry information, one that might help would be scale > differences. I have had issues in the past where my boss at the time > freaked out when a graph spiked and we had to point out that the one he > was looking at had spiked from bits to kbits... not from mbits to gbits. > ;-) A way to color the scale in the area (logarithmically?) would help > when scanning graphs quickly. It wouldn't give the same cool fire effect > but "ripples" in the area paint could effectively replace the need for > grid lines. Thats one of the reasons I wrote it. A negative height would be aligned to the x axis, so that increasing values on the line change to the next color, ie a gradient from green to red. Of course, to be really useful, I would need to change it so that the height was relative to the data set, and not given in pixels. I'll have to see how to do that. gfx_area_fit maybe? > I'd also recommend that the default second color be set to the graph > background color with the transparency set to 0x20 and not be forced to > #000000. Might as well make it do something cool by default no matter > what color scheme they use. Maybe. I figured it didn't matter much what the color was if the alpha was zero. That way it always appeared to fade into whatever is behind it, be it the background or another AREA. I'll have to play with it and see what it looks like. > Also, I'm jealous of Rian because I've been wanting to write this patch > for like 5-6 years and never had the time. ;-) It looks even better than > I hoped. I'm looking forward to this being in the main build. All the heavy lifting is done by cairo :D. All I did was allow the source pattern to be a gradient as well as a solid color. I think the other option is to make the source pattern another image. -- rian _______________________________________________ rrd-developers mailing list rrd-developers@... https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers |
| Free embeddable forum powered by Nabble | Forum Help |