/* 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
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;
w += width * unspanned * d0;
}
- rows[x].width = w / d;
+ rows[x].width = MAX (rows[x].width, w / d);
w -= rows[x].width * d;
}
}
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. */
/* 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;
}
{
if (page != NULL && --page->ref_cnt == 0)
{
+ int i;
struct render_overflow *overflow, *next;
HMAP_FOR_EACH_SAFE (overflow, next, struct render_overflow, node,
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);
}
}
\f
/* 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])
{
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];
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);
+}
\f
/* Breaking up tables to fit on a 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,
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(),
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;
}
return of;
}
-