@lightningjs/renderer 3.0.0-beta3 → 3.0.0-beta5

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 (69) hide show
  1. package/dist/src/core/CoreNode.d.ts +3 -2
  2. package/dist/src/core/CoreNode.js +14 -8
  3. package/dist/src/core/CoreNode.js.map +1 -1
  4. package/dist/src/core/CoreTextNode.d.ts +2 -0
  5. package/dist/src/core/CoreTextNode.js +8 -0
  6. package/dist/src/core/CoreTextNode.js.map +1 -1
  7. package/dist/src/core/CoreTextureManager.d.ts +2 -0
  8. package/dist/src/core/CoreTextureManager.js +7 -5
  9. package/dist/src/core/CoreTextureManager.js.map +1 -1
  10. package/dist/src/core/Stage.d.ts +5 -0
  11. package/dist/src/core/Stage.js +10 -5
  12. package/dist/src/core/Stage.js.map +1 -1
  13. package/dist/src/core/lib/validateImageBitmap.d.ts +2 -1
  14. package/dist/src/core/lib/validateImageBitmap.js +4 -4
  15. package/dist/src/core/lib/validateImageBitmap.js.map +1 -1
  16. package/dist/src/core/platforms/Platform.d.ts +37 -0
  17. package/dist/src/core/platforms/Platform.js +22 -0
  18. package/dist/src/core/platforms/Platform.js.map +1 -0
  19. package/dist/src/core/platforms/web/WebPlatform.d.ts +9 -0
  20. package/dist/src/core/platforms/web/WebPlatform.js +58 -0
  21. package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
  22. package/dist/src/core/renderers/CoreRenderer.d.ts +3 -1
  23. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  24. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  25. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +3 -1
  26. package/dist/src/core/renderers/webgl/WebGlRenderer.js +86 -60
  27. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  28. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +5 -0
  29. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  30. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -1
  31. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +50 -2
  32. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  33. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +6 -2
  34. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  35. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +1 -1
  36. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +66 -8
  37. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  38. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +13 -0
  39. package/dist/src/core/text-rendering/renderers/TextRenderer.js +3 -0
  40. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  41. package/dist/src/core/textures/ImageTexture.d.ts +1 -0
  42. package/dist/src/core/textures/ImageTexture.js +5 -3
  43. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  44. package/dist/src/core/textures/Texture.d.ts +9 -2
  45. package/dist/src/core/textures/Texture.js +18 -6
  46. package/dist/src/core/textures/Texture.js.map +1 -1
  47. package/dist/src/main-api/Renderer.d.ts +12 -0
  48. package/dist/src/main-api/Renderer.js +14 -2
  49. package/dist/src/main-api/Renderer.js.map +1 -1
  50. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  51. package/package.json +1 -1
  52. package/src/core/CoreNode.ts +18 -10
  53. package/src/core/CoreTextNode.ts +10 -0
  54. package/src/core/CoreTextureManager.ts +9 -5
  55. package/src/core/Stage.ts +20 -4
  56. package/src/core/lib/validateImageBitmap.ts +17 -6
  57. package/src/core/platforms/Platform.ts +77 -0
  58. package/src/core/platforms/web/WebPlatform.ts +84 -0
  59. package/src/core/renderers/CoreRenderer.ts +3 -1
  60. package/src/core/renderers/canvas/CanvasRenderer.ts +1 -1
  61. package/src/core/renderers/webgl/WebGlRenderer.ts +105 -75
  62. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +5 -0
  63. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +51 -3
  64. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +6 -0
  65. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +96 -7
  66. package/src/core/text-rendering/renderers/TextRenderer.ts +17 -0
  67. package/src/core/textures/ImageTexture.ts +19 -8
  68. package/src/core/textures/Texture.ts +28 -7
  69. package/src/main-api/Renderer.ts +28 -2
@@ -0,0 +1,77 @@
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ import { type Stage } from '../Stage.js';
21
+
22
+ export abstract class Platform {
23
+ /**
24
+ * Creates a new canvas element.
25
+ * @returns The created HTMLCanvasElement.
26
+ */
27
+ abstract createCanvas(): HTMLCanvasElement;
28
+
29
+ /**
30
+ * Get a DOM element by ID
31
+ * @returns The DOM element (or null)
32
+ */
33
+ abstract getElementById(id: string): HTMLElement | null;
34
+
35
+ /**
36
+ * Starts the main rendering loop, calling the provided update function every frame.
37
+ * @param Stage - The stage for rendering
38
+ */
39
+ abstract startLoop(stage: Stage): void;
40
+
41
+ /**
42
+ * Abstracted createImageBitmap method.
43
+ * @param blob - The image source to create the ImageBitmap from.
44
+ * @param sxOrOptions - The source rectangle x coordinate or ImageBitmapOptions.
45
+ * @param sy - The source rectangle y coordinate.
46
+ * @param sw - The source rectangle width.
47
+ * @param sh - The source rectangle height.
48
+ * @param options - The ImageBitmapOptions.
49
+ * @returns A promise that resolves with the created ImageBitmap.
50
+ */
51
+ abstract createImageBitmap(blob: ImageBitmapSource): Promise<ImageBitmap>;
52
+ abstract createImageBitmap(
53
+ blob: ImageBitmapSource,
54
+ options: ImageBitmapOptions,
55
+ ): Promise<ImageBitmap>;
56
+ abstract createImageBitmap(
57
+ blob: ImageBitmapSource,
58
+ sx: number,
59
+ sy: number,
60
+ sw: number,
61
+ sh: number,
62
+ ): Promise<ImageBitmap>;
63
+ abstract createImageBitmap(
64
+ blob: ImageBitmapSource,
65
+ sx: number,
66
+ sy: number,
67
+ sw: number,
68
+ sh: number,
69
+ options: ImageBitmapOptions,
70
+ ): Promise<ImageBitmap>;
71
+
72
+ /**
73
+ * Retrieves the current timestamp.
74
+ * @returns The current timestamp.
75
+ */
76
+ abstract getTimeStamp(): number;
77
+ }
@@ -0,0 +1,84 @@
1
+ import { Platform } from '../Platform.js';
2
+ import type { Stage } from '../../Stage.js';
3
+
4
+ export class WebPlatform extends Platform {
5
+ ////////////////////////
6
+ // Platform-specific methods
7
+ ////////////////////////
8
+
9
+ override createCanvas(): HTMLCanvasElement {
10
+ const canvas = document.createElement('canvas');
11
+ return canvas;
12
+ }
13
+
14
+ override getElementById(id: string): HTMLElement | null {
15
+ return document.getElementById(id);
16
+ }
17
+
18
+ ////////////////////////
19
+ // Update loop
20
+ ////////////////////////
21
+
22
+ override startLoop(stage: Stage): void {
23
+ let isIdle = false;
24
+ const runLoop = () => {
25
+ stage.updateFrameTime();
26
+ stage.updateAnimations();
27
+
28
+ if (!stage.hasSceneUpdates()) {
29
+ // We still need to calculate the fps else it looks like the app is frozen
30
+ stage.calculateFps();
31
+ setTimeout(runLoop, 16.666666666666668);
32
+
33
+ if (!isIdle) {
34
+ stage.shManager.cleanup();
35
+ stage.eventBus.emit('idle');
36
+ isIdle = true;
37
+ }
38
+
39
+ if (stage.txMemManager.checkCleanup() === true) {
40
+ stage.txMemManager.cleanup(false);
41
+ }
42
+
43
+ stage.flushFrameEvents();
44
+ return;
45
+ }
46
+
47
+ isIdle = false;
48
+ stage.drawFrame();
49
+ stage.flushFrameEvents();
50
+ requestAnimationFrame(runLoop);
51
+ };
52
+ requestAnimationFrame(runLoop);
53
+ }
54
+
55
+ ////////////////////////
56
+ // ImageBitmap
57
+ ////////////////////////
58
+
59
+ override createImageBitmap(
60
+ blob: ImageBitmapSource,
61
+ sxOrOptions?: number | ImageBitmapOptions,
62
+ sy?: number,
63
+ sw?: number,
64
+ sh?: number,
65
+ options?: ImageBitmapOptions,
66
+ ): Promise<ImageBitmap> {
67
+ if (typeof sxOrOptions === 'number') {
68
+ return createImageBitmap(
69
+ blob,
70
+ sxOrOptions,
71
+ sy ?? 0,
72
+ sw ?? 0,
73
+ sh ?? 0,
74
+ options,
75
+ );
76
+ } else {
77
+ return createImageBitmap(blob, sxOrOptions);
78
+ }
79
+ }
80
+
81
+ getTimeStamp(): number {
82
+ return performance ? performance.now() : Date.now();
83
+ }
84
+ }
@@ -25,7 +25,7 @@ import type { ContextSpy } from '../lib/ContextSpy.js';
25
25
  import type { RenderCoords } from '../lib/RenderCoords.js';
26
26
  import type { RectWithValid } from '../lib/utils.js';
27
27
  import type { CoreShaderProgram } from './CoreShaderProgram.js';
28
- import type { Texture } from '../textures/Texture.js';
28
+ import type { Texture, TextureCoords } from '../textures/Texture.js';
29
29
  import { CoreContextTexture } from './CoreContextTexture.js';
30
30
  import type { CoreShaderType, CoreShaderNode } from './CoreShaderNode.js';
31
31
 
@@ -38,6 +38,7 @@ export interface QuadOptions {
38
38
  colorBr: number;
39
39
  texture: Texture | null;
40
40
  textureOptions: TextureOptions | null;
41
+ textureCoords: TextureCoords | undefined;
41
42
  zIndex: number;
42
43
  shader: CoreShaderNode | null;
43
44
  alpha: number;
@@ -104,4 +105,5 @@ export abstract class CoreRenderer {
104
105
  abstract getBufferInfo(): BufferInfo | null;
105
106
  abstract getQuadCount(): number | null;
106
107
  abstract updateClearColor(color: number): void;
108
+ getTextureCoords?(node: CoreNode): TextureCoords;
107
109
  }
@@ -292,7 +292,7 @@ export class CanvasRenderer extends CoreRenderer {
292
292
  this.clearColor = this.getParsedColor(color);
293
293
  }
294
294
 
295
- override getDefaultShaderNode() {
295
+ getDefaultShaderNode() {
296
296
  return null;
297
297
  }
298
298
  }
@@ -35,7 +35,11 @@ import {
35
35
  type WebGlColor,
36
36
  } from './internal/RendererUtils.js';
37
37
  import { WebGlCtxTexture } from './WebGlCtxTexture.js';
38
- import { Texture, TextureType } from '../../textures/Texture.js';
38
+ import {
39
+ Texture,
40
+ TextureType,
41
+ type TextureCoords,
42
+ } from '../../textures/Texture.js';
39
43
  import { SubTexture } from '../../textures/SubTexture.js';
40
44
  import { WebGlCtxSubTexture } from './WebGlCtxSubTexture.js';
41
45
  import { BufferCollection } from './internal/BufferCollection.js';
@@ -48,7 +52,6 @@ import { WebGlCtxRenderTexture } from './WebGlCtxRenderTexture.js';
48
52
  import { Default } from '../../shaders/webgl/Default.js';
49
53
  import type { WebGlShaderType } from './WebGlShaderNode.js';
50
54
  import { WebGlShaderNode } from './WebGlShaderNode.js';
51
- import type { CoreShaderType } from '../CoreShaderNode.js';
52
55
 
53
56
  const WORDS_PER_QUAD = 32;
54
57
  // const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
@@ -77,6 +80,13 @@ export class WebGlRenderer extends CoreRenderer {
77
80
  override rttNodes: CoreNode[] = [];
78
81
  activeRttNode: CoreNode | null = null;
79
82
 
83
+ defaultTextureCoords: TextureCoords = {
84
+ x1: 0,
85
+ y1: 0,
86
+ x2: 1,
87
+ y2: 1,
88
+ };
89
+
80
90
  //// Default Shader
81
91
  defaultShaderNode: WebGlShaderNode | null = null;
82
92
  quadBufferCollection: BufferCollection;
@@ -258,84 +268,22 @@ export class WebGlRenderer extends CoreRenderer {
258
268
  this.newRenderOp(params, bufferIdx);
259
269
  }
260
270
 
261
- let texCoordX1 = 0;
262
- let texCoordY1 = 0;
263
- let texCoordX2 = 1;
264
- let texCoordY2 = 1;
265
-
266
271
  if (texture.type === TextureType.subTexture) {
267
- const {
268
- x: tx,
269
- y: ty,
270
- width: tw,
271
- height: th,
272
- } = (texture as SubTexture).props;
273
- const { width: parentW = 0, height: parentH = 0 } = (
274
- texture as SubTexture
275
- ).parentTexture.dimensions || { width: 0, height: 0 };
276
- texCoordX1 = tx / parentW;
277
- texCoordX2 = texCoordX1 + tw / parentW;
278
- texCoordY1 = ty / parentH;
279
- texCoordY2 = texCoordY1 + th / parentH;
280
272
  texture = (texture as SubTexture).parentTexture;
281
273
  }
282
274
 
283
- if (
284
- texture.type === TextureType.image &&
285
- params.textureOptions !== null &&
286
- params.textureOptions.resizeMode !== undefined &&
287
- texture.dimensions !== null
288
- ) {
289
- const resizeMode = params.textureOptions.resizeMode;
290
- const { width: tw, height: th } = texture.dimensions;
291
- if (resizeMode.type === 'cover') {
292
- const scaleX = params.width / tw;
293
- const scaleY = params.height / th;
294
- const scale = Math.max(scaleX, scaleY);
295
- const precision = 1 / scale;
296
- // Determine based on width
297
- if (scale && scaleX && scaleX < scale) {
298
- const desiredSize = precision * params.width;
299
- texCoordX1 = (1 - desiredSize / tw) * (resizeMode.clipX ?? 0.5);
300
- texCoordX2 = texCoordX1 + desiredSize / tw;
301
- }
302
- // Determine based on height
303
- if (scale && scaleY && scaleY < scale) {
304
- const desiredSize = precision * params.height;
305
- texCoordY1 = (1 - desiredSize / th) * (resizeMode.clipY ?? 0.5);
306
- texCoordY2 = texCoordY1 + desiredSize / th;
307
- }
308
- }
309
- }
310
-
311
- // Flip texture coordinates if dictated by texture options
312
- let flipY = 0;
313
- if (params.textureOptions !== null) {
314
- if (params.textureOptions.flipX === true) {
315
- [texCoordX1, texCoordX2] = [texCoordX2, texCoordX1];
316
- }
317
-
318
- // convert to integer for bitwise operation below
319
- flipY = +(params.textureOptions.flipY || false);
320
- }
321
-
322
- // Eitherone should be true
323
- if (flipY ^ +(texture.type === TextureType.renderToTexture)) {
324
- [texCoordY1, texCoordY2] = [texCoordY2, texCoordY1];
325
- }
326
-
327
- const ctxTexture = texture.ctxTexture as WebGlCtxTexture;
328
- assertTruthy(ctxTexture instanceof WebGlCtxTexture);
329
- const textureIdx = this.addTexture(ctxTexture, bufferIdx);
275
+ assertTruthy(texture.ctxTexture instanceof WebGlCtxTexture);
276
+ const textureIdx = this.addTexture(texture.ctxTexture, bufferIdx);
330
277
 
331
278
  assertTruthy(this.curRenderOp !== null);
332
279
  assertTruthy(params.renderCoords);
280
+ assertTruthy(params.textureCoords);
333
281
 
334
282
  // Upper-Left
335
283
  fQuadBuffer[bufferIdx++] = params.renderCoords.x1; // vertexX
336
284
  fQuadBuffer[bufferIdx++] = params.renderCoords.y1; // vertexY
337
- fQuadBuffer[bufferIdx++] = texCoordX1; // texCoordX
338
- fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
285
+ fQuadBuffer[bufferIdx++] = params.textureCoords.x1; // texCoordX
286
+ fQuadBuffer[bufferIdx++] = params.textureCoords.y1; // texCoordY
339
287
  uiQuadBuffer[bufferIdx++] = params.colorTl; // color
340
288
  fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
341
289
  fQuadBuffer[bufferIdx++] = 0; //node X coord
@@ -344,8 +292,8 @@ export class WebGlRenderer extends CoreRenderer {
344
292
  // Upper-Right
345
293
  fQuadBuffer[bufferIdx++] = params.renderCoords.x2;
346
294
  fQuadBuffer[bufferIdx++] = params.renderCoords.y2;
347
- fQuadBuffer[bufferIdx++] = texCoordX2;
348
- fQuadBuffer[bufferIdx++] = texCoordY1;
295
+ fQuadBuffer[bufferIdx++] = params.textureCoords.x2;
296
+ fQuadBuffer[bufferIdx++] = params.textureCoords.y1;
349
297
  uiQuadBuffer[bufferIdx++] = params.colorTr;
350
298
  fQuadBuffer[bufferIdx++] = textureIdx;
351
299
  fQuadBuffer[bufferIdx++] = 1; //node X coord
@@ -354,8 +302,8 @@ export class WebGlRenderer extends CoreRenderer {
354
302
  // Lower-Left
355
303
  fQuadBuffer[bufferIdx++] = params.renderCoords.x4;
356
304
  fQuadBuffer[bufferIdx++] = params.renderCoords.y4;
357
- fQuadBuffer[bufferIdx++] = texCoordX1;
358
- fQuadBuffer[bufferIdx++] = texCoordY2;
305
+ fQuadBuffer[bufferIdx++] = params.textureCoords.x1;
306
+ fQuadBuffer[bufferIdx++] = params.textureCoords.y2;
359
307
  uiQuadBuffer[bufferIdx++] = params.colorBl;
360
308
  fQuadBuffer[bufferIdx++] = textureIdx;
361
309
  fQuadBuffer[bufferIdx++] = 0; //node X coord
@@ -364,8 +312,8 @@ export class WebGlRenderer extends CoreRenderer {
364
312
  // Lower-Right
365
313
  fQuadBuffer[bufferIdx++] = params.renderCoords.x3;
366
314
  fQuadBuffer[bufferIdx++] = params.renderCoords.y3;
367
- fQuadBuffer[bufferIdx++] = texCoordX2;
368
- fQuadBuffer[bufferIdx++] = texCoordY2;
315
+ fQuadBuffer[bufferIdx++] = params.textureCoords.x2;
316
+ fQuadBuffer[bufferIdx++] = params.textureCoords.y2;
369
317
  uiQuadBuffer[bufferIdx++] = params.colorBr;
370
318
  fQuadBuffer[bufferIdx++] = textureIdx;
371
319
  fQuadBuffer[bufferIdx++] = 1; //node X coord
@@ -694,6 +642,88 @@ export class WebGlRenderer extends CoreRenderer {
694
642
  return this.defaultShaderNode;
695
643
  }
696
644
 
645
+ override getTextureCoords(node: CoreNode): TextureCoords {
646
+ const texture = node.texture;
647
+ if (texture === null) {
648
+ return this.defaultTextureCoords;
649
+ }
650
+
651
+ const textureOptions = node.textureOptions;
652
+ if (
653
+ texture.type === TextureType.subTexture ||
654
+ texture.type === TextureType.image ||
655
+ texture.type === TextureType.renderToTexture ||
656
+ textureOptions !== null
657
+ ) {
658
+ const result = {
659
+ x1: 0,
660
+ y1: 0,
661
+ x2: 1,
662
+ y2: 1,
663
+ };
664
+
665
+ if (texture.type === TextureType.subTexture) {
666
+ const props = (texture as SubTexture).props;
667
+ const { width: parentW = 0, height: parentH = 0 } = (
668
+ texture as SubTexture
669
+ ).parentTexture.dimensions || { width: 0, height: 0 };
670
+ result.x1 = props.x / parentW;
671
+ result.x2 = result.x1 + props.width / parentW;
672
+ result.y1 = props.y / parentH;
673
+ result.y2 = result.y1 + props.height / parentH;
674
+ }
675
+
676
+ if (
677
+ texture.type === TextureType.image &&
678
+ textureOptions !== null &&
679
+ textureOptions.resizeMode !== undefined &&
680
+ texture.dimensions !== null
681
+ ) {
682
+ const resizeMode = textureOptions.resizeMode;
683
+ const dimensions = texture.dimensions;
684
+ if (resizeMode.type === 'cover') {
685
+ const scaleX = node.props.width / dimensions.width;
686
+ const scaleY = node.props.height / dimensions.height;
687
+ const scale = Math.max(scaleX, scaleY);
688
+ const precision = 1 / scale;
689
+ // Determine based on width
690
+ if (scaleX < scale) {
691
+ const desiredSize = precision * node.props.width;
692
+ result.x1 =
693
+ (1 - desiredSize / dimensions.width) * (resizeMode.clipX ?? 0.5);
694
+ result.x2 = result.x1 + desiredSize / dimensions.width;
695
+ }
696
+ // Determine based on height
697
+ if (scaleY < scale) {
698
+ const desiredSize = precision * node.props.height;
699
+ result.y1 =
700
+ (1 - desiredSize / dimensions.height) * (resizeMode.clipY ?? 0.5);
701
+ result.y2 = result.y1 + desiredSize / dimensions.height;
702
+ }
703
+ }
704
+ }
705
+
706
+ // Flip texture coordinates if dictated by texture options
707
+ let flipY = 0;
708
+ if (textureOptions !== null) {
709
+ if (textureOptions.flipX === true) {
710
+ [result.x1, result.x2] = [result.x2, result.x1];
711
+ }
712
+
713
+ // convert to integer for bitwise operation below
714
+ flipY = +(textureOptions.flipY || false);
715
+ }
716
+
717
+ // Eitherone should be true
718
+ if (flipY ^ +(texture.type === TextureType.renderToTexture)) {
719
+ [result.y1, result.y2] = [result.y2, result.y1];
720
+ }
721
+ return result as TextureCoords;
722
+ }
723
+
724
+ return this.defaultTextureCoords;
725
+ }
726
+
697
727
  /**
698
728
  * Updates the WebGL context's clear color and clears the color buffer.
699
729
  *
@@ -217,6 +217,10 @@ export class CanvasTextRenderer extends TextRenderer<CanvasTextRendererState> {
217
217
  state.props.verticalAlign = value;
218
218
  this.invalidateLayoutCache(state);
219
219
  },
220
+ wordBreak: (state, value) => {
221
+ state.props.wordBreak = value;
222
+ this.invalidateLayoutCache(state);
223
+ },
220
224
  overflowSuffix: (state, value) => {
221
225
  state.props.overflowSuffix = value;
222
226
  this.invalidateLayoutCache(state);
@@ -435,6 +439,7 @@ export class CanvasTextRenderer extends TextRenderer<CanvasTextRendererState> {
435
439
  textBaseline: state.props.textBaseline,
436
440
  verticalAlign: state.props.verticalAlign,
437
441
  overflowSuffix: state.props.overflowSuffix,
442
+ wordBreak: state.props.wordBreak,
438
443
  w: state.props.contain !== 'none' ? state.props.width : undefined,
439
444
  };
440
445
  state.renderInfo = state.lightning2TextRenderer.calculateRenderInfo();
@@ -74,7 +74,7 @@ export interface Settings {
74
74
  trFontFace: WebTrFontFace | null;
75
75
  wordWrap: boolean;
76
76
  wordWrapWidth: number;
77
- wordBreak: boolean;
77
+ wordBreak: 'normal' | 'break-all' | 'break-word';
78
78
  textOverflow: TextOverflow | null;
79
79
  lineHeight: number | null;
80
80
  textBaseline: TextBaseline;
@@ -305,6 +305,7 @@ export class LightningTextTextureRenderer {
305
305
  }
306
306
 
307
307
  // Text overflow
308
+ // TODO Probably never used
308
309
  if (this._settings.textOverflow && !this._settings.wordWrap) {
309
310
  let suffix;
310
311
  switch (this._settings.textOverflow) {
@@ -724,7 +725,54 @@ export class LightningTextTextureRenderer {
724
725
  ? wordWidth
725
726
  : wordWidth + this.measureText(space, letterSpacing);
726
727
 
727
- if (j === 0 || wordWidthWithSpace > spaceLeft) {
728
+ if (
729
+ this._settings.wordBreak === 'break-all' &&
730
+ wordWidthWithSpace > spaceLeft
731
+ ) {
732
+ const letters = word.split('');
733
+ for (let k = 0; k < letters.length; k++) {
734
+ const letter = letters[k]!;
735
+ const letterWidthWithSpace =
736
+ k > 0
737
+ ? this.measureText(letter, letterSpacing)
738
+ : this.measureText(space + letter, letterSpacing);
739
+
740
+ if (letterWidthWithSpace > spaceLeft) {
741
+ resultLines.push(result);
742
+ result = letter;
743
+ spaceLeft = wordWrapWidth - letterWidthWithSpace;
744
+ } else {
745
+ spaceLeft -= letterWidthWithSpace;
746
+ result += k > 0 ? letter : space + letter;
747
+ }
748
+ }
749
+ } else if (
750
+ this._settings.wordBreak === 'break-word' &&
751
+ wordWidthWithSpace > spaceLeft
752
+ ) {
753
+ if (wordWidth < wordWrapWidth) {
754
+ resultLines.push(result);
755
+ result = word;
756
+ spaceLeft = wordWrapWidth - wordWidth - (j === 0 ? indent : 0);
757
+ } else {
758
+ if (result.length > 0) resultLines.push(result);
759
+ result = '';
760
+ spaceLeft = wordWrapWidth - indent;
761
+ const letters = word.split('');
762
+ for (let k = 0; k < letters.length; k++) {
763
+ const letter = letters[k]!;
764
+ const letterWidth = this.measureText(letter, letterSpacing);
765
+ if (letterWidth > spaceLeft) {
766
+ resultLines.push(result);
767
+ result = '';
768
+ spaceLeft = wordWrapWidth - indent;
769
+ } else {
770
+ result += letter;
771
+ spaceLeft -= letterWidth;
772
+ }
773
+ }
774
+ }
775
+ } else if (j === 0 || wordWidthWithSpace > spaceLeft) {
728
776
  if (j > 0) {
729
777
  resultLines.push(result);
730
778
  result = '';
@@ -775,7 +823,7 @@ export class LightningTextTextureRenderer {
775
823
  trFontFace: null,
776
824
  wordWrap: true,
777
825
  wordWrapWidth: 0,
778
- wordBreak: false,
826
+ wordBreak: 'normal',
779
827
  textOverflow: '',
780
828
  lineHeight: null,
781
829
  textBaseline: 'alphabetic',
@@ -281,6 +281,10 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
281
281
  state.props.overflowSuffix = value;
282
282
  this.invalidateLayoutCache(state);
283
283
  },
284
+ wordBreak: (state, value) => {
285
+ state.props.wordBreak = value;
286
+ this.invalidateLayoutCache(state);
287
+ },
284
288
  debug: (state, value) => {
285
289
  state.props.debug = value;
286
290
  },
@@ -435,6 +439,7 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
435
439
  verticalAlign,
436
440
  scrollable,
437
441
  overflowSuffix,
442
+ wordBreak,
438
443
  maxLines,
439
444
  } = state.props;
440
445
 
@@ -573,6 +578,7 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
573
578
  forceFullLayoutCalc,
574
579
  scrollable,
575
580
  overflowSuffix,
581
+ wordBreak,
576
582
  maxLines,
577
583
  );
578
584