Add separate type for Icons (same repr as buffer)
This commit is contained in:
parent
c085094394
commit
f6e350cf9f
@ -27,6 +27,9 @@ class MMap : public RefObject {
|
|||||||
|
|
||||||
extern volatile bool paniced;
|
extern volatile bool paniced;
|
||||||
|
|
||||||
|
// Buffer and Icon share representation.
|
||||||
|
typedef Buffer Icon;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEVICE_EVT_ANY 0
|
#define DEVICE_EVT_ANY 0
|
||||||
|
@ -130,82 +130,6 @@ void _blitLine(int xw, int y, Buffer buf, Draw mode) {
|
|||||||
blitLineCore(XX(xw), y, YY(xw), buf->data, 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. */
|
/** Clear screen and reset font to normal. */
|
||||||
//%
|
//%
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -309,11 +233,23 @@ extern "C" void drawPanic(int code) {
|
|||||||
updateLCD();
|
updateLCD();
|
||||||
|
|
||||||
int fd = open("/dev/lms_ui", O_RDWR);
|
int fd = open("/dev/lms_ui", O_RDWR);
|
||||||
uint8_t cmd[] = { 48 + 5, 0 };
|
uint8_t cmd[] = {48 + 5, 0};
|
||||||
write(fd, cmd, 2);
|
write(fd, cmd, 2);
|
||||||
close(fd);
|
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 {
|
namespace pxt {
|
||||||
@ -321,3 +257,105 @@ void screen_init() {
|
|||||||
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);
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ namespace screen {
|
|||||||
currFont = f
|
currFont = f
|
||||||
}
|
}
|
||||||
|
|
||||||
export const heart = hex`f007 367f7f3e1c08`
|
export const heart = iconOf(hex`f007 367f7f3e1c08`)
|
||||||
|
|
||||||
export function defaultFont(): Font {
|
export function defaultFont(): Font {
|
||||||
return {
|
return {
|
||||||
@ -112,6 +112,7 @@ namespace screen {
|
|||||||
let byteWidth = (currFont.charWidth + 7) >> 3
|
let byteWidth = (currFont.charWidth + 7) >> 3
|
||||||
let charSize = byteWidth * currFont.charHeight
|
let charSize = byteWidth * currFont.charHeight
|
||||||
let iconBuf = output.createBuffer(2 + charSize)
|
let iconBuf = output.createBuffer(2 + charSize)
|
||||||
|
let icon = iconOf(iconBuf)
|
||||||
let double = (mode & Draw.Quad) ? 4 : (mode & Draw.Double) ? 2 : 1
|
let double = (mode & Draw.Quad) ? 4 : (mode & Draw.Double) ? 2 : 1
|
||||||
iconBuf[0] = 0xf0
|
iconBuf[0] = 0xf0
|
||||||
iconBuf[1] = currFont.charWidth
|
iconBuf[1] = currFont.charWidth
|
||||||
@ -127,7 +128,7 @@ namespace screen {
|
|||||||
iconBuf.fill(0, 2)
|
iconBuf.fill(0, 2)
|
||||||
else
|
else
|
||||||
iconBuf.write(2, currFont.data.slice(idx, charSize))
|
iconBuf.write(2, currFont.data.slice(idx, charSize))
|
||||||
drawIcon(x, y, iconBuf, mode)
|
icon.draw(x, y, mode)
|
||||||
x += double * currFont.charWidth
|
x += double * currFont.charWidth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
libs/core/shims.d.ts
vendored
35
libs/core/shims.d.ts
vendored
@ -78,17 +78,36 @@ declare namespace screen {
|
|||||||
}
|
}
|
||||||
declare namespace screen {
|
declare namespace screen {
|
||||||
|
|
||||||
/** Double size of an icon. */
|
|
||||||
//% shim=screen::doubleIcon
|
|
||||||
function doubleIcon(buf: Buffer): Buffer;
|
|
||||||
|
|
||||||
/** Draw an icon on the screen. */
|
|
||||||
//% shim=screen::drawIcon
|
|
||||||
function drawIcon(x: int32, y: int32, buf: Buffer, mode: Draw): void;
|
|
||||||
|
|
||||||
/** Clear screen and reset font to normal. */
|
/** Clear screen and reset font to normal. */
|
||||||
//% shim=screen::clear
|
//% shim=screen::clear
|
||||||
function clear(): void;
|
function clear(): void;
|
||||||
|
|
||||||
|
/** Makes an icon bound to a buffer. */
|
||||||
|
//% shim=screen::iconOf
|
||||||
|
function iconOf(buf: Buffer): Icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
declare interface Icon {
|
||||||
|
/** Returns the underlaying Buffer object. */
|
||||||
|
//% property shim=IconMethods::buffer
|
||||||
|
buffer: Buffer;
|
||||||
|
|
||||||
|
/** Returns the width of an icon. */
|
||||||
|
//% property shim=IconMethods::width
|
||||||
|
width: int32;
|
||||||
|
|
||||||
|
/** Returns the height of an icon. */
|
||||||
|
//% property shim=IconMethods::height
|
||||||
|
height: int32;
|
||||||
|
|
||||||
|
/** Double size of an icon. */
|
||||||
|
//% shim=IconMethods::doubled
|
||||||
|
doubled(): Icon;
|
||||||
|
|
||||||
|
/** Draw an icon on the screen. */
|
||||||
|
//% shim=IconMethods::draw
|
||||||
|
draw(x: int32, y: int32, mode: Draw): void;
|
||||||
}
|
}
|
||||||
declare namespace output {
|
declare namespace output {
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ screen.print("PXT!", 10, 30, Draw.Quad)
|
|||||||
screen.drawRect(40, 40, 20, 10, Draw.Fill)
|
screen.drawRect(40, 40, 20, 10, Draw.Fill)
|
||||||
output.setStatusLight(LightsPattern.Orange)
|
output.setStatusLight(LightsPattern.Orange)
|
||||||
|
|
||||||
screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent)
|
screen.heart.doubled().draw(100, 50, Draw.Double | Draw.Transparent)
|
||||||
|
|
||||||
input.buttonEnter.onEvent(ButtonEvent.Click, () => {
|
input.buttonEnter.onEvent(ButtonEvent.Click, () => {
|
||||||
screen.clear()
|
screen.clear()
|
||||||
|
Loading…
Reference in New Issue
Block a user