in libs/screen/image.cpp [628:832]
bool drawImageCore(Image_ img, Image_ from, int x, int y, int color) {
auto w = from->width();
auto h = from->height();
auto sh = img->height();
auto sw = img->width();
if (x + w <= 0)
return false;
if (x >= sw)
return false;
if (y + h <= 0)
return false;
if (y >= sh)
return false;
auto len = y < 0 ? min(sh, h + y) : min(sh - y, h);
auto tbp = img->bpp();
auto fbp = from->bpp();
auto y0 = y;
if (color == -2 && x == 0 && y == 0 && tbp == fbp && w == sw && h == sh) {
copyFrom(img, from);
return false;
}
// DMESG("drawIMG(%d,%d) at (%d,%d) w=%d bh=%d len=%d",
// w,h,x, y, img->width(), img->byteHeight(), len );
auto fromH = from->byteHeight();
auto imgH = img->byteHeight();
auto fromBase = from->pix();
auto imgBase = img->pix(0, y);
#define LOOPHD \
for (int xx = 0; xx < w; ++xx, ++x) \
if (0 <= x && x < sw)
if (tbp == 4 && fbp == 4) {
auto wordH = fromH >> 2;
LOOPHD {
y = y0;
auto fdata = (uint32_t *)fromBase + wordH * xx;
auto tdata = imgBase + imgH * x;
// DMESG("%d,%d xx=%d/%d - %p (%p) -- %d",x,y,xx,w,tdata,img->pix(),
// (uint8_t*)fdata - from->pix());
auto cnt = wordH;
auto bot = min(sh, y + h);
#define COLS(s) ((v >> (s)) & 0xf)
#define COL(s) COLS(s)
#define STEPA(s) \
if (COL(s) && 0 <= y && y < bot) \
SETLOW(s); \
y++;
#define STEPB(s) \
if (COL(s) && 0 <= y && y < bot) \
SETHIGH(s); \
y++; \
tdata++;
#define STEPAQ(s) \
if (COL(s)) \
SETLOW(s);
#define STEPBQ(s) \
if (COL(s)) \
SETHIGH(s); \
tdata++;
// perf: expanded version 5% faster
#define ORDER(A, B) \
A(0); \
B(4); \
A(8); \
B(12); \
A(16); \
B(20); \
A(24); \
B(28)
//#define ORDER(A,B) for (int k = 0; k < 32; k += 8) { A(k); B(4+k); }
#define LOOP(A, B, xbot) \
while (cnt--) { \
auto v = *fdata++; \
if (0 <= y && y <= xbot - 8) { \
ORDER(A##Q, B##Q); \
y += 8; \
} else { \
ORDER(A, B); \
} \
}
#define LOOPS(xbot) \
if (y & 1) \
LOOP(STEPB, STEPA, xbot) \
else \
LOOP(STEPA, STEPB, xbot)
if (color >= 0) {
#define SETHIGH(s) *tdata = (*tdata & 0x0f) | ((COLS(s)) << 4)
#define SETLOW(s) *tdata = (*tdata & 0xf0) | COLS(s)
LOOPS(sh)
} else if (color == -2) {
#undef COL
#define COL(s) 1
LOOPS(bot)
} else {
#undef COL
#define COL(s) COLS(s)
#undef SETHIGH
#define SETHIGH(s) \
if (*tdata & 0xf0) \
return true
#undef SETLOW
#define SETLOW(s) \
if (*tdata & 0x0f) \
return true
LOOPS(sh)
}
}
} else if (tbp == 1 && fbp == 1) {
auto left = img->pix() - imgBase;
auto right = img->pix(0, img->height() - 1) - imgBase;
LOOPHD {
y = y0;
auto data = fromBase + fromH * xx;
auto off = imgBase + imgH * x;
auto off0 = off + left;
auto off1 = off + right;
int shift = (y & 7);
int y1 = y + h + (y & 7);
int prev = 0;
while (y < y1 - 8) {
int curr = *data++ << shift;
if (off0 <= off && off <= off1) {
uint8_t v = (curr >> 0) | (prev >> 8);
if (color == -1) {
if (*off & v)
return true;
} else {
*off |= v;
}
}
off++;
prev = curr;
y += 8;
}
int left = y1 - y;
if (left > 0) {
int curr = *data << shift;
if (off0 <= off && off <= off1) {
uint8_t v = ((curr >> 0) | (prev >> 8)) & (0xff >> (8 - left));
if (color == -1) {
if (*off & v)
return true;
} else {
*off |= v;
}
}
}
}
} else if (tbp == 4 && fbp == 1) {
if (y < 0) {
fromBase = from->pix(0, -y);
imgBase = img->pix();
}
// icon mode
LOOPHD {
auto fdata = fromBase + fromH * xx;
auto tdata = imgBase + imgH * x;
unsigned mask = 0x01;
auto v = *fdata++;
int off = (y & 1) ? 1 : 0;
if (y < 0) {
mask <<= -y & 7;
off = 0;
}
for (int i = off; i < len + off; ++i) {
if (mask == 0x100) {
mask = 0x01;
v = *fdata++;
}
if (v & mask) {
if (i & 1)
*tdata = (*tdata & 0x0f) | (color << 4);
else
*tdata = (*tdata & 0xf0) | color;
}
mask <<= 1;
if (i & 1)
tdata++;
}
}
}
return false;
}