Tasmota/lib/lib_display/UDisplay/uDisplay_graphics.cpp

138 lines
3.8 KiB
C++

#include "uDisplay.h"
#include "uDisplay_config.h"
// ===== Basic Drawing Primitives =====
static constexpr uint16_t RGB16_TO_MONO = 0x8410;
static constexpr uint16_t RGB16_SWAP_TO_MONO = 0x1084;
void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) {
if (universal_panel->drawPixel(x, y, color)) {
return; // Handled by universal panel
}
if (framebuffer) {
Renderer::drawPixel(x, y, color);
return;
}
}
void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
// Rudimentary clipping
if((x >= _width) || (y >= _height)) return;
if((x + w - 1) >= _width) w = _width - x;
if (universal_panel->drawFastHLine(x, y, w, color)) {
return;
}
if (framebuffer) {
Renderer::drawFastHLine(x, y, w, color);
return;
}
}
void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
if (framebuffer) {
Renderer::drawFastVLine(x, y, h, color);
return;
}
// Rudimentary clipping
if ((x >= _width) || (y >= _height)) return;
if ((y + h - 1) >= _height) h = _height - y;
if (universal_panel->drawFastVLine(x, y, h, color)) {
return;
}
}
void uDisplay::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
if (universal_panel->fillRect(x, y, w, h, color)) {
return;
}
if (framebuffer) {
Renderer::fillRect(x, y, w, h, color);
return;
}
}
void uDisplay::fillScreen(uint16_t color) {
fillRect(0, 0, width(), height(), color);
}
static inline void lvgl_color_swap(uint16_t *data, uint16_t len) { for (uint32_t i = 0; i < len; i++) (data[i] = data[i] << 8 | data[i] >> 8); }
void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { //not_swapped is always true in call form LVGL driver!!!!
if (lvgl_param.swap_color) {
not_swapped = !not_swapped;
}
universal_panel->pushColors(data, len, not_swapped);
}
// convert to mono, these are framebuffer based
void uDisplay::pushColorsMono(uint16_t *data, uint16_t len, bool rgb16_swap) {
// pixel is white if at least one of the 3 components is above 50%
// this is tested with a simple mask, swapped if needed
uint16_t rgb16_to_mono_mask = rgb16_swap ? RGB16_SWAP_TO_MONO : RGB16_TO_MONO;
for (uint32_t y = seta_yp1; y < seta_yp2; y++) {
seta_yp1++;
if (lvgl_param.invert_bw) {
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
uint16_t color = *data++;
if (bpp == 1) color = (color & rgb16_to_mono_mask) ? 0 : 1;
drawPixel(x, y, color); // todo - inline the method to save speed
len--;
if (!len) return; // failsafe - exist if len (pixel number) is exhausted
}
} else {
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
uint16_t color = *data++;
if (bpp == 1) color = (color & rgb16_to_mono_mask) ? 1 : 0;
drawPixel(x, y, color); // todo - inline the method to save speed
len--;
if (!len) return; // failsafe - exist if len (pixel number) is exhausted
}
}
}
}
void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
universal_panel->setAddrWindow(x0, y0, x1, y1);
}
void uDisplay::setRotation(uint8_t rotation) {
cur_rot = rotation;
if (universal_panel->setRotation(rotation)) {
// Update Renderer dimensions based on rotation
switch (rotation) {
case 0:
case 2:
_width = gxs;
_height = gys;
break;
case 1:
case 3:
_width = gys;
_height = gxs;
break;
}
return;
}
if (framebuffer) {
Renderer::setRotation(cur_rot);
return;
}
}
void uDisplay::Updateframe(void) {
universal_panel->updateFrame();
}