@lightningjs/renderer 3.0.0-beta8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. package/LICENSE +202 -202
  2. package/NOTICE +3 -3
  3. package/README.md +230 -147
  4. package/dist/exports/canvas.d.ts +1 -1
  5. package/dist/exports/canvas.js +1 -1
  6. package/dist/exports/canvas.js.map +1 -1
  7. package/dist/exports/index.d.ts +5 -6
  8. package/dist/exports/index.js +3 -5
  9. package/dist/exports/index.js.map +1 -1
  10. package/dist/exports/platform.d.ts +7 -0
  11. package/dist/exports/platform.js +27 -0
  12. package/dist/exports/platform.js.map +1 -0
  13. package/dist/exports/webgl.d.ts +2 -1
  14. package/dist/exports/webgl.js +2 -1
  15. package/dist/exports/webgl.js.map +1 -1
  16. package/dist/src/common/CommonTypes.d.ts +15 -3
  17. package/dist/src/core/AutosizeManager.d.ts +29 -0
  18. package/dist/src/core/AutosizeManager.js +169 -0
  19. package/dist/src/core/AutosizeManager.js.map +1 -0
  20. package/dist/src/core/Autosizer.d.ts +35 -0
  21. package/dist/src/core/Autosizer.js +196 -0
  22. package/dist/src/core/Autosizer.js.map +1 -0
  23. package/dist/src/core/CoreNode.d.ts +106 -58
  24. package/dist/src/core/CoreNode.js +530 -282
  25. package/dist/src/core/CoreNode.js.map +1 -1
  26. package/dist/src/core/CoreTextNode.d.ts +73 -88
  27. package/dist/src/core/CoreTextNode.js +375 -236
  28. package/dist/src/core/CoreTextNode.js.map +1 -1
  29. package/dist/src/core/CoreTextureManager.d.ts +23 -26
  30. package/dist/src/core/CoreTextureManager.js +60 -166
  31. package/dist/src/core/CoreTextureManager.js.map +1 -1
  32. package/dist/src/core/Stage.d.ts +63 -9
  33. package/dist/src/core/Stage.js +233 -133
  34. package/dist/src/core/Stage.js.map +1 -1
  35. package/dist/src/core/TextureError.d.ts +11 -0
  36. package/dist/src/core/TextureError.js +37 -0
  37. package/dist/src/core/TextureError.js.map +1 -0
  38. package/dist/src/core/TextureMemoryManager.d.ts +3 -5
  39. package/dist/src/core/TextureMemoryManager.js +84 -94
  40. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  41. package/dist/src/core/animations/Animation.d.ts +21 -0
  42. package/dist/src/core/animations/Animation.js +194 -0
  43. package/dist/src/core/animations/Animation.js.map +1 -0
  44. package/dist/src/core/animations/CoreAnimation.d.ts +3 -3
  45. package/dist/src/core/animations/CoreAnimation.js +3 -3
  46. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  47. package/dist/src/core/animations/CoreAnimationController.d.ts +1 -1
  48. package/dist/src/core/animations/CoreAnimationController.js +8 -5
  49. package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
  50. package/dist/src/core/animations/Playback.d.ts +64 -0
  51. package/dist/src/core/animations/Playback.js +169 -0
  52. package/dist/src/core/animations/Playback.js.map +1 -0
  53. package/dist/src/core/animations/Transition.d.ts +27 -0
  54. package/dist/src/core/animations/Transition.js +52 -0
  55. package/dist/src/core/animations/Transition.js.map +1 -0
  56. package/dist/src/core/animations/utils.d.ts +2 -0
  57. package/dist/src/core/animations/utils.js +136 -0
  58. package/dist/src/core/animations/utils.js.map +1 -0
  59. package/dist/src/core/lib/ImageWorker.d.ts +2 -2
  60. package/dist/src/core/lib/ImageWorker.js +30 -11
  61. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  62. package/dist/src/core/lib/WebGlContextWrapper.d.ts +41 -3
  63. package/dist/src/core/lib/WebGlContextWrapper.js +105 -28
  64. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  65. package/dist/src/core/lib/collectionUtils.d.ts +4 -0
  66. package/dist/src/core/lib/collectionUtils.js +72 -0
  67. package/dist/src/core/lib/collectionUtils.js.map +1 -0
  68. package/dist/src/core/lib/colorCache.d.ts +1 -0
  69. package/dist/src/core/lib/colorCache.js +19 -0
  70. package/dist/src/core/lib/colorCache.js.map +1 -0
  71. package/dist/src/core/lib/colorParser.d.ts +21 -0
  72. package/dist/src/core/lib/colorParser.js +72 -0
  73. package/dist/src/core/lib/colorParser.js.map +1 -0
  74. package/dist/src/core/lib/textureCompression.d.ts +14 -2
  75. package/dist/src/core/lib/textureCompression.js +320 -67
  76. package/dist/src/core/lib/textureCompression.js.map +1 -1
  77. package/dist/src/core/lib/utils.d.ts +6 -6
  78. package/dist/src/core/lib/utils.js +21 -65
  79. package/dist/src/core/lib/utils.js.map +1 -1
  80. package/dist/src/core/platform.d.ts +10 -0
  81. package/dist/src/core/platform.js +81 -0
  82. package/dist/src/core/platform.js.map +1 -0
  83. package/dist/src/core/platforms/GlContextWrapper.d.ts +136 -0
  84. package/{src/core/text-rendering/TextRenderingUtils.ts → dist/src/core/platforms/GlContextWrapper.js} +32 -36
  85. package/dist/src/core/platforms/GlContextWrapper.js.map +1 -0
  86. package/dist/src/core/platforms/Platform.d.ts +78 -12
  87. package/dist/src/core/platforms/Platform.js +18 -0
  88. package/dist/src/core/platforms/Platform.js.map +1 -1
  89. package/dist/src/core/platforms/web/WebGlContextWrapper.d.ts +776 -0
  90. package/dist/src/core/platforms/web/WebGlContextWrapper.js +1208 -0
  91. package/dist/src/core/platforms/web/WebGlContextWrapper.js.map +1 -0
  92. package/dist/src/core/platforms/web/WebPlatform.d.ts +17 -2
  93. package/dist/src/core/platforms/web/WebPlatform.js +158 -13
  94. package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
  95. package/dist/src/core/platforms/web/WebPlatformChrome50.d.ts +19 -0
  96. package/dist/src/core/platforms/web/WebPlatformChrome50.js +54 -0
  97. package/dist/src/core/platforms/web/WebPlatformChrome50.js.map +1 -0
  98. package/dist/src/core/platforms/web/WebPlatformLegacy.d.ts +20 -0
  99. package/dist/src/core/platforms/web/WebPlatformLegacy.js +105 -0
  100. package/dist/src/core/platforms/web/WebPlatformLegacy.js.map +1 -0
  101. package/dist/src/core/platforms/web/WebPlatformNext.d.ts +21 -0
  102. package/dist/src/core/platforms/web/WebPlatformNext.js +52 -0
  103. package/dist/src/core/platforms/web/WebPlatformNext.js.map +1 -0
  104. package/dist/src/core/platforms/web/lib/ImageWorker.d.ts +21 -0
  105. package/dist/src/core/platforms/web/lib/ImageWorker.js +136 -0
  106. package/dist/src/core/platforms/web/lib/ImageWorker.js.map +1 -0
  107. package/dist/src/core/platforms/web/lib/ImageWorkerDefault.d.ts +6 -0
  108. package/dist/src/core/platforms/web/lib/ImageWorkerDefault.js +92 -0
  109. package/dist/src/core/platforms/web/lib/ImageWorkerDefault.js.map +1 -0
  110. package/dist/src/core/platforms/web/lib/ImageWorkerLegacy.d.ts +1 -0
  111. package/dist/src/core/platforms/web/lib/ImageWorkerLegacy.js +63 -0
  112. package/dist/src/core/platforms/web/lib/ImageWorkerLegacy.js.map +1 -0
  113. package/dist/src/core/platforms/web/lib/ImageWorkerNoOptions.d.ts +7 -0
  114. package/dist/src/core/platforms/web/lib/ImageWorkerNoOptions.js +75 -0
  115. package/dist/src/core/platforms/web/lib/ImageWorkerNoOptions.js.map +1 -0
  116. package/dist/src/core/platforms/web/lib/createImageBitmap.d.ts +1 -0
  117. package/dist/src/core/platforms/web/lib/createImageBitmap.js +27 -0
  118. package/dist/src/core/platforms/web/lib/createImageBitmap.js.map +1 -0
  119. package/dist/src/core/platforms/web/lib/textureCompression.d.ts +26 -0
  120. package/dist/src/core/platforms/web/lib/textureCompression.js +301 -0
  121. package/dist/src/core/platforms/web/lib/textureCompression.js.map +1 -0
  122. package/dist/src/core/platforms/web/lib/textureSvg.d.ts +7 -0
  123. package/dist/src/core/platforms/web/lib/textureSvg.js +51 -0
  124. package/dist/src/core/platforms/web/lib/textureSvg.js.map +1 -0
  125. package/dist/src/core/platforms/web/lib/utils.d.ts +5 -0
  126. package/dist/src/core/platforms/web/lib/utils.js +86 -0
  127. package/dist/src/core/platforms/web/lib/utils.js.map +1 -0
  128. package/dist/src/core/renderers/CoreContextTexture.d.ts +2 -1
  129. package/dist/src/core/renderers/CoreContextTexture.js.map +1 -1
  130. package/dist/src/core/renderers/CoreRenderer.d.ts +4 -40
  131. package/dist/src/core/renderers/CoreRenderer.js +3 -4
  132. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  133. package/dist/src/core/renderers/CoreShader.d.ts +9 -0
  134. package/{src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts → dist/src/core/renderers/CoreShader.js} +28 -32
  135. package/dist/src/core/renderers/CoreShader.js.map +1 -0
  136. package/dist/src/core/renderers/CoreShaderNode.d.ts +10 -0
  137. package/dist/src/core/renderers/CoreShaderNode.js +19 -2
  138. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  139. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +33 -0
  140. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +250 -0
  141. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -0
  142. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +17 -0
  143. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +125 -0
  144. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -0
  145. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +5 -6
  146. package/dist/src/core/renderers/canvas/CanvasRenderer.js +67 -91
  147. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  148. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
  149. package/dist/src/core/renderers/canvas/CanvasShaderNode.js +5 -4
  150. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
  151. package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +3 -2
  152. package/dist/src/core/renderers/canvas/CanvasTexture.js +17 -13
  153. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -1
  154. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +13 -0
  155. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +113 -192
  156. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -1
  157. package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +0 -2
  158. package/dist/src/core/renderers/canvas/internal/ColorUtils.js +0 -14
  159. package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -1
  160. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.d.ts +10 -0
  161. package/{src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts → dist/src/core/renderers/canvas/shaders/UnsupportedShader.js} +43 -40
  162. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js.map +1 -0
  163. package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +33 -0
  164. package/dist/src/core/renderers/webgl/SdfRenderOp.js +98 -0
  165. package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
  166. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.d.ts +12 -0
  167. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +58 -0
  168. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +1 -0
  169. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.d.ts +9 -0
  170. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js +38 -0
  171. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js.map +1 -0
  172. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +69 -0
  173. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +272 -0
  174. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -0
  175. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.d.ts +34 -0
  176. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +114 -0
  177. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +1 -0
  178. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +133 -0
  179. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +649 -0
  180. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -0
  181. package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +78 -0
  182. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +202 -0
  183. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -0
  184. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +4 -2
  185. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +14 -6
  186. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
  187. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +15 -2
  188. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +34 -5
  189. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -1
  190. package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +19 -9
  191. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +101 -49
  192. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  193. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +3 -2
  194. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +14 -5
  195. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  196. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +11 -23
  197. package/dist/src/core/renderers/webgl/WebGlRenderer.js +122 -133
  198. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  199. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +4 -6
  200. package/dist/src/core/renderers/webgl/WebGlShaderNode.js +3 -3
  201. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
  202. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +11 -9
  203. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +83 -46
  204. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  205. package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +4 -4
  206. package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -1
  207. package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +3 -3
  208. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +38 -37
  209. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
  210. package/dist/src/core/renderers/webgl/shaders/DefaultShader.d.ts +9 -0
  211. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +84 -0
  212. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -0
  213. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.d.ts +10 -0
  214. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +108 -0
  215. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +1 -0
  216. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +29 -0
  217. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +408 -0
  218. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -0
  219. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.d.ts +28 -0
  220. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +126 -0
  221. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -0
  222. package/dist/src/core/renderers/webgl/shaders/SdfShader.d.ts +47 -0
  223. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +148 -0
  224. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -0
  225. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.d.ts +31 -0
  226. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +71 -0
  227. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js.map +1 -0
  228. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.d.ts +30 -0
  229. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +58 -0
  230. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js.map +1 -0
  231. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.d.ts +31 -0
  232. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +71 -0
  233. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js.map +1 -0
  234. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.d.ts +31 -0
  235. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +71 -0
  236. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js.map +1 -0
  237. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.d.ts +31 -0
  238. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +71 -0
  239. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js.map +1 -0
  240. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.d.ts +9 -0
  241. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js +136 -0
  242. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js.map +1 -0
  243. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.d.ts +36 -0
  244. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +85 -0
  245. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js.map +1 -0
  246. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.d.ts +45 -0
  247. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js +104 -0
  248. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js.map +1 -0
  249. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.d.ts +22 -0
  250. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +45 -0
  251. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js.map +1 -0
  252. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.d.ts +58 -0
  253. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +80 -0
  254. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js.map +1 -0
  255. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.d.ts +35 -0
  256. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +134 -0
  257. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +1 -0
  258. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.d.ts +40 -0
  259. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +143 -0
  260. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +1 -0
  261. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.d.ts +61 -0
  262. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +127 -0
  263. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js.map +1 -0
  264. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.d.ts +40 -0
  265. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +71 -0
  266. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js.map +1 -0
  267. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.d.ts +115 -0
  268. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js +61 -0
  269. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js.map +1 -0
  270. package/dist/src/core/shaders/canvas/Border.d.ts +8 -2
  271. package/dist/src/core/shaders/canvas/Border.js +64 -25
  272. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  273. package/dist/src/core/shaders/canvas/HolePunch.js +4 -3
  274. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
  275. package/dist/src/core/shaders/canvas/LinearGradient.js +7 -5
  276. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  277. package/dist/src/core/shaders/canvas/RadialGradient.js +12 -10
  278. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  279. package/dist/src/core/shaders/canvas/Rounded.js +3 -3
  280. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
  281. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +6 -3
  282. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +41 -11
  283. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  284. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +2 -3
  285. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +46 -9
  286. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  287. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +6 -5
  288. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  289. package/dist/src/core/shaders/canvas/Shadow.js +4 -2
  290. package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
  291. package/dist/src/core/shaders/canvas/utils/render.d.ts +1 -1
  292. package/dist/src/core/shaders/canvas/utils/render.js +31 -18
  293. package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
  294. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +11 -1
  295. package/dist/src/core/shaders/templates/BorderTemplate.js +30 -10
  296. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  297. package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +2 -2
  298. package/dist/src/core/shaders/templates/HolePunchTemplate.js +2 -2
  299. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -1
  300. package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +8 -6
  301. package/dist/src/core/shaders/templates/RadialGradientTemplate.js +2 -2
  302. package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +1 -1
  303. package/dist/src/core/shaders/webgl/Border.js +138 -84
  304. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  305. package/dist/src/core/shaders/webgl/Default.js +46 -47
  306. package/dist/src/core/shaders/webgl/Default.js.map +1 -1
  307. package/dist/src/core/shaders/webgl/DefaultBatched.js +61 -61
  308. package/dist/src/core/shaders/webgl/HolePunch.js +34 -34
  309. package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -1
  310. package/dist/src/core/shaders/webgl/LinearGradient.js +60 -36
  311. package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -1
  312. package/dist/src/core/shaders/webgl/RadialGradient.js +60 -37
  313. package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -1
  314. package/dist/src/core/shaders/webgl/Rounded.js +74 -72
  315. package/dist/src/core/shaders/webgl/Rounded.js.map +1 -1
  316. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +172 -113
  317. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  318. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +191 -132
  319. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  320. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +57 -55
  321. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
  322. package/dist/src/core/shaders/webgl/SdfShader.d.ts +0 -2
  323. package/dist/src/core/shaders/webgl/SdfShader.js +56 -66
  324. package/dist/src/core/shaders/webgl/SdfShader.js.map +1 -1
  325. package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
  326. package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
  327. package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
  328. package/dist/src/core/shaders/webgl/Shadow.js +89 -83
  329. package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
  330. package/dist/src/core/text-rendering/CanvasFont.d.ts +14 -0
  331. package/dist/src/core/text-rendering/CanvasFont.js +111 -0
  332. package/dist/src/core/text-rendering/CanvasFont.js.map +1 -0
  333. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +59 -0
  334. package/dist/src/core/text-rendering/CanvasFontHandler.js +224 -0
  335. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -0
  336. package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +17 -0
  337. package/dist/src/core/text-rendering/CanvasTextRenderer.js +157 -0
  338. package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -0
  339. package/dist/src/core/text-rendering/CoreFont.d.ts +33 -0
  340. package/dist/src/core/text-rendering/CoreFont.js +48 -0
  341. package/dist/src/core/text-rendering/CoreFont.js.map +1 -0
  342. package/dist/src/core/text-rendering/FontManager.d.ts +11 -0
  343. package/dist/src/core/text-rendering/FontManager.js +42 -0
  344. package/dist/src/core/text-rendering/FontManager.js.map +1 -0
  345. package/dist/src/core/text-rendering/SdfFont.d.ts +29 -0
  346. package/dist/src/core/text-rendering/SdfFont.js +142 -0
  347. package/dist/src/core/text-rendering/SdfFont.js.map +1 -0
  348. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +182 -0
  349. package/dist/src/core/text-rendering/SdfFontHandler.js +381 -0
  350. package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -0
  351. package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +17 -0
  352. package/dist/src/core/text-rendering/SdfTextRenderer.js +301 -0
  353. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -0
  354. package/dist/src/core/text-rendering/TextLayoutEngine.d.ts +18 -0
  355. package/dist/src/core/text-rendering/TextLayoutEngine.js +380 -0
  356. package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -0
  357. package/dist/src/core/text-rendering/TextRenderer.d.ts +383 -0
  358. package/{src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts → dist/src/core/text-rendering/TextRenderer.js} +20 -38
  359. package/dist/src/core/text-rendering/TextRenderer.js.map +1 -0
  360. package/dist/src/core/text-rendering/TextTextureRendererUtils.js.map +1 -1
  361. package/dist/src/core/text-rendering/Utils.d.ts +30 -0
  362. package/dist/src/core/text-rendering/Utils.js +84 -0
  363. package/dist/src/core/text-rendering/Utils.js.map +1 -0
  364. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js +2 -2
  365. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js.map +1 -1
  366. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +0 -5
  367. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  368. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -7
  369. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +2 -50
  370. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  371. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +3 -2
  372. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +87 -46
  373. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  374. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +1 -1
  375. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +8 -66
  376. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  377. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +4 -14
  378. package/dist/src/core/text-rendering/renderers/TextRenderer.js +0 -3
  379. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  380. package/dist/src/core/textures/ColorTexture.d.ts +1 -1
  381. package/dist/src/core/textures/ColorTexture.js +3 -4
  382. package/dist/src/core/textures/ColorTexture.js.map +1 -1
  383. package/dist/src/core/textures/ImageTexture.d.ts +33 -14
  384. package/dist/src/core/textures/ImageTexture.js +46 -125
  385. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  386. package/dist/src/core/textures/NoiseTexture.d.ts +3 -3
  387. package/dist/src/core/textures/NoiseTexture.js +8 -8
  388. package/dist/src/core/textures/NoiseTexture.js.map +1 -1
  389. package/dist/src/core/textures/RenderTexture.d.ts +7 -7
  390. package/dist/src/core/textures/RenderTexture.js +12 -12
  391. package/dist/src/core/textures/RenderTexture.js.map +1 -1
  392. package/dist/src/core/textures/SubTexture.d.ts +6 -8
  393. package/dist/src/core/textures/SubTexture.js +22 -40
  394. package/dist/src/core/textures/SubTexture.js.map +1 -1
  395. package/dist/src/core/textures/Texture.d.ts +74 -11
  396. package/dist/src/core/textures/Texture.js +136 -18
  397. package/dist/src/core/textures/Texture.js.map +1 -1
  398. package/dist/src/core/utils.d.ts +2 -1
  399. package/dist/src/core/utils.js +1 -1
  400. package/dist/src/core/utils.js.map +1 -1
  401. package/dist/src/main-api/DynamicShaderController.d.ts +29 -0
  402. package/dist/src/main-api/DynamicShaderController.js +58 -0
  403. package/dist/src/main-api/DynamicShaderController.js.map +1 -0
  404. package/dist/src/main-api/Inspector.d.ts +129 -1
  405. package/dist/src/main-api/Inspector.js +462 -23
  406. package/dist/src/main-api/Inspector.js.map +1 -1
  407. package/dist/src/main-api/Renderer.d.ts +223 -41
  408. package/dist/src/main-api/Renderer.js +107 -62
  409. package/dist/src/main-api/Renderer.js.map +1 -1
  410. package/dist/src/main-api/ShaderController.d.ts +31 -0
  411. package/dist/src/main-api/ShaderController.js +37 -0
  412. package/dist/src/main-api/ShaderController.js.map +1 -0
  413. package/dist/src/utils.d.ts +0 -2
  414. package/dist/src/utils.js +0 -36
  415. package/dist/src/utils.js.map +1 -1
  416. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  417. package/dist/tsconfig.tsbuildinfo +1 -0
  418. package/exports/canvas-shaders.ts +28 -28
  419. package/exports/canvas.ts +45 -45
  420. package/exports/index.ts +90 -90
  421. package/exports/inspector.ts +24 -24
  422. package/exports/platform.ts +31 -0
  423. package/exports/utils.ts +50 -50
  424. package/exports/webgl-shaders.ts +28 -28
  425. package/exports/webgl.ts +52 -50
  426. package/package.json +16 -15
  427. package/src/common/CommonTypes.ts +163 -146
  428. package/src/common/EventEmitter.ts +77 -77
  429. package/src/common/IAnimationController.ts +92 -92
  430. package/src/common/IEventEmitter.ts +28 -28
  431. package/src/core/Autosizer.ts +224 -0
  432. package/src/core/CoreNode.test.ts +365 -202
  433. package/src/core/CoreNode.ts +2785 -2483
  434. package/src/core/CoreShaderManager.ts +188 -188
  435. package/src/core/CoreTextNode.test.ts +311 -0
  436. package/src/core/CoreTextNode.ts +598 -451
  437. package/src/core/CoreTextureManager.ts +484 -608
  438. package/src/core/Stage.ts +927 -800
  439. package/src/core/TextureError.ts +46 -0
  440. package/src/core/TextureMemoryManager.ts +418 -435
  441. package/src/core/animations/AnimationManager.ts +38 -38
  442. package/src/core/animations/CoreAnimation.ts +290 -291
  443. package/src/core/animations/CoreAnimationController.ts +169 -164
  444. package/src/core/lib/ContextSpy.ts +41 -41
  445. package/src/core/lib/Matrix3d.ts +244 -244
  446. package/src/core/lib/RenderCoords.ts +71 -71
  447. package/src/core/lib/collectionUtils.ts +83 -0
  448. package/src/core/lib/colorCache.ts +20 -0
  449. package/src/core/{renderers/canvas/internal/ColorUtils.ts → lib/colorParser.ts} +85 -85
  450. package/src/core/lib/utils.ts +337 -390
  451. package/src/core/platforms/GlContextWrapper.ts +291 -0
  452. package/src/core/platforms/Platform.ts +176 -77
  453. package/src/core/{lib → platforms/web}/WebGlContextWrapper.ts +1547 -1374
  454. package/src/core/platforms/web/WebPlatform.ts +306 -84
  455. package/src/core/platforms/web/WebPlatformChrome50.ts +63 -0
  456. package/src/core/platforms/web/WebPlatformLegacy.ts +150 -0
  457. package/src/core/platforms/web/WebPlatformNext.ts +57 -0
  458. package/src/core/platforms/web/lib/ImageWorker.ts +192 -0
  459. package/src/core/platforms/web/lib/ImageWorkerDefault.ts +117 -0
  460. package/src/core/platforms/web/lib/ImageWorkerLegacy.ts +87 -0
  461. package/src/core/platforms/web/lib/ImageWorkerNoOptions.ts +99 -0
  462. package/src/core/platforms/web/lib/createImageBitmap.ts +40 -0
  463. package/src/core/platforms/web/lib/textureCompression.ts +391 -0
  464. package/src/core/{lib → platforms/web/lib}/textureSvg.ts +66 -78
  465. package/src/core/platforms/web/lib/utils.ts +105 -0
  466. package/src/core/renderers/CoreContextTexture.ts +44 -43
  467. package/src/core/renderers/CoreRenderOp.ts +22 -22
  468. package/src/core/renderers/CoreRenderer.ts +71 -110
  469. package/src/core/renderers/CoreShaderNode.ts +202 -175
  470. package/src/core/renderers/CoreShaderProgram.ts +23 -23
  471. package/src/core/renderers/canvas/CanvasRenderer.ts +258 -302
  472. package/src/core/renderers/canvas/CanvasShaderNode.ts +95 -96
  473. package/src/core/renderers/canvas/CanvasTexture.ts +160 -156
  474. package/src/core/renderers/webgl/SdfRenderOp.ts +106 -0
  475. package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +89 -86
  476. package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +95 -50
  477. package/src/core/renderers/webgl/WebGlCtxTexture.ts +350 -298
  478. package/src/core/renderers/webgl/WebGlRenderer.ts +726 -747
  479. package/src/core/renderers/webgl/WebGlShaderNode.ts +430 -435
  480. package/src/core/renderers/webgl/WebGlShaderProgram.ts +362 -318
  481. package/src/core/renderers/webgl/internal/BufferCollection.ts +54 -54
  482. package/src/core/renderers/webgl/internal/RendererUtils.ts +151 -155
  483. package/src/core/renderers/webgl/internal/ShaderUtils.ts +283 -281
  484. package/src/core/renderers/webgl/internal/WebGlUtils.ts +35 -35
  485. package/src/core/shaders/canvas/Border.ts +132 -78
  486. package/src/core/shaders/canvas/HolePunch.ts +56 -62
  487. package/src/core/shaders/canvas/LinearGradient.ts +73 -71
  488. package/src/core/shaders/canvas/RadialGradient.ts +96 -99
  489. package/src/core/shaders/canvas/Rounded.ts +55 -55
  490. package/src/core/shaders/canvas/RoundedWithBorder.ts +122 -74
  491. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +136 -90
  492. package/src/core/shaders/canvas/RoundedWithShadow.ts +71 -70
  493. package/src/core/shaders/canvas/Shadow.ts +54 -52
  494. package/src/core/shaders/canvas/utils/render.ts +160 -151
  495. package/src/core/shaders/templates/BorderTemplate.ts +145 -115
  496. package/src/core/shaders/templates/HolePunchTemplate.ts +82 -82
  497. package/src/core/shaders/templates/LinearGradientTemplate.ts +71 -71
  498. package/src/core/shaders/templates/RadialGradientTemplate.ts +83 -81
  499. package/src/core/shaders/templates/RoundedTemplate.ts +98 -98
  500. package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +38 -38
  501. package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +35 -35
  502. package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +35 -35
  503. package/src/core/shaders/templates/ShadowTemplate.ts +106 -106
  504. package/src/core/shaders/utils.ts +46 -46
  505. package/src/core/shaders/webgl/Border.ts +169 -116
  506. package/src/core/shaders/webgl/Default.ts +88 -89
  507. package/src/core/shaders/webgl/DefaultBatched.ts +129 -129
  508. package/src/core/shaders/webgl/HolePunch.ts +75 -75
  509. package/src/core/shaders/webgl/LinearGradient.ts +106 -82
  510. package/src/core/shaders/webgl/RadialGradient.ts +108 -85
  511. package/src/core/shaders/webgl/Rounded.ts +115 -117
  512. package/src/core/shaders/webgl/RoundedWithBorder.ts +210 -155
  513. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +234 -175
  514. package/src/core/shaders/webgl/RoundedWithShadow.ts +96 -98
  515. package/src/core/shaders/webgl/SdfShader.ts +122 -134
  516. package/src/core/shaders/webgl/Shadow.ts +121 -115
  517. package/src/core/text-rendering/CanvasFontHandler.ts +304 -0
  518. package/src/core/text-rendering/CanvasTextRenderer.ts +255 -0
  519. package/src/core/text-rendering/SdfFontHandler.ts +584 -0
  520. package/src/core/text-rendering/SdfTextRenderer.ts +403 -0
  521. package/src/core/text-rendering/TextLayoutEngine.ts +672 -0
  522. package/src/core/text-rendering/TextRenderer.ts +444 -0
  523. package/src/core/text-rendering/Utils.ts +99 -0
  524. package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +453 -0
  525. package/src/core/textures/ColorTexture.ts +104 -102
  526. package/src/core/textures/ImageTexture.ts +292 -418
  527. package/src/core/textures/NoiseTexture.ts +106 -104
  528. package/src/core/textures/RenderTexture.ts +87 -85
  529. package/src/core/textures/SubTexture.ts +184 -205
  530. package/src/core/textures/Texture.ts +524 -372
  531. package/src/core/utils.ts +229 -227
  532. package/src/env.d.ts +7 -7
  533. package/src/main-api/INode.ts +100 -100
  534. package/src/main-api/Inspector.ts +1278 -569
  535. package/src/main-api/Renderer.ts +1030 -818
  536. package/src/main-api/utils.ts +45 -45
  537. package/src/utils.ts +220 -267
  538. package/COPYING +0 -1
  539. package/src/core/lib/ImageWorker.ts +0 -286
  540. package/src/core/lib/textureCompression.ts +0 -152
  541. package/src/core/lib/validateImageBitmap.ts +0 -87
  542. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +0 -220
  543. package/src/core/renderers/webgl/WebGlRenderOp.ts +0 -161
  544. package/src/core/text-rendering/TextTextureRendererUtils.ts +0 -263
  545. package/src/core/text-rendering/TrFontManager.ts +0 -183
  546. package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +0 -176
  547. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/FontShaper.ts +0 -139
  548. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +0 -173
  549. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +0 -171
  550. package/src/core/text-rendering/font-face-types/TrFontFace.ts +0 -187
  551. package/src/core/text-rendering/font-face-types/WebTrFontFace.ts +0 -94
  552. package/src/core/text-rendering/font-face-types/utils.ts +0 -39
  553. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +0 -514
  554. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +0 -863
  555. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +0 -793
  556. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts +0 -48
  557. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts +0 -66
  558. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts +0 -52
  559. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +0 -117
  560. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.test.ts +0 -133
  561. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +0 -497
  562. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +0 -49
  563. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +0 -52
  564. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +0 -205
  565. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.ts +0 -93
  566. package/src/core/text-rendering/renderers/TextRenderer.ts +0 -567
package/src/core/Stage.ts CHANGED
@@ -1,800 +1,927 @@
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 { assertTruthy, setPremultiplyMode } from '../utils.js';
21
- import { AnimationManager } from './animations/AnimationManager.js';
22
- import {
23
- UpdateType,
24
- CoreNode,
25
- CoreNodeRenderState,
26
- type CoreNodeProps,
27
- } from './CoreNode.js';
28
- import { CoreTextureManager } from './CoreTextureManager.js';
29
- import { TrFontManager } from './text-rendering/TrFontManager.js';
30
- import { CoreShaderManager } from './CoreShaderManager.js';
31
- import {
32
- TextRenderer,
33
- type TextRendererMap,
34
- type TrProps,
35
- } from './text-rendering/renderers/TextRenderer.js';
36
-
37
- import { EventEmitter } from '../common/EventEmitter.js';
38
- import { ContextSpy } from './lib/ContextSpy.js';
39
- import type {
40
- FpsUpdatePayload,
41
- FrameTickPayload,
42
- QuadsUpdatePayload,
43
- } from '../common/CommonTypes.js';
44
- import {
45
- TextureMemoryManager,
46
- type TextureMemoryManagerSettings,
47
- } from './TextureMemoryManager.js';
48
- import { CoreRenderer } from './renderers/CoreRenderer.js';
49
- import { CoreTextNode, type CoreTextNodeProps } from './CoreTextNode.js';
50
- import { santizeCustomDataMap } from '../main-api/utils.js';
51
- import type { SdfTextRenderer } from './text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
52
- import type { CanvasTextRenderer } from './text-rendering/renderers/CanvasTextRenderer.js';
53
- import { pointInBound } from './lib/utils.js';
54
- import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
55
- import { createBound, createPreloadBounds, type Bound } from './lib/utils.js';
56
- import type { Texture } from './textures/Texture.js';
57
- import { ColorTexture } from './textures/ColorTexture.js';
58
- import type { Platform } from './platforms/Platform.js';
59
- import type { WebPlatform } from './platforms/web/WebPlatform.js';
60
- import type { RendererMainSettings } from '../main-api/Renderer.js';
61
-
62
- export type StageOptions = Omit<
63
- RendererMainSettings,
64
- 'inspector' | 'platform'
65
- > & {
66
- textureMemory: TextureMemoryManagerSettings;
67
- canvas: HTMLCanvasElement | OffscreenCanvas;
68
- fpsUpdateInterval: number;
69
- eventBus: EventEmitter;
70
- platform: Platform | WebPlatform;
71
- inspector: boolean;
72
- };
73
-
74
- export type StageFpsUpdateHandler = (
75
- stage: Stage,
76
- fpsData: FpsUpdatePayload,
77
- ) => void;
78
-
79
- export type StageFrameTickHandler = (
80
- stage: Stage,
81
- frameTickData: FrameTickPayload,
82
- ) => void;
83
-
84
- export interface Point {
85
- x: number;
86
- y: number;
87
- }
88
-
89
- const autoStart = true;
90
-
91
- export class Stage {
92
- /// Module Instances
93
- public readonly animationManager: AnimationManager;
94
- public readonly txManager: CoreTextureManager;
95
- public readonly txMemManager: TextureMemoryManager;
96
- public readonly fontManager: TrFontManager;
97
- public readonly textRenderers: Partial<TextRendererMap>;
98
- public readonly shManager: CoreShaderManager;
99
- public readonly renderer: CoreRenderer;
100
- public readonly root: CoreNode;
101
- public readonly interactiveNodes: Set<CoreNode> = new Set();
102
- public boundsMargin: [number, number, number, number];
103
- public readonly defShaderNode: CoreShaderNode | null = null;
104
- public strictBound: Bound;
105
- public preloadBound: Bound;
106
- public readonly strictBounds: boolean;
107
- public readonly defaultTexture: Texture | null = null;
108
- public pixelRatio: number;
109
- public readonly bufferMemory: number = 2e6;
110
- public readonly platform: Platform | WebPlatform;
111
- public readonly calculateTextureCoord: boolean;
112
-
113
- /**
114
- * Renderer Event Bus for the Stage to emit events onto
115
- *
116
- * @remarks
117
- * In reality this is just the RendererMain instance, which is an EventEmitter.
118
- * this allows us to directly emit events from the Stage to RendererMain
119
- * without having to set up forwarding handlers.
120
- */
121
- public readonly eventBus: EventEmitter;
122
-
123
- /// State
124
- deltaTime = 0;
125
- lastFrameTime = 0;
126
- currentFrameTime = 0;
127
- private clrColor = 0x00000000;
128
- private fpsNumFrames = 0;
129
- private fpsElapsedTime = 0;
130
- private numQuadsRendered = 0;
131
- private renderRequested = false;
132
- private frameEventQueue: [name: string, payload: unknown][] = [];
133
- private fontResolveMap: Record<string, CanvasTextRenderer | SdfTextRenderer> =
134
- {};
135
-
136
- /// Debug data
137
- contextSpy: ContextSpy | null = null;
138
-
139
- /**
140
- * Stage constructor
141
- */
142
- constructor(public options: StageOptions) {
143
- const {
144
- canvas,
145
- clearColor,
146
- appWidth,
147
- appHeight,
148
- boundsMargin,
149
- enableContextSpy,
150
- forceWebGL2,
151
- numImageWorkers,
152
- textureMemory,
153
- renderEngine,
154
- fontEngines,
155
- createImageBitmapSupport,
156
- platform,
157
- } = options;
158
-
159
- assertTruthy(
160
- platform !== null,
161
- 'A CorePlatform is not provided in the options',
162
- );
163
-
164
- this.platform = platform;
165
-
166
- this.eventBus = options.eventBus;
167
- this.txManager = new CoreTextureManager(this, {
168
- numImageWorkers,
169
- createImageBitmapSupport,
170
- });
171
-
172
- // Wait for the Texture Manager to initialize
173
- // once it does, request a render
174
- this.txManager.on('initialized', () => {
175
- this.requestRender();
176
- });
177
-
178
- this.txMemManager = new TextureMemoryManager(this, textureMemory);
179
-
180
- this.animationManager = new AnimationManager();
181
- this.contextSpy = enableContextSpy ? new ContextSpy() : null;
182
- this.strictBounds = options.strictBounds;
183
-
184
- let bm = [0, 0, 0, 0] as [number, number, number, number];
185
- if (boundsMargin) {
186
- bm = Array.isArray(boundsMargin)
187
- ? boundsMargin
188
- : [boundsMargin, boundsMargin, boundsMargin, boundsMargin];
189
- }
190
- this.boundsMargin = bm;
191
-
192
- // precalculate our viewport bounds
193
- this.strictBound = createBound(0, 0, appWidth, appHeight);
194
- this.preloadBound = createPreloadBounds(this.strictBound, bm);
195
-
196
- this.clrColor = clearColor;
197
-
198
- this.pixelRatio =
199
- options.devicePhysicalPixelRatio * options.deviceLogicalPixelRatio;
200
-
201
- this.renderer = new renderEngine({
202
- stage: this,
203
- canvas,
204
- contextSpy: this.contextSpy,
205
- forceWebGL2,
206
- });
207
-
208
- this.shManager = new CoreShaderManager(this);
209
-
210
- this.defShaderNode = this.renderer.getDefaultShaderNode();
211
- this.calculateTextureCoord = this.renderer.getTextureCoords !== undefined;
212
-
213
- const renderMode = this.renderer.mode || 'webgl';
214
-
215
- this.createDefaultTexture();
216
- setPremultiplyMode(renderMode);
217
-
218
- // Must do this after renderer is created
219
- this.txManager.renderer = this.renderer;
220
-
221
- // Create text renderers
222
- this.textRenderers = {};
223
- fontEngines.forEach((fontEngineConstructor) => {
224
- const fontEngineInstance = new fontEngineConstructor(this);
225
- const className = fontEngineInstance.type;
226
-
227
- if (className === 'sdf' && renderMode === 'canvas') {
228
- console.warn(
229
- 'SdfTextRenderer is not compatible with Canvas renderer. Skipping...',
230
- );
231
- return;
232
- }
233
-
234
- if (fontEngineInstance instanceof TextRenderer) {
235
- if (className === 'canvas') {
236
- this.textRenderers['canvas'] =
237
- fontEngineInstance as CanvasTextRenderer;
238
- } else if (className === 'sdf') {
239
- this.textRenderers['sdf'] = fontEngineInstance as SdfTextRenderer;
240
- }
241
- }
242
- });
243
-
244
- if (Object.keys(this.textRenderers).length === 0) {
245
- console.warn('No text renderers available. Your text will not render.');
246
- }
247
-
248
- this.fontManager = new TrFontManager(this.textRenderers);
249
-
250
- // create root node
251
- const rootNode = new CoreNode(this, {
252
- x: 0,
253
- y: 0,
254
- width: appWidth,
255
- height: appHeight,
256
- alpha: 1,
257
- autosize: false,
258
- boundsMargin: null,
259
- clipping: false,
260
- color: 0x00000000,
261
- colorTop: 0x00000000,
262
- colorBottom: 0x00000000,
263
- colorLeft: 0x00000000,
264
- colorRight: 0x00000000,
265
- colorTl: 0x00000000,
266
- colorTr: 0x00000000,
267
- colorBl: 0x00000000,
268
- colorBr: 0x00000000,
269
- zIndex: 0,
270
- zIndexLocked: 0,
271
- scaleX: 1,
272
- scaleY: 1,
273
- mountX: 0,
274
- mountY: 0,
275
- mount: 0,
276
- pivot: 0.5,
277
- pivotX: 0.5,
278
- pivotY: 0.5,
279
- rotation: 0,
280
- parent: null,
281
- texture: null,
282
- textureOptions: {},
283
- shader: this.defShaderNode,
284
- rtt: false,
285
- src: null,
286
- scale: 1,
287
- strictBounds: this.strictBounds,
288
- });
289
-
290
- this.root = rootNode;
291
-
292
- // execute platform start loop
293
- if (autoStart === true) {
294
- this.platform.startLoop(this);
295
- }
296
- }
297
-
298
- setClearColor(color: number) {
299
- this.clearColor = color;
300
- this.renderer.updateClearColor(color);
301
- this.renderRequested = true;
302
- }
303
-
304
- updateFrameTime() {
305
- const newFrameTime = this.platform!.getTimeStamp();
306
- this.lastFrameTime = this.currentFrameTime;
307
- this.currentFrameTime = newFrameTime;
308
- this.deltaTime = !this.lastFrameTime
309
- ? 100 / 6
310
- : newFrameTime - this.lastFrameTime;
311
- this.txManager.frameTime = newFrameTime;
312
- this.txMemManager.frameTime = newFrameTime;
313
-
314
- // This event is emitted at the beginning of the frame (before any updates
315
- // or rendering), so no need to to use `stage.queueFrameEvent` here.
316
- this.eventBus.emit('frameTick', {
317
- time: this.currentFrameTime,
318
- delta: this.deltaTime,
319
- });
320
- }
321
-
322
- /**
323
- * Create default PixelTexture
324
- */
325
- createDefaultTexture() {
326
- (this.defaultTexture as ColorTexture) = this.txManager.createTexture(
327
- 'ColorTexture',
328
- {
329
- color: 0xffffffff,
330
- },
331
- );
332
-
333
- assertTruthy(this.defaultTexture instanceof ColorTexture);
334
- this.txManager.loadTexture(this.defaultTexture, true);
335
-
336
- // Mark the default texture as ALWAYS renderable
337
- // This prevents it from ever being cleaned up.
338
- // Fixes https://github.com/lightning-js/renderer/issues/262
339
- this.defaultTexture.setRenderableOwner(this, true);
340
-
341
- // When the default texture is loaded, request a render in case the
342
- // RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
343
- this.defaultTexture.once('loaded', () => {
344
- this.requestRender();
345
- });
346
- }
347
-
348
- /**
349
- * Update animations
350
- */
351
- updateAnimations() {
352
- const { animationManager } = this;
353
- if (!this.root) {
354
- return;
355
- }
356
- // step animation
357
- animationManager.update(this.deltaTime);
358
- }
359
-
360
- /**
361
- * Check if the scene has updates
362
- */
363
- hasSceneUpdates() {
364
- return (
365
- !!this.root.updateType ||
366
- this.renderRequested ||
367
- this.txManager.hasUpdates()
368
- );
369
- }
370
-
371
- /**
372
- * Start a new frame draw
373
- */
374
- drawFrame() {
375
- const { renderer, renderRequested, root } = this;
376
- const txMemManager = this.txMemManager;
377
-
378
- // Update tree if needed
379
- if (root.updateType !== 0) {
380
- root.update(this.deltaTime, root.clippingRect);
381
- }
382
-
383
- // Process some textures
384
- this.txManager.processSome(this.options.textureProcessingTimeLimit);
385
-
386
- // Reset render operations and clear the canvas
387
- renderer.reset();
388
-
389
- // Check if we need to cleanup textures
390
- if (txMemManager.criticalCleanupRequested === true) {
391
- txMemManager.cleanup(false);
392
-
393
- if (txMemManager.criticalCleanupRequested === true) {
394
- // If we still need to cleanup, request another but aggressive cleanup
395
- txMemManager.cleanup(true);
396
- }
397
- }
398
-
399
- // If we have RTT nodes draw them first
400
- // So we can use them as textures in the main scene
401
- if (renderer.rttNodes.length > 0) {
402
- renderer.renderRTTNodes();
403
- }
404
-
405
- // Fill quads buffer
406
- this.addQuads(this.root);
407
-
408
- // Perform render pass
409
- renderer.render();
410
-
411
- this.calculateFps();
412
- this.calculateQuads();
413
-
414
- // Reset renderRequested flag if it was set
415
- if (renderRequested === true) {
416
- this.renderRequested = false;
417
- }
418
- }
419
-
420
- /**
421
- * Queue an event to be emitted after the current/next frame is rendered
422
- *
423
- * @remarks
424
- * When we are operating in the context of the render loop, we may want to
425
- * emit events that are related to the current frame. However, we generally do
426
- * NOT want to emit events directly in the middle of the render loop, since
427
- * this could enable event handlers to modify the scene graph and cause
428
- * unexpected behavior. Instead, we queue up events to be emitted and then
429
- * flush the queue after the frame has been rendered.
430
- *
431
- * @param name
432
- * @param data
433
- */
434
- queueFrameEvent(name: string, data: unknown) {
435
- this.frameEventQueue.push([name, data]);
436
- }
437
-
438
- /**
439
- * Emit all queued frame events
440
- *
441
- * @remarks
442
- * This method should be called after the frame has been rendered to emit
443
- * all events that were queued during the frame.
444
- *
445
- * See {@link queueFrameEvent} for more information.
446
- */
447
- flushFrameEvents() {
448
- for (const [name, data] of this.frameEventQueue) {
449
- this.eventBus.emit(name, data);
450
- }
451
- this.frameEventQueue = [];
452
- }
453
-
454
- calculateFps() {
455
- // If there's an FPS update interval, emit the FPS update event
456
- // when the specified interval has elapsed.
457
- const { fpsUpdateInterval } = this.options;
458
- if (fpsUpdateInterval) {
459
- this.fpsNumFrames++;
460
- this.fpsElapsedTime += this.deltaTime;
461
- if (this.fpsElapsedTime >= fpsUpdateInterval) {
462
- const fps = Math.round(
463
- (this.fpsNumFrames * 1000) / this.fpsElapsedTime,
464
- );
465
- this.fpsNumFrames = 0;
466
- this.fpsElapsedTime = 0;
467
- this.queueFrameEvent('fpsUpdate', {
468
- fps,
469
- contextSpyData: this.contextSpy?.getData() ?? null,
470
- } satisfies FpsUpdatePayload);
471
- this.contextSpy?.reset();
472
- }
473
- }
474
- }
475
-
476
- calculateQuads() {
477
- const quads = this.renderer.getQuadCount();
478
- if (quads && quads !== this.numQuadsRendered) {
479
- this.numQuadsRendered = quads;
480
- this.queueFrameEvent('quadsUpdate', {
481
- quads,
482
- } satisfies QuadsUpdatePayload);
483
- }
484
- }
485
-
486
- addQuads(node: CoreNode) {
487
- assertTruthy(this.renderer);
488
-
489
- // If the node is renderable and has a loaded texture, render it
490
- if (node.isRenderable === true) {
491
- node.renderQuads(this.renderer);
492
- }
493
-
494
- for (let i = 0; i < node.children.length; i++) {
495
- const child = node.children[i];
496
-
497
- if (child === undefined) {
498
- continue;
499
- }
500
-
501
- if (
502
- child.worldAlpha === 0 ||
503
- (child.strictBounds === true &&
504
- child.renderState === CoreNodeRenderState.OutOfBounds)
505
- ) {
506
- continue;
507
- }
508
-
509
- this.addQuads(child);
510
- }
511
- }
512
-
513
- /**
514
- * Request a render pass without forcing an update
515
- */
516
- requestRender() {
517
- this.renderRequested = true;
518
- }
519
-
520
- /**
521
- * Given a font name, and possible renderer override, return the best compatible text renderer.
522
- *
523
- * @remarks
524
- * Will try to return a canvas renderer if no other suitable renderer can be resolved.
525
- *
526
- * @param fontFamily
527
- * @param textRendererOverride
528
- * @returns
529
- */
530
- resolveTextRenderer(
531
- trProps: TrProps,
532
- textRendererOverride: keyof TextRendererMap | null = null,
533
- ): TextRenderer | null {
534
- const fontCacheString = `${trProps.fontFamily}${trProps.fontStyle}${
535
- trProps.fontWeight
536
- }${trProps.fontStretch}${textRendererOverride ? textRendererOverride : ''}`;
537
-
538
- // check our resolve cache first
539
- if (this.fontResolveMap[fontCacheString] !== undefined) {
540
- return this.fontResolveMap[fontCacheString] as unknown as TextRenderer;
541
- }
542
-
543
- // Resolve the text renderer
544
- let rendererId = textRendererOverride;
545
- let overrideFallback = false;
546
-
547
- // Check if the override is valid (if one is provided)
548
- if (rendererId) {
549
- const possibleRenderer = this.textRenderers[rendererId];
550
- if (!possibleRenderer) {
551
- console.warn(`Text renderer override '${rendererId}' not found.`);
552
- rendererId = null;
553
- overrideFallback = true;
554
- } else if (!possibleRenderer.canRenderFont(trProps)) {
555
- console.warn(
556
- `Cannot use override text renderer '${rendererId}' for font`,
557
- trProps,
558
- );
559
- rendererId = null;
560
- overrideFallback = true;
561
- }
562
- }
563
-
564
- if (!rendererId) {
565
- // Iterate through the text renderers and find the first one that can render the font
566
- for (const [trId, tr] of Object.entries(this.textRenderers)) {
567
- if (tr.canRenderFont(trProps)) {
568
- rendererId = trId as keyof TextRendererMap;
569
- break;
570
- }
571
- }
572
- if (!rendererId && this.textRenderers.canvas !== undefined) {
573
- // If no renderer can be found, use the canvas renderer
574
- rendererId = 'canvas';
575
- }
576
- }
577
-
578
- if (overrideFallback) {
579
- console.warn(`Falling back to text renderer ${String(rendererId)}`);
580
- }
581
-
582
- if (!rendererId) {
583
- // silently fail if no renderer can be found, the error is already created
584
- // at the constructor level
585
- return null;
586
- }
587
-
588
- // By now we are guaranteed to have a valid rendererId (at least Canvas);
589
- const resolvedTextRenderer = this.textRenderers[rendererId];
590
- assertTruthy(resolvedTextRenderer, 'resolvedTextRenderer undefined');
591
-
592
- // cache the resolved renderer for future use with these trProps
593
- this.fontResolveMap[fontCacheString] = resolvedTextRenderer;
594
-
595
- // Need to explicitly cast to TextRenderer because TS doesn't like
596
- // the covariant state argument in the setter method map
597
- return resolvedTextRenderer as unknown as TextRenderer;
598
- }
599
-
600
- createNode(props: Partial<CoreNodeProps>) {
601
- const resolvedProps = this.resolveNodeDefaults(props);
602
- return new CoreNode(this, resolvedProps);
603
- }
604
-
605
- createTextNode(props: Partial<CoreTextNodeProps>) {
606
- const fontSize = props.fontSize ?? 16;
607
- const resolvedProps = Object.assign(this.resolveNodeDefaults(props), {
608
- text: props.text ?? '',
609
- textRendererOverride: props.textRendererOverride ?? null,
610
- fontSize,
611
- fontFamily: props.fontFamily ?? 'sans-serif',
612
- fontStyle: props.fontStyle ?? 'normal',
613
- fontWeight: props.fontWeight ?? 'normal',
614
- fontStretch: props.fontStretch ?? 'normal',
615
- textAlign: props.textAlign ?? 'left',
616
- contain: props.contain ?? 'none',
617
- scrollable: props.scrollable ?? false,
618
- scrollY: props.scrollY ?? 0,
619
- offsetY: props.offsetY ?? 0,
620
- letterSpacing: props.letterSpacing ?? 0,
621
- lineHeight: props.lineHeight, // `undefined` is a valid value
622
- maxLines: props.maxLines ?? 0,
623
- textBaseline: props.textBaseline ?? 'alphabetic',
624
- verticalAlign: props.verticalAlign ?? 'middle',
625
- overflowSuffix: props.overflowSuffix ?? '...',
626
- wordBreak: props.wordBreak ?? 'normal',
627
- debug: props.debug ?? {},
628
- });
629
-
630
- const resolvedTextRenderer = this.resolveTextRenderer(
631
- resolvedProps,
632
- props.textRendererOverride,
633
- );
634
-
635
- if (!resolvedTextRenderer) {
636
- throw new Error(
637
- `No compatible text renderer found for ${resolvedProps.fontFamily}`,
638
- );
639
- }
640
-
641
- return new CoreTextNode(this, resolvedProps, resolvedTextRenderer);
642
- }
643
-
644
- setBoundsMargin(value: number | [number, number, number, number]) {
645
- this.boundsMargin = Array.isArray(value)
646
- ? value
647
- : [value, value, value, value];
648
-
649
- this.root.setUpdateType(UpdateType.RenderBounds);
650
- }
651
-
652
- /**
653
- * Update the viewport bounds
654
- */
655
- updateViewportBounds() {
656
- const { appWidth, appHeight } = this.options;
657
- this.strictBound = createBound(0, 0, appWidth, appHeight);
658
- this.preloadBound = createPreloadBounds(
659
- this.strictBound,
660
- this.boundsMargin,
661
- );
662
- this.root.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
663
- this.root.childUpdateType |= UpdateType.RenderBounds;
664
- }
665
-
666
- /** Find all nodes at a given point
667
- * @param data
668
- */
669
- findNodesAtPoint(data: Point): CoreNode[] {
670
- const x = data.x / this.options.deviceLogicalPixelRatio;
671
- const y = data.y / this.options.deviceLogicalPixelRatio;
672
- const nodes: CoreNode[] = [];
673
- for (const node of this.interactiveNodes) {
674
- if (node.isRenderable === false) {
675
- continue;
676
- }
677
- if (pointInBound(x, y, node.renderBound!) === true) {
678
- nodes.push(node);
679
- }
680
- }
681
- return nodes;
682
- }
683
-
684
- /**
685
- * Find the top node at a given point
686
- * @param data
687
- * @returns
688
- */
689
- getNodeFromPosition(data: Point): CoreNode | null {
690
- const nodes: CoreNode[] = this.findNodesAtPoint(data);
691
- if (nodes.length === 0) {
692
- return null;
693
- }
694
- let topNode = nodes[0] as CoreNode;
695
- for (let i = 0; i < nodes.length; i++) {
696
- if (nodes[i]!.zIndex > topNode.zIndex) {
697
- topNode = nodes[i]!;
698
- }
699
- }
700
- return topNode || null;
701
- }
702
-
703
- /**
704
- * Resolves the default property values for a Node
705
- *
706
- * @remarks
707
- * This method is used internally by the RendererMain to resolve the default
708
- * property values for a Node. It is exposed publicly so that it can be used
709
- * by Core Driver implementations.
710
- *
711
- * @param props
712
- * @returns
713
- */
714
- protected resolveNodeDefaults(props: Partial<CoreNodeProps>): CoreNodeProps {
715
- const color = props.color ?? 0xffffffff;
716
- const colorTop = props.colorTop ?? color;
717
- const colorBottom = props.colorBottom ?? color;
718
- const colorLeft = props.colorLeft ?? color;
719
- const colorRight = props.colorRight ?? color;
720
-
721
- const colorTl = props.colorTl ?? colorTop ?? colorLeft ?? color;
722
- const colorTr = props.colorTr ?? colorTop ?? colorRight ?? color;
723
- const colorBl = props.colorBl ?? colorBottom ?? colorLeft ?? color;
724
- const colorBr = props.colorBr ?? colorBottom ?? colorRight ?? color;
725
-
726
- const scale = props.scale ?? null;
727
- const mount = props.mount ?? 0;
728
- const pivot = props.pivot ?? 0.5;
729
-
730
- const data = this.options.inspector
731
- ? santizeCustomDataMap(props.data ?? {})
732
- : {};
733
-
734
- return {
735
- x: props.x ?? 0,
736
- y: props.y ?? 0,
737
- width: props.width ?? 0,
738
- height: props.height ?? 0,
739
- alpha: props.alpha ?? 1,
740
- autosize: props.autosize ?? false,
741
- boundsMargin: props.boundsMargin ?? null,
742
- clipping: props.clipping ?? false,
743
- color,
744
- colorTop,
745
- colorBottom,
746
- colorLeft,
747
- colorRight,
748
- colorTl,
749
- colorTr,
750
- colorBl,
751
- colorBr,
752
- zIndex: props.zIndex ?? 0,
753
- zIndexLocked: props.zIndexLocked ?? 0,
754
- parent: props.parent ?? null,
755
- texture: props.texture ?? null,
756
- textureOptions: props.textureOptions ?? {},
757
- shader: props.shader ?? this.defShaderNode,
758
- src: props.src ?? null,
759
- srcHeight: props.srcHeight,
760
- srcWidth: props.srcWidth,
761
- srcX: props.srcX,
762
- srcY: props.srcY,
763
- scale,
764
- scaleX: props.scaleX ?? scale ?? 1,
765
- scaleY: props.scaleY ?? scale ?? 1,
766
- mount,
767
- mountX: props.mountX ?? mount,
768
- mountY: props.mountY ?? mount,
769
- pivot,
770
- pivotX: props.pivotX ?? pivot,
771
- pivotY: props.pivotY ?? pivot,
772
- rotation: props.rotation ?? 0,
773
- rtt: props.rtt ?? false,
774
- data,
775
- imageType: props.imageType,
776
- interactive: props.interactive ?? false,
777
- strictBounds: props.strictBounds ?? this.strictBounds,
778
- };
779
- }
780
-
781
- /**
782
- * Cleanup Orphaned Textures
783
- *
784
- * @remarks
785
- * This method is used to cleanup orphaned textures that are no longer in use.
786
- */
787
- cleanup(aggressive: boolean) {
788
- this.txMemManager.cleanup(aggressive);
789
- }
790
-
791
- set clearColor(value: number) {
792
- this.renderer.updateClearColor(value);
793
- this.renderRequested = true;
794
- this.clrColor = value;
795
- }
796
-
797
- get clearColor() {
798
- return this.clrColor;
799
- }
800
- }
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 { assertTruthy, setPremultiplyMode } from '../utils.js';
21
+ import { AnimationManager } from './animations/AnimationManager.js';
22
+ import {
23
+ UpdateType,
24
+ CoreNode,
25
+ CoreNodeRenderState,
26
+ type CoreNodeProps,
27
+ } from './CoreNode.js';
28
+ import { CoreTextureManager } from './CoreTextureManager.js';
29
+ import { CoreShaderManager } from './CoreShaderManager.js';
30
+ import {
31
+ type FontHandler,
32
+ type FontLoadOptions,
33
+ type TextRenderer,
34
+ type TextRenderers,
35
+ type TrProps,
36
+ } from './text-rendering/TextRenderer.js';
37
+
38
+ import { EventEmitter } from '../common/EventEmitter.js';
39
+ import { ContextSpy } from './lib/ContextSpy.js';
40
+ import type {
41
+ FpsUpdatePayload,
42
+ FrameTickPayload,
43
+ QuadsUpdatePayload,
44
+ } from '../common/CommonTypes.js';
45
+ import {
46
+ TextureMemoryManager,
47
+ type TextureMemoryManagerSettings,
48
+ } from './TextureMemoryManager.js';
49
+ import { CoreRenderer } from './renderers/CoreRenderer.js';
50
+ import { CoreTextNode, type CoreTextNodeProps } from './CoreTextNode.js';
51
+ import { santizeCustomDataMap } from '../main-api/utils.js';
52
+ import { pointInBound } from './lib/utils.js';
53
+ import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
54
+ import { createBound, createPreloadBounds, type Bound } from './lib/utils.js';
55
+ import type { Texture } from './textures/Texture.js';
56
+ import { ColorTexture } from './textures/ColorTexture.js';
57
+ import type { Platform } from './platforms/Platform.js';
58
+ import type { WebPlatform } from './platforms/web/WebPlatform.js';
59
+ import type { RendererMainSettings } from '../main-api/Renderer.js';
60
+
61
+ export type StageOptions = Omit<
62
+ RendererMainSettings,
63
+ 'inspector' | 'platform' | 'maxRetryCount'
64
+ > & {
65
+ textureMemory: TextureMemoryManagerSettings;
66
+ canvas: HTMLCanvasElement | OffscreenCanvas;
67
+ fpsUpdateInterval: number;
68
+ eventBus: EventEmitter;
69
+ platform: Platform | WebPlatform;
70
+ inspector: boolean;
71
+ maxRetryCount: number;
72
+ enableClear: boolean;
73
+ };
74
+
75
+ export type StageFpsUpdateHandler = (
76
+ stage: Stage,
77
+ fpsData: FpsUpdatePayload,
78
+ ) => void;
79
+
80
+ export type StageFrameTickHandler = (
81
+ stage: Stage,
82
+ frameTickData: FrameTickPayload,
83
+ ) => void;
84
+
85
+ export interface Point {
86
+ x: number;
87
+ y: number;
88
+ }
89
+
90
+ const autoStart = true;
91
+
92
+ export class Stage {
93
+ /// Module Instances
94
+ public readonly animationManager: AnimationManager;
95
+ public readonly txManager: CoreTextureManager;
96
+ public readonly txMemManager: TextureMemoryManager;
97
+ public readonly textRenderers: Record<string, TextRenderer> = {};
98
+ public readonly fontHandlers: Record<string, FontHandler> = {};
99
+ public readonly shManager: CoreShaderManager;
100
+ public readonly renderer: CoreRenderer;
101
+ public readonly root: CoreNode;
102
+ public readonly interactiveNodes: Set<CoreNode> = new Set();
103
+ public boundsMargin: [number, number, number, number];
104
+ public readonly defShaderNode: CoreShaderNode | null = null;
105
+ public strictBound: Bound;
106
+ public preloadBound: Bound;
107
+ public readonly defaultTexture: Texture | null = null;
108
+ public pixelRatio: number;
109
+ public readonly bufferMemory: number = 2e6;
110
+ public readonly platform: Platform | WebPlatform;
111
+ public readonly calculateTextureCoord: boolean;
112
+
113
+ /**
114
+ * Target frame time in milliseconds (calculated from targetFPS)
115
+ *
116
+ * @remarks
117
+ * This is pre-calculated to avoid recalculating on every frame.
118
+ * - 0 means no throttling (use display refresh rate)
119
+ * - >0 means throttle to this frame time (1000 / targetFPS)
120
+ */
121
+ public targetFrameTime: number = 0;
122
+
123
+ /**
124
+ * Renderer Event Bus for the Stage to emit events onto
125
+ *
126
+ * @remarks
127
+ * In reality this is just the RendererMain instance, which is an EventEmitter.
128
+ * this allows us to directly emit events from the Stage to RendererMain
129
+ * without having to set up forwarding handlers.
130
+ */
131
+ public readonly eventBus: EventEmitter;
132
+
133
+ /// State
134
+ startTime = 0;
135
+ deltaTime = 0;
136
+ lastFrameTime = 0;
137
+ currentFrameTime = 0;
138
+ elapsedTime = 0;
139
+ private timedNodes: CoreNode[] = [];
140
+ private clrColor = 0x00000000;
141
+ private fpsNumFrames = 0;
142
+ private fpsElapsedTime = 0;
143
+ private numQuadsRendered = 0;
144
+ private renderRequested = false;
145
+ private frameEventQueue: [name: string, payload: unknown][] = [];
146
+
147
+ // Font resolve optimisation flags
148
+ private hasOnlyOneFontEngine: boolean;
149
+ private hasOnlyCanvasFontEngine: boolean;
150
+ private hasCanvasEngine: boolean;
151
+ private singleFontEngine: TextRenderer | null = null;
152
+ private singleFontHandler: FontHandler | null = null;
153
+
154
+ // Debug data
155
+ contextSpy: ContextSpy | null = null;
156
+
157
+ /**
158
+ * Stage constructor
159
+ */
160
+ constructor(public options: StageOptions) {
161
+ const {
162
+ clearColor,
163
+ appWidth,
164
+ appHeight,
165
+ boundsMargin,
166
+ enableContextSpy,
167
+ numImageWorkers,
168
+ textureMemory,
169
+ renderEngine,
170
+ fontEngines,
171
+ createImageBitmapSupport,
172
+ platform,
173
+ maxRetryCount,
174
+ } = options;
175
+
176
+ assertTruthy(
177
+ platform !== null,
178
+ 'A CorePlatform is not provided in the options',
179
+ );
180
+
181
+ this.platform = platform;
182
+
183
+ this.startTime = platform.getTimeStamp();
184
+
185
+ this.eventBus = options.eventBus;
186
+
187
+ // Calculate target frame time from targetFPS option
188
+ this.targetFrameTime = options.targetFPS > 0 ? 1000 / options.targetFPS : 0;
189
+
190
+ this.txManager = new CoreTextureManager(this, {
191
+ numImageWorkers,
192
+ createImageBitmapSupport,
193
+ maxRetryCount,
194
+ });
195
+
196
+ this.txMemManager = new TextureMemoryManager(this, textureMemory);
197
+
198
+ this.animationManager = new AnimationManager();
199
+ this.contextSpy = enableContextSpy ? new ContextSpy() : null;
200
+
201
+ let bm = [0, 0, 0, 0] as [number, number, number, number];
202
+ if (boundsMargin) {
203
+ bm = Array.isArray(boundsMargin)
204
+ ? boundsMargin
205
+ : [boundsMargin, boundsMargin, boundsMargin, boundsMargin];
206
+ }
207
+ this.boundsMargin = bm;
208
+
209
+ // precalculate our viewport bounds
210
+ this.strictBound = createBound(0, 0, appWidth, appHeight);
211
+ this.preloadBound = createPreloadBounds(this.strictBound, bm);
212
+
213
+ this.clrColor = clearColor;
214
+
215
+ this.pixelRatio =
216
+ options.devicePhysicalPixelRatio * options.deviceLogicalPixelRatio;
217
+
218
+ this.renderer = new renderEngine(this);
219
+
220
+ this.shManager = new CoreShaderManager(this);
221
+
222
+ this.defShaderNode = this.renderer.getDefaultShaderNode();
223
+ this.calculateTextureCoord = this.renderer.getTextureCoords !== undefined;
224
+
225
+ const renderMode = this.renderer.mode || 'webgl';
226
+
227
+ this.createDefaultTexture();
228
+ setPremultiplyMode(renderMode);
229
+
230
+ // Must do this after renderer is created
231
+ this.txManager.renderer = this.renderer;
232
+
233
+ // Create text renderers
234
+ this.hasOnlyOneFontEngine = fontEngines.length === 1;
235
+ this.hasOnlyCanvasFontEngine =
236
+ fontEngines.length === 1 && fontEngines[0]!.type === 'canvas';
237
+ this.hasCanvasEngine = false;
238
+ this.singleFontEngine = this.hasOnlyOneFontEngine
239
+ ? (fontEngines[0] as TextRenderer)
240
+ : null;
241
+ this.singleFontHandler = this.hasOnlyOneFontEngine
242
+ ? (fontEngines[0]?.font as FontHandler)
243
+ : null;
244
+
245
+ if (this.singleFontEngine === null) {
246
+ // Multiple font engines case
247
+ // Filter out incompatible engines first
248
+ const compatibleEngines = fontEngines.filter(
249
+ (fontEngine: TextRenderer) => {
250
+ const type = fontEngine.type;
251
+
252
+ if (type === 'sdf' && renderMode === 'canvas') {
253
+ console.warn(
254
+ 'MsdfTextRenderer is not compatible with Canvas renderer. Skipping...',
255
+ );
256
+ return false;
257
+ }
258
+
259
+ if (type === 'canvas') {
260
+ this.hasCanvasEngine = true;
261
+ }
262
+
263
+ return true;
264
+ },
265
+ );
266
+
267
+ // Sort engines: SDF first, Canvas last, others in between
268
+ const sortedEngines = compatibleEngines.sort(
269
+ (a: TextRenderer, b: TextRenderer) => {
270
+ if (a.type === 'sdf') return -1;
271
+ if (b.type === 'sdf') return 1;
272
+ if (a.type === 'canvas') return 1;
273
+ if (b.type === 'canvas') return -1;
274
+ return 0;
275
+ },
276
+ );
277
+
278
+ // Initialize engines in sorted order
279
+ sortedEngines.forEach((fontEngine: TextRenderer) => {
280
+ const type = fontEngine.type;
281
+
282
+ // Add to map for type-based access
283
+ this.textRenderers[type] = fontEngine;
284
+ this.textRenderers[type].init(this);
285
+
286
+ this.fontHandlers[type] = fontEngine.font;
287
+ });
288
+ } else {
289
+ // Single font engine case - initialize it directly
290
+ const fontEngine = this.singleFontEngine;
291
+ const type = fontEngine.type;
292
+
293
+ // Check compatibility
294
+ if (type === 'sdf' && renderMode === 'canvas') {
295
+ console.warn(
296
+ 'MsdfTextRenderer is not compatible with Canvas renderer. Skipping...',
297
+ );
298
+ } else {
299
+ if (type === 'canvas') {
300
+ this.hasCanvasEngine = true;
301
+ }
302
+
303
+ // Add to map for type-based access
304
+ this.textRenderers[type] = fontEngine;
305
+ this.fontHandlers[type] = fontEngine.font;
306
+ this.textRenderers[type].init(this);
307
+ }
308
+ }
309
+
310
+ if (Object.keys(this.textRenderers).length === 0) {
311
+ console.warn('No text renderers available. Your text will not render.');
312
+ }
313
+
314
+ // create root node
315
+ const rootNode = new CoreNode(this, {
316
+ x: 0,
317
+ y: 0,
318
+ w: appWidth,
319
+ h: appHeight,
320
+ alpha: 1,
321
+ autosize: false,
322
+ boundsMargin: null,
323
+ clipping: false,
324
+ color: 0x00000000,
325
+ colorTop: 0x00000000,
326
+ colorBottom: 0x00000000,
327
+ colorLeft: 0x00000000,
328
+ colorRight: 0x00000000,
329
+ colorTl: 0x00000000,
330
+ colorTr: 0x00000000,
331
+ colorBl: 0x00000000,
332
+ colorBr: 0x00000000,
333
+ zIndex: 0,
334
+ scaleX: 1,
335
+ scaleY: 1,
336
+ mountX: 0,
337
+ mountY: 0,
338
+ mount: 0,
339
+ pivot: 0.5,
340
+ pivotX: 0.5,
341
+ pivotY: 0.5,
342
+ rotation: 0,
343
+ parent: null,
344
+ texture: null,
345
+ textureOptions: {},
346
+ shader: this.defShaderNode,
347
+ rtt: false,
348
+ src: null,
349
+ scale: 1,
350
+ });
351
+
352
+ this.root = rootNode;
353
+
354
+ // execute platform start loop
355
+ if (autoStart === true) {
356
+ this.platform.startLoop(this);
357
+ }
358
+ }
359
+
360
+ setClearColor(color: number) {
361
+ this.clearColor = color;
362
+ this.renderer.updateClearColor(color);
363
+ this.renderRequested = true;
364
+ }
365
+
366
+ /**
367
+ * Update the target frame time based on the current targetFPS setting
368
+ *
369
+ * @remarks
370
+ * This should be called whenever the targetFPS option is changed
371
+ * to ensure targetFrameTime stays in sync.
372
+ * targetFPS of 0 means no throttling (targetFrameTime = 0)
373
+ * targetFPS > 0 means throttle to 1000/targetFPS milliseconds
374
+ */
375
+ updateTargetFrameTime() {
376
+ this.targetFrameTime =
377
+ this.options.targetFPS > 0 ? 1000 / this.options.targetFPS : 0;
378
+ }
379
+
380
+ updateFrameTime() {
381
+ const newFrameTime = this.platform.getTimeStamp();
382
+ this.lastFrameTime = this.currentFrameTime;
383
+ this.currentFrameTime = newFrameTime;
384
+ this.elapsedTime = newFrameTime - this.startTime;
385
+ this.deltaTime = !this.lastFrameTime
386
+ ? 100 / 6
387
+ : newFrameTime - this.lastFrameTime;
388
+ this.txManager.frameTime = newFrameTime;
389
+ this.txMemManager.frameTime = newFrameTime;
390
+
391
+ // This event is emitted at the beginning of the frame (before any updates
392
+ // or rendering), so no need to to use `stage.queueFrameEvent` here.
393
+ this.eventBus.emit('frameTick', {
394
+ time: this.currentFrameTime,
395
+ delta: this.deltaTime,
396
+ });
397
+ }
398
+
399
+ /**
400
+ * Create default PixelTexture
401
+ */
402
+ createDefaultTexture() {
403
+ (this.defaultTexture as ColorTexture) = this.txManager.createTexture(
404
+ 'ColorTexture',
405
+ {
406
+ color: 0xffffffff,
407
+ },
408
+ );
409
+
410
+ assertTruthy(this.defaultTexture instanceof ColorTexture);
411
+ this.txManager.loadTexture(this.defaultTexture, true);
412
+
413
+ // Mark the default texture as ALWAYS renderable
414
+ // This prevents it from ever being cleaned up.
415
+ // Fixes https://github.com/lightning-js/renderer/issues/262
416
+ this.defaultTexture.setRenderableOwner('stage', true);
417
+
418
+ // When the default texture is loaded, request a render in case the
419
+ // RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
420
+ this.defaultTexture.once('loaded', () => {
421
+ this.requestRender();
422
+ });
423
+ }
424
+
425
+ /**
426
+ * Update animations
427
+ */
428
+ updateAnimations() {
429
+ const { animationManager } = this;
430
+ if (!this.root) {
431
+ return;
432
+ }
433
+ // step animation
434
+ animationManager.update(this.deltaTime);
435
+ }
436
+
437
+ /**
438
+ * Check if the scene has updates
439
+ */
440
+ hasSceneUpdates() {
441
+ return (
442
+ !!this.root.updateType ||
443
+ this.renderRequested ||
444
+ this.txManager.hasUpdates()
445
+ );
446
+ }
447
+
448
+ /**
449
+ * Start a new frame draw
450
+ */
451
+ drawFrame() {
452
+ const { renderer, renderRequested, root } = this;
453
+ const txMemManager = this.txMemManager;
454
+
455
+ // Update tree if needed
456
+ if (root.updateType !== 0) {
457
+ root.update(this.deltaTime, root.clippingRect);
458
+ }
459
+
460
+ // Process some textures asynchronously but don't block the frame
461
+ // Use a background task to prevent frame drops
462
+ if (this.txManager.hasUpdates() === true) {
463
+ this.txManager
464
+ .processSome(this.options.textureProcessingTimeLimit)
465
+ .catch((err) => {
466
+ console.error('Error processing textures:', err);
467
+ });
468
+ }
469
+
470
+ // Reset render operations and clear the canvas
471
+ renderer.reset();
472
+
473
+ // If we have RTT nodes draw them first
474
+ // So we can use them as textures in the main scene
475
+ if (renderer.rttNodes.length > 0) {
476
+ renderer.renderRTTNodes();
477
+ }
478
+
479
+ // Fill quads buffer
480
+ this.addQuads(this.root);
481
+
482
+ // Perform render pass
483
+ renderer.render();
484
+
485
+ this.calculateFps();
486
+ this.calculateQuads();
487
+
488
+ // Reset renderRequested flag if it was set
489
+ if (renderRequested === true) {
490
+ this.renderRequested = false;
491
+ }
492
+
493
+ if (this.timedNodes.length > 0) {
494
+ for (let key in this.timedNodes) {
495
+ if (this.timedNodes[key]!.isRenderable === true) {
496
+ this.requestRender();
497
+ break;
498
+ }
499
+ }
500
+ }
501
+ // Check if we need to cleanup textures
502
+ if (this.txMemManager.criticalCleanupRequested === true) {
503
+ this.txMemManager.cleanup();
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Queue an event to be emitted after the current/next frame is rendered
509
+ *
510
+ * @remarks
511
+ * When we are operating in the context of the render loop, we may want to
512
+ * emit events that are related to the current frame. However, we generally do
513
+ * NOT want to emit events directly in the middle of the render loop, since
514
+ * this could enable event handlers to modify the scene graph and cause
515
+ * unexpected behavior. Instead, we queue up events to be emitted and then
516
+ * flush the queue after the frame has been rendered.
517
+ *
518
+ * @param name
519
+ * @param data
520
+ */
521
+ queueFrameEvent(name: string, data: unknown) {
522
+ this.frameEventQueue.push([name, data]);
523
+ }
524
+
525
+ /**
526
+ * Emit all queued frame events
527
+ *
528
+ * @remarks
529
+ * This method should be called after the frame has been rendered to emit
530
+ * all events that were queued during the frame.
531
+ *
532
+ * See {@link queueFrameEvent} for more information.
533
+ */
534
+ flushFrameEvents() {
535
+ for (const [name, data] of this.frameEventQueue) {
536
+ this.eventBus.emit(name, data);
537
+ }
538
+ this.frameEventQueue = [];
539
+ }
540
+
541
+ calculateFps() {
542
+ // If there's an FPS update interval, emit the FPS update event
543
+ // when the specified interval has elapsed.
544
+ const { fpsUpdateInterval } = this.options;
545
+ if (fpsUpdateInterval) {
546
+ this.fpsNumFrames++;
547
+ this.fpsElapsedTime += this.deltaTime;
548
+ if (this.fpsElapsedTime >= fpsUpdateInterval) {
549
+ const fps = Math.round(
550
+ (this.fpsNumFrames * 1000) / this.fpsElapsedTime,
551
+ );
552
+ this.fpsNumFrames = 0;
553
+ this.fpsElapsedTime = 0;
554
+ this.queueFrameEvent('fpsUpdate', {
555
+ fps,
556
+ contextSpyData: this.contextSpy?.getData() ?? null,
557
+ } satisfies FpsUpdatePayload);
558
+ this.contextSpy?.reset();
559
+ }
560
+ }
561
+ }
562
+
563
+ calculateQuads() {
564
+ const quads = this.renderer.getQuadCount();
565
+ if (quads && quads !== this.numQuadsRendered) {
566
+ this.numQuadsRendered = quads;
567
+ this.queueFrameEvent('quadsUpdate', {
568
+ quads,
569
+ } satisfies QuadsUpdatePayload);
570
+ }
571
+ }
572
+
573
+ addQuads(node: CoreNode) {
574
+ assertTruthy(this.renderer);
575
+
576
+ // If the node is renderable and has a loaded texture, render it
577
+ if (node.isRenderable === true) {
578
+ node.renderQuads(this.renderer);
579
+ }
580
+
581
+ for (let i = 0; i < node.children.length; i++) {
582
+ const child = node.children[i];
583
+
584
+ if (child === undefined) {
585
+ continue;
586
+ }
587
+
588
+ if (
589
+ child.worldAlpha === 0 ||
590
+ child.renderState === CoreNodeRenderState.OutOfBounds
591
+ ) {
592
+ continue;
593
+ }
594
+
595
+ this.addQuads(child);
596
+ }
597
+ }
598
+
599
+ /**
600
+ * Request a render pass without forcing an update
601
+ */
602
+ requestRender() {
603
+ this.renderRequested = true;
604
+ }
605
+
606
+ /**
607
+ * Given a font name, and possible renderer override, return the best compatible text renderer.
608
+ *
609
+ * @remarks
610
+ * Will try to return a canvas renderer if no other suitable renderer can be resolved.
611
+ *
612
+ * @param fontFamily
613
+ * @param textRendererOverride
614
+ * @returns
615
+ */
616
+ resolveTextRenderer(
617
+ trProps: TrProps,
618
+ textRendererOverride: keyof TextRenderers | null = null,
619
+ ): TextRenderer | null {
620
+ // If we have an overide, return it
621
+ if (textRendererOverride !== null) {
622
+ const overrideKey = String(textRendererOverride);
623
+ if (this.textRenderers[overrideKey] === undefined) {
624
+ console.warn(`Text renderer override '${overrideKey}' not found.`);
625
+ return null;
626
+ }
627
+
628
+ return this.textRenderers[overrideKey];
629
+ }
630
+
631
+ // If we have only one font engine early return it
632
+ if (this.singleFontEngine !== null) {
633
+ // If we have only one font engine and its the canvas engine, we can just return it
634
+ if (this.hasOnlyCanvasFontEngine === true) {
635
+ return this.singleFontEngine;
636
+ }
637
+
638
+ // If we have only one font engine and it can render the font, return it
639
+ if (this.singleFontHandler?.canRenderFont(trProps) === true) {
640
+ return this.singleFontEngine;
641
+ }
642
+
643
+ // If we have only one font engine and it cannot render the font, return null
644
+ console.warn(`Text renderer cannot render font`, trProps);
645
+
646
+ return null;
647
+ }
648
+
649
+ // Multi font handling - If we have multiple font engines, we need to resolve the best one
650
+
651
+ // First check SDF
652
+ if (this.fontHandlers['sdf']?.canRenderFont(trProps) === true) {
653
+ return this.textRenderers.sdf || null;
654
+ }
655
+
656
+ // If we have a canvas engine, we can return it (it can render all fonts)
657
+ if (this.hasCanvasEngine === true) {
658
+ return this.textRenderers.canvas || null;
659
+ }
660
+
661
+ // If we have no font engines, return null
662
+ console.warn('No text renderers available. Your text will not render.');
663
+ return null;
664
+ }
665
+
666
+ createNode(props: Partial<CoreNodeProps>) {
667
+ const resolvedProps = this.resolveNodeDefaults(props);
668
+ return new CoreNode(this, resolvedProps);
669
+ }
670
+
671
+ createTextNode(props: Partial<CoreTextNodeProps>) {
672
+ const fontSize = props.fontSize || 16;
673
+ const resolvedProps = Object.assign(this.resolveNodeDefaults(props), {
674
+ text: props.text || '',
675
+ textRendererOverride: props.textRendererOverride || null,
676
+ fontSize,
677
+ fontFamily: props.fontFamily || 'sans-serif',
678
+ fontStyle: props.fontStyle || 'normal',
679
+ textAlign: props.textAlign || 'left',
680
+ offsetY: props.offsetY || 0,
681
+ letterSpacing: props.letterSpacing || 0,
682
+ lineHeight: props.lineHeight || 1.2,
683
+ maxLines: props.maxLines || 0,
684
+ verticalAlign: props.verticalAlign || 'top',
685
+ overflowSuffix: props.overflowSuffix || '...',
686
+ wordBreak: props.wordBreak || 'break-word',
687
+ contain: props.contain || 'none',
688
+ maxWidth: props.maxWidth || 0,
689
+ maxHeight: props.maxHeight || 0,
690
+ forceLoad: props.forceLoad || false,
691
+ });
692
+
693
+ const resolvedTextRenderer = this.resolveTextRenderer(
694
+ resolvedProps,
695
+ resolvedProps.textRendererOverride as keyof TextRenderers | null,
696
+ );
697
+
698
+ if (!resolvedTextRenderer) {
699
+ throw new Error(
700
+ `No compatible text renderer found for ${resolvedProps.fontFamily}`,
701
+ );
702
+ }
703
+
704
+ return new CoreTextNode(this, resolvedProps, resolvedTextRenderer);
705
+ }
706
+
707
+ setBoundsMargin(value: number | [number, number, number, number]) {
708
+ this.boundsMargin = Array.isArray(value)
709
+ ? value
710
+ : [value, value, value, value];
711
+
712
+ this.root.setUpdateType(UpdateType.RenderBounds);
713
+ }
714
+
715
+ /**
716
+ * Update the viewport bounds
717
+ */
718
+ updateViewportBounds() {
719
+ const { appWidth, appHeight } = this.options;
720
+ this.strictBound = createBound(0, 0, appWidth, appHeight);
721
+ this.preloadBound = createPreloadBounds(
722
+ this.strictBound,
723
+ this.boundsMargin,
724
+ );
725
+ this.root.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
726
+ this.root.childUpdateType |= UpdateType.RenderBounds;
727
+ }
728
+
729
+ /** Find all nodes at a given point
730
+ * @param data
731
+ */
732
+ findNodesAtPoint(data: Point): CoreNode[] {
733
+ const x = data.x / this.options.deviceLogicalPixelRatio;
734
+ const y = data.y / this.options.deviceLogicalPixelRatio;
735
+ const nodes: CoreNode[] = [];
736
+ for (const node of this.interactiveNodes) {
737
+ if (node.isRenderable === false) {
738
+ continue;
739
+ }
740
+ if (pointInBound(x, y, node.renderBound!) === true) {
741
+ nodes.push(node);
742
+ }
743
+ }
744
+ return nodes;
745
+ }
746
+
747
+ /**
748
+ * Find the top node at a given point
749
+ * @param data
750
+ * @returns
751
+ */
752
+ getNodeFromPosition(data: Point): CoreNode | null {
753
+ const nodes: CoreNode[] = this.findNodesAtPoint(data);
754
+ if (nodes.length === 0) {
755
+ return null;
756
+ }
757
+
758
+ //get last node in array (as top node)
759
+ let topNode = nodes[nodes.length - 1] as CoreNode;
760
+ for (let i = 0; i < nodes.length; i++) {
761
+ if (nodes[i]!.zIndex > topNode.zIndex) {
762
+ topNode = nodes[i]!;
763
+ }
764
+ }
765
+ return topNode || null;
766
+ }
767
+
768
+ /**
769
+ * add node to timeNodes arrays
770
+ * @param node
771
+ * @returns
772
+ */
773
+ trackTimedNode(node: CoreNode) {
774
+ if (this.timedNodes[node.id] !== undefined) {
775
+ return;
776
+ }
777
+ this.timedNodes[node.id] = node;
778
+ }
779
+
780
+ /**
781
+ * remove node from timeNodes arrays
782
+ * @param node
783
+ * @returns
784
+ */
785
+ untrackTimedNode(node: CoreNode) {
786
+ if (this.timedNodes[node.id] === undefined) {
787
+ return;
788
+ }
789
+ delete this.timedNodes[node.id];
790
+ }
791
+
792
+ /**
793
+ * Resolves the default property values for a Node
794
+ *
795
+ * @remarks
796
+ * This method is used internally by the RendererMain to resolve the default
797
+ * property values for a Node. It is exposed publicly so that it can be used
798
+ * by Core Driver implementations.
799
+ *
800
+ * @param props
801
+ * @returns
802
+ */
803
+ protected resolveNodeDefaults(props: Partial<CoreNodeProps>): CoreNodeProps {
804
+ const {
805
+ colorTop: top,
806
+ colorBottom: bottom,
807
+ colorLeft: left,
808
+ colorRight: right,
809
+ } = props;
810
+
811
+ const color = props.color ?? 0xffffffff;
812
+ const colorTop = top ?? color;
813
+ const colorBottom = bottom ?? color;
814
+ const colorLeft = left ?? color;
815
+ const colorRight = right ?? color;
816
+
817
+ const colorTl = props.colorTl ?? top ?? left ?? color;
818
+ const colorTr = props.colorTr ?? top ?? right ?? color;
819
+ const colorBl = props.colorBl ?? bottom ?? left ?? color;
820
+ const colorBr = props.colorBr ?? bottom ?? right ?? color;
821
+
822
+ const scale = props.scale ?? null;
823
+ const mount = props.mount ?? 0;
824
+ const pivot = props.pivot ?? 0.5;
825
+
826
+ const data = this.options.inspector
827
+ ? santizeCustomDataMap(props.data ?? {})
828
+ : {};
829
+
830
+ return {
831
+ x: props.x ?? 0,
832
+ y: props.y ?? 0,
833
+ w: props.w ?? 0,
834
+ h: props.h ?? 0,
835
+ alpha: props.alpha ?? 1,
836
+ autosize: props.autosize ?? false,
837
+ boundsMargin: props.boundsMargin ?? null,
838
+ clipping: props.clipping ?? false,
839
+ color,
840
+ colorTop,
841
+ colorBottom,
842
+ colorLeft,
843
+ colorRight,
844
+ colorTl,
845
+ colorTr,
846
+ colorBl,
847
+ colorBr,
848
+ zIndex: props.zIndex ?? 0,
849
+ parent: props.parent ?? null,
850
+ texture: props.texture ?? null,
851
+ textureOptions: props.textureOptions ?? {},
852
+ shader: props.shader ?? this.defShaderNode,
853
+ src: props.src ?? null,
854
+ srcHeight: props.srcHeight,
855
+ srcWidth: props.srcWidth,
856
+ srcX: props.srcX,
857
+ srcY: props.srcY,
858
+ scale,
859
+ scaleX: props.scaleX ?? scale ?? 1,
860
+ scaleY: props.scaleY ?? scale ?? 1,
861
+ mount,
862
+ mountX: props.mountX ?? mount,
863
+ mountY: props.mountY ?? mount,
864
+ pivot,
865
+ pivotX: props.pivotX ?? pivot,
866
+ pivotY: props.pivotY ?? pivot,
867
+ rotation: props.rotation ?? 0,
868
+ rtt: props.rtt ?? false,
869
+ data,
870
+ imageType: props.imageType,
871
+ interactive: props.interactive ?? false,
872
+ };
873
+ }
874
+
875
+ /**
876
+ * Cleanup Orphaned Textures
877
+ *
878
+ * @remarks
879
+ * This method is used to cleanup orphaned textures that are no longer in use.
880
+ */
881
+ cleanup(full: boolean = false) {
882
+ this.txMemManager.cleanup(full);
883
+ }
884
+
885
+ set clearColor(value: number) {
886
+ this.renderer.updateClearColor(value);
887
+ this.renderRequested = true;
888
+ this.clrColor = value;
889
+ }
890
+
891
+ get clearColor() {
892
+ return this.clrColor;
893
+ }
894
+
895
+ /**
896
+ * Load a font using a specific text renderer type
897
+ *
898
+ * @remarks
899
+ * This method allows consumers to explicitly load fonts for a specific
900
+ * text renderer type (e.g., 'canvas', 'sdf'). Consumers must specify
901
+ * the renderer type to ensure fonts are loaded with the correct pipeline.
902
+ *
903
+ * For Canvas fonts, provide fontUrl (e.g., .ttf, .woff, .woff2)
904
+ * For SDF fonts, provide atlasUrl (image) and atlasDataUrl (JSON glyph data)
905
+ *
906
+ * @param rendererType - The type of text renderer ('canvas', 'sdf', etc.)
907
+ * @param options - Font loading options specific to the renderer type
908
+ * @returns Promise that resolves when the font is loaded
909
+ */
910
+ async loadFont(
911
+ rendererType: TextRenderers,
912
+ options: FontLoadOptions,
913
+ ): Promise<void> {
914
+ const rendererTypeKey = String(rendererType);
915
+ const fontHandler = this.fontHandlers[rendererTypeKey];
916
+
917
+ if (!fontHandler) {
918
+ throw new Error(
919
+ `Font handler for renderer type '${rendererTypeKey}' not found. Available types: ${Object.keys(
920
+ this.fontHandlers,
921
+ ).join(', ')}`,
922
+ );
923
+ }
924
+
925
+ return fontHandler.loadFont(this, options);
926
+ }
927
+ }