@jbrowse/render-core 4.3.0 → 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,167 @@
1
+ // AUTO-GENERATED by packages/shader-tools/src/shader-codegen from linkMark.slang.
2
+ // Do not edit. Run `pnpm gen:shaders` to regenerate.
3
+
4
+ // Scalar twins of linkMark.slang, transliterated from slangc's WGSL so
5
+ // the Canvas2D and SVG paths run the shader's own math. See adr-051.
6
+
7
+ function _clamp(x: number, lo: number, hi: number) {
8
+ return _min(_max(x, lo), hi)
9
+ }
10
+
11
+ function _max(a: number, b: number) {
12
+ return b > a || Number.isNaN(a) ? b : a
13
+ }
14
+
15
+ function _min(a: number, b: number) {
16
+ return b < a || Number.isNaN(a) ? b : a
17
+ }
18
+
19
+ function log1pf(x: number): number {
20
+ let u = (1.0 + x)
21
+ let _t0: number
22
+ if ((u == 1.0)) {
23
+ _t0 = x
24
+ } else {
25
+ _t0 = (Math.log(u) * (x / (u - 1.0)))
26
+ }
27
+ return _t0
28
+ }
29
+
30
+ function symlogTransform(x: number, c: number): number {
31
+ return ((((Math.sign(x)) | 0)) * log1pf(Math.abs((x / c))))
32
+ }
33
+
34
+ function normalizeScoreUnclamped(score: number, domainMin: number, domainMax: number, scaleType: number, symlogConstant: number): number {
35
+ let tMax: number
36
+ let tMin: number
37
+ let t: number
38
+ if ((scaleType == 2)) {
39
+ let _t0 = symlogTransform(score, symlogConstant)
40
+ let _t1 = symlogTransform(domainMin, symlogConstant)
41
+ tMax = symlogTransform(domainMax, symlogConstant)
42
+ tMin = _t1
43
+ t = _t0
44
+ } else {
45
+ if ((scaleType == 1)) {
46
+ if ((domainMin > 0.0)) {
47
+ tMax = domainMin
48
+ } else {
49
+ tMax = 1.0
50
+ }
51
+ let _t2 = Math.log2(_max(score, tMax))
52
+ let _t3 = Math.log2(tMax)
53
+ tMax = Math.log2(_max(domainMax, tMax))
54
+ tMin = _t3
55
+ t = _t2
56
+ } else {
57
+ tMax = domainMax
58
+ tMin = domainMin
59
+ t = score
60
+ }
61
+ }
62
+ let tRange = (tMax - tMin)
63
+ if ((tRange <= 0.0)) {
64
+ if ((t > tMin)) {
65
+ tMax = 1.0
66
+ } else {
67
+ tMax = 0.0
68
+ }
69
+ return tMax
70
+ }
71
+ return ((t - tMin) / tRange)
72
+ }
73
+
74
+ function normalizeScore(score: number, domainMin: number, domainMax: number, scaleType: number, symlogConstant: number): number {
75
+ return _clamp(normalizeScoreUnclamped(score, domainMin, domainMax, scaleType, symlogConstant), 0.0, 1.0)
76
+ }
77
+
78
+ export function linkStrokeWidthPx(raw: number, sizeMode: number, constantPx: number, domainMin: number, domainMax: number, scaleType: number, rangeMin: number, rangeMax: number, dpr: number): number {
79
+ let w: number
80
+ if ((sizeMode == 1)) {
81
+ if ((raw > -1.00000001504746622e+29)) {
82
+ w = (rangeMin + (normalizeScore(raw, domainMin, domainMax, scaleType, 1.0) * (rangeMax - rangeMin)))
83
+ } else {
84
+ w = rangeMin
85
+ }
86
+ } else {
87
+ w = constantPx
88
+ }
89
+ return _max(w, (1.5 / dpr))
90
+ }
91
+
92
+ function rowBandTopPx(rowOffsetPx: number, rowHeight: number, slot: number): number {
93
+ return (rowOffsetPx + (rowHeight * (slot)))
94
+ }
95
+
96
+ export function linkBaseYPx(rowOffsetPx: number, rowHeight: number, row: number, reverse: number): number {
97
+ let _t0 = rowBandTopPx(rowOffsetPx, rowHeight, row)
98
+ let _t1: number
99
+ if ((reverse != 0)) {
100
+ _t1 = 0.0
101
+ } else {
102
+ _t1 = rowHeight
103
+ }
104
+ return (_t0 + _t1)
105
+ }
106
+
107
+ function valueToYPxScaled(value: number, domainMin: number, domainMax: number, h: number, scaleType: number, symlogConstant: number): number {
108
+ return ((1.0 - normalizeScore(value, domainMin, domainMax, scaleType, symlogConstant)) * h)
109
+ }
110
+
111
+ function insetValueYPx(value: number, domainMin: number, domainMax: number, h: number, scaleType: number, insetPx: number, symlogConstant: number): number {
112
+ let _t0 = _min(insetPx, (h * 0.5))
113
+ return (_t0 + valueToYPxScaled(value, domainMin, domainMax, (h - (2.0 * _t0)), scaleType, symlogConstant))
114
+ }
115
+
116
+ export function linkValuePx(value: number, domainMin: number, domainMax: number, h: number, scaleType: number, insetPx: number, symlogConstant: number): number {
117
+ return (h - insetValueYPx(value, domainMin, domainMax, h, scaleType, insetPx, symlogConstant))
118
+ }
119
+
120
+ export function linkApexPx(halfWidthPx: number, reachPx: number, linkShape: number, valued: number, valuePx: number): number {
121
+ if ((valued != 0)) {
122
+ return valuePx
123
+ }
124
+ if ((linkShape == 2)) {
125
+ return 0.0
126
+ }
127
+ if ((linkShape == 1)) {
128
+ return halfWidthPx
129
+ }
130
+ return _min(halfWidthPx, reachPx)
131
+ }
132
+
133
+ function linkIsFar(halfWidthPx: number, screenWidthPx: number): boolean {
134
+ return ((2.0 * halfWidthPx) > (3.0 * screenWidthPx))
135
+ }
136
+
137
+ export function linkRadiiPx(halfWidthPx: number, apexPx: number, screenWidthPx: number): [number, number] {
138
+ if (linkIsFar(halfWidthPx, screenWidthPx)) {
139
+ return [halfWidthPx, halfWidthPx]
140
+ }
141
+ return [halfWidthPx, apexPx]
142
+ }
143
+
144
+ export function linkFootDir(feet: number, shift: number): number {
145
+ let d = (((feet >>> shift) & 3) >>> 0)
146
+ let _t0: number
147
+ if ((d == 1)) {
148
+ _t0 = 1.0
149
+ } else {
150
+ if ((d == 2)) {
151
+ _t0 = -1.0
152
+ } else {
153
+ _t0 = 0.0
154
+ }
155
+ }
156
+ return _t0
157
+ }
158
+
159
+ export function linkFootLenPx(x: number, dir: number, leftPx: number, rightPx: number, footPx: number): number {
160
+ let _t0: number
161
+ if ((dir > 0.0)) {
162
+ _t0 = (rightPx - x)
163
+ } else {
164
+ _t0 = (x - leftPx)
165
+ }
166
+ return _max(0.0, _min(footPx, _t0))
167
+ }
@@ -0,0 +1,439 @@
1
+ // The `link` mark shape: one instance is a stroked curve between two genomic
2
+ // positions — `x` on the displayed region whose payload holds the instance and
3
+ // `x2` on whichever displayed region the instance names, the same one,
4
+ // another, or none. The mark draws over the whole canvas rather than inside a
5
+ // block's column, so a curve crosses regions holding neither foot. Both feet
6
+ // place through a uniform table of the view's displayed regions, so a pan or
7
+ // zoom writes the table and no buffer.
8
+ //
9
+ // The curve is a half-ellipse whose hull is a triangle strip inflated by the
10
+ // half stroke plus one antialiasing ramp, and a fragment that measures the
11
+ // true distance to the analytic curve, so the hull's facets never reach the
12
+ // picture. A pair wider than LINK_FAR_SCREEN_WIDTHS view widths degenerates to
13
+ // a circle whose legs rise from each real foot, built endpoint-relative so a
14
+ // radius in the millions of px cancels nothing. A foot the table cannot place
15
+ // draws a stem at the placed one, so an off-view mate still says it exists. A
16
+ // foot may carry a breakend tick along the baseline, pointing along the arm
17
+ // its junction keeps. Under `line` the pair is a straight segment at the apex
18
+ // height instead, GenomeSpy's fourth link shape.
19
+ //
20
+ // The apex is a value on the display's y scale where the mark names one, else
21
+ // the pair's own half-width, clamped to the band under `dome` and left to
22
+ // leave it under `arc`. A reversed scale puts the baseline at the band's top
23
+ // and the curve below it.
24
+ //! targets: wgsl, glsl
25
+ //! topology: triangle-strip
26
+ //! coverage: analytic
27
+ //! export-consts: LINK_SHAPE_DOME, LINK_SHAPE_ARC, LINK_SHAPE_LINE, LINK_LINE_MIN_PX, LINK_NO_REGION, LINK_ELSEWHERE, LINK_MAX_REGIONS, LINK_STEM_PX, LINK_FOOT_PX, LINK_FAR_SCREEN_WIDTHS, LINK_SIZE_CONSTANT, LINK_SIZE_SCALED, LINK_NO_SIZE, LINK_CURVE_SEGMENTS
28
+ //! js-export: linkApexPx, linkRadiiPx, linkStrokeWidthPx, linkValuePx, linkBaseYPx, linkFootLenPx, linkFootDir
29
+ //! js-skip: linkIsFar — reached as a private helper inside the generated linkRadiiPx, so the far decision is shared without a second way to ask it
30
+
31
+ import antialias;
32
+ import colorPack;
33
+ import curveDistance;
34
+ import hpmath;
35
+ import markColor;
36
+ import rowTable;
37
+ import scoreScale;
38
+ import valueScale;
39
+
40
+ public static const uint LINK_CURVE_SEGMENTS = 64u;
41
+ static const uint CURVE_VERTS = (LINK_CURVE_SEGMENTS + 1u) * 2u;
42
+ // Each foot's block of the strip: the join's repeated vertex, then its quad
43
+ // with the first corner doubled, so both joins are degenerate triangles.
44
+ static const uint FOOT_VERTS = 6u;
45
+ public static const uint VERTS_PER_INSTANCE = CURVE_VERTS + 2u * FOOT_VERTS;
46
+ static const float PI = 3.14159265359;
47
+
48
+ public static const int LINK_SHAPE_DOME = 0;
49
+ public static const int LINK_SHAPE_ARC = 1;
50
+ public static const int LINK_SHAPE_LINE = 2;
51
+ // The shortest segment a `line` draws, widened about its midpoint, so a pair
52
+ // under a pixel apart still paints.
53
+ public static const float LINK_LINE_MIN_PX = 2.5;
54
+ // An `x2Region` the table has no entry for: the mate lies on no displayed
55
+ // region, so the instance draws its stem.
56
+ public static const uint LINK_NO_REGION = 0xFFFFFFFFu;
57
+ // An `x2Region` for an instance another region's payload draws: the far half
58
+ // of a pair both of whose ends have records, or a record fetched twice.
59
+ public static const uint LINK_ELSEWHERE = 0xFFFFFFFEu;
60
+ public static const uint LINK_MAX_REGIONS = 256u;
61
+ public static const float LINK_STEM_PX = 12.0;
62
+ // How long a breakend foot is where its region has the room: a tick along
63
+ // the baseline over the arm its junction keeps, BreakpointSplitView's length.
64
+ public static const float LINK_FOOT_PX = 20.0;
65
+ // How many view widths a pair may span before its ellipse becomes a true
66
+ // circle, which the band clips down to near-vertical legs at each real foot.
67
+ // Not 1, because a circle throws the pair's direction away, and the limit is
68
+ // tessellation: reference/ARC_BAND.md.
69
+ public static const float LINK_FAR_SCREEN_WIDTHS = 3.0;
70
+ public static const int LINK_SIZE_CONSTANT = 0;
71
+ public static const int LINK_SIZE_SCALED = 1;
72
+ // The `size` lane's value for an instance holding no number, which takes the
73
+ // range's first px. A sentinel rather than NaN, which a vertex attribute may
74
+ // not carry through every driver's fast math.
75
+ public static const float LINK_NO_SIZE = -1.0e30;
76
+
77
+ static const float KIND_ELLIPSE = 0.0;
78
+ static const float KIND_CIRCLE = 1.0;
79
+ static const float KIND_STEM = 2.0;
80
+ static const float KIND_LINE = 3.0;
81
+ static const float KIND_FOOT = 4.0;
82
+
83
+ struct LinkInstance {
84
+ uint x : ATTR0;
85
+ uint x2 : ATTR1;
86
+ uint x2Region : ATTR2;
87
+ float y : ATTR3;
88
+ float size : ATTR4;
89
+ uint color : ATTR5;
90
+ uint row : ATTR6;
91
+ uint feet : ATTR7;
92
+ };
93
+
94
+ struct Uniforms {
95
+ float canvasHeight;
96
+ float devicePixelRatio;
97
+ float rowHeight;
98
+ float rowOffsetPx;
99
+ int reverse;
100
+ float stemPx;
101
+ float dashPx;
102
+ float gapPx;
103
+ float footPx;
104
+ // The segments the curve's strip takes this draw: LINK_CURVE_SEGMENTS, or
105
+ // one for a straight `line`, so a read cloud's bars shade 16 vertices each.
106
+ uint curveSegments;
107
+ float insetPx;
108
+ float domainMin;
109
+ float domainMax;
110
+ int valueScaleType;
111
+ float valueSymlogConstant;
112
+ int rampMode;
113
+ float rampMin;
114
+ float rampMax;
115
+ float rampMidNorm;
116
+ // `markColor`'s threshold: how many cuts are in use, the cuts four to a
117
+ // vector, and the colour of each interval between them.
118
+ int colorCutCount;
119
+ float4 colorCuts[2];
120
+ float4 colorBands[MAX_COLOR_BANDS];
121
+ // Whether the mark names a `y`: the apex is then the value's height.
122
+ int valued;
123
+ int linkShape;
124
+ int sizeMode;
125
+ float sizeConstantPx;
126
+ float sizeDomainMin;
127
+ float sizeDomainMax;
128
+ int sizeScaleType;
129
+ float sizeRangeMin;
130
+ float sizeRangeMax;
131
+ float canvasWidth;
132
+ uint regionCount;
133
+ float zero;
134
+ // The table entry of the region whose payload is drawing, which every
135
+ // instance's `x` is on; carried apart from the table so a region past its
136
+ // end places.
137
+ float4 ownEntry;
138
+ // The own region's screen extent, (leftPx, rightPx), which bounds its foot.
139
+ float4 ownSpan;
140
+ // One entry per displayed region: (anchorPx, anchorBpHi, anchorBpLo,
141
+ // signedPxPerBp), the anchor a bp of the region near the view so a foot's
142
+ // offset from it stays inside float32.
143
+ float4 regionTable[LINK_MAX_REGIONS];
144
+ // Each region's screen extent, two to an element: (left, right) of region
145
+ // 2i in xy and of region 2i + 1 in zw.
146
+ float4 regionSpan[LINK_MAX_REGIONS / 2u];
147
+ // The keys the bound row table holds, −1 where `row` is the band itself.
148
+ int rowTableKeys;
149
+ };
150
+ [[vk::binding(1, 0)]] ConstantBuffer<Uniforms> u;
151
+ [[vk::binding(2, 0)]] Sampler2D<float4> colorRamp;
152
+ [[vk::binding(4, 0)]] Sampler2D<float4> rowTable;
153
+
154
+ struct VsOut {
155
+ float4 position : SV_Position;
156
+ float4 color : COLOR0;
157
+ // Fragment position in the frame its curve is measured in, y negative away
158
+ // from the baseline: the ellipse's centre, a far circle's leg foot, a
159
+ // stem's foot, or a line's left end; along and across a breakend foot.
160
+ float2 local : COLOR1;
161
+ nointerpolation float2 radii : COLOR2;
162
+ nointerpolation float kind : COLOR3;
163
+ // The resolved half stroke width, carried so the hull the vertex stage
164
+ // inflated and the ink the fragment measures are one width.
165
+ nointerpolation float halfWidthPx : COLOR4;
166
+ // Which leg of a far circle a vertex belongs to, ±1, and +1 throughout for
167
+ // one connected curve. The strip has no break in it, so the quad between
168
+ // the two legs' tips rasterizes; both tips carry the same `local`, so its
169
+ // distance comes out ~0 and it inks a bar. The fragment discards where this
170
+ // ramps between the legs.
171
+ float legSide : COLOR5;
172
+ };
173
+
174
+ float entryPx(uint bp, float4 r, float hpZero) {
175
+ return r.x - hpViewportOffsetBp(hpSplitUint(bp), float3(r.y, r.z, 0.0), hpZero) * r.w;
176
+ }
177
+
178
+ bool linkIsFar(float halfWidthPx, float screenWidthPx) {
179
+ return 2.0 * halfWidthPx > LINK_FAR_SCREEN_WIDTHS * screenWidthPx;
180
+ }
181
+
182
+ // The height above the baseline a mark's `y` value stands at: `valueScale`'s
183
+ // inset range, anchored at the band's bottom rather than a point's top.
184
+ public float linkValuePx(float value, float domainMin, float domainMax, float h, int scaleType, float insetPx, float symlogConstant) {
185
+ return h - insetValueYPx(value, domainMin, domainMax, h, scaleType, insetPx, symlogConstant);
186
+ }
187
+
188
+ // The apex height of a pair, in CSS px above the baseline.
189
+ public float linkApexPx(float halfWidthPx, float reachPx, int linkShape, int valued, float valuePx) {
190
+ if (valued != 0) { return valuePx; }
191
+ if (linkShape == LINK_SHAPE_LINE) { return 0.0; }
192
+ if (linkShape == LINK_SHAPE_ARC) { return halfWidthPx; }
193
+ return min(halfWidthPx, reachPx);
194
+ }
195
+
196
+ // The baseline of a row's band, in canvas px: its bottom, or its top under a
197
+ // reversed scale.
198
+ public float linkBaseYPx(float rowOffsetPx, float rowHeight, uint row, int reverse) {
199
+ return rowBandTopPx(rowOffsetPx, rowHeight, row) + (reverse != 0 ? 0.0 : rowHeight);
200
+ }
201
+
202
+ // The two radii of the half-ellipse a pair draws, or a true circle's once the
203
+ // pair is far. `//! js-export`ed as a pair because the decision IS the pair,
204
+ // and it is what the painter, the ink and the hit test read.
205
+ public float2 linkRadiiPx(float halfWidthPx, float apexPx, float screenWidthPx) {
206
+ if (linkIsFar(halfWidthPx, screenWidthPx)) {
207
+ return float2(halfWidthPx, halfWidthPx);
208
+ }
209
+ return float2(halfWidthPx, apexPx);
210
+ }
211
+
212
+ // An instance's stroke width: the constant, or its raw `size` value through
213
+ // the size scale into the px range, floored at 1.5 device px so the single
214
+ // antialiasing ramp always has room (arc-antialiasing-without-msaa.md).
215
+ public float linkStrokeWidthPx(float raw, int sizeMode, float constantPx, float domainMin, float domainMax, int scaleType, float rangeMin, float rangeMax, float dpr) {
216
+ float w = constantPx;
217
+ if (sizeMode == LINK_SIZE_SCALED) {
218
+ w = raw > -1.0e29
219
+ ? rangeMin + normalizeScore(raw, domainMin, domainMax, scaleType, 1.0) * (rangeMax - rangeMin)
220
+ : rangeMin;
221
+ }
222
+ return max(w, 1.5 / dpr);
223
+ }
224
+
225
+ // A foot's genomic direction off the `feet` lane: two bits per foot, 1 for
226
+ // forward and 2 for reverse, the `x` foot in the low pair.
227
+ public float linkFootDir(uint feet, uint shift) {
228
+ uint d = (feet >> shift) & 3u;
229
+ return d == 1u ? 1.0 : (d == 2u ? -1.0 : 0.0);
230
+ }
231
+
232
+ float2 regionSpanPx(uint region) {
233
+ float4 s = u.regionSpan[region / 2u];
234
+ return (region % 2u) == 0u ? s.xy : s.zw;
235
+ }
236
+
237
+ // How far a foot at `x` runs in screen direction `dir`, up to `footPx` and
238
+ // no further than its own region's edge, so it stops at a seam.
239
+ public float linkFootLenPx(float x, float dir, float leftPx, float rightPx, float footPx) {
240
+ return max(0.0, min(footPx, dir > 0.0 ? rightPx - x : x - leftPx));
241
+ }
242
+
243
+ // What every vertex of one instance shares.
244
+ struct LinkEnv {
245
+ float strokeHalf;
246
+ float hw;
247
+ float baseY;
248
+ float ySign;
249
+ float reach;
250
+ float xPx;
251
+ float x2Px;
252
+ bool placed;
253
+ };
254
+
255
+ struct LinkVertex {
256
+ float2 screen;
257
+ float2 local;
258
+ float2 radii;
259
+ float kind;
260
+ float legSide;
261
+ };
262
+
263
+ LinkVertex curveVertex(LinkInstance inst, LinkEnv e, uint seg, float side) {
264
+ float t = float(seg) / float(u.curveSegments);
265
+ // Positive on the outer flank; the frame's y is negative upward.
266
+ float pad = side * e.hw;
267
+ float2 origin;
268
+ float legDir = 1.0;
269
+ LinkVertex v;
270
+ v.legSide = 1.0;
271
+ if (!e.placed) {
272
+ v.kind = KIND_STEM;
273
+ v.radii = float2(0.0, u.stemPx);
274
+ // The stem's tip is a round cap, so the quad runs one pad past it. Its foot
275
+ // stops at the baseline, where every dome's feet stop.
276
+ v.local = float2(pad, -t * (u.stemPx + e.hw));
277
+ origin = float2(e.xPx, e.baseY);
278
+ } else {
279
+ float pairHalf = abs(e.x2Px - e.xPx) * 0.5;
280
+ float valuePx = linkValuePx(inst.y, u.domainMin, u.domainMax, u.rowHeight,
281
+ u.valueScaleType, u.insetPx, u.valueSymlogConstant);
282
+ float apex = linkApexPx(pairHalf, e.reach, u.linkShape, u.valued, valuePx);
283
+ v.radii = linkRadiiPx(pairHalf, apex, u.canvasWidth);
284
+ float2 ends = float2(min(e.xPx, e.x2Px), max(e.xPx, e.x2Px));
285
+ if (u.linkShape == LINK_SHAPE_LINE) {
286
+ v.kind = KIND_LINE;
287
+ float len = max(2.0 * pairHalf, LINK_LINE_MIN_PX);
288
+ v.radii = float2(len, 0.0);
289
+ v.local = float2(t * len, pad);
290
+ origin = float2((e.xPx + e.x2Px) * 0.5 - len * 0.5, e.baseY - apex * e.ySign);
291
+ } else if (linkIsFar(pairHalf, u.canvasWidth)) {
292
+ v.kind = KIND_CIRCLE;
293
+ float legSweep = legSweepAngle(v.radii.x, e.reach + e.hw);
294
+ // Two legs, each built from ITS OWN foot outward with the half-angle
295
+ // identity, so a radius past 1e6 px cancels nothing.
296
+ float2 leg = wideCircleLeg(seg, u.curveSegments, legSweep);
297
+ float b = leg.y;
298
+ float halfStep =
299
+ 0.5 * wideCircleLegStep(seg, u.curveSegments, legSweep);
300
+ v.local = wideCircleHullPoint(sin(b), sin(b * 0.5), cos(halfStep),
301
+ v.radii.x, pad);
302
+ v.local.y = -v.local.y;
303
+ origin = float2(leg.x > 0.0 ? ends.y : ends.x, e.baseY);
304
+ legDir = leg.x;
305
+ v.legSide = legDir;
306
+ } else {
307
+ v.kind = KIND_ELLIPSE;
308
+ float a = t * PI;
309
+ float halfStep = PI / (2.0 * float(u.curveSegments));
310
+ v.local = ellipseHullPoint(cos(a), sin(a), cos(halfStep), sin(halfStep),
311
+ v.radii.x, v.radii.y, pad);
312
+ v.local.y = -v.local.y;
313
+ origin = float2((e.xPx + e.x2Px) * 0.5, e.baseY);
314
+ }
315
+ }
316
+ v.screen = origin + float2(legDir * v.local.x, v.local.y * e.ySign);
317
+ return v;
318
+ }
319
+
320
+ // Corner `c` (0-3, strip order) of foot `f`'s quad, or undefined where the
321
+ // foot draws nothing, reported through `present`.
322
+ LinkVertex footCorner(LinkInstance inst, LinkEnv e, uint f, uint c, out bool present) {
323
+ float x = f == 0u ? e.xPx : e.x2Px;
324
+ uint far = min(inst.x2Region, LINK_MAX_REGIONS - 1u);
325
+ float4 entry = f == 0u ? u.ownEntry : u.regionTable[far];
326
+ float2 span = f == 0u ? u.ownSpan.xy : regionSpanPx(far);
327
+ float dir = linkFootDir(inst.feet, f * 2u) * sign(entry.w);
328
+ float len = linkFootLenPx(x, dir, span.x, span.y, u.footPx);
329
+ present = dir != 0.0 && len > 0.0 && (f == 0u || e.placed);
330
+ float along = (c >= 2u) ? len : 0.0;
331
+ float across = (c % 2u == 0u) ? -e.hw : e.hw;
332
+ LinkVertex v;
333
+ v.kind = KIND_FOOT;
334
+ v.radii = float2(len, 0.0);
335
+ v.legSide = 1.0;
336
+ v.local = float2(along, across);
337
+ v.screen = float2(x + dir * along, e.baseY - e.ySign * e.strokeHalf + across);
338
+ return v;
339
+ }
340
+
341
+ // The vertex a foot's block of the strip starts from: the one before it, so
342
+ // the join is two degenerate triangles.
343
+ LinkVertex footBlockStart(LinkInstance inst, LinkEnv e, uint f) {
344
+ LinkVertex tail = curveVertex(inst, e, u.curveSegments, 1.0);
345
+ if (f == 0u) { return tail; }
346
+ bool first;
347
+ LinkVertex last = footCorner(inst, e, 0u, 3u, first);
348
+ return first ? last : tail;
349
+ }
350
+
351
+ // Vertex `k` of foot `f`'s six: the block's start repeated, then the quad
352
+ // with its first corner doubled. A foot that draws nothing repeats the start.
353
+ LinkVertex footVertex(LinkInstance inst, LinkEnv e, uint f, uint k) {
354
+ LinkVertex start = footBlockStart(inst, e, f);
355
+ if (k == 0u) { return start; }
356
+ bool present;
357
+ LinkVertex v = footCorner(inst, e, f, k <= 2u ? 0u : k - 2u, present);
358
+ return present ? v : start;
359
+ }
360
+
361
+ [shader("vertex")]
362
+ VsOut vs_main(LinkInstance inst, uint vid : SV_VertexID) {
363
+ RowPlacement place = rowTableLookup(rowTable, inst.row, u.rowTableKeys,
364
+ markScaleColor(colorRamp, inst.color, u.rampMode, u.rampMin, u.rampMax, u.rampMidNorm, u.colorCutCount, u.colorCuts[0], u.colorCuts[1], u.colorBands));
365
+ LinkEnv e;
366
+ e.strokeHalf = 0.5 * linkStrokeWidthPx(
367
+ inst.size, u.sizeMode, u.sizeConstantPx, u.sizeDomainMin, u.sizeDomainMax,
368
+ u.sizeScaleType, u.sizeRangeMin, u.sizeRangeMax, u.devicePixelRatio);
369
+ e.hw = e.strokeHalf + aaHalfPx(u.devicePixelRatio);
370
+ e.baseY = linkBaseYPx(u.rowOffsetPx, u.rowHeight, place.slot, u.reverse);
371
+ e.ySign = u.reverse != 0 ? -1.0 : 1.0;
372
+ e.reach = max(u.rowHeight - u.insetPx, 0.0);
373
+ e.xPx = entryPx(inst.x, u.ownEntry, u.zero);
374
+ e.placed = inst.x2Region < u.regionCount;
375
+ e.x2Px = e.placed ? entryPx(inst.x2, u.regionTable[inst.x2Region], u.zero) : e.xPx;
376
+
377
+ uint curveVerts = (u.curveSegments + 1u) * 2u;
378
+ LinkVertex v;
379
+ if (vid < curveVerts) {
380
+ v = curveVertex(inst, e, vid / 2u, (vid % 2u == 0u) ? -1.0 : 1.0);
381
+ } else {
382
+ uint j = vid - curveVerts;
383
+ v = footVertex(inst, e, j / FOOT_VERTS, j % FOOT_VERTS);
384
+ }
385
+
386
+ VsOut o;
387
+ o.position = inst.x2Region == LINK_ELSEWHERE || place.hidden
388
+ ? float4(-2.0, -2.0, 0.0, 1.0)
389
+ : float4(
390
+ v.screen.x / u.canvasWidth * 2.0 - 1.0,
391
+ yPxToClipY(v.screen.y, u.canvasHeight),
392
+ 0.0, 1.0);
393
+ o.color = place.color;
394
+ o.local = v.local;
395
+ o.radii = v.radii;
396
+ o.kind = v.kind;
397
+ o.halfWidthPx = e.strokeHalf;
398
+ o.legSide = v.legSide;
399
+ return o;
400
+ }
401
+
402
+ // Perpendicular distance in CSS px from this fragment to its analytic curve.
403
+ float linkDistance(VsOut i) {
404
+ if (i.kind >= 2.5) {
405
+ float x = clamp(i.local.x, 0.0, i.radii.x);
406
+ return length(float2(i.local.x - x, i.local.y));
407
+ }
408
+ if (i.kind >= 1.5) {
409
+ float y = clamp(i.local.y, -i.radii.y, 0.0);
410
+ return length(float2(i.local.x, i.local.y - y));
411
+ }
412
+ if (i.kind >= 0.5) { return distToWideCircle(i.local, i.radii.x); }
413
+ return sdEllipse(i.local, i.radii);
414
+ }
415
+
416
+ // How far along a straight segment's axis the fragment is, from the end the
417
+ // dash pattern starts at; a curve carries no dash.
418
+ float linkDashAlong(VsOut i) {
419
+ if (i.kind >= 3.5) { return -1.0; }
420
+ if (i.kind >= 2.5) { return i.local.x; }
421
+ if (i.kind >= 1.5) { return -i.local.y; }
422
+ return -1.0;
423
+ }
424
+
425
+ float linkDash(VsOut i) {
426
+ float along = linkDashAlong(i);
427
+ return u.dashPx > 0.0 && along >= 0.0
428
+ ? dashCoverage(along, u.dashPx, u.gapPx, u.devicePixelRatio)
429
+ : 1.0;
430
+ }
431
+
432
+ [shader("fragment")]
433
+ float4 fs_main(VsOut fragIn) : SV_Target {
434
+ if (abs(fragIn.legSide) < 0.999) { discard; }
435
+ // |∇d| is 1 per CSS px, so the ramp is a constant number of device pixels.
436
+ float alpha = edgeCoverage(fragIn.halfWidthPx - linkDistance(fragIn), u.devicePixelRatio)
437
+ * linkDash(fragIn);
438
+ return float4(fragIn.color.rgb, fragIn.color.a * alpha);
439
+ }