From d2ee46757c7602fb0d6827136fdb00af1140e2e1 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 13 Sep 2014 10:39:38 -0700 Subject: [PATCH] render: Push all rendering, not just pagination, into render_pager. In future commits this will allow adding support for rendering captions and (to be introduced) footnotes in render_pager. --- src/output/ascii.c | 69 +++++++++++++++++++--------------------- src/output/cairo.c | 77 ++++++++++++++++++++++----------------------- src/output/render.c | 65 ++++++++++++++++++++++++++++++++------ src/output/render.h | 15 +++++---- 4 files changed, 132 insertions(+), 94 deletions(-) diff --git a/src/output/ascii.c b/src/output/ascii.c index 48cad0f234..3548844693 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -423,7 +423,6 @@ ascii_output_table_item (struct ascii_driver *a, { 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; @@ -462,44 +461,42 @@ ascii_output_table_item (struct ascii_driver *a, 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); } @@ -947,7 +944,7 @@ ascii_layout_subtable (struct ascii_driver *a, { 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; @@ -969,9 +966,9 @@ ascii_layout_subtable (struct ascii_driver *a, 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++) @@ -991,11 +988,11 @@ ascii_layout_subtable (struct ascii_driver *a, 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; diff --git a/src/output/cairo.c b/src/output/cairo.c index 87bca8cb44..22e060cf93 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -543,7 +543,7 @@ xr_init_caption_cell (const char *caption, struct table_cell *cell, 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) { @@ -565,7 +565,8 @@ xr_render_table_item (struct xr_driver *xr, const struct table_item *item, 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 @@ -1047,7 +1048,7 @@ xr_layout_cell_subtable (struct xr_driver *xr, 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; @@ -1073,11 +1074,11 @@ xr_layout_cell_subtable (struct xr_driver *xr, } 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++) @@ -1099,13 +1100,13 @@ xr_layout_cell_subtable (struct xr_driver *xr, 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) @@ -1207,7 +1208,7 @@ struct xr_rendering struct output_item *item; /* Table items. */ - struct render_page *page; + struct render_pager *p; struct xr_driver *xr; int title_width; int title_height; @@ -1285,8 +1286,8 @@ xr_rendering_create (struct xr_driver *xr, const struct output_item *item, 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)) { @@ -1303,7 +1304,7 @@ xr_rendering_destroy (struct xr_rendering *r) if (r) { output_item_unref (r->item); - render_page_unref (r->page); + render_pager_destroy (r->p); free (r); } } @@ -1313,10 +1314,10 @@ xr_rendering_measure (struct xr_rendering *r, int *w, int *h) { 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 { @@ -1348,9 +1349,9 @@ xr_rendering_draw (struct xr_rendering *r, cairo_t *cr, } 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, @@ -1447,29 +1448,28 @@ xr_table_render (struct xr_render_fsm *fsm, struct xr_driver *xr) 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; } @@ -1488,7 +1488,6 @@ static struct xr_render_fsm * 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); @@ -1499,12 +1498,10 @@ xr_render_table (struct xr_driver *xr, const struct table_item *table_item) 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; } diff --git a/src/output/render.c b/src/output/render.c index e1cec909f8..35e0a7a94c 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -1301,6 +1301,7 @@ cell_is_breakable (const struct render_break *b, int cell) struct render_pager { int width; + struct render_page *page; struct render_break x_break; struct render_break y_break; }; @@ -1312,6 +1313,7 @@ render_pager_create (struct render_page *page) { 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; @@ -1325,6 +1327,7 @@ render_pager_destroy (struct render_pager *p) { render_break_destroy (&p->x_break); render_break_destroy (&p->y_break); + render_page_unref (p->page); free (p); } } @@ -1355,17 +1358,59 @@ render_pager_has_next (const struct render_pager *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); } /* render_page_select() and helpers. */ diff --git a/src/output/render.h b/src/output/render.h index eed29e8512..927009e9cb 100644 --- a/src/output/render.h +++ b/src/output/render.h @@ -108,13 +108,6 @@ struct render_page *render_page_create (const struct render_params *, 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); /* An iterator for breaking render_pages into smaller chunks. */ @@ -122,6 +115,12 @@ struct render_pager *render_pager_create (struct render_page *); 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 */ -- 2.30.2