output: Add support for colors in cells.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 19 Nov 2018 06:23:28 +0000 (22:23 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 25 Dec 2018 20:34:53 +0000 (12:34 -0800)
Background colors aren't painted very well until the following commit adds
support for cell margins.

src/output/cairo.c
src/output/tab.c
src/output/tab.h
src/output/table-provider.h
src/output/table.c

index 8b621be39dac83bea593d2ab30580104d16f099d..0909b629a15657c9590d10f1426ea6180b401b70 100644 (file)
@@ -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
index 8d24aab07bb720dd35621135b6133d1a1334728e..a158b22979e1cb79b9ec3f2dc2bd57e325ef42e9 100644 (file)
@@ -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
index 4bf7816fadd668563c2d18d533c59c062d5f8711..43f0278964fb90e3d6767850e700c31e2f2565ec 100644 (file)
@@ -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;
 
index a511e13bd5c95439dc0504b91abb64f414e7aedf..9a790612287033a2db29fcfe269d62a6b54ae36c 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef OUTPUT_TABLE_PROVIDER
 #define OUTPUT_TABLE_PROVIDER 1
 
+#include <stdint.h>
 #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;
index 7f37479984274dc357d50da44f03423d2ea891bd..9a90c61b48807620f76e853cc9e8a1d8876b8758 100644 (file)
@@ -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);
 }