-xr_draw_line (void *xr_, int bb[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 x3 = bb[H][1];
- const int y3 = bb[V][1];
- const int top = styles[H][0];
- const int bottom = styles[H][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.
-
- Three additional ordinates are assigned along the x axis. The
- first is xc, midway between x0 and x3. The others are x1 and
- x2; for a single vertical line these are equal to xc, and for
- a double vertical line they are the ordinates of the left and
- right half of the double line.
-
- yc, y1, and y2 are assigned similarly along the y axis.
-
- The following diagram shows the coordinate system and output
- for double top and bottom lines, single left line, and no
- right line:
-
- x0 x1 xc x2 x3
- y0 ________________________
- | # # |
- | # # |
- | # # |
- | # # |
- | # # |
- y1 = y2 = yc |######### # |
- | # # |
- | # # |
- | # # |
- | # # |
- y3 |________#_____#_______|
- */
- struct xr_driver *xr = xr_;
-
- /* Offset from center of each line in a pair of double lines. */
- int double_line_ofs = (xr->line_space + xr->line_width) / 2;
-
- /* Are the lines along each axis single or double?
- (It doesn't make sense to have different kinds of line on the
- same axis, so we don't try to gracefully handle that case.) */
- bool double_vert = top == RENDER_LINE_DOUBLE || bottom == RENDER_LINE_DOUBLE;
- bool double_horz = start_of_line == RENDER_LINE_DOUBLE || end_of_line == RENDER_LINE_DOUBLE;
-
- /* When horizontal lines are doubled,
- the left-side line along y1 normally runs from x0 to x2,
- and the right-side line along y1 from x3 to x1.
- If the top-side line is also doubled, we shorten the y1 lines,
- so that the left-side line runs only to x1,
- and the right-side line only to x2.
- Otherwise, the horizontal line at y = y1 below would cut off
- the intersection, which looks ugly:
- x0 x1 x2 x3
- y0 ________________________
- | # # |
- | # # |
- | # # |
- | # # |
- y1 |######### ########|
- | |
- | |
- y2 |######################|
- | |
- | |
- y3 |______________________|
- It is more of a judgment call when the horizontal line is
- single. We actually choose to cut off the line anyhow, as
- shown in the first diagram above.
- */
- bool shorten_y1_lines = top == RENDER_LINE_DOUBLE;
- bool shorten_y2_lines = bottom == RENDER_LINE_DOUBLE;
- bool shorten_yc_line = shorten_y1_lines && shorten_y2_lines;
- int horz_line_ofs = double_vert ? double_line_ofs : 0;
- int xc = (x0 + x3) / 2;
- int x1 = xc - horz_line_ofs;
- int x2 = xc + horz_line_ofs;
-
- bool shorten_x1_lines = start_of_line == RENDER_LINE_DOUBLE;
- bool shorten_x2_lines = end_of_line == RENDER_LINE_DOUBLE;
- bool shorten_xc_line = shorten_x1_lines && shorten_x2_lines;
- int vert_line_ofs = double_horz ? double_line_ofs : 0;
- int yc = (y0 + y3) / 2;
- int y1 = yc - vert_line_ofs;
- int y2 = yc + vert_line_ofs;
-
- if (!double_horz)
- 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,
- 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, top_color, bottom_color,
- shorten_xc_line);
- else
- {
- 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);
- }