diff --git a/source/jsffi.c b/source/jsffi.c index 2b575a2a..045c6681 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -6,6 +6,7 @@ #include "stb_rect_pack.h" #define STB_DXT_IMPLEMENTATION #include "stb_dxt.h" +#include "stb_image_write.h" #include "string.h" #include "spline.h" #include @@ -5597,8 +5598,8 @@ JSC_CCALL(surface_pitch, static const JSCFunctionListEntry js_SDL_Surface_funcs[] = { MIST_FUNC_DEF(surface, blit, 3), MIST_FUNC_DEF(surface, scale, 1), - MIST_FUNC_DEF(surface,fill,1), - MIST_FUNC_DEF(surface,rect,2), + MIST_FUNC_DEF(surface, fill,1), + MIST_FUNC_DEF(surface, rect,2), MIST_FUNC_DEF(surface, dup, 0), MIST_FUNC_DEF(surface, pixels, 0), MIST_FUNC_DEF(surface, convert, 1), @@ -7298,6 +7299,19 @@ JSC_CCALL(graphics_hsl_to_rgb, return color2js(js, (colorf){r+m, g+m, b+m, 1}); ) +JSC_CCALL(graphics_save_png, + const char *file = JS_ToCString(js, argv[0]); + int w, h, comp, pitch; + JS_ToInt32(js, &w, argv[1]); + JS_ToInt32(js, &h, argv[2]); + JS_ToInt32(js, &pitch, argv[4]); + size_t size; + void *data = JS_GetArrayBuffer(js, &size, argv[3]); + + if (!stbi_write_png(file, w, h, 4, data, pitch)) + return JS_ThrowInternalError(js, "Could not write png"); +) + static const JSCFunctionListEntry js_graphics_funcs[] = { MIST_FUNC_DEF(gpu, make_sprite_mesh, 2), MIST_FUNC_DEF(gpu, make_sprite_queue, 4), @@ -7314,6 +7328,7 @@ static const JSCFunctionListEntry js_graphics_funcs[] = { MIST_FUNC_DEF(os, make_sprite, 1), MIST_FUNC_DEF(os, make_line_prim, 5), MIST_FUNC_DEF(graphics, hsl_to_rgb, 3), + MIST_FUNC_DEF(graphics, save_png, 4), }; static const JSCFunctionListEntry js_video_funcs[] = { diff --git a/source/qjs_qr.c b/source/qjs_qr.c index c3b4809a..3e14775d 100644 --- a/source/qjs_qr.c +++ b/source/qjs_qr.c @@ -5,6 +5,7 @@ #include // for sqrt #include // for size_t, etc. #include // for memcpy, strcmp +#include #include @@ -18,10 +19,27 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa int version = 0; // 0 means auto-select in qrencode int errc = QR_ECLEVEL_L; // Default to "L" int casesensitive = 1; // Default to true (qrencode treats 1 as case-sensitive) + int use_byte_mode = 0; // Handle options object (argv[1]) if (argc > 1 && !JS_IsUndefined(argv[1]) && JS_IsObject(argv[1])) { JSValue opt = argv[1]; + + JSValue m = JS_GetPropertyStr(js, opt, "mode"); + if (!JS_IsUndefined(m)) { + const char *smode = JS_ToCString(js, m); + if (!smode) { JS_FreeValue(js, m); return JS_EXCEPTION; } + if (!strcasecmp(smode, "byte") || !strcasecmp(smode, "binary")) + use_byte_mode = 1; + else if (!strcasecmp(smode, "text")) + use_byte_mode = 0; + else { + JS_FreeCString(js, smode); JS_FreeValue(js, m); + return JS_ThrowRangeError(js, "mode must be 'byte' or 'text'"); + } + JS_FreeCString(js, smode); + JS_FreeValue(js, m); + } // Version (1-40) JSValue v = JS_GetPropertyStr(js, opt, "version"); @@ -75,14 +93,14 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa int must_free_data = 0; // Handle string input - if (JS_IsString(argv[0])) { + if (!use_byte_mode && JS_IsString(argv[0])) { data = JS_ToCStringLen(js, &data_len, argv[0]); if (!data) { return JS_ThrowTypeError(js, "Invalid string input"); } must_free_data = 1; } else { - // Check if it's an ArrayBuffer + /* treat everything else as raw bytes */ uint8_t *buf = JS_GetArrayBuffer(js, &data_len, argv[0]); if (!buf) { return JS_ThrowTypeError(js, "encode expects a string or ArrayBuffer"); @@ -91,7 +109,12 @@ static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSVa } // Encode using qrencode - QRcode *qrcode = QRcode_encodeString(data, version, errc, QR_MODE_8, casesensitive); + QRcode *qrcode; + if (use_byte_mode) + qrcode = QRcode_encodeData(data_len, data, version, errc); + else + qrcode = QRcode_encodeString(data, version, errc, QR_MODE_8, casesensitive); + if (!qrcode) { if (must_free_data) JS_FreeCString(js, data); @@ -189,7 +212,8 @@ static JSValue js_qr_decode(JSContext *js, JSValueConst this_val, int argc, JSVa quirc_extract(qr, i, &code); printf("code is %p\n", code.size); if (quirc_decode(&code, &qdata) == QUIRC_SUCCESS) { - JSValue item = JS_NewStringLen(js, (const char *)qdata.payload, qdata.payload_len); + JSValue item = JS_NewArrayBufferCopy(js, qdata.payload, qdata.payload_len); +// JSValue item = JS_NewStringLen(js, (const char *)qdata.payload, qdata.payload_len); JS_SetPropertyUint32(js, result, i, item); } } @@ -198,10 +222,71 @@ static JSValue js_qr_decode(JSContext *js, JSValueConst this_val, int argc, JSVa return result; } +static JSValue js_qr_rgba(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) +{ + if (argc < 1) + return JS_ThrowTypeError(js, "qr.rgba(mods, ...) needs a modules object"); + + JSValue mods = argv[0]; + + uint32_t on = 0xFF000000u; /* black opaque */ + uint32_t off = 0xFFFFFFFFu; /* white opaque */ + if (argc > 1) JS_ToUint32(js, &on, argv[1]); + if (argc > 2) JS_ToUint32(js, &off, argv[2]); + + JSValue js_w = JS_GetPropertyStr(js, mods, "width"); + if (JS_IsUndefined(js_w)) { + JS_FreeValue(js, js_w); + return JS_ThrowTypeError(js, "mods.width missing"); + } + int32_t m = 0; + JS_ToInt32(js, &m, js_w); + JS_FreeValue(js, js_w); + + if (m <= 0) + return JS_ThrowRangeError(js, "mods.width must be > 0"); + + JSValue js_bits = JS_GetPropertyStr(js, mods, "data"); + size_t len = JS_ArrayLength(js, js_bits); + + if (len < (size_t)m * (size_t)m) { + JS_FreeValue(js, js_bits); + return JS_ThrowRangeError(js, "mods.data too small for width²"); + } + + const int w = m, h = m, pitch = w * 4; + const size_t bytes = (size_t)h * (size_t)pitch; + uint8_t *tmp = js_malloc(js, bytes); + if (!tmp) { JS_FreeValue(js, js_bits); return JS_EXCEPTION; } + + for (int y = 0; y < h; ++y) { + uint32_t *row = (uint32_t *)(tmp + y * pitch); + for (int x = 0; x < w; x++) { + uint32_t idx = y * m + x; + JSValue vbit = JS_GetPropertyUint32(js, js_bits, idx); + int on_bit = JS_ToBool(js, vbit); + JS_FreeValue(js, vbit); + row[x] = on_bit ? on : off; + } + } + + JSValue ab = JS_NewArrayBufferCopy(js, tmp, bytes); /* GC owns copy */ + js_free(js, tmp); + JS_FreeValue(js, js_bits); /* done with src */ + + JSValue obj = JS_NewObject(js); + JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, w)); + JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, h)); + JS_SetPropertyStr(js, obj, "pitch", JS_NewInt32(js, pitch)); + JS_SetPropertyStr(js, obj, "buffer", ab); + return obj; +} + // Exported functions for the module static const JSCFunctionListEntry js_qr_funcs[] = { JS_CFUNC_DEF("encode", 2, js_qr_encode), // Updated to expect 2 args JS_CFUNC_DEF("decode", 4, js_qr_decode), + JS_CFUNC_DEF("rgba", 3, js_qr_rgba), }; // Helper to return the default export object diff --git a/tests/level.json b/tests/level.json new file mode 100644 index 00000000..a0a81e2a --- /dev/null +++ b/tests/level.json @@ -0,0 +1,2056 @@ +{ + "name": "More Selective Friends", + "level": [ + { + "x": 0, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 0, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 1, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 13, + "value": [ + "glass" + ] + }, + { + "x": 2, + "y": 14, + "value": [ + "glass" + ] + }, + { + "x": 2, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 2, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 2, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 3, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 3, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 3, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 6, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 7, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 8, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 9, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 10, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 11, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 12, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 13, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 14, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 3, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 3, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 4, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 4, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 4, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 4, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 4, + "y": 7, + "value": [ + "flowers" + ] + }, + { + "x": 4, + "y": 8, + "value": [ + "flowers" + ] + }, + { + "x": 4, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 4, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 4, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 4, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 4, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 5, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 5, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 5, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 5, + "y": 6, + "value": [ + "flowers" + ] + }, + { + "x": 5, + "y": 7, + "value": [ + "wizhut" + ] + }, + { + "x": 5, + "y": 8, + "value": [ + "invisible_wall" + ] + }, + { + "x": 5, + "y": 9, + "value": [ + "flowers" + ] + }, + { + "x": 5, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 5, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 5, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 5, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 5, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 6, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 6, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 6, + "y": 6, + "value": [ + "flowers" + ] + }, + { + "x": 6, + "y": 7, + "value": [ + "flowers" + ] + }, + { + "x": 6, + "y": 8, + "value": [ + "flowers" + ] + }, + { + "x": 6, + "y": 9, + "value": [ + "flowers" + ] + }, + { + "x": 6, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 6, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 6, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 6, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 6, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 7, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 7, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 7, + "y": 5, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 6, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 7, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 8, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 9, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 10, + "value": [ + "flowers" + ] + }, + { + "x": 7, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 7, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 7, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 7, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 7, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 8, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 8, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 8, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 6, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 7, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 8, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 9, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 10, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 8, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 8, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 8, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 8, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 9, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 9, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 9, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 9, + "y": 6, + "value": [ + "spikes" + ] + }, + { + "x": 9, + "y": 7, + "value": [ + "spikes" + ] + }, + { + "x": 9, + "y": 8, + "value": [ + "spikes" + ] + }, + { + "x": 9, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 9, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 9, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 9, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 9, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 10, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 10, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 10, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 10, + "y": 6, + "value": [ + "spikes" + ] + }, + { + "x": 10, + "y": 7, + "value": [ + "portal" + ] + }, + { + "x": 10, + "y": 8, + "value": [ + "spikes" + ] + }, + { + "x": 10, + "y": 10, + "value": [ + "fool" + ] + }, + { + "x": 10, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 10, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 10, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 10, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 10, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 11, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 11, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 11, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 11, + "y": 6, + "value": [ + "spikes" + ] + }, + { + "x": 11, + "y": 7, + "value": [ + "spikes" + ] + }, + { + "x": 11, + "y": 8, + "value": [ + "spikes" + ] + }, + { + "x": 11, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 11, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 11, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 11, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 11, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 12, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 12, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 12, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 6, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 7, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 8, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 9, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 10, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 12, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 12, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 12, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 12, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 13, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 13, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 13, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 13, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 13, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 13, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 13, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 14, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 14, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 14, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 14, + "y": 5, + "value": [ + "player" + ] + }, + { + "x": 14, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 14, + "y": 14, + "value": [ + "thrall_ghost" + ] + }, + { + "x": 14, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 14, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 14, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 15, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 15, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 15, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 15, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 15, + "y": 13, + "value": [ + "spikes" + ] + }, + { + "x": 15, + "y": 14, + "value": [ + "thrall" + ] + }, + { + "x": 15, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 15, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 15, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 16, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 16, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 16, + "y": 4, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 5, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 6, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 7, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 8, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 9, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 10, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 11, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 12, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 13, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 14, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 16, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 16, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 13, + "value": [ + "glass" + ] + }, + { + "x": 17, + "y": 14, + "value": [ + "glass" + ] + }, + { + "x": 17, + "y": 15, + "value": [ + "glass" + ] + }, + { + "x": 17, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 17, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 18, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 19, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": 20, + "y": 17, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 2, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 3, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 4, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 5, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 6, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 7, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 8, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 9, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 10, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 11, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 12, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 13, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 14, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 15, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 16, + "value": [ + "wall" + ] + }, + { + "x": -1, + "y": 17, + "value": [ + "wall" + ] + } + ], + "thumbnail": { + "path": "game/1.png" + }, + "file": "game/1.json", + "id": 61, + "version": "0.1", + "portals": 1 +} \ No newline at end of file diff --git a/tests/qr.js b/tests/qr.js index 6dafcbcf..7c018fef 100644 --- a/tests/qr.js +++ b/tests/qr.js @@ -8,7 +8,5 @@ var myqr = qr.encode("HELLO WORLD", { casesensitive: false }) - - console.log("test finished success.") os.exit() diff --git a/tests/qr_drag.js b/tests/qr_drag.js index af682ef1..3d275736 100644 --- a/tests/qr_drag.js +++ b/tests/qr_drag.js @@ -39,11 +39,35 @@ io.mount('/') var qr = use('qr') +var myimg = qr.encode("HELLO WORLD") +var mybytes = qr.rgba(myimg) + +graphics.save_png("qr_hello.png", mybytes.width, mybytes.height, mybytes.buffer, mybytes.pitch); + +// test saving a zipped json +var miniz = use('miniz') + +var lvl = io.slurp('tests/level.json') +var lvl_cmp = miniz.compress(lvl) + +var qr_lvl = qr.encode(lvl_cmp) +var lvl_bytes = qr.rgba(qr_lvl) +graphics.save_png("qr_level.png", lvl_bytes.width, lvl_bytes.height, lvl_bytes.buffer, lvl_bytes.pitch) + +console.log(`saved compressed level as qr; size was ${lvl_cmp.byteLength}`) + $_.send(ioguy, { type: "subscribe", actor: $_ }) +function strToArrayBuffer(binStr) { + const view = new Uint8Array(binStr.length); + for (let i = 0; i < binStr.length; i++) + view[i] = binStr.codePointAt(i) & 0xff; // mask keeps it 0-255 + return view.buffer; +} + $_.receiver(e => { if (e.type === 'quit') os.exit() @@ -53,7 +77,12 @@ $_.receiver(e => { console.log(`got ${e.data} dropped`) img = e.data var image = graphics.texture(e.data) - console.log(json.encode(qr.decode(image.surface.pixels(), image.surface.width(), image.surface.height(), image.surface.pitch()))) + var data = qr.decode(image.surface.pixels(), image.surface.width(), image.surface.height(), image.surface.pitch()) + console.log(`found ${data.length} qr`) + data = data[0] + console.log(data.byteLength) + var ddata = miniz.decompress(data, true) + console.log(ddata) } })