output: Add support for vertical alignment of cells.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 17 Nov 2018 19:12:55 +0000 (11:12 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 25 Dec 2018 20:34:14 +0000 (12:34 -0800)
It makes sense to bottom-align top headings but to top-align data cells,
for example.

src/output/ascii.c
src/output/cairo.c
src/output/html.c
src/output/render.c
src/output/table.h
tests/output/render-test.c

index 507e758e3fd727316f4f147d9162fd4f15218c02..ff5b1ba826588fb2ae35fd00f25fed5546ee10ac 100644 (file)
@@ -627,7 +627,7 @@ text_draw (struct ascii_driver *a, unsigned int options,
   if (y < y0 || y >= y1)
     return;
 
-  switch (options & TAB_ALIGNMENT)
+  switch (options & TAB_HALIGN)
     {
     case TAB_LEFT:
       x = bb[H][0];
index c0a2b5ee0ff8375e407df101c0403aff23c55312..b363aef51d6109fa8faa747fc97d9a02bb869e43 100644 (file)
@@ -926,7 +926,7 @@ xr_layout_cell_text (struct xr_driver *xr,
 
   if (contents->n_footnotes == 0)
     merge_footnotes = false;
-  else if (contents->n_footnotes == 1 && (options & TAB_ALIGNMENT) == TAB_RIGHT)
+  else if (contents->n_footnotes == 1 && (options & TAB_HALIGN) == TAB_RIGHT)
     {
       PangoAttrList *attrs;
 
@@ -991,8 +991,8 @@ xr_layout_cell_text (struct xr_driver *xr,
 
   pango_layout_set_alignment (
     font->layout,
-    ((options & TAB_ALIGNMENT) == TAB_RIGHT ? PANGO_ALIGN_RIGHT
-     : (options & TAB_ALIGNMENT) == TAB_LEFT ? PANGO_ALIGN_LEFT
+    ((options & TAB_HALIGN) == TAB_RIGHT ? PANGO_ALIGN_RIGHT
+     : (options & TAB_HALIGN) == TAB_LEFT ? PANGO_ALIGN_LEFT
      : PANGO_ALIGN_CENTER));
   pango_layout_set_width (
     font->layout,
index 55bcb6daa09d95064e87a6d600c3e83047f8d644..9cc9a5c2b8f594d16de8c617b977e5618343d2a1 100644 (file)
@@ -466,7 +466,7 @@ html_output_table (struct html_driver *html, const struct table_item *item)
           struct table_cell cell;
           const char *tag;
           bool is_header;
-          int alignment, colspan, rowspan;
+          int colspan, rowspan;
           int top, left, right, bottom, n_borders;
 
           table_get_cell (t, x, y, &cell);
@@ -481,12 +481,19 @@ html_output_table (struct html_driver *html, const struct table_item *item)
           tag = is_header ? "TH" : "TD";
           fprintf (html->file, "    <%s", tag);
 
-          alignment = (cell.n_contents > 0
-                       ? cell.contents[0].options & TAB_ALIGNMENT
-                       : TAB_LEFT);
-          if (alignment != TAB_LEFT)
+          int halign = (cell.n_contents > 0
+                        ? cell.contents[0].options & TAB_HALIGN
+                        : TAB_LEFT);
+          if (halign != TAB_LEFT)
             fprintf (html->file, " ALIGN=\"%s\"",
-                     alignment == TAB_RIGHT ? "RIGHT" : "CENTER");
+                     halign == TAB_RIGHT ? "RIGHT" : "CENTER");
+
+          int valign = (cell.n_contents > 0
+                        ? cell.contents[0].options & TAB_VALIGN
+                        : TAB_LEFT);
+          if (valign != TAB_TOP)
+            fprintf (html->file, " ALIGN=\"%s\"",
+                     valign == TAB_BOTTOM ? "BOTTOM" : "MIDDLE");
 
           colspan = table_cell_colspan (&cell);
           if (colspan > 1)
index 9a9370ad175997309f015172ecd476cc389eba57..60cda45b16bb4c44a2442671f06a3f301e738127 100644 (file)
@@ -59,7 +59,9 @@ struct render_page
     int n[TABLE_N_AXES];
     int h[TABLE_N_AXES][2];
 
-    /* cp[H] represents x positions within the table.
+    /* "Cell positions".
+
+       cp[H] represents x positions within the table.
        cp[H][0] = 0.
        cp[H][1] = the width of the leftmost vertical rule.
        cp[H][2] = cp[H][1] + the width of the leftmost column.
@@ -967,6 +969,22 @@ render_cell (const struct render_page *page, const int ofs[TABLE_N_AXES],
   bb[V][0] = clip[V][0] = ofs[V] + page->cp[V][cell->d[V][0] * 2 + 1];
   bb[V][1] = clip[V][1] = ofs[V] + page->cp[V][cell->d[V][1] * 2];
 
+  int valign = (cell->n_contents
+                ? cell->contents->options & TAB_VALIGN
+                : TAB_TOP);
+  if (valign != TAB_TOP)
+    {
+      int height = page->params->measure_cell_height (
+        page->params->aux, cell, bb[H][1] - bb[H][0]);
+      int extra = bb[V][1] - bb[V][0] - height;
+      if (extra > 0)
+        {
+          if (valign == TAB_MIDDLE)
+            extra /= 2;
+          bb[V][0] += extra;
+        }
+    }
+
   of = find_overflow (page, cell->d[H][0], cell->d[V][0]);
   if (of)
     {
index d93c69e38cdb31b339353ab9d80f818ada96fa87..0a7c4b61b568e5275ac764cf4c0e1c2ad7534758 100644 (file)
@@ -48,20 +48,26 @@ enum
   {
     TAB_NONE = 0,
 
-    /* Alignment of cell contents. */
-    TAB_RIGHT      = 0 << 0,    /* Right justify. */
-    TAB_LEFT       = 1 << 0,    /* Left justify. */
-    TAB_CENTER     = 2 << 0,    /* Centered. */
-    TAB_ALIGNMENT  = 3 << 0,   /* Alignment mask. */
+    /* Horizontal alignment of cell contents. */
+    TAB_RIGHT      = 0 << 0,
+    TAB_LEFT       = 1 << 0,
+    TAB_CENTER     = 2 << 0,
+    TAB_HALIGN     = 3 << 0,   /* Alignment mask. */
+
+    /* Vertical alignment of cell contents. */
+    TAB_TOP        = 0 << 2,
+    TAB_MIDDLE     = 1 << 2,
+    TAB_BOTTOM     = 2 << 2,
+    TAB_VALIGN     = 3 << 2,   /* Alignment mask. */
 
     /* These flags may be combined with any alignment. */
-    TAB_EMPH       = 1 << 2,    /* Emphasize cell contents. */
-    TAB_FIX        = 1 << 3,    /* Use fixed font. */
+    TAB_EMPH       = 1 << 4,    /* Emphasize cell contents. */
+    TAB_FIX        = 1 << 5,    /* Use fixed font. */
 
     /* Bits with values (1 << TAB_FIRST_AVAILABLE) and higher are
        not used, so they are available for subclasses to use as
        they wish. */
-    TAB_FIRST_AVAILABLE = 4
+    TAB_FIRST_AVAILABLE = 6
   };
 
 /* Styles for the rules around table cells. */
index 2a874d1c917c7f3948db1cf35811c7e0e0799473..e286f6bea4c044ca4573e7d879278a419ba269a2 100644 (file)
@@ -426,17 +426,17 @@ read_table (FILE *stream)
                 break;
 
               case '(':
-                opt &= ~TAB_ALIGNMENT;
+                opt &= ~TAB_HALIGN;
                 opt |= TAB_LEFT;
                 break;
 
               case ')':
-                opt &= ~TAB_ALIGNMENT;
+                opt &= ~TAB_HALIGN;
                 opt |= TAB_RIGHT;
                 break;
 
               case '|':
-                opt &= ~TAB_ALIGNMENT;
+                opt &= ~TAB_HALIGN;
                 opt |= TAB_CENTER;
                 break;