dynamic text update 비용과 bitmap/glyph 전략
텍스트가 바뀌면 단순히 문자열만 바뀌는 것이 아닙니다. layout, rasterize, GPU upload가 이어질 수 있습니다.
dynamic text invalidation 코드
텍스트가 바뀌면 layout, raster texture, GPU upload를 순서대로 dirty 처리합니다.
function updateTextNode(editor, nodeId, text) {
editor.dispatch({
type: "updateNode",
id: nodeId,
patch: { text },
meta: {
dirtyLayout: true,
dirtyTextTexture: true
}
});
}
function rebuildDirtyText(renderer, scene) {
for (const node of scene.nodes) {
if (node.type !== "text" || !node.dirtyTextTexture) continue;
const layout = layoutText(node);
const bitmap = rasterizeTextLayout(layout);
renderer.textureCache.update(node.id, bitmap);
node.dirtyTextTexture = false;
}
}
비용 흐름
text changed
measure/layout
rasterize to canvas
upload texture
render preview
자주 바뀌는 숫자, 라벨, debug text는 glyph atlas나 bitmap text 전략이 더 안정적일 수 있습니다.
glyph atlas 후보를 분리한다
function chooseTextRenderMode(node) {
if (node.editing) return "dom-overlay";
if (node.dynamic && node.maxLength < 32) return "glyph-atlas";
if (node.hasRichStyle || node.multiline) return "canvas-texture";
return "glyph-atlas";
}
function renderTextNode(renderer, node) {
const mode = chooseTextRenderMode(node);
if (mode === "glyph-atlas") renderer.drawGlyphRuns(node);
if (mode === "canvas-texture") renderer.drawTextTexture(node);
if (mode === "dom-overlay") renderer.drawTextEditingBounds(node);
}
모든 text를 하나의 방식으로 처리하면 어느 순간 비용이나 편집성이 깨집니다. 편집 중, 짧은 동적 라벨, 복잡한 multiline text는 서로 다른 렌더링 전략을 가져야 합니다.
오늘의 핵심
텍스트는 편집 UX와 렌더링 비용이 만나는 지점입니다. 편집 중 DOM overlay와 표시용 GPU preview를 분리하는 판단이 중요합니다.