@lightningjs/renderer 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -196
- package/dist/src/core/CoreNode.js +25 -4
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.d.ts +9 -2
- package/dist/src/core/CoreTextNode.js +32 -11
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +8 -0
- package/dist/src/core/CoreTextureManager.js +13 -1
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.d.ts +8 -0
- package/dist/src/core/Stage.js +23 -0
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/TextureMemoryManager.d.ts +8 -13
- package/dist/src/core/TextureMemoryManager.js +22 -27
- package/dist/src/core/TextureMemoryManager.js.map +1 -1
- package/dist/src/core/lib/ImageWorker.d.ts +2 -2
- package/dist/src/core/lib/ImageWorker.js +31 -12
- package/dist/src/core/lib/ImageWorker.js.map +1 -1
- package/dist/src/core/lib/WebGlContextWrapper.d.ts +105 -56
- package/dist/src/core/lib/WebGlContextWrapper.js +164 -158
- package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
- package/dist/src/core/lib/textureCompression.js +19 -10
- package/dist/src/core/lib/textureCompression.js.map +1 -1
- package/dist/src/core/lib/validateImageBitmap.d.ts +2 -1
- package/dist/src/core/lib/validateImageBitmap.js +4 -4
- package/dist/src/core/lib/validateImageBitmap.js.map +1 -1
- package/dist/src/core/platform.js +2 -2
- package/dist/src/core/platform.js.map +1 -1
- package/dist/src/core/platforms/Platform.d.ts +4 -0
- package/dist/src/core/platforms/Platform.js.map +1 -1
- package/dist/src/core/platforms/web/WebPlatform.d.ts +2 -0
- package/dist/src/core/platforms/web/WebPlatform.js +13 -0
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
- package/dist/src/core/renderers/CoreRenderer.d.ts +6 -0
- package/dist/src/core/renderers/CoreRenderer.js +8 -0
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +1 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +5 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +45 -0
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js +127 -0
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +2 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +30 -22
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/CanvasFont.d.ts +14 -0
- package/dist/src/core/text-rendering/CanvasFont.js +120 -0
- package/dist/src/core/text-rendering/CanvasFont.js.map +1 -0
- package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +1 -2
- package/dist/src/core/text-rendering/CanvasTextRenderer.js +11 -19
- package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/CoreFont.d.ts +33 -0
- package/dist/src/core/text-rendering/CoreFont.js +48 -0
- package/dist/src/core/text-rendering/CoreFont.js.map +1 -0
- package/dist/src/core/text-rendering/FontManager.d.ts +11 -0
- package/dist/src/core/text-rendering/FontManager.js +41 -0
- package/dist/src/core/text-rendering/FontManager.js.map +1 -0
- package/dist/src/core/text-rendering/SdfFont.d.ts +29 -0
- package/dist/src/core/text-rendering/SdfFont.js +142 -0
- package/dist/src/core/text-rendering/SdfFont.js.map +1 -0
- package/dist/src/core/text-rendering/SdfFontHandler.js +7 -5
- package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -1
- package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +2 -2
- package/dist/src/core/text-rendering/SdfTextRenderer.js +141 -132
- package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/TextGenerator.d.ts +10 -0
- package/dist/src/core/text-rendering/TextGenerator.js +36 -0
- package/dist/src/core/text-rendering/TextGenerator.js.map +1 -0
- package/dist/src/core/text-rendering/TextRenderer.d.ts +26 -20
- package/dist/src/core/text-rendering/Utils.d.ts +2 -0
- package/dist/src/core/text-rendering/Utils.js +3 -0
- package/dist/src/core/text-rendering/Utils.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +14 -0
- package/dist/src/main-api/Renderer.js +29 -3
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/core/CoreNode.ts +29 -4
- package/src/core/CoreTextNode.test.ts +237 -0
- package/src/core/CoreTextNode.ts +53 -33
- package/src/core/CoreTextureManager.ts +14 -2
- package/src/core/Stage.ts +29 -0
- package/src/core/TextureMemoryManager.test.ts +134 -0
- package/src/core/TextureMemoryManager.ts +23 -30
- package/src/core/platforms/Platform.ts +5 -0
- package/src/core/platforms/web/WebPlatform.ts +13 -0
- package/src/core/renderers/CoreRenderer.ts +10 -0
- package/src/core/renderers/canvas/CanvasRenderer.ts +6 -0
- package/src/core/renderers/webgl/WebGlRenderer.rtt.test.ts +551 -0
- package/src/core/renderers/webgl/WebGlRenderer.ts +38 -28
- package/src/core/text-rendering/CanvasTextRenderer.ts +13 -41
- package/src/core/text-rendering/SdfFontHandler.ts +8 -5
- package/src/core/text-rendering/SdfTextRenderer.ts +166 -163
- package/src/core/text-rendering/TextRenderer.ts +23 -21
- package/src/core/text-rendering/Utils.ts +5 -1
- package/src/main-api/Renderer.test.ts +153 -0
- package/src/main-api/Renderer.ts +33 -3
- package/dist/src/core/renderers/webgl/WebGlCoreShader.destroy.d.ts +0 -1
- package/dist/src/core/renderers/webgl/WebGlCoreShader.destroy.js +0 -2
- package/dist/src/core/renderers/webgl/WebGlCoreShader.destroy.js.map +0 -1
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* See the License for the specific language governing permissions and
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { hasZeroWidthSpace } from './Utils.js';
|
|
19
|
+
import { getLayoutCacheKey, hasZeroWidthSpace } from './Utils.js';
|
|
20
20
|
import * as SdfFontHandler from './SdfFontHandler.js';
|
|
21
21
|
import { WebGlRenderer } from '../renderers/webgl/WebGlRenderer.js';
|
|
22
22
|
import { SdfRenderOp } from '../renderers/webgl/SdfRenderOp.js';
|
|
@@ -38,6 +38,7 @@ const init = (stage) => {
|
|
|
38
38
|
sdfShader = stage.shManager.createShader('Sdf');
|
|
39
39
|
};
|
|
40
40
|
const font = SdfFontHandler;
|
|
41
|
+
const layoutCache = new Map();
|
|
41
42
|
/**
|
|
42
43
|
* SDF text renderer using MSDF/SDF fonts with WebGL
|
|
43
44
|
*
|
|
@@ -53,6 +54,17 @@ const renderText = (props) => {
|
|
|
53
54
|
height: 0,
|
|
54
55
|
};
|
|
55
56
|
}
|
|
57
|
+
const cacheKey = getLayoutCacheKey(props);
|
|
58
|
+
let layout = layoutCache.get(cacheKey);
|
|
59
|
+
if (layout !== undefined) {
|
|
60
|
+
return {
|
|
61
|
+
width: layout.width,
|
|
62
|
+
height: layout.height,
|
|
63
|
+
remainingLines: layout.remainingLines,
|
|
64
|
+
hasRemainingText: layout.hasRemainingText,
|
|
65
|
+
layout, // Cache layout for addQuads
|
|
66
|
+
};
|
|
67
|
+
}
|
|
56
68
|
// Get font cache for this font family
|
|
57
69
|
const fontData = SdfFontHandler.getFontData(props.fontFamily);
|
|
58
70
|
if (fontData === undefined) {
|
|
@@ -63,89 +75,27 @@ const renderText = (props) => {
|
|
|
63
75
|
};
|
|
64
76
|
}
|
|
65
77
|
// Calculate text layout and generate glyph data for caching
|
|
66
|
-
|
|
78
|
+
layout = generateTextLayout(props, fontData);
|
|
79
|
+
layoutCache.set(cacheKey, layout);
|
|
67
80
|
// For SDF renderer, ImageData is null since we render via WebGL
|
|
68
81
|
return {
|
|
69
|
-
remainingLines: 0,
|
|
70
|
-
hasRemainingText: false,
|
|
71
82
|
width: layout.width,
|
|
72
83
|
height: layout.height,
|
|
84
|
+
remainingLines: layout.remainingLines,
|
|
85
|
+
hasRemainingText: layout.hasRemainingText,
|
|
73
86
|
layout, // Cache layout for addQuads
|
|
74
87
|
};
|
|
75
88
|
};
|
|
76
|
-
/**
|
|
77
|
-
* Add quads for rendering using cached layout data
|
|
78
|
-
*/
|
|
79
|
-
const addQuads = (layout) => {
|
|
80
|
-
if (layout === undefined) {
|
|
81
|
-
return null; // No layout data available
|
|
82
|
-
}
|
|
83
|
-
const glyphs = layout.glyphs;
|
|
84
|
-
const glyphsLength = glyphs.length;
|
|
85
|
-
if (glyphsLength === 0) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
const vertexBuffer = new Float32Array(glyphsLength * VERTICES_PER_GLYPH * FLOATS_PER_VERTEX);
|
|
89
|
-
let bufferIndex = 0;
|
|
90
|
-
let glyphIndex = 0;
|
|
91
|
-
while (glyphIndex < glyphsLength) {
|
|
92
|
-
const glyph = glyphs[glyphIndex];
|
|
93
|
-
glyphIndex++;
|
|
94
|
-
if (glyph === undefined) {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
const x1 = glyph.x;
|
|
98
|
-
const y1 = glyph.y;
|
|
99
|
-
const x2 = x1 + glyph.width;
|
|
100
|
-
const y2 = y1 + glyph.height;
|
|
101
|
-
const u1 = glyph.atlasX;
|
|
102
|
-
const v1 = glyph.atlasY;
|
|
103
|
-
const u2 = u1 + glyph.atlasWidth;
|
|
104
|
-
const v2 = v1 + glyph.atlasHeight;
|
|
105
|
-
// Triangle 1: Top-left, top-right, bottom-left
|
|
106
|
-
// Vertex 1: Top-left
|
|
107
|
-
vertexBuffer[bufferIndex++] = x1;
|
|
108
|
-
vertexBuffer[bufferIndex++] = y1;
|
|
109
|
-
vertexBuffer[bufferIndex++] = u1;
|
|
110
|
-
vertexBuffer[bufferIndex++] = v1;
|
|
111
|
-
// Vertex 2: Top-right
|
|
112
|
-
vertexBuffer[bufferIndex++] = x2;
|
|
113
|
-
vertexBuffer[bufferIndex++] = y1;
|
|
114
|
-
vertexBuffer[bufferIndex++] = u2;
|
|
115
|
-
vertexBuffer[bufferIndex++] = v1;
|
|
116
|
-
// Vertex 3: Bottom-left
|
|
117
|
-
vertexBuffer[bufferIndex++] = x1;
|
|
118
|
-
vertexBuffer[bufferIndex++] = y2;
|
|
119
|
-
vertexBuffer[bufferIndex++] = u1;
|
|
120
|
-
vertexBuffer[bufferIndex++] = v2;
|
|
121
|
-
// Triangle 2: Top-right, bottom-right, bottom-left
|
|
122
|
-
// Vertex 4: Top-right (duplicate)
|
|
123
|
-
vertexBuffer[bufferIndex++] = x2;
|
|
124
|
-
vertexBuffer[bufferIndex++] = y1;
|
|
125
|
-
vertexBuffer[bufferIndex++] = u2;
|
|
126
|
-
vertexBuffer[bufferIndex++] = v1;
|
|
127
|
-
// Vertex 5: Bottom-right
|
|
128
|
-
vertexBuffer[bufferIndex++] = x2;
|
|
129
|
-
vertexBuffer[bufferIndex++] = y2;
|
|
130
|
-
vertexBuffer[bufferIndex++] = u2;
|
|
131
|
-
vertexBuffer[bufferIndex++] = v2;
|
|
132
|
-
// Vertex 6: Bottom-left (duplicate)
|
|
133
|
-
vertexBuffer[bufferIndex++] = x1;
|
|
134
|
-
vertexBuffer[bufferIndex++] = y2;
|
|
135
|
-
vertexBuffer[bufferIndex++] = u1;
|
|
136
|
-
vertexBuffer[bufferIndex++] = v2;
|
|
137
|
-
}
|
|
138
|
-
return vertexBuffer;
|
|
139
|
-
};
|
|
140
89
|
/**
|
|
141
90
|
* Create and submit WebGL render operations for SDF text
|
|
142
91
|
* This is called from CoreTextNode during rendering to add SDF text to the render pipeline
|
|
143
92
|
*/
|
|
144
|
-
const renderQuads = (renderer, layout,
|
|
93
|
+
const renderQuads = (renderer, layout, renderProps) => {
|
|
145
94
|
const fontFamily = renderProps.fontFamily;
|
|
146
95
|
const color = renderProps.color;
|
|
147
96
|
const worldAlpha = renderProps.worldAlpha;
|
|
148
97
|
const globalTransform = renderProps.globalTransform;
|
|
98
|
+
const vertexBuffer = layout.vertexBuffer;
|
|
149
99
|
const atlasTexture = SdfFontHandler.getAtlas(fontFamily);
|
|
150
100
|
if (atlasTexture === null) {
|
|
151
101
|
console.warn(`SDF atlas texture not found for font: ${fontFamily}`);
|
|
@@ -154,53 +104,66 @@ const renderQuads = (renderer, layout, vertexBuffer, renderProps) => {
|
|
|
154
104
|
// We can safely assume this is a WebGL renderer else this wouldn't be called
|
|
155
105
|
const glw = renderer.glw;
|
|
156
106
|
const stride = 4 * Float32Array.BYTES_PER_ELEMENT;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Wraps a WebGLBuffer in a BufferCollection with the standard SDF vertex
|
|
109
|
+
* layout, creates and submits an SdfRenderOp. Called by both the cache-miss
|
|
110
|
+
* and cache-hit paths so attribute/op setup only exists in one place.
|
|
111
|
+
*/
|
|
112
|
+
const buildAndSubmitRenderOp = (gpuBuffer) => {
|
|
113
|
+
const webGlBuffers = new BufferCollection([
|
|
114
|
+
{
|
|
115
|
+
buffer: gpuBuffer,
|
|
116
|
+
attributes: {
|
|
117
|
+
a_position: {
|
|
118
|
+
name: 'a_position',
|
|
119
|
+
size: 2,
|
|
120
|
+
type: glw.FLOAT,
|
|
121
|
+
normalized: false,
|
|
122
|
+
stride,
|
|
123
|
+
offset: 0,
|
|
124
|
+
},
|
|
125
|
+
a_textureCoords: {
|
|
126
|
+
name: 'a_textureCoords',
|
|
127
|
+
size: 2,
|
|
128
|
+
type: glw.FLOAT,
|
|
129
|
+
normalized: false,
|
|
130
|
+
stride,
|
|
131
|
+
offset: 2 * Float32Array.BYTES_PER_ELEMENT,
|
|
132
|
+
},
|
|
181
133
|
},
|
|
182
134
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
135
|
+
]);
|
|
136
|
+
const renderOp = new SdfRenderOp(renderer, sdfShader, {
|
|
137
|
+
transform: globalTransform,
|
|
138
|
+
color: mergeColorAlpha(color, worldAlpha),
|
|
139
|
+
size: layout.fontScale,
|
|
140
|
+
distanceRange: layout.distanceRange,
|
|
141
|
+
}, webGlBuffers, worldAlpha,
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
143
|
+
renderProps.clippingRect, layout.width, layout.height, false, renderProps.parentHasRenderTexture,
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
145
|
+
renderProps.framebufferDimensions);
|
|
146
|
+
renderOp.addTexture(atlasTexture.ctxTexture);
|
|
147
|
+
renderOp.numQuads = layout.glyphCount;
|
|
148
|
+
renderer.addRenderOp(renderOp);
|
|
149
|
+
};
|
|
150
|
+
// Reuse the cached WebGLBuffer if one was provided — avoids a createBuffer
|
|
151
|
+
// call every frame on nodes whose text has not changed.
|
|
152
|
+
const glBufferRefBox = renderProps.glBufferRef;
|
|
153
|
+
if (glBufferRefBox.current === null) {
|
|
154
|
+
// Cache miss: allocate a new buffer, upload vertex data, then cache it.
|
|
155
|
+
const newBuffer = glw.createBuffer();
|
|
156
|
+
if (newBuffer === null) {
|
|
157
|
+
console.warn('Failed to create WebGL buffer for SDF text');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Upload vertex data directly into the new buffer.
|
|
161
|
+
glw.arrayBufferData(newBuffer, vertexBuffer, glw.STATIC_DRAW);
|
|
162
|
+
// Write back into the ref box so the owning node can reuse it next frame.
|
|
163
|
+
glBufferRefBox.current = newBuffer;
|
|
188
164
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
transform: globalTransform,
|
|
192
|
-
color: mergeColorAlpha(color, worldAlpha),
|
|
193
|
-
size: layout.fontScale, // Use proper font scaling in shader
|
|
194
|
-
distanceRange: layout.distanceRange,
|
|
195
|
-
}, webGlBuffers, worldAlpha,
|
|
196
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
197
|
-
renderProps.clippingRect, layout.width, layout.height, false, renderProps.parentHasRenderTexture,
|
|
198
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
199
|
-
renderProps.framebufferDimensions);
|
|
200
|
-
// Add atlas texture and set quad count
|
|
201
|
-
renderOp.addTexture(atlasTexture.ctxTexture);
|
|
202
|
-
renderOp.numQuads = layout.glyphs.length;
|
|
203
|
-
renderer.addRenderOp(renderOp);
|
|
165
|
+
// Cache hit (or freshly allocated): build the render op and submit.
|
|
166
|
+
buildAndSubmitRenderOp(glBufferRefBox.current);
|
|
204
167
|
};
|
|
205
168
|
/**
|
|
206
169
|
* Generate complete text layout with glyph positioning for caching
|
|
@@ -222,7 +185,23 @@ const generateTextLayout = (props, fontCache) => {
|
|
|
222
185
|
const maxHeight = props.maxHeight;
|
|
223
186
|
const [lines, remainingLines, hasRemainingText, bareLineHeight, lineHeightPx, effectiveWidth, effectiveHeight,] = mapTextLayout(SdfFontHandler.measureText, metrics, props.text, props.textAlign, fontFamily, lineHeight, props.overflowSuffix, props.wordBreak, letterSpacing, props.maxLines, maxWidth, maxHeight);
|
|
224
187
|
const lineAmount = lines.length;
|
|
225
|
-
|
|
188
|
+
let bufferIndex = 0;
|
|
189
|
+
let glyphCount = 0;
|
|
190
|
+
// Count total glyphs (excluding spaces) for buffer allocation
|
|
191
|
+
for (let i = 0; i < lineAmount; i++) {
|
|
192
|
+
const textLine = lines[i][0];
|
|
193
|
+
for (const char of textLine) {
|
|
194
|
+
if (hasZeroWidthSpace(char) === true) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const codepoint = char.codePointAt(0);
|
|
198
|
+
if (codepoint === undefined) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
glyphCount++;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const vertexBuffer = new Float32Array(glyphCount * VERTICES_PER_GLYPH * FLOATS_PER_VERTEX);
|
|
226
205
|
let currentX = 0;
|
|
227
206
|
let currentY = 0;
|
|
228
207
|
for (let i = 0; i < lineAmount; i++) {
|
|
@@ -253,22 +232,46 @@ const generateTextLayout = (props, fontCache) => {
|
|
|
253
232
|
}
|
|
254
233
|
// Apply pair kerning before placing this glyph.
|
|
255
234
|
currentX += kerning;
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
235
|
+
const x1 = currentX + glyph.xoffset;
|
|
236
|
+
const y1 = currentY + glyph.yoffset;
|
|
237
|
+
const x2 = x1 + glyph.width;
|
|
238
|
+
const y2 = y1 + glyph.height;
|
|
239
|
+
const u1 = glyph.x / atlasWidth;
|
|
240
|
+
const v1 = glyph.y / atlasHeight;
|
|
241
|
+
const u2 = u1 + glyph.width / atlasWidth;
|
|
242
|
+
const v2 = v1 + glyph.height / atlasHeight;
|
|
243
|
+
// Triangle 1: Top-left, top-right, bottom-left
|
|
244
|
+
// Vertex 1: Top-left
|
|
245
|
+
vertexBuffer[bufferIndex++] = x1;
|
|
246
|
+
vertexBuffer[bufferIndex++] = y1;
|
|
247
|
+
vertexBuffer[bufferIndex++] = u1;
|
|
248
|
+
vertexBuffer[bufferIndex++] = v1;
|
|
249
|
+
// Vertex 2: Top-right
|
|
250
|
+
vertexBuffer[bufferIndex++] = x2;
|
|
251
|
+
vertexBuffer[bufferIndex++] = y1;
|
|
252
|
+
vertexBuffer[bufferIndex++] = u2;
|
|
253
|
+
vertexBuffer[bufferIndex++] = v1;
|
|
254
|
+
// Vertex 3: Bottom-left
|
|
255
|
+
vertexBuffer[bufferIndex++] = x1;
|
|
256
|
+
vertexBuffer[bufferIndex++] = y2;
|
|
257
|
+
vertexBuffer[bufferIndex++] = u1;
|
|
258
|
+
vertexBuffer[bufferIndex++] = v2;
|
|
259
|
+
// Triangle 2: Top-right, bottom-right, bottom-left
|
|
260
|
+
// Vertex 4: Top-right (duplicate)
|
|
261
|
+
vertexBuffer[bufferIndex++] = x2;
|
|
262
|
+
vertexBuffer[bufferIndex++] = y1;
|
|
263
|
+
vertexBuffer[bufferIndex++] = u2;
|
|
264
|
+
vertexBuffer[bufferIndex++] = v1;
|
|
265
|
+
// Vertex 5: Bottom-right
|
|
266
|
+
vertexBuffer[bufferIndex++] = x2;
|
|
267
|
+
vertexBuffer[bufferIndex++] = y2;
|
|
268
|
+
vertexBuffer[bufferIndex++] = u2;
|
|
269
|
+
vertexBuffer[bufferIndex++] = v2;
|
|
270
|
+
// Vertex 6: Bottom-left (duplicate)
|
|
271
|
+
vertexBuffer[bufferIndex++] = x1;
|
|
272
|
+
vertexBuffer[bufferIndex++] = y2;
|
|
273
|
+
vertexBuffer[bufferIndex++] = u1;
|
|
274
|
+
vertexBuffer[bufferIndex++] = v2;
|
|
272
275
|
// Advance position with letter spacing (in design units)
|
|
273
276
|
currentX += glyph.xadvance + letterSpacing;
|
|
274
277
|
prevGlyphId = glyph.id;
|
|
@@ -277,15 +280,21 @@ const generateTextLayout = (props, fontCache) => {
|
|
|
277
280
|
}
|
|
278
281
|
// Convert final dimensions to pixel space for the layout
|
|
279
282
|
return {
|
|
280
|
-
|
|
283
|
+
vertexBuffer,
|
|
284
|
+
glyphCount,
|
|
281
285
|
distanceRange: fontScale * fontData.distanceField.distanceRange,
|
|
282
286
|
width: effectiveWidth * fontScale,
|
|
283
287
|
height: effectiveHeight,
|
|
284
288
|
fontScale: fontScale,
|
|
285
289
|
lineHeight: lineHeightPx,
|
|
286
290
|
fontFamily,
|
|
291
|
+
remainingLines,
|
|
292
|
+
hasRemainingText,
|
|
287
293
|
};
|
|
288
294
|
};
|
|
295
|
+
const clearCache = () => {
|
|
296
|
+
layoutCache.clear();
|
|
297
|
+
};
|
|
289
298
|
/**
|
|
290
299
|
* SDF Text Renderer - implements TextRenderer interface
|
|
291
300
|
*/
|
|
@@ -293,9 +302,9 @@ const SdfTextRenderer = {
|
|
|
293
302
|
type,
|
|
294
303
|
font,
|
|
295
304
|
renderText,
|
|
296
|
-
addQuads,
|
|
297
305
|
renderQuads,
|
|
298
306
|
init,
|
|
307
|
+
clearCache,
|
|
299
308
|
};
|
|
300
309
|
export default SdfTextRenderer;
|
|
301
310
|
//# sourceMappingURL=SdfTextRenderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SdfTextRenderer.js","sourceRoot":"","sources":["../../../../src/core/text-rendering/SdfTextRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAUH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"SdfTextRenderer.js","sourceRoot":"","sources":["../../../../src/core/text-rendering/SdfTextRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Stage } from "../Stage";
|
|
2
|
+
import type { FontLoadOptions, TextRenderer, TextRenderers } from "./TextRenderer";
|
|
3
|
+
export default class TextGenerator {
|
|
4
|
+
readonly stage: Stage;
|
|
5
|
+
private layoutCache;
|
|
6
|
+
fontEngines: Record<string, TextRenderer>;
|
|
7
|
+
constructor(stage: Stage, fontEngines: TextRenderer[]);
|
|
8
|
+
loadFont(rendererType: TextRenderers, options: FontLoadOptions): any;
|
|
9
|
+
destroy(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export default class TextGenerator {
|
|
2
|
+
stage;
|
|
3
|
+
layoutCache = new Map();
|
|
4
|
+
fontEngines = {};
|
|
5
|
+
constructor(stage, fontEngines) {
|
|
6
|
+
this.stage = stage;
|
|
7
|
+
if (stage.renderer.mode === 'canvas') {
|
|
8
|
+
//filter out SDF renderer if the main renderer is canvas, since SDF rendering is not supported in that case
|
|
9
|
+
fontEngines = fontEngines.filter(engine => {
|
|
10
|
+
if (engine.type === 'canvas') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
console.warn(`SDF text rendering is not supported in canvas mode. The SDF text renderer will be ignored.`);
|
|
14
|
+
return false;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
for (let i = 0; i < fontEngines.length; i++) {
|
|
18
|
+
const engine = fontEngines[i];
|
|
19
|
+
this.fontEngines[engine.type] = engine;
|
|
20
|
+
engine.init(stage);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
loadFont(rendererType, options) {
|
|
24
|
+
const rendererTypeKey = String(rendererType);
|
|
25
|
+
const fontEngine = this.fontEngines[rendererTypeKey];
|
|
26
|
+
if (fontEngine === undefined) {
|
|
27
|
+
throw new Error(`Font handler for renderer type '${rendererTypeKey}' not found. Available types: ${Object.keys(this.fontEngines).join(', ')}`);
|
|
28
|
+
}
|
|
29
|
+
return fontEngine.font.loadFont(this.stage, options);
|
|
30
|
+
}
|
|
31
|
+
destroy() {
|
|
32
|
+
// Clean up resources if necessary
|
|
33
|
+
this.layoutCache.clear();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=TextGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextGenerator.js","sourceRoot":"","sources":["../../../../src/core/text-rendering/TextGenerator.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,OAAO,aAAa;IAKX;IAJb,WAAW,GAA4B,IAAI,GAAG,EAAE,CAAC;IAEzD,WAAW,GAAiC,EAAE,CAAC;IAE/C,YAAqB,KAAY,EAAE,WAA2B;QAAzC,UAAK,GAAL,KAAK,CAAO;QAC/B,IAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,2GAA2G;YAC3G,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;gBACxC,IAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;gBAC3G,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAE,CAAC;YAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAGD,QAAQ,CAAC,YAA2B,EAAE,OAAwB;QAC5D,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QAErD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,mCAAmC,eAAe,iCAAiC,MAAM,CAAC,IAAI,CAC5F,IAAI,CAAC,WAAW,CACjB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACf,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QAEL,kCAAkC;QAClC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -220,14 +220,6 @@ export interface TrProps extends TrFontProps {
|
|
|
220
220
|
* Glyph layout information for WebGL rendering
|
|
221
221
|
*/
|
|
222
222
|
export interface GlyphLayout {
|
|
223
|
-
/**
|
|
224
|
-
* Unicode codepoint
|
|
225
|
-
*/
|
|
226
|
-
codepoint: number;
|
|
227
|
-
/**
|
|
228
|
-
* Glyph ID in the font atlas
|
|
229
|
-
*/
|
|
230
|
-
glyphId: number;
|
|
231
223
|
/**
|
|
232
224
|
* X position relative to text origin
|
|
233
225
|
*/
|
|
@@ -244,14 +236,6 @@ export interface GlyphLayout {
|
|
|
244
236
|
* Height of glyph in font units
|
|
245
237
|
*/
|
|
246
238
|
height: number;
|
|
247
|
-
/**
|
|
248
|
-
* X offset for glyph positioning
|
|
249
|
-
*/
|
|
250
|
-
xOffset: number;
|
|
251
|
-
/**
|
|
252
|
-
* Y offset for glyph positioning
|
|
253
|
-
*/
|
|
254
|
-
yOffset: number;
|
|
255
239
|
/**
|
|
256
240
|
* Atlas texture coordinates (normalized 0-1)
|
|
257
241
|
*/
|
|
@@ -265,9 +249,13 @@ export interface GlyphLayout {
|
|
|
265
249
|
*/
|
|
266
250
|
export interface TextLayout {
|
|
267
251
|
/**
|
|
268
|
-
*
|
|
252
|
+
* vertices for rendering quads in WebGL
|
|
269
253
|
*/
|
|
270
|
-
|
|
254
|
+
vertexBuffer: Float32Array;
|
|
255
|
+
/**
|
|
256
|
+
* glyph count in layout
|
|
257
|
+
*/
|
|
258
|
+
glyphCount: number;
|
|
271
259
|
/**
|
|
272
260
|
* Total text width
|
|
273
261
|
*/
|
|
@@ -292,6 +280,14 @@ export interface TextLayout {
|
|
|
292
280
|
* distanceRange used
|
|
293
281
|
*/
|
|
294
282
|
distanceRange: number;
|
|
283
|
+
/**
|
|
284
|
+
* number of lines that exceeded maxHeight and were truncated
|
|
285
|
+
*/
|
|
286
|
+
remainingLines: number;
|
|
287
|
+
/**
|
|
288
|
+
* Whether there is remaining text that exceeded maxHeight and was truncated
|
|
289
|
+
*/
|
|
290
|
+
hasRemainingText: boolean;
|
|
295
291
|
}
|
|
296
292
|
export interface FontLoadOptions {
|
|
297
293
|
fontFamily: string;
|
|
@@ -329,6 +325,16 @@ export interface TextRenderProps {
|
|
|
329
325
|
parentHasRenderTexture: boolean;
|
|
330
326
|
framebufferDimensions: unknown;
|
|
331
327
|
stage: Stage;
|
|
328
|
+
/**
|
|
329
|
+
* Mutable wrapper ref used by the SDF renderer to cache the underlying
|
|
330
|
+
* WebGLBuffer across frames. The SDF renderer reads and writes the
|
|
331
|
+
* `.current` property so the node's ref box is updated in-place.
|
|
332
|
+
* CoreTextNode owns the ref and is responsible for calling
|
|
333
|
+
* deleteBuffer when the buffer is no longer needed.
|
|
334
|
+
*/
|
|
335
|
+
glBufferRef: {
|
|
336
|
+
current: WebGLBuffer | null;
|
|
337
|
+
};
|
|
332
338
|
}
|
|
333
339
|
export interface TextRenderInfo {
|
|
334
340
|
width: number;
|
|
@@ -342,9 +348,9 @@ export interface TextRenderer {
|
|
|
342
348
|
type: 'canvas' | 'sdf';
|
|
343
349
|
font: FontHandler;
|
|
344
350
|
renderText: (props: CoreTextNodeProps) => TextRenderInfo;
|
|
345
|
-
|
|
346
|
-
renderQuads: (renderer: CoreRenderer, layout: TextLayout, vertexBuffer: Float32Array, renderProps: TextRenderProps) => void;
|
|
351
|
+
renderQuads: (renderer: CoreRenderer, layout: TextLayout, renderProps: TextRenderProps) => void;
|
|
347
352
|
init: (stage: Stage) => void;
|
|
353
|
+
clearCache: () => void;
|
|
348
354
|
}
|
|
349
355
|
/**
|
|
350
356
|
* Text line struct for text mapping
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CoreTextNodeProps } from '../CoreTextNode.js';
|
|
1
2
|
/**
|
|
2
3
|
* Returns CSS font setting string for use in canvas context.
|
|
3
4
|
*
|
|
@@ -28,3 +29,4 @@ export declare function isSpace(space: string): boolean;
|
|
|
28
29
|
* @param text
|
|
29
30
|
*/
|
|
30
31
|
export declare function tokenizeString(tokenRegex: RegExp, text: string): string[];
|
|
32
|
+
export declare function getLayoutCacheKey(props: CoreTextNodeProps): string;
|
|
@@ -81,4 +81,7 @@ export function tokenizeString(tokenRegex, text) {
|
|
|
81
81
|
final.pop();
|
|
82
82
|
return final.filter((word) => word != '');
|
|
83
83
|
}
|
|
84
|
+
export function getLayoutCacheKey(props) {
|
|
85
|
+
return `${props.text}-${props.fontFamily}-${props.fontSize}-${props.letterSpacing}-${props.lineHeight}-${props.maxHeight}-${props.maxWidth}-${props.textAlign}-${props.wordBreak}-${props.maxLines}-${props.overflowSuffix}`;
|
|
86
|
+
}
|
|
84
87
|
//# sourceMappingURL=Utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../src/core/text-rendering/Utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,cAAc,GAAG,yCAAyC,CAAC;AAEjE;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,QAA2B,EAC3B,SAAiB,EACjB,QAAgB,EAChB,SAAiB,EACjB,eAAuB;IAEvB,IAAI,EAAE,GAAG,QAAQ,CAAC;IAElB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACvB,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAClB,6EAA6E;QAC7E,gBAAgB;QAChB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,KAAK,GAAG,eAAe,CAAC;QAC1B,CAAC;QACD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,IAAY;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,UAAU,CAAC,CAAC,CAAE,CAAC,CAAC;IACxC,CAAC;IACD,KAAK,CAAC,GAAG,EAAE,CAAC;IACZ,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC"}
|
|
1
|
+
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../src/core/text-rendering/Utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,cAAc,GAAG,yCAAyC,CAAC;AAEjE;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,QAA2B,EAC3B,SAAiB,EACjB,QAAgB,EAChB,SAAiB,EACjB,eAAuB;IAEvB,IAAI,EAAE,GAAG,QAAQ,CAAC;IAElB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACvB,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAClB,6EAA6E;QAC7E,gBAAgB;QAChB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,KAAK,GAAG,eAAe,CAAC;QAC1B,CAAC;QACD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,IAAY;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,UAAU,CAAC,CAAC,CAAE,CAAC,CAAC;IACxC,CAAC;IACD,KAAK,CAAC,GAAG,EAAE,CAAC;IACZ,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;AAC/N,CAAC"}
|
|
@@ -624,4 +624,18 @@ export declare class RendererMain extends EventEmitter {
|
|
|
624
624
|
* ```
|
|
625
625
|
*/
|
|
626
626
|
set targetFPS(fps: number);
|
|
627
|
+
private windowDevicePixelRatio;
|
|
628
|
+
/**
|
|
629
|
+
* Close and destroy the renderer, releasing all resources.
|
|
630
|
+
*
|
|
631
|
+
* @remarks
|
|
632
|
+
* This method performs a full teardown of the renderer:
|
|
633
|
+
* - Stops the platform render loop
|
|
634
|
+
* - Destroys all scene nodes (including text node font resources)
|
|
635
|
+
* - Releases all texture memory and GPU resources
|
|
636
|
+
* - Terminates image worker threads
|
|
637
|
+
* - Removes the canvas element from the target div
|
|
638
|
+
* - Destroys the inspector if active
|
|
639
|
+
*/
|
|
640
|
+
close(): void;
|
|
627
641
|
}
|
|
@@ -95,7 +95,7 @@ export class RendererMain extends EventEmitter {
|
|
|
95
95
|
textureMemory: resolvedTxSettings,
|
|
96
96
|
boundsMargin: settings.boundsMargin || 0,
|
|
97
97
|
deviceLogicalPixelRatio: settings.deviceLogicalPixelRatio || 1,
|
|
98
|
-
devicePhysicalPixelRatio: settings.devicePhysicalPixelRatio ||
|
|
98
|
+
devicePhysicalPixelRatio: settings.devicePhysicalPixelRatio || this.windowDevicePixelRatio() || 1,
|
|
99
99
|
clearColor: settings.clearColor ?? 0x00000000,
|
|
100
100
|
fpsUpdateInterval: settings.fpsUpdateInterval || 0,
|
|
101
101
|
enableClear: settings.enableClear ?? true,
|
|
@@ -128,8 +128,10 @@ export class RendererMain extends EventEmitter {
|
|
|
128
128
|
this.canvas = platform.canvas;
|
|
129
129
|
this.canvas.width = deviceLogicalWidth * devicePhysicalPixelRatio;
|
|
130
130
|
this.canvas.height = deviceLogicalHeight * devicePhysicalPixelRatio;
|
|
131
|
-
this.canvas.style
|
|
132
|
-
|
|
131
|
+
if (this.canvas.style) {
|
|
132
|
+
this.canvas.style.width = `${deviceLogicalWidth}px`;
|
|
133
|
+
this.canvas.style.height = `${deviceLogicalHeight}px`;
|
|
134
|
+
}
|
|
133
135
|
// Initialize the stage
|
|
134
136
|
this.stage = new Stage({
|
|
135
137
|
appWidth,
|
|
@@ -482,5 +484,29 @@ export class RendererMain extends EventEmitter {
|
|
|
482
484
|
this.stage.options.targetFPS = fps > 0 ? fps : 0;
|
|
483
485
|
this.stage.updateTargetFrameTime();
|
|
484
486
|
}
|
|
487
|
+
windowDevicePixelRatio() {
|
|
488
|
+
return typeof window !== 'undefined' ? window.devicePixelRatio : undefined;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Close and destroy the renderer, releasing all resources.
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* This method performs a full teardown of the renderer:
|
|
495
|
+
* - Stops the platform render loop
|
|
496
|
+
* - Destroys all scene nodes (including text node font resources)
|
|
497
|
+
* - Releases all texture memory and GPU resources
|
|
498
|
+
* - Terminates image worker threads
|
|
499
|
+
* - Removes the canvas element from the target div
|
|
500
|
+
* - Destroys the inspector if active
|
|
501
|
+
*/
|
|
502
|
+
close() {
|
|
503
|
+
// Destroy the inspector first
|
|
504
|
+
this.inspector?.destroy();
|
|
505
|
+
this.inspector = null;
|
|
506
|
+
// Destroy the stage (stops loop, destroys nodes, releases textures/GPU)
|
|
507
|
+
this.stage.destroy();
|
|
508
|
+
// Remove the canvas from the DOM
|
|
509
|
+
this.canvas.remove();
|
|
510
|
+
}
|
|
485
511
|
}
|
|
486
512
|
//# sourceMappingURL=Renderer.js.map
|