in ebcli/bundled/asciimatics/screen.py [0:0]
def draw(self, x, y, char=None, colour=7, bg=0, thin=False):
"""
Draw a line from drawing cursor to the specified position.
This uses a modified Bressenham algorithm, interpolating twice as many points to
render down to anti-aliased characters when no character is specified,
or uses standard algorithm plotting with the specified character.
:param x: The column (x coord) for the location to check.
:param y: The line (y coord) for the location to check.
:param char: Optional character to use to draw the line.
:param colour: Optional colour for plotting the line.
:param bg: Optional background colour for plotting the line.
:param thin: Optional width of anti-aliased line.
"""
# Decide what type of line drawing to use.
line_chars = (self._uni_line_chars if self._unicode_aware else
self._line_chars)
# Define line end points.
x0 = self._x
y0 = self._y
x1 = int(round(x * 2, 0))
y1 = int(round(y * 2, 0))
# Remember last point for next line.
self._x = x1
self._y = y1
# Don't bother drawing anything if we're guaranteed to be off-screen
if ((x0 < 0 and x1 < 0) or (x0 >= self.width * 2 and x1 >= self.width * 2) or
(y0 < 0 and y1 < 0) or (y0 >= self.height * 2 and y1 >= self.height * 2)):
return
dx = abs(x1 - x0)
dy = abs(y1 - y0)
sx = -1 if x0 > x1 else 1
sy = -1 if y0 > y1 else 1
def _get_start_char(cx, cy):
needle = self.get_from(cx, cy)
if needle is not None:
letter, cfg, _, cbg = needle
if colour == cfg and bg == cbg and chr(letter) in line_chars:
return line_chars.find(chr(letter))
return 0
def _fast_fill(start_x, end_x, iy):
next_char = -1
for ix in range(start_x, end_x):
if ix % 2 == 0 or next_char == -1:
next_char = _get_start_char(ix // 2, iy // 2)
next_char |= 2 ** abs(ix % 2) * 4 ** (iy % 2)
if ix % 2 == 1:
self.print_at(line_chars[next_char], ix // 2, iy // 2, colour, bg=bg)
if end_x % 2 == 1:
self.print_at(line_chars[next_char], end_x // 2, iy // 2, colour, bg=bg)
def _draw_on_x(ix, iy):
err = dx
px = ix - 2
py = iy - 2
next_char = 0
while ix != x1:
if ix < px or ix - px >= 2 or iy < py or iy - py >= 2:
px = ix & ~1
py = iy & ~1
next_char = _get_start_char(px // 2, py // 2)
next_char |= 2 ** abs(ix % 2) * 4 ** (iy % 2)
err -= 2 * dy
if err < 0:
iy += sy
err += 2 * dx
ix += sx
if char is None:
self.print_at(line_chars[next_char],
px // 2, py // 2, colour, bg=bg)
else:
self.print_at(char, px // 2, py // 2, colour, bg=bg)
def _draw_on_y(ix, iy):
err = dy
px = ix - 2
py = iy - 2
next_char = 0
while iy != y1:
if ix < px or ix - px >= 2 or iy < py or iy - py >= 2:
px = ix & ~1
py = iy & ~1
next_char = _get_start_char(px // 2, py // 2)
next_char |= 2 ** abs(ix % 2) * 4 ** (iy % 2)
err -= 2 * dx
if err < 0:
ix += sx
err += 2 * dy
iy += sy
if char is None:
self.print_at(line_chars[next_char],
px // 2, py // 2, colour, bg=bg)
else:
self.print_at(char, px // 2, py // 2, colour, bg=bg)
if dy == 0 and thin and char is None:
# Fast-path for polygon filling
_fast_fill(min(x0, x1), max(x0, x1), y0)
elif dx > dy:
_draw_on_x(x0, y0)
if not thin:
_draw_on_x(x0, y0 + 1)
else:
_draw_on_y(x0, y0)
if not thin:
_draw_on_y(x0 + 1, y0)