fundus 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +58 -0
  2. package/build/client/_app/immutable/assets/0.DLhIsYA_.css.br +0 -0
  3. package/build/client/_app/immutable/assets/0.DLhIsYA_.css.gz +0 -0
  4. package/build/client/_app/immutable/assets/2.wavcNhPC.css +1 -0
  5. package/build/client/_app/immutable/assets/2.wavcNhPC.css.br +0 -0
  6. package/build/client/_app/immutable/assets/2.wavcNhPC.css.gz +0 -0
  7. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css +1 -0
  8. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css.br +0 -0
  9. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css.gz +0 -0
  10. package/build/client/_app/immutable/assets/4.p004hmEN.css +1 -0
  11. package/build/client/_app/immutable/assets/4.p004hmEN.css.br +0 -0
  12. package/build/client/_app/immutable/assets/4.p004hmEN.css.gz +0 -0
  13. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css +1 -0
  14. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.br +0 -0
  15. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.gz +0 -0
  16. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css +1 -0
  17. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css.br +0 -0
  18. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css.gz +0 -0
  19. package/build/client/_app/immutable/chunks/BiIto6ft.js +1 -0
  20. package/build/client/_app/immutable/chunks/BiIto6ft.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/BiIto6ft.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/Bjy-W4x2.js.br +0 -0
  23. package/build/client/_app/immutable/chunks/Bjy-W4x2.js.gz +0 -0
  24. package/build/client/_app/immutable/chunks/CNRz3sSw.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/CNRz3sSw.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/CO4RBJfa.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/CO4RBJfa.js.gz +0 -0
  28. package/{dist/editor/_app/immutable/chunks/DjvOiDmq.js → build/client/_app/immutable/chunks/CvY6YsFE.js} +1 -1
  29. package/build/client/_app/immutable/chunks/CvY6YsFE.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/CvY6YsFE.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/DL0_39Ys.js +5 -0
  32. package/build/client/_app/immutable/chunks/DL0_39Ys.js.br +0 -0
  33. package/build/client/_app/immutable/chunks/DL0_39Ys.js.gz +0 -0
  34. package/{dist/editor/_app/immutable/chunks/BfPE5wdt.js → build/client/_app/immutable/chunks/DQ8SXFaX.js} +1 -1
  35. package/build/client/_app/immutable/chunks/DQ8SXFaX.js.br +0 -0
  36. package/build/client/_app/immutable/chunks/DQ8SXFaX.js.gz +0 -0
  37. package/build/client/_app/immutable/chunks/DjdrdRzT.js.br +0 -0
  38. package/build/client/_app/immutable/chunks/DjdrdRzT.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/xihTtKlq.js.br +1 -0
  40. package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
  41. package/{dist/editor/_app/immutable/entry/app.BkqbfI8n.js → build/client/_app/immutable/entry/app.ubN0v9bN.js} +2 -2
  42. package/build/client/_app/immutable/entry/app.ubN0v9bN.js.br +0 -0
  43. package/build/client/_app/immutable/entry/app.ubN0v9bN.js.gz +0 -0
  44. package/build/client/_app/immutable/entry/start.BW8dBDh6.js +1 -0
  45. package/build/client/_app/immutable/entry/start.BW8dBDh6.js.br +0 -0
  46. package/build/client/_app/immutable/entry/start.BW8dBDh6.js.gz +0 -0
  47. package/{dist/editor/_app/immutable/nodes/0.xdMI5GEU.js → build/client/_app/immutable/nodes/0.Dr5ijCIl.js} +1 -1
  48. package/build/client/_app/immutable/nodes/0.Dr5ijCIl.js.br +0 -0
  49. package/build/client/_app/immutable/nodes/0.Dr5ijCIl.js.gz +0 -0
  50. package/{dist/editor/_app/immutable/nodes/1.D9p2tfoJ.js → build/client/_app/immutable/nodes/1.DiIGIRAb.js} +1 -1
  51. package/build/client/_app/immutable/nodes/1.DiIGIRAb.js.br +3 -0
  52. package/build/client/_app/immutable/nodes/1.DiIGIRAb.js.gz +0 -0
  53. package/{dist/editor/_app/immutable/nodes/2.BrA0Hyzu.js → build/client/_app/immutable/nodes/2.B8KYmQcV.js} +3 -3
  54. package/build/client/_app/immutable/nodes/2.B8KYmQcV.js.br +0 -0
  55. package/build/client/_app/immutable/nodes/2.B8KYmQcV.js.gz +0 -0
  56. package/build/client/_app/immutable/nodes/3.B1jc7arT.js +104 -0
  57. package/build/client/_app/immutable/nodes/3.B1jc7arT.js.br +0 -0
  58. package/build/client/_app/immutable/nodes/3.B1jc7arT.js.gz +0 -0
  59. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js +2 -0
  60. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js.br +0 -0
  61. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js.gz +0 -0
  62. package/build/client/_app/version.json +1 -0
  63. package/build/client/_app/version.json.br +0 -0
  64. package/build/client/_app/version.json.gz +0 -0
  65. package/build/env.js +100 -0
  66. package/build/env.js.map +1 -0
  67. package/build/handler.js +22 -0
  68. package/build/handler.js.map +1 -0
  69. package/build/index.js +145 -0
  70. package/build/index.js.map +1 -0
  71. package/build/server/chunks/chunks/context.js-Bw4WWLhG.js +443 -0
  72. package/build/server/chunks/chunks/context.js-Bw4WWLhG.js.map +1 -0
  73. package/build/server/chunks/chunks/core.js-DDntpb72.js +409 -0
  74. package/build/server/chunks/chunks/core.js-DDntpb72.js.map +1 -0
  75. package/build/server/chunks/chunks/env.js-l0sNRNKZ.js +2 -0
  76. package/build/server/chunks/chunks/env.js-l0sNRNKZ.js.map +1 -0
  77. package/build/server/chunks/chunks/exports.js-CLTzaOxn.js +152 -0
  78. package/build/server/chunks/chunks/exports.js-CLTzaOxn.js.map +1 -0
  79. package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js +64 -0
  80. package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js.map +1 -0
  81. package/build/server/chunks/chunks/http.js-Dxoa-jtP.js +100 -0
  82. package/build/server/chunks/chunks/http.js-Dxoa-jtP.js.map +1 -0
  83. package/build/server/chunks/chunks/internal.js-BDBSzJId.js +5753 -0
  84. package/build/server/chunks/chunks/internal.js-BDBSzJId.js.map +1 -0
  85. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js +22 -0
  86. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -0
  87. package/{dist/operations-DYM-5KVl.js → build/server/chunks/chunks/library-store.js-BP8cL-qD.js} +344 -444
  88. package/build/server/chunks/chunks/library-store.js-BP8cL-qD.js.map +1 -0
  89. package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js +146 -0
  90. package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js.map +1 -0
  91. package/build/server/chunks/chunks/routing.js-y-tryuip.js +213 -0
  92. package/build/server/chunks/chunks/routing.js-y-tryuip.js.map +1 -0
  93. package/build/server/chunks/chunks/shared.js-BWXgl1Xf.js +255 -0
  94. package/build/server/chunks/chunks/shared.js-BWXgl1Xf.js.map +1 -0
  95. package/build/server/chunks/chunks/utils.js-9oI5Oz0w.js +1048 -0
  96. package/build/server/chunks/chunks/utils.js-9oI5Oz0w.js.map +1 -0
  97. package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-WknZVW_S.js +27 -0
  98. package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-WknZVW_S.js.map +1 -0
  99. package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-BrZ__-HZ.js +24 -0
  100. package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-BrZ__-HZ.js.map +1 -0
  101. package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-PqADGPXc.js +45 -0
  102. package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-PqADGPXc.js.map +1 -0
  103. package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-OqoE5PN-.js +31 -0
  104. package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-OqoE5PN-.js.map +1 -0
  105. package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-CJ08e1ho.js +31 -0
  106. package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-CJ08e1ho.js.map +1 -0
  107. package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-DdF3eK2I.js +38 -0
  108. package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-DdF3eK2I.js.map +1 -0
  109. package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-Cxt6jsJ5.js +31 -0
  110. package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-Cxt6jsJ5.js.map +1 -0
  111. package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BWVM2Ntl.js +24 -0
  112. package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BWVM2Ntl.js.map +1 -0
  113. package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-Z2bM-qHM.js +31 -0
  114. package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-Z2bM-qHM.js.map +1 -0
  115. package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-BX9H2Z34.js +24 -0
  116. package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-BX9H2Z34.js.map +1 -0
  117. package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-BWHDZ8mz.js +27 -0
  118. package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-BWHDZ8mz.js.map +1 -0
  119. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-CR_7mndO.js +24 -0
  120. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-CR_7mndO.js.map +1 -0
  121. package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-Cw1PDBvb.js +24 -0
  122. package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-Cw1PDBvb.js.map +1 -0
  123. package/build/server/chunks/entries/hooks.server.js-BHoE0yBi.js +23 -0
  124. package/build/server/chunks/entries/hooks.server.js-BHoE0yBi.js.map +1 -0
  125. package/build/server/chunks/handler-10cx4zHn.js +1475 -0
  126. package/build/server/chunks/handler-10cx4zHn.js.map +1 -0
  127. package/build/server/chunks/index.js-DvPfiC00.js +3789 -0
  128. package/build/server/chunks/index.js-DvPfiC00.js.map +1 -0
  129. package/build/server/chunks/manifest.js-DoPjUnzD.js +149 -0
  130. package/build/server/chunks/manifest.js-DoPjUnzD.js.map +1 -0
  131. package/build/server/chunks/nodes/0.js-Di3qgAtW.js +11 -0
  132. package/build/server/chunks/nodes/0.js-Di3qgAtW.js.map +1 -0
  133. package/build/server/chunks/nodes/1.js-BlWSFIA8.js +7 -0
  134. package/build/server/chunks/nodes/1.js-BlWSFIA8.js.map +1 -0
  135. package/build/server/chunks/nodes/2.js-CO9nSPUN.js +7 -0
  136. package/build/server/chunks/nodes/2.js-CO9nSPUN.js.map +1 -0
  137. package/build/server/chunks/nodes/3.js-C2D6xpEO.js +7 -0
  138. package/build/server/chunks/nodes/3.js-C2D6xpEO.js.map +1 -0
  139. package/build/server/chunks/nodes/4.js-B3IuagJW.js +7 -0
  140. package/build/server/chunks/nodes/4.js-B3IuagJW.js.map +1 -0
  141. package/build/shims.js +33 -0
  142. package/build/shims.js.map +1 -0
  143. package/dist/cli.d.ts +2 -1
  144. package/dist/cli.js +109 -1332
  145. package/dist/config.d.ts +3 -2
  146. package/dist/config.js +2 -2
  147. package/dist/core/api-types.d.ts +141 -0
  148. package/dist/core/api-types.js +1 -0
  149. package/dist/core/asset-id.d.ts +28 -0
  150. package/dist/core/asset-id.js +59 -0
  151. package/dist/core/asset-reference.d.ts +23 -0
  152. package/dist/core/asset-reference.js +15 -0
  153. package/dist/core/canonicalize.d.ts +9 -0
  154. package/dist/core/canonicalize.js +36 -0
  155. package/dist/core/chroma-key.d.ts +30 -0
  156. package/dist/core/chroma-key.js +55 -0
  157. package/dist/core/config.d.ts +35 -0
  158. package/dist/core/config.js +4 -0
  159. package/dist/core/folder-path.d.ts +19 -0
  160. package/dist/core/folder-path.js +86 -0
  161. package/dist/core/index.d.ts +33 -499
  162. package/dist/core/index.js +17 -962
  163. package/dist/core/ingest.d.ts +18 -0
  164. package/dist/core/ingest.js +58 -0
  165. package/dist/core/library.d.ts +54 -0
  166. package/dist/core/library.js +138 -0
  167. package/dist/core/manifest-appearance.d.ts +35 -0
  168. package/dist/core/manifest-appearance.js +123 -0
  169. package/dist/core/manifest-entry.d.ts +104 -0
  170. package/dist/core/manifest-entry.js +1 -0
  171. package/dist/core/manifest-membership.d.ts +56 -0
  172. package/dist/core/manifest-membership.js +54 -0
  173. package/dist/core/plugins/audio.d.ts +26 -0
  174. package/dist/core/plugins/audio.js +44 -0
  175. package/dist/core/plugins/chroma-key-video.d.ts +29 -0
  176. package/dist/core/plugins/chroma-key-video.js +69 -0
  177. package/dist/core/plugins/contract.d.ts +35 -0
  178. package/dist/core/plugins/contract.js +1 -0
  179. package/dist/core/plugins/image.d.ts +30 -0
  180. package/dist/core/plugins/image.js +45 -0
  181. package/dist/core/plugins/slice.d.ts +22 -0
  182. package/dist/core/plugins/slice.js +60 -0
  183. package/dist/core/plugins/video.d.ts +45 -0
  184. package/dist/core/plugins/video.js +77 -0
  185. package/dist/core/reference-graph.d.ts +41 -0
  186. package/dist/core/reference-graph.js +138 -0
  187. package/dist/core/slice-data.d.ts +61 -0
  188. package/dist/core/slice-data.js +49 -0
  189. package/dist/runtime/chroma-key-gl.d.ts +40 -22
  190. package/dist/runtime/chroma-key-gl.js +189 -183
  191. package/dist/runtime/components/ChromaKeyVideo.svelte +3 -3
  192. package/dist/runtime/components/ChromaKeyVideo.svelte.d.ts +21 -0
  193. package/dist/runtime/components/Image.svelte +1 -1
  194. package/dist/runtime/components/Image.svelte.d.ts +9 -0
  195. package/dist/runtime/components/Slice.svelte +1 -1
  196. package/dist/runtime/components/Slice.svelte.d.ts +19 -0
  197. package/dist/runtime/components/SliceCanvas.svelte +3 -3
  198. package/dist/runtime/components/SliceCanvas.svelte.d.ts +10 -0
  199. package/dist/runtime/components/SliceDom.svelte +3 -3
  200. package/dist/runtime/components/SliceDom.svelte.d.ts +10 -0
  201. package/dist/runtime/components/Video.svelte +2 -2
  202. package/dist/runtime/components/Video.svelte.d.ts +18 -0
  203. package/dist/runtime/geometry.d.ts +55 -35
  204. package/dist/runtime/geometry.js +186 -191
  205. package/dist/runtime/index.d.ts +9 -9
  206. package/dist/runtime/index.js +9 -9
  207. package/dist/runtime/kind-handlers.d.ts +33 -24
  208. package/dist/runtime/kind-handlers.js +74 -65
  209. package/dist/runtime/manifest.d.ts +53 -47
  210. package/dist/runtime/manifest.js +133 -113
  211. package/dist/runtime/observe-border-box-size.d.ts +1 -4
  212. package/dist/runtime/observe-border-box-size.js +9 -10
  213. package/dist/runtime/preload-registry.d.ts +22 -8
  214. package/dist/runtime/preload-registry.js +65 -62
  215. package/dist/server/build.d.ts +8 -0
  216. package/dist/server/build.js +25 -0
  217. package/dist/server/check.d.ts +24 -0
  218. package/dist/server/check.js +199 -0
  219. package/dist/server/cli-commands.d.ts +25 -0
  220. package/dist/server/cli-commands.js +1178 -0
  221. package/dist/server/cli-init.d.ts +3 -0
  222. package/dist/server/cli-init.js +53 -0
  223. package/dist/server/cli-io.d.ts +46 -0
  224. package/dist/server/cli-io.js +105 -0
  225. package/dist/server/codegen.d.ts +58 -0
  226. package/dist/server/codegen.js +185 -0
  227. package/dist/server/config-loader.d.ts +34 -0
  228. package/dist/server/config-loader.js +103 -0
  229. package/dist/server/context.d.ts +8 -0
  230. package/dist/server/context.js +19 -0
  231. package/dist/server/folder-filesystem.d.ts +7 -0
  232. package/dist/server/folder-filesystem.js +39 -0
  233. package/dist/server/http.d.ts +12 -0
  234. package/dist/server/http.js +100 -0
  235. package/dist/server/index.d.ts +16 -0
  236. package/dist/server/index.js +9 -0
  237. package/dist/server/job-hash.d.ts +10 -0
  238. package/dist/server/job-hash.js +23 -0
  239. package/dist/server/library-store.d.ts +82 -0
  240. package/dist/server/library-store.js +763 -0
  241. package/dist/server/operations.d.ts +87 -0
  242. package/dist/server/operations.js +427 -0
  243. package/dist/server/plugins/audio.d.ts +7 -0
  244. package/dist/server/plugins/audio.js +27 -0
  245. package/dist/server/plugins/chroma-key-video.d.ts +9 -0
  246. package/dist/server/plugins/chroma-key-video.js +38 -0
  247. package/dist/server/plugins/contract.d.ts +100 -0
  248. package/dist/server/plugins/contract.js +16 -0
  249. package/dist/server/plugins/image.d.ts +8 -0
  250. package/dist/server/plugins/image.js +30 -0
  251. package/dist/server/plugins/slice.d.ts +14 -0
  252. package/dist/server/plugins/slice.js +63 -0
  253. package/dist/server/plugins/video.d.ts +6 -0
  254. package/dist/server/plugins/video.js +29 -0
  255. package/dist/server/plugins.d.ts +23 -0
  256. package/dist/server/plugins.js +33 -0
  257. package/dist/server/processing/audio-processing.d.ts +17 -0
  258. package/dist/server/processing/audio-processing.js +46 -0
  259. package/dist/server/processing/ffmpeg.d.ts +9 -0
  260. package/dist/server/processing/ffmpeg.js +50 -0
  261. package/dist/server/processing/image-processing.d.ts +16 -0
  262. package/dist/server/processing/image-processing.js +26 -0
  263. package/dist/server/processing/media-probe.d.ts +15 -0
  264. package/dist/server/processing/media-probe.js +27 -0
  265. package/dist/server/processing/processor.d.ts +50 -0
  266. package/dist/server/processing/processor.js +158 -0
  267. package/dist/server/processing/video-processing.d.ts +35 -0
  268. package/dist/server/processing/video-processing.js +87 -0
  269. package/dist/server/server.d.ts +13 -0
  270. package/dist/server/server.js +57 -0
  271. package/dist/server/start.d.ts +1 -0
  272. package/dist/server/start.js +33 -0
  273. package/package.json +29 -16
  274. package/dist/build-CZYFLLvl.js +0 -191
  275. package/dist/core/image-Dqmz8FXS.js +0 -54
  276. package/dist/core/reference-graph-CjuHbLDw.d.ts +0 -280
  277. package/dist/core/testing.d.ts +0 -27
  278. package/dist/core/testing.js +0 -80
  279. package/dist/editor/200.html +0 -37
  280. package/dist/editor/_app/immutable/assets/2.DIbbW7U1.css +0 -1
  281. package/dist/editor/_app/immutable/assets/3.C-9vFQ9A.css +0 -1
  282. package/dist/editor/_app/immutable/assets/4.BS8ElpOV.css +0 -1
  283. package/dist/editor/_app/immutable/assets/ConfirmDialog.CHEISE-L.css +0 -1
  284. package/dist/editor/_app/immutable/assets/LibraryContextMenu.CDjCmdV-.css +0 -1
  285. package/dist/editor/_app/immutable/chunks/Cx6qtxJg.js +0 -1
  286. package/dist/editor/_app/immutable/chunks/n7mvYc42.js +0 -5
  287. package/dist/editor/_app/immutable/entry/start.C8HHOLly.js +0 -1
  288. package/dist/editor/_app/immutable/nodes/3.WO7tZH_d.js +0 -104
  289. package/dist/editor/_app/immutable/nodes/4.DQtx17aW.js +0 -2
  290. package/dist/editor/_app/version.json +0 -1
  291. package/dist/index.d.ts +0 -370
  292. package/dist/index.js +0 -4
  293. package/dist/start-Bhnqt9Dc.js +0 -279
  294. package/dist/start-D2IXOrni.js +0 -2
  295. /package/{dist/editor → build/client}/_app/immutable/assets/0.DLhIsYA_.css +0 -0
  296. /package/{dist/editor → build/client}/_app/immutable/chunks/Bjy-W4x2.js +0 -0
  297. /package/{dist/editor → build/client}/_app/immutable/chunks/CNRz3sSw.js +0 -0
  298. /package/{dist/editor → build/client}/_app/immutable/chunks/CO4RBJfa.js +0 -0
  299. /package/{dist/editor → build/client}/_app/immutable/chunks/DjdrdRzT.js +0 -0
  300. /package/{dist/editor → build/client}/_app/immutable/chunks/xihTtKlq.js +0 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The slice data model keeps the source image separate from slicing metadata
3
+ * (Fundus tracks raw files and
4
+ * proxy dimensions separately), so there is no `SliceSource` here.
5
+ *
6
+ * The geometry is stored as **insets** (border thickness in source pixels), the
7
+ * canonical, render-ready form — equivalent to CSS `border-image-slice`.
8
+ * `slicedAxesFor` is the single source of truth for which axes each mode uses.
9
+ */
10
+ export declare const SLICE_MODES: readonly ["nine", "three-horizontal", "three-vertical", "one"];
11
+ export type SliceMode = (typeof SLICE_MODES)[number];
12
+ /** Border thickness in source pixels. Always integers (pixel-precise). */
13
+ export interface SliceInsets {
14
+ top: number;
15
+ right: number;
16
+ bottom: number;
17
+ left: number;
18
+ }
19
+ /**
20
+ * Full slicing description for an image, independent of which image it applies
21
+ * to. Stored in the library as (part of) the slice plugin's parameters and
22
+ * emitted into generated manifest entries.
23
+ */
24
+ export interface Slicing {
25
+ mode: SliceMode;
26
+ insets: SliceInsets;
27
+ /**
28
+ * Source pixels per CSS pixel — the scale the asset was exported at
29
+ * (`1` = @1x, `2` = @2x, `3` = @3x). All fixed slice dimensions (9-slice
30
+ * corners) are divided by this when rendering, so a high-resolution asset
31
+ * displays at its intended logical size.
32
+ */
33
+ pixelRatio: number;
34
+ /**
35
+ * Per-side thickness (in source pixels) of the image's baked-in overdraw — a
36
+ * drop shadow / glow painted around the actual element. The renderers treat
37
+ * the image **minus** the overdraw as the element: that core fills the layout
38
+ * box, and the overdraw band is painted outside it (like a CSS `box-shadow`).
39
+ * Optional: absent means no overdraw.
40
+ */
41
+ overdraw?: SliceInsets;
42
+ }
43
+ /** All-zero insets — the "no overdraw" value. */
44
+ export declare function createZeroInsets(): SliceInsets;
45
+ /**
46
+ * Default insets for a freshly ingested image: each border a quarter of the
47
+ * corresponding dimension (at least 1px where the image is large enough),
48
+ * always clamped so a center of at least one source pixel remains on each
49
+ * axis. For an axis too small for insets + a 1px center (width/height ≤ 2)
50
+ * the insets on that axis are 0 — structurally valid slicing for any size ≥ 1.
51
+ */
52
+ export declare function defaultInsetsForSize(width: number, height: number): SliceInsets;
53
+ /** Which source-image axes are sliced for a mode. */
54
+ export declare function slicedAxesFor(mode: SliceMode): {
55
+ horizontal: boolean;
56
+ vertical: boolean;
57
+ };
58
+ /** Maximum inset on one side while preserving the opposite inset. */
59
+ export declare function maxInset(insets: SliceInsets, side: keyof SliceInsets, width: number, height: number): number;
60
+ /** Maximum overdraw on one side while preserving at least one core source pixel. */
61
+ export declare function maxOverdraw(overdraw: SliceInsets, side: keyof SliceInsets, width: number, height: number): number;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The slice data model keeps the source image separate from slicing metadata
3
+ * (Fundus tracks raw files and
4
+ * proxy dimensions separately), so there is no `SliceSource` here.
5
+ *
6
+ * The geometry is stored as **insets** (border thickness in source pixels), the
7
+ * canonical, render-ready form — equivalent to CSS `border-image-slice`.
8
+ * `slicedAxesFor` is the single source of truth for which axes each mode uses.
9
+ */
10
+ export const SLICE_MODES = ['nine', 'three-horizontal', 'three-vertical', 'one'];
11
+ /** All-zero insets — the "no overdraw" value. */
12
+ export function createZeroInsets() {
13
+ return { top: 0, right: 0, bottom: 0, left: 0 };
14
+ }
15
+ /**
16
+ * Default insets for a freshly ingested image: each border a quarter of the
17
+ * corresponding dimension (at least 1px where the image is large enough),
18
+ * always clamped so a center of at least one source pixel remains on each
19
+ * axis. For an axis too small for insets + a 1px center (width/height ≤ 2)
20
+ * the insets on that axis are 0 — structurally valid slicing for any size ≥ 1.
21
+ */
22
+ export function defaultInsetsForSize(width, height) {
23
+ // max(1, quarter) is the desired border; min(…, floor((size − 1) / 2)) caps
24
+ // it so `2 × inset ≤ size − 1`, i.e. the center keeps ≥ 1 source pixel.
25
+ const horizontal = Math.min(Math.max(1, Math.floor(width / 4)), Math.floor((width - 1) / 2));
26
+ const vertical = Math.min(Math.max(1, Math.floor(height / 4)), Math.floor((height - 1) / 2));
27
+ return { top: vertical, right: horizontal, bottom: vertical, left: horizontal };
28
+ }
29
+ /** Which source-image axes are sliced for a mode. */
30
+ export function slicedAxesFor(mode) {
31
+ return {
32
+ horizontal: mode === 'nine' || mode === 'three-horizontal',
33
+ vertical: mode === 'nine' || mode === 'three-vertical'
34
+ };
35
+ }
36
+ /** Maximum inset on one side while preserving the opposite inset. */
37
+ export function maxInset(insets, side, width, height) {
38
+ if (side === 'left')
39
+ return width - insets.right;
40
+ if (side === 'right')
41
+ return width - insets.left;
42
+ if (side === 'top')
43
+ return height - insets.bottom;
44
+ return height - insets.top;
45
+ }
46
+ /** Maximum overdraw on one side while preserving at least one core source pixel. */
47
+ export function maxOverdraw(overdraw, side, width, height) {
48
+ return maxInset(overdraw, side, width, height) - 1;
49
+ }
@@ -1,23 +1,41 @@
1
- import { ChromaKeyParameters } from "#fundus/core";
2
-
3
- //#region src/chroma-key-gl.d.ts
4
- declare class ChromaKeyGl {
5
- #private;
6
- /** Returns null when WebGL2 is unavailable or the shader fails to compile. */
7
- static create(canvas: HTMLCanvasElement): ChromaKeyGl | null;
8
- private constructor();
9
- /**
10
- * Set (or clear) the grayscale shape mask multiplied onto the output alpha. The
11
- * mask is stretched over the full video frame, so author it at the video's aspect
12
- * ratio. Pass null to remove the mask.
13
- */
14
- setMask(image: TexImageSource | null): void;
15
- /**
16
- * Upload the video's current frame and render it keyed. Sizes the drawing buffer to
17
- * the video's intrinsic size on first draw (and after a size change).
18
- */
19
- draw(video: HTMLVideoElement, parameters: ChromaKeyParameters): void;
20
- dispose(): void;
1
+ /**
2
+ * WebGL2 chroma-key video renderer based on the public UnityChromakey shader
3
+ * (https://github.com/otdavies/UnityChromakey, `Shaders/ChromaKey.shader`) so a
4
+ * greenscreen video plays with a transparent background.
5
+ *
6
+ * The keying algorithm follows the upstream shader: the key color and each
7
+ * pixel are converted to YCbCr chroma (Cb/Cr), the squared chroma distance is mapped
8
+ * through a cutoff/feather window (`colorclose`), the resulting mask is blurred with a
9
+ * 3×3 neighbourhood + smoothstep-sharpened, the keyed color is despilled (green pulled
10
+ * toward the red/blue average, lost luminance re-added), and the output is
11
+ * `vec4(color * mask, mask)` the upstream output formula (tint fixed at white; tinting
12
+ * is host styling, not asset data) — emitted premultiplied (rgb × alpha) for the canvas
13
+ * compositor (see the fragColor note).
14
+ *
15
+ * Fundus adds an optional mask pass (`setMask`): a grayscale image
16
+ * sampled at the same UVs whose luminance multiplies the final alpha white keeps a
17
+ * pixel, black drops it, gray fades it (no alpha clip). Absent a mask, a 1×1 white
18
+ * fallback texture makes the pass a no-op.
19
+ *
20
+ * Owns its own GL context on the given canvas. `create` returns null when WebGL2 is
21
+ * unavailable. Browser-only; the caller drives it per frame with the playing <video>.
22
+ */
23
+ import type { ChromaKeyParameters } from '../core/index.js';
24
+ export declare class ChromaKeyGl {
25
+ #private;
26
+ /** Returns null when WebGL2 is unavailable or the shader fails to compile. */
27
+ static create(canvas: HTMLCanvasElement): ChromaKeyGl | null;
28
+ private constructor();
29
+ /**
30
+ * Set (or clear) the grayscale shape mask multiplied onto the output alpha. The
31
+ * mask is stretched over the full video frame, so author it at the video's aspect
32
+ * ratio. Pass null to remove the mask.
33
+ */
34
+ setMask(image: TexImageSource | null): void;
35
+ /**
36
+ * Upload the video's current frame and render it keyed. Sizes the drawing buffer to
37
+ * the video's intrinsic size on first draw (and after a size change).
38
+ */
39
+ draw(video: HTMLVideoElement, parameters: ChromaKeyParameters): void;
40
+ dispose(): void;
21
41
  }
22
- //#endregion
23
- export { ChromaKeyGl };
@@ -1,4 +1,3 @@
1
- //#region src/chroma-key-gl.ts
2
1
  const VERTEX_SHADER = `#version 300 es
3
2
  in vec2 a_pos;
4
3
  out vec2 v_uv;
@@ -8,6 +7,10 @@ void main() {
8
7
  v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
9
8
  gl_Position = vec4(a_pos, 0.0, 1.0);
10
9
  }`;
10
+ // The upstream fragment, translated HLSL → GLSL. Kept structurally identical (same
11
+ // function names, same sample pattern, same constants) so it can be diffed against
12
+ // the original; only the texel-size plumbing differs (u_texelSize is (1/w, 1/h),
13
+ // Unity's _MainTex_TexelSize packs (1/w, 1/h, w, h)).
11
14
  const FRAGMENT_SHADER = `#version 300 es
12
15
  precision highp float;
13
16
 
@@ -105,186 +108,189 @@ void main() {
105
108
  fragColor = vec4(keyed.rgb * keyed.a, keyed.a);
106
109
  }`;
107
110
  function compileProgram(gl) {
108
- const compile = (type, source) => {
109
- const shader = gl.createShader(type);
110
- gl.shaderSource(shader, source);
111
- gl.compileShader(shader);
112
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
113
- const log = gl.getShaderInfoLog(shader);
114
- gl.deleteShader(shader);
115
- throw new Error(`Chroma-key shader compilation failed: ${log}.`);
116
- }
117
- return shader;
118
- };
119
- const program = gl.createProgram();
120
- gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX_SHADER));
121
- gl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
122
- gl.linkProgram(program);
123
- if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
124
- const log = gl.getProgramInfoLog(program);
125
- gl.deleteProgram(program);
126
- throw new Error(`Chroma-key program linking failed: ${log}.`);
127
- }
128
- return program;
111
+ const compile = (type, source) => {
112
+ const shader = gl.createShader(type);
113
+ gl.shaderSource(shader, source);
114
+ gl.compileShader(shader);
115
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
116
+ const log = gl.getShaderInfoLog(shader);
117
+ gl.deleteShader(shader);
118
+ throw new Error(`Chroma-key shader compilation failed: ${log}.`);
119
+ }
120
+ return shader;
121
+ };
122
+ const program = gl.createProgram();
123
+ gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX_SHADER));
124
+ gl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
125
+ gl.linkProgram(program);
126
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
127
+ const log = gl.getProgramInfoLog(program);
128
+ gl.deleteProgram(program);
129
+ throw new Error(`Chroma-key program linking failed: ${log}.`);
130
+ }
131
+ return program;
132
+ }
133
+ export class ChromaKeyGl {
134
+ #gl;
135
+ #canvas;
136
+ // GL resources — recreated on context restore, so not readonly.
137
+ #program;
138
+ #quadBuffer;
139
+ #texture;
140
+ #uniforms;
141
+ #maskTexture;
142
+ /** Last mask image, kept so the texture can be re-uploaded after a context restore. */
143
+ #maskImage = null;
144
+ /** True between webglcontextlost and webglcontextrestored — draw no-ops meanwhile. */
145
+ #contextLost = false;
146
+ /** Returns null when WebGL2 is unavailable or the shader fails to compile. */
147
+ static create(canvas) {
148
+ // Premultiplied alpha — the fragment shader multiplies rgb by alpha (see the
149
+ // note above fragColor), which reproduces the upstream blend and survives
150
+ // iOS WKWebView, which composites as premultiplied no matter what this flag says.
151
+ const gl = canvas.getContext('webgl2', {
152
+ premultipliedAlpha: true,
153
+ alpha: true,
154
+ depth: false,
155
+ stencil: false,
156
+ antialias: false
157
+ });
158
+ if (!gl)
159
+ return null;
160
+ try {
161
+ return new ChromaKeyGl(gl, canvas);
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ }
167
+ constructor(gl, canvas) {
168
+ this.#gl = gl;
169
+ this.#canvas = canvas;
170
+ // A real context loss (Android background/foreground, GPU pressure) invalidates
171
+ // every GL object; preventDefault keeps the context restorable and the next
172
+ // draw() after the rebuild repaints from the still-playing video.
173
+ canvas.addEventListener('webglcontextlost', this.#handleContextLost);
174
+ canvas.addEventListener('webglcontextrestored', this.#handleContextRestored);
175
+ this.#initResources();
176
+ }
177
+ #handleContextLost = (event) => {
178
+ event.preventDefault();
179
+ this.#contextLost = true;
180
+ };
181
+ #handleContextRestored = () => {
182
+ try {
183
+ this.#initResources();
184
+ this.#contextLost = false;
185
+ }
186
+ catch {
187
+ this.#contextLost = true;
188
+ }
189
+ };
190
+ /** (Re)create all GL resources on the current context — at construction and after restore. */
191
+ #initResources() {
192
+ const gl = this.#gl;
193
+ this.#program = compileProgram(gl);
194
+ gl.useProgram(this.#program);
195
+ const location = (name) => gl.getUniformLocation(this.#program, name);
196
+ this.#uniforms = {
197
+ texelSize: location('u_texelSize'),
198
+ keyColor: location('u_keyColor'),
199
+ tintColor: location('u_tintColor'),
200
+ colorCutoff: location('u_colorCutoff'),
201
+ colorFeathering: location('u_colorFeathering'),
202
+ maskFeathering: location('u_maskFeathering'),
203
+ sharpening: location('u_sharpening'),
204
+ despill: location('u_despill'),
205
+ despillLuminanceAdd: location('u_despillLuminanceAdd')
206
+ };
207
+ gl.uniform1i(gl.getUniformLocation(this.#program, 'u_texture'), 0);
208
+ gl.uniform1i(gl.getUniformLocation(this.#program, 'u_mask'), 1);
209
+ // Tint stays constant white; presentation styling belongs to the host.
210
+ gl.uniform4f(this.#uniforms.tintColor, 1, 1, 1, 1);
211
+ this.#quadBuffer = gl.createBuffer();
212
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.#quadBuffer);
213
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
214
+ const positionLocation = gl.getAttribLocation(this.#program, 'a_pos');
215
+ gl.enableVertexAttribArray(positionLocation);
216
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
217
+ this.#texture = gl.createTexture();
218
+ gl.bindTexture(gl.TEXTURE_2D, this.#texture);
219
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
220
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
221
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
222
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
223
+ this.#maskTexture = gl.createTexture();
224
+ gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
225
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
226
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
227
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
228
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
229
+ // The old mask texture is invalid after a context loss; re-upload the kept image.
230
+ this.#uploadMask();
231
+ gl.disable(gl.DEPTH_TEST);
232
+ gl.disable(gl.BLEND);
233
+ gl.clearColor(0, 0, 0, 0);
234
+ }
235
+ /**
236
+ * Set (or clear) the grayscale shape mask multiplied onto the output alpha. The
237
+ * mask is stretched over the full video frame, so author it at the video's aspect
238
+ * ratio. Pass null to remove the mask.
239
+ */
240
+ setMask(image) {
241
+ this.#maskImage = image;
242
+ if (!this.#contextLost)
243
+ this.#uploadMask();
244
+ }
245
+ #uploadMask() {
246
+ const gl = this.#gl;
247
+ gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
248
+ if (this.#maskImage) {
249
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.#maskImage);
250
+ }
251
+ else {
252
+ // 1×1 white — the mask multiply becomes a no-op.
253
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));
254
+ }
255
+ }
256
+ /**
257
+ * Upload the video's current frame and render it keyed. Sizes the drawing buffer to
258
+ * the video's intrinsic size on first draw (and after a size change).
259
+ */
260
+ draw(video, parameters) {
261
+ if (this.#contextLost || video.videoWidth === 0)
262
+ return;
263
+ const gl = this.#gl;
264
+ if (this.#canvas.width !== video.videoWidth || this.#canvas.height !== video.videoHeight) {
265
+ this.#canvas.width = video.videoWidth;
266
+ this.#canvas.height = video.videoHeight;
267
+ gl.viewport(0, 0, video.videoWidth, video.videoHeight);
268
+ }
269
+ gl.activeTexture(gl.TEXTURE1);
270
+ gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
271
+ gl.activeTexture(gl.TEXTURE0);
272
+ gl.bindTexture(gl.TEXTURE_2D, this.#texture);
273
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
274
+ gl.useProgram(this.#program);
275
+ gl.uniform2f(this.#uniforms.texelSize, 1 / video.videoWidth, 1 / video.videoHeight);
276
+ gl.uniform3fv(this.#uniforms.keyColor, parameters.keyColor);
277
+ gl.uniform1f(this.#uniforms.colorCutoff, parameters.colorCutoff);
278
+ gl.uniform1f(this.#uniforms.colorFeathering, parameters.colorFeathering);
279
+ gl.uniform1f(this.#uniforms.maskFeathering, parameters.maskFeathering);
280
+ gl.uniform1f(this.#uniforms.sharpening, parameters.sharpening);
281
+ gl.uniform1f(this.#uniforms.despill, parameters.despill);
282
+ gl.uniform1f(this.#uniforms.despillLuminanceAdd, parameters.despillLuminanceAdd);
283
+ gl.clear(gl.COLOR_BUFFER_BIT);
284
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
285
+ }
286
+ dispose() {
287
+ this.#canvas.removeEventListener('webglcontextlost', this.#handleContextLost);
288
+ this.#canvas.removeEventListener('webglcontextrestored', this.#handleContextRestored);
289
+ const gl = this.#gl;
290
+ gl.deleteBuffer(this.#quadBuffer);
291
+ gl.deleteTexture(this.#texture);
292
+ gl.deleteTexture(this.#maskTexture);
293
+ gl.deleteProgram(this.#program);
294
+ gl.getExtension('WEBGL_lose_context')?.loseContext();
295
+ }
129
296
  }
130
- var ChromaKeyGl = class ChromaKeyGl {
131
- #gl;
132
- #canvas;
133
- #program;
134
- #quadBuffer;
135
- #texture;
136
- #uniforms;
137
- #maskTexture;
138
- /** Last mask image, kept so the texture can be re-uploaded after a context restore. */
139
- #maskImage = null;
140
- /** True between webglcontextlost and webglcontextrestored — draw no-ops meanwhile. */
141
- #contextLost = false;
142
- /** Returns null when WebGL2 is unavailable or the shader fails to compile. */
143
- static create(canvas) {
144
- const gl = canvas.getContext("webgl2", {
145
- premultipliedAlpha: true,
146
- alpha: true,
147
- depth: false,
148
- stencil: false,
149
- antialias: false
150
- });
151
- if (!gl) return null;
152
- try {
153
- return new ChromaKeyGl(gl, canvas);
154
- } catch {
155
- return null;
156
- }
157
- }
158
- constructor(gl, canvas) {
159
- this.#gl = gl;
160
- this.#canvas = canvas;
161
- canvas.addEventListener("webglcontextlost", this.#handleContextLost);
162
- canvas.addEventListener("webglcontextrestored", this.#handleContextRestored);
163
- this.#initResources();
164
- }
165
- #handleContextLost = (event) => {
166
- event.preventDefault();
167
- this.#contextLost = true;
168
- };
169
- #handleContextRestored = () => {
170
- try {
171
- this.#initResources();
172
- this.#contextLost = false;
173
- } catch {
174
- this.#contextLost = true;
175
- }
176
- };
177
- /** (Re)create all GL resources on the current context — at construction and after restore. */
178
- #initResources() {
179
- const gl = this.#gl;
180
- this.#program = compileProgram(gl);
181
- gl.useProgram(this.#program);
182
- const location = (name) => gl.getUniformLocation(this.#program, name);
183
- this.#uniforms = {
184
- texelSize: location("u_texelSize"),
185
- keyColor: location("u_keyColor"),
186
- tintColor: location("u_tintColor"),
187
- colorCutoff: location("u_colorCutoff"),
188
- colorFeathering: location("u_colorFeathering"),
189
- maskFeathering: location("u_maskFeathering"),
190
- sharpening: location("u_sharpening"),
191
- despill: location("u_despill"),
192
- despillLuminanceAdd: location("u_despillLuminanceAdd")
193
- };
194
- gl.uniform1i(gl.getUniformLocation(this.#program, "u_texture"), 0);
195
- gl.uniform1i(gl.getUniformLocation(this.#program, "u_mask"), 1);
196
- gl.uniform4f(this.#uniforms.tintColor, 1, 1, 1, 1);
197
- this.#quadBuffer = gl.createBuffer();
198
- gl.bindBuffer(gl.ARRAY_BUFFER, this.#quadBuffer);
199
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
200
- -1,
201
- -1,
202
- 1,
203
- -1,
204
- -1,
205
- 1,
206
- 1,
207
- 1
208
- ]), gl.STATIC_DRAW);
209
- const positionLocation = gl.getAttribLocation(this.#program, "a_pos");
210
- gl.enableVertexAttribArray(positionLocation);
211
- gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
212
- this.#texture = gl.createTexture();
213
- gl.bindTexture(gl.TEXTURE_2D, this.#texture);
214
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
215
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
216
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
217
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
218
- this.#maskTexture = gl.createTexture();
219
- gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
220
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
221
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
222
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
223
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
224
- this.#uploadMask();
225
- gl.disable(gl.DEPTH_TEST);
226
- gl.disable(gl.BLEND);
227
- gl.clearColor(0, 0, 0, 0);
228
- }
229
- /**
230
- * Set (or clear) the grayscale shape mask multiplied onto the output alpha. The
231
- * mask is stretched over the full video frame, so author it at the video's aspect
232
- * ratio. Pass null to remove the mask.
233
- */
234
- setMask(image) {
235
- this.#maskImage = image;
236
- if (!this.#contextLost) this.#uploadMask();
237
- }
238
- #uploadMask() {
239
- const gl = this.#gl;
240
- gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
241
- if (this.#maskImage) gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.#maskImage);
242
- else gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
243
- 255,
244
- 255,
245
- 255,
246
- 255
247
- ]));
248
- }
249
- /**
250
- * Upload the video's current frame and render it keyed. Sizes the drawing buffer to
251
- * the video's intrinsic size on first draw (and after a size change).
252
- */
253
- draw(video, parameters) {
254
- if (this.#contextLost || video.videoWidth === 0) return;
255
- const gl = this.#gl;
256
- if (this.#canvas.width !== video.videoWidth || this.#canvas.height !== video.videoHeight) {
257
- this.#canvas.width = video.videoWidth;
258
- this.#canvas.height = video.videoHeight;
259
- gl.viewport(0, 0, video.videoWidth, video.videoHeight);
260
- }
261
- gl.activeTexture(gl.TEXTURE1);
262
- gl.bindTexture(gl.TEXTURE_2D, this.#maskTexture);
263
- gl.activeTexture(gl.TEXTURE0);
264
- gl.bindTexture(gl.TEXTURE_2D, this.#texture);
265
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
266
- gl.useProgram(this.#program);
267
- gl.uniform2f(this.#uniforms.texelSize, 1 / video.videoWidth, 1 / video.videoHeight);
268
- gl.uniform3fv(this.#uniforms.keyColor, parameters.keyColor);
269
- gl.uniform1f(this.#uniforms.colorCutoff, parameters.colorCutoff);
270
- gl.uniform1f(this.#uniforms.colorFeathering, parameters.colorFeathering);
271
- gl.uniform1f(this.#uniforms.maskFeathering, parameters.maskFeathering);
272
- gl.uniform1f(this.#uniforms.sharpening, parameters.sharpening);
273
- gl.uniform1f(this.#uniforms.despill, parameters.despill);
274
- gl.uniform1f(this.#uniforms.despillLuminanceAdd, parameters.despillLuminanceAdd);
275
- gl.clear(gl.COLOR_BUFFER_BIT);
276
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
277
- }
278
- dispose() {
279
- this.#canvas.removeEventListener("webglcontextlost", this.#handleContextLost);
280
- this.#canvas.removeEventListener("webglcontextrestored", this.#handleContextRestored);
281
- const gl = this.#gl;
282
- gl.deleteBuffer(this.#quadBuffer);
283
- gl.deleteTexture(this.#texture);
284
- gl.deleteTexture(this.#maskTexture);
285
- gl.deleteProgram(this.#program);
286
- gl.getExtension("WEBGL_lose_context")?.loseContext();
287
- }
288
- };
289
- //#endregion
290
- export { ChromaKeyGl };
@@ -4,9 +4,9 @@
4
4
  -->
5
5
  <script lang="ts">
6
6
  import { onMount, type Snippet } from 'svelte';
7
- import type { ChromaKeyVideoManifestEntry } from '#fundus/core';
8
- import { ChromaKeyGl } from '../chroma-key-gl';
9
- import { resolveRetainedSource } from '../preload-registry';
7
+ import type { ChromaKeyVideoManifestEntry } from '../../core/index.js';
8
+ import { ChromaKeyGl } from '../chroma-key-gl.js';
9
+ import { resolveRetainedSource } from '../preload-registry.js';
10
10
 
11
11
  interface Props {
12
12
  src: ChromaKeyVideoManifestEntry;
@@ -0,0 +1,21 @@
1
+ import { type Snippet } from 'svelte';
2
+ import type { ChromaKeyVideoManifestEntry } from '../../core/index.js';
3
+ interface Props {
4
+ src: ChromaKeyVideoManifestEntry;
5
+ /** Loop playback (default true for keyed clips). */
6
+ loop?: boolean;
7
+ /**
8
+ * Playback on/off (default true) — false pauses the video AND the render loop,
9
+ * so an off-screen instance costs nothing. The canvas keeps showing the last
10
+ * keyed frame; a keying-parameter change repaints that still frame in place.
11
+ */
12
+ playing?: boolean;
13
+ /** Rendered instead of the canvas when WebGL2 is unavailable; overrides the entry's fallback image. */
14
+ fallback?: Snippet;
15
+ /** Bindable handle on the (hidden) source element, so a host can drive playback itself. */
16
+ videoElement?: HTMLVideoElement;
17
+ class?: string;
18
+ }
19
+ declare const ChromaKeyVideo: import("svelte").Component<Props, {}, "videoElement">;
20
+ type ChromaKeyVideo = ReturnType<typeof ChromaKeyVideo>;
21
+ export default ChromaKeyVideo;
@@ -4,7 +4,7 @@
4
4
  file loads.
5
5
  -->
6
6
  <script lang="ts">
7
- import type { ImageManifestEntry } from '#fundus/core';
7
+ import type { ImageManifestEntry } from '../../core/index.js';
8
8
 
9
9
  interface Props {
10
10
  src: ImageManifestEntry;
@@ -0,0 +1,9 @@
1
+ import type { ImageManifestEntry } from '../../core/index.js';
2
+ interface Props {
3
+ src: ImageManifestEntry;
4
+ alt?: string;
5
+ class?: string;
6
+ }
7
+ declare const Image: import("svelte").Component<Props, {}, "">;
8
+ type Image = ReturnType<typeof Image>;
9
+ export default Image;
@@ -5,7 +5,7 @@
5
5
  (`computeRenderCells`) and therefore render the same cells.
6
6
  -->
7
7
  <script lang="ts">
8
- import type { SliceManifestEntry } from '#fundus/core';
8
+ import type { SliceManifestEntry } from '../../core/index.js';
9
9
  import SliceDom from './SliceDom.svelte';
10
10
  import SliceCanvas from './SliceCanvas.svelte';
11
11
 
@@ -0,0 +1,19 @@
1
+ import type { SliceManifestEntry } from '../../core/index.js';
2
+ interface Props {
3
+ src: SliceManifestEntry;
4
+ /**
5
+ * Rendering backend. `dom` (default) paints one absolutely-positioned
6
+ * `<img>` window per cell; `canvas` draws every cell into a single
7
+ * `<canvas>`. Both produce the same cells — but the DOM backend can
8
+ * flicker in some situations (cells are separate elements the browser
9
+ * composites independently, so a resize mid-animation can tear), so
10
+ * hosts pick `canvas` where that hurts.
11
+ */
12
+ backend?: 'dom' | 'canvas';
13
+ /** Accessible label for the rendered graphic. */
14
+ alt?: string;
15
+ class?: string;
16
+ }
17
+ declare const Slice: import("svelte").Component<Props, {}, "">;
18
+ type Slice = ReturnType<typeof Slice>;
19
+ export default Slice;
@@ -16,9 +16,9 @@
16
16
  size — exactly where the DOM backend positions its overdraw cells.
17
17
  -->
18
18
  <script lang="ts">
19
- import type { SliceManifestEntry } from '#fundus/core';
20
- import { computeCanvasPaintLayout, computeRenderCells } from '../geometry';
21
- import { observeBorderBoxSize } from '../observe-border-box-size';
19
+ import type { SliceManifestEntry } from '../../core/index.js';
20
+ import { computeCanvasPaintLayout, computeRenderCells } from '../geometry.js';
21
+ import { observeBorderBoxSize } from '../observe-border-box-size.js';
22
22
 
23
23
  interface Props {
24
24
  src: SliceManifestEntry;