+/* Maps a contiguous range of cells from a page to the underlying table along
+ the horizpntal or vertical dimension. */
+struct map
+ {
+ int p0; /* First ordinate in the page. */
+ int t0; /* First ordinate in the table. */
+ int n; /* Number of ordinates in page and table. */
+ };
+
+/* Initializes M to a mapping from PAGE to PAGE->table along axis A. The
+ mapping includes ordinate Z (in PAGE). */
+static void
+get_map (const struct render_page *page, enum table_axis a, int z,
+ struct map *m)
+{
+ if (z < page->h[a][0])
+ {
+ m->p0 = 0;
+ m->t0 = 0;
+ m->n = page->h[a][0];
+ }
+ else if (z < page->n[a] - page->h[a][1])
+ {
+ m->p0 = page->h[a][0];
+ m->t0 = page->r[a][0];
+ m->n = page->r[a][1] - page->r[a][0];
+ }
+ else
+ {
+ m->p0 = page->n[a] - page->h[a][1];
+ m->t0 = page->table->n[a] - page->table->h[a][1];
+ m->n = page->h[a][1];
+ }
+}
+
+/* Initializes CELL with the contents of the table cell at column X and row Y
+ within PAGE. When CELL is no longer needed, the caller is responsible for
+ freeing it by calling table_cell_free(CELL).
+
+ The caller must ensure that CELL is destroyed before TABLE is unref'ed.
+
+ This is equivalent to table_get_cell(), except X and Y are in terms of the
+ page's rows and columns rather than the underlying table's. */
+static void
+render_get_cell (const struct render_page *page, int x, int y,
+ struct table_cell *cell)
+{
+ int d[TABLE_N_AXES] = { [H] = x, [V] = y };
+ struct map map[TABLE_N_AXES];
+
+ for (enum table_axis a = 0; a < TABLE_N_AXES; a++)
+ {
+ struct map *m = &map[a];
+ get_map (page, a, d[a], m);
+ d[a] += m->t0 - m->p0;
+ }
+ table_get_cell (page->table, d[H], d[V], cell);
+
+ for (enum table_axis a = 0; a < TABLE_N_AXES; a++)
+ {
+ struct map *m = &map[a];
+
+ for (int i = 0; i < 2; i++)
+ cell->d[a][i] -= m->t0 - m->p0;
+ cell->d[a][0] = MAX (cell->d[a][0], m->p0);
+ cell->d[a][1] = MIN (cell->d[a][1], m->p0 + m->n);
+ }
+}
+