diff --git a/ports/wasm/js/display.mjs b/ports/wasm/js/display.mjs index 5a9616113ae..08472f0dcfb 100644 --- a/ports/wasm/js/display.mjs +++ b/ports/wasm/js/display.mjs @@ -27,8 +27,13 @@ export class Display { ? this._ctx.createImageData(this._fbWidth, this._fbHeight) : null; - // Scale canvas to match displayio + // Match the canvas to the framebuffer. The backing-store resolution + // (width/height attributes) MUST equal the framebuffer, else + // putImageData() of a fbWidth×fbHeight ImageData is clipped to the + // canvas default (300×150). CSS width/height then scale it for display. if (canvas) { + canvas.width = this._fbWidth; + canvas.height = this._fbHeight; canvas.style.width = this._fbWidth + 'px'; canvas.style.height = this._fbHeight + 'px'; } diff --git a/py/compile.c b/py/compile.c index 8644ad58606..0df255da720 100644 --- a/py/compile.c +++ b/py/compile.c @@ -103,7 +103,11 @@ static const emit_method_table_t *emit_native_table[] = { &emit_native_xtensa_method_table, &emit_native_xtensawin_method_table, &emit_native_rv32_method_table, + #if MICROPY_EMIT_WASM &emit_native_wasm_method_table, + #else + NULL, // wasm native emitter is a PORT feature (needs mp_wasm_compile_native); absent in host mpy-cross + #endif &emit_native_debug_method_table, }; diff --git a/requirements-dev.txt b/requirements-dev.txt index 6a33c49daec..f676ff3783c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -31,6 +31,10 @@ cryptography minify_html jsmin +# for the wasm port's display-resource generation (tools/gen_display_resources.py) +huffman +adafruit-circuitpython-bitmap-font + # for Silicon Labs Configurator (SLC) websockets colorama diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py index 9ed829f7d37..fbc26f7b94e 100644 --- a/tools/gen_display_resources.py +++ b/tools/gen_display_resources.py @@ -29,10 +29,26 @@ class BitmapStub: def __init__(self, width, height, color_depth): self.width = width - self.rows = [b""] * height + self.height = height + self._stride = (width + 7) // 8 # bytes per row, MSB-first byte-packed + self._buf = bytearray(self._stride * height) - def _load_row(self, y, row): - self.rows[y] = bytes(row) + def _load_row(self, y, row): # old bitmap_font API (row = packed bytes) + b = bytes(row) + self._buf[y * self._stride:y * self._stride + self._stride] = b[:self._stride] + + def __setitem__(self, index, value): # new bitmap_font API: flat y*width+x -> 0/1 + y, x = divmod(index, self.width) + off = y * self._stride + (x >> 3) + if value: + self._buf[off] |= 1 << (7 - (x & 7)) + else: + self._buf[off] &= ~(1 << (7 - (x & 7))) & 0xFF + + @property + def rows(self): + s = self._stride + return [bytes(self._buf[y * s:y * s + s]) for y in range(self.height)] f = bitmap_font.load_font(args.font, BitmapStub) @@ -69,7 +85,7 @@ def _load_row(self, y, row): filtered_characters = filtered_characters.replace(c, "") continue g = f.get_glyph(ord(c)) - if g["shift"][1] != 0: + if g.shift_y != 0: raise RuntimeError("y shift") if missing > 0: @@ -83,10 +99,10 @@ def _load_row(self, y, row): for x, c in enumerate(filtered_characters): g = f.get_glyph(ord(c)) - start_bit = x * tile_x + g["bounds"][2] - start_y = (tile_y - 2) - (g["bounds"][1] + g["bounds"][3]) - for y, row in enumerate(g["bitmap"].rows): - for i in range(g["bounds"][0]): + start_bit = x * tile_x + g.dx + start_y = (tile_y - 2) - (g.height + g.dy) + for y, row in enumerate(g.bitmap.rows): + for i in range(g.width): byte = i // 8 bit = i % 8 if row[byte] & (1 << (7 - bit)) != 0: