@typecad/ui 0.1.0-alpha.1
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.
- package/LICENSE +21 -0
- package/README.md +1443 -0
- package/dist/engine-index.d.ts +7 -0
- package/dist/engine-index.js +41 -0
- package/dist/index.d.ts +165 -0
- package/dist/index.js +42 -0
- package/dist/preview/build-program.d.ts +7 -0
- package/dist/preview/build-program.js +665 -0
- package/dist/preview/host-gfx.d.ts +90 -0
- package/dist/preview/host-gfx.js +552 -0
- package/dist/preview/host-ui-runtime.d.ts +241 -0
- package/dist/preview/host-ui-runtime.js +3236 -0
- package/dist/preview/types.d.ts +83 -0
- package/dist/preview/types.js +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.js +10 -0
- package/dist/ui-engine/block-layout.d.ts +8 -0
- package/dist/ui-engine/block-layout.js +95 -0
- package/dist/ui-engine/color.d.ts +49 -0
- package/dist/ui-engine/color.js +273 -0
- package/dist/ui-engine/css-parser.d.ts +155 -0
- package/dist/ui-engine/css-parser.js +1058 -0
- package/dist/ui-engine/default-keyboards.d.ts +3 -0
- package/dist/ui-engine/default-keyboards.js +53 -0
- package/dist/ui-engine/easing.d.ts +12 -0
- package/dist/ui-engine/easing.js +76 -0
- package/dist/ui-engine/font-assets.d.ts +50 -0
- package/dist/ui-engine/font-assets.js +431 -0
- package/dist/ui-engine/html-parser.d.ts +116 -0
- package/dist/ui-engine/html-parser.js +284 -0
- package/dist/ui-engine/image-assets.d.ts +21 -0
- package/dist/ui-engine/image-assets.js +125 -0
- package/dist/ui-engine/inline-parser.d.ts +30 -0
- package/dist/ui-engine/inline-parser.js +66 -0
- package/dist/ui-engine/keyframes.d.ts +3 -0
- package/dist/ui-engine/keyframes.js +39 -0
- package/dist/ui-engine/layout-engine.d.ts +35 -0
- package/dist/ui-engine/layout-engine.js +203 -0
- package/dist/ui-engine/model.d.ts +239 -0
- package/dist/ui-engine/model.js +987 -0
- package/dist/ui-engine/rich-layout.d.ts +51 -0
- package/dist/ui-engine/rich-layout.js +220 -0
- package/dist/ui-engine/run-types.d.ts +13 -0
- package/dist/ui-engine/run-types.js +1 -0
- package/dist/ui-engine/runtime-header/antialiasing.d.ts +1 -0
- package/dist/ui-engine/runtime-header/antialiasing.js +141 -0
- package/dist/ui-engine/runtime-header/blend-bodies.d.ts +1 -0
- package/dist/ui-engine/runtime-header/blend-bodies.js +39 -0
- package/dist/ui-engine/runtime-header/canvas-helpers.d.ts +1 -0
- package/dist/ui-engine/runtime-header/canvas-helpers.js +155 -0
- package/dist/ui-engine/runtime-header/canvas-scrollbar.d.ts +1 -0
- package/dist/ui-engine/runtime-header/canvas-scrollbar.js +105 -0
- package/dist/ui-engine/runtime-header/color-mono-refresh.d.ts +1 -0
- package/dist/ui-engine/runtime-header/color-mono-refresh.js +154 -0
- package/dist/ui-engine/runtime-header/dirty-scroll-mutators.d.ts +1 -0
- package/dist/ui-engine/runtime-header/dirty-scroll-mutators.js +169 -0
- package/dist/ui-engine/runtime-header/display-shim.d.ts +1 -0
- package/dist/ui-engine/runtime-header/display-shim.js +104 -0
- package/dist/ui-engine/runtime-header/forward-decls.d.ts +1 -0
- package/dist/ui-engine/runtime-header/forward-decls.js +137 -0
- package/dist/ui-engine/runtime-header/guard-close.d.ts +1 -0
- package/dist/ui-engine/runtime-header/guard-close.js +8 -0
- package/dist/ui-engine/runtime-header/image-drawing.d.ts +1 -0
- package/dist/ui-engine/runtime-header/image-drawing.js +300 -0
- package/dist/ui-engine/runtime-header/init-press-input.d.ts +1 -0
- package/dist/ui-engine/runtime-header/init-press-input.js +126 -0
- package/dist/ui-engine/runtime-header/keyboard.d.ts +1 -0
- package/dist/ui-engine/runtime-header/keyboard.js +342 -0
- package/dist/ui-engine/runtime-header/node-decoration.d.ts +1 -0
- package/dist/ui-engine/runtime-header/node-decoration.js +212 -0
- package/dist/ui-engine/runtime-header/paint-order-coords.d.ts +1 -0
- package/dist/ui-engine/runtime-header/paint-order-coords.js +190 -0
- package/dist/ui-engine/runtime-header/paint-rects-repair.d.ts +1 -0
- package/dist/ui-engine/runtime-header/paint-rects-repair.js +553 -0
- package/dist/ui-engine/runtime-header/scroll-physics.d.ts +1 -0
- package/dist/ui-engine/runtime-header/scroll-physics.js +161 -0
- package/dist/ui-engine/runtime-header/state-bindings-nav.d.ts +1 -0
- package/dist/ui-engine/runtime-header/state-bindings-nav.js +176 -0
- package/dist/ui-engine/runtime-header/structs.d.ts +1 -0
- package/dist/ui-engine/runtime-header/structs.js +220 -0
- package/dist/ui-engine/runtime-header/text-rendering.d.ts +1 -0
- package/dist/ui-engine/runtime-header/text-rendering.js +715 -0
- package/dist/ui-engine/runtime-header/tick/bindings-phase.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick/bindings-phase.js +103 -0
- package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.js +1051 -0
- package/dist/ui-engine/runtime-header/tick/flush-phase.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick/flush-phase.js +17 -0
- package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.js +15 -0
- package/dist/ui-engine/runtime-header/tick/transitions-phase.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick/transitions-phase.js +213 -0
- package/dist/ui-engine/runtime-header/tick-motion-helpers.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick-motion-helpers.js +26 -0
- package/dist/ui-engine/runtime-header/tick.d.ts +1 -0
- package/dist/ui-engine/runtime-header/tick.js +17 -0
- package/dist/ui-engine/runtime-header/touch-keyboard-fwd.d.ts +1 -0
- package/dist/ui-engine/runtime-header/touch-keyboard-fwd.js +406 -0
- package/dist/ui-engine/runtime-header/types-defines.d.ts +1 -0
- package/dist/ui-engine/runtime-header/types-defines.js +79 -0
- package/dist/ui-engine/runtime-header.d.ts +1 -0
- package/dist/ui-engine/runtime-header.js +69 -0
- package/dist/ui-engine/scroll-memory-diagnostics.d.ts +16 -0
- package/dist/ui-engine/scroll-memory-diagnostics.js +58 -0
- package/dist/ui-engine/select-engine.d.ts +4 -0
- package/dist/ui-engine/select-engine.js +19 -0
- package/dist/ui-engine/style-resolver.d.ts +77 -0
- package/dist/ui-engine/style-resolver.js +341 -0
- package/dist/ui-engine/text-layout.d.ts +19 -0
- package/dist/ui-engine/text-layout.js +92 -0
- package/dist/ui-engine/transpile-ui.d.ts +11 -0
- package/dist/ui-engine/transpile-ui.js +33 -0
- package/dist/ui-engine/ua-stylesheet.d.ts +3 -0
- package/dist/ui-engine/ua-stylesheet.js +56 -0
- package/dist/ui-engine/ui-file-splitter.d.ts +14 -0
- package/dist/ui-engine/ui-file-splitter.js +47 -0
- package/dist/ui-engine/ui-lowering.d.ts +33 -0
- package/dist/ui-engine/ui-lowering.js +390 -0
- package/dist/ui-engine/ui-registry.d.ts +81 -0
- package/dist/ui-engine/ui-registry.js +429 -0
- package/dist/ui-engine/yoga-layout.d.ts +12 -0
- package/dist/ui-engine/yoga-layout.js +314 -0
- package/package.json +86 -0
- package/src/engine-index.ts +51 -0
- package/src/index.ts +232 -0
- package/src/preview/build-program.ts +734 -0
- package/src/preview/host-gfx.ts +580 -0
- package/src/preview/host-ui-runtime.ts +3245 -0
- package/src/preview/types.ts +96 -0
- package/src/types.ts +127 -0
- package/src/ui-engine/block-layout.ts +104 -0
- package/src/ui-engine/color.ts +263 -0
- package/src/ui-engine/css-parser.ts +1003 -0
- package/src/ui-engine/default-keyboards.ts +58 -0
- package/src/ui-engine/easing.ts +53 -0
- package/src/ui-engine/font-assets.ts +512 -0
- package/src/ui-engine/html-parser.ts +397 -0
- package/src/ui-engine/image-assets.ts +170 -0
- package/src/ui-engine/inline-parser.ts +78 -0
- package/src/ui-engine/keyframes.ts +47 -0
- package/src/ui-engine/layout-engine.ts +228 -0
- package/src/ui-engine/model.ts +1225 -0
- package/src/ui-engine/rich-layout.ts +257 -0
- package/src/ui-engine/run-types.ts +14 -0
- package/src/ui-engine/runtime-header/antialiasing.ts +141 -0
- package/src/ui-engine/runtime-header/blend-bodies.ts +39 -0
- package/src/ui-engine/runtime-header/canvas-helpers.ts +155 -0
- package/src/ui-engine/runtime-header/canvas-scrollbar.ts +105 -0
- package/src/ui-engine/runtime-header/color-mono-refresh.ts +154 -0
- package/src/ui-engine/runtime-header/dirty-scroll-mutators.ts +169 -0
- package/src/ui-engine/runtime-header/display-shim.ts +104 -0
- package/src/ui-engine/runtime-header/forward-decls.ts +137 -0
- package/src/ui-engine/runtime-header/guard-close.ts +8 -0
- package/src/ui-engine/runtime-header/image-drawing.ts +300 -0
- package/src/ui-engine/runtime-header/init-press-input.ts +126 -0
- package/src/ui-engine/runtime-header/keyboard.ts +342 -0
- package/src/ui-engine/runtime-header/node-decoration.ts +212 -0
- package/src/ui-engine/runtime-header/paint-order-coords.ts +190 -0
- package/src/ui-engine/runtime-header/paint-rects-repair.ts +553 -0
- package/src/ui-engine/runtime-header/scroll-physics.ts +161 -0
- package/src/ui-engine/runtime-header/state-bindings-nav.ts +176 -0
- package/src/ui-engine/runtime-header/structs.ts +220 -0
- package/src/ui-engine/runtime-header/text-rendering.ts +715 -0
- package/src/ui-engine/runtime-header/tick/bindings-phase.ts +103 -0
- package/src/ui-engine/runtime-header/tick/dirty-draw-phase.ts +1051 -0
- package/src/ui-engine/runtime-header/tick/flush-phase.ts +17 -0
- package/src/ui-engine/runtime-header/tick/scroll-canvas-phase.ts +15 -0
- package/src/ui-engine/runtime-header/tick/transitions-phase.ts +213 -0
- package/src/ui-engine/runtime-header/tick-motion-helpers.ts +26 -0
- package/src/ui-engine/runtime-header/tick.ts +18 -0
- package/src/ui-engine/runtime-header/touch-keyboard-fwd.ts +406 -0
- package/src/ui-engine/runtime-header/types-defines.ts +79 -0
- package/src/ui-engine/runtime-header.ts +71 -0
- package/src/ui-engine/scroll-memory-diagnostics.ts +79 -0
- package/src/ui-engine/select-engine.ts +21 -0
- package/src/ui-engine/style-resolver.ts +416 -0
- package/src/ui-engine/text-layout.ts +114 -0
- package/src/ui-engine/transpile-ui.ts +45 -0
- package/src/ui-engine/ua-stylesheet.ts +60 -0
- package/src/ui-engine/ui-file-splitter.ts +59 -0
- package/src/ui-engine/ui-lowering.ts +459 -0
- package/src/ui-engine/ui-registry.ts +530 -0
- package/src/ui-engine/yoga-layout.ts +309 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Slice of the C++ runtime header (original source lines 1449-1547).
|
|
2
|
+
// Canvas push/draw helpers, buffered scroll canvas push, scrollbar direct.
|
|
3
|
+
// See docs/superpowers/specs/2026-07-12-split-runtime-header-design.md.
|
|
4
|
+
export function emitCanvasScrollbar() {
|
|
5
|
+
return `
|
|
6
|
+
static inline void ui_push_canvas_rect(CuttlefishCanvas16* canvas, int16_t x, int16_t y, int16_t w, int16_t h) {
|
|
7
|
+
if (!canvas || !display_canvasBuffer(canvas)) return;
|
|
8
|
+
UI_COLOR_T* pixels = display_canvasBuffer(canvas);
|
|
9
|
+
int16_t stride = display_canvasWidth(canvas);
|
|
10
|
+
// The canvas is viewport-sized: buffer row 0 = the first row of the viewport.
|
|
11
|
+
// The display destination is (x, y) but the source buffer starts at (0, 0).
|
|
12
|
+
// When a full-screen framebuffer is the active draw target, composite into it
|
|
13
|
+
// via __ui_gfx (so the single bulk push at frame end captures everything).
|
|
14
|
+
// Otherwise write straight to the display in one SPI transaction.
|
|
15
|
+
if (__ui_fb) {
|
|
16
|
+
if (w == stride) {
|
|
17
|
+
ui_display_draw_rgb_bitmap(x, y, pixels, w, h);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (int16_t row = 0; row < h; row++) {
|
|
21
|
+
ui_display_draw_rgb_bitmap(x, y + row, pixels + (int32_t)row * stride, w, 1);
|
|
22
|
+
}
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
display_startWrite();
|
|
26
|
+
display_setAddrWindow(x, y, w, h);
|
|
27
|
+
if (w == stride) {
|
|
28
|
+
// Full-width: contiguous in buffer, single write.
|
|
29
|
+
display_writePixels(pixels, (uint32_t)w * h);
|
|
30
|
+
display_endWrite();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
for (int16_t row = 0; row < h; row++) {
|
|
34
|
+
display_writePixels(pixels + (int32_t)row * stride, w);
|
|
35
|
+
}
|
|
36
|
+
display_endWrite();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static inline void ui_draw_canvas_rect(CuttlefishCanvas16* canvas, int16_t x, int16_t y, int16_t w, int16_t h) {
|
|
40
|
+
if (!canvas || !display_canvasBuffer(canvas)) return;
|
|
41
|
+
UI_COLOR_T* pixels = display_canvasBuffer(canvas);
|
|
42
|
+
int16_t stride = display_canvasWidth(canvas);
|
|
43
|
+
if (w == stride && h == display_canvasHeight(canvas)) {
|
|
44
|
+
ui_display_draw_rgb_bitmap(x, y, pixels, w, h);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
for (int16_t row = 0; row < h; row++) {
|
|
48
|
+
ui_display_draw_rgb_bitmap(x, y + row, pixels + (int32_t)row * stride, w, 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static inline void ui_push_buffered_scroll_canvas(CuttlefishCanvas16* bufferedScrollCanvas,
|
|
53
|
+
CuttlefishCanvas16* bufferedScrollRepaintCanvas,
|
|
54
|
+
int16_t bufferedScrollNode,
|
|
55
|
+
int16_t bufferedScrollVX,
|
|
56
|
+
int16_t bufferedScrollVY,
|
|
57
|
+
int16_t bufferedScrollRepaintY,
|
|
58
|
+
int16_t bufferedScrollRepaintH,
|
|
59
|
+
CuttlefishDisplayTarget* drawTarget) {
|
|
60
|
+
if (bufferedScrollNode < 0 || !bufferedScrollCanvas || !display_canvasBuffer(bufferedScrollCanvas)) return;
|
|
61
|
+
// Draw scrollbar into the canvas (canvas-local coords: 0,0 = viewport top-left).
|
|
62
|
+
ui_display_set_target(bufferedScrollCanvas);
|
|
63
|
+
int16_t si = bufferedScrollNode;
|
|
64
|
+
int16_t vw = __ui_nodes[si].box.w;
|
|
65
|
+
int16_t vh = __ui_nodes[si].box.h;
|
|
66
|
+
if (bufferedScrollRepaintCanvas && bufferedScrollRepaintH > 0) {
|
|
67
|
+
ui_draw_canvas_rect(bufferedScrollRepaintCanvas, 0, bufferedScrollRepaintY, vw, bufferedScrollRepaintH);
|
|
68
|
+
}
|
|
69
|
+
int16_t tx = vw - 4;
|
|
70
|
+
uint16_t thumbH = (uint32_t)vh * vh / __ui_nodes[si].contentHeight;
|
|
71
|
+
if (thumbH < 8) thumbH = 8;
|
|
72
|
+
int16_t maxScroll = __ui_nodes[si].contentHeight - vh;
|
|
73
|
+
uint16_t thumbY = (uint32_t)(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
|
|
74
|
+
UI_COLOR_T dimFg = (UI_COLOR_T)((__ui_nodes[si].fg >> 1) & UI_DIM_MASK);
|
|
75
|
+
ui_display_fill_rect(tx, 0, 3, vh, dimFg);
|
|
76
|
+
ui_display_fill_rect(tx, thumbY, 3, thumbH, __ui_nodes[si].fg);
|
|
77
|
+
// Record the scrollY this canvas now reflects, so the next scroll frame can
|
|
78
|
+
// compute its shift delta (Mode B) from scrollY - lastPaintedScrollY.
|
|
79
|
+
__ui_nodes[si].lastPaintedScrollY = __ui_nodes[si].scrollY;
|
|
80
|
+
// Push the canvas to the draw target at the viewport position (the
|
|
81
|
+
// framebuffer when active, else the display directly).
|
|
82
|
+
ui_display_set_target(drawTarget);
|
|
83
|
+
ui_push_canvas_rect(bufferedScrollCanvas,
|
|
84
|
+
bufferedScrollVX, bufferedScrollVY,
|
|
85
|
+
vw, vh);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Draw a scroll container's scrollbar directly on the display (Mode C).
|
|
89
|
+
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;
|
|
91
|
+
int16_t vw = __ui_nodes[si].box.w;
|
|
92
|
+
int16_t vh = __ui_nodes[si].box.h;
|
|
93
|
+
if (__ui_nodes[si].contentHeight <= vh) return;
|
|
94
|
+
int16_t tx = vox + vw - 4;
|
|
95
|
+
uint16_t thumbH = (uint32_t)vh * vh / __ui_nodes[si].contentHeight;
|
|
96
|
+
if (thumbH < 8) thumbH = 8;
|
|
97
|
+
int16_t maxScroll = __ui_nodes[si].contentHeight - vh;
|
|
98
|
+
uint16_t thumbY = (uint32_t)(vh - thumbH) * __ui_nodes[si].scrollY / (maxScroll > 0 ? maxScroll : 1);
|
|
99
|
+
UI_COLOR_T dimFg = (UI_COLOR_T)((__ui_nodes[si].fg >> 1) & UI_DIM_MASK);
|
|
100
|
+
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);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Per-node dirty marker (called by press handlers and binding evaluation).`;
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function emitColorMonoRefresh(): string;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Slice of the C++ runtime header (original source lines 304-451).
|
|
2
|
+
// lerp/blend fwd-decls, color-depth selection, mono snap, per-frame refresh dispatch.
|
|
3
|
+
// See docs/superpowers/specs/2026-07-12-split-runtime-header-design.md.
|
|
4
|
+
export function emitColorMonoRefresh() {
|
|
5
|
+
return `
|
|
6
|
+
|
|
7
|
+
// ── Color depth → blend/lerp selection ───────────────────────────────────────
|
|
8
|
+
// UI_COLOR_DEPTH is emitted by the UI emitter from the display profile's
|
|
9
|
+
// colorFormat (565 for TFT byte-identity, 888 for rgb666+). The value depth
|
|
10
|
+
// and the blend math MUST switch together: on 565, node fields hold 565 values
|
|
11
|
+
// and ui_blend565 is correct; on 888, node fields hold 888 values and
|
|
12
|
+
// ui_blend888 is correct. Forward-declare the four functions and define the
|
|
13
|
+
// ui_blend/UI_LERP_COLOR macros here (before any call site) so they resolve
|
|
14
|
+
// everywhere; the function bodies are defined later in this header.
|
|
15
|
+
#ifndef UI_COLOR_DEPTH
|
|
16
|
+
#define UI_COLOR_DEPTH 565
|
|
17
|
+
#endif
|
|
18
|
+
// Color value type tracks the depth: 888 holds 24-bit RGB (R<<16|G<<8|B),
|
|
19
|
+
// 565 holds 16-bit. Draw wrappers and locals use UI_COLOR_T so 888 is not
|
|
20
|
+
// narrowed before reaching the HAL. Under 565/mono this is uint16_t and the
|
|
21
|
+
// emitted code is byte-identical with the pre-widening runtime.
|
|
22
|
+
#if UI_COLOR_DEPTH == 888
|
|
23
|
+
#ifndef UI_COLOR_T
|
|
24
|
+
#define UI_COLOR_T uint32_t
|
|
25
|
+
#endif
|
|
26
|
+
#ifndef UI_DIM_MASK
|
|
27
|
+
#define UI_DIM_MASK 0x7F7F7Fu // halve each 8-bit channel independently
|
|
28
|
+
#endif
|
|
29
|
+
#else
|
|
30
|
+
#ifndef UI_COLOR_T
|
|
31
|
+
#define UI_COLOR_T uint16_t
|
|
32
|
+
#endif
|
|
33
|
+
#ifndef UI_DIM_MASK
|
|
34
|
+
#define UI_DIM_MASK 0x7BEFu // 565 dim mask (top bit clear per channel)
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
37
|
+
static inline uint16_t ui_blend565(uint16_t fg, uint16_t bg, uint8_t opacity);
|
|
38
|
+
static inline uint32_t ui_blend888(uint32_t fg, uint32_t bg, uint8_t opacity);
|
|
39
|
+
static inline uint16_t lerp_color(uint16_t a, uint16_t b, uint8_t k100);
|
|
40
|
+
static inline uint32_t lerp_color_888(uint32_t a, uint32_t b, uint8_t k100);
|
|
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))
|
|
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))
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
// ── 1-bit mono snap (UI_NATIVE_MONO) ─────────────────────────────────────────
|
|
50
|
+
// On a B&W e-ink panel, any color value must resolve to black or white. Node
|
|
51
|
+
// fields are pre-snapped at transpile, but blended/lerped runtime values
|
|
52
|
+
// (opacity, shadows, gradients) need a defensive snap in the draw path. The
|
|
53
|
+
// macro is a no-op on color targets so TFT output is byte-identical.
|
|
54
|
+
#ifdef UI_NATIVE_MONO
|
|
55
|
+
// Snap an RGB888 value to 1-bit mono (white/black) by luminance.
|
|
56
|
+
static inline uint32_t ui_snap_mono(uint32_t c) {
|
|
57
|
+
uint8_t r = (c >> 16) & 0xff, g = (c >> 8) & 0xff, b = c & 0xff;
|
|
58
|
+
// Match the transpile-time toMono threshold: (0.299r + 0.587g + 0.114b)/255 >= 0.27.
|
|
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;
|
|
61
|
+
}
|
|
62
|
+
// Snap an RGB565 value to 1-bit mono. Mono panels run at UI_COLOR_DEPTH 565, so
|
|
63
|
+
// node fields hold 565 values; reconstruct 8-bit channels then apply the threshold.
|
|
64
|
+
// Pre-snapped values (0x0000/0x0001/0xffff) pass through directly — the
|
|
65
|
+
// transpiler resolves #ffffff/#000000 to 0x0001/0x0000 on mono targets.
|
|
66
|
+
static inline uint16_t ui_snap_mono565(uint16_t c) {
|
|
67
|
+
if (c == 0x0000u) return 0x0000u;
|
|
68
|
+
if (c == 0x0001u || c == 0xffffu) return 0xffffu;
|
|
69
|
+
uint8_t r5 = (c >> 11) & 0x1f, g6 = (c >> 5) & 0x3f, b5 = c & 0x1f;
|
|
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;
|
|
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)))
|
|
75
|
+
#else
|
|
76
|
+
#define UI_MAYBE_SNAP_MONO(c) (c)
|
|
77
|
+
#define UI_MAYBE_SNAP_MONO565(c) (c)
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
// ── Per-frame refresh dispatch ──────────────────────────────────────────────
|
|
81
|
+
// Three mutually-exclusive compile-time paths, in priority order:
|
|
82
|
+
// 1. UI_REQUIRES_BACKING_STORE (e-ink): dirty-rect accumulator + partial refresh.
|
|
83
|
+
// 2. UI_BATCH_SPI_WRITES (TFT immediate): one startWrite/endWrite per frame.
|
|
84
|
+
// 3. default (SDL native host): no-ops.
|
|
85
|
+
// Exactly one branch ever compiles — the emitter's guards ensure the first two
|
|
86
|
+
// are never both defined (UI_REQUIRES_BACKING_STORE ⟹ requiresBackingStore,
|
|
87
|
+
// UI_BATCH_SPI_WRITES ⟹ immediate && !requiresBackingStore).
|
|
88
|
+
#if defined(UI_REQUIRES_BACKING_STORE)
|
|
89
|
+
// e-ink / deferred-partial: dirty-rect accumulator. Each painted node reports
|
|
90
|
+
// its paint rect; at frame end the union is refreshed as one partial update
|
|
91
|
+
// via display_partial_refresh.
|
|
92
|
+
#define UI_REFRESH_MAX_RECTS 16
|
|
93
|
+
struct UIRect16 { int16_t x, y, w, h; };
|
|
94
|
+
static UIRect16 __ui_refresh_rects[UI_REFRESH_MAX_RECTS];
|
|
95
|
+
static uint8_t __ui_refresh_rect_n = 0;
|
|
96
|
+
static inline void ui_refresh_begin_frame() { __ui_refresh_rect_n = 0; }
|
|
97
|
+
static inline void ui_refresh_add_rect(int16_t x, int16_t y, int16_t w, int16_t h) {
|
|
98
|
+
if (w <= 0 || h <= 0) return;
|
|
99
|
+
if (__ui_refresh_rect_n < UI_REFRESH_MAX_RECTS) {
|
|
100
|
+
__ui_refresh_rects[__ui_refresh_rect_n].x = x;
|
|
101
|
+
__ui_refresh_rects[__ui_refresh_rect_n].y = y;
|
|
102
|
+
__ui_refresh_rects[__ui_refresh_rect_n].w = w;
|
|
103
|
+
__ui_refresh_rects[__ui_refresh_rect_n].h = h;
|
|
104
|
+
__ui_refresh_rect_n++;
|
|
105
|
+
}
|
|
106
|
+
// TODO Phase 5: coalesce overlapping rects into a tighter union; cap by
|
|
107
|
+
// refresh budget; trigger a periodic full refresh for ghost clearing.
|
|
108
|
+
}
|
|
109
|
+
// Union all accumulated rects and issue one partial refresh of the bounding
|
|
110
|
+
// region via the shim's display_partial_refresh entry point.
|
|
111
|
+
static inline void ui_refresh_flush() {
|
|
112
|
+
if (__ui_refresh_rect_n == 0) return;
|
|
113
|
+
int16_t x0 = 32767, y0 = 32767, x1 = -32768, y1 = -32768;
|
|
114
|
+
for (uint8_t i = 0; i < __ui_refresh_rect_n; i++) {
|
|
115
|
+
const UIRect16& r = __ui_refresh_rects[i];
|
|
116
|
+
if (r.x < x0) x0 = r.x;
|
|
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);
|
|
119
|
+
if (rx1 > x1) x1 = rx1;
|
|
120
|
+
if (ry1 > y1) y1 = ry1;
|
|
121
|
+
}
|
|
122
|
+
if (x0 < 0) x0 = 0;
|
|
123
|
+
if (y0 < 0) y0 = 0;
|
|
124
|
+
if (x1 > display_width()) x1 = display_width();
|
|
125
|
+
if (y1 > display_height()) y1 = display_height();
|
|
126
|
+
if (x1 > x0 && y1 > y0) {
|
|
127
|
+
display_partial_refresh(x0, y0, (int16_t)(x1 - x0), (int16_t)(y1 - y0));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
#elif defined(UI_BATCH_SPI_WRITES)
|
|
131
|
+
// TFT immediate-refresh batching (CURRENTLY UNUSED — see note below).
|
|
132
|
+
// Wraps the frame's draws in ONE SPI transaction so all per-node writes share
|
|
133
|
+
// a single CS-asserted burst. add_rect is a no-op: TFT has no partial-refresh
|
|
134
|
+
// concept; the per-node draws already target the right pixels.
|
|
135
|
+
//
|
|
136
|
+
// NOTE: this branch is left in place but the emitter does NOT define
|
|
137
|
+
// UI_BATCH_SPI_WRITES by default. The design assumed Adafruit_SPITFT's
|
|
138
|
+
// startWrite/endWrite are reference-counted (nested calls = no-op for CS),
|
|
139
|
+
// but the Adafruit_GFX version in this repo is NOT — every endWrite raises
|
|
140
|
+
// CS unconditionally. So an outer frame startWrite gets closed by the first
|
|
141
|
+
// inner draw's endWrite → black screen. Re-enable only after either (a)
|
|
142
|
+
// upgrading to a ref-counted Adafruit_GFX or (b) adding a runtime flag the
|
|
143
|
+
// inner draw primitives check to skip their own startWrite/endWrite.
|
|
144
|
+
// See docs/superpowers/specs/2026-07-06-tft-spi-write-batching-design.md.
|
|
145
|
+
static inline void ui_refresh_begin_frame() { display_startWrite(); }
|
|
146
|
+
static inline void ui_refresh_add_rect(int16_t x, int16_t y, int16_t w, int16_t h) { (void)x; (void)y; (void)w; (void)h; }
|
|
147
|
+
static inline void ui_refresh_flush() { display_endWrite(); }
|
|
148
|
+
#else
|
|
149
|
+
// No batching (e.g. SDL native host render): true no-ops.
|
|
150
|
+
#define ui_refresh_begin_frame() ((void)0)
|
|
151
|
+
#define ui_refresh_add_rect(x, y, w, h) ((void)0)
|
|
152
|
+
#define ui_refresh_flush() ((void)0)
|
|
153
|
+
#endif`;
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function emitDirtyScrollMutators(): string;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Slice of the C++ runtime header (original source lines 1548-1710).
|
|
2
|
+
// mark_dirty, subtree dirty, scroll direct prepare/compositor, scroll view dirty/overlap/invalidate.
|
|
3
|
+
// See docs/superpowers/specs/2026-07-12-split-runtime-header-design.md.
|
|
4
|
+
export function emitDirtyScrollMutators() {
|
|
5
|
+
return `
|
|
6
|
+
static inline void ui_mark_dirty(uint16_t nodeIdx) {
|
|
7
|
+
if (nodeIdx >= __ui_node_count) return;
|
|
8
|
+
__ui_nodes[nodeIdx].dirty = 1;
|
|
9
|
+
if (ui_is_effectively_visible(nodeIdx) &&
|
|
10
|
+
__ui_nodes[nodeIdx].screenId == __ui_active_screen) {
|
|
11
|
+
UIRect r;
|
|
12
|
+
ui_node_current_paint_rect(nodeIdx, &r);
|
|
13
|
+
if (r.w <= 0 || r.h <= 0) {
|
|
14
|
+
ui_mark_overlapping_higher_layers_dirty(nodeIdx);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
uint16_t p = __ui_nodes[nodeIdx].parent;
|
|
18
|
+
while (p != UI_NO_PARENT && p < __ui_node_count) {
|
|
19
|
+
if (__ui_nodes[p].scrollable &&
|
|
20
|
+
!__ui_nodes[p].virtualized &&
|
|
21
|
+
__ui_nodes[p].contentHeight > __ui_nodes[p].box.h) {
|
|
22
|
+
UIRect clip = {
|
|
23
|
+
__ui_nodes[p].box.x,
|
|
24
|
+
__ui_nodes[p].box.y,
|
|
25
|
+
__ui_nodes[p].box.w,
|
|
26
|
+
__ui_nodes[p].box.h
|
|
27
|
+
};
|
|
28
|
+
if (!ui_rects_intersect(r.x, r.y, r.w, r.h, clip.x, clip.y, clip.w, clip.h)) {
|
|
29
|
+
__ui_nodes[nodeIdx].dirty = 0;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (r.x < clip.x ||
|
|
33
|
+
r.x + r.w > clip.x + clip.w ||
|
|
34
|
+
r.y < clip.y ||
|
|
35
|
+
r.y + r.h > clip.y + clip.h) {
|
|
36
|
+
ui_mark_scroll_view_dirty(p);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Fully inside the viewport, but overflow scroll content is canvas-
|
|
40
|
+
// composited. Promote to a scroll repaint — otherwise the defer path
|
|
41
|
+
// drops the child's dirty flag without drawing (e.g. :pressed buttons).
|
|
42
|
+
ui_mark_scroll_view_dirty(p);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
p = __ui_nodes[p].parent;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
ui_mark_overlapping_higher_layers_dirty(nodeIdx);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Set dirty=1 across a scroll subtree WITHOUT the per-child O(n) overlap repair.
|
|
52
|
+
// During scroll the subtree repaints into a freshly-cleared off-screen canvas, so
|
|
53
|
+
// intra-subtree overlap repair is pointless, and scroll children are draw-clipped
|
|
54
|
+
// to the container's viewport box — so all external higher-z neighbors of the
|
|
55
|
+
// viewport are covered by ONE overlap check at the container's paint rect (done by
|
|
56
|
+
// the caller). This drops scroll marking from O(K·n) to O(K + n).
|
|
57
|
+
static inline void ui_mark_subtree_dirty_local(uint16_t scrollNode) {
|
|
58
|
+
if (scrollNode >= __ui_node_count) return;
|
|
59
|
+
for (uint16_t c = scrollNode + 1; c < __ui_nodes[scrollNode].subtreeEnd; c++) {
|
|
60
|
+
__ui_nodes[c].dirty = 1;
|
|
61
|
+
}
|
|
62
|
+
__ui_nodes[scrollNode].dirty = 1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Mode C strip-only: direct-partial scroll when no viewport canvas fits and the
|
|
66
|
+
// scroll delta is small. Fills only the exposed strip on the display, then marks
|
|
67
|
+
// visible descendants dirty for direct draw — never clears the whole viewport.
|
|
68
|
+
static inline void ui_scroll_direct_prepare(uint16_t s, int16_t* outVX, int16_t* outVY) {
|
|
69
|
+
int16_t vw = __ui_nodes[s].box.w;
|
|
70
|
+
int16_t vh = __ui_nodes[s].box.h;
|
|
71
|
+
int16_t vox = __ui_nodes[s].box.x;
|
|
72
|
+
int16_t voy = __ui_nodes[s].box.y;
|
|
73
|
+
UI_COLOR_T scrollBg = __ui_nodes[s].hasBg ? __ui_nodes[s].bg : __ui_nodes[s].clearColor;
|
|
74
|
+
int16_t deltaY = __ui_nodes[s].scrollY - __ui_nodes[s].lastPaintedScrollY;
|
|
75
|
+
int16_t absDelta = deltaY < 0 ? -deltaY : deltaY;
|
|
76
|
+
int16_t stripY = deltaY > 0 ? (int16_t)(vh - absDelta) : 0;
|
|
77
|
+
ui_display_fill_rect(vox, (int16_t)(voy + stripY), vw, absDelta, scrollBg);
|
|
78
|
+
for (uint16_t c = s + 1; c < __ui_nodes[s].subtreeEnd; c++) {
|
|
79
|
+
if (!ui_is_effectively_visible(c) || __ui_nodes[c].screenId != __ui_active_screen) {
|
|
80
|
+
__ui_nodes[c].dirty = 0;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
__ui_nodes[c].dirty = 1;
|
|
84
|
+
if (__ui_nodes[c].kind == NODE_PROGRESS || __ui_nodes[c].kind == NODE_RANGE) {
|
|
85
|
+
__ui_nodes[c].lastTextWidth = -1;
|
|
86
|
+
}
|
|
87
|
+
__ui_nodes[c].lastTextHeight = 0;
|
|
88
|
+
}
|
|
89
|
+
__ui_nodes[s].dirty = 0;
|
|
90
|
+
if (outVX) *outVX = vox;
|
|
91
|
+
if (outVY) *outVY = voy;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Nearest overflow scroll container owning nodeIdx (or nodeIdx itself).
|
|
95
|
+
static inline int16_t ui_overflow_scroll_compositor(uint16_t nodeIdx) {
|
|
96
|
+
if (nodeIdx >= __ui_node_count) return -1;
|
|
97
|
+
if (__ui_nodes[nodeIdx].scrollable && !__ui_nodes[nodeIdx].virtualized &&
|
|
98
|
+
__ui_nodes[nodeIdx].contentHeight > __ui_nodes[nodeIdx].box.h) {
|
|
99
|
+
return (int16_t)nodeIdx;
|
|
100
|
+
}
|
|
101
|
+
uint16_t p = __ui_nodes[nodeIdx].parent;
|
|
102
|
+
while (p != UI_NO_PARENT && p < __ui_node_count) {
|
|
103
|
+
if (__ui_nodes[p].scrollable && !__ui_nodes[p].virtualized &&
|
|
104
|
+
__ui_nodes[p].contentHeight > __ui_nodes[p].box.h) {
|
|
105
|
+
return (int16_t)p;
|
|
106
|
+
}
|
|
107
|
+
p = __ui_nodes[p].parent;
|
|
108
|
+
}
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static inline void ui_mark_scroll_view_overlaps_dirty(uint16_t scrollNode) {
|
|
113
|
+
if (scrollNode >= __ui_node_count) return;
|
|
114
|
+
if (!ui_is_effectively_visible(scrollNode)) return;
|
|
115
|
+
if (__ui_nodes[scrollNode].screenId != __ui_active_screen) return;
|
|
116
|
+
UIRect r;
|
|
117
|
+
ui_node_current_paint_rect(scrollNode, &r);
|
|
118
|
+
if (r.w <= 0 || r.h <= 0) return;
|
|
119
|
+
for (uint16_t c = 0; c < __ui_node_count; c++) {
|
|
120
|
+
if (c == scrollNode) continue;
|
|
121
|
+
if (c > scrollNode && c < __ui_nodes[scrollNode].subtreeEnd) continue;
|
|
122
|
+
if (__ui_nodes[c].dirty) continue;
|
|
123
|
+
if (!ui_is_effectively_visible(c)) continue;
|
|
124
|
+
if (__ui_nodes[c].screenId != __ui_active_screen) continue;
|
|
125
|
+
if (!ui_node_draws_before(scrollNode, c)) continue;
|
|
126
|
+
UIRect cr;
|
|
127
|
+
ui_node_current_paint_rect(c, &cr);
|
|
128
|
+
if (cr.w <= 0 || cr.h <= 0) continue;
|
|
129
|
+
if (ui_rects_intersect(r.x, r.y, r.w, r.h, cr.x, cr.y, cr.w, cr.h)) {
|
|
130
|
+
__ui_nodes[c].dirty = 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static inline void ui_mark_scroll_subtree_dirty(uint16_t scrollNode) {
|
|
136
|
+
ui_mark_subtree_dirty_local(scrollNode);
|
|
137
|
+
// Single overlap check at the container's paint rect covers every external
|
|
138
|
+
// higher-z neighbor of the viewport. The container index is the right one to
|
|
139
|
+
// pass: scroll content lives within the container's stacking context, so
|
|
140
|
+
// ui_node_draws_before(scrollNode, c) selects exactly the external layers that
|
|
141
|
+
// should be repaired when the viewport is repainted.
|
|
142
|
+
ui_mark_overlapping_higher_layers_dirty(scrollNode);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static inline void ui_mark_scroll_view_dirty(uint16_t scrollNode) {
|
|
146
|
+
if (scrollNode >= __ui_node_count) return;
|
|
147
|
+
__ui_nodes[scrollNode].dirty = 1;
|
|
148
|
+
ui_mark_scroll_view_overlaps_dirty(scrollNode);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static inline int16_t ui_scroll_ancestor_for_node(uint16_t nodeIdx) {
|
|
152
|
+
uint16_t p = __ui_nodes[nodeIdx].parent;
|
|
153
|
+
while (p != UI_NO_PARENT && p < __ui_node_count) {
|
|
154
|
+
if (__ui_nodes[p].scrollable) return (int16_t)p;
|
|
155
|
+
p = __ui_nodes[p].parent;
|
|
156
|
+
}
|
|
157
|
+
return -1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static inline void ui_invalidate_scroll_canvas_for_node(uint16_t nodeIdx) {
|
|
161
|
+
int16_t scrollParent = ui_scroll_ancestor_for_node(nodeIdx);
|
|
162
|
+
if (scrollParent < 0) return;
|
|
163
|
+
if (__ui_nodes[scrollParent].virtualized) return;
|
|
164
|
+
if (__ui_nodes[scrollParent].contentHeight <= __ui_nodes[scrollParent].box.h) return;
|
|
165
|
+
int16_t span = __ui_nodes[scrollParent].box.h > 0 ? __ui_nodes[scrollParent].box.h : 1;
|
|
166
|
+
__ui_nodes[scrollParent].lastPaintedScrollY = __ui_nodes[scrollParent].scrollY - span;
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function emitDisplayShim(): string;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Slice of the C++ runtime header (original source lines 902-999).
|
|
2
|
+
// ui_display_* target/pixel/bitmap/rect/cursor/text shim layer.
|
|
3
|
+
// See docs/superpowers/specs/2026-07-12-split-runtime-header-design.md.
|
|
4
|
+
export function emitDisplayShim() {
|
|
5
|
+
return `
|
|
6
|
+
|
|
7
|
+
static inline CuttlefishDisplayTarget* ui_display_get_target() { return __ui_gfx; }
|
|
8
|
+
static inline void ui_display_set_target(CuttlefishDisplayTarget* target) {
|
|
9
|
+
__ui_gfx = target ? target : display_defaultTarget();
|
|
10
|
+
}
|
|
11
|
+
static inline void ui_display_use_default_target() {
|
|
12
|
+
__ui_gfx = display_defaultTarget();
|
|
13
|
+
}
|
|
14
|
+
static inline uint8_t ui_display_is_default_target() {
|
|
15
|
+
return __ui_gfx == display_defaultTarget();
|
|
16
|
+
}
|
|
17
|
+
static inline int16_t ui_display_target_width() {
|
|
18
|
+
return display_targetWidth(__ui_gfx);
|
|
19
|
+
}
|
|
20
|
+
static inline int16_t ui_display_target_height() {
|
|
21
|
+
return display_targetHeight(__ui_gfx);
|
|
22
|
+
}
|
|
23
|
+
static inline int16_t ui_clamp_i16(int16_t value, int16_t lo, int16_t hi) {
|
|
24
|
+
if (value < lo) return lo;
|
|
25
|
+
if (value > hi) return hi;
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
static inline void ui_display_target_bounds(int16_t* left, int16_t* top, int16_t* right, int16_t* bottom) {
|
|
29
|
+
if (left) *left = (int16_t)(-__ui_draw_off_x);
|
|
30
|
+
if (top) *top = (int16_t)(-__ui_draw_off_y);
|
|
31
|
+
if (right) *right = (int16_t)(ui_display_target_width() - __ui_draw_off_x);
|
|
32
|
+
if (bottom) *bottom = (int16_t)(ui_display_target_height() - __ui_draw_off_y);
|
|
33
|
+
}
|
|
34
|
+
static inline uint8_t ui_clip_rect_to_display_target(int16_t* x, int16_t* y, int16_t* w, int16_t* h) {
|
|
35
|
+
if (!x || !y || !w || !h || *w <= 0 || *h <= 0) return 0;
|
|
36
|
+
int16_t left, top, right, bottom;
|
|
37
|
+
ui_display_target_bounds(&left, &top, &right, &bottom);
|
|
38
|
+
int16_t x0 = *x > left ? *x : left;
|
|
39
|
+
int16_t y0 = *y > top ? *y : top;
|
|
40
|
+
int16_t x1 = (int16_t)(*x + *w);
|
|
41
|
+
int16_t y1 = (int16_t)(*y + *h);
|
|
42
|
+
if (x1 > right) x1 = right;
|
|
43
|
+
if (y1 > bottom) y1 = bottom;
|
|
44
|
+
if (x0 >= x1 || y0 >= y1) return 0;
|
|
45
|
+
*x = x0;
|
|
46
|
+
*y = y0;
|
|
47
|
+
*w = (int16_t)(x1 - x0);
|
|
48
|
+
*h = (int16_t)(y1 - y0);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
static inline void ui_display_draw_pixel(int16_t x, int16_t y, UI_COLOR_T color) {
|
|
52
|
+
display_targetDrawPixel(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, UI_MAYBE_SNAP_MONO565(color));
|
|
53
|
+
}
|
|
54
|
+
static inline void ui_display_draw_rgb_bitmap(int16_t x, int16_t y, const UI_COLOR_T* bitmap, int16_t w, int16_t h) {
|
|
55
|
+
display_targetDrawRGBBitmap(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, bitmap, w, h);
|
|
56
|
+
}
|
|
57
|
+
static inline void ui_display_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) {
|
|
58
|
+
display_targetFillRect(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, w, h, UI_MAYBE_SNAP_MONO565(color));
|
|
59
|
+
}
|
|
60
|
+
static inline void ui_display_draw_fast_hline(int16_t x, int16_t y, int16_t w, UI_COLOR_T color) {
|
|
61
|
+
display_targetDrawFastHLine(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, w, UI_MAYBE_SNAP_MONO565(color));
|
|
62
|
+
}
|
|
63
|
+
static inline void ui_display_draw_fast_vline(int16_t x, int16_t y, int16_t h, UI_COLOR_T color) {
|
|
64
|
+
display_targetDrawFastVLine(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, h, UI_MAYBE_SNAP_MONO565(color));
|
|
65
|
+
}
|
|
66
|
+
static inline void ui_display_fill_round_rect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) {
|
|
67
|
+
display_targetFillRoundRect(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, w, h, r, UI_MAYBE_SNAP_MONO565(color));
|
|
68
|
+
}
|
|
69
|
+
static inline void ui_display_draw_rect(int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) {
|
|
70
|
+
display_targetDrawRect(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, w, h, UI_MAYBE_SNAP_MONO565(color));
|
|
71
|
+
}
|
|
72
|
+
static inline void ui_display_draw_round_rect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) {
|
|
73
|
+
display_targetDrawRoundRect(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, w, h, r, UI_MAYBE_SNAP_MONO565(color));
|
|
74
|
+
}
|
|
75
|
+
static inline void ui_display_draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T color) {
|
|
76
|
+
display_targetDrawLine(__ui_gfx, x0 + __ui_draw_off_x, y0 + __ui_draw_off_y,
|
|
77
|
+
x1 + __ui_draw_off_x, y1 + __ui_draw_off_y, UI_MAYBE_SNAP_MONO565(color));
|
|
78
|
+
}
|
|
79
|
+
static inline void ui_display_fill_circle(int16_t x, int16_t y, int16_t r, UI_COLOR_T color) {
|
|
80
|
+
display_targetFillCircle(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, r, UI_MAYBE_SNAP_MONO565(color));
|
|
81
|
+
}
|
|
82
|
+
static inline void ui_display_draw_circle(int16_t x, int16_t y, int16_t r, UI_COLOR_T color) {
|
|
83
|
+
display_targetDrawCircle(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y, r, UI_MAYBE_SNAP_MONO565(color));
|
|
84
|
+
}
|
|
85
|
+
static inline void ui_display_set_cursor(int16_t x, int16_t y) {
|
|
86
|
+
display_targetSetCursor(__ui_gfx, x + __ui_draw_off_x, y + __ui_draw_off_y);
|
|
87
|
+
}
|
|
88
|
+
static inline void ui_display_set_text_color(UI_COLOR_T fg, UI_COLOR_T bg) {
|
|
89
|
+
display_targetSetTextColorBg(__ui_gfx, fg, bg);
|
|
90
|
+
}
|
|
91
|
+
static inline void ui_display_set_text_color_solid(UI_COLOR_T fg) {
|
|
92
|
+
display_targetSetTextColor(__ui_gfx, fg);
|
|
93
|
+
}
|
|
94
|
+
static inline void ui_display_set_text_size(uint8_t size) {
|
|
95
|
+
display_targetSetTextSize(__ui_gfx, size);
|
|
96
|
+
}
|
|
97
|
+
static inline void ui_display_set_text_wrap(bool wrap) {
|
|
98
|
+
display_targetSetTextWrap(__ui_gfx, wrap);
|
|
99
|
+
}
|
|
100
|
+
static inline void ui_display_print(const char* text) {
|
|
101
|
+
display_targetPrint(__ui_gfx, text);
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function emitForwardDecls(): string;
|