Hi Melchior, cool ... looking at your sample graphs it seems that the watermark at the bottom of the graph is runing into the labeling ...
http://mrab.de/wp-content/uploads/go_all_w___.png Also your patch lacks a patch for doc/rrdgrah.pod I will be glad to integrate an updated version. cheers tobi Feb 9 Melchior Rabe wrote: > Hello together, > > at the moment the legend section is placed below the graph. This is in > the most cases fine as the time axis gets a much space as possible. But > I want to graph data that is a set of stacked values (up to 25) and also > want to print some informational numbers into the legend. In that case I > find it more convinient placing the legend on the side of the graph > (Possibly that might be also nice for the pie chart function...). I > created a patch that is introducing two new options: > --legend-position north|south|west|east (default: south) > --legend-direction topdown|bottomup (default: topdown) > > The first option decides where the legend is placed and the second can > be used to reverse the vertical order of the legend items. In a stack > the first item (AREA, LINEx) is the bottommost and the following is > stacked on top of it. The legend is placed in the same sequence. That > means that the first item and the next one is placed (after a line > break) below the preceeding ones. So the graph is stacked bottomup while > the legend is "stacked" topdown. The --legend-direction is reversing the > vertical order of the legend items. > > > Some not so nice (but IMHO acceptable) side effects: > > - Placing the legend on the side will result in a very wide graph with > all items in one line (as long as there is no manual line break > inserted). So the user has to take care for the line breaks. I think > that is acceptable, as any other solution I thought of (giving the width > of the legend or defining some ratio between legend and graph) was > leading to more parameters. > > - Placing the legend items bottomup might lead to an incomplete first > line, because only the vertical alignment is inverted, but not the > sequence of the items e.g. like that: > > topdown legend: > first second third > forth fifth sixth > seventh > > will lead to bottomup: > seventh > forth fifth sixth > first second third > > The patch is tested on WinXP32, but as there is only some painting > affected I do not expect any problems on other systems. I wrote a short > description with some example images (http://mrab.de/?p=64) and placed > the patch below also in a zip at > http://mrab.de/wp-content/uploads/rrdtool_patch_legend-position.zip > > Any comments, hints and tips are appreciated! > > Cheers, > > Melchior > > Patch for rrd_graph.h > ----------------------- BEGIN ---------------------------------------- > Index: rrd_graph.h > =================================================================== > --- rrd_graph.h (revision 1746) > +++ rrd_graph.h (working copy) > @@ -81,6 +81,8 @@ > TEXT_PROP_LAST > }; > > +enum legend_pos{ NORTH = 0, WEST, SOUTH, EAST }; > +enum legend_direction { TOP_DOWN = 0, BOTTOM_UP }; > > enum gfx_if_en { IF_PNG = 0, IF_SVG, IF_EPS, IF_PDF }; > enum gfx_en { GFX_LINE = 0, GFX_AREA, GFX_TEXT }; > @@ -231,6 +233,8 @@ > reasonable probablility that the > existing one is out of date */ > int slopemode; /* connect the dots of the curve directly, not > using a stair */ > + legend_pos legendposition; /* the position of the legend: north, west, > south or east */ > + legend_direction legenddirection; /* The direction of the legend topdown > or bottomup */ > int logarithmic; /* scale the yaxis logarithmic */ > double force_scale_min; /* Force a scale--min */ > double force_scale_max; /* Force a scale--max */ > @@ -238,7 +242,12 @@ > /* status information */ > int with_markup; > long xorigin, yorigin; /* where is (0,0) of the graph */ > + long xOriginTitle, yOriginTitle; /* where is the origin of the > title */ > + long xOriginLegendY, yOriginLegendY; /* where is the origin of the > y legend */ > + long xOriginLegendY2, yOriginLegendY2; /* where is the origin of > the second y legend */ > + long xOriginLegend, yOriginLegend; /* where is the origin of the > legend */ > long ximg, yimg; /* total size of the image */ > + long legendwidth, legendheight; /* the calculated height and width > of the legend */ > size_t rendered_image_size; > double zoom; > double magfact; /* numerical magnitude */ > ----------------------- END ---------------------------------------- > > Patch for rrd_graph.c > ----------------------- BEGIN ---------------------------------------- > Index: rrd_graph.c > =================================================================== > --- rrd_graph.c (revision 1746) > +++ rrd_graph.c (working copy) > @@ -1613,26 +1613,37 @@ > } > > > + > /* place legends with color spots */ > int leg_place( > image_desc_t *im, > - int *gY) > + bool calc_width) > { > /* graph labels */ > int interleg = im->text_prop[TEXT_PROP_LEGEND].size * 2.0; > int border = im->text_prop[TEXT_PROP_LEGEND].size * 2.0; > int fill = 0, fill_last; > + double legendwidth; // = im->ximg - 2 * border; > int leg_c = 0; > double leg_x = border; > - int leg_y = im->yimg; > - int leg_y_prev = im->yimg; > + int leg_y = 0; //im->yimg; > + int leg_y_prev = 0; // im->yimg; > int leg_cc; > double glue = 0; > int i, ii, mark = 0; > char default_txtalign = TXA_JUSTIFIED; /*default line orientation */ > int *legspace; > char *tab; > + char saved_legend[FMT_LEG_LEN + 5]; > > + if(calc_width){ > + legendwidth = 0; > + } > + else{ > + legendwidth = im->legendwidth - 2 * border; > + } > + > + > if (!(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH)) { > if ((legspace = (int*)(malloc(im->gdes_c * sizeof(int)))) == NULL) { > rrd_set_error("malloc for legspace"); > @@ -1641,6 +1652,10 @@ > > for (i = 0; i < im->gdes_c; i++) { > char prt_fctn; /*special printfunctions */ > + if(calc_width){ > + strcpy(saved_legend, im->gdes[i].legend); > + } > + > fill_last = fill; > /* hide legends for rules which are not displayed */ > if (im->gdes[i].gf == GF_TEXTALIGN) { > @@ -1663,6 +1678,7 @@ > memmove(tab, tab + 1, strlen(tab)); > tab[0] = (char) 9; > } > + > leg_cc = strlen(im->gdes[i].legend); > /* is there a controle code at the end of the legend string ? */ > if (leg_cc >= 2 && im->gdes[i].legend[leg_cc - 2] == '\\') { > @@ -1721,7 +1737,10 @@ > } > > if (prt_fctn == '\0') { > - if (i == im->gdes_c - 1 || fill > im->ximg - 2 * border) { > + if(calc_width && (fill > legendwidth)){ > + legendwidth = fill; > + } > + if (i == im->gdes_c - 1 || fill > legendwidth) { > /* just one legend item is left right or center */ > switch (default_txtalign) { > case TXA_RIGHT: > @@ -1739,7 +1758,7 @@ > } > } > /* is it time to place the legends ? */ > - if (fill > im->ximg - 2 * border) { > + if (fill > legendwidth) { > if (leg_c > 1) { > /* go back one */ > i--; > @@ -1752,23 +1771,22 @@ > } > } > > - > if (prt_fctn != '\0') { > leg_x = border; > if (leg_c >= 2 && prt_fctn == 'j') { > - glue = (double)(im->ximg - fill - 2 * border) / > (double)(leg_c - 1); > + glue = (double)(legendwidth - fill) / (double)(leg_c - > 1); > } else { > glue = 0; > } > if (prt_fctn == 'c') > - leg_x = (double)(im->ximg - fill) / 2.0; > + leg_x = (double)(legendwidth - fill) / 2.0; > if (prt_fctn == 'r') > - leg_x = im->ximg - fill - border; > + leg_x = legendwidth - fill - border; > for (ii = mark; ii <= i; ii++) { > if (im->gdes[ii].legend[0] == '\0') > continue; /* skip empty legends */ > im->gdes[ii].leg_x = leg_x; > - im->gdes[ii].leg_y = leg_y; > + im->gdes[ii].leg_y = leg_y + border; > leg_x += > (double)gfx_get_text_width(im, leg_x, > im-> > @@ -1784,27 +1802,26 @@ > leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8; > if (prt_fctn == 's') > leg_y -= im->text_prop[TEXT_PROP_LEGEND].size; > + > + if(calc_width && (fill > legendwidth)){ > + legendwidth = fill; > + } > fill = 0; > leg_c = 0; > mark = ii; > } > - } > > - if (im->extra_flags & FULL_SIZE_MODE) { > - /* now for some backpaddeling. We have to shift up all the > - legend items into the graph and tell the caller about the > - space we used up. */ > - long shift_up = leg_y - im->yimg - > im->text_prop[TEXT_PROP_LEGEND].size * 1.8 + border * 0.7; > - for (i = 0; i < im->gdes_c; i++) { > - im->gdes[i].leg_y -= shift_up; > + if(calc_width){ > + strcpy(im->gdes[i].legend, saved_legend); > } > - im->yorigin = im->yorigin - leg_y + im->yimg - > im->text_prop[TEXT_PROP_LEGEND].size * 1.8 - border; > - *gY = im->yorigin; > - } else { > - im->yimg = > - leg_y - im->text_prop[TEXT_PROP_LEGEND].size * 1.8 + > - border * 0.6; > } > + > + if(calc_width){ > + im->legendwidth = legendwidth + 2 * border; > + } > + else{ > + im->legendheight = leg_y + border * 0.6; > + } > free(legspace); > } > return 0; > @@ -2590,24 +2607,20 @@ > /* yaxis unit description */ > if (im->ylegend[0] != '\0'){ > gfx_text(im, > - 10, > - (im->yorigin - > - im->ysize / 2), > + im->xOriginLegendY+10, > + im->yOriginLegendY, > im->graph_col[GRC_FONT], > im-> > text_prop[TEXT_PROP_UNIT]. > font_desc, > im->tabwidth, > RRDGRAPH_YLEGEND_ANGLE, GFX_H_CENTER, GFX_V_CENTER, > im->ylegend); > + > } > if (im->second_axis_legend[0] != '\0'){ > - double Xylabel=gfx_get_text_width(im, 0, > - im->text_prop[TEXT_PROP_AXIS].font_desc, > - im->tabwidth, > - "0") * im->unitslength > - + im->text_prop[TEXT_PROP_UNIT].size *2; > gfx_text( im, > - im->xorigin+im->xsize+Xylabel+8, (im->yorigin - > im->ysize/2), > + im->xOriginLegendY2+10, > + im->yOriginLegendY2, > im->graph_col[GRC_FONT], > im->text_prop[TEXT_PROP_UNIT].font_desc, > im->tabwidth, > @@ -2618,7 +2631,7 @@ > > /* graph title */ > gfx_text(im, > - im->ximg / 2, 6, > + im->xOriginTitle, im->yOriginTitle+6, > im->graph_col[GRC_FONT], > im-> > text_prop[TEXT_PROP_TITLE]. > @@ -2628,7 +2641,8 @@ > if (!(im->extra_flags & NO_RRDTOOL_TAG)){ > water_color = im->graph_col[GRC_FONT]; > water_color.alpha = 0.3; > - gfx_text(im, im->ximg - 4, 5, > + double xpos = im->legendposition == EAST ? im->xOriginLegendY : > im->ximg - 4; > + gfx_text(im, xpos, 5, > water_color, > im-> > text_prop[TEXT_PROP_WATERMARK]. > @@ -2652,8 +2666,8 @@ > if (im->gdes[i].legend[0] == '\0') > continue; > /* im->gdes[i].leg_y is the bottom of the legend */ > - X0 = im->gdes[i].leg_x; > - Y0 = im->gdes[i].leg_y; > + X0 = im->xOriginLegend + im->gdes[i].leg_x; > + Y0 = im->legenddirection == TOP_DOWN ? im->yOriginLegend + > im->gdes[i].leg_y : im->yOriginLegend + im->legendheight - im->gdes[i].leg_y; > gfx_text(im, X0, Y0, > im->graph_col[GRC_FONT], > im-> > @@ -2770,22 +2784,12 @@ > /* The actual size of the image to draw is determined from > ** several sources. The size given on the command line is > ** the graph area but we need more as we have to draw labels > - ** and other things outside the graph area > + ** and other things outside the graph area. If the option > + ** --full-size-mode is selected the size defines the total > + ** image size and the size available for the graph is > + ** calculated. > */ > > - int Xvertical = 0, Ytitle = > - 0, Xylabel = 0, Xmain = 0, Ymain = > - 0, Yxlabel = 0, Xspacing = 15, Yspacing = 15, Ywatermark = 4; > - > - if (im->extra_flags & ONLY_GRAPH) { > - im->xorigin = 0; > - im->ximg = im->xsize; > - im->yimg = im->ysize; > - im->yorigin = im->ysize; > - ytr(im, DNAN); > - return 0; > - } > - > /** +---+-----------------------------------+ > ** | y |...............graph title.........| > ** | +---+-------------------------------+ > @@ -2806,10 +2810,33 @@ > ** +---------------------------------------+ > */ > > + int Xvertical = 0, Xvertical2 = 0, Ytitle = > + 0, Xylabel = 0, Xmain = 0, Ymain = > + 0, Yxlabel = 0, Xspacing = 15, Yspacing = 15, Ywatermark = 4; > + > + // no legends and no the shall be plotted it's easy > + if (im->extra_flags & ONLY_GRAPH) { > + im->xorigin = 0; > + im->ximg = im->xsize; > + im->yimg = im->ysize; > + im->yorigin = im->ysize; > + ytr(im, DNAN); > + return 0; > + } > + > + // calculate the width of the left vertical legend > if (im->ylegend[0] != '\0') { > Xvertical = im->text_prop[TEXT_PROP_UNIT].size * 2; > } > > + // calculate the width of the right vertical legend > + if (im->second_axis_legend[0] != '\0') { > + Xvertical2 = im->text_prop[TEXT_PROP_UNIT].size * 2; > + } > + else{ > + Xvertical2 = Xspacing; > + } > + > if (im->title[0] != '\0') { > /* The title is placed "inbetween" two text lines so it > ** automatically has some vertical spacing. The horizontal > @@ -2818,92 +2845,112 @@ > /* if necessary, reduce the font size of the title until it fits the > image width */ > Ytitle = im->text_prop[TEXT_PROP_TITLE].size * 2.6 + 10; > } > + else{ > + // we have no title; get a little clearing from the top > + Ytitle = 1.5 * Yspacing; > + } > > if (elements) { > if (im->draw_x_grid) { > + // calculate the height of the horizontal labelling > Yxlabel = im->text_prop[TEXT_PROP_AXIS].size * 2.5; > } > if (im->draw_y_grid || im->forceleftspace) { > + // calculate the width of the vertical labelling > Xylabel = > gfx_get_text_width(im, 0, > - im-> > - text_prop > - [TEXT_PROP_AXIS]. > - font_desc, > + im->text_prop[TEXT_PROP_AXIS].font_desc, > im->tabwidth, "0") * im->unitslength; > } > } > > + // add some space to the labelling > + Xylabel += Xspacing; > + > + /* If the legend is printed besides the graph the width has to be > + ** calculated first. Placing the legend north or south of the > + ** graph requires the width calculation first, so the legend is > + ** skipped for the moment. > + */ > + im->legendheight = 0; > + im->legendwidth = 0; > + if (!(im->extra_flags & NOLEGEND)) { > + if(im->legendposition == WEST || im->legendposition == EAST){ > + if (leg_place(im, true) == -1){ > + return -1; > + } > + } > + } > + > if (im->extra_flags & FULL_SIZE_MODE) { > + > /* The actual size of the image to draw has been determined by the > user. > ** The graph area is the space remaining after accounting for the > legend, > ** the watermark, the axis labels, and the title. > */ > - im->xorigin = 0; > im->ximg = im->xsize; > im->yimg = im->ysize; > - im->yorigin = im->ysize; > Xmain = im->ximg; > Ymain = im->yimg; > + > /* Now calculate the total size. Insert some spacing where > desired. im->xorigin and im->yorigin need to correspond > with the lower left corner of the main graph area or, if > this one is not set, the imaginary box surrounding the > pie chart area. */ > /* Initial size calculation for the main graph area */ > - Xmain = im->ximg - Xylabel - 3 * Xspacing; > > - im->xorigin = Xspacing + Xylabel; > - > - if (Xvertical) { /* unit description */ > - Xmain -= Xvertical; > - im->xorigin += Xvertical; > + Xmain -= Xylabel;// + Xspacing; > + if((im->legendposition == WEST || im->legendposition == EAST) && > !(im->extra_flags & NOLEGEND) ){ > + Xmain -= im->legendwidth;// + Xspacing; > } > - > - /* adjust space for second axis */ > if (im->second_axis_scale != 0){ > - Xmain -= Xylabel + Xspacing; > + Xmain -= Xylabel; > } > - if (im->extra_flags & NO_RRDTOOL_TAG){ > - Xmain += Xspacing; > + if (!(im->extra_flags & NO_RRDTOOL_TAG)){ > + Xmain -= Xspacing; > } > - if (im->second_axis_legend[0] != '\0' ) { > - Xmain -= im->text_prop[TEXT_PROP_UNIT].size * 1.5; > + > + Xmain -= Xvertical + Xvertical2; > + > + /* limit the remaining space to 0 */ > + if(Xmain < 1){ > + Xmain = 1; > } > - > im->xsize = Xmain; > > - xtr(im, 0); > - /* The vertical size of the image is known in advance. The main > graph area > - ** (Ymain) and im->yorigin must be set according to the space > requirements > - ** of the legend and the axis labels. > - */ > - if (im->extra_flags & NOLEGEND) { > - im->yorigin = im->yimg - > - im->text_prop[TEXT_PROP_AXIS].size * 2.5 - Yspacing; > - Ymain = im->yorigin; > + /* Putting the legend north or south, the height can now be > calculated */ > + if (!(im->extra_flags & NOLEGEND)) { > + if(im->legendposition == NORTH || im->legendposition == SOUTH){ > + im->legendwidth = im->ximg; > + if (leg_place(im, false) == -1){ > + return -1; > + } > + } > } > - else { > - /* Determine where to place the legends onto the image. > - ** Set Ymain and adjust im->yorigin to match the space > requirements. > - */ > - if (leg_place(im, &Ymain) == -1) > - return -1; > + > + if( (im->legendposition == NORTH || im->legendposition == SOUTH) && > !(im->extra_flags & NOLEGEND) ){ > + Ymain -= Yxlabel + im->legendheight; > } > + else{ > + Ymain -= Yxlabel; > + } > + > + /* reserve space for the title *or* some padding above the graph */ > + Ymain -= Ytitle; > > - > - /* remove title space *or* some padding above the graph from the > main graph area */ > - if (Ytitle) { > - Ymain -= Ytitle; > - } else { > - Ymain -= 1.5 * Yspacing; > + /* reserve space for padding below the graph */ > + if (im->extra_flags & NOLEGEND) { > + Ymain -= Yspacing; > } > > - /* watermark doesn't seem to effect the vertical size of the main > graph area, oh well! */ > if (im->watermark[0] != '\0') { > Ymain -= Ywatermark; > } > - > + /* limit the remaining height to 0 */ > + if(Ymain < 1){ > + Ymain = 1; > + } > im->ysize = Ymain; > } else { /* dimension options -width and -height refer to the > dimensions of the main graph area */ > > @@ -2913,94 +2960,171 @@ > ** and other things outside the graph area. > */ > > - if (im->ylegend[0] != '\0') { > - Xvertical = im->text_prop[TEXT_PROP_UNIT].size * 2; > + if (elements) { > + Xmain = im->xsize; // + Xspacing; > + Ymain = im->ysize; > } > > - > - if (im->title[0] != '\0') { > - /* The title is placed "inbetween" two text lines so it > - ** automatically has some vertical spacing. The horizontal > - ** spacing is added here, on each side. > - */ > - /* don't care for the with of the title > - Xtitle = gfx_get_text_width(im->canvas, 0, > - im->text_prop[TEXT_PROP_TITLE].font_desc, > - im->tabwidth, > - im->title, 0) + 2*Xspacing; */ > - Ytitle = im->text_prop[TEXT_PROP_TITLE].size * 2.6 + 10; > + im->ximg = Xmain + Xylabel; > + if (!(im->extra_flags & NO_RRDTOOL_TAG)){ > + im->ximg += Xspacing; > } > > - if (elements) { > - Xmain = im->xsize; > - Ymain = im->ysize; > + if( (im->legendposition == WEST || im->legendposition == EAST) && > !(im->extra_flags & NOLEGEND) ){ > + im->ximg += im->legendwidth;// + Xspacing; > } > - /* Now calculate the total size. Insert some spacing where > - desired. im->xorigin and im->yorigin need to correspond > - with the lower left corner of the main graph area or, if > - this one is not set, the imaginary box surrounding the > - pie chart area. */ > + if (im->second_axis_scale != 0){ > + im->ximg += Xylabel; > + } > > - /* The legend width cannot yet be determined, as a result we > - ** have problems adjusting the image to it. For now, we just > - ** forget about it at all; the legend will have to fit in the > - ** size already allocated. > - */ > - im->ximg = Xylabel + Xmain + 2 * Xspacing; > + im->ximg += Xvertical + Xvertical2; > > - if (im->second_axis_scale != 0){ > - im->ximg += Xylabel + Xspacing; > + if (!(im->extra_flags & NOLEGEND)) { > + if(im->legendposition == NORTH || im->legendposition == SOUTH){ > + im->legendwidth = im->ximg; > + if (leg_place(im, false) == -1){ > + return -1; > + } > + } > } > - if (im->extra_flags & NO_RRDTOOL_TAG){ > - im->ximg -= Xspacing; > + > + im->yimg = Ymain + Yxlabel; > + if( (im->legendposition == NORTH || im->legendposition == SOUTH) && > !(im->extra_flags & NOLEGEND) ){ > + im->yimg += im->legendheight; > } > > - if (Xmain) > - im->ximg += Xspacing; > - im->xorigin = Xspacing + Xylabel; > - /* the length of the title should not influence with width of the > graph > - if (Xtitle > im->ximg) im->ximg = Xtitle; */ > - if (Xvertical) { /* unit description */ > - im->ximg += Xvertical; > - im->xorigin += Xvertical; > - } > - if (im->second_axis_legend[0] != '\0' ) { > - im->ximg += Xvertical; > - } > - > - xtr(im, 0); > - /* The vertical size is interesting... we need to compare > - ** the sum of {Ytitle, Ymain, Yxlabel, Ylegend, Ywatermark} with > - ** Yvertical however we need to know {Ytitle+Ymain+Yxlabel} > - ** in order to start even thinking about Ylegend or Ywatermark. > - ** > - ** Do it in three portions: First calculate the inner part, > - ** then do the legend, then adjust the total height of the img, > - ** adding space for a watermark if one exists; > - */ > - /* reserve space for main and/or pie */ > - im->yimg = Ymain + Yxlabel; > - im->yorigin = im->yimg - Yxlabel; > /* reserve space for the title *or* some padding above the graph */ > if (Ytitle) { > im->yimg += Ytitle; > - im->yorigin += Ytitle; > } else { > im->yimg += 1.5 * Yspacing; > - im->yorigin += 1.5 * Yspacing; > } > /* reserve space for padding below the graph */ > - im->yimg += Yspacing; > - /* Determine where to place the legends onto the image. > - ** Adjust im->yimg to match the space requirements. > - */ > - if (leg_place(im, 0) == -1) > - return -1; > + if (im->extra_flags & NOLEGEND) { > + im->yimg += Yspacing; > + } > + > if (im->watermark[0] != '\0') { > im->yimg += Ywatermark; > } > } > > + > + /* In case of putting the legend in west or east position the first > + ** legend calculation might lead to wrong positions if some items > + ** are not aligned on the left hand side (e.g. centered) as the > + ** legendwidth wight have been increased after the item was placed. > + ** In this case the positions have to be recalculated. > + */ > + if (!(im->extra_flags & NOLEGEND)) { > + if(im->legendposition == WEST || im->legendposition == EAST){ > + if (leg_place(im, false) == -1){ > + return -1; > + } > + } > + } > + > + /* After calculating all dimensions > + ** it is now possible to calculate > + ** all offsets. > + */ > + switch(im->legendposition){ > + case NORTH: > + im->xOriginTitle = Xvertical + Xylabel + (im->xsize / 2); > + im->yOriginTitle = 0; > + > + im->xOriginLegend = 0; > + im->yOriginLegend = Ytitle; > + > + im->xOriginLegendY = 0; > + im->yOriginLegendY = Ytitle + im->legendheight + (Ymain + > Yxlabel) / 2; > + > + im->xorigin = Xvertical + Xylabel; > + im->yorigin = Ytitle + im->legendheight + Ymain; > + > + im->xOriginLegendY2 = Xvertical + Xylabel + Xmain; > + if (im->second_axis_scale != 0){ > + im->xOriginLegendY2 += Xylabel; > + } > + im->yOriginLegendY2 = Ytitle + im->legendheight + (Ymain + > Yxlabel) / 2; > + > + break; > + > + case WEST: > + im->xOriginTitle = im->legendwidth + Xvertical + Xylabel + > im->xsize / 2; > + im->yOriginTitle = 0; > + > + im->xOriginLegend = 0; > + im->yOriginLegend = Ytitle; > + > + im->xOriginLegendY = im->legendwidth; > + im->yOriginLegendY = (Ytitle + Ymain + Yxlabel) / 2; > + > + im->xorigin = im->legendwidth + Xvertical + Xylabel; > + im->yorigin = Ytitle + Ymain; > + > + im->xOriginLegendY2 = im->legendwidth + Xvertical + Xylabel + > Xmain; > + if (im->second_axis_scale != 0){ > + im->xOriginLegendY2 += Xylabel; > + } > + im->yOriginLegendY2 = (Ytitle + Ymain + Yxlabel) / 2; > + > + break; > + > + case SOUTH: > + im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2; > + im->yOriginTitle = 0; > + > + im->xOriginLegend = 0; > + im->yOriginLegend = Ytitle + Ymain + Yxlabel; > + > + im->xOriginLegendY = 0; > + im->yOriginLegendY = (Ytitle + Ymain + Yxlabel) / 2; > + > + im->xorigin = Xvertical + Xylabel; > + im->yorigin = Ytitle + Ymain; > + > + im->xOriginLegendY2 = Xvertical + Xylabel + Xmain; > + if (im->second_axis_scale != 0){ > + im->xOriginLegendY2 += Xylabel; > + } > + im->yOriginLegendY2 = (Ytitle + Ymain + Yxlabel) / 2; > + > + break; > + > + case EAST: > + im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2; > + im->yOriginTitle = 0; > + > + im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2; > + if (im->second_axis_scale != 0){ > + im->xOriginLegend += Xylabel; > + } > + im->yOriginLegend = Ytitle; > + > + im->xOriginLegendY = 0; > + im->yOriginLegendY = (Ytitle + Ymain + Yxlabel) / 2; > + > + im->xorigin = Xvertical + Xylabel; > + im->yorigin = Ytitle + Ymain; > + > + im->xOriginLegendY2 = Xvertical + Xylabel + Xmain; > + if (im->second_axis_scale != 0){ > + im->xOriginLegendY2 += Xylabel; > + } > + im->yOriginLegendY2 = (Ytitle + Ymain + Yxlabel) / 2; > + > + if (!(im->extra_flags & NO_RRDTOOL_TAG)){ > + im->xOriginTitle += Xspacing; > + im->xOriginLegend += Xspacing; > + im->xOriginLegendY += Xspacing; > + im->xorigin += Xspacing; > + im->xOriginLegendY2 += Xspacing; > + } > + break; > + } > + > + xtr(im, 0); > ytr(im, DNAN); > return 0; > } > @@ -3827,6 +3951,10 @@ > im->imgformat = IF_PNG; > im->imginfo = NULL; > im->lazy = 0; > + im->legenddirection = TOP_DOWN; > + im->legendheight = 0; > + im->legendposition = SOUTH; > + im->legendwidth = 0; > im->logarithmic = 0; > im->maxval = DNAN; > im->minval = 0; > @@ -3848,6 +3976,10 @@ > im->ximg = 0; > im->xlab_user.minsec = -1; > im->xorigin = 0; > + im->xOriginLegend = 0; > + im->xOriginLegendY = 0; > + im->xOriginLegendY2 = 0; > + im->xOriginTitle = 0; > im->xsize = 400; > im->ygridstep = DNAN; > im->yimg = 0; > @@ -3857,6 +3989,10 @@ > im->second_axis_legend[0] = '\0'; > im->second_axis_format[0] = '\0'; > im->yorigin = 0; > + im->yOriginLegend = 0; > + im->yOriginLegendY = 0; > + im->yOriginLegendY2 = 0; > + im->yOriginTitle = 0; > im->ysize = 100; > im->zoom = 1; > > @@ -3941,6 +4077,8 @@ > { "lazy", no_argument, 0, 'z'}, > { "zoom", required_argument, 0, 'm'}, > { "no-legend", no_argument, 0, 'g'}, > + { "legend-position", required_argument, 0, 1005}, > + { "legend-direction", required_argument, 0, 1006}, > { "force-rules-legend", no_argument, 0, 'F'}, > { "only-graph", no_argument, 0, 'j'}, > { "alt-y-grid", no_argument, 0, 'Y'}, > @@ -4005,6 +4143,30 @@ > case 'g': > im->extra_flags |= NOLEGEND; > break; > + case 1005: > + if (strcmp(optarg, "north") == 0) { > + im->legendposition = NORTH; > + } else if (strcmp(optarg, "west") == 0) { > + im->legendposition = WEST; > + } else if (strcmp(optarg, "south") == 0) { > + im->legendposition = SOUTH; > + } else if (strcmp(optarg, "east") == 0) { > + im->legendposition = EAST; > + } else { > + rrd_set_error("unknown legend-position '%s'", optarg); > + return; > + } > + break; > + case 1006: > + if (strcmp(optarg, "topdown") == 0) { > + im->legenddirection = TOP_DOWN; > + } else if (strcmp(optarg, "bottomup") == 0) { > + im->legenddirection = BOTTOM_UP; > + } else { > + rrd_set_error("unknown legend-position '%s'", optarg); > + return; > + } > + break; > case 'F': > im->extra_flags |= FORCE_RULES_LEGEND; > break; > ----------------------- END ---------------------------------------- > > > _______________________________________________ > rrd-developers mailing list > [email protected] > https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers > > -- Tobi Oetiker, OETIKER+PARTNER AG, Aarweg 15 CH-4600 Olten, Switzerland http://it.oetiker.ch [email protected] ++41 62 775 9902 / sb: -9900 _______________________________________________ rrd-developers mailing list [email protected] https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
