#include "libpspp/assertion.h"
#include "libpspp/hash-functions.h"
#include "libpspp/hmap.h"
+#include "libpspp/pool.h"
#include "output/render.h"
#include "output/tab.h"
#include "output/table-item.h"
};
static struct render_page *render_page_create (const struct render_params *,
- struct table *);
+ struct table *, int min_width);
struct render_page *render_page_ref (const struct render_page *page_);
static void render_page_unref (struct render_page *);
/* Determine all types of rules that are present, as a bitmap in 'rules'
where rule type 't' is present if bit 2**t is set. */
+ struct cell_color color;
rules = 0;
d[a] = z;
for (d[b] = 0; d[b] < table->n[b]; d[b]++)
- rules |= 1u << table_get_rule (table, a, d[H], d[V]);
+ rules |= 1u << table_get_rule (table, a, d[H], d[V], &color);
/* Turn off TAL_NONE because it has width 0 and we needn't bother. However,
if the device doesn't support margins, make sure that there is at least a
/* Calculate maximum width of the rules that are present. */
int width = 0;
- for (size_t i = 0; i < N_LINES; i++)
+ for (size_t i = 0; i < TABLE_N_STROKES; i++)
if (rules & (1u << i))
width = MAX (width, params->line_widths[a][rule_to_render_type (i)]);
return width;
size is PARAMS->size, but the caller is responsible for actually breaking it
up to fit on such a device, using the render_break abstraction. */
static struct render_page *
-render_page_create (const struct render_params *params, struct table *table)
+render_page_create (const struct render_params *params, struct table *table,
+ int min_width)
{
struct render_page *page;
enum { MIN, MAX };
x = cell.d[H][1];
table_cell_free (&cell);
}
+ if (min_width > 0)
+ for (i = 0; i < 2; i++)
+ distribute_spanned_width (min_width, &columns[i][0], rules[H], nc);
/* In pathological cases, spans can cause the minimum width of a column to
exceed the maximum width. This bollixes our interpolation algorithm
static inline enum render_line_style
get_rule (const struct render_page *page, enum table_axis axis,
- const int d[TABLE_N_AXES])
+ const int d[TABLE_N_AXES], struct cell_color *color)
{
return rule_to_render_type (table_get_rule (page->table,
- axis, d[H] / 2, d[V] / 2));
+ axis, d[H] / 2, d[V] / 2,
+ color));
}
static bool
const int d[TABLE_N_AXES])
{
enum render_line_style styles[TABLE_N_AXES][2];
+ struct cell_color colors[TABLE_N_AXES][2];
enum table_axis a;
for (a = 0; a < TABLE_N_AXES; a++)
e[H] = d[H];
e[V] = d[V];
e[b]--;
- styles[a][0] = get_rule (page, a, e);
+ styles[a][0] = get_rule (page, a, e, &colors[a][0]);
}
if (d[b] / 2 < page->table->n[b])
- styles[a][1] = get_rule (page, a, d);
+ styles[a][1] = get_rule (page, a, d, &colors[a][1]);
}
else
- styles[a][0] = styles[a][1] = get_rule (page, a, d);
+ {
+ styles[a][0] = styles[a][1] = get_rule (page, a, d, &colors[a][0]);
+ colors[a][1] = colors[a][0];
+ }
}
if (styles[H][0] != RENDER_LINE_NONE || styles[H][1] != RENDER_LINE_NONE
bb[H][0] = ofs[H] + page->cp[H][d[H]];
bb[H][1] = ofs[H] + page->cp[H][d[H] + 1];
- if (render_direction_rtl ())
+ if (page->params->rtl)
{
int temp = bb[H][0];
bb[H][0] = render_page_get_size (page, H) - bb[H][1];
}
bb[V][0] = ofs[V] + page->cp[V][d[V]];
bb[V][1] = ofs[V] + page->cp[V][d[V] + 1];
- page->params->draw_line (page->params->aux, bb, styles);
+ page->params->draw_line (page->params->aux, bb, styles, colors);
}
}
bb[H][0] = clip[H][0] = ofs[H] + page->cp[H][cell->d[H][0] * 2 + 1];
bb[H][1] = clip[H][1] = ofs[H] + page->cp[H][cell->d[H][1] * 2];
- if (render_direction_rtl ())
+ if (page->params->rtl)
{
int temp = bb[H][0];
bb[H][0] = clip[H][0] = render_page_get_size (page, H) - bb[H][1];
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)
+ enum table_valign valign = cell->style->cell_style.valign;
+ if (valign != TABLE_VALIGN_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)
+ if (valign == TABLE_VALIGN_CENTER)
extra /= 2;
bb[V][0] += extra;
}
}
}
- page->params->draw_cell (page->params->aux, cell, bb, clip);
+ int spill[TABLE_N_AXES][2];
+ for (enum table_axis axis = 0; axis < TABLE_N_AXES; axis++)
+ {
+ spill[axis][0] = rule_width (page, axis, cell->d[axis][0]) / 2;
+ spill[axis][1] = rule_width (page, axis, cell->d[axis][1]) / 2;
+ }
+
+ int color_idx = (cell->d[V][0] < page->h[V][0]
+ || page->n[V] - (cell->d[V][0] + 1) < page->h[V][1]
+ ? 0
+ : (cell->d[V][0] - page->h[V][0]) & 1);
+ page->params->draw_cell (page->params->aux, cell, color_idx,
+ bb, spill, clip);
}
/* Draws the cells of PAGE indicated in BB. */
render_page_draw_cells (const struct render_page *page,
int ofs[TABLE_N_AXES], int bb[TABLE_N_AXES][2])
{
- int x, y;
-
- for (y = bb[V][0]; y < bb[V][1]; y++)
- for (x = bb[H][0]; x < bb[H][1]; )
- if (is_rule (x) || is_rule (y))
- {
- int d[TABLE_N_AXES];
- d[H] = x;
- d[V] = y;
- render_rule (page, ofs, d);
- x++;
- }
- else
+ for (int y = bb[V][0]; y < bb[V][1]; y++)
+ for (int x = bb[H][0]; x < bb[H][1]; )
+ if (!is_rule (x) && !is_rule (y))
{
struct table_cell cell;
x = rule_ofs (cell.d[H][1]);
table_cell_free (&cell);
}
+ else
+ x++;
+
+ for (int y = bb[V][0]; y < bb[V][1]; y++)
+ for (int x = bb[H][0]; x < bb[H][1]; x++)
+ if (is_rule (x) || is_rule (y))
+ {
+ int d[TABLE_N_AXES];
+ d[H] = x;
+ d[V] = y;
+ render_rule (page, ofs, d);
+ }
}
/* Renders PAGE, by calling the 'draw_line' and 'draw_cell' functions from the
};
static const struct render_page *
-render_pager_add_table (struct render_pager *p, struct table *table)
+render_pager_add_table (struct render_pager *p, struct table *table,
+ int min_width)
{
struct render_page *page;
if (p->n_pages >= p->allocated_pages)
p->pages = x2nrealloc (p->pages, &p->allocated_pages, sizeof *p->pages);
- page = p->pages[p->n_pages++] = render_page_create (p->params, table);
+ page = p->pages[p->n_pages++] = render_page_create (p->params, table,
+ min_width);
return page;
}
{
tab_text_format (t, 0, i, TAB_LEFT, "%s.", f[i]->marker);
tab_text (t, 1, i, TAB_LEFT, f[i]->content);
+ if (f[i]->style)
+ {
+ tab_add_style (t, 0, i, f[i]->style);
+ tab_add_style (t, 1, i, f[i]->style);
+ }
}
- render_pager_add_table (p, &t->table);
+ render_pager_add_table (p, &t->table, 0);
free (f);
}
static void
-add_text_page (struct render_pager *p, const struct table_item_text *t)
+add_text_page (struct render_pager *p, const struct table_item_text *t,
+ int min_width)
{
if (!t)
return;
struct tab_table *tab = tab_create (1, 1);
- tab_text (tab, 0, 0, TAB_LEFT, t->content);
+ tab_text (tab, 0, 0, 0, t->content);
for (size_t i = 0; i < t->n_footnotes; i++)
tab_add_footnote (tab, 0, 0, t->footnotes[i]);
- render_pager_add_table (p, &tab->table);
+ if (t->style)
+ tab->styles[0] = area_style_clone (tab->container, t->style);
+ render_pager_add_table (p, &tab->table, min_width);
}
/* Creates and returns a new render_pager for rendering TABLE_ITEM on the
render_pager_create (const struct render_params *params,
const struct table_item *table_item)
{
+ const struct table *table = table_item_get_table (table_item);
struct render_pager *p;
p = xzalloc (sizeof *p);
p->params = params;
+ struct render_page *page = render_page_create (params, table_ref (table), 0);
+ struct render_break b;
+ render_break_init (&b, page, H);
+ struct render_page *subpage = render_break_next (&b, p->params->size[H]);
+ int title_width = subpage ? subpage->cp[H][2 * subpage->n[H] + 1] : 0;
+ render_page_unref (subpage);
+ render_break_destroy (&b);
+
/* Title. */
- add_text_page (p, table_item_get_title (table_item));
+ add_text_page (p, table_item_get_title (table_item), title_width);
+
+ /* Layers. */
+ add_text_page (p, table_item_get_layers (table_item), title_width);
/* Body. */
- render_pager_add_table (p, table_ref (table_item_get_table (table_item)));
+ render_pager_add_table (p, table_ref (table_item_get_table (table_item)), 0);
/* Caption. */
- add_text_page (p, table_item_get_caption (table_item));
+ add_text_page (p, table_item_get_caption (table_item), 0);
/* Footnotes. */
add_footnote_page (p, table_item);