static bool ascii_open_page (struct ascii_driver *);
static void ascii_draw_line (void *, int bb[TABLE_N_AXES][2],
- enum render_line_style styles[TABLE_N_AXES][2]);
+ enum render_line_style styles[TABLE_N_AXES][2],
+ struct cell_color colors[TABLE_N_AXES][2]);
static void ascii_measure_cell_width (void *, const struct table_cell *,
int *min, int *max);
static int ascii_measure_cell_height (void *, const struct table_cell *,
static void
ascii_draw_line (void *a_, int bb[TABLE_N_AXES][2],
- enum render_line_style styles[TABLE_N_AXES][2])
+ enum render_line_style styles[TABLE_N_AXES][2],
+ struct cell_color colors[TABLE_N_AXES][2] UNUSED)
{
struct ascii_driver *a = a_;
char mbchar[6];
static void xr_driver_run_fsm (struct xr_driver *);
static void xr_draw_line (void *, int bb[TABLE_N_AXES][2],
- enum render_line_style styles[TABLE_N_AXES][2]);
+ enum render_line_style styles[TABLE_N_AXES][2],
+ struct cell_color colors[TABLE_N_AXES][2]);
static void xr_measure_cell_width (void *, const struct table_cell *,
int *min, int *max);
static int xr_measure_cell_height (void *, const struct table_cell *,
int *width, int *height, int *brk);
static void
-dump_line (struct xr_driver *xr, int x0, int y0, int x1, int y1, int style)
+dump_line (struct xr_driver *xr, int x0, int y0, int x1, int y1, int style,
+ const struct cell_color *color)
{
cairo_new_path (xr->cairo);
+ cairo_set_source_rgb (xr->cairo,
+ color->r / 255.0, color->g / 255.0, color->b / 255.0);
cairo_set_line_width (
xr->cairo,
xr_to_pt (style == RENDER_LINE_THICK ? xr->line_width * 2
static void
horz_line (struct xr_driver *xr, int x0, int x1, int x2, int x3, int y,
enum render_line_style left, enum render_line_style right,
+ const struct cell_color *left_color,
+ const struct cell_color *right_color,
bool shorten)
{
- if (left != RENDER_LINE_NONE && right != RENDER_LINE_NONE && !shorten)
- dump_line (xr, x0, y, x3, y, left);
+ if (left != RENDER_LINE_NONE && right != RENDER_LINE_NONE && !shorten
+ && cell_color_equal (left_color, right_color))
+ dump_line (xr, x0, y, x3, y, left, left_color);
else
{
if (left != RENDER_LINE_NONE)
- dump_line (xr, x0, y, shorten ? x1 : x2, y, left);
+ dump_line (xr, x0, y, shorten ? x1 : x2, y, left, left_color);
if (right != RENDER_LINE_NONE)
- dump_line (xr, shorten ? x2 : x1, y, x3, y, right);
+ dump_line (xr, shorten ? x2 : x1, y, x3, y, right, right_color);
}
}
static void
vert_line (struct xr_driver *xr, int y0, int y1, int y2, int y3, int x,
enum render_line_style top, enum render_line_style bottom,
+ const struct cell_color *top_color,
+ const struct cell_color *bottom_color,
bool shorten)
{
- if (top != RENDER_LINE_NONE && bottom != RENDER_LINE_NONE && !shorten)
- dump_line (xr, x, y0, x, y3, top);
+ if (top != RENDER_LINE_NONE && bottom != RENDER_LINE_NONE && !shorten
+ && cell_color_equal (top_color, bottom_color))
+ dump_line (xr, x, y0, x, y3, top, top_color);
else
{
if (top != RENDER_LINE_NONE)
- dump_line (xr, x, y0, x, shorten ? y1 : y2, top);
+ dump_line (xr, x, y0, x, shorten ? y1 : y2, top, top_color);
if (bottom != RENDER_LINE_NONE)
- dump_line (xr, x, shorten ? y2 : y1, x, y3, bottom);
+ dump_line (xr, x, shorten ? y2 : y1, x, y3, bottom, bottom_color);
}
}
static void
xr_draw_line (void *xr_, int bb[TABLE_N_AXES][2],
- enum render_line_style styles[TABLE_N_AXES][2])
+ enum render_line_style styles[TABLE_N_AXES][2],
+ struct cell_color colors[TABLE_N_AXES][2])
{
const int x0 = bb[H][0];
const int y0 = bb[V][0];
const int y3 = bb[V][1];
const int top = styles[H][0];
const int bottom = styles[H][1];
- const int start_of_line = render_direction_rtl() ? styles[V][1]: styles[V][0];
- const int end_of_line = render_direction_rtl() ? styles[V][0]: styles[V][1];
+
+ int start_side = render_direction_rtl();
+ int end_side = !start_side;
+ const int start_of_line = styles[V][start_side];
+ const int end_of_line = styles[V][end_side];
+ const struct cell_color *top_color = &colors[H][0];
+ const struct cell_color *bottom_color = &colors[H][1];
+ const struct cell_color *start_color = &colors[V][start_side];
+ const struct cell_color *end_color = &colors[V][end_side];
/* The algorithm here is somewhat subtle, to allow it to handle
all the kinds of intersections that we need.
int y2 = yc + vert_line_ofs;
if (!double_horz)
- horz_line (xr, x0, x1, x2, x3, yc, start_of_line, end_of_line, shorten_yc_line);
+ horz_line (xr, x0, x1, x2, x3, yc, start_of_line, end_of_line,
+ start_color, end_color, shorten_yc_line);
else
{
- horz_line (xr, x0, x1, x2, x3, y1, start_of_line, end_of_line, shorten_y1_lines);
- horz_line (xr, x0, x1, x2, x3, y2, start_of_line, end_of_line, shorten_y2_lines);
+ horz_line (xr, x0, x1, x2, x3, y1, start_of_line, end_of_line,
+ start_color, end_color, shorten_y1_lines);
+ horz_line (xr, x0, x1, x2, x3, y2, start_of_line, end_of_line,
+ start_color, end_color, shorten_y2_lines);
}
if (!double_vert)
- vert_line (xr, y0, y1, y2, y3, xc, top, bottom, shorten_xc_line);
+ vert_line (xr, y0, y1, y2, y3, xc, top, bottom, top_color, bottom_color,
+ shorten_xc_line);
else
{
- vert_line (xr, y0, y1, y2, y3, x1, top, bottom, shorten_x1_lines);
- vert_line (xr, y0, y1, y2, y3, x2, top, bottom, shorten_x2_lines);
+ vert_line (xr, y0, y1, y2, y3, x1, top, bottom, top_color, bottom_color,
+ shorten_x1_lines);
+ vert_line (xr, y0, y1, y2, y3, x2, top, bottom, top_color, bottom_color,
+ shorten_x2_lines);
}
}
if (0)
{
if (best && !xr->nest)
- {
- cairo_save (xr->cairo);
- cairo_set_source_rgb (xr->cairo, 0, 1, 0);
- dump_line (xr, -xr->left_margin, best,
- xr->width + xr->right_margin, best,
- RENDER_LINE_SINGLE);
- cairo_restore (xr->cairo);
- }
+ dump_line (xr, -xr->left_margin, best,
+ xr->width + xr->right_margin, best,
+ RENDER_LINE_SINGLE, &CELL_COLOR (0, 255, 0));
}
}
/* Cell borders. */
int n_borders = 0;
- top = table_get_rule (t, TABLE_VERT, x, y);
+ struct cell_color color;
+ top = table_get_rule (t, TABLE_VERT, x, y, &color);
put_border (html->file, &n_borders, top, "top");
if (y + rowspan == table_nr (t))
{
- bottom = table_get_rule (t, TABLE_VERT, x, y + rowspan);
+ bottom = table_get_rule (t, TABLE_VERT, x, y + rowspan,
+ &color);
put_border (html->file, &n_borders, bottom, "bottom");
}
- left = table_get_rule (t, TABLE_HORZ, x, y);
+ left = table_get_rule (t, TABLE_HORZ, x, y, &color);
put_border (html->file, &n_borders, left, "left");
if (x + colspan == table_nc (t))
{
- right = table_get_rule (t, TABLE_HORZ, x + colspan, y);
+ right = table_get_rule (t, TABLE_HORZ, x + colspan, y,
+ &color);
put_border (html->file, &n_borders, right, "right");
}
/* 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. */
+ struct cell_color color;
rules = 0;
d[a] = z;
for (d[b] = 0; d[b] < table->n[b]; d[b]++)
- rules |= 1u << table_get_rule (table, a, d[H], d[V]);
+ rules |= 1u << table_get_rule (table, a, d[H], d[V], &color);
/* Turn off TAL_NONE because it has width 0 and we needn't bother. However,
if the device doesn't support margins, make sure that there is at least a
static inline enum render_line_style
get_rule (const struct render_page *page, enum table_axis axis,
- const int d[TABLE_N_AXES])
+ const int d[TABLE_N_AXES], struct cell_color *color)
{
return rule_to_render_type (table_get_rule (page->table,
- axis, d[H] / 2, d[V] / 2));
+ axis, d[H] / 2, d[V] / 2,
+ color));
}
static bool
const int d[TABLE_N_AXES])
{
enum render_line_style styles[TABLE_N_AXES][2];
+ struct cell_color colors[TABLE_N_AXES][2];
enum table_axis a;
for (a = 0; a < TABLE_N_AXES; a++)
e[H] = d[H];
e[V] = d[V];
e[b]--;
- styles[a][0] = get_rule (page, a, e);
+ styles[a][0] = get_rule (page, a, e, &colors[a][0]);
}
if (d[b] / 2 < page->table->n[b])
- styles[a][1] = get_rule (page, a, d);
+ styles[a][1] = get_rule (page, a, d, &colors[a][1]);
}
else
- styles[a][0] = styles[a][1] = get_rule (page, a, d);
+ {
+ styles[a][0] = styles[a][1] = get_rule (page, a, d, &colors[a][0]);
+ colors[a][1] = colors[a][0];
+ }
}
if (styles[H][0] != RENDER_LINE_NONE || styles[H][1] != RENDER_LINE_NONE
}
bb[V][0] = ofs[V] + page->cp[V][d[V]];
bb[V][1] = ofs[V] + page->cp[V][d[V] + 1];
- page->params->draw_line (page->params->aux, bb, styles);
+ page->params->draw_line (page->params->aux, bb, styles, colors);
}
}
STYLES[TABLE_VERT][0]: style of line from left of BB to its center.
STYLES[TABLE_VERT][1]: style of line from right of BB to its center. */
void (*draw_line) (void *aux, int bb[TABLE_N_AXES][2],
- enum render_line_style styles[TABLE_N_AXES][2]);
+ enum render_line_style styles[TABLE_N_AXES][2],
+ struct cell_color colors[TABLE_N_AXES][2]);
/* Draws CELL within bounding box BB. CLIP is the same as BB (the common
case) or a subregion enclosed by BB. In the latter case only the part
t->fmtmap[RC_OTHER] = *settings_get_format ();
memset (t->styles, 0, sizeof t->styles);
+ memset (t->rule_colors, 0, sizeof t->rule_colors);
t->col_ofs = t->row_ofs = 0;
}
static int
-tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
+tab_get_rule (const struct table *table, enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
const struct tab_table *t = tab_cast (table);
- return (axis == TABLE_VERT
- ? t->rh[x + t->cf * y] : t->rv[x + (t->cf + 1) * y]);
+ uint8_t raw = (axis == TABLE_VERT
+ ? t->rh[x + t->cf * y] : t->rv[x + (t->cf + 1) * y]);
+ struct cell_color *p = t->rule_colors[(raw & TAB_RULE_STYLE_MASK)
+ >> TAB_RULE_STYLE_SHIFT];
+ if (p)
+ *color = *p;
+ return (raw & TAB_RULE_TYPE_MASK) >> TAB_RULE_TYPE_SHIFT;
}
static const struct table_class tab_table_class = {
#define TAB_STYLE_MASK (7u << (TAB_FIRST_AVAILABLE + 3))
#define TAB_STYLE_SHIFT (TAB_FIRST_AVAILABLE + 3)
+/* Rule masks. */
+#define TAB_RULE_TYPE_MASK 7
+#define TAB_RULE_TYPE_SHIFT 0
+#define TAB_RULE_STYLE_MASK (31 << TAB_RULE_STYLE_SHIFT)
+#define TAB_RULE_STYLE_SHIFT 3
+
/* A table. */
struct tab_table
{
points to a struct tab_joined_cell. */
void **cc; /* Cell contents; void *[nr][nc]. */
unsigned short *ct; /* Cell types; unsigned short[nr][nc]. */
+ struct cell_style *styles[8];
/* Rules. */
unsigned char *rh; /* Horiz rules; unsigned char[nr+1][nc]. */
unsigned char *rv; /* Vert rules; unsigned char[nr][nc+1]. */
-
- /* Cell styles. */
- struct cell_style *styles[8];
+ struct cell_color *rule_colors[32];
/* X and Y offsets. */
int col_ofs, row_ofs;
static int
table_casereader_get_rule (const struct table *t, enum table_axis axis,
- int x UNUSED, int y)
+ int x UNUSED, int y,
+ struct cell_color *color UNUSED)
{
struct table_casereader *tc = table_casereader_cast (t);
if (axis == TABLE_VERT)
static int
table_paste_get_rule (const struct table *t,
- enum table_axis axis, int x, int y)
+ enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
struct table_paste *tp = table_paste_cast (t);
int h = tp->orientation == TABLE_HORZ ? x : y;
ps = paste_subtable_lookup (tp, h == 0 ? 0 : h - 1, &start);
if (tp->orientation == TABLE_HORZ) /* XXX */
- r = table_get_rule (ps->table, axis, h - start, k);
+ r = table_get_rule (ps->table, axis, h - start, k, color);
else
- r = table_get_rule (ps->table, axis, k, h - start);
+ r = table_get_rule (ps->table, axis, k, h - start, color);
if (h == start + tower_node_get_size (&ps->node))
{
struct tower_node *ps2_ = tower_next (&tp->subtables, &ps->node);
int r2;
if (tp->orientation == TABLE_HORZ) /* XXX */
- r2 = table_get_rule (ps2->table, axis, 0, k);
+ r2 = table_get_rule (ps2->table, axis, 0, k, color);
else
- r2 = table_get_rule (ps2->table, axis, k, 0);
+ r2 = table_get_rule (ps2->table, axis, k, 0, color);
return table_rule_combine (r, r2);
}
}
{
ps = paste_subtable_lookup (tp, h, &start);
if (tp->orientation == TABLE_HORZ) /* XXX */
- return table_get_rule (ps->table, axis, h - start, k);
+ return table_get_rule (ps->table, axis, h - start, k, color);
else
- return table_get_rule (ps->table, axis, k, h - start);
+ return table_get_rule (ps->table, axis, k, h - start, color);
}
}
See table_get_rule() in table.c for a detailed explanation of the
meaning of AXIS and X and Y, including a diagram. */
int (*get_rule) (const struct table *table,
- enum table_axis axis, int x, int y);
+ enum table_axis axis, int x, int y,
+ struct cell_color *color);
/* This function is optional and most table classes will not implement it.
/* For use primarily by output drivers. */
void table_get_cell (const struct table *, int x, int y, struct table_cell *);
-int table_get_rule (const struct table *, enum table_axis, int x, int y);
+int table_get_rule (const struct table *, enum table_axis, int x, int y,
+ struct cell_color *);
size_t table_collect_footnotes (const struct table_item *,
const struct footnote ***);
static int
table_select_get_rule (const struct table *ti,
enum table_axis axis,
- int x, int y)
+ int x, int y, struct cell_color *color)
{
struct table_select *ts = table_select_cast (ti);
return table_get_rule (ts->subtable, axis,
x + ts->ofs[TABLE_HORZ],
- y + ts->ofs[TABLE_VERT]);
+ y + ts->ofs[TABLE_VERT], color);
}
static struct table *
static int
table_stomp_get_rule (const struct table *t,
- enum table_axis axis, int x, int y)
+ enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
struct table_stomp *ts = table_stomp_cast (t);
return table_get_rule (ts->subtable, axis, x,
- axis == H || y == 0 ? y : ts->subtable->n[V]);
+ axis == H || y == 0 ? y : ts->subtable->n[V],
+ color);
}
static const struct table_class table_stomp_class =
static int
table_transpose_get_rule (const struct table *ti,
enum table_axis axis,
- int x, int y)
+ int x, int y, struct cell_color *color)
{
struct table_transpose *tt = table_transpose_cast (ti);
- return table_get_rule (tt->subtable, !axis, y, x);
+ return table_get_rule (tt->subtable, !axis, y, x, color);
}
static const struct table_class table_transpose_class =
between that cell and cell (0,1); and so on, up to (0,NR), which runs
horizontally below cell (0,NR-1). */
int
-table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
+table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
- return table->klass->get_rule (table, axis, x, y);
+ *color = CELL_COLOR_BLACK;
+ return table->klass->get_rule (table, axis, x, y, color);
}
void
static int
table_unshared_get_rule (const struct table *tiu_,
- enum table_axis axis, int x, int y)
+ enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
struct table_unshared *tiu = table_unshared_cast (tiu_);
- return table_get_rule (tiu->subtable, axis, x, y);
+ return table_get_rule (tiu->subtable, axis, x, y, color);
}
static const struct table_class table_unshared_class =
static int
table_string_get_rule (const struct table *ts UNUSED,
- enum table_axis axis UNUSED, int x UNUSED, int y UNUSED)
+ enum table_axis axis UNUSED, int x UNUSED, int y UNUSED,
+ struct cell_color *color UNUSED)
{
return TAL_0;
}