diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 287c02a..09dba2d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,9 @@ +0.5.0 + - tests + - fix page drawing 0.4.0 - - ILI9486, XPT2046 - - rotation + - ILI9486, XPT2046 + - rotation 0.2.1 - CS & LED pin do ILI drv 0.2.0 diff --git a/gfxlcd/drawing/page.py b/gfxlcd/drawing/page.py index d9c899c..d5720ee 100644 --- a/gfxlcd/drawing/page.py +++ b/gfxlcd/drawing/page.py @@ -22,56 +22,79 @@ class Page(Pixel, metaclass=abc.ABCMeta): """calculate lineparts - helper""" steps = [length for _ in range(0, step)] if step * length < required_length: - for idx in range(0, required_length - step * length): - steps[idx] += 1 + offset = len(steps) // 2 + rest = required_length - step * length + steps_even = True if len(steps) & 1 == 0 else False + rest_even = True if rest & 1 == 0 else False + appendix = 0 + for idx in range(0, rest): + steps[offset + appendix] += 1 + if steps_even: + appendix = self._calculate_appendix(appendix) + elif idx > 0 and rest_even: + appendix = self._calculate_appendix(appendix) + elif not rest_even: + appendix = self._calculate_appendix(appendix) return steps + def _calculate_appendix(self, appendix): + """calculate appendix during drawing a line""" + if appendix == 0: + appendix = -1 + elif appendix < 0: + appendix *= -1 + else: + appendix = (appendix + 1) * -1 + + return appendix + def draw_line(self, pos_x1, pos_y1, pos_x2, pos_y2): """draw diagonal line""" width = abs(pos_x2 - pos_x1) height = abs(pos_y2 - pos_y1) if pos_x1 == pos_x2: - steps = [height] + steps = [height+1] horizontal = False offset_x = offset_y = 0 elif pos_y1 == pos_y2: - steps = [width] + steps = [width+1] horizontal = True offset_x = offset_y = 0 elif width > height: + width += 1 if pos_x2 < pos_x1: pos_x1, pos_x2 = pos_x2, pos_x1 pos_y1, pos_y2 = pos_y2, pos_y1 offset_y = 1 if pos_y2 > pos_y1 else -1 offset_x = 1 if pos_x2 > pos_x1 else -1 horizontal = True - step = height - length = width / step + step = height + 1 + length = width // step steps = self._calculate_steps(length, step, width) - else: + height += 1 if pos_y2 < pos_y1: pos_x1, pos_x2 = pos_x2, pos_x1 pos_y1, pos_y2 = pos_y2, pos_y1 offset_y = 1 if pos_y2 > pos_y1 else -1 offset_x = 1 if pos_x2 > pos_x1 else -1 horizontal = False - step = width - length = height / step + step = width + 1 + length = height // step steps = self._calculate_steps(length, step, height) delta_y = 0 delta_x = 0 for idx, step in enumerate(steps): if horizontal: - for appendix in range(int(step)+1): + for appendix in range(int(step)): self.draw_pixel( int(pos_x1 + delta_x + appendix), int(pos_y1 + (idx * offset_y)) ) delta_x += step * offset_x else: - for appendix in range(int(step)+1): + for appendix in range(int(step)): self.draw_pixel( int(pos_x1 + (idx * offset_x)), int(pos_y1 + delta_y + appendix) diff --git a/gfxlcd/driver/null/__init__.py b/gfxlcd/driver/null/__init__.py new file mode 100644 index 0000000..c2d021b --- /dev/null +++ b/gfxlcd/driver/null/__init__.py @@ -0,0 +1,2 @@ +"""null driver module""" +__author__ = 'Bartosz Kosciow' diff --git a/gfxlcd/driver/null/null_page.py b/gfxlcd/driver/null/null_page.py new file mode 100644 index 0000000..7915153 --- /dev/null +++ b/gfxlcd/driver/null/null_page.py @@ -0,0 +1,45 @@ +"""Null Page test chip drover""" +from gfxlcd.drawing.page import Page +from gfxlcd.abstract.chip import Chip + + +class NullPage(Page, Chip): + """Test chip driver for page drawing""" + def __init__(self, width, height, driver, auto_flush=True): + Chip.__init__(self, width, height, driver, auto_flush) + Page.__init__(self, driver) + self.rotation = 0 + self.buffer = [] + self.area = { + 'start_x': 0, + 'start_y': 0, + 'end_x': width-1, + 'end_y': height-1 + } + + def init(self): + """inits a device""" + Page.init(self) + Chip.init(self) + + def _converted_background_color(self): + """convert RGB background to available color""" + return 1 + + def _converted_color(self): + """convert RGB color to available color""" + return 1 + + def flush(self, force=None): + """flush buffer to device + :force - boolean|None""" + return self.buffer + + def set_area(self, pos_x1, pos_y1, pos_x2, pos_y2): + """set area to work on""" + self.area = { + 'start_x': pos_x1, + 'start_y': pos_y1, + 'end_x': pos_x2, + 'end_y': pos_y2 + } diff --git a/gfxlcd/tests/dummy_test.py b/gfxlcd/tests/dummy_test.py deleted file mode 100644 index 360a45d..0000000 --- a/gfxlcd/tests/dummy_test.py +++ /dev/null @@ -1,6 +0,0 @@ -from nose.tools import assert_equal - - -class DummyTest(object): - def test_init(self): - assert_equal(1, 1) diff --git a/gfxlcd/tests/test_page_drawing.py b/gfxlcd/tests/test_page_drawing.py new file mode 100644 index 0000000..ad825de --- /dev/null +++ b/gfxlcd/tests/test_page_drawing.py @@ -0,0 +1,219 @@ +import sys +from nose.tools import assert_equal +sys.path.append("../../") +from gfxlcd.driver.null.null_page import NullPage + + +class TestPageDrawing(object): + def setUp(self): + self.lcd = NullPage(10, 16, None, False) + self.buffer = [[0] * (16 // 8) for x in range(10)] + self.lcd.init() + + def get_buffer(self): + return [[0] * (16 // 8) for x in range(10)] + + def test_has_correct_size(self): + assert_equal(self.lcd.width, 10) + assert_equal(self.lcd.height, 16) + + def test_empty_buffer_after_init(self): + assert_equal(self.lcd.buffer, self.buffer) + + def test_draw_pixel(self): + self.lcd.draw_pixel(1, 1) + buffer = self.get_buffer() + buffer[1][0] = 2 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_pixels_on_same_page(self): + self.lcd.draw_pixel(1, 1) + self.lcd.draw_pixel(1, 4) + buffer = self.get_buffer() + buffer[1][0] = 18 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_pixels_on_different_pages(self): + self.lcd.draw_pixel(2, 9) + self.lcd.draw_pixel(1, 4) + buffer = self.get_buffer() + buffer[1][0] = 16 + buffer[2][1] = 2 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_horizontal_line(self): + self.lcd.draw_line(1, 1, 8, 1) + buffer = self.get_buffer() + buffer[1][0] = 2 + buffer[2][0] = 2 + buffer[3][0] = 2 + buffer[4][0] = 2 + buffer[5][0] = 2 + buffer[6][0] = 2 + buffer[7][0] = 2 + buffer[8][0] = 2 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_vertical_line(self): + self.lcd.draw_line(1, 1, 1, 14) + buffer = self.get_buffer() + buffer[1][0] = 254 + buffer[1][1] = 127 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_overlapping_lines(self): + self.lcd.draw_line(1, 1, 8, 1) + self.lcd.draw_line(1, 1, 1, 14) + buffer = self.get_buffer() + buffer[1][0] = 254 + buffer[2][0] = 2 + buffer[3][0] = 2 + buffer[4][0] = 2 + buffer[5][0] = 2 + buffer[6][0] = 2 + buffer[7][0] = 2 + buffer[8][0] = 2 + buffer[1][1] = 127 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_diagonal_line(self): + self.lcd.draw_line(0, 0, 9, 1) + buffer = self.get_buffer() + buffer[0][0] = 1 + buffer[1][0] = 1 + buffer[2][0] = 1 + buffer[3][0] = 1 + buffer[4][0] = 1 + buffer[5][0] = 2 + buffer[6][0] = 2 + buffer[7][0] = 2 + buffer[8][0] = 2 + buffer[9][0] = 2 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_diagonal_line_even_steps(self): + self.lcd.draw_line(0, 0, 9, 15) + buffer = self.get_buffer() + buffer[0][0] = 1 + buffer[1][0] = 2 + buffer[2][0] = 4+8 + buffer[3][0] = 16+32 + buffer[4][0] = 128+64 + buffer[5][1] = 1+2 + buffer[6][1] = 4+8 + buffer[7][1] = 16+32 + buffer[8][1] = 64 + buffer[9][1] = 128 + self.draw_buffer(self.lcd.buffer) + assert_equal(self.lcd.buffer, buffer) + + def test_draw_diagonal_line_even_steps_even_rest(self): + self.lcd.draw_line(0, 0, 9, 5) + buffer = self.get_buffer() + buffer[0][0] = 1 + buffer[1][0] = 2 + buffer[2][0] = 2 + buffer[3][0] = 4 + buffer[4][0] = 4 + buffer[5][0] = 8 + buffer[6][0] = 8 + buffer[7][0] = 16 + buffer[8][0] = 16 + buffer[9][0] = 32 + + assert_equal(self.lcd.buffer, buffer) + + def test_draw_diagonal_line_odd_steps_even_rest(self): + self.lcd.draw_line(0, 0, 9, 6) + buffer = self.get_buffer() + buffer[0][0] = 1 + buffer[1][0] = 2 + buffer[2][0] = 4 + buffer[3][0] = 4 + buffer[4][0] = 8 + buffer[5][0] = 8 + buffer[6][0] = 16 + buffer[7][0] = 16 + buffer[8][0] = 32 + buffer[9][0] = 64 + + assert_equal(self.lcd.buffer, buffer) + + def test_draw_diagonal_line_even_steps_odd_rest(self): + self.lcd.draw_line(0, 0, 9, 6) + buffer = self.get_buffer() + buffer[0][0] = 1 + buffer[1][0] = 2 + buffer[2][0] = 4 + buffer[3][0] = 4 + buffer[4][0] = 8 + buffer[5][0] = 8 + buffer[6][0] = 16 + buffer[7][0] = 16 + buffer[8][0] = 32 + buffer[9][0] = 64 + + assert_equal(self.lcd.buffer, buffer) + + def test_fill_rect(self): + self.lcd.fill_rect(2, 2, 7, 11) + buffer = self.get_buffer() + buffer[2][0] = 4+8+16+32+64+128 + buffer[3][0] = 4+8+16+32+64+128 + buffer[4][0] = 4+8+16+32+64+128 + buffer[5][0] = 4+8+16+32+64+128 + buffer[6][0] = 4+8+16+32+64+128 + buffer[7][0] = 4+8+16+32+64+128 + buffer[2][1] = 1+2+4+8 + buffer[3][1] = 1+2+4+8 + buffer[4][1] = 1+2+4+8 + buffer[5][1] = 1+2+4+8 + buffer[6][1] = 1+2+4+8 + buffer[7][1] = 1+2+4+8 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_circle(self): + self.lcd.draw_circle(5, 8, 3) + buffer = self.get_buffer() + buffer[2][0] = 128 + buffer[3][0] = 64+128 + buffer[4][0] = 32+64 + buffer[5][0] = 32 + buffer[6][0] = 32+64 + buffer[7][0] = 64+128 + buffer[8][0] = 128 + buffer[2][1] = 1+2 + buffer[3][1] = 2+4 + buffer[4][1] = 4+8 + buffer[5][1] = 8 + buffer[6][1] = 4+8 + buffer[7][1] = 2+4 + buffer[8][1] = 1+2 + assert_equal(self.lcd.buffer, buffer) + + def test_draw_arc(self): + self.lcd.draw_arc(5, 8, 3, 90, 270) + buffer = self.get_buffer() + buffer[2][0] = 128 + buffer[3][0] = 64+128 + buffer[4][0] = 32+64 + buffer[5][0] = 32 + buffer[2][1] = 1+2 + buffer[3][1] = 2+4 + buffer[4][1] = 4+8 + buffer[5][1] = 8 + self.draw_buffer(self.lcd.buffer) + assert_equal(self.lcd.buffer, buffer) + + def draw_buffer(self, buffer): + for page in range(2): + print(page) + row = "" + for y in [1, 2, 4, 8, 16, 32, 64, 128]: + for x in range(10): + if buffer[x][page] & y: + row += "#" + else: + row += "_" + print(row) + row = ""