@lightningjs/renderer 2.3.2 → 2.5.0

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.
Files changed (157) hide show
  1. package/dist/exports/core-api.d.ts +74 -0
  2. package/dist/exports/core-api.js +96 -0
  3. package/dist/exports/core-api.js.map +1 -0
  4. package/dist/exports/main-api.d.ts +30 -0
  5. package/dist/exports/main-api.js +45 -0
  6. package/dist/exports/main-api.js.map +1 -0
  7. package/dist/src/common/CommonTypes.d.ts +6 -0
  8. package/dist/src/core/CoreExtension.d.ts +12 -0
  9. package/dist/src/core/CoreExtension.js +29 -0
  10. package/dist/src/core/CoreExtension.js.map +1 -0
  11. package/dist/src/core/CoreNode.js +37 -39
  12. package/dist/src/core/CoreNode.js.map +1 -1
  13. package/dist/src/core/Stage.d.ts +1 -0
  14. package/dist/src/core/Stage.js +4 -1
  15. package/dist/src/core/Stage.js.map +1 -1
  16. package/dist/src/core/animations/CoreAnimation.d.ts +1 -0
  17. package/dist/src/core/animations/CoreAnimation.js +6 -0
  18. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  19. package/dist/src/core/animations/CoreAnimationController.d.ts +1 -0
  20. package/dist/src/core/animations/CoreAnimationController.js +6 -0
  21. package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
  22. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +1 -1
  23. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +7 -1
  24. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  25. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +11 -4
  26. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +1 -1
  27. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +94 -98
  28. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  29. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +4 -0
  30. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +1 -1
  31. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +5 -1
  32. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +1 -1
  33. package/dist/src/core/text-rendering/TrFontManager.d.ts +1 -1
  34. package/dist/src/core/text-rendering/TrFontManager.js +2 -2
  35. package/dist/src/core/text-rendering/TrFontManager.js.map +1 -1
  36. package/dist/src/core/text-rendering/font-face-types/TrFontFace.js.map +1 -1
  37. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +5 -6
  38. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  39. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +18 -10
  40. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  41. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +4 -4
  42. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  43. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +3 -1
  44. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  45. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.js +2 -1
  46. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.js.map +1 -1
  47. package/dist/src/core/textures/ColorTexture.d.ts +2 -1
  48. package/dist/src/core/textures/ColorTexture.js +2 -1
  49. package/dist/src/core/textures/ColorTexture.js.map +1 -1
  50. package/dist/src/core/textures/ImageTexture.d.ts +2 -1
  51. package/dist/src/core/textures/ImageTexture.js +4 -3
  52. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  53. package/dist/src/core/textures/NoiseTexture.d.ts +2 -1
  54. package/dist/src/core/textures/NoiseTexture.js +2 -1
  55. package/dist/src/core/textures/NoiseTexture.js.map +1 -1
  56. package/dist/src/core/textures/RenderTexture.d.ts +2 -1
  57. package/dist/src/core/textures/RenderTexture.js +2 -1
  58. package/dist/src/core/textures/RenderTexture.js.map +1 -1
  59. package/dist/src/core/textures/SubTexture.d.ts +2 -1
  60. package/dist/src/core/textures/SubTexture.js +2 -1
  61. package/dist/src/core/textures/SubTexture.js.map +1 -1
  62. package/dist/src/core/textures/Texture.d.ts +9 -0
  63. package/dist/src/core/textures/Texture.js +10 -0
  64. package/dist/src/core/textures/Texture.js.map +1 -1
  65. package/dist/src/core/utils.d.ts +1 -1
  66. package/dist/src/main-api/ICoreDriver.d.ts +24 -0
  67. package/dist/src/main-api/ICoreDriver.js +20 -0
  68. package/dist/src/main-api/ICoreDriver.js.map +1 -0
  69. package/dist/src/main-api/Renderer.js +1 -0
  70. package/dist/src/main-api/Renderer.js.map +1 -1
  71. package/dist/src/main-api/RendererMain.d.ts +378 -0
  72. package/dist/src/main-api/RendererMain.js +367 -0
  73. package/dist/src/main-api/RendererMain.js.map +1 -0
  74. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.d.ts +9 -0
  75. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js +38 -0
  76. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js.map +1 -0
  77. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.d.ts +56 -0
  78. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js +101 -0
  79. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js.map +1 -0
  80. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.d.ts +32 -0
  81. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js +28 -0
  82. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js.map +1 -0
  83. package/dist/src/render-drivers/main/MainCoreDriver.d.ts +21 -0
  84. package/dist/src/render-drivers/main/MainCoreDriver.js +115 -0
  85. package/dist/src/render-drivers/main/MainCoreDriver.js.map +1 -0
  86. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +101 -0
  87. package/dist/src/render-drivers/main/MainOnlyNode.js +425 -0
  88. package/dist/src/render-drivers/main/MainOnlyNode.js.map +1 -0
  89. package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +47 -0
  90. package/dist/src/render-drivers/main/MainOnlyTextNode.js +204 -0
  91. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +1 -0
  92. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +93 -0
  93. package/dist/src/render-drivers/threadx/NodeStruct.js +290 -0
  94. package/dist/src/render-drivers/threadx/NodeStruct.js.map +1 -0
  95. package/dist/src/render-drivers/threadx/SharedNode.d.ts +40 -0
  96. package/dist/src/render-drivers/threadx/SharedNode.js +61 -0
  97. package/dist/src/render-drivers/threadx/SharedNode.js.map +1 -0
  98. package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +44 -0
  99. package/dist/src/render-drivers/threadx/TextNodeStruct.js +203 -0
  100. package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +1 -0
  101. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +25 -0
  102. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +232 -0
  103. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +1 -0
  104. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.d.ts +24 -0
  105. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js +113 -0
  106. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js.map +1 -0
  107. package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +46 -0
  108. package/dist/src/render-drivers/threadx/ThreadXMainNode.js +160 -0
  109. package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +1 -0
  110. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +28 -0
  111. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +55 -0
  112. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +1 -0
  113. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +70 -0
  114. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js +32 -0
  115. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +1 -0
  116. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.d.ts +19 -0
  117. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +184 -0
  118. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +1 -0
  119. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +27 -0
  120. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +109 -0
  121. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +1 -0
  122. package/dist/src/render-drivers/threadx/worker/renderer.d.ts +1 -0
  123. package/dist/src/render-drivers/threadx/worker/renderer.js +147 -0
  124. package/dist/src/render-drivers/threadx/worker/renderer.js.map +1 -0
  125. package/dist/src/render-drivers/utils.d.ts +12 -0
  126. package/dist/src/render-drivers/utils.js +74 -0
  127. package/dist/src/render-drivers/utils.js.map +1 -0
  128. package/dist/src/utils.js +1 -1
  129. package/dist/src/utils.js.map +1 -1
  130. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  131. package/dist/tsconfig.tsbuildinfo +1 -0
  132. package/package.json +1 -1
  133. package/src/common/CommonTypes.ts +7 -0
  134. package/src/core/CoreNode.ts +38 -55
  135. package/src/core/Stage.ts +6 -1
  136. package/src/core/animations/CoreAnimation.ts +7 -0
  137. package/src/core/animations/CoreAnimationController.ts +12 -0
  138. package/src/core/renderers/webgl/WebGlCoreCtxTexture.ts +7 -1
  139. package/src/core/renderers/webgl/WebGlCoreRenderOp.ts +13 -4
  140. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +122 -136
  141. package/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts +7 -0
  142. package/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts +8 -1
  143. package/src/core/text-rendering/TrFontManager.ts +3 -1
  144. package/src/core/text-rendering/font-face-types/TrFontFace.ts +0 -1
  145. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +7 -7
  146. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +28 -14
  147. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +8 -6
  148. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +5 -1
  149. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +2 -1
  150. package/src/core/textures/ColorTexture.ts +3 -1
  151. package/src/core/textures/ImageTexture.ts +5 -3
  152. package/src/core/textures/NoiseTexture.ts +3 -1
  153. package/src/core/textures/RenderTexture.ts +3 -1
  154. package/src/core/textures/SubTexture.ts +3 -0
  155. package/src/core/textures/Texture.ts +11 -0
  156. package/src/main-api/Renderer.ts +1 -0
  157. package/src/utils.ts +1 -1
@@ -34,7 +34,7 @@ import {
34
34
  getWebGlExtensions,
35
35
  } from './internal/RendererUtils.js';
36
36
  import { WebGlCoreCtxTexture } from './WebGlCoreCtxTexture.js';
37
- import { Texture } from '../../textures/Texture.js';
37
+ import { Texture, TextureType } from '../../textures/Texture.js';
38
38
  import { ColorTexture } from '../../textures/ColorTexture.js';
39
39
  import { SubTexture } from '../../textures/SubTexture.js';
40
40
  import { WebGlCoreCtxSubTexture } from './WebGlCoreCtxSubTexture.js';
@@ -231,232 +231,220 @@ export class WebGlCoreRenderer extends CoreRenderer {
231
231
  */
232
232
  addQuad(params: QuadOptions) {
233
233
  const { fQuadBuffer, uiQuadBuffer } = this;
234
- const {
235
- width,
236
- height,
237
- colorTl,
238
- colorTr,
239
- colorBl,
240
- colorBr,
241
- textureOptions,
242
- shader,
243
- shaderProps,
244
- alpha,
245
- clippingRect,
246
- tx,
247
- ty,
248
- ta,
249
- tb,
250
- tc,
251
- td,
252
- renderCoords,
253
- rtt: renderToTexture,
254
- parentHasRenderTexture,
255
- framebufferDimensions,
256
- } = params;
257
- let { texture } = params;
234
+ let texture = params.texture || this.defaultTexture;
258
235
 
259
236
  /**
260
237
  * If the shader props contain any automatic properties, update it with the
261
238
  * current dimensions and or alpha that will be used to render the quad.
262
239
  */
263
- if (shaderProps !== null) {
264
- if (hasOwn(shaderProps, '$dimensions')) {
265
- const dimensions = shaderProps.$dimensions as Dimensions;
266
- dimensions.width = width;
267
- dimensions.height = height;
240
+ if (params.shaderProps !== null) {
241
+ if (hasOwn(params.shaderProps, '$dimensions') == true) {
242
+ const dimensions = params.shaderProps.$dimensions as Dimensions;
243
+ dimensions.width = params.width;
244
+ dimensions.height = params.height;
268
245
  }
269
246
 
270
- if (hasOwn(shaderProps, '$alpha')) {
271
- shaderProps.$alpha = alpha;
247
+ if (hasOwn(params.shaderProps, '$alpha') === true) {
248
+ params.shaderProps.$alpha = params.alpha;
272
249
  }
273
250
  }
274
251
 
275
- texture = texture ?? this.defaultTexture;
276
- assertTruthy(texture instanceof Texture, 'Invalid texture type');
252
+ assertTruthy(texture.ctxTexture !== undefined, 'Invalid texture type');
277
253
 
278
254
  let { curBufferIdx: bufferIdx, curRenderOp } = this;
279
- const targetDims = {
280
- width,
281
- height,
282
- };
283
- const targetShader = shader || this.defaultShader;
284
- assertTruthy(targetShader instanceof WebGlCoreShader);
255
+ const targetDims = { width: -1, height: -1 };
256
+ targetDims.width = params.width;
257
+ targetDims.height = params.height;
258
+
259
+ const targetShader =
260
+ (params.shader as WebGlCoreShader) || this.defaultShader;
261
+ assertTruthy(
262
+ targetShader.getUniformLocation !== undefined,
263
+ 'Invalid WebGL shader',
264
+ );
285
265
 
286
- if (!this.reuseRenderOp(params)) {
266
+ if (this.reuseRenderOp(params) === false) {
287
267
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
288
268
  this.newRenderOp(
289
269
  targetShader,
290
- shaderProps as Record<string, unknown>,
291
- alpha,
270
+ params.shaderProps as Record<string, unknown>,
271
+ params.alpha,
292
272
  targetDims,
293
- clippingRect,
273
+ params.clippingRect,
294
274
  bufferIdx,
295
- renderToTexture,
296
- parentHasRenderTexture,
297
- framebufferDimensions,
275
+ params.rtt,
276
+ params.parentHasRenderTexture,
277
+ params.framebufferDimensions,
298
278
  );
299
279
  curRenderOp = this.curRenderOp;
300
280
  assertTruthy(curRenderOp);
301
281
  }
302
282
 
303
- const flipX = textureOptions?.flipX ?? false;
304
- let flipY = textureOptions?.flipY ?? false;
305
-
306
- // always flip flipY for render textures
307
- if (texture instanceof RenderTexture) {
308
- flipY = !flipY;
309
- }
310
-
311
283
  let texCoordX1 = 0;
312
284
  let texCoordY1 = 0;
313
285
  let texCoordX2 = 1;
314
286
  let texCoordY2 = 1;
315
287
 
316
- if (texture instanceof SubTexture) {
317
- const { x: tx, y: ty, width: tw, height: th } = texture.props;
318
- const { width: parentW = 0, height: parentH = 0 } = texture.parentTexture
319
- .dimensions || { width: 0, height: 0 };
288
+ if (texture.type === TextureType.subTexture) {
289
+ const {
290
+ x: tx,
291
+ y: ty,
292
+ width: tw,
293
+ height: th,
294
+ } = (texture as SubTexture).props;
295
+ const { width: parentW = 0, height: parentH = 0 } = (
296
+ texture as SubTexture
297
+ ).parentTexture.dimensions || { width: 0, height: 0 };
320
298
  texCoordX1 = tx / parentW;
321
299
  texCoordX2 = texCoordX1 + tw / parentW;
322
300
  texCoordY1 = ty / parentH;
323
301
  texCoordY2 = texCoordY1 + th / parentH;
324
- texture = texture.parentTexture;
302
+ texture = (texture as SubTexture).parentTexture;
325
303
  }
326
304
 
327
- const resizeMode = textureOptions?.resizeMode ?? false;
328
-
329
- if (texture instanceof ImageTexture) {
330
- if (resizeMode && texture.dimensions) {
331
- const { width: tw, height: th } = texture.dimensions;
332
- if (resizeMode.type === 'cover') {
333
- const scaleX = width / tw;
334
- const scaleY = height / th;
335
- const scale = Math.max(scaleX, scaleY);
336
- const precision = 1 / scale;
337
- // Determine based on width
338
- if (scale && scaleX && scaleX < scale) {
339
- const desiredSize = precision * width;
340
- texCoordX1 = (1 - desiredSize / tw) * (resizeMode.clipX ?? 0.5);
341
- texCoordX2 = texCoordX1 + desiredSize / tw;
342
- }
343
- // Determine based on height
344
- if (scale && scaleY && scaleY < scale) {
345
- const desiredSize = precision * height;
346
- texCoordY1 = (1 - desiredSize / th) * (resizeMode.clipY ?? 0.5);
347
- texCoordY2 = texCoordY1 + desiredSize / th;
348
- }
305
+ if (
306
+ texture.type === TextureType.image &&
307
+ params.textureOptions !== null &&
308
+ params.textureOptions.resizeMode !== undefined &&
309
+ texture.dimensions !== null
310
+ ) {
311
+ const resizeMode = params.textureOptions.resizeMode;
312
+ const { width: tw, height: th } = texture.dimensions;
313
+ if (resizeMode.type === 'cover') {
314
+ const scaleX = params.width / tw;
315
+ const scaleY = params.height / th;
316
+ const scale = Math.max(scaleX, scaleY);
317
+ const precision = 1 / scale;
318
+ // Determine based on width
319
+ if (scale && scaleX && scaleX < scale) {
320
+ const desiredSize = precision * params.width;
321
+ texCoordX1 = (1 - desiredSize / tw) * (resizeMode.clipX ?? 0.5);
322
+ texCoordX2 = texCoordX1 + desiredSize / tw;
323
+ }
324
+ // Determine based on height
325
+ if (scale && scaleY && scaleY < scale) {
326
+ const desiredSize = precision * params.height;
327
+ texCoordY1 = (1 - desiredSize / th) * (resizeMode.clipY ?? 0.5);
328
+ texCoordY2 = texCoordY1 + desiredSize / th;
349
329
  }
350
330
  }
351
331
  }
352
332
 
353
333
  // Flip texture coordinates if dictated by texture options
354
- if (flipX) {
355
- [texCoordX1, texCoordX2] = [texCoordX2, texCoordX1];
334
+ let flipY = 0;
335
+ if (params.textureOptions !== null) {
336
+ if (params.textureOptions.flipX === true) {
337
+ [texCoordX1, texCoordX2] = [texCoordX2, texCoordX1];
338
+ }
339
+
340
+ // convert to integer for bitwise operation below
341
+ flipY = +(params.textureOptions.flipY || false);
356
342
  }
357
- if (flipY) {
343
+
344
+ // Eitherone should be true
345
+ if (flipY ^ +(texture.type === TextureType.renderToTexture)) {
358
346
  [texCoordY1, texCoordY2] = [texCoordY2, texCoordY1];
359
347
  }
360
348
 
361
- const ctxTexture = texture.ctxTexture;
362
- assertTruthy(ctxTexture instanceof WebGlCoreCtxTexture);
349
+ const ctxTexture = texture.ctxTexture as WebGlCoreCtxTexture;
350
+ assertTruthy(ctxTexture.ctxTexture !== undefined);
363
351
  const textureIdx = this.addTexture(ctxTexture, bufferIdx);
364
352
 
365
- curRenderOp = this.curRenderOp;
366
- assertTruthy(curRenderOp);
367
- if (renderCoords) {
368
- const { x1, y1, x2, y2, x3, y3, x4, y4 } = renderCoords;
353
+ assertTruthy(this.curRenderOp !== null);
354
+ if (params.renderCoords) {
369
355
  // Upper-Left
370
- fQuadBuffer[bufferIdx++] = x1; // vertexX
371
- fQuadBuffer[bufferIdx++] = y1; // vertexY
356
+ fQuadBuffer[bufferIdx++] = params.renderCoords.x1; // vertexX
357
+ fQuadBuffer[bufferIdx++] = params.renderCoords.y1; // vertexY
372
358
  fQuadBuffer[bufferIdx++] = texCoordX1; // texCoordX
373
359
  fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
374
- uiQuadBuffer[bufferIdx++] = colorTl; // color
360
+ uiQuadBuffer[bufferIdx++] = params.colorTl; // color
375
361
  fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
376
362
 
377
363
  // Upper-Right
378
- fQuadBuffer[bufferIdx++] = x2;
379
- fQuadBuffer[bufferIdx++] = y2;
364
+ fQuadBuffer[bufferIdx++] = params.renderCoords.x2;
365
+ fQuadBuffer[bufferIdx++] = params.renderCoords.y2;
380
366
  fQuadBuffer[bufferIdx++] = texCoordX2;
381
367
  fQuadBuffer[bufferIdx++] = texCoordY1;
382
- uiQuadBuffer[bufferIdx++] = colorTr;
368
+ uiQuadBuffer[bufferIdx++] = params.colorTr;
383
369
  fQuadBuffer[bufferIdx++] = textureIdx;
384
370
 
385
371
  // Lower-Left
386
- fQuadBuffer[bufferIdx++] = x4;
387
- fQuadBuffer[bufferIdx++] = y4;
372
+ fQuadBuffer[bufferIdx++] = params.renderCoords.x4;
373
+ fQuadBuffer[bufferIdx++] = params.renderCoords.y4;
388
374
  fQuadBuffer[bufferIdx++] = texCoordX1;
389
375
  fQuadBuffer[bufferIdx++] = texCoordY2;
390
- uiQuadBuffer[bufferIdx++] = colorBl;
376
+ uiQuadBuffer[bufferIdx++] = params.colorBl;
391
377
  fQuadBuffer[bufferIdx++] = textureIdx;
392
378
 
393
379
  // Lower-Right
394
- fQuadBuffer[bufferIdx++] = x3;
395
- fQuadBuffer[bufferIdx++] = y3;
380
+ fQuadBuffer[bufferIdx++] = params.renderCoords.x3;
381
+ fQuadBuffer[bufferIdx++] = params.renderCoords.y3;
396
382
  fQuadBuffer[bufferIdx++] = texCoordX2;
397
383
  fQuadBuffer[bufferIdx++] = texCoordY2;
398
- uiQuadBuffer[bufferIdx++] = colorBr;
384
+ uiQuadBuffer[bufferIdx++] = params.colorBr;
399
385
  fQuadBuffer[bufferIdx++] = textureIdx;
400
- } else if (tb !== 0 || tc !== 0) {
386
+ } else if (params.tb !== 0 || params.tc !== 0) {
401
387
  // Upper-Left
402
- fQuadBuffer[bufferIdx++] = tx; // vertexX
403
- fQuadBuffer[bufferIdx++] = ty; // vertexY
388
+ fQuadBuffer[bufferIdx++] = params.tx; // vertexX
389
+ fQuadBuffer[bufferIdx++] = params.ty; // vertexY
404
390
  fQuadBuffer[bufferIdx++] = texCoordX1; // texCoordX
405
391
  fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
406
- uiQuadBuffer[bufferIdx++] = colorTl; // color
392
+ uiQuadBuffer[bufferIdx++] = params.colorTl; // color
407
393
  fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
408
394
 
409
395
  // Upper-Right
410
- fQuadBuffer[bufferIdx++] = tx + width * ta;
411
- fQuadBuffer[bufferIdx++] = ty + width * tc;
396
+ fQuadBuffer[bufferIdx++] = params.tx + params.width * params.ta;
397
+ fQuadBuffer[bufferIdx++] = params.ty + params.width * params.tc;
412
398
  fQuadBuffer[bufferIdx++] = texCoordX2;
413
399
  fQuadBuffer[bufferIdx++] = texCoordY1;
414
- uiQuadBuffer[bufferIdx++] = colorTr;
400
+ uiQuadBuffer[bufferIdx++] = params.colorTr;
415
401
  fQuadBuffer[bufferIdx++] = textureIdx;
416
402
 
417
403
  // Lower-Left
418
- fQuadBuffer[bufferIdx++] = tx + height * tb;
419
- fQuadBuffer[bufferIdx++] = ty + height * td;
404
+ fQuadBuffer[bufferIdx++] = params.tx + params.height * params.tb;
405
+ fQuadBuffer[bufferIdx++] = params.ty + params.height * params.td;
420
406
  fQuadBuffer[bufferIdx++] = texCoordX1;
421
407
  fQuadBuffer[bufferIdx++] = texCoordY2;
422
- uiQuadBuffer[bufferIdx++] = colorBl;
408
+ uiQuadBuffer[bufferIdx++] = params.colorBl;
423
409
  fQuadBuffer[bufferIdx++] = textureIdx;
424
410
 
425
411
  // Lower-Right
426
- fQuadBuffer[bufferIdx++] = tx + width * ta + height * tb;
427
- fQuadBuffer[bufferIdx++] = ty + width * tc + height * td;
412
+ fQuadBuffer[bufferIdx++] =
413
+ params.tx + params.width * params.ta + params.height * params.tb;
414
+ fQuadBuffer[bufferIdx++] =
415
+ params.ty + params.width * params.tc + params.height * params.td;
428
416
  fQuadBuffer[bufferIdx++] = texCoordX2;
429
417
  fQuadBuffer[bufferIdx++] = texCoordY2;
430
- uiQuadBuffer[bufferIdx++] = colorBr;
418
+ uiQuadBuffer[bufferIdx++] = params.colorBr;
431
419
  fQuadBuffer[bufferIdx++] = textureIdx;
432
420
  } else {
433
421
  // Calculate the right corner of the quad
434
422
  // multiplied by the scale
435
- const rightCornerX = tx + width * ta;
436
- const rightCornerY = ty + height * td;
423
+ const rightCornerX = params.tx + params.width * params.ta;
424
+ const rightCornerY = params.ty + params.height * params.td;
437
425
 
438
426
  // Upper-Left
439
- fQuadBuffer[bufferIdx++] = tx; // vertexX
440
- fQuadBuffer[bufferIdx++] = ty; // vertexY
427
+ fQuadBuffer[bufferIdx++] = params.tx; // vertexX
428
+ fQuadBuffer[bufferIdx++] = params.ty; // vertexY
441
429
  fQuadBuffer[bufferIdx++] = texCoordX1; // texCoordX
442
430
  fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
443
- uiQuadBuffer[bufferIdx++] = colorTl; // color
431
+ uiQuadBuffer[bufferIdx++] = params.colorTl; // color
444
432
  fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
445
433
 
446
434
  // Upper-Right
447
435
  fQuadBuffer[bufferIdx++] = rightCornerX;
448
- fQuadBuffer[bufferIdx++] = ty;
436
+ fQuadBuffer[bufferIdx++] = params.ty;
449
437
  fQuadBuffer[bufferIdx++] = texCoordX2;
450
438
  fQuadBuffer[bufferIdx++] = texCoordY1;
451
- uiQuadBuffer[bufferIdx++] = colorTr;
439
+ uiQuadBuffer[bufferIdx++] = params.colorTr;
452
440
  fQuadBuffer[bufferIdx++] = textureIdx;
453
441
 
454
442
  // Lower-Left
455
- fQuadBuffer[bufferIdx++] = tx;
443
+ fQuadBuffer[bufferIdx++] = params.tx;
456
444
  fQuadBuffer[bufferIdx++] = rightCornerY;
457
445
  fQuadBuffer[bufferIdx++] = texCoordX1;
458
446
  fQuadBuffer[bufferIdx++] = texCoordY2;
459
- uiQuadBuffer[bufferIdx++] = colorBl;
447
+ uiQuadBuffer[bufferIdx++] = params.colorBl;
460
448
  fQuadBuffer[bufferIdx++] = textureIdx;
461
449
 
462
450
  // Lower-Right
@@ -464,12 +452,12 @@ export class WebGlCoreRenderer extends CoreRenderer {
464
452
  fQuadBuffer[bufferIdx++] = rightCornerY;
465
453
  fQuadBuffer[bufferIdx++] = texCoordX2;
466
454
  fQuadBuffer[bufferIdx++] = texCoordY2;
467
- uiQuadBuffer[bufferIdx++] = colorBr;
455
+ uiQuadBuffer[bufferIdx++] = params.colorBr;
468
456
  fQuadBuffer[bufferIdx++] = textureIdx;
469
457
  }
470
458
  // Update the length of the current render op
471
- curRenderOp.length += WORDS_PER_QUAD;
472
- curRenderOp.numQuads++;
459
+ this.curRenderOp.length += WORDS_PER_QUAD;
460
+ this.curRenderOp.numQuads++;
473
461
  this.curBufferIdx = bufferIdx;
474
462
  }
475
463
 
@@ -536,14 +524,12 @@ export class WebGlCoreRenderer extends CoreRenderer {
536
524
  throw new Error('Unable to add texture to render op');
537
525
  }
538
526
 
539
- const { shader, shaderProps, dimensions, clippingRect, alpha } =
540
- curRenderOp;
541
527
  this.newRenderOp(
542
- shader,
543
- shaderProps,
544
- alpha,
545
- dimensions,
546
- clippingRect,
528
+ curRenderOp.shader,
529
+ curRenderOp.shaderProps,
530
+ curRenderOp.alpha,
531
+ curRenderOp.dimensions,
532
+ curRenderOp.clippingRect,
547
533
  bufferIdx,
548
534
  );
549
535
  return this.addTexture(texture, bufferIdx, true);
@@ -556,7 +542,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
556
542
  * @param params
557
543
  * @returns
558
544
  */
559
- reuseRenderOp(params: QuadOptions) {
545
+ reuseRenderOp(params: QuadOptions): boolean {
560
546
  const { shader, shaderProps, parentHasRenderTexture, rtt, clippingRect } =
561
547
  params;
562
548
 
@@ -22,6 +22,7 @@ import {
22
22
  type DefaultEffectProps,
23
23
  ShaderEffect,
24
24
  type ShaderEffectUniforms,
25
+ type ShaderEffectValueMap,
25
26
  } from './ShaderEffect.js';
26
27
 
27
28
  /**
@@ -54,6 +55,12 @@ export class LinearGradientEffect extends ShaderEffect {
54
55
  override readonly name = 'linearGradient';
55
56
 
56
57
  static override getEffectKey(props: LinearGradientEffectProps): string {
58
+ if ((props.colors as unknown as ShaderEffectValueMap).value as number[]) {
59
+ return `linearGradient${
60
+ ((props.colors as unknown as ShaderEffectValueMap).value as number[])
61
+ .length
62
+ }`;
63
+ }
57
64
  return `linearGradient${props.colors!.length}`;
58
65
  }
59
66
 
@@ -25,6 +25,7 @@ import {
25
25
  type DefaultEffectProps,
26
26
  ShaderEffect,
27
27
  type ShaderEffectUniforms,
28
+ type ShaderEffectValueMap,
28
29
  } from './ShaderEffect.js';
29
30
 
30
31
  /**
@@ -62,7 +63,13 @@ export class RadialGradientEffect extends ShaderEffect {
62
63
  override readonly name = 'radialGradient';
63
64
 
64
65
  static override getEffectKey(props: RadialGradientEffectProps): string {
65
- return `radialGradient${props.colors!.length}`;
66
+ if ((props.colors as unknown as ShaderEffectValueMap).value as number[]) {
67
+ return `linearGradient${
68
+ ((props.colors as unknown as ShaderEffectValueMap).value as number[])
69
+ .length
70
+ }`;
71
+ }
72
+ return `linearGradient${props.colors!.length}`;
66
73
  }
67
74
 
68
75
  static override resolveDefaults(
@@ -46,6 +46,7 @@ function resolveFontToUse(
46
46
 
47
47
  for (const fontFamiles of familyMapsByPriority) {
48
48
  const fontFaces = fontFamiles[family];
49
+
49
50
  if (!fontFaces) {
50
51
  continue;
51
52
  }
@@ -157,9 +158,10 @@ export class TrFontManager {
157
158
  public resolveFontFace(
158
159
  familyMapsByPriority: FontFamilyMap[],
159
160
  props: TrFontProps,
161
+ rendererType: 'canvas' | 'sdf',
160
162
  ): TrFontFace | undefined {
161
163
  const { fontFamily, fontWeight, fontStyle, fontStretch } = props;
162
- const fontCacheString = `${fontFamily}${fontStyle}${fontWeight}${fontStretch}`;
164
+ const fontCacheString = `${rendererType}_${fontFamily}_${fontStyle}_${fontWeight}_${fontStretch}`;
163
165
 
164
166
  if (this.fontCache.has(fontCacheString) === true) {
165
167
  return this.fontCache.get(fontCacheString);
@@ -154,7 +154,6 @@ export class TrFontFace extends EventEmitter {
154
154
  lineGap: metrics.lineGap / metrics.unitsPerEm,
155
155
  };
156
156
  }
157
-
158
157
  this.fontFamily = fontFamily;
159
158
  this.descriptors = {
160
159
  style: 'normal',
@@ -242,24 +242,22 @@ export class CanvasTextRenderer extends TextRenderer<CanvasTextRendererState> {
242
242
  // the `isFontFaceSupported` check)
243
243
  assertTruthy(fontFace instanceof WebTrFontFace);
244
244
 
245
+ const fontFamily = fontFace.fontFamily;
246
+
245
247
  // Add the font face to the document
246
248
  // Except for the 'sans-serif' font family, which the Renderer provides
247
249
  // as a special default fallback.
248
- if (fontFace.fontFamily !== 'sans-serif') {
250
+ if (fontFamily !== 'sans-serif') {
249
251
  // @ts-expect-error `add()` method should be available from a FontFaceSet
250
252
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
251
253
  globalFontSet.add(fontFace.fontFace);
252
254
  }
253
255
 
254
- const { fontFamilies } = this;
255
- const familyName = fontFace.fontFace.family;
256
-
257
- let faceSet = fontFamilies[familyName];
256
+ let faceSet = this.fontFamilies[fontFamily];
258
257
  if (!faceSet) {
259
258
  faceSet = new Set();
260
- fontFamilies[familyName] = faceSet;
259
+ this.fontFamilies[fontFamily] = faceSet;
261
260
  }
262
-
263
261
  faceSet.add(fontFace);
264
262
  }
265
263
 
@@ -384,9 +382,11 @@ export class CanvasTextRenderer extends TextRenderer<CanvasTextRendererState> {
384
382
 
385
383
  loadFont = (state: CanvasTextRendererState): void => {
386
384
  const cssString = getFontCssString(state.props);
385
+
387
386
  const trFontFace = this.stage.fontManager.resolveFontFace(
388
387
  this.fontFamilyArray,
389
388
  state.props,
389
+ 'canvas',
390
390
  ) as WebTrFontFace | undefined;
391
391
  assertTruthy(trFontFace, `Could not resolve font face for ${cssString}`);
392
392
  state.fontInfo = {
@@ -22,7 +22,10 @@
22
22
  import { assertTruthy } from '../../../utils.js';
23
23
  import { getRgbaString, type RGBA } from '../../lib/utils.js';
24
24
  import { calcDefaultLineHeight } from '../TextRenderingUtils.js';
25
- import { getWebFontMetrics } from '../TextTextureRendererUtils.js';
25
+ import {
26
+ getWebFontMetrics,
27
+ isZeroWidthSpace,
28
+ } from '../TextTextureRendererUtils.js';
26
29
  import type { NormalizedFontMetrics } from '../font-face-types/TrFontFace.js';
27
30
  import type { WebTrFontFace } from '../font-face-types/WebTrFontFace.js';
28
31
 
@@ -682,38 +685,43 @@ export class LightningTextTextureRenderer {
682
685
  letterSpacing: number,
683
686
  indent = 0,
684
687
  ) {
685
- // Greedy wrapping algorithm that will wrap words as the line grows longer.
686
- // than its horizontal bounds.
688
+ const spaceRegex = / |\u200B/g; // ZWSP and spaces
687
689
  const lines = text.split(/\r?\n/g);
688
690
  let allLines: string[] = [];
689
- const realNewlines = [];
691
+ const realNewlines: number[] = [];
692
+
690
693
  for (let i = 0; i < lines.length; i++) {
691
- const resultLines = [];
694
+ const resultLines: string[] = [];
692
695
  let result = '';
693
696
  let spaceLeft = wordWrapWidth - indent;
694
- const words = lines[i]!.split(' ');
697
+
698
+ // Split the line into words, considering ZWSP
699
+ const words = lines[i]!.split(spaceRegex);
700
+ const spaces = lines[i]!.match(spaceRegex) || [];
701
+
695
702
  for (let j = 0; j < words.length; j++) {
696
- const wordWidth = this.measureText(words[j]!, letterSpacing);
697
- const wordWidthWithSpace =
698
- wordWidth + this.measureText(' ', letterSpacing);
703
+ const space = spaces[j - 1] || '';
704
+ const word = words[j]!;
705
+ const wordWidth = this.measureText(word, letterSpacing);
706
+ const wordWidthWithSpace = isZeroWidthSpace(space)
707
+ ? wordWidth
708
+ : wordWidth + this.measureText(space, letterSpacing);
709
+
699
710
  if (j === 0 || wordWidthWithSpace > spaceLeft) {
700
- // Skip printing the newline if it's the first word of the line that is.
701
- // greater than the word wrap width.
702
711
  if (j > 0) {
703
712
  resultLines.push(result);
704
713
  result = '';
705
714
  }
706
- result += words[j];
715
+ result += word;
707
716
  spaceLeft = wordWrapWidth - wordWidth - (j === 0 ? indent : 0);
708
717
  } else {
709
718
  spaceLeft -= wordWidthWithSpace;
710
- result += ` ${words[j]!}`;
719
+ result += space + word;
711
720
  }
712
721
  }
713
722
 
714
723
  resultLines.push(result);
715
724
  result = '';
716
-
717
725
  allLines = allLines.concat(resultLines);
718
726
 
719
727
  if (i < lines.length - 1) {
@@ -728,7 +736,13 @@ export class LightningTextTextureRenderer {
728
736
  if (!space) {
729
737
  return this._context.measureText(word).width;
730
738
  }
739
+
740
+ // Split word into characters, but skip ZWSP in the width calculation
731
741
  return word.split('').reduce((acc, char) => {
742
+ // Check if the character is a zero-width space and skip it
743
+ if (isZeroWidthSpace(char)) {
744
+ return acc;
745
+ }
732
746
  return acc + this._context.measureText(char).width + space;
733
747
  }, 0);
734
748
  }
@@ -396,10 +396,10 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
396
396
  }
397
397
 
398
398
  // Resolve font face if we haven't yet
399
- if (!trFontFace) {
399
+ if (trFontFace === undefined) {
400
400
  trFontFace = this.resolveFontFace(state.props);
401
401
  state.trFontFace = trFontFace;
402
- if (!trFontFace) {
402
+ if (trFontFace === undefined) {
403
403
  const msg = `SdfTextRenderer: Could not resolve font face for family: '${state.props.fontFamily}'`;
404
404
  console.error(msg);
405
405
  this.setStatus(state, 'failed', new Error(msg));
@@ -410,7 +410,7 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
410
410
 
411
411
  // If the font hasn't been loaded yet, stop here.
412
412
  // Listen for the 'loaded' event and forward fontLoaded event
413
- if (!trFontFace.loaded) {
413
+ if (trFontFace.loaded === false) {
414
414
  trFontFace.once('loaded', () => {
415
415
  this.scheduleUpdateState(state);
416
416
  });
@@ -791,9 +791,11 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
791
791
  //#endregion Overrides
792
792
 
793
793
  public resolveFontFace(props: TrFontProps): SdfTrFontFace | undefined {
794
- return this.stage.fontManager.resolveFontFace(this.fontFamilyArray, props) as
795
- | SdfTrFontFace
796
- | undefined;
794
+ return this.stage.fontManager.resolveFontFace(
795
+ this.fontFamilyArray,
796
+ props,
797
+ 'sdf',
798
+ ) as SdfTrFontFace | undefined;
797
799
  }
798
800
 
799
801
  /**
@@ -192,7 +192,11 @@ export function layoutText(
192
192
 
193
193
  // If we encounter a word boundary (white space or newline) we invalidate
194
194
  // the lastWord and set the xStartLastWordBoundary if we haven't already.
195
- if (glyph.codepoint === 32 || glyph.codepoint === 10) {
195
+ if (
196
+ glyph.codepoint === 32 ||
197
+ glyph.codepoint === 10 ||
198
+ glyph.codepoint === 8203
199
+ ) {
196
200
  if (lastWord.codepointIndex !== -1) {
197
201
  lastWord.codepointIndex = -1;
198
202
  xStartLastWordBoundary = curX;
@@ -43,7 +43,8 @@ export function measureText(
43
43
  );
44
44
  let width = 0;
45
45
  for (const glyph of glyphs) {
46
- if (glyph.mapped) {
46
+ if (glyph.mapped && glyph.codepoint !== 8203) {
47
+ // Skip ZWSP (\u200B)
47
48
  width += glyph.xAdvance;
48
49
  }
49
50
  }