@jbrowse/render-core 5.0.0-beta.1 → 5.0.0-beta.10

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 (352) hide show
  1. package/esm/RenderCanvas.d.ts +2 -2
  2. package/esm/RenderLifecycleMixin.d.ts +52 -20
  3. package/esm/RenderLifecycleMixin.js +89 -23
  4. package/esm/canvas2dUtils.d.ts +90 -23
  5. package/esm/canvas2dUtils.js +119 -36
  6. package/esm/colorRampLut.d.ts +5 -5
  7. package/esm/colorRampLut.js +6 -6
  8. package/esm/computePipeline.d.ts +14 -0
  9. package/esm/computePipeline.js +62 -0
  10. package/esm/contractReports.d.ts +54 -0
  11. package/esm/contractReports.js +112 -0
  12. package/esm/coverageBand.d.ts +13 -8
  13. package/esm/coverageBand.js +15 -5
  14. package/esm/coverageBandBuffers.d.ts +2 -9
  15. package/esm/coverageBandBuffers.js +1 -13
  16. package/esm/createRenderingBackend.d.ts +14 -18
  17. package/esm/createRenderingBackend.js +4 -2
  18. package/esm/displayPhase.d.ts +83 -104
  19. package/esm/displayPhase.js +42 -82
  20. package/esm/encodeMemo.d.ts +14 -0
  21. package/esm/encodeMemo.js +48 -0
  22. package/esm/gpuContextLostError.d.ts +30 -0
  23. package/esm/gpuContextLostError.js +40 -0
  24. package/esm/gpuDevice.d.ts +29 -10
  25. package/esm/gpuDevice.js +35 -16
  26. package/esm/graphicsCapabilities.d.ts +27 -19
  27. package/esm/graphicsCapabilities.js +40 -18
  28. package/esm/hal/createHal.d.ts +4 -5
  29. package/esm/hal/createHal.js +14 -4
  30. package/esm/hal/deviceGpuCache.d.ts +25 -30
  31. package/esm/hal/deviceGpuCache.js +88 -97
  32. package/esm/hal/gpuHalBase.d.ts +5 -4
  33. package/esm/hal/gpuHalBase.js +25 -14
  34. package/esm/hal/index.d.ts +2 -2
  35. package/esm/hal/index.js +1 -1
  36. package/esm/hal/mockHal.d.ts +15 -10
  37. package/esm/hal/mockHal.js +31 -18
  38. package/esm/hal/oomReporter.d.ts +7 -0
  39. package/esm/hal/oomReporter.js +10 -0
  40. package/esm/hal/passIds.d.ts +8 -7
  41. package/esm/hal/passIds.js +11 -10
  42. package/esm/hal/regionRegistry.d.ts +0 -1
  43. package/esm/hal/regionRegistry.js +3 -15
  44. package/esm/hal/types.d.ts +55 -18
  45. package/esm/hal/webgl2Hal.d.ts +23 -6
  46. package/esm/hal/webgl2Hal.js +161 -155
  47. package/esm/hal/webgpuHal.d.ts +29 -13
  48. package/esm/hal/webgpuHal.js +221 -153
  49. package/esm/installUpload.d.ts +16 -3
  50. package/esm/installUpload.js +13 -41
  51. package/esm/instanceCache.d.ts +10 -7
  52. package/esm/instanceCache.js +14 -15
  53. package/esm/instancePass.d.ts +2 -1
  54. package/esm/mapUploadSync.d.ts +2 -10
  55. package/esm/mapUploadSync.js +2 -3
  56. package/esm/marks/barMark.d.ts +30 -0
  57. package/esm/marks/barMark.js +149 -0
  58. package/esm/marks/colorFill.d.ts +17 -0
  59. package/esm/marks/colorFill.js +26 -0
  60. package/esm/marks/drawAgainstHit.d.ts +113 -0
  61. package/esm/marks/drawAgainstHit.js +407 -0
  62. package/esm/marks/ellipseDistance.d.ts +10 -0
  63. package/esm/marks/ellipseDistance.js +136 -0
  64. package/esm/marks/glyphPaint.d.ts +36 -0
  65. package/esm/marks/glyphPaint.js +77 -0
  66. package/esm/marks/index.d.ts +33 -0
  67. package/esm/marks/index.js +20 -0
  68. package/esm/marks/lineMark.d.ts +37 -0
  69. package/esm/marks/lineMark.js +416 -0
  70. package/esm/marks/linkMark.d.ts +76 -0
  71. package/esm/marks/linkMark.js +585 -0
  72. package/esm/marks/markBackend.d.ts +118 -0
  73. package/esm/marks/markBackend.js +196 -0
  74. package/esm/marks/markHit.d.ts +32 -0
  75. package/esm/marks/markHit.js +61 -0
  76. package/esm/marks/markInk.d.ts +18 -0
  77. package/esm/marks/markInk.js +71 -0
  78. package/esm/marks/markPaint.d.ts +14 -0
  79. package/esm/marks/markPaint.js +32 -0
  80. package/esm/marks/markPlan.d.ts +25 -0
  81. package/esm/marks/markPlan.js +20 -0
  82. package/esm/marks/markRamp.d.ts +72 -0
  83. package/esm/marks/markRamp.js +197 -0
  84. package/esm/marks/nearestMarkHit.d.ts +55 -0
  85. package/esm/marks/nearestMarkHit.js +158 -0
  86. package/esm/marks/pathRecorder.d.ts +14 -0
  87. package/esm/marks/pathRecorder.js +80 -0
  88. package/esm/marks/pointMark.d.ts +42 -0
  89. package/esm/marks/pointMark.js +125 -0
  90. package/esm/marks/rowLane.d.ts +39 -0
  91. package/esm/marks/rowLane.js +41 -0
  92. package/esm/marks/rowSpanIndex.d.ts +29 -0
  93. package/esm/marks/rowSpanIndex.js +141 -0
  94. package/esm/marks/rowTable.d.ts +41 -0
  95. package/esm/marks/rowTable.js +75 -0
  96. package/esm/marks/ruleMark.d.ts +21 -0
  97. package/esm/marks/ruleMark.js +91 -0
  98. package/esm/marks/spanMark.d.ts +42 -0
  99. package/esm/marks/spanMark.js +81 -0
  100. package/esm/marks/types.d.ts +261 -0
  101. package/esm/marks/types.js +175 -0
  102. package/esm/marks/valueScale.d.ts +23 -0
  103. package/esm/marks/valueScale.js +11 -0
  104. package/esm/namedReactions.d.ts +3 -4
  105. package/esm/namedReactions.js +3 -4
  106. package/esm/perRegionRenderingBackend.d.ts +21 -3
  107. package/esm/perRegionRenderingBackend.js +37 -3
  108. package/esm/regionDataMap.d.ts +2 -2
  109. package/esm/regionDataMap.js +25 -23
  110. package/esm/renderBlock.d.ts +14 -0
  111. package/esm/renderBlock.js +25 -0
  112. package/esm/renderingBackendBase.d.ts +20 -14
  113. package/esm/renderingBackendBase.js +12 -7
  114. package/esm/scoreScale.d.ts +27 -0
  115. package/esm/scoreScale.js +88 -0
  116. package/esm/shaders/barMark.generated.d.ts +3 -0
  117. package/esm/shaders/barMark.generated.js +7 -0
  118. package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
  119. package/esm/shaders/barMark.glsl.generated.js +4 -0
  120. package/esm/shaders/barMark.iface.generated.d.ts +90 -0
  121. package/esm/shaders/barMark.iface.generated.js +205 -0
  122. package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
  123. package/esm/shaders/barMark.wgsl.generated.js +3 -0
  124. package/esm/shaders/capsule.js.generated.d.ts +1 -0
  125. package/esm/shaders/capsule.js.generated.js +11 -0
  126. package/esm/shaders/clipStrip.generated.d.ts +2 -0
  127. package/esm/shaders/clipStrip.generated.js +4 -0
  128. package/esm/shaders/clipStrip.js.generated.d.ts +1 -0
  129. package/esm/shaders/clipStrip.js.generated.js +21 -0
  130. package/esm/shaders/colorRampLut.js.generated.d.ts +1 -0
  131. package/esm/shaders/colorRampLut.js.generated.js +17 -0
  132. package/esm/shaders/coverageBar.generated.d.ts +2 -3
  133. package/esm/shaders/coverageBar.generated.js +4 -3
  134. package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
  135. package/esm/shaders/coverageBar.glsl.generated.js +4 -0
  136. package/esm/shaders/coverageBar.iface.generated.js +1 -1
  137. package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
  138. package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
  139. package/esm/shaders/coverageClip.generated.d.ts +3 -0
  140. package/esm/shaders/coverageClip.generated.js +7 -0
  141. package/esm/shaders/coverageClip.glsl.generated.d.ts +2 -0
  142. package/esm/shaders/coverageClip.glsl.generated.js +4 -0
  143. package/esm/shaders/coverageClip.iface.generated.d.ts +85 -0
  144. package/esm/shaders/coverageClip.iface.generated.js +114 -0
  145. package/esm/shaders/coverageClip.wgsl.generated.d.ts +1 -0
  146. package/esm/shaders/coverageClip.wgsl.generated.js +3 -0
  147. package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
  148. package/esm/shaders/coverageIndicator.generated.js +4 -3
  149. package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
  150. package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
  151. package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
  152. package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
  153. package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
  154. package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
  155. package/esm/shaders/coverageInterbase.generated.js +4 -3
  156. package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
  157. package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
  158. package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
  159. package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
  160. package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
  161. package/esm/shaders/coverageMod.generated.d.ts +2 -3
  162. package/esm/shaders/coverageMod.generated.js +4 -3
  163. package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
  164. package/esm/shaders/coverageMod.glsl.generated.js +4 -0
  165. package/esm/shaders/coverageMod.iface.generated.js +1 -1
  166. package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
  167. package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
  168. package/esm/shaders/coverageSnp.generated.d.ts +2 -3
  169. package/esm/shaders/coverageSnp.generated.js +4 -3
  170. package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
  171. package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
  172. package/esm/shaders/coverageSnp.iface.generated.js +1 -1
  173. package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
  174. package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
  175. package/esm/shaders/curveDistance.js.generated.d.ts +5 -0
  176. package/esm/shaders/curveDistance.js.generated.js +87 -0
  177. package/esm/shaders/hpmath.js.generated.d.ts +2 -1
  178. package/esm/shaders/hpmath.js.generated.js +5 -2
  179. package/esm/shaders/lineCenterMark.generated.d.ts +3 -0
  180. package/esm/shaders/lineCenterMark.generated.js +7 -0
  181. package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -0
  182. package/esm/shaders/lineCenterMark.glsl.generated.js +4 -0
  183. package/esm/shaders/lineCenterMark.iface.generated.d.ts +104 -0
  184. package/esm/shaders/lineCenterMark.iface.generated.js +237 -0
  185. package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -0
  186. package/esm/shaders/lineCenterMark.wgsl.generated.js +3 -0
  187. package/esm/shaders/lineCommon.generated.d.ts +2 -0
  188. package/esm/shaders/lineCommon.generated.js +4 -0
  189. package/esm/shaders/lineStepMark.generated.d.ts +3 -0
  190. package/esm/shaders/lineStepMark.generated.js +7 -0
  191. package/esm/shaders/lineStepMark.glsl.generated.d.ts +2 -0
  192. package/esm/shaders/lineStepMark.glsl.generated.js +4 -0
  193. package/esm/shaders/lineStepMark.iface.generated.d.ts +98 -0
  194. package/esm/shaders/lineStepMark.iface.generated.js +225 -0
  195. package/esm/shaders/lineStepMark.wgsl.generated.d.ts +1 -0
  196. package/esm/shaders/lineStepMark.wgsl.generated.js +3 -0
  197. package/esm/shaders/linkMark.consts.generated.d.ts +14 -0
  198. package/esm/shaders/linkMark.consts.generated.js +16 -0
  199. package/esm/shaders/linkMark.generated.d.ts +4 -0
  200. package/esm/shaders/linkMark.generated.js +8 -0
  201. package/esm/shaders/linkMark.glsl.generated.d.ts +2 -0
  202. package/esm/shaders/linkMark.glsl.generated.js +4 -0
  203. package/esm/shaders/linkMark.iface.generated.d.ts +142 -0
  204. package/esm/shaders/linkMark.iface.generated.js +1829 -0
  205. package/esm/shaders/linkMark.js.generated.d.ts +7 -0
  206. package/esm/shaders/linkMark.js.generated.js +159 -0
  207. package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -0
  208. package/esm/shaders/linkMark.wgsl.generated.js +3 -0
  209. package/esm/shaders/markColor.generated.d.ts +9 -0
  210. package/esm/shaders/markColor.generated.js +11 -0
  211. package/esm/shaders/pointGlyph.js.generated.d.ts +2 -0
  212. package/esm/shaders/pointGlyph.js.generated.js +15 -0
  213. package/esm/shaders/pointMark.consts.generated.d.ts +7 -0
  214. package/esm/shaders/pointMark.consts.generated.js +9 -0
  215. package/esm/shaders/pointMark.generated.d.ts +4 -0
  216. package/esm/shaders/pointMark.generated.js +8 -0
  217. package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
  218. package/esm/shaders/pointMark.glsl.generated.js +4 -0
  219. package/esm/shaders/pointMark.iface.generated.d.ts +98 -0
  220. package/esm/shaders/pointMark.iface.generated.js +219 -0
  221. package/esm/shaders/pointMark.js.generated.d.ts +3 -0
  222. package/esm/shaders/pointMark.js.generated.js +93 -0
  223. package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
  224. package/esm/shaders/pointMark.wgsl.generated.js +3 -0
  225. package/esm/shaders/rowRect.generated.d.ts +0 -1
  226. package/esm/shaders/rowRect.generated.js +0 -1
  227. package/esm/shaders/rowTable.generated.d.ts +1 -0
  228. package/esm/shaders/rowTable.generated.js +3 -0
  229. package/esm/shaders/rowTable.js.generated.d.ts +5 -0
  230. package/esm/shaders/rowTable.js.generated.js +29 -0
  231. package/esm/shaders/scoreScale.generated.d.ts +2 -0
  232. package/esm/shaders/scoreScale.generated.js +4 -0
  233. package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
  234. package/esm/shaders/scoreScale.js.generated.js +50 -23
  235. package/esm/shaders/spanMark.generated.d.ts +3 -0
  236. package/esm/shaders/spanMark.generated.js +7 -0
  237. package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
  238. package/esm/shaders/spanMark.glsl.generated.js +4 -0
  239. package/esm/shaders/spanMark.iface.generated.d.ts +81 -0
  240. package/esm/shaders/spanMark.iface.generated.js +215 -0
  241. package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
  242. package/esm/shaders/spanMark.wgsl.generated.js +3 -0
  243. package/esm/sharedBackendKey.d.ts +18 -0
  244. package/esm/{keyedRenderingBackend.js → sharedBackendKey.js} +5 -0
  245. package/esm/slangPass.d.ts +18 -11
  246. package/esm/slangPass.js +12 -4
  247. package/esm/useGraphicsCapabilities.d.ts +1 -1
  248. package/esm/useGraphicsCapabilities.js +1 -1
  249. package/esm/useRenderingBackend.d.ts +13 -13
  250. package/esm/useRenderingBackend.js +58 -20
  251. package/esm/webgpuUtils.d.ts +3 -11
  252. package/esm/webgpuUtils.js +12 -33
  253. package/package.json +32 -7
  254. package/src/shaders/antialias.slang +46 -0
  255. package/src/shaders/arcHull.test.ts +267 -0
  256. package/src/shaders/barMark.generated.ts +11 -0
  257. package/src/shaders/barMark.glsl.generated.ts +6 -0
  258. package/src/shaders/barMark.iface.generated.ts +285 -0
  259. package/src/shaders/barMark.slang +167 -0
  260. package/src/shaders/barMark.wgsl.generated.ts +4 -0
  261. package/src/shaders/capsule.js.generated.ts +14 -0
  262. package/src/shaders/capsule.slang +12 -4
  263. package/src/shaders/clipStrip.generated.ts +6 -0
  264. package/src/shaders/clipStrip.js.generated.ts +22 -0
  265. package/src/shaders/clipStrip.slang +34 -0
  266. package/src/shaders/clipStrip.test.ts +39 -0
  267. package/src/shaders/colorPack.slang +5 -1
  268. package/src/shaders/colorRampLut.js.generated.ts +22 -0
  269. package/src/shaders/colorRampLut.slang +15 -1
  270. package/src/shaders/coverageBand.slang +64 -32
  271. package/src/shaders/coverageBar.generated.ts +6 -5
  272. package/src/shaders/coverageBar.glsl.generated.ts +6 -0
  273. package/src/shaders/coverageBar.iface.generated.ts +1 -1
  274. package/src/shaders/coverageBar.slang +10 -10
  275. package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
  276. package/src/shaders/coverageClip.generated.ts +11 -0
  277. package/src/shaders/coverageClip.glsl.generated.ts +6 -0
  278. package/src/shaders/coverageClip.iface.generated.ts +172 -0
  279. package/src/shaders/coverageClip.slang +38 -0
  280. package/src/shaders/coverageClip.wgsl.generated.ts +4 -0
  281. package/src/shaders/coverageIndicator.generated.ts +6 -5
  282. package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
  283. package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
  284. package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
  285. package/src/shaders/coverageInterbase.generated.ts +6 -5
  286. package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
  287. package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
  288. package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
  289. package/src/shaders/coverageMod.generated.ts +6 -5
  290. package/src/shaders/coverageMod.glsl.generated.ts +6 -0
  291. package/src/shaders/coverageMod.iface.generated.ts +1 -1
  292. package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
  293. package/src/shaders/coverageSnp.generated.ts +6 -5
  294. package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
  295. package/src/shaders/coverageSnp.iface.generated.ts +1 -1
  296. package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
  297. package/src/shaders/curveDistance.js.generated.ts +91 -0
  298. package/src/shaders/curveDistance.slang +265 -0
  299. package/src/shaders/hpClampFloor.test.ts +87 -0
  300. package/src/shaders/hpmath.js.generated.ts +6 -2
  301. package/src/shaders/hpmath.slang +100 -48
  302. package/src/shaders/insetValueScale.test.ts +67 -0
  303. package/src/shaders/lineCenterMark.generated.ts +11 -0
  304. package/src/shaders/lineCenterMark.glsl.generated.ts +6 -0
  305. package/src/shaders/lineCenterMark.iface.generated.ts +328 -0
  306. package/src/shaders/lineCenterMark.slang +127 -0
  307. package/src/shaders/lineCenterMark.wgsl.generated.ts +4 -0
  308. package/src/shaders/lineCommon.generated.ts +6 -0
  309. package/src/shaders/lineCommon.slang +102 -0
  310. package/src/shaders/lineStepMark.generated.ts +11 -0
  311. package/src/shaders/lineStepMark.glsl.generated.ts +6 -0
  312. package/src/shaders/lineStepMark.iface.generated.ts +311 -0
  313. package/src/shaders/lineStepMark.slang +125 -0
  314. package/src/shaders/lineStepMark.wgsl.generated.ts +4 -0
  315. package/src/shaders/linkMark.consts.generated.ts +30 -0
  316. package/src/shaders/linkMark.generated.ts +12 -0
  317. package/src/shaders/linkMark.glsl.generated.ts +6 -0
  318. package/src/shaders/linkMark.iface.generated.ts +1954 -0
  319. package/src/shaders/linkMark.js.generated.ts +167 -0
  320. package/src/shaders/linkMark.slang +439 -0
  321. package/src/shaders/linkMark.wgsl.generated.ts +4 -0
  322. package/src/shaders/markColor.generated.ts +20 -0
  323. package/src/shaders/markColor.slang +128 -0
  324. package/src/shaders/pointGlyph.js.generated.ts +20 -0
  325. package/src/shaders/pointGlyph.slang +23 -7
  326. package/src/shaders/pointGlyphPad.test.ts +242 -0
  327. package/src/shaders/pointMark.consts.generated.ts +16 -0
  328. package/src/shaders/pointMark.generated.ts +12 -0
  329. package/src/shaders/pointMark.glsl.generated.ts +6 -0
  330. package/src/shaders/pointMark.iface.generated.ts +304 -0
  331. package/src/shaders/pointMark.js.generated.ts +99 -0
  332. package/src/shaders/pointMark.slang +227 -0
  333. package/src/shaders/pointMark.wgsl.generated.ts +4 -0
  334. package/src/shaders/rowRect.generated.ts +0 -2
  335. package/src/shaders/rowRect.slang +39 -58
  336. package/src/shaders/rowTable.generated.ts +4 -0
  337. package/src/shaders/rowTable.js.generated.ts +37 -0
  338. package/src/shaders/rowTable.slang +98 -0
  339. package/src/shaders/scoreScale.generated.ts +6 -0
  340. package/src/shaders/scoreScale.js.generated.ts +48 -23
  341. package/src/shaders/scoreScale.slang +49 -55
  342. package/src/shaders/sdEllipse.test.ts +211 -0
  343. package/src/shaders/spanMark.generated.ts +11 -0
  344. package/src/shaders/spanMark.glsl.generated.ts +6 -0
  345. package/src/shaders/spanMark.iface.generated.ts +289 -0
  346. package/src/shaders/spanMark.slang +77 -0
  347. package/src/shaders/spanMark.wgsl.generated.ts +4 -0
  348. package/src/shaders/valueScale.slang +26 -0
  349. package/src/shaders/wideCircleLeg.test.ts +85 -0
  350. package/esm/globalRenderingBackend.d.ts +0 -90
  351. package/esm/globalRenderingBackend.js +0 -53
  352. package/esm/keyedRenderingBackend.d.ts +0 -41
@@ -0,0 +1,118 @@
1
+ import { Canvas2DPerRegionRenderingBackend, GpuPerRegionRenderingBackend } from '../perRegionRenderingBackend.ts';
2
+ import type { BlockClipResult } from '../blockClipUtils.ts';
3
+ import type { CanvasScale } from '../canvas2dUtils.ts';
4
+ import type { GpuHal } from '../hal/index.ts';
5
+ import type { SampleCount } from '../hal/types.ts';
6
+ import type { InstancePass } from '../instancePass.ts';
7
+ import type { ClearColor, PerRegionRenderingBackend } from '../perRegionRenderingBackend.ts';
8
+ import type { RenderBlock } from '../renderBlock.ts';
9
+ import type { FrameDimensions } from '../renderingBackendBase.ts';
10
+ import type { MarkPlan } from './markPlan.ts';
11
+ import type { Mark, MarkTexture, TextureBinder } from './types.ts';
12
+ /** Pack and upload one region's buffers for a mark list. */
13
+ export declare function uploadMarks<TRegion, TState extends FrameDimensions>(hal: GpuHal, regionKey: number, marks: readonly Mark<TRegion, TState>[], data: TRegion): void;
14
+ /**
15
+ * Draw one already-clipped block through a mark list.
16
+ *
17
+ * **The viewport is this helper's, the scissor is the caller's.** Every shape
18
+ * maps bp across the block column, so nobody wants a viewport narrower than the
19
+ * clip; a caller does want a narrower scissor, which is how alignments clips a
20
+ * coverage strip inside the column it hands over. `GpuPerRegionRenderingBackend`
21
+ * sets both per block already, so for a backend on that scaffold the viewport
22
+ * set here is the same rect twice.
23
+ *
24
+ * A caller that narrows it must hand over marks declaring no `band`, and that
25
+ * is the one way the two clips do not compose: a banded mark scissors to its
26
+ * strip and hands the BLOCK COLUMN back rather than what the caller had. The
27
+ * split is deliberate — `render-core/CLAUDE.md` §Drawing has which displays
28
+ * take which side — but nothing enforces it, so it is stated at both.
29
+ */
30
+ export declare function drawMarks<TRegion, TState extends FrameDimensions>(hal: GpuHal, scratch: ArrayBuffer, marks: readonly Mark<TRegion, TState>[], block: RenderBlock, clip: BlockClipResult, region: TRegion, state: TState, regionKey: number, textures?: TextureBinder): void;
31
+ /**
32
+ * Draw one block's planned passes off the uniforms the caller has already
33
+ * staged for it. No gate, no lens, no write: `planMarks` settled the frame
34
+ * question and the caller's own `hal.writeUniforms` settled the block's, so
35
+ * what is left per mark is the `drawPass` — the loop a display with its own
36
+ * frame scaffold was already running over a hand-kept pass list.
37
+ *
38
+ * Viewport and scissor are the caller's, as with `drawMarks`' scissor: a
39
+ * plan's marks declare no `band`, so nothing here narrows or restores either.
40
+ */
41
+ export declare function drawPlannedPasses(hal: GpuHal, plan: Pick<MarkPlan<never, never>, 'passes'>, regionKey: number): void;
42
+ /**
43
+ * The texture each textured pass holds, by identity — the mirror of the one
44
+ * texture the HAL keeps per pass, so an unchanged ramp, strip or table costs a
45
+ * frame nothing and a backend rebuilt after context loss re-uploads. Per pass
46
+ * and per backend, never per region: a lens answering nothing for a region
47
+ * leaves the pass's texture where it is, and binds the inert table only while
48
+ * the pass has none at all, since a ring canvas draws one region per pass and
49
+ * a lens with no opinion on the other regions must not swap the strip out and
50
+ * back on every frame.
51
+ */
52
+ export declare class MarkTextureBinder implements TextureBinder {
53
+ private hal;
54
+ private bound;
55
+ constructor(hal: GpuHal);
56
+ bind(passId: string, sampler: string, texture: MarkTexture | undefined): void;
57
+ }
58
+ /**
59
+ * The HAL-side half of `createMarkBackend`, exported so a display's mark list
60
+ * can be driven against `MockHal`: which marks upload, which draw off another's
61
+ * buffer, and which blocks a shape declines.
62
+ */
63
+ export declare class GpuMarkBackend<TRegion, TState extends FrameDimensions> extends GpuPerRegionRenderingBackend<TRegion, TState> {
64
+ private clear?;
65
+ protected regionPasses: InstancePass<TRegion>[];
66
+ private textures;
67
+ private blockMarks;
68
+ private viewMarks;
69
+ constructor(hal: GpuHal, marks: readonly Mark<TRegion, TState>[], clear?: ((state: TState) => ClearColor) | undefined);
70
+ protected clearColor(state: TState): ClearColor;
71
+ private drawWith;
72
+ protected drawRegion(block: RenderBlock, clip: BlockClipResult, region: TRegion, state: TState): void;
73
+ protected drawOverBlocks(regions: ReadonlyMap<number, TRegion>, state: TState, scale: CanvasScale): boolean;
74
+ }
75
+ /**
76
+ * The Canvas2D half, exported for the same reason `GpuMarkBackend` is: a
77
+ * display's frame scaffold — the ground it clears to, the blocks it paints — is
78
+ * a property of the pair, and a suite pinning it on one backend has to pin it
79
+ * on the other.
80
+ */
81
+ export declare class Canvas2DMarkBackend<TRegion, TState extends FrameDimensions> extends Canvas2DPerRegionRenderingBackend<TRegion, TState> {
82
+ private marks;
83
+ private clear?;
84
+ constructor(canvas: HTMLCanvasElement, marks: readonly Mark<TRegion, TState>[], clear?: ((state: TState) => ClearColor) | undefined);
85
+ protected clearColor(state: TState): ClearColor | undefined;
86
+ protected draw(blocks: RenderBlock[], regions: ReadonlyMap<number, TRegion>, state: TState): void;
87
+ }
88
+ /**
89
+ * Build a display's rendering backend from its mark declarations.
90
+ *
91
+ * **This is the only module on the mark path that reaches the HAL**, which is
92
+ * why it is not on the `marks` subpath: a display's declaration, its painter
93
+ * and its hit test are all things a state model can legitimately reach, and a
94
+ * state model is eager (ADR-091). Reaching the backend costs the GPU stack at
95
+ * plugin-install time, so it is a separate import a display makes once, from
96
+ * the factory the component hands to `DisplayChrome`.
97
+ *
98
+ * This is the whole of what a display used to spell as a `GpuXxxRenderer`
99
+ * class, a `Canvas2DXxxRenderer` class, a pass list and a factory: the passes
100
+ * are the marks' own and each backend walks the same list.
101
+ *
102
+ * One uniform buffer serves every mark because each writes its own layout into
103
+ * the scratch immediately before its `drawPass`, the ordering the HAL's
104
+ * write-then-draw contract already guarantees for a multi-pass renderer — or
105
+ * draws off the struct the previous mark of the same block already staged, per
106
+ * `StagedUniforms`.
107
+ */
108
+ export declare function createMarkBackend<TRegion, TState extends FrameDimensions>(canvas: HTMLCanvasElement, marks: readonly Mark<TRegion, TState>[], opts?: {
109
+ sampleCount?: SampleCount;
110
+ /**
111
+ * What the frame is cleared to, when transparent is the wrong answer. The
112
+ * GPU side hands it to `beginFrame` and the Canvas2D side fills it after
113
+ * `prepareCanvas`, so both backends composite over the same colour — which
114
+ * synteny needs, its indel wedges being pre-blended against the band's
115
+ * ground rather than composited over it.
116
+ */
117
+ clearColor?: (state: TState) => ClearColor;
118
+ }): Promise<PerRegionRenderingBackend<TRegion, TState>>;
@@ -0,0 +1,196 @@
1
+ import { clipBlock } from '../blockClipUtils.js';
2
+ import { COLOR_RAMP_LUT_ENTRIES, uploadColorRampLut } from '../colorRampLut.js';
3
+ import { createRenderingBackend } from '../createRenderingBackend.js';
4
+ import { uploadPass } from '../instancePass.js';
5
+ import { Canvas2DPerRegionRenderingBackend, GpuPerRegionRenderingBackend, } from '../perRegionRenderingBackend.js';
6
+ import { canvasWideBlock } from '../renderBlock.js';
7
+ import { paintMarkBlocks } from './markPaint.js';
8
+ // The passes a mark list owns a buffer for: the whole list minus those drawing
9
+ // off another's (`bufferOf`). Uploading to a borrowed pass is silent and its
10
+ // buffer is the lender's, so the skip is stated once, here — module-local,
11
+ // because `marks/backend` is a published subpath and nothing outside wants it.
12
+ function ownedPasses(marks) {
13
+ return marks.filter(m => !m.bufferOf).map(m => m.pass);
14
+ }
15
+ /** Pack and upload one region's buffers for a mark list. */
16
+ export function uploadMarks(hal, regionKey, marks, data) {
17
+ for (const pass of ownedPasses(marks)) {
18
+ uploadPass(hal, regionKey, pass, data);
19
+ }
20
+ }
21
+ /**
22
+ * Draw one already-clipped block through a mark list.
23
+ *
24
+ * **The viewport is this helper's, the scissor is the caller's.** Every shape
25
+ * maps bp across the block column, so nobody wants a viewport narrower than the
26
+ * clip; a caller does want a narrower scissor, which is how alignments clips a
27
+ * coverage strip inside the column it hands over. `GpuPerRegionRenderingBackend`
28
+ * sets both per block already, so for a backend on that scaffold the viewport
29
+ * set here is the same rect twice.
30
+ *
31
+ * A caller that narrows it must hand over marks declaring no `band`, and that
32
+ * is the one way the two clips do not compose: a banded mark scissors to its
33
+ * strip and hands the BLOCK COLUMN back rather than what the caller had. The
34
+ * split is deliberate — `render-core/CLAUDE.md` §Drawing has which displays
35
+ * take which side — but nothing enforces it, so it is stated at both.
36
+ */
37
+ export function drawMarks(hal, scratch, marks, block, clip, region, state, regionKey, textures) {
38
+ hal.setViewport(clip.pxX, 0, clip.pxW, clip.pxH);
39
+ // One call is one block, which is exactly the life of a `StagedUniforms`
40
+ const staged = { writer: undefined, params: undefined };
41
+ for (const mark of marks) {
42
+ mark.drawRegion(hal, scratch, block, clip, region, state, regionKey, staged, textures);
43
+ }
44
+ }
45
+ /**
46
+ * Draw one block's planned passes off the uniforms the caller has already
47
+ * staged for it. No gate, no lens, no write: `planMarks` settled the frame
48
+ * question and the caller's own `hal.writeUniforms` settled the block's, so
49
+ * what is left per mark is the `drawPass` — the loop a display with its own
50
+ * frame scaffold was already running over a hand-kept pass list.
51
+ *
52
+ * Viewport and scissor are the caller's, as with `drawMarks`' scissor: a
53
+ * plan's marks declare no `band`, so nothing here narrows or restores either.
54
+ */
55
+ export function drawPlannedPasses(hal, plan, regionKey) {
56
+ const { passes } = plan;
57
+ for (let i = 0; i < passes.length; i++) {
58
+ const pass = passes[i];
59
+ hal.drawPass(pass.id, regionKey, pass.bufferOf);
60
+ }
61
+ }
62
+ // What a textured pass binds while its mark names no ramp: a shader declares
63
+ // its sampler unconditionally, and a textured pass missing a texture draws
64
+ // nothing on either GPU HAL. A mark declaring no `texture` at all is the same case —
65
+ // `pointMark` carries a sampler for the shapes that ramp, and a point of a
66
+ // constant colour draws it without one.
67
+ const INERT_RAMP = new Uint8Array(COLOR_RAMP_LUT_ENTRIES * 4);
68
+ /**
69
+ * The texture each textured pass holds, by identity — the mirror of the one
70
+ * texture the HAL keeps per pass, so an unchanged ramp, strip or table costs a
71
+ * frame nothing and a backend rebuilt after context loss re-uploads. Per pass
72
+ * and per backend, never per region: a lens answering nothing for a region
73
+ * leaves the pass's texture where it is, and binds the inert table only while
74
+ * the pass has none at all, since a ring canvas draws one region per pass and
75
+ * a lens with no opinion on the other regions must not swap the strip out and
76
+ * back on every frame.
77
+ */
78
+ export class MarkTextureBinder {
79
+ hal;
80
+ bound = new Map();
81
+ constructor(hal) {
82
+ this.hal = hal;
83
+ }
84
+ bind(passId, sampler, texture) {
85
+ const key = `${passId}\u0000${sampler}`;
86
+ const bound = this.bound.get(key);
87
+ const next = texture ?? bound ?? INERT_RAMP;
88
+ if (next !== bound) {
89
+ if (next instanceof Uint8Array) {
90
+ uploadColorRampLut(this.hal, next, [passId], sampler);
91
+ }
92
+ else if ('image' in next) {
93
+ this.hal.uploadTexture(passId, next.image, next.width, next.height, sampler);
94
+ }
95
+ else {
96
+ this.hal.uploadTexture(passId, next.bytes, next.width, next.height, sampler);
97
+ }
98
+ this.bound.set(key, next);
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * The HAL-side half of `createMarkBackend`, exported so a display's mark list
104
+ * can be driven against `MockHal`: which marks upload, which draw off another's
105
+ * buffer, and which blocks a shape declines.
106
+ */
107
+ export class GpuMarkBackend extends GpuPerRegionRenderingBackend {
108
+ clear;
109
+ // The base's upload loop already IS the mark walk, so this backend names its
110
+ // passes instead of overriding `upload` with a second spelling of it.
111
+ regionPasses;
112
+ textures;
113
+ blockMarks;
114
+ viewMarks;
115
+ constructor(hal, marks, clear) {
116
+ super(hal);
117
+ this.clear = clear;
118
+ this.regionPasses = ownedPasses(marks);
119
+ this.textures = new MarkTextureBinder(hal);
120
+ this.blockMarks = marks.filter(m => !m.spansView);
121
+ this.viewMarks = marks.filter(m => m.spansView);
122
+ }
123
+ clearColor(state) {
124
+ return this.clear ? this.clear(state) : super.clearColor(state);
125
+ }
126
+ drawWith(marks, block, clip, region, state) {
127
+ drawMarks(this.hal, this.uniformData, marks, block, clip, region, state, block.displayedRegionIndex, this.textures);
128
+ }
129
+ drawRegion(block, clip, region, state) {
130
+ this.drawWith(this.blockMarks, block, clip, region, state);
131
+ }
132
+ drawOverBlocks(regions, state, scale) {
133
+ if (this.viewMarks.length === 0 || regions.size === 0) {
134
+ return false;
135
+ }
136
+ const { canvasWidth, canvasHeight } = state;
137
+ for (const [key, region] of regions) {
138
+ const block = canvasWideBlock(key, canvasWidth);
139
+ const clip = clipBlock(block, canvasWidth, canvasHeight, scale);
140
+ if (clip) {
141
+ this.drawWith(this.viewMarks, block, clip, region, state);
142
+ }
143
+ }
144
+ return true;
145
+ }
146
+ }
147
+ /**
148
+ * The Canvas2D half, exported for the same reason `GpuMarkBackend` is: a
149
+ * display's frame scaffold — the ground it clears to, the blocks it paints — is
150
+ * a property of the pair, and a suite pinning it on one backend has to pin it
151
+ * on the other.
152
+ */
153
+ export class Canvas2DMarkBackend extends Canvas2DPerRegionRenderingBackend {
154
+ marks;
155
+ clear;
156
+ constructor(canvas, marks, clear) {
157
+ super(canvas);
158
+ this.marks = marks;
159
+ this.clear = clear;
160
+ }
161
+ clearColor(state) {
162
+ return this.clear ? this.clear(state) : super.clearColor(state);
163
+ }
164
+ draw(blocks, regions, state) {
165
+ paintMarkBlocks(this.ctx, this.marks, regions, blocks, state);
166
+ }
167
+ }
168
+ /**
169
+ * Build a display's rendering backend from its mark declarations.
170
+ *
171
+ * **This is the only module on the mark path that reaches the HAL**, which is
172
+ * why it is not on the `marks` subpath: a display's declaration, its painter
173
+ * and its hit test are all things a state model can legitimately reach, and a
174
+ * state model is eager (ADR-091). Reaching the backend costs the GPU stack at
175
+ * plugin-install time, so it is a separate import a display makes once, from
176
+ * the factory the component hands to `DisplayChrome`.
177
+ *
178
+ * This is the whole of what a display used to spell as a `GpuXxxRenderer`
179
+ * class, a `Canvas2DXxxRenderer` class, a pass list and a factory: the passes
180
+ * are the marks' own and each backend walks the same list.
181
+ *
182
+ * One uniform buffer serves every mark because each writes its own layout into
183
+ * the scratch immediately before its `drawPass`, the ordering the HAL's
184
+ * write-then-draw contract already guarantees for a multi-pass renderer — or
185
+ * draws off the struct the previous mark of the same block already staged, per
186
+ * `StagedUniforms`.
187
+ */
188
+ export function createMarkBackend(canvas, marks, opts = {}) {
189
+ const { clearColor } = opts;
190
+ return createRenderingBackend(canvas, {
191
+ passes: marks.map(m => m.pass),
192
+ sampleCount: opts.sampleCount,
193
+ createGpuBackend: hal => new GpuMarkBackend(hal, marks, clearColor),
194
+ createCanvas2DBackend: c => new Canvas2DMarkBackend(c, marks, clearColor),
195
+ });
196
+ }
@@ -0,0 +1,32 @@
1
+ import type { MarkHit, MarkShape } from './types.ts';
2
+ /** One instance's ink measured against a cursor — a `MarkHit` before it is one. */
3
+ export type InkHit = Omit<MarkHit, 'index'>;
4
+ /**
5
+ * Where a rect's ink sits nearest `(xPx, yPx)`, and how far: the point itself
6
+ * where the cursor is inside, else the nearest point on the edge.
7
+ */
8
+ export declare function inkOnRect(xPx: number, yPx: number, left: number, top: number, width: number, height: number): InkHit;
9
+ /** The same for a mark with no extent to clamp into. */
10
+ export declare function inkAtPoint(xPx: number, yPx: number, x: number, y: number): InkHit;
11
+ /**
12
+ * The nearest of `candidates` by where each one's ink is, or undefined when
13
+ * none beats `maxDistSq`.
14
+ *
15
+ * This is the whole of every shape's `hitNearest` but the geometry: `inkAt`
16
+ * answers where instance `i` put ink and how far that is, and this keeps the
17
+ * closest. Only a STRICTLY nearer candidate replaces the best, so on a tie the
18
+ * first wins, so a caller that iterates back to front gets the mark on top.
19
+ * Five shapes used to spell that rule out separately.
20
+ *
21
+ * `inkAt` may answer `undefined` for an instance that drew nothing at all, as
22
+ * against one that drew somewhere far away: a bar clipped out of its band has
23
+ * no ink to be near.
24
+ */
25
+ export declare function nearestInk(candidates: Iterable<number>, maxDistSq: number, inkAt: (index: number) => InkHit | undefined): MarkHit | undefined;
26
+ /**
27
+ * The hit test a shape's `ink` implies: the nearest of its boxes, edges
28
+ * included, so a point inside one answers it at distance 0.
29
+ */
30
+ export declare function inkHitNearest<C, P>(ink: NonNullable<MarkShape<C, P>['ink']>): NonNullable<MarkShape<C, P>['hitNearest']>;
31
+ /** A shape's own `hitNearest`, else the one its `ink` implies, else none. */
32
+ export declare function shapeHitNearest<C, P>(shape: MarkShape<C, P>): MarkShape<C, P>['hitNearest'];
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Where a rect's ink sits nearest `(xPx, yPx)`, and how far: the point itself
3
+ * where the cursor is inside, else the nearest point on the edge.
4
+ */
5
+ export function inkOnRect(xPx, yPx, left, top, width, height) {
6
+ const x = Math.min(Math.max(xPx, left), left + width);
7
+ const y = Math.min(Math.max(yPx, top), top + height);
8
+ const dx = xPx - x;
9
+ const dy = yPx - y;
10
+ return { x, y, distSq: dx * dx + dy * dy };
11
+ }
12
+ /** The same for a mark with no extent to clamp into. */
13
+ export function inkAtPoint(xPx, yPx, x, y) {
14
+ const dx = xPx - x;
15
+ const dy = yPx - y;
16
+ return { x, y, distSq: dx * dx + dy * dy };
17
+ }
18
+ /**
19
+ * The nearest of `candidates` by where each one's ink is, or undefined when
20
+ * none beats `maxDistSq`.
21
+ *
22
+ * This is the whole of every shape's `hitNearest` but the geometry: `inkAt`
23
+ * answers where instance `i` put ink and how far that is, and this keeps the
24
+ * closest. Only a STRICTLY nearer candidate replaces the best, so on a tie the
25
+ * first wins, so a caller that iterates back to front gets the mark on top.
26
+ * Five shapes used to spell that rule out separately.
27
+ *
28
+ * `inkAt` may answer `undefined` for an instance that drew nothing at all, as
29
+ * against one that drew somewhere far away: a bar clipped out of its band has
30
+ * no ink to be near.
31
+ */
32
+ export function nearestInk(candidates, maxDistSq, inkAt) {
33
+ let best;
34
+ let bestDistSq = maxDistSq;
35
+ for (const index of candidates) {
36
+ const ink = inkAt(index);
37
+ if (ink && ink.distSq < bestDistSq) {
38
+ bestDistSq = ink.distSq;
39
+ // Field by field, not `{ index, ...ink }`, which is both slower and one
40
+ // shape away from minting a hidden class per ink source and making every
41
+ // downstream `hit.x` read polymorphic.
42
+ best = { index, x: ink.x, y: ink.y, distSq: ink.distSq };
43
+ }
44
+ }
45
+ return best;
46
+ }
47
+ /**
48
+ * The hit test a shape's `ink` implies: the nearest of its boxes, edges
49
+ * included, so a point inside one answers it at distance 0.
50
+ */
51
+ export function inkHitNearest(ink) {
52
+ return (channels, block, frame, params, xPx, yPx, candidates, maxDistSq) => nearestInk(candidates, maxDistSq, i => {
53
+ const r = ink(channels, block, frame, params, i);
54
+ return r && inkOnRect(xPx, yPx, r.left, r.top, r.width, r.height);
55
+ });
56
+ }
57
+ /** A shape's own `hitNearest`, else the one its `ink` implies, else none. */
58
+ export function shapeHitNearest(shape) {
59
+ return (shape.hitNearest ??
60
+ (shape.ink ? inkHitNearest(shape.ink.bind(shape)) : undefined));
61
+ }
@@ -0,0 +1,18 @@
1
+ import type { RenderBlock } from '../renderBlock.ts';
2
+ import type { InkRect, Mark, MarkFrame } from './types.ts';
3
+ /** `r` moved by (`dx`, `dy`), its stroke with it. */
4
+ export declare function shiftInk<R extends InkRect>(r: R, dx: number, dy: number): R;
5
+ /** One instance of one mark in a display's list, as a highlight names it. */
6
+ export interface MarkInstance {
7
+ mark: number;
8
+ index: number;
9
+ }
10
+ /**
11
+ * The boxes a set of instances painted this frame: each mark's `ink` for the
12
+ * instances a display names in each region, clipped to the block's column the
13
+ * way the painter was, or to the canvas for a mark spanning the view, asked
14
+ * over `regionKeys` (the blocks' own by default). What a highlight guide
15
+ * draws, so a display says WHICH instances are lit and nothing about where
16
+ * they are.
17
+ */
18
+ export declare function inkOfInstances<TRegion, TState extends MarkFrame>(marks: readonly Mark<TRegion, TState>[], blocks: readonly RenderBlock[], regionOf: (displayedRegionIndex: number) => TRegion | undefined, state: TState, instancesOf: (displayedRegionIndex: number) => Iterable<MarkInstance> | undefined, regionKeys?: Iterable<number>): InkRect[];
@@ -0,0 +1,71 @@
1
+ import { canvasWideBlock } from '../renderBlock.js';
2
+ /** `r` moved by (`dx`, `dy`), its stroke with it. */
3
+ export function shiftInk(r, dx, dy) {
4
+ const { stroke } = r;
5
+ return {
6
+ ...r,
7
+ left: r.left + dx,
8
+ top: r.top + dy,
9
+ ...(stroke
10
+ ? {
11
+ stroke: {
12
+ ...stroke,
13
+ originX: stroke.originX + dx,
14
+ originY: stroke.originY + dy,
15
+ },
16
+ }
17
+ : {}),
18
+ };
19
+ }
20
+ function clippedTo(r, x0, x1) {
21
+ const left = Math.max(r.left, x0);
22
+ const right = Math.min(r.left + r.width, x1);
23
+ return right >= left ? { ...r, left, width: right - left } : undefined;
24
+ }
25
+ /**
26
+ * The boxes a set of instances painted this frame: each mark's `ink` for the
27
+ * instances a display names in each region, clipped to the block's column the
28
+ * way the painter was, or to the canvas for a mark spanning the view, asked
29
+ * over `regionKeys` (the blocks' own by default). What a highlight guide
30
+ * draws, so a display says WHICH instances are lit and nothing about where
31
+ * they are.
32
+ */
33
+ export function inkOfInstances(marks, blocks, regionOf, state, instancesOf, regionKeys) {
34
+ const rects = [];
35
+ for (const block of blocks) {
36
+ const region = regionOf(block.displayedRegionIndex);
37
+ const instances = region && instancesOf(block.displayedRegionIndex);
38
+ if (!instances) {
39
+ continue;
40
+ }
41
+ const x0 = Math.min(block.screenStartPx, block.screenEndPx);
42
+ const x1 = Math.max(block.screenStartPx, block.screenEndPx);
43
+ for (const { mark, index } of instances) {
44
+ const m = marks[mark];
45
+ const r = m && !m.spansView && m.ink?.(region, block, state, index);
46
+ const clipped = r && clippedTo(r, x0, x1);
47
+ if (clipped) {
48
+ rects.push(clipped);
49
+ }
50
+ }
51
+ }
52
+ if (marks.some(m => m.spansView)) {
53
+ for (const key of regionKeys ?? blocks.map(b => b.displayedRegionIndex)) {
54
+ const region = regionOf(key);
55
+ const instances = region && instancesOf(key);
56
+ if (!instances) {
57
+ continue;
58
+ }
59
+ const block = canvasWideBlock(key, state.canvasWidth);
60
+ for (const { mark, index } of instances) {
61
+ const m = marks[mark];
62
+ const r = m?.spansView && m.ink?.(region, block, state, index);
63
+ const clipped = r && clippedTo(r, 0, state.canvasWidth);
64
+ if (clipped) {
65
+ rects.push(clipped);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return rects;
71
+ }
@@ -0,0 +1,14 @@
1
+ import type { RenderBlock } from '../renderBlock.ts';
2
+ import type { Mark, MarkContext2D, MarkFrame } from './types.ts';
3
+ /**
4
+ * Paint one frame's blocks with a mark list — the Canvas2D half of a
5
+ * declaration, and the SVG export path, since `MarkContext2D` is satisfied by
6
+ * both a real 2D context and the SVG one. A mark that spans the view paints
7
+ * after the blocks, over the whole canvas, from every region in `regions`.
8
+ *
9
+ * Its own module, away from the backend that calls it: an SVG export runs with
10
+ * no backend attached at all (and must, or a headless export would depend on a
11
+ * GPU device having been probed), so the path that draws must not pull the HAL
12
+ * in behind it.
13
+ */
14
+ export declare function paintMarkBlocks<TRegion, TState extends MarkFrame>(ctx: MarkContext2D, marks: readonly Mark<TRegion, TState>[], regions: ReadonlyMap<number, TRegion>, blocks: RenderBlock[], state: TState): void;
@@ -0,0 +1,32 @@
1
+ import { forEachClippedBlock, withClip } from '../canvas2dUtils.js';
2
+ import { canvasWideBlock } from '../renderBlock.js';
3
+ /**
4
+ * Paint one frame's blocks with a mark list — the Canvas2D half of a
5
+ * declaration, and the SVG export path, since `MarkContext2D` is satisfied by
6
+ * both a real 2D context and the SVG one. A mark that spans the view paints
7
+ * after the blocks, over the whole canvas, from every region in `regions`.
8
+ *
9
+ * Its own module, away from the backend that calls it: an SVG export runs with
10
+ * no backend attached at all (and must, or a headless export would depend on a
11
+ * GPU device having been probed), so the path that draws must not pull the HAL
12
+ * in behind it.
13
+ */
14
+ export function paintMarkBlocks(ctx, marks, regions, blocks, state) {
15
+ const blockMarks = marks.filter(m => !m.spansView);
16
+ forEachClippedBlock(ctx, blocks, state.canvasWidth, state.canvasHeight, block => regions.get(block.displayedRegionIndex), (region, block) => {
17
+ for (const mark of blockMarks) {
18
+ mark.paintBlock(ctx, region, block, state);
19
+ }
20
+ });
21
+ const viewMarks = marks.filter(m => m.spansView);
22
+ if (viewMarks.length > 0) {
23
+ withClip(ctx, 0, 0, state.canvasWidth, state.canvasHeight, () => {
24
+ for (const [key, region] of regions) {
25
+ const block = canvasWideBlock(key, state.canvasWidth);
26
+ for (const mark of viewMarks) {
27
+ mark.paintBlock(ctx, region, block, state);
28
+ }
29
+ }
30
+ });
31
+ }
32
+ }
@@ -0,0 +1,25 @@
1
+ import type { Mark, MarkFrame, PlannedPass } from './types.ts';
2
+ /**
3
+ * A mark list resolved against one frame's state: the marks whose `enabled`
4
+ * said yes, in list order, and the passes they draw.
5
+ *
6
+ * `drawMarks` asks every mark's gate, lens and staged compare per block, which
7
+ * is the right shape for a display that stages its uniforms through the marks
8
+ * — and at 120 section blocks a frame it is the whole cost the pileup measured
9
+ * and declined (`benches/pileupUniformWrite.bench.ts` has the table). A
10
+ * display that writes the uniforms itself, once per section, has nothing left
11
+ * for the per-block walk to decide: `planMarks` answers the frame question
12
+ * once, `drawPlannedPasses` issues a `drawPass` per planned mark against
13
+ * whatever the caller staged, and `marks` is the painter's list.
14
+ */
15
+ export interface MarkPlan<TRegion, TState extends MarkFrame> {
16
+ readonly marks: readonly Mark<TRegion, TState>[];
17
+ readonly passes: readonly PlannedPass[];
18
+ }
19
+ /**
20
+ * Resolve which marks draw this frame. Throws for an enabled mark the plan
21
+ * form cannot carry — one with a `band` or a `paintsBlock` — since a plan
22
+ * neither scissors nor asks the block anything, and without the throw the GPU
23
+ * would draw what Canvas2D declines.
24
+ */
25
+ export declare function planMarks<TRegion, TState extends MarkFrame>(marks: readonly Mark<TRegion, TState>[], state: TState): MarkPlan<TRegion, TState>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Resolve which marks draw this frame. Throws for an enabled mark the plan
3
+ * form cannot carry — one with a `band` or a `paintsBlock` — since a plan
4
+ * neither scissors nor asks the block anything, and without the throw the GPU
5
+ * would draw what Canvas2D declines.
6
+ */
7
+ export function planMarks(marks, state) {
8
+ const enabled = [];
9
+ const passes = [];
10
+ for (const mark of marks) {
11
+ if (!mark.enabled || mark.enabled(state)) {
12
+ if (!mark.planned) {
13
+ throw new Error(`mark ${mark.pass.id} declares a band or a block gate, which a frame plan does not carry; draw it through drawMarks`);
14
+ }
15
+ enabled.push(mark);
16
+ passes.push(mark.planned);
17
+ }
18
+ }
19
+ return { marks: enabled, passes };
20
+ }
@@ -0,0 +1,72 @@
1
+ import type { MarkColorScale, MarkThreshold } from './types.ts';
2
+ /**
3
+ * A colour channel as a shape reads it: `color`, the packed ABGR the worker
4
+ * resolved — one per instance, or one number for all of them — or
5
+ * `colorValue`, the raw values a frame's {@link MarkColorScale} turns into
6
+ * colours here. A shape reading a scale declares both optional and asks
7
+ * {@link colorBits} for the GPU and {@link paintColors} for Canvas2D.
8
+ */
9
+ export interface ColorChannel {
10
+ color?: Uint32Array | number;
11
+ colorValue?: Float32Array;
12
+ /** The Canvas2D bake, memoized on the payload; nothing else writes it. */
13
+ rampBake?: RampBake;
14
+ /** A constant `color` as Canvas2D paints it, memoized as `rampBake` is. */
15
+ constantBake?: Uint32Array;
16
+ }
17
+ interface RampBake {
18
+ values: Float32Array;
19
+ scale: MarkColorScale;
20
+ colors: Uint32Array;
21
+ }
22
+ /** Whether a colour scale is a threshold rather than a ramp. */
23
+ export declare function isThreshold(scale: MarkColorScale): scale is MarkThreshold;
24
+ type Rgba = [number, number, number, number];
25
+ type Bands = [Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba];
26
+ /**
27
+ * `markColor.slang`'s uniforms for a frame's colour scale, or for none: the
28
+ * mode, a ramp's domain and middle, and a threshold's cuts and band colours.
29
+ * Every valued shape's uniform block carries the set.
30
+ */
31
+ export declare function rampUniforms(scale: MarkColorScale | undefined): {
32
+ rampMode: number;
33
+ rampMin: number;
34
+ rampMax: number;
35
+ rampMidNorm: number;
36
+ colorCutCount: number;
37
+ colorCuts: [Rgba, Rgba];
38
+ colorBands: Bands;
39
+ };
40
+ /**
41
+ * The 4-byte instance lane, for the packer. Under a scale it is the value's
42
+ * float32 bits viewed as the `uint` the attribute declares — the reinterpret
43
+ * `markColor.slang`'s `asfloat` undoes, and the reason a quantitative colour
44
+ * adds no lane. A constant colour fills a lane for the pack alone, which the
45
+ * payload never holds.
46
+ */
47
+ export declare function colorBits(c: ColorChannel, count: number): ArrayLike<number>;
48
+ /** Instance `i`'s `color` alone, as a one-instance channel carries it. */
49
+ export declare function instanceColor(color: ColorChannel['color'], i: number): number | Uint32Array<ArrayBufferLike> | undefined;
50
+ /** A value lane's float32 values viewed as their bits. */
51
+ export declare function rampValueBits(values: Float32Array): Uint32Array<ArrayBufferLike>;
52
+ /**
53
+ * A value lane's values kept where `keep` says, copied as bits: a JS number
54
+ * read out of the lane may lose the payload `RAMP_NO_VALUE_BITS` marks a
55
+ * feature with no value by.
56
+ */
57
+ export declare function keepRampValues(values: Float32Array, keep: (value: number, index: number) => boolean): Float32Array<ArrayBuffer>;
58
+ /**
59
+ * The interval a value is in on a threshold: how many of the ascending cuts it
60
+ * is at or past, `thresholdIndex`'s rule and the shader's `thresholdBand`.
61
+ */
62
+ export declare function thresholdBandOf(value: number, cuts: readonly number[]): number;
63
+ /**
64
+ * The packed colours a painter fills with. Under a scale the values are baked
65
+ * against it once and kept on the payload, so a repaint at an unchanged scale
66
+ * — every pan and every hover — walks no values and the painters' fill
67
+ * batching still sees runs of one colour. The bake reruns when the domain, the
68
+ * scale type, the ramp's bytes or a threshold's cuts or colours move. A
69
+ * constant colour expands once and is kept the same way.
70
+ */
71
+ export declare function paintColors(c: ColorChannel, count: number, scale: MarkColorScale | undefined): ArrayLike<number>;
72
+ export {};