@fairyhunter13/opentui-core 0.1.91 → 0.1.94
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/3d/SpriteResourceManager.d.ts +74 -0
- package/3d/SpriteUtils.d.ts +13 -0
- package/3d/TextureUtils.d.ts +24 -0
- package/3d/ThreeRenderable.d.ts +40 -0
- package/3d/WGPURenderer.d.ts +61 -0
- package/3d/animation/ExplodingSpriteEffect.d.ts +71 -0
- package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +76 -0
- package/3d/animation/SpriteAnimator.d.ts +124 -0
- package/3d/animation/SpriteParticleGenerator.d.ts +62 -0
- package/3d/canvas.d.ts +44 -0
- package/3d/index.d.ts +12 -0
- package/3d/physics/PlanckPhysicsAdapter.d.ts +19 -0
- package/3d/physics/RapierPhysicsAdapter.d.ts +19 -0
- package/3d/physics/physics-interface.d.ts +27 -0
- package/3d.d.ts +2 -0
- package/3d.js +34042 -0
- package/3d.js.map +155 -0
- package/LICENSE +21 -0
- package/NativeSpanFeed.d.ts +41 -0
- package/Renderable.d.ts +334 -0
- package/animation/Timeline.d.ts +126 -0
- package/ansi.d.ts +13 -0
- package/buffer.d.ts +107 -0
- package/console.d.ts +143 -0
- package/edit-buffer.d.ts +98 -0
- package/editor-view.d.ts +73 -0
- package/index-e6ec7apq.js +18415 -0
- package/index-e6ec7apq.js.map +64 -0
- package/index-h066zmrb.js +12619 -0
- package/index-h066zmrb.js.map +43 -0
- package/index-ynzawt3n.js +113 -0
- package/index-ynzawt3n.js.map +10 -0
- package/index.d.ts +21 -0
- package/index.js +430 -0
- package/index.js.map +9 -0
- package/lib/KeyHandler.d.ts +61 -0
- package/lib/RGBA.d.ts +25 -0
- package/lib/ascii.font.d.ts +508 -0
- package/lib/border.d.ts +49 -0
- package/lib/bunfs.d.ts +7 -0
- package/lib/clipboard.d.ts +17 -0
- package/lib/clock.d.ts +15 -0
- package/lib/data-paths.d.ts +26 -0
- package/lib/debounce.d.ts +42 -0
- package/lib/detect-links.d.ts +6 -0
- package/lib/env.d.ts +42 -0
- package/lib/extmarks-history.d.ts +17 -0
- package/lib/extmarks.d.ts +89 -0
- package/lib/hast-styled-text.d.ts +17 -0
- package/lib/index.d.ts +21 -0
- package/lib/keymapping.d.ts +25 -0
- package/lib/objects-in-viewport.d.ts +24 -0
- package/lib/output.capture.d.ts +24 -0
- package/lib/parse.keypress-kitty.d.ts +2 -0
- package/lib/parse.keypress.d.ts +26 -0
- package/lib/parse.mouse.d.ts +30 -0
- package/lib/paste.d.ts +7 -0
- package/lib/queue.d.ts +15 -0
- package/lib/renderable.validations.d.ts +12 -0
- package/lib/scroll-acceleration.d.ts +43 -0
- package/lib/selection.d.ts +63 -0
- package/lib/singleton.d.ts +7 -0
- package/lib/stdin-parser.d.ts +76 -0
- package/lib/styled-text.d.ts +63 -0
- package/lib/terminal-capability-detection.d.ts +30 -0
- package/lib/terminal-palette.d.ts +50 -0
- package/lib/tree-sitter/assets/update.d.ts +11 -0
- package/lib/tree-sitter/client.d.ts +47 -0
- package/lib/tree-sitter/default-parsers.d.ts +2 -0
- package/lib/tree-sitter/download-utils.d.ts +21 -0
- package/lib/tree-sitter/index.d.ts +8 -0
- package/lib/tree-sitter/parser.worker.d.ts +1 -0
- package/lib/tree-sitter/parsers-config.d.ts +38 -0
- package/lib/tree-sitter/resolve-ft.d.ts +2 -0
- package/lib/tree-sitter/types.d.ts +81 -0
- package/lib/tree-sitter-styled-text.d.ts +14 -0
- package/lib/validate-dir-name.d.ts +1 -0
- package/lib/yoga.options.d.ts +32 -0
- package/package.json +51 -63
- package/parser.worker.js +869 -0
- package/parser.worker.js.map +12 -0
- package/plugins/core-slot.d.ts +72 -0
- package/plugins/registry.d.ts +38 -0
- package/plugins/types.d.ts +34 -0
- package/post/filters.d.ts +105 -0
- package/renderables/ASCIIFont.d.ts +52 -0
- package/renderables/Box.d.ts +72 -0
- package/renderables/Code.d.ts +78 -0
- package/renderables/Diff.d.ts +142 -0
- package/renderables/EditBufferRenderable.d.ts +162 -0
- package/renderables/FrameBuffer.d.ts +16 -0
- package/renderables/Input.d.ts +67 -0
- package/renderables/LineNumberRenderable.d.ts +74 -0
- package/renderables/Markdown.d.ts +173 -0
- package/renderables/ScrollBar.d.ts +77 -0
- package/renderables/ScrollBox.d.ts +124 -0
- package/renderables/Select.d.ts +115 -0
- package/renderables/Slider.d.ts +44 -0
- package/renderables/TabSelect.d.ts +96 -0
- package/renderables/Text.d.ts +36 -0
- package/renderables/TextBufferRenderable.d.ts +105 -0
- package/renderables/TextNode.d.ts +91 -0
- package/renderables/TextTable.d.ts +140 -0
- package/renderables/Textarea.d.ts +114 -0
- package/renderables/TimeToFirstDraw.d.ts +24 -0
- package/renderables/__tests__/renderable-test-utils.d.ts +12 -0
- package/renderables/composition/VRenderable.d.ts +16 -0
- package/renderables/composition/constructs.d.ts +35 -0
- package/renderables/composition/vnode.d.ts +46 -0
- package/renderables/index.d.ts +22 -0
- package/renderables/markdown-parser.d.ts +10 -0
- package/renderer.d.ts +388 -0
- package/runtime-plugin-support.d.ts +3 -0
- package/runtime-plugin-support.js +29 -0
- package/runtime-plugin-support.js.map +10 -0
- package/runtime-plugin.d.ts +11 -0
- package/runtime-plugin.js +16 -0
- package/runtime-plugin.js.map +9 -0
- package/syntax-style.d.ts +54 -0
- package/testing/manual-clock.d.ts +16 -0
- package/testing/mock-keys.d.ts +81 -0
- package/testing/mock-mouse.d.ts +38 -0
- package/testing/mock-tree-sitter-client.d.ts +23 -0
- package/testing/spy.d.ts +7 -0
- package/testing/test-recorder.d.ts +61 -0
- package/testing/test-renderer.d.ts +23 -0
- package/testing.d.ts +6 -0
- package/testing.js +675 -0
- package/testing.js.map +15 -0
- package/text-buffer-view.d.ts +42 -0
- package/text-buffer.d.ts +67 -0
- package/types.d.ts +131 -0
- package/utils.d.ts +14 -0
- package/zig-structs.d.ts +155 -0
- package/zig.d.ts +351 -0
- package/dev/keypress-debug-renderer.ts +0 -148
- package/dev/keypress-debug.ts +0 -43
- package/dev/print-env-vars.ts +0 -32
- package/dev/test-tmux-graphics-334.sh +0 -68
- package/dev/thai-debug-test.ts +0 -68
- package/docs/development.md +0 -141
- package/docs/env-vars.md +0 -140
- package/docs/getting-started.md +0 -353
- package/docs/renderables-vs-constructs.md +0 -159
- package/docs/tree-sitter.md +0 -311
- package/scripts/build.ts +0 -400
- package/scripts/publish.ts +0 -60
- package/src/3d/SpriteResourceManager.ts +0 -286
- package/src/3d/SpriteUtils.ts +0 -71
- package/src/3d/TextureUtils.ts +0 -196
- package/src/3d/ThreeRenderable.ts +0 -197
- package/src/3d/WGPURenderer.ts +0 -294
- package/src/3d/animation/ExplodingSpriteEffect.ts +0 -513
- package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +0 -429
- package/src/3d/animation/SpriteAnimator.ts +0 -633
- package/src/3d/animation/SpriteParticleGenerator.ts +0 -435
- package/src/3d/canvas.ts +0 -464
- package/src/3d/index.ts +0 -12
- package/src/3d/physics/PlanckPhysicsAdapter.ts +0 -72
- package/src/3d/physics/RapierPhysicsAdapter.ts +0 -66
- package/src/3d/physics/physics-interface.ts +0 -31
- package/src/3d/shaders/supersampling.wgsl +0 -201
- package/src/3d.ts +0 -3
- package/src/NativeSpanFeed.ts +0 -300
- package/src/Renderable.ts +0 -1698
- package/src/__snapshots__/buffer.test.ts.snap +0 -28
- package/src/animation/Timeline.test.ts +0 -2709
- package/src/animation/Timeline.ts +0 -598
- package/src/ansi.ts +0 -18
- package/src/benchmark/latest-all-bench-run.json +0 -707
- package/src/benchmark/latest-async-bench-run.json +0 -336
- package/src/benchmark/latest-default-bench-run.json +0 -657
- package/src/benchmark/latest-large-bench-run.json +0 -707
- package/src/benchmark/latest-quick-bench-run.json +0 -207
- package/src/benchmark/markdown-benchmark.ts +0 -1804
- package/src/benchmark/native-span-feed-async-benchmark.ts +0 -355
- package/src/benchmark/native-span-feed-benchmark.md +0 -56
- package/src/benchmark/native-span-feed-benchmark.ts +0 -596
- package/src/benchmark/native-span-feed-compare.ts +0 -280
- package/src/benchmark/renderer-benchmark.ts +0 -754
- package/src/benchmark/text-table-benchmark.ts +0 -947
- package/src/buffer.test.ts +0 -291
- package/src/buffer.ts +0 -519
- package/src/console.test.ts +0 -612
- package/src/console.ts +0 -1255
- package/src/edit-buffer.test.ts +0 -1769
- package/src/edit-buffer.ts +0 -411
- package/src/editor-view.test.ts +0 -1032
- package/src/editor-view.ts +0 -284
- package/src/examples/ascii-font-selection-demo.ts +0 -245
- package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
- package/src/examples/assets/concrete.png +0 -0
- package/src/examples/assets/crate.png +0 -0
- package/src/examples/assets/crate_emissive.png +0 -0
- package/src/examples/assets/forrest_background.png +0 -0
- package/src/examples/assets/hast-example.json +0 -1018
- package/src/examples/assets/heart.png +0 -0
- package/src/examples/assets/main_char_heavy_attack.png +0 -0
- package/src/examples/assets/main_char_idle.png +0 -0
- package/src/examples/assets/main_char_jump_end.png +0 -0
- package/src/examples/assets/main_char_jump_landing.png +0 -0
- package/src/examples/assets/main_char_jump_start.png +0 -0
- package/src/examples/assets/main_char_run_loop.png +0 -0
- package/src/examples/assets/roughness_map.jpg +0 -0
- package/src/examples/build.ts +0 -115
- package/src/examples/code-demo.ts +0 -584
- package/src/examples/console-demo.ts +0 -358
- package/src/examples/core-plugin-slots-demo.ts +0 -759
- package/src/examples/diff-demo.ts +0 -699
- package/src/examples/draggable-three-demo.ts +0 -259
- package/src/examples/editor-demo.ts +0 -322
- package/src/examples/extmarks-demo.ts +0 -204
- package/src/examples/focus-restore-demo.ts +0 -310
- package/src/examples/fonts.ts +0 -245
- package/src/examples/fractal-shader-demo.ts +0 -268
- package/src/examples/framebuffer-demo.ts +0 -674
- package/src/examples/full-unicode-demo.ts +0 -181
- package/src/examples/golden-star-demo.ts +0 -933
- package/src/examples/grayscale-buffer-demo.ts +0 -249
- package/src/examples/hast-syntax-highlighting-demo.ts +0 -129
- package/src/examples/index.ts +0 -925
- package/src/examples/input-demo.ts +0 -377
- package/src/examples/input-select-layout-demo.ts +0 -425
- package/src/examples/install.sh +0 -143
- package/src/examples/keypress-debug-demo.ts +0 -452
- package/src/examples/lib/HexList.ts +0 -122
- package/src/examples/lib/PaletteGrid.ts +0 -125
- package/src/examples/lib/standalone-keys.ts +0 -25
- package/src/examples/lib/tab-controller.ts +0 -243
- package/src/examples/lights-phong-demo.ts +0 -290
- package/src/examples/link-demo.ts +0 -220
- package/src/examples/live-state-demo.ts +0 -480
- package/src/examples/markdown-demo.ts +0 -620
- package/src/examples/mouse-interaction-demo.ts +0 -428
- package/src/examples/nested-zindex-demo.ts +0 -357
- package/src/examples/opacity-example.ts +0 -235
- package/src/examples/opentui-demo.ts +0 -1057
- package/src/examples/physx-planck-2d-demo.ts +0 -507
- package/src/examples/physx-rapier-2d-demo.ts +0 -526
- package/src/examples/relative-positioning-demo.ts +0 -323
- package/src/examples/scroll-example.ts +0 -214
- package/src/examples/scrollbox-mouse-test.ts +0 -112
- package/src/examples/scrollbox-overlay-hit-test.ts +0 -206
- package/src/examples/select-demo.ts +0 -237
- package/src/examples/shader-cube-demo.ts +0 -772
- package/src/examples/simple-layout-example.ts +0 -591
- package/src/examples/slider-demo.ts +0 -617
- package/src/examples/split-mode-demo.ts +0 -445
- package/src/examples/sprite-animation-demo.ts +0 -443
- package/src/examples/sprite-particle-generator-demo.ts +0 -486
- package/src/examples/static-sprite-demo.ts +0 -193
- package/src/examples/sticky-scroll-example.ts +0 -308
- package/src/examples/styled-text-demo.ts +0 -282
- package/src/examples/tab-select-demo.ts +0 -219
- package/src/examples/terminal-title.ts +0 -29
- package/src/examples/terminal.ts +0 -305
- package/src/examples/text-node-demo.ts +0 -416
- package/src/examples/text-selection-demo.ts +0 -377
- package/src/examples/text-table-demo.ts +0 -503
- package/src/examples/text-truncation-demo.ts +0 -481
- package/src/examples/text-wrap.ts +0 -757
- package/src/examples/texture-loading-demo.ts +0 -259
- package/src/examples/timeline-example.ts +0 -670
- package/src/examples/transparency-demo.ts +0 -241
- package/src/examples/vnode-composition-demo.ts +0 -404
- package/src/index.ts +0 -22
- package/src/lib/KeyHandler.integration.test.ts +0 -292
- package/src/lib/KeyHandler.stopPropagation.test.ts +0 -289
- package/src/lib/KeyHandler.test.ts +0 -662
- package/src/lib/KeyHandler.ts +0 -222
- package/src/lib/RGBA.test.ts +0 -984
- package/src/lib/RGBA.ts +0 -204
- package/src/lib/ascii.font.ts +0 -330
- package/src/lib/border.test.ts +0 -83
- package/src/lib/border.ts +0 -168
- package/src/lib/bunfs.test.ts +0 -27
- package/src/lib/bunfs.ts +0 -18
- package/src/lib/clipboard.test.ts +0 -41
- package/src/lib/clipboard.ts +0 -47
- package/src/lib/clock.ts +0 -31
- package/src/lib/data-paths.test.ts +0 -133
- package/src/lib/data-paths.ts +0 -109
- package/src/lib/debounce.ts +0 -106
- package/src/lib/detect-links.test.ts +0 -98
- package/src/lib/detect-links.ts +0 -56
- package/src/lib/env.test.ts +0 -228
- package/src/lib/env.ts +0 -209
- package/src/lib/extmarks-history.ts +0 -51
- package/src/lib/extmarks-multiwidth.test.ts +0 -322
- package/src/lib/extmarks.test.ts +0 -3457
- package/src/lib/extmarks.ts +0 -843
- package/src/lib/fonts/block.json +0 -405
- package/src/lib/fonts/grid.json +0 -265
- package/src/lib/fonts/huge.json +0 -741
- package/src/lib/fonts/pallet.json +0 -314
- package/src/lib/fonts/shade.json +0 -591
- package/src/lib/fonts/slick.json +0 -321
- package/src/lib/fonts/tiny.json +0 -69
- package/src/lib/hast-styled-text.ts +0 -59
- package/src/lib/index.ts +0 -21
- package/src/lib/keymapping.test.ts +0 -280
- package/src/lib/keymapping.ts +0 -87
- package/src/lib/objects-in-viewport.test.ts +0 -787
- package/src/lib/objects-in-viewport.ts +0 -153
- package/src/lib/output.capture.ts +0 -58
- package/src/lib/parse.keypress-kitty.protocol.test.ts +0 -340
- package/src/lib/parse.keypress-kitty.test.ts +0 -663
- package/src/lib/parse.keypress-kitty.ts +0 -439
- package/src/lib/parse.keypress.test.ts +0 -1849
- package/src/lib/parse.keypress.ts +0 -397
- package/src/lib/parse.mouse.test.ts +0 -552
- package/src/lib/parse.mouse.ts +0 -232
- package/src/lib/paste.ts +0 -16
- package/src/lib/queue.ts +0 -65
- package/src/lib/renderable.validations.test.ts +0 -87
- package/src/lib/renderable.validations.ts +0 -83
- package/src/lib/scroll-acceleration.ts +0 -98
- package/src/lib/selection.ts +0 -240
- package/src/lib/singleton.ts +0 -28
- package/src/lib/stdin-parser.test.ts +0 -1676
- package/src/lib/stdin-parser.ts +0 -1248
- package/src/lib/styled-text.ts +0 -178
- package/src/lib/terminal-capability-detection.test.ts +0 -202
- package/src/lib/terminal-capability-detection.ts +0 -79
- package/src/lib/terminal-palette.test.ts +0 -878
- package/src/lib/terminal-palette.ts +0 -383
- package/src/lib/tree-sitter/assets/README.md +0 -118
- package/src/lib/tree-sitter/assets/update.ts +0 -331
- package/src/lib/tree-sitter/assets.d.ts +0 -9
- package/src/lib/tree-sitter/cache.test.ts +0 -270
- package/src/lib/tree-sitter/client.test.ts +0 -1061
- package/src/lib/tree-sitter/client.ts +0 -615
- package/src/lib/tree-sitter/default-parsers.ts +0 -80
- package/src/lib/tree-sitter/download-utils.ts +0 -148
- package/src/lib/tree-sitter/index.ts +0 -28
- package/src/lib/tree-sitter/parser.worker.ts +0 -1001
- package/src/lib/tree-sitter/parsers-config.ts +0 -75
- package/src/lib/tree-sitter/resolve-ft.ts +0 -62
- package/src/lib/tree-sitter/types.ts +0 -81
- package/src/lib/tree-sitter-styled-text.test.ts +0 -1253
- package/src/lib/tree-sitter-styled-text.ts +0 -306
- package/src/lib/validate-dir-name.ts +0 -55
- package/src/lib/yoga.options.test.ts +0 -628
- package/src/lib/yoga.options.ts +0 -346
- package/src/plugins/core-slot.ts +0 -579
- package/src/plugins/registry.ts +0 -377
- package/src/plugins/types.ts +0 -46
- package/src/post/filters.ts +0 -888
- package/src/renderables/ASCIIFont.ts +0 -219
- package/src/renderables/Box.test.ts +0 -160
- package/src/renderables/Box.ts +0 -295
- package/src/renderables/Code.test.ts +0 -2062
- package/src/renderables/Code.ts +0 -357
- package/src/renderables/Diff.regression.test.ts +0 -226
- package/src/renderables/Diff.test.ts +0 -3027
- package/src/renderables/Diff.ts +0 -1209
- package/src/renderables/EditBufferRenderable.ts +0 -764
- package/src/renderables/FrameBuffer.ts +0 -47
- package/src/renderables/Input.test.ts +0 -1228
- package/src/renderables/Input.ts +0 -245
- package/src/renderables/LineNumberRenderable.ts +0 -675
- package/src/renderables/Markdown.ts +0 -1106
- package/src/renderables/ScrollBar.ts +0 -422
- package/src/renderables/ScrollBox.ts +0 -883
- package/src/renderables/Select.test.ts +0 -1010
- package/src/renderables/Select.ts +0 -523
- package/src/renderables/Slider.test.ts +0 -456
- package/src/renderables/Slider.ts +0 -347
- package/src/renderables/TabSelect.test.ts +0 -197
- package/src/renderables/TabSelect.ts +0 -455
- package/src/renderables/Text.selection-buffer.test.ts +0 -123
- package/src/renderables/Text.test.ts +0 -2660
- package/src/renderables/Text.ts +0 -147
- package/src/renderables/TextBufferRenderable.ts +0 -518
- package/src/renderables/TextNode.test.ts +0 -1058
- package/src/renderables/TextNode.ts +0 -325
- package/src/renderables/TextTable.test.ts +0 -1421
- package/src/renderables/TextTable.ts +0 -1344
- package/src/renderables/Textarea.ts +0 -732
- package/src/renderables/TimeToFirstDraw.ts +0 -89
- package/src/renderables/__snapshots__/Code.test.ts.snap +0 -13
- package/src/renderables/__snapshots__/Diff.test.ts.snap +0 -785
- package/src/renderables/__snapshots__/Text.test.ts.snap +0 -421
- package/src/renderables/__snapshots__/TextTable.test.ts.snap +0 -215
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +0 -144
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +0 -816
- package/src/renderables/__tests__/LineNumberRenderable.test.ts +0 -1787
- package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +0 -85
- package/src/renderables/__tests__/Markdown.test.ts +0 -2287
- package/src/renderables/__tests__/MultiRenderable.selection.test.ts +0 -87
- package/src/renderables/__tests__/Textarea.buffer.test.ts +0 -682
- package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +0 -675
- package/src/renderables/__tests__/Textarea.editing.test.ts +0 -2041
- package/src/renderables/__tests__/Textarea.error-handling.test.ts +0 -35
- package/src/renderables/__tests__/Textarea.events.test.ts +0 -738
- package/src/renderables/__tests__/Textarea.highlights.test.ts +0 -590
- package/src/renderables/__tests__/Textarea.keybinding.test.ts +0 -3149
- package/src/renderables/__tests__/Textarea.paste.test.ts +0 -357
- package/src/renderables/__tests__/Textarea.rendering.test.ts +0 -1864
- package/src/renderables/__tests__/Textarea.scroll.test.ts +0 -733
- package/src/renderables/__tests__/Textarea.selection.test.ts +0 -1590
- package/src/renderables/__tests__/Textarea.stress.test.ts +0 -670
- package/src/renderables/__tests__/Textarea.undo-redo.test.ts +0 -383
- package/src/renderables/__tests__/Textarea.visual-lines.test.ts +0 -310
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +0 -221
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +0 -89
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +0 -457
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +0 -158
- package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +0 -387
- package/src/renderables/__tests__/markdown-parser.test.ts +0 -217
- package/src/renderables/__tests__/renderable-test-utils.ts +0 -60
- package/src/renderables/composition/README.md +0 -8
- package/src/renderables/composition/VRenderable.ts +0 -32
- package/src/renderables/composition/constructs.ts +0 -127
- package/src/renderables/composition/vnode.ts +0 -289
- package/src/renderables/index.ts +0 -22
- package/src/renderables/markdown-parser.ts +0 -66
- package/src/renderer.ts +0 -2363
- package/src/runtime-plugin-support.ts +0 -39
- package/src/runtime-plugin.ts +0 -144
- package/src/syntax-style.test.ts +0 -841
- package/src/syntax-style.ts +0 -264
- package/src/testing/README.md +0 -210
- package/src/testing/capture-spans.test.ts +0 -194
- package/src/testing/integration.test.ts +0 -276
- package/src/testing/manual-clock.ts +0 -106
- package/src/testing/mock-keys.test.ts +0 -1356
- package/src/testing/mock-keys.ts +0 -449
- package/src/testing/mock-mouse.test.ts +0 -218
- package/src/testing/mock-mouse.ts +0 -247
- package/src/testing/mock-tree-sitter-client.ts +0 -73
- package/src/testing/spy.ts +0 -13
- package/src/testing/test-recorder.test.ts +0 -415
- package/src/testing/test-recorder.ts +0 -145
- package/src/testing/test-renderer.ts +0 -116
- package/src/testing.ts +0 -7
- package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +0 -481
- package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +0 -19
- package/src/tests/__snapshots__/scrollbox.test.ts.snap +0 -29
- package/src/tests/absolute-positioning.snapshot.test.ts +0 -638
- package/src/tests/allocator-stats.test.ts +0 -38
- package/src/tests/destroy-during-render.test.ts +0 -200
- package/src/tests/hover-cursor.test.ts +0 -98
- package/src/tests/native-span-feed-async.test.ts +0 -173
- package/src/tests/native-span-feed-close.test.ts +0 -120
- package/src/tests/native-span-feed-coverage.test.ts +0 -227
- package/src/tests/native-span-feed-edge-cases.test.ts +0 -352
- package/src/tests/native-span-feed-use-after-free.test.ts +0 -45
- package/src/tests/opacity.test.ts +0 -123
- package/src/tests/renderable.snapshot.test.ts +0 -524
- package/src/tests/renderable.test.ts +0 -1281
- package/src/tests/renderer.console-startup.test.ts +0 -65
- package/src/tests/renderer.control.test.ts +0 -364
- package/src/tests/renderer.core-slot-binding.test.ts +0 -952
- package/src/tests/renderer.cursor.test.ts +0 -26
- package/src/tests/renderer.destroy-during-render.test.ts +0 -110
- package/src/tests/renderer.focus-restore.test.ts +0 -228
- package/src/tests/renderer.focus.test.ts +0 -251
- package/src/tests/renderer.idle.test.ts +0 -219
- package/src/tests/renderer.input.test.ts +0 -2145
- package/src/tests/renderer.kitty-flags.test.ts +0 -195
- package/src/tests/renderer.mouse.test.ts +0 -1269
- package/src/tests/renderer.palette.test.ts +0 -629
- package/src/tests/renderer.selection.test.ts +0 -49
- package/src/tests/renderer.slot-registry.test.ts +0 -649
- package/src/tests/renderer.useMouse.test.ts +0 -50
- package/src/tests/runtime-plugin-support.fixture.ts +0 -11
- package/src/tests/runtime-plugin-support.test.ts +0 -28
- package/src/tests/runtime-plugin.fixture.ts +0 -40
- package/src/tests/runtime-plugin.test.ts +0 -190
- package/src/tests/scrollbox-culling-bug.test.ts +0 -114
- package/src/tests/scrollbox-hitgrid-resize.test.ts +0 -136
- package/src/tests/scrollbox-hitgrid.test.ts +0 -909
- package/src/tests/scrollbox.test.ts +0 -1530
- package/src/tests/wrap-resize-perf.test.ts +0 -229
- package/src/tests/yoga-setters.test.ts +0 -921
- package/src/text-buffer-view.test.ts +0 -705
- package/src/text-buffer-view.ts +0 -189
- package/src/text-buffer.test.ts +0 -347
- package/src/text-buffer.ts +0 -250
- package/src/types.ts +0 -152
- package/src/utils.ts +0 -88
- package/src/zig/ansi.zig +0 -268
- package/src/zig/bench/README.md +0 -50
- package/src/zig/bench/buffer-draw-text-buffer_bench.zig +0 -887
- package/src/zig/bench/edit-buffer_bench.zig +0 -476
- package/src/zig/bench/native-span-feed_bench.zig +0 -100
- package/src/zig/bench/rope-markers_bench.zig +0 -713
- package/src/zig/bench/rope_bench.zig +0 -514
- package/src/zig/bench/styled-text_bench.zig +0 -470
- package/src/zig/bench/text-buffer-coords_bench.zig +0 -362
- package/src/zig/bench/text-buffer-view_bench.zig +0 -459
- package/src/zig/bench/text-chunk-graphemes_bench.zig +0 -273
- package/src/zig/bench/utf8_bench.zig +0 -799
- package/src/zig/bench-utils.zig +0 -431
- package/src/zig/bench.zig +0 -217
- package/src/zig/buffer.zig +0 -2223
- package/src/zig/build.zig +0 -289
- package/src/zig/build.zig.zon +0 -16
- package/src/zig/edit-buffer.zig +0 -825
- package/src/zig/editor-view.zig +0 -802
- package/src/zig/event-bus.zig +0 -13
- package/src/zig/event-emitter.zig +0 -65
- package/src/zig/file-logger.zig +0 -92
- package/src/zig/grapheme.zig +0 -599
- package/src/zig/lib.zig +0 -1834
- package/src/zig/link.zig +0 -333
- package/src/zig/logger.zig +0 -43
- package/src/zig/mem-registry.zig +0 -125
- package/src/zig/native-span-feed-bench-lib.zig +0 -7
- package/src/zig/native-span-feed.zig +0 -708
- package/src/zig/renderer.zig +0 -1386
- package/src/zig/rope.zig +0 -1220
- package/src/zig/syntax-style.zig +0 -161
- package/src/zig/terminal.zig +0 -975
- package/src/zig/test.zig +0 -70
- package/src/zig/tests/README.md +0 -18
- package/src/zig/tests/buffer_test.zig +0 -2526
- package/src/zig/tests/edit-buffer-history_test.zig +0 -271
- package/src/zig/tests/edit-buffer_test.zig +0 -1689
- package/src/zig/tests/editor-view_test.zig +0 -3299
- package/src/zig/tests/event-emitter_test.zig +0 -249
- package/src/zig/tests/grapheme_test.zig +0 -1304
- package/src/zig/tests/link_test.zig +0 -190
- package/src/zig/tests/mem-registry_test.zig +0 -473
- package/src/zig/tests/memory_leak_regression_test.zig +0 -159
- package/src/zig/tests/native-span-feed_test.zig +0 -1264
- package/src/zig/tests/renderer_test.zig +0 -1010
- package/src/zig/tests/rope-nested_test.zig +0 -712
- package/src/zig/tests/rope_fuzz_test.zig +0 -238
- package/src/zig/tests/rope_test.zig +0 -2362
- package/src/zig/tests/segment-merge.test.zig +0 -148
- package/src/zig/tests/syntax-style_test.zig +0 -557
- package/src/zig/tests/terminal_test.zig +0 -719
- package/src/zig/tests/text-buffer-drawing_test.zig +0 -3237
- package/src/zig/tests/text-buffer-highlights_test.zig +0 -666
- package/src/zig/tests/text-buffer-iterators_test.zig +0 -776
- package/src/zig/tests/text-buffer-segment_test.zig +0 -320
- package/src/zig/tests/text-buffer-selection_test.zig +0 -1035
- package/src/zig/tests/text-buffer-selection_viewport_test.zig +0 -358
- package/src/zig/tests/text-buffer-view_test.zig +0 -3649
- package/src/zig/tests/text-buffer_test.zig +0 -2191
- package/src/zig/tests/unicode-width-map.zon +0 -3909
- package/src/zig/tests/utf8_no_zwj_test.zig +0 -260
- package/src/zig/tests/utf8_test.zig +0 -4057
- package/src/zig/tests/utf8_wcwidth_cursor_test.zig +0 -267
- package/src/zig/tests/utf8_wcwidth_test.zig +0 -357
- package/src/zig/tests/word-wrap-editing_test.zig +0 -498
- package/src/zig/tests/wrap-cache-perf_test.zig +0 -113
- package/src/zig/text-buffer-iterators.zig +0 -499
- package/src/zig/text-buffer-segment.zig +0 -404
- package/src/zig/text-buffer-view.zig +0 -1371
- package/src/zig/text-buffer.zig +0 -1180
- package/src/zig/utf8.zig +0 -1948
- package/src/zig/utils.zig +0 -9
- package/src/zig-structs.ts +0 -261
- package/src/zig.ts +0 -3843
- package/tsconfig.build.json +0 -22
- package/tsconfig.json +0 -28
- /package/{src/lib/tree-sitter/assets → assets}/javascript/highlights.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/javascript/tree-sitter-javascript.wasm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/markdown/highlights.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/markdown/injections.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/markdown/tree-sitter-markdown.wasm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/highlights.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/typescript/highlights.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/typescript/tree-sitter-typescript.wasm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/zig/highlights.scm +0 -0
- /package/{src/lib/tree-sitter/assets → assets}/zig/tree-sitter-zig.wasm +0 -0
package/src/post/filters.ts
DELETED
|
@@ -1,888 +0,0 @@
|
|
|
1
|
-
import type { OptimizedBuffer } from "../buffer.js"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Applies a scanline effect by darkening every nth row.
|
|
5
|
-
*/
|
|
6
|
-
export function applyScanlines(buffer: OptimizedBuffer, strength: number = 0.8, step: number = 2): void {
|
|
7
|
-
const width = buffer.width
|
|
8
|
-
const height = buffer.height
|
|
9
|
-
const bg = buffer.buffers.bg
|
|
10
|
-
|
|
11
|
-
for (let y = 0; y < height; y += step) {
|
|
12
|
-
for (let x = 0; x < width; x++) {
|
|
13
|
-
const colorIndex = (y * width + x) * 4
|
|
14
|
-
bg[colorIndex] *= strength // R
|
|
15
|
-
bg[colorIndex + 1] *= strength // G
|
|
16
|
-
bg[colorIndex + 2] *= strength // B
|
|
17
|
-
// Keep Alpha the same
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Converts the buffer colors to grayscale.
|
|
24
|
-
*/
|
|
25
|
-
export function applyGrayscale(buffer: OptimizedBuffer): void {
|
|
26
|
-
const size = buffer.width * buffer.height
|
|
27
|
-
const fg = buffer.buffers.fg
|
|
28
|
-
const bg = buffer.buffers.bg
|
|
29
|
-
|
|
30
|
-
for (let i = 0; i < size; i++) {
|
|
31
|
-
const colorIndex = i * 4
|
|
32
|
-
|
|
33
|
-
// Grayscale foreground
|
|
34
|
-
const fgR = fg[colorIndex]
|
|
35
|
-
const fgG = fg[colorIndex + 1]
|
|
36
|
-
const fgB = fg[colorIndex + 2]
|
|
37
|
-
const fgLum = 0.299 * fgR + 0.587 * fgG + 0.114 * fgB
|
|
38
|
-
fg[colorIndex] = fgLum
|
|
39
|
-
fg[colorIndex + 1] = fgLum
|
|
40
|
-
fg[colorIndex + 2] = fgLum
|
|
41
|
-
|
|
42
|
-
// Grayscale background
|
|
43
|
-
const bgR = bg[colorIndex]
|
|
44
|
-
const bgG = bg[colorIndex + 1]
|
|
45
|
-
const bgB = bg[colorIndex + 2]
|
|
46
|
-
const bgLum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB
|
|
47
|
-
bg[colorIndex] = bgLum
|
|
48
|
-
bg[colorIndex + 1] = bgLum
|
|
49
|
-
bg[colorIndex + 2] = bgLum
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Applies a sepia tone to the buffer.
|
|
55
|
-
*/
|
|
56
|
-
export function applySepia(buffer: OptimizedBuffer): void {
|
|
57
|
-
const size = buffer.width * buffer.height
|
|
58
|
-
const fg = buffer.buffers.fg
|
|
59
|
-
const bg = buffer.buffers.bg
|
|
60
|
-
|
|
61
|
-
for (let i = 0; i < size; i++) {
|
|
62
|
-
const colorIndex = i * 4
|
|
63
|
-
|
|
64
|
-
// Sepia foreground
|
|
65
|
-
let fgR = fg[colorIndex]
|
|
66
|
-
let fgG = fg[colorIndex + 1]
|
|
67
|
-
let fgB = fg[colorIndex + 2]
|
|
68
|
-
let newFgR = Math.min(1.0, fgR * 0.393 + fgG * 0.769 + fgB * 0.189)
|
|
69
|
-
let newFgG = Math.min(1.0, fgR * 0.349 + fgG * 0.686 + fgB * 0.168)
|
|
70
|
-
let newFgB = Math.min(1.0, fgR * 0.272 + fgG * 0.534 + fgB * 0.131)
|
|
71
|
-
fg[colorIndex] = newFgR
|
|
72
|
-
fg[colorIndex + 1] = newFgG
|
|
73
|
-
fg[colorIndex + 2] = newFgB
|
|
74
|
-
|
|
75
|
-
// Sepia background
|
|
76
|
-
let bgR = bg[colorIndex]
|
|
77
|
-
let bgG = bg[colorIndex + 1]
|
|
78
|
-
let bgB = bg[colorIndex + 2]
|
|
79
|
-
let newBgR = Math.min(1.0, bgR * 0.393 + bgG * 0.769 + bgB * 0.189)
|
|
80
|
-
let newBgG = Math.min(1.0, bgR * 0.349 + bgG * 0.686 + bgB * 0.168)
|
|
81
|
-
let newBgB = Math.min(1.0, bgR * 0.272 + bgG * 0.534 + bgB * 0.131)
|
|
82
|
-
bg[colorIndex] = newBgR
|
|
83
|
-
bg[colorIndex + 1] = newBgG
|
|
84
|
-
bg[colorIndex + 2] = newBgB
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Inverts the colors in the buffer.
|
|
90
|
-
*/
|
|
91
|
-
export function applyInvert(buffer: OptimizedBuffer): void {
|
|
92
|
-
const size = buffer.width * buffer.height
|
|
93
|
-
const fg = buffer.buffers.fg
|
|
94
|
-
const bg = buffer.buffers.bg
|
|
95
|
-
|
|
96
|
-
for (let i = 0; i < size; i++) {
|
|
97
|
-
const colorIndex = i * 4
|
|
98
|
-
fg[colorIndex] = 1.0 - fg[colorIndex]
|
|
99
|
-
fg[colorIndex + 1] = 1.0 - fg[colorIndex + 1]
|
|
100
|
-
fg[colorIndex + 2] = 1.0 - fg[colorIndex + 2]
|
|
101
|
-
|
|
102
|
-
bg[colorIndex] = 1.0 - bg[colorIndex]
|
|
103
|
-
bg[colorIndex + 1] = 1.0 - bg[colorIndex + 1]
|
|
104
|
-
bg[colorIndex + 2] = 1.0 - bg[colorIndex + 2]
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Adds random noise to the buffer colors.
|
|
110
|
-
*/
|
|
111
|
-
export function applyNoise(buffer: OptimizedBuffer, strength: number = 0.1): void {
|
|
112
|
-
const size = buffer.width * buffer.height
|
|
113
|
-
const fg = buffer.buffers.fg
|
|
114
|
-
const bg = buffer.buffers.bg
|
|
115
|
-
|
|
116
|
-
for (let i = 0; i < size; i++) {
|
|
117
|
-
const colorIndex = i * 4
|
|
118
|
-
const noise = (Math.random() - 0.5) * strength
|
|
119
|
-
|
|
120
|
-
fg[colorIndex] = Math.max(0, Math.min(1, fg[colorIndex] + noise))
|
|
121
|
-
fg[colorIndex + 1] = Math.max(0, Math.min(1, fg[colorIndex + 1] + noise))
|
|
122
|
-
fg[colorIndex + 2] = Math.max(0, Math.min(1, fg[colorIndex + 2] + noise))
|
|
123
|
-
|
|
124
|
-
bg[colorIndex] = Math.max(0, Math.min(1, bg[colorIndex] + noise))
|
|
125
|
-
bg[colorIndex + 1] = Math.max(0, Math.min(1, bg[colorIndex + 1] + noise))
|
|
126
|
-
bg[colorIndex + 2] = Math.max(0, Math.min(1, bg[colorIndex + 2] + noise))
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Applies a simplified chromatic aberration effect.
|
|
132
|
-
*/
|
|
133
|
-
export function applyChromaticAberration(buffer: OptimizedBuffer, strength: number = 1): void {
|
|
134
|
-
const width = buffer.width
|
|
135
|
-
const height = buffer.height
|
|
136
|
-
const srcFg = Float32Array.from(buffer.buffers.fg) // Copy original fg data
|
|
137
|
-
const destFg = buffer.buffers.fg
|
|
138
|
-
const centerX = width / 2
|
|
139
|
-
const centerY = height / 2
|
|
140
|
-
|
|
141
|
-
for (let y = 0; y < height; y++) {
|
|
142
|
-
for (let x = 0; x < width; x++) {
|
|
143
|
-
const dx = x - centerX
|
|
144
|
-
const dy = y - centerY
|
|
145
|
-
const offset = Math.round((Math.sqrt(dx * dx + dy * dy) / Math.max(centerX, centerY)) * strength)
|
|
146
|
-
|
|
147
|
-
const rX = Math.max(0, Math.min(width - 1, x - offset))
|
|
148
|
-
const bX = Math.max(0, Math.min(width - 1, x + offset))
|
|
149
|
-
|
|
150
|
-
const rIndex = (y * width + rX) * 4
|
|
151
|
-
const gIndex = (y * width + x) * 4 // Green from original position
|
|
152
|
-
const bIndex = (y * width + bX) * 4
|
|
153
|
-
const destIndex = (y * width + x) * 4
|
|
154
|
-
|
|
155
|
-
destFg[destIndex] = srcFg[rIndex] // Red from left offset
|
|
156
|
-
destFg[destIndex + 1] = srcFg[gIndex + 1] // Green from center
|
|
157
|
-
destFg[destIndex + 2] = srcFg[bIndex + 2] // Blue from right offset
|
|
158
|
-
// Keep original Alpha
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Converts the buffer to ASCII art based on background brightness.
|
|
165
|
-
*/
|
|
166
|
-
export function applyAsciiArt(buffer: OptimizedBuffer, ramp: string = " .:-=+*#%@"): void {
|
|
167
|
-
const width = buffer.width
|
|
168
|
-
const height = buffer.height
|
|
169
|
-
const chars = buffer.buffers.char
|
|
170
|
-
const bg = buffer.buffers.bg
|
|
171
|
-
const rampLength = ramp.length
|
|
172
|
-
|
|
173
|
-
for (let y = 0; y < height; y++) {
|
|
174
|
-
for (let x = 0; x < width; x++) {
|
|
175
|
-
const index = y * width + x
|
|
176
|
-
const colorIndex = index * 4
|
|
177
|
-
const bgR = bg[colorIndex]
|
|
178
|
-
const bgG = bg[colorIndex + 1]
|
|
179
|
-
const bgB = bg[colorIndex + 2]
|
|
180
|
-
const lum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB // Luminance
|
|
181
|
-
const rampIndex = Math.min(rampLength - 1, Math.floor(lum * rampLength))
|
|
182
|
-
chars[index] = ramp[rampIndex].charCodeAt(0)
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
interface ActiveGlitch {
|
|
188
|
-
y: number
|
|
189
|
-
type: "shift" | "flip" | "color"
|
|
190
|
-
amount: number
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export class DistortionEffect {
|
|
194
|
-
// --- Configurable Parameters ---
|
|
195
|
-
public glitchChancePerSecond: number = 0.5
|
|
196
|
-
public maxGlitchLines: number = 3
|
|
197
|
-
public minGlitchDuration: number = 0.05
|
|
198
|
-
public maxGlitchDuration: number = 0.2
|
|
199
|
-
public maxShiftAmount: number = 10
|
|
200
|
-
public shiftFlipRatio: number = 0.6
|
|
201
|
-
public colorGlitchChance: number = 0.2
|
|
202
|
-
|
|
203
|
-
// --- Internal State ---
|
|
204
|
-
private lastGlitchTime: number = 0
|
|
205
|
-
private glitchDuration: number = 0
|
|
206
|
-
private activeGlitches: ActiveGlitch[] = []
|
|
207
|
-
|
|
208
|
-
constructor(options?: Partial<DistortionEffect>) {
|
|
209
|
-
if (options) {
|
|
210
|
-
Object.assign(this, options)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Applies the animated distortion/glitch effect to the buffer.
|
|
216
|
-
*/
|
|
217
|
-
public apply(buffer: OptimizedBuffer, deltaTime: number): void {
|
|
218
|
-
const width = buffer.width
|
|
219
|
-
const height = buffer.height
|
|
220
|
-
const buf = buffer.buffers
|
|
221
|
-
// Note: Using internal timer based on deltaTime is more reliable than Date.now()
|
|
222
|
-
|
|
223
|
-
// Update glitch timer
|
|
224
|
-
this.lastGlitchTime += deltaTime
|
|
225
|
-
|
|
226
|
-
// End current glitch if duration is over
|
|
227
|
-
if (this.activeGlitches.length > 0 && this.lastGlitchTime >= this.glitchDuration) {
|
|
228
|
-
this.activeGlitches = []
|
|
229
|
-
this.glitchDuration = 0
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Chance to start a new glitch
|
|
233
|
-
if (this.activeGlitches.length === 0 && Math.random() < this.glitchChancePerSecond * deltaTime) {
|
|
234
|
-
this.lastGlitchTime = 0
|
|
235
|
-
this.glitchDuration = this.minGlitchDuration + Math.random() * (this.maxGlitchDuration - this.minGlitchDuration)
|
|
236
|
-
const numGlitches = 1 + Math.floor(Math.random() * this.maxGlitchLines)
|
|
237
|
-
|
|
238
|
-
for (let i = 0; i < numGlitches; i++) {
|
|
239
|
-
const y = Math.floor(Math.random() * height)
|
|
240
|
-
let type: ActiveGlitch["type"]
|
|
241
|
-
let amount = 0
|
|
242
|
-
|
|
243
|
-
const typeRoll = Math.random()
|
|
244
|
-
if (typeRoll < this.colorGlitchChance) {
|
|
245
|
-
type = "color"
|
|
246
|
-
} else {
|
|
247
|
-
// Determine shift or flip based on remaining probability
|
|
248
|
-
const shiftRoll = (typeRoll - this.colorGlitchChance) / (1 - this.colorGlitchChance)
|
|
249
|
-
if (shiftRoll < this.shiftFlipRatio) {
|
|
250
|
-
type = "shift"
|
|
251
|
-
amount = Math.floor((Math.random() - 0.5) * 2 * this.maxShiftAmount)
|
|
252
|
-
} else {
|
|
253
|
-
type = "flip"
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Avoid glitching the same line twice in one burst
|
|
258
|
-
if (!this.activeGlitches.some((g) => g.y === y)) {
|
|
259
|
-
this.activeGlitches.push({ y, type, amount })
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Apply active glitches
|
|
265
|
-
if (this.activeGlitches.length > 0) {
|
|
266
|
-
// Create temporary arrays lazily if needed (minor optimization for shift/flip)
|
|
267
|
-
let tempChar: Uint32Array | null = null
|
|
268
|
-
let tempFg: Float32Array | null = null
|
|
269
|
-
let tempBg: Float32Array | null = null
|
|
270
|
-
let tempAttr: Uint8Array | null = null
|
|
271
|
-
|
|
272
|
-
for (const glitch of this.activeGlitches) {
|
|
273
|
-
const y = glitch.y
|
|
274
|
-
// Ensure y is within bounds (safer)
|
|
275
|
-
if (y < 0 || y >= height) continue
|
|
276
|
-
const baseIndex = y * width
|
|
277
|
-
|
|
278
|
-
if (glitch.type === "shift" || glitch.type === "flip") {
|
|
279
|
-
// Lazily create temp buffers only when needed for shift/flip
|
|
280
|
-
if (!tempChar) {
|
|
281
|
-
tempChar = new Uint32Array(width)
|
|
282
|
-
tempFg = new Float32Array(width * 4)
|
|
283
|
-
tempBg = new Float32Array(width * 4)
|
|
284
|
-
tempAttr = new Uint8Array(width)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// 1. Copy original row data to temp buffers
|
|
288
|
-
try {
|
|
289
|
-
tempChar.set(buf.char.subarray(baseIndex, baseIndex + width))
|
|
290
|
-
tempFg!.set(buf.fg.subarray(baseIndex * 4, (baseIndex + width) * 4))
|
|
291
|
-
tempBg!.set(buf.bg.subarray(baseIndex * 4, (baseIndex + width) * 4))
|
|
292
|
-
tempAttr!.set(buf.attributes.subarray(baseIndex, baseIndex + width))
|
|
293
|
-
} catch (e) {
|
|
294
|
-
// Handle potential range errors if buffer size changes unexpectedly
|
|
295
|
-
console.error(`Error copying row ${y} for distortion:`, e)
|
|
296
|
-
continue
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (glitch.type === "shift") {
|
|
300
|
-
const shift = glitch.amount
|
|
301
|
-
for (let x = 0; x < width; x++) {
|
|
302
|
-
const srcX = (x - shift + width) % width // Wrap around shift
|
|
303
|
-
const destIndex = baseIndex + x
|
|
304
|
-
const srcTempIndex = srcX
|
|
305
|
-
|
|
306
|
-
buf.char[destIndex] = tempChar[srcTempIndex]
|
|
307
|
-
buf.attributes[destIndex] = tempAttr![srcTempIndex]
|
|
308
|
-
|
|
309
|
-
const destColorIndex = destIndex * 4
|
|
310
|
-
const srcTempColorIndex = srcTempIndex * 4
|
|
311
|
-
|
|
312
|
-
buf.fg.set(tempFg!.subarray(srcTempColorIndex, srcTempColorIndex + 4), destColorIndex)
|
|
313
|
-
buf.bg.set(tempBg!.subarray(srcTempColorIndex, srcTempColorIndex + 4), destColorIndex)
|
|
314
|
-
}
|
|
315
|
-
} else {
|
|
316
|
-
// type === 'flip'
|
|
317
|
-
for (let x = 0; x < width; x++) {
|
|
318
|
-
const srcX = width - 1 - x // Flipped index
|
|
319
|
-
const destIndex = baseIndex + x
|
|
320
|
-
const srcTempIndex = srcX
|
|
321
|
-
|
|
322
|
-
buf.char[destIndex] = tempChar[srcTempIndex]
|
|
323
|
-
buf.attributes[destIndex] = tempAttr![srcTempIndex]
|
|
324
|
-
|
|
325
|
-
const destColorIndex = destIndex * 4
|
|
326
|
-
const srcTempColorIndex = srcTempIndex * 4
|
|
327
|
-
|
|
328
|
-
buf.fg.set(tempFg!.subarray(srcTempColorIndex, srcTempColorIndex + 4), destColorIndex)
|
|
329
|
-
buf.bg.set(tempBg!.subarray(srcTempColorIndex, srcTempColorIndex + 4), destColorIndex)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
} else if (glitch.type === "color") {
|
|
333
|
-
const glitchStart = Math.floor(Math.random() * width)
|
|
334
|
-
// Make glitch length at least 1 pixel, up to the rest of the line
|
|
335
|
-
const maxPossibleLength = width - glitchStart
|
|
336
|
-
// Introduce more variability: sometimes short, sometimes long, but not always full width
|
|
337
|
-
let glitchLength = Math.floor(Math.random() * maxPossibleLength) + 1
|
|
338
|
-
if (Math.random() < 0.2) {
|
|
339
|
-
// 20% chance of a shorter, more intense glitch segment
|
|
340
|
-
glitchLength = Math.floor(Math.random() * (width / 4)) + 1
|
|
341
|
-
}
|
|
342
|
-
glitchLength = Math.min(glitchLength, maxPossibleLength)
|
|
343
|
-
|
|
344
|
-
for (let x = glitchStart; x < glitchStart + glitchLength; x++) {
|
|
345
|
-
if (x >= width) break // Boundary check
|
|
346
|
-
|
|
347
|
-
const destIndex = baseIndex + x
|
|
348
|
-
const destColorIndex = destIndex * 4
|
|
349
|
-
|
|
350
|
-
let rFg, gFg, bFg, rBg, gBg, bBg
|
|
351
|
-
|
|
352
|
-
// More varied and "glitchy" colors
|
|
353
|
-
const colorMode = Math.random()
|
|
354
|
-
if (colorMode < 0.33) {
|
|
355
|
-
// Pure random
|
|
356
|
-
rFg = Math.random()
|
|
357
|
-
gFg = Math.random()
|
|
358
|
-
bFg = Math.random()
|
|
359
|
-
rBg = Math.random()
|
|
360
|
-
gBg = Math.random()
|
|
361
|
-
bBg = Math.random()
|
|
362
|
-
} else if (colorMode < 0.66) {
|
|
363
|
-
// Single channel emphasis or block color
|
|
364
|
-
const emphasis = Math.random()
|
|
365
|
-
if (emphasis < 0.25) {
|
|
366
|
-
rFg = Math.random()
|
|
367
|
-
gFg = 0
|
|
368
|
-
bFg = 0
|
|
369
|
-
} // Red
|
|
370
|
-
else if (emphasis < 0.5) {
|
|
371
|
-
rFg = 0
|
|
372
|
-
gFg = Math.random()
|
|
373
|
-
bFg = 0
|
|
374
|
-
} // Green
|
|
375
|
-
else if (emphasis < 0.75) {
|
|
376
|
-
rFg = 0
|
|
377
|
-
gFg = 0
|
|
378
|
-
bFg = Math.random()
|
|
379
|
-
} // Blue
|
|
380
|
-
else {
|
|
381
|
-
// Bright glitch color
|
|
382
|
-
const glitchColorRoll = Math.random()
|
|
383
|
-
if (glitchColorRoll < 0.33) {
|
|
384
|
-
rFg = 1
|
|
385
|
-
gFg = 0
|
|
386
|
-
bFg = 1
|
|
387
|
-
} // Magenta
|
|
388
|
-
else if (glitchColorRoll < 0.66) {
|
|
389
|
-
rFg = 0
|
|
390
|
-
gFg = 1
|
|
391
|
-
bFg = 1
|
|
392
|
-
} // Cyan
|
|
393
|
-
else {
|
|
394
|
-
rFg = 1
|
|
395
|
-
gFg = 1
|
|
396
|
-
bFg = 0
|
|
397
|
-
} // Yellow
|
|
398
|
-
}
|
|
399
|
-
// Background can be inverted or similar to FG
|
|
400
|
-
if (Math.random() < 0.5) {
|
|
401
|
-
rBg = 1 - rFg
|
|
402
|
-
gBg = 1 - gFg
|
|
403
|
-
bBg = 1 - bFg
|
|
404
|
-
} else {
|
|
405
|
-
rBg = rFg * (Math.random() * 0.5 + 0.2) // Darker shade of fg
|
|
406
|
-
gBg = gFg * (Math.random() * 0.5 + 0.2)
|
|
407
|
-
bBg = bFg * (Math.random() * 0.5 + 0.2)
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
// Inverted or high contrast
|
|
411
|
-
rFg = Math.random() > 0.5 ? 1 : 0
|
|
412
|
-
gFg = Math.random() > 0.5 ? 1 : 0
|
|
413
|
-
bFg = Math.random() > 0.5 ? 1 : 0
|
|
414
|
-
rBg = 1 - rFg
|
|
415
|
-
gBg = 1 - gFg
|
|
416
|
-
bBg = 1 - bFg
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
buf.fg[destColorIndex] = rFg
|
|
420
|
-
buf.fg[destColorIndex + 1] = gFg
|
|
421
|
-
buf.fg[destColorIndex + 2] = bFg
|
|
422
|
-
// Keep alpha buf.fg[destColorIndex + 3]
|
|
423
|
-
|
|
424
|
-
buf.bg[destColorIndex] = rBg
|
|
425
|
-
buf.bg[destColorIndex + 1] = gBg
|
|
426
|
-
buf.bg[destColorIndex + 2] = bBg
|
|
427
|
-
// Keep alpha buf.bg[destColorIndex + 3]
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Applies a vignette effect by darkening the corners, optimized with precomputation.
|
|
437
|
-
*/
|
|
438
|
-
export class VignetteEffect {
|
|
439
|
-
private _strength: number
|
|
440
|
-
// Stores the base attenuation (0 at center, 1 at max distance) for each pixel
|
|
441
|
-
private precomputedBaseAttenuation: Float32Array | null = null
|
|
442
|
-
private cachedWidth: number = -1
|
|
443
|
-
private cachedHeight: number = -1
|
|
444
|
-
|
|
445
|
-
constructor(strength: number = 0.5) {
|
|
446
|
-
this._strength = strength
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
public set strength(newStrength: number) {
|
|
450
|
-
this._strength = Math.max(0, newStrength) // Ensure strength is non-negative
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
public get strength(): number {
|
|
454
|
-
return this._strength
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
private _computeFactors(width: number, height: number): void {
|
|
458
|
-
this.precomputedBaseAttenuation = new Float32Array(width * height)
|
|
459
|
-
const centerX = width / 2
|
|
460
|
-
const centerY = height / 2
|
|
461
|
-
const maxDistSq = centerX * centerX + centerY * centerY
|
|
462
|
-
const safeMaxDistSq = maxDistSq === 0 ? 1 : maxDistSq // Avoid division by zero
|
|
463
|
-
|
|
464
|
-
for (let y = 0; y < height; y++) {
|
|
465
|
-
const dy = y - centerY
|
|
466
|
-
const dySq = dy * dy
|
|
467
|
-
for (let x = 0; x < width; x++) {
|
|
468
|
-
const dx = x - centerX
|
|
469
|
-
const distSq = dx * dx + dySq
|
|
470
|
-
// Calculate base attenuation (0 to 1 based on distance)
|
|
471
|
-
const baseAttenuation = Math.min(1, distSq / safeMaxDistSq)
|
|
472
|
-
const index = y * width + x
|
|
473
|
-
this.precomputedBaseAttenuation[index] = baseAttenuation
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
this.cachedWidth = width
|
|
477
|
-
this.cachedHeight = height
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Applies the vignette effect using precomputed base attenuation and current strength.
|
|
482
|
-
*/
|
|
483
|
-
public apply(buffer: OptimizedBuffer): void {
|
|
484
|
-
const width = buffer.width
|
|
485
|
-
const height = buffer.height
|
|
486
|
-
const buf = buffer.buffers
|
|
487
|
-
const size = width * height
|
|
488
|
-
|
|
489
|
-
// Recompute base attenuation if dimensions changed or factors haven't been computed yet
|
|
490
|
-
if (width !== this.cachedWidth || height !== this.cachedHeight || !this.precomputedBaseAttenuation) {
|
|
491
|
-
this._computeFactors(width, height)
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Apply effect using precomputed base and current strength
|
|
495
|
-
for (let i = 0; i < size; i++) {
|
|
496
|
-
// Calculate the final factor dynamically
|
|
497
|
-
const factor = Math.max(0, 1 - this.precomputedBaseAttenuation![i] * this._strength)
|
|
498
|
-
const colorIndex = i * 4
|
|
499
|
-
|
|
500
|
-
buf.fg[colorIndex] *= factor
|
|
501
|
-
buf.fg[colorIndex + 1] *= factor
|
|
502
|
-
buf.fg[colorIndex + 2] *= factor
|
|
503
|
-
|
|
504
|
-
buf.bg[colorIndex] *= factor
|
|
505
|
-
buf.bg[colorIndex + 1] *= factor
|
|
506
|
-
buf.bg[colorIndex + 2] *= factor
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* Adjusts the overall brightness of the buffer.
|
|
513
|
-
*/
|
|
514
|
-
export class BrightnessEffect {
|
|
515
|
-
private _brightness: number
|
|
516
|
-
|
|
517
|
-
constructor(brightness: number = 1.0) {
|
|
518
|
-
this._brightness = Math.max(0, brightness) // Ensure brightness is non-negative
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
public set brightness(newBrightness: number) {
|
|
522
|
-
this._brightness = Math.max(0, newBrightness)
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
public get brightness(): number {
|
|
526
|
-
return this._brightness
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
/**
|
|
530
|
-
* Applies the brightness adjustment to the buffer.
|
|
531
|
-
*/
|
|
532
|
-
public apply(buffer: OptimizedBuffer): void {
|
|
533
|
-
const size = buffer.width * buffer.height
|
|
534
|
-
const fg = buffer.buffers.fg
|
|
535
|
-
const bg = buffer.buffers.bg
|
|
536
|
-
const factor = this._brightness
|
|
537
|
-
|
|
538
|
-
// No need to process if brightness is 1 (no change)
|
|
539
|
-
if (factor === 1.0) {
|
|
540
|
-
return
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
for (let i = 0; i < size; i++) {
|
|
544
|
-
const colorIndex = i * 4
|
|
545
|
-
|
|
546
|
-
// Adjust foreground
|
|
547
|
-
fg[colorIndex] = Math.min(1.0, fg[colorIndex] * factor)
|
|
548
|
-
fg[colorIndex + 1] = Math.min(1.0, fg[colorIndex + 1] * factor)
|
|
549
|
-
fg[colorIndex + 2] = Math.min(1.0, fg[colorIndex + 2] * factor)
|
|
550
|
-
// Alpha fg[colorIndex + 3] remains unchanged
|
|
551
|
-
|
|
552
|
-
// Adjust background
|
|
553
|
-
bg[colorIndex] = Math.min(1.0, bg[colorIndex] * factor)
|
|
554
|
-
bg[colorIndex + 1] = Math.min(1.0, bg[colorIndex + 1] * factor)
|
|
555
|
-
bg[colorIndex + 2] = Math.min(1.0, bg[colorIndex + 2] * factor)
|
|
556
|
-
// Alpha bg[colorIndex + 3] remains unchanged
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Applies a simple box blur. (Expensive and may look bad with text).
|
|
563
|
-
*/
|
|
564
|
-
export class BlurEffect {
|
|
565
|
-
private _radius: number
|
|
566
|
-
|
|
567
|
-
constructor(radius: number = 1) {
|
|
568
|
-
this._radius = Math.max(0, Math.round(radius)) // Radius should be a non-negative integer
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
public set radius(newRadius: number) {
|
|
572
|
-
this._radius = Math.max(0, Math.round(newRadius))
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
public get radius(): number {
|
|
576
|
-
return this._radius
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/**
|
|
580
|
-
* Applies an optimized separable box blur using a moving average (sliding window).
|
|
581
|
-
*/
|
|
582
|
-
public apply(buffer: OptimizedBuffer): void {
|
|
583
|
-
const radius = this._radius
|
|
584
|
-
if (radius <= 0) return // No blur if radius is 0 or less
|
|
585
|
-
|
|
586
|
-
const width = buffer.width
|
|
587
|
-
const height = buffer.height
|
|
588
|
-
const buf = buffer.buffers // Get the full buffer object
|
|
589
|
-
const srcFg = buf.fg
|
|
590
|
-
const srcBg = buf.bg
|
|
591
|
-
const destFg = buf.fg // We'll write back to the original buffer
|
|
592
|
-
const destBg = buf.bg
|
|
593
|
-
const chars = buf.char // Get reference to character buffer
|
|
594
|
-
const size = width * height
|
|
595
|
-
const numChannels = 4 // RGBA
|
|
596
|
-
|
|
597
|
-
// Temporary buffer for the horizontal pass result
|
|
598
|
-
const tempBufferFg = new Float32Array(size * numChannels)
|
|
599
|
-
const tempBufferBg = new Float32Array(size * numChannels)
|
|
600
|
-
|
|
601
|
-
const windowSize = radius * 2 + 1
|
|
602
|
-
|
|
603
|
-
// --- Horizontal Pass --- Fg
|
|
604
|
-
for (let y = 0; y < height; y++) {
|
|
605
|
-
let sumR = 0,
|
|
606
|
-
sumG = 0,
|
|
607
|
-
sumB = 0,
|
|
608
|
-
sumA = 0
|
|
609
|
-
const baseRowIndex = y * width
|
|
610
|
-
|
|
611
|
-
// Initialize sum for the first window
|
|
612
|
-
for (let x = -radius; x <= radius; x++) {
|
|
613
|
-
const sampleX = Math.max(0, Math.min(width - 1, x))
|
|
614
|
-
const srcIndex = (baseRowIndex + sampleX) * numChannels
|
|
615
|
-
sumR += srcFg[srcIndex]
|
|
616
|
-
sumG += srcFg[srcIndex + 1]
|
|
617
|
-
sumB += srcFg[srcIndex + 2]
|
|
618
|
-
sumA += srcFg[srcIndex + 3]
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// Slide the window across the row
|
|
622
|
-
for (let x = 0; x < width; x++) {
|
|
623
|
-
const destIndex = (baseRowIndex + x) * numChannels
|
|
624
|
-
tempBufferFg[destIndex] = sumR / windowSize
|
|
625
|
-
tempBufferFg[destIndex + 1] = sumG / windowSize
|
|
626
|
-
tempBufferFg[destIndex + 2] = sumB / windowSize
|
|
627
|
-
tempBufferFg[destIndex + 3] = sumA / windowSize
|
|
628
|
-
|
|
629
|
-
// Subtract pixel leaving the window (left edge)
|
|
630
|
-
const leavingX = Math.max(0, Math.min(width - 1, x - radius))
|
|
631
|
-
const leavingIndex = (baseRowIndex + leavingX) * numChannels
|
|
632
|
-
sumR -= srcFg[leavingIndex]
|
|
633
|
-
sumG -= srcFg[leavingIndex + 1]
|
|
634
|
-
sumB -= srcFg[leavingIndex + 2]
|
|
635
|
-
sumA -= srcFg[leavingIndex + 3]
|
|
636
|
-
|
|
637
|
-
// Add pixel entering the window (right edge)
|
|
638
|
-
const enteringX = Math.max(0, Math.min(width - 1, x + radius + 1))
|
|
639
|
-
const enteringIndex = (baseRowIndex + enteringX) * numChannels
|
|
640
|
-
sumR += srcFg[enteringIndex]
|
|
641
|
-
sumG += srcFg[enteringIndex + 1]
|
|
642
|
-
sumB += srcFg[enteringIndex + 2]
|
|
643
|
-
sumA += srcFg[enteringIndex + 3]
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// --- Horizontal Pass --- Bg
|
|
648
|
-
for (let y = 0; y < height; y++) {
|
|
649
|
-
let sumR = 0,
|
|
650
|
-
sumG = 0,
|
|
651
|
-
sumB = 0,
|
|
652
|
-
sumA = 0
|
|
653
|
-
const baseRowIndex = y * width
|
|
654
|
-
for (let x = -radius; x <= radius; x++) {
|
|
655
|
-
const sampleX = Math.max(0, Math.min(width - 1, x))
|
|
656
|
-
const srcIndex = (baseRowIndex + sampleX) * numChannels
|
|
657
|
-
sumR += srcBg[srcIndex]
|
|
658
|
-
sumG += srcBg[srcIndex + 1]
|
|
659
|
-
sumB += srcBg[srcIndex + 2]
|
|
660
|
-
sumA += srcBg[srcIndex + 3]
|
|
661
|
-
}
|
|
662
|
-
for (let x = 0; x < width; x++) {
|
|
663
|
-
const destIndex = (baseRowIndex + x) * numChannels
|
|
664
|
-
tempBufferBg[destIndex] = sumR / windowSize
|
|
665
|
-
tempBufferBg[destIndex + 1] = sumG / windowSize
|
|
666
|
-
tempBufferBg[destIndex + 2] = sumB / windowSize
|
|
667
|
-
tempBufferBg[destIndex + 3] = sumA / windowSize
|
|
668
|
-
const leavingX = Math.max(0, Math.min(width - 1, x - radius))
|
|
669
|
-
const leavingIndex = (baseRowIndex + leavingX) * numChannels
|
|
670
|
-
sumR -= srcBg[leavingIndex]
|
|
671
|
-
sumG -= srcBg[leavingIndex + 1]
|
|
672
|
-
sumB -= srcBg[leavingIndex + 2]
|
|
673
|
-
sumA -= srcBg[leavingIndex + 3]
|
|
674
|
-
const enteringX = Math.max(0, Math.min(width - 1, x + radius + 1))
|
|
675
|
-
const enteringIndex = (baseRowIndex + enteringX) * numChannels
|
|
676
|
-
sumR += srcBg[enteringIndex]
|
|
677
|
-
sumG += srcBg[enteringIndex + 1]
|
|
678
|
-
sumB += srcBg[enteringIndex + 2]
|
|
679
|
-
sumA += srcBg[enteringIndex + 3]
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// --- Vertical Pass --- Fg
|
|
684
|
-
for (let x = 0; x < width; x++) {
|
|
685
|
-
let sumR = 0,
|
|
686
|
-
sumG = 0,
|
|
687
|
-
sumB = 0,
|
|
688
|
-
sumA = 0
|
|
689
|
-
|
|
690
|
-
// Initialize sum for the first window
|
|
691
|
-
for (let y = -radius; y <= radius; y++) {
|
|
692
|
-
const sampleY = Math.max(0, Math.min(height - 1, y))
|
|
693
|
-
const srcIndex = (sampleY * width + x) * numChannels
|
|
694
|
-
sumR += tempBufferFg[srcIndex]
|
|
695
|
-
sumG += tempBufferFg[srcIndex + 1]
|
|
696
|
-
sumB += tempBufferFg[srcIndex + 2]
|
|
697
|
-
sumA += tempBufferFg[srcIndex + 3]
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// Slide the window down the column
|
|
701
|
-
for (let y = 0; y < height; y++) {
|
|
702
|
-
const destIndex = (y * width + x) * numChannels
|
|
703
|
-
destFg[destIndex] = sumR / windowSize
|
|
704
|
-
destFg[destIndex + 1] = sumG / windowSize
|
|
705
|
-
destFg[destIndex + 2] = sumB / windowSize
|
|
706
|
-
destFg[destIndex + 3] = sumA / windowSize
|
|
707
|
-
|
|
708
|
-
// Subtract pixel leaving the window (top edge)
|
|
709
|
-
const leavingY = Math.max(0, Math.min(height - 1, y - radius))
|
|
710
|
-
const leavingIndex = (leavingY * width + x) * numChannels
|
|
711
|
-
sumR -= tempBufferFg[leavingIndex]
|
|
712
|
-
sumG -= tempBufferFg[leavingIndex + 1]
|
|
713
|
-
sumB -= tempBufferFg[leavingIndex + 2]
|
|
714
|
-
sumA -= tempBufferFg[leavingIndex + 3]
|
|
715
|
-
|
|
716
|
-
// Add pixel entering the window (bottom edge)
|
|
717
|
-
const enteringY = Math.max(0, Math.min(height - 1, y + radius + 1))
|
|
718
|
-
const enteringIndex = (enteringY * width + x) * numChannels
|
|
719
|
-
sumR += tempBufferFg[enteringIndex]
|
|
720
|
-
sumG += tempBufferFg[enteringIndex + 1]
|
|
721
|
-
sumB += tempBufferFg[enteringIndex + 2]
|
|
722
|
-
sumA += tempBufferFg[enteringIndex + 3]
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// --- Vertical Pass --- Bg
|
|
727
|
-
for (let x = 0; x < width; x++) {
|
|
728
|
-
let sumR = 0,
|
|
729
|
-
sumG = 0,
|
|
730
|
-
sumB = 0,
|
|
731
|
-
sumA = 0
|
|
732
|
-
for (let y = -radius; y <= radius; y++) {
|
|
733
|
-
const sampleY = Math.max(0, Math.min(height - 1, y))
|
|
734
|
-
const srcIndex = (sampleY * width + x) * numChannels
|
|
735
|
-
sumR += tempBufferBg[srcIndex]
|
|
736
|
-
sumG += tempBufferBg[srcIndex + 1]
|
|
737
|
-
sumB += tempBufferBg[srcIndex + 2]
|
|
738
|
-
sumA += tempBufferBg[srcIndex + 3]
|
|
739
|
-
}
|
|
740
|
-
for (let y = 0; y < height; y++) {
|
|
741
|
-
const destIndex = (y * width + x) * numChannels
|
|
742
|
-
destBg[destIndex] = sumR / windowSize
|
|
743
|
-
destBg[destIndex + 1] = sumG / windowSize
|
|
744
|
-
destBg[destIndex + 2] = sumB / windowSize
|
|
745
|
-
destBg[destIndex + 3] = sumA / windowSize
|
|
746
|
-
const leavingY = Math.max(0, Math.min(height - 1, y - radius))
|
|
747
|
-
const leavingIndex = (leavingY * width + x) * numChannels
|
|
748
|
-
sumR -= tempBufferBg[leavingIndex]
|
|
749
|
-
sumG -= tempBufferBg[leavingIndex + 1]
|
|
750
|
-
sumB -= tempBufferBg[leavingIndex + 2]
|
|
751
|
-
sumA -= tempBufferBg[leavingIndex + 3]
|
|
752
|
-
const enteringY = Math.max(0, Math.min(height - 1, y + radius + 1))
|
|
753
|
-
const enteringIndex = (enteringY * width + x) * numChannels
|
|
754
|
-
sumR += tempBufferBg[enteringIndex]
|
|
755
|
-
sumG += tempBufferBg[enteringIndex + 1]
|
|
756
|
-
sumB += tempBufferBg[enteringIndex + 2]
|
|
757
|
-
sumA += tempBufferBg[enteringIndex + 3]
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// --- Character Pass (Based on blurred FG Alpha) ---
|
|
762
|
-
const charRamp = [" ", "░", "▒", "▓", " "] // Space, Light, Medium, Dark, Full
|
|
763
|
-
const rampLength = charRamp.length
|
|
764
|
-
|
|
765
|
-
for (let i = 0; i < size; i++) {
|
|
766
|
-
const alphaIndex = i * numChannels + 3
|
|
767
|
-
const fgAlpha = destFg[alphaIndex] // Get the final blurred FG alpha
|
|
768
|
-
|
|
769
|
-
// Clamp alpha just in case, although blur should keep it in [0, 1]
|
|
770
|
-
const clampedAlpha = Math.max(0, Math.min(1, fgAlpha))
|
|
771
|
-
|
|
772
|
-
// Map alpha to character ramp
|
|
773
|
-
// Ensure index doesn't exceed ramp bounds if alpha is exactly 1.0
|
|
774
|
-
const rampIndex = Math.min(rampLength - 1, Math.floor(clampedAlpha * rampLength))
|
|
775
|
-
|
|
776
|
-
chars[i] = charRamp[rampIndex].charCodeAt(0)
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/**
|
|
782
|
-
* Applies a bloom effect based on bright areas (Simplified).
|
|
783
|
-
*/
|
|
784
|
-
export class BloomEffect {
|
|
785
|
-
private _threshold: number
|
|
786
|
-
private _strength: number
|
|
787
|
-
private _radius: number
|
|
788
|
-
|
|
789
|
-
constructor(threshold: number = 0.8, strength: number = 0.2, radius: number = 2) {
|
|
790
|
-
this._threshold = Math.max(0, Math.min(1, threshold))
|
|
791
|
-
this._strength = Math.max(0, strength)
|
|
792
|
-
this._radius = Math.max(0, Math.round(radius))
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
public set threshold(newThreshold: number) {
|
|
796
|
-
this._threshold = Math.max(0, Math.min(1, newThreshold))
|
|
797
|
-
}
|
|
798
|
-
public get threshold(): number {
|
|
799
|
-
return this._threshold
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
public set strength(newStrength: number) {
|
|
803
|
-
this._strength = Math.max(0, newStrength)
|
|
804
|
-
}
|
|
805
|
-
public get strength(): number {
|
|
806
|
-
return this._strength
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
public set radius(newRadius: number) {
|
|
810
|
-
this._radius = Math.max(0, Math.round(newRadius))
|
|
811
|
-
}
|
|
812
|
-
public get radius(): number {
|
|
813
|
-
return this._radius
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
public apply(buffer: OptimizedBuffer): void {
|
|
817
|
-
const threshold = this._threshold
|
|
818
|
-
const strength = this._strength
|
|
819
|
-
const radius = this._radius
|
|
820
|
-
|
|
821
|
-
if (strength <= 0 || radius <= 0) return // No bloom if strength or radius is non-positive
|
|
822
|
-
|
|
823
|
-
const width = buffer.width
|
|
824
|
-
const height = buffer.height
|
|
825
|
-
// Operate directly on the buffer's data for bloom, but need a source copy temporarily
|
|
826
|
-
const srcFg = Float32Array.from(buffer.buffers.fg)
|
|
827
|
-
const srcBg = Float32Array.from(buffer.buffers.bg)
|
|
828
|
-
const destFg = buffer.buffers.fg
|
|
829
|
-
const destBg = buffer.buffers.bg
|
|
830
|
-
|
|
831
|
-
const brightPixels: { x: number; y: number; intensity: number }[] = []
|
|
832
|
-
|
|
833
|
-
// 1. Find bright pixels based on original data
|
|
834
|
-
for (let y = 0; y < height; y++) {
|
|
835
|
-
for (let x = 0; x < width; x++) {
|
|
836
|
-
const index = (y * width + x) * 4
|
|
837
|
-
// Consider max component brightness, or luminance? Using luminance.
|
|
838
|
-
const fgLum = 0.299 * srcFg[index] + 0.587 * srcFg[index + 1] + 0.114 * srcFg[index + 2]
|
|
839
|
-
const bgLum = 0.299 * srcBg[index] + 0.587 * srcBg[index + 1] + 0.114 * srcBg[index + 2]
|
|
840
|
-
const lum = Math.max(fgLum, bgLum)
|
|
841
|
-
if (lum > threshold) {
|
|
842
|
-
const intensity = (lum - threshold) / (1 - threshold + 1e-6) // Add epsilon to avoid div by zero
|
|
843
|
-
brightPixels.push({ x, y, intensity: Math.max(0, intensity) })
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
// If no bright pixels found, exit early
|
|
849
|
-
if (brightPixels.length === 0) return
|
|
850
|
-
|
|
851
|
-
// Initialize destination buffers by copying original state before applying bloom
|
|
852
|
-
// This prevents bloom from compounding on itself within one frame pass
|
|
853
|
-
destFg.set(srcFg)
|
|
854
|
-
destBg.set(srcBg)
|
|
855
|
-
|
|
856
|
-
// 2. Apply bloom spread from bright pixels onto the destination buffers
|
|
857
|
-
for (const bright of brightPixels) {
|
|
858
|
-
for (let ky = -radius; ky <= radius; ky++) {
|
|
859
|
-
for (let kx = -radius; kx <= radius; kx++) {
|
|
860
|
-
if (kx === 0 && ky === 0) continue // Don't bloom self
|
|
861
|
-
|
|
862
|
-
const sampleX = bright.x + kx
|
|
863
|
-
const sampleY = bright.y + ky
|
|
864
|
-
|
|
865
|
-
if (sampleX >= 0 && sampleX < width && sampleY >= 0 && sampleY < height) {
|
|
866
|
-
const distSq = kx * kx + ky * ky // Use squared distance for falloff calculation
|
|
867
|
-
const radiusSq = radius * radius
|
|
868
|
-
if (distSq <= radiusSq) {
|
|
869
|
-
// Simple linear falloff based on squared distance
|
|
870
|
-
const falloff = 1 - distSq / radiusSq
|
|
871
|
-
const bloomAmount = bright.intensity * strength * falloff
|
|
872
|
-
const destIndex = (sampleY * width + sampleX) * 4
|
|
873
|
-
|
|
874
|
-
// Add bloom to both fg and bg, clamping at 1.0
|
|
875
|
-
destFg[destIndex] = Math.min(1.0, destFg[destIndex] + bloomAmount)
|
|
876
|
-
destFg[destIndex + 1] = Math.min(1.0, destFg[destIndex + 1] + bloomAmount)
|
|
877
|
-
destFg[destIndex + 2] = Math.min(1.0, destFg[destIndex + 2] + bloomAmount)
|
|
878
|
-
|
|
879
|
-
destBg[destIndex] = Math.min(1.0, destBg[destIndex] + bloomAmount)
|
|
880
|
-
destBg[destIndex + 1] = Math.min(1.0, destBg[destIndex + 1] + bloomAmount)
|
|
881
|
-
destBg[destIndex + 2] = Math.min(1.0, destBg[destIndex + 2] + bloomAmount)
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
}
|