{
const char *caption = table_item_get_caption (table_item);
struct render_params params;
- struct render_page *page;
struct render_pager *p;
int caption_height;
int i;
if (a->file == NULL && !ascii_open_page (a))
return;
- page = render_page_create (¶ms, table_item_get_table (table_item));
- p = render_pager_create (page);
+ p = render_pager_create (render_page_create (¶ms, table_item_get_table (
+ table_item)));
while (render_pager_has_next (p))
{
- int space = a->length - (a->y + (a->y > 0) + caption_height);
- struct render_page *slice = render_pager_next (p, space);
- if (!slice)
+ int used;
+
+ if (a->y > 0)
+ a->y++;
+ a->y += caption_height;
+ used = render_pager_draw_next (p, a->length - a->y);
+ if (used == 0)
{
assert (a->y > 0);
ascii_close_page (a);
if (!ascii_open_page (a))
- {
- render_pager_destroy (p);
- return;
- }
- continue;
+ break;
}
-
- if (a->y > 0)
- a->y++;
-
- if (caption_height)
+ else
{
- struct table_cell cell;
- int bb[TABLE_N_AXES][2];
-
- ascii_init_caption_cell (caption, &cell);
- bb[H][0] = 0;
- bb[H][1] = a->width;
- bb[V][0] = 0;
- bb[V][1] = caption_height;
- ascii_draw_cell (a, &cell, bb, bb);
- a->y += caption_height;
- caption_height = 0;
+ if (caption_height)
+ {
+ struct table_cell cell;
+ int bb[TABLE_N_AXES][2];
+
+ ascii_init_caption_cell (caption, &cell);
+ bb[H][0] = 0;
+ bb[H][1] = a->width;
+ bb[V][0] = 0;
+ bb[V][1] = caption_height;
+ a->y -= caption_height;
+ ascii_draw_cell (a, &cell, bb, bb);
+ a->y += caption_height;
+ caption_height = 0;
+ }
+ a->y += used;
}
- render_page_draw (slice);
- a->y += render_page_get_size (slice, V);
- render_page_unref (slice);
}
render_pager_destroy (p);
}
{
const struct table *table = contents->table;
struct render_params params;
- struct render_page *page;
+ struct render_pager *p;
int r[TABLE_N_AXES][2];
int width, height;
int i;
params.line_widths[V][i] = width;
}
- page = render_page_create (¶ms, table);
- width = render_page_get_size (page, TABLE_HORZ);
- height = render_page_get_size (page, TABLE_VERT);
+ p = render_pager_create (render_page_create (¶ms, table));
+ width = render_pager_get_size (p, TABLE_HORZ);
+ height = render_pager_get_size (p, TABLE_VERT);
/* r = intersect(bb, clip) - bb. */
for (i = 0; i < TABLE_N_AXES; i++)
else if (alignment == TAB_CENTER)
a->x += (params.size[H] - width) / 2;
a->y += bb[TABLE_VERT][0];
- render_page_draw (page);
+ render_pager_draw (p);
a->y -= bb[TABLE_VERT][0];
a->x = save_x;
}
- render_page_unref (page);
+ render_pager_destroy (p);
if (width > *widthp)
*widthp = width;
cell->destructor = NULL;
}
-static struct render_page *
+static struct render_pager *
xr_render_table_item (struct xr_driver *xr, const struct table_item *item,
int *caption_widthp, int *caption_heightp)
{
else
*caption_heightp = 0;
- return render_page_create (xr->params, table_item_get_table (item));
+ return render_pager_create (render_page_create (xr->params,
+ table_item_get_table (item)));
}
static void
const struct table *table = contents->table;
int single_width, double_width;
struct render_params params;
- struct render_page *page;
+ struct render_pager *p;
int r[TABLE_N_AXES][2];
int width, height;
int i;
}
xr->nest++;
- page = render_page_create (¶ms, table);
- width = render_page_get_size (page, H);
- height = render_page_get_size (page, V);
+ p = render_pager_create (render_page_create (¶ms, table));
+ width = render_pager_get_size (p, H);
+ height = render_pager_get_size (p, V);
if (bb[V][0] + height >= bb[V][1])
- *brk = bb[V][0] + render_page_get_best_breakpoint (page, bb[V][1] - bb[V][0]);
+ *brk = bb[V][0] + render_pager_get_best_breakpoint (p, bb[V][1] - bb[V][0]);
/* r = intersect(bb, clip) - bb. */
for (i = 0; i < TABLE_N_AXES; i++)
else if (alignment == TAB_CENTER)
xr->x += (params.size[H] - width) / 2;
xr->y += bb[V][0];
- render_page_draw_region (page, r[H][0], r[V][0],
- r[H][1] - r[H][0], r[V][1] - r[V][0]);
+ render_pager_draw_region (p, r[H][0], r[V][0],
+ r[H][1] - r[H][0], r[V][1] - r[V][0]);
xr->y -= bb[V][0];
xr->x = save_x;
cairo_restore (xr->cairo);
}
- render_page_unref (page);
+ render_pager_destroy (p);
xr->nest--;
if (width > *widthp)
struct output_item *item;
/* Table items. */
- struct render_page *page;
+ struct render_pager *p;
struct xr_driver *xr;
int title_width;
int title_height;
r->item = output_item_ref (item);
r->xr = xr;
xr_set_cairo (xr, cr);
- r->page = xr_render_table_item (xr, to_table_item (item),
- &r->title_width, &r->title_height);
+ r->p = xr_render_table_item (xr, to_table_item (item),
+ &r->title_width, &r->title_height);
}
else if (is_chart_item (item))
{
if (r)
{
output_item_unref (r->item);
- render_page_unref (r->page);
+ render_pager_destroy (r->p);
free (r);
}
}
{
if (is_table_item (r->item))
{
- int w0 = render_page_get_size (r->page, H);
+ int w0 = render_pager_get_size (r->p, H);
int w1 = r->title_width;
*w = MAX (w0, w1) / XR_POINT;
- *h = (render_page_get_size (r->page, V) + r->title_height) / XR_POINT;
+ *h = (render_pager_get_size (r->p, V) + r->title_height) / XR_POINT;
}
else
{
}
xr->y = r->title_height;
- render_page_draw_region (r->page,
- x * XR_POINT, (y * XR_POINT) - r->title_height,
- w * XR_POINT, h * XR_POINT);
+ render_pager_draw_region (r->p,
+ x * XR_POINT, (y * XR_POINT) - r->title_height,
+ w * XR_POINT, h * XR_POINT);
}
else
xr_draw_chart (to_chart_item (r->item), cr,
while (render_pager_has_next (ts->p))
{
- int space = xr->length - xr->y - ts->caption_height;
- struct render_page *slice = render_pager_next (ts->p, space);
+ int caption_height = ts->caption_height;
+ int used;
- if (!slice)
+ xr->y += caption_height;
+ used = render_pager_draw_next (ts->p, xr->length - xr->y);
+ xr->y -= caption_height;
+ if (!used)
{
assert (xr->y > 0);
return true;
}
-
- if (ts->caption_height)
+ else
{
- if (xr->cairo)
- xr_draw_title (xr, table_item_get_caption (ts->table_item),
- xr->width, ts->caption_height);
-
- xr->y += ts->caption_height;
- ts->caption_height = 0;
+ if (ts->caption_height)
+ {
+ if (xr->cairo)
+ xr_draw_title (xr, table_item_get_caption (ts->table_item),
+ xr->width, ts->caption_height);
+ ts->caption_height = 0;
+ }
+ xr->y += caption_height + used;
}
-
- if (xr->cairo)
- render_page_draw (slice);
- xr->y += render_page_get_size (slice, V);
- render_page_unref (slice);
}
return false;
}
xr_render_table (struct xr_driver *xr, const struct table_item *table_item)
{
struct xr_table_state *ts;
- struct render_page *page;
int caption_width;
ts = xmalloc (sizeof *ts);
if (xr->y > 0)
xr->y += xr->char_height;
- page = xr_render_table_item (xr, table_item,
- &caption_width, &ts->caption_height);
+ ts->p = xr_render_table_item (xr, table_item,
+ &caption_width, &ts->caption_height);
xr->params->size[V] = xr->length - ts->caption_height;
- ts->p = render_pager_create (page);
-
return &ts->fsm;
}
\f
struct render_pager
{
int width;
+ struct render_page *page;
struct render_break x_break;
struct render_break y_break;
};
{
struct render_pager *p = xmalloc (sizeof *p);
p->width = page->params->size[H];
+ p->page = render_page_ref (page);
render_break_init (&p->x_break, page, H);
render_break_init_empty (&p->y_break);
return p;
{
render_break_destroy (&p->x_break);
render_break_destroy (&p->y_break);
+ render_page_unref (p->page);
free (p);
}
}
return true;
}
-/* Returns the next render_page from P to render in a space that has vertical
- size SPACE and the horizontal size as specified in render_params passed to
- render_page_create(). The caller takes ownership of the returned
- render_page. If no content remains to render, or if SPACE is too small to
- render anything, returns NULL. */
-struct render_page *
-render_pager_next (struct render_pager *p, int space)
+/* Draws a chunk of content from P to fit in a space that has vertical size
+ SPACE and the horizontal size specified in the render_params passed to
+ render_page_create(). Returns the amount of space actually used by the
+ rendered chunk, which will be 0 if SPACE is too small to render anything or
+ if no content remains (use render_pager_has_next() to distinguish these
+ cases). */
+int
+render_pager_draw_next (struct render_pager *p, int space)
+{
+ struct render_page *page = (render_pager_has_next (p)
+ ? render_break_next (&p->y_break, space)
+ : NULL);
+ if (page)
+ {
+ int used = render_page_get_size (page, V);
+
+ render_page_draw (page);
+ render_page_unref (page);
+ return used;
+ }
+ else
+ return 0;
+}
+
+/* Draws all of P's content. */
+void
+render_pager_draw (const struct render_pager *p)
+{
+ render_page_draw (p->page);
+}
+
+/* Draws the region of P's content that lies in the region (X,Y)-(X+W,Y+H).
+ Some extra content might be drawn; the device should perform clipping as
+ necessary. */
+void
+render_pager_draw_region (const struct render_pager *p,
+ int x, int y, int w, int h)
+{
+ render_page_draw_region (p->page, x, y, w, h);
+}
+
+/* Returns the size of P's content along AXIS; i.e. the content's width if AXIS
+ is TABLE_HORZ and its length if AXIS is TABLE_VERT. */
+int
+render_pager_get_size (const struct render_pager *p, enum table_axis axis)
+{
+ return render_page_get_size (p->page, axis);
+}
+
+int
+render_pager_get_best_breakpoint (const struct render_pager *p, int height)
{
- return (render_pager_has_next (p)
- ? render_break_next (&p->y_break, space)
- : NULL);
+ return render_page_get_best_breakpoint (p->page, height);
}
\f
/* render_page_select() and helpers. */
struct render_page *render_page_ref (const struct render_page *);
void render_page_unref (struct render_page *);
-
-int render_page_get_size (const struct render_page *, enum table_axis);
-void render_page_draw (const struct render_page *);
-void render_page_draw_region (const struct render_page *,
- int x, int y, int w, int h);
-
-int render_page_get_best_breakpoint (const struct render_page *, int height);
\f
/* An iterator for breaking render_pages into smaller chunks. */
void render_pager_destroy (struct render_pager *);
bool render_pager_has_next (const struct render_pager *);
-struct render_page *render_pager_next (struct render_pager *, int height);
+int render_pager_draw_next (struct render_pager *, int space);
+
+void render_pager_draw (const struct render_pager *);
+void render_pager_draw_region (const struct render_pager *,
+ int x, int y, int w, int h);
+int render_pager_get_size (const struct render_pager *, enum table_axis);
+int render_pager_get_best_breakpoint (const struct render_pager *, int height);
#endif /* output/render.h */