extmod/modframebuf.c framebuf1_text() does not clear pixels
This section of the code looks wrong:
if (vline_data & 1) { // only draw if pixel set
if (0 <= y && y < self->height) { // clip y
uint byte_pos = x0 + self->stride * ((uint)y >> 3);
if (col == 0) {
// clear pixel
self->buf[byte_pos] &= ~(1 << (y & 7));
} else {
// set pixel
self->buf[byte_pos] |= 1 << (y & 7);
}
}
If the pixel is not set, it should surely clear down the pixel in the framebuf as we don't know its prior contents. Further, if we happen to be drawing with col==0 to a part of the framebuf which is already zero, then nothing will be drawn, because in that circumstance the code never sets a pixel.
I hope I'm right on this observation from reviewing the code: I haven't had the opportunity to try it since my SSD1306 was DOA.
extmod/modframebuf: Validate framebuf bounds against buffer.
Fixes #12562 and #12563. cc @gwangmu
I'm not sure why FrameBuffer never validated these arguments, I guess maybe as a code size optimisation but I think this is a useful thing to guard against accidental mistakes and improve usability / reduce confusion as debugging "why doesn't the display look right" can be quite difficult.
Also fixes the length calculation in framebuf_get_buffer which was completely wrong for most formats as it did not take into account the bits-per-pixel. (Edit: Rather than fixing this, just make it forward directly to the underlying buffer)
This ensures that the buffer is large enough for the specified width, height, bits-per-pixel, and stride.
Also makes the legacy FrameBuffer1 constructor re-use the FrameBuffer make_new to save some code size and hopefully offset this a bit.
This work was funded through GitHub Sponsors.