X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Foutput%2Frender.c;h=32e6f4513710dbd8696a296e207d7362b24b717f;hb=8502b942ecdbc7d5a688f695cebc6f1bfac79868;hp=aae6f7901fc8c76131554f1cd7ec56479e4f04af;hpb=11f756eeedc92ee354345940fa621737886a75da;p=pspp diff --git a/src/output/render.c b/src/output/render.c index aae6f7901f..32e6f45137 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -480,25 +480,27 @@ measure_rule (const struct render_params *params, const struct table *table, } /* 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; } @@ -508,14 +510,15 @@ render_page_allocate__ (const struct render_params *params, 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 @@ -638,6 +641,12 @@ render_get_cell (const struct render_page *page, int x, int y, 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 @@ -1410,30 +1419,16 @@ struct render_pager 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); } @@ -1447,26 +1442,24 @@ render_pager_create (const struct render_params *params, 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); } @@ -1474,13 +1467,7 @@ render_pager_create (const struct render_params *params, /* 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. @@ -1492,11 +1479,9 @@ render_pager_create (const struct render_params *params, 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); @@ -1512,8 +1497,7 @@ render_pager_destroy (struct render_pager *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); } } @@ -1531,13 +1515,9 @@ render_pager_has_next (const struct render_pager *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 ( @@ -1563,22 +1543,17 @@ render_pager_draw_next (struct render_pager *p, int space) } 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) @@ -1606,18 +1581,14 @@ render_pager_draw_region (const struct render_pager *p, 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 @@ -1625,32 +1596,16 @@ render_pager_draw_region (const struct render_pager *p, 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)); } /* render_page_select() and helpers. */ @@ -1707,18 +1662,21 @@ render_page_select (const struct render_page *page, enum table_axis axis, /* 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. */