@perspective-dev/viewer-charts 4.3.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 (258) hide show
  1. package/LICENSE.md +193 -0
  2. package/dist/cdn/perspective-viewer-charts.js +3 -0
  3. package/dist/cdn/perspective-viewer-charts.js.map +7 -0
  4. package/dist/esm/axis/axis-primitives.d.ts +24 -0
  5. package/dist/esm/axis/bar-axis.d.ts +51 -0
  6. package/dist/esm/axis/canvas.d.ts +24 -0
  7. package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
  8. package/dist/esm/axis/categorical-axis.d.ts +27 -0
  9. package/dist/esm/axis/facet-chrome.d.ts +13 -0
  10. package/dist/esm/axis/label-geometry.d.ts +41 -0
  11. package/dist/esm/axis/legend.d.ts +44 -0
  12. package/dist/esm/axis/numeric-axis.d.ts +20 -0
  13. package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
  14. package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
  15. package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
  16. package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
  17. package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
  18. package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
  19. package/dist/esm/charts/canvas-types.d.ts +15 -0
  20. package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
  21. package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
  22. package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
  23. package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
  24. package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
  25. package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
  26. package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
  27. package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
  28. package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
  29. package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
  30. package/dist/esm/charts/chart-base.d.ts +402 -0
  31. package/dist/esm/charts/chart.d.ts +338 -0
  32. package/dist/esm/charts/common/band-layout.d.ts +32 -0
  33. package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
  34. package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
  35. package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
  36. package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
  37. package/dist/esm/charts/common/leaf-color.d.ts +33 -0
  38. package/dist/esm/charts/common/node-store.d.ts +81 -0
  39. package/dist/esm/charts/common/tree-chart.d.ts +48 -0
  40. package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
  41. package/dist/esm/charts/common/tree-data.d.ts +54 -0
  42. package/dist/esm/charts/common/visible-extent.d.ts +51 -0
  43. package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
  44. package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
  45. package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
  46. package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
  47. package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
  48. package/dist/esm/charts/map/map.d.ts +67 -0
  49. package/dist/esm/charts/registry.d.ts +14 -0
  50. package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
  51. package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
  52. package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
  53. package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
  54. package/dist/esm/charts/series/series-build.d.ts +228 -0
  55. package/dist/esm/charts/series/series-interact.d.ts +35 -0
  56. package/dist/esm/charts/series/series-render.d.ts +41 -0
  57. package/dist/esm/charts/series/series-type.d.ts +49 -0
  58. package/dist/esm/charts/series/series.d.ts +317 -0
  59. package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
  60. package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
  61. package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
  62. package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
  63. package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
  64. package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
  65. package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
  66. package/dist/esm/charts/treemap/treemap.d.ts +74 -0
  67. package/dist/esm/config.d.ts +27 -0
  68. package/dist/esm/data/lazy-row.d.ts +32 -0
  69. package/dist/esm/data/split-groups.d.ts +20 -0
  70. package/dist/esm/data/view-reader.d.ts +35 -0
  71. package/dist/esm/event-detail.d.ts +28 -0
  72. package/dist/esm/index.d.ts +3 -0
  73. package/dist/esm/interaction/hit-test.d.ts +30 -0
  74. package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
  75. package/dist/esm/interaction/host-sink-message.d.ts +46 -0
  76. package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
  77. package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
  78. package/dist/esm/interaction/spatial-grid.d.ts +15 -0
  79. package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
  80. package/dist/esm/interaction/zoom-controller.d.ts +106 -0
  81. package/dist/esm/interaction/zoom-router.d.ts +48 -0
  82. package/dist/esm/layout/facet-grid.d.ts +126 -0
  83. package/dist/esm/layout/plot-layout.d.ts +104 -0
  84. package/dist/esm/layout/ticks.d.ts +17 -0
  85. package/dist/esm/map/mercator.d.ts +102 -0
  86. package/dist/esm/map/tile-cache.d.ts +38 -0
  87. package/dist/esm/map/tile-layer.d.ts +66 -0
  88. package/dist/esm/map/tile-loader.d.ts +52 -0
  89. package/dist/esm/map/tile-source.d.ts +66 -0
  90. package/dist/esm/perspective-viewer-charts.js +3 -0
  91. package/dist/esm/perspective-viewer-charts.js.map +7 -0
  92. package/dist/esm/plugin/charts.d.ts +40 -0
  93. package/dist/esm/plugin/plugin.d.ts +95 -0
  94. package/dist/esm/render/scheduler.d.ts +41 -0
  95. package/dist/esm/theme/gradient.d.ts +48 -0
  96. package/dist/esm/theme/palette.d.ts +13 -0
  97. package/dist/esm/theme/theme-snapshot.d.ts +7 -0
  98. package/dist/esm/theme/theme.d.ts +53 -0
  99. package/dist/esm/transport/protocol.d.ts +430 -0
  100. package/dist/esm/transport/renderer-transport.d.ts +201 -0
  101. package/dist/esm/utils/css.d.ts +1 -0
  102. package/dist/esm/utils/font-snapshot.d.ts +50 -0
  103. package/dist/esm/webgl/buffer-pool.d.ts +62 -0
  104. package/dist/esm/webgl/context-manager.d.ts +184 -0
  105. package/dist/esm/webgl/gradient-texture.d.ts +17 -0
  106. package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
  107. package/dist/esm/webgl/plot-frame.d.ts +39 -0
  108. package/dist/esm/webgl/program-cache.d.ts +13 -0
  109. package/dist/esm/webgl/shader-manifest.d.ts +53 -0
  110. package/dist/esm/webgl/shader-registry.d.ts +22 -0
  111. package/dist/esm/worker/boot.d.ts +0 -0
  112. package/dist/esm/worker/dispatch.d.ts +9 -0
  113. package/dist/esm/worker/font-loader.d.ts +2 -0
  114. package/dist/esm/worker/renderer.worker.d.ts +115 -0
  115. package/dist/esm/worker/session-host.d.ts +26 -0
  116. package/package.json +47 -0
  117. package/src/css/perspective-viewer-charts.css +95 -0
  118. package/src/ts/axis/axis-primitives.ts +125 -0
  119. package/src/ts/axis/bar-axis.ts +345 -0
  120. package/src/ts/axis/canvas.ts +64 -0
  121. package/src/ts/axis/categorical-axis-core.ts +125 -0
  122. package/src/ts/axis/categorical-axis.ts +716 -0
  123. package/src/ts/axis/facet-chrome.ts +42 -0
  124. package/src/ts/axis/label-geometry.ts +188 -0
  125. package/src/ts/axis/legend.ts +218 -0
  126. package/src/ts/axis/numeric-axis.ts +353 -0
  127. package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
  128. package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
  129. package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
  130. package/src/ts/charts/candlestick/candlestick.ts +367 -0
  131. package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
  132. package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
  133. package/src/ts/charts/canvas-types.ts +30 -0
  134. package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
  135. package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
  136. package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
  137. package/src/ts/charts/cartesian/cartesian.ts +469 -0
  138. package/src/ts/charts/cartesian/glyph.ts +81 -0
  139. package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
  140. package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
  141. package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
  142. package/src/ts/charts/cartesian/label-interner.ts +56 -0
  143. package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
  144. package/src/ts/charts/chart-base.ts +840 -0
  145. package/src/ts/charts/chart.ts +427 -0
  146. package/src/ts/charts/common/band-layout.ts +63 -0
  147. package/src/ts/charts/common/categorical-y-chart.ts +81 -0
  148. package/src/ts/charts/common/category-axis-resolver.ts +314 -0
  149. package/src/ts/charts/common/chrome-cache.ts +79 -0
  150. package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
  151. package/src/ts/charts/common/leaf-color.ts +92 -0
  152. package/src/ts/charts/common/node-store.ts +235 -0
  153. package/src/ts/charts/common/tree-chart.ts +76 -0
  154. package/src/ts/charts/common/tree-chrome.ts +123 -0
  155. package/src/ts/charts/common/tree-data.ts +623 -0
  156. package/src/ts/charts/common/visible-extent.ts +112 -0
  157. package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
  158. package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
  159. package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
  160. package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
  161. package/src/ts/charts/heatmap/heatmap.ts +368 -0
  162. package/src/ts/charts/map/map.ts +201 -0
  163. package/src/ts/charts/registry.ts +65 -0
  164. package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
  165. package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
  166. package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
  167. package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
  168. package/src/ts/charts/series/series-build.ts +848 -0
  169. package/src/ts/charts/series/series-interact.ts +604 -0
  170. package/src/ts/charts/series/series-render.ts +1109 -0
  171. package/src/ts/charts/series/series-type.ts +99 -0
  172. package/src/ts/charts/series/series.ts +794 -0
  173. package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
  174. package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
  175. package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
  176. package/src/ts/charts/sunburst/sunburst.ts +248 -0
  177. package/src/ts/charts/treemap/treemap-interact.ts +445 -0
  178. package/src/ts/charts/treemap/treemap-layout.ts +328 -0
  179. package/src/ts/charts/treemap/treemap-render.ts +886 -0
  180. package/src/ts/charts/treemap/treemap.ts +247 -0
  181. package/src/ts/config.ts +41 -0
  182. package/src/ts/data/lazy-row.ts +140 -0
  183. package/src/ts/data/split-groups.ts +97 -0
  184. package/src/ts/data/view-reader.ts +107 -0
  185. package/src/ts/event-detail.ts +44 -0
  186. package/src/ts/index.ts +53 -0
  187. package/src/ts/interaction/hit-test.ts +106 -0
  188. package/src/ts/interaction/host-sink-dom.ts +85 -0
  189. package/src/ts/interaction/host-sink-message.ts +75 -0
  190. package/src/ts/interaction/lazy-tooltip.ts +102 -0
  191. package/src/ts/interaction/raw-event-forwarder.ts +175 -0
  192. package/src/ts/interaction/spatial-grid.ts +100 -0
  193. package/src/ts/interaction/tooltip-controller.ts +407 -0
  194. package/src/ts/interaction/zoom-controller.ts +468 -0
  195. package/src/ts/interaction/zoom-router.ts +230 -0
  196. package/src/ts/layout/facet-grid.ts +346 -0
  197. package/src/ts/layout/plot-layout.ts +277 -0
  198. package/src/ts/layout/ticks.ts +168 -0
  199. package/src/ts/map/mercator.ts +204 -0
  200. package/src/ts/map/tile-cache.ts +96 -0
  201. package/src/ts/map/tile-layer.ts +382 -0
  202. package/src/ts/map/tile-loader.ts +143 -0
  203. package/src/ts/map/tile-source.ts +156 -0
  204. package/src/ts/plugin/charts.ts +286 -0
  205. package/src/ts/plugin/plugin.ts +668 -0
  206. package/src/ts/render/scheduler.ts +339 -0
  207. package/src/ts/shaders/area.frag.glsl +20 -0
  208. package/src/ts/shaders/area.vert.glsl +19 -0
  209. package/src/ts/shaders/bar.frag.glsl +25 -0
  210. package/src/ts/shaders/bar.vert.glsl +60 -0
  211. package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
  212. package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
  213. package/src/ts/shaders/density-extreme.frag.glsl +30 -0
  214. package/src/ts/shaders/density-mrt.frag.glsl +44 -0
  215. package/src/ts/shaders/density-mrt.vert.glsl +48 -0
  216. package/src/ts/shaders/density-resolve.frag.glsl +89 -0
  217. package/src/ts/shaders/density-resolve.vert.glsl +23 -0
  218. package/src/ts/shaders/density-splat.frag.glsl +34 -0
  219. package/src/ts/shaders/density-splat.vert.glsl +52 -0
  220. package/src/ts/shaders/gridline.frag.glsl +18 -0
  221. package/src/ts/shaders/gridline.vert.glsl +18 -0
  222. package/src/ts/shaders/heatmap.frag.glsl +23 -0
  223. package/src/ts/shaders/heatmap.vert.glsl +42 -0
  224. package/src/ts/shaders/line-uniform.frag.glsl +26 -0
  225. package/src/ts/shaders/line-uniform.vert.glsl +54 -0
  226. package/src/ts/shaders/line.frag.glsl +28 -0
  227. package/src/ts/shaders/line.vert.glsl +87 -0
  228. package/src/ts/shaders/scatter.frag.glsl +39 -0
  229. package/src/ts/shaders/scatter.vert.glsl +67 -0
  230. package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
  231. package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
  232. package/src/ts/shaders/tile.frag.glsl +27 -0
  233. package/src/ts/shaders/tile.vert.glsl +35 -0
  234. package/src/ts/shaders/treemap.frag.glsl +19 -0
  235. package/src/ts/shaders/treemap.vert.glsl +25 -0
  236. package/src/ts/shaders/y-scatter.frag.glsl +30 -0
  237. package/src/ts/shaders/y-scatter.vert.glsl +31 -0
  238. package/src/ts/theme/gradient.ts +312 -0
  239. package/src/ts/theme/palette.ts +64 -0
  240. package/src/ts/theme/theme-snapshot.ts +66 -0
  241. package/src/ts/theme/theme.ts +166 -0
  242. package/src/ts/transport/protocol.ts +497 -0
  243. package/src/ts/transport/renderer-transport.ts +788 -0
  244. package/src/ts/utils/css.ts +36 -0
  245. package/src/ts/utils/font-snapshot.ts +159 -0
  246. package/src/ts/webgl/buffer-pool.ts +163 -0
  247. package/src/ts/webgl/context-manager.ts +414 -0
  248. package/src/ts/webgl/gradient-texture.ts +84 -0
  249. package/src/ts/webgl/instanced-attrs.ts +139 -0
  250. package/src/ts/webgl/plot-frame.ts +91 -0
  251. package/src/ts/webgl/program-cache.ts +46 -0
  252. package/src/ts/webgl/shader-manifest.ts +148 -0
  253. package/src/ts/webgl/shader-registry.ts +97 -0
  254. package/src/ts/worker/boot.ts +22 -0
  255. package/src/ts/worker/dispatch.ts +99 -0
  256. package/src/ts/worker/font-loader.ts +89 -0
  257. package/src/ts/worker/renderer.worker.ts +734 -0
  258. package/src/ts/worker/session-host.ts +118 -0
@@ -0,0 +1,91 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { PlotLayout } from "../layout/plot-layout";
14
+
15
+ type GL = WebGL2RenderingContext | WebGLRenderingContext;
16
+
17
+ /**
18
+ * Return CSS-pixel dimensions of the GL canvas.
19
+ */
20
+ export function cssSize(
21
+ gl: GL,
22
+ dpr: number,
23
+ ): { cssWidth: number; cssHeight: number } {
24
+ return {
25
+ cssWidth: gl.canvas.width / dpr,
26
+ cssHeight: gl.canvas.height / dpr,
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Clear the framebuffer + enable alpha blending. Call once per frame,
32
+ * before any per-plot-rect {@link withScissor} invocations. Faceted
33
+ * renderers call this once and then loop {@link withScissor} per cell
34
+ * so the inter-facet clears don't wipe each other's pixels.
35
+ */
36
+ export function clearAndSetupFrame(gl: GL): void {
37
+ gl.clearColor(0, 0, 0, 0);
38
+ gl.clear(gl.COLOR_BUFFER_BIT);
39
+ gl.enable(gl.BLEND);
40
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
41
+ }
42
+
43
+ /**
44
+ * Scissor-constrain `draw` to `layout.plotRect`. Caller handles
45
+ * projection / uniforms / VBO bindings inside `draw`; this helper only
46
+ * manages the scissor enable/disable bracket.
47
+ *
48
+ * Unlike {@link renderInPlotFrame}, this does *not* clear the
49
+ * framebuffer — so it's safe to call repeatedly per frame (one per
50
+ * facet). Pair with {@link clearAndSetupFrame} at the start of each
51
+ * frame.
52
+ */
53
+ export function withScissor(
54
+ gl: GL,
55
+ layout: PlotLayout,
56
+ dpr: number,
57
+ draw: () => void,
58
+ ): void {
59
+ gl.enable(gl.SCISSOR_TEST);
60
+ gl.scissor(
61
+ Math.round(layout.margins.left * dpr),
62
+ Math.round(layout.margins.bottom * dpr),
63
+ Math.round(layout.plotRect.width * dpr),
64
+ Math.round(layout.plotRect.height * dpr),
65
+ );
66
+ try {
67
+ draw();
68
+ } finally {
69
+ gl.disable(gl.SCISSOR_TEST);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * One-shot convenience: clear + setup blend + scissor + draw. Used by
75
+ * single-plot callers (bar / heatmap / candlestick / scatter-without-
76
+ * splits) that only draw into one plot rect per frame.
77
+ *
78
+ * Faceted callers must use {@link clearAndSetupFrame} +
79
+ * {@link withScissor} instead; calling this helper in a per-facet loop
80
+ * would clear the framebuffer on each invocation and wipe out every
81
+ * previously-drawn facet.
82
+ */
83
+ export function renderInPlotFrame(
84
+ gl: GL,
85
+ layout: PlotLayout,
86
+ dpr: number,
87
+ draw: () => void,
88
+ ): void {
89
+ clearAndSetupFrame(gl);
90
+ withScissor(gl, layout, dpr, draw);
91
+ }
@@ -0,0 +1,46 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { WebGLContextManager } from "./context-manager";
14
+
15
+ /**
16
+ * Compile (or fetch from the shader registry) a program and resolve a
17
+ * flat record of uniform + attribute locations keyed by name. Uniforms
18
+ * resolve to `WebGLUniformLocation | null`; attribs resolve to `number`.
19
+ *
20
+ * Each glyph drawer used to repeat ~10 lines of `gl.getUniformLocation`
21
+ * / `gl.getAttribLocation` calls — replacing those with one
22
+ * `compileProgram(...)` call shrinks the worker bundle by ~80 bytes per
23
+ * site (uniform/attrib name strings still ship — WebGL needs them
24
+ * verbatim — but the per-call wrapper goes away).
25
+ */
26
+ export function compileProgram<C>(
27
+ glManager: WebGLContextManager,
28
+ key: string,
29
+ vert: string,
30
+ frag: string,
31
+ uniforms: readonly string[],
32
+ attrs: readonly string[],
33
+ ): C {
34
+ const program = glManager.shaders.getOrCreate(key, vert, frag);
35
+ const gl = glManager.gl;
36
+ const out: any = { program };
37
+ for (const n of uniforms) {
38
+ out[n] = gl.getUniformLocation(program, n);
39
+ }
40
+
41
+ for (const n of attrs) {
42
+ out[n] = gl.getAttribLocation(program, n);
43
+ }
44
+
45
+ return out as C;
46
+ }
@@ -0,0 +1,148 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import barVert from "../shaders/bar.vert.glsl";
14
+ import barFrag from "../shaders/bar.frag.glsl";
15
+ import lineVert from "../shaders/line.vert.glsl";
16
+ import lineFrag from "../shaders/line.frag.glsl";
17
+ import scatterVert from "../shaders/scatter.vert.glsl";
18
+ import scatterFrag from "../shaders/scatter.frag.glsl";
19
+ import areaVert from "../shaders/area.vert.glsl";
20
+ import areaFrag from "../shaders/area.frag.glsl";
21
+ import lineUniformVert from "../shaders/line-uniform.vert.glsl";
22
+ import lineUniformFrag from "../shaders/line-uniform.frag.glsl";
23
+ import yScatterVert from "../shaders/y-scatter.vert.glsl";
24
+ import yScatterFrag from "../shaders/y-scatter.frag.glsl";
25
+ import candlestickBodyVert from "../shaders/candlestick-body.vert.glsl";
26
+ import candlestickBodyFrag from "../shaders/candlestick-body.frag.glsl";
27
+ import heatmapVert from "../shaders/heatmap.vert.glsl";
28
+ import heatmapFrag from "../shaders/heatmap.frag.glsl";
29
+ import sunburstArcVert from "../shaders/sunburst-arc.vert.glsl";
30
+ import sunburstArcFrag from "../shaders/sunburst-arc.frag.glsl";
31
+ import treemapVert from "../shaders/treemap.vert.glsl";
32
+ import treemapFrag from "../shaders/treemap.frag.glsl";
33
+ import densitySplatVert from "../shaders/density-splat.vert.glsl";
34
+ import densitySplatFrag from "../shaders/density-splat.frag.glsl";
35
+ import densityExtremeFrag from "../shaders/density-extreme.frag.glsl";
36
+ import densityMrtVert from "../shaders/density-mrt.vert.glsl";
37
+ import densityMrtFrag from "../shaders/density-mrt.frag.glsl";
38
+ import densityResolveVert from "../shaders/density-resolve.vert.glsl";
39
+ import densityResolveFrag from "../shaders/density-resolve.frag.glsl";
40
+ import tileVert from "../shaders/tile.vert.glsl";
41
+ import tileFrag from "../shaders/tile.frag.glsl";
42
+
43
+ /**
44
+ * One shader program in the build's static manifest. The `name` is the
45
+ * cache key consumed by `ShaderRegistry.getOrCreate(name, ...)` —
46
+ * call sites must pass the same name (and the same vert/frag source)
47
+ * for the cache to hit. The single source of truth for both fields is
48
+ * this file; glyph code re-imports from here so the manifest and the
49
+ * call sites can never drift.
50
+ */
51
+ export interface ShaderSpec {
52
+ name: string;
53
+ vert: string;
54
+ frag: string;
55
+ }
56
+
57
+ /**
58
+ * Every WebGL program the build ships, keyed by cache name. Used by
59
+ * `ShaderRegistry.precompile(SHADER_MANIFEST)` to compile + link all
60
+ * programs eagerly during renderer construction so the first-frame
61
+ * path doesn't pay the compile cost inline.
62
+ *
63
+ * Names mirror the existing `getOrCreate` keys at each call site —
64
+ * the lazy path stays valid; precompile just primes the cache early.
65
+ */
66
+ export const SHADER_MANIFEST: readonly ShaderSpec[] = [
67
+ { name: "bar", vert: barVert, frag: barFrag },
68
+ { name: "line", vert: lineVert, frag: lineFrag },
69
+ { name: "scatter", vert: scatterVert, frag: scatterFrag },
70
+ { name: "bar-area", vert: areaVert, frag: areaFrag },
71
+ { name: "bar-scatter", vert: yScatterVert, frag: yScatterFrag },
72
+
73
+ // Shared by series-line glyph (`bar-line` consolidated here),
74
+ // candlestick wicks, and OHLC. One compile per context.
75
+ { name: "line-uniform", vert: lineUniformVert, frag: lineUniformFrag },
76
+ {
77
+ name: "candlestick-body",
78
+ vert: candlestickBodyVert,
79
+ frag: candlestickBodyFrag,
80
+ },
81
+ { name: "heatmap", vert: heatmapVert, frag: heatmapFrag },
82
+ { name: "sunburst-arc", vert: sunburstArcVert, frag: sunburstArcFrag },
83
+ { name: "treemap", vert: treemapVert, frag: treemapFrag },
84
+ {
85
+ name: "density-splat",
86
+ vert: densitySplatVert,
87
+ frag: densitySplatFrag,
88
+ },
89
+ {
90
+ name: "density-extreme",
91
+ vert: densitySplatVert,
92
+ frag: densityExtremeFrag,
93
+ },
94
+ {
95
+ name: "density-resolve",
96
+ vert: densityResolveVert,
97
+ frag: densityResolveFrag,
98
+ },
99
+ // The MRT variant declares `#extension GL_EXT_draw_buffers :
100
+ // require` and only compiles on contexts that advertise it. The
101
+ // glyph compiles it lazily after probing `OES_draw_buffers_indexed`
102
+ // — adding it here would crash precompile on hardware without
103
+ // multi-render-target support.
104
+
105
+ // Map tile basemap (textured quad in Mercator space). Compiled
106
+ // unconditionally because the program is GLSL 100 and links on
107
+ // every WebGL1/2 context; the loader only kicks in when a map
108
+ // plugin tag activates.
109
+ { name: "map-tile", vert: tileVert, frag: tileFrag },
110
+ ];
111
+
112
+ // Re-export each shader source so glyph modules can import their
113
+ // source from the manifest rather than from `../shaders/*.glsl`
114
+ // directly. This keeps the manifest's vert/frag fields and the
115
+ // `getOrCreate` call sites pointing at exactly the same string
116
+ // constants — module dedup ensures reference identity, so cache
117
+ // hits work even on the lazy path.
118
+ export {
119
+ barVert,
120
+ barFrag,
121
+ lineVert,
122
+ lineFrag,
123
+ scatterVert,
124
+ scatterFrag,
125
+ areaVert,
126
+ areaFrag,
127
+ lineUniformVert,
128
+ lineUniformFrag,
129
+ yScatterVert,
130
+ yScatterFrag,
131
+ candlestickBodyVert,
132
+ candlestickBodyFrag,
133
+ heatmapVert,
134
+ heatmapFrag,
135
+ sunburstArcVert,
136
+ sunburstArcFrag,
137
+ treemapVert,
138
+ treemapFrag,
139
+ densitySplatVert,
140
+ densitySplatFrag,
141
+ densityExtremeFrag,
142
+ densityMrtVert,
143
+ densityMrtFrag,
144
+ densityResolveVert,
145
+ densityResolveFrag,
146
+ tileVert,
147
+ tileFrag,
148
+ };
@@ -0,0 +1,97 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { ShaderSpec } from "./shader-manifest";
14
+
15
+ type GL = WebGL2RenderingContext | WebGLRenderingContext;
16
+
17
+ export class ShaderRegistry {
18
+ private _gl: GL;
19
+ private _programs: Map<string, WebGLProgram> = new Map();
20
+
21
+ constructor(gl: GL) {
22
+ this._gl = gl;
23
+ }
24
+
25
+ /**
26
+ * Compile + link every program in `specs` eagerly. Used by
27
+ * `WebGLContextManager` when constructed with `precompile: true`
28
+ * so the first-frame path doesn't pay the compile cost inline.
29
+ *
30
+ * Compilation is synchronous and serial — single-digit ms per
31
+ * program on a modern GPU. With `KHR_parallel_shader_compile`
32
+ * (browser-supported but not yet wired here) the work could be
33
+ * dispatched to driver threads; today we accept the wall-time
34
+ * cost in exchange for simpler code and a deterministic init.
35
+ */
36
+ precompile(specs: readonly ShaderSpec[]): void {
37
+ for (const spec of specs) {
38
+ this.getOrCreate(spec.name, spec.vert, spec.frag);
39
+ }
40
+ }
41
+
42
+ getOrCreate(name: string, vertSrc: string, fragSrc: string): WebGLProgram {
43
+ let program = this._programs.get(name);
44
+ if (program) {
45
+ return program;
46
+ }
47
+
48
+ const gl = this._gl;
49
+
50
+ const vert = gl.createShader(gl.VERTEX_SHADER)!;
51
+ gl.shaderSource(vert, vertSrc);
52
+ gl.compileShader(vert);
53
+ if (!gl.getShaderParameter(vert, gl.COMPILE_STATUS)) {
54
+ const info = gl.getShaderInfoLog(vert);
55
+ gl.deleteShader(vert);
56
+ throw new Error(`Vertex shader compile error [${name}]: ${info}`);
57
+ }
58
+
59
+ const frag = gl.createShader(gl.FRAGMENT_SHADER)!;
60
+ gl.shaderSource(frag, fragSrc);
61
+ gl.compileShader(frag);
62
+ if (!gl.getShaderParameter(frag, gl.COMPILE_STATUS)) {
63
+ const info = gl.getShaderInfoLog(frag);
64
+ gl.deleteShader(vert);
65
+ gl.deleteShader(frag);
66
+ throw new Error(`Fragment shader compile error [${name}]: ${info}`);
67
+ }
68
+
69
+ program = gl.createProgram()!;
70
+ gl.attachShader(program, vert);
71
+ gl.attachShader(program, frag);
72
+ gl.linkProgram(program);
73
+
74
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
75
+ const info = gl.getProgramInfoLog(program);
76
+ gl.deleteProgram(program);
77
+ gl.deleteShader(vert);
78
+ gl.deleteShader(frag);
79
+ throw new Error(`Shader link error [${name}]: ${info}`);
80
+ }
81
+
82
+ // Shaders can be deleted after linking
83
+ gl.deleteShader(vert);
84
+ gl.deleteShader(frag);
85
+
86
+ this._programs.set(name, program);
87
+ return program;
88
+ }
89
+
90
+ releaseAll(): void {
91
+ for (const program of this._programs.values()) {
92
+ this._gl.deleteProgram(program);
93
+ }
94
+
95
+ this._programs.clear();
96
+ }
97
+ }
@@ -0,0 +1,22 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ // In Web Worker scope, `window` is undefined but some bundled code
14
+ // (`@perspective-dev/viewer` wasm-bindgen JS, plus a few feature
15
+ // detects) probes it. Provide a stub *only* in worker scope — when
16
+ // this module is dynamic-imported on the main thread for the
17
+ // in-process renderer path, `window` is the real `Window` and we must
18
+ // not clobber it.
19
+ if (typeof window === "undefined") {
20
+ // @ts-ignore
21
+ globalThis.window = {};
22
+ }
@@ -0,0 +1,99 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { ControlMsg } from "../transport/protocol";
14
+ import type { WorkerRenderer } from "./renderer.worker";
15
+
16
+ /**
17
+ * Stateless control-message dispatcher. The renderer instance is
18
+ * supplied by the caller so worker mode (one global instance) and
19
+ * in-process mode (one instance per host element) share the same
20
+ * routing logic.
21
+ */
22
+ export function dispatch(r: WorkerRenderer, msg: ControlMsg): void {
23
+ switch (msg.kind) {
24
+ case "setViewByName":
25
+ r.setViewByName(msg.name);
26
+ break;
27
+ case "setColumnsConfig":
28
+ r.chartImpl.setColumnsConfig?.(msg.cfg);
29
+ break;
30
+ case "setPluginConfig":
31
+ r.chartImpl.setPluginConfig?.(msg.cfg);
32
+ r.redraw();
33
+ break;
34
+ case "setBufferMaxCapacity":
35
+ r.glManager.bufferPool.maxCapacity = msg.n;
36
+ break;
37
+ case "loadAndRender":
38
+ r.loadAndRender(msg);
39
+ break;
40
+ case "redraw":
41
+ r.redraw();
42
+ break;
43
+ case "resize":
44
+ console.log("resize");
45
+ r.resize(msg.cssWidth, msg.cssHeight, msg.dpr);
46
+ r.redraw();
47
+ break;
48
+ case "clear":
49
+ r.clear();
50
+ break;
51
+ case "invalidateTheme":
52
+ r.chartImpl.setTheme?.(msg.themeVars);
53
+ r.chartImpl.invalidateTheme?.();
54
+ r.resize(r.cssWidth, r.cssHeight, r.dpr);
55
+ break;
56
+ case "restoreZoom":
57
+ r.restoreZoom(msg.state);
58
+ break;
59
+ case "resetAllZooms":
60
+ r.resetAllZooms();
61
+ r.redraw();
62
+ r.post({
63
+ kind: "zoomChanged",
64
+ isDefault: r.allZoomsDefault(),
65
+ });
66
+ break;
67
+ case "resetExpandedDomain":
68
+ r.resetExpandedDomain();
69
+ break;
70
+ case "interaction":
71
+ r.onInteraction(msg.event);
72
+ break;
73
+ case "saveZoom":
74
+ r.post({
75
+ kind: "saveZoomReply",
76
+ requestId: msg.requestId,
77
+ state: r.saveZoom(),
78
+ });
79
+ break;
80
+ case "destroy":
81
+ r.destroy();
82
+ break;
83
+ case "init":
84
+ // Re-init not supported; ignore to keep the renderer alive
85
+ // for the host's `delete()` cleanup path.
86
+ break;
87
+ case "snapshotPng": {
88
+ const requestId = msg.requestId;
89
+ r.snapshotPng()
90
+ .then((blob) => {
91
+ r.post({ kind: "snapshotPngReply", requestId, blob });
92
+ })
93
+ .catch((err) => {
94
+ r.post({ kind: "error", message: String(err) });
95
+ });
96
+ break;
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,89 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { FontFaceDescriptor } from "../transport/protocol";
14
+
15
+ /**
16
+ * Worker-scope font registration cache, keyed by `family|src|weight|
17
+ * style`. Multiple sessions in one shared worker often ship identical
18
+ * font snapshots (the host's `snapshotFontFaces()` walks
19
+ * `document.styleSheets`, which is page-global). Without this cache,
20
+ * each session would `face.load()` + `fonts.add(face)` afresh —
21
+ * harmless but wasteful, since `fonts.add` dedupes by family but each
22
+ * `face.load()` still pays the await.
23
+ *
24
+ * The first session to ask for a given font owns the load promise;
25
+ * every subsequent session awaits it.
26
+ */
27
+ const FONT_LOADS = new Map<string, Promise<void>>();
28
+
29
+ export async function loadFontDeduped(d: FontFaceDescriptor): Promise<void> {
30
+ const key = [
31
+ d.family,
32
+ d.src,
33
+ d.weight ?? "",
34
+ d.style ?? "",
35
+ // d.stretch ?? "",
36
+ // d.unicodeRange ?? "",
37
+ // d.variant ?? "",
38
+ // d.featureSettings ?? "",
39
+ // d.display ?? "",
40
+ ].join("|");
41
+
42
+ let p = FONT_LOADS.get(key);
43
+ if (p) {
44
+ await p;
45
+ return;
46
+ }
47
+
48
+ p = (async () => {
49
+ try {
50
+ const descriptors: FontFaceDescriptors = {};
51
+ if (d.style) {
52
+ descriptors.style = d.style;
53
+ }
54
+
55
+ if (d.weight) {
56
+ descriptors.weight = d.weight;
57
+ }
58
+
59
+ if (d.stretch) {
60
+ descriptors.stretch = d.stretch;
61
+ }
62
+
63
+ // if (d.unicodeRange) {
64
+ // descriptors.unicodeRange = d.unicodeRange;
65
+ // }
66
+
67
+ // if (d.variant) {
68
+ // (descriptors as any).variant = d.variant;
69
+ // }
70
+
71
+ // if (d.featureSettings) {
72
+ // descriptors.featureSettings = d.featureSettings;
73
+ // }
74
+
75
+ // if (d.display) {
76
+ // (descriptors as any).display = d.display;
77
+ // }
78
+
79
+ const face = new FontFace(d.family, d.src, descriptors);
80
+ await face.load();
81
+ (self as any).fonts.add(face);
82
+ } catch (err) {
83
+ console.warn(`Failed to load font ${d.family}:`, err);
84
+ }
85
+ })();
86
+
87
+ FONT_LOADS.set(key, p);
88
+ await p;
89
+ }