@typecad/ui 0.1.0-alpha.2 → 1.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +7 -1
  2. package/dist/engine-index.js +2 -2
  3. package/dist/preview/host-ui-runtime.d.ts +1 -0
  4. package/dist/preview/host-ui-runtime.js +56 -11
  5. package/dist/ui-engine/font-assets.d.ts +8 -0
  6. package/dist/ui-engine/font-assets.js +13 -0
  7. package/dist/ui-engine/layout-engine.js +19 -6
  8. package/dist/ui-engine/model.d.ts +1 -1
  9. package/dist/ui-engine/model.js +10 -4
  10. package/dist/ui-engine/runtime-header/antialiasing.js +52 -32
  11. package/dist/ui-engine/runtime-header/blend-bodies.js +4 -4
  12. package/dist/ui-engine/runtime-header/canvas-helpers.js +42 -69
  13. package/dist/ui-engine/runtime-header/canvas-scrollbar.js +22 -10
  14. package/dist/ui-engine/runtime-header/color-mono-refresh.js +10 -10
  15. package/dist/ui-engine/runtime-header/cuttlefish-gfx.d.ts +1 -0
  16. package/dist/ui-engine/runtime-header/cuttlefish-gfx.js +563 -0
  17. package/dist/ui-engine/runtime-header/dirty-scroll-mutators.js +26 -10
  18. package/dist/ui-engine/runtime-header/display-shim.js +8 -8
  19. package/dist/ui-engine/runtime-header/forward-decls.js +52 -10
  20. package/dist/ui-engine/runtime-header/image-drawing.js +154 -84
  21. package/dist/ui-engine/runtime-header/init-press-input.js +20 -5
  22. package/dist/ui-engine/runtime-header/keyboard.js +62 -18
  23. package/dist/ui-engine/runtime-header/node-decoration.js +8 -9
  24. package/dist/ui-engine/runtime-header/node-draw-body.d.ts +1 -0
  25. package/dist/ui-engine/runtime-header/node-draw-body.js +1402 -0
  26. package/dist/ui-engine/runtime-header/paint-order-coords.js +48 -18
  27. package/dist/ui-engine/runtime-header/paint-rects-repair.js +38 -17
  28. package/dist/ui-engine/runtime-header/scroll-physics.js +15 -18
  29. package/dist/ui-engine/runtime-header/state-bindings-nav.js +23 -13
  30. package/dist/ui-engine/runtime-header/structs.js +12 -10
  31. package/dist/ui-engine/runtime-header/text-rendering.js +132 -71
  32. package/dist/ui-engine/runtime-header/tick/bindings-phase.js +29 -10
  33. package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.js +336 -749
  34. package/dist/ui-engine/runtime-header/tick/flush-phase.js +7 -3
  35. package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.js +19 -3
  36. package/dist/ui-engine/runtime-header/tick/transitions-phase.js +31 -24
  37. package/dist/ui-engine/runtime-header/touch-keyboard-fwd.js +46 -41
  38. package/dist/ui-engine/runtime-header/types-defines.js +23 -3
  39. package/dist/ui-engine/runtime-header.d.ts +10 -1
  40. package/dist/ui-engine/runtime-header.js +7 -1
  41. package/dist/ui-engine/transpile-ui.js +2 -2
  42. package/dist/ui-engine/ua-stylesheet.js +46 -3
  43. package/dist/ui-engine/ui-lowering.d.ts +1 -3
  44. package/dist/ui-engine/ui-lowering.js +18 -24
  45. package/dist/ui-engine/ui-registry.js +1 -6
  46. package/package.json +2 -2
  47. package/src/engine-index.ts +2 -2
  48. package/src/preview/host-ui-runtime.ts +56 -12
  49. package/src/ui-engine/font-assets.ts +13 -0
  50. package/src/ui-engine/layout-engine.ts +19 -6
  51. package/src/ui-engine/model.ts +10 -5
  52. package/src/ui-engine/runtime-header/antialiasing.ts +52 -32
  53. package/src/ui-engine/runtime-header/blend-bodies.ts +4 -4
  54. package/src/ui-engine/runtime-header/canvas-helpers.ts +42 -69
  55. package/src/ui-engine/runtime-header/canvas-scrollbar.ts +22 -10
  56. package/src/ui-engine/runtime-header/color-mono-refresh.ts +10 -10
  57. package/src/ui-engine/runtime-header/cuttlefish-gfx.ts +566 -0
  58. package/src/ui-engine/runtime-header/dirty-scroll-mutators.ts +26 -10
  59. package/src/ui-engine/runtime-header/display-shim.ts +8 -8
  60. package/src/ui-engine/runtime-header/forward-decls.ts +52 -10
  61. package/src/ui-engine/runtime-header/image-drawing.ts +154 -84
  62. package/src/ui-engine/runtime-header/init-press-input.ts +20 -5
  63. package/src/ui-engine/runtime-header/keyboard.ts +62 -18
  64. package/src/ui-engine/runtime-header/node-decoration.ts +8 -9
  65. package/src/ui-engine/runtime-header/node-draw-body.ts +1402 -0
  66. package/src/ui-engine/runtime-header/paint-order-coords.ts +48 -18
  67. package/src/ui-engine/runtime-header/paint-rects-repair.ts +38 -17
  68. package/src/ui-engine/runtime-header/scroll-physics.ts +15 -18
  69. package/src/ui-engine/runtime-header/state-bindings-nav.ts +23 -13
  70. package/src/ui-engine/runtime-header/structs.ts +12 -10
  71. package/src/ui-engine/runtime-header/text-rendering.ts +132 -71
  72. package/src/ui-engine/runtime-header/tick/bindings-phase.ts +29 -10
  73. package/src/ui-engine/runtime-header/tick/dirty-draw-phase.ts +336 -749
  74. package/src/ui-engine/runtime-header/tick/flush-phase.ts +7 -3
  75. package/src/ui-engine/runtime-header/tick/scroll-canvas-phase.ts +19 -3
  76. package/src/ui-engine/runtime-header/tick/transitions-phase.ts +31 -24
  77. package/src/ui-engine/runtime-header/touch-keyboard-fwd.ts +46 -41
  78. package/src/ui-engine/runtime-header/types-defines.ts +23 -3
  79. package/src/ui-engine/runtime-header.ts +17 -1
  80. package/src/ui-engine/transpile-ui.ts +2 -2
  81. package/src/ui-engine/ua-stylesheet.ts +46 -3
  82. package/src/ui-engine/ui-lowering.ts +19 -26
  83. package/src/ui-engine/ui-registry.ts +1 -7
  84. package/dist/ui-engine/scroll-memory-diagnostics.d.ts +0 -16
  85. package/dist/ui-engine/scroll-memory-diagnostics.js +0 -58
  86. package/src/ui-engine/scroll-memory-diagnostics.ts +0 -79
@@ -1,5 +1,5 @@
1
1
  // Slice of the C++ runtime header (original source lines 753-901).
2
- // Persistent canvas release/create/get/shift/repair/warn helpers.
2
+ // Persistent canvas release/create/get/shift/repair helpers.
3
3
  // See docs/superpowers/specs/2026-07-12-split-runtime-header-design.md.
4
4
  export function emitCanvasHelpers() {
5
5
  return `
@@ -10,6 +10,8 @@ static inline void ui_release_canvas_state() {
10
10
  __ui_list_canvas_node = -1;
11
11
  display_deleteCanvas(__ui_node_canvas); __ui_node_canvas = nullptr;
12
12
  display_deleteCanvas(__ui_repair_canvas); __ui_repair_canvas = nullptr;
13
+ display_deleteCanvas(__ui_band_canvas); __ui_band_canvas = nullptr;
14
+ display_deleteCanvas(__ui_kb_canvas); __ui_kb_canvas = nullptr;
13
15
  }
14
16
 
15
17
  // Lazily allocate/reuse a viewport-sized canvas for a scroll container. Resizes
@@ -22,7 +24,18 @@ static inline CuttlefishCanvas16* ui_create_canvas_best(int16_t w, int16_t h) {
22
24
  #if defined(ESP32) && defined(BOARD_HAS_PSRAM)
23
25
  if (psramFound()) {
24
26
  CuttlefishCanvas16* c = display_createCanvasPsram(w, h);
25
- if (c && display_canvasBuffer(c)) return c;
27
+ if (c && display_canvasBuffer(c)) {
28
+ static uint8_t psram_logged = 0;
29
+ if (!psram_logged) {
30
+ psram_logged = 1;
31
+ #if defined(ESP32) && defined(ARDUINO)
32
+ Serial.printf("[psram] canvas %dx%d allocated in PSRAM (free=%u)\n", w, h, ESP.getFreePsram());
33
+ #else
34
+ printf("[psram] canvas %dx%d allocated in PSRAM\n", w, h);
35
+ #endif
36
+ }
37
+ return c;
38
+ }
26
39
  // PSRAM allocation failed (rare — fragmented PSRAM) → fall through to SRAM.
27
40
  }
28
41
  #endif
@@ -30,63 +43,18 @@ static inline CuttlefishCanvas16* ui_create_canvas_best(int16_t w, int16_t h) {
30
43
  }
31
44
 
32
45
  static inline CuttlefishCanvas16* ui_get_container_canvas(int16_t w, int16_t h) {
33
- if (w <= 0 || h <= 0) return nullptr;
34
- if (!__ui_container_canvas ||
35
- display_canvasWidth(__ui_container_canvas) != w ||
36
- display_canvasHeight(__ui_container_canvas) != h) {
37
- display_deleteCanvas(__ui_container_canvas);
38
- __ui_container_canvas = ui_create_canvas_best(w, h);
39
- }
40
- return (__ui_container_canvas && display_canvasBuffer(__ui_container_canvas))
41
- ? __ui_container_canvas : nullptr;
42
- }
43
-
44
- // Defined after the node table by UI lowering (scroll overflow nodes with ids).
45
- static inline const char* __ui_scroll_node_id(uint16_t idx);
46
-
47
- // Emit a one-time Serial warning when scroll rendering cannot be accurate due
48
- // to heap limits. reason: 0=canvas alloc failed, 1=viewport exceeds budget,
49
- // 2=Mode C strip fallback (reduced accuracy).
50
- static inline void ui_warn_scroll_memory(uint16_t nodeIdx, uint8_t reason) {
51
- if (nodeIdx >= __ui_node_count) return;
52
- if (!__ui_scroll_mem_warned) return;
53
- if (__ui_scroll_mem_warned[nodeIdx]) return;
54
- __ui_scroll_mem_warned[nodeIdx] = 1;
55
-
56
- int16_t vw = __ui_nodes[nodeIdx].box.w;
57
- int16_t vh = __ui_nodes[nodeIdx].box.h;
58
- uint32_t need = (uint32_t)(vw > 0 ? vw : 0) * (uint32_t)(vh > 0 ? vh : 0) * 2u;
59
- const char* id = __ui_scroll_node_id(nodeIdx);
60
- const char* label = (id && id[0]) ? id : "scroll viewport";
61
- const char* reasonText = "scroll canvas allocation failed";
62
- if (reason == 1) reasonText = "scroll viewport exceeds compile-time canvas budget";
63
- else if (reason == 2) reasonText = "using Mode C strip fallback (smooth scroll canvas unavailable)";
64
-
65
- #if defined(ESP32)
66
- uint32_t freeHeap = ESP.getFreeHeap();
67
- uint32_t maxAlloc = ESP.getMaxAllocHeap();
68
- Serial.printf(
69
- "[cuttlefish] WARNING: #%s (%dx%d) needs %lu bytes for accurate scroll — %s. "
70
- "heap free=%lu max_alloc=%lu budget=%d. "
71
- "Shrink the scroll viewport in CSS, trim fonts/images, or use PSRAM.\\n",
72
- label, vw, vh, (unsigned long)need, reasonText,
73
- (unsigned long)freeHeap, (unsigned long)maxAlloc, UI_SCROLL_CANVAS_BUDGET_BYTES);
74
- #elif defined(ESP8266)
75
- uint32_t freeHeap = ESP.getFreeHeap();
76
- Serial.printf(
77
- "[cuttlefish] WARNING: #%s (%dx%d) needs %lu bytes for accurate scroll — %s. "
78
- "heap free=%lu budget=%d. "
79
- "Shrink the scroll viewport in CSS, trim fonts/images, or reduce UI footprint.\\n",
80
- label, vw, vh, (unsigned long)need, reasonText,
81
- (unsigned long)freeHeap, UI_SCROLL_CANVAS_BUDGET_BYTES);
82
- #else
83
- // Non-Arduino target (e.g. SDL native): no Serial, so use standard-C printf.
84
- // The native framework forces <cstdio> so printf is available here.
85
- printf(
86
- "[cuttlefish] WARNING: #%s (%dx%d) needs %lu bytes for accurate scroll — %s. "
87
- "budget=%d. Shrink the scroll viewport in CSS or trim UI assets.\\n",
88
- label, vw, vh, (unsigned long)need, reasonText, UI_SCROLL_CANVAS_BUDGET_BYTES);
89
- #endif
46
+ // Intentionally returns nullptr: scroll containers always use the band
47
+ // renderer (ui_render_scroll_bands), not the Mode B viewport canvas.
48
+ // Mode B holds the whole viewport in one large canvas and pushes it in a
49
+ // single transaction every frame — on SPI TFTs that full-viewport push
50
+ // (especially from PSRAM) visibly flashes on child state changes like a
51
+ // button press. The band renderer composites into a small ~10KB SRAM canvas
52
+ // strip-by-strip, pushing each band only after it's complete — tear-free and
53
+ // flash-free regardless of target memory. PSRAM still benefits the other
54
+ // canvases (list, keyboard, repair); only the scroll viewport deliberately
55
+ // bypasses it for visual quality.
56
+ (void)w; (void)h;
57
+ return nullptr;
90
58
  }
91
59
 
92
60
  // Shift the canvas buffer vertically by deltaY (cheap memmove of existing
@@ -117,16 +85,16 @@ static inline void ui_shift_container_canvas(CuttlefishCanvas16* canvas, int16_t
117
85
  // band at the TOP. (Matches the proven pre-rewrite direction.)
118
86
  if (deltaY > 0) {
119
87
  for (int16_t row = 0; row < h - shift; row++) {
120
- memmove(pixels + (int32_t)row * stride,
121
- pixels + (int32_t)(row + shift) * stride,
122
- (size_t)contentW * sizeof(UI_COLOR_T));
88
+ memmove(pixels + static_cast<int32_t>(row) * stride,
89
+ pixels + static_cast<int32_t>(row + shift) * stride,
90
+ static_cast<size_t>(contentW) * sizeof(UI_COLOR_T));
123
91
  }
124
92
  if (exposedY) *exposedY = h - shift;
125
93
  } else {
126
94
  for (int16_t row = h - shift - 1; row >= 0; row--) {
127
- memmove(pixels + (int32_t)(row + shift) * stride,
128
- pixels + (int32_t)row * stride,
129
- (size_t)contentW * sizeof(UI_COLOR_T));
95
+ memmove(pixels + static_cast<int32_t>(row + shift) * stride,
96
+ pixels + static_cast<int32_t>(row) * stride,
97
+ static_cast<size_t>(contentW) * sizeof(UI_COLOR_T));
130
98
  }
131
99
  if (exposedY) *exposedY = 0;
132
100
  }
@@ -139,13 +107,18 @@ static inline void ui_shift_container_canvas(CuttlefishCanvas16* canvas, int16_t
139
107
  }
140
108
 
141
109
  // Repair canvas: parent-seeded background repaints + exposed-strip redraws.
142
- // Grow-only between navigations so small scroll-delta changes do not allocate
143
- // and free a new strip canvas during drag.
110
+ // Reused across navigations when size matches; reallocated on exact-size
111
+ // mismatch (a reused larger canvas would keep its old stride, corrupting the
112
+ // pushed pixels — see the inline comment below).
144
113
  static inline CuttlefishCanvas16* ui_get_repair_canvas(int16_t w, int16_t h) {
145
114
  if (w <= 0 || h <= 0) return nullptr;
115
+ // Reallocate when size differs at all (not just when growing). A reused
116
+ // larger canvas keeps its old stride, and ui_push_canvas_rect uses that
117
+ // stride for row offsets — a mismatch with the caller's expected (w,h)
118
+ // corrupts the pushed pixels. Exact-size reallocation guarantees stride == w.
146
119
  if (!__ui_repair_canvas || !display_canvasBuffer(__ui_repair_canvas) ||
147
- display_canvasWidth(__ui_repair_canvas) < w ||
148
- display_canvasHeight(__ui_repair_canvas) < h) {
120
+ display_canvasWidth(__ui_repair_canvas) != w ||
121
+ display_canvasHeight(__ui_repair_canvas) != h) {
149
122
  display_deleteCanvas(__ui_repair_canvas);
150
123
  __ui_repair_canvas = ui_create_canvas_best(w, h);
151
124
  }
@@ -13,12 +13,16 @@ static inline void ui_push_canvas_rect(CuttlefishCanvas16* canvas, int16_t x, in
13
13
  // via __ui_gfx (so the single bulk push at frame end captures everything).
14
14
  // Otherwise write straight to the display in one SPI transaction.
15
15
  if (__ui_fb) {
16
+ // The framebuffer is the composition target. Track this publish so a
17
+ // geometry repair or scroll-canvas repair that does not leave a node dirty
18
+ // still reaches the panel during the frame-end flush.
19
+ ui_fb_add_rect(x, y, w, h);
16
20
  if (w == stride) {
17
21
  ui_display_draw_rgb_bitmap(x, y, pixels, w, h);
18
22
  return;
19
23
  }
20
24
  for (int16_t row = 0; row < h; row++) {
21
- ui_display_draw_rgb_bitmap(x, y + row, pixels + (int32_t)row * stride, w, 1);
25
+ ui_display_draw_rgb_bitmap(x, y + row, pixels + static_cast<int32_t>(row) * stride, w, 1);
22
26
  }
23
27
  return;
24
28
  }
@@ -26,12 +30,12 @@ static inline void ui_push_canvas_rect(CuttlefishCanvas16* canvas, int16_t x, in
26
30
  display_setAddrWindow(x, y, w, h);
27
31
  if (w == stride) {
28
32
  // Full-width: contiguous in buffer, single write.
29
- display_writePixels(pixels, (uint32_t)w * h);
33
+ display_writePixels(pixels, static_cast<uint32_t>(w) * h);
30
34
  display_endWrite();
31
35
  return;
32
36
  }
33
37
  for (int16_t row = 0; row < h; row++) {
34
- display_writePixels(pixels + (int32_t)row * stride, w);
38
+ display_writePixels(pixels + static_cast<int32_t>(row) * stride, w);
35
39
  }
36
40
  display_endWrite();
37
41
  }
@@ -45,7 +49,7 @@ static inline void ui_draw_canvas_rect(CuttlefishCanvas16* canvas, int16_t x, in
45
49
  return;
46
50
  }
47
51
  for (int16_t row = 0; row < h; row++) {
48
- ui_display_draw_rgb_bitmap(x, y + row, pixels + (int32_t)row * stride, w, 1);
52
+ ui_display_draw_rgb_bitmap(x, y + row, pixels + static_cast<int32_t>(row) * stride, w, 1);
49
53
  }
50
54
  }
51
55
 
@@ -67,10 +71,14 @@ static inline void ui_push_buffered_scroll_canvas(CuttlefishCanvas16* bufferedSc
67
71
  ui_draw_canvas_rect(bufferedScrollRepaintCanvas, 0, bufferedScrollRepaintY, vw, bufferedScrollRepaintH);
68
72
  }
69
73
  int16_t tx = vw - 4;
70
- uint16_t thumbH = (uint32_t)vh * vh / __ui_nodes[si].contentHeight;
74
+ uint16_t thumbH = static_cast<uint32_t>(vh) * vh / __ui_nodes[si].contentHeight;
71
75
  if (thumbH < 8) thumbH = 8;
76
+ // Clamp to vh so (vh - thumbH) below can't underflow on a degenerate sub-8px
77
+ // viewport (which would cast a negative value to a huge uint32_t and place the
78
+ // thumb off-screen). Matches the guard in ui_render_scroll_bands.
79
+ if (thumbH > static_cast<uint16_t>(vh)) thumbH = static_cast<uint16_t>(vh);
72
80
  int16_t maxScroll = __ui_nodes[si].contentHeight - vh;
73
- uint16_t thumbY = (uint32_t)(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
81
+ uint16_t thumbY = static_cast<uint32_t>(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
74
82
  UI_COLOR_T dimFg = (UI_COLOR_T)((__ui_nodes[si].fg >> 1) & UI_DIM_MASK);
75
83
  ui_display_fill_rect(tx, 0, 3, vh, dimFg);
76
84
  ui_display_fill_rect(tx, thumbY, 3, thumbH, __ui_nodes[si].fg);
@@ -87,18 +95,22 @@ static inline void ui_push_buffered_scroll_canvas(CuttlefishCanvas16* bufferedSc
87
95
 
88
96
  // Draw a scroll container's scrollbar directly on the display (Mode C).
89
97
  static inline void ui_draw_scrollbar_direct(int16_t si, int16_t vox, int16_t voy) {
90
- if (si < 0 || si >= (int16_t)__ui_node_count) return;
98
+ if (si < 0 || si >= static_cast<int16_t>(__ui_node_count)) return;
91
99
  int16_t vw = __ui_nodes[si].box.w;
92
100
  int16_t vh = __ui_nodes[si].box.h;
93
101
  if (__ui_nodes[si].contentHeight <= vh) return;
94
102
  int16_t tx = vox + vw - 4;
95
- uint16_t thumbH = (uint32_t)vh * vh / __ui_nodes[si].contentHeight;
103
+ uint16_t thumbH = static_cast<uint32_t>(vh) * vh / __ui_nodes[si].contentHeight;
96
104
  if (thumbH < 8) thumbH = 8;
105
+ // Clamp to vh so (vh - thumbH) below can't underflow on a degenerate sub-8px
106
+ // viewport (which would cast a negative value to a huge uint32_t and place the
107
+ // thumb off-screen). Matches the guard in ui_render_scroll_bands.
108
+ if (thumbH > static_cast<uint16_t>(vh)) thumbH = static_cast<uint16_t>(vh);
97
109
  int16_t maxScroll = __ui_nodes[si].contentHeight - vh;
98
- uint16_t thumbY = (uint32_t)(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
110
+ uint16_t thumbY = static_cast<uint32_t>(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
99
111
  UI_COLOR_T dimFg = (UI_COLOR_T)((__ui_nodes[si].fg >> 1) & UI_DIM_MASK);
100
112
  ui_display_fill_rect(tx, voy, 3, vh, dimFg);
101
- ui_display_fill_rect(tx, (int16_t)(voy + thumbY), 3, thumbH, __ui_nodes[si].fg);
113
+ ui_display_fill_rect(tx, static_cast<int16_t>(voy + thumbY), 3, thumbH, __ui_nodes[si].fg);
102
114
  }
103
115
 
104
116
  // Per-node dirty marker (called by press handlers and binding evaluation).`;
@@ -39,11 +39,11 @@ static inline uint32_t ui_blend888(uint32_t fg, uint32_t bg, uint8_t opacity);
39
39
  static inline uint16_t lerp_color(uint16_t a, uint16_t b, uint8_t k100);
40
40
  static inline uint32_t lerp_color_888(uint32_t a, uint32_t b, uint8_t k100);
41
41
  #if UI_COLOR_DEPTH == 888
42
- #define ui_blend(fg, bg, op) ui_blend888((uint32_t)(fg), (uint32_t)(bg), (op))
43
- #define UI_LERP_COLOR(a, b, k) lerp_color_888((uint32_t)(a), (uint32_t)(b), (k))
42
+ #define ui_blend(fg, bg, op) ui_blend888(static_cast<uint32_t>(fg), static_cast<uint32_t>(bg), (op))
43
+ #define UI_LERP_COLOR(a, b, k) lerp_color_888(static_cast<uint32_t>(a), static_cast<uint32_t>(b), (k))
44
44
  #else
45
- #define ui_blend(fg, bg, op) ui_blend565((uint16_t)(fg), (uint16_t)(bg), (op))
46
- #define UI_LERP_COLOR(a, b, k) lerp_color((uint16_t)(a), (uint16_t)(b), (k))
45
+ #define ui_blend(fg, bg, op) ui_blend565(static_cast<uint16_t>(fg), static_cast<uint16_t>(bg), (op))
46
+ #define UI_LERP_COLOR(a, b, k) lerp_color(static_cast<uint16_t>(a), static_cast<uint16_t>(b), (k))
47
47
  #endif
48
48
 
49
49
  // ── 1-bit mono snap (UI_NATIVE_MONO) ─────────────────────────────────────────
@@ -57,7 +57,7 @@ static inline uint32_t ui_snap_mono(uint32_t c) {
57
57
  uint8_t r = (c >> 16) & 0xff, g = (c >> 8) & 0xff, b = c & 0xff;
58
58
  // Match the transpile-time toMono threshold: (0.299r + 0.587g + 0.114b)/255 >= 0.27.
59
59
  // Integer form: 299r+587g+114b >= 68850 (= 0.27*255*1000). Verified 0 mismatches.
60
- return ((uint32_t)(299 * r + 587 * g + 114 * b) >= 68850u) ? 0xffffffu : 0x000000u;
60
+ return (static_cast<uint32_t>(299 * r + 587 * g + 114 * b) >= 68850u) ? 0xffffffu : 0x000000u;
61
61
  }
62
62
  // Snap an RGB565 value to 1-bit mono. Mono panels run at UI_COLOR_DEPTH 565, so
63
63
  // node fields hold 565 values; reconstruct 8-bit channels then apply the threshold.
@@ -68,10 +68,10 @@ static inline uint16_t ui_snap_mono565(uint16_t c) {
68
68
  if (c == 0x0001u || c == 0xffffu) return 0xffffu;
69
69
  uint8_t r5 = (c >> 11) & 0x1f, g6 = (c >> 5) & 0x3f, b5 = c & 0x1f;
70
70
  uint8_t r = (r5 << 3) | (r5 >> 2), g = (g6 << 2) | (g6 >> 4), b = (b5 << 3) | (b5 >> 2);
71
- return ((uint32_t)(299 * r + 587 * g + 114 * b) >= 68850u) ? 0xffffu : 0x0000u;
71
+ return (static_cast<uint32_t>(299 * r + 587 * g + 114 * b) >= 68850u) ? 0xffffu : 0x0000u;
72
72
  }
73
- #define UI_MAYBE_SNAP_MONO(c) (ui_snap_mono((uint32_t)(c)))
74
- #define UI_MAYBE_SNAP_MONO565(c) (ui_snap_mono565((uint16_t)(c)))
73
+ #define UI_MAYBE_SNAP_MONO(c) (ui_snap_mono(static_cast<uint32_t>(c)))
74
+ #define UI_MAYBE_SNAP_MONO565(c) (ui_snap_mono565(static_cast<uint16_t>(c)))
75
75
  #else
76
76
  #define UI_MAYBE_SNAP_MONO(c) (c)
77
77
  #define UI_MAYBE_SNAP_MONO565(c) (c)
@@ -115,7 +115,7 @@ static inline uint16_t ui_snap_mono565(uint16_t c) {
115
115
  const UIRect16& r = __ui_refresh_rects[i];
116
116
  if (r.x < x0) x0 = r.x;
117
117
  if (r.y < y0) y0 = r.y;
118
- int16_t rx1 = (int16_t)(r.x + r.w), ry1 = (int16_t)(r.y + r.h);
118
+ int16_t rx1 = static_cast<int16_t>(r.x + r.w), ry1 = static_cast<int16_t>(r.y + r.h);
119
119
  if (rx1 > x1) x1 = rx1;
120
120
  if (ry1 > y1) y1 = ry1;
121
121
  }
@@ -124,7 +124,7 @@ static inline uint16_t ui_snap_mono565(uint16_t c) {
124
124
  if (x1 > display_width()) x1 = display_width();
125
125
  if (y1 > display_height()) y1 = display_height();
126
126
  if (x1 > x0 && y1 > y0) {
127
- display_partial_refresh(x0, y0, (int16_t)(x1 - x0), (int16_t)(y1 - y0));
127
+ display_partial_refresh(x0, y0, static_cast<int16_t>(x1 - x0), static_cast<int16_t>(y1 - y0));
128
128
  }
129
129
  }
130
130
  #elif defined(UI_BATCH_SPI_WRITES)
@@ -0,0 +1 @@
1
+ export declare function emitCuttlefishGfx(active: boolean): string;