We need tests for GfxLCD and we need it now! But this is a driver so what can we test? W can and must test all drawing functions. We have two algorithms the page and the area. Let’ begin with page one.

We can mock a chip class in such way that it won’t use a driver and all drawing would go to a buffer and we always can check if buffer looks as we want.

## Null page chip

First, let’s write a NullPage chip driver. It should be relatively easy because true driver works on the buffer. So we have all required bricks.

Tests for *initialization, pixel_drawing, horizontal|vertical line drawing, fill_rect, draw_circle, draw_arc* are green.

But diagonal line shows bugs just as I thought 🙂

First, we have wrong steps calculation. We divide values as floats, not ints. And it is hard to draw a half of pixel 😀

The second bug was with losing 1 point in every direction. Why? Because when we start at 0 and draw to 9 we should have 10 pixels but 9 – 0 = 9 🙂 Adding one fixes the problem.

The third is a problem with symmetry. Our algorithm divides a diagonal line into smaller horizontal or vertical lines. When we divide and have a rest we must add this rest to some sublines. We were doing it by adding 1 to sublines starting from first. But this creates such effect:

#_________ #_________ _#________ _#________ __#_______ __#_______ ___#______ ___#______ ____#_____ ____#_____ _____#____ _____#____ ______#___ _______#__ ________#_ _________#

Look at the beginning and the end. What can we do with it?

I think it is better to add rest from the middle to the sides.

We have four cases, even or odd steps and even or odd rest. But we can make two from it.

The simplest case is with even steps. We just need to add offsets (starting middle): 0, -1, 1, -2, 2, -3, 3… same for odd rest.

And other case for odd steps and odd rest is [0, 0, -1, +1 …].

We can now refactor function:

def _calculate_steps(self, length, step, required_length): """calculate lineparts - helper""" steps = [length for _ in range(0, step)] if step * length < required_length: 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

With this we have a nice line:

#_________ _#________ __#_______ __#_______ ___#______ ___#______ ____#_____ ____#_____ _____#____ _____#____ ______#___ ______#___ _______#__ _______#__ ________#_ _________#

## Summary

We have tests for all drawing that works on a page. We had problems with line drawing but all is fixed.

And drawing a line is not so simple as it looks 🙂