Skip to content

Commit 8813820

Browse files
committed
chore: format graphics sources
1 parent 7756043 commit 8813820

3 files changed

Lines changed: 54 additions & 35 deletions

File tree

‎src/graphics.c‎

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,25 @@ static void dirty_mark(struct Clayterm *ct, int x, int y, int w, int h) {
403403

404404
/* ── Removal, denial, resize (§7.2/§11.2/§10.5) ───────────────────── */
405405

406+
/* Reconcile (and clear) the front-table records of one id — or every id
407+
* when only_id is 0 — without emitting bytes. The terminal's cells revert
408+
* to the blank state the moment the pixels are gone. */
409+
static void reconcile_and_clear(struct Clayterm *ct, uint32_t only_id) {
410+
struct Graphics *g = ct->gfx;
411+
for (int i = 0; i < PLACEMENT_CAP; i++) {
412+
struct ImagePlacement *p = &g->placements_front[i];
413+
if (p->used && (only_id == 0 || p->registry_id == only_id)) {
414+
reconcile_blank(ct, p);
415+
p->used = 0;
416+
}
417+
g->placements_back[i].used = 0;
418+
}
419+
g->placement_count = 0;
420+
}
421+
406422
/* Deletion bytes for every image with live front placements (one d=I per
407-
* registry id, deduplicated), transmission-state reset, table clear, and
408-
* cell reconciliation. Shared by removeImage (scoped to one id), denial,
409-
* and resize (all images). Returns bytes written. */
423+
* registry id, deduplicated) plus the reconcile/clear above. The denial
424+
* (§11.2) and resize (§10.5) paths. Returns bytes written. */
410425
static int emit_deletions_and_clear(struct Clayterm *ct, uint32_t only_id) {
411426
struct Graphics *g = ct->gfx;
412427
int wrote = 0;
@@ -440,16 +455,7 @@ static int emit_deletions_and_clear(struct Clayterm *ct, uint32_t only_id) {
440455
}
441456
wrote = 1;
442457
}
443-
/* reconcile + clear: both tables die with their placements */
444-
for (int i = 0; i < PLACEMENT_CAP; i++) {
445-
struct ImagePlacement *p = &g->placements_front[i];
446-
if (p->used && (only_id == 0 || p->registry_id == only_id)) {
447-
reconcile_blank(ct, p);
448-
p->used = 0;
449-
}
450-
g->placements_back[i].used = 0;
451-
}
452-
g->placement_count = 0;
458+
reconcile_and_clear(ct, only_id);
453459
return wrote;
454460
}
455461

@@ -459,15 +465,18 @@ int image_remove(struct Clayterm *ct, uint32_t id) {
459465
if (e == NULL || !e->live) {
460466
return -IMG_ERR_UNKNOWN;
461467
}
462-
/* bytes whenever the id was live (§7.2), regardless of evidence */
468+
/* bytes whenever the id was live (§7.2) — a never-placed image's d=I is
469+
* a harmless no-op; a placed image's must flow even when the evidence
470+
* has since been denied (the terminal may still hold the pixels) */
463471
ct->out.length = 0;
464-
emit_deletions_and_clear(ct, id);
472+
kitty_delete_image(ct, id);
473+
reconcile_and_clear(ct, id);
465474
e->live = 0;
466475
e->id = 0; /* frees the slot for entry_free_slot */
467476
return ct->out.length;
468477
}
469478

470-
void graphics_capability(struct Clayterm *ct, int kitty_graphics) {
479+
int graphics_capability(struct Clayterm *ct, int kitty_graphics) {
471480
struct Graphics *g = ct->gfx;
472481
int was = g->kitty_graphics;
473482
g->kitty_graphics = (uint8_t)(kitty_graphics != 0);
@@ -476,6 +485,7 @@ void graphics_capability(struct Clayterm *ct, int kitty_graphics) {
476485
ct->out.length = 0;
477486
emit_deletions_and_clear(ct, 0);
478487
}
488+
return ct->out.length;
479489
}
480490

481491
int graphics_resize_prepare(struct Clayterm *ct) {
@@ -733,6 +743,21 @@ void graphics_paint_ascii(struct Clayterm *ct, const struct ImageEntry *e,
733743

734744
/* ── Frame phases (§9.2.6 ordering) ───────────────────────────────── */
735745

746+
/* Any covered cell differing front-vs-back? (§10.2's repair trigger.) */
747+
static int box_differs(struct Clayterm *ct, const struct ImagePlacement *bp) {
748+
for (int y = bp->y; y < bp->y + bp->h; y++) {
749+
for (int x = bp->x; x < bp->x + bp->w; x++) {
750+
if (x < 0 || x >= ct->w || y < 0 || y >= ct->h) {
751+
continue;
752+
}
753+
if (cell_cmp(cell_at(ct, ct->front, x, y), cell_at(ct, ct->back, x, y))) {
754+
return 1; /* one write is enough to heal the whole box */
755+
}
756+
}
757+
}
758+
return 0;
759+
}
760+
736761
/* Phase 0, before any emission: the repair precheck (§10.2) — a placement
737762
* whose covered cells will receive writes (front ≠ back anywhere in its
738763
* box) must be re-placed this frame; run before any dirty-marking mutates
@@ -744,18 +769,7 @@ static void graphics_precheck_repairs(struct Clayterm *ct) {
744769
if (!bp->used || bp->tier != IMG_TIER_KITTY) {
745770
continue;
746771
}
747-
for (int y = bp->y; y < bp->y + bp->h; y++) {
748-
for (int x = bp->x; x < bp->x + bp->w; x++) {
749-
if (x < 0 || x >= ct->w || y < 0 || y >= ct->h) {
750-
continue;
751-
}
752-
if (cell_cmp(cell_at(ct, ct->front, x, y),
753-
cell_at(ct, ct->back, x, y))) {
754-
bp->repair = 1;
755-
return; /* one write is enough to heal the whole box */
756-
}
757-
}
758-
}
772+
bp->repair = (uint8_t)box_differs(ct, bp);
759773
}
760774
}
761775

@@ -871,7 +885,10 @@ void graphics_emit_placements(struct Clayterm *ct, int row) {
871885
struct ImagePlacement *fp = front_match(g, p->registry_id, p->placement_id);
872886
int moved = fp == NULL || fp->x != p->x || fp->y != p->y || fp->w != p->w ||
873887
fp->h != p->h;
874-
if (!moved && !p->repair) {
888+
/* a re-transmitted image lost its terminal placements (the protocol's
889+
* delete-before-re-transmit) — the same frame must re-place it */
890+
int retransmitted = fp != NULL && fp->data_version != p->data_version;
891+
if ((!moved && !retransmitted) && !p->repair) {
875892
continue;
876893
}
877894
emit_cursor(ct, p->x, p->y, row);

‎src/graphics.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,9 @@ int image_remove(struct Clayterm *ct, uint32_t id);
122122
/* Capability mirror (terminfo-spec §4.2). A true→false transition is a
123123
* capability denial (§11.2): emits deletion bytes for every image with live
124124
* placements into the output buffer (reset first), resets transmission
125-
* state, clears the placements tables, and reconciles covered cells. */
126-
void graphics_capability(struct Clayterm *ct, int kitty_graphics);
125+
* state, clears the placements tables, and reconciles covered cells.
126+
* Returns the byte length written (0 = nothing emitted). */
127+
int graphics_capability(struct Clayterm *ct, int kitty_graphics);
127128

128129
/* Resize (§10.5): before the dimension-dependent state is discarded, emit
129130
* one data-freeing deletion per image with live placements into the output

‎term-native.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export interface Native {
5757
imageBegin(ct: number, id: number, w: number, h: number): number;
5858
imageCommit(ct: number, id: number): number;
5959
imageRemove(ct: number, id: number): number;
60-
graphicsCapability(ct: number, kitty: number): void;
60+
graphicsCapability(ct: number, kitty: number): number;
6161
graphicsResizePrepare(ct: number): number;
6262
setPointer(x: number, y: number, down: boolean): void;
6363
getPointerOverIds(): string[];
@@ -73,6 +73,7 @@ import { compiled } from "./wasm.ts";
7373
export async function createTermNative(
7474
w: number,
7575
h: number,
76+
imagePoolBytes?: number,
7677
): Promise<Native> {
7778
let memory = new WebAssembly.Memory({ initial: 2 });
7879
let exports: Record<string, CallableFunction> = {};
@@ -121,7 +122,7 @@ export async function createTermNative(
121122
image_begin(ct: number, id: number, w: number, h: number): number;
122123
image_commit(ct: number, id: number): number;
123124
image_remove(ct: number, id: number): number;
124-
graphics_capability(ct: number, kitty: number): void;
125+
graphics_capability(ct: number, kitty: number): number;
125126
graphics_resize_prepare(ct: number): number;
126127
Clay_SetPointerState(vec: number, down: number): void;
127128
pointer_over_count(): number;
@@ -155,9 +156,9 @@ export async function createTermNative(
155156
function layout(lw: number, lh: number): void {
156157
let heap = ct.__heap_base.value as number;
157158
if (gfxPtr === 0) {
158-
gfxBytes = ct.graphics_size(DEFAULT_IMAGE_POOL_BYTES);
159+
gfxBytes = ct.graphics_size(imagePoolBytes ?? DEFAULT_IMAGE_POOL_BYTES);
159160
gfxPtr = heap;
160-
ct.graphics_init(gfxPtr, DEFAULT_IMAGE_POOL_BYTES);
161+
ct.graphics_init(gfxPtr, imagePoolBytes ?? DEFAULT_IMAGE_POOL_BYTES);
161162
}
162163
let size = ct.clayterm_size(lw, lh);
163164
let clayBase = gfxPtr + gfxBytes;

0 commit comments

Comments
 (0)