Skip to content
UrushiDocumentation

Draw paths and connected lines

Canvas provides two line models:

  • marker paths draw one chosen grapheme along horizontal, vertical, or diagonal segments;
  • LineNetwork joins horizontal and vertical segments with corners, tees, and crossings.
canvas.line(
Position::new(0, 4),
Position::new(4, 0),
Grapheme::new("*"),
TextStyle::new(),
);
canvas.polyline(
[Position::new(5, 0), Position::new(8, 0), Position::new(8, 4)],
Grapheme::new("+"),
TextStyle::new(),
);

In a 9×5 Canvas this produces:

Rendered output
*++++
* +
* +
* +
* +

polyline connects each adjacent pair of points. rectangle is a closed, cell-aligned marker path; zero width or height draws nothing.

For example, a five-by-three rectangle uses the requested width and height as its complete outer extent:

canvas.rectangle(
Position::new(0, 0),
5,
3,
Grapheme::new("#"),
TextStyle::new(),
);
Rendered output
#####
# #
#####

All endpoints are inclusive. Paths use Composition::Overlay unless the corresponding *_with method specifies another rule.

Use one LineNetwork when intersecting segments must choose box-drawing glyphs from their combined connectivity:

let mut network = LineNetwork::new(LineGlyphs::NORMAL, TextStyle::new());
network
.horizontal(2, 0..=6)
.vertical(3, 0..=4);
canvas.line_network(network);
Rendered output
│
│
───┼───
│
│

Only segments in the same LineNetwork form junctions. Separate network commands compose as cells but do not merge connectivity.

Choose LineGlyphs::NORMAL, ROUNDED, ASCII, THICK, DOUBLE, or HIDDEN, or construct a complete custom repertoire. Every repertoire character must be printable and one cell wide.

let repertoires = [
LineGlyphs::NORMAL,
LineGlyphs::ROUNDED,
LineGlyphs::ASCII,
LineGlyphs::THICK,
LineGlyphs::DOUBLE,
LineGlyphs::HIDDEN,
];
The same corner in each repertoire
NORMAL ┌─ ROUNDED ╭─ ASCII +- THICK ┏━ DOUBLE ╔═ HIDDEN
│ │ | ┃ ║

horizontal_with and vertical_with accept LineContinuations. START, END, and BOTH affect the glyph selected at an inclusive endpoint without drawing another cell outside the supplied range. This is useful when rendering one clipped portion of a larger network.

Here the first network ends at its top edge. The second declares that its vertical segment continues upward beyond the visible range:

let mut ended = LineNetwork::new(LineGlyphs::NORMAL, TextStyle::new());
ended
.horizontal(0, 2..=4)
.vertical(2, 0..=2);
canvas.line_network(ended);
let mut continued = LineNetwork::new(LineGlyphs::NORMAL, TextStyle::new());
continued
.horizontal(0, 8..=10)
.vertical_with(8, 0..=2, LineContinuations::START);
canvas.line_network(continued);

In an 11×3 Canvas, the two networks render side by side:

Rendered output
┌── ├──
│ │
│ │

START changes the visible endpoint from a corner to a tee. It does not draw another cell above the Canvas.