The main reason is new environmental sensor boards with LCD.
This means I need to anti-alias text, digits, lines, circles, etc. Previously I had pre-rendered 16 level fonts and icons. But I have moved away from pre-rendered bit map fonts in my latest e-paper code already.
I have gone through several approaches to this. The fact my fonts are vector based previously allowed me to just draw lines and circles on the e-paper. That is fine when over plotting is no problem, i.e. white on white is white.
But if you want to anti-alias you have to over sample, e.g. a 4x4 matrix to then know how many pixels are set (0-16) and use that to control alpha blending of existing pixel and new pixel (or background pixel and foreground pixel).
My first approach for fonts was to make code to allow me to tell if a point x,y is plotted or not - so instead of actively plotting dots (circles) and multiple lines that over lap other lines and dots, I have to do the maths to work out "is this point within a dot" and "is this point on a line". The dot is easy - simple Pythagoras. But the lines was more work - I can work out distance to a point is within stroke width using squares. Working out end of line is harder, so ended up working out the point of perpendicular intersection so I could range check end points and then check distance using squares.
It worked, and allowed me to over sample 4x4 and work out grey levels.
A better way
The problem with the above is the 16 times processing of points. So I came up with a new plan - scan lines and run lengths.
The new logic scans the character top to bottom to determine the left/right for each line or dot that is in the character at that scan line. This is actually quite easy for a dot as I can use a look up to get the left/right for any point on a circle and scale. The line is a rectangle, and the fact it is only ever horizontal, vertical, or a 45 degree line means I don't even need square roots to work out the points, and simply work out the left/right for the specified Y scan. It is simple to merge overlapping runs on a scan line and the max runs is low as we know how the font works (up to 6 ranges).
This means only 4 times the processing of non anti-aliasing, as opposed to 16 times. The runs can then be worked out 4 scan lines at a time and plotting a sequence of the same grey level. The same logic works for anti-aliased or not, just not 4 times over sampling on the Y axis when not anti-aliasing.
7 segment digits
The 7 segment digits are not simple lines and dots, they are a complex path (original in SVG), but it is easy to render and run length encode the scan lines for a single large 7 segment digit (well, 9 segments with colon and dot). I can then scale which lines I extract from this large image to make the same run length logic as I do for the vector fonts and use the same run length plotting code.
Lines and circles
Another primitive is lines and circles, and whilst arbitrary angle lines do need one fast integer square root to get the corners, converting to run length on scan lines is, again, simple, and can use the same run length plotting code.
The same is true for a circle, using the same circle lookup table (with interpolation for a larger circle than the table).
Even faster
All of the above still comes down to pixels, but there is a simple important step I could add to that. I could make the pixel plot primitive have a horizontal run length parameter. This allows a number of checks and memory access and so on to be worked out once, and then a simple loop to apply a run length of pixels plotted the same. When plotting 100% alpha it is extra quick as no checking of existing pixel and alpha blending. It can be a simple loop incrementing memory address. Having all of the primitives for fonts, 7 seg, lines, circles, and so on actually convert to run length makes it easy to use such a primitive. So that may be the next step.
QR!
P.S. Yes, everyone knows I am a stickler for accurate valid QR codes, but I have in fact gone as bit mad with an option here - the targets are 100% correct but the pixels are circles. This is because of the way QR codes are decoded hitting the pixel centres (having found the targets to get accurate alignment), so this should always work whilst having a subtly different aesthetic. I think it is better than some of the other QR code abuse, but it is an option on my EPD code.