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

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 (353) hide show
  1. package/esm/RenderCanvas.d.ts +3 -3
  2. package/esm/RenderCanvas.js +1 -1
  3. package/esm/RenderLifecycleMixin.d.ts +52 -20
  4. package/esm/RenderLifecycleMixin.js +89 -23
  5. package/esm/canvas2dUtils.d.ts +90 -23
  6. package/esm/canvas2dUtils.js +120 -37
  7. package/esm/colorRampLut.d.ts +5 -5
  8. package/esm/colorRampLut.js +6 -6
  9. package/esm/computePipeline.d.ts +14 -0
  10. package/esm/computePipeline.js +62 -0
  11. package/esm/contractReports.d.ts +54 -0
  12. package/esm/contractReports.js +112 -0
  13. package/esm/coverageBand.d.ts +13 -8
  14. package/esm/coverageBand.js +15 -5
  15. package/esm/coverageBandBuffers.d.ts +2 -9
  16. package/esm/coverageBandBuffers.js +1 -13
  17. package/esm/createRenderingBackend.d.ts +16 -20
  18. package/esm/createRenderingBackend.js +6 -4
  19. package/esm/displayPhase.d.ts +83 -104
  20. package/esm/displayPhase.js +42 -82
  21. package/esm/encodeMemo.d.ts +14 -0
  22. package/esm/encodeMemo.js +48 -0
  23. package/esm/gpuContextLostError.d.ts +30 -0
  24. package/esm/gpuContextLostError.js +40 -0
  25. package/esm/gpuDevice.d.ts +29 -10
  26. package/esm/gpuDevice.js +35 -16
  27. package/esm/graphicsCapabilities.d.ts +27 -19
  28. package/esm/graphicsCapabilities.js +41 -19
  29. package/esm/hal/createHal.d.ts +4 -5
  30. package/esm/hal/createHal.js +15 -5
  31. package/esm/hal/deviceGpuCache.d.ts +25 -30
  32. package/esm/hal/deviceGpuCache.js +85 -97
  33. package/esm/hal/gpuHalBase.d.ts +5 -4
  34. package/esm/hal/gpuHalBase.js +25 -14
  35. package/esm/hal/index.d.ts +2 -2
  36. package/esm/hal/index.js +1 -1
  37. package/esm/hal/mockHal.d.ts +15 -10
  38. package/esm/hal/mockHal.js +31 -18
  39. package/esm/hal/oomReporter.d.ts +7 -0
  40. package/esm/hal/oomReporter.js +10 -0
  41. package/esm/hal/passIds.d.ts +8 -7
  42. package/esm/hal/passIds.js +11 -10
  43. package/esm/hal/regionRegistry.d.ts +0 -1
  44. package/esm/hal/regionRegistry.js +3 -15
  45. package/esm/hal/types.d.ts +53 -18
  46. package/esm/hal/webgl2Hal.d.ts +23 -6
  47. package/esm/hal/webgl2Hal.js +158 -155
  48. package/esm/hal/webgpuHal.d.ts +29 -13
  49. package/esm/hal/webgpuHal.js +220 -153
  50. package/esm/installUpload.d.ts +16 -3
  51. package/esm/installUpload.js +13 -41
  52. package/esm/instanceCache.d.ts +10 -7
  53. package/esm/instanceCache.js +14 -15
  54. package/esm/instancePass.d.ts +2 -1
  55. package/esm/mapUploadSync.d.ts +2 -10
  56. package/esm/mapUploadSync.js +2 -3
  57. package/esm/marks/barMark.d.ts +30 -0
  58. package/esm/marks/barMark.js +149 -0
  59. package/esm/marks/colorFill.d.ts +17 -0
  60. package/esm/marks/colorFill.js +26 -0
  61. package/esm/marks/drawAgainstHit.d.ts +113 -0
  62. package/esm/marks/drawAgainstHit.js +407 -0
  63. package/esm/marks/ellipseDistance.d.ts +10 -0
  64. package/esm/marks/ellipseDistance.js +136 -0
  65. package/esm/marks/glyphPaint.d.ts +36 -0
  66. package/esm/marks/glyphPaint.js +77 -0
  67. package/esm/marks/index.d.ts +33 -0
  68. package/esm/marks/index.js +20 -0
  69. package/esm/marks/lineMark.d.ts +37 -0
  70. package/esm/marks/lineMark.js +416 -0
  71. package/esm/marks/linkMark.d.ts +76 -0
  72. package/esm/marks/linkMark.js +585 -0
  73. package/esm/marks/markBackend.d.ts +118 -0
  74. package/esm/marks/markBackend.js +196 -0
  75. package/esm/marks/markHit.d.ts +32 -0
  76. package/esm/marks/markHit.js +61 -0
  77. package/esm/marks/markInk.d.ts +18 -0
  78. package/esm/marks/markInk.js +71 -0
  79. package/esm/marks/markPaint.d.ts +14 -0
  80. package/esm/marks/markPaint.js +32 -0
  81. package/esm/marks/markPlan.d.ts +25 -0
  82. package/esm/marks/markPlan.js +20 -0
  83. package/esm/marks/markRamp.d.ts +74 -0
  84. package/esm/marks/markRamp.js +205 -0
  85. package/esm/marks/nearestMarkHit.d.ts +55 -0
  86. package/esm/marks/nearestMarkHit.js +158 -0
  87. package/esm/marks/pathRecorder.d.ts +14 -0
  88. package/esm/marks/pathRecorder.js +80 -0
  89. package/esm/marks/pointMark.d.ts +42 -0
  90. package/esm/marks/pointMark.js +125 -0
  91. package/esm/marks/rowLane.d.ts +39 -0
  92. package/esm/marks/rowLane.js +41 -0
  93. package/esm/marks/rowSpanIndex.d.ts +30 -0
  94. package/esm/marks/rowSpanIndex.js +151 -0
  95. package/esm/marks/rowTable.d.ts +41 -0
  96. package/esm/marks/rowTable.js +75 -0
  97. package/esm/marks/ruleMark.d.ts +21 -0
  98. package/esm/marks/ruleMark.js +91 -0
  99. package/esm/marks/spanMark.d.ts +42 -0
  100. package/esm/marks/spanMark.js +81 -0
  101. package/esm/marks/types.d.ts +261 -0
  102. package/esm/marks/types.js +175 -0
  103. package/esm/marks/valueScale.d.ts +23 -0
  104. package/esm/marks/valueScale.js +11 -0
  105. package/esm/namedReactions.d.ts +3 -4
  106. package/esm/namedReactions.js +3 -4
  107. package/esm/perRegionRenderingBackend.d.ts +21 -3
  108. package/esm/perRegionRenderingBackend.js +37 -3
  109. package/esm/regionDataMap.d.ts +2 -2
  110. package/esm/regionDataMap.js +25 -23
  111. package/esm/renderBlock.d.ts +14 -0
  112. package/esm/renderBlock.js +25 -0
  113. package/esm/renderingBackendBase.d.ts +20 -14
  114. package/esm/renderingBackendBase.js +12 -7
  115. package/esm/scoreScale.d.ts +27 -0
  116. package/esm/scoreScale.js +88 -0
  117. package/esm/shaders/barMark.generated.d.ts +3 -0
  118. package/esm/shaders/barMark.generated.js +7 -0
  119. package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
  120. package/esm/shaders/barMark.glsl.generated.js +4 -0
  121. package/esm/shaders/barMark.iface.generated.d.ts +90 -0
  122. package/esm/shaders/barMark.iface.generated.js +205 -0
  123. package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
  124. package/esm/shaders/barMark.wgsl.generated.js +3 -0
  125. package/esm/shaders/capsule.js.generated.d.ts +1 -0
  126. package/esm/shaders/capsule.js.generated.js +11 -0
  127. package/esm/shaders/clipStrip.generated.d.ts +2 -0
  128. package/esm/shaders/clipStrip.generated.js +4 -0
  129. package/esm/shaders/clipStrip.js.generated.d.ts +1 -0
  130. package/esm/shaders/clipStrip.js.generated.js +21 -0
  131. package/esm/shaders/colorRampLut.js.generated.d.ts +1 -0
  132. package/esm/shaders/colorRampLut.js.generated.js +17 -0
  133. package/esm/shaders/coverageBar.generated.d.ts +2 -3
  134. package/esm/shaders/coverageBar.generated.js +4 -3
  135. package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
  136. package/esm/shaders/coverageBar.glsl.generated.js +4 -0
  137. package/esm/shaders/coverageBar.iface.generated.js +1 -1
  138. package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
  139. package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
  140. package/esm/shaders/coverageClip.generated.d.ts +3 -0
  141. package/esm/shaders/coverageClip.generated.js +7 -0
  142. package/esm/shaders/coverageClip.glsl.generated.d.ts +2 -0
  143. package/esm/shaders/coverageClip.glsl.generated.js +4 -0
  144. package/esm/shaders/coverageClip.iface.generated.d.ts +85 -0
  145. package/esm/shaders/coverageClip.iface.generated.js +114 -0
  146. package/esm/shaders/coverageClip.wgsl.generated.d.ts +1 -0
  147. package/esm/shaders/coverageClip.wgsl.generated.js +3 -0
  148. package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
  149. package/esm/shaders/coverageIndicator.generated.js +4 -3
  150. package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
  151. package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
  152. package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
  153. package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
  154. package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
  155. package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
  156. package/esm/shaders/coverageInterbase.generated.js +4 -3
  157. package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
  158. package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
  159. package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
  160. package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
  161. package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
  162. package/esm/shaders/coverageMod.generated.d.ts +2 -3
  163. package/esm/shaders/coverageMod.generated.js +4 -3
  164. package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
  165. package/esm/shaders/coverageMod.glsl.generated.js +4 -0
  166. package/esm/shaders/coverageMod.iface.generated.js +1 -1
  167. package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
  168. package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
  169. package/esm/shaders/coverageSnp.generated.d.ts +2 -3
  170. package/esm/shaders/coverageSnp.generated.js +4 -3
  171. package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
  172. package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
  173. package/esm/shaders/coverageSnp.iface.generated.js +1 -1
  174. package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
  175. package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
  176. package/esm/shaders/curveDistance.js.generated.d.ts +5 -0
  177. package/esm/shaders/curveDistance.js.generated.js +87 -0
  178. package/esm/shaders/hpmath.js.generated.d.ts +2 -1
  179. package/esm/shaders/hpmath.js.generated.js +5 -2
  180. package/esm/shaders/lineCenterMark.generated.d.ts +3 -0
  181. package/esm/shaders/lineCenterMark.generated.js +7 -0
  182. package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -0
  183. package/esm/shaders/lineCenterMark.glsl.generated.js +4 -0
  184. package/esm/shaders/lineCenterMark.iface.generated.d.ts +104 -0
  185. package/esm/shaders/lineCenterMark.iface.generated.js +237 -0
  186. package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -0
  187. package/esm/shaders/lineCenterMark.wgsl.generated.js +3 -0
  188. package/esm/shaders/lineCommon.generated.d.ts +2 -0
  189. package/esm/shaders/lineCommon.generated.js +4 -0
  190. package/esm/shaders/lineStepMark.generated.d.ts +3 -0
  191. package/esm/shaders/lineStepMark.generated.js +7 -0
  192. package/esm/shaders/lineStepMark.glsl.generated.d.ts +2 -0
  193. package/esm/shaders/lineStepMark.glsl.generated.js +4 -0
  194. package/esm/shaders/lineStepMark.iface.generated.d.ts +98 -0
  195. package/esm/shaders/lineStepMark.iface.generated.js +225 -0
  196. package/esm/shaders/lineStepMark.wgsl.generated.d.ts +1 -0
  197. package/esm/shaders/lineStepMark.wgsl.generated.js +3 -0
  198. package/esm/shaders/linkMark.consts.generated.d.ts +14 -0
  199. package/esm/shaders/linkMark.consts.generated.js +16 -0
  200. package/esm/shaders/linkMark.generated.d.ts +4 -0
  201. package/esm/shaders/linkMark.generated.js +8 -0
  202. package/esm/shaders/linkMark.glsl.generated.d.ts +2 -0
  203. package/esm/shaders/linkMark.glsl.generated.js +4 -0
  204. package/esm/shaders/linkMark.iface.generated.d.ts +142 -0
  205. package/esm/shaders/linkMark.iface.generated.js +1829 -0
  206. package/esm/shaders/linkMark.js.generated.d.ts +7 -0
  207. package/esm/shaders/linkMark.js.generated.js +159 -0
  208. package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -0
  209. package/esm/shaders/linkMark.wgsl.generated.js +3 -0
  210. package/esm/shaders/markColor.generated.d.ts +9 -0
  211. package/esm/shaders/markColor.generated.js +11 -0
  212. package/esm/shaders/pointGlyph.js.generated.d.ts +2 -0
  213. package/esm/shaders/pointGlyph.js.generated.js +15 -0
  214. package/esm/shaders/pointMark.consts.generated.d.ts +7 -0
  215. package/esm/shaders/pointMark.consts.generated.js +9 -0
  216. package/esm/shaders/pointMark.generated.d.ts +4 -0
  217. package/esm/shaders/pointMark.generated.js +8 -0
  218. package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
  219. package/esm/shaders/pointMark.glsl.generated.js +4 -0
  220. package/esm/shaders/pointMark.iface.generated.d.ts +98 -0
  221. package/esm/shaders/pointMark.iface.generated.js +219 -0
  222. package/esm/shaders/pointMark.js.generated.d.ts +3 -0
  223. package/esm/shaders/pointMark.js.generated.js +93 -0
  224. package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
  225. package/esm/shaders/pointMark.wgsl.generated.js +3 -0
  226. package/esm/shaders/rowRect.generated.d.ts +0 -1
  227. package/esm/shaders/rowRect.generated.js +0 -1
  228. package/esm/shaders/rowTable.generated.d.ts +1 -0
  229. package/esm/shaders/rowTable.generated.js +3 -0
  230. package/esm/shaders/rowTable.js.generated.d.ts +5 -0
  231. package/esm/shaders/rowTable.js.generated.js +29 -0
  232. package/esm/shaders/scoreScale.generated.d.ts +2 -0
  233. package/esm/shaders/scoreScale.generated.js +4 -0
  234. package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
  235. package/esm/shaders/scoreScale.js.generated.js +50 -23
  236. package/esm/shaders/spanMark.generated.d.ts +3 -0
  237. package/esm/shaders/spanMark.generated.js +7 -0
  238. package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
  239. package/esm/shaders/spanMark.glsl.generated.js +4 -0
  240. package/esm/shaders/spanMark.iface.generated.d.ts +81 -0
  241. package/esm/shaders/spanMark.iface.generated.js +215 -0
  242. package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
  243. package/esm/shaders/spanMark.wgsl.generated.js +3 -0
  244. package/esm/sharedBackendKey.d.ts +18 -0
  245. package/esm/{keyedRenderingBackend.js → sharedBackendKey.js} +5 -0
  246. package/esm/slangPass.d.ts +17 -11
  247. package/esm/slangPass.js +12 -4
  248. package/esm/useGraphicsCapabilities.d.ts +1 -1
  249. package/esm/useGraphicsCapabilities.js +1 -1
  250. package/esm/useRenderingBackend.d.ts +13 -13
  251. package/esm/useRenderingBackend.js +58 -20
  252. package/esm/webgpuUtils.d.ts +3 -11
  253. package/esm/webgpuUtils.js +12 -33
  254. package/package.json +32 -7
  255. package/src/shaders/antialias.slang +46 -0
  256. package/src/shaders/arcHull.test.ts +267 -0
  257. package/src/shaders/barMark.generated.ts +11 -0
  258. package/src/shaders/barMark.glsl.generated.ts +6 -0
  259. package/src/shaders/barMark.iface.generated.ts +285 -0
  260. package/src/shaders/barMark.slang +167 -0
  261. package/src/shaders/barMark.wgsl.generated.ts +4 -0
  262. package/src/shaders/capsule.js.generated.ts +14 -0
  263. package/src/shaders/capsule.slang +13 -5
  264. package/src/shaders/clipStrip.generated.ts +6 -0
  265. package/src/shaders/clipStrip.js.generated.ts +22 -0
  266. package/src/shaders/clipStrip.slang +34 -0
  267. package/src/shaders/clipStrip.test.ts +39 -0
  268. package/src/shaders/colorPack.slang +5 -1
  269. package/src/shaders/colorRampLut.js.generated.ts +22 -0
  270. package/src/shaders/colorRampLut.slang +15 -1
  271. package/src/shaders/coverageBand.slang +64 -32
  272. package/src/shaders/coverageBar.generated.ts +6 -5
  273. package/src/shaders/coverageBar.glsl.generated.ts +6 -0
  274. package/src/shaders/coverageBar.iface.generated.ts +1 -1
  275. package/src/shaders/coverageBar.slang +10 -10
  276. package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
  277. package/src/shaders/coverageClip.generated.ts +11 -0
  278. package/src/shaders/coverageClip.glsl.generated.ts +6 -0
  279. package/src/shaders/coverageClip.iface.generated.ts +172 -0
  280. package/src/shaders/coverageClip.slang +38 -0
  281. package/src/shaders/coverageClip.wgsl.generated.ts +4 -0
  282. package/src/shaders/coverageIndicator.generated.ts +6 -5
  283. package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
  284. package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
  285. package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
  286. package/src/shaders/coverageInterbase.generated.ts +6 -5
  287. package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
  288. package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
  289. package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
  290. package/src/shaders/coverageMod.generated.ts +6 -5
  291. package/src/shaders/coverageMod.glsl.generated.ts +6 -0
  292. package/src/shaders/coverageMod.iface.generated.ts +1 -1
  293. package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
  294. package/src/shaders/coverageSnp.generated.ts +6 -5
  295. package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
  296. package/src/shaders/coverageSnp.iface.generated.ts +1 -1
  297. package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
  298. package/src/shaders/curveDistance.js.generated.ts +91 -0
  299. package/src/shaders/curveDistance.slang +265 -0
  300. package/src/shaders/hpClampFloor.test.ts +87 -0
  301. package/src/shaders/hpmath.js.generated.ts +6 -2
  302. package/src/shaders/hpmath.slang +100 -48
  303. package/src/shaders/insetValueScale.test.ts +67 -0
  304. package/src/shaders/lineCenterMark.generated.ts +11 -0
  305. package/src/shaders/lineCenterMark.glsl.generated.ts +6 -0
  306. package/src/shaders/lineCenterMark.iface.generated.ts +328 -0
  307. package/src/shaders/lineCenterMark.slang +127 -0
  308. package/src/shaders/lineCenterMark.wgsl.generated.ts +4 -0
  309. package/src/shaders/lineCommon.generated.ts +6 -0
  310. package/src/shaders/lineCommon.slang +102 -0
  311. package/src/shaders/lineStepMark.generated.ts +11 -0
  312. package/src/shaders/lineStepMark.glsl.generated.ts +6 -0
  313. package/src/shaders/lineStepMark.iface.generated.ts +311 -0
  314. package/src/shaders/lineStepMark.slang +125 -0
  315. package/src/shaders/lineStepMark.wgsl.generated.ts +4 -0
  316. package/src/shaders/linkMark.consts.generated.ts +30 -0
  317. package/src/shaders/linkMark.generated.ts +12 -0
  318. package/src/shaders/linkMark.glsl.generated.ts +6 -0
  319. package/src/shaders/linkMark.iface.generated.ts +1954 -0
  320. package/src/shaders/linkMark.js.generated.ts +167 -0
  321. package/src/shaders/linkMark.slang +439 -0
  322. package/src/shaders/linkMark.wgsl.generated.ts +4 -0
  323. package/src/shaders/markColor.generated.ts +20 -0
  324. package/src/shaders/markColor.slang +128 -0
  325. package/src/shaders/pointGlyph.js.generated.ts +20 -0
  326. package/src/shaders/pointGlyph.slang +23 -7
  327. package/src/shaders/pointGlyphPad.test.ts +242 -0
  328. package/src/shaders/pointMark.consts.generated.ts +16 -0
  329. package/src/shaders/pointMark.generated.ts +12 -0
  330. package/src/shaders/pointMark.glsl.generated.ts +6 -0
  331. package/src/shaders/pointMark.iface.generated.ts +304 -0
  332. package/src/shaders/pointMark.js.generated.ts +99 -0
  333. package/src/shaders/pointMark.slang +227 -0
  334. package/src/shaders/pointMark.wgsl.generated.ts +4 -0
  335. package/src/shaders/rowRect.generated.ts +0 -2
  336. package/src/shaders/rowRect.slang +39 -58
  337. package/src/shaders/rowTable.generated.ts +4 -0
  338. package/src/shaders/rowTable.js.generated.ts +37 -0
  339. package/src/shaders/rowTable.slang +98 -0
  340. package/src/shaders/scoreScale.generated.ts +6 -0
  341. package/src/shaders/scoreScale.js.generated.ts +48 -23
  342. package/src/shaders/scoreScale.slang +49 -55
  343. package/src/shaders/sdEllipse.test.ts +211 -0
  344. package/src/shaders/spanMark.generated.ts +11 -0
  345. package/src/shaders/spanMark.glsl.generated.ts +6 -0
  346. package/src/shaders/spanMark.iface.generated.ts +289 -0
  347. package/src/shaders/spanMark.slang +77 -0
  348. package/src/shaders/spanMark.wgsl.generated.ts +4 -0
  349. package/src/shaders/valueScale.slang +26 -0
  350. package/src/shaders/wideCircleLeg.test.ts +85 -0
  351. package/esm/globalRenderingBackend.d.ts +0 -90
  352. package/esm/globalRenderingBackend.js +0 -53
  353. package/esm/keyedRenderingBackend.d.ts +0 -41
@@ -25,7 +25,7 @@ export interface RenderCanvasHandle {
25
25
  * render-prop body on the same value for the displays on the chrome, which it
26
26
  * does *not* get for free from the `renderError` unmount (that covers only a
27
27
  * reported loss — see the `canvasKey` note in useRenderingBackend.ts).
28
- * GPU_RENDERING.md said so and ended with "any new consumer rendering its own
28
+ * GPU_DISPLAY_LIFECYCLE.md said so and ended with "any new consumer rendering its own
29
29
  * banner must too" — a rule enforced by remembering to read the doc. Rendering
30
30
  * the element here makes it structural instead: there is no way to mount this
31
31
  * canvas without the key.
@@ -47,11 +47,11 @@ export default function RenderCanvas({ handle, drawn, phase, ...canvasProps }: {
47
47
  /**
48
48
  * Whether this canvas holds finished content — each view's own `settled`, the
49
49
  * same flag its `*_canvas_done` testid is built from. Published as
50
- * `data-display-drawn`, which is what `PENDING_DISPLAYS`
50
+ * `data-display-drawn`, the attribute `PENDING_DISPLAYS`
51
51
  * (`@jbrowse/browser-test-utils`) selects on, so these views answer "has
52
52
  * everything painted?" with the same attribute every LGV display does.
53
53
  *
54
- * Required, and that is the point: `PENDING_DISPLAYS` used to name
54
+ * The prop is required because `PENDING_DISPLAYS` used to name
55
55
  * `synteny_canvas` explicitly and simply **forgot dotplot**, so an unpainted
56
56
  * dotplot counted as finished and a capture could land on it blank. A new
57
57
  * drop-to-primitive view would have been forgotten the same way.
@@ -16,7 +16,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
16
  * render-prop body on the same value for the displays on the chrome, which it
17
17
  * does *not* get for free from the `renderError` unmount (that covers only a
18
18
  * reported loss — see the `canvasKey` note in useRenderingBackend.ts).
19
- * GPU_RENDERING.md said so and ended with "any new consumer rendering its own
19
+ * GPU_DISPLAY_LIFECYCLE.md said so and ended with "any new consumer rendering its own
20
20
  * banner must too" — a rule enforced by remembering to read the doc. Rendering
21
21
  * the element here makes it structural instead: there is no way to mount this
22
22
  * canvas without the key.
@@ -25,6 +25,13 @@ export interface RenderingBackendCallbacks<B> {
25
25
  * depend on.
26
26
  */
27
27
  render: (backend: B) => boolean;
28
+ /**
29
+ * Hand back whatever the backend allocated for a canvas that is no longer on
30
+ * the page. Called after every render tick while the display is off screen,
31
+ * drawn or not, so it has to be idempotent and must not leave the backend
32
+ * unable to draw the next frame.
33
+ */
34
+ releaseTargets: (backend: B) => void;
28
35
  }
29
36
  /**
30
37
  * Owns the GPU draw lifecycle for any display that paints to a canvas.
@@ -45,9 +52,9 @@ export interface RenderingBackendCallbacks<B> {
45
52
  * recovery. Autoruns read it each tick so they re-fire against the new
46
53
  * one without being reinstalled.
47
54
  * - `renderTick` — counter the render autorun observes; bumped by
48
- * `renderNow()` (tab-visibility restore) and after every upload
49
- * (ensures render re-fires when an upload happens but renderState
50
- * identity stays stable).
55
+ * `renderNow()` after every upload that reached the backend, on
56
+ * tab-visibility restore, and when a circular ring backend starts. None of
57
+ * those is a pan or zoom, so off screen a moved tick means new data.
51
58
  * - `autorunsInstalled` — guards `attachRenderingBackend` so the autorun
52
59
  * pair is spawned once per model instance, not once per backend
53
60
  * assignment.
@@ -64,10 +71,12 @@ export interface RenderingBackendCallbacks<B> {
64
71
  */
65
72
  export declare function RenderLifecycleMixin(): import("@jbrowse/mobx-state-tree").IModelType<{}, {
66
73
  canvasDrawn: boolean;
74
+ paintCount: number;
67
75
  currentRenderingBackend: unknown;
68
76
  renderTick: number;
69
77
  autorunsInstalled: boolean;
70
78
  renderError: unknown;
79
+ offScreen: boolean;
71
80
  } & {
72
81
  /**
73
82
  * #getter
@@ -95,22 +104,21 @@ export declare function RenderLifecycleMixin(): import("@jbrowse/mobx-state-tree
95
104
  * never called and `canvasDrawn` can never flip).
96
105
  *
97
106
  * Lives here, beside `canvasDrawn`, because every consumer of "has this
98
- * display painted" needs the pair — and until 2026-08 each family
99
- * declared its own copy (per-region hard-coded `true`, global carried the
100
- * hook for LD), so a display could express the state only to whichever
101
- * family it happened to compose. See `painted` below for the reader that
102
- * was missed.
107
+ * display painted" needs the pair. Both LGV fetch foundations fill it
108
+ * with `!fetchInert`, so a display there states its placeholder once,
109
+ * through that hook; the raw default reaches only a display composing
110
+ * this mixin outside them. See `painted` below for the reader that was
111
+ * missed while the two were separate overrides.
103
112
  */
104
113
  readonly rendersCanvas: boolean;
105
114
  /**
106
115
  * #getter
107
116
  * Overridable hook (default false): the display has reached a state it
108
117
  * will not paint its way out of, so `painted` below should answer
109
- * *finished* rather than *pending*. Both LGV fetch families fill it with
110
- * `!!error` — a fetch that failed before first paint keeps its canvas
111
- * mounted, since the error bar is an overlay rather than a subtree
112
- * replacement, so nothing ever draws into it. Named for `fetchInert` on
113
- * the comparative side.
118
+ * *finished* rather than *pending*. Both LGV fetch families fill it
119
+ * through `foundationPaintInert`: a failed fetch, a standing cancel, no
120
+ * content on screen, or the too-large banner in the canvas's place. Named
121
+ * for `fetchInert` on the comparative side.
114
122
  *
115
123
  * A hook rather than a read of `error` here, for two reasons that both
116
124
  * bite: this package is a leaf and `error` belongs to the fetch mixins,
@@ -119,13 +127,30 @@ export declare function RenderLifecycleMixin(): import("@jbrowse/mobx-state-tree
119
127
  * and the two families compose the two mixins in opposite orders.
120
128
  */
121
129
  readonly paintInert: boolean;
130
+ /**
131
+ * #getter
132
+ * Overridable hook (default false): what is on the canvas was painted
133
+ * from data a later change has made wrong, so `painted` below should
134
+ * answer *pending* until the repaint lands even though `canvasDrawn` is
135
+ * still true. The per-region fetch foundation fills it with
136
+ * `staleSettingsDrawn` — held data drawn under settings that have since
137
+ * moved — which is the state `clearAllRpcData` used to express by
138
+ * resetting `canvasDrawn` on every settings change, blanking the display
139
+ * to do it. A capture waiting on `data-display-drawn` then waits for the
140
+ * refetch rather than snapshotting the previous setting's pixels.
141
+ *
142
+ * A hook and not a reset of the flag, because the flag is re-marked by
143
+ * any redraw — a pan between the settings change and the refetch would
144
+ * report the stale canvas drawn — and a derivation cannot be raced.
145
+ */
146
+ readonly paintSuperseded: boolean;
122
147
  } & {
123
148
  /**
124
149
  * #getter
125
150
  * **The first-paint answer every consumer outside the display should
126
151
  * read**, `canvasDrawn` being only the raw flag: a display that is
127
- * deliberately not painting a canvas has finished, and saying otherwise
128
- * is a lie that never resolves.
152
+ * deliberately not painting a canvas has finished, and reporting it
153
+ * unfinished leaves every waiter on it waiting forever.
129
154
  *
130
155
  * The two `rendersCanvas: false` states each had three of their four
131
156
  * consumers wired by hand — the loading scrim (`rendersCanvas` /
@@ -133,14 +158,17 @@ export declare function RenderLifecycleMixin(): import("@jbrowse/mobx-state-tree
133
158
  * while the fourth, `data-display-drawn`, went on publishing `"false"`
134
159
  * forever off the raw flag. That attribute is what `PENDING_DISPLAYS`
135
160
  * (`@jbrowse/browser-test-utils`) selects on, so a zoomed-out reference
136
- * sequence track made every `waitForDisplaysDone` on the page burn its
137
- * full timeout — silently, since that wait swallows its own. Same shape
138
- * as `fetchInert` on the comparative side: the reader you forget is the
139
- * one outside the display, so the display has to publish one name for it.
161
+ * sequence track made every capture wait on the page run to its
162
+ * full timeout, and that wait swallows its own timeout without reporting
163
+ * it. `fetchInert` on the comparative side has the same problem: the
164
+ * forgotten reader is the one outside the display, so the display has to
165
+ * publish one name for it.
140
166
  *
141
167
  * `paintInert` is the third term and the same argument once more, for the
142
168
  * state where a display *would* paint a canvas and never gets to — a fetch
143
- * that failed before first paint. See that hook.
169
+ * that failed before first paint. `paintSuperseded` is the fourth, and
170
+ * the one that subtracts: a canvas painted from data a settings change
171
+ * has made wrong is drawn and not finished. See both hooks.
144
172
  */
145
173
  readonly painted: boolean;
146
174
  } & {
@@ -160,6 +188,10 @@ export declare function RenderLifecycleMixin(): import("@jbrowse/mobx-state-tree
160
188
  * #action
161
189
  */
162
190
  renderNow(): void;
191
+ /**
192
+ * #action
193
+ */
194
+ setOffScreen(offScreen: boolean): void;
163
195
  /**
164
196
  * #action
165
197
  * set/clear the render-backend error. Called by `useRenderingBackend`:
@@ -19,9 +19,9 @@ import { namedAutorun } from './namedReactions.js';
19
19
  * recovery. Autoruns read it each tick so they re-fire against the new
20
20
  * one without being reinstalled.
21
21
  * - `renderTick` — counter the render autorun observes; bumped by
22
- * `renderNow()` (tab-visibility restore) and after every upload
23
- * (ensures render re-fires when an upload happens but renderState
24
- * identity stays stable).
22
+ * `renderNow()` after every upload that reached the backend, on
23
+ * tab-visibility restore, and when a circular ring backend starts. None of
24
+ * those is a pan or zoom, so off screen a moved tick means new data.
25
25
  * - `autorunsInstalled` — guards `attachRenderingBackend` so the autorun
26
26
  * pair is spawned once per model instance, not once per backend
27
27
  * assignment.
@@ -45,6 +45,13 @@ export function RenderLifecycleMixin() {
45
45
  * flips true on first paint; read by test selectors to detect render
46
46
  */
47
47
  canvasDrawn: false,
48
+ /**
49
+ * #volatile
50
+ * bumped after every frame the backend painted, so a consumer that
51
+ * reads this display's canvas — the circular view's ring, which copies
52
+ * the strip into a texture — knows when the pixels moved
53
+ */
54
+ paintCount: 0,
48
55
  /**
49
56
  * #volatile
50
57
  * current backend reference, updated on context-loss recovery.
@@ -74,6 +81,22 @@ export function RenderLifecycleMixin() {
74
81
  * the scrim) and by `DisplayChrome` (shows the retry overlay).
75
82
  */
76
83
  renderError: undefined,
84
+ /**
85
+ * #volatile
86
+ * the display's canvas has scrolled out of the page, so the render
87
+ * autorun skips pan and zoom redraws, still draws new data, and hands its
88
+ * GPU targets back after every tick. Written
89
+ * by `useRenderingBackend`, which watches the canvas element itself —
90
+ * false everywhere `IntersectionObserver` is absent, which is every unit
91
+ * test and every non-browser host.
92
+ *
93
+ * A whole view that scrolls away is already unmounted
94
+ * (`useViewVisibility`) and a minimized track never mounts, so what this
95
+ * covers is the track below the fold of a view that IS mounted: the
96
+ * display list is not windowed, and each of those tracks holds a
97
+ * full-height multisampled target.
98
+ */
99
+ offScreen: false,
77
100
  }))
78
101
  .views(() => ({
79
102
  /**
@@ -104,11 +127,11 @@ export function RenderLifecycleMixin() {
104
127
  * never called and `canvasDrawn` can never flip).
105
128
  *
106
129
  * Lives here, beside `canvasDrawn`, because every consumer of "has this
107
- * display painted" needs the pair — and until 2026-08 each family
108
- * declared its own copy (per-region hard-coded `true`, global carried the
109
- * hook for LD), so a display could express the state only to whichever
110
- * family it happened to compose. See `painted` below for the reader that
111
- * was missed.
130
+ * display painted" needs the pair. Both LGV fetch foundations fill it
131
+ * with `!fetchInert`, so a display there states its placeholder once,
132
+ * through that hook; the raw default reaches only a display composing
133
+ * this mixin outside them. See `painted` below for the reader that was
134
+ * missed while the two were separate overrides.
112
135
  */
113
136
  get rendersCanvas() {
114
137
  return true;
@@ -117,11 +140,10 @@ export function RenderLifecycleMixin() {
117
140
  * #getter
118
141
  * Overridable hook (default false): the display has reached a state it
119
142
  * will not paint its way out of, so `painted` below should answer
120
- * *finished* rather than *pending*. Both LGV fetch families fill it with
121
- * `!!error` — a fetch that failed before first paint keeps its canvas
122
- * mounted, since the error bar is an overlay rather than a subtree
123
- * replacement, so nothing ever draws into it. Named for `fetchInert` on
124
- * the comparative side.
143
+ * *finished* rather than *pending*. Both LGV fetch families fill it
144
+ * through `foundationPaintInert`: a failed fetch, a standing cancel, no
145
+ * content on screen, or the too-large banner in the canvas's place. Named
146
+ * for `fetchInert` on the comparative side.
125
147
  *
126
148
  * A hook rather than a read of `error` here, for two reasons that both
127
149
  * bite: this package is a leaf and `error` belongs to the fetch mixins,
@@ -132,14 +154,33 @@ export function RenderLifecycleMixin() {
132
154
  get paintInert() {
133
155
  return false;
134
156
  },
157
+ /**
158
+ * #getter
159
+ * Overridable hook (default false): what is on the canvas was painted
160
+ * from data a later change has made wrong, so `painted` below should
161
+ * answer *pending* until the repaint lands even though `canvasDrawn` is
162
+ * still true. The per-region fetch foundation fills it with
163
+ * `staleSettingsDrawn` — held data drawn under settings that have since
164
+ * moved — which is the state `clearAllRpcData` used to express by
165
+ * resetting `canvasDrawn` on every settings change, blanking the display
166
+ * to do it. A capture waiting on `data-display-drawn` then waits for the
167
+ * refetch rather than snapshotting the previous setting's pixels.
168
+ *
169
+ * A hook and not a reset of the flag, because the flag is re-marked by
170
+ * any redraw — a pan between the settings change and the refetch would
171
+ * report the stale canvas drawn — and a derivation cannot be raced.
172
+ */
173
+ get paintSuperseded() {
174
+ return false;
175
+ },
135
176
  }))
136
177
  .views(self => ({
137
178
  /**
138
179
  * #getter
139
180
  * **The first-paint answer every consumer outside the display should
140
181
  * read**, `canvasDrawn` being only the raw flag: a display that is
141
- * deliberately not painting a canvas has finished, and saying otherwise
142
- * is a lie that never resolves.
182
+ * deliberately not painting a canvas has finished, and reporting it
183
+ * unfinished leaves every waiter on it waiting forever.
143
184
  *
144
185
  * The two `rendersCanvas: false` states each had three of their four
145
186
  * consumers wired by hand — the loading scrim (`rendersCanvas` /
@@ -147,17 +188,22 @@ export function RenderLifecycleMixin() {
147
188
  * while the fourth, `data-display-drawn`, went on publishing `"false"`
148
189
  * forever off the raw flag. That attribute is what `PENDING_DISPLAYS`
149
190
  * (`@jbrowse/browser-test-utils`) selects on, so a zoomed-out reference
150
- * sequence track made every `waitForDisplaysDone` on the page burn its
151
- * full timeout — silently, since that wait swallows its own. Same shape
152
- * as `fetchInert` on the comparative side: the reader you forget is the
153
- * one outside the display, so the display has to publish one name for it.
191
+ * sequence track made every capture wait on the page run to its
192
+ * full timeout, and that wait swallows its own timeout without reporting
193
+ * it. `fetchInert` on the comparative side has the same problem: the
194
+ * forgotten reader is the one outside the display, so the display has to
195
+ * publish one name for it.
154
196
  *
155
197
  * `paintInert` is the third term and the same argument once more, for the
156
198
  * state where a display *would* paint a canvas and never gets to — a fetch
157
- * that failed before first paint. See that hook.
199
+ * that failed before first paint. `paintSuperseded` is the fourth, and
200
+ * the one that subtracts: a canvas painted from data a settings change
201
+ * has made wrong is drawn and not finished. See both hooks.
158
202
  */
159
203
  get painted() {
160
- return self.canvasDrawn || !self.rendersCanvas || self.paintInert;
204
+ return ((self.canvasDrawn && !self.paintSuperseded) ||
205
+ !self.rendersCanvas ||
206
+ self.paintInert);
161
207
  },
162
208
  }))
163
209
  .actions(self => ({
@@ -165,6 +211,7 @@ export function RenderLifecycleMixin() {
165
211
  * #action
166
212
  */
167
213
  markCanvasDrawn() {
214
+ self.paintCount += 1;
168
215
  if (!self.canvasDrawn) {
169
216
  self.canvasDrawn = true;
170
217
  }
@@ -190,6 +237,14 @@ export function RenderLifecycleMixin() {
190
237
  renderNow() {
191
238
  self.renderTick += 1;
192
239
  },
240
+ /**
241
+ * #action
242
+ */
243
+ setOffScreen(offScreen) {
244
+ if (self.offScreen !== offScreen) {
245
+ self.offScreen = offScreen;
246
+ }
247
+ },
193
248
  /**
194
249
  * #action
195
250
  * set/clear the render-backend error. Called by `useRenderingBackend`:
@@ -225,6 +280,7 @@ export function RenderLifecycleMixin() {
225
280
  // un-installed and the next backend can try again.
226
281
  const cbs = setup();
227
282
  self.autorunsInstalled = true;
283
+ let drawnTick = -1;
228
284
  namedAutorun(self, () => {
229
285
  const b = self.currentRenderingBackend;
230
286
  if (b === undefined || !self.canRender) {
@@ -253,7 +309,7 @@ export function RenderLifecycleMixin() {
253
309
  }, { name: 'RenderLifecycle:upload' });
254
310
  namedAutorun(self, () => {
255
311
  const b = self.currentRenderingBackend;
256
- void self.renderTick;
312
+ const tick = self.renderTick;
257
313
  if (b === undefined || !self.canRender) {
258
314
  return;
259
315
  }
@@ -265,10 +321,20 @@ export function RenderLifecycleMixin() {
265
321
  // Same loop caveat as the upload autorun above: the
266
322
  // unmount-and-dispose that prevents re-fire is DisplayChrome's,
267
323
  // not a shared canvas's.
324
+ // Off screen, only a re-fire with no `renderNow()` behind it (a
325
+ // pan, a zoom) is skipped: new data draws wherever the canvas is,
326
+ // so `painted` never stands over a partial picture. The tick is
327
+ // recorded even when the render answers false, since Canvas2D
328
+ // resizes before answering.
268
329
  try {
269
- if (cbs.render(b)) {
330
+ const skip = self.offScreen && self.canvasDrawn && tick === drawnTick;
331
+ drawnTick = tick;
332
+ if (!skip && cbs.render(b)) {
270
333
  self.markCanvasDrawn();
271
334
  }
335
+ if (self.offScreen) {
336
+ cbs.releaseTargets(b);
337
+ }
272
338
  }
273
339
  catch (e) {
274
340
  self.setRenderError(e);
@@ -109,7 +109,7 @@ export interface ClipContext2D {
109
109
  * Clip to one rect, paint, unclip — the `save`/`clip`/`restore` triple with the
110
110
  * `restore` in a `finally`.
111
111
  *
112
- * The `finally` is the whole point, and the cost of missing it is not local: an
112
+ * The `finally` is required, and missing it breaks more than the one frame: an
113
113
  * on-screen ctx outlives the frame and `prepareCanvas`'s setTransform/clearRect
114
114
  * do **not** reset clip state, so one painter throwing once leaves every later
115
115
  * frame drawing through a stale clip. A transient error becomes permanent
@@ -120,8 +120,11 @@ export interface ClipContext2D {
120
120
  * own. Reach for this one for the clips *nested inside* a block — a display
121
121
  * whose bands each own a horizontal strip of the canvas (alignments clips its
122
122
  * coverage, pileup and arc bands separately within one block clip), where the
123
- * nesting is what makes a hand-rolled pairing easy to get wrong: an early
123
+ * nesting makes a hand-rolled pairing easy to get wrong: an early
124
124
  * `return` inside the band body unbalances the block's `save` too.
125
+ *
126
+ * An empty rect paints nothing, as the GPU's empty scissor does; the SVG export
127
+ * would otherwise record every path of a band nothing can show.
125
128
  */
126
129
  export declare function withClip(ctx: ClipContext2D, x: number, y: number, w: number, h: number, paint: () => void): void;
127
130
  /**
@@ -203,13 +206,62 @@ export declare function strokeRectInside(ctx: {
203
206
  * Scalar in, scalar out: runs per feature per frame, so it must not allocate.
204
207
  */
205
208
  export declare function spanLeft(x1: number, x2: number, width: number): number;
209
+ /**
210
+ * The `fillRect` x and width a genomic span paints as, given a bare
211
+ * `makeBpMapper`: `spanLeft`'s pivot and the min-width floor that goes with it,
212
+ * as one value a painter and its hit box can both read.
213
+ *
214
+ * `minWidth` defaults to 0, which makes this plain screen ordering — the
215
+ * leftmost projected edge and the unsigned distance. Pass a floor and the span
216
+ * grows away from `startBp`, which is the reversed-block rule `spanLeft` owns:
217
+ * anchoring the leftmost edge instead slides a sub-pixel mark by up to the floor
218
+ * on a flipped region and never on a forward one.
219
+ *
220
+ * Reach for this over `spanLeft` wherever the *numbers* are wanted rather than a
221
+ * fill — a hover box, an SVG rect, a cull test, an overlay div — which is where
222
+ * the pivot and the floor were being restated separately. The multi-row painter
223
+ * and the hover box it has to line up with each spelled out both.
224
+ * `fillBpSpan` is the same span when a `fillRect` is the only consumer.
225
+ *
226
+ * Not for a per-instance paint loop: this allocates a result per call, so the
227
+ * span mark's painter and wiggle's two bar loops take `spanLeft` and the two
228
+ * numbers inline, and stay the last hand-written copies of this arithmetic.
229
+ */
230
+ export declare function spanRect(toX: (bp: number) => number, startBp: number, endBp: number, minWidth?: number): {
231
+ left: number;
232
+ width: number;
233
+ };
206
234
  export declare function makeRampFillStyleLut(ramp: Uint8Array): (t: number) => string;
207
- export declare function bpToScreenPx(absBp: number, regionStart: number, regionEnd: number, screenStartPx: number, screenEndPx: number, reversed?: boolean): number;
235
+ /**
236
+ * A block's bp→px projection as four numbers, for a placement function reading
237
+ * its block off a frame object. `makeBpMapper` closes over the same four.
238
+ */
239
+ export interface BpProjection {
240
+ originPx: number;
241
+ startBp: number;
242
+ spanBp: number;
243
+ signedSpanPx: number;
244
+ }
245
+ export declare function bpProjection(bounds: BpRegionBounds): BpProjection;
246
+ export declare function projectBp(p: BpProjection, bp: number): number;
247
+ /**
248
+ * One closure literal for both orientations. Split per orientation, a paint
249
+ * loop's mapper call goes megamorphic on a view mixing them, and the loop ran
250
+ * 1.9-2.3x slower (`benches/bpMapper.bench.ts`).
251
+ */
208
252
  export declare function makeBpMapper(bounds: BpRegionBounds): (bp: number) => number;
209
253
  /**
210
- * Left edge of the **1bp cell** covering `bp` — for painters that fill a rect
211
- * per base (MAF alignment cells, the alignments pileup's mismatch /
212
- * modification / per-base quality+letter / soft-clip base layers).
254
+ * Screen px one base occupies in this region: the scale factor, unsigned, with
255
+ * the block's direction left to `makeBpMapper` and `spanLeft`. Shared so a mark
256
+ * sized against it in a draw pass and hit-tested against it in a component
257
+ * read one number.
258
+ */
259
+ export declare function pxPerBpOf(bounds: BpRegionBounds): number;
260
+ /**
261
+ * Left edge of the **1bp cell** covering `bp`, for a painter filling a rect
262
+ * exactly one base wide. A cell floored wider than its base grows from the
263
+ * base's low-coordinate edge instead, leftward on a reversed block, as the
264
+ * alignments pileup's `cellPlacement` does.
213
265
  *
214
266
  * Use this, not `makeBpMapper`, whenever the mark is a cell rather than a point
215
267
  * or a two-edge span. `makeBpMapper(bp)` is the cell's left edge only on a
@@ -226,22 +278,7 @@ export declare function makeBpMapper(bounds: BpRegionBounds): (bp: number) => nu
226
278
  * `bpToClipX(pos)`→`bpToClipX(pos+1)` unflipped and mirror via `flipX` — and
227
279
  * gets its own pivot from `writeBpRangeUniforms`.
228
280
  *
229
- * Callers own the cell *width*: it's a per-plugin rule (MAF uses the raw
230
- * bp-scale; the pileup floors at 1px and adds a seam fudge). Only the pivot is
231
- * shared.
232
- */
233
- /**
234
- * Screen px one base occupies in this region — the scale factor, unsigned, with
235
- * the block's direction deliberately left out (that lives in `makeBpMapper` and
236
- * `spanLeft`, and folding it in here would make a *scale* carry an orientation).
237
- *
238
- * Shared because it is usually an input to something a second painter has to
239
- * reproduce exactly: a mark sized against it in a draw pass and hit-tested
240
- * against it in a component is two spellings of one number, and the hit target
241
- * silently stops covering the mark if they ever drift. Trivial arithmetic, but
242
- * the drift is not.
243
281
  */
244
- export declare function pxPerBpOf(bounds: BpRegionBounds): number;
245
282
  export declare function makeCellLeftMapper(bounds: BpRegionBounds): (bp: number) => number;
246
283
  /**
247
284
  * Fill the rect covering genomic `[startBp, endBp)`, given a bare
@@ -251,7 +288,7 @@ export declare function makeCellLeftMapper(bounds: BpRegionBounds): (bp: number)
251
288
  *
252
289
  * Prefer this to `makeCellLeftMapper` + a caller-computed width for anything
253
290
  * wider than one base. The pivot in `makeCellLeftMapper` is exactly one base,
254
- * which is right for a 1bp cell and silently wrong for an N-bp span — it
291
+ * which is right for a 1bp cell and wrong for an N-bp span — it
255
292
  * anchors the rect one base from the correct edge and then grows it the wrong
256
293
  * way. `fillBpSpan(bp, bp + 1)` is *identical* to the cell-mapper spelling, so
257
294
  * a per-base painter can use this too and never think about orientation again.
@@ -308,7 +345,7 @@ export declare function fillBpSpan(ctx: {
308
345
  * `14468.9936` — and rounding the *offset* and then adding such an anchor
309
346
  * returns the anchor's fraction untouched. The result is then not a base at
310
347
  * all, and every caller that indexes one by equality (a mismatch column, a
311
- * coverage bin, the sort-at-this-column anchor) misses silently: the pileup
348
+ * coverage bin, the sort-at-this-column anchor) finds no match: the pileup
312
349
  * offered no SNP submenu over a mismatch it was drawing. Rounding
313
350
  * `whole + fraction + offset` in one step instead fixes that and hands back the
314
351
  * genome-scale addend the paragraph above exists to keep out, so the whole base
@@ -370,3 +407,33 @@ export declare function regionAtPixel<R extends {
370
407
  screenStartPx: number;
371
408
  screenEndPx: number;
372
409
  }>(regions: readonly R[], px: number): R | undefined;
410
+ /**
411
+ * CSS px a Canvas2D painter adds to the drawn width of a rect whose neighbours
412
+ * abut it. `fillRect` antialiases each edge on its own, so two rects meeting on
413
+ * a fractional column each take partial coverage of it and a hairline of
414
+ * background shows through; abutting GPU quads share an exact clip-space edge
415
+ * and the rasterizer fills it once, so a shader grows no matching pad.
416
+ */
417
+ export declare const CANVAS_SEAM_PX = 0.8;
418
+ export interface PathPaintContext {
419
+ beginPath(): void;
420
+ fill(): void;
421
+ stroke(): void;
422
+ }
423
+ /**
424
+ * One batched Canvas2D path of many shapes, painted in pieces a browser will
425
+ * rasterize. Opens a path on construction; call `add()` before appending each
426
+ * shape and `flush()` to paint what it holds and reopen.
427
+ */
428
+ export declare class CappedPath {
429
+ private shapes;
430
+ private readonly ctx;
431
+ private readonly paint;
432
+ constructor(ctx: PathPaintContext, paint: 'fill' | 'stroke');
433
+ /**
434
+ * True when the path was full and has been painted and reopened, so a
435
+ * polyline must `moveTo` its pen again.
436
+ */
437
+ add(): boolean;
438
+ flush(): void;
439
+ }