@lightningjs/renderer 3.0.0-beta21 → 3.0.0-beta23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -0
- package/dist/exports/index.d.ts +1 -0
- package/dist/exports/index.js +1 -0
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/platform.d.ts +7 -0
- package/dist/exports/platform.js +27 -0
- package/dist/exports/platform.js.map +1 -0
- package/dist/src/common/CommonTypes.d.ts +2 -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.js +10 -14
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +0 -13
- package/dist/src/core/CoreTextureManager.js +4 -78
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.js +2 -12
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/animations/CoreAnimationController.d.ts +1 -1
- package/dist/src/core/animations/CoreAnimationController.js +4 -2
- package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
- package/dist/src/core/lib/collectionUtils.js +3 -2
- package/dist/src/core/lib/collectionUtils.js.map +1 -1
- package/dist/src/core/lib/utils.d.ts +0 -5
- package/dist/src/core/lib/utils.js +0 -63
- package/dist/src/core/lib/utils.js.map +1 -1
- package/dist/src/core/platforms/GlContextWrapper.d.ts +136 -0
- package/dist/src/core/platforms/GlContextWrapper.js +32 -0
- package/dist/src/core/platforms/GlContextWrapper.js.map +1 -0
- package/dist/src/core/platforms/Platform.d.ts +74 -13
- package/dist/src/core/platforms/Platform.js +18 -0
- package/dist/src/core/platforms/Platform.js.map +1 -1
- package/dist/src/core/platforms/web/WebGlContextWrapper.d.ts +776 -0
- package/dist/src/core/platforms/web/WebGlContextWrapper.js +1208 -0
- package/dist/src/core/platforms/web/WebGlContextWrapper.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatform.d.ts +13 -2
- package/dist/src/core/platforms/web/WebPlatform.js +109 -8
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
- package/dist/src/core/platforms/web/WebPlatformChrome50.d.ts +17 -0
- package/dist/src/core/platforms/web/WebPlatformChrome50.js +50 -0
- package/dist/src/core/platforms/web/WebPlatformChrome50.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.d.ts +18 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.js +99 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatformNext.d.ts +21 -0
- package/dist/src/core/platforms/web/WebPlatformNext.js +52 -0
- package/dist/src/core/platforms/web/WebPlatformNext.js.map +1 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.d.ts +15 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.js +189 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.js.map +1 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.d.ts +1 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.js +27 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.js.map +1 -0
- package/dist/src/core/platforms/web/lib/textureCompression.d.ts +26 -0
- package/dist/src/core/platforms/web/lib/textureCompression.js +301 -0
- package/dist/src/core/platforms/web/lib/textureCompression.js.map +1 -0
- package/dist/src/core/platforms/web/lib/textureSvg.d.ts +7 -0
- package/dist/src/core/platforms/web/lib/textureSvg.js +51 -0
- package/dist/src/core/platforms/web/lib/textureSvg.js.map +1 -0
- package/dist/src/core/platforms/web/lib/utils.d.ts +5 -0
- package/dist/src/core/platforms/web/lib/utils.js +86 -0
- package/dist/src/core/platforms/web/lib/utils.js.map +1 -0
- package/dist/src/core/renderers/CoreRenderer.d.ts +1 -9
- package/dist/src/core/renderers/CoreRenderer.js +2 -4
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +3 -2
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +4 -3
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +3 -2
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +3 -3
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +1 -2
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +3 -2
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js +3 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +5 -5
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +7 -8
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +4 -4
- package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +3 -3
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
- package/dist/src/core/shaders/webgl/Border.js +13 -17
- package/dist/src/core/shaders/webgl/Border.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +12 -21
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +10 -12
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/text-rendering/CanvasFont.d.ts +14 -0
- package/dist/src/core/text-rendering/CanvasFont.js +111 -0
- package/dist/src/core/text-rendering/CanvasFont.js.map +1 -0
- package/dist/src/core/text-rendering/CoreFont.d.ts +33 -0
- package/dist/src/core/text-rendering/CoreFont.js +48 -0
- package/dist/src/core/text-rendering/CoreFont.js.map +1 -0
- package/dist/src/core/text-rendering/FontManager.d.ts +11 -0
- package/dist/src/core/text-rendering/FontManager.js +42 -0
- package/dist/src/core/text-rendering/FontManager.js.map +1 -0
- package/dist/src/core/text-rendering/SdfFont.d.ts +29 -0
- package/dist/src/core/text-rendering/SdfFont.js +142 -0
- package/dist/src/core/text-rendering/SdfFont.js.map +1 -0
- package/dist/src/core/textures/ImageTexture.d.ts +24 -11
- package/dist/src/core/textures/ImageTexture.js +32 -95
- package/dist/src/core/textures/ImageTexture.js.map +1 -1
- package/dist/src/core/textures/Texture.d.ts +5 -4
- package/dist/src/core/textures/Texture.js.map +1 -1
- package/dist/src/core/utils.d.ts +1 -1
- package/dist/src/main-api/Inspector.d.ts +4 -0
- package/dist/src/main-api/Inspector.js +160 -0
- package/dist/src/main-api/Inspector.js.map +1 -1
- package/dist/src/main-api/Renderer.js +18 -21
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/src/utils.d.ts +0 -2
- package/dist/src/utils.js +0 -36
- package/dist/src/utils.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/exports/index.ts +5 -0
- package/exports/platform.ts +31 -0
- package/package.json +3 -2
- package/src/common/CommonTypes.ts +2 -1
- package/src/core/CoreNode.ts +11 -15
- package/src/core/CoreTextureManager.ts +10 -103
- package/src/core/Stage.ts +1 -14
- package/src/core/animations/CoreAnimationController.ts +5 -2
- package/src/core/lib/collectionUtils.ts +3 -2
- package/src/core/lib/utils.ts +0 -78
- package/src/core/platforms/GlContextWrapper.ts +291 -0
- package/src/core/platforms/Platform.ts +121 -28
- package/src/core/{lib → platforms/web}/WebGlContextWrapper.ts +129 -4
- package/src/core/platforms/web/WebPlatform.ts +171 -22
- package/src/core/platforms/web/WebPlatformChrome50.ts +57 -0
- package/src/core/platforms/web/WebPlatformLegacy.ts +140 -0
- package/src/core/platforms/web/WebPlatformNext.ts +57 -0
- package/src/core/{lib → platforms/web/lib}/ImageWorker.ts +10 -74
- package/src/core/platforms/web/lib/createImageBitmap.ts +40 -0
- package/src/core/{lib → platforms/web/lib}/textureCompression.ts +19 -138
- package/src/core/{lib → platforms/web/lib}/textureSvg.ts +3 -15
- package/src/core/platforms/web/lib/utils.ts +105 -0
- package/src/core/renderers/CoreRenderer.ts +2 -11
- package/src/core/renderers/canvas/CanvasRenderer.ts +6 -4
- package/src/core/renderers/webgl/SdfRenderOp.ts +3 -2
- package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +2 -2
- package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +2 -2
- package/src/core/renderers/webgl/WebGlCtxTexture.ts +3 -4
- package/src/core/renderers/webgl/WebGlRenderer.ts +12 -19
- package/src/core/renderers/webgl/WebGlShaderNode.ts +2 -2
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +2 -2
- package/src/core/renderers/webgl/internal/RendererUtils.ts +4 -8
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +3 -3
- package/src/core/shaders/webgl/Border.ts +13 -17
- package/src/core/shaders/webgl/RoundedWithBorder.ts +12 -21
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +10 -12
- package/src/core/textures/ImageTexture.ts +42 -161
- package/src/core/textures/Texture.ts +11 -7
- package/src/main-api/Inspector.ts +215 -0
- package/src/main-api/Renderer.ts +24 -22
- package/src/utils.ts +0 -47
- package/src/core/lib/validateImageBitmap.ts +0 -87
|
@@ -1,14 +1,34 @@
|
|
|
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 2026 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
|
+
|
|
1
20
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
2
21
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
22
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
4
23
|
|
|
5
|
-
import { assertTruthy, isProductionEnvironment } from '../../utils.js';
|
|
6
24
|
import type {
|
|
7
25
|
Vec2,
|
|
8
26
|
Vec3,
|
|
9
27
|
Vec4,
|
|
10
|
-
} from '
|
|
11
|
-
import { isWebGl2 } from '
|
|
28
|
+
} from '../../renderers/webgl/internal/ShaderUtils.js';
|
|
29
|
+
import { isWebGl2 } from '../../renderers/webgl/internal/WebGlUtils.js';
|
|
30
|
+
import { GlContextWrapper } from '../GlContextWrapper.js';
|
|
31
|
+
import type { CompressedData } from '../../textures/Texture.js';
|
|
12
32
|
|
|
13
33
|
/**
|
|
14
34
|
* Optimized WebGL Context Wrapper
|
|
@@ -29,7 +49,7 @@ import { isWebGl2 } from '../renderers/webgl/internal/WebGlUtils.js';
|
|
|
29
49
|
* A subset of GLenum constants are also exposed as properties on this class
|
|
30
50
|
* for convenience.
|
|
31
51
|
*/
|
|
32
|
-
export class WebGlContextWrapper {
|
|
52
|
+
export class WebGlContextWrapper extends GlContextWrapper {
|
|
33
53
|
//#region Cached WebGL State
|
|
34
54
|
private activeTextureUnit = 0;
|
|
35
55
|
private texture2dUnits: Array<WebGLTexture | null>;
|
|
@@ -97,6 +117,7 @@ export class WebGlContextWrapper {
|
|
|
97
117
|
//#endregion WebGL Enums
|
|
98
118
|
|
|
99
119
|
constructor(private gl: WebGLRenderingContext | WebGL2RenderingContext) {
|
|
120
|
+
super();
|
|
100
121
|
// The following code extracts the current state of the WebGL context
|
|
101
122
|
// to our local JavaScript cached version of it. This is so we can
|
|
102
123
|
// avoid making WebGL calls if we don't need to.
|
|
@@ -1367,6 +1388,110 @@ export class WebGlContextWrapper {
|
|
|
1367
1388
|
}
|
|
1368
1389
|
return null;
|
|
1369
1390
|
}
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
*
|
|
1394
|
+
* Compressed Textures support
|
|
1395
|
+
*/
|
|
1396
|
+
uploadKTX(texture: WebGLTexture, data: CompressedData) {
|
|
1397
|
+
const { glInternalFormat, mipmaps, w: width, h: height, blockInfo } = data;
|
|
1398
|
+
if (mipmaps === undefined) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
this.bindTexture(texture);
|
|
1403
|
+
|
|
1404
|
+
const blockWidth = blockInfo.width;
|
|
1405
|
+
const blockHeight = blockInfo.height;
|
|
1406
|
+
let w = width;
|
|
1407
|
+
let h = height;
|
|
1408
|
+
|
|
1409
|
+
for (let i = 0; i < mipmaps!.length; i++) {
|
|
1410
|
+
let view = new Uint8Array(mipmaps![i]!);
|
|
1411
|
+
|
|
1412
|
+
const uploadW = Math.ceil(w / blockWidth) * blockWidth;
|
|
1413
|
+
const uploadH = Math.ceil(h / blockHeight) * blockHeight;
|
|
1414
|
+
|
|
1415
|
+
const expectedBytes =
|
|
1416
|
+
Math.ceil(w / blockWidth) *
|
|
1417
|
+
Math.ceil(h / blockHeight) *
|
|
1418
|
+
blockInfo.bytes;
|
|
1419
|
+
|
|
1420
|
+
if (view.byteLength < expectedBytes) {
|
|
1421
|
+
const padded = new Uint8Array(expectedBytes);
|
|
1422
|
+
padded.set(view);
|
|
1423
|
+
view = padded;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
this.compressedTexImage2D(i, glInternalFormat, uploadW, uploadH, 0, view);
|
|
1427
|
+
|
|
1428
|
+
w = Math.max(1, w >> 1);
|
|
1429
|
+
h = Math.max(1, h >> 1);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
this.texParameteri(this.TEXTURE_WRAP_S, this.CLAMP_TO_EDGE);
|
|
1433
|
+
this.texParameteri(this.TEXTURE_WRAP_T, this.CLAMP_TO_EDGE);
|
|
1434
|
+
this.texParameteri(this.TEXTURE_MAG_FILTER, this.LINEAR);
|
|
1435
|
+
this.texParameteri(
|
|
1436
|
+
this.TEXTURE_MIN_FILTER,
|
|
1437
|
+
mipmaps!.length > 1 ? this.LINEAR_MIPMAP_LINEAR : this.LINEAR,
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
uploadPVR(texture: WebGLTexture, data: CompressedData) {
|
|
1442
|
+
const { glInternalFormat, mipmaps, w: width, h: height } = data;
|
|
1443
|
+
if (mipmaps === undefined) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
this.bindTexture(texture);
|
|
1447
|
+
|
|
1448
|
+
let w = width;
|
|
1449
|
+
let h = height;
|
|
1450
|
+
|
|
1451
|
+
for (let i = 0; i < mipmaps!.length; i++) {
|
|
1452
|
+
this.compressedTexImage2D(
|
|
1453
|
+
i,
|
|
1454
|
+
glInternalFormat,
|
|
1455
|
+
w,
|
|
1456
|
+
h,
|
|
1457
|
+
0,
|
|
1458
|
+
new Uint8Array(mipmaps[i]!),
|
|
1459
|
+
);
|
|
1460
|
+
|
|
1461
|
+
w = Math.max(1, w >> 1);
|
|
1462
|
+
h = Math.max(1, h >> 1);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
this.texParameteri(this.TEXTURE_WRAP_S, this.CLAMP_TO_EDGE);
|
|
1466
|
+
this.texParameteri(this.TEXTURE_WRAP_T, this.CLAMP_TO_EDGE);
|
|
1467
|
+
this.texParameteri(this.TEXTURE_MAG_FILTER, this.LINEAR);
|
|
1468
|
+
this.texParameteri(
|
|
1469
|
+
this.TEXTURE_MIN_FILTER,
|
|
1470
|
+
mipmaps.length > 1 ? this.LINEAR_MIPMAP_LINEAR : this.LINEAR,
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
uploadASTC(texture: WebGLTexture, data: CompressedData) {
|
|
1475
|
+
if (this.getExtension('WEBGL_compressed_texture_astc') === null) {
|
|
1476
|
+
throw new Error('ASTC compressed textures not supported by this device');
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
this.bindTexture(texture);
|
|
1480
|
+
|
|
1481
|
+
const { glInternalFormat, mipmaps, w, h } = data;
|
|
1482
|
+
if (mipmaps === undefined) {
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
const view = new Uint8Array(mipmaps[0]!);
|
|
1487
|
+
|
|
1488
|
+
this.compressedTexImage2D(0, glInternalFormat, w, h, 0, view);
|
|
1489
|
+
// ASTC textures MUST use no mipmaps unless stored
|
|
1490
|
+
this.texParameteri(this.TEXTURE_WRAP_S, this.CLAMP_TO_EDGE);
|
|
1491
|
+
this.texParameteri(this.TEXTURE_WRAP_T, this.CLAMP_TO_EDGE);
|
|
1492
|
+
this.texParameteri(this.TEXTURE_MAG_FILTER, this.LINEAR);
|
|
1493
|
+
this.texParameteri(this.TEXTURE_MIN_FILTER, this.LINEAR);
|
|
1494
|
+
}
|
|
1370
1495
|
}
|
|
1371
1496
|
|
|
1372
1497
|
// prettier-ignore
|
|
@@ -1,5 +1,37 @@
|
|
|
1
|
-
|
|
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 2026 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 { Platform, type PlatformSettings } from '../Platform.js';
|
|
21
|
+
import { ImageWorkerManager } from './lib/ImageWorker.js';
|
|
2
22
|
import type { Stage } from '../../Stage.js';
|
|
23
|
+
import {
|
|
24
|
+
dataURIToBlob,
|
|
25
|
+
isBase64Image,
|
|
26
|
+
convertUrlToAbsolute,
|
|
27
|
+
createWebGLContext,
|
|
28
|
+
} from './lib/utils.js';
|
|
29
|
+
|
|
30
|
+
import type { ImageResponse } from '../../textures/ImageTexture.js';
|
|
31
|
+
import { loadSvg } from './lib/textureSvg.js';
|
|
32
|
+
import { loadCompressedTexture } from './lib/textureCompression.js';
|
|
33
|
+
import { WebGlContextWrapper } from './WebGlContextWrapper.js';
|
|
34
|
+
import type { GlContextWrapper } from '../GlContextWrapper.js';
|
|
3
35
|
|
|
4
36
|
/**
|
|
5
37
|
* make fontface add not show errors
|
|
@@ -9,13 +41,33 @@ interface FontFaceSetWithAdd extends FontFaceSet {
|
|
|
9
41
|
}
|
|
10
42
|
|
|
11
43
|
export class WebPlatform extends Platform {
|
|
44
|
+
private useImageWorker: boolean;
|
|
45
|
+
private imageWorkerManager: ImageWorkerManager | null = null;
|
|
46
|
+
private hasWorker = !!self.Worker;
|
|
47
|
+
|
|
48
|
+
constructor(settings: PlatformSettings = {}) {
|
|
49
|
+
super(settings);
|
|
50
|
+
|
|
51
|
+
const numImageWorkers = settings.numImageWorkers ?? 0;
|
|
52
|
+
this.useImageWorker = numImageWorkers > 0 && this.hasWorker;
|
|
53
|
+
|
|
54
|
+
if (this.useImageWorker === true) {
|
|
55
|
+
this.imageWorkerManager = new ImageWorkerManager(numImageWorkers);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
12
59
|
////////////////////////
|
|
13
60
|
// Platform-specific methods
|
|
14
61
|
////////////////////////
|
|
15
62
|
|
|
16
63
|
override createCanvas(): HTMLCanvasElement {
|
|
17
|
-
|
|
18
|
-
|
|
64
|
+
return document.createElement('canvas');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override createContext(): GlContextWrapper {
|
|
68
|
+
const gl = createWebGLContext(this.canvas!, this.settings.forceWebGL2);
|
|
69
|
+
this.glw = new WebGlContextWrapper(gl);
|
|
70
|
+
return this.glw;
|
|
19
71
|
}
|
|
20
72
|
|
|
21
73
|
override getElementById(id: string): HTMLElement | null {
|
|
@@ -76,7 +128,11 @@ export class WebPlatform extends Platform {
|
|
|
76
128
|
return;
|
|
77
129
|
}
|
|
78
130
|
|
|
79
|
-
isIdle
|
|
131
|
+
if (isIdle === true) {
|
|
132
|
+
stage.eventBus.emit('active');
|
|
133
|
+
isIdle = false;
|
|
134
|
+
}
|
|
135
|
+
|
|
80
136
|
stage.drawFrame();
|
|
81
137
|
stage.flushFrameEvents();
|
|
82
138
|
|
|
@@ -97,31 +153,124 @@ export class WebPlatform extends Platform {
|
|
|
97
153
|
}
|
|
98
154
|
|
|
99
155
|
////////////////////////
|
|
100
|
-
//
|
|
156
|
+
// Image handling
|
|
101
157
|
////////////////////////
|
|
102
158
|
|
|
103
|
-
override
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
159
|
+
override fetch(url: string): Promise<Blob> {
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
const xhr = new XMLHttpRequest();
|
|
162
|
+
xhr.responseType = '';
|
|
163
|
+
xhr.onreadystatechange = function () {
|
|
164
|
+
if (xhr.readyState == XMLHttpRequest.DONE) {
|
|
165
|
+
// On most devices like WebOS and Tizen, the file protocol returns 0 while http(s) protocol returns 200
|
|
166
|
+
if (xhr.status === 0 || xhr.status === 200) {
|
|
167
|
+
resolve(xhr.response);
|
|
168
|
+
} else {
|
|
169
|
+
reject(xhr.statusText);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
xhr.open('GET', url, true);
|
|
174
|
+
xhr.send(null);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override async createImage(
|
|
179
|
+
blob: Blob,
|
|
180
|
+
premultiplyAlpha: boolean | null,
|
|
181
|
+
sx: number | null,
|
|
182
|
+
sy: number | null,
|
|
183
|
+
sw: number | null,
|
|
184
|
+
sh: number | null,
|
|
185
|
+
): Promise<ImageResponse> {
|
|
186
|
+
const hasAlphaChannel = premultiplyAlpha ?? blob.type.includes('image/png');
|
|
187
|
+
|
|
188
|
+
if (sw !== null && sh !== null) {
|
|
189
|
+
// createImageBitmap with crop
|
|
190
|
+
const bitmap = await createImageBitmap(blob, sx || 0, sy || 0, sw, sh, {
|
|
191
|
+
premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
|
|
192
|
+
colorSpaceConversion: 'none',
|
|
193
|
+
imageOrientation: 'none',
|
|
194
|
+
});
|
|
195
|
+
return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// default createImageBitmap without crop but with options
|
|
199
|
+
const bitmap = await createImageBitmap(blob, {
|
|
200
|
+
premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
|
|
201
|
+
colorSpaceConversion: 'none',
|
|
202
|
+
imageOrientation: 'none',
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
override async loadImage(
|
|
209
|
+
src: string,
|
|
210
|
+
premultiplyAlpha: boolean | null,
|
|
211
|
+
sx?: number | null,
|
|
212
|
+
sy?: number | null,
|
|
213
|
+
sw?: number | null,
|
|
214
|
+
sh?: number | null,
|
|
215
|
+
): Promise<ImageResponse> {
|
|
216
|
+
const isBase64 = isBase64Image(src);
|
|
217
|
+
const absoluteSrc = convertUrlToAbsolute(src);
|
|
218
|
+
const x = sx ?? null;
|
|
219
|
+
const y = sy ?? null;
|
|
220
|
+
const width = sw ?? null;
|
|
221
|
+
const height = sh ?? null;
|
|
222
|
+
|
|
223
|
+
// check if image worker is enabled
|
|
224
|
+
if (this.imageWorkerManager !== null && isBase64 === false) {
|
|
225
|
+
return this.imageWorkerManager.getImage(
|
|
226
|
+
absoluteSrc,
|
|
227
|
+
premultiplyAlpha,
|
|
228
|
+
x,
|
|
229
|
+
y,
|
|
230
|
+
width,
|
|
231
|
+
height,
|
|
119
232
|
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// fallback to main thread loading
|
|
236
|
+
let blob: Blob;
|
|
237
|
+
if (isBase64Image(src) === true) {
|
|
238
|
+
blob = dataURIToBlob(src);
|
|
120
239
|
} else {
|
|
121
|
-
|
|
240
|
+
blob = await this.fetch(absoluteSrc);
|
|
122
241
|
}
|
|
242
|
+
|
|
243
|
+
return this.createImage(blob, premultiplyAlpha, x, y, width, height);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
override async loadSvg(
|
|
247
|
+
src: string,
|
|
248
|
+
width: number | null,
|
|
249
|
+
height: number | null,
|
|
250
|
+
sx?: number | null,
|
|
251
|
+
sy?: number | null,
|
|
252
|
+
sw?: number | null,
|
|
253
|
+
sh?: number | null,
|
|
254
|
+
): Promise<ImageResponse> {
|
|
255
|
+
return loadSvg(
|
|
256
|
+
convertUrlToAbsolute(src),
|
|
257
|
+
width,
|
|
258
|
+
height,
|
|
259
|
+
sx ?? null,
|
|
260
|
+
sy ?? null,
|
|
261
|
+
sw ?? null,
|
|
262
|
+
sh ?? null,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
override async loadCompressedTexture(src: string): Promise<ImageResponse> {
|
|
267
|
+
return loadCompressedTexture(convertUrlToAbsolute(src));
|
|
123
268
|
}
|
|
124
269
|
|
|
270
|
+
////////////////////////
|
|
271
|
+
// Utilities
|
|
272
|
+
////////////////////////
|
|
273
|
+
|
|
125
274
|
getTimeStamp(): number {
|
|
126
275
|
return performance ? performance.now() : Date.now();
|
|
127
276
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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 2026 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 { WebPlatform } from './WebPlatform.js';
|
|
21
|
+
import type { ImageResponse } from '../../textures/ImageTexture.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Chrome 50 Web Platform implementation with limited createImageBitmap support
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* This platform is designed for Chrome 50 and similar browsers that support
|
|
28
|
+
* createImageBitmap but with a limited signature (no options or cropping parameters).
|
|
29
|
+
*
|
|
30
|
+
* Limitations:
|
|
31
|
+
* - createImageBitmap is called without options (premultiplyAlpha, colorSpaceConversion, imageOrientation)
|
|
32
|
+
* - Image cropping (sx, sy, sw, sh parameters) is not supported
|
|
33
|
+
* - Image workers can still be used if enabled via settings
|
|
34
|
+
*/
|
|
35
|
+
export class WebPlatformChrome50 extends WebPlatform {
|
|
36
|
+
override async createImage(
|
|
37
|
+
blob: Blob,
|
|
38
|
+
premultiplyAlpha: boolean | null,
|
|
39
|
+
// Cropping parameters are not supported in Chrome 50
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41
|
+
sx: number | null,
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
43
|
+
sy: number | null,
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
45
|
+
sw: number | null,
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
47
|
+
sh: number | null,
|
|
48
|
+
): Promise<ImageResponse> {
|
|
49
|
+
const hasAlphaChannel = premultiplyAlpha ?? blob.type.includes('image/png');
|
|
50
|
+
|
|
51
|
+
// Chrome 50 createImageBitmap signature: createImageBitmap(blob)
|
|
52
|
+
// No options or cropping parameters supported
|
|
53
|
+
const bitmap = await createImageBitmap(blob);
|
|
54
|
+
|
|
55
|
+
return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
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 2026 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 { WebPlatform } from './WebPlatform.js';
|
|
21
|
+
import type { PlatformSettings } from '../Platform.js';
|
|
22
|
+
import type { ImageResponse } from '../../textures/ImageTexture.js';
|
|
23
|
+
import {
|
|
24
|
+
isBase64Image,
|
|
25
|
+
dataURIToBlob,
|
|
26
|
+
convertUrlToAbsolute,
|
|
27
|
+
} from './lib/utils.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Legacy Web Platform implementation that uses Image() instead of createImageBitmap
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* This platform is designed for environments that don't support createImageBitmap API,
|
|
34
|
+
* or for compatibility with older browsers. It uses the traditional HTMLImageElement
|
|
35
|
+
* approach for image loading.
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
export class WebPlatformLegacy extends WebPlatform {
|
|
39
|
+
constructor(settings: PlatformSettings = {}) {
|
|
40
|
+
// Force image workers to be disabled in legacy mode
|
|
41
|
+
super({ ...settings, numImageWorkers: 0 });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override async loadImage(
|
|
45
|
+
src: string,
|
|
46
|
+
premultiplyAlpha: boolean | null,
|
|
47
|
+
sx?: number | null,
|
|
48
|
+
sy?: number | null,
|
|
49
|
+
sw?: number | null,
|
|
50
|
+
sh?: number | null,
|
|
51
|
+
): Promise<ImageResponse> {
|
|
52
|
+
const isBase64 = isBase64Image(src);
|
|
53
|
+
const absoluteSrc = convertUrlToAbsolute(src);
|
|
54
|
+
|
|
55
|
+
// For base64 images, use blob conversion
|
|
56
|
+
if (isBase64 === true) {
|
|
57
|
+
const blob = dataURIToBlob(src);
|
|
58
|
+
return this.createImage(
|
|
59
|
+
blob,
|
|
60
|
+
premultiplyAlpha,
|
|
61
|
+
sx ?? null,
|
|
62
|
+
sy ?? null,
|
|
63
|
+
sw ?? null,
|
|
64
|
+
sh ?? null,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// For regular URLs, load directly without blob conversion
|
|
69
|
+
const hasAlpha =
|
|
70
|
+
premultiplyAlpha ?? absoluteSrc.toLowerCase().endsWith('.png');
|
|
71
|
+
const img = new Image();
|
|
72
|
+
img.crossOrigin = 'anonymous';
|
|
73
|
+
|
|
74
|
+
return new Promise<ImageResponse>((resolve, reject) => {
|
|
75
|
+
img.onload = () => {
|
|
76
|
+
resolve({ data: img, premultiplyAlpha: hasAlpha });
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
img.onerror = (err) => {
|
|
80
|
+
const errorMessage =
|
|
81
|
+
err instanceof Error
|
|
82
|
+
? err.message
|
|
83
|
+
: err instanceof Event
|
|
84
|
+
? `Image loading failed for ${img.src}`
|
|
85
|
+
: 'Unknown image loading error';
|
|
86
|
+
reject(new Error(`Image loading failed: ${errorMessage}`));
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
img.src = absoluteSrc;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override async createImage(
|
|
94
|
+
blob: Blob,
|
|
95
|
+
premultiplyAlpha: boolean | null,
|
|
96
|
+
// Cropping parameters are not supported in legacy mode
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
98
|
+
sx: number | null,
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
100
|
+
sy: number | null,
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
102
|
+
sw: number | null,
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
104
|
+
sh: number | null,
|
|
105
|
+
): Promise<ImageResponse> {
|
|
106
|
+
const hasAlpha = premultiplyAlpha ?? blob.type.includes('image/png');
|
|
107
|
+
const src = URL.createObjectURL(blob);
|
|
108
|
+
const img = new Image();
|
|
109
|
+
|
|
110
|
+
if (typeof src === 'string' && isBase64Image(src) === false) {
|
|
111
|
+
img.crossOrigin = 'anonymous';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return new Promise<ImageResponse>((resolve, reject) => {
|
|
115
|
+
img.onload = () => {
|
|
116
|
+
URL.revokeObjectURL(src);
|
|
117
|
+
resolve({ data: img, premultiplyAlpha: hasAlpha });
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
img.onerror = (err) => {
|
|
121
|
+
URL.revokeObjectURL(src);
|
|
122
|
+
const errorMessage =
|
|
123
|
+
err instanceof Error
|
|
124
|
+
? err.message
|
|
125
|
+
: err instanceof Event
|
|
126
|
+
? `Image loading failed for ${img.src}`
|
|
127
|
+
: 'Unknown image loading error';
|
|
128
|
+
reject(new Error(`Image loading failed: ${errorMessage}`));
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
img.src = src;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
override async loadCompressedTexture(src: string): Promise<ImageResponse> {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Compressed textures are not supported in legacy mode. Attempted to load: ${src}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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 2026 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 { WebPlatform } from './WebPlatform.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Next-generation Web Platform implementation that uses Fetch API
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* This platform uses the modern Fetch API instead of XMLHttpRequest for
|
|
27
|
+
* loading image resources. The Fetch API provides a more modern, promise-based
|
|
28
|
+
* interface for network requests and better streaming capabilities.
|
|
29
|
+
*
|
|
30
|
+
* Benefits over XMLHttpRequest:
|
|
31
|
+
* - Promise-based (no callback-based API)
|
|
32
|
+
* - Better error handling
|
|
33
|
+
* - More consistent across browsers
|
|
34
|
+
* - Better streaming support
|
|
35
|
+
* - Service Worker compatible
|
|
36
|
+
*
|
|
37
|
+
* All other platform features remain the same as WebPlatform.
|
|
38
|
+
*/
|
|
39
|
+
export class WebPlatformNext extends WebPlatform {
|
|
40
|
+
override async fetch(url: string): Promise<Blob> {
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(url);
|
|
43
|
+
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Failed to fetch resource: ${response.status} ${response.statusText}`,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return await response.blob();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const errorMessage =
|
|
53
|
+
error instanceof Error ? error.message : 'Unknown fetch error';
|
|
54
|
+
throw new Error(`Fetch failed for ${url}: ${errorMessage}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|