@codexo/exojs 0.8.3 → 0.9.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 (317) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/README.md +26 -5
  3. package/dist/esm/animation/Tween.d.ts +20 -3
  4. package/dist/esm/animation/Tween.js +16 -8
  5. package/dist/esm/animation/Tween.js.map +1 -1
  6. package/dist/esm/animation/TweenManager.d.ts +16 -1
  7. package/dist/esm/animation/TweenManager.js +27 -2
  8. package/dist/esm/animation/TweenManager.js.map +1 -1
  9. package/dist/esm/audio/AudioAnalyser.d.ts +2 -0
  10. package/dist/esm/audio/AudioAnalyser.js +24 -9
  11. package/dist/esm/audio/AudioAnalyser.js.map +1 -1
  12. package/dist/esm/audio/AudioBus.d.ts +1 -0
  13. package/dist/esm/audio/AudioBus.js +8 -4
  14. package/dist/esm/audio/AudioBus.js.map +1 -1
  15. package/dist/esm/audio/AudioListener.d.ts +1 -0
  16. package/dist/esm/audio/AudioListener.js +7 -5
  17. package/dist/esm/audio/AudioListener.js.map +1 -1
  18. package/dist/esm/audio/AudioManager.d.ts +8 -2
  19. package/dist/esm/audio/AudioManager.js +14 -1
  20. package/dist/esm/audio/AudioManager.js.map +1 -1
  21. package/dist/esm/audio/BeatDetector.d.ts +2 -0
  22. package/dist/esm/audio/BeatDetector.js +27 -661
  23. package/dist/esm/audio/BeatDetector.js.map +1 -1
  24. package/dist/esm/audio/Music.d.ts +1 -0
  25. package/dist/esm/audio/Music.js +7 -3
  26. package/dist/esm/audio/Music.js.map +1 -1
  27. package/dist/esm/audio/OscillatorSound.d.ts +1 -0
  28. package/dist/esm/audio/OscillatorSound.js +7 -3
  29. package/dist/esm/audio/OscillatorSound.js.map +1 -1
  30. package/dist/esm/audio/Sound.d.ts +1 -0
  31. package/dist/esm/audio/Sound.js +7 -3
  32. package/dist/esm/audio/Sound.js.map +1 -1
  33. package/dist/esm/audio/audio-context.d.ts +2 -2
  34. package/dist/esm/audio/audio-context.js +4 -4
  35. package/dist/esm/audio/audio-context.js.map +1 -1
  36. package/dist/esm/audio/filters/ChorusFilter.d.ts +1 -0
  37. package/dist/esm/audio/filters/ChorusFilter.js +7 -3
  38. package/dist/esm/audio/filters/ChorusFilter.js.map +1 -1
  39. package/dist/esm/audio/filters/CompressorFilter.d.ts +1 -0
  40. package/dist/esm/audio/filters/CompressorFilter.js +7 -3
  41. package/dist/esm/audio/filters/CompressorFilter.js.map +1 -1
  42. package/dist/esm/audio/filters/DelayFilter.d.ts +1 -0
  43. package/dist/esm/audio/filters/DelayFilter.js +7 -3
  44. package/dist/esm/audio/filters/DelayFilter.js.map +1 -1
  45. package/dist/esm/audio/filters/EqualizerFilter.d.ts +1 -0
  46. package/dist/esm/audio/filters/EqualizerFilter.js +7 -3
  47. package/dist/esm/audio/filters/EqualizerFilter.js.map +1 -1
  48. package/dist/esm/audio/filters/GranularFilter.js +1 -86
  49. package/dist/esm/audio/filters/GranularFilter.js.map +1 -1
  50. package/dist/esm/audio/filters/HighpassFilter.d.ts +1 -0
  51. package/dist/esm/audio/filters/HighpassFilter.js +7 -3
  52. package/dist/esm/audio/filters/HighpassFilter.js.map +1 -1
  53. package/dist/esm/audio/filters/LowpassFilter.d.ts +1 -0
  54. package/dist/esm/audio/filters/LowpassFilter.js +7 -3
  55. package/dist/esm/audio/filters/LowpassFilter.js.map +1 -1
  56. package/dist/esm/audio/filters/PitchShiftFilter.js +1 -71
  57. package/dist/esm/audio/filters/PitchShiftFilter.js.map +1 -1
  58. package/dist/esm/audio/filters/ReverbFilter.d.ts +1 -0
  59. package/dist/esm/audio/filters/ReverbFilter.js +7 -3
  60. package/dist/esm/audio/filters/ReverbFilter.js.map +1 -1
  61. package/dist/esm/audio/filters/VocoderFilter.js +1 -89
  62. package/dist/esm/audio/filters/VocoderFilter.js.map +1 -1
  63. package/dist/esm/audio/filters/WorkletFilter.d.ts +2 -0
  64. package/dist/esm/audio/filters/WorkletFilter.js +10 -5
  65. package/dist/esm/audio/filters/WorkletFilter.js.map +1 -1
  66. package/dist/esm/audio/index.d.ts +15 -10
  67. package/dist/esm/audio/worklet/registerWorklet.d.ts +1 -1
  68. package/dist/esm/audio/worklet/registerWorklet.js +2 -2
  69. package/dist/esm/audio/worklet/registerWorklet.js.map +1 -1
  70. package/dist/esm/audio/worklets/beat-detector.worklet.d.ts +1 -0
  71. package/dist/esm/audio/worklets/beat-detector.worklet.js +647 -0
  72. package/dist/esm/audio/worklets/beat-detector.worklet.js.map +1 -0
  73. package/dist/esm/audio/worklets/granular.worklet.d.ts +1 -0
  74. package/dist/esm/audio/worklets/granular.worklet.js +89 -0
  75. package/dist/esm/audio/worklets/granular.worklet.js.map +1 -0
  76. package/dist/esm/audio/worklets/pitch-shift.worklet.d.ts +1 -0
  77. package/dist/esm/audio/worklets/pitch-shift.worklet.js +74 -0
  78. package/dist/esm/audio/worklets/pitch-shift.worklet.js.map +1 -0
  79. package/dist/esm/audio/worklets/vocoder.worklet.d.ts +1 -0
  80. package/dist/esm/audio/worklets/vocoder.worklet.js +92 -0
  81. package/dist/esm/audio/worklets/vocoder.worklet.js.map +1 -0
  82. package/dist/esm/core/Application.d.ts +62 -24
  83. package/dist/esm/core/Application.js +116 -40
  84. package/dist/esm/core/Application.js.map +1 -1
  85. package/dist/esm/core/Color.d.ts +0 -8
  86. package/dist/esm/core/Color.js +0 -24
  87. package/dist/esm/core/Color.js.map +1 -1
  88. package/dist/esm/core/Scene.d.ts +32 -72
  89. package/dist/esm/core/Scene.js +56 -36
  90. package/dist/esm/core/Scene.js.map +1 -1
  91. package/dist/esm/core/SceneManager.d.ts +11 -25
  92. package/dist/esm/core/SceneManager.js +37 -100
  93. package/dist/esm/core/SceneManager.js.map +1 -1
  94. package/dist/esm/core/SceneNode.d.ts +28 -14
  95. package/dist/esm/core/SceneNode.js +66 -33
  96. package/dist/esm/core/SceneNode.js.map +1 -1
  97. package/dist/esm/core/Signal.d.ts +24 -28
  98. package/dist/esm/core/Signal.js +64 -50
  99. package/dist/esm/core/Signal.js.map +1 -1
  100. package/dist/esm/core/Timer.d.ts +1 -0
  101. package/dist/esm/core/Timer.js +3 -0
  102. package/dist/esm/core/Timer.js.map +1 -1
  103. package/dist/esm/debug/BoundingBoxesLayer.js +1 -1
  104. package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
  105. package/dist/esm/debug/HitTestLayer.js +1 -1
  106. package/dist/esm/debug/HitTestLayer.js.map +1 -1
  107. package/dist/esm/debug/PerformanceLayer.js +1 -2
  108. package/dist/esm/debug/PerformanceLayer.js.map +1 -1
  109. package/dist/esm/debug/PointerStackLayer.js +1 -2
  110. package/dist/esm/debug/PointerStackLayer.js.map +1 -1
  111. package/dist/esm/debug/RenderPassInspectorLayer.js +1 -2
  112. package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -1
  113. package/dist/esm/index.js +23 -7
  114. package/dist/esm/index.js.map +1 -1
  115. package/dist/esm/input/InputManager.d.ts +1 -0
  116. package/dist/esm/input/InputManager.js +30 -3
  117. package/dist/esm/input/InputManager.js.map +1 -1
  118. package/dist/esm/input/InteractionManager.d.ts +5 -2
  119. package/dist/esm/input/InteractionManager.js +29 -18
  120. package/dist/esm/input/InteractionManager.js.map +1 -1
  121. package/dist/esm/input/Pointer.js +3 -2
  122. package/dist/esm/input/Pointer.js.map +1 -1
  123. package/dist/esm/input/internal/interactionManagerRegistry.d.ts +9 -0
  124. package/dist/esm/input/internal/interactionManagerRegistry.js +10 -0
  125. package/dist/esm/input/internal/interactionManagerRegistry.js.map +1 -0
  126. package/dist/esm/math/AbstractVector.d.ts +1 -7
  127. package/dist/esm/math/AbstractVector.js +6 -20
  128. package/dist/esm/math/AbstractVector.js.map +1 -1
  129. package/dist/esm/math/Circle.js +0 -2
  130. package/dist/esm/math/Circle.js.map +1 -1
  131. package/dist/esm/math/Collision.d.ts +9 -3
  132. package/dist/esm/math/Ellipse.d.ts +2 -5
  133. package/dist/esm/math/Ellipse.js +10 -7
  134. package/dist/esm/math/Ellipse.js.map +1 -1
  135. package/dist/esm/math/ObservableVector.d.ts +1 -1
  136. package/dist/esm/math/ObservableVector.js +3 -3
  137. package/dist/esm/math/ObservableVector.js.map +1 -1
  138. package/dist/esm/math/Polygon.d.ts +0 -2
  139. package/dist/esm/math/Polygon.js +1 -9
  140. package/dist/esm/math/Polygon.js.map +1 -1
  141. package/dist/esm/math/Rectangle.js +0 -2
  142. package/dist/esm/math/Rectangle.js.map +1 -1
  143. package/dist/esm/math/collision-detection.d.ts +19 -4
  144. package/dist/esm/math/collision-detection.js +61 -4
  145. package/dist/esm/math/collision-detection.js.map +1 -1
  146. package/dist/esm/math/swept-collision.d.ts +16 -12
  147. package/dist/esm/math/swept-collision.js +109 -19
  148. package/dist/esm/math/swept-collision.js.map +1 -1
  149. package/dist/esm/particles/ParticleSystem.js +1 -1
  150. package/dist/esm/particles/ParticleSystem.js.map +1 -1
  151. package/dist/esm/particles/index.d.ts +1 -0
  152. package/dist/esm/rendering/CallbackRenderPass.d.ts +1 -0
  153. package/dist/esm/rendering/CallbackRenderPass.js +1 -0
  154. package/dist/esm/rendering/CallbackRenderPass.js.map +1 -1
  155. package/dist/esm/rendering/Container.d.ts +2 -1
  156. package/dist/esm/rendering/Container.js +17 -16
  157. package/dist/esm/rendering/Container.js.map +1 -1
  158. package/dist/esm/rendering/RenderBackend.d.ts +1 -0
  159. package/dist/esm/rendering/RenderNode.d.ts +1 -3
  160. package/dist/esm/rendering/RenderNode.js +12 -19
  161. package/dist/esm/rendering/RenderNode.js.map +1 -1
  162. package/dist/esm/rendering/RenderPass.d.ts +1 -0
  163. package/dist/esm/rendering/RenderStats.d.ts +9 -0
  164. package/dist/esm/rendering/RenderStats.js +2 -0
  165. package/dist/esm/rendering/RenderStats.js.map +1 -1
  166. package/dist/esm/rendering/RendererRegistry.d.ts +1 -0
  167. package/dist/esm/rendering/RendererRegistry.js +1 -0
  168. package/dist/esm/rendering/RendererRegistry.js.map +1 -1
  169. package/dist/esm/rendering/View.d.ts +23 -0
  170. package/dist/esm/rendering/View.js +42 -0
  171. package/dist/esm/rendering/View.js.map +1 -1
  172. package/dist/esm/rendering/index.d.ts +89 -59
  173. package/dist/esm/rendering/mesh/Mesh.js +1 -1
  174. package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
  175. package/dist/esm/rendering/mesh/MeshShader.d.ts +1 -0
  176. package/dist/esm/rendering/mesh/MeshShader.js +1 -0
  177. package/dist/esm/rendering/mesh/MeshShader.js.map +1 -1
  178. package/dist/esm/rendering/shader/Shader.d.ts +1 -0
  179. package/dist/esm/rendering/shader/Shader.js +1 -0
  180. package/dist/esm/rendering/shader/Shader.js.map +1 -1
  181. package/dist/esm/rendering/shader/ShaderUniform.d.ts +1 -0
  182. package/dist/esm/rendering/shader/ShaderUniform.js +1 -0
  183. package/dist/esm/rendering/shader/ShaderUniform.js.map +1 -1
  184. package/dist/esm/rendering/sprite/Sprite.d.ts +3 -2
  185. package/dist/esm/rendering/sprite/Sprite.js +15 -13
  186. package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
  187. package/dist/esm/rendering/text/AbstractText.d.ts +36 -0
  188. package/dist/esm/rendering/text/AbstractText.js +49 -0
  189. package/dist/esm/rendering/text/AbstractText.js.map +1 -0
  190. package/dist/esm/rendering/text/BitmapText.d.ts +97 -0
  191. package/dist/esm/rendering/text/BitmapText.js +220 -0
  192. package/dist/esm/rendering/text/BitmapText.js.map +1 -0
  193. package/dist/esm/rendering/text/BmFont.d.ts +50 -0
  194. package/dist/esm/rendering/text/BmFont.js +24 -0
  195. package/dist/esm/rendering/text/BmFont.js.map +1 -0
  196. package/dist/esm/rendering/text/GlyphAtlas.d.ts +104 -0
  197. package/dist/esm/rendering/text/GlyphAtlas.js +347 -0
  198. package/dist/esm/rendering/text/GlyphAtlas.js.map +1 -0
  199. package/dist/esm/rendering/text/GlyphAtlasPool.d.ts +40 -0
  200. package/dist/esm/rendering/text/GlyphAtlasPool.js +67 -0
  201. package/dist/esm/rendering/text/GlyphAtlasPool.js.map +1 -0
  202. package/dist/esm/rendering/text/GlyphSdf.d.ts +92 -0
  203. package/dist/esm/rendering/text/GlyphSdf.js +220 -0
  204. package/dist/esm/rendering/text/GlyphSdf.js.map +1 -0
  205. package/dist/esm/rendering/text/HTMLText.d.ts +107 -0
  206. package/dist/esm/rendering/text/HTMLText.js +284 -0
  207. package/dist/esm/rendering/text/HTMLText.js.map +1 -0
  208. package/dist/esm/rendering/text/LayoutOptions.d.ts +30 -0
  209. package/dist/esm/rendering/text/Text.d.ts +89 -20
  210. package/dist/esm/rendering/text/Text.js +176 -101
  211. package/dist/esm/rendering/text/Text.js.map +1 -1
  212. package/dist/esm/rendering/text/TextLayout.d.ts +20 -8
  213. package/dist/esm/rendering/text/TextLayout.js +234 -25
  214. package/dist/esm/rendering/text/TextLayout.js.map +1 -1
  215. package/dist/esm/rendering/text/TextStyle.d.ts +154 -87
  216. package/dist/esm/rendering/text/TextStyle.js +257 -203
  217. package/dist/esm/rendering/text/TextStyle.js.map +1 -1
  218. package/dist/esm/rendering/text/types.d.ts +73 -13
  219. package/dist/esm/rendering/texture/Texture.d.ts +1 -0
  220. package/dist/esm/rendering/texture/Texture.js +1 -0
  221. package/dist/esm/rendering/texture/Texture.js.map +1 -1
  222. package/dist/esm/rendering/types.d.ts +3 -1
  223. package/dist/esm/rendering/types.js +2 -0
  224. package/dist/esm/rendering/types.js.map +1 -1
  225. package/dist/esm/rendering/video/Video.d.ts +2 -1
  226. package/dist/esm/rendering/video/Video.js +9 -5
  227. package/dist/esm/rendering/video/Video.js.map +1 -1
  228. package/dist/esm/rendering/webgl2/WebGl2Backend.js +41 -5
  229. package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
  230. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js +4 -4
  231. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js.map +1 -1
  232. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.d.ts +56 -0
  233. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js +482 -0
  234. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js.map +1 -0
  235. package/dist/esm/rendering/webgl2/glsl/text-color.frag.js +4 -0
  236. package/dist/esm/rendering/webgl2/glsl/text-color.frag.js.map +1 -0
  237. package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js +4 -0
  238. package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js.map +1 -0
  239. package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js +4 -0
  240. package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js.map +1 -0
  241. package/dist/esm/rendering/webgl2/glsl/text.vert.js +4 -0
  242. package/dist/esm/rendering/webgl2/glsl/text.vert.js.map +1 -0
  243. package/dist/esm/rendering/webgpu/WebGpuBackend.js +16 -8
  244. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  245. package/dist/esm/rendering/webgpu/WebGpuBlendState.js +26 -0
  246. package/dist/esm/rendering/webgpu/WebGpuBlendState.js.map +1 -1
  247. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +2 -2
  248. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +23 -15
  249. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
  250. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +9 -1
  251. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
  252. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts +70 -0
  253. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js +773 -0
  254. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js.map +1 -0
  255. package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js +96 -0
  256. package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js.map +1 -0
  257. package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js +68 -0
  258. package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js.map +1 -0
  259. package/dist/esm/resources/Asset.d.ts +23 -0
  260. package/dist/esm/resources/Asset.js +23 -0
  261. package/dist/esm/resources/Asset.js.map +1 -0
  262. package/dist/esm/resources/AssetDefinitions.d.ts +137 -0
  263. package/dist/esm/resources/Assets.d.ts +35 -0
  264. package/dist/esm/resources/Assets.js +32 -0
  265. package/dist/esm/resources/Assets.js.map +1 -0
  266. package/dist/esm/resources/IndexedDbDatabase.js +17 -1
  267. package/dist/esm/resources/IndexedDbDatabase.js.map +1 -1
  268. package/dist/esm/resources/IndexedDbStore.js +17 -1
  269. package/dist/esm/resources/IndexedDbStore.js.map +1 -1
  270. package/dist/esm/resources/Loader.d.ts +244 -18
  271. package/dist/esm/resources/Loader.js +456 -50
  272. package/dist/esm/resources/Loader.js.map +1 -1
  273. package/dist/esm/resources/LoadingQueue.d.ts +28 -0
  274. package/dist/esm/resources/LoadingQueue.js +59 -0
  275. package/dist/esm/resources/LoadingQueue.js.map +1 -0
  276. package/dist/esm/resources/factories/BmFontFactory.d.ts +25 -0
  277. package/dist/esm/resources/factories/BmFontFactory.js +96 -0
  278. package/dist/esm/resources/factories/BmFontFactory.js.map +1 -0
  279. package/dist/esm/resources/factories/CsvFactory.d.ts +35 -0
  280. package/dist/esm/resources/factories/CsvFactory.js +87 -0
  281. package/dist/esm/resources/factories/CsvFactory.js.map +1 -0
  282. package/dist/esm/resources/factories/MusicFactory.d.ts +8 -2
  283. package/dist/esm/resources/factories/MusicFactory.js +25 -14
  284. package/dist/esm/resources/factories/MusicFactory.js.map +1 -1
  285. package/dist/esm/resources/factories/SoundFactory.d.ts +2 -2
  286. package/dist/esm/resources/factories/SoundFactory.js.map +1 -1
  287. package/dist/esm/resources/factories/SubtitleFactory.d.ts +28 -0
  288. package/dist/esm/resources/factories/SubtitleFactory.js +203 -0
  289. package/dist/esm/resources/factories/SubtitleFactory.js.map +1 -0
  290. package/dist/esm/resources/factories/SvgFactory.d.ts +18 -1
  291. package/dist/esm/resources/factories/SvgFactory.js +21 -2
  292. package/dist/esm/resources/factories/SvgFactory.js.map +1 -1
  293. package/dist/esm/resources/factories/VideoFactory.d.ts +8 -2
  294. package/dist/esm/resources/factories/VideoFactory.js +27 -20
  295. package/dist/esm/resources/factories/VideoFactory.js.map +1 -1
  296. package/dist/esm/resources/factories/XmlFactory.d.ts +24 -0
  297. package/dist/esm/resources/factories/XmlFactory.js +37 -0
  298. package/dist/esm/resources/factories/XmlFactory.js.map +1 -0
  299. package/dist/esm/resources/index.d.ts +8 -1
  300. package/dist/esm/resources/tokens.d.ts +49 -3
  301. package/dist/esm/resources/tokens.js +50 -4
  302. package/dist/esm/resources/tokens.js.map +1 -1
  303. package/dist/exo.esm.js +6635 -2550
  304. package/dist/exo.esm.js.map +1 -1
  305. package/package.json +19 -6
  306. package/dist/esm/input/interaction-hooks.d.ts +0 -34
  307. package/dist/esm/input/interaction-hooks.js +0 -35
  308. package/dist/esm/input/interaction-hooks.js.map +0 -1
  309. package/dist/esm/rendering/text/DynamicGlyphAtlas.d.ts +0 -33
  310. package/dist/esm/rendering/text/DynamicGlyphAtlas.js +0 -134
  311. package/dist/esm/rendering/text/DynamicGlyphAtlas.js.map +0 -1
  312. package/dist/esm/rendering/text/atlas-singleton.d.ts +0 -7
  313. package/dist/esm/rendering/text/atlas-singleton.js +0 -17
  314. package/dist/esm/rendering/text/atlas-singleton.js.map +0 -1
  315. package/dist/esm/resources/factories/VttFactory.d.ts +0 -24
  316. package/dist/esm/resources/factories/VttFactory.js +0 -158
  317. package/dist/esm/resources/factories/VttFactory.js.map +0 -1
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Signed Distance Field generator for individual glyphs.
3
+ *
4
+ * Uses the Canvas 2D API to rasterize each character, then applies a 2D
5
+ * Euclidean Distance Transform (Felzenszwalb & Huttenlocher, 2012) to
6
+ * produce a single-channel R8 SDF buffer.
7
+ *
8
+ * Output encoding: 128/255 ≈ 0.502 is the glyph edge. Values above 0.5
9
+ * are inside the glyph, values below 0.5 are outside. The range encoded
10
+ * by the SDF extends `radius` pixels beyond the geometric edge.
11
+ *
12
+ * Compatible with `cutoff = 0.5` in the shader's `smoothstep(0.5 − soft, 0.5 + soft, sd)`.
13
+ */
14
+ const inf = 1e20;
15
+ /**
16
+ * SDF generator for a single font variant.
17
+ *
18
+ * Maintains an internal canvas that is resized per glyph and a set of reusable
19
+ * EDT working arrays that grow on demand (no per-call allocations once the
20
+ * largest glyph has been processed).
21
+ * @advanced
22
+ */
23
+ class GlyphSdf {
24
+ _buffer;
25
+ _radius;
26
+ _cutoff;
27
+ _font;
28
+ _canvasW = 0;
29
+ _canvasH = 0;
30
+ _canvas;
31
+ _ctx;
32
+ // Reusable EDT working arrays — grown lazily.
33
+ _gridOuter = new Float64Array(0);
34
+ _gridInner = new Float64Array(0);
35
+ _f = new Float64Array(0);
36
+ _d = new Float64Array(0);
37
+ _z = new Float64Array(0);
38
+ _v = new Int16Array(0);
39
+ _out = new Uint8ClampedArray(0);
40
+ constructor(options) {
41
+ this._buffer = options.buffer ?? 8;
42
+ this._radius = options.radius ?? this._buffer;
43
+ this._cutoff = options.cutoff ?? 0.5;
44
+ const stylePart = options.fontStyle && options.fontStyle !== 'normal' ? `${options.fontStyle} ` : '';
45
+ const weight = options.fontWeight ?? 'normal';
46
+ this._font = `${stylePart}${weight} ${options.fontSize}px ${options.fontFamily}`;
47
+ if (typeof OffscreenCanvas !== 'undefined') {
48
+ const c = new OffscreenCanvas(1, 1);
49
+ this._canvas = c;
50
+ this._ctx = c.getContext('2d');
51
+ }
52
+ else {
53
+ const c = document.createElement('canvas');
54
+ this._canvas = c;
55
+ this._ctx = c.getContext('2d');
56
+ }
57
+ }
58
+ /**
59
+ * Rasterize `char` and compute its SDF.
60
+ *
61
+ * Returns a new {@link GlyphSdfResult} each call. The `data` buffer is a
62
+ * fresh `Uint8ClampedArray`; the caller may hold a reference to it safely
63
+ * across subsequent `draw()` calls.
64
+ */
65
+ draw(char) {
66
+ const ctx = this._ctx;
67
+ const buf = this._buffer;
68
+ // ── Measure ──────────────────────────────────────────────────────────
69
+ ctx.font = this._font;
70
+ ctx.textBaseline = 'alphabetic';
71
+ const m = ctx.measureText(char);
72
+ const advance = m.width;
73
+ // Canvas 2D `actualBoundingBoxLeft` is the distance from the text's
74
+ // left-alignment point going LEFT to the left edge of the glyph bounding
75
+ // box. For most LTR characters this is 0; italic fonts may have a small
76
+ // positive value (left overhang).
77
+ const bbLeft = Math.max(0, Math.ceil(m.actualBoundingBoxLeft ?? 0));
78
+ const bbRight = Math.max(0, Math.ceil(m.actualBoundingBoxRight ?? advance));
79
+ const bbAscent = Math.max(0, Math.ceil(m.fontBoundingBoxAscent ??
80
+ m.actualBoundingBoxAscent ??
81
+ 0));
82
+ const bbDescent = Math.max(0, Math.ceil(m.fontBoundingBoxDescent ??
83
+ m.actualBoundingBoxDescent ??
84
+ 0));
85
+ const glyphWidth = Math.max(1, bbLeft + bbRight);
86
+ const glyphHeight = Math.max(1, bbAscent + bbDescent);
87
+ const tileW = glyphWidth + 2 * buf;
88
+ const tileH = glyphHeight + 2 * buf;
89
+ // ── Resize canvas if the tile dimensions changed ───────────────────────
90
+ if (this._canvasW !== tileW || this._canvasH !== tileH) {
91
+ this._canvas.width = tileW;
92
+ this._canvas.height = tileH;
93
+ this._canvasW = tileW;
94
+ this._canvasH = tileH;
95
+ }
96
+ // ── Rasterize white glyph on transparent background ───────────────────
97
+ ctx.clearRect(0, 0, tileW, tileH);
98
+ ctx.fillStyle = '#ffffff';
99
+ // Position so glyph's left edge lands at x = buf and baseline at y = buf + bbAscent.
100
+ ctx.fillText(char, buf + bbLeft, buf + bbAscent);
101
+ const rgba = ctx.getImageData(0, 0, tileW, tileH).data;
102
+ const n = tileW * tileH;
103
+ // ── Grow working arrays lazily ────────────────────────────────────────
104
+ if (n > this._gridOuter.length) {
105
+ const maxDim = Math.max(tileW, tileH);
106
+ this._gridOuter = new Float64Array(n);
107
+ this._gridInner = new Float64Array(n);
108
+ this._f = new Float64Array(maxDim);
109
+ this._d = new Float64Array(maxDim);
110
+ this._z = new Float64Array(maxDim + 1);
111
+ this._v = new Int16Array(maxDim);
112
+ }
113
+ if (n > this._out.length) {
114
+ this._out = new Uint8ClampedArray(n);
115
+ }
116
+ // ── Initialise EDT grids from the alpha channel ───────────────────────
117
+ //
118
+ // gridOuter[i]: squared distance to the nearest fully-outside pixel
119
+ // (0 for inside pixels, inf for outside pixels, blended for edges)
120
+ // gridInner[i]: squared distance to the nearest fully-inside pixel
121
+ // (inf for inside pixels, 0 for outside pixels)
122
+ for (let i = 0; i < n; i++) {
123
+ const a = rgba[i * 4 + 3] / 255; // alpha 0..1 from the R channel (white glyph)
124
+ if (a === 1) {
125
+ this._gridOuter[i] = 0;
126
+ this._gridInner[i] = inf;
127
+ }
128
+ else if (a === 0) {
129
+ this._gridOuter[i] = inf;
130
+ this._gridInner[i] = 0;
131
+ }
132
+ else {
133
+ this._gridOuter[i] = Math.max(0, 0.5 - a) ** 2;
134
+ this._gridInner[i] = Math.max(0, a - 0.5) ** 2;
135
+ }
136
+ }
137
+ // ── Apply 2D EDT ──────────────────────────────────────────────────────
138
+ _edt2d(this._gridOuter, tileW, tileH, this._f, this._d, this._v, this._z);
139
+ _edt2d(this._gridInner, tileW, tileH, this._f, this._d, this._v, this._z);
140
+ // ── Normalise to R8 ───────────────────────────────────────────────────
141
+ //
142
+ // SDF value d = outer_dist − inner_dist:
143
+ // d < 0 → inside glyph (inner_dist > 0, outer_dist = 0)
144
+ // d = 0 → at glyph edge
145
+ // d > 0 → outside glyph
146
+ //
147
+ // Mapping: value = clamp(round(255 − 255 × (d / radius + cutoff)), 0, 255)
148
+ // With cutoff = 0.5: edge (d=0) → 128, deep inside → 255, far outside → 0.
149
+ for (let i = 0; i < n; i++) {
150
+ const d = this._gridOuter[i] - this._gridInner[i];
151
+ this._out[i] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this._radius + this._cutoff))));
152
+ }
153
+ return {
154
+ data: this._out.slice(0, n), // fresh copy so caller may hold the reference
155
+ width: tileW,
156
+ height: tileH,
157
+ glyphWidth,
158
+ glyphHeight,
159
+ glyphTop: buf, // glyph content starts buf px from tile top
160
+ glyphLeft: buf, // glyph content starts buf px from tile left
161
+ glyphAdvance: advance,
162
+ };
163
+ }
164
+ }
165
+ // ── EDT algorithm ─────────────────────────────────────────────────────────────
166
+ // 2D Euclidean Distance Transform (Felzenszwalb & Huttenlocher, TPAMI 2012).
167
+ // Applied separably: one pass per column, then one pass per row + sqrt.
168
+ function _edt2d(data, width, height, f, d, v, z) {
169
+ // Vertical pass: transform along each column
170
+ for (let x = 0; x < width; x++) {
171
+ for (let y = 0; y < height; y++)
172
+ f[y] = data[y * width + x];
173
+ _edt1d(f, d, v, z, height);
174
+ for (let y = 0; y < height; y++)
175
+ data[y * width + x] = d[y];
176
+ }
177
+ // Horizontal pass + sqrt: transform along each row, then take sqrt
178
+ for (let y = 0; y < height; y++) {
179
+ for (let x = 0; x < width; x++)
180
+ f[x] = data[y * width + x];
181
+ _edt1d(f, d, v, z, width);
182
+ for (let x = 0; x < width; x++)
183
+ data[y * width + x] = Math.sqrt(d[x]);
184
+ }
185
+ }
186
+ /**
187
+ * 1D EDT (squared Euclidean distance) via the parabola-envelope algorithm.
188
+ * Writes squared distances into `d[0..n−1]` for the function values in `f`.
189
+ */
190
+ function _edt1d(f, d, v, z, n) {
191
+ let k = 0;
192
+ v[0] = 0;
193
+ z[0] = -inf;
194
+ z[1] = inf;
195
+ for (let q = 1; q < n; q++) {
196
+ // Find the parabola intersection s (break-point) for site q.
197
+ let s;
198
+ do {
199
+ const r = v[k];
200
+ s = (f[q] + q * q - f[r] - r * r) / (2 * (q - r));
201
+ if (s > z[k])
202
+ break;
203
+ k--;
204
+ } while (k >= 0);
205
+ k++;
206
+ v[k] = q;
207
+ z[k] = s;
208
+ z[k + 1] = inf;
209
+ }
210
+ k = 0;
211
+ for (let q = 0; q < n; q++) {
212
+ while (z[k + 1] < q)
213
+ k++;
214
+ const r = v[k];
215
+ d[q] = (q - r) * (q - r) + f[r];
216
+ }
217
+ }
218
+
219
+ export { GlyphSdf };
220
+ //# sourceMappingURL=GlyphSdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GlyphSdf.js","sources":["../../../../../src/rendering/text/GlyphSdf.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;;;;;;AAYG;AAEH,MAAM,GAAG,GAAG,IAAI;AAuDhB;;;;;;;AAOG;MACU,QAAQ,CAAA;AACF,IAAA,OAAO;AACP,IAAA,OAAO;AACP,IAAA,OAAO;AACP,IAAA,KAAK;IAEd,QAAQ,GAAG,CAAC;IACZ,QAAQ,GAAG,CAAC;AACH,IAAA,OAAO;AACP,IAAA,IAAI;;AAGb,IAAA,UAAU,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;AAChC,IAAA,UAAU,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;AAChC,IAAA,EAAE,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;AACxB,IAAA,EAAE,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;AACxB,IAAA,EAAE,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;AACxB,IAAA,EAAE,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC;AACtB,IAAA,IAAI,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC;AAEvC,IAAA,WAAA,CAAmB,OAAwB,EAAA;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO;QAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG;QAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,QAAQ,GAAG,CAAA,EAAG,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE;AACpG,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,IAAI,QAAQ;AAC7C,QAAA,IAAI,CAAC,KAAK,GAAG,CAAA,EAAG,SAAS,GAAG,MAAM,CAAA,CAAA,EAAI,OAAO,CAAC,QAAQ,CAAA,GAAA,EAAM,OAAO,CAAC,UAAU,EAAE;AAEhF,QAAA,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE;YAC1C,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;AACnC,YAAA,IAAI,CAAC,OAAO,GAAG,CAAC;YAChB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAE;QACjC;aAAO;YACL,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AAC1C,YAAA,IAAI,CAAC,OAAO,GAAG,CAAC;YAChB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAE;QACjC;IACF;AAEA;;;;;;AAMG;AACI,IAAA,IAAI,CAAC,IAAY,EAAA;AACtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI;AACrB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO;;AAGxB,QAAA,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;AACrB,QAAA,GAAG,CAAC,YAAY,GAAG,YAAY;QAE/B,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC;AAC/B,QAAA,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK;;;;;AAMvB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAE,CAAsD,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC;AACzH,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAE,CAAuD,CAAC,sBAAsB,IAAI,OAAO,CAAC,CAAC;AAClI,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,CAAC,EACD,IAAI,CAAC,IAAI,CACN,CAAsD,CAAC,qBAAqB;AAC1E,YAAA,CAAwD,CAAC,uBAAuB;YACjF,CAAC,CACJ,CACF;AACD,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,CAAC,EACD,IAAI,CAAC,IAAI,CACN,CAAuD,CAAC,sBAAsB;AAC5E,YAAA,CAAyD,CAAC,wBAAwB;YACnF,CAAC,CACJ,CACF;AAED,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;AAChD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;AACrD,QAAA,MAAM,KAAK,GAAG,UAAU,GAAG,CAAC,GAAG,GAAG;AAClC,QAAA,MAAM,KAAK,GAAG,WAAW,GAAG,CAAC,GAAG,GAAG;;AAGnC,QAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE;AACtD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK;AAC1B,YAAA,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK;AAC3B,YAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;AACrB,YAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;QACvB;;QAGA,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;AACjC,QAAA,GAAG,CAAC,SAAS,GAAG,SAAS;;AAEzB,QAAA,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,GAAG,QAAQ,CAAC;AAEhD,QAAA,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI;AACtD,QAAA,MAAM,CAAC,GAAG,KAAK,GAAG,KAAK;;QAGvB,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;YACrC,IAAI,CAAC,UAAU,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC,UAAU,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC;YAClC,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC;YAClC,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YACtC,IAAI,CAAC,EAAE,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC;QAClC;QACA,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YACxB,IAAI,CAAC,IAAI,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC;QACtC;;;;;;;AAQA,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;AAC1B,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;AAChC,YAAA,IAAI,CAAC,KAAK,CAAC,EAAE;AACX,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;AACtB,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG;YAC1B;AAAO,iBAAA,IAAI,CAAC,KAAK,CAAC,EAAE;AAClB,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG;AACxB,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;YACxB;iBAAO;AACL,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC;AAC9C,gBAAA,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;YAChD;QACF;;QAGA,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;;;;;;;;;;AAWzE,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;AAC1B,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACjD,YAAA,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACtG;QAEA,OAAO;AACL,YAAA,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC3B,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,MAAM,EAAE,KAAK;YACb,UAAU;YACV,WAAW;YACX,QAAQ,EAAE,GAAG;YACb,SAAS,EAAE,GAAG;AACd,YAAA,YAAY,EAAE,OAAO;SACtB;IACH;AACD;AAED;AACA;AACA;AAEA,SAAS,MAAM,CAAC,IAAkB,EAAE,KAAa,EAAE,MAAc,EAAE,CAAe,EAAE,CAAe,EAAE,CAAa,EAAE,CAAe,EAAA;;AAEjI,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE;AAAE,YAAA,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC3D,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE;AAAE,YAAA,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D;;AAGA,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;AAAE,YAAA,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC1D,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;AAAE,YAAA,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE;AACF;AAEA;;;AAGG;AACH,SAAS,MAAM,CAAC,CAAe,EAAE,CAAe,EAAE,CAAa,EAAE,CAAe,EAAE,CAAS,EAAA;IACzF,IAAI,CAAC,GAAG,CAAC;AACT,IAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACR,IAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG;AACX,IAAA,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;AAEV,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;;AAE1B,QAAA,IAAI,CAAS;AACb,QAAA,GAAG;AACD,YAAA,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACd,YAAA,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,YAAA,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAAE;AACd,YAAA,CAAC,EAAE;AACL,QAAA,CAAC,QAAQ,CAAC,IAAI,CAAC;AAEf,QAAA,CAAC,EAAE;AACH,QAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACR,QAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACR,QAAA,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG;IAChB;IAEA,CAAC,GAAG,CAAC;AACL,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;AAC1B,QAAA,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;AAAE,YAAA,CAAC,EAAE;AACxB,QAAA,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACd,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACjC;AACF;;;;"}
@@ -0,0 +1,107 @@
1
+ import { Container } from '@/rendering/Container';
2
+ export type FontFormat = 'woff2' | 'woff' | 'ttf' | 'otf';
3
+ export interface HTMLTextOptions {
4
+ /** CSS injected inside a &lt;style&gt; tag within the SVG foreignObject. */
5
+ css?: string;
6
+ /** Logical width in pixels. Default: 256 */
7
+ width?: number;
8
+ /** Logical height in pixels. Default: 128 */
9
+ height?: number;
10
+ /**
11
+ * Device-pixel ratio applied to the backing canvas.
12
+ * Values >1 produce a sharper texture at the cost of a larger canvas.
13
+ * Default: 1
14
+ */
15
+ resolution?: number;
16
+ }
17
+ /**
18
+ * Text node that renders arbitrary HTML+CSS into a canvas texture via an
19
+ * SVG `<foreignObject>` pass and displays the result as a textured quad.
20
+ *
21
+ * Full CSS typography and rich markup are supported. External resources
22
+ * (`<img src>`, `background-image: url(...)`) are **blocked** by browsers
23
+ * when loading SVG blob-URIs — inline those as base-64 data URIs.
24
+ *
25
+ * Custom web fonts must be registered with {@link addFont} before use;
26
+ * pass the raw font bytes (from {@link BinaryAsset} or a plain `fetch`):
27
+ *
28
+ * ```ts
29
+ * const bytes = await loader.load(BinaryAsset, 'roboto.woff2');
30
+ * htmlText.addFont('Roboto', bytes, 'woff2');
31
+ * ```
32
+ *
33
+ * The HTML must be valid XHTML (tags closed, `&amp;` for `&`, etc.)
34
+ * because it is embedded inside an XML document.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const label = new HTMLText(
39
+ * '<b>Score</b>: <span style="color:gold">9999</span>',
40
+ * { width: 200, height: 40, css: 'body { font: 20px Arial; color: white; }' },
41
+ * );
42
+ * scene.addChild(label);
43
+ * await label.ready; // optional — wait for first render
44
+ * ```
45
+ * @stable
46
+ */
47
+ export declare class HTMLText extends Container {
48
+ private _html;
49
+ private _css;
50
+ private _width;
51
+ private _height;
52
+ private _resolution;
53
+ private _canvas;
54
+ private _ctx;
55
+ private _texture;
56
+ private _mesh;
57
+ private _destroyed;
58
+ private _renderVersion;
59
+ private _activeRender;
60
+ private readonly _fonts;
61
+ constructor(html: string, options?: HTMLTextOptions);
62
+ get html(): string;
63
+ set html(v: string);
64
+ get css(): string;
65
+ set css(v: string);
66
+ get width(): number;
67
+ set width(v: number);
68
+ get height(): number;
69
+ set height(v: number);
70
+ get resolution(): number;
71
+ set resolution(v: number);
72
+ /**
73
+ * Resolves when the current render pass finishes writing to the canvas.
74
+ * Await before adding to a scene if you need the first frame to be visible
75
+ * immediately.
76
+ */
77
+ get ready(): Promise<void>;
78
+ /**
79
+ * Register a font by its raw bytes for use inside this node's SVG render.
80
+ * The `family` name must match the `font-family` value used in your CSS.
81
+ *
82
+ * Registering the same family twice replaces the previous entry.
83
+ *
84
+ * ```ts
85
+ * const bytes = await loader.load(BinaryAsset, 'roboto.woff2');
86
+ * label.addFont('Roboto', bytes, 'woff2');
87
+ * ```
88
+ */
89
+ addFont(family: string, data: ArrayBuffer, format?: FontFormat): this;
90
+ /** Remove a previously registered font and trigger a re-render. */
91
+ removeFont(family: string): this;
92
+ /**
93
+ * Change the logical dimensions and rebuild the mesh.
94
+ * Prefer this over setting `width` and `height` individually when changing
95
+ * both at once — it triggers a single re-render instead of two.
96
+ */
97
+ resize(width: number, height: number): this;
98
+ destroy(): void;
99
+ private _schedule;
100
+ private _render;
101
+ private _buildSvg;
102
+ private _buildMesh;
103
+ private _rebuildMesh;
104
+ private _resizeCanvas;
105
+ private static _toBase64;
106
+ private static _makeCanvas;
107
+ }
@@ -0,0 +1,284 @@
1
+ import { Container } from '../Container.js';
2
+ import { Mesh } from '../mesh/Mesh.js';
3
+ import { Texture } from '../texture/Texture.js';
4
+
5
+ const fontMime = {
6
+ woff2: 'font/woff2',
7
+ woff: 'font/woff',
8
+ ttf: 'font/ttf',
9
+ otf: 'font/otf',
10
+ };
11
+ /**
12
+ * Text node that renders arbitrary HTML+CSS into a canvas texture via an
13
+ * SVG `<foreignObject>` pass and displays the result as a textured quad.
14
+ *
15
+ * Full CSS typography and rich markup are supported. External resources
16
+ * (`<img src>`, `background-image: url(...)`) are **blocked** by browsers
17
+ * when loading SVG blob-URIs — inline those as base-64 data URIs.
18
+ *
19
+ * Custom web fonts must be registered with {@link addFont} before use;
20
+ * pass the raw font bytes (from {@link BinaryAsset} or a plain `fetch`):
21
+ *
22
+ * ```ts
23
+ * const bytes = await loader.load(BinaryAsset, 'roboto.woff2');
24
+ * htmlText.addFont('Roboto', bytes, 'woff2');
25
+ * ```
26
+ *
27
+ * The HTML must be valid XHTML (tags closed, `&amp;` for `&`, etc.)
28
+ * because it is embedded inside an XML document.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const label = new HTMLText(
33
+ * '<b>Score</b>: <span style="color:gold">9999</span>',
34
+ * { width: 200, height: 40, css: 'body { font: 20px Arial; color: white; }' },
35
+ * );
36
+ * scene.addChild(label);
37
+ * await label.ready; // optional — wait for first render
38
+ * ```
39
+ * @stable
40
+ */
41
+ // eslint-disable-next-line @typescript-eslint/naming-convention
42
+ class HTMLText extends Container {
43
+ _html;
44
+ _css;
45
+ _width;
46
+ _height;
47
+ _resolution;
48
+ _canvas;
49
+ _ctx;
50
+ _texture;
51
+ _mesh;
52
+ _destroyed = false;
53
+ _renderVersion = 0;
54
+ _activeRender = null;
55
+ _fonts = [];
56
+ constructor(html, options = {}) {
57
+ super();
58
+ this._html = html;
59
+ this._css = options.css ?? '';
60
+ this._width = options.width ?? 256;
61
+ this._height = options.height ?? 128;
62
+ this._resolution = options.resolution ?? 1;
63
+ const [canvas, ctx] = HTMLText._makeCanvas(Math.ceil(this._width * this._resolution), Math.ceil(this._height * this._resolution));
64
+ this._canvas = canvas;
65
+ this._ctx = ctx;
66
+ this._texture = new Texture(canvas);
67
+ this._texture.setSize(this._width, this._height);
68
+ this._mesh = this._buildMesh();
69
+ this.addChild(this._mesh);
70
+ if (html.length > 0) {
71
+ this._schedule();
72
+ }
73
+ }
74
+ // ── Properties ────────────────────────────────────────────────────────────
75
+ get html() {
76
+ return this._html;
77
+ }
78
+ set html(v) {
79
+ if (this._html === v)
80
+ return;
81
+ this._html = v;
82
+ this._schedule();
83
+ }
84
+ get css() {
85
+ return this._css;
86
+ }
87
+ set css(v) {
88
+ if (this._css === v)
89
+ return;
90
+ this._css = v;
91
+ this._schedule();
92
+ }
93
+ get width() {
94
+ return this._width;
95
+ }
96
+ set width(v) {
97
+ this.resize(v, this._height);
98
+ }
99
+ get height() {
100
+ return this._height;
101
+ }
102
+ set height(v) {
103
+ this.resize(this._width, v);
104
+ }
105
+ get resolution() {
106
+ return this._resolution;
107
+ }
108
+ set resolution(v) {
109
+ if (this._resolution === v)
110
+ return;
111
+ this._resolution = v;
112
+ this._resizeCanvas();
113
+ this._schedule();
114
+ }
115
+ /**
116
+ * Resolves when the current render pass finishes writing to the canvas.
117
+ * Await before adding to a scene if you need the first frame to be visible
118
+ * immediately.
119
+ */
120
+ get ready() {
121
+ return this._activeRender ?? Promise.resolve();
122
+ }
123
+ // ── Font registration ─────────────────────────────────────────────────────
124
+ /**
125
+ * Register a font by its raw bytes for use inside this node's SVG render.
126
+ * The `family` name must match the `font-family` value used in your CSS.
127
+ *
128
+ * Registering the same family twice replaces the previous entry.
129
+ *
130
+ * ```ts
131
+ * const bytes = await loader.load(BinaryAsset, 'roboto.woff2');
132
+ * label.addFont('Roboto', bytes, 'woff2');
133
+ * ```
134
+ */
135
+ addFont(family, data, format = 'woff2') {
136
+ const dataUri = `data:${fontMime[format]};base64,${HTMLText._toBase64(data)}`;
137
+ const existing = this._fonts.findIndex(f => f.family === family);
138
+ if (existing >= 0) {
139
+ this._fonts[existing] = { family, dataUri };
140
+ }
141
+ else {
142
+ this._fonts.push({ family, dataUri });
143
+ }
144
+ this._schedule();
145
+ return this;
146
+ }
147
+ /** Remove a previously registered font and trigger a re-render. */
148
+ removeFont(family) {
149
+ const idx = this._fonts.findIndex(f => f.family === family);
150
+ if (idx >= 0) {
151
+ this._fonts.splice(idx, 1);
152
+ this._schedule();
153
+ }
154
+ return this;
155
+ }
156
+ // ── Dimensions ────────────────────────────────────────────────────────────
157
+ /**
158
+ * Change the logical dimensions and rebuild the mesh.
159
+ * Prefer this over setting `width` and `height` individually when changing
160
+ * both at once — it triggers a single re-render instead of two.
161
+ */
162
+ resize(width, height) {
163
+ if (this._width === width && this._height === height)
164
+ return this;
165
+ this._width = width;
166
+ this._height = height;
167
+ this._resizeCanvas();
168
+ this._rebuildMesh();
169
+ this._schedule();
170
+ return this;
171
+ }
172
+ destroy() {
173
+ this._destroyed = true;
174
+ this._renderVersion++;
175
+ this._activeRender = null;
176
+ this._texture.destroy();
177
+ super.destroy();
178
+ }
179
+ // ── Private ───────────────────────────────────────────────────────────────
180
+ _schedule() {
181
+ const version = ++this._renderVersion;
182
+ this._activeRender = this._render(version).catch(error => {
183
+ // eslint-disable-next-line no-console -- SVG/HTML render failures are meaningful dev-time diagnostics
184
+ console.warn('[ExoJS] HTMLText render failed.', error);
185
+ });
186
+ }
187
+ async _render(version) {
188
+ if (typeof Blob === 'undefined' || typeof Image === 'undefined')
189
+ return; // SSR / Node.js
190
+ // Blob URL avoids the size and encoding overhead of a data URI,
191
+ // which matters when large base-64 fonts are inlined.
192
+ const blob = new Blob([this._buildSvg()], { type: 'image/svg+xml;charset=utf-8' });
193
+ const url = URL.createObjectURL(blob);
194
+ const img = new Image();
195
+ try {
196
+ await new Promise((resolve, reject) => {
197
+ img.onload = () => resolve();
198
+ img.onerror = () => reject(new Error('HTMLText: SVG render failed'));
199
+ img.src = url;
200
+ });
201
+ }
202
+ finally {
203
+ URL.revokeObjectURL(url);
204
+ }
205
+ if (this._destroyed || version !== this._renderVersion)
206
+ return;
207
+ const cw = Math.ceil(this._width * this._resolution);
208
+ const ch = Math.ceil(this._height * this._resolution);
209
+ this._ctx.clearRect(0, 0, cw, ch);
210
+ this._ctx.drawImage(img, 0, 0, cw, ch);
211
+ this._texture.updateSource();
212
+ }
213
+ _buildSvg() {
214
+ const w = this._width;
215
+ const h = this._height;
216
+ const fontFaceRules = this._fonts
217
+ .map(({ family, dataUri }) => {
218
+ const escaped = family.replaceAll('\\', '\\\\').replaceAll("'", "\\'");
219
+ return `@font-face{font-family:'${escaped}';src:url('${dataUri}');}`;
220
+ })
221
+ .join('');
222
+ // Guard against the user's CSS accidentally closing the <style> tag early.
223
+ const userCss = this._css.replaceAll(/<\/style>/gi, '<\\/style>');
224
+ const styleBlock = fontFaceRules || userCss ? `<style>${fontFaceRules}${userCss}</style>` : '';
225
+ return (`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">` +
226
+ `<foreignObject width="100%" height="100%">` +
227
+ `<div xmlns="http://www.w3.org/1999/xhtml"` +
228
+ ` style="width:${w}px;height:${h}px;overflow:hidden;box-sizing:border-box;">${styleBlock}${this._html}</div>` +
229
+ `</foreignObject>` +
230
+ `</svg>`);
231
+ }
232
+ _buildMesh() {
233
+ const w = this._width;
234
+ const h = this._height;
235
+ return new Mesh({
236
+ vertices: new Float32Array([0, 0, w, 0, w, h, 0, h]),
237
+ uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
238
+ indices: new Uint16Array([0, 1, 2, 0, 2, 3]),
239
+ texture: this._texture,
240
+ });
241
+ }
242
+ _rebuildMesh() {
243
+ this.removeChild(this._mesh);
244
+ this._mesh.destroy();
245
+ this._mesh = this._buildMesh();
246
+ this.addChild(this._mesh);
247
+ }
248
+ _resizeCanvas() {
249
+ const cw = Math.ceil(this._width * this._resolution);
250
+ const ch = Math.ceil(this._height * this._resolution);
251
+ this._canvas.width = cw;
252
+ this._canvas.height = ch;
253
+ // Canvas is blank after resize; the scheduled render fills it.
254
+ // updateSource() bumps the texture version so the GPU re-uploads.
255
+ this._texture.updateSource();
256
+ }
257
+ static _toBase64(buffer) {
258
+ const bytes = new Uint8Array(buffer);
259
+ let binary = '';
260
+ for (let i = 0; i < bytes.length; i++) {
261
+ binary += String.fromCharCode(bytes[i]);
262
+ }
263
+ return btoa(binary);
264
+ }
265
+ static _makeCanvas(width, height) {
266
+ if (typeof OffscreenCanvas !== 'undefined') {
267
+ const canvas = new OffscreenCanvas(width, height);
268
+ const ctx = canvas.getContext('2d');
269
+ if (!ctx)
270
+ throw new Error('HTMLText: could not obtain 2D context.');
271
+ return [canvas, ctx];
272
+ }
273
+ const canvas = document.createElement('canvas');
274
+ canvas.width = width;
275
+ canvas.height = height;
276
+ const ctx = canvas.getContext('2d');
277
+ if (!ctx)
278
+ throw new Error('HTMLText: could not obtain 2D context.');
279
+ return [canvas, ctx];
280
+ }
281
+ }
282
+
283
+ export { HTMLText };
284
+ //# sourceMappingURL=HTMLText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HTMLText.js","sources":["../../../../../src/rendering/text/HTMLText.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Controls text flow and overflow — separate from {@link TextStyle} which
3
+ * describes visual appearance. Pass to {@link Text} or {@link layoutText}.
4
+ */
5
+ export interface LayoutOptions {
6
+ /** Word-wrap boundary in pixels. Lines exceeding this width are broken at word boundaries. */
7
+ maxWidth?: number;
8
+ /** Clip boundary in pixels. Text beyond this height is clipped or ellipsized. */
9
+ maxHeight?: number;
10
+ /** What to do when text overflows `maxHeight`. Defaults to `'visible'`. */
11
+ overflow?: 'visible' | 'clip' | 'ellipsis';
12
+ /** Additional gap in pixels between glyphs (on top of the font's advance). */
13
+ letterSpacing?: number;
14
+ /** Text direction. Defaults to `'ltr'`. RTL is not fully implemented. */
15
+ direction?: 'ltr' | 'rtl';
16
+ /**
17
+ * Break individual words that are wider than `maxWidth` at character boundaries.
18
+ * Only applies when `maxWidth` is set. Defaults to `false`.
19
+ */
20
+ breakWords?: boolean;
21
+ /**
22
+ * Whitespace handling mode:
23
+ * - `'normal'` — Consecutive spaces collapse to one; `\n` becomes a space (standard wrap).
24
+ * - `'pre'` — Spaces and newlines preserved verbatim.
25
+ * - `'pre-line'` — Spaces collapse; `\n` preserved (default when no explicit mode).
26
+ *
27
+ * Defaults to `'pre-line'` (current historical behaviour).
28
+ */
29
+ whiteSpace?: 'normal' | 'pre' | 'pre-line';
30
+ }