X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Frender.c;h=a91e1f7b799570aa4a29689b984fdf17af33758c;hb=24c5f7c629e68801492d7ca1766953a2a954a820;hp=05db149ab07a7a14b7a9b56f50ff8de0692d3ec5;hpb=d0b91eae59319ab2756d0d43b9cb15eb9cd3c234;p=pspp diff --git a/src/output/render.c b/src/output/render.c index 05db149ab0..a91e1f7b79 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -359,9 +359,14 @@ distribute_spanned_width (int width, w1 by the common denominator of all three calculations (d), dividing that out in the column width calculation, and then keeping the remainder for the next iteration. + + (We actually compute the unspanned width of a column as twice the + unspanned width, plus the width of the rule on the left, plus the width of + the rule on the right. That way each rule contributes to both the cell on + its left and on its right.) */ d0 = n; - d1 = total_unspanned * 2.0; + d1 = 2.0 * (total_unspanned > 0 ? total_unspanned : 1.0); d = d0 * d1; if (total_unspanned > 0) d *= 2.0; @@ -379,7 +384,7 @@ distribute_spanned_width (int width, w += width * unspanned * d0; } - rows[x].width = w / d; + rows[x].width = MAX (rows[x].width, w / d); w -= rows[x].width * d; } } @@ -450,7 +455,7 @@ measure_rule (const struct render_params *params, const struct table *table, enum table_axis b = !a; unsigned int rules; int d[TABLE_N_AXES]; - int width, i; + int width; /* 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. */ @@ -461,10 +466,11 @@ measure_rule (const struct render_params *params, const struct table *table, /* Calculate maximum width of the rules that are present. */ width = 0; - for (i = 0; i < N_LINES; i++) - if (rules & (1u << i)) - width = MAX (width, params->line_widths[a][rule_to_render_type (i)]); - + if (rules & (1u << TAL_1) + || (z > 0 && z < table->n[a] && rules & (1u << TAL_GAP))) + width = params->line_widths[a][RENDER_LINE_SINGLE]; + if (rules & (1u << TAL_2)) + width = MAX (width, params->line_widths[a][RENDER_LINE_DOUBLE]); return width; } @@ -778,6 +784,7 @@ render_page_unref (struct render_page *page) { if (page != NULL && --page->ref_cnt == 0) { + int i; struct render_overflow *overflow, *next; HMAP_FOR_EACH_SAFE (overflow, next, struct render_overflow, node, @@ -786,8 +793,13 @@ render_page_unref (struct render_page *page) hmap_destroy (&page->overflows); table_unref (page->table); - free (page->cp[H]); - free (page->cp[V]); + + for (i = 0; i < TABLE_N_AXES; ++i) + { + free (page->join_crossing[i]); + free (page->cp[i]); + } + free (page); } } @@ -803,7 +815,7 @@ render_page_get_size (const struct render_page *page, enum table_axis axis) /* Drawing render_pages. */ -static enum render_line_style +static inline enum render_line_style get_rule (const struct render_page *page, enum table_axis axis, const int d[TABLE_N_AXES]) { @@ -902,15 +914,15 @@ render_cell (const struct render_page *page, const struct table_cell *cell) page->params->draw_cell (page->params->aux, cell, bb, clip); } -/* Renders PAGE, by calling the 'draw_line' and 'draw_cell' functions from the - render_params provided to render_page_create(). */ -void -render_page_draw (const struct render_page *page) +/* Draws the cells of PAGE indicated in BB. */ +static void +render_page_draw_cells (const struct render_page *page, + int bb[TABLE_N_AXES][2]) { int x, y; - for (y = 0; y <= page->n[V] * 2; y++) - for (x = 0; x <= page->n[H] * 2; ) + 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]; @@ -924,12 +936,91 @@ render_page_draw (const struct render_page *page) struct table_cell cell; table_get_cell (page->table, x / 2, y / 2, &cell); - if (y / 2 == cell.d[V][0]) + if (y == bb[V][0] || y / 2 == cell.d[V][0]) render_cell (page, &cell); x = rule_ofs (cell.d[H][1]); table_cell_free (&cell); } } + +/* Renders PAGE, by calling the 'draw_line' and 'draw_cell' functions from the + render_params provided to render_page_create(). */ +void +render_page_draw (const struct render_page *page) +{ + int bb[TABLE_N_AXES][2]; + + bb[H][0] = 0; + bb[H][1] = page->n[H] * 2 + 1; + bb[V][0] = 0; + bb[V][1] = page->n[V] * 2 + 1; + + render_page_draw_cells (page, bb); +} + +/* Returns the greatest value i, 0 <= i < n, such that cp[i] <= x0. */ +static int +get_clip_min_extent (int x0, const int cp[], int n) +{ + int low, high, best; + + low = 0; + high = n; + best = 0; + while (low < high) + { + int middle = low + (high - low) / 2; + + if (cp[middle] <= x0) + { + best = middle; + low = middle + 1; + } + else + high = middle; + } + + return best; +} + +/* Returns the least value i, 0 <= i < n, such that cp[i + 1] >= x1. */ +static int +get_clip_max_extent (int x1, const int cp[], int n) +{ + int low, high, best; + + low = 0; + high = n; + best = n; + while (low < high) + { + int middle = low + (high - low) / 2; + + if (cp[middle] >= x1) + best = high = middle; + else + low = middle + 1; + } + + return best; +} + +/* Renders the cells of PAGE that intersect (X,Y)-(X+W,Y+H), by calling the + 'draw_line' and 'draw_cell' functions from the render_params provided to + render_page_create(). */ +void +render_page_draw_region (const struct render_page *page, + int x, int y, int w, int h) +{ + int bb[TABLE_N_AXES][2]; + + bb[H][0] = get_clip_min_extent (x, page->cp[H], page->n[H] * 2 + 1); + bb[H][1] = get_clip_max_extent (x + w, page->cp[H], page->n[H] * 2 + 1); + bb[V][0] = get_clip_min_extent (y, page->cp[V], page->n[V] * 2 + 1); + bb[V][1] = get_clip_max_extent (y + h, page->cp[V], page->n[V] * 2 + 1); + + render_page_draw_cells (page, bb); +} /* Breaking up tables to fit on a page. */ @@ -955,12 +1046,27 @@ render_break_init (struct render_break *b, struct render_page *page, b->hw = headers_width (page, axis); } +/* Initializes B as a render_break structure for which + render_break_has_next() always returns false. */ +void +render_break_init_empty (struct render_break *b) +{ + b->page = NULL; + b->axis = TABLE_HORZ; + b->cell = 0; + b->pixel = 0; + b->hw = 0; +} + /* Frees B and unrefs the render_page that it owns. */ void render_break_destroy (struct render_break *b) { if (b != NULL) - render_page_unref (b->page); + { + render_page_unref (b->page); + b->page = NULL; + } } /* Returns true if B still has cells that are yet to be returned, @@ -971,7 +1077,7 @@ render_break_has_next (const struct render_break *b) const struct render_page *page = b->page; enum table_axis axis = b->axis; - return b->cell < page->n[axis] - page->h[axis][1]; + return page != NULL && b->cell < page->n[axis] - page->h[axis][1]; } /* Returns the minimum SIZE argument that, if passed to render_break_next(), @@ -1112,7 +1218,7 @@ render_page_select (const struct render_page *page, enum table_axis axis, if (z0 == page->h[a][0] && p0 == 0 && z1 == page->n[a] - page->h[a][1] && p1 == 0) { - struct render_page *page_rw = (struct render_page *) page; + struct render_page *page_rw = CONST_CAST (struct render_page *, page); page_rw->ref_cnt++; return page_rw; } @@ -1299,4 +1405,3 @@ insert_overflow (struct render_page_selection *s, return of; } -