Add the possibility to draw a bitmap through a mask
This commit is contained in:
+62
-3
@@ -377,7 +377,7 @@ void BitmapBuffer::drawAnnulusSector(coord_t x, coord_t y, coord_t internalRadiu
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, LcdFlags flags, coord_t offset, coord_t width)
|
||||
void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, LcdFlags flags, coord_t offsetX, coord_t width)
|
||||
{
|
||||
if (!mask)
|
||||
return;
|
||||
@@ -397,7 +397,7 @@ void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, Lcd
|
||||
|
||||
if (x < xmin) {
|
||||
width += x - xmin;
|
||||
offset -= x - xmin;
|
||||
offsetX -= x - xmin;
|
||||
x = xmin;
|
||||
}
|
||||
|
||||
@@ -410,7 +410,7 @@ void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, Lcd
|
||||
if (y + row < ymin || y + row >= ymax)
|
||||
continue;
|
||||
pixel_t * p = getPixelPtr(x, y + row);
|
||||
const pixel_t * q = mask->getPixelPtr(offset, row);
|
||||
const pixel_t * q = mask->getPixelPtr(offsetX, row);
|
||||
for (coord_t col = 0; col < width; col++) {
|
||||
drawAlphaPixel(p, *((uint8_t *)q), color);
|
||||
MOVE_TO_NEXT_RIGHT_PIXEL(p);
|
||||
@@ -419,6 +419,50 @@ void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, Lcd
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, const BitmapBuffer * srcBitmap, coord_t offsetX, coord_t offsetY, coord_t width, coord_t height)
|
||||
{
|
||||
if (!mask || !srcBitmap)
|
||||
return;
|
||||
|
||||
APPLY_OFFSET();
|
||||
|
||||
coord_t maskWidth = mask->width();
|
||||
coord_t maskHeight = mask->height();
|
||||
|
||||
if (!width || width > maskWidth) {
|
||||
width = maskWidth;
|
||||
}
|
||||
|
||||
if (!height || height > maskHeight) {
|
||||
height = maskHeight;
|
||||
}
|
||||
|
||||
if (x + width > xmax) {
|
||||
width = xmax - x;
|
||||
}
|
||||
|
||||
if (x < xmin) {
|
||||
width += x - xmin;
|
||||
offsetX -= x - xmin;
|
||||
x = xmin;
|
||||
}
|
||||
|
||||
if (y >= ymax || x >= xmax || width <= 0 || x + width < xmin || y + height < ymin)
|
||||
return;
|
||||
|
||||
for (coord_t row = 0; row < height; row++) {
|
||||
if (y + row < ymin || y + row >= ymax)
|
||||
continue;
|
||||
pixel_t * p = getPixelPtr(x, y + row);
|
||||
const pixel_t * q = mask->getPixelPtr(offsetX, offsetY + row);
|
||||
for (coord_t col = 0; col < width; col++) {
|
||||
drawAlphaPixel(p, *((uint8_t *)q), *srcBitmap->getPixelPtr(row, col));
|
||||
MOVE_TO_NEXT_RIGHT_PIXEL(p);
|
||||
MOVE_TO_NEXT_RIGHT_PIXEL(q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapBuffer::drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset, coord_t width)
|
||||
{
|
||||
APPLY_OFFSET();
|
||||
@@ -676,6 +720,21 @@ BitmapBuffer * BitmapBuffer::loadMask(const char * filename)
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
BitmapBuffer * BitmapBuffer::invertMask() const
|
||||
{
|
||||
BitmapBuffer * result = new BitmapBuffer(format, width(), height());
|
||||
pixel_t * srcData = data;
|
||||
pixel_t * destData = result->data;
|
||||
for (auto y = 0; y < height(); y++) {
|
||||
for (auto x = 0; x < width(); x++) {
|
||||
destData[x] = OPACITY_MAX - (uint8_t)srcData[x];
|
||||
}
|
||||
srcData += width();
|
||||
destData += width();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BitmapBuffer * BitmapBuffer::horizontalFlip() const
|
||||
{
|
||||
BitmapBuffer * result = new BitmapBuffer(format, width(), height());
|
||||
|
||||
+6
-2
@@ -33,7 +33,7 @@ constexpr uint8_t DOTTED = 0x55;
|
||||
constexpr uint8_t STASHED = 0x33;
|
||||
|
||||
#define MOVE_OFFSET() coord_t offsetX = this->offsetX; x += offsetX; this->offsetX = 0; coord_t offsetY = this->offsetY; y += offsetY; this->offsetY = 0
|
||||
#define APPLY_OFFSET() x += offsetX; y += offsetY
|
||||
#define APPLY_OFFSET() x += this->offsetX; y += this->offsetY
|
||||
#define RESTORE_OFFSET() this->offsetX = offsetX, this->offsetY = offsetY
|
||||
|
||||
#if defined(LCD_VERTICAL_INVERT)
|
||||
@@ -369,7 +369,9 @@ class BitmapBuffer: public BitmapBufferBase<pixel_t>
|
||||
|
||||
static BitmapBuffer * loadMaskOnBackground(const char * filename, LcdFlags foreground, LcdFlags background);
|
||||
|
||||
void drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, LcdFlags flags, coord_t offset=0, coord_t width=0);
|
||||
void drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, LcdFlags flags, coord_t offsetX = 0, coord_t width = 0);
|
||||
|
||||
void drawMask(coord_t x, coord_t y, const BitmapBuffer * mask, const BitmapBuffer * srcBitmap, coord_t offsetX = 0, coord_t offsetY = 0, coord_t width = 0, coord_t height = 0);
|
||||
|
||||
void drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset=0, coord_t width=0);
|
||||
|
||||
@@ -506,6 +508,8 @@ class BitmapBuffer: public BitmapBufferBase<pixel_t>
|
||||
|
||||
BitmapBuffer * verticalFlip() const;
|
||||
|
||||
BitmapBuffer * invertMask() const;
|
||||
|
||||
protected:
|
||||
static BitmapBuffer * load_bmp(const char * filename);
|
||||
static BitmapBuffer * load_stb(const char * filename);
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ void MenuBody::paint(BitmapBuffer * dc)
|
||||
for (unsigned i = 0; i < lines.size(); i++) {
|
||||
auto & line = lines[i];
|
||||
LcdFlags flags = MENU_COLOR | MENU_FONT;
|
||||
if (selectedIndex == i) {
|
||||
if (selectedIndex == (int)i) {
|
||||
flags = MENU_HIGHLIGHT_COLOR | MENU_FONT;
|
||||
if (MENU_HIGHLIGHT_BGCOLOR != MENU_BGCOLOR) {
|
||||
dc->drawSolidFilledRect(0, i * MENUS_LINE_HEIGHT, width(), MENUS_LINE_HEIGHT, MENU_HIGHLIGHT_BGCOLOR);
|
||||
|
||||
+17
-3
@@ -46,6 +46,14 @@ class Roller: public Choice {
|
||||
lastScrollPositionY = scrollPositionY;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "Roller";
|
||||
}
|
||||
#endif
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
int32_t value = getValue();
|
||||
@@ -85,20 +93,26 @@ class Roller: public Choice {
|
||||
{
|
||||
Window::checkEvents();
|
||||
|
||||
if (lastEditMode != editMode) {
|
||||
setScrollPositionY(ROLLER_LINE_HEIGHT * (this->getValue() - vmin - 1));
|
||||
lastScrollPositionY = scrollPositionY;
|
||||
lastEditMode = editMode;
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
if (touchState.event != TE_SLIDE) {
|
||||
if (scrollPositionY != lastScrollPositionY) {
|
||||
updateScrollPosition();
|
||||
updateValueFromScrollPosition();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
coord_t lastScrollPositionY = 0;
|
||||
bool lastEditMode = false;
|
||||
|
||||
void updateScrollPosition()
|
||||
void updateValueFromScrollPosition()
|
||||
{
|
||||
lastScrollPositionY = scrollPositionY;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user