@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.
- package/LICENSE.md +193 -0
- package/dist/cdn/perspective-viewer-charts.js +3 -0
- package/dist/cdn/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/axis/axis-primitives.d.ts +24 -0
- package/dist/esm/axis/bar-axis.d.ts +51 -0
- package/dist/esm/axis/canvas.d.ts +24 -0
- package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
- package/dist/esm/axis/categorical-axis.d.ts +27 -0
- package/dist/esm/axis/facet-chrome.d.ts +13 -0
- package/dist/esm/axis/label-geometry.d.ts +41 -0
- package/dist/esm/axis/legend.d.ts +44 -0
- package/dist/esm/axis/numeric-axis.d.ts +20 -0
- package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
- package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
- package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
- package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
- package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
- package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
- package/dist/esm/charts/canvas-types.d.ts +15 -0
- package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
- package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
- package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
- package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
- package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
- package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
- package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
- package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
- package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
- package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
- package/dist/esm/charts/chart-base.d.ts +402 -0
- package/dist/esm/charts/chart.d.ts +338 -0
- package/dist/esm/charts/common/band-layout.d.ts +32 -0
- package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
- package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
- package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
- package/dist/esm/charts/common/leaf-color.d.ts +33 -0
- package/dist/esm/charts/common/node-store.d.ts +81 -0
- package/dist/esm/charts/common/tree-chart.d.ts +48 -0
- package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
- package/dist/esm/charts/common/tree-data.d.ts +54 -0
- package/dist/esm/charts/common/visible-extent.d.ts +51 -0
- package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
- package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
- package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
- package/dist/esm/charts/map/map.d.ts +67 -0
- package/dist/esm/charts/registry.d.ts +14 -0
- package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
- package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
- package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
- package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
- package/dist/esm/charts/series/series-build.d.ts +228 -0
- package/dist/esm/charts/series/series-interact.d.ts +35 -0
- package/dist/esm/charts/series/series-render.d.ts +41 -0
- package/dist/esm/charts/series/series-type.d.ts +49 -0
- package/dist/esm/charts/series/series.d.ts +317 -0
- package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
- package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
- package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
- package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
- package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
- package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
- package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
- package/dist/esm/charts/treemap/treemap.d.ts +74 -0
- package/dist/esm/config.d.ts +27 -0
- package/dist/esm/data/lazy-row.d.ts +32 -0
- package/dist/esm/data/split-groups.d.ts +20 -0
- package/dist/esm/data/view-reader.d.ts +35 -0
- package/dist/esm/event-detail.d.ts +28 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/interaction/hit-test.d.ts +30 -0
- package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
- package/dist/esm/interaction/host-sink-message.d.ts +46 -0
- package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
- package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
- package/dist/esm/interaction/spatial-grid.d.ts +15 -0
- package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
- package/dist/esm/interaction/zoom-controller.d.ts +106 -0
- package/dist/esm/interaction/zoom-router.d.ts +48 -0
- package/dist/esm/layout/facet-grid.d.ts +126 -0
- package/dist/esm/layout/plot-layout.d.ts +104 -0
- package/dist/esm/layout/ticks.d.ts +17 -0
- package/dist/esm/map/mercator.d.ts +102 -0
- package/dist/esm/map/tile-cache.d.ts +38 -0
- package/dist/esm/map/tile-layer.d.ts +66 -0
- package/dist/esm/map/tile-loader.d.ts +52 -0
- package/dist/esm/map/tile-source.d.ts +66 -0
- package/dist/esm/perspective-viewer-charts.js +3 -0
- package/dist/esm/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/plugin/charts.d.ts +40 -0
- package/dist/esm/plugin/plugin.d.ts +95 -0
- package/dist/esm/render/scheduler.d.ts +41 -0
- package/dist/esm/theme/gradient.d.ts +48 -0
- package/dist/esm/theme/palette.d.ts +13 -0
- package/dist/esm/theme/theme-snapshot.d.ts +7 -0
- package/dist/esm/theme/theme.d.ts +53 -0
- package/dist/esm/transport/protocol.d.ts +430 -0
- package/dist/esm/transport/renderer-transport.d.ts +201 -0
- package/dist/esm/utils/css.d.ts +1 -0
- package/dist/esm/utils/font-snapshot.d.ts +50 -0
- package/dist/esm/webgl/buffer-pool.d.ts +62 -0
- package/dist/esm/webgl/context-manager.d.ts +184 -0
- package/dist/esm/webgl/gradient-texture.d.ts +17 -0
- package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
- package/dist/esm/webgl/plot-frame.d.ts +39 -0
- package/dist/esm/webgl/program-cache.d.ts +13 -0
- package/dist/esm/webgl/shader-manifest.d.ts +53 -0
- package/dist/esm/webgl/shader-registry.d.ts +22 -0
- package/dist/esm/worker/boot.d.ts +0 -0
- package/dist/esm/worker/dispatch.d.ts +9 -0
- package/dist/esm/worker/font-loader.d.ts +2 -0
- package/dist/esm/worker/renderer.worker.d.ts +115 -0
- package/dist/esm/worker/session-host.d.ts +26 -0
- package/package.json +47 -0
- package/src/css/perspective-viewer-charts.css +95 -0
- package/src/ts/axis/axis-primitives.ts +125 -0
- package/src/ts/axis/bar-axis.ts +345 -0
- package/src/ts/axis/canvas.ts +64 -0
- package/src/ts/axis/categorical-axis-core.ts +125 -0
- package/src/ts/axis/categorical-axis.ts +716 -0
- package/src/ts/axis/facet-chrome.ts +42 -0
- package/src/ts/axis/label-geometry.ts +188 -0
- package/src/ts/axis/legend.ts +218 -0
- package/src/ts/axis/numeric-axis.ts +353 -0
- package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
- package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
- package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
- package/src/ts/charts/candlestick/candlestick.ts +367 -0
- package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
- package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
- package/src/ts/charts/canvas-types.ts +30 -0
- package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
- package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
- package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
- package/src/ts/charts/cartesian/cartesian.ts +469 -0
- package/src/ts/charts/cartesian/glyph.ts +81 -0
- package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
- package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
- package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
- package/src/ts/charts/cartesian/label-interner.ts +56 -0
- package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
- package/src/ts/charts/chart-base.ts +840 -0
- package/src/ts/charts/chart.ts +427 -0
- package/src/ts/charts/common/band-layout.ts +63 -0
- package/src/ts/charts/common/categorical-y-chart.ts +81 -0
- package/src/ts/charts/common/category-axis-resolver.ts +314 -0
- package/src/ts/charts/common/chrome-cache.ts +79 -0
- package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
- package/src/ts/charts/common/leaf-color.ts +92 -0
- package/src/ts/charts/common/node-store.ts +235 -0
- package/src/ts/charts/common/tree-chart.ts +76 -0
- package/src/ts/charts/common/tree-chrome.ts +123 -0
- package/src/ts/charts/common/tree-data.ts +623 -0
- package/src/ts/charts/common/visible-extent.ts +112 -0
- package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
- package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
- package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
- package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
- package/src/ts/charts/heatmap/heatmap.ts +368 -0
- package/src/ts/charts/map/map.ts +201 -0
- package/src/ts/charts/registry.ts +65 -0
- package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
- package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
- package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
- package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
- package/src/ts/charts/series/series-build.ts +848 -0
- package/src/ts/charts/series/series-interact.ts +604 -0
- package/src/ts/charts/series/series-render.ts +1109 -0
- package/src/ts/charts/series/series-type.ts +99 -0
- package/src/ts/charts/series/series.ts +794 -0
- package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
- package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
- package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
- package/src/ts/charts/sunburst/sunburst.ts +248 -0
- package/src/ts/charts/treemap/treemap-interact.ts +445 -0
- package/src/ts/charts/treemap/treemap-layout.ts +328 -0
- package/src/ts/charts/treemap/treemap-render.ts +886 -0
- package/src/ts/charts/treemap/treemap.ts +247 -0
- package/src/ts/config.ts +41 -0
- package/src/ts/data/lazy-row.ts +140 -0
- package/src/ts/data/split-groups.ts +97 -0
- package/src/ts/data/view-reader.ts +107 -0
- package/src/ts/event-detail.ts +44 -0
- package/src/ts/index.ts +53 -0
- package/src/ts/interaction/hit-test.ts +106 -0
- package/src/ts/interaction/host-sink-dom.ts +85 -0
- package/src/ts/interaction/host-sink-message.ts +75 -0
- package/src/ts/interaction/lazy-tooltip.ts +102 -0
- package/src/ts/interaction/raw-event-forwarder.ts +175 -0
- package/src/ts/interaction/spatial-grid.ts +100 -0
- package/src/ts/interaction/tooltip-controller.ts +407 -0
- package/src/ts/interaction/zoom-controller.ts +468 -0
- package/src/ts/interaction/zoom-router.ts +230 -0
- package/src/ts/layout/facet-grid.ts +346 -0
- package/src/ts/layout/plot-layout.ts +277 -0
- package/src/ts/layout/ticks.ts +168 -0
- package/src/ts/map/mercator.ts +204 -0
- package/src/ts/map/tile-cache.ts +96 -0
- package/src/ts/map/tile-layer.ts +382 -0
- package/src/ts/map/tile-loader.ts +143 -0
- package/src/ts/map/tile-source.ts +156 -0
- package/src/ts/plugin/charts.ts +286 -0
- package/src/ts/plugin/plugin.ts +668 -0
- package/src/ts/render/scheduler.ts +339 -0
- package/src/ts/shaders/area.frag.glsl +20 -0
- package/src/ts/shaders/area.vert.glsl +19 -0
- package/src/ts/shaders/bar.frag.glsl +25 -0
- package/src/ts/shaders/bar.vert.glsl +60 -0
- package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
- package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
- package/src/ts/shaders/density-extreme.frag.glsl +30 -0
- package/src/ts/shaders/density-mrt.frag.glsl +44 -0
- package/src/ts/shaders/density-mrt.vert.glsl +48 -0
- package/src/ts/shaders/density-resolve.frag.glsl +89 -0
- package/src/ts/shaders/density-resolve.vert.glsl +23 -0
- package/src/ts/shaders/density-splat.frag.glsl +34 -0
- package/src/ts/shaders/density-splat.vert.glsl +52 -0
- package/src/ts/shaders/gridline.frag.glsl +18 -0
- package/src/ts/shaders/gridline.vert.glsl +18 -0
- package/src/ts/shaders/heatmap.frag.glsl +23 -0
- package/src/ts/shaders/heatmap.vert.glsl +42 -0
- package/src/ts/shaders/line-uniform.frag.glsl +26 -0
- package/src/ts/shaders/line-uniform.vert.glsl +54 -0
- package/src/ts/shaders/line.frag.glsl +28 -0
- package/src/ts/shaders/line.vert.glsl +87 -0
- package/src/ts/shaders/scatter.frag.glsl +39 -0
- package/src/ts/shaders/scatter.vert.glsl +67 -0
- package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
- package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
- package/src/ts/shaders/tile.frag.glsl +27 -0
- package/src/ts/shaders/tile.vert.glsl +35 -0
- package/src/ts/shaders/treemap.frag.glsl +19 -0
- package/src/ts/shaders/treemap.vert.glsl +25 -0
- package/src/ts/shaders/y-scatter.frag.glsl +30 -0
- package/src/ts/shaders/y-scatter.vert.glsl +31 -0
- package/src/ts/theme/gradient.ts +312 -0
- package/src/ts/theme/palette.ts +64 -0
- package/src/ts/theme/theme-snapshot.ts +66 -0
- package/src/ts/theme/theme.ts +166 -0
- package/src/ts/transport/protocol.ts +497 -0
- package/src/ts/transport/renderer-transport.ts +788 -0
- package/src/ts/utils/css.ts +36 -0
- package/src/ts/utils/font-snapshot.ts +159 -0
- package/src/ts/webgl/buffer-pool.ts +163 -0
- package/src/ts/webgl/context-manager.ts +414 -0
- package/src/ts/webgl/gradient-texture.ts +84 -0
- package/src/ts/webgl/instanced-attrs.ts +139 -0
- package/src/ts/webgl/plot-frame.ts +91 -0
- package/src/ts/webgl/program-cache.ts +46 -0
- package/src/ts/webgl/shader-manifest.ts +148 -0
- package/src/ts/webgl/shader-registry.ts +97 -0
- package/src/ts/worker/boot.ts +22 -0
- package/src/ts/worker/dispatch.ts +99 -0
- package/src/ts/worker/font-loader.ts +89 -0
- package/src/ts/worker/renderer.worker.ts +734 -0
- package/src/ts/worker/session-host.ts +118 -0
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
export function parseCSSColorToVec3(
|
|
14
|
+
colorStr: string,
|
|
15
|
+
): [number, number, number] {
|
|
16
|
+
const s = colorStr.trim();
|
|
17
|
+
if (s.startsWith("#")) {
|
|
18
|
+
let hex = s.slice(1);
|
|
19
|
+
if (hex.length === 3) {
|
|
20
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return [
|
|
24
|
+
parseInt(hex.slice(0, 2), 16) / 255,
|
|
25
|
+
parseInt(hex.slice(2, 4), 16) / 255,
|
|
26
|
+
parseInt(hex.slice(4, 6), 16) / 255,
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const m = s.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
|
|
31
|
+
if (m) {
|
|
32
|
+
return [+m[1] / 255, +m[2] / 255, +m[3] / 255];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return [0.5, 0.5, 0.5];
|
|
36
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
* Walk every accessible `@font-face` rule in the document and collect a
|
|
17
|
+
* descriptor list ready for forwarding to a Web Worker, where each
|
|
18
|
+
* entry is reconstituted via `new FontFace(family, src, descriptors)`
|
|
19
|
+
* and registered in the worker's own `self.fonts` set.
|
|
20
|
+
*
|
|
21
|
+
* Background: a `Worker` has its own `FontFaceSet` distinct from the
|
|
22
|
+
* document's. Fonts loaded into `document.fonts` (by `<link>`,
|
|
23
|
+
* `@font-face`, or programmatic `FontFace`) are *not* visible to the
|
|
24
|
+
* worker — Canvas2D `ctx.font` lookups inside the worker fall back to
|
|
25
|
+
* the platform default if the family isn't in `self.fonts`. This
|
|
26
|
+
* helper bridges that gap for the in-CSS case.
|
|
27
|
+
*
|
|
28
|
+
* # CORS / security caveats
|
|
29
|
+
*
|
|
30
|
+
* 1. **Cross-origin stylesheets without permissive CORS** throw
|
|
31
|
+
* `SecurityError` on `cssRules` access, and we silently skip them.
|
|
32
|
+
* Their `@font-face` rules are unreachable to JS regardless of
|
|
33
|
+
* where the worker would re-load them, so this is the same
|
|
34
|
+
* fundamental limitation the document itself has.
|
|
35
|
+
*
|
|
36
|
+
* 2. **Font URLs are absolutized against the parent stylesheet's
|
|
37
|
+
* `href`** before forwarding. The worker's own script URL is a
|
|
38
|
+
* Blob URL produced by `WorkerPlugin`, so relative URLs in the raw
|
|
39
|
+
* `src:` declaration would resolve against the Blob origin (i.e.
|
|
40
|
+
* fail). Callers should treat the absolute URLs as the canonical
|
|
41
|
+
* source.
|
|
42
|
+
*
|
|
43
|
+
* 3. **The actual font fetch issued by `face.load()` in the worker
|
|
44
|
+
* is a fresh cross-origin request from the worker scope.** The
|
|
45
|
+
* font server must respond with `Access-Control-Allow-Origin`
|
|
46
|
+
* (e.g. `*` or the page origin) and an appropriate
|
|
47
|
+
* `Access-Control-Allow-Headers` policy if any non-simple headers
|
|
48
|
+
* are involved. A "no-cors" / opaque response is *not* usable
|
|
49
|
+
* here: `FontFace.load()` rejects on opaque responses, and even
|
|
50
|
+
* if it didn't, painted glyphs would taint the canvas and break
|
|
51
|
+
* `getImageData`. Same-origin fonts (including `data:` URIs)
|
|
52
|
+
* sidestep this entirely.
|
|
53
|
+
*
|
|
54
|
+
* 4. **Programmatic fonts** (e.g. `document.fonts.add(new
|
|
55
|
+
* FontFace(name, source))`) are *not* captured by this walker —
|
|
56
|
+
* they don't appear in any stylesheet's `cssRules`. Iterating
|
|
57
|
+
* `document.fonts` directly would catch them, but `FontFace`
|
|
58
|
+
* instances don't expose their source URL or buffer post-
|
|
59
|
+
* construction, so there's no public path to forward them. If a
|
|
60
|
+
* test or app needs that, it must register the same fonts in the
|
|
61
|
+
* worker explicitly.
|
|
62
|
+
*/
|
|
63
|
+
export function snapshotFontFaces(): FontFaceDescriptor[] {
|
|
64
|
+
const out: FontFaceDescriptor[] = [];
|
|
65
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
66
|
+
let rules: CSSRuleList;
|
|
67
|
+
try {
|
|
68
|
+
rules = sheet.cssRules;
|
|
69
|
+
} catch {
|
|
70
|
+
// Cross-origin stylesheet without permissive CORS — its
|
|
71
|
+
// `@font-face` rules are unreachable to JS. See caveat (1).
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const base = sheet.href ?? document.baseURI;
|
|
76
|
+
for (const rule of Array.from(rules)) {
|
|
77
|
+
if (!(rule instanceof CSSFontFaceRule)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const style = rule.style;
|
|
82
|
+
const rawFamily = style.getPropertyValue("font-family").trim();
|
|
83
|
+
const rawSrc = style.getPropertyValue("src").trim();
|
|
84
|
+
if (!rawFamily || !rawSrc) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
out.push({
|
|
89
|
+
// CSSOM serializes multi-word family names with their
|
|
90
|
+
// CSS quotes preserved (e.g. `"Roboto Mono"`). The
|
|
91
|
+
// `FontFace` constructor *doesn't* unquote on parse —
|
|
92
|
+
// Chromium stores the literal input and re-quotes /
|
|
93
|
+
// escapes on `face.family` getter access, yielding
|
|
94
|
+
// `"\"Roboto Mono\""` and a name that no `ctx.font`
|
|
95
|
+
// lookup can match. Strip one layer of matching outer
|
|
96
|
+
// quotes here so the worker's font set keys align
|
|
97
|
+
// with how Canvas2D resolves family names.
|
|
98
|
+
family: stripOuterQuotes(rawFamily),
|
|
99
|
+
src: resolveSrcUrls(rawSrc, base),
|
|
100
|
+
style: optional(style, "font-style"),
|
|
101
|
+
weight: optional(style, "font-weight"),
|
|
102
|
+
stretch: optional(style, "font-stretch"),
|
|
103
|
+
unicodeRange: optional(style, "unicode-range"),
|
|
104
|
+
variant: optional(style, "font-variant"),
|
|
105
|
+
featureSettings: optional(style, "font-feature-settings"),
|
|
106
|
+
display: optional(style, "font-display"),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function optional(
|
|
115
|
+
style: CSSStyleDeclaration,
|
|
116
|
+
prop: string,
|
|
117
|
+
): string | undefined {
|
|
118
|
+
const v = style.getPropertyValue(prop).trim();
|
|
119
|
+
return v || undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Remove a single matching pair of outer `"…"` or `'…'` quotes from a
|
|
124
|
+
* family name. CSSOM serializes multi-word `font-family` descriptor
|
|
125
|
+
* values with their quotes preserved; `FontFace` then re-quotes on
|
|
126
|
+
* serialization, producing the literal `"\"Foo\""` double-quoting
|
|
127
|
+
* observed in `face.family`. Stripping one layer here aligns the
|
|
128
|
+
* stored family with what Canvas2D resolves at render time.
|
|
129
|
+
*/
|
|
130
|
+
function stripOuterQuotes(s: string): string {
|
|
131
|
+
if (s.length >= 2) {
|
|
132
|
+
const first = s.charCodeAt(0);
|
|
133
|
+
const last = s.charCodeAt(s.length - 1);
|
|
134
|
+
if (first === last && (first === 0x22 || first === 0x27)) {
|
|
135
|
+
return s.slice(1, -1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return s;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Rewrite every `url(...)` token inside a CSS `src:` value to its
|
|
144
|
+
* absolute form. Multi-source declarations (`url(...) format(...),
|
|
145
|
+
* url(...) format(...)`) are handled by replacing each `url(...)`
|
|
146
|
+
* chunk independently. See caveat (2).
|
|
147
|
+
*/
|
|
148
|
+
function resolveSrcUrls(src: string, base: string): string {
|
|
149
|
+
return src.replace(
|
|
150
|
+
/url\(\s*(['"]?)([^'")]+)\1\s*\)/g,
|
|
151
|
+
(match, _quote, url) => {
|
|
152
|
+
try {
|
|
153
|
+
return `url(${new URL(url, base).href})`;
|
|
154
|
+
} catch {
|
|
155
|
+
return match;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
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 { BUFFER_POOL_STRICT } from "../config";
|
|
14
|
+
|
|
15
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
16
|
+
|
|
17
|
+
export interface ManagedBuffer {
|
|
18
|
+
buffer: WebGLBuffer;
|
|
19
|
+
byteCapacity: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class BufferPool {
|
|
23
|
+
private _gl: GL;
|
|
24
|
+
private _buffers: Map<string, ManagedBuffer> = new Map();
|
|
25
|
+
private _totalCapacity = 0;
|
|
26
|
+
private _maxCapacity = 0;
|
|
27
|
+
|
|
28
|
+
constructor(gl: GL) {
|
|
29
|
+
this._gl = gl;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get totalCapacity(): number {
|
|
33
|
+
return this._totalCapacity;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get maxCapacity() {
|
|
37
|
+
return this._maxCapacity;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
set maxCapacity(cap: number) {
|
|
41
|
+
this._maxCapacity = cap;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ensureCapacity(totalRows: number): void {
|
|
45
|
+
this._totalCapacity =
|
|
46
|
+
this._maxCapacity > 0
|
|
47
|
+
? Math.min(totalRows, this._maxCapacity)
|
|
48
|
+
: totalRows;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Read-only lookup by name. Returns the existing managed buffer, or
|
|
53
|
+
* `undefined` if no buffer has been allocated under that name yet.
|
|
54
|
+
*
|
|
55
|
+
* Render-path callers that bind buffers for `drawArrays` /
|
|
56
|
+
* `drawArraysInstanced` MUST use this rather than `getOrCreate`:
|
|
57
|
+
* the latter recreates (zero-initialized) when `_totalCapacity` has
|
|
58
|
+
* grown past the current `byteCapacity`. That recreate is desired
|
|
59
|
+
* during `upload` (where `bufferSubData` immediately writes the
|
|
60
|
+
* actual data) but catastrophic during render — it wipes the
|
|
61
|
+
* previous draw's vertex data, leaving `drawArrays` to issue
|
|
62
|
+
* against zeros and produce no visible glyphs (a one-frame blank
|
|
63
|
+
* plot area while gridlines/chrome remain correct).
|
|
64
|
+
*
|
|
65
|
+
* Specifically, `ensureBufferCapacity(totalRows)` from a pending
|
|
66
|
+
* draw updates `_totalCapacity` *before* its matching `uploadChunk`
|
|
67
|
+
* has run; a pan/zoom-induced render landing in that window would
|
|
68
|
+
* otherwise see `requiredBytes > byteCapacity` and recreate.
|
|
69
|
+
*/
|
|
70
|
+
peek(name: string): ManagedBuffer | undefined {
|
|
71
|
+
return this._buffers.get(name);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getOrCreate(
|
|
75
|
+
name: string,
|
|
76
|
+
componentsPerVertex: number,
|
|
77
|
+
bytesPerElement: number,
|
|
78
|
+
): ManagedBuffer {
|
|
79
|
+
const requiredBytes =
|
|
80
|
+
this._totalCapacity * componentsPerVertex * bytesPerElement;
|
|
81
|
+
let managed = this._buffers.get(name);
|
|
82
|
+
if (managed && managed.byteCapacity >= requiredBytes) {
|
|
83
|
+
return managed;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const gl = this._gl;
|
|
87
|
+
if (managed) {
|
|
88
|
+
gl.deleteBuffer(managed.buffer);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const buffer = gl.createBuffer()!;
|
|
92
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
93
|
+
gl.bufferData(gl.ARRAY_BUFFER, requiredBytes, gl.DYNAMIC_DRAW);
|
|
94
|
+
|
|
95
|
+
managed = { buffer, byteCapacity: requiredBytes };
|
|
96
|
+
this._buffers.set(name, managed);
|
|
97
|
+
return managed;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Upload `data` into the named GPU buffer at `byteOffset`. The
|
|
102
|
+
* buffer is sized lazily by `getOrCreate` to
|
|
103
|
+
* `_totalCapacity × componentsPerVertex × data.BYTES_PER_ELEMENT`.
|
|
104
|
+
* Callers MUST keep `byteOffset + data.byteLength` within that
|
|
105
|
+
* capacity — `bufferSubData` raises `INVALID_VALUE` on overflow
|
|
106
|
+
* and the upload is silently dropped at the GL layer.
|
|
107
|
+
*
|
|
108
|
+
* Common pitfall: passing a module-level scratch typed array whose
|
|
109
|
+
* `length` exceeds the current frame's valid-data count. Scratch
|
|
110
|
+
* buffers in chart impls grow monotonically across frames; the
|
|
111
|
+
* GPU buffer is sized to the *current* `_totalCapacity`. After a
|
|
112
|
+
* renderer-session reset (e.g. plugin disconnect/reconnect) the
|
|
113
|
+
* GPU buffer is fresh while the scratch retains its historical-
|
|
114
|
+
* peak length, and the upload writes past the buffer end. Always
|
|
115
|
+
* pass `data.subarray(0, n × componentsPerVertex)` when uploading
|
|
116
|
+
* from a scratch.
|
|
117
|
+
*
|
|
118
|
+
* Set `BUFFER_POOL_STRICT = true` in `config.ts` to convert
|
|
119
|
+
* overflows from opaque GL errors into descriptive throws at the
|
|
120
|
+
* offending stack frame.
|
|
121
|
+
*/
|
|
122
|
+
upload(
|
|
123
|
+
name: string,
|
|
124
|
+
data: Float32Array | Int32Array,
|
|
125
|
+
byteOffset: number,
|
|
126
|
+
componentsPerVertex: number = 1,
|
|
127
|
+
): WebGLBuffer {
|
|
128
|
+
const gl = this._gl;
|
|
129
|
+
const managed = this.getOrCreate(
|
|
130
|
+
name,
|
|
131
|
+
componentsPerVertex,
|
|
132
|
+
data.BYTES_PER_ELEMENT,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
if (BUFFER_POOL_STRICT) {
|
|
136
|
+
const writeEnd = byteOffset + data.byteLength;
|
|
137
|
+
if (writeEnd > managed.byteCapacity) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
`BufferPool.upload("${name}"): write ${byteOffset}..${writeEnd} ` +
|
|
140
|
+
`exceeds capacity ${managed.byteCapacity} ` +
|
|
141
|
+
`(_totalCapacity=${this._totalCapacity}, ` +
|
|
142
|
+
`components=${componentsPerVertex}, ` +
|
|
143
|
+
`bytes=${data.BYTES_PER_ELEMENT}). ` +
|
|
144
|
+
`Did you pass the full scratch buffer instead of a subarray(0, n)?`,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, managed.buffer);
|
|
150
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, byteOffset, data);
|
|
151
|
+
|
|
152
|
+
return managed.buffer;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
releaseAll(): void {
|
|
156
|
+
for (const managed of this._buffers.values()) {
|
|
157
|
+
this._gl.deleteBuffer(managed.buffer);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this._buffers.clear();
|
|
161
|
+
this._totalCapacity = 0;
|
|
162
|
+
}
|
|
163
|
+
}
|