From 66a8687fbbe219b8c5b8d4dcd7aa2249fd55f5cf Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 18 Nov 2018 22:23:28 -0800 Subject: [PATCH] output: Add support for colors in cells. Background colors aren't painted very well until the following commit adds support for cell margins. --- src/output/cairo.c | 36 ++++++++++++++++++++++++++++++++---- src/output/tab.c | 7 +++++++ src/output/tab.h | 6 ++++++ src/output/table-provider.h | 23 +++++++++++++++++++++++ src/output/table.c | 8 ++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/output/cairo.c b/src/output/cairo.c index 8b621be39d..0909b629a1 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -371,7 +371,7 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) xr->char_width = MAX (xr->char_width, pango_to_xr (char_width)); xr->char_height = MAX (xr->char_height, pango_to_xr (char_height)); } - xr->cell_margin = xr->char_width; + xr->cell_margin = xr->char_width / 2; if (xr->params == NULL) { @@ -668,6 +668,17 @@ dump_rectangle (struct xr_driver *xr, int x0, int y0, int x1, int y1) cairo_stroke (xr->cairo); } +static void +fill_rectangle (struct xr_driver *xr, int x0, int y0, int x1, int y1) +{ + cairo_new_path (xr->cairo); + cairo_set_line_width (xr->cairo, xr_to_pt (xr->line_width)); + cairo_rectangle (xr->cairo, + xr_to_pt (x0 + xr->x), xr_to_pt (y0 + xr->y), + xr_to_pt (x1 - x0), xr_to_pt (y1 - y0)); + cairo_fill (xr->cairo); +} + /* Draws a horizontal line X0...X2 at Y if LEFT says so, shortening it to X0...X1 if SHORTEN is true. Draws a horizontal line X1...X3 at Y if RIGHT says so, @@ -861,6 +872,8 @@ xr_measure_cell_height (void *xr_, const struct table_cell *cell, int width) return h; } +static void xr_clip (struct xr_driver *, int clip[TABLE_N_AXES][2]); + static void xr_draw_cell (void *xr_, const struct table_cell *cell, int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2]) @@ -868,11 +881,26 @@ xr_draw_cell (void *xr_, const struct table_cell *cell, struct xr_driver *xr = xr_; int w, h, brk; + cairo_save (xr->cairo); + xr_clip (xr, clip); + cairo_set_source_rgb (xr->cairo, + cell->style->bg.r / 255., + cell->style->bg.g / 255., + cell->style->bg.b / 255.); + fill_rectangle (xr, bb[H][0], bb[V][0], bb[H][1], bb[V][1]); + cairo_restore (xr->cairo); + + cairo_save (xr->cairo); + cairo_set_source_rgb (xr->cairo, + cell->style->fg.r / 255., + cell->style->fg.g / 255., + cell->style->fg.b / 255.); + bb[H][0] += xr->cell_margin; bb[H][1] -= xr->cell_margin; - if (bb[H][0] >= bb[H][1]) - return; - xr_layout_cell (xr, cell, bb, clip, &w, &h, &brk); + if (bb[H][0] < bb[H][1]) + xr_layout_cell (xr, cell, bb, clip, &w, &h, &brk); + cairo_restore (xr->cairo); } static int diff --git a/src/output/tab.c b/src/output/tab.c index 8d24aab07b..a158b22979 100644 --- a/src/output/tab.c +++ b/src/output/tab.c @@ -105,6 +105,8 @@ tab_create (int nc, int nr) t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER]; t->fmtmap[RC_OTHER] = *settings_get_format (); + memset (t->styles, 0, sizeof t->styles); + t->col_ofs = t->row_ofs = 0; return t; @@ -823,6 +825,11 @@ tab_get_cell (const struct table *table, int x, int y, cell->n_contents = 0; } } + + int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT; + const struct cell_style *style = t->styles[style_idx]; + if (style) + cell->style = style; } static int diff --git a/src/output/tab.h b/src/output/tab.h index 4bf7816fad..43f0278964 100644 --- a/src/output/tab.h +++ b/src/output/tab.h @@ -51,6 +51,9 @@ enum result_class n_RC }; +#define TAB_STYLE_MASK (7u << (TAB_FIRST_AVAILABLE + 3)) +#define TAB_STYLE_SHIFT (TAB_FIRST_AVAILABLE + 3) + /* A table. */ struct tab_table { @@ -74,6 +77,9 @@ struct tab_table unsigned char *rh; /* Horiz rules; unsigned char[nr+1][nc]. */ unsigned char *rv; /* Vert rules; unsigned char[nr][nc+1]. */ + /* Cell styles. */ + struct cell_style *styles[8]; + /* X and Y offsets. */ int col_ofs, row_ofs; diff --git a/src/output/table-provider.h b/src/output/table-provider.h index a511e13bd5..9a79061228 100644 --- a/src/output/table-provider.h +++ b/src/output/table-provider.h @@ -17,6 +17,7 @@ #ifndef OUTPUT_TABLE_PROVIDER #define OUTPUT_TABLE_PROVIDER 1 +#include #include "output/table.h" struct string; @@ -42,6 +43,26 @@ struct cell_contents void cell_contents_format_footnote_markers (const struct cell_contents *, struct string *); +struct cell_color + { + uint8_t r, g, b; + }; + +#define CELL_COLOR(r, g, b) (struct cell_color) { r, g, b } +#define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0) +#define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255) + +static inline bool +cell_color_equal (const struct cell_color *a, const struct cell_color *b) +{ + return a->r == b->r && a->g == b->g && a->b == b->b; +} + +struct cell_style + { + struct cell_color fg, bg; + }; + /* A cell in a table. */ struct table_cell { @@ -75,6 +96,8 @@ struct table_cell size_t n_contents; struct cell_contents inline_contents; + const struct cell_style *style; + /* Called to free the cell's data, if nonnull. */ void (*destructor) (void *destructor_aux); void *destructor_aux; diff --git a/src/output/table.c b/src/output/table.c index 7f37479984..9a90c61b48 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -140,6 +140,14 @@ table_get_cell (const struct table *table, int x, int y, { assert (x >= 0 && x < table->n[TABLE_HORZ]); assert (y >= 0 && y < table->n[TABLE_VERT]); + + static const struct cell_style default_style = + { + .fg = { 0, 0, 0 }, + .bg = { 255, 255, 255 }, + }; + cell->style = &default_style; + table->klass->get_cell (table, x, y, cell); } -- 2.30.2