@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,19 @@
|
|
|
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
|
+
precision highp float;
|
|
14
|
+
|
|
15
|
+
varying vec4 v_color;
|
|
16
|
+
|
|
17
|
+
void main() {
|
|
18
|
+
gl_FragColor = v_color;
|
|
19
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
// Per-vertex (divisor=0): position in the unit triangle-strip template.
|
|
14
|
+
// a_strip_t ∈ [0, 1] angular parameter along the arc
|
|
15
|
+
// a_side ∈ {0, 1} 0 = inner radius, 1 = outer radius
|
|
16
|
+
attribute float a_strip_t;
|
|
17
|
+
attribute float a_side;
|
|
18
|
+
|
|
19
|
+
// Per-instance (divisor=1) arc geometry.
|
|
20
|
+
attribute vec2 a_angles; // (a0, a1) in radians
|
|
21
|
+
attribute vec2 a_radii; // (r0, r1) inner / outer pixel radius
|
|
22
|
+
attribute vec4 a_color;
|
|
23
|
+
|
|
24
|
+
uniform vec2 u_center; // chart center in pixel space
|
|
25
|
+
uniform vec2 u_resolution; // viewport size in device pixels
|
|
26
|
+
uniform float u_border_px; // symmetric inset, in device pixels
|
|
27
|
+
|
|
28
|
+
varying vec4 v_color;
|
|
29
|
+
varying vec2 v_edge; // (angular t, radial t) for optional AA fringe
|
|
30
|
+
|
|
31
|
+
void main() {
|
|
32
|
+
// Symmetric inset: shrink the arc by half the border on every edge
|
|
33
|
+
// so adjacent arcs each give up half, producing a
|
|
34
|
+
// `u_border_px`-wide gap in pixel space.
|
|
35
|
+
//
|
|
36
|
+
// Radial inset is constant; angular inset is computed per-vertex
|
|
37
|
+
// based on the vertex's *actual* radius. This keeps the angular gap
|
|
38
|
+
// at exactly `u_border_px` pixels wide at every radial position —
|
|
39
|
+
// without it, the gap narrows toward the center (since the same
|
|
40
|
+
// dTheta corresponds to fewer pixels at smaller r).
|
|
41
|
+
//
|
|
42
|
+
// Side effect: the arc's side edges are slightly non-radial (they
|
|
43
|
+
// curve so that the outer endpoint sits inside the inner endpoint's
|
|
44
|
+
// wedge). At 1 px borders this is imperceptible; at very wide
|
|
45
|
+
// borders the arc looks like a thin curved parallelogram — which
|
|
46
|
+
// is, in fact, the shape with constant pixel-width gaps.
|
|
47
|
+
float half_border = u_border_px * 0.5;
|
|
48
|
+
|
|
49
|
+
float adjR0 = a_radii.x + half_border;
|
|
50
|
+
float adjR1 = a_radii.y - half_border;
|
|
51
|
+
if(adjR1 <= adjR0) {
|
|
52
|
+
// Arc thinner than the border radially — nothing to draw.
|
|
53
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
54
|
+
v_color = vec4(0.0);
|
|
55
|
+
v_edge = vec2(0.0);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Per-vertex radius + angular inset. dTheta scales with 1/r so the
|
|
60
|
+
// pixel-space gap is constant at every radial position. Clamp to
|
|
61
|
+
// at most `span / 2` so narrow arcs collapse their inner edge to
|
|
62
|
+
// a point at the midpoint angle instead of inverting (which would
|
|
63
|
+
// send inner vertices past outer ones and rasterize degenerate
|
|
64
|
+
// triangles across the screen). Every vertex of an instance takes
|
|
65
|
+
// the same clamp path, so the triangle strip stays well-formed.
|
|
66
|
+
float r = mix(adjR0, adjR1, a_side);
|
|
67
|
+
float dTheta = half_border / max(r, 1.0);
|
|
68
|
+
float span = a_angles.y - a_angles.x;
|
|
69
|
+
dTheta = min(dTheta, span * 0.5);
|
|
70
|
+
float angle = mix(a_angles.x + dTheta, a_angles.y - dTheta, a_strip_t);
|
|
71
|
+
|
|
72
|
+
vec2 pixel = u_center + vec2(cos(angle), sin(angle)) * r;
|
|
73
|
+
// Pixel → clip: origin top-left, Y flipped to match 2D canvas conv.
|
|
74
|
+
vec2 clip = (pixel / u_resolution) * 2.0 - 1.0;
|
|
75
|
+
gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
|
|
76
|
+
|
|
77
|
+
v_color = a_color;
|
|
78
|
+
v_edge = vec2(a_strip_t, a_side);
|
|
79
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
precision highp float;
|
|
14
|
+
|
|
15
|
+
varying vec2 v_uv;
|
|
16
|
+
|
|
17
|
+
uniform sampler2D u_tile;
|
|
18
|
+
|
|
19
|
+
// Optional alpha multiplier (0.0..1.0). Used to fade the tile basemap
|
|
20
|
+
// when the chart's theme prefers a subdued backdrop behind the glyph
|
|
21
|
+
// layer; defaults to 1.0 so callers can omit it.
|
|
22
|
+
uniform float u_alpha;
|
|
23
|
+
|
|
24
|
+
void main() {
|
|
25
|
+
vec4 c = texture2D(u_tile, v_uv);
|
|
26
|
+
gl_FragColor = vec4(c.rgb, c.a * u_alpha);
|
|
27
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
// Unit-quad vertex shader for one map tile. The same static [0..1]
|
|
14
|
+
// corner buffer is bound for every tile in a frame; per-tile uniforms
|
|
15
|
+
// stretch the corner into Mercator space and pick the UV sub-rect.
|
|
16
|
+
// Sub-rect support is for the parent-tile fallback path (sample the
|
|
17
|
+
// loaded parent at the child's quadrant while the child fetches).
|
|
18
|
+
attribute vec2 a_corner;
|
|
19
|
+
|
|
20
|
+
uniform mat4 u_projection;
|
|
21
|
+
uniform vec2 u_extent_min;
|
|
22
|
+
uniform vec2 u_extent_max;
|
|
23
|
+
uniform vec2 u_uv_min;
|
|
24
|
+
uniform vec2 u_uv_max;
|
|
25
|
+
|
|
26
|
+
varying vec2 v_uv;
|
|
27
|
+
|
|
28
|
+
void main() {
|
|
29
|
+
vec2 pos = mix(u_extent_min, u_extent_max, a_corner);
|
|
30
|
+
// Tiles ship north-up; the WebGL Y axis points up at clip
|
|
31
|
+
// coordinates so flip the V channel before sampling.
|
|
32
|
+
vec2 uv = mix(u_uv_min, u_uv_max, vec2(a_corner.x, 1.0 - a_corner.y));
|
|
33
|
+
v_uv = uv;
|
|
34
|
+
gl_Position = u_projection * vec4(pos, 0.0, 1.0);
|
|
35
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
precision highp float;
|
|
14
|
+
|
|
15
|
+
varying vec4 v_color;
|
|
16
|
+
|
|
17
|
+
void main() {
|
|
18
|
+
gl_FragColor = v_color;
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
attribute vec2 a_position;
|
|
14
|
+
attribute vec4 a_color;
|
|
15
|
+
|
|
16
|
+
uniform vec2 u_resolution;
|
|
17
|
+
|
|
18
|
+
varying vec4 v_color;
|
|
19
|
+
|
|
20
|
+
void main() {
|
|
21
|
+
vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;
|
|
22
|
+
clip.y = -clip.y;
|
|
23
|
+
gl_Position = vec4(clip, 0.0, 1.0);
|
|
24
|
+
v_color = a_color;
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
precision highp float;
|
|
14
|
+
|
|
15
|
+
varying vec3 v_color;
|
|
16
|
+
varying float v_point_size;
|
|
17
|
+
|
|
18
|
+
void main() {
|
|
19
|
+
vec2 coord = gl_PointCoord - vec2(0.5);
|
|
20
|
+
float dist = length(coord);
|
|
21
|
+
|
|
22
|
+
if(dist > 0.5)
|
|
23
|
+
discard;
|
|
24
|
+
|
|
25
|
+
// Anti-alias at the circle edge.
|
|
26
|
+
float pixelWidth = 1.5 / max(v_point_size, 1.0);
|
|
27
|
+
float alpha = 1.0 - smoothstep(0.5 - pixelWidth, 0.5, dist);
|
|
28
|
+
|
|
29
|
+
gl_FragColor = vec4(v_color, alpha);
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
// Per-vertex: one point per (series, category) sample. Color is carried
|
|
14
|
+
// per-vertex so a single draw call can render every scatter series with
|
|
15
|
+
// its palette color, no gradient lookup.
|
|
16
|
+
|
|
17
|
+
attribute vec2 a_position;
|
|
18
|
+
attribute vec3 a_color;
|
|
19
|
+
|
|
20
|
+
uniform mat4 u_projection;
|
|
21
|
+
uniform float u_point_size;
|
|
22
|
+
|
|
23
|
+
varying vec3 v_color;
|
|
24
|
+
varying float v_point_size;
|
|
25
|
+
|
|
26
|
+
void main() {
|
|
27
|
+
gl_Position = u_projection * vec4(a_position, 0.0, 1.0);
|
|
28
|
+
gl_PointSize = u_point_size;
|
|
29
|
+
v_point_size = u_point_size;
|
|
30
|
+
v_color = a_color;
|
|
31
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
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 { parseCSSColorToVec3 } from "../utils/css";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A single stop on a parsed CSS gradient. `offset` ∈ [0, 1].
|
|
17
|
+
*/
|
|
18
|
+
export interface GradientStop {
|
|
19
|
+
offset: number;
|
|
20
|
+
color: [number, number, number, number]; // RGBA, each ∈ [0, 1]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const DEFAULT_STOPS: GradientStop[] = [
|
|
24
|
+
{ offset: 0, color: [0x03 / 255, 0x66 / 255, 0xd6 / 255, 1] },
|
|
25
|
+
{ offset: 1, color: [0xff / 255, 0x7f / 255, 0x0e / 255, 1] },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Parse a `linear-gradient(...)` CSS expression into ordered stops. Tolerates
|
|
30
|
+
* missing percentages (distributes linearly between known offsets, matching
|
|
31
|
+
* the CSS standard) and leading direction tokens (`to right`, `90deg`, etc.)
|
|
32
|
+
* which are simply skipped.
|
|
33
|
+
*
|
|
34
|
+
* Returns the default blue → orange two-stop on any parse failure so themes
|
|
35
|
+
* that never set the gradient still produce sane output.
|
|
36
|
+
*/
|
|
37
|
+
export function parseCssGradient(
|
|
38
|
+
src: string | null | undefined,
|
|
39
|
+
): GradientStop[] {
|
|
40
|
+
if (!src) {
|
|
41
|
+
return DEFAULT_STOPS.slice();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const trimmed = src.trim();
|
|
45
|
+
if (!trimmed) {
|
|
46
|
+
return DEFAULT_STOPS.slice();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Strip the `linear-gradient(` wrapper. Bail out if we don't find it.
|
|
50
|
+
const openIdx = trimmed.indexOf("(");
|
|
51
|
+
if (openIdx < 0) {
|
|
52
|
+
return DEFAULT_STOPS.slice();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!/^linear-gradient\s*\(/i.test(trimmed)) {
|
|
56
|
+
return DEFAULT_STOPS.slice();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const closeIdx = trimmed.lastIndexOf(")");
|
|
60
|
+
if (closeIdx <= openIdx) {
|
|
61
|
+
return DEFAULT_STOPS.slice();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const body = trimmed.substring(openIdx + 1, closeIdx);
|
|
65
|
+
|
|
66
|
+
// Split on commas at depth 0 (respecting nested `rgb(...)` / `rgba(...)` /
|
|
67
|
+
// `hsl(...)` parens which also contain commas).
|
|
68
|
+
const parts: string[] = [];
|
|
69
|
+
let depth = 0;
|
|
70
|
+
let start = 0;
|
|
71
|
+
for (let i = 0; i < body.length; i++) {
|
|
72
|
+
const ch = body[i];
|
|
73
|
+
if (ch === "(") {
|
|
74
|
+
depth++;
|
|
75
|
+
} else if (ch === ")") {
|
|
76
|
+
depth--;
|
|
77
|
+
} else if (ch === "," && depth === 0) {
|
|
78
|
+
parts.push(body.substring(start, i));
|
|
79
|
+
start = i + 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
parts.push(body.substring(start));
|
|
84
|
+
|
|
85
|
+
// First part may be a direction (`to right`, `90deg`, `to bottom right`)
|
|
86
|
+
// rather than a color-stop. Detect by: no matching color syntax.
|
|
87
|
+
const stops: Array<{
|
|
88
|
+
color: [number, number, number];
|
|
89
|
+
offset: number | null;
|
|
90
|
+
}> = [];
|
|
91
|
+
let startIdx = 0;
|
|
92
|
+
if (parts.length > 0) {
|
|
93
|
+
const firstNorm = parts[0].trim().toLowerCase();
|
|
94
|
+
if (
|
|
95
|
+
firstNorm.startsWith("to ") ||
|
|
96
|
+
/^[-\d.]+(deg|rad|grad|turn)/.test(firstNorm)
|
|
97
|
+
) {
|
|
98
|
+
startIdx = 1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (let i = startIdx; i < parts.length; i++) {
|
|
103
|
+
const piece = parts[i].trim();
|
|
104
|
+
if (!piece) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Peel off an optional trailing `<number>%` or `<number>px`.
|
|
109
|
+
const pctMatch = piece.match(/\s([\-\d.]+)%\s*$/);
|
|
110
|
+
const color = pctMatch
|
|
111
|
+
? piece.substring(0, pctMatch.index).trim()
|
|
112
|
+
: piece;
|
|
113
|
+
const offset = pctMatch ? parseFloat(pctMatch[1]) / 100 : null;
|
|
114
|
+
try {
|
|
115
|
+
const rgb = parseCSSColorToVec3(color);
|
|
116
|
+
stops.push({ color: rgb, offset });
|
|
117
|
+
} catch {
|
|
118
|
+
// skip unparseable stop
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (stops.length === 0) {
|
|
123
|
+
return DEFAULT_STOPS.slice();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (stops.length === 1) {
|
|
127
|
+
// Single stop → solid color. Duplicate across [0, 1] so sampling works.
|
|
128
|
+
const [r, g, b] = stops[0].color;
|
|
129
|
+
return [
|
|
130
|
+
{ offset: 0, color: [r, g, b, 1] },
|
|
131
|
+
{ offset: 1, color: [r, g, b, 1] },
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Fill in missing offsets by linear interpolation of neighbours with
|
|
136
|
+
// known positions (CSS implicit-position semantics).
|
|
137
|
+
if (stops[0].offset === null) {
|
|
138
|
+
stops[0].offset = 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (stops[stops.length - 1].offset === null) {
|
|
142
|
+
stops[stops.length - 1].offset = 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (let i = 1; i < stops.length - 1; i++) {
|
|
146
|
+
if (stops[i].offset !== null) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Find next known offset.
|
|
151
|
+
let j = i + 1;
|
|
152
|
+
while (j < stops.length && stops[j].offset === null) {
|
|
153
|
+
j++;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const before = stops[i - 1].offset!;
|
|
157
|
+
const after = stops[j].offset!;
|
|
158
|
+
const span = j - (i - 1);
|
|
159
|
+
for (let k = i; k < j; k++) {
|
|
160
|
+
stops[k].offset =
|
|
161
|
+
before + ((k - (i - 1)) / span) * (after - before);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
i = j - 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Clamp offsets to [0, 1] and ensure non-decreasing order.
|
|
168
|
+
let prev = 0;
|
|
169
|
+
const result: GradientStop[] = stops.map((s) => {
|
|
170
|
+
const off = Math.max(prev, Math.min(1, s.offset!));
|
|
171
|
+
prev = off;
|
|
172
|
+
return {
|
|
173
|
+
offset: off,
|
|
174
|
+
color: [s.color[0], s.color[1], s.color[2], 1],
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Piecewise-linear color sample at `t ∈ [0, 1]`. Returns RGBA in [0, 1].
|
|
183
|
+
* Clamps `t` to the gradient's first/last stop outside `[0, 1]`.
|
|
184
|
+
*/
|
|
185
|
+
export function sampleGradient(
|
|
186
|
+
stops: GradientStop[],
|
|
187
|
+
t: number,
|
|
188
|
+
): [number, number, number, number] {
|
|
189
|
+
if (stops.length === 0) {
|
|
190
|
+
return [0, 0, 0, 1];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (t <= stops[0].offset) {
|
|
194
|
+
return stops[0].color.slice() as [number, number, number, number];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const last = stops[stops.length - 1];
|
|
198
|
+
if (t >= last.offset) {
|
|
199
|
+
return last.color.slice() as [number, number, number, number];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Bisect for the interval containing `t`.
|
|
203
|
+
let lo = 0;
|
|
204
|
+
let hi = stops.length - 1;
|
|
205
|
+
while (hi - lo > 1) {
|
|
206
|
+
const mid = (lo + hi) >> 1;
|
|
207
|
+
if (stops[mid].offset <= t) {
|
|
208
|
+
lo = mid;
|
|
209
|
+
} else {
|
|
210
|
+
hi = mid;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const a = stops[lo];
|
|
215
|
+
const b = stops[hi];
|
|
216
|
+
const span = b.offset - a.offset;
|
|
217
|
+
const u = span > 0 ? (t - a.offset) / span : 0;
|
|
218
|
+
return [
|
|
219
|
+
a.color[0] + (b.color[0] - a.color[0]) * u,
|
|
220
|
+
a.color[1] + (b.color[1] - a.color[1]) * u,
|
|
221
|
+
a.color[2] + (b.color[2] - a.color[2]) * u,
|
|
222
|
+
a.color[3] + (b.color[3] - a.color[3]) * u,
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Sign-aware normalization. Returns `t ∈ [0, 1]` where the 50% stop is
|
|
228
|
+
* always the sign pivot:
|
|
229
|
+
* - crosses zero → `[-maxAbs, maxAbs]` stretched symmetrically; 0 → 0.5.
|
|
230
|
+
* - all-positive → `[0, colorMax]` occupies top half `[0.5, 1]`.
|
|
231
|
+
* - all-negative → `[colorMin, 0]` occupies bottom half `[0, 0.5]`.
|
|
232
|
+
* - degenerate → 0.5 (single colour at the midpoint).
|
|
233
|
+
*/
|
|
234
|
+
export function colorValueToT(
|
|
235
|
+
value: number,
|
|
236
|
+
colorMin: number,
|
|
237
|
+
colorMax: number,
|
|
238
|
+
): number {
|
|
239
|
+
if (!isFinite(value) || colorMin === colorMax) {
|
|
240
|
+
return 0.5;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let denom: number;
|
|
244
|
+
if (colorMin >= 0) {
|
|
245
|
+
denom = colorMax;
|
|
246
|
+
} else if (colorMax <= 0) {
|
|
247
|
+
denom = -colorMin;
|
|
248
|
+
} else {
|
|
249
|
+
denom = Math.max(-colorMin, colorMax);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (denom <= 0) {
|
|
253
|
+
return 0.5;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const t = 0.5 + 0.5 * (value / denom);
|
|
257
|
+
return t < 0 ? 0 : t > 1 ? 1 : t;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Convert a discrete series palette (from `--psp-charts--series-N--color`)
|
|
262
|
+
* into a `GradientStop[]` with stops at `i / (N - 1)`. The resulting
|
|
263
|
+
* stops can feed `buildGradientLUT` / `ensureGradientTexture` / any
|
|
264
|
+
* other code path that already accepts a gradient — so categorical
|
|
265
|
+
* coloring and numeric gradients share one LUT pipeline. Integer idx
|
|
266
|
+
* sampling via `t = idx / (N - 1)` lands exactly on a palette color;
|
|
267
|
+
* the linear blend between stops is only hit by non-integer samples
|
|
268
|
+
* (which categorical data doesn't produce).
|
|
269
|
+
*/
|
|
270
|
+
export function paletteToStops(
|
|
271
|
+
palette: [number, number, number][],
|
|
272
|
+
): GradientStop[] {
|
|
273
|
+
if (palette.length === 0) {
|
|
274
|
+
return DEFAULT_STOPS.slice();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (palette.length === 1) {
|
|
278
|
+
const [r, g, b] = palette[0];
|
|
279
|
+
return [
|
|
280
|
+
{ offset: 0, color: [r, g, b, 1] },
|
|
281
|
+
{ offset: 1, color: [r, g, b, 1] },
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const denom = palette.length - 1;
|
|
286
|
+
return palette.map(([r, g, b], i) => ({
|
|
287
|
+
offset: i / denom,
|
|
288
|
+
color: [r, g, b, 1],
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Bake a sampled LUT for GPU upload as RGBA8 (`size × 1`). Default 256
|
|
294
|
+
* samples — visually indistinguishable from a denser sample at typical
|
|
295
|
+
* viewport sizes and keeps the texture tiny (1 KB).
|
|
296
|
+
*/
|
|
297
|
+
export function buildGradientLUT(
|
|
298
|
+
stops: GradientStop[],
|
|
299
|
+
size: number = 256,
|
|
300
|
+
): Uint8Array {
|
|
301
|
+
const out = new Uint8Array(size * 4);
|
|
302
|
+
for (let i = 0; i < size; i++) {
|
|
303
|
+
const t = size === 1 ? 0 : i / (size - 1);
|
|
304
|
+
const c = sampleGradient(stops, t);
|
|
305
|
+
out[i * 4] = Math.round(c[0] * 255);
|
|
306
|
+
out[i * 4 + 1] = Math.round(c[1] * 255);
|
|
307
|
+
out[i * 4 + 2] = Math.round(c[2] * 255);
|
|
308
|
+
out[i * 4 + 3] = Math.round(c[3] * 255);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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 { sampleGradient, type GradientStop } from "./gradient";
|
|
14
|
+
|
|
15
|
+
export type Vec3 = [number, number, number];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Build a series palette of length `count` by sampling the theme gradient
|
|
19
|
+
* at evenly-spaced offsets. For count == 1 returns the 50% stop.
|
|
20
|
+
*/
|
|
21
|
+
export function interpolatePalette(
|
|
22
|
+
stops: GradientStop[],
|
|
23
|
+
count: number,
|
|
24
|
+
): Vec3[] {
|
|
25
|
+
if (count <= 0) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const out: Vec3[] = new Array(count);
|
|
30
|
+
for (let i = 0; i < count; i++) {
|
|
31
|
+
const t = count === 1 ? 0.5 : i / (count - 1);
|
|
32
|
+
const c = sampleGradient(stops, t);
|
|
33
|
+
out[i] = [c[0], c[1], c[2]];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a series palette: use the discrete `--psp-charts--series-N--color`
|
|
41
|
+
* palette when available, otherwise fall back to evenly-spaced samples of
|
|
42
|
+
* the theme gradient.
|
|
43
|
+
*/
|
|
44
|
+
export function resolvePalette(
|
|
45
|
+
discrete: Vec3[],
|
|
46
|
+
stops: GradientStop[],
|
|
47
|
+
count: number,
|
|
48
|
+
): Vec3[] {
|
|
49
|
+
if (discrete.length > 0) {
|
|
50
|
+
if (discrete.length >= count) {
|
|
51
|
+
return discrete.slice(0, count);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Cycle through the discrete palette for overflow indices.
|
|
55
|
+
const out: Vec3[] = new Array(count);
|
|
56
|
+
for (let i = 0; i < count; i++) {
|
|
57
|
+
out[i] = discrete[i % discrete.length];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return interpolatePalette(stops, count);
|
|
64
|
+
}
|