Add separate type for Icons (same repr as buffer)
This commit is contained in:
@ -130,82 +130,6 @@ void _blitLine(int xw, int y, Buffer buf, Draw mode) {
|
||||
blitLineCore(XX(xw), y, YY(xw), buf->data, mode);
|
||||
}
|
||||
|
||||
static uint8_t ones[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
bool isValidIcon(Buffer buf) {
|
||||
return buf->length >= 3 && buf->data[0] == 0xf0;
|
||||
}
|
||||
|
||||
static const uint8_t bitdouble[] = {
|
||||
0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
|
||||
};
|
||||
|
||||
/** Double size of an icon. */
|
||||
//%
|
||||
Buffer doubleIcon(Buffer buf) {
|
||||
if (!isValidIcon(buf))
|
||||
return NULL;
|
||||
int w = buf->data[1];
|
||||
if (w > 126)
|
||||
return NULL;
|
||||
int bw = PIX2BYTES(w);
|
||||
int h = (buf->length - 2) / bw;
|
||||
int bw2 = PIX2BYTES(w * 2);
|
||||
Buffer out = mkBuffer(NULL, 2 + bw2 * h * 2);
|
||||
out->data[0] = 0xf0;
|
||||
out->data[1] = w * 2;
|
||||
uint8_t *src = buf->data + 2;
|
||||
uint8_t *dst = out->data + 2;
|
||||
for (int i = 0; i < h; ++i) {
|
||||
for (int jj = 0; jj < 2; ++jj) {
|
||||
auto p = src;
|
||||
for (int j = 0; j < bw; ++j) {
|
||||
*dst++ = bitdouble[*p & 0xf];
|
||||
*dst++ = bitdouble[*p >> 4];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
src += bw;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Draw an icon on the screen. */
|
||||
//%
|
||||
void drawIcon(int x, int y, Buffer buf, Draw mode) {
|
||||
if (!isValidIcon(buf))
|
||||
return;
|
||||
if (mode & (Draw::Double | Draw::Quad)) {
|
||||
buf = doubleIcon(buf);
|
||||
if (mode & Draw::Quad) {
|
||||
auto pbuf = buf;
|
||||
buf = doubleIcon(buf);
|
||||
decrRC(pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
int pixwidth = buf->data[1];
|
||||
int ptr = 2;
|
||||
int bytewidth = PIX2BYTES(pixwidth);
|
||||
pixwidth = min(pixwidth, LCD_WIDTH);
|
||||
while (ptr + bytewidth <= buf->length) {
|
||||
if (mode & (Draw::Clear | Draw::Xor | Draw::Transparent)) {
|
||||
// no erase of background
|
||||
} else {
|
||||
blitLineCore(x, y, pixwidth, ones, Draw::Clear);
|
||||
}
|
||||
blitLineCore(x, y, pixwidth, &buf->data[ptr], mode);
|
||||
y++;
|
||||
ptr += bytewidth;
|
||||
}
|
||||
|
||||
if (mode & Draw::Double)
|
||||
decrRC(buf);
|
||||
}
|
||||
|
||||
/** Clear screen and reset font to normal. */
|
||||
//%
|
||||
void clear() {
|
||||
@ -309,11 +233,23 @@ extern "C" void drawPanic(int code) {
|
||||
updateLCD();
|
||||
|
||||
int fd = open("/dev/lms_ui", O_RDWR);
|
||||
uint8_t cmd[] = { 48 + 5, 0 };
|
||||
uint8_t cmd[] = {48 + 5, 0};
|
||||
write(fd, cmd, 2);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
bool isValidIcon(Buffer buf) {
|
||||
return buf->length >= 3 && buf->data[0] == 0xf0;
|
||||
}
|
||||
|
||||
/** Makes an icon bound to a buffer. */
|
||||
//%
|
||||
Icon iconOf(Buffer buf) {
|
||||
if (!isValidIcon(buf))
|
||||
return NULL;
|
||||
incrRC(buf);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
namespace pxt {
|
||||
@ -321,3 +257,105 @@ void screen_init() {
|
||||
screen::init();
|
||||
}
|
||||
}
|
||||
|
||||
//% fixedInstances
|
||||
namespace IconMethods {
|
||||
|
||||
using namespace screen;
|
||||
|
||||
static const uint8_t bitdouble[] = {
|
||||
0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
|
||||
};
|
||||
|
||||
static uint8_t ones[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
/** Returns the underlaying Buffer object. */
|
||||
//% property
|
||||
Buffer buffer(Icon ic) {
|
||||
incrRC(ic);
|
||||
return ic;
|
||||
}
|
||||
|
||||
/** Returns the width of an icon. */
|
||||
//% property
|
||||
int width(Icon ic) {
|
||||
if (!isValidIcon(ic))
|
||||
return 0;
|
||||
return ic->data[1];
|
||||
}
|
||||
|
||||
/** Returns the height of an icon. */
|
||||
//% property
|
||||
int height(Icon ic) {
|
||||
if (!isValidIcon(ic))
|
||||
return 0;
|
||||
int bw = PIX2BYTES(ic->data[1]);
|
||||
return (ic->length - 2) / bw;
|
||||
}
|
||||
|
||||
/** Double size of an icon. */
|
||||
//%
|
||||
Icon doubled(Icon buf) {
|
||||
if (!isValidIcon(buf))
|
||||
return NULL;
|
||||
int w = buf->data[1];
|
||||
if (w > 126)
|
||||
return NULL;
|
||||
int bw = PIX2BYTES(w);
|
||||
int h = (buf->length - 2) / bw;
|
||||
int bw2 = PIX2BYTES(w * 2);
|
||||
Buffer out = mkBuffer(NULL, 2 + bw2 * h * 2);
|
||||
out->data[0] = 0xf0;
|
||||
out->data[1] = w * 2;
|
||||
uint8_t *src = buf->data + 2;
|
||||
uint8_t *dst = out->data + 2;
|
||||
for (int i = 0; i < h; ++i) {
|
||||
for (int jj = 0; jj < 2; ++jj) {
|
||||
auto p = src;
|
||||
for (int j = 0; j < bw; ++j) {
|
||||
*dst++ = bitdouble[*p & 0xf];
|
||||
*dst++ = bitdouble[*p >> 4];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
src += bw;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Draw an icon on the screen. */
|
||||
//%
|
||||
void draw(Icon buf, int x, int y, Draw mode) {
|
||||
if (!isValidIcon(buf))
|
||||
return;
|
||||
if (mode & (Draw::Double | Draw::Quad)) {
|
||||
buf = doubled(buf);
|
||||
if (mode & Draw::Quad) {
|
||||
auto pbuf = buf;
|
||||
buf = doubled(buf);
|
||||
decrRC(pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
int pixwidth = buf->data[1];
|
||||
int ptr = 2;
|
||||
int bytewidth = PIX2BYTES(pixwidth);
|
||||
pixwidth = min(pixwidth, LCD_WIDTH);
|
||||
while (ptr + bytewidth <= buf->length) {
|
||||
if (mode & (Draw::Clear | Draw::Xor | Draw::Transparent)) {
|
||||
// no erase of background
|
||||
} else {
|
||||
blitLineCore(x, y, pixwidth, ones, Draw::Clear);
|
||||
}
|
||||
blitLineCore(x, y, pixwidth, &buf->data[ptr], mode);
|
||||
y++;
|
||||
ptr += bytewidth;
|
||||
}
|
||||
|
||||
if (mode & (Draw::Double | Draw::Quad))
|
||||
decrRC(buf);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user