pimoroni-pico/libraries/pico_graphics/pico_graphics_pen_p8.cpp

69 lines
2.3 KiB
C++

#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenP8::PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
this->pen_type = PEN_P8;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
}
for(auto i = 0u; i < 256; i++) {
palette[i] = {0, 0, 0};
used[i] = false;
}
}
void PicoGraphics_PenP8::set_pen(uint c) {
color = c;
}
void PicoGraphics_PenP8::set_pen(uint8_t r, uint8_t g, uint8_t b) {
int pen = RGB(r, g, b).closest(palette, 16);
if(pen != -1) color = pen;
}
int PicoGraphics_PenP8::update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
i &= 0xff;
palette[i] = {r, g, b};
return i;
}
int PicoGraphics_PenP8::create_pen(uint8_t r, uint8_t g, uint8_t b) {
// Create a colour and place it in the palette if there's space
for(auto i = 0u; i < 256u; i++) {
if(!used[i]) {
palette[i] = {r, g, b};
used[i] = true;
return i;
}
}
return -1;
}
int PicoGraphics_PenP8::reset_pen(uint8_t i) {
palette[i] = {0, 0, 0};
used[i] = false;
return i;
}
void PicoGraphics_PenP8::set_pixel(const Point &p) {
uint8_t *buf = (uint8_t *)frame_buffer;
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenP8::scanline_convert(PenType type, conversion_callback_func callback) {
if(type == PEN_RGB565) {
// Cache the RGB888 palette as RGB565
RGB565 cache[256];
for(auto i = 0u; i < 256; i++) {
cache[i] = palette[i].to_rgb565();
}
// Treat our void* frame_buffer as uint8_t
uint8_t *src = (uint8_t *)frame_buffer;
// Allocate a per-row temporary buffer
uint16_t row_buf[bounds.w];
for(auto y = 0; y < bounds.h; y++) {
for(auto x = 0; x < bounds.w; x++) {
row_buf[x] = cache[src[bounds.w * y + x]];
}
// Callback to the driver with the row data
callback(row_buf, bounds.w * sizeof(uint8_t));
}
}
}
}