@lightningjs/renderer 3.0.0-beta10 → 3.0.0-beta12

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 (355) hide show
  1. package/LICENSE +202 -202
  2. package/NOTICE +3 -3
  3. package/README.md +133 -133
  4. package/dist/src/common/CommonTypes.d.ts +2 -2
  5. package/dist/src/core/CoreNode.d.ts +8 -7
  6. package/dist/src/core/CoreNode.js +57 -61
  7. package/dist/src/core/CoreNode.js.map +1 -1
  8. package/dist/src/core/CoreTextNode.d.ts +3 -0
  9. package/dist/src/core/CoreTextNode.js +54 -19
  10. package/dist/src/core/CoreTextNode.js.map +1 -1
  11. package/dist/src/core/Stage.js +4 -4
  12. package/dist/src/core/Stage.js.map +1 -1
  13. package/dist/src/core/lib/textureCompression.js +4 -4
  14. package/dist/src/core/lib/textureCompression.js.map +1 -1
  15. package/dist/src/core/platform.d.ts +10 -0
  16. package/dist/src/core/platform.js +81 -0
  17. package/dist/src/core/platform.js.map +1 -0
  18. package/dist/src/core/renderers/CoreShader.d.ts +9 -0
  19. package/dist/src/core/renderers/CoreShader.js +28 -0
  20. package/dist/src/core/renderers/CoreShader.js.map +1 -0
  21. package/dist/src/core/renderers/CoreShaderNode.js +2 -2
  22. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  23. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +33 -0
  24. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +250 -0
  25. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -0
  26. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +16 -0
  27. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +124 -0
  28. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -0
  29. package/dist/src/core/renderers/canvas/CanvasRenderer.js +1 -1
  30. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  31. package/dist/src/core/renderers/canvas/CanvasTexture.js +5 -5
  32. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -1
  33. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +13 -0
  34. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +113 -192
  35. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -1
  36. package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +0 -2
  37. package/dist/src/core/renderers/canvas/internal/ColorUtils.js +0 -14
  38. package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -1
  39. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.d.ts +10 -0
  40. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js +43 -0
  41. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js.map +1 -0
  42. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.d.ts +12 -0
  43. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +58 -0
  44. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +1 -0
  45. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.d.ts +9 -0
  46. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js +38 -0
  47. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js.map +1 -0
  48. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +56 -0
  49. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +239 -0
  50. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -0
  51. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.d.ts +34 -0
  52. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +114 -0
  53. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +1 -0
  54. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +133 -0
  55. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +616 -0
  56. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -0
  57. package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +83 -0
  58. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +233 -0
  59. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -0
  60. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +5 -6
  61. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
  62. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +13 -0
  63. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +34 -5
  64. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -1
  65. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +21 -21
  66. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  67. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +1 -1
  68. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  69. package/dist/src/core/renderers/webgl/WebGlRenderer.js +12 -11
  70. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  71. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +2 -2
  72. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  73. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +35 -35
  74. package/dist/src/core/renderers/webgl/shaders/DefaultShader.d.ts +9 -0
  75. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +87 -0
  76. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -0
  77. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.d.ts +10 -0
  78. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +119 -0
  79. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +1 -0
  80. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +29 -0
  81. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +413 -0
  82. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -0
  83. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.d.ts +28 -0
  84. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +131 -0
  85. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -0
  86. package/dist/src/core/renderers/webgl/shaders/SdfShader.d.ts +47 -0
  87. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +160 -0
  88. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -0
  89. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.d.ts +31 -0
  90. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +71 -0
  91. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js.map +1 -0
  92. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.d.ts +30 -0
  93. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +58 -0
  94. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js.map +1 -0
  95. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.d.ts +31 -0
  96. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +71 -0
  97. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js.map +1 -0
  98. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.d.ts +31 -0
  99. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +71 -0
  100. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js.map +1 -0
  101. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.d.ts +31 -0
  102. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +71 -0
  103. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js.map +1 -0
  104. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.d.ts +9 -0
  105. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js +136 -0
  106. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js.map +1 -0
  107. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.d.ts +36 -0
  108. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +85 -0
  109. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js.map +1 -0
  110. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.d.ts +45 -0
  111. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js +104 -0
  112. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js.map +1 -0
  113. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.d.ts +22 -0
  114. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +45 -0
  115. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js.map +1 -0
  116. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.d.ts +58 -0
  117. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +80 -0
  118. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js.map +1 -0
  119. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.d.ts +35 -0
  120. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +129 -0
  121. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +1 -0
  122. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.d.ts +39 -0
  123. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +116 -0
  124. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +1 -0
  125. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.d.ts +61 -0
  126. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +127 -0
  127. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js.map +1 -0
  128. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.d.ts +40 -0
  129. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +71 -0
  130. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js.map +1 -0
  131. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.d.ts +115 -0
  132. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js +61 -0
  133. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js.map +1 -0
  134. package/dist/src/core/shaders/canvas/Border.js +4 -4
  135. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  136. package/dist/src/core/shaders/canvas/HolePunch.js +3 -3
  137. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
  138. package/dist/src/core/shaders/canvas/LinearGradient.js +2 -2
  139. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  140. package/dist/src/core/shaders/canvas/RadialGradient.js +4 -4
  141. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  142. package/dist/src/core/shaders/canvas/Rounded.js +1 -1
  143. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
  144. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +3 -3
  145. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  146. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +3 -3
  147. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  148. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +1 -1
  149. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  150. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +1 -1
  151. package/dist/src/core/shaders/templates/BorderTemplate.js +10 -10
  152. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  153. package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +2 -2
  154. package/dist/src/core/shaders/templates/HolePunchTemplate.js +2 -2
  155. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -1
  156. package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +2 -2
  157. package/dist/src/core/shaders/templates/RadialGradientTemplate.js +2 -2
  158. package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +1 -1
  159. package/dist/src/core/shaders/templates/shaderUtils.d.ts +5 -0
  160. package/dist/src/core/shaders/templates/shaderUtils.js +41 -0
  161. package/dist/src/core/shaders/templates/shaderUtils.js.map +1 -0
  162. package/dist/src/core/shaders/webgl/Border.js +83 -83
  163. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  164. package/dist/src/core/shaders/webgl/Default.js +47 -47
  165. package/dist/src/core/shaders/webgl/DefaultBatched.js +61 -61
  166. package/dist/src/core/shaders/webgl/HolePunch.js +34 -34
  167. package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -1
  168. package/dist/src/core/shaders/webgl/LinearGradient.js +36 -36
  169. package/dist/src/core/shaders/webgl/RadialGradient.js +35 -35
  170. package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -1
  171. package/dist/src/core/shaders/webgl/Rounded.js +72 -72
  172. package/dist/src/core/shaders/webgl/Rounded.js.map +1 -1
  173. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +113 -113
  174. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  175. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +132 -132
  176. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  177. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +55 -55
  178. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
  179. package/dist/src/core/shaders/webgl/SdfShader.js +62 -62
  180. package/dist/src/core/shaders/webgl/Shadow.js +83 -83
  181. package/dist/src/core/shaders/webgl/Spinner.d.ts +1 -0
  182. package/dist/src/core/shaders/webgl/Spinner.js +2 -0
  183. package/dist/src/core/shaders/webgl/Spinner.js.map +1 -0
  184. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +16 -0
  185. package/dist/src/core/text-rendering/CanvasFontHandler.js +29 -0
  186. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -1
  187. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +15 -0
  188. package/dist/src/core/text-rendering/SdfFontHandler.js +34 -2
  189. package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -1
  190. package/dist/src/core/text-rendering/TextRenderer.d.ts +2 -0
  191. package/dist/src/core/text-rendering/TextTextureRendererUtils.js.map +1 -1
  192. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js +2 -2
  193. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js.map +1 -1
  194. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +0 -5
  195. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  196. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -7
  197. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +2 -50
  198. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  199. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +3 -2
  200. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +83 -42
  201. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  202. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +1 -1
  203. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +8 -66
  204. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  205. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +4 -14
  206. package/dist/src/core/text-rendering/renderers/TextRenderer.js +0 -3
  207. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  208. package/dist/src/core/text-rendering/sdf/PeekableGenerator.d.ts +12 -0
  209. package/dist/src/core/text-rendering/sdf/PeekableGenerator.js +61 -0
  210. package/dist/src/core/text-rendering/sdf/PeekableGenerator.js.map +1 -0
  211. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.d.ts +45 -0
  212. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js +69 -0
  213. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js.map +1 -0
  214. package/dist/src/core/textures/ColorTexture.js +1 -1
  215. package/dist/src/core/textures/ColorTexture.js.map +1 -1
  216. package/dist/src/core/textures/ImageTexture.d.ts +2 -2
  217. package/dist/src/core/textures/ImageTexture.js +11 -11
  218. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  219. package/dist/src/core/textures/NoiseTexture.d.ts +2 -2
  220. package/dist/src/core/textures/NoiseTexture.js +6 -6
  221. package/dist/src/core/textures/NoiseTexture.js.map +1 -1
  222. package/dist/src/core/textures/RenderTexture.d.ts +6 -6
  223. package/dist/src/core/textures/RenderTexture.js +10 -10
  224. package/dist/src/core/textures/RenderTexture.js.map +1 -1
  225. package/dist/src/core/textures/SubTexture.d.ts +4 -4
  226. package/dist/src/core/textures/SubTexture.js +8 -8
  227. package/dist/src/core/textures/SubTexture.js.map +1 -1
  228. package/dist/src/core/textures/Texture.d.ts +3 -4
  229. package/dist/src/core/textures/Texture.js +4 -4
  230. package/dist/src/core/textures/Texture.js.map +1 -1
  231. package/dist/src/main-api/DynamicShaderController.d.ts +29 -0
  232. package/dist/src/main-api/DynamicShaderController.js +58 -0
  233. package/dist/src/main-api/DynamicShaderController.js.map +1 -0
  234. package/dist/src/main-api/Inspector.js +7 -7
  235. package/dist/src/main-api/Inspector.js.map +1 -1
  236. package/dist/src/main-api/Renderer.js +2 -2
  237. package/dist/src/main-api/Renderer.js.map +1 -1
  238. package/dist/src/main-api/ShaderController.d.ts +31 -0
  239. package/dist/src/main-api/ShaderController.js +37 -0
  240. package/dist/src/main-api/ShaderController.js.map +1 -0
  241. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  242. package/exports/canvas-shaders.ts +28 -28
  243. package/exports/canvas.ts +45 -45
  244. package/exports/index.ts +82 -82
  245. package/exports/inspector.ts +24 -24
  246. package/exports/utils.ts +50 -50
  247. package/exports/webgl-shaders.ts +28 -28
  248. package/exports/webgl.ts +52 -52
  249. package/package.json +2 -1
  250. package/src/common/CommonTypes.ts +146 -146
  251. package/src/common/EventEmitter.ts +77 -77
  252. package/src/common/IAnimationController.ts +92 -92
  253. package/src/common/IEventEmitter.ts +28 -28
  254. package/src/core/CoreNode.test.ts +202 -202
  255. package/src/core/CoreNode.ts +2481 -2491
  256. package/src/core/CoreShaderManager.ts +188 -188
  257. package/src/core/CoreTextNode.ts +483 -443
  258. package/src/core/CoreTextureManager.ts +565 -565
  259. package/src/core/Stage.ts +906 -906
  260. package/src/core/TextureMemoryManager.ts +445 -445
  261. package/src/core/animations/AnimationManager.ts +38 -38
  262. package/src/core/animations/CoreAnimation.ts +291 -291
  263. package/src/core/animations/CoreAnimationController.ts +166 -166
  264. package/src/core/lib/ContextSpy.ts +41 -41
  265. package/src/core/lib/ImageWorker.ts +286 -286
  266. package/src/core/lib/Matrix3d.ts +244 -244
  267. package/src/core/lib/RenderCoords.ts +71 -71
  268. package/src/core/lib/WebGlContextWrapper.ts +1381 -1381
  269. package/src/core/lib/colorCache.ts +20 -20
  270. package/src/core/lib/colorParser.ts +85 -85
  271. package/src/core/lib/textureCompression.ts +152 -152
  272. package/src/core/lib/textureSvg.ts +78 -78
  273. package/src/core/lib/utils.ts +412 -412
  274. package/src/core/lib/validateImageBitmap.ts +87 -87
  275. package/src/core/platforms/Platform.ts +77 -77
  276. package/src/core/platforms/web/WebPlatform.ts +121 -121
  277. package/src/core/renderers/CoreContextTexture.ts +43 -43
  278. package/src/core/renderers/CoreRenderOp.ts +22 -22
  279. package/src/core/renderers/CoreRenderer.ts +110 -110
  280. package/src/core/renderers/CoreShaderNode.ts +175 -175
  281. package/src/core/renderers/CoreShaderProgram.ts +23 -23
  282. package/src/core/renderers/canvas/CanvasRenderer.ts +283 -283
  283. package/src/core/renderers/canvas/CanvasShaderNode.ts +96 -96
  284. package/src/core/renderers/canvas/CanvasTexture.ts +156 -156
  285. package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +81 -91
  286. package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +95 -50
  287. package/src/core/renderers/webgl/WebGlCtxTexture.ts +301 -310
  288. package/src/core/renderers/webgl/WebGlRenderOp.ts +167 -167
  289. package/src/core/renderers/webgl/WebGlRenderer.ts +746 -747
  290. package/src/core/renderers/webgl/WebGlShaderNode.ts +435 -435
  291. package/src/core/renderers/webgl/WebGlShaderProgram.ts +341 -341
  292. package/src/core/renderers/webgl/internal/BufferCollection.ts +54 -54
  293. package/src/core/renderers/webgl/internal/RendererUtils.ts +155 -155
  294. package/src/core/renderers/webgl/internal/ShaderUtils.ts +281 -281
  295. package/src/core/renderers/webgl/internal/WebGlUtils.ts +35 -35
  296. package/src/core/shaders/canvas/Border.ts +75 -75
  297. package/src/core/shaders/canvas/HolePunch.ts +55 -62
  298. package/src/core/shaders/canvas/LinearGradient.ts +71 -71
  299. package/src/core/shaders/canvas/RadialGradient.ts +99 -99
  300. package/src/core/shaders/canvas/Rounded.ts +55 -55
  301. package/src/core/shaders/canvas/RoundedWithBorder.ts +72 -74
  302. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +88 -90
  303. package/src/core/shaders/canvas/RoundedWithShadow.ts +70 -70
  304. package/src/core/shaders/canvas/Shadow.ts +52 -52
  305. package/src/core/shaders/canvas/utils/render.ts +151 -151
  306. package/src/core/shaders/templates/BorderTemplate.ts +115 -115
  307. package/src/core/shaders/templates/HolePunchTemplate.ts +82 -82
  308. package/src/core/shaders/templates/LinearGradientTemplate.ts +71 -71
  309. package/src/core/shaders/templates/RadialGradientTemplate.ts +81 -81
  310. package/src/core/shaders/templates/RoundedTemplate.ts +98 -98
  311. package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +38 -38
  312. package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +35 -35
  313. package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +35 -35
  314. package/src/core/shaders/templates/ShadowTemplate.ts +106 -106
  315. package/src/core/shaders/utils.ts +46 -46
  316. package/src/core/shaders/webgl/Border.ts +116 -116
  317. package/src/core/shaders/webgl/Default.ts +89 -89
  318. package/src/core/shaders/webgl/DefaultBatched.ts +129 -129
  319. package/src/core/shaders/webgl/HolePunch.ts +75 -75
  320. package/src/core/shaders/webgl/LinearGradient.ts +82 -82
  321. package/src/core/shaders/webgl/RadialGradient.ts +85 -85
  322. package/src/core/shaders/webgl/Rounded.ts +113 -117
  323. package/src/core/shaders/webgl/RoundedWithBorder.ts +151 -155
  324. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +175 -175
  325. package/src/core/shaders/webgl/RoundedWithShadow.ts +94 -98
  326. package/src/core/shaders/webgl/SdfShader.ts +134 -134
  327. package/src/core/shaders/webgl/Shadow.ts +115 -115
  328. package/src/core/text-rendering/CanvasFontHandler.ts +210 -176
  329. package/src/core/text-rendering/CanvasTextRenderer.ts +622 -622
  330. package/src/core/text-rendering/SdfFontHandler.ts +554 -517
  331. package/src/core/text-rendering/SdfTextRenderer.ts +466 -466
  332. package/src/core/text-rendering/TextRenderer.ts +406 -404
  333. package/src/core/text-rendering/Utils.ts +257 -257
  334. package/src/core/text-rendering/canvas/Settings.ts +99 -99
  335. package/src/core/text-rendering/canvas/Utils.test.ts +206 -206
  336. package/src/core/text-rendering/canvas/Utils.ts +178 -178
  337. package/src/core/text-rendering/canvas/calculateRenderInfo.ts +299 -299
  338. package/src/core/text-rendering/canvas/draw.ts +165 -165
  339. package/src/core/text-rendering/sdf/Utils.test.ts +402 -402
  340. package/src/core/text-rendering/sdf/Utils.ts +436 -436
  341. package/src/core/text-rendering/sdf/index.ts +20 -20
  342. package/src/core/textures/ColorTexture.ts +102 -102
  343. package/src/core/textures/ImageTexture.ts +418 -418
  344. package/src/core/textures/NoiseTexture.ts +104 -104
  345. package/src/core/textures/RenderTexture.ts +85 -85
  346. package/src/core/textures/SubTexture.ts +205 -205
  347. package/src/core/textures/Texture.ts +381 -381
  348. package/src/core/utils.ts +227 -227
  349. package/src/env.d.ts +7 -7
  350. package/src/main-api/INode.ts +100 -100
  351. package/src/main-api/Inspector.ts +567 -567
  352. package/src/main-api/Renderer.ts +873 -873
  353. package/src/main-api/utils.ts +45 -45
  354. package/src/utils.ts +267 -267
  355. package/COPYING +0 -1
@@ -1,517 +1,554 @@
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 2025 Comcast Cable Communications Management, LLC.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the License);
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
-
20
- import type {
21
- FontFamilyMap,
22
- FontMetrics,
23
- NormalizedFontMetrics,
24
- TrProps,
25
- FontLoadOptions,
26
- } from './TextRenderer.js';
27
- import type { ImageTexture } from '../textures/ImageTexture.js';
28
- import type { Stage } from '../Stage.js';
29
-
30
- /**
31
- * SDF Font Data structure matching msdf-bmfont-xml output
32
- */
33
- export interface SdfFontData {
34
- pages: string[];
35
- chars: Array<{
36
- id: number;
37
- char: string;
38
- x: number;
39
- y: number;
40
- width: number;
41
- height: number;
42
- xoffset: number;
43
- yoffset: number;
44
- xadvance: number;
45
- page: number;
46
- chnl: number;
47
- }>;
48
-
49
- kernings: Array<{
50
- first: number;
51
- second: number;
52
- amount: number;
53
- }>;
54
- info: {
55
- face: string;
56
- size: number;
57
- bold: number;
58
- italic: number;
59
- charset: string[];
60
- unicode: number;
61
- stretchH: number;
62
- smooth: number;
63
- aa: number;
64
- padding: [number, number, number, number]; // [up, right, down, left]
65
- spacing: [number, number]; // [horizontal, vertical]
66
- outline: number;
67
- };
68
- common: {
69
- lineHeight: number;
70
- base: number;
71
- scaleW: number;
72
- scaleH: number;
73
- pages: number;
74
- packed: number;
75
- alphaChnl: number;
76
- redChnl: number;
77
- greenChnl: number;
78
- blueChnl: number;
79
- };
80
- distanceField: {
81
- // msdf-bmfont-xml uses the string 'sdf' for single-channel SDF.
82
- fieldType: 'sdf' | 'msdf';
83
- distanceRange: number;
84
- };
85
- lightningMetrics?: FontMetrics;
86
- }
87
-
88
- /**
89
- * @typedef {Object} SdfGlyph
90
- * @property {number} id - Glyph ID
91
- * @property {string} char - Character
92
- * @property {number} x - Atlas x position
93
- * @property {number} y - Atlas y position
94
- * @property {number} width - Glyph width
95
- * @property {number} height - Glyph height
96
- * @property {number} xoffset - X offset
97
- * @property {number} yoffset - Y offset
98
- * @property {number} xadvance - Character advance width
99
- * @property {number} page - Page number
100
- * @property {number} chnl - Channel
101
- */
102
-
103
- /**
104
- * @typedef {Object} KerningTable
105
- * Fast lookup table for kerning values
106
- */
107
- type KerningTable = Record<
108
- number,
109
- Record<number, number | undefined> | undefined
110
- >;
111
-
112
- /**
113
- * @typedef {Object} SdfFontCache
114
- * Cached font data for performance
115
- */
116
- interface SdfFontCache {
117
- data: SdfFontData;
118
- glyphMap: Map<number, SdfFontData['chars'][0]>;
119
- kernings: KerningTable;
120
- atlasTexture: ImageTexture;
121
- metrics: NormalizedFontMetrics;
122
- maxCharHeight: number;
123
- }
124
-
125
- //global state variables for SdfFontHandler
126
- const fontCache: Record<string, SdfFontCache> = Object.create(null);
127
- const loadedFonts = new Set<string>();
128
- const fontLoadPromises = new Map<string, Promise<void>>();
129
- let initialized = false;
130
-
131
- /**
132
- * Normalize font metrics to be in the range of 0 to 1
133
- */
134
- const normalizeMetrics = (metrics: FontMetrics): NormalizedFontMetrics => ({
135
- ascender: metrics.ascender / metrics.unitsPerEm,
136
- descender: metrics.descender / metrics.unitsPerEm,
137
- lineGap: metrics.lineGap / metrics.unitsPerEm,
138
- });
139
-
140
- /**
141
- * Build kerning lookup table for fast access
142
- * @param {Array} kernings - Kerning data from font
143
- * @returns {KerningTable} Optimized kerning lookup table
144
- */
145
- const buildKerningTable = (kernings: SdfFontData['kernings']): KerningTable => {
146
- const kerningTable: KerningTable = {};
147
-
148
- let i = 0;
149
- const length = kernings.length;
150
-
151
- while (i < length) {
152
- const kerning = kernings[i];
153
- i++;
154
- if (kerning === undefined) {
155
- continue;
156
- }
157
- const second = kerning.second;
158
-
159
- let firsts = kerningTable[second];
160
- if (firsts === undefined) {
161
- firsts = {};
162
- kerningTable[second] = firsts;
163
- }
164
- firsts[kerning.first] = kerning.amount;
165
- }
166
-
167
- return kerningTable;
168
- };
169
-
170
- /**
171
- * Build glyph map from font data for fast character lookup
172
- * @param {Array} chars - Character data from font
173
- * @returns {Map} Glyph map for character to glyph lookup
174
- */
175
- const buildGlyphMap = (
176
- chars: SdfFontData['chars'],
177
- ): Map<number, SdfFontData['chars'][0]> => {
178
- const glyphMap = new Map<number, SdfFontData['chars'][0]>();
179
- let maxCharHeight = 0;
180
-
181
- let i = 0;
182
- const length = chars.length;
183
-
184
- while (i < length) {
185
- const glyph = chars[i];
186
-
187
- i++;
188
- if (glyph === undefined) {
189
- continue;
190
- }
191
-
192
- glyphMap.set(glyph.id, glyph);
193
-
194
- const charHeight = glyph.yoffset + glyph.height;
195
- if (charHeight > maxCharHeight) {
196
- maxCharHeight = charHeight;
197
- }
198
- }
199
-
200
- return glyphMap;
201
- };
202
-
203
- /**
204
- * Process font data and create optimized cache entry
205
- * @param {string} fontFamily - Font family name
206
- * @param {SdfFontData} fontData - Raw font data
207
- * @param {ImageTexture} atlasTexture - Atlas texture
208
- * @param {FontMetrics} metrics - Font metrics
209
- */
210
- const processFontData = (
211
- fontFamily: string,
212
- fontData: SdfFontData,
213
- atlasTexture: ImageTexture,
214
- metrics?: FontMetrics,
215
- ): void => {
216
- // Build optimized data structures
217
- const glyphMap = buildGlyphMap(fontData.chars);
218
- const kernings = buildKerningTable(fontData.kernings);
219
-
220
- // Calculate max char height
221
- let maxCharHeight = 0;
222
- let i = 0;
223
- const length = fontData.chars.length;
224
-
225
- while (i < length) {
226
- const glyph = fontData.chars[i];
227
- if (glyph !== undefined) {
228
- const charHeight = glyph.yoffset + glyph.height;
229
- if (charHeight > maxCharHeight) {
230
- maxCharHeight = charHeight;
231
- }
232
- }
233
- i++;
234
- }
235
-
236
- // Determine metrics
237
- let normalizedMetrics: NormalizedFontMetrics;
238
-
239
- if (metrics !== undefined) {
240
- normalizedMetrics = normalizeMetrics(metrics);
241
- } else if (fontData.lightningMetrics !== undefined) {
242
- normalizedMetrics = normalizeMetrics(fontData.lightningMetrics);
243
- } else {
244
- console.warn(
245
- `Font metrics not found for SDF font ${fontFamily}. ` +
246
- 'Make sure you are using the latest version of the Lightning ' +
247
- '3 msdf-generator tool to generate your SDF fonts. Using default metrics.',
248
- );
249
- // Use default metrics
250
- normalizedMetrics = {
251
- ascender: 0.8,
252
- descender: -0.2,
253
- lineGap: 0.2,
254
- };
255
- }
256
- // Cache processed data
257
- fontCache[fontFamily] = {
258
- data: fontData,
259
- glyphMap,
260
- kernings,
261
- atlasTexture,
262
- metrics: normalizedMetrics,
263
- maxCharHeight,
264
- };
265
- };
266
-
267
- /**
268
- * Check if the SDF font handler can render a font
269
- * @param {TrProps} trProps - Text rendering properties
270
- * @returns {boolean} True if the font can be rendered
271
- */
272
- export const canRenderFont = (trProps: TrProps): boolean => {
273
- return isFontLoaded(trProps.fontFamily);
274
- };
275
-
276
- /**
277
- * Load SDF font from JSON + PNG atlas
278
- * @param {Object} options - Font loading options
279
- * @param {string} options.fontFamily - Font family name
280
- * @param {string} options.fontUrl - JSON font data URL (atlasDataUrl)
281
- * @param {string} options.atlasUrl - PNG atlas texture URL
282
- * @param {FontMetrics} options.metrics - Optional font metrics
283
- */
284
- export const loadFont = async (
285
- stage: Stage,
286
- options: FontLoadOptions,
287
- ): Promise<void> => {
288
- const { fontFamily, atlasUrl, atlasDataUrl, metrics } = options;
289
-
290
- // Early return if already loaded
291
- if (loadedFonts.has(fontFamily) === true) {
292
- return;
293
- }
294
-
295
- // Early return if already loading
296
- const existingPromise = fontLoadPromises.get(fontFamily);
297
- if (existingPromise !== undefined) {
298
- return existingPromise;
299
- }
300
-
301
- if (atlasDataUrl === undefined) {
302
- throw new Error(
303
- `Atlas data URL must be provided for SDF font: ${fontFamily}`,
304
- );
305
- }
306
-
307
- // Create loading promise
308
- const loadPromise = (async (): Promise<void> => {
309
- // Load font JSON data
310
- const response = await fetch(atlasDataUrl);
311
- if (!response.ok) {
312
- throw new Error(`Failed to load font data: ${response.statusText}`);
313
- }
314
-
315
- const fontData = (await response.json()) as SdfFontData;
316
- if (!fontData || !fontData.chars) {
317
- throw new Error('Invalid SDF font data format');
318
- }
319
-
320
- // Atlas texture should be provided externally
321
- if (!atlasUrl) {
322
- throw new Error('Atlas texture must be provided for SDF fonts');
323
- }
324
-
325
- // Wait for atlas texture to load
326
- return new Promise<void>((resolve, reject) => {
327
- // create new atlas texture using ImageTexture
328
- const atlasTexture = stage.txManager.createTexture('ImageTexture', {
329
- src: atlasUrl,
330
- premultiplyAlpha: false,
331
- });
332
-
333
- atlasTexture.preventCleanup = true; // Prevent automatic cleanup
334
-
335
- if (atlasTexture.state === 'loaded') {
336
- // If already loaded, process immediately
337
- processFontData(fontFamily, fontData, atlasTexture, metrics);
338
- loadedFonts.add(fontFamily);
339
- fontLoadPromises.delete(fontFamily);
340
- return resolve();
341
- }
342
-
343
- atlasTexture.on('loaded', () => {
344
- // Process and cache font data
345
- processFontData(fontFamily, fontData, atlasTexture, metrics);
346
-
347
- // Mark as loaded
348
- loadedFonts.add(fontFamily);
349
- fontLoadPromises.delete(fontFamily);
350
- resolve();
351
- });
352
-
353
- atlasTexture.on('failed', (error: Error) => {
354
- // Cleanup on error
355
- fontLoadPromises.delete(fontFamily);
356
- if (fontCache[fontFamily]) {
357
- delete fontCache[fontFamily];
358
- }
359
- console.error(`Failed to load SDF font: ${fontFamily}`, error);
360
- reject(error);
361
- });
362
-
363
- atlasTexture.setRenderableOwner(stage, true);
364
- });
365
- })();
366
-
367
- fontLoadPromises.set(fontFamily, loadPromise);
368
- return loadPromise;
369
- };
370
-
371
- /**
372
- * Get the font families map for resolving fonts
373
- */
374
- export const getFontFamilies = (): FontFamilyMap => {
375
- const families: FontFamilyMap = {};
376
-
377
- // SDF fonts don't use the traditional FontFamilyMap structure
378
- // Return empty map since SDF fonts are handled differently
379
- return families;
380
- };
381
-
382
- /**
383
- * Initialize the SDF font handler
384
- */
385
- export const init = (
386
- c?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
387
- ): void => {
388
- if (initialized === true) {
389
- return;
390
- }
391
-
392
- initialized = true;
393
- };
394
-
395
- export const type = 'sdf';
396
-
397
- /**
398
- * Check if a font is already loaded by font family
399
- */
400
- export const isFontLoaded = (fontFamily: string): boolean => {
401
- return loadedFonts.has(fontFamily);
402
- };
403
-
404
- /**
405
- * Get normalized font metrics for a font family
406
- */
407
- export const getFontMetrics = (
408
- fontFamily: string,
409
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
410
- fontSize: number,
411
- ): NormalizedFontMetrics => {
412
- const cache = fontCache[fontFamily];
413
- return cache ? cache.metrics : { ascender: 0, descender: 0, lineGap: 0 };
414
- };
415
-
416
- /**
417
- * Set font metrics for a font family
418
- */
419
- export const setFontMetrics = (
420
- fontFamily: string,
421
- metrics: NormalizedFontMetrics,
422
- ): void => {
423
- const cache = fontCache[fontFamily];
424
- if (cache !== undefined) {
425
- cache.metrics = metrics;
426
- }
427
- };
428
-
429
- /**
430
- * Get glyph data for a character in a specific font
431
- * @param {string} fontFamily - Font family name
432
- * @param {number} codepoint - Character codepoint
433
- * @returns {Object|null} Glyph data or null if not found
434
- */
435
- export const getGlyph = (
436
- fontFamily: string,
437
- codepoint: number,
438
- ): SdfFontData['chars'][0] | null => {
439
- const cache = fontCache[fontFamily];
440
- if (cache === undefined) return null;
441
-
442
- return cache.glyphMap.get(codepoint) || cache.glyphMap.get(63) || null; // 63 = '?'
443
- };
444
-
445
- /**
446
- * Get kerning value between two glyphs
447
- * @param {string} fontFamily - Font family name
448
- * @param {number} firstGlyph - First glyph ID
449
- * @param {number} secondGlyph - Second glyph ID
450
- * @returns {number} Kerning value or 0
451
- */
452
- export const getKerning = (
453
- fontFamily: string,
454
- firstGlyph: number,
455
- secondGlyph: number,
456
- ): number => {
457
- const cache = fontCache[fontFamily];
458
- if (cache === undefined) return 0;
459
-
460
- const seconds = cache.kernings[secondGlyph];
461
- return seconds ? seconds[firstGlyph] || 0 : 0;
462
- };
463
-
464
- /**
465
- * Get atlas texture for a font family
466
- * @param {string} fontFamily - Font family name
467
- * @returns {ImageTexture|null} Atlas texture or null
468
- */
469
- export const getAtlas = (fontFamily: string): ImageTexture | null => {
470
- const cache = fontCache[fontFamily];
471
- return cache !== undefined ? cache.atlasTexture : null;
472
- };
473
-
474
- /**
475
- * Get font data for a font family
476
- * @param {string} fontFamily - Font family name
477
- * @returns {SdfFontData|null} Font data or null
478
- */
479
- export const getFontData = (fontFamily: string): SdfFontData | null => {
480
- const cache = fontCache[fontFamily];
481
- return cache !== undefined ? cache.data : null;
482
- };
483
-
484
- /**
485
- * Get maximum character height for a font family
486
- * @param {string} fontFamily - Font family name
487
- * @returns {number} Max character height or 0
488
- */
489
- export const getMaxCharHeight = (fontFamily: string): number => {
490
- const cache = fontCache[fontFamily];
491
- return cache !== undefined ? cache.maxCharHeight : 0;
492
- };
493
-
494
- /**
495
- * Get all loaded font families
496
- * @returns {string[]} Array of font family names
497
- */
498
- export const getLoadedFonts = (): string[] => {
499
- return Array.from(loadedFonts);
500
- };
501
-
502
- /**
503
- * Unload a font and free resources
504
- * @param {string} fontFamily - Font family name
505
- */
506
- export const unloadFont = (fontFamily: string): void => {
507
- const cache = fontCache[fontFamily];
508
- if (cache !== undefined) {
509
- // Free texture if needed
510
- if (typeof cache.atlasTexture.free === 'function') {
511
- cache.atlasTexture.free();
512
- }
513
-
514
- delete fontCache[fontFamily];
515
- loadedFonts.delete(fontFamily);
516
- }
517
- };
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 2025 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ import type {
21
+ FontFamilyMap,
22
+ FontMetrics,
23
+ NormalizedFontMetrics,
24
+ TrProps,
25
+ FontLoadOptions,
26
+ } from './TextRenderer.js';
27
+ import type { ImageTexture } from '../textures/ImageTexture.js';
28
+ import type { Stage } from '../Stage.js';
29
+ import type { CoreTextNode } from '../CoreTextNode.js';
30
+ import { UpdateType } from '../CoreNode.js';
31
+
32
+ /**
33
+ * SDF Font Data structure matching msdf-bmfont-xml output
34
+ */
35
+ export interface SdfFontData {
36
+ pages: string[];
37
+ chars: Array<{
38
+ id: number;
39
+ char: string;
40
+ x: number;
41
+ y: number;
42
+ width: number;
43
+ height: number;
44
+ xoffset: number;
45
+ yoffset: number;
46
+ xadvance: number;
47
+ page: number;
48
+ chnl: number;
49
+ }>;
50
+
51
+ kernings: Array<{
52
+ first: number;
53
+ second: number;
54
+ amount: number;
55
+ }>;
56
+ info: {
57
+ face: string;
58
+ size: number;
59
+ bold: number;
60
+ italic: number;
61
+ charset: string[];
62
+ unicode: number;
63
+ stretchH: number;
64
+ smooth: number;
65
+ aa: number;
66
+ padding: [number, number, number, number]; // [up, right, down, left]
67
+ spacing: [number, number]; // [horizontal, vertical]
68
+ outline: number;
69
+ };
70
+ common: {
71
+ lineHeight: number;
72
+ base: number;
73
+ scaleW: number;
74
+ scaleH: number;
75
+ pages: number;
76
+ packed: number;
77
+ alphaChnl: number;
78
+ redChnl: number;
79
+ greenChnl: number;
80
+ blueChnl: number;
81
+ };
82
+ distanceField: {
83
+ // msdf-bmfont-xml uses the string 'sdf' for single-channel SDF.
84
+ fieldType: 'sdf' | 'msdf';
85
+ distanceRange: number;
86
+ };
87
+ lightningMetrics?: FontMetrics;
88
+ }
89
+
90
+ /**
91
+ * @typedef {Object} SdfGlyph
92
+ * @property {number} id - Glyph ID
93
+ * @property {string} char - Character
94
+ * @property {number} x - Atlas x position
95
+ * @property {number} y - Atlas y position
96
+ * @property {number} width - Glyph width
97
+ * @property {number} height - Glyph height
98
+ * @property {number} xoffset - X offset
99
+ * @property {number} yoffset - Y offset
100
+ * @property {number} xadvance - Character advance width
101
+ * @property {number} page - Page number
102
+ * @property {number} chnl - Channel
103
+ */
104
+
105
+ /**
106
+ * @typedef {Object} KerningTable
107
+ * Fast lookup table for kerning values
108
+ */
109
+ type KerningTable = Record<
110
+ number,
111
+ Record<number, number | undefined> | undefined
112
+ >;
113
+
114
+ /**
115
+ * @typedef {Object} SdfFontCache
116
+ * Cached font data for performance
117
+ */
118
+ interface SdfFontCache {
119
+ data: SdfFontData;
120
+ glyphMap: Map<number, SdfFontData['chars'][0]>;
121
+ kernings: KerningTable;
122
+ atlasTexture: ImageTexture;
123
+ metrics: NormalizedFontMetrics;
124
+ maxCharHeight: number;
125
+ }
126
+
127
+ //global state variables for SdfFontHandler
128
+ const fontCache: Record<string, SdfFontCache> = Object.create(null);
129
+ const loadedFonts = new Set<string>();
130
+ const fontLoadPromises = new Map<string, Promise<void>>();
131
+ const nodesWaitingForFont: Record<string, CoreTextNode[]> = Object.create(null);
132
+ let initialized = false;
133
+
134
+ /**
135
+ * Normalize font metrics to be in the range of 0 to 1
136
+ */
137
+ const normalizeMetrics = (metrics: FontMetrics): NormalizedFontMetrics => ({
138
+ ascender: metrics.ascender / metrics.unitsPerEm,
139
+ descender: metrics.descender / metrics.unitsPerEm,
140
+ lineGap: metrics.lineGap / metrics.unitsPerEm,
141
+ });
142
+
143
+ /**
144
+ * Build kerning lookup table for fast access
145
+ * @param {Array} kernings - Kerning data from font
146
+ * @returns {KerningTable} Optimized kerning lookup table
147
+ */
148
+ const buildKerningTable = (kernings: SdfFontData['kernings']): KerningTable => {
149
+ const kerningTable: KerningTable = {};
150
+
151
+ let i = 0;
152
+ const length = kernings.length;
153
+
154
+ while (i < length) {
155
+ const kerning = kernings[i];
156
+ i++;
157
+ if (kerning === undefined) {
158
+ continue;
159
+ }
160
+ const second = kerning.second;
161
+
162
+ let firsts = kerningTable[second];
163
+ if (firsts === undefined) {
164
+ firsts = {};
165
+ kerningTable[second] = firsts;
166
+ }
167
+ firsts[kerning.first] = kerning.amount;
168
+ }
169
+
170
+ return kerningTable;
171
+ };
172
+
173
+ /**
174
+ * Build glyph map from font data for fast character lookup
175
+ * @param {Array} chars - Character data from font
176
+ * @returns {Map} Glyph map for character to glyph lookup
177
+ */
178
+ const buildGlyphMap = (
179
+ chars: SdfFontData['chars'],
180
+ ): Map<number, SdfFontData['chars'][0]> => {
181
+ const glyphMap = new Map<number, SdfFontData['chars'][0]>();
182
+ let maxCharHeight = 0;
183
+
184
+ let i = 0;
185
+ const length = chars.length;
186
+
187
+ while (i < length) {
188
+ const glyph = chars[i];
189
+
190
+ i++;
191
+ if (glyph === undefined) {
192
+ continue;
193
+ }
194
+
195
+ glyphMap.set(glyph.id, glyph);
196
+
197
+ const charHeight = glyph.yoffset + glyph.height;
198
+ if (charHeight > maxCharHeight) {
199
+ maxCharHeight = charHeight;
200
+ }
201
+ }
202
+
203
+ return glyphMap;
204
+ };
205
+
206
+ /**
207
+ * Process font data and create optimized cache entry
208
+ * @param {string} fontFamily - Font family name
209
+ * @param {SdfFontData} fontData - Raw font data
210
+ * @param {ImageTexture} atlasTexture - Atlas texture
211
+ * @param {FontMetrics} metrics - Font metrics
212
+ */
213
+ const processFontData = (
214
+ fontFamily: string,
215
+ fontData: SdfFontData,
216
+ atlasTexture: ImageTexture,
217
+ metrics?: FontMetrics,
218
+ ): void => {
219
+ // Build optimized data structures
220
+ const glyphMap = buildGlyphMap(fontData.chars);
221
+ const kernings = buildKerningTable(fontData.kernings);
222
+
223
+ // Calculate max char height
224
+ let maxCharHeight = 0;
225
+ let i = 0;
226
+ const length = fontData.chars.length;
227
+
228
+ while (i < length) {
229
+ const glyph = fontData.chars[i];
230
+ if (glyph !== undefined) {
231
+ const charHeight = glyph.yoffset + glyph.height;
232
+ if (charHeight > maxCharHeight) {
233
+ maxCharHeight = charHeight;
234
+ }
235
+ }
236
+ i++;
237
+ }
238
+
239
+ // Determine metrics
240
+ let normalizedMetrics: NormalizedFontMetrics;
241
+
242
+ if (metrics !== undefined) {
243
+ normalizedMetrics = normalizeMetrics(metrics);
244
+ } else if (fontData.lightningMetrics !== undefined) {
245
+ normalizedMetrics = normalizeMetrics(fontData.lightningMetrics);
246
+ } else {
247
+ console.warn(
248
+ `Font metrics not found for SDF font ${fontFamily}. ` +
249
+ 'Make sure you are using the latest version of the Lightning ' +
250
+ '3 msdf-generator tool to generate your SDF fonts. Using default metrics.',
251
+ );
252
+ // Use default metrics
253
+ normalizedMetrics = {
254
+ ascender: 0.8,
255
+ descender: -0.2,
256
+ lineGap: 0.2,
257
+ };
258
+ }
259
+ // Cache processed data
260
+ fontCache[fontFamily] = {
261
+ data: fontData,
262
+ glyphMap,
263
+ kernings,
264
+ atlasTexture,
265
+ metrics: normalizedMetrics,
266
+ maxCharHeight,
267
+ };
268
+ };
269
+
270
+ /**
271
+ * Check if the SDF font handler can render a font
272
+ * @param {TrProps} trProps - Text rendering properties
273
+ * @returns {boolean} True if the font can be rendered
274
+ */
275
+ export const canRenderFont = (trProps: TrProps): boolean => {
276
+ return (
277
+ isFontLoaded(trProps.fontFamily) || fontLoadPromises.has(trProps.fontFamily)
278
+ );
279
+ };
280
+
281
+ /**
282
+ * Load SDF font from JSON + PNG atlas
283
+ * @param {Object} options - Font loading options
284
+ * @param {string} options.fontFamily - Font family name
285
+ * @param {string} options.fontUrl - JSON font data URL (atlasDataUrl)
286
+ * @param {string} options.atlasUrl - PNG atlas texture URL
287
+ * @param {FontMetrics} options.metrics - Optional font metrics
288
+ */
289
+ export const loadFont = async (
290
+ stage: Stage,
291
+ options: FontLoadOptions,
292
+ ): Promise<void> => {
293
+ const { fontFamily, atlasUrl, atlasDataUrl, metrics } = options;
294
+ // Early return if already loaded
295
+ if (loadedFonts.has(fontFamily) === true) {
296
+ return;
297
+ }
298
+
299
+ // Early return if already loading
300
+ const existingPromise = fontLoadPromises.get(fontFamily);
301
+ if (existingPromise !== undefined) {
302
+ return existingPromise;
303
+ }
304
+
305
+ if (atlasDataUrl === undefined) {
306
+ throw new Error(
307
+ `Atlas data URL must be provided for SDF font: ${fontFamily}`,
308
+ );
309
+ }
310
+
311
+ const nwff: CoreTextNode[] = (nodesWaitingForFont[fontFamily] = []);
312
+ // Create loading promise
313
+ const loadPromise = (async (): Promise<void> => {
314
+ // Load font JSON data
315
+ const response = await fetch(atlasDataUrl);
316
+ if (!response.ok) {
317
+ throw new Error(`Failed to load font data: ${response.statusText}`);
318
+ }
319
+
320
+ const fontData = (await response.json()) as SdfFontData;
321
+ if (!fontData || !fontData.chars) {
322
+ throw new Error('Invalid SDF font data format');
323
+ }
324
+
325
+ // Atlas texture should be provided externally
326
+ if (!atlasUrl) {
327
+ throw new Error('Atlas texture must be provided for SDF fonts');
328
+ }
329
+
330
+ // Wait for atlas texture to load
331
+ return new Promise<void>((resolve, reject) => {
332
+ // create new atlas texture using ImageTexture
333
+ const atlasTexture = stage.txManager.createTexture('ImageTexture', {
334
+ src: atlasUrl,
335
+ premultiplyAlpha: false,
336
+ });
337
+
338
+ atlasTexture.setRenderableOwner(this, true);
339
+ atlasTexture.preventCleanup = true; // Prevent automatic cleanup
340
+
341
+ if (atlasTexture.state === 'loaded') {
342
+ // If already loaded, process immediately
343
+ processFontData(fontFamily, fontData, atlasTexture, metrics);
344
+ loadedFonts.add(fontFamily);
345
+ fontLoadPromises.delete(fontFamily);
346
+
347
+ for (let key in nwff) {
348
+ nwff[key]!.setUpdateType(UpdateType.Local);
349
+ }
350
+ delete nodesWaitingForFont[fontFamily];
351
+ return resolve();
352
+ }
353
+
354
+ atlasTexture.on('loaded', () => {
355
+ // Process and cache font data
356
+ processFontData(fontFamily, fontData, atlasTexture, metrics);
357
+
358
+ // Mark as loaded
359
+ loadedFonts.add(fontFamily);
360
+ fontLoadPromises.delete(fontFamily);
361
+
362
+ for (let key in nwff) {
363
+ nwff[key]!.setUpdateType(UpdateType.Local);
364
+ }
365
+ delete nodesWaitingForFont[fontFamily];
366
+ resolve();
367
+ });
368
+
369
+ atlasTexture.on('failed', (error: Error) => {
370
+ // Cleanup on error
371
+ fontLoadPromises.delete(fontFamily);
372
+ if (fontCache[fontFamily]) {
373
+ delete fontCache[fontFamily];
374
+ }
375
+ console.error(`Failed to load SDF font: ${fontFamily}`, error);
376
+ reject(error);
377
+ });
378
+ });
379
+ })();
380
+
381
+ fontLoadPromises.set(fontFamily, loadPromise);
382
+ return loadPromise;
383
+ };
384
+
385
+ /**
386
+ * Stop waiting for a font to load
387
+ * @param {string} fontFamily - Font family name
388
+ * @param {CoreTextNode} node - Node that was waiting for the font
389
+ */
390
+ export const waitingForFont = (fontFamily: string, node: CoreTextNode) => {
391
+ nodesWaitingForFont[fontFamily]![node.id] = node;
392
+ };
393
+
394
+ /**
395
+ * Stop waiting for a font to load
396
+ *
397
+ * @param fontFamily
398
+ * @param node
399
+ * @returns
400
+ */
401
+ export const stopWaitingForFont = (fontFamily: string, node: CoreTextNode) => {
402
+ if (nodesWaitingForFont[fontFamily] === undefined) {
403
+ return;
404
+ }
405
+ delete nodesWaitingForFont[fontFamily][node.id];
406
+ };
407
+
408
+ /**
409
+ * Get the font families map for resolving fonts
410
+ */
411
+ export const getFontFamilies = (): FontFamilyMap => {
412
+ const families: FontFamilyMap = {};
413
+
414
+ // SDF fonts don't use the traditional FontFamilyMap structure
415
+ // Return empty map since SDF fonts are handled differently
416
+ return families;
417
+ };
418
+
419
+ /**
420
+ * Initialize the SDF font handler
421
+ */
422
+ export const init = (
423
+ c?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
424
+ ): void => {
425
+ if (initialized === true) {
426
+ return;
427
+ }
428
+
429
+ initialized = true;
430
+ };
431
+
432
+ export const type = 'sdf';
433
+
434
+ /**
435
+ * Check if a font is already loaded by font family
436
+ */
437
+ export const isFontLoaded = (fontFamily: string): boolean => {
438
+ return loadedFonts.has(fontFamily);
439
+ };
440
+
441
+ /**
442
+ * Get normalized font metrics for a font family
443
+ */
444
+ export const getFontMetrics = (
445
+ fontFamily: string,
446
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
447
+ fontSize: number,
448
+ ): NormalizedFontMetrics => {
449
+ const cache = fontCache[fontFamily];
450
+ return cache ? cache.metrics : { ascender: 0, descender: 0, lineGap: 0 };
451
+ };
452
+
453
+ /**
454
+ * Set font metrics for a font family
455
+ */
456
+ export const setFontMetrics = (
457
+ fontFamily: string,
458
+ metrics: NormalizedFontMetrics,
459
+ ): void => {
460
+ const cache = fontCache[fontFamily];
461
+ if (cache !== undefined) {
462
+ cache.metrics = metrics;
463
+ }
464
+ };
465
+
466
+ /**
467
+ * Get glyph data for a character in a specific font
468
+ * @param {string} fontFamily - Font family name
469
+ * @param {number} codepoint - Character codepoint
470
+ * @returns {Object|null} Glyph data or null if not found
471
+ */
472
+ export const getGlyph = (
473
+ fontFamily: string,
474
+ codepoint: number,
475
+ ): SdfFontData['chars'][0] | null => {
476
+ const cache = fontCache[fontFamily];
477
+ if (cache === undefined) return null;
478
+
479
+ return cache.glyphMap.get(codepoint) || cache.glyphMap.get(63) || null; // 63 = '?'
480
+ };
481
+
482
+ /**
483
+ * Get kerning value between two glyphs
484
+ * @param {string} fontFamily - Font family name
485
+ * @param {number} firstGlyph - First glyph ID
486
+ * @param {number} secondGlyph - Second glyph ID
487
+ * @returns {number} Kerning value or 0
488
+ */
489
+ export const getKerning = (
490
+ fontFamily: string,
491
+ firstGlyph: number,
492
+ secondGlyph: number,
493
+ ): number => {
494
+ const cache = fontCache[fontFamily];
495
+ if (cache === undefined) return 0;
496
+
497
+ const seconds = cache.kernings[secondGlyph];
498
+ return seconds ? seconds[firstGlyph] || 0 : 0;
499
+ };
500
+
501
+ /**
502
+ * Get atlas texture for a font family
503
+ * @param {string} fontFamily - Font family name
504
+ * @returns {ImageTexture|null} Atlas texture or null
505
+ */
506
+ export const getAtlas = (fontFamily: string): ImageTexture | null => {
507
+ const cache = fontCache[fontFamily];
508
+ return cache !== undefined ? cache.atlasTexture : null;
509
+ };
510
+
511
+ /**
512
+ * Get font data for a font family
513
+ * @param {string} fontFamily - Font family name
514
+ * @returns {SdfFontData|null} Font data or null
515
+ */
516
+ export const getFontData = (fontFamily: string): SdfFontData | null => {
517
+ const cache = fontCache[fontFamily];
518
+ return cache !== undefined ? cache.data : null;
519
+ };
520
+
521
+ /**
522
+ * Get maximum character height for a font family
523
+ * @param {string} fontFamily - Font family name
524
+ * @returns {number} Max character height or 0
525
+ */
526
+ export const getMaxCharHeight = (fontFamily: string): number => {
527
+ const cache = fontCache[fontFamily];
528
+ return cache !== undefined ? cache.maxCharHeight : 0;
529
+ };
530
+
531
+ /**
532
+ * Get all loaded font families
533
+ * @returns {string[]} Array of font family names
534
+ */
535
+ export const getLoadedFonts = (): string[] => {
536
+ return Array.from(loadedFonts);
537
+ };
538
+
539
+ /**
540
+ * Unload a font and free resources
541
+ * @param {string} fontFamily - Font family name
542
+ */
543
+ export const unloadFont = (fontFamily: string): void => {
544
+ const cache = fontCache[fontFamily];
545
+ if (cache !== undefined) {
546
+ // Free texture if needed
547
+ if (typeof cache.atlasTexture.free === 'function') {
548
+ cache.atlasTexture.free();
549
+ }
550
+
551
+ delete fontCache[fontFamily];
552
+ loadedFonts.delete(fontFamily);
553
+ }
554
+ };