From: Ben Pfaff Date: Sat, 17 Nov 2018 23:49:27 +0000 (-0800) Subject: output: Add support for dashed, thick, and thin rules. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b676d85cb983fa0e719de9300935d2c8b549b14;hp=214ed115df21d414f1a785a090d74e8b2525108a;p=pspp output: Add support for dashed, thick, and thin rules. --- diff --git a/src/output/ascii.c b/src/output/ascii.c index ff5b1ba826..f899c97678 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -60,8 +60,16 @@ #define H TABLE_HORZ #define V TABLE_VERT -#define N_BOX (RENDER_N_LINES * RENDER_N_LINES \ - * RENDER_N_LINES * RENDER_N_LINES) +enum + { + ASCII_LINE_NONE, + ASCII_LINE_SINGLE, + ASCII_LINE_DOUBLE, + ASCII_N_LINES + }; + +#define N_BOX (ASCII_N_LINES * ASCII_N_LINES \ + * ASCII_N_LINES * ASCII_N_LINES) static const ucs4_t ascii_box_chars[N_BOX] = { @@ -125,18 +133,43 @@ static const ucs4_t unicode_box_chars[N_BOX] = 0x2566, 0x256c, 0x256c, }; -static inline int -make_box_index (int left, int right, int top, int bottom) +static int +ascii_line_from_render_line (int render_line) { - int start_side = left; - int end_side = right; - if (render_direction_rtl ()) + switch (render_line) { - start_side = right; - end_side = left; + case RENDER_LINE_NONE: + return ASCII_LINE_NONE; + + case RENDER_LINE_SINGLE: + case RENDER_LINE_DASHED: + case RENDER_LINE_THICK: + case RENDER_LINE_THIN: + return ASCII_LINE_SINGLE; + + case RENDER_LINE_DOUBLE: + return ASCII_LINE_DOUBLE; + + default: + return ASCII_LINE_NONE; } - return ((end_side * RENDER_N_LINES + bottom) * RENDER_N_LINES + start_side) * RENDER_N_LINES + top; +} + +static int +make_box_index (int left_, int right_, int top_, int bottom_) +{ + bool rtl = render_direction_rtl (); + int left = ascii_line_from_render_line (rtl ? right_ : left_); + int right = ascii_line_from_render_line (rtl ? left_ : right_); + int top = ascii_line_from_render_line (top_); + int bottom = ascii_line_from_render_line (bottom_); + + int idx = right; + idx = idx * ASCII_N_LINES + bottom; + idx = idx * ASCII_N_LINES + left; + idx = idx * ASCII_N_LINES + top; + return idx; } /* How to emphasize text. */ diff --git a/src/output/cairo.c b/src/output/cairo.c index b363aef51d..8b621be39d 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -283,10 +283,10 @@ apply_options (struct xr_driver *xr, struct string_map *o) xr->fonts[XR_FONT_FIXED].desc = parse_font (d, o, "fixed-font", "monospace", font_size); xr->fonts[XR_FONT_PROPORTIONAL].desc = parse_font (d, o, "prop-font", - "serif", font_size); + "sans serif", font_size); xr->fonts[XR_FONT_EMPHASIS].desc = parse_font (d, o, "emph-font", - "serif italic", font_size); - xr->fonts[XR_FONT_MARKER].desc = parse_font (d, o, "marker-font", "serif", + "sans serif italic", font_size); + xr->fonts[XR_FONT_MARKER].desc = parse_font (d, o, "marker-font", "sans serif", font_size * PANGO_SCALE_X_SMALL); xr->line_gutter = XR_POINT / 2; @@ -375,8 +375,6 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) if (xr->params == NULL) { - int single_width, double_width; - xr->params = xmalloc (sizeof *xr->params); xr->params->draw_line = xr_draw_line; xr->params->measure_cell_width = xr_measure_cell_width; @@ -389,13 +387,17 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) xr->params->font_size[H] = xr->char_width; xr->params->font_size[V] = xr->char_height; - single_width = 2 * xr->line_gutter + xr->line_width; - double_width = 2 * xr->line_gutter + xr->line_space + 2 * xr->line_width; + int lg = xr->line_gutter; + int lw = xr->line_width; + int ls = xr->line_space; for (i = 0; i < TABLE_N_AXES; i++) { xr->params->line_widths[i][RENDER_LINE_NONE] = 0; - xr->params->line_widths[i][RENDER_LINE_SINGLE] = single_width; - xr->params->line_widths[i][RENDER_LINE_DOUBLE] = double_width; + xr->params->line_widths[i][RENDER_LINE_SINGLE] = 2 * lg + lw; + xr->params->line_widths[i][RENDER_LINE_DASHED] = 2 * lg + lw; + xr->params->line_widths[i][RENDER_LINE_THICK] = 2 * lg + lw * 3; + xr->params->line_widths[i][RENDER_LINE_THIN] = 2 * lg + lw / 2; + xr->params->line_widths[i][RENDER_LINE_DOUBLE] = 2 * (lg + lw) + ls; } for (i = 0; i < TABLE_N_AXES; i++) @@ -640,9 +642,14 @@ xr_layout_cell (struct xr_driver *, 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) +dump_line (struct xr_driver *xr, int x0, int y0, int x1, int y1, int style) { cairo_new_path (xr->cairo); + cairo_set_line_width ( + xr->cairo, + xr_to_pt (style == RENDER_LINE_THICK ? xr->line_width * 3 + : style == RENDER_LINE_THIN ? xr->line_width / 2 + : xr->line_width)); cairo_move_to (xr->cairo, xr_to_pt (x0 + xr->x), xr_to_pt (y0 + xr->y)); cairo_line_to (xr->cairo, xr_to_pt (x1 + xr->x), xr_to_pt (y1 + xr->y)); cairo_stroke (xr->cairo); @@ -652,6 +659,7 @@ static void UNUSED dump_rectangle (struct xr_driver *xr, int x0, int y0, int x1, int y1) { cairo_new_path (xr->cairo); + cairo_set_line_width (xr->cairo, xr_to_pt (xr->line_width)); cairo_move_to (xr->cairo, xr_to_pt (x0 + xr->x), xr_to_pt (y0 + xr->y)); cairo_line_to (xr->cairo, xr_to_pt (x1 + xr->x), xr_to_pt (y0 + xr->y)); cairo_line_to (xr->cairo, xr_to_pt (x1 + xr->x), xr_to_pt (y1 + xr->y)); @@ -670,13 +678,13 @@ horz_line (struct xr_driver *xr, int x0, int x1, int x2, int x3, int y, bool shorten) { if (left != RENDER_LINE_NONE && right != RENDER_LINE_NONE && !shorten) - dump_line (xr, x0, y, x3, y); + dump_line (xr, x0, y, x3, y, left); else { if (left != RENDER_LINE_NONE) - dump_line (xr, x0, y, shorten ? x1 : x2, y); + dump_line (xr, x0, y, shorten ? x1 : x2, y, left); if (right != RENDER_LINE_NONE) - dump_line (xr, shorten ? x2 : x1, y, x3, y); + dump_line (xr, shorten ? x2 : x1, y, x3, y, right); } } @@ -690,13 +698,13 @@ vert_line (struct xr_driver *xr, int y0, int y1, int y2, int y3, int x, bool shorten) { if (top != RENDER_LINE_NONE && bottom != RENDER_LINE_NONE && !shorten) - dump_line (xr, x, y0, x, y3); + dump_line (xr, x, y0, x, y3, top); else { if (top != RENDER_LINE_NONE) - dump_line (xr, x, y0, x, shorten ? y1 : y2); + dump_line (xr, x, y0, x, shorten ? y1 : y2, top); if (bottom != RENDER_LINE_NONE) - dump_line (xr, x, shorten ? y2 : y1, x, y3); + dump_line (xr, x, shorten ? y2 : y1, x, y3, bottom); } } @@ -1082,7 +1090,9 @@ xr_layout_cell_text (struct xr_driver *xr, { 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); + dump_line (xr, -xr->left_margin, best, + xr->width + xr->right_margin, best, + RENDER_LINE_SINGLE); cairo_restore (xr->cairo); } } diff --git a/src/output/html.c b/src/output/html.c index 9cc9a5c2b8..f9d45736ef 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -361,13 +361,45 @@ escape_string (FILE *file, } } +static const char * +border_to_css (int border) +{ + switch (border) + { + case TAL_NONE: + return NULL; + + case TAL_SOLID: + return "solid"; + + case TAL_DASHED: + return "dashed"; + + case TAL_THICK: + return "thick solid"; + + case TAL_THIN: + return "thin solid"; + + case TAL_DOUBLE: + return "double"; + + default: + return NULL; + } + +} + static void -put_border (FILE *file, int n_borders, int style, const char *border_name) +put_border (FILE *file, int *n_borders, int style, const char *border_name) { - fprintf (file, "%sborder-%s: %s", - n_borders == 0 ? " STYLE=\"" : "; ", - border_name, - style == TAL_1 ? "thin solid" : "double"); + const char *css = border_to_css (style); + if (css) + { + fprintf (file, "%sborder-%s: %s", + (*n_borders)++ == 0 ? " STYLE=\"" : "; ", + border_name, css); + } } static void @@ -467,7 +499,7 @@ html_output_table (struct html_driver *html, const struct table_item *item) const char *tag; bool is_header; int colspan, rowspan; - int top, left, right, bottom, n_borders; + int top, left, right, bottom; table_get_cell (t, x, y, &cell); if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0]) @@ -506,28 +538,24 @@ html_output_table (struct html_driver *html, const struct table_item *item) if (html->borders) { /* Cell borders. */ - n_borders = 0; + int n_borders = 0; top = table_get_rule (t, TABLE_VERT, x, y); - if (top > TAL_0) - put_border (html->file, n_borders++, top, "top"); + put_border (html->file, &n_borders, top, "top"); if (y + rowspan == table_nr (t)) { bottom = table_get_rule (t, TABLE_VERT, x, y + rowspan); - if (bottom > TAL_0) - put_border (html->file, n_borders++, bottom, "bottom"); + put_border (html->file, &n_borders, bottom, "bottom"); } left = table_get_rule (t, TABLE_HORZ, x, y); - if (left > TAL_0) - put_border (html->file, n_borders++, left, "left"); + put_border (html->file, &n_borders, left, "left"); if (x + colspan == table_nc (t)) { right = table_get_rule (t, TABLE_HORZ, x + colspan, y); - if (right > TAL_0) - put_border (html->file, n_borders++, right, "right"); + put_border (html->file, &n_borders, right, "right"); } if (n_borders > 0) diff --git a/src/output/render.c b/src/output/render.c index 60cda45b16..3984a44a74 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -458,11 +458,17 @@ rule_to_render_type (unsigned char type) { switch (type) { - case TAL_0: + case TAL_NONE: return RENDER_LINE_NONE; - case TAL_1: + case TAL_SOLID: return RENDER_LINE_SINGLE; - case TAL_2: + case TAL_DASHED: + return RENDER_LINE_DASHED; + case TAL_THICK: + return RENDER_LINE_THICK; + case TAL_THIN: + return RENDER_LINE_THIN; + case TAL_DOUBLE: return RENDER_LINE_DOUBLE; default: NOT_REACHED (); @@ -478,7 +484,6 @@ 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; /* 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. */ @@ -491,20 +496,18 @@ measure_rule (const struct render_params *params, const struct table *table, if the device doesn't support margins, make sure that there is at least a small gap between cells (but we don't need any at the left or right edge of the table). */ - if (rules & (1u << TAL_0)) + if (rules & (1u << TAL_NONE)) { - rules &= ~(1u << TAL_0); + rules &= ~(1u << TAL_NONE); if (z > 0 && z < table->n[a] && !params->supports_margins && a == H) - rules |= 1u << TAL_1; + rules |= 1u << TAL_SOLID; } /* Calculate maximum width of the rules that are present. */ - width = 0; - if (rules & (1u << TAL_1) - || (z > 0 && z < table->n[a] && rules & (1u << TAL_0))) - width = params->line_widths[a][RENDER_LINE_SINGLE]; - if (rules & (1u << TAL_2)) - width = MAX (width, params->line_widths[a][RENDER_LINE_DOUBLE]); + int width = 0; + for (size_t i = 0; i < N_LINES; i++) + if (rules & (1u << i)) + width = MAX (width, params->line_widths[a][rule_to_render_type (i)]); return width; } diff --git a/src/output/render.h b/src/output/render.h index 365c8036d4..5089a3bdd4 100644 --- a/src/output/render.h +++ b/src/output/render.h @@ -25,9 +25,12 @@ struct table_item; enum render_line_style { - RENDER_LINE_NONE, /* No line. */ - RENDER_LINE_SINGLE, /* Single line. */ - RENDER_LINE_DOUBLE, /* Double line. */ + RENDER_LINE_NONE, + RENDER_LINE_SINGLE, + RENDER_LINE_DASHED, + RENDER_LINE_THICK, + RENDER_LINE_THIN, + RENDER_LINE_DOUBLE, RENDER_N_LINES }; diff --git a/src/output/tab.c b/src/output/tab.c index fe4b27402d..8d24aab07b 100644 --- a/src/output/tab.c +++ b/src/output/tab.c @@ -45,11 +45,8 @@ #define _(msgid) gettext (msgid) -#if DEBUGGING static const bool debugging = true; -#else -static const bool debugging = false; -#endif + /* Cell options. */ #define TAB_JOIN (1u << TAB_FIRST_AVAILABLE) diff --git a/src/output/table.h b/src/output/table.h index 0a7c4b61b5..8b1d68f654 100644 --- a/src/output/table.h +++ b/src/output/table.h @@ -73,9 +73,15 @@ enum /* Styles for the rules around table cells. */ enum { - TAL_0, /* No line. */ - TAL_1, /* Single line. */ - TAL_2, /* Double line. */ + TAL_NONE, /* No spacing. */ +#define TAL_0 TAL_NONE + TAL_SOLID, +#define TAL_1 TAL_SOLID + TAL_DASHED, + TAL_THICK, + TAL_THIN, + TAL_DOUBLE, +#define TAL_2 TAL_DOUBLE N_LINES };