@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.
- package/dist/src/core/CoreNode.d.ts +3 -2
- package/dist/src/core/CoreNode.js +14 -8
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.d.ts +2 -0
- package/dist/src/core/CoreTextNode.js +8 -0
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +2 -0
- package/dist/src/core/CoreTextureManager.js +7 -5
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.d.ts +5 -0
- package/dist/src/core/Stage.js +10 -5
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/lib/validateImageBitmap.d.ts +2 -1
- package/dist/src/core/lib/validateImageBitmap.js +4 -4
- package/dist/src/core/lib/validateImageBitmap.js.map +1 -1
- package/dist/src/core/platforms/Platform.d.ts +37 -0
- package/dist/src/core/platforms/Platform.js +22 -0
- package/dist/src/core/platforms/Platform.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatform.d.ts +9 -0
- package/dist/src/core/platforms/web/WebPlatform.js +58 -0
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
- package/dist/src/core/renderers/CoreRenderer.d.ts +3 -1
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +3 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +86 -60
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +5 -0
- package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -1
- package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +50 -2
- package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +6 -2
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +1 -1
- 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/TextRenderer.d.ts +13 -0
- package/dist/src/core/text-rendering/renderers/TextRenderer.js +3 -0
- package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
- package/dist/src/core/textures/ImageTexture.d.ts +1 -0
- package/dist/src/core/textures/ImageTexture.js +5 -3
- package/dist/src/core/textures/ImageTexture.js.map +1 -1
- package/dist/src/core/textures/Texture.d.ts +9 -2
- package/dist/src/core/textures/Texture.js +18 -6
- package/dist/src/core/textures/Texture.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +12 -0
- package/dist/src/main-api/Renderer.js +14 -2
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/CoreNode.ts +18 -10
- package/src/core/CoreTextNode.ts +10 -0
- package/src/core/CoreTextureManager.ts +9 -5
- package/src/core/Stage.ts +20 -4
- package/src/core/lib/validateImageBitmap.ts +17 -6
- package/src/core/platforms/Platform.ts +77 -0
- package/src/core/platforms/web/WebPlatform.ts +84 -0
- package/src/core/renderers/CoreRenderer.ts +3 -1
- package/src/core/renderers/canvas/CanvasRenderer.ts +1 -1
- package/src/core/renderers/webgl/WebGlRenderer.ts +105 -75
- package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +5 -0
- package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +51 -3
- package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +6 -0
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +96 -7
- package/src/core/text-rendering/renderers/TextRenderer.ts +17 -0
- package/src/core/textures/ImageTexture.ts +19 -8
- package/src/core/textures/Texture.ts +28 -7
- 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
|
}
|
|
@@ -35,7 +35,11 @@ import {
|
|
|
35
35
|
type WebGlColor,
|
|
36
36
|
} from './internal/RendererUtils.js';
|
|
37
37
|
import { WebGlCtxTexture } from './WebGlCtxTexture.js';
|
|
38
|
-
import {
|
|
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
|
-
|
|
284
|
-
|
|
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++] =
|
|
338
|
-
fQuadBuffer[bufferIdx++] =
|
|
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++] =
|
|
348
|
-
fQuadBuffer[bufferIdx++] =
|
|
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++] =
|
|
358
|
-
fQuadBuffer[bufferIdx++] =
|
|
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++] =
|
|
368
|
-
fQuadBuffer[bufferIdx++] =
|
|
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:
|
|
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 (
|
|
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:
|
|
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
|
|