@genome-spy/core 0.77.0 → 0.79.0

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 (317) hide show
  1. package/dist/bundle/{browser-KWU9rWZT.js → browser-CETrb2cm.js} +53 -33
  2. package/dist/bundle/esm-BdLYkz-m.js +248 -0
  3. package/dist/bundle/esm-BwiDsqSb.js +1367 -0
  4. package/dist/bundle/esm-CDFd1cjk.js +441 -0
  5. package/dist/bundle/{esm-CRMf_I9V.js → esm-CTUHLDbv.js} +30 -30
  6. package/dist/bundle/esm-Cx-EbkOj.js +1221 -0
  7. package/dist/bundle/esm-DlYGqi79.js +128 -0
  8. package/dist/bundle/{esm-BygJiwh0.js → esm-k9p3oHkt.js} +133 -158
  9. package/dist/bundle/{esm-CT3ygiMq.js → esm-zAZJQO6D.js} +226 -212
  10. package/dist/bundle/index.es.js +14102 -10810
  11. package/dist/bundle/index.js +109 -95
  12. package/dist/bundle/{parquetRead-DG_-F5j5.js → parquetRead-Cad1SOVV.js} +473 -399
  13. package/dist/schema.json +23788 -11049
  14. package/dist/src/config/axisConfig.d.ts +2 -2
  15. package/dist/src/config/axisConfig.d.ts.map +1 -1
  16. package/dist/src/config/axisConfig.js +28 -44
  17. package/dist/src/config/configLayers.d.ts +45 -0
  18. package/dist/src/config/configLayers.d.ts.map +1 -0
  19. package/dist/src/config/configLayers.js +110 -0
  20. package/dist/src/config/defaultConfig.d.ts.map +1 -1
  21. package/dist/src/config/defaultConfig.js +8 -1
  22. package/dist/src/config/defaults/legendDefaults.d.ts +14 -0
  23. package/dist/src/config/defaults/legendDefaults.d.ts.map +1 -0
  24. package/dist/src/config/defaults/legendDefaults.js +46 -0
  25. package/dist/src/config/defaults/titleDefaults.d.ts.map +1 -1
  26. package/dist/src/config/defaults/titleDefaults.js +26 -18
  27. package/dist/src/config/legendConfig.d.ts +11 -0
  28. package/dist/src/config/legendConfig.d.ts.map +1 -0
  29. package/dist/src/config/legendConfig.js +63 -0
  30. package/dist/src/config/styleUtils.d.ts +8 -2
  31. package/dist/src/config/styleUtils.d.ts.map +1 -1
  32. package/dist/src/config/styleUtils.js +25 -1
  33. package/dist/src/config/themes.d.ts.map +1 -1
  34. package/dist/src/config/themes.js +21 -2
  35. package/dist/src/config/titleConfig.d.ts.map +1 -1
  36. package/dist/src/config/titleConfig.js +2 -18
  37. package/dist/src/data/collector.d.ts.map +1 -1
  38. package/dist/src/data/collector.js +40 -18
  39. package/dist/src/data/flowInit.d.ts +6 -0
  40. package/dist/src/data/flowInit.d.ts.map +1 -1
  41. package/dist/src/data/flowInit.js +1 -1
  42. package/dist/src/data/flowNode.d.ts +32 -0
  43. package/dist/src/data/flowNode.d.ts.map +1 -1
  44. package/dist/src/data/flowNode.js +59 -0
  45. package/dist/src/data/sources/lazy/bamSource.d.ts +0 -1
  46. package/dist/src/data/sources/lazy/bamSource.d.ts.map +1 -1
  47. package/dist/src/data/sources/lazy/bamSource.js +39 -30
  48. package/dist/src/data/sources/lazy/bigBedSource.d.ts +0 -10
  49. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  50. package/dist/src/data/sources/lazy/bigBedSource.js +127 -62
  51. package/dist/src/data/sources/lazy/bigWigSource.d.ts +2 -2
  52. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  53. package/dist/src/data/sources/lazy/bigWigSource.js +234 -81
  54. package/dist/src/data/sources/lazy/gff3Source.d.ts +7 -3
  55. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  56. package/dist/src/data/sources/lazy/gff3Source.js +7 -8
  57. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts +1 -1
  58. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  59. package/dist/src/data/sources/lazy/indexedFastaSource.js +28 -19
  60. package/dist/src/data/sources/lazy/legendEntriesSource.d.ts +24 -0
  61. package/dist/src/data/sources/lazy/legendEntriesSource.d.ts.map +1 -0
  62. package/dist/src/data/sources/lazy/legendEntriesSource.js +217 -0
  63. package/dist/src/data/sources/lazy/legendGradientSource.d.ts +30 -0
  64. package/dist/src/data/sources/lazy/legendGradientSource.d.ts.map +1 -0
  65. package/dist/src/data/sources/lazy/legendGradientSource.js +388 -0
  66. package/dist/src/data/sources/lazy/mockLazySource.d.ts +4 -1
  67. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -1
  68. package/dist/src/data/sources/lazy/mockLazySource.js +49 -4
  69. package/dist/src/data/sources/lazy/registerCoreLazySources.js +2 -0
  70. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  71. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +3 -4
  72. package/dist/src/data/sources/lazy/tabixSource.d.ts +9 -4
  73. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  74. package/dist/src/data/sources/lazy/tabixSource.js +201 -70
  75. package/dist/src/data/sources/lazy/tabixTsvSource.d.ts +2 -3
  76. package/dist/src/data/sources/lazy/tabixTsvSource.d.ts.map +1 -1
  77. package/dist/src/data/sources/lazy/tabixTsvSource.js +14 -12
  78. package/dist/src/data/sources/lazy/vcfSource.d.ts +7 -3
  79. package/dist/src/data/sources/lazy/vcfSource.d.ts.map +1 -1
  80. package/dist/src/data/sources/lazy/vcfSource.js +7 -8
  81. package/dist/src/data/sources/urlDescriptor.d.ts +165 -0
  82. package/dist/src/data/sources/urlDescriptor.d.ts.map +1 -0
  83. package/dist/src/data/sources/urlDescriptor.js +473 -0
  84. package/dist/src/data/sources/urlDescriptorController.d.ts +25 -0
  85. package/dist/src/data/sources/urlDescriptorController.d.ts.map +1 -0
  86. package/dist/src/data/sources/urlDescriptorController.js +72 -0
  87. package/dist/src/data/sources/urlDescriptorState.d.ts +47 -0
  88. package/dist/src/data/sources/urlDescriptorState.d.ts.map +1 -0
  89. package/dist/src/data/sources/urlDescriptorState.js +129 -0
  90. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  91. package/dist/src/data/sources/urlSource.js +101 -61
  92. package/dist/src/data/transforms/packLegendLabels.d.ts +21 -0
  93. package/dist/src/data/transforms/packLegendLabels.d.ts.map +1 -0
  94. package/dist/src/data/transforms/packLegendLabels.js +189 -0
  95. package/dist/src/data/transforms/transformFactory.d.ts.map +1 -1
  96. package/dist/src/data/transforms/transformFactory.js +4 -0
  97. package/dist/src/data/transforms/truncateText.d.ts +27 -0
  98. package/dist/src/data/transforms/truncateText.d.ts.map +1 -0
  99. package/dist/src/data/transforms/truncateText.js +94 -0
  100. package/dist/src/debug/dataflowDebugSnapshot.d.ts +58 -0
  101. package/dist/src/debug/dataflowDebugSnapshot.d.ts.map +1 -0
  102. package/dist/src/debug/dataflowDebugSnapshot.js +159 -0
  103. package/dist/src/debug/markDebugSnapshot.d.ts +54 -0
  104. package/dist/src/debug/markDebugSnapshot.d.ts.map +1 -0
  105. package/dist/src/debug/markDebugSnapshot.js +100 -0
  106. package/dist/src/debug/paramDebugSnapshot.d.ts +53 -0
  107. package/dist/src/debug/paramDebugSnapshot.d.ts.map +1 -0
  108. package/dist/src/debug/paramDebugSnapshot.js +86 -0
  109. package/dist/src/debug/resolutionDebugSnapshot.d.ts +155 -0
  110. package/dist/src/debug/resolutionDebugSnapshot.d.ts.map +1 -0
  111. package/dist/src/debug/resolutionDebugSnapshot.js +291 -0
  112. package/dist/src/debug/valuePreview.d.ts +9 -0
  113. package/dist/src/debug/valuePreview.d.ts.map +1 -0
  114. package/dist/src/debug/valuePreview.js +57 -0
  115. package/dist/src/debug/viewDebugSnapshot.d.ts +131 -0
  116. package/dist/src/debug/viewDebugSnapshot.d.ts.map +1 -0
  117. package/dist/src/debug/viewDebugSnapshot.js +390 -0
  118. package/dist/src/embedFactory.d.ts.map +1 -1
  119. package/dist/src/embedFactory.js +6 -1
  120. package/dist/src/encoder/encoder.d.ts +2 -2
  121. package/dist/src/encoder/encoder.d.ts.map +1 -1
  122. package/dist/src/encoder/encoder.js +5 -4
  123. package/dist/src/fonts/bmFontManager.d.ts +1 -1
  124. package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
  125. package/dist/src/fonts/bmFontManager.js +45 -10
  126. package/dist/src/fonts/textMetrics.d.ts +69 -0
  127. package/dist/src/fonts/textMetrics.d.ts.map +1 -0
  128. package/dist/src/fonts/textMetrics.js +73 -0
  129. package/dist/src/genomeSpy/headlessBootstrap.d.ts.map +1 -1
  130. package/dist/src/genomeSpy/headlessBootstrap.js +8 -0
  131. package/dist/src/genomeSpy/interactionController.d.ts +4 -1
  132. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  133. package/dist/src/genomeSpy/interactionController.js +57 -13
  134. package/dist/src/genomeSpy/renderCoordinator.d.ts.map +1 -1
  135. package/dist/src/genomeSpy/renderCoordinator.js +25 -3
  136. package/dist/src/genomeSpy/viewDataInit.d.ts +14 -0
  137. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  138. package/dist/src/genomeSpy/viewDataInit.js +45 -8
  139. package/dist/src/genomeSpyBase.d.ts +6 -0
  140. package/dist/src/genomeSpyBase.d.ts.map +1 -1
  141. package/dist/src/genomeSpyBase.js +25 -4
  142. package/dist/src/gl/glslScaleGenerator.d.ts +17 -0
  143. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  144. package/dist/src/gl/glslScaleGenerator.js +39 -2
  145. package/dist/src/gl/includes/common.glsl.js +1 -1
  146. package/dist/src/gl/vertexRangeIndex.d.ts.map +1 -1
  147. package/dist/src/gl/vertexRangeIndex.js +4 -2
  148. package/dist/src/gl/webGLHelper.d.ts +1 -1
  149. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  150. package/dist/src/gl/webGLHelper.js +13 -8
  151. package/dist/src/marks/__snapshots__/shaderSnapshot.test.js.snap +140 -3
  152. package/dist/src/marks/mark.d.ts +47 -4
  153. package/dist/src/marks/mark.d.ts.map +1 -1
  154. package/dist/src/marks/mark.js +158 -54
  155. package/dist/src/marks/point.d.ts.map +1 -1
  156. package/dist/src/marks/point.js +4 -0
  157. package/dist/src/marks/point.vertex.glsl.js +1 -1
  158. package/dist/src/marks/text.d.ts +1 -1
  159. package/dist/src/marks/text.d.ts.map +1 -1
  160. package/dist/src/marks/text.js +2 -7
  161. package/dist/src/marks/text.vertex.glsl.js +1 -1
  162. package/dist/src/paramRuntime/paramUtils.d.ts +43 -9
  163. package/dist/src/paramRuntime/paramUtils.d.ts.map +1 -1
  164. package/dist/src/paramRuntime/paramUtils.js +61 -1
  165. package/dist/src/paramRuntime/viewParamRuntime.d.ts +32 -0
  166. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -1
  167. package/dist/src/paramRuntime/viewParamRuntime.js +63 -0
  168. package/dist/src/scales/axisResolution.d.ts +35 -0
  169. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  170. package/dist/src/scales/axisResolution.js +115 -7
  171. package/dist/src/scales/domainExpressions.d.ts +21 -0
  172. package/dist/src/scales/domainExpressions.d.ts.map +1 -0
  173. package/dist/src/scales/domainExpressions.js +43 -0
  174. package/dist/src/scales/domainPlanner.d.ts +12 -1
  175. package/dist/src/scales/domainPlanner.d.ts.map +1 -1
  176. package/dist/src/scales/domainPlanner.js +55 -36
  177. package/dist/src/scales/legendResolution.d.ts +83 -0
  178. package/dist/src/scales/legendResolution.d.ts.map +1 -0
  179. package/dist/src/scales/legendResolution.js +461 -0
  180. package/dist/src/scales/scaleInstanceManager.d.ts +1 -0
  181. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  182. package/dist/src/scales/scaleInstanceManager.js +5 -0
  183. package/dist/src/scales/scalePropsResolver.d.ts +6 -1
  184. package/dist/src/scales/scalePropsResolver.d.ts.map +1 -1
  185. package/dist/src/scales/scalePropsResolver.js +35 -10
  186. package/dist/src/scales/scaleResolution.d.ts +52 -0
  187. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  188. package/dist/src/scales/scaleResolution.js +195 -16
  189. package/dist/src/scales/scaleRules.d.ts +10 -0
  190. package/dist/src/scales/scaleRules.d.ts.map +1 -1
  191. package/dist/src/scales/scaleRules.js +38 -1
  192. package/dist/src/scales/viewLevelGuideConfig.d.ts +53 -0
  193. package/dist/src/scales/viewLevelGuideConfig.d.ts.map +1 -0
  194. package/dist/src/scales/viewLevelGuideConfig.js +224 -0
  195. package/dist/src/scales/viewLevelScaleConfig.d.ts +45 -0
  196. package/dist/src/scales/viewLevelScaleConfig.d.ts.map +1 -0
  197. package/dist/src/scales/viewLevelScaleConfig.js +149 -0
  198. package/dist/src/spec/axis.d.ts +109 -3
  199. package/dist/src/spec/channel.d.ts +23 -4
  200. package/dist/src/spec/config.d.ts +59 -4
  201. package/dist/src/spec/data.d.ts +177 -17
  202. package/dist/src/spec/legend.d.ts +246 -0
  203. package/dist/src/spec/mark.d.ts +16 -4
  204. package/dist/src/spec/scale.d.ts +19 -6
  205. package/dist/src/spec/title.d.ts +58 -1
  206. package/dist/src/spec/transform.d.ts +149 -0
  207. package/dist/src/spec/view.d.ts +50 -6
  208. package/dist/src/styles/genome-spy.css +4 -1
  209. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  210. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  211. package/dist/src/styles/genome-spy.css.js +4 -1
  212. package/dist/src/types/embedApi.d.ts +262 -6
  213. package/dist/src/types/rendering.d.ts +19 -3
  214. package/dist/src/types/viewContext.d.ts +18 -2
  215. package/dist/src/utils/arrayUtils.d.ts +11 -0
  216. package/dist/src/utils/arrayUtils.d.ts.map +1 -1
  217. package/dist/src/utils/arrayUtils.js +23 -0
  218. package/dist/src/utils/suspension.d.ts +17 -0
  219. package/dist/src/utils/suspension.d.ts.map +1 -0
  220. package/dist/src/utils/suspension.js +41 -0
  221. package/dist/src/utils/ui/tooltip.d.ts +4 -0
  222. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  223. package/dist/src/utils/ui/tooltip.js +35 -10
  224. package/dist/src/view/axisGridView.d.ts.map +1 -1
  225. package/dist/src/view/axisGridView.js +1 -4
  226. package/dist/src/view/axisView.d.ts +18 -2
  227. package/dist/src/view/axisView.d.ts.map +1 -1
  228. package/dist/src/view/axisView.js +180 -75
  229. package/dist/src/view/concatView.d.ts +10 -2
  230. package/dist/src/view/concatView.d.ts.map +1 -1
  231. package/dist/src/view/concatView.js +46 -9
  232. package/dist/src/view/containerMutationHelper.d.ts +20 -1
  233. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  234. package/dist/src/view/containerMutationHelper.js +203 -32
  235. package/dist/src/view/facetView.d.ts +1 -1
  236. package/dist/src/view/gridView/gridChild.d.ts +54 -4
  237. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  238. package/dist/src/view/gridView/gridChild.js +301 -120
  239. package/dist/src/view/gridView/gridChildLegends.d.ts +57 -0
  240. package/dist/src/view/gridView/gridChildLegends.d.ts.map +1 -0
  241. package/dist/src/view/gridView/gridChildLegends.js +503 -0
  242. package/dist/src/view/gridView/gridView.d.ts +25 -0
  243. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  244. package/dist/src/view/gridView/gridView.js +454 -78
  245. package/dist/src/view/gridView/legendLayout.d.ts +26 -0
  246. package/dist/src/view/gridView/legendLayout.d.ts.map +1 -0
  247. package/dist/src/view/gridView/legendLayout.js +111 -0
  248. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  249. package/dist/src/view/gridView/scrollbar.js +1 -4
  250. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  251. package/dist/src/view/gridView/selectionRect.js +1 -4
  252. package/dist/src/view/gridView/separatorView.d.ts.map +1 -1
  253. package/dist/src/view/gridView/separatorView.js +1 -4
  254. package/dist/src/view/layerView.d.ts +9 -2
  255. package/dist/src/view/layerView.d.ts.map +1 -1
  256. package/dist/src/view/layerView.js +18 -1
  257. package/dist/src/view/layout/flexLayout.d.ts +20 -4
  258. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  259. package/dist/src/view/layout/flexLayout.js +331 -31
  260. package/dist/src/view/layout/rectangle.d.ts +14 -0
  261. package/dist/src/view/layout/rectangle.d.ts.map +1 -1
  262. package/dist/src/view/layout/rectangle.js +40 -0
  263. package/dist/src/view/legend/legendEntries.d.ts +20 -0
  264. package/dist/src/view/legend/legendEntries.d.ts.map +1 -0
  265. package/dist/src/view/legend/legendEntries.js +21 -0
  266. package/dist/src/view/legendView.d.ts +134 -0
  267. package/dist/src/view/legendView.d.ts.map +1 -0
  268. package/dist/src/view/legendView.js +1611 -0
  269. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
  270. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +26 -4
  271. package/dist/src/view/renderingContext/clipOptions.d.ts +44 -0
  272. package/dist/src/view/renderingContext/clipOptions.d.ts.map +1 -0
  273. package/dist/src/view/renderingContext/clipOptions.js +140 -0
  274. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -1
  275. package/dist/src/view/renderingContext/simpleViewRenderingContext.js +12 -1
  276. package/dist/src/view/resolutionPlanner.d.ts +2 -1
  277. package/dist/src/view/resolutionPlanner.d.ts.map +1 -1
  278. package/dist/src/view/resolutionPlanner.js +89 -25
  279. package/dist/src/view/testUtils.d.ts +4 -2
  280. package/dist/src/view/testUtils.d.ts.map +1 -1
  281. package/dist/src/view/testUtils.js +29 -7
  282. package/dist/src/view/titleView.d.ts +37 -0
  283. package/dist/src/view/titleView.d.ts.map +1 -0
  284. package/dist/src/view/titleView.js +584 -0
  285. package/dist/src/view/unitView.d.ts +3 -3
  286. package/dist/src/view/unitView.d.ts.map +1 -1
  287. package/dist/src/view/unitView.js +3 -2
  288. package/dist/src/view/view.d.ts +25 -24
  289. package/dist/src/view/view.d.ts.map +1 -1
  290. package/dist/src/view/view.js +121 -16
  291. package/dist/src/view/viewFactory.d.ts +2 -5
  292. package/dist/src/view/viewFactory.d.ts.map +1 -1
  293. package/dist/src/view/viewFactory.js +1 -2
  294. package/dist/src/view/viewIdentityRegistry.d.ts +37 -0
  295. package/dist/src/view/viewIdentityRegistry.d.ts.map +1 -0
  296. package/dist/src/view/viewIdentityRegistry.js +71 -0
  297. package/dist/src/view/viewMutationAcidTestUtils.d.ts +112 -0
  298. package/dist/src/view/viewMutationAcidTestUtils.d.ts.map +1 -0
  299. package/dist/src/view/viewMutationAcidTestUtils.js +234 -0
  300. package/dist/src/view/viewMutationApi.d.ts +42 -0
  301. package/dist/src/view/viewMutationApi.d.ts.map +1 -0
  302. package/dist/src/view/viewMutationApi.js +811 -0
  303. package/dist/src/view/viewSelectors.d.ts +10 -0
  304. package/dist/src/view/viewSelectors.d.ts.map +1 -1
  305. package/dist/src/view/viewSelectors.js +23 -1
  306. package/package.json +4 -4
  307. package/dist/bundle/esm-0dYHNV_D.js +0 -121
  308. package/dist/bundle/esm-C49STiCR.js +0 -1248
  309. package/dist/bundle/esm-CscjKVDc.js +0 -1426
  310. package/dist/bundle/esm-CuMSzCHy.js +0 -298
  311. package/dist/bundle/esm-DMXpJXM4.js +0 -369
  312. package/dist/src/view/title.d.ts +0 -13
  313. package/dist/src/view/title.d.ts.map +0 -1
  314. package/dist/src/view/title.js +0 -154
  315. /package/dist/bundle/{AbortablePromiseCache-3gHJdF3E.js → AbortablePromiseCache-BTmAcN-t.js} +0 -0
  316. /package/dist/bundle/{esm-CuVa5T98.js → esm-VvpZ9hsq.js} +0 -0
  317. /package/dist/bundle/{chunk-DmhlhrBa.js → rolldown-runtime-Dy4uBu1J.js} +0 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @typedef {import("./bmFontManager.js").BMFontMetrics} BMFontMetrics
3
+ * @typedef {import("../spec/font.js").FontStyle} FontStyle
4
+ * @typedef {import("../spec/font.js").FontWeight} FontWeight
5
+ * @typedef {{ metrics?: BMFontMetrics, texture?: WebGLTexture }} FontEntryLike
6
+ * @typedef {{
7
+ * font?: string,
8
+ * fontStyle?: FontStyle,
9
+ * fontWeight?: FontWeight,
10
+ * }} FontConfig
11
+ * @typedef {{
12
+ * getDefaultFont: () => FontEntryLike,
13
+ * getFont: (
14
+ * family?: string,
15
+ * style?: FontStyle,
16
+ * weight?: FontWeight
17
+ * ) => FontEntryLike,
18
+ * }} FontManagerLike
19
+ */
20
+
21
+ /**
22
+ * Requests a font entry and registers asynchronous loading for custom fonts.
23
+ *
24
+ * @param {FontManagerLike} fontManager
25
+ * @param {FontConfig} config
26
+ * @returns {FontEntryLike}
27
+ */
28
+ export function requestFont(fontManager, config) {
29
+ return fontManager.getFont(
30
+ config.font,
31
+ config.fontStyle,
32
+ config.fontWeight
33
+ );
34
+ }
35
+
36
+ /**
37
+ * @param {BMFontMetrics} metrics
38
+ * @param {number} fontSize
39
+ */
40
+ export function getTextHeight(metrics, fontSize) {
41
+ return (
42
+ ((metrics.capHeight + metrics.descent) / metrics.common.base) * fontSize
43
+ );
44
+ }
45
+
46
+ /**
47
+ * @param {BMFontMetrics} metrics
48
+ * @param {string} text
49
+ * @param {number} fontSize
50
+ */
51
+ export function measureText(metrics, text, fontSize) {
52
+ return {
53
+ width: metrics.measureWidth(text, fontSize),
54
+ height: getTextHeight(metrics, fontSize),
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Returns the projected text extent along a layout direction after rotation.
60
+ *
61
+ * @param {{ width: number, height: number }} size
62
+ * @param {number} angle
63
+ * @param {"horizontal" | "vertical"} direction
64
+ */
65
+ export function getProjectedTextExtent(size, angle, direction) {
66
+ const radians = (angle * Math.PI) / 180;
67
+ const absSin = Math.abs(Math.sin(radians));
68
+ const absCos = Math.abs(Math.cos(radians));
69
+
70
+ return direction == "vertical"
71
+ ? size.width * absSin + size.height * absCos
72
+ : size.width * absCos + size.height * absSin;
73
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"headlessBootstrap.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/headlessBootstrap.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"headlessBootstrap.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/headlessBootstrap.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,oDAhCW;IACN,kBAAkB,CAAC,EAAE,OAAO,wBAAwB,EAAE,kBAAkB,CAAC;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,sBAAsB,EAAE,OAAO,CAAC;IAClD,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAClD,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,CAAC;IAC/D,eAAe,CAAC,EAAE,MAAM,GAAG,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9E,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,CACpB,IAAI,EAAE,SAAS,GAAG,OAAO,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,KACrC,IAAI,CAAC;IACV,oBAAoB,CAAC,EAAE,CACrB,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAClD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,KACpE,IAAI,CAAC;IACV,uBAAuB,CAAC,EAAE,CACxB,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAClD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,KACpE,IAAI,CAAC;IACV,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IACzE,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,KAAK,OAAO,CAAC;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,sBAAsB,EAAE,OAAO,CAAC;CACnD,GACS,WAAW,CA4DvB;AAED;;;;GAIG;AACH,+CAFW,OAAO,iBAAiB,EAAE,OAAO,QAK3C;AAED;;;;;;;;;;;GAWG;AACH,2CARW,QAAQ,YACR;IACN,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CAChD,GACS,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAiCtF;AAED;;;;;;;;;;;GAWG;AACH,kDARW,QAAQ,YACR;IACN,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,kBAAkB,CAAC,EAAE,OAAO,wBAAwB,EAAE,kBAAkB,CAAC;CAC1E,GACS,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAwBtF;;;;uBA1PY,OAAO,iBAAiB,EAAE,QAAQ;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO;qBAGjC,qBAAqB;wBAClB,0BAA0B;0BACxB,2BAA2B;kCAGnB,4BAA4B"}
@@ -14,6 +14,11 @@ import { resolveBaseConfig } from "../config/resolveConfig.js";
14
14
  import { createViewContext } from "./viewContextFactory.js";
15
15
  import { ViewFactory, VIEW_ROOT_NAME } from "../view/viewFactory.js";
16
16
  import { ensureAssembliesForView } from "../genome/assemblyPreflight.js";
17
+ import { attachViewLevelScaleConfigs } from "../scales/viewLevelScaleConfig.js";
18
+ import {
19
+ attachViewLevelAxisConfigs,
20
+ attachViewLevelLegendConfigs,
21
+ } from "../scales/viewLevelGuideConfig.js";
17
22
  import {
18
23
  configureViewHierarchy,
19
24
  configureViewOpacity,
@@ -196,6 +201,9 @@ export async function createHeadlessEngine(spec, options = {}) {
196
201
  VIEW_ROOT_NAME
197
202
  );
198
203
 
204
+ attachViewLevelScaleConfigs(view);
205
+ attachViewLevelAxisConfigs(view);
206
+ attachViewLevelLegendConfigs(view);
199
207
  await ensureAssembliesForView(view, context.genomeStore);
200
208
  prepareViewHierarchy(view);
201
209
 
@@ -30,7 +30,10 @@ export default class InteractionController {
30
30
  * @param {MouseEvent} [mouseEvent]
31
31
  */
32
32
  resumeHoverTracking(mouseEvent?: MouseEvent): void;
33
- registerInteractionEvents(): void;
33
+ /**
34
+ * @returns {() => void}
35
+ */
36
+ registerInteractionEvents(): () => void;
34
37
  /**
35
38
  * This method should be called in a mouseMove handler. If not called, the
36
39
  * tooltip will be hidden.
@@ -1 +1 @@
1
- {"version":3,"file":"interactionController.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/interactionController.js"],"names":[],"mappings":"AAWA;IAoCI;;;;;;;;;;OAUG;IACH,mIATG;QAAmD,QAAQ,EAAnD,OAAO,iBAAiB,EAAE,OAAO;QACe,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QACY,OAAO,EAAzD,OAAO,wBAAwB,EAAE,OAAO;QACQ,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QACM,SAAS,EAArD,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI;QAC6C,eAAe,EAA9F,MAAM,CAAC,MAAM,EAAE,OAAO,8BAA8B,EAAE,cAAc,CAAC;QACjD,wBAAwB,EAA5C,MAAM,IAAI;QACY,mBAAmB,EAAzC,MAAM,MAAM;KACtB,EAiCA;IAED;cA3DkB,OAAO,kBAAkB,EAAE,OAAO;eAAS,OAAO,qBAAqB,EAAE,KAAK;kBAAY,MAAM;MA6DjH;IAED,6BAQC;IAED;;OAEG;IACH,iCAFW,UAAU,QA8CpB;IAED,kCAycC;IA+JD;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAgBlF;;CACJ;8BAGY;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC"}
1
+ {"version":3,"file":"interactionController.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/interactionController.js"],"names":[],"mappings":"AAWA;IA2CI;;;;;;;;;;OAUG;IACH,mIATG;QAAmD,QAAQ,EAAnD,OAAO,iBAAiB,EAAE,OAAO;QACe,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QACY,OAAO,EAAzD,OAAO,wBAAwB,EAAE,OAAO;QACQ,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QACM,SAAS,EAArD,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI;QAC6C,eAAe,EAA9F,MAAM,CAAC,MAAM,EAAE,OAAO,8BAA8B,EAAE,cAAc,CAAC;QACjD,wBAAwB,EAA5C,MAAM,IAAI;QACY,mBAAmB,EAAzC,MAAM,MAAM;KACtB,EAiCA;IAED;cAlEkB,OAAO,kBAAkB,EAAE,OAAO;eAAS,OAAO,qBAAqB,EAAE,KAAK;kBAAY,MAAM;MAoEjH;IAED,6BAQC;IAED;;OAEG;IACH,iCAFW,UAAU,QA8CpB;IAED;;OAEG;IACH,6BAFa,MAAM,IAAI,CA6etB;IA+JD;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAgBlF;;CACJ;8BAGY;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC"}
@@ -45,6 +45,13 @@ export default class InteractionController {
45
45
  #suppressTooltipUntilMouseMove = false;
46
46
  #hoverTrackingSuspensionCount = 0;
47
47
  #postRenderHoverRefreshRequested = false;
48
+
49
+ #dismissStickyTooltip() {
50
+ this.#tooltip.sticky = false;
51
+ this.#suppressTooltipUntilMouseMove = true;
52
+ this.#tooltip.clear();
53
+ }
54
+
48
55
  /**
49
56
  * @param {object} options
50
57
  * @param {import("../view/view.js").default} options.viewRoot
@@ -153,14 +160,49 @@ export default class InteractionController {
153
160
  this.#cursorManager.clear();
154
161
  }
155
162
 
163
+ /**
164
+ * @returns {() => void}
165
+ */
156
166
  registerInteractionEvents() {
157
167
  const canvas = this.#glHelper.canvas;
168
+ /** @type {Array<() => void>} */
169
+ const removers = [];
170
+
171
+ /**
172
+ * @param {EventTarget} target
173
+ * @param {string} type
174
+ * @param {EventListener} listener
175
+ * @param {AddEventListenerOptions} [options]
176
+ */
177
+ const addListener = (target, type, listener, options) => {
178
+ target.addEventListener(type, listener, options);
179
+ removers.push(() =>
180
+ target.removeEventListener(type, listener, options)
181
+ );
182
+ };
158
183
 
159
184
  let lastWheelEvent = performance.now();
160
185
  let longPressTriggered = false;
161
186
  /** @type {{ pointerCount: 1 | 2, centerX: number, centerY: number, distance: number } | undefined} */
162
187
  let previousTouchGesture;
163
188
 
189
+ if (globalThis.document?.addEventListener) {
190
+ addListener(
191
+ document,
192
+ "mousedown",
193
+ (/** @type {MouseEvent} */ event) => {
194
+ if (
195
+ this.#tooltip.sticky &&
196
+ !event.composedPath().includes(canvas) &&
197
+ !this.#tooltip.containsEvent(event)
198
+ ) {
199
+ this.#dismissStickyTooltip();
200
+ }
201
+ },
202
+ { capture: true }
203
+ );
204
+ }
205
+
164
206
  /**
165
207
  * @param {Point} point
166
208
  * @param {import("../utils/interactionEvent.js").InteractionUiEvent} uiEvent
@@ -343,15 +385,13 @@ export default class InteractionController {
343
385
  }
344
386
  };
345
387
 
346
- canvas.addEventListener("mousedown", (/** @type {MouseEvent} */ e) => {
388
+ addListener(canvas, "mousedown", (/** @type {MouseEvent} */ e) => {
347
389
  this.#mouseDownCoords = Point.fromMouseEvent(e);
348
390
  this.#longPressPending = false;
349
391
  const hasModifier = e.shiftKey || e.ctrlKey || e.metaKey;
350
392
 
351
393
  if (this.#tooltip.sticky) {
352
- this.#tooltip.sticky = false;
353
- this.#suppressTooltipUntilMouseMove = true;
354
- this.#tooltip.clear();
394
+ this.#dismissStickyTooltip();
355
395
  // Dismiss the sticky tooltip before routing the press so the
356
396
  // click only affects the tooltip state.
357
397
  longPressTriggered = true;
@@ -427,7 +467,7 @@ export default class InteractionController {
427
467
  "mousemove",
428
468
  "contextmenu",
429
469
  "dblclick",
430
- ].forEach((type) => canvas.addEventListener(type, listener));
470
+ ].forEach((type) => addListener(canvas, type, listener));
431
471
 
432
472
  /**
433
473
  * @param {number} clientX
@@ -574,25 +614,23 @@ export default class InteractionController {
574
614
  previousTouchGesture = readTouchGesture(touchEvent.touches);
575
615
  };
576
616
 
577
- canvas.addEventListener("touchstart", handleTouchStartOrMove, {
617
+ addListener(canvas, "touchstart", handleTouchStartOrMove, {
578
618
  passive: false,
579
619
  });
580
- canvas.addEventListener("touchmove", handleTouchStartOrMove, {
620
+ addListener(canvas, "touchmove", handleTouchStartOrMove, {
581
621
  passive: false,
582
622
  });
583
- canvas.addEventListener("touchend", handleTouchEndOrCancel, {
623
+ addListener(canvas, "touchend", handleTouchEndOrCancel, {
584
624
  passive: false,
585
625
  });
586
- canvas.addEventListener("touchcancel", handleTouchEndOrCancel, {
626
+ addListener(canvas, "touchcancel", handleTouchEndOrCancel, {
587
627
  passive: false,
588
628
  });
589
629
 
590
630
  // Prevent text selections etc while dragging
591
- canvas.addEventListener("dragstart", (event) =>
592
- event.stopPropagation()
593
- );
631
+ addListener(canvas, "dragstart", (event) => event.stopPropagation());
594
632
 
595
- canvas.addEventListener("mouseout", (event) => {
633
+ addListener(canvas, "mouseout", (event) => {
596
634
  if (this.#isInteractionFrozen()) {
597
635
  return;
598
636
  }
@@ -610,6 +648,12 @@ export default class InteractionController {
610
648
  this.#tooltip.clear();
611
649
  this.#currentHover = null;
612
650
  });
651
+
652
+ return () => {
653
+ for (const remove of removers) {
654
+ remove();
655
+ }
656
+ };
613
657
  }
614
658
 
615
659
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"renderCoordinator.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/renderCoordinator.js"],"names":[],"mappings":"AAIA;IAiBI;;;;;;;OAOG;IACH,iFANG;QAAmD,QAAQ,EAAnD,OAAO,iBAAiB,EAAE,OAAO;QACe,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QAChB,aAAa,EAAnC,MAAM,MAAM;QACyE,SAAS,EAA9F,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI;QACvD,gBAAgB,EAApC,MAAM,IAAI;KACpB,EAqBA;IAED,sBAkDC;IAED,kBAIC;IAED,iCAOC;;CACJ"}
1
+ {"version":3,"file":"renderCoordinator.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/renderCoordinator.js"],"names":[],"mappings":"AAIA;IAiBI;;;;;;;OAOG;IACH,iFANG;QAAmD,QAAQ,EAAnD,OAAO,iBAAiB,EAAE,OAAO;QACe,QAAQ,EAAxD,OAAO,sBAAsB,EAAE,OAAO;QAChB,aAAa,EAAnC,MAAM,MAAM;QACyE,SAAS,EAA9F,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI;QACvD,gBAAgB,EAApC,MAAM,IAAI;KACpB,EAqBA;IAED,sBA2BC;IA+CD,kBAIC;IAED,iCAOC;;CACJ"}
@@ -57,6 +57,29 @@ export default class RenderCoordinator {
57
57
 
58
58
  this.#broadcast("layout");
59
59
 
60
+ // Layout may change the root-derived canvas size. Start with a fresh
61
+ // size, then repeat only if the pass caused the applied canvas size to
62
+ // change so buffered render commands use current dimensions.
63
+ this.#glHelper.invalidateSize();
64
+ let remainingPasses = 5;
65
+ while (this.#computeLayoutPass()) {
66
+ if (!this.#glHelper.invalidateSize()) {
67
+ this.#onLayoutComputed();
68
+ this.#broadcast("layoutComputed");
69
+ return;
70
+ }
71
+
72
+ remainingPasses--;
73
+ if (remainingPasses == 0) {
74
+ throw new Error(
75
+ "Layout did not settle: canvas size kept changing."
76
+ );
77
+ }
78
+ }
79
+ }
80
+
81
+ #computeLayoutPass() {
82
+ const root = this.#viewRoot;
60
83
  const canvasSize = this.#glHelper.getLogicalCanvasSize();
61
84
 
62
85
  if (isNaN(canvasSize.width) || isNaN(canvasSize.height)) {
@@ -64,7 +87,7 @@ export default class RenderCoordinator {
64
87
  console.log(
65
88
  `NaN in canvas size: ${canvasSize.width}x${canvasSize.height}. Skipping computeLayout().`
66
89
  );
67
- return;
90
+ return false;
68
91
  }
69
92
 
70
93
  const commonOptions = {
@@ -97,8 +120,7 @@ export default class RenderCoordinator {
97
120
  Rectangle.create(0, 0, canvasSize.width, canvasSize.height)
98
121
  );
99
122
 
100
- this.#onLayoutComputed();
101
- this.#broadcast("layoutComputed");
123
+ return true;
102
124
  }
103
125
 
104
126
  renderAll() {
@@ -19,4 +19,18 @@ export function initializeViewData(viewRoot: import("../view/view.js").default,
19
19
  * @returns {Promise<import("../data/dataFlow.js").default>}
20
20
  */
21
21
  export function initializeVisibleViewData(viewRoot: import("../view/view.js").default, dataFlow: import("../data/dataFlow.js").default, fontManager: import("../fonts/bmFontManager.js").default): Promise<import("../data/dataFlow.js").default>;
22
+ /**
23
+ * Initializes dataflow/graphics for selected views while avoiding unnecessary
24
+ * data source reloads.
25
+ *
26
+ * If a selected view attaches downstream of an already completed collector,
27
+ * the collector is repropagated instead of reloading the source.
28
+ *
29
+ * @param {import("../view/view.js").default} viewRoot
30
+ * @param {import("../data/dataFlow.js").default} dataFlow
31
+ * @param {import("../fonts/bmFontManager.js").default} fontManager
32
+ * @param {Iterable<import("../view/view.js").default>} candidateViews
33
+ * @returns {Promise<import("../data/dataFlow.js").default>}
34
+ */
35
+ export function initializeViewDataForViews(viewRoot: import("../view/view.js").default, dataFlow: import("../data/dataFlow.js").default, fontManager: import("../fonts/bmFontManager.js").default, candidateViews: Iterable<import("../view/view.js").default>): Promise<import("../data/dataFlow.js").default>;
22
36
  //# sourceMappingURL=viewDataInit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"viewDataInit.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewDataInit.js"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,6CANW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,mBAC3C,CAAC,QAAQ,EAAE,OAAO,qBAAqB,EAAE,OAAO,KAAK,IAAI,GACvD,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAoC1D;AAED;;;;;;;;GAQG;AACH,oDALW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,GACzC,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CA6E1D"}
1
+ {"version":3,"file":"viewDataInit.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewDataInit.js"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,6CANW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,mBAC3C,CAAC,QAAQ,EAAE,OAAO,qBAAqB,EAAE,OAAO,KAAK,IAAI,GACvD,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAoC1D;AAED;;;;;;;;GAQG;AACH,oDALW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,GACzC,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAqB1D;AAED;;;;;;;;;;;;GAYG;AACH,qDANW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,kBAC3C,QAAQ,CAAC,OAAO,iBAAiB,EAAE,OAAO,CAAC,GACzC,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CA+E1D"}
@@ -1,4 +1,5 @@
1
1
  import {
2
+ broadcastSubtreeDataReady,
2
3
  initializeViewSubtree,
3
4
  loadViewSubtreeData,
4
5
  } from "../data/flowInit.js";
@@ -38,6 +39,8 @@ export async function initializeViewData(
38
39
  // await fonts inside text mark graphics updates and before loading data for
39
40
  // subtrees that contain measureText transforms.
40
41
  await fontManager.waitUntilReady();
42
+ viewRoot.invalidateSizeCache();
43
+ await finalizeSubtreeGraphics(graphicsPromises);
41
44
 
42
45
  // Find all data sources and initiate loading.
43
46
  await loadViewSubtreeData(
@@ -46,8 +49,6 @@ export async function initializeViewData(
46
49
  visibilityPredicate
47
50
  );
48
51
 
49
- await finalizeSubtreeGraphics(graphicsPromises);
50
-
51
52
  return builtDataFlow;
52
53
  }
53
54
 
@@ -65,10 +66,6 @@ export async function initializeVisibleViewData(
65
66
  dataFlow,
66
67
  fontManager
67
68
  ) {
68
- // Initialize dataflow/graphics for views that have become visible since the
69
- // initial load, while avoiding unnecessary data source reloads. If a view
70
- // attaches downstream of an already completed collector, repropagate that
71
- // collector instead of reloading the source.
72
69
  const visibilityPredicate = (
73
70
  /** @type {import("../view/view.js").default} */ view
74
71
  ) => view.isConfiguredVisible();
@@ -77,6 +74,45 @@ export async function initializeVisibleViewData(
77
74
  (view) => view.getDataInitializationState() === "none"
78
75
  );
79
76
 
77
+ return initializeViewDataForViews(
78
+ viewRoot,
79
+ dataFlow,
80
+ fontManager,
81
+ viewsToInitialize
82
+ );
83
+ }
84
+
85
+ /**
86
+ * Initializes dataflow/graphics for selected views while avoiding unnecessary
87
+ * data source reloads.
88
+ *
89
+ * If a selected view attaches downstream of an already completed collector,
90
+ * the collector is repropagated instead of reloading the source.
91
+ *
92
+ * @param {import("../view/view.js").default} viewRoot
93
+ * @param {import("../data/dataFlow.js").default} dataFlow
94
+ * @param {import("../fonts/bmFontManager.js").default} fontManager
95
+ * @param {Iterable<import("../view/view.js").default>} candidateViews
96
+ * @returns {Promise<import("../data/dataFlow.js").default>}
97
+ */
98
+ export async function initializeViewDataForViews(
99
+ viewRoot,
100
+ dataFlow,
101
+ fontManager,
102
+ candidateViews
103
+ ) {
104
+ const candidates = new Set(candidateViews);
105
+ const visibilityPredicate = (
106
+ /** @type {import("../view/view.js").default} */ view
107
+ ) => view.isConfiguredVisible();
108
+ const viewsToInitialize = collectVisibleViews(
109
+ viewRoot,
110
+ visibilityPredicate
111
+ ).filter(
112
+ (view) =>
113
+ candidates.has(view) && view.getDataInitializationState() === "none"
114
+ );
115
+
80
116
  if (viewsToInitialize.length === 0) {
81
117
  return dataFlow;
82
118
  }
@@ -113,6 +149,8 @@ export async function initializeVisibleViewData(
113
149
  // Newly visible subtrees may introduce text marks or measureText transforms
114
150
  // that request fonts during initializeViewSubtree.
115
151
  await fontManager.waitUntilReady();
152
+ viewRoot.invalidateSizeCache();
153
+ await finalizeSubtreeGraphics(graphicsPromises);
116
154
 
117
155
  for (const collector of collectorsToRepropagate) {
118
156
  collector.repropagate();
@@ -131,8 +169,7 @@ export async function initializeVisibleViewData(
131
169
  )
132
170
  );
133
171
  }
134
-
135
- await finalizeSubtreeGraphics(graphicsPromises);
172
+ broadcastSubtreeDataReady(viewRoot);
136
173
 
137
174
  return builtDataFlow;
138
175
  }
@@ -24,6 +24,8 @@ export default class GenomeSpy {
24
24
  /** @type {(function(string):object[])[]} */
25
25
  namedDataProviders: ((arg0: string) => object[])[];
26
26
  animator: Animator;
27
+ /** @type {(timestamp?: number) => void} */
28
+ _layoutReflowTransition: (timestamp?: number) => void;
27
29
  /** @type {GenomeStore} */
28
30
  genomeStore: GenomeStore;
29
31
  /**
@@ -122,6 +124,10 @@ export default class GenomeSpy {
122
124
  height: number | undefined;
123
125
  };
124
126
  computeLayout(): void;
127
+ /**
128
+ * Recomputes layout and schedules the buffered render commands to be drawn.
129
+ */
130
+ requestLayoutReflow(): void;
125
131
  renderAll(): void;
126
132
  renderPickingFramebuffer(): void;
127
133
  getSearchableViews(): UnitView<import("./spec/view.js").UnitSpec>[];
@@ -1 +1 @@
1
- {"version":3,"file":"genomeSpyBase.d.ts","sourceRoot":"","sources":["../../src/genomeSpyBase.js"],"names":[],"mappings":"AA+CA;;;GAGG;AAEH;IAoBI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA0CpD;IAvCG,uBAA0B;IAC1B,oDAAsB;IAItB,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,qEAAM,KAAK,OAAO,CAE8B;IAE/D,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,8EAAyB;IAIzB,YAAkC;IAatC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;;OAIG;IACH,eAFW,MAAM,oFAIhB;IAED;;;OAGG;IACH,uBAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;OAGG;IACH,0BAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAMb;IAmEG,iDAAsB;IAQ1B;;OAEG;IACH,gBAqBC;IA0ND;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CAyC5B;IAED,2CAiBC;IAED;;;;;OAKG;IACH,8BAFW,WAAW,iBAerB;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAKlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UAuBhB;IAED;;;MAEC;IAED;eACwB,MAAM,GAAG,SAAS;gBAAU,MAAM,GAAG,SAAS;MAcrE;IAED,sBAGC;IAED,kBAEC;IAED,iCAEC;IAED,oEAYC;IAED,uFAWC;;CACJ;;;;iCAzpBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BAvBnC,uBAAuB;qBAP9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}
1
+ {"version":3,"file":"genomeSpyBase.d.ts","sourceRoot":"","sources":["../../src/genomeSpyBase.js"],"names":[],"mappings":"AAoDA;;;GAGG;AAEH;IAoBI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA+CpD;IA5CG,uBAA0B;IAC1B,oDAAsB;IAItB,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAIpD,2CAA2C;IAC3C,yBADW,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CACkB;IAEzD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,qEAAM,KAAK,OAAO,CAE8B;IAE/D,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,8EAAyB;IAIzB,YAAkC;IAatC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;;OAIG;IACH,eAFW,MAAM,oFAIhB;IAED;;;OAGG;IACH,uBAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;OAGG;IACH,0BAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAMb;IAmEG,iDAAsB;IAQ1B;;OAEG;IACH,gBAqBC;IA6ND;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CA2C5B;IAED,2CAiBC;IAED;;;;;OAKG;IACH,8BAFW,WAAW,iBAerB;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAKlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UAuBhB;IAED;;;MAEC;IAED;eACwB,MAAM,GAAG,SAAS;gBAAU,MAAM,GAAG,SAAS;MAcrE;IAED,sBAEC;IAED;;OAEG;IACH,4BAEC;IAED,kBAEC;IAED,iCAEC;IAED,oEAYC;IAED,uFAWC;;CACJ;;;;iCAzqBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BA5BnC,uBAAuB;qBAP9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}
@@ -34,6 +34,11 @@ import { validateSelectorConstraints } from "./view/viewSelectors.js";
34
34
  import { resolveEmbedParam } from "./paramRuntime/embedParamApi.js";
35
35
  import SingleAxisWindowedSource from "./data/sources/lazy/singleAxisWindowedSource.js";
36
36
  import { ensureAssembliesForView } from "./genome/assemblyPreflight.js";
37
+ import { attachViewLevelScaleConfigs } from "./scales/viewLevelScaleConfig.js";
38
+ import {
39
+ attachViewLevelAxisConfigs,
40
+ attachViewLevelLegendConfigs,
41
+ } from "./scales/viewLevelGuideConfig.js";
37
42
  import { resolveRootGenomeConfig } from "./genome/rootGenomeConfig.js";
38
43
  import { awaitSubtreeLazyReady } from "./view/dataReadiness.js";
39
44
  import { INTERNAL_DEFAULT_CONFIG } from "./config/defaultConfig.js";
@@ -99,6 +104,11 @@ export default class GenomeSpy {
99
104
 
100
105
  this.animator = new Animator(() => this.renderAll());
101
106
 
107
+ // Use a stable callback identity so repeated layout requests coalesce
108
+ // in Animator's transition queue before the next render.
109
+ /** @type {(timestamp?: number) => void} */
110
+ this._layoutReflowTransition = () => this.computeLayout();
111
+
102
112
  /** @type {GenomeStore} */
103
113
  this.genomeStore = undefined;
104
114
 
@@ -439,6 +449,9 @@ export default class GenomeSpy {
439
449
  // Reminder: assemblies must be ensured after view creation (imports and
440
450
  // inheritance resolved), but before any code path that may touch scales
441
451
  // (e.g. step-based sizes, dynamic opacity, encoder initialization).
452
+ attachViewLevelScaleConfigs(this.viewRoot);
453
+ attachViewLevelAxisConfigs(this.viewRoot);
454
+ attachViewLevelLegendConfigs(this.viewRoot);
442
455
  await ensureAssembliesForView(this.viewRoot, this.genomeStore);
443
456
 
444
457
  this.#loadingStatusRegistry.set(this.viewRoot, "loading");
@@ -484,7 +497,7 @@ export default class GenomeSpy {
484
497
 
485
498
  // Allow early layout requests from view subscriptions created during initialization.
486
499
  // Layout will be recomputed anyway once launch completes.
487
- context.requestLayoutReflow = this.computeLayout.bind(this);
500
+ context.requestLayoutReflow = this.requestLayoutReflow.bind(this);
488
501
 
489
502
  this.#setupDpr();
490
503
  }
@@ -505,7 +518,7 @@ export default class GenomeSpy {
505
518
  */
506
519
  #finalizeViewInitialization(context) {
507
520
  // Allow layout computation (in case a custom context overrode the early assignment).
508
- context.requestLayoutReflow = this.computeLayout.bind(this);
521
+ context.requestLayoutReflow = this.requestLayoutReflow.bind(this);
509
522
 
510
523
  // Invalidate cached sizes to ensure that step-based sizes are current.
511
524
  // TODO: This should be done automatically when the domains of band/point scales are updated.
@@ -535,7 +548,9 @@ export default class GenomeSpy {
535
548
 
536
549
  await this.#prepareViewsAndData();
537
550
 
538
- this.#interactionController.registerInteractionEvents();
551
+ this.#destructionCallbacks.push(
552
+ this.#interactionController.registerInteractionEvents()
553
+ );
539
554
 
540
555
  this.computeLayout();
541
556
  this.animator.requestRender();
@@ -675,7 +690,13 @@ export default class GenomeSpy {
675
690
 
676
691
  computeLayout() {
677
692
  this.#renderCoordinator.computeLayout();
678
- this.#glHelper.invalidateSize();
693
+ }
694
+
695
+ /**
696
+ * Recomputes layout and schedules the buffered render commands to be drawn.
697
+ */
698
+ requestLayoutReflow() {
699
+ this.animator.requestTransition(this._layoutReflowTransition);
679
700
  }
680
701
 
681
702
  renderAll() {
@@ -1,3 +1,20 @@
1
+ /**
2
+ * Gets the boundary values that the shader uses for discretizing scale buckets.
3
+ * Threshold scales expose the boundaries as their domain, while quantize scales
4
+ * derive them from the domain extent and range count.
5
+ *
6
+ * @param {any} scale
7
+ * @returns {number[]}
8
+ */
9
+ export function getDiscretizingDomainForGlsl(scale: any): number[];
10
+ /**
11
+ * Gets the number of buckets needed for a discrete or discretizing range
12
+ * texture.
13
+ *
14
+ * @param {any} scale
15
+ * @returns {number}
16
+ */
17
+ export function getDiscreteRangeCountForGlsl(scale: any): number;
1
18
  /**
2
19
  *
3
20
  * @param {Channel} channel
@@ -1 +1 @@
1
- {"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":"AAsDA;;;;;GAKG;AACH,kDAJW,OAAO,mBACP,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,mDALW,OAAO,mBACP,MAAM,SACN,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,GAClC,aAAa,CA4CzB;AAED;;;;;;;GAOG;AACH,4DAJW,OAAO,mBACP,MAAM,GACJ,aAAa,CAkCzB;AAED;;;;;;GAMG;AACH,0CANW,OAAO,SACP,GAAG,mBACH,MAAM,+BACN,OAAO,EAAE,GACP,aAAa,CA8BzB;AACD;;;;;GAKG;AACH,qDALW,OAAO,SACP,GAAG,mBACH,MAAM,GACJ,aAAa,CAyBzB;AAED;;;;;GAKG;AACH,2CAJW,OAAO,SACP,GAAG,cACH,OAAO,oBAAoB,EAAE,UAAU;;;;;;EAsQjD;AAED;;;;GAIG;AACH,wDAHW,OAAO,YACP,OAAO,qBAAqB,EAAE,cAAc,EAAE,UA+BxD;AAmED;;GAEG;AACH,qDAFW,OAAO,6BAQjB;AAuCD;;;;GAIG;AACH,iDAHW,OAAO,qBAAqB,EAAE,SAAS,WACvC,OAAO,oBAAoB,EAAE,OAAO;mBAQjB,MAAM;sBAAoB,sBAAsB,GAAG,sBAAsB,GAAG,uBAAuB;;;;;;EAoBhI;AAED;;;;GAIG;AACH,2CAFW,MAAM,6BAIhB;AAED;;;;GAIG;AACH,sCAFW,MAAM,EAAE,WAIlB;AAMD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAED;;;GAGG;AACH,2CAHW,MAAM,QACN,MAAM,EAAE,YAUlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AAwBD;;;;GAIG;AACH,uCAJW,MAAM,EAAE,cACR,MAAM,EAAE,GACN,MAAM,CAgClB;AAr0BD,+BAAgC,OAAO,CAAC;AACxC,4BAA6B,UAAU,CAAC;AACxC,2BAA4B,QAAQ,CAAC;AACrC,uCAAwC,WAAW,CAAC;AACpD,oCAAqC,QAAQ,CAAC;AAC9C,qCAAsC,YAAY,CAAC;AACnD,mCAAoC,gBAAgB,CAAC;AACrD,2BAA4B,SAAS,CAAC;AACtC,uCAAwC,iBAAiB,CAAC;AAoqB1D,wCAAyC,EAAE,CAAC;AAC5C,+CAAwE;AACxE,+CAAuE;AA4GhE,uCAJI,GAAG,WACH,OAAO,GACL,MAAM,EAAE,CAQA;sBAlxBR,OAAO,oBAAoB,EAAE,OAAO;;aA+BvC,OAAO;kBACP,MAAM;0BACN,MAAM;oBACN,MAAM;oBACN,MAAM;kBACN,MAAM;kBACN,MAAM;eACN,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG;;;;;8BAkfZ,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBA0LhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BAruBJ,WAAW"}
1
+ {"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":"AAsDA;;;;;;;GAOG;AACH,oDAHW,GAAG,GACD,MAAM,EAAE,CAQpB;AAED;;;;;;GAMG;AACH,oDAHW,GAAG,GACD,MAAM,CAUlB;AAED;;;;;GAKG;AACH,kDAJW,OAAO,mBACP,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,mDALW,OAAO,mBACP,MAAM,SACN,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,GAClC,aAAa,CA4CzB;AAED;;;;;;;GAOG;AACH,4DAJW,OAAO,mBACP,MAAM,GACJ,aAAa,CAkCzB;AAED;;;;;;GAMG;AACH,0CANW,OAAO,SACP,GAAG,mBACH,MAAM,+BACN,OAAO,EAAE,GACP,aAAa,CA8BzB;AACD;;;;;GAKG;AACH,qDALW,OAAO,SACP,GAAG,mBACH,MAAM,GACJ,aAAa,CAyBzB;AAED;;;;;GAKG;AACH,2CAJW,OAAO,SACP,GAAG,cACH,OAAO,oBAAoB,EAAE,UAAU;;;;;;EA0QjD;AAED;;;;GAIG;AACH,wDAHW,OAAO,YACP,OAAO,qBAAqB,EAAE,cAAc,EAAE,UA+BxD;AAmED;;GAEG;AACH,qDAFW,OAAO,6BAQjB;AAuCD;;;;GAIG;AACH,iDAHW,OAAO,qBAAqB,EAAE,SAAS,WACvC,OAAO,oBAAoB,EAAE,OAAO;mBAQjB,MAAM;sBAAoB,sBAAsB,GAAG,sBAAsB,GAAG,uBAAuB;;;;;;EAoBhI;AAED;;;;GAIG;AACH,2CAFW,MAAM,6BAIhB;AAED;;;;GAIG;AACH,sCAFW,MAAM,EAAE,WAIlB;AAMD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAED;;;GAGG;AACH,2CAHW,MAAM,QACN,MAAM,EAAE,YAUlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AAwBD;;;;GAIG;AACH,uCAJW,MAAM,EAAE,cACR,MAAM,EAAE,GACN,MAAM,CAgClB;AA12BD,+BAAgC,OAAO,CAAC;AACxC,4BAA6B,UAAU,CAAC;AACxC,2BAA4B,QAAQ,CAAC;AACrC,uCAAwC,WAAW,CAAC;AACpD,oCAAqC,QAAQ,CAAC;AAC9C,qCAAsC,YAAY,CAAC;AACnD,mCAAoC,gBAAgB,CAAC;AACrD,2BAA4B,SAAS,CAAC;AACtC,uCAAwC,iBAAiB,CAAC;AAysB1D,wCAAyC,EAAE,CAAC;AAC5C,+CAAwE;AACxE,+CAAuE;AA4GhE,uCAJI,GAAG,WACH,OAAO,GACL,MAAM,EAAE,CAQA;sBAvzBR,OAAO,oBAAoB,EAAE,OAAO;;aAgEvC,OAAO;kBACP,MAAM;0BACN,MAAM;oBACN,MAAM;oBACN,MAAM;kBACN,MAAM;kBACN,MAAM;eACN,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG;;;;;8BAsfZ,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBA0LhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BA1wBJ,WAAW"}
@@ -52,6 +52,39 @@ function splitScaleType(type) {
52
52
  };
53
53
  }
54
54
 
55
+ /**
56
+ * Gets the boundary values that the shader uses for discretizing scale buckets.
57
+ * Threshold scales expose the boundaries as their domain, while quantize scales
58
+ * derive them from the domain extent and range count.
59
+ *
60
+ * @param {any} scale
61
+ * @returns {number[]}
62
+ */
63
+ export function getDiscretizingDomainForGlsl(scale) {
64
+ if (scale.type === "quantize") {
65
+ return scale.thresholds();
66
+ } else {
67
+ return scale.domain();
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Gets the number of buckets needed for a discrete or discretizing range
73
+ * texture.
74
+ *
75
+ * @param {any} scale
76
+ * @returns {number}
77
+ */
78
+ export function getDiscreteRangeCountForGlsl(scale) {
79
+ if (scale.type === "quantize") {
80
+ return scale.range().length;
81
+ } else if (scale.type === "threshold") {
82
+ return scale.domain().length + 1;
83
+ } else {
84
+ return scale.domain().length;
85
+ }
86
+ }
87
+
55
88
  /**
56
89
  *
57
90
  * @param {Channel} channel
@@ -250,7 +283,11 @@ export function generateScaleGlsl(channel, scale, channelDef) {
250
283
 
251
284
  const { hp, attributeType } = getAttributeAndArrayTypes(scale, channel);
252
285
 
253
- const domainLength = scale.domain ? scale.domain().length : undefined;
286
+ const domainLength = scale.domain
287
+ ? isDiscretizing(scale.type)
288
+ ? getDiscretizingDomainForGlsl(scale).length
289
+ : scale.domain().length
290
+ : undefined;
254
291
 
255
292
  /** @type {string} */
256
293
  let domainUniform;
@@ -345,8 +382,8 @@ export function generateScaleGlsl(channel, scale, channelDef) {
345
382
  break;
346
383
 
347
384
  case "threshold":
385
+ case "quantize":
348
386
  // TODO: Quantile (it's a specialization of threshold scale)
349
- // TODO: Quantize
350
387
  break;
351
388
 
352
389
  default:
@@ -1,2 +1,2 @@
1
- const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}const highp uint HASH_EMPTY_KEY=0xffffffffu;highp uint hash32(highp uint key){highp uint v=key;v ^=v>>16u;v*=0x7feb352du;v ^=v>>15u;v*=0x846ca68bu;v ^=v>>16u;return v;}bool isEmptyHashTexture(highp usampler2D s){ivec2 texSize=textureSize(s,0);return texSize.x==1&&texSize.y==1&&texelFetch(s,ivec2(0,0),0).r==HASH_EMPTY_KEY;}bool hashContainsTexture(highp usampler2D s,highp uint value){ivec2 texSize=textureSize(s,0);highp uint width=uint(texSize.x);highp uint size=width*uint(texSize.y);highp uint mask=size-1u;highp uint index=hash32(value)&mask;for(highp uint probe=0u;probe<size;probe+=1u){ivec2 coord=ivec2(int(index % width),int(index/width));highp uint entry=texelFetch(s,coord,0).r;if(entry==value){return true;}if(entry==HASH_EMPTY_KEY){return false;}index=(index+1u)&mask;}return false;}/***Calculates a gamma for antialiasing opacity based on the color.*/float getGammaForColor(vec3 rgb){return mix(1.25,0.75,smoothstep(0.0,1.0,dot(rgb,vec3(0.299,0.587,0.114))));}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,vec4 background,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : background,distanceToRatio(sd));}else{return mix(background,fill,distanceToRatio(-d));}}";
1
+ const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;mediump vec4 uLogicalVisibleRect;lowp vec2 uCullByVisibleRange;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}bool isOutsideVisibleRange(vec2 pos){return(uCullByVisibleRange.x>0.5&&(pos.x<uLogicalVisibleRect.x||pos.x>uLogicalVisibleRect.z))||(uCullByVisibleRange.y>0.5&&(pos.y<uLogicalVisibleRect.y||pos.y>uLogicalVisibleRect.w));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}const highp uint HASH_EMPTY_KEY=0xffffffffu;highp uint hash32(highp uint key){highp uint v=key;v ^=v>>16u;v*=0x7feb352du;v ^=v>>15u;v*=0x846ca68bu;v ^=v>>16u;return v;}bool isEmptyHashTexture(highp usampler2D s){ivec2 texSize=textureSize(s,0);return texSize.x==1&&texSize.y==1&&texelFetch(s,ivec2(0,0),0).r==HASH_EMPTY_KEY;}bool hashContainsTexture(highp usampler2D s,highp uint value){ivec2 texSize=textureSize(s,0);highp uint width=uint(texSize.x);highp uint size=width*uint(texSize.y);highp uint mask=size-1u;highp uint index=hash32(value)&mask;for(highp uint probe=0u;probe<size;probe+=1u){ivec2 coord=ivec2(int(index % width),int(index/width));highp uint entry=texelFetch(s,coord,0).r;if(entry==value){return true;}if(entry==HASH_EMPTY_KEY){return false;}index=(index+1u)&mask;}return false;}/***Calculates a gamma for antialiasing opacity based on the color.*/float getGammaForColor(vec3 rgb){return mix(1.25,0.75,smoothstep(0.0,1.0,dot(rgb,vec3(0.299,0.587,0.114))));}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,vec4 background,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : background,distanceToRatio(sd));}else{return mix(background,fill,distanceToRatio(-d));}}";
2
2
  export default shader;