diff options
Diffstat (limited to 'src/web/app.mjs')
| -rw-r--r-- | src/web/app.mjs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/web/app.mjs b/src/web/app.mjs index 312627df..2a4f8a65 100644 --- a/src/web/app.mjs +++ b/src/web/app.mjs @@ -54,6 +54,16 @@ export class DomRenderer { const cursorY = this.wasm.pardes_cursor_y(); const cursorBar = this.wasm.pardes_cursor_bar() !== 0; const raw = new Array(count); + const tagCovered = new Uint8Array(count); + if (this.wasm.pardes_tag_layer_limit) { + for (let i = 0; i < this.wasm.pardes_tag_layer_limit(); i++) { + const val = field => this.wasm.pardes_tag_layer_value(i, field); + if (!val(0)) continue; + for (let x = val(4); x < Math.min(cols, val(4) + val(6)); x++) { + if (val(5) < rows) tagCovered[val(5) * cols + x] = 1; + } + } + } for (let index = 0; index < count; index += 1) { const off = index * CELL_SIZE; @@ -66,6 +76,7 @@ export class DomRenderer { const y = Math.floor(index / cols); const cursor = x === cursorX && y === cursorY; const cell = this.cells[index]; + cell.style.visibility = tagCovered[index] ? "hidden" : ""; if (cell.textContent !== text) cell.textContent = text; const styleKey = `${fg}:${bg}:${attrs}:${cursor ? 1 : 0}:${cursorBar ? 1 : 0}`; if (cell.pardesStyle !== styleKey) { @@ -75,10 +86,58 @@ export class DomRenderer { raw[index] = { text, fg, bg, attrs }; } this.renderBodyLayers(); + this.renderTagLayers(); this.snapshot = { cols, rows, cells: raw, cursorX, cursorY, cursorBar }; return this.snapshot; } + renderTagLayers() { + if (!this.wasm.pardes_tag_layer_limit || !this.cellWidth) return; + if (!this.tagRoot?.isConnected) { + this.tagRoot = this.root.ownerDocument.createElement("div"); + this.tagRoot.style.cssText = "position:absolute;inset:0;pointer-events:none;overflow:hidden"; + this.root.style.position = "relative"; + this.root.append(this.tagRoot); + } + this.tagNodes ??= new Map(); + const nodes = []; + const bw = this.cellWidth, bh = this.cellHeight, tw = this.taglineWidth, th = this.taglineHeight; + for (let i = 0; i < this.wasm.pardes_tag_layer_limit(); i++) { + const values = Array.from({length:11}, (_,field) => this.wasm.pardes_tag_layer_value(i,field)); + const cols = values[0]; + if (!cols) continue; + const ptr = this.wasm.pardes_tag_layer_cells(i); + if (!ptr) continue; + const bytes = new Uint8Array(this.wasm.memory.buffer,ptr,cols*CELL_SIZE); + const offset = this.wasm.pardes_tagline_band_offset(values[5],this.rowCount*bh*256,Math.round(bh*256),Math.round(th*256))/256; + const geometry = [bw,bh,tw,th,offset,...values].join(":"); + const cached = this.tagNodes.get(i); + if (cached && cached.geometry === geometry && cached.bytes.length === bytes.length && cached.bytes.every((byte,index)=>byte===bytes[index])) { + nodes.push(cached.node); + continue; + } + const view = new DataView(this.wasm.memory.buffer,ptr,cols*CELL_SIZE); + const layer = this.root.ownerDocument.createElement("div"); + layer.dataset.tagLayer = String(i); + layer.style.cssText = `position:absolute;overflow:hidden;white-space:pre;left:${values[4]*bw}px;top:${values[5]*bh+offset}px;width:${values[6]*bw}px;height:${th}px;background:${color(values[10],DEFAULT_BG)}`; + for (let col = 0; col < cols; col++) { + const off = col*CELL_SIZE; + const cell = this.root.ownerDocument.createElement("span"); + cell.className = "pardes-cell"; + cell.textContent = decoder.decode(bytes.subarray(off,off+view.getUint8(off+18))) || " "; + applyStyle(cell,view.getUint32(off+8,true),view.getUint32(off+12,true),view.getUint16(off+16,true),col===values[8],values[9]!==0); + cell.style.textAlign = "left"; + cell.style.width = `${tw}px`; + cell.style.height = `${th}px`; + cell.style.lineHeight = `${th}px`; + layer.append(cell); + } + this.tagNodes.set(i,{geometry,bytes:bytes.slice(),node:layer}); + nodes.push(layer); + } + if (nodes.length !== this.tagRoot.childNodes.length || nodes.some((node,index)=>node!==this.tagRoot.childNodes[index])) this.tagRoot.replaceChildren(...nodes); + } + renderBodyLayers() { if (!this.wasm.pardes_body_layer_limit || !this.cellWidth) return; if (!this.layerRoot?.isConnected) { |
