snapshot
This commit is contained in:
661
libraries/GFX_Library_for_Arduino/src/canvas/Arduino_Canvas.cpp
Normal file
661
libraries/GFX_Library_for_Arduino/src/canvas/Arduino_Canvas.cpp
Normal file
@@ -0,0 +1,661 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas.h"
|
||||
|
||||
Arduino_Canvas::Arduino_Canvas(
|
||||
int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, uint8_t r)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
}
|
||||
|
||||
Arduino_Canvas::~Arduino_Canvas()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas::begin(int32_t speed)
|
||||
{
|
||||
if (
|
||||
(speed != GFX_SKIP_OUTPUT_BEGIN) && (_output))
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = _width * _height * 2;
|
||||
#if defined(ESP32)
|
||||
_framebuffer = (uint16_t *)aligned_alloc(16, s);
|
||||
#else
|
||||
_framebuffer = (uint16_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
|
||||
uint16_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = color;
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = color;
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = color;
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = color;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
row[i++] = color_index[(b32 & 0xff)];
|
||||
row[i++] = color_index[(b32 & 0xff00) >> 8];
|
||||
row[i++] = color_index[(b32 & 0xff0000) >> 16];
|
||||
row[i++] = color_index[(b32 & 0xff000000) >> 24];
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
row[i++] = color_index[*bitmap++];
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, chroma_key, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
uint8_t color_key;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
color_key = (b32 & 0xff);
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff00) >> 8;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff0000) >> 16;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff000000) >> 24;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 2:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 3:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
default: // case 0:
|
||||
gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitRGBBitmapWithTranColor(
|
||||
int16_t x, int16_t y,
|
||||
uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitRGBBitmapWithTranColor(x, y, bitmap, transparent_color, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip = (x + w - 1) - _max_x;
|
||||
w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
uint16_t p;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
p = (b32 & 0xffff);
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
p = (b32 & 0xffff0000) >> 16;
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
wi -= 2;
|
||||
bitmap += 2;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
p = *bitmap++;
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitBeRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip = (x + w - 1) - _max_x;
|
||||
w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
uint16_t color;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color = *bitmap++;
|
||||
MSB_16_SET(row[i], color);
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->draw16bitRGBBitmap(_output_x, _output_y, _framebuffer, WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::flushQuad(bool force_flush)
|
||||
{
|
||||
int16_t y = _output_y;
|
||||
uint16_t *row1 = _framebuffer;
|
||||
uint16_t *row2 = _framebuffer + WIDTH;
|
||||
if (_output)
|
||||
{
|
||||
int16_t hQuad = HEIGHT / 2;
|
||||
int16_t wQuad = WIDTH / 2;
|
||||
if (!_rowBuf)
|
||||
{
|
||||
_rowBuf = (uint16_t *)malloc(wQuad * 2);
|
||||
}
|
||||
uint16_t p;
|
||||
while (hQuad--)
|
||||
{
|
||||
for (int16_t i = 0; i < wQuad; ++i)
|
||||
{
|
||||
p = (*row1++ & 0b1110011110011100) >> 2;
|
||||
p += (*row1++ & 0b1110011110011100) >> 2;
|
||||
p += (*row2++ & 0b1110011110011100) >> 2;
|
||||
p += (*row2++ & 0b1110011110011100) >> 2;
|
||||
_rowBuf[i] = p;
|
||||
}
|
||||
_output->draw16bitRGBBitmap(_output_x, _output_y + y++, _rowBuf, wQuad, 1);
|
||||
row1 += WIDTH;
|
||||
row2 += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::shade(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t shade_mask)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] &= shade_mask;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t *Arduino_Canvas::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_H_
|
||||
#define _ARDUINO_CANVAS_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, uint8_t rotation = 0);
|
||||
~Arduino_Canvas();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmapWithTranColor(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
void flushQuad(bool force_flush = false);
|
||||
void shade(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t shade_mask);
|
||||
uint16_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint16_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
int16_t MAX_X, MAX_Y;
|
||||
|
||||
// for flushQuad() only
|
||||
uint16_t *_rowBuf = nullptr;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_3bit.h"
|
||||
|
||||
Arduino_Canvas_3bit::Arduino_Canvas_3bit(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
}
|
||||
|
||||
Arduino_Canvas_3bit::~Arduino_Canvas_3bit()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_3bit::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = (_width * _height + 1) / 2;
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_3bit::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
int32_t pos = x + (y * _width);
|
||||
int32_t idx = pos >> 1;
|
||||
uint8_t c = (((color & 0b1000000000000000) ? 0b100 : 0) |
|
||||
((color & 0b0000010000000000) ? 0b010 : 0) |
|
||||
((color & 0b0000000000010000) ? 0b001 : 0));
|
||||
if (pos & 1)
|
||||
{
|
||||
_framebuffer[idx] = (_framebuffer[idx] & 0b00111000) | c;
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[idx] = (_framebuffer[idx] & 0b00000111) | (c << 3);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_3bit::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->draw3bitRGBBitmap(_output_x, _output_y, _framebuffer, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_3bit::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_3BIT_H_
|
||||
#define _ARDUINO_CANVAS_3BIT_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas_3bit : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_3bit(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0);
|
||||
~Arduino_Canvas_3bit();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_3BIT_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,564 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_Indexed.h"
|
||||
|
||||
Arduino_Canvas_Indexed::Arduino_Canvas_Indexed(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, uint8_t r, uint8_t mask_level)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
|
||||
if (mask_level >= MAXMASKLEVEL)
|
||||
{
|
||||
mask_level = MAXMASKLEVEL - 1;
|
||||
}
|
||||
_current_mask_level = mask_level;
|
||||
_color_mask = mask_level_list[_current_mask_level];
|
||||
}
|
||||
|
||||
Arduino_Canvas_Indexed::~Arduino_Canvas_Indexed()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_Indexed::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = _width * _height;
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
uint8_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = idx;
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = idx;
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = idx;
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = idx;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, idx);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, idx);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, idx);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint8_t idx)
|
||||
{
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint8_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (h--)
|
||||
{
|
||||
*fb = idx;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, idx);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, idx);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, idx);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint8_t idx)
|
||||
{
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint8_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = idx;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
if (!_isDirectUseColorIndex)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t offset = 0;
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
writePixel(x + i, y, bitmap[offset++]);
|
||||
}
|
||||
offset += x_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
*((uint32_t *)&row[i]) = *((uint32_t *)bitmap);
|
||||
i += 4;
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
row[i++] = *bitmap++;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = get_color_index(color_index[*bitmap++]);
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
if (!_isDirectUseColorIndex)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, chroma_key, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t offset = 0;
|
||||
uint8_t color_key;
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
color_key = bitmap[offset++];
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
writePixel(x + i, y, color_key);
|
||||
}
|
||||
}
|
||||
offset += x_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
uint8_t color_key;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_key;
|
||||
}
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = get_color_index(color_index[color_key]);
|
||||
}
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->drawIndexedBitmap(_output_x, _output_y, _framebuffer, _color_index, WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_Indexed::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_Canvas_Indexed::getColorIndex()
|
||||
{
|
||||
return _color_index;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::setDirectUseColorIndex(bool isEnable)
|
||||
{
|
||||
_isDirectUseColorIndex = isEnable;
|
||||
}
|
||||
|
||||
uint8_t Arduino_Canvas_Indexed::get_color_index(uint16_t color)
|
||||
{
|
||||
color &= _color_mask;
|
||||
for (uint8_t i = 0; i < _indexed_size; i++)
|
||||
{
|
||||
if (_color_index[i] == color)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (_indexed_size == (COLOR_IDX_SIZE - 1)) // overflowed
|
||||
{
|
||||
raise_mask_level();
|
||||
}
|
||||
_color_index[_indexed_size] = color;
|
||||
// print("color_index[");
|
||||
// print(_indexed_size);
|
||||
// print("] = ");
|
||||
// println(color);
|
||||
return _indexed_size++;
|
||||
}
|
||||
|
||||
GFX_INLINE uint16_t Arduino_Canvas_Indexed::get_index_color(uint8_t idx)
|
||||
{
|
||||
return _color_index[idx];
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::raise_mask_level()
|
||||
{
|
||||
if ((_current_mask_level + 1) < MAXMASKLEVEL)
|
||||
{
|
||||
int32_t buffer_size = _width * _height;
|
||||
uint8_t old_indexed_size = _indexed_size;
|
||||
uint8_t new_color;
|
||||
_indexed_size = 0;
|
||||
_color_mask = mask_level_list[++_current_mask_level];
|
||||
// print("Raised mask level: ");
|
||||
// println(_current_mask_level);
|
||||
|
||||
// update _framebuffer color index, it is a time consuming job
|
||||
for (uint8_t old_color = 0; old_color < old_indexed_size; old_color++)
|
||||
{
|
||||
new_color = get_color_index(_color_index[old_color]);
|
||||
for (int32_t i = 0; i < buffer_size; i++)
|
||||
{
|
||||
if (_framebuffer[i] == old_color)
|
||||
{
|
||||
_framebuffer[i] = new_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_INDEXED_H_
|
||||
#define _ARDUINO_CANVAS_INDEXED_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
#define COLOR_IDX_SIZE 256
|
||||
|
||||
class Arduino_Canvas_Indexed : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_Indexed(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, uint8_t rotation = 0, uint8_t mask_level = 0);
|
||||
~Arduino_Canvas_Indexed();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint8_t idx);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint8_t idx);
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
uint16_t *getColorIndex();
|
||||
void setDirectUseColorIndex(bool isEnable);
|
||||
|
||||
uint8_t get_color_index(uint16_t color);
|
||||
uint16_t get_index_color(uint8_t idx);
|
||||
void raise_mask_level();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
int16_t MAX_X, MAX_Y;
|
||||
|
||||
uint16_t _color_index[COLOR_IDX_SIZE];
|
||||
uint8_t _indexed_size = 0;
|
||||
bool _isDirectUseColorIndex = false;
|
||||
|
||||
uint8_t _current_mask_level;
|
||||
uint16_t _color_mask;
|
||||
#define MAXMASKLEVEL 3
|
||||
uint16_t mask_level_list[MAXMASKLEVEL] = {
|
||||
0b1111111111111111, // 16-bit, 65536 colors
|
||||
0b1111011110011110, // 12-bit, 4096 colors
|
||||
0b1100011100011000 // 7-bit, 128 colors
|
||||
};
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_INDEXED_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_Mono.h"
|
||||
|
||||
Arduino_Canvas_Mono::Arduino_Canvas_Mono(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, bool verticalByte)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y), _verticalByte(verticalByte),
|
||||
_canvas_width(w), _canvas_height(h)
|
||||
{
|
||||
}
|
||||
|
||||
Arduino_Canvas_Mono::~Arduino_Canvas_Mono()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_Mono::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s;
|
||||
|
||||
// allocate memory by full bytes.
|
||||
if (_verticalByte)
|
||||
{
|
||||
s = _canvas_width * (_canvas_height + 7) / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = (_canvas_width + 7) / 8 * _canvas_height;
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Mono::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
// change the pixel in the original orientation of the bitmap buffer
|
||||
if (_verticalByte)
|
||||
{
|
||||
// vertical buffer layout: 1 byte in the buffer contains 8 vertical pixels
|
||||
int32_t pos = x + (y / 8) * _canvas_width;
|
||||
|
||||
if (color & 0b1000010000010000)
|
||||
{
|
||||
_framebuffer[pos] |= (1 << (y & 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[pos] &= ~(1 << (y & 7));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// horizontal buffer layout: 1 byte in the buffer contains 8 horizontal pixels
|
||||
int16_t w = (_canvas_width + 7) / 8;
|
||||
int32_t pos = (y * w) + (x / 8);
|
||||
|
||||
if (color & 0b1000010000010000)
|
||||
{
|
||||
_framebuffer[pos] |= 0x80 >> (x & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[pos] &= ~(0x80 >> (x & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Mono::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->drawBitmap(_output_x, _output_y, _framebuffer, _canvas_width, _canvas_height, RGB565_WHITE, RGB565_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_Mono::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_MONO_H_
|
||||
#define _ARDUINO_CANVAS_MONO_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas_Mono : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_Mono(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, bool verticalByte = false);
|
||||
~Arduino_Canvas_Mono();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
bool _verticalByte;
|
||||
int16_t _canvas_width, _canvas_height; // width and height of canvas buffer
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_MONO_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
15
libraries/GFX_Library_for_Arduino/src/canvas/readme.md
Normal file
15
libraries/GFX_Library_for_Arduino/src/canvas/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# About the canvas mono class of the GFX library
|
||||
|
||||
There are some Display Chips on the market that can display a small amount of graphic data but
|
||||
don't offer much functionality on it's own on other than data transfer. Examples are the OLED
|
||||
Displays Chips SSD1306 or SH1106.
|
||||
|
||||
These displays need an in memory copy of the graphics and updating the display is implemented by
|
||||
a bulk data transfer of the internal memory to the display.
|
||||
|
||||
Therefore the Canvas Mono class must be initialized in a way the internal memory fits to the
|
||||
memory inside the graphic driver chip including the width and height of the display memory and
|
||||
the orientation of a byte to either horizontal or vertical.
|
||||
|
||||
Bei changing the orientation of the canvas the graphics elements like lines or characters are positioned on the display memory accordingly. When the rotating in 90 or 270 degrees der width and height of the logical display will be swapped but not the memory organization.
|
||||
|
||||
Reference in New Issue
Block a user