@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.
- package/CHANGELOG.md +107 -0
- package/README.md +26 -5
- package/dist/esm/animation/Tween.d.ts +20 -3
- package/dist/esm/animation/Tween.js +16 -8
- package/dist/esm/animation/Tween.js.map +1 -1
- package/dist/esm/animation/TweenManager.d.ts +16 -1
- package/dist/esm/animation/TweenManager.js +27 -2
- package/dist/esm/animation/TweenManager.js.map +1 -1
- package/dist/esm/audio/AudioAnalyser.d.ts +2 -0
- package/dist/esm/audio/AudioAnalyser.js +24 -9
- package/dist/esm/audio/AudioAnalyser.js.map +1 -1
- package/dist/esm/audio/AudioBus.d.ts +1 -0
- package/dist/esm/audio/AudioBus.js +8 -4
- package/dist/esm/audio/AudioBus.js.map +1 -1
- package/dist/esm/audio/AudioListener.d.ts +1 -0
- package/dist/esm/audio/AudioListener.js +7 -5
- package/dist/esm/audio/AudioListener.js.map +1 -1
- package/dist/esm/audio/AudioManager.d.ts +8 -2
- package/dist/esm/audio/AudioManager.js +14 -1
- package/dist/esm/audio/AudioManager.js.map +1 -1
- package/dist/esm/audio/BeatDetector.d.ts +2 -0
- package/dist/esm/audio/BeatDetector.js +27 -661
- package/dist/esm/audio/BeatDetector.js.map +1 -1
- package/dist/esm/audio/Music.d.ts +1 -0
- package/dist/esm/audio/Music.js +7 -3
- package/dist/esm/audio/Music.js.map +1 -1
- package/dist/esm/audio/OscillatorSound.d.ts +1 -0
- package/dist/esm/audio/OscillatorSound.js +7 -3
- package/dist/esm/audio/OscillatorSound.js.map +1 -1
- package/dist/esm/audio/Sound.d.ts +1 -0
- package/dist/esm/audio/Sound.js +7 -3
- package/dist/esm/audio/Sound.js.map +1 -1
- package/dist/esm/audio/audio-context.d.ts +2 -2
- package/dist/esm/audio/audio-context.js +4 -4
- package/dist/esm/audio/audio-context.js.map +1 -1
- package/dist/esm/audio/filters/ChorusFilter.d.ts +1 -0
- package/dist/esm/audio/filters/ChorusFilter.js +7 -3
- package/dist/esm/audio/filters/ChorusFilter.js.map +1 -1
- package/dist/esm/audio/filters/CompressorFilter.d.ts +1 -0
- package/dist/esm/audio/filters/CompressorFilter.js +7 -3
- package/dist/esm/audio/filters/CompressorFilter.js.map +1 -1
- package/dist/esm/audio/filters/DelayFilter.d.ts +1 -0
- package/dist/esm/audio/filters/DelayFilter.js +7 -3
- package/dist/esm/audio/filters/DelayFilter.js.map +1 -1
- package/dist/esm/audio/filters/EqualizerFilter.d.ts +1 -0
- package/dist/esm/audio/filters/EqualizerFilter.js +7 -3
- package/dist/esm/audio/filters/EqualizerFilter.js.map +1 -1
- package/dist/esm/audio/filters/GranularFilter.js +1 -86
- package/dist/esm/audio/filters/GranularFilter.js.map +1 -1
- package/dist/esm/audio/filters/HighpassFilter.d.ts +1 -0
- package/dist/esm/audio/filters/HighpassFilter.js +7 -3
- package/dist/esm/audio/filters/HighpassFilter.js.map +1 -1
- package/dist/esm/audio/filters/LowpassFilter.d.ts +1 -0
- package/dist/esm/audio/filters/LowpassFilter.js +7 -3
- package/dist/esm/audio/filters/LowpassFilter.js.map +1 -1
- package/dist/esm/audio/filters/PitchShiftFilter.js +1 -71
- package/dist/esm/audio/filters/PitchShiftFilter.js.map +1 -1
- package/dist/esm/audio/filters/ReverbFilter.d.ts +1 -0
- package/dist/esm/audio/filters/ReverbFilter.js +7 -3
- package/dist/esm/audio/filters/ReverbFilter.js.map +1 -1
- package/dist/esm/audio/filters/VocoderFilter.js +1 -89
- package/dist/esm/audio/filters/VocoderFilter.js.map +1 -1
- package/dist/esm/audio/filters/WorkletFilter.d.ts +2 -0
- package/dist/esm/audio/filters/WorkletFilter.js +10 -5
- package/dist/esm/audio/filters/WorkletFilter.js.map +1 -1
- package/dist/esm/audio/index.d.ts +15 -10
- package/dist/esm/audio/worklet/registerWorklet.d.ts +1 -1
- package/dist/esm/audio/worklet/registerWorklet.js +2 -2
- package/dist/esm/audio/worklet/registerWorklet.js.map +1 -1
- package/dist/esm/audio/worklets/beat-detector.worklet.d.ts +1 -0
- package/dist/esm/audio/worklets/beat-detector.worklet.js +647 -0
- package/dist/esm/audio/worklets/beat-detector.worklet.js.map +1 -0
- package/dist/esm/audio/worklets/granular.worklet.d.ts +1 -0
- package/dist/esm/audio/worklets/granular.worklet.js +89 -0
- package/dist/esm/audio/worklets/granular.worklet.js.map +1 -0
- package/dist/esm/audio/worklets/pitch-shift.worklet.d.ts +1 -0
- package/dist/esm/audio/worklets/pitch-shift.worklet.js +74 -0
- package/dist/esm/audio/worklets/pitch-shift.worklet.js.map +1 -0
- package/dist/esm/audio/worklets/vocoder.worklet.d.ts +1 -0
- package/dist/esm/audio/worklets/vocoder.worklet.js +92 -0
- package/dist/esm/audio/worklets/vocoder.worklet.js.map +1 -0
- package/dist/esm/core/Application.d.ts +62 -24
- package/dist/esm/core/Application.js +116 -40
- package/dist/esm/core/Application.js.map +1 -1
- package/dist/esm/core/Color.d.ts +0 -8
- package/dist/esm/core/Color.js +0 -24
- package/dist/esm/core/Color.js.map +1 -1
- package/dist/esm/core/Scene.d.ts +32 -72
- package/dist/esm/core/Scene.js +56 -36
- package/dist/esm/core/Scene.js.map +1 -1
- package/dist/esm/core/SceneManager.d.ts +11 -25
- package/dist/esm/core/SceneManager.js +37 -100
- package/dist/esm/core/SceneManager.js.map +1 -1
- package/dist/esm/core/SceneNode.d.ts +28 -14
- package/dist/esm/core/SceneNode.js +66 -33
- package/dist/esm/core/SceneNode.js.map +1 -1
- package/dist/esm/core/Signal.d.ts +24 -28
- package/dist/esm/core/Signal.js +64 -50
- package/dist/esm/core/Signal.js.map +1 -1
- package/dist/esm/core/Timer.d.ts +1 -0
- package/dist/esm/core/Timer.js +3 -0
- package/dist/esm/core/Timer.js.map +1 -1
- package/dist/esm/debug/BoundingBoxesLayer.js +1 -1
- package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
- package/dist/esm/debug/HitTestLayer.js +1 -1
- package/dist/esm/debug/HitTestLayer.js.map +1 -1
- package/dist/esm/debug/PerformanceLayer.js +1 -2
- package/dist/esm/debug/PerformanceLayer.js.map +1 -1
- package/dist/esm/debug/PointerStackLayer.js +1 -2
- package/dist/esm/debug/PointerStackLayer.js.map +1 -1
- package/dist/esm/debug/RenderPassInspectorLayer.js +1 -2
- package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -1
- package/dist/esm/index.js +23 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/input/InputManager.d.ts +1 -0
- package/dist/esm/input/InputManager.js +30 -3
- package/dist/esm/input/InputManager.js.map +1 -1
- package/dist/esm/input/InteractionManager.d.ts +5 -2
- package/dist/esm/input/InteractionManager.js +29 -18
- package/dist/esm/input/InteractionManager.js.map +1 -1
- package/dist/esm/input/Pointer.js +3 -2
- package/dist/esm/input/Pointer.js.map +1 -1
- package/dist/esm/input/internal/interactionManagerRegistry.d.ts +9 -0
- package/dist/esm/input/internal/interactionManagerRegistry.js +10 -0
- package/dist/esm/input/internal/interactionManagerRegistry.js.map +1 -0
- package/dist/esm/math/AbstractVector.d.ts +1 -7
- package/dist/esm/math/AbstractVector.js +6 -20
- package/dist/esm/math/AbstractVector.js.map +1 -1
- package/dist/esm/math/Circle.js +0 -2
- package/dist/esm/math/Circle.js.map +1 -1
- package/dist/esm/math/Collision.d.ts +9 -3
- package/dist/esm/math/Ellipse.d.ts +2 -5
- package/dist/esm/math/Ellipse.js +10 -7
- package/dist/esm/math/Ellipse.js.map +1 -1
- package/dist/esm/math/ObservableVector.d.ts +1 -1
- package/dist/esm/math/ObservableVector.js +3 -3
- package/dist/esm/math/ObservableVector.js.map +1 -1
- package/dist/esm/math/Polygon.d.ts +0 -2
- package/dist/esm/math/Polygon.js +1 -9
- package/dist/esm/math/Polygon.js.map +1 -1
- package/dist/esm/math/Rectangle.js +0 -2
- package/dist/esm/math/Rectangle.js.map +1 -1
- package/dist/esm/math/collision-detection.d.ts +19 -4
- package/dist/esm/math/collision-detection.js +61 -4
- package/dist/esm/math/collision-detection.js.map +1 -1
- package/dist/esm/math/swept-collision.d.ts +16 -12
- package/dist/esm/math/swept-collision.js +109 -19
- package/dist/esm/math/swept-collision.js.map +1 -1
- package/dist/esm/particles/ParticleSystem.js +1 -1
- package/dist/esm/particles/ParticleSystem.js.map +1 -1
- package/dist/esm/particles/index.d.ts +1 -0
- package/dist/esm/rendering/CallbackRenderPass.d.ts +1 -0
- package/dist/esm/rendering/CallbackRenderPass.js +1 -0
- package/dist/esm/rendering/CallbackRenderPass.js.map +1 -1
- package/dist/esm/rendering/Container.d.ts +2 -1
- package/dist/esm/rendering/Container.js +17 -16
- package/dist/esm/rendering/Container.js.map +1 -1
- package/dist/esm/rendering/RenderBackend.d.ts +1 -0
- package/dist/esm/rendering/RenderNode.d.ts +1 -3
- package/dist/esm/rendering/RenderNode.js +12 -19
- package/dist/esm/rendering/RenderNode.js.map +1 -1
- package/dist/esm/rendering/RenderPass.d.ts +1 -0
- package/dist/esm/rendering/RenderStats.d.ts +9 -0
- package/dist/esm/rendering/RenderStats.js +2 -0
- package/dist/esm/rendering/RenderStats.js.map +1 -1
- package/dist/esm/rendering/RendererRegistry.d.ts +1 -0
- package/dist/esm/rendering/RendererRegistry.js +1 -0
- package/dist/esm/rendering/RendererRegistry.js.map +1 -1
- package/dist/esm/rendering/View.d.ts +23 -0
- package/dist/esm/rendering/View.js +42 -0
- package/dist/esm/rendering/View.js.map +1 -1
- package/dist/esm/rendering/index.d.ts +89 -59
- package/dist/esm/rendering/mesh/Mesh.js +1 -1
- package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
- package/dist/esm/rendering/mesh/MeshShader.d.ts +1 -0
- package/dist/esm/rendering/mesh/MeshShader.js +1 -0
- package/dist/esm/rendering/mesh/MeshShader.js.map +1 -1
- package/dist/esm/rendering/shader/Shader.d.ts +1 -0
- package/dist/esm/rendering/shader/Shader.js +1 -0
- package/dist/esm/rendering/shader/Shader.js.map +1 -1
- package/dist/esm/rendering/shader/ShaderUniform.d.ts +1 -0
- package/dist/esm/rendering/shader/ShaderUniform.js +1 -0
- package/dist/esm/rendering/shader/ShaderUniform.js.map +1 -1
- package/dist/esm/rendering/sprite/Sprite.d.ts +3 -2
- package/dist/esm/rendering/sprite/Sprite.js +15 -13
- package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
- package/dist/esm/rendering/text/AbstractText.d.ts +36 -0
- package/dist/esm/rendering/text/AbstractText.js +49 -0
- package/dist/esm/rendering/text/AbstractText.js.map +1 -0
- package/dist/esm/rendering/text/BitmapText.d.ts +97 -0
- package/dist/esm/rendering/text/BitmapText.js +220 -0
- package/dist/esm/rendering/text/BitmapText.js.map +1 -0
- package/dist/esm/rendering/text/BmFont.d.ts +50 -0
- package/dist/esm/rendering/text/BmFont.js +24 -0
- package/dist/esm/rendering/text/BmFont.js.map +1 -0
- package/dist/esm/rendering/text/GlyphAtlas.d.ts +104 -0
- package/dist/esm/rendering/text/GlyphAtlas.js +347 -0
- package/dist/esm/rendering/text/GlyphAtlas.js.map +1 -0
- package/dist/esm/rendering/text/GlyphAtlasPool.d.ts +40 -0
- package/dist/esm/rendering/text/GlyphAtlasPool.js +67 -0
- package/dist/esm/rendering/text/GlyphAtlasPool.js.map +1 -0
- package/dist/esm/rendering/text/GlyphSdf.d.ts +92 -0
- package/dist/esm/rendering/text/GlyphSdf.js +220 -0
- package/dist/esm/rendering/text/GlyphSdf.js.map +1 -0
- package/dist/esm/rendering/text/HTMLText.d.ts +107 -0
- package/dist/esm/rendering/text/HTMLText.js +284 -0
- package/dist/esm/rendering/text/HTMLText.js.map +1 -0
- package/dist/esm/rendering/text/LayoutOptions.d.ts +30 -0
- package/dist/esm/rendering/text/Text.d.ts +89 -20
- package/dist/esm/rendering/text/Text.js +176 -101
- package/dist/esm/rendering/text/Text.js.map +1 -1
- package/dist/esm/rendering/text/TextLayout.d.ts +20 -8
- package/dist/esm/rendering/text/TextLayout.js +234 -25
- package/dist/esm/rendering/text/TextLayout.js.map +1 -1
- package/dist/esm/rendering/text/TextStyle.d.ts +154 -87
- package/dist/esm/rendering/text/TextStyle.js +257 -203
- package/dist/esm/rendering/text/TextStyle.js.map +1 -1
- package/dist/esm/rendering/text/types.d.ts +73 -13
- package/dist/esm/rendering/texture/Texture.d.ts +1 -0
- package/dist/esm/rendering/texture/Texture.js +1 -0
- package/dist/esm/rendering/texture/Texture.js.map +1 -1
- package/dist/esm/rendering/types.d.ts +3 -1
- package/dist/esm/rendering/types.js +2 -0
- package/dist/esm/rendering/types.js.map +1 -1
- package/dist/esm/rendering/video/Video.d.ts +2 -1
- package/dist/esm/rendering/video/Video.js +9 -5
- package/dist/esm/rendering/video/Video.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2Backend.js +41 -5
- package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js +4 -4
- package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2TextRenderer.d.ts +56 -0
- package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js +482 -0
- package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js.map +1 -0
- package/dist/esm/rendering/webgl2/glsl/text-color.frag.js +4 -0
- package/dist/esm/rendering/webgl2/glsl/text-color.frag.js.map +1 -0
- package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js +4 -0
- package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js.map +1 -0
- package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js +4 -0
- package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js.map +1 -0
- package/dist/esm/rendering/webgl2/glsl/text.vert.js +4 -0
- package/dist/esm/rendering/webgl2/glsl/text.vert.js.map +1 -0
- package/dist/esm/rendering/webgpu/WebGpuBackend.js +16 -8
- package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuBlendState.js +26 -0
- package/dist/esm/rendering/webgpu/WebGpuBlendState.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +2 -2
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +23 -15
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +9 -1
- package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts +70 -0
- package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js +773 -0
- package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js.map +1 -0
- package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js +96 -0
- package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js.map +1 -0
- package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js +68 -0
- package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js.map +1 -0
- package/dist/esm/resources/Asset.d.ts +23 -0
- package/dist/esm/resources/Asset.js +23 -0
- package/dist/esm/resources/Asset.js.map +1 -0
- package/dist/esm/resources/AssetDefinitions.d.ts +137 -0
- package/dist/esm/resources/Assets.d.ts +35 -0
- package/dist/esm/resources/Assets.js +32 -0
- package/dist/esm/resources/Assets.js.map +1 -0
- package/dist/esm/resources/IndexedDbDatabase.js +17 -1
- package/dist/esm/resources/IndexedDbDatabase.js.map +1 -1
- package/dist/esm/resources/IndexedDbStore.js +17 -1
- package/dist/esm/resources/IndexedDbStore.js.map +1 -1
- package/dist/esm/resources/Loader.d.ts +244 -18
- package/dist/esm/resources/Loader.js +456 -50
- package/dist/esm/resources/Loader.js.map +1 -1
- package/dist/esm/resources/LoadingQueue.d.ts +28 -0
- package/dist/esm/resources/LoadingQueue.js +59 -0
- package/dist/esm/resources/LoadingQueue.js.map +1 -0
- package/dist/esm/resources/factories/BmFontFactory.d.ts +25 -0
- package/dist/esm/resources/factories/BmFontFactory.js +96 -0
- package/dist/esm/resources/factories/BmFontFactory.js.map +1 -0
- package/dist/esm/resources/factories/CsvFactory.d.ts +35 -0
- package/dist/esm/resources/factories/CsvFactory.js +87 -0
- package/dist/esm/resources/factories/CsvFactory.js.map +1 -0
- package/dist/esm/resources/factories/MusicFactory.d.ts +8 -2
- package/dist/esm/resources/factories/MusicFactory.js +25 -14
- package/dist/esm/resources/factories/MusicFactory.js.map +1 -1
- package/dist/esm/resources/factories/SoundFactory.d.ts +2 -2
- package/dist/esm/resources/factories/SoundFactory.js.map +1 -1
- package/dist/esm/resources/factories/SubtitleFactory.d.ts +28 -0
- package/dist/esm/resources/factories/SubtitleFactory.js +203 -0
- package/dist/esm/resources/factories/SubtitleFactory.js.map +1 -0
- package/dist/esm/resources/factories/SvgFactory.d.ts +18 -1
- package/dist/esm/resources/factories/SvgFactory.js +21 -2
- package/dist/esm/resources/factories/SvgFactory.js.map +1 -1
- package/dist/esm/resources/factories/VideoFactory.d.ts +8 -2
- package/dist/esm/resources/factories/VideoFactory.js +27 -20
- package/dist/esm/resources/factories/VideoFactory.js.map +1 -1
- package/dist/esm/resources/factories/XmlFactory.d.ts +24 -0
- package/dist/esm/resources/factories/XmlFactory.js +37 -0
- package/dist/esm/resources/factories/XmlFactory.js.map +1 -0
- package/dist/esm/resources/index.d.ts +8 -1
- package/dist/esm/resources/tokens.d.ts +49 -3
- package/dist/esm/resources/tokens.js +50 -4
- package/dist/esm/resources/tokens.js.map +1 -1
- package/dist/exo.esm.js +6635 -2550
- package/dist/exo.esm.js.map +1 -1
- package/package.json +19 -6
- package/dist/esm/input/interaction-hooks.d.ts +0 -34
- package/dist/esm/input/interaction-hooks.js +0 -35
- package/dist/esm/input/interaction-hooks.js.map +0 -1
- package/dist/esm/rendering/text/DynamicGlyphAtlas.d.ts +0 -33
- package/dist/esm/rendering/text/DynamicGlyphAtlas.js +0 -134
- package/dist/esm/rendering/text/DynamicGlyphAtlas.js.map +0 -1
- package/dist/esm/rendering/text/atlas-singleton.d.ts +0 -7
- package/dist/esm/rendering/text/atlas-singleton.js +0 -17
- package/dist/esm/rendering/text/atlas-singleton.js.map +0 -1
- package/dist/esm/resources/factories/VttFactory.d.ts +0 -24
- package/dist/esm/resources/factories/VttFactory.js +0 -158
- package/dist/esm/resources/factories/VttFactory.js.map +0 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { Signal } from '../../core/Signal.js';
|
|
2
|
+
import { DataTexture } from '../texture/DataTexture.js';
|
|
3
|
+
import { Texture } from '../texture/Texture.js';
|
|
4
|
+
import { GlyphSdf } from './GlyphSdf.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SDF buffer radius in pixels — the maximum distance outside a glyph that the
|
|
8
|
+
* SDF field encodes. Determines the maximum usable outline/shadow reach.
|
|
9
|
+
* Exported so applications can import this constant when computing shader uniforms.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
12
|
+
const SDF_RADIUS = 8;
|
|
13
|
+
const glyphPadding = 2;
|
|
14
|
+
class ShelfPacker {
|
|
15
|
+
_shelves = [];
|
|
16
|
+
_width;
|
|
17
|
+
_height;
|
|
18
|
+
constructor(width, height) {
|
|
19
|
+
this._width = width;
|
|
20
|
+
this._height = height;
|
|
21
|
+
}
|
|
22
|
+
insert(width, height) {
|
|
23
|
+
for (const shelf of this._shelves) {
|
|
24
|
+
if (shelf.height >= height && shelf.cursorX + width <= this._width) {
|
|
25
|
+
const x = shelf.cursorX;
|
|
26
|
+
shelf.cursorX += width;
|
|
27
|
+
return { x, y: shelf.y };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const last = this._shelves[this._shelves.length - 1];
|
|
31
|
+
const bottomY = last === undefined ? 0 : last.y + last.height;
|
|
32
|
+
if (bottomY + height > this._height) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
this._shelves.push({ y: bottomY, height, cursorX: width });
|
|
36
|
+
return { x: 0, y: bottomY };
|
|
37
|
+
}
|
|
38
|
+
reset() {
|
|
39
|
+
this._shelves.length = 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function makeCtx(width, height) {
|
|
43
|
+
if (typeof OffscreenCanvas !== 'undefined') {
|
|
44
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
45
|
+
const ctx = canvas.getContext('2d');
|
|
46
|
+
if (!ctx)
|
|
47
|
+
throw new Error('GlyphAtlas: could not obtain OffscreenCanvas 2D context.');
|
|
48
|
+
return { canvas, ctx };
|
|
49
|
+
}
|
|
50
|
+
const canvas = document.createElement('canvas');
|
|
51
|
+
canvas.width = width;
|
|
52
|
+
canvas.height = height;
|
|
53
|
+
const ctx = canvas.getContext('2d');
|
|
54
|
+
if (!ctx)
|
|
55
|
+
throw new Error('GlyphAtlas: could not obtain canvas 2D context.');
|
|
56
|
+
return { canvas, ctx };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A single texture page within a {@link GlyphAtlas}. Glyphs are packed into
|
|
60
|
+
* the page using a shelf-bin algorithm.
|
|
61
|
+
*
|
|
62
|
+
* In `'sdf'` mode the page owns a `DataTexture` (`r8`) populated by tiny-sdf
|
|
63
|
+
* output. In `'color'` mode a Canvas 2D context preserves full glyph colours
|
|
64
|
+
* for emoji.
|
|
65
|
+
* @advanced
|
|
66
|
+
*/
|
|
67
|
+
class AtlasPage {
|
|
68
|
+
texture;
|
|
69
|
+
index;
|
|
70
|
+
mode;
|
|
71
|
+
_packer;
|
|
72
|
+
_width;
|
|
73
|
+
_height;
|
|
74
|
+
// SDF mode
|
|
75
|
+
_sdfBuffer = null;
|
|
76
|
+
_sdfTexture = null;
|
|
77
|
+
// Canvas mode
|
|
78
|
+
_ctx = null;
|
|
79
|
+
_colorGlyphs;
|
|
80
|
+
constructor(index, width, height, mode) {
|
|
81
|
+
this.index = index;
|
|
82
|
+
this.mode = mode;
|
|
83
|
+
this._width = width;
|
|
84
|
+
this._height = height;
|
|
85
|
+
this._colorGlyphs = mode === 'color';
|
|
86
|
+
this._packer = new ShelfPacker(width, height);
|
|
87
|
+
if (mode === 'sdf') {
|
|
88
|
+
this._sdfBuffer = new Uint8Array(width * height);
|
|
89
|
+
this._sdfTexture = new DataTexture({ width, height, format: 'r8', data: this._sdfBuffer });
|
|
90
|
+
this._sdfTexture.setSize(width, height);
|
|
91
|
+
this.texture = this._sdfTexture;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const { canvas, ctx } = makeCtx(width, height);
|
|
95
|
+
this._ctx = ctx;
|
|
96
|
+
this.texture = new Texture(canvas);
|
|
97
|
+
this.texture.setSize(width, height);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
insert(w, h) {
|
|
101
|
+
return this._packer.insert(w, h);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Copy R8 SDF data into the page buffer at the given slot origin.
|
|
105
|
+
* Only valid in `'sdf'` mode.
|
|
106
|
+
*
|
|
107
|
+
* `data` is a `Uint8ClampedArray` of single-channel SDF values as produced
|
|
108
|
+
* by {@link GlyphSdf.draw}. Each value is one byte (0 = far outside the
|
|
109
|
+
* glyph, 255 = deep inside, ~128 = glyph edge).
|
|
110
|
+
*/
|
|
111
|
+
writeSdf(data, slotX, slotY, srcW, srcH) {
|
|
112
|
+
const buf = this._sdfBuffer;
|
|
113
|
+
const dstW = this._width;
|
|
114
|
+
for (let row = 0; row < srcH; row++) {
|
|
115
|
+
const srcOff = row * srcW;
|
|
116
|
+
const dstOff = (slotY + row) * dstW + slotX;
|
|
117
|
+
buf.set(data.subarray(srcOff, srcOff + srcW), dstOff);
|
|
118
|
+
}
|
|
119
|
+
this._sdfTexture.commitRect(slotX, slotY, srcW, srcH);
|
|
120
|
+
}
|
|
121
|
+
measureGlyph(char, font) {
|
|
122
|
+
if (this._ctx !== null) {
|
|
123
|
+
this._ctx.font = font;
|
|
124
|
+
this._ctx.textBaseline = 'alphabetic';
|
|
125
|
+
return this._ctx.measureText(char);
|
|
126
|
+
}
|
|
127
|
+
const c = typeof OffscreenCanvas !== 'undefined' ? new OffscreenCanvas(1, 1) : document.createElement('canvas');
|
|
128
|
+
const ctx = c.getContext('2d');
|
|
129
|
+
ctx.font = font;
|
|
130
|
+
ctx.textBaseline = 'alphabetic';
|
|
131
|
+
return ctx.measureText(char);
|
|
132
|
+
}
|
|
133
|
+
/** Rasterize a white glyph into the canvas at the given padded slot origin (canvas mode only). */
|
|
134
|
+
rasterize(char, slotX, slotY, ascent, bbLeft, font) {
|
|
135
|
+
const ctx = this._ctx;
|
|
136
|
+
ctx.font = font;
|
|
137
|
+
ctx.textBaseline = 'alphabetic';
|
|
138
|
+
if (!this._colorGlyphs) {
|
|
139
|
+
ctx.fillStyle = '#ffffff';
|
|
140
|
+
}
|
|
141
|
+
ctx.fillText(char, slotX + glyphPadding + bbLeft, slotY + glyphPadding + ascent);
|
|
142
|
+
}
|
|
143
|
+
uploadDirtyRegion() {
|
|
144
|
+
if (this._sdfTexture !== null) {
|
|
145
|
+
this._sdfTexture.commit();
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.texture.updateSource();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
reset() {
|
|
152
|
+
this._packer.reset();
|
|
153
|
+
if (this._sdfBuffer !== null && this._sdfTexture !== null) {
|
|
154
|
+
this._sdfBuffer.fill(0);
|
|
155
|
+
this._sdfTexture.commit();
|
|
156
|
+
}
|
|
157
|
+
else if (this._ctx !== null) {
|
|
158
|
+
this._ctx.clearRect(0, 0, this._width, this._height);
|
|
159
|
+
this.texture.updateSource();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// ── GlyphAtlas ───────────────────────────────────────────────────────────────
|
|
164
|
+
/**
|
|
165
|
+
* A per-font-variant glyph atlas with automatic multi-page growth.
|
|
166
|
+
*
|
|
167
|
+
* In `'sdf'` mode (default) each atlas page is a single-channel R8
|
|
168
|
+
* `DataTexture` populated by {@link GlyphSdf}. One `GlyphSdf` instance is kept per
|
|
169
|
+
* font size so the atlas can mix sizes efficiently.
|
|
170
|
+
*
|
|
171
|
+
* In `'color'` mode pages are RGBA canvas textures that preserve full glyph
|
|
172
|
+
* colour data for emoji and colour fonts.
|
|
173
|
+
* @advanced
|
|
174
|
+
*/
|
|
175
|
+
class GlyphAtlas {
|
|
176
|
+
_pages = [];
|
|
177
|
+
_cache = new Map();
|
|
178
|
+
_kerningCache = new Map();
|
|
179
|
+
_pageSize;
|
|
180
|
+
_family;
|
|
181
|
+
_fontStyle;
|
|
182
|
+
_fontWeight;
|
|
183
|
+
_mode;
|
|
184
|
+
_sdfRadius;
|
|
185
|
+
/**
|
|
186
|
+
* Dispatched whenever a new atlas page is allocated.
|
|
187
|
+
*
|
|
188
|
+
* Listen here to detect unexpected atlas growth (e.g. many unique CJK glyphs
|
|
189
|
+
* or an oversized font size). The payload is the zero-based page index.
|
|
190
|
+
*
|
|
191
|
+
* ```ts
|
|
192
|
+
* const atlas = pool.getAtlas('Roboto', 'normal', '400');
|
|
193
|
+
* atlas.onPageAdded.on(idx => console.warn(`Atlas page ${idx} added`));
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
onPageAdded = new Signal();
|
|
197
|
+
/** {@link GlyphSdf} instances keyed by font size — only used in SDF mode. */
|
|
198
|
+
_sdfInstances = new Map();
|
|
199
|
+
constructor(family, fontStyle, fontWeight, pageSize = 1024, mode = 'sdf', sdfRadius = SDF_RADIUS) {
|
|
200
|
+
this._family = family;
|
|
201
|
+
this._fontStyle = fontStyle;
|
|
202
|
+
this._fontWeight = fontWeight;
|
|
203
|
+
this._pageSize = pageSize;
|
|
204
|
+
this._mode = mode;
|
|
205
|
+
this._sdfRadius = sdfRadius;
|
|
206
|
+
this._addPage();
|
|
207
|
+
}
|
|
208
|
+
get pages() {
|
|
209
|
+
return this._pages;
|
|
210
|
+
}
|
|
211
|
+
get mode() {
|
|
212
|
+
return this._mode;
|
|
213
|
+
}
|
|
214
|
+
getGlyph(char, size) {
|
|
215
|
+
const key = `${char}:${size}`;
|
|
216
|
+
const cached = this._cache.get(key);
|
|
217
|
+
if (cached !== undefined)
|
|
218
|
+
return cached;
|
|
219
|
+
return this._mode === 'sdf' ? this._rasterizeSdf(char, size, key) : this._rasterizeCanvas(char, size, key);
|
|
220
|
+
}
|
|
221
|
+
getKerning(prev, next, fontSize) {
|
|
222
|
+
const key = `${prev}${next}:${fontSize}`;
|
|
223
|
+
const cached = this._kerningCache.get(key);
|
|
224
|
+
if (cached !== undefined)
|
|
225
|
+
return cached;
|
|
226
|
+
const font = this._cssFont(fontSize);
|
|
227
|
+
const page = this._pages[0];
|
|
228
|
+
const pair = page.measureGlyph(prev + next, font).width;
|
|
229
|
+
const a = page.measureGlyph(prev, font).width;
|
|
230
|
+
const b = page.measureGlyph(next, font).width;
|
|
231
|
+
const kerning = pair - a - b;
|
|
232
|
+
this._kerningCache.set(key, kerning);
|
|
233
|
+
return kerning;
|
|
234
|
+
}
|
|
235
|
+
clear() {
|
|
236
|
+
this._cache.clear();
|
|
237
|
+
this._kerningCache.clear();
|
|
238
|
+
this._sdfInstances.clear();
|
|
239
|
+
for (const page of this._pages) {
|
|
240
|
+
page.reset();
|
|
241
|
+
}
|
|
242
|
+
this._pages = [];
|
|
243
|
+
this._addPage();
|
|
244
|
+
}
|
|
245
|
+
// ── Private ──────────────────────────────────────────────────────────────
|
|
246
|
+
_addPage() {
|
|
247
|
+
const index = this._pages.length;
|
|
248
|
+
const page = new AtlasPage(index, this._pageSize, this._pageSize, this._mode);
|
|
249
|
+
this._pages.push(page);
|
|
250
|
+
if (index > 0)
|
|
251
|
+
this.onPageAdded.dispatch(index);
|
|
252
|
+
return page;
|
|
253
|
+
}
|
|
254
|
+
_cssFont(size) {
|
|
255
|
+
const style = this._fontStyle !== 'normal' ? `${this._fontStyle} ` : '';
|
|
256
|
+
return `${style}${this._fontWeight} ${size}px ${this._family}`;
|
|
257
|
+
}
|
|
258
|
+
_getSdf(fontSize) {
|
|
259
|
+
let instance = this._sdfInstances.get(fontSize);
|
|
260
|
+
if (instance === undefined) {
|
|
261
|
+
instance = new GlyphSdf({
|
|
262
|
+
fontSize,
|
|
263
|
+
fontFamily: this._family,
|
|
264
|
+
fontWeight: this._fontWeight,
|
|
265
|
+
fontStyle: this._fontStyle,
|
|
266
|
+
buffer: this._sdfRadius,
|
|
267
|
+
radius: this._sdfRadius,
|
|
268
|
+
cutoff: 0.5,
|
|
269
|
+
});
|
|
270
|
+
this._sdfInstances.set(fontSize, instance);
|
|
271
|
+
}
|
|
272
|
+
return instance;
|
|
273
|
+
}
|
|
274
|
+
_rasterizeSdf(char, size, key) {
|
|
275
|
+
const result = this._getSdf(size).draw(char);
|
|
276
|
+
const { page, slot } = this._allocateSlot(result.width, result.height);
|
|
277
|
+
page.writeSdf(result.data, slot.x, slot.y, result.width, result.height);
|
|
278
|
+
const ps = this._pageSize;
|
|
279
|
+
const info = {
|
|
280
|
+
x: slot.x,
|
|
281
|
+
y: slot.y,
|
|
282
|
+
width: result.width,
|
|
283
|
+
height: result.height,
|
|
284
|
+
advance: result.glyphAdvance,
|
|
285
|
+
ascent: result.glyphTop + result.glyphHeight, // distance from tile top to glyph bottom
|
|
286
|
+
page: page.index,
|
|
287
|
+
uvLeft: slot.x / ps,
|
|
288
|
+
uvTop: slot.y / ps,
|
|
289
|
+
uvRight: (slot.x + result.width) / ps,
|
|
290
|
+
uvBottom: (slot.y + result.height) / ps,
|
|
291
|
+
// Shift the quad left/up by the SDF buffer so the glyph content aligns
|
|
292
|
+
// with the logical cursor position (bearing = −buffer on both axes).
|
|
293
|
+
xBearing: -result.glyphLeft,
|
|
294
|
+
yBearing: -result.glyphTop,
|
|
295
|
+
};
|
|
296
|
+
this._cache.set(key, info);
|
|
297
|
+
return info;
|
|
298
|
+
}
|
|
299
|
+
_rasterizeCanvas(char, size, key) {
|
|
300
|
+
const font = this._cssFont(size);
|
|
301
|
+
const metrics = this._pages[0].measureGlyph(char, font);
|
|
302
|
+
const ascent = Math.ceil(metrics.fontBoundingBoxAscent ?? metrics.actualBoundingBoxAscent ?? size * 0.8);
|
|
303
|
+
const descent = Math.ceil(metrics.fontBoundingBoxDescent ?? metrics.actualBoundingBoxDescent ?? size * 0.2);
|
|
304
|
+
const advance = metrics.width;
|
|
305
|
+
const bbLeft = metrics.actualBoundingBoxLeft ?? 0;
|
|
306
|
+
const bbRight = metrics.actualBoundingBoxRight ?? 0;
|
|
307
|
+
const glyphWidth = Math.max(1, Math.ceil(bbLeft + bbRight) || Math.ceil(advance));
|
|
308
|
+
const glyphHeight = Math.max(1, ascent + descent);
|
|
309
|
+
const slotW = glyphWidth + glyphPadding * 2;
|
|
310
|
+
const slotH = glyphHeight + glyphPadding * 2;
|
|
311
|
+
const { page, slot } = this._allocateSlot(slotW, slotH);
|
|
312
|
+
page.rasterize(char, slot.x, slot.y, ascent, bbLeft, font);
|
|
313
|
+
page.uploadDirtyRegion();
|
|
314
|
+
const ps = this._pageSize;
|
|
315
|
+
const info = {
|
|
316
|
+
x: slot.x,
|
|
317
|
+
y: slot.y,
|
|
318
|
+
width: glyphWidth,
|
|
319
|
+
height: glyphHeight,
|
|
320
|
+
advance,
|
|
321
|
+
ascent,
|
|
322
|
+
page: page.index,
|
|
323
|
+
uvLeft: slot.x / ps,
|
|
324
|
+
uvTop: slot.y / ps,
|
|
325
|
+
uvRight: (slot.x + slotW) / ps,
|
|
326
|
+
uvBottom: (slot.y + slotH) / ps,
|
|
327
|
+
};
|
|
328
|
+
this._cache.set(key, info);
|
|
329
|
+
return info;
|
|
330
|
+
}
|
|
331
|
+
_allocateSlot(w, h) {
|
|
332
|
+
for (const page of this._pages) {
|
|
333
|
+
const slot = page.insert(w, h);
|
|
334
|
+
if (slot !== null)
|
|
335
|
+
return { page, slot };
|
|
336
|
+
}
|
|
337
|
+
const newPage = this._addPage();
|
|
338
|
+
const slot = newPage.insert(w, h);
|
|
339
|
+
if (slot === null) {
|
|
340
|
+
throw new Error(`GlyphAtlas: glyph (${w}×${h}px) exceeds page size (${this._pageSize}px).`);
|
|
341
|
+
}
|
|
342
|
+
return { page: newPage, slot };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export { AtlasPage, GlyphAtlas, SDF_RADIUS };
|
|
347
|
+
//# sourceMappingURL=GlyphAtlas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlyphAtlas.js","sources":["../../../../../src/rendering/text/GlyphAtlas.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type AtlasMode, GlyphAtlas } from './GlyphAtlas';
|
|
2
|
+
/**
|
|
3
|
+
* Manages one {@link GlyphAtlas} per font variant + mode combination.
|
|
4
|
+
*
|
|
5
|
+
* The pool key is `"${family}:${fontStyle}:${fontWeight}:${mode}"`. All text
|
|
6
|
+
* nodes sharing the same font variant and mode draw from the same atlas pages,
|
|
7
|
+
* so identical glyphs are rasterized only once regardless of which node first
|
|
8
|
+
* requests them.
|
|
9
|
+
*
|
|
10
|
+
* Use {@link getDefaultGlyphAtlasPool} to obtain the shared process-wide
|
|
11
|
+
* instance. Tests can mock that function to inject a fake pool.
|
|
12
|
+
* @advanced
|
|
13
|
+
*/
|
|
14
|
+
export declare class GlyphAtlasPool {
|
|
15
|
+
private readonly _atlases;
|
|
16
|
+
private readonly _pageSize;
|
|
17
|
+
constructor(pageSize?: number);
|
|
18
|
+
/**
|
|
19
|
+
* Returns (or lazily creates) the atlas for the given font variant and mode.
|
|
20
|
+
* Defaults to `'sdf'` mode (R8 DataTexture, tiny-sdf rasterization).
|
|
21
|
+
*
|
|
22
|
+
* Nodes with different `sdfRadius` values get separate atlas instances so
|
|
23
|
+
* each can encode a different outline/shadow reach without conflict.
|
|
24
|
+
*/
|
|
25
|
+
getAtlas(family: string, fontStyle: 'normal' | 'italic', fontWeight: string, mode?: AtlasMode, sdfRadius?: number): GlyphAtlas;
|
|
26
|
+
clearAll(): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns the shared process-wide {@link GlyphAtlasPool}, creating it lazily
|
|
30
|
+
* on first call. All {@link Text} instances use this pool by default.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getDefaultGlyphAtlasPool(): GlyphAtlasPool;
|
|
33
|
+
/**
|
|
34
|
+
* Override the default pool. Passing no argument (or `undefined`) causes the
|
|
35
|
+
* next {@link getDefaultGlyphAtlasPool} call to create a fresh instance.
|
|
36
|
+
*
|
|
37
|
+
* Intended for tests: call with a mock pool in `beforeEach` and with no
|
|
38
|
+
* argument in `afterEach` to restore default behaviour.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resetDefaultGlyphAtlasPool(pool?: GlyphAtlasPool): void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SDF_RADIUS, GlyphAtlas } from './GlyphAtlas.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manages one {@link GlyphAtlas} per font variant + mode combination.
|
|
5
|
+
*
|
|
6
|
+
* The pool key is `"${family}:${fontStyle}:${fontWeight}:${mode}"`. All text
|
|
7
|
+
* nodes sharing the same font variant and mode draw from the same atlas pages,
|
|
8
|
+
* so identical glyphs are rasterized only once regardless of which node first
|
|
9
|
+
* requests them.
|
|
10
|
+
*
|
|
11
|
+
* Use {@link getDefaultGlyphAtlasPool} to obtain the shared process-wide
|
|
12
|
+
* instance. Tests can mock that function to inject a fake pool.
|
|
13
|
+
* @advanced
|
|
14
|
+
*/
|
|
15
|
+
class GlyphAtlasPool {
|
|
16
|
+
_atlases = new Map();
|
|
17
|
+
_pageSize;
|
|
18
|
+
constructor(pageSize = 1024) {
|
|
19
|
+
this._pageSize = pageSize;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns (or lazily creates) the atlas for the given font variant and mode.
|
|
23
|
+
* Defaults to `'sdf'` mode (R8 DataTexture, tiny-sdf rasterization).
|
|
24
|
+
*
|
|
25
|
+
* Nodes with different `sdfRadius` values get separate atlas instances so
|
|
26
|
+
* each can encode a different outline/shadow reach without conflict.
|
|
27
|
+
*/
|
|
28
|
+
getAtlas(family, fontStyle, fontWeight, mode = 'sdf', sdfRadius = SDF_RADIUS) {
|
|
29
|
+
const key = `${family}:${fontStyle}:${fontWeight}:${mode}:${sdfRadius}`;
|
|
30
|
+
let atlas = this._atlases.get(key);
|
|
31
|
+
if (atlas === undefined) {
|
|
32
|
+
atlas = new GlyphAtlas(family, fontStyle, fontWeight, this._pageSize, mode, sdfRadius);
|
|
33
|
+
this._atlases.set(key, atlas);
|
|
34
|
+
}
|
|
35
|
+
return atlas;
|
|
36
|
+
}
|
|
37
|
+
clearAll() {
|
|
38
|
+
for (const atlas of this._atlases.values()) {
|
|
39
|
+
atlas.clear();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// ── Module-level default pool ────────────────────────────────────────────────
|
|
44
|
+
let _defaultPool = null;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the shared process-wide {@link GlyphAtlasPool}, creating it lazily
|
|
47
|
+
* on first call. All {@link Text} instances use this pool by default.
|
|
48
|
+
*/
|
|
49
|
+
function getDefaultGlyphAtlasPool() {
|
|
50
|
+
if (_defaultPool === null) {
|
|
51
|
+
_defaultPool = new GlyphAtlasPool();
|
|
52
|
+
}
|
|
53
|
+
return _defaultPool;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Override the default pool. Passing no argument (or `undefined`) causes the
|
|
57
|
+
* next {@link getDefaultGlyphAtlasPool} call to create a fresh instance.
|
|
58
|
+
*
|
|
59
|
+
* Intended for tests: call with a mock pool in `beforeEach` and with no
|
|
60
|
+
* argument in `afterEach` to restore default behaviour.
|
|
61
|
+
*/
|
|
62
|
+
function resetDefaultGlyphAtlasPool(pool) {
|
|
63
|
+
_defaultPool = pool ?? null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { GlyphAtlasPool, getDefaultGlyphAtlasPool, resetDefaultGlyphAtlasPool };
|
|
67
|
+
//# sourceMappingURL=GlyphAtlasPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlyphAtlasPool.js","sources":["../../../../../src/rendering/text/GlyphAtlasPool.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAEA;;;;;;;;;;;AAWG;MACU,cAAc,CAAA;AACR,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAsB;AACxC,IAAA,SAAS;IAE1B,WAAA,CAAmB,QAAQ,GAAG,IAAI,EAAA;AAChC,QAAA,IAAI,CAAC,SAAS,GAAG,QAAQ;IAC3B;AAEA;;;;;;AAMG;AACI,IAAA,QAAQ,CAAC,MAAc,EAAE,SAA8B,EAAE,UAAkB,EAAE,IAAA,GAAkB,KAAK,EAAE,SAAS,GAAG,UAAU,EAAA;AACjI,QAAA,MAAM,GAAG,GAAG,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,SAAS,EAAE;QACvE,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;AAElC,QAAA,IAAI,KAAK,KAAK,SAAS,EAAE;AACvB,YAAA,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC;YACtF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;QAC/B;AAEA,QAAA,OAAO,KAAK;IACd;IAEO,QAAQ,GAAA;QACb,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE;YAC1C,KAAK,CAAC,KAAK,EAAE;QACf;IACF;AACD;AAED;AAEA,IAAI,YAAY,GAA0B,IAAI;AAE9C;;;AAGG;SACa,wBAAwB,GAAA;AACtC,IAAA,IAAI,YAAY,KAAK,IAAI,EAAE;AACzB,QAAA,YAAY,GAAG,IAAI,cAAc,EAAE;IACrC;AACA,IAAA,OAAO,YAAY;AACrB;AAEA;;;;;;AAMG;AACG,SAAU,0BAA0B,CAAC,IAAqB,EAAA;AAC9D,IAAA,YAAY,GAAG,IAAI,IAAI,IAAI;AAC7B;;;;"}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
export interface GlyphSdfOptions {
|
|
15
|
+
/** Font size in pixels used for rasterization. */
|
|
16
|
+
fontSize: number;
|
|
17
|
+
/** CSS font-family string. */
|
|
18
|
+
fontFamily: string;
|
|
19
|
+
fontWeight?: string;
|
|
20
|
+
fontStyle?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Pixels of SDF padding added around the glyph bounding box on each side.
|
|
23
|
+
* Determines the maximum reach of outline and shadow effects.
|
|
24
|
+
* Defaults to 8.
|
|
25
|
+
*/
|
|
26
|
+
buffer?: number;
|
|
27
|
+
/**
|
|
28
|
+
* EDT search radius. Values above `radius` pixels from the edge are
|
|
29
|
+
* clamped. Must be ≥ `buffer` for full-range SDF coverage.
|
|
30
|
+
* Defaults to `buffer`.
|
|
31
|
+
*/
|
|
32
|
+
radius?: number;
|
|
33
|
+
/**
|
|
34
|
+
* SDF normalisation cutoff (0..1). Value at the glyph edge = 1 − cutoff.
|
|
35
|
+
* Use `0.5` so the shader's threshold of 0.5 matches the edge exactly.
|
|
36
|
+
* Defaults to 0.5.
|
|
37
|
+
*/
|
|
38
|
+
cutoff?: number;
|
|
39
|
+
}
|
|
40
|
+
/** Result of {@link GlyphSdf.draw}. */
|
|
41
|
+
export interface GlyphSdfResult {
|
|
42
|
+
/** R8 SDF values: 0 = far outside, 255 = deep inside, ~128 = edge. */
|
|
43
|
+
data: Uint8ClampedArray;
|
|
44
|
+
/** Tile width in pixels (= glyphWidth + 2 × buffer). */
|
|
45
|
+
width: number;
|
|
46
|
+
/** Tile height in pixels (= glyphHeight + 2 × buffer). */
|
|
47
|
+
height: number;
|
|
48
|
+
/** Actual glyph width in pixels (bounding box, no padding). */
|
|
49
|
+
glyphWidth: number;
|
|
50
|
+
/** Actual glyph height in pixels (ascent + descent, no padding). */
|
|
51
|
+
glyphHeight: number;
|
|
52
|
+
/** Pixels from tile top to glyph top = buffer. */
|
|
53
|
+
glyphTop: number;
|
|
54
|
+
/** Pixels from tile left to glyph left = buffer. */
|
|
55
|
+
glyphLeft: number;
|
|
56
|
+
/** Logical horizontal advance for cursor movement. */
|
|
57
|
+
glyphAdvance: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* SDF generator for a single font variant.
|
|
61
|
+
*
|
|
62
|
+
* Maintains an internal canvas that is resized per glyph and a set of reusable
|
|
63
|
+
* EDT working arrays that grow on demand (no per-call allocations once the
|
|
64
|
+
* largest glyph has been processed).
|
|
65
|
+
* @advanced
|
|
66
|
+
*/
|
|
67
|
+
export declare class GlyphSdf {
|
|
68
|
+
private readonly _buffer;
|
|
69
|
+
private readonly _radius;
|
|
70
|
+
private readonly _cutoff;
|
|
71
|
+
private readonly _font;
|
|
72
|
+
private _canvasW;
|
|
73
|
+
private _canvasH;
|
|
74
|
+
private readonly _canvas;
|
|
75
|
+
private readonly _ctx;
|
|
76
|
+
private _gridOuter;
|
|
77
|
+
private _gridInner;
|
|
78
|
+
private _f;
|
|
79
|
+
private _d;
|
|
80
|
+
private _z;
|
|
81
|
+
private _v;
|
|
82
|
+
private _out;
|
|
83
|
+
constructor(options: GlyphSdfOptions);
|
|
84
|
+
/**
|
|
85
|
+
* Rasterize `char` and compute its SDF.
|
|
86
|
+
*
|
|
87
|
+
* Returns a new {@link GlyphSdfResult} each call. The `data` buffer is a
|
|
88
|
+
* fresh `Uint8ClampedArray`; the caller may hold a reference to it safely
|
|
89
|
+
* across subsequent `draw()` calls.
|
|
90
|
+
*/
|
|
91
|
+
draw(char: string): GlyphSdfResult;
|
|
92
|
+
}
|