Add separate type for Icons (same repr as buffer)
This commit is contained in:
		@@ -27,6 +27,9 @@ class MMap : public RefObject {
 | 
			
		||||
 | 
			
		||||
extern volatile bool paniced;
 | 
			
		||||
 | 
			
		||||
// Buffer and Icon share representation.
 | 
			
		||||
typedef Buffer Icon;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -27,7 +27,7 @@ namespace screen {
 | 
			
		||||
        currFont = f
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export const heart = hex`f007 367f7f3e1c08`
 | 
			
		||||
    export const heart = iconOf(hex`f007 367f7f3e1c08`)
 | 
			
		||||
 | 
			
		||||
    export function defaultFont(): Font {
 | 
			
		||||
        return {
 | 
			
		||||
@@ -112,6 +112,7 @@ namespace screen {
 | 
			
		||||
        let byteWidth = (currFont.charWidth + 7) >> 3
 | 
			
		||||
        let charSize = byteWidth * currFont.charHeight
 | 
			
		||||
        let iconBuf = output.createBuffer(2 + charSize)
 | 
			
		||||
        let icon = iconOf(iconBuf)
 | 
			
		||||
        let double = (mode & Draw.Quad) ? 4 : (mode & Draw.Double) ? 2 : 1
 | 
			
		||||
        iconBuf[0] = 0xf0
 | 
			
		||||
        iconBuf[1] = currFont.charWidth
 | 
			
		||||
@@ -127,7 +128,7 @@ namespace screen {
 | 
			
		||||
                iconBuf.fill(0, 2)
 | 
			
		||||
            else
 | 
			
		||||
                iconBuf.write(2, currFont.data.slice(idx, charSize))
 | 
			
		||||
            drawIcon(x, y, iconBuf, mode)
 | 
			
		||||
            icon.draw(x, y, mode)
 | 
			
		||||
            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 {
 | 
			
		||||
 | 
			
		||||
    /** 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. */
 | 
			
		||||
    //% shim=screen::clear
 | 
			
		||||
    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 {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ screen.print("PXT!", 10, 30, Draw.Quad)
 | 
			
		||||
screen.drawRect(40, 40, 20, 10, Draw.Fill)
 | 
			
		||||
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, () => {
 | 
			
		||||
    screen.clear()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user