@lightningjs/renderer 3.0.3 → 3.0.5
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/dist/src/common/EventEmitter.d.ts +7 -4
- package/dist/src/common/EventEmitter.js +1 -1
- package/dist/src/common/EventEmitter.js.map +1 -1
- package/dist/src/core/AutosizeManager.d.ts +29 -0
- package/dist/src/core/AutosizeManager.js +169 -0
- package/dist/src/core/AutosizeManager.js.map +1 -0
- package/dist/src/core/CoreNode.d.ts +2 -1
- package/dist/src/core/CoreNode.js +6 -3
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.d.ts +18 -5
- package/dist/src/core/CoreTextNode.js +141 -59
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTextNodeCanvas.d.ts +215 -0
- package/dist/src/core/CoreTextNodeCanvas.js +236 -0
- package/dist/src/core/CoreTextNodeCanvas.js.map +1 -0
- package/dist/src/core/Stage.js +10 -0
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/TextureMemoryManager.js +4 -3
- package/dist/src/core/TextureMemoryManager.js.map +1 -1
- package/dist/src/core/animations/Animation.d.ts +21 -0
- package/dist/src/core/animations/Animation.js +194 -0
- package/dist/src/core/animations/Animation.js.map +1 -0
- package/dist/src/core/animations/AnimationManager.d.ts +1 -1
- package/dist/src/core/animations/AnimationManager.js +5 -5
- package/dist/src/core/animations/AnimationManager.js.map +1 -1
- package/dist/src/core/animations/CoreAnimation.d.ts +11 -2
- package/dist/src/core/animations/CoreAnimation.js +44 -38
- package/dist/src/core/animations/CoreAnimation.js.map +1 -1
- package/dist/src/core/animations/CoreAnimationController.d.ts +6 -0
- package/dist/src/core/animations/CoreAnimationController.js +16 -3
- package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
- package/dist/src/core/animations/Playback.d.ts +64 -0
- package/dist/src/core/animations/Playback.js +169 -0
- package/dist/src/core/animations/Playback.js.map +1 -0
- package/dist/src/core/animations/Ticker.d.ts +71 -0
- package/dist/src/core/animations/Ticker.js +89 -0
- package/dist/src/core/animations/Ticker.js.map +1 -0
- package/dist/src/core/animations/Transition.d.ts +38 -0
- package/dist/src/core/animations/Transition.js +35 -0
- package/dist/src/core/animations/Transition.js.map +1 -0
- package/dist/src/core/animations/TransitionsController.d.ts +10 -0
- package/dist/src/core/animations/TransitionsController.js +39 -0
- package/dist/src/core/animations/TransitionsController.js.map +1 -0
- package/dist/src/core/animations/utils.d.ts +2 -0
- package/dist/src/core/animations/utils.js +136 -0
- package/dist/src/core/animations/utils.js.map +1 -0
- package/dist/src/core/lib/ImageWorker.d.ts +2 -2
- package/dist/src/core/lib/ImageWorker.js +11 -30
- package/dist/src/core/lib/ImageWorker.js.map +1 -1
- package/dist/src/core/lib/WebGlContextWrapper.d.ts +5 -16
- package/dist/src/core/lib/WebGlContextWrapper.js +1 -35
- package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
- package/dist/src/core/lib/textureCompression.d.ts +2 -14
- package/dist/src/core/lib/textureCompression.js +67 -320
- package/dist/src/core/lib/textureCompression.js.map +1 -1
- package/dist/src/core/platform.js +9 -38
- package/dist/src/core/platform.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +0 -1
- package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +3 -11
- package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +1 -2
- package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +11 -16
- package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +14 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +1 -1
- package/dist/src/core/renderers/canvas/CanvasTexture.js +16 -6
- package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -1
- package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +0 -13
- package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +192 -113
- package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -1
- package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +2 -0
- package/dist/src/core/renderers/canvas/internal/ColorUtils.js +14 -0
- package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.d.ts +1 -2
- package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +5 -12
- package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +6 -18
- package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +60 -102
- package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +1 -3
- package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +31 -74
- package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +7 -2
- package/dist/src/core/renderers/webgl/WebGlCoreShader.js +50 -21
- package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +2 -3
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js +1 -3
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +1 -0
- package/dist/src/core/renderers/webgl/WebGlShaderNode.js +23 -0
- package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +4 -5
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +1 -0
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +6 -3
- package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +11 -0
- package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +10 -5
- package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +10 -5
- package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/SdfShader.js +12 -0
- package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js +2 -2
- package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +5 -5
- package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.d.ts +1 -0
- package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +30 -14
- package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.d.ts +0 -1
- package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +3 -13
- package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +1 -1
- package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +5 -5
- package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
- package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
- package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
- package/dist/src/core/text-rendering/CanvasFont.d.ts +1 -1
- package/dist/src/core/text-rendering/CanvasFont.js +7 -16
- package/dist/src/core/text-rendering/CanvasFont.js.map +1 -1
- package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +1 -1
- package/dist/src/core/text-rendering/CanvasFontHandler.js +1 -1
- package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -1
- package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +2 -3
- package/dist/src/core/text-rendering/CanvasTextRenderer.js +7 -5
- package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/CoreFont.d.ts +1 -1
- package/dist/src/core/text-rendering/CoreFont.js +1 -1
- package/dist/src/core/text-rendering/CoreFont.js.map +1 -1
- package/dist/src/core/text-rendering/FontManager.js +2 -1
- package/dist/src/core/text-rendering/FontManager.js.map +1 -1
- package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +3 -5
- package/dist/src/core/text-rendering/SdfTextRenderer.js +19 -109
- package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/TextLayoutEngine.js +43 -12
- package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -1
- package/dist/src/core/text-rendering/TextRenderer.d.ts +16 -8
- package/dist/src/core/text-rendering/canvas/Settings.d.ts +64 -0
- package/dist/src/core/text-rendering/canvas/Settings.js +20 -0
- package/dist/src/core/text-rendering/canvas/Settings.js.map +1 -0
- package/dist/src/core/text-rendering/canvas/Utils.d.ts +20 -0
- package/dist/src/core/text-rendering/canvas/Utils.js +144 -0
- package/dist/src/core/text-rendering/canvas/Utils.js.map +1 -0
- package/dist/src/core/text-rendering/canvas/calculateRenderInfo.d.ts +60 -0
- package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js +183 -0
- package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js.map +1 -0
- package/dist/src/core/text-rendering/canvas/draw.d.ts +5 -0
- package/dist/src/core/text-rendering/canvas/draw.js +132 -0
- package/dist/src/core/text-rendering/canvas/draw.js.map +1 -0
- package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js +2 -2
- package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +3 -4
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +46 -98
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.d.ts +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +2 -2
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +66 -8
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.d.ts +1 -1
- package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +1 -1
- package/dist/src/core/text-rendering/renderers/canvas/CanvasTextRenderer.d.ts +26 -0
- package/dist/src/core/text-rendering/renderers/canvas/CanvasTextRenderer.js +158 -0
- package/dist/src/core/text-rendering/renderers/canvas/CanvasTextRenderer.js.map +1 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/draw.d.ts +5 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/draw.js +127 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/draw.js.map +1 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/mergeDefaults.d.ts +2 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/mergeDefaults.js +50 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/mergeDefaults.js.map +1 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/renderInfo.d.ts +33 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/renderInfo.js +192 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/renderInfo.js.map +1 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/types.d.ts +66 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/types.js +2 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/types.js.map +1 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/utils.d.ts +91 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/utils.js +282 -0
- package/dist/src/core/text-rendering/renderers/canvas/internal/utils.js.map +1 -0
- package/dist/src/core/text-rendering/sdf/PeekableGenerator.d.ts +12 -0
- package/dist/src/core/text-rendering/sdf/PeekableGenerator.js +61 -0
- package/dist/src/core/text-rendering/sdf/PeekableGenerator.js.map +1 -0
- package/dist/src/core/text-rendering/sdf/SimpleFontShaper.d.ts +45 -0
- package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js +69 -0
- package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js.map +1 -0
- package/dist/src/core/text-rendering/sdf/Utils.d.ts +26 -0
- package/dist/src/core/text-rendering/sdf/Utils.js +301 -0
- package/dist/src/core/text-rendering/sdf/Utils.js.map +1 -0
- package/dist/src/core/text-rendering/sdf/index.d.ts +1 -0
- package/dist/src/core/text-rendering/sdf/index.js +20 -0
- package/dist/src/core/text-rendering/sdf/index.js.map +1 -0
- package/dist/src/core/textures/ImageTexture.js +11 -0
- package/dist/src/core/textures/ImageTexture.js.map +1 -1
- package/dist/src/core/textures/Texture.js +5 -0
- package/dist/src/core/textures/Texture.js.map +1 -1
- package/dist/src/main-api/Inspector.d.ts +1 -1
- package/dist/src/main-api/Inspector.js +25 -20
- package/dist/src/main-api/Inspector.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/src/common/EventEmitter.ts +6 -8
- package/src/core/CoreNode.test.ts +1 -1
- package/src/core/CoreNode.ts +8 -4
- package/src/core/CoreTextNode.test.ts +138 -25
- package/src/core/CoreTextNode.ts +174 -67
- package/src/core/Stage.ts +11 -0
- package/src/core/TextureMemoryManager.ts +4 -3
- package/src/core/animations/AnimationManager.ts +5 -5
- package/src/core/animations/CoreAnimation.ts +61 -45
- package/src/core/animations/CoreAnimationController.ts +16 -7
- package/src/core/renderers/canvas/CanvasRenderer.ts +19 -1
- package/src/core/renderers/canvas/CanvasTexture.ts +23 -8
- package/src/core/renderers/webgl/WebGlRenderer.ts +2 -3
- package/src/core/renderers/webgl/WebGlShaderNode.ts +24 -0
- package/src/core/renderers/webgl/WebGlShaderProgram.test.ts +274 -0
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +10 -10
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +1 -0
- package/src/core/text-rendering/CanvasFontHandler.ts +2 -2
- package/src/core/text-rendering/CanvasTextRenderer.ts +14 -7
- package/src/core/text-rendering/SdfTextRenderer.ts +28 -140
- package/src/core/text-rendering/TextLayoutEngine.ts +61 -28
- package/src/core/text-rendering/TextRenderer.ts +19 -12
- package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +20 -0
- package/src/core/textures/ImageTexture.ts +18 -0
- package/src/core/textures/Texture.ts +6 -0
- package/src/main-api/Inspector.ts +25 -25
- package/dist/src/core/text-rendering/TextGenerator.d.ts +0 -10
- package/dist/src/core/text-rendering/TextGenerator.js +0 -36
- package/dist/src/core/text-rendering/TextGenerator.js.map +0 -1
- package/src/core/renderers/webgl/SdfRenderOp.ts +0 -106
|
@@ -319,8 +319,30 @@ describe('CoreTextNode', () => {
|
|
|
319
319
|
});
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
function createSdfRenderInfo() {
|
|
323
|
+
return {
|
|
324
|
+
type: 'sdf' as const,
|
|
325
|
+
width: 100,
|
|
326
|
+
height: 20,
|
|
327
|
+
atlasTexture: {} as any,
|
|
328
|
+
layout: {
|
|
329
|
+
glyphCount: 1,
|
|
330
|
+
width: 100,
|
|
331
|
+
height: 20,
|
|
332
|
+
fontScale: 1,
|
|
333
|
+
lineHeight: 20,
|
|
334
|
+
fontFamily: 'Arial',
|
|
335
|
+
distanceRange: 4,
|
|
336
|
+
vertexBuffer: new Float32Array([0, 0, 0, 0, 10, 0, 1, 0]),
|
|
337
|
+
truncatedTextLines: 0,
|
|
338
|
+
},
|
|
339
|
+
hasRemainingText: false,
|
|
340
|
+
remainingLines: 0,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
322
344
|
describe('updateRenderState – SDF buffer release on OutOfBounds', () => {
|
|
323
|
-
it('should call renderer.deleteBuffer and clear
|
|
345
|
+
it('should call renderer.deleteBuffer and clear _sdfBuffer when transitioning to OutOfBounds', () => {
|
|
324
346
|
const deleteBuffer = vi.fn();
|
|
325
347
|
const node = new CoreTextNode(
|
|
326
348
|
makeStageWithDeleteBuffer(deleteBuffer),
|
|
@@ -328,17 +350,17 @@ describe('CoreTextNode', () => {
|
|
|
328
350
|
mockTextRenderer,
|
|
329
351
|
);
|
|
330
352
|
|
|
331
|
-
// Simulate a live WebGLBuffer sitting in the ref
|
|
332
353
|
const fakeBuffer = {};
|
|
333
|
-
(node as any).
|
|
354
|
+
(node as any)._sdfBuffer = fakeBuffer;
|
|
355
|
+
(node as any)._renderInfo = createSdfRenderInfo();
|
|
334
356
|
|
|
335
357
|
node.updateRenderState(CoreNodeRenderState.OutOfBounds);
|
|
336
358
|
|
|
337
359
|
expect(deleteBuffer).toHaveBeenCalledWith(fakeBuffer);
|
|
338
|
-
expect((node as any).
|
|
360
|
+
expect((node as any)._sdfBuffer).toBeNull();
|
|
339
361
|
});
|
|
340
362
|
|
|
341
|
-
it('should not call renderer.deleteBuffer when
|
|
363
|
+
it('should not call renderer.deleteBuffer when _sdfBuffer is already null', () => {
|
|
342
364
|
const deleteBuffer = vi.fn();
|
|
343
365
|
const node = new CoreTextNode(
|
|
344
366
|
makeStageWithDeleteBuffer(deleteBuffer),
|
|
@@ -346,7 +368,7 @@ describe('CoreTextNode', () => {
|
|
|
346
368
|
mockTextRenderer,
|
|
347
369
|
);
|
|
348
370
|
|
|
349
|
-
|
|
371
|
+
(node as any)._renderInfo = createSdfRenderInfo();
|
|
350
372
|
node.updateRenderState(CoreNodeRenderState.OutOfBounds);
|
|
351
373
|
|
|
352
374
|
expect(deleteBuffer).not.toHaveBeenCalled();
|
|
@@ -361,12 +383,13 @@ describe('CoreTextNode', () => {
|
|
|
361
383
|
);
|
|
362
384
|
|
|
363
385
|
const fakeBuffer = {};
|
|
364
|
-
(node as any).
|
|
386
|
+
(node as any)._sdfBuffer = fakeBuffer;
|
|
387
|
+
(node as any)._renderInfo = createSdfRenderInfo();
|
|
365
388
|
|
|
366
389
|
node.updateRenderState(CoreNodeRenderState.InBounds);
|
|
367
390
|
|
|
368
391
|
expect(deleteBuffer).not.toHaveBeenCalled();
|
|
369
|
-
expect((node as any).
|
|
392
|
+
expect((node as any)._sdfBuffer).toBe(fakeBuffer);
|
|
370
393
|
});
|
|
371
394
|
|
|
372
395
|
it('should not release the buffer for a canvas-type text node', () => {
|
|
@@ -382,7 +405,14 @@ describe('CoreTextNode', () => {
|
|
|
382
405
|
canvasTextRenderer,
|
|
383
406
|
);
|
|
384
407
|
|
|
385
|
-
(node as any).
|
|
408
|
+
(node as any)._renderInfo = {
|
|
409
|
+
type: 'canvas',
|
|
410
|
+
width: 100,
|
|
411
|
+
height: 20,
|
|
412
|
+
imageData: {} as ImageData,
|
|
413
|
+
hasRemainingText: false,
|
|
414
|
+
remainingLines: 0,
|
|
415
|
+
};
|
|
386
416
|
|
|
387
417
|
node.updateRenderState(CoreNodeRenderState.OutOfBounds);
|
|
388
418
|
|
|
@@ -401,12 +431,12 @@ describe('CoreTextNode', () => {
|
|
|
401
431
|
);
|
|
402
432
|
|
|
403
433
|
const fakeBuffer = {} as WebGLBuffer;
|
|
404
|
-
(node as any).
|
|
434
|
+
(node as any)._sdfBuffer = fakeBuffer;
|
|
405
435
|
|
|
406
436
|
node.update(16, clippingRect);
|
|
407
437
|
|
|
408
438
|
expect(deleteBuffer).toHaveBeenCalledWith(fakeBuffer);
|
|
409
|
-
expect((node as any).
|
|
439
|
+
expect((node as any)._sdfBuffer).toBeNull();
|
|
410
440
|
});
|
|
411
441
|
|
|
412
442
|
it('should call renderer.deleteBuffer again on each subsequent layout regeneration', () => {
|
|
@@ -424,12 +454,12 @@ describe('CoreTextNode', () => {
|
|
|
424
454
|
// Trigger a second layout pass by invalidating the layout
|
|
425
455
|
node.fontSize = 24;
|
|
426
456
|
const secondBuffer = {} as WebGLBuffer;
|
|
427
|
-
(node as any).
|
|
457
|
+
(node as any)._sdfBuffer = secondBuffer;
|
|
428
458
|
|
|
429
459
|
node.update(16, clippingRect);
|
|
430
460
|
|
|
431
461
|
expect(deleteBuffer).toHaveBeenCalledWith(secondBuffer);
|
|
432
|
-
expect((node as any).
|
|
462
|
+
expect((node as any)._sdfBuffer).toBeNull();
|
|
433
463
|
});
|
|
434
464
|
|
|
435
465
|
it('should not call renderer.deleteBuffer when buffer is already null at regeneration time', () => {
|
|
@@ -441,7 +471,7 @@ describe('CoreTextNode', () => {
|
|
|
441
471
|
mockTextRenderer,
|
|
442
472
|
);
|
|
443
473
|
|
|
444
|
-
//
|
|
474
|
+
// _sdfBuffer is null by default
|
|
445
475
|
node.update(16, clippingRect);
|
|
446
476
|
|
|
447
477
|
expect(deleteBuffer).not.toHaveBeenCalled();
|
|
@@ -460,14 +490,14 @@ describe('CoreTextNode', () => {
|
|
|
460
490
|
|
|
461
491
|
// Prime the node with a cached buffer
|
|
462
492
|
const fakeBuffer = {} as WebGLBuffer;
|
|
463
|
-
(node as any).
|
|
493
|
+
(node as any)._sdfBuffer = fakeBuffer;
|
|
464
494
|
(node as any)._layoutGenerated = true;
|
|
465
495
|
|
|
466
496
|
node.text = '';
|
|
467
497
|
node.update(16, clippingRect);
|
|
468
498
|
|
|
469
499
|
expect(deleteBuffer).toHaveBeenCalledWith(fakeBuffer);
|
|
470
|
-
expect((node as any).
|
|
500
|
+
expect((node as any)._sdfBuffer).toBeNull();
|
|
471
501
|
});
|
|
472
502
|
|
|
473
503
|
it('should not call renderer.deleteBuffer when text is invalid and buffer is already null', () => {
|
|
@@ -484,7 +514,7 @@ describe('CoreTextNode', () => {
|
|
|
484
514
|
expect(deleteBuffer).not.toHaveBeenCalled();
|
|
485
515
|
});
|
|
486
516
|
|
|
487
|
-
it('should also clear
|
|
517
|
+
it('should also clear _renderInfo when text becomes invalid', () => {
|
|
488
518
|
const deleteBuffer = vi.fn();
|
|
489
519
|
const props = { ...defaultTextProps, text: 'Hello', forceLoad: true };
|
|
490
520
|
const node = new CoreTextNode(
|
|
@@ -493,13 +523,12 @@ describe('CoreTextNode', () => {
|
|
|
493
523
|
mockTextRenderer,
|
|
494
524
|
);
|
|
495
525
|
|
|
496
|
-
(node as any).
|
|
497
|
-
(node as any)._layoutGenerated = true;
|
|
526
|
+
(node as any)._renderInfo = createSdfRenderInfo();
|
|
498
527
|
|
|
499
528
|
node.text = '';
|
|
500
529
|
node.update(16, clippingRect);
|
|
501
530
|
|
|
502
|
-
expect((node as any).
|
|
531
|
+
expect((node as any)._renderInfo).toBeNull();
|
|
503
532
|
});
|
|
504
533
|
});
|
|
505
534
|
|
|
@@ -513,12 +542,12 @@ describe('CoreTextNode', () => {
|
|
|
513
542
|
);
|
|
514
543
|
|
|
515
544
|
const fakeBuffer = {} as WebGLBuffer;
|
|
516
|
-
(node as any).
|
|
545
|
+
(node as any)._sdfBuffer = fakeBuffer;
|
|
517
546
|
|
|
518
547
|
node.destroy();
|
|
519
548
|
|
|
520
549
|
expect(deleteBuffer).toHaveBeenCalledWith(fakeBuffer);
|
|
521
|
-
expect((node as any).
|
|
550
|
+
expect((node as any)._sdfBuffer).toBeNull();
|
|
522
551
|
});
|
|
523
552
|
|
|
524
553
|
it('should not call renderer.deleteBuffer on destroy when buffer is already null', () => {
|
|
@@ -535,14 +564,98 @@ describe('CoreTextNode', () => {
|
|
|
535
564
|
expect(deleteBuffer).not.toHaveBeenCalled();
|
|
536
565
|
});
|
|
537
566
|
|
|
538
|
-
it('should clear
|
|
567
|
+
it('should clear _renderInfo on destroy', () => {
|
|
539
568
|
const node = new CoreTextNode(stage, defaultTextProps, mockTextRenderer);
|
|
540
569
|
|
|
541
|
-
(node as any).
|
|
570
|
+
(node as any)._renderInfo = createSdfRenderInfo();
|
|
542
571
|
|
|
543
572
|
node.destroy();
|
|
544
573
|
|
|
545
|
-
expect((node as any).
|
|
574
|
+
expect((node as any)._renderInfo).toBeNull();
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
describe('SDF render path', () => {
|
|
579
|
+
it('reuses the uploaded SDF buffer across renderQuads calls', () => {
|
|
580
|
+
const createBuffer = vi.fn().mockReturnValue({ label: 'sdf-buffer' });
|
|
581
|
+
const arrayBufferData = vi.fn();
|
|
582
|
+
const glw = {
|
|
583
|
+
createBuffer,
|
|
584
|
+
arrayBufferData,
|
|
585
|
+
STATIC_DRAW: 0x88e4,
|
|
586
|
+
FLOAT: 0x1406,
|
|
587
|
+
};
|
|
588
|
+
const sdfStage = mock<Stage>({
|
|
589
|
+
strictBound: createBound(0, 0, 1920, 1080),
|
|
590
|
+
preloadBound: createBound(0, 0, 1920, 1080),
|
|
591
|
+
defaultTexture: { state: 'loaded' },
|
|
592
|
+
renderer: { glw } as unknown as CoreRenderer,
|
|
593
|
+
});
|
|
594
|
+
const node = new CoreTextNode(
|
|
595
|
+
sdfStage,
|
|
596
|
+
defaultTextProps,
|
|
597
|
+
mockTextRenderer,
|
|
598
|
+
);
|
|
599
|
+
const transform = new Float32Array([1, 0, 0, 1, 0, 0]);
|
|
600
|
+
|
|
601
|
+
(node as any).handleRenderResult(createSdfRenderInfo());
|
|
602
|
+
(node as any).globalTransform = {
|
|
603
|
+
getFloatArr: vi.fn().mockReturnValue(transform),
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
node.renderQuads(sdfStage.renderer);
|
|
607
|
+
node.renderQuads(sdfStage.renderer);
|
|
608
|
+
|
|
609
|
+
expect(createBuffer).toHaveBeenCalledTimes(1);
|
|
610
|
+
expect(arrayBufferData).toHaveBeenCalledTimes(1);
|
|
611
|
+
expect(mockTextRenderer.renderQuads).toHaveBeenCalledTimes(2);
|
|
612
|
+
expect((node as any)._sdfBuffer).toEqual({ label: 'sdf-buffer' });
|
|
613
|
+
expect(node.sdfShaderProps.transform).toBe(transform);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it('uses framebuffer-relative scissor coordinates for RTT draws', () => {
|
|
617
|
+
const bindRenderOp = vi.fn();
|
|
618
|
+
const useShader = vi.fn();
|
|
619
|
+
const setScissorTest = vi.fn();
|
|
620
|
+
const scissor = vi.fn();
|
|
621
|
+
const drawArrays = vi.fn();
|
|
622
|
+
const sdfStage = mock<Stage>({
|
|
623
|
+
strictBound: createBound(0, 0, 1920, 1080),
|
|
624
|
+
preloadBound: createBound(0, 0, 1920, 1080),
|
|
625
|
+
defaultTexture: { state: 'loaded' },
|
|
626
|
+
pixelRatio: 2,
|
|
627
|
+
platform: { canvas: { width: 1920, height: 1080 } } as any,
|
|
628
|
+
shManager: { useShader } as any,
|
|
629
|
+
});
|
|
630
|
+
const node = new CoreTextNode(
|
|
631
|
+
sdfStage,
|
|
632
|
+
defaultTextProps,
|
|
633
|
+
mockTextRenderer,
|
|
634
|
+
);
|
|
635
|
+
const shader = { program: { bindRenderOp } };
|
|
636
|
+
|
|
637
|
+
node.props.shader = shader as any;
|
|
638
|
+
node.numQuads = 2;
|
|
639
|
+
node.clippingRect = { x: 10, y: 20, w: 30, h: 40, valid: true };
|
|
640
|
+
node.parentHasRenderTexture = true;
|
|
641
|
+
node.rttParent = { framebufferDimensions: { w: 320, h: 180 } } as any;
|
|
642
|
+
node.props.h = 25;
|
|
643
|
+
|
|
644
|
+
node.draw({
|
|
645
|
+
glw: {
|
|
646
|
+
TRIANGLES: 4,
|
|
647
|
+
setScissorTest,
|
|
648
|
+
scissor,
|
|
649
|
+
drawArrays,
|
|
650
|
+
},
|
|
651
|
+
stage: sdfStage,
|
|
652
|
+
} as any);
|
|
653
|
+
|
|
654
|
+
expect(useShader).toHaveBeenCalledWith(shader.program);
|
|
655
|
+
expect(bindRenderOp).toHaveBeenCalledWith(node);
|
|
656
|
+
expect(setScissorTest).toHaveBeenCalledWith(true);
|
|
657
|
+
expect(scissor).toHaveBeenCalledWith(10, 155, 30, 40);
|
|
658
|
+
expect(drawArrays).toHaveBeenCalledWith(4, 0, 12);
|
|
546
659
|
});
|
|
547
660
|
});
|
|
548
661
|
});
|
package/src/core/CoreTextNode.ts
CHANGED
|
@@ -21,7 +21,6 @@ import type {
|
|
|
21
21
|
FontHandler,
|
|
22
22
|
TextRenderer,
|
|
23
23
|
TrProps,
|
|
24
|
-
TextLayout,
|
|
25
24
|
TextRenderInfo,
|
|
26
25
|
} from './text-rendering/TextRenderer.js';
|
|
27
26
|
import {
|
|
@@ -40,6 +39,11 @@ import type { RectWithValid } from './lib/utils.js';
|
|
|
40
39
|
import type { CoreRenderer } from './renderers/CoreRenderer.js';
|
|
41
40
|
import type { TextureLoadedEventHandler } from './textures/Texture.js';
|
|
42
41
|
import { Matrix3d } from './lib/Matrix3d.js';
|
|
42
|
+
import { BufferCollection } from './renderers/webgl/internal/BufferCollection.js';
|
|
43
|
+
import type { SdfShaderProps } from './shaders/webgl/SdfShader.js';
|
|
44
|
+
import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
|
|
45
|
+
import type { WebGlCtxTexture } from './renderers/webgl/WebGlCtxTexture.js';
|
|
46
|
+
import { mergeColorAlpha } from '../utils.js';
|
|
43
47
|
export interface CoreTextNodeProps extends CoreNodeProps, TrProps {
|
|
44
48
|
/**
|
|
45
49
|
* Force Text Node to use a specific Text Renderer
|
|
@@ -63,21 +67,14 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
63
67
|
private _waitingForFont = false;
|
|
64
68
|
private _containType: TextConstraint = TextConstraint.none;
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
private
|
|
68
|
-
|
|
69
|
-
// created WebGLBuffer back into it, allowing reuse across frames.
|
|
70
|
-
private _sdfBufferRef: { current: WebGLBuffer | null } = { current: null };
|
|
70
|
+
private _sdfBuffer: WebGLBuffer | null = null;
|
|
71
|
+
private _sdfQuadCollection: BufferCollection | null = null;
|
|
72
|
+
private _sdfShaderProps: Partial<SdfShaderProps> | null = null;
|
|
71
73
|
|
|
72
74
|
// Text renderer properties - stored directly on the node
|
|
73
|
-
|
|
75
|
+
textProps: CoreTextNodeProps;
|
|
74
76
|
|
|
75
|
-
private _renderInfo: TextRenderInfo =
|
|
76
|
-
width: 0,
|
|
77
|
-
height: 0,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
private _type: 'sdf' | 'canvas' = 'sdf'; // Default to SDF renderer
|
|
77
|
+
private _renderInfo: TextRenderInfo | null = null;
|
|
81
78
|
|
|
82
79
|
constructor(
|
|
83
80
|
stage: Stage,
|
|
@@ -87,7 +84,6 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
87
84
|
super(stage, props);
|
|
88
85
|
this.textRenderer = textRenderer;
|
|
89
86
|
this.fontHandler = textRenderer.font;
|
|
90
|
-
this._type = textRenderer.type;
|
|
91
87
|
|
|
92
88
|
// Initialize text properties from props
|
|
93
89
|
// Props are guaranteed to have all defaults resolved by Stage.createTextNode
|
|
@@ -121,10 +117,11 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
121
117
|
* Safe to call from destroy() or on text change.
|
|
122
118
|
*/
|
|
123
119
|
private releaseSdfBuffer(): void {
|
|
124
|
-
const buf = this.
|
|
120
|
+
const buf = this._sdfBuffer;
|
|
125
121
|
if (buf === null) return;
|
|
126
122
|
this.stage.renderer.deleteBuffer(buf);
|
|
127
|
-
this.
|
|
123
|
+
this._sdfBuffer = null;
|
|
124
|
+
this._sdfQuadCollection = null;
|
|
128
125
|
}
|
|
129
126
|
|
|
130
127
|
allowTextGeneration() {
|
|
@@ -221,7 +218,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
221
218
|
) {
|
|
222
219
|
if (this.fontHandler.isFontLoaded(this.textProps.fontFamily) === true) {
|
|
223
220
|
this._waitingForFont = false;
|
|
224
|
-
this.
|
|
221
|
+
this._renderInfo = null; // Clear any previous render info before generating new layout
|
|
225
222
|
this.releaseSdfBuffer(); // Free the cached WebGLBuffer
|
|
226
223
|
const resp = this.textRenderer.renderText(this.textProps);
|
|
227
224
|
this.handleRenderResult(resp);
|
|
@@ -236,7 +233,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
236
233
|
// If text is invalid, ensure node is not renderable
|
|
237
234
|
this.setRenderable(false);
|
|
238
235
|
this._layoutGenerated = false;
|
|
239
|
-
this.
|
|
236
|
+
this._renderInfo = null;
|
|
240
237
|
this.releaseSdfBuffer(); // Free the cached WebGLBuffer
|
|
241
238
|
}
|
|
242
239
|
|
|
@@ -251,19 +248,19 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
251
248
|
// Guard: Text nodes are never renderable without valid text
|
|
252
249
|
const hasValidText =
|
|
253
250
|
typeof this.textProps.text === 'string' && this.textProps.text.length > 0;
|
|
254
|
-
|
|
251
|
+
|
|
252
|
+
const renderInfo = this._renderInfo;
|
|
253
|
+
if (hasValidText === false || renderInfo === null) {
|
|
255
254
|
this.setRenderable(false);
|
|
256
255
|
return;
|
|
257
256
|
}
|
|
258
257
|
|
|
259
258
|
// SDF text nodes are always renderable if they have a valid layout
|
|
260
|
-
if (
|
|
259
|
+
if (renderInfo.type === 'canvas') {
|
|
261
260
|
super.updateIsRenderable();
|
|
262
261
|
return;
|
|
263
262
|
}
|
|
264
|
-
|
|
265
|
-
// For SDF, check if we have a cached layout
|
|
266
|
-
this.setRenderable(this._cachedLayout !== null);
|
|
263
|
+
this.setRenderable(true);
|
|
267
264
|
}
|
|
268
265
|
|
|
269
266
|
/**
|
|
@@ -271,10 +268,19 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
271
268
|
*/
|
|
272
269
|
private handleRenderResult(result: TextRenderInfo): void {
|
|
273
270
|
// Host paths on top
|
|
274
|
-
const textRendererType =
|
|
271
|
+
const textRendererType = result.type;
|
|
275
272
|
let width = result.width;
|
|
276
273
|
let height = result.height;
|
|
277
274
|
|
|
275
|
+
// Handle zero-dimension case (can happen with certain text inputs or font issues)
|
|
276
|
+
if (width === 0 || height === 0) {
|
|
277
|
+
this.emit('failed', {
|
|
278
|
+
type: 'text',
|
|
279
|
+
error: new Error('Text rendering failed, width or height zero'),
|
|
280
|
+
} satisfies NodeTextFailedPayload);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
278
284
|
// Handle Canvas renderer (uses ImageData)
|
|
279
285
|
if (textRendererType === 'canvas') {
|
|
280
286
|
if (result.imageData === undefined) {
|
|
@@ -291,6 +297,9 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
291
297
|
premultiplyAlpha: true,
|
|
292
298
|
src: result.imageData as ImageData,
|
|
293
299
|
});
|
|
300
|
+
|
|
301
|
+
this.props.w = width;
|
|
302
|
+
this.props.h = height;
|
|
294
303
|
// It isn't renderable until the texture is loaded we have to set it to false here to avoid it
|
|
295
304
|
// being detected as a renderable default color node in the next frame
|
|
296
305
|
// it will be corrected once the texture is loaded
|
|
@@ -300,25 +309,31 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
300
309
|
// We do want the texture to load immediately
|
|
301
310
|
this.texture.setRenderableOwner(this._id, true);
|
|
302
311
|
}
|
|
303
|
-
}
|
|
312
|
+
} else {
|
|
313
|
+
const layout = result.layout;
|
|
314
|
+
// For SDF, we rely on the presence of a valid layout to determine renderability
|
|
315
|
+
if (layout === undefined) {
|
|
316
|
+
this.emit('failed', {
|
|
317
|
+
type: 'text',
|
|
318
|
+
error: new Error(
|
|
319
|
+
'SDF text rendering failed, no layout data returned',
|
|
320
|
+
),
|
|
321
|
+
} satisfies NodeTextFailedPayload);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
304
324
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
this.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
} satisfies NodeTextFailedPayload);
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
325
|
+
this.props.w = width;
|
|
326
|
+
this.props.h = height;
|
|
327
|
+
this.setUpdateType(UpdateType.Local);
|
|
328
|
+
this.setRenderable(true);
|
|
329
|
+
this.numQuads = layout.glyphCount;
|
|
313
330
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
331
|
+
this._sdfShaderProps = {
|
|
332
|
+
size: layout.fontScale,
|
|
333
|
+
distanceRange: layout.distanceRange,
|
|
334
|
+
};
|
|
317
335
|
|
|
318
|
-
|
|
319
|
-
if (textRendererType === 'sdf') {
|
|
320
|
-
this.setRenderable(true);
|
|
321
|
-
this.setUpdateType(UpdateType.Local);
|
|
336
|
+
this.renderOpTextures = [result.atlasTexture as WebGlCtxTexture];
|
|
322
337
|
}
|
|
323
338
|
|
|
324
339
|
this._renderInfo = result;
|
|
@@ -327,6 +342,8 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
327
342
|
|
|
328
343
|
// Reusable bound method for emitting loaded event
|
|
329
344
|
private emitTextLoadedEvent = () => {
|
|
345
|
+
if (this._renderInfo === null) return; // Guard against unexpected null
|
|
346
|
+
|
|
330
347
|
this.emit('loaded', {
|
|
331
348
|
type: 'text',
|
|
332
349
|
dimensions: {
|
|
@@ -346,42 +363,68 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
346
363
|
return;
|
|
347
364
|
}
|
|
348
365
|
|
|
349
|
-
//
|
|
350
|
-
if (this.
|
|
351
|
-
super.renderQuads(renderer);
|
|
366
|
+
// Early return if no renderInfo
|
|
367
|
+
if (this._renderInfo === null) {
|
|
352
368
|
return;
|
|
353
369
|
}
|
|
354
370
|
|
|
355
|
-
//
|
|
356
|
-
if (this.
|
|
371
|
+
// Canvas renderer: use standard texture rendering via CoreNode
|
|
372
|
+
if (this._renderInfo.type === 'canvas') {
|
|
373
|
+
super.renderQuads(renderer);
|
|
357
374
|
return;
|
|
358
375
|
}
|
|
359
376
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
:
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
if (this._sdfBuffer === null) {
|
|
378
|
+
const glw = (this.stage.renderer as WebGlRenderer).glw;
|
|
379
|
+
this._sdfBuffer = glw.createBuffer();
|
|
380
|
+
if (this._sdfBuffer === null) {
|
|
381
|
+
console.error('Failed to create WebGL buffer for SDF text rendering');
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
glw.arrayBufferData(
|
|
385
|
+
this._sdfBuffer,
|
|
386
|
+
this._renderInfo.layout.vertexBuffer,
|
|
387
|
+
glw.STATIC_DRAW,
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
this._sdfQuadCollection = new BufferCollection([
|
|
391
|
+
{
|
|
392
|
+
buffer: this._sdfBuffer,
|
|
393
|
+
attributes: {
|
|
394
|
+
a_position: {
|
|
395
|
+
name: 'a_position',
|
|
396
|
+
size: 2,
|
|
397
|
+
type: glw.FLOAT as number,
|
|
398
|
+
normalized: false,
|
|
399
|
+
stride: 4 * Float32Array.BYTES_PER_ELEMENT,
|
|
400
|
+
offset: 0,
|
|
401
|
+
},
|
|
402
|
+
a_textureCoords: {
|
|
403
|
+
name: 'a_textureCoords',
|
|
404
|
+
size: 2,
|
|
405
|
+
type: glw.FLOAT as number,
|
|
406
|
+
normalized: false,
|
|
407
|
+
stride: 4 * Float32Array.BYTES_PER_ELEMENT,
|
|
408
|
+
offset: 2 * Float32Array.BYTES_PER_ELEMENT,
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
]);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this.sdfShaderProps!.transform = this.globalTransform!.getFloatArr();
|
|
416
|
+
this.sdfShaderProps!.color = mergeColorAlpha(
|
|
417
|
+
this.props.color,
|
|
418
|
+
this.worldAlpha,
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
this.textRenderer.renderQuads(this);
|
|
379
422
|
}
|
|
380
423
|
|
|
381
424
|
override updateRenderState(renderState: CoreNodeRenderState): void {
|
|
382
425
|
super.updateRenderState(renderState);
|
|
383
426
|
if (
|
|
384
|
-
this.
|
|
427
|
+
this._renderInfo !== null &&
|
|
385
428
|
renderState === CoreNodeRenderState.OutOfBounds
|
|
386
429
|
) {
|
|
387
430
|
this.releaseSdfBuffer();
|
|
@@ -394,7 +437,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
394
437
|
}
|
|
395
438
|
|
|
396
439
|
// Clear cached layout and vertex buffer
|
|
397
|
-
this.
|
|
440
|
+
this._renderInfo = null;
|
|
398
441
|
this.releaseSdfBuffer(); // Delete the cached WebGLBuffer before losing stage ref
|
|
399
442
|
|
|
400
443
|
this.fontHandler = null!; // Clear reference to avoid memory leaks
|
|
@@ -403,6 +446,70 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
403
446
|
super.destroy();
|
|
404
447
|
}
|
|
405
448
|
|
|
449
|
+
/**
|
|
450
|
+
* used in webgl SDF shader to get the quad buffer collection for rendering text quads
|
|
451
|
+
*/
|
|
452
|
+
override get quadBufferCollection(): BufferCollection {
|
|
453
|
+
return this._sdfQuadCollection || super.quadBufferCollection;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* used in webgl SDF shader to get the SDF shader props for rendering text quads
|
|
458
|
+
*/
|
|
459
|
+
get sdfShaderProps(): SdfShaderProps {
|
|
460
|
+
return this._sdfShaderProps as SdfShaderProps;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
override get isSdfRenderOp(): boolean {
|
|
464
|
+
return this.textRenderer.type === 'sdf';
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
override draw(renderer: WebGlRenderer) {
|
|
468
|
+
if (this.textRenderer.type === 'canvas') {
|
|
469
|
+
super.draw(renderer);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const { glw, stage } = renderer;
|
|
474
|
+
const canvas = stage.platform!.canvas!;
|
|
475
|
+
const shader = this.props.shader as any;
|
|
476
|
+
|
|
477
|
+
stage.shManager.useShader(shader.program);
|
|
478
|
+
shader.program.bindRenderOp(this);
|
|
479
|
+
|
|
480
|
+
const clippingRect = this.clippingRect;
|
|
481
|
+
|
|
482
|
+
// Clipping
|
|
483
|
+
if (clippingRect.valid === true) {
|
|
484
|
+
const pixelRatio = this.parentHasRenderTexture ? 1 : stage.pixelRatio;
|
|
485
|
+
|
|
486
|
+
const clipX = Math.round(clippingRect.x * pixelRatio);
|
|
487
|
+
const clipWidth = Math.round(clippingRect.w * pixelRatio);
|
|
488
|
+
const clipHeight = Math.round(clippingRect.h * pixelRatio);
|
|
489
|
+
let clipY = Math.round(
|
|
490
|
+
canvas.height - clipHeight - clippingRect.y * pixelRatio,
|
|
491
|
+
);
|
|
492
|
+
// if parent has render texture, we need to adjust the scissor rect
|
|
493
|
+
// to be relative to the parent's framebuffer
|
|
494
|
+
if (this.parentHasRenderTexture) {
|
|
495
|
+
const parentFramebufferDimensions = this.parentFramebufferDimensions;
|
|
496
|
+
clipY =
|
|
497
|
+
parentFramebufferDimensions !== null
|
|
498
|
+
? parentFramebufferDimensions.h - this.props.h
|
|
499
|
+
: 0;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
glw.setScissorTest(true);
|
|
503
|
+
glw.scissor(clipX, clipY, clipWidth, clipHeight);
|
|
504
|
+
} else {
|
|
505
|
+
glw.setScissorTest(false);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// SDF rendering uses drawArrays with explicit triangle vertices (6 vertices per quad)
|
|
509
|
+
// Note: buffers should be bound by bindRenderOp -> bindBufferCollection
|
|
510
|
+
glw.drawArrays(glw.TRIANGLES, 0, 6 * this.numQuads);
|
|
511
|
+
}
|
|
512
|
+
|
|
406
513
|
override set w(value: number) {
|
|
407
514
|
this.maxWidth = value;
|
|
408
515
|
}
|
|
@@ -621,7 +728,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
|
|
|
621
728
|
}
|
|
622
729
|
}
|
|
623
730
|
|
|
624
|
-
get renderInfo(): TextRenderInfo {
|
|
731
|
+
get renderInfo(): TextRenderInfo | null {
|
|
625
732
|
return this._renderInfo;
|
|
626
733
|
}
|
|
627
734
|
}
|
package/src/core/Stage.ts
CHANGED
|
@@ -224,6 +224,17 @@ export class Stage {
|
|
|
224
224
|
|
|
225
225
|
const renderMode = this.renderer.mode || 'webgl';
|
|
226
226
|
|
|
227
|
+
// Canvas2D textures are plain JS heap objects managed by the browser GC.
|
|
228
|
+
// Threshold-based upload blocking makes no sense for JS heap — disable it
|
|
229
|
+
// by setting criticalThreshold to 0 while keeping the eviction machinery.
|
|
230
|
+
if (renderMode === 'canvas') {
|
|
231
|
+
this.txMemManager.updateSettings({
|
|
232
|
+
...textureMemory,
|
|
233
|
+
criticalThreshold: 0,
|
|
234
|
+
doNotExceedCriticalThreshold: false,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
227
238
|
this.createDefaultTexture();
|
|
228
239
|
setPremultiplyMode(renderMode);
|
|
229
240
|
|