@lightningjs/renderer 0.8.1 → 0.8.3

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 (100) hide show
  1. package/dist/src/core/CoreNode.d.ts +5 -0
  2. package/dist/src/core/CoreNode.js +35 -4
  3. package/dist/src/core/CoreNode.js.map +1 -1
  4. package/dist/src/core/CoreShaderManager.d.ts +2 -0
  5. package/dist/src/core/CoreShaderManager.js +8 -0
  6. package/dist/src/core/CoreShaderManager.js.map +1 -1
  7. package/dist/src/core/Stage.d.ts +3 -2
  8. package/dist/src/core/Stage.js +16 -5
  9. package/dist/src/core/Stage.js.map +1 -1
  10. package/dist/src/core/lib/ImageWorker.js +2 -2
  11. package/dist/src/core/renderers/CoreRenderer.d.ts +21 -3
  12. package/dist/src/core/renderers/CoreRenderer.js +13 -2
  13. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  14. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +16 -0
  15. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +155 -0
  16. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -0
  17. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +17 -0
  18. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +122 -0
  19. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -0
  20. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +5 -0
  21. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +32 -0
  22. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -0
  23. package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +15 -0
  24. package/dist/src/core/renderers/canvas/internal/ColorUtils.js +45 -0
  25. package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -0
  26. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.d.ts +10 -0
  27. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js +43 -0
  28. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js.map +1 -0
  29. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +2 -20
  30. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +3 -15
  31. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  32. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +1 -0
  33. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +23 -0
  34. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -1
  35. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +3 -1
  36. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  37. package/dist/src/core/textures/ImageTexture.js +3 -0
  38. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  39. package/dist/src/main-api/INode.d.ts +13 -0
  40. package/dist/src/main-api/Inspector.js +11 -1
  41. package/dist/src/main-api/Inspector.js.map +1 -1
  42. package/dist/src/main-api/RendererMain.d.ts +4 -0
  43. package/dist/src/main-api/RendererMain.js +2 -0
  44. package/dist/src/main-api/RendererMain.js.map +1 -1
  45. package/dist/src/render-drivers/main/MainCoreDriver.js +1 -0
  46. package/dist/src/render-drivers/main/MainCoreDriver.js.map +1 -1
  47. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +2 -0
  48. package/dist/src/render-drivers/main/MainOnlyNode.js +7 -0
  49. package/dist/src/render-drivers/main/MainOnlyNode.js.map +1 -1
  50. package/dist/src/render-drivers/main/MainOnlyTextNode.js +1 -0
  51. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +1 -1
  52. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +3 -0
  53. package/dist/src/render-drivers/threadx/NodeStruct.js +9 -0
  54. package/dist/src/render-drivers/threadx/NodeStruct.js.map +1 -1
  55. package/dist/src/render-drivers/threadx/SharedNode.d.ts +1 -0
  56. package/dist/src/render-drivers/threadx/SharedNode.js +1 -0
  57. package/dist/src/render-drivers/threadx/SharedNode.js.map +1 -1
  58. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +2 -0
  59. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +1 -1
  60. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +1 -0
  61. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +1 -1
  62. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +1 -0
  63. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +1 -1
  64. package/dist/src/render-drivers/threadx/worker/renderer.js +2 -0
  65. package/dist/src/render-drivers/threadx/worker/renderer.js.map +1 -1
  66. package/dist/src/render-drivers/utils.js +1 -1
  67. package/dist/src/render-drivers/utils.js.map +1 -1
  68. package/dist/src/utils.d.ts +20 -6
  69. package/dist/src/utils.js +29 -9
  70. package/dist/src/utils.js.map +1 -1
  71. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  72. package/package.json +1 -1
  73. package/src/core/CoreNode.ts +49 -4
  74. package/src/core/CoreShaderManager.ts +10 -0
  75. package/src/core/Stage.ts +19 -5
  76. package/src/core/lib/ImageWorker.ts +2 -2
  77. package/src/core/renderers/CoreRenderer.ts +32 -6
  78. package/src/core/renderers/canvas/CanvasCoreRenderer.ts +178 -0
  79. package/src/core/renderers/canvas/CanvasCoreTexture.ts +138 -0
  80. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +34 -0
  81. package/src/core/renderers/canvas/internal/ColorUtils.ts +55 -0
  82. package/src/core/renderers/canvas/shaders/UnsupportedShader.ts +49 -0
  83. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +8 -38
  84. package/src/core/renderers/webgl/shaders/DynamicShader.ts +31 -0
  85. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +3 -1
  86. package/src/core/textures/ImageTexture.ts +3 -0
  87. package/src/main-api/INode.ts +13 -0
  88. package/src/main-api/Inspector.ts +11 -1
  89. package/src/main-api/RendererMain.ts +8 -0
  90. package/src/render-drivers/main/MainCoreDriver.ts +1 -0
  91. package/src/render-drivers/main/MainOnlyNode.ts +9 -0
  92. package/src/render-drivers/main/MainOnlyTextNode.ts +1 -0
  93. package/src/render-drivers/threadx/NodeStruct.ts +10 -0
  94. package/src/render-drivers/threadx/SharedNode.ts +2 -0
  95. package/src/render-drivers/threadx/ThreadXCoreDriver.ts +2 -0
  96. package/src/render-drivers/threadx/worker/ThreadXRendererNode.ts +1 -0
  97. package/src/render-drivers/threadx/worker/ThreadXRendererTextNode.ts +1 -0
  98. package/src/render-drivers/threadx/worker/renderer.ts +2 -0
  99. package/src/render-drivers/utils.ts +1 -1
  100. package/src/utils.ts +32 -9
@@ -0,0 +1,55 @@
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
+ export interface IParsedColor {
21
+ isWhite: boolean;
22
+ a: number;
23
+ r: number;
24
+ g: number;
25
+ b: number;
26
+ }
27
+
28
+ const WHITE: IParsedColor = {
29
+ isWhite: true,
30
+ a: 1,
31
+ r: 0xff,
32
+ g: 0xff,
33
+ b: 0xff
34
+ }
35
+
36
+ /**
37
+ * Extract color components
38
+ */
39
+ export function parseColor(abgr: number): IParsedColor {
40
+ if (abgr === 0xffffffff) {
41
+ return WHITE;
42
+ }
43
+ const a = ((abgr >>> 24) & 0xff) / 255;
44
+ const b = ((abgr >>> 16) & 0xff) & 0xff;
45
+ const g = ((abgr >>> 8) & 0xff) & 0xff;
46
+ const r = (abgr & 0xff) & 0xff;
47
+ return { isWhite: false, a, r, g, b }
48
+ }
49
+
50
+ /**
51
+ * Format a parsed color into a rgba CSS color
52
+ */
53
+ export function formatRgba({ a, r, g, b }: IParsedColor): string {
54
+ return `rgba(${r},${g},${b},${a})`;
55
+ }
@@ -0,0 +1,49 @@
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 { CoreShader } from "../../CoreShader.js";
21
+
22
+ export const ROUNDED_RECTANGLE_SHADER_TYPE = "RoundedRectangle"
23
+
24
+ export class UnsupportedShader extends CoreShader {
25
+
26
+ public shType: string;
27
+
28
+ constructor(shType: string) {
29
+ super();
30
+ this.shType = shType;
31
+ if (shType !== ROUNDED_RECTANGLE_SHADER_TYPE) {
32
+ console.warn('Unsupported shader:', shType);
33
+ }
34
+ }
35
+
36
+ bindRenderOp(): void {
37
+ // noop
38
+ }
39
+ protected bindProps(): void {
40
+ // noop
41
+ }
42
+
43
+ attach(): void {
44
+ // noop
45
+ }
46
+ detach(): void {
47
+ // noop
48
+ }
49
+ }
@@ -21,9 +21,8 @@ import {
21
21
  assertTruthy,
22
22
  createWebGLContext,
23
23
  hasOwn,
24
- mergeColorAlphaPremultiplied,
25
24
  } from '../../../utils.js';
26
- import { CoreRenderer, type QuadOptions } from '../CoreRenderer.js';
25
+ import { CoreRenderer, type CoreRendererOptions, type QuadOptions } from '../CoreRenderer.js';
27
26
  import { WebGlCoreRenderOp } from './WebGlCoreRenderOp.js';
28
27
  import type { CoreContextTexture } from '../CoreContextTexture.js';
29
28
  import {
@@ -36,43 +35,23 @@ import {
36
35
  import { WebGlCoreCtxTexture } from './WebGlCoreCtxTexture.js';
37
36
  import { Texture } from '../../textures/Texture.js';
38
37
  import { ColorTexture } from '../../textures/ColorTexture.js';
39
- import type { Stage } from '../../Stage.js';
40
38
  import { SubTexture } from '../../textures/SubTexture.js';
41
39
  import { WebGlCoreCtxSubTexture } from './WebGlCoreCtxSubTexture.js';
42
- import type {
43
- CoreTextureManager,
44
- TextureOptions,
45
- } from '../../CoreTextureManager.js';
46
40
  import { CoreShaderManager } from '../../CoreShaderManager.js';
47
- import type { CoreShader } from '../CoreShader.js';
48
41
  import { BufferCollection } from './internal/BufferCollection.js';
49
42
  import {
50
43
  compareRect,
51
44
  getNormalizedRgbaComponents,
52
- type Rect,
53
45
  type RectWithValid,
54
46
  } from '../../lib/utils.js';
55
47
  import type { Dimensions } from '../../../common/CommonTypes.js';
56
48
  import { WebGlCoreShader } from './WebGlCoreShader.js';
57
- import { RoundedRectangle } from './shaders/RoundedRectangle.js';
58
- import { ContextSpy } from '../../lib/ContextSpy.js';
59
49
  import { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
60
- import type { TextureMemoryManager } from '../../TextureMemoryManager.js';
61
50
 
62
51
  const WORDS_PER_QUAD = 24;
63
- const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
64
-
65
- export interface WebGlCoreRendererOptions {
66
- stage: Stage;
67
- canvas: HTMLCanvasElement | OffscreenCanvas;
68
- pixelRatio: number;
69
- txManager: CoreTextureManager;
70
- txMemManager: TextureMemoryManager;
71
- shManager: CoreShaderManager;
72
- clearColor: number;
73
- bufferMemory: number;
74
- contextSpy: ContextSpy | null;
75
- }
52
+ // const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
53
+
54
+ export type WebGlCoreRendererOptions = CoreRendererOptions;
76
55
 
77
56
  interface CoreWebGlSystem {
78
57
  parameters: CoreWebGlParameters;
@@ -84,14 +63,6 @@ export class WebGlCoreRenderer extends CoreRenderer {
84
63
  glw: WebGlContextWrapper;
85
64
  system: CoreWebGlSystem;
86
65
 
87
- //// Core Managers
88
- txManager: CoreTextureManager;
89
- txMemManager: TextureMemoryManager;
90
- shManager: CoreShaderManager;
91
-
92
- //// Options
93
- options: Required<WebGlCoreRendererOptions>;
94
-
95
66
  //// Persistent data
96
67
  quadBuffer: ArrayBuffer = new ArrayBuffer(1024 * 1024 * 4);
97
68
  fQuadBuffer: Float32Array = new Float32Array(this.quadBuffer);
@@ -113,12 +84,11 @@ export class WebGlCoreRenderer extends CoreRenderer {
113
84
  defaultTexture: Texture;
114
85
 
115
86
  constructor(options: WebGlCoreRendererOptions) {
116
- super(options.stage);
87
+ super(options);
88
+ this.mode = 'webgl';
89
+
117
90
  const { canvas, clearColor, bufferMemory } = options;
118
- this.options = options;
119
- this.txManager = options.txManager;
120
- this.txMemManager = options.txMemManager;
121
- this.shManager = options.shManager;
91
+
122
92
  this.defaultTexture = new ColorTexture(this.txManager);
123
93
  // When the default texture is loaded, request a render in case the
124
94
  // RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
@@ -170,6 +170,37 @@ export class DynamicShader extends WebGlCoreShader {
170
170
  });
171
171
  }
172
172
 
173
+ override canBatchShaderProps(
174
+ propsA: Required<DynamicShaderProps>,
175
+ propsB: Required<DynamicShaderProps>,
176
+ ): boolean {
177
+ if (
178
+ propsA.$dimensions.width !== propsB.$dimensions.width ||
179
+ propsA.$dimensions.height !== propsB.$dimensions.height ||
180
+ propsA.effects.length !== propsB.effects.length
181
+ ) {
182
+ return false;
183
+ }
184
+ const propsEffectsLen = propsA.effects.length;
185
+ let i = 0;
186
+ for (; i < propsEffectsLen; i++) {
187
+ const effectA = propsA.effects[i]!;
188
+ const effectB = propsB.effects[i]!;
189
+ if (effectA.type !== effectB.type) {
190
+ return false;
191
+ }
192
+ for (const key in effectA.props) {
193
+ if (
194
+ (effectB.props && !effectB.props[key]) ||
195
+ effectA.props[key] !== effectB.props![key]
196
+ ) {
197
+ return false;
198
+ }
199
+ }
200
+ }
201
+ return true;
202
+ }
203
+
173
204
  static createShader(
174
205
  props: DynamicShaderProps,
175
206
  effectContructors: Partial<EffectMap>,
@@ -56,6 +56,7 @@ import type {
56
56
  import type { WebGlCoreCtxTexture } from '../../../renderers/webgl/WebGlCoreCtxTexture.js';
57
57
  import { EventEmitter } from '../../../../common/EventEmitter.js';
58
58
  import type { Matrix3d } from '../../../lib/Matrix3d.js';
59
+ import { WebGlCoreRenderer } from '../../../renderers/webgl/WebGlCoreRenderer.js';
59
60
 
60
61
  declare module '../TextRenderer.js' {
61
62
  interface TextRendererMap {
@@ -580,7 +581,8 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
580
581
  return;
581
582
  }
582
583
 
583
- const { renderer } = this.stage;
584
+ const renderer: WebGlCoreRenderer = this.stage.renderer as WebGlCoreRenderer;
585
+ assertTruthy(renderer instanceof WebGlCoreRenderer);
584
586
 
585
587
  const { fontSize, color, contain, scrollable, zIndex, debug } = state.props;
586
588
 
@@ -117,6 +117,9 @@ export class ImageTexture extends Texture {
117
117
  };
118
118
  } else {
119
119
  const img = new Image();
120
+ if (!(src.substr(0, 5) === 'data:')) {
121
+ img.crossOrigin = 'Anonymous';
122
+ }
120
123
  img.src = src;
121
124
  await new Promise<void>((resolve, reject) => {
122
125
  img.onload = () => resolve();
@@ -72,6 +72,19 @@ export interface INodeWritableProps {
72
72
  * @default `1`
73
73
  */
74
74
  alpha: number;
75
+ /**
76
+ * Autosize mode
77
+ *
78
+ * @remarks
79
+ * When enabled, when a texture is loaded into the Node, the Node will
80
+ * automatically resize to the dimensions of the texture.
81
+ *
82
+ * Text Nodes are always autosized based on their text content regardless
83
+ * of this mode setting.
84
+ *
85
+ * @default `false`
86
+ */
87
+ autosize: boolean;
75
88
  /**
76
89
  * Clipping Mode
77
90
  *
@@ -260,6 +260,11 @@ export class Inspector {
260
260
  ): ITextNode {
261
261
  const node = driver.createTextNode(properties);
262
262
  const div = this.createDiv(node, properties);
263
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
264
+ (div as any).node = node;
265
+
266
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
267
+ (node as any).div = div;
263
268
  return this.createProxy(node, div) as ITextNode;
264
269
  }
265
270
 
@@ -388,7 +393,12 @@ export class Inspector {
388
393
  if (property === 'data') {
389
394
  for (const key in value) {
390
395
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
391
- div.setAttribute(`data-${key}`, String(value[key]));
396
+ const keyValue: unknown = value[key];
397
+ if (keyValue === undefined) {
398
+ div.removeAttribute(`data-${key}`);
399
+ } else {
400
+ div.setAttribute(`data-${key}`, String(keyValue));
401
+ }
392
402
  }
393
403
  return;
394
404
  }
@@ -41,6 +41,7 @@ import { EventEmitter } from '../common/EventEmitter.js';
41
41
  import { Inspector } from './Inspector.js';
42
42
  import { santizeCustomDataMap } from '../render-drivers/utils.js';
43
43
  import { isProductionEnvironment } from '../utils.js';
44
+ import type { StageOptions } from '../core/Stage.js';
44
45
 
45
46
  /**
46
47
  * An immutable reference to a specific Texture type
@@ -270,6 +271,11 @@ export interface RendererMainSettings {
270
271
  * @defaultValue `false` (disabled)
271
272
  */
272
273
  enableInspector?: boolean;
274
+
275
+ /**
276
+ * Renderer mode
277
+ */
278
+ renderMode?: 'webgl' | 'canvas';
273
279
  }
274
280
 
275
281
  /**
@@ -344,6 +350,7 @@ export class RendererMain extends EventEmitter {
344
350
  settings.numImageWorkers !== undefined ? settings.numImageWorkers : 2,
345
351
  enableContextSpy: settings.enableContextSpy ?? false,
346
352
  enableInspector: settings.enableInspector ?? false,
353
+ renderMode: settings.renderMode ?? 'webgl'
347
354
  };
348
355
  this.settings = resolvedSettings;
349
356
 
@@ -534,6 +541,7 @@ export class RendererMain extends EventEmitter {
534
541
  width: props.width ?? 0,
535
542
  height: props.height ?? 0,
536
543
  alpha: props.alpha ?? 1,
544
+ autosize: props.autosize ?? false,
537
545
  clipping: props.clipping ?? false,
538
546
  color,
539
547
  colorTop: props.colorTop ?? color,
@@ -64,6 +64,7 @@ export class MainCoreDriver implements ICoreDriver {
64
64
  fpsUpdateInterval: rendererSettings.fpsUpdateInterval,
65
65
  enableContextSpy: rendererSettings.enableContextSpy,
66
66
  numImageWorkers: rendererSettings.numImageWorkers,
67
+ renderMode: rendererSettings.renderMode,
67
68
  debug: {
68
69
  monitorTextureCache: false,
69
70
  },
@@ -78,6 +78,7 @@ export class MainOnlyNode extends EventEmitter implements INode {
78
78
  width: props.width,
79
79
  height: props.height,
80
80
  alpha: props.alpha,
81
+ autosize: props.autosize,
81
82
  clipping: props.clipping,
82
83
  color: props.color,
83
84
  colorTop: props.colorTop,
@@ -163,6 +164,14 @@ export class MainOnlyNode extends EventEmitter implements INode {
163
164
  this.coreNode.alpha = value;
164
165
  }
165
166
 
167
+ get autosize(): boolean {
168
+ return this.coreNode.autosize;
169
+ }
170
+
171
+ set autosize(value: boolean) {
172
+ this.coreNode.autosize = value;
173
+ }
174
+
166
175
  get clipping(): boolean {
167
176
  return this.coreNode.clipping;
168
177
  }
@@ -45,6 +45,7 @@ export class MainOnlyTextNode extends MainOnlyNode implements ITextNode {
45
45
  width: props.width,
46
46
  height: props.height,
47
47
  alpha: props.alpha,
48
+ autosize: props.autosize,
48
49
  clipping: props.clipping,
49
50
  color: props.color,
50
51
  colorTop: props.colorTop,
@@ -25,6 +25,7 @@ export interface NodeStructWritableProps {
25
25
  width: number;
26
26
  height: number;
27
27
  alpha: number;
28
+ autosize: boolean;
28
29
  clipping: boolean;
29
30
  color: number;
30
31
  colorTop: number;
@@ -100,6 +101,15 @@ export class NodeStruct
100
101
  // Decorator will handle this
101
102
  }
102
103
 
104
+ @structProp('boolean')
105
+ get autosize(): boolean {
106
+ return false;
107
+ }
108
+
109
+ set autosize(value: boolean) {
110
+ // Decorator will handle this
111
+ }
112
+
103
113
  @structProp('boolean')
104
114
  get clipping(): boolean {
105
115
  return false;
@@ -40,6 +40,7 @@ export class SharedNode extends SharedObject {
40
40
  width: sharedNodeStruct.width,
41
41
  height: sharedNodeStruct.height,
42
42
  alpha: sharedNodeStruct.alpha,
43
+ autosize: sharedNodeStruct.autosize,
43
44
  clipping: sharedNodeStruct.clipping,
44
45
  color: sharedNodeStruct.color,
45
46
  colorTop: sharedNodeStruct.colorTop,
@@ -72,6 +73,7 @@ export class SharedNode extends SharedObject {
72
73
  declare width: number;
73
74
  declare height: number;
74
75
  declare alpha: number;
76
+ declare autosize: boolean;
75
77
  declare clipping: boolean;
76
78
  declare color: number;
77
79
  declare colorTop: number;
@@ -151,6 +151,7 @@ export class ThreadXCoreDriver implements ICoreDriver {
151
151
  width: props.width,
152
152
  height: props.height,
153
153
  parentId: props.parent ? props.parent.id : 0,
154
+ autosize: props.autosize,
154
155
  clipping: props.clipping,
155
156
  color: props.color,
156
157
  colorTop: props.colorTop,
@@ -208,6 +209,7 @@ export class ThreadXCoreDriver implements ICoreDriver {
208
209
  colorBl: props.colorBl,
209
210
  colorBr: props.colorBr,
210
211
  alpha: props.alpha,
212
+ autosize: props.autosize,
211
213
  zIndex: props.zIndex,
212
214
  zIndexLocked: props.zIndexLocked,
213
215
  scaleX: props.scaleX,
@@ -209,6 +209,7 @@ export class ThreadXRendererNode extends SharedNode {
209
209
  width: sharedNodeStruct.width,
210
210
  height: sharedNodeStruct.height,
211
211
  alpha: sharedNodeStruct.alpha,
212
+ autosize: sharedNodeStruct.autosize,
212
213
  clipping: sharedNodeStruct.clipping,
213
214
  color: sharedNodeStruct.color,
214
215
  colorTop: sharedNodeStruct.colorTop,
@@ -46,6 +46,7 @@ export class ThreadXRendererTextNode extends ThreadXRendererNode {
46
46
  width: sharedNodeStruct.width,
47
47
  height: sharedNodeStruct.height,
48
48
  alpha: sharedNodeStruct.alpha,
49
+ autosize: sharedNodeStruct.autosize,
49
50
  clipping: sharedNodeStruct.clipping,
50
51
  color: sharedNodeStruct.color,
51
52
  colorTop: sharedNodeStruct.colorTop,
@@ -75,6 +75,7 @@ const threadx = ThreadX.init({
75
75
  fpsUpdateInterval: message.fpsUpdateInterval,
76
76
  enableContextSpy: message.enableContextSpy,
77
77
  numImageWorkers: message.numImageWorkers,
78
+ renderMode: 'webgl',
78
79
  debug: {
79
80
  monitorTextureCache: false,
80
81
  },
@@ -90,6 +91,7 @@ const threadx = ThreadX.init({
90
91
  width: coreRootNode.width,
91
92
  height: coreRootNode.height,
92
93
  alpha: coreRootNode.alpha,
94
+ autosize: coreRootNode.autosize,
93
95
  clipping: coreRootNode.clipping,
94
96
  color: coreRootNode.color,
95
97
  colorTop: coreRootNode.colorTop,
@@ -58,7 +58,7 @@ export async function loadCoreExtension(
58
58
  }
59
59
 
60
60
  export function santizeCustomDataMap(d: CustomDataMap): CustomDataMap {
61
- const validTypes = { boolean: true, string: true, number: true };
61
+ const validTypes = { boolean: true, string: true, number: true, undefined: true };
62
62
 
63
63
  const keys = Object.keys(d);
64
64
  for (let i = 0; i < keys.length; i++) {
package/src/utils.ts CHANGED
@@ -143,19 +143,30 @@ export function mergeColorAlpha(rgba: number, alpha: number): number {
143
143
  return ((r << 24) | (g << 16) | (b << 8) | a) >>> 0;
144
144
  }
145
145
 
146
+ let premultiplyRGB = true;
147
+
148
+ /**
149
+ * RGB components should not be premultiplied when using Canvas renderer
150
+ * @param mode Renderer mode
151
+ */
152
+ export function setPremultiplyMode(mode: 'webgl' | 'canvas'): void {
153
+ premultiplyRGB = mode === 'webgl';
154
+ }
155
+
146
156
  /**
147
157
  * Given an RGBA encoded number, returns back the RGBA number with it's alpha
148
- * component multiplied by the passed `alpha` parameter. Before returning, the
149
- * final alpha value is multiplied into the color channels.
158
+ * component multiplied by the passed `alpha` parameter.
159
+ *
160
+ * For the webGl renderer, each color channel is premultiplied by the final alpha value.
150
161
  *
151
162
  * @remarks
152
163
  * If `flipEndianess` is set to true, the function will returned an ABGR encoded number
153
164
  * which is useful when the color value needs to be passed into a shader attribute.
154
165
  *
155
- * NOTE: This method returns a PREMULTIPLIED alpha color which is generally only useful
156
- * in the context of the internal rendering process. Use {@link mergeColorAlpha} if you
157
- * need to blend an alpha value into a color in the context of the Renderer's
158
- * main API.
166
+ * NOTE: Depending on the mode set by {@link setPremultiplyMode}, this method returns
167
+ * a PREMULTIPLIED alpha color which is generally only useful in the context of the
168
+ * internal rendering process. Use {@link mergeColorAlpha} if you need to blend an alpha
169
+ * value into a color in the context of the Renderer's main API.
159
170
  *
160
171
  * @internalRemarks
161
172
  * Do not expose this method in the main API because Renderer users should instead use
@@ -173,9 +184,10 @@ export function mergeColorAlphaPremultiplied(
173
184
  flipEndianess = false,
174
185
  ): number {
175
186
  const newAlpha = ((rgba & 0xff) / 255) * alpha;
176
- const r = Math.trunc((rgba >>> 24) * newAlpha);
177
- const g = Math.trunc(((rgba >>> 16) & 0xff) * newAlpha);
178
- const b = Math.trunc(((rgba >>> 8) & 0xff) * newAlpha);
187
+ const rgbAlpha = premultiplyRGB ? newAlpha : 1;
188
+ const r = Math.trunc((rgba >>> 24) * rgbAlpha);
189
+ const g = Math.trunc(((rgba >>> 16) & 0xff) * rgbAlpha);
190
+ const b = Math.trunc(((rgba >>> 8) & 0xff) * rgbAlpha);
179
191
  const a = Math.trunc(newAlpha * 255);
180
192
 
181
193
  if (flipEndianess) {
@@ -206,6 +218,17 @@ export function deg2Rad(degrees: number): number {
206
218
  return (degrees * Math.PI) / 180;
207
219
  }
208
220
 
221
+ /**
222
+ * Returns image aspect ratio
223
+ *
224
+ * @param width
225
+ * @param height
226
+ * @returns
227
+ */
228
+ export function getImageAspectRatio(width: number, height: number): number {
229
+ return width / height;
230
+ }
231
+
209
232
  /**
210
233
  * Checks import.meta if env is production
211
234
  *