Move some big template methods into .cpp with explicit instantiation

This commit is contained in:
Raphael Coeffic
2021-05-07 22:41:43 +02:00
parent 7510577dfc
commit 347bc76b2b
2 changed files with 223 additions and 188 deletions
+211 -1
View File
@@ -25,7 +25,217 @@
#include "libopenui_file.h"
#include "font.h"
void BitmapBuffer::drawAlphaPixel(pixel_t * p, uint8_t opacity, uint16_t color)
RLEBitmap::RLEBitmap(uint8_t format, const uint8_t* rle_data) :
BitmapBufferBase<uint16_t>(format, 0, 0, nullptr)
{
_width = *((uint16_t *)rle_data);
_height = *(((uint16_t *)rle_data)+1);
uint32_t pixels = _width * _height;
data = (uint16_t*)malloc(align32(pixels * sizeof(uint16_t)));
decode((uint8_t *)data, pixels * sizeof(uint16_t), rle_data+4);
data_end = data + pixels;
}
RLEBitmap::~RLEBitmap()
{
free(data);
}
int RLEBitmap::decode(uint8_t *dest, unsigned int destSize, const uint8_t *src)
{
uint8_t prevByte = 0;
bool prevByteValid = false;
const uint8_t *destEnd = dest + destSize;
uint8_t *d = dest;
while (d < destEnd) {
uint8_t byte = *src++;
*d++ = byte;
if (prevByteValid && byte == prevByte) {
uint8_t count = *src++;
if (d + count > destEnd) {
TRACE("rle_decode_8bit: destination overflow!\n");
return -1;
}
memset(d, byte, count);
d += count;
prevByteValid = false;
} else {
prevByte = byte;
prevByteValid = true;
}
}
return d - dest;
}
BitmapBuffer::BitmapBuffer(uint8_t format, uint16_t width, uint16_t height) :
BitmapBufferBase<uint16_t>(format, width, height, nullptr),
dataAllocated(true)
#if defined(DEBUG)
, leakReported(false)
#endif
{
data = (uint16_t *)malloc(align32(width * height * sizeof(uint16_t)));
data_end = data + (width * height);
}
BitmapBuffer::BitmapBuffer(uint8_t format, uint16_t width, uint16_t height,
uint16_t *data) :
BitmapBufferBase<uint16_t>(format, width, height, data),
dataAllocated(false)
#if defined(DEBUG)
, leakReported(false)
#endif
{
}
BitmapBuffer::~BitmapBuffer()
{
if (dataAllocated) {
free(data);
}
}
template <class T>
void BitmapBuffer::drawBitmap(coord_t x, coord_t y, const T *bmp, coord_t srcx,
coord_t srcy, coord_t srcw, coord_t srch,
float scale)
{
if (!data || !bmp) return;
APPLY_OFFSET();
if (x >= xmax || y >= ymax) return;
drawBitmapAbs<T>(x, y, bmp, srcx, srcy, srcw, srch, scale);
}
template void BitmapBuffer::drawBitmap(
coord_t, coord_t, BitmapBufferBase<unsigned short const> const *, coord_t,
coord_t, coord_t, coord_t, float);
template void BitmapBuffer::drawBitmap(coord_t, coord_t, const BitmapBuffer *,
coord_t, coord_t, coord_t, coord_t,
float);
template void BitmapBuffer::drawBitmap(coord_t, coord_t, const RLEBitmap *,
coord_t, coord_t, coord_t, coord_t,
float);
template <class T>
void BitmapBuffer::drawScaledBitmap(const T *bitmap, coord_t x, coord_t y,
coord_t w, coord_t h)
{
if (bitmap) {
float vscale = float(h) / bitmap->height();
float hscale = float(w) / bitmap->width();
float scale = vscale < hscale ? vscale : hscale;
int xshift = (w - (bitmap->width() * scale)) / 2;
int yshift = (h - (bitmap->height() * scale)) / 2;
drawBitmap(x + xshift, y + yshift, bitmap, 0, 0, 0, 0, scale);
}
}
template void BitmapBuffer::drawScaledBitmap(const BitmapBuffer *, coord_t,
coord_t, coord_t, coord_t);
template <class T>
void BitmapBuffer::drawBitmapAbs(coord_t x, coord_t y, const T *bmp,
coord_t srcx, coord_t srcy,
coord_t srcw, coord_t srch,
float scale)
{
coord_t bmpw = bmp->width();
coord_t bmph = bmp->height();
if (srcw == 0) srcw = bmpw;
if (srch == 0) srch = bmph;
if (srcx + srcw > bmpw) srcw = bmpw - srcx;
if (srcy + srch > bmph) srch = bmph - srcy;
if (scale == 0) {
if (x < xmin) {
srcw += x - xmin;
srcx -= x - xmin;
x = xmin;
}
if (y < ymin) {
srch += y - ymin;
srcy -= y - ymin;
y = ymin;
}
if (x + srcw > xmax) {
srcw = xmax - x;
}
if (y + srch > ymax) {
srch = ymax - y;
}
} else {
if (x < xmin) {
srcw += (x - xmin) / scale;
srcx -= (x - xmin) / scale;
x = xmin;
}
if (y < ymin) {
srch += (y - ymin) / scale;
srcy -= (y - ymin) / scale;
y = ymin;
}
if (x + srcw * scale > xmax) {
srcw = (xmax - x) / scale;
}
if (y + srch * scale > ymax) {
srch = (ymax - y) / scale;
}
}
if (srcw <= 0 || srch <= 0) {
return;
}
if (scale == 0) {
if (bmp->getFormat() == BMP_ARGB4444) {
DMACopyAlphaBitmap(data, _width, _height, x, y, bmp->getData(), bmpw,
bmph, srcx, srcy, srcw, srch);
} else {
DMACopyBitmap(data, _width, _height, x, y, bmp->getData(), bmpw, bmph,
srcx, srcy, srcw, srch);
}
} else {
int scaledw = srcw * scale;
int scaledh = srch * scale;
if (x + scaledw > _width) scaledw = _width - x;
if (y + scaledh > _height) scaledh = _height - y;
for (int i = 0; i < scaledh; i++) {
pixel_t *p = getPixelPtrAbs(x, y + i);
const pixel_t *qstart = bmp->getPixelPtrAbs(srcx, srcy + int(i / scale));
for (int j = 0; j < scaledw; j++) {
const pixel_t *q = qstart;
MOVE_PIXEL_RIGHT(q, int(j / scale));
if (bmp->getFormat() == BMP_ARGB4444) {
ARGB_SPLIT(*q, a, r, g, b);
drawAlphaPixel(p, a, RGB_JOIN(r << 1, g << 2, b << 1));
} else {
drawPixel(p, *q);
}
MOVE_TO_NEXT_RIGHT_PIXEL(p);
}
}
}
}
template
void BitmapBuffer::drawBitmapAbs(coord_t, coord_t, const BitmapBuffer *,
coord_t srcx, coord_t srcy,
coord_t srcw, coord_t srch,
float scale);
void BitmapBuffer::drawAlphaPixel(pixel_t *p, uint8_t opacity, uint16_t color)
{
if (opacity == OPACITY_MAX) {
drawPixel(p, color);
+12 -187
View File
@@ -183,54 +183,10 @@ class RLEBitmap:
public BitmapBufferBase<uint16_t>
{
public:
RLEBitmap(uint8_t format, const uint8_t* rle_data) :
BitmapBufferBase<uint16_t>(format, 0, 0, nullptr)
{
_width = *((uint16_t *)rle_data);
_height = *(((uint16_t *)rle_data)+1);
uint32_t pixels = _width * _height;
data = (uint16_t*)malloc(align32(pixels * sizeof(uint16_t)));
decode((uint8_t *)data, pixels * sizeof(uint16_t), rle_data+4);
data_end = data + pixels;
}
RLEBitmap(uint8_t format, const uint8_t* rle_data);
~RLEBitmap();
~RLEBitmap()
{
free(data);
}
static int decode(uint8_t * dest, unsigned int destSize, const uint8_t * src)
{
uint8_t prevByte = 0;
bool prevByteValid = false;
const uint8_t * destEnd = dest + destSize;
uint8_t * d = dest;
while (d < destEnd) {
uint8_t byte = *src++;
*d++ = byte;
if (prevByteValid && byte == prevByte) {
uint8_t count = *src++;
if (d + count > destEnd) {
TRACE("rle_decode_8bit: destination overflow!\n");
return -1;
}
memset(d, byte, count);
d += count;
prevByteValid = false;
}
else {
prevByte = byte;
prevByteValid = true;
}
}
return d - dest;
}
static int decode(uint8_t * dest, unsigned int destSize, const uint8_t * src);
};
class BitmapBuffer: public BitmapBufferBase<pixel_t>
@@ -242,32 +198,10 @@ class BitmapBuffer: public BitmapBufferBase<pixel_t>
#endif
public:
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height):
BitmapBufferBase<uint16_t>(format, width, height, nullptr),
dataAllocated(true)
#if defined(DEBUG)
, leakReported(false)
#endif
{
data = (uint16_t *)malloc(align32(width * height * sizeof(uint16_t)));
data_end = data + (width * height);
}
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height);
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height, uint16_t * data);
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height, uint16_t * data):
BitmapBufferBase<uint16_t>(format, width, height, data),
dataAllocated(false)
#if defined(DEBUG)
, leakReported(false)
#endif
{
}
~BitmapBuffer()
{
if (dataAllocated) {
free(data);
}
}
~BitmapBuffer();
inline void setFormat(uint8_t format)
{
@@ -384,32 +318,10 @@ class BitmapBuffer: public BitmapBufferBase<pixel_t>
coord_t drawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags = 0, uint8_t len = 0, const char * prefix = nullptr, const char * suffix = nullptr);
template<class T>
void drawBitmap(coord_t x, coord_t y, const T * bmp, coord_t srcx = 0, coord_t srcy = 0, coord_t srcw = 0, coord_t srch = 0, float scale = 0)
{
if (!data || !bmp)
return;
APPLY_OFFSET();
if (x >= xmax || y >= ymax)
return;
drawBitmapAbs<T>(x, y, bmp, srcx, srcy, srcw, srch, scale);
}
void drawBitmap(coord_t x, coord_t y, const T * bmp, coord_t srcx = 0, coord_t srcy = 0, coord_t srcw = 0, coord_t srch = 0, float scale = 0);
template<class T>
void drawScaledBitmap(const T * bitmap, coord_t x, coord_t y, coord_t w, coord_t h)
{
if (bitmap) {
float vscale = float(h) / bitmap->height();
float hscale = float(w) / bitmap->width();
float scale = vscale < hscale ? vscale : hscale;
int xshift = (w - (bitmap->width() * scale)) / 2;
int yshift = (h - (bitmap->height() * scale)) / 2;
drawBitmap(x + xshift, y + yshift, bitmap, 0, 0, 0, 0, scale);
}
}
void drawScaledBitmap(const T * bitmap, coord_t x, coord_t y, coord_t w, coord_t h);
BitmapBuffer * horizontalFlip() const;
@@ -455,97 +367,10 @@ class BitmapBuffer: public BitmapBufferBase<pixel_t>
return data && h > 0 && w > 0;
}
template<class T>
void drawBitmapAbs(coord_t x, coord_t y, const T * bmp, coord_t srcx = 0, coord_t srcy = 0, coord_t srcw = 0, coord_t srch = 0, float scale = 0)
{
coord_t bmpw = bmp->width();
coord_t bmph = bmp->height();
if (srcw == 0)
srcw = bmpw;
if (srch == 0)
srch = bmph;
if (srcx + srcw > bmpw)
srcw = bmpw - srcx;
if (srcy + srch > bmph)
srch = bmph - srcy;
if (scale == 0) {
if (x < xmin) {
srcw += x - xmin;
srcx -= x - xmin;
x = xmin;
}
if (y < ymin) {
srch += y - ymin;
srcy -= y - ymin;
y = ymin;
}
if (x + srcw > xmax) {
srcw = xmax - x;
}
if (y + srch > ymax) {
srch = ymax - y;
}
}
else {
if (x < xmin) {
srcw += (x - xmin) / scale;
srcx -= (x - xmin) / scale;
x = xmin;
}
if (y < ymin) {
srch += (y - ymin) / scale;
srcy -= (y - ymin) / scale;
y = ymin;
}
if (x + srcw * scale > xmax) {
srcw = (xmax - x) / scale;
}
if (y + srch * scale > ymax) {
srch = (ymax - y) / scale;
}
}
if (srcw <= 0 || srch <= 0) {
return;
}
if (scale == 0) {
if (bmp->getFormat() == BMP_ARGB4444) {
DMACopyAlphaBitmap(data, _width, _height, x, y, bmp->getData(), bmpw, bmph, srcx, srcy, srcw, srch);
}
else {
DMACopyBitmap(data, _width, _height, x, y, bmp->getData(), bmpw, bmph, srcx, srcy, srcw, srch);
}
}
else {
int scaledw = srcw * scale;
int scaledh = srch * scale;
if (x + scaledw > _width)
scaledw = _width - x;
if (y + scaledh > _height)
scaledh = _height - y;
for (int i = 0; i < scaledh; i++) {
pixel_t * p = getPixelPtrAbs(x, y + i);
const pixel_t * qstart = bmp->getPixelPtrAbs(srcx, srcy + int(i / scale));
for (int j = 0; j < scaledw; j++) {
const pixel_t * q = qstart;
MOVE_PIXEL_RIGHT(q, int(j / scale));
if (bmp->getFormat() == BMP_ARGB4444) {
ARGB_SPLIT(*q, a, r, g, b);
drawAlphaPixel(p, a, RGB_JOIN(r<<1, g<<2, b<<1));
}
else {
drawPixel(p, *q);
}
MOVE_TO_NEXT_RIGHT_PIXEL(p);
}
}
}
}
template <class T>
void drawBitmapAbs(coord_t x, coord_t y, const T* bmp, coord_t srcx = 0,
coord_t srcy = 0, coord_t srcw = 0, coord_t srch = 0,
float scale = 0);
uint8_t drawChar(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, unsigned int index, LcdFlags flags);