Paint an EXISTING DOM subtree to a fresh Screen at its natural * height, scan for query. Returns positions relative to the element's * bounding box (row 0 = element top). * * The element comes from the MAIN tree — built with all real * providers, yoga already computed. We paint it
(el: dom.DOMElement)
| 1173 | * |
| 1174 | * ~1-2ms (paint only, no reconcile — the DOM is already built). */ |
| 1175 | scanElementSubtree(el: dom.DOMElement): MatchPosition[] { |
| 1176 | if (!this.searchHighlightQuery || !el.yogaNode) return []; |
| 1177 | const width = Math.ceil(el.yogaNode.getComputedWidth()); |
| 1178 | const height = Math.ceil(el.yogaNode.getComputedHeight()); |
| 1179 | if (width <= 0 || height <= 0) return []; |
| 1180 | // renderNodeToOutput adds el's OWN computedLeft/Top to offsetX/Y. |
| 1181 | // Passing -elLeft/-elTop nets to 0 → paints at (0,0) in our buffer. |
| 1182 | const elLeft = el.yogaNode.getComputedLeft(); |
| 1183 | const elTop = el.yogaNode.getComputedTop(); |
| 1184 | const screen = createScreen(width, height, this.stylePool, this.charPool, this.hyperlinkPool); |
| 1185 | const output = new Output({ |
| 1186 | width, |
| 1187 | height, |
| 1188 | stylePool: this.stylePool, |
| 1189 | screen, |
| 1190 | }); |
| 1191 | renderNodeToOutput(el, output, { |
| 1192 | offsetX: -elLeft, |
| 1193 | offsetY: -elTop, |
| 1194 | prevScreen: undefined, |
| 1195 | }); |
| 1196 | const rendered = output.get(); |
| 1197 | // renderNodeToOutput wrote our offset positions to nodeCache — |
| 1198 | // corrupts the main render (it'd blit from wrong coords). Mark the |
| 1199 | // subtree dirty so the next main render repaints + re-caches |
| 1200 | // correctly. One extra paint of this message, but correct > fast. |
| 1201 | dom.markDirty(el); |
| 1202 | const positions = scanPositions(rendered, this.searchHighlightQuery); |
| 1203 | this.logger.debug( |
| 1204 | `scanElementSubtree: q='${this.searchHighlightQuery}' ` + |
| 1205 | `el=${width}x${height}@(${elLeft},${elTop}) n=${positions.length} ` + |
| 1206 | `[${positions |
| 1207 | .slice(0, 10) |
| 1208 | .map(p => `${p.row}:${p.col}`) |
| 1209 | .join(',')}` + |
| 1210 | `${positions.length > 10 ? ',…' : ''}]`, |
| 1211 | ); |
| 1212 | return positions; |
| 1213 | } |
| 1214 | |
| 1215 | /** Set the position-based highlight state. Every frame, writes CURRENT |
| 1216 | * style at positions[currentIdx] + rowOffset. null clears. The scan- |
no test coverage detected