From bf025d78c0e45fa9b8d8395aa290a0dd6fbeafe8 Mon Sep 17 00:00:00 2001 From: Ryan Rauh Date: Sun, 14 Jun 2026 07:02:03 -0400 Subject: [PATCH] removes the unneeded logic of undefined color fallbacks as its not possible --- ops.ts | 8 +++++--- src/clayterm.c | 29 +++++++++++++++++++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/ops.ts b/ops.ts index cb93969..4f80c41 100644 --- a/ops.ts +++ b/ops.ts @@ -190,9 +190,11 @@ export function pack( ); o += 4; - // Resolved per-side attributes (CSS-like fallback expansion done - // here, not in C): fg/bg word pairs in top, right, bottom, left - // order. The C renderer consumes these as explicit values. + // Must match render_border() in src/clayterm.c. + // Resolve CSS-like side fallbacks here, then write eight required + // attribute words: fg/bg pairs in top, right, bottom, left order. + // C treats the presence and order of these words as a wire-format + // invariant and only consumes the explicit values. for (let side of [b.top, b.right, b.bottom, b.left]) { view.setUint32(o, sideFg(side, b.color), true); o += 4; diff --git a/src/clayterm.c b/src/clayterm.c index 42b478d..e701790 100644 --- a/src/clayterm.c +++ b/src/clayterm.c @@ -303,17 +303,26 @@ static void render_text(struct Clayterm *ct, int x0, int y0, static void render_border(struct Clayterm *ct, int x0, int y0, int x1, int y1, Clay_RenderCommand *cmd) { Clay_BorderRenderData *b = &cmd->renderData.border; - /* userData points at eight words in the command buffer carrying resolved - * per-side attributes as fg/bg pairs in top, right, bottom, left order. - * Fallback resolution (shared color/bg vs side overrides) happens on the - * TypeScript side; this renderer consumes explicit values only. The - * command buffer outlives the render pass within reduce(). */ + /* Must match border packing in ops.ts. + * userData points at eight required words in the command buffer: resolved + * fg/bg pairs in top, right, bottom, left order. Fallback resolution + * (shared color/bg vs side overrides) happens on the TypeScript side; this + * renderer consumes explicit values only. The command buffer outlives the + * render pass within reduce(). Missing userData is a wire-format violation. + */ const uint32_t *s = (const uint32_t *)cmd->userData; - uint32_t deffg = color(b->color); - uint32_t top_fg = s ? s[0] : deffg, top_bg = s ? s[1] : ATTR_DEFAULT; - uint32_t right_fg = s ? s[2] : deffg, right_bg = s ? s[3] : ATTR_DEFAULT; - uint32_t bot_fg = s ? s[4] : deffg, bot_bg = s ? s[5] : ATTR_DEFAULT; - uint32_t left_fg = s ? s[6] : deffg, left_bg = s ? s[7] : ATTR_DEFAULT; + if (s == NULL) { + __builtin_trap(); + } + + uint32_t top_fg = s[0]; + uint32_t top_bg = s[1]; + uint32_t right_fg = s[2]; + uint32_t right_bg = s[3]; + uint32_t bot_fg = s[4]; + uint32_t bot_bg = s[5]; + uint32_t left_fg = s[6]; + uint32_t left_bg = s[7]; int top = b->width.top > 0; int bot = b->width.bottom > 0; int left = b->width.left > 0; -- 2.51.2