From f05d58132752a83b29612c35c8972bfe3fa8abe8 Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Fri, 11 Jan 2019 16:31:30 +0100 Subject: [PATCH] sadf: SVG: Add new "customcol" option Add a new option to sadf SVG output. Entering something like "sadf -g -O customcol (...)" enables the user to select a second distinct color palette that will be used to draw the graphs. This second palette is intended to be fully customizable by the user. Signed-off-by: Sebastien GODARD --- sa.h | 17 ++++++++++ sadf.c | 5 +++ sadf_misc.c | 15 ++++++--- svg_stats.c | 96 +++++++++++++++++++++++++++++++++++------------------ 4 files changed, 95 insertions(+), 38 deletions(-) diff --git a/sa.h b/sa.h index 78107d2..fd978cc 100644 --- a/sa.h +++ b/sa.h @@ -224,6 +224,7 @@ #define K_HEIGHT "height=" #define K_PACKED "packed" #define K_SHOWTOC "showtoc" +#define K_CUSTOMCOL "customcol" /* Groups of activities */ #define G_DEFAULT 0x00 @@ -1100,6 +1101,22 @@ struct report_format { /* Maximum number of horizontal lines for the background grid */ #define MAX_HLINES_NR 10 +/* Color palette constants */ +#define SVG_COLORS_IDX_MASK 0x0f +#define SVG_COL_PALETTE_SIZE 24 +#define SVG_COL_PALETTE_NR 2 +#define SVG_COL_BCKGRD_IDX 16 +#define SVG_COL_AXIS_IDX 17 +#define SVG_COL_GRID_IDX 18 +#define SVG_COL_TITLE_IDX 19 +#define SVG_COL_INFO_IDX 20 +#define SVG_COL_DEFAULT_IDX 21 +#define SVG_COL_HEADER_IDX 22 +#define SVG_COL_ERROR_IDX 23 + +#define SVG_DEFAULT_COL_PALETTE 0 +#define SVG_CUSTOM_COL_PALETTE 1 + #define MAYBE 0x80 /* diff --git a/sadf.c b/sadf.c index 114cb6a..dc0f467 100644 --- a/sadf.c +++ b/sadf.c @@ -51,6 +51,8 @@ int endian_mismatch = FALSE; int arch_64 = FALSE; /* Number of decimal places */ int dplaces_nr = -1; +/* Color palette number */ +int palette = SVG_DEFAULT_COL_PALETTE; unsigned int flags = 0; unsigned int dm_major; /* Device-mapper major number */ @@ -1566,6 +1568,9 @@ int main(int argc, char **argv) else if (!strcmp(t, K_SHOWTOC)) { flags |= S_F_SVG_SHOW_TOC; } + else if (!strcmp(t, K_CUSTOMCOL)) { + palette = SVG_CUSTOM_COL_PALETTE; + } else { usage(argv[0]); } diff --git a/sadf_misc.c b/sadf_misc.c index bbb4c2f..7510af0 100644 --- a/sadf_misc.c +++ b/sadf_misc.c @@ -35,6 +35,8 @@ extern unsigned int flags; extern char *seps[]; +extern int palette; +extern unsigned int svg_colors[][SVG_COL_PALETTE_SIZE]; /* *************************************************************************** @@ -954,9 +956,11 @@ __printf_funct_t print_svg_header(void *parm, int action, char *dfile, height = 100; } printf(" width=\"%d\" height=\"%d\"" - " fill=\"black\" stroke=\"gray\" stroke-width=\"1\">\n", - SVG_T_XSIZE * (hdr_parm->views_per_row), height); - printf(""); + " fill=\"black\" stroke=\"#%06x\" stroke-width=\"1\">\n", + SVG_T_XSIZE * (hdr_parm->views_per_row), height, + svg_colors[palette][SVG_COL_DEFAULT_IDX]); + printf("", + svg_colors[palette][SVG_COL_HEADER_IDX]); print_gal_header(localtime_r((const time_t *) &(file_hdr->sa_ust_time), &rectime), file_hdr->sa_sysname, file_hdr->sa_release, file_hdr->sa_nodename, file_hdr->sa_machine, @@ -985,9 +989,10 @@ __printf_funct_t print_svg_header(void *parm, int action, char *dfile, if (!(action & F_BEGIN)) { if (!hdr_parm->graph_nr) { /* No views displayed */ - printf("", + printf("", SVG_H_YSIZE + - SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0)); + SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0), + svg_colors[palette][SVG_COL_ERROR_IDX]); printf("No data!\n"); } /* Give actual SVG height */ diff --git a/svg_stats.c b/svg_stats.c index 2caecfe..5e0363e 100644 --- a/svg_stats.c +++ b/svg_stats.c @@ -38,12 +38,22 @@ #endif extern unsigned int flags; - -unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, - 0xe85f00, 0x0000ff, 0x006020, 0x7030a0, - 0xffff00, 0x666635, 0xd60093, 0x00bfbf, - 0xcc3300, 0x50040f, 0xffffbf, 0x193d55}; -#define SVG_COLORS_IDX_MASK 0x0f +extern int palette; + +unsigned int svg_colors[SVG_COL_PALETTE_NR][SVG_COL_PALETTE_SIZE] = + {{0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, /* Default palette */ + 0xe85f00, 0x0000ff, 0x006020, 0x7030a0, + 0xffff00, 0x666635, 0xd60093, 0x00bfbf, + 0xcc3300, 0x50040f, 0xffffbf, 0x193d55, + 0x000000, 0xffffff, 0x202020, 0xffff00, + 0xffff00, 0x808080, 0xa52a2a, 0xff0000}, + + {0x915c83, 0x0000ff, 0x8a2be2, 0xde5d83, /* Custom color palette */ + 0xff55a3, 0x993300, 0x800020, 0x008080, + 0xdc143c, 0x006400, 0x483d8b, 0x2f4f4f, + 0xcc3300, 0x50040f, 0xffffbf, 0x193d55, + 0xf5f5dc, 0x000000, 0x536872, 0xff6347, + 0xff6347, 0x808080, 0xa52a2a, 0xff0000}}; /* *************************************************************************** @@ -592,8 +602,10 @@ void display_hgrid(double ypos, double yfactor, double lmax, int dp) /* Display horizontal lines (except on X axis) */ if (j > 0) { printf("\n", - ypos * j, SVG_G_XSIZE, ypos * j, yfactor); + "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n", + ypos * j, SVG_G_XSIZE, ypos * j, + svg_colors[palette][SVG_COL_GRID_IDX], + yfactor); } /* @@ -602,9 +614,11 @@ void display_hgrid(double ypos, double yfactor, double lmax, int dp) * to make sure they are properly aligned. */ sprintf(stmp, "%.2f", ypos * j); - printf("%.*f.\n", - (long) (atof(stmp) * yfactor), dp, ypos * j); + (long) (atof(stmp) * yfactor), + svg_colors[palette][SVG_COL_AXIS_IDX], + dp, ypos * j); j++; } while ((ypos * j <= lmax) && (j < MAX_HLINES_NR)); @@ -642,29 +656,36 @@ void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL); set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime); printf("\n", - xpos * j, xpos * j, -SVG_G_YSIZE, xfactor); + "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n", + xpos * j, xpos * j, -SVG_G_YSIZE, + svg_colors[palette][SVG_COL_GRID_IDX], + xfactor); /* * Display graduations. * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile. * In this case, we should rather display the exact time instead of only the hour. */ if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) { - printf("%2d:00\n", - (long) (xpos * j * xfactor) - 15, rectime.tm_hour); + (long) (xpos * j * xfactor) - 15, + svg_colors[palette][SVG_COL_AXIS_IDX], + rectime.tm_hour); } else { - printf("%s\n", - (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time); + (long) (xpos * j * xfactor), + svg_colors[palette][SVG_COL_AXIS_IDX], + (long) (xpos * j * xfactor), cur_time); } stamp.ust_time += xpos; } if (!PRINT_LOCAL_TIME(flags)) { - printf("UTC\n"); + printf("UTC\n", + svg_colors[palette][SVG_COL_INFO_IDX]); } } @@ -873,19 +894,23 @@ int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], } /* Graph background */ - printf("\n", - xv, yv, SVG_V_YSIZE, SVG_V_XSIZE); + printf("\n", + xv, yv, SVG_V_YSIZE, SVG_V_XSIZE, + svg_colors[palette][SVG_COL_BCKGRD_IDX]); /* Graph title */ - printf("%s", - xv, 20 + yv, title[i]); + printf("%s", + xv, 20 + yv, + svg_colors[palette][SVG_COL_TITLE_IDX], + title[i]); if (item_name) { printf(" [%s]", item_name); } printf("\n"); - printf("" + printf("" "(Min, Max values)\n\n", - xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25); + xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25, + svg_colors[palette][SVG_COL_INFO_IDX]); /* * At least two samples are needed. @@ -894,17 +919,20 @@ int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], if ((record_hdr->ust_time == svg_p->ust_time_first) || (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) { /* No data found */ - printf("No data\n", - xv, yv + SVG_M_YSIZE); + printf("No data\n", + xv, yv + SVG_M_YSIZE, + svg_colors[palette][SVG_COL_ERROR_IDX]); skip_current_view(out, &pos, group[i]); continue; } /* X and Y axis */ - printf("\n", + printf("\n", xv + SVG_M_XSIZE, yv + SVG_M_YSIZE, xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE, - xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE); + xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE, + svg_colors[palette][SVG_COL_BCKGRD_IDX], + svg_colors[palette][SVG_COL_AXIS_IDX]); /* Autoscaling graphs if needed */ gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax); @@ -917,7 +945,7 @@ int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], printf("" "%s %s(%.*f, %.*f)\n", xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15, - svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp, + svg_colors[palette][(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp, asfactor[j] == 1 ? "" : val, !dp * 2, *(spmin + pos + j) * asfactor[j], !dp * 2, *(spmax + pos + j) * asfactor[j]); @@ -926,18 +954,20 @@ int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], if (DISPLAY_INFO(flags)) { /* Display additional info (hostname, date) */ printf("" + "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">" "%s\n", xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE, + svg_colors[palette][SVG_COL_INFO_IDX], svg_p->file_hdr->sa_nodename); /* Get report date */ set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime), cur_date, sizeof(cur_date)); printf("" + "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">" "%s\n\n", xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14, + svg_colors[palette][SVG_COL_INFO_IDX], cur_date); } @@ -998,14 +1028,14 @@ int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" " "transform=\"scale(%f,%f)\"/>\n", out_p, - svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], + svg_colors[palette][(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor * asfactor[j]); } else if (*out_p) { /* Ignore flat bars */ /* Bar graphs */ printf("\n", - svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor); + svg_colors[palette][(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor); printf("%s\n", out_p); printf("\n"); } -- 2.40.0