}
/* Allocates and returns a new render_page using PARAMS and TABLE. Allocates
- space for rendering a table with dimensions given in N. The caller must
- initialize most of the members itself. */
+ space for rendering a table with dimensions given in N, headers in H, and
+ content in R. The caller must initialize most of the members itself. */
static struct render_page *
render_page_allocate__ (const struct render_params *params,
- struct table *table, int n[TABLE_N_AXES])
+ struct table *table,
+ const int n[TABLE_N_AXES],
+ const int h[TABLE_N_AXES],
+ const int r[TABLE_N_AXES][2])
{
struct render_page *page = xmalloc (sizeof *page);
- page->params = params;
- page->table = table;
- page->ref_cnt = 1;
- page->n[H] = n[H];
- page->n[V] = n[V];
-
- for (int i = 0; i < TABLE_N_AXES; i++)
- page->cp[i] = xcalloc ((2 * n[i] + 2) , sizeof *page->cp[i]);
-
- hmap_init (&page->overflows);
- memset (page->is_edge_cutoff, 0, sizeof page->is_edge_cutoff);
-
+ *page = (struct render_page) {
+ .params = params,
+ .table = table,
+ .ref_cnt = 1,
+ .n = { [H] = n[H], [V] = n[V] },
+ .h = { [H] = h[H], [V] = h[V] },
+ .r = { [H] = { r[H][0], r[H][1] }, [V] = { r[V][0], r[V][1] } },
+ .cp = { [H] = xcalloc (2 * n[H] + 2, sizeof *page->cp[H]),
+ [V] = xcalloc (2 * n[V] + 2, sizeof *page->cp[V]) },
+ .overflows = HMAP_INITIALIZER (page->overflows),
+ };
return page;
}
static struct render_page *
render_page_allocate (const struct render_params *params, struct table *table)
{
- struct render_page *page = render_page_allocate__ (params, table, table->n);
+ int h[TABLE_N_AXES];
+ int r[TABLE_N_AXES][2];
for (enum table_axis a = 0; a < TABLE_N_AXES; a++)
{
- page->h[a] = table->h[a];
- page->r[a][0] = table->h[a];
- page->r[a][1] = table->n[a];
+ h[a] = table->h[a];
+ r[a][0] = table->h[a];
+ r[a][1] = table->n[a];
}
- return page;
+ return render_page_allocate__ (params, table, table->n, h, r);
}
/* Allocates and returns a new render_page for PARAMS and TABLE, initializing
cell->d[a][0] = MAX (cell->d[a][0], m->p0);
cell->d[a][1] = MIN (cell->d[a][1], m->p0 + m->n);
}
+
+ if (cell->options & TABLE_CELL_FULL_WIDTH)
+ {
+ cell->d[H][0] = 0;
+ cell->d[H][1] = page->n[H];
+ }
}
/* Creates and returns a new render_page for rendering TABLE on a device
const struct render_params *params;
double scale;
- /* An array of "render_page"s to be rendered, in order, vertically. There
- may be up to 5 pages, for the pivot table's title, layers, body,
- captions, and footnotes. */
- struct render_page *pages[5];
- size_t n_pages;
+ struct render_page *page;
- size_t cur_page;
struct render_break x_break;
struct render_break y_break;
};
-static void
-render_pager_add_table (struct render_pager *p, struct table *table,
- int min_width)
-{
- if (table)
- p->pages[p->n_pages++] = render_page_create (p->params, table, min_width);
-}
-
static void
render_pager_start_page (struct render_pager *p)
{
- render_break_init (&p->x_break, render_page_ref (p->pages[p->cur_page++]),
- H);
+ render_break_init (&p->x_break, render_page_ref (p->page), H);
render_break_init_empty (&p->y_break);
}
if (!layer_indexes)
layer_indexes = pt->current_layer;
- struct table *title, *layers, *body, *caption, *footnotes;
- pivot_output (pt, layer_indexes, params->printing,
- &title, &layers, &body, &caption, &footnotes, NULL, NULL);
+ struct table *table = pivot_output_monolithic (pt, layer_indexes,
+ params->printing);
- /* Figure out the width of the body of the table. Use this to determine the
- base scale. */
- struct render_page *body_page = render_page_create (params, body, 0);
- int body_width = table_width (body_page, H);
+ /* Measure the table width and use it to determine the base scale. */
+ struct render_page *page = render_page_create (params, table, 0);
+ int width = table_width (page, H);
double scale = 1.0;
- if (body_width > params->size[H])
+ if (width > params->size[H])
{
if (pt->look->shrink_to_fit[H] && params->ops->scale)
- scale = params->size[H] / (double) body_width;
+ scale = params->size[H] / (double) width;
else
{
struct render_break b;
- render_break_init (&b, render_page_ref (body_page), H);
+ render_break_init (&b, render_page_ref (page), H);
struct render_page *subpage
= render_break_next (&b, params->size[H]);
- body_width = subpage ? subpage->cp[H][2 * subpage->n[H] + 1] : 0;
+ width = subpage ? subpage->cp[H][2 * subpage->n[H] + 1] : 0;
render_page_unref (subpage);
render_break_destroy (&b);
}
/* Create the pager. */
struct render_pager *p = xmalloc (sizeof *p);
- *p = (struct render_pager) { .params = params, .scale = scale };
- render_pager_add_table (p, title, body_width);
- render_pager_add_table (p, layers, body_width);
- p->pages[p->n_pages++] = body_page;
- render_pager_add_table (p, caption, 0);
- render_pager_add_table (p, footnotes, 0);
- assert (p->n_pages <= sizeof p->pages / sizeof *p->pages);
+ *p = (struct render_pager) { .params = params, .scale = scale, .page = page };
/* If we're shrinking tables to fit the page length, then adjust the scale
factor.
necessary would require an iterative search. */
if (pt->look->shrink_to_fit[V] && params->ops->scale)
{
- int total_height = 0;
- for (size_t i = 0; i < p->n_pages; i++)
- total_height += table_width (p->pages[i], V);
- if (total_height * p->scale >= params->size[V])
- p->scale *= params->size[V] / (double) total_height;
+ double height = table_width (p->page, V);
+ if (height * p->scale >= params->size[V])
+ p->scale *= params->size[V] / height;
}
render_pager_start_page (p);
{
render_break_destroy (&p->x_break);
render_break_destroy (&p->y_break);
- for (size_t i = 0; i < p->n_pages; i++)
- render_page_unref (p->pages[i]);
+ render_page_unref (p->page);
free (p);
}
}
if (!render_break_has_next (&p->x_break))
{
render_break_destroy (&p->x_break);
- if (p->cur_page >= p->n_pages)
- {
- render_break_init_empty (&p->x_break);
- render_break_init_empty (&p->y_break);
- return false;
- }
- render_pager_start_page (p);
+ render_break_init_empty (&p->x_break);
+ render_break_init_empty (&p->y_break);
+ return false;
}
else
render_break_init (
}
int ofs[TABLE_N_AXES] = { 0, 0 };
- size_t start_page = SIZE_MAX;
- while (render_pager_has_next (p))
+ if (render_pager_has_next (p))
{
- if (start_page == p->cur_page)
- break;
- start_page = p->cur_page;
-
struct render_page *page
= render_break_next (&p->y_break, space - ofs[V]);
- if (!page)
- break;
-
- render_page_draw (page, ofs);
- ofs[V] += render_page_get_size (page, V);
- render_page_unref (page);
+ if (page)
+ {
+ render_page_draw (page, ofs);
+ ofs[V] += render_page_get_size (page, V);
+ render_page_unref (page);
+ }
}
if (p->scale != 1.0)
clip[H][0] = x;
clip[H][1] = x + w;
- for (size_t i = 0; i < p->n_pages; i++)
- {
- const struct render_page *page = p->pages[i];
- int size = render_page_get_size (page, V);
+ int size = render_page_get_size (p->page, V);
- clip[V][0] = MAX (y, ofs[V]) - ofs[V];
- clip[V][1] = MIN (y + h, ofs[V] + size) - ofs[V];
- if (clip[V][1] > clip[V][0])
- render_page_draw_region (page, ofs, clip);
+ clip[V][0] = MAX (y, ofs[V]) - ofs[V];
+ clip[V][1] = MIN (y + h, ofs[V] + size) - ofs[V];
+ if (clip[V][1] > clip[V][0])
+ render_page_draw_region (p->page, ofs, clip);
- ofs[V] += size;
- }
+ ofs[V] += size;
}
/* Returns the size of P's content along AXIS; i.e. the content's width if AXIS
int
render_pager_get_size (const struct render_pager *p, enum table_axis axis)
{
- int size = 0;
-
- for (size_t i = 0; i < p->n_pages; i++)
- {
- int subsize = render_page_get_size (p->pages[i], axis);
- size = axis == H ? MAX (size, subsize) : size + subsize;
- }
-
- return size;
+ return render_page_get_size (p->page, axis);
}
int
render_pager_get_best_breakpoint (const struct render_pager *p, int height)
{
- int y = 0;
- size_t i;
-
- for (i = 0; i < p->n_pages; i++)
- {
- int size = render_page_get_size (p->pages[i], V);
- if (y + size >= height)
- return render_page_get_best_breakpoint (p->pages[i], height - y) + y;
- y += size;
- }
-
- return height;
+ int size = render_page_get_size (p->page, V);
+ return (size < height
+ ? height
+ : render_page_get_best_breakpoint (p->page, height));
}
\f
/* render_page_select() and helpers. */
/* Allocate subpage. */
int trim[2] = { z0 - page->h[a], page->n[a] - z1 };
+
int n[TABLE_N_AXES] = { [H] = page->n[H], [V] = page->n[V] };
n[a] -= trim[0] + trim[1];
- struct render_page *subpage = render_page_allocate__ (
- page->params, table_ref (page->table), n);
+
+ int r[TABLE_N_AXES][2];
for (enum table_axis k = 0; k < TABLE_N_AXES; k++)
{
- subpage->h[k] = page->h[k];
- subpage->r[k][0] = page->r[k][0];
- subpage->r[k][1] = page->r[k][1];
+ r[k][0] = page->r[k][0];
+ r[k][1] = page->r[k][1];
}
- subpage->r[a][0] += trim[0];
- subpage->r[a][1] -= trim[1];
+ r[a][0] += trim[0];
+ r[a][1] -= trim[1];
+
+ struct render_page *subpage = render_page_allocate__ (
+ page->params, table_ref (page->table), n, page->h, r);
/* An edge is cut off if it was cut off in PAGE or if we're trimming pixels
off that side of the page and there are no headers. */