PicoGraphics: Add set_pixel_span and call where appropriate.

This commit is contained in:
jon 2022-06-17 08:08:47 +01:00 committed by Phil Howard
parent 76715e45f8
commit 077159adeb
7 changed files with 87 additions and 14 deletions

View File

@ -2,12 +2,9 @@
namespace pimoroni {
void PicoGraphics::set_pen(uint c) {};
void PicoGraphics::set_pen(uint8_t r, uint8_t g, uint8_t b) {};
int PicoGraphics::update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {return -1;};
int PicoGraphics::reset_pen(uint8_t i) {return -1;};
int PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {return -1;};
void PicoGraphics::set_pixel(const Point &p) {};
void PicoGraphics::set_pixel_dither(const Point &p, const RGB &c) {};
void PicoGraphics::set_pixel_dither(const Point &p, const RGB565 &c) {};
void PicoGraphics::scanline_convert(PenType type, conversion_callback_func callback) {};
@ -74,10 +71,7 @@ namespace pimoroni {
if(clipped.x + l >= clip.x + clip.w) {l = clip.x + clip.w - clipped.x;}
Point dest(clipped.x, clipped.y);
while(l--) {
set_pixel(dest);
dest.x++;
}
set_pixel_span(dest, l);
}
void PicoGraphics::rectangle(const Rect &r) {
@ -89,7 +83,7 @@ namespace pimoroni {
Point dest(clipped.x, clipped.y);
while(clipped.h--) {
// draw span of pixels for this row
pixel_span(dest, clipped.w);
set_pixel_span(dest, clipped.w);
// move to next scanline
dest.y++;
}

View File

@ -437,12 +437,14 @@ namespace pimoroni {
set_font(&font6);
};
virtual void set_pen(uint c);
virtual void set_pen(uint8_t r, uint8_t g, uint8_t b);
virtual void set_pen(uint c) = 0;
virtual void set_pen(uint8_t r, uint8_t g, uint8_t b) = 0;
virtual void set_pixel(const Point &p) = 0;
virtual void set_pixel_span(const Point &p, uint l) = 0;
virtual int create_pen(uint8_t r, uint8_t g, uint8_t b);
virtual int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b);
virtual int reset_pen(uint8_t i);
virtual int create_pen(uint8_t r, uint8_t g, uint8_t b);
virtual void set_pixel(const Point &p);
virtual void set_pixel_dither(const Point &p, const RGB &c);
virtual void set_pixel_dither(const Point &p, const RGB565 &c);
virtual void scanline_convert(PenType type, conversion_callback_func callback);
@ -483,6 +485,7 @@ namespace pimoroni {
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
static size_t buffer_size(uint w, uint h) {
return w * h / 8;
@ -511,6 +514,7 @@ namespace pimoroni {
int reset_pen(uint8_t i) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
void get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates);
void set_pixel_dither(const Point &p, const RGB &c) override;
@ -541,6 +545,7 @@ namespace pimoroni {
int reset_pen(uint8_t i) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
void get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates);
void set_pixel_dither(const Point &p, const RGB &c) override;
@ -559,6 +564,7 @@ namespace pimoroni {
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
void set_pixel_dither(const Point &p, const RGB &c) override;
void set_pixel_dither(const Point &p, const RGB565 &c) override;
@ -579,6 +585,7 @@ namespace pimoroni {
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
static size_t buffer_size(uint w, uint h) {
return w * h * sizeof(RGB565);
}

View File

@ -32,4 +32,29 @@ namespace pimoroni {
*f |= (color << bo);
}
void PicoGraphics_Pen1Bit::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
uint8_t *f = &buf[(p.x / 8) + (p.y * bounds.w / 8)];
uint bo = 7 - (p.x & 0b111);
// TODO: this could trivially be sped up by processing single bits only at
// the start and the end of the span and writing full bytes (8 pixels at
// a time) in the middle portion of the span. would only be more efficient
// for longer spans (probably around 20 pixels or more)
while(l--) {
// forceably clear the bit and then set to the correct value
*f &= ~(1U << bo);
*f |= (color << bo);
if(bo == 0) { // last bit of this byte?
// move to next byte in framebuffer and reset the bit offset
f++; bo = 8;
}
bo--;
}
}
}

View File

@ -1,6 +1,7 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenP4::PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
this->pen_type = PEN_P4;
@ -19,7 +20,7 @@ namespace pimoroni {
}
void PicoGraphics_PenP4::set_pen(uint c) {
color = c & 0xf;
}
}
void PicoGraphics_PenP4::set_pen(uint8_t r, uint8_t g, uint8_t b) {
int pen = RGB(r, g, b).closest(palette, palette_size);
if(pen != -1) color = pen;
@ -61,7 +62,25 @@ namespace pimoroni {
*f &= m; // clear bits
*f |= b; // set value
}
void PicoGraphics_PenP4::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
uint8_t *f = &buf[(p.x / 2) + (p.y * bounds.w / 2)];
// doubled up color value, so the color is stored in both nibbles
uint8_t cc = color | (color << 4);
// handle the first pixel if not byte aligned
if(p.x & 0b1) {*f &= 0b11110000; *f |= (cc & 0b00001111); f++; l--;}
// write any double nibble pixels
while(l > 1) {*f++ = cc; l -= 2;}
// handle the last pixel if not byte aligned
if(l) {*f &= 0b00001111; *f |= (cc & 0b11110000);}
}
void PicoGraphics_PenP4::get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates) {
RGB error;
for(size_t i = 0; i < candidates.size(); i++) {

View File

@ -50,6 +50,16 @@ namespace pimoroni {
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenP8::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
buf = &buf[p.y * bounds.w + p.x];
while(l--) {
*buf++ = color;
}
}
void PicoGraphics_PenP8::get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates) {
RGB error;
for(size_t i = 0; i < candidates.size(); i++) {

View File

@ -22,6 +22,15 @@ namespace pimoroni {
uint8_t *buf = (uint8_t *)frame_buffer;
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenRGB332::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
buf = &buf[p.y * bounds.w + p.x];
while(l--) {
*buf++ = color;
}
}
void PicoGraphics_PenRGB332::set_pixel_dither(const Point &p, const RGB &c) {
if(!bounds.contains(p)) return;
static uint8_t _odm[16] = {

View File

@ -22,4 +22,13 @@ namespace pimoroni {
uint16_t *buf = (uint16_t *)frame_buffer;
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenRGB565::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint16_t *buf = (uint16_t *)frame_buffer;
buf = &buf[p.y * bounds.w + p.x];
while(l--) {
*buf++ = color;
}
}
}