@jbrowse/render-core 5.0.0-beta.13 → 5.0.0-beta.14
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/esm/OverlayCanvas.d.ts +3 -2
- package/esm/OverlayCanvas.js +4 -2
- package/esm/RenderCanvas.d.ts +4 -3
- package/esm/RenderCanvas.js +4 -2
- package/esm/ScrollLockedOverlay.d.ts +2 -2
- package/esm/ScrollLockedOverlay.js +3 -2
- package/esm/blockClipUtils.d.ts +5 -5
- package/esm/blockClipUtils.js +4 -3
- package/esm/canvas2dUtils.d.ts +15 -21
- package/esm/canvas2dUtils.js +25 -55
- package/esm/colorRampLut.d.ts +2 -2
- package/esm/colorRampLut.js +2 -2
- package/esm/coverageBand.d.ts +0 -1
- package/esm/coverageBand.js +0 -5
- package/esm/coverageBandBuffers.d.ts +8 -5
- package/esm/createRenderingBackend.d.ts +1 -1
- package/esm/displayPhase.d.ts +5 -9
- package/esm/displayPhase.js +2 -2
- package/esm/hal/mockHal.d.ts +3 -4
- package/esm/hal/mockHal.js +5 -4
- package/esm/hal/types.d.ts +5 -5
- package/esm/hal/webgl2Hal.d.ts +4 -1
- package/esm/hal/webgl2Hal.js +15 -6
- package/esm/hal/webgpuHal.js +2 -2
- package/esm/linkFeet.d.ts +4 -0
- package/esm/linkFeet.js +7 -0
- package/esm/marks/barMark.d.ts +1 -1
- package/esm/marks/colorFill.d.ts +4 -4
- package/esm/marks/colorFill.js +4 -4
- package/esm/marks/connectorMark.d.ts +48 -0
- package/esm/marks/connectorMark.js +285 -0
- package/esm/marks/drawAgainstHit.d.ts +1 -1
- package/esm/marks/drawAgainstHit.js +4 -4
- package/esm/marks/glyphPaint.d.ts +5 -4
- package/esm/marks/glyphPaint.js +17 -7
- package/esm/marks/index.d.ts +6 -3
- package/esm/marks/index.js +5 -3
- package/esm/marks/lineMark.d.ts +44 -10
- package/esm/marks/lineMark.js +20 -19
- package/esm/marks/linkMark.d.ts +22 -5
- package/esm/marks/linkMark.js +103 -25
- package/esm/marks/markBackend.d.ts +1 -1
- package/esm/marks/markBackend.js +1 -1
- package/esm/marks/markRamp.d.ts +11 -11
- package/esm/marks/markRamp.js +9 -9
- package/esm/marks/pointMark.d.ts +11 -5
- package/esm/marks/pointMark.js +34 -9
- package/esm/marks/rowLane.d.ts +3 -3
- package/esm/marks/rowLane.js +2 -2
- package/esm/marks/rowTable.d.ts +5 -5
- package/esm/marks/rowTable.js +4 -4
- package/esm/marks/ruleMark.js +1 -0
- package/esm/marks/spanMark.d.ts +4 -4
- package/esm/marks/types.d.ts +4 -4
- package/esm/marks/types.js +5 -0
- package/esm/perRegionRenderingBackend.d.ts +1 -1
- package/esm/perRegionRenderingBackend.js +1 -1
- package/esm/regionDataMap.d.ts +2 -2
- package/esm/regionDataMap.js +2 -2
- package/esm/shaders/capsule.js.generated.d.ts +1 -1
- package/esm/shaders/capsule.js.generated.js +2 -2
- package/esm/shaders/connectorMark.consts.generated.d.ts +11 -0
- package/esm/shaders/connectorMark.consts.generated.js +13 -0
- package/esm/shaders/{coverageIndicator.generated.d.ts → connectorMark.generated.d.ts} +2 -1
- package/esm/shaders/connectorMark.generated.js +8 -0
- package/esm/shaders/connectorMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/connectorMark.glsl.generated.js +4 -0
- package/esm/shaders/connectorMark.iface.generated.d.ts +88 -0
- package/esm/shaders/connectorMark.iface.generated.js +1194 -0
- package/esm/shaders/connectorMark.js.generated.d.ts +5 -0
- package/esm/shaders/connectorMark.js.generated.js +47 -0
- package/esm/shaders/connectorMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/connectorMark.wgsl.generated.js +3 -0
- package/esm/shaders/coverageInterbase.glsl.generated.d.ts +1 -1
- package/esm/shaders/coverageInterbase.glsl.generated.js +1 -1
- package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -1
- package/esm/shaders/coverageInterbase.wgsl.generated.js +1 -1
- package/esm/shaders/curveDistance.js.generated.d.ts +3 -0
- package/esm/shaders/curveDistance.js.generated.js +104 -0
- package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -2
- package/esm/shaders/lineCenterMark.glsl.generated.js +2 -2
- package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -1
- package/esm/shaders/lineCenterMark.wgsl.generated.js +1 -1
- package/esm/shaders/linkMark.consts.generated.d.ts +1 -0
- package/esm/shaders/linkMark.consts.generated.js +1 -0
- package/esm/shaders/linkMark.glsl.generated.d.ts +2 -2
- package/esm/shaders/linkMark.glsl.generated.js +2 -2
- package/esm/shaders/linkMark.js.generated.d.ts +2 -1
- package/esm/shaders/linkMark.js.generated.js +30 -1
- package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -1
- package/esm/shaders/linkMark.wgsl.generated.js +1 -1
- package/esm/shaders/pointMark.glsl.generated.d.ts +1 -1
- package/esm/shaders/pointMark.glsl.generated.js +1 -1
- package/esm/shaders/pointMark.iface.generated.d.ts +10 -8
- package/esm/shaders/pointMark.iface.generated.js +18 -16
- package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -1
- package/esm/shaders/pointMark.wgsl.generated.js +1 -1
- package/package.json +7 -4
- package/src/shaders/arcHull.test.ts +87 -0
- package/src/shaders/barMark.slang +2 -2
- package/src/shaders/capsule.js.generated.ts +2 -2
- package/src/shaders/capsule.slang +69 -24
- package/src/shaders/clipStrip.slang +1 -1
- package/src/shaders/colorPack.slang +2 -2
- package/src/shaders/colorRampLut.slang +7 -7
- package/src/shaders/connectorMark.consts.generated.ts +24 -0
- package/src/shaders/connectorMark.generated.ts +12 -0
- package/src/shaders/connectorMark.glsl.generated.ts +6 -0
- package/src/shaders/connectorMark.iface.generated.ts +1270 -0
- package/src/shaders/connectorMark.js.generated.ts +52 -0
- package/src/shaders/connectorMark.slang +287 -0
- package/src/shaders/connectorMark.wgsl.generated.ts +4 -0
- package/src/shaders/coverageBand.slang +10 -12
- package/src/shaders/coverageInterbase.glsl.generated.ts +1 -1
- package/src/shaders/coverageInterbase.slang +24 -21
- package/src/shaders/coverageInterbase.wgsl.generated.ts +1 -1
- package/src/shaders/coverageSnp.slang +1 -1
- package/src/shaders/curveDistance.js.generated.ts +100 -0
- package/src/shaders/curveDistance.slang +104 -1
- package/src/shaders/farDome.test.ts +117 -0
- package/src/shaders/hpClampFloor.test.ts +0 -4
- package/src/shaders/lineCenterMark.glsl.generated.ts +2 -2
- package/src/shaders/lineCenterMark.slang +14 -22
- package/src/shaders/lineCenterMark.wgsl.generated.ts +1 -1
- package/src/shaders/lineCommon.slang +10 -10
- package/src/shaders/lineStepMark.slang +5 -5
- package/src/shaders/linkMark.consts.generated.ts +2 -0
- package/src/shaders/linkMark.glsl.generated.ts +2 -2
- package/src/shaders/linkMark.js.generated.ts +27 -1
- package/src/shaders/linkMark.slang +58 -18
- package/src/shaders/linkMark.wgsl.generated.ts +1 -1
- package/src/shaders/markColor.slang +10 -10
- package/src/shaders/pointMark.glsl.generated.ts +1 -1
- package/src/shaders/pointMark.iface.generated.ts +19 -16
- package/src/shaders/pointMark.slang +12 -8
- package/src/shaders/pointMark.wgsl.generated.ts +1 -1
- package/src/shaders/rowRect.slang +3 -3
- package/src/shaders/rowTable.slang +7 -7
- package/src/shaders/scoreScale.slang +1 -1
- package/src/shaders/spanMark.slang +5 -5
- package/src/shaders/viewRegion.slang +13 -0
- package/esm/shaders/coverageIndicator.generated.js +0 -7
- package/esm/shaders/coverageIndicator.glsl.generated.d.ts +0 -2
- package/esm/shaders/coverageIndicator.glsl.generated.js +0 -4
- package/esm/shaders/coverageIndicator.iface.generated.d.ts +0 -85
- package/esm/shaders/coverageIndicator.iface.generated.js +0 -114
- package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +0 -1
- package/esm/shaders/coverageIndicator.wgsl.generated.js +0 -3
- package/src/shaders/coverageIndicator.generated.ts +0 -11
- package/src/shaders/coverageIndicator.glsl.generated.ts +0 -6
- package/src/shaders/coverageIndicator.iface.generated.ts +0 -172
- package/src/shaders/coverageIndicator.slang +0 -61
- package/src/shaders/coverageIndicator.wgsl.generated.ts +0 -4
package/esm/marks/lineMark.d.ts
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import type { ColorChannel } from './markRamp.ts';
|
|
2
2
|
import type { RowChannel, RowParams } from './rowLane.ts';
|
|
3
|
-
import type { MarkColorScale, MarkShape } from './types.ts';
|
|
3
|
+
import type { MarkColorScale, MarkContext2D, MarkShape } from './types.ts';
|
|
4
4
|
import type { MarkValueScale } from './valueScale.ts';
|
|
5
5
|
/**
|
|
6
6
|
* The `line` shape's channels: a stroke through consecutive instances of one
|
|
7
|
-
* row
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* row and one `series`, in the order given, each instance a span from `x` to
|
|
8
|
+
* `x2` at `y` on the value scale. The caller hands each series' instances
|
|
9
|
+
* together; a change of row or series starts a new run, and absent, a row is
|
|
10
|
+
* one series. `gapBp` is the linear variant's break: a midpoint further than
|
|
11
|
+
* that from the previous one starts a new run. Both ride with the data, as
|
|
12
|
+
* the neighbour fields the packer derives from them do, so both backends
|
|
13
|
+
* break in the same place.
|
|
12
14
|
*/
|
|
13
15
|
export interface LineChannels extends ColorChannel, RowChannel {
|
|
14
16
|
x: Uint32Array;
|
|
15
17
|
x2: Uint32Array;
|
|
16
18
|
y: Float32Array;
|
|
19
|
+
series?: Uint32Array;
|
|
17
20
|
gapBp?: number;
|
|
18
21
|
count: number;
|
|
19
22
|
}
|
|
20
23
|
export interface LineParams extends RowParams, MarkValueScale {
|
|
21
|
-
/** The quantitative
|
|
24
|
+
/** The quantitative color scale, for a line whose color is a ramp or a threshold. */
|
|
22
25
|
colorScale?: MarkColorScale;
|
|
23
26
|
/**
|
|
24
|
-
* Whether the
|
|
25
|
-
* cut sit on the y scale, so the line changes
|
|
26
|
-
* otherwise each instance takes its own value's
|
|
27
|
+
* Whether the color field is the plotted `y`. Only then does a threshold's
|
|
28
|
+
* cut sit on the y scale, so the line changes color where it crosses one;
|
|
29
|
+
* otherwise each instance takes its own value's color.
|
|
27
30
|
*/
|
|
28
31
|
colorFromY?: boolean;
|
|
29
32
|
/** The value a step drops to across a gap. */
|
|
@@ -35,6 +38,37 @@ export interface LineParams extends RowParams, MarkValueScale {
|
|
|
35
38
|
}
|
|
36
39
|
/** `step` holds each value across its span; `linear` joins the spans' midpoints. */
|
|
37
40
|
export type LineInterpolate = 'step' | 'linear';
|
|
41
|
+
/**
|
|
42
|
+
* What the two tracers hand a pen: the polyline's points, each with the y its
|
|
43
|
+
* color is read at where that differs from the y it is drawn at, and the
|
|
44
|
+
* instance the next points belong to.
|
|
45
|
+
*/
|
|
46
|
+
export interface LinePen {
|
|
47
|
+
instance(i: number): void;
|
|
48
|
+
moveTo(x: number, y: number, colorY?: number): void;
|
|
49
|
+
lineTo(x: number, y: number, colorY?: number): void;
|
|
50
|
+
/** Reads the next segment's color from `colorY` without moving the pen. */
|
|
51
|
+
recolor(colorY: number): void;
|
|
52
|
+
endRun(): void;
|
|
53
|
+
end(): void;
|
|
54
|
+
}
|
|
55
|
+
export declare class BandPen implements LinePen {
|
|
56
|
+
private readonly ctx;
|
|
57
|
+
private readonly top;
|
|
58
|
+
private readonly bottom;
|
|
59
|
+
private x;
|
|
60
|
+
private y;
|
|
61
|
+
private colorY;
|
|
62
|
+
private drawing;
|
|
63
|
+
private readonly path;
|
|
64
|
+
constructor(ctx: MarkContext2D, top: number, bottom: number);
|
|
65
|
+
instance(): void;
|
|
66
|
+
moveTo(x: number, y: number, colorY?: number): void;
|
|
67
|
+
recolor(colorY: number): void;
|
|
68
|
+
lineTo(x: number, y: number, colorY?: number): void;
|
|
69
|
+
endRun(): void;
|
|
70
|
+
end(): void;
|
|
71
|
+
}
|
|
38
72
|
/** The step variant: three square-capped quads an instance, flat filled. */
|
|
39
73
|
export declare const lineStepMark: MarkShape<LineChannels, LineParams>;
|
|
40
74
|
/** The linear variant: one round-capped capsule an instance, max blended. */
|
package/esm/marks/lineMark.js
CHANGED
|
@@ -13,18 +13,19 @@ import { colorBits, isThreshold, paintColors, rampUniforms, } from './markRamp.j
|
|
|
13
13
|
import { bandHeightPx, rowColor, rowColorOverride, rowLane, rowSlot, rowTableKeys, rowTableTextures, } from './rowLane.js';
|
|
14
14
|
import { valueScaleUniforms } from './valueScale.js';
|
|
15
15
|
const NO_GAP = Number.POSITIVE_INFINITY;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// Whether instances `a` and `b` stand on one row and in one series.
|
|
17
|
+
function sameRun(c, row, a, b) {
|
|
18
|
+
return row[a] === row[b] && (!c.series || c.series[a] === c.series[b]);
|
|
18
19
|
}
|
|
19
|
-
// Whether instance `i` abuts the one before it
|
|
20
|
+
// Whether instance `i` abuts the one before it in its run, so the step joins
|
|
20
21
|
// them at a shared corner.
|
|
21
22
|
function abutsBefore(c, row, i) {
|
|
22
|
-
return i > 0 &&
|
|
23
|
+
return i > 0 && sameRun(c, row, i - 1, i) && c.x2[i - 1] === c.x[i];
|
|
23
24
|
}
|
|
24
25
|
// Whether the linear variant links instance `i` to the one before it: the same
|
|
25
|
-
// row, within `gapBp` midpoint to midpoint.
|
|
26
|
+
// row and series, within `gapBp` midpoint to midpoint.
|
|
26
27
|
function linksBefore(c, row, i) {
|
|
27
|
-
if (i === 0 || !
|
|
28
|
+
if (i === 0 || !sameRun(c, row, i - 1, i)) {
|
|
28
29
|
return false;
|
|
29
30
|
}
|
|
30
31
|
const gapBp = c.gapBp ?? NO_GAP;
|
|
@@ -98,16 +99,16 @@ function valueYPx(g, value, slot) {
|
|
|
98
99
|
return (rowBandTopPx(g.rowOffsetPx, g.pitch, slot) +
|
|
99
100
|
valueToYPxScaled(value, g.domainMin, g.domainMax, g.band, g.scaleType, g.symlogConstant));
|
|
100
101
|
}
|
|
101
|
-
// A value's y in the band for the
|
|
102
|
+
// A value's y in the band for the color test, placed UNCLAMPED where
|
|
102
103
|
// `valueYPx` clamps it to draw: the cuts go through it, and so does the line a
|
|
103
|
-
// threshold
|
|
104
|
+
// threshold colors along, as the shader's `lineColorYPx` does.
|
|
104
105
|
function colorYPx(g, value, slot) {
|
|
105
106
|
const norm = normalizeScoreUnclamped(value, g.domainMin, g.domainMax, g.scaleType, g.symlogConstant);
|
|
106
107
|
return rowBandTopPx(g.rowOffsetPx, g.pitch, slot) + (1 - norm) * g.band;
|
|
107
108
|
}
|
|
108
|
-
// One
|
|
109
|
-
// the pen, so a segment carries the
|
|
110
|
-
// the shader's per-instance
|
|
109
|
+
// One color per instance: a change ends the stroke batch and reopens it from
|
|
110
|
+
// the pen, so a segment carries the color of the instance it belongs to, as
|
|
111
|
+
// the shader's per-instance color does.
|
|
111
112
|
class InstancePen {
|
|
112
113
|
ctx;
|
|
113
114
|
colorOf;
|
|
@@ -154,7 +155,7 @@ class InstancePen {
|
|
|
154
155
|
}
|
|
155
156
|
// The part of the segment from y0 to y1, as a fraction of it, inside the band
|
|
156
157
|
// top < y <= bottom; undefined where it misses. A band owns its lower edge,
|
|
157
|
-
// so a line lying on a cut takes the
|
|
158
|
+
// so a line lying on a cut takes the color above it, as the shader does.
|
|
158
159
|
function bandSpan(y0, y1, top, bottom) {
|
|
159
160
|
if (y0 === y1) {
|
|
160
161
|
return top < y0 && y0 <= bottom ? [0, 1] : undefined;
|
|
@@ -168,10 +169,10 @@ function bandSpan(y0, y1, top, bottom) {
|
|
|
168
169
|
: undefined;
|
|
169
170
|
}
|
|
170
171
|
// Keeps the part of each segment inside one threshold band, cut where it
|
|
171
|
-
// crosses the band's edges, so a line stroked once per band changes
|
|
172
|
-
// where the shader's fragments do. A point's
|
|
172
|
+
// crosses the band's edges, so a line stroked once per band changes color
|
|
173
|
+
// where the shader's fragments do. A point's color y is where the band test
|
|
173
174
|
// reads it and its y where it draws, which part where the drawn y is clamped.
|
|
174
|
-
class BandPen {
|
|
175
|
+
export class BandPen {
|
|
175
176
|
ctx;
|
|
176
177
|
top;
|
|
177
178
|
bottom;
|
|
@@ -227,8 +228,8 @@ class BandPen {
|
|
|
227
228
|
}
|
|
228
229
|
// The step polyline over `indices`, in order: a rise from the origin, the top
|
|
229
230
|
// across the span, the step at each joint and a drop to the origin at a gap.
|
|
230
|
-
// A rise is
|
|
231
|
-
//
|
|
231
|
+
// A rise is colored along the y it is drawn at, a level run by its value's
|
|
232
|
+
// color y, as the shader reads them.
|
|
232
233
|
function traceStep(pen, c, g, rows, indices, origin) {
|
|
233
234
|
const { x, x2, y, row, count } = c;
|
|
234
235
|
let inRun = false;
|
|
@@ -285,7 +286,7 @@ function traceCenter(pen, c, g, rows, indices) {
|
|
|
285
286
|
}
|
|
286
287
|
// Along y, the line is stroked once per band per row, each pass keeping the
|
|
287
288
|
// parts of the polyline inside its band; otherwise once, in each instance's
|
|
288
|
-
// own
|
|
289
|
+
// own color. A row the table recolors takes its override either way.
|
|
289
290
|
function paintLine(ctx, c, g, params, trace) {
|
|
290
291
|
const { row, count } = c;
|
|
291
292
|
const scale = params.colorScale;
|
|
@@ -315,7 +316,7 @@ function paintLine(ctx, c, g, params, trace) {
|
|
|
315
316
|
if (scale && isThreshold(scale)) {
|
|
316
317
|
const { cuts, colors } = scale;
|
|
317
318
|
for (const [slot, indices] of bySlot) {
|
|
318
|
-
const cutYs = cuts.map(cut => colorYPx(g, cut, slot));
|
|
319
|
+
const cutYs = cuts.map(cut => colorYPx(g, Math.fround(cut), slot));
|
|
319
320
|
for (let k = 0; k <= cuts.length; k++) {
|
|
320
321
|
ctx.strokeStyle = abgrToCssRgba(colors[k] ?? 0);
|
|
321
322
|
const pen = new BandPen(ctx, k < cuts.length ? cutYs[k] : Number.NEGATIVE_INFINITY, k > 0 ? cutYs[k - 1] : Number.POSITIVE_INFINITY);
|
package/esm/marks/linkMark.d.ts
CHANGED
|
@@ -25,10 +25,9 @@ export interface LinkChannels extends ColorChannel, RowChannel {
|
|
|
25
25
|
feet?: Uint8Array;
|
|
26
26
|
count: number;
|
|
27
27
|
}
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export declare function linkFeet(xDir: number, x2Dir: number): number;
|
|
28
|
+
export { LINK_FOOT_FORWARD, LINK_FOOT_REVERSE, linkFeet } from '../linkFeet.ts';
|
|
29
|
+
/** The channels cut down to instance `i`, for its own painter to trace alone. */
|
|
30
|
+
export declare function linkInstance(c: LinkChannels, i: number): LinkChannels;
|
|
32
31
|
/**
|
|
33
32
|
* One displayed region as a foot places through it: the canvas px of an
|
|
34
33
|
* anchor bp chosen near the view, so a foot's offset from it stays inside
|
|
@@ -50,7 +49,7 @@ export interface LinkSizeScale {
|
|
|
50
49
|
}
|
|
51
50
|
export type LinkShape = 'dome' | 'arc' | 'line';
|
|
52
51
|
export interface LinkParams extends RowParams, MarkValueScale {
|
|
53
|
-
/** The quantitative
|
|
52
|
+
/** The quantitative color scale, for a link whose color is a ramp or a threshold. */
|
|
54
53
|
colorScale?: MarkColorScale;
|
|
55
54
|
/** The view's displayed regions, indexed as `x2Region` and the block's own index are. */
|
|
56
55
|
regions: readonly LinkRegion[];
|
|
@@ -73,6 +72,7 @@ export interface LinkParams extends RowParams, MarkValueScale {
|
|
|
73
72
|
/** How far inside the band the value range ends, the axis's own. */
|
|
74
73
|
insetPx?: number;
|
|
75
74
|
}
|
|
75
|
+
export declare function regionPx(regions: readonly LinkRegion[], index: number, bp: number): number;
|
|
76
76
|
/**
|
|
77
77
|
* Where an instance's curve peaks as the painter and the shader draw it: the
|
|
78
78
|
* centreline's apex in canvas px and how far it stands off its baseline.
|
|
@@ -92,5 +92,22 @@ export interface LinkApex {
|
|
|
92
92
|
* at all, or a far pair's circle, which the band clips to its legs.
|
|
93
93
|
*/
|
|
94
94
|
export declare function linkApex(c: LinkChannels, block: RenderBlock, frame: MarkFrame, params: LinkParams, i: number): LinkApex | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Where a label of instance `i` stands: its apex, or for a far dome whose
|
|
97
|
+
* apex is off the canvas, the dome's point over the middle of the stretch the
|
|
98
|
+
* canvas shows, so a view inside the pair still carries the label. `rise` is
|
|
99
|
+
* the curve's height there.
|
|
100
|
+
*/
|
|
101
|
+
export declare function linkLabelAnchor(c: LinkChannels, block: RenderBlock, frame: MarkFrame, params: LinkParams, i: number): LinkApex | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* The view's region table as a view-spanning shader's uniforms take it: the
|
|
104
|
+
* entries in use, their count, and the drawing region's own entry. Shared
|
|
105
|
+
* arrays, rewritten per call, so a frame allocates nothing per block.
|
|
106
|
+
*/
|
|
107
|
+
export declare function viewRegionUniforms(regions: readonly LinkRegion[], own: number): {
|
|
108
|
+
regionCount: number;
|
|
109
|
+
ownEntry: [number, number, number, number];
|
|
110
|
+
regionTable: [[number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number], [number, number, number, number]];
|
|
111
|
+
};
|
|
95
112
|
export declare const linkMark: MarkShape<LinkChannels, LinkParams>;
|
|
96
113
|
export { LINK_ELSEWHERE, LINK_NO_REGION };
|
package/esm/marks/linkMark.js
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import { getDpr } from '../canvas2dUtils.js';
|
|
2
2
|
import { SCALE_TYPE_LOG } from '../scoreScale.js';
|
|
3
|
-
import { distToWideCirclePx, legSweepAngle, } from '../shaders/curveDistance.js.generated.js';
|
|
3
|
+
import { distToWideCirclePx, farDomeParam, legSweepAngle, } from '../shaders/curveDistance.js.generated.js';
|
|
4
4
|
import { LINK_CURVE_SEGMENTS, LINK_ELSEWHERE, LINK_FOOT_PX, LINK_MAX_REGIONS, LINK_NO_REGION, LINK_NO_SIZE, LINK_LINE_MIN_PX, LINK_SHAPE_ARC, LINK_SHAPE_DOME, LINK_SHAPE_LINE, LINK_SIZE_CONSTANT, LINK_SIZE_SCALED, LINK_STEM_PX, } from '../shaders/linkMark.consts.generated.js';
|
|
5
5
|
import * as shader from '../shaders/linkMark.generated.js';
|
|
6
|
-
import { linkApexPx, linkBaseYPx, linkFootDir, linkFootLenPx, linkIsFar, linkRadiiPx, linkStrokeWidthPx, linkValuePx, } from '../shaders/linkMark.js.generated.js';
|
|
6
|
+
import { linkApexHeld, linkApexPx, linkBaseYPx, linkFootDir, linkFootLenPx, linkIsFar, linkRadiiPx, linkStrokeWidthPx, linkValuePx, } from '../shaders/linkMark.js.generated.js';
|
|
7
7
|
import { slangPass } from '../slangPass.js';
|
|
8
8
|
import { abgrToCssRgba } from './colorFill.js';
|
|
9
9
|
import { ellipseNearest } from './ellipseDistance.js';
|
|
10
10
|
import { nearestInk } from './markHit.js';
|
|
11
|
-
import { colorBits, paintColors, rampUniforms } from './markRamp.js';
|
|
11
|
+
import { colorBits, instanceColor, paintColors, rampUniforms, } from './markRamp.js';
|
|
12
12
|
import { bandHeightPx, rowColor, rowLane, rowSlot, rowTableKeys, rowTableTextures, } from './rowLane.js';
|
|
13
13
|
import { valueScaleUniforms } from './valueScale.js';
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
export { LINK_FOOT_FORWARD, LINK_FOOT_REVERSE, linkFeet } from '../linkFeet.js';
|
|
15
|
+
/** The channels cut down to instance `i`, for its own painter to trace alone. */
|
|
16
|
+
export function linkInstance(c, i) {
|
|
17
|
+
return {
|
|
18
|
+
x: c.x.subarray(i, i + 1),
|
|
19
|
+
x2: c.x2.subarray(i, i + 1),
|
|
20
|
+
x2Region: c.x2Region.subarray(i, i + 1),
|
|
21
|
+
y: c.y?.subarray(i, i + 1),
|
|
22
|
+
size: c.size?.subarray(i, i + 1),
|
|
23
|
+
feet: c.feet?.subarray(i, i + 1),
|
|
24
|
+
row: c.row?.subarray(i, i + 1),
|
|
25
|
+
color: instanceColor(c.color, i),
|
|
26
|
+
count: 1,
|
|
27
|
+
};
|
|
20
28
|
}
|
|
21
29
|
const KIND_ELLIPSE = 0;
|
|
22
30
|
const KIND_CIRCLE = 1;
|
|
@@ -26,6 +34,7 @@ const KIND_LINE = 4;
|
|
|
26
34
|
// The painter's leg polyline: enough segments that the chord sagitta on any
|
|
27
35
|
// leg the band can show is under a pixel.
|
|
28
36
|
const LEG_SEGMENTS = 32;
|
|
37
|
+
const FAR_DOME_COARSE = 16;
|
|
29
38
|
function linkFrame(block, frame, params) {
|
|
30
39
|
const band = bandHeightPx(params, frame.canvasHeight);
|
|
31
40
|
const { valueScaleType, valueSymlogConstant } = valueScaleUniforms(params);
|
|
@@ -88,7 +97,7 @@ function linkShapeCode(shape) {
|
|
|
88
97
|
? LINK_SHAPE_LINE
|
|
89
98
|
: LINK_SHAPE_DOME;
|
|
90
99
|
}
|
|
91
|
-
function regionPx(regions, index, bp) {
|
|
100
|
+
export function regionPx(regions, index, bp) {
|
|
92
101
|
const r = regions[index];
|
|
93
102
|
return r.anchorPx + (bp - r.anchorBp) * r.signedPxPerBp;
|
|
94
103
|
}
|
|
@@ -171,10 +180,12 @@ function placeCurve(c, g, i) {
|
|
|
171
180
|
g.ry = apex;
|
|
172
181
|
return;
|
|
173
182
|
}
|
|
174
|
-
const [rx, ry] = linkRadiiPx(pairHalf, apex, g.screenW);
|
|
183
|
+
const [rx, ry] = linkRadiiPx(pairHalf, apex, g.screenW, linkApexHeld(g.valued, c.y ? c.y[i] : 0, g.domainMax));
|
|
175
184
|
g.rx = rx;
|
|
176
185
|
g.ry = ry;
|
|
177
|
-
|
|
186
|
+
// A far pair with a low apex keeps its apex (`linkRadiiPx`) and is an
|
|
187
|
+
// ellipse still, traced as chords (`farDomePoints`).
|
|
188
|
+
if (linkIsFar(pairHalf, g.screenW) && ry >= rx) {
|
|
178
189
|
g.kind = KIND_CIRCLE;
|
|
179
190
|
g.legSweep = legSweepAngle(rx, g.reach + g.strokePx / 2);
|
|
180
191
|
g.legHeight = rx * Math.sin(g.legSweep);
|
|
@@ -183,13 +194,7 @@ function placeCurve(c, g, i) {
|
|
|
183
194
|
g.kind = KIND_ELLIPSE;
|
|
184
195
|
}
|
|
185
196
|
}
|
|
186
|
-
|
|
187
|
-
* Instance `i`'s apex, undefined where it draws none on the band: no curve
|
|
188
|
-
* at all, or a far pair's circle, which the band clips to its legs.
|
|
189
|
-
*/
|
|
190
|
-
export function linkApex(c, block, frame, params, i) {
|
|
191
|
-
const g = linkFrame(block, frame, params);
|
|
192
|
-
placeCurve(c, g, i);
|
|
197
|
+
function apexOf(g) {
|
|
193
198
|
if (g.kind === KIND_NONE || g.kind === KIND_CIRCLE) {
|
|
194
199
|
return undefined;
|
|
195
200
|
}
|
|
@@ -202,6 +207,37 @@ export function linkApex(c, block, frame, params, i) {
|
|
|
202
207
|
inward: g.reverse ? -1 : 1,
|
|
203
208
|
};
|
|
204
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Instance `i`'s apex, undefined where it draws none on the band: no curve
|
|
212
|
+
* at all, or a far pair's circle, which the band clips to its legs.
|
|
213
|
+
*/
|
|
214
|
+
export function linkApex(c, block, frame, params, i) {
|
|
215
|
+
const g = linkFrame(block, frame, params);
|
|
216
|
+
placeCurve(c, g, i);
|
|
217
|
+
return apexOf(g);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Where a label of instance `i` stands: its apex, or for a far dome whose
|
|
221
|
+
* apex is off the canvas, the dome's point over the middle of the stretch the
|
|
222
|
+
* canvas shows, so a view inside the pair still carries the label. `rise` is
|
|
223
|
+
* the curve's height there.
|
|
224
|
+
*/
|
|
225
|
+
export function linkLabelAnchor(c, block, frame, params, i) {
|
|
226
|
+
const g = linkFrame(block, frame, params);
|
|
227
|
+
placeCurve(c, g, i);
|
|
228
|
+
const apex = apexOf(g);
|
|
229
|
+
if (!apex || g.kind !== KIND_ELLIPSE || !linkIsFar(g.rx, g.screenW)) {
|
|
230
|
+
return apex;
|
|
231
|
+
}
|
|
232
|
+
const from = Math.max(apex.x - g.rx, 0);
|
|
233
|
+
const to = Math.min(apex.x + g.rx, g.screenW);
|
|
234
|
+
if (to <= from || (apex.x >= 0 && apex.x <= g.screenW)) {
|
|
235
|
+
return apex;
|
|
236
|
+
}
|
|
237
|
+
const x = (from + to) / 2;
|
|
238
|
+
const rise = g.ry * Math.sqrt(Math.max(1 - ((x - apex.x) / g.rx) ** 2, 0));
|
|
239
|
+
return { ...apex, x, y: yAt(g, rise), rise };
|
|
240
|
+
}
|
|
205
241
|
function sizeLane(c) {
|
|
206
242
|
const lane = new Float32Array(c.count);
|
|
207
243
|
for (let i = 0; i < c.count; i++) {
|
|
@@ -243,6 +279,18 @@ function fillTable(regions) {
|
|
|
243
279
|
}
|
|
244
280
|
return n;
|
|
245
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* The view's region table as a view-spanning shader's uniforms take it: the
|
|
284
|
+
* entries in use, their count, and the drawing region's own entry. Shared
|
|
285
|
+
* arrays, rewritten per call, so a frame allocates nothing per block.
|
|
286
|
+
*/
|
|
287
|
+
export function viewRegionUniforms(regions, own) {
|
|
288
|
+
return {
|
|
289
|
+
regionCount: fillTable(regions),
|
|
290
|
+
ownEntry: tableEntry(regions[own]),
|
|
291
|
+
regionTable: TABLE,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
246
294
|
// Canvas y of a point `up` px from the baseline on the drawn side.
|
|
247
295
|
function yAt(g, up) {
|
|
248
296
|
return g.baseY - g.ySign * up;
|
|
@@ -265,6 +313,34 @@ function legPoints(g, footX, legDir) {
|
|
|
265
313
|
}
|
|
266
314
|
return points;
|
|
267
315
|
}
|
|
316
|
+
// A far dome as chords from the foot nearer the canvas, stepped as the shader
|
|
317
|
+
// steps it: fine over the stretch the canvas shows, coarse over the rest. A
|
|
318
|
+
// canvas flattens an ellipse tens of thousands of px wide into too few curves
|
|
319
|
+
// to hold its feet.
|
|
320
|
+
function farDomePoints(g, left, right) {
|
|
321
|
+
const fromRight = g.screenW / 2 - left > g.rx;
|
|
322
|
+
const footX = fromRight ? right : left;
|
|
323
|
+
const dir = fromRight ? -1 : 1;
|
|
324
|
+
const margin = g.strokePx;
|
|
325
|
+
const u0 = farDomeParam(fromRight ? footX - g.screenW - margin : -margin - footX, g.rx);
|
|
326
|
+
const u1 = Math.max(u0, farDomeParam(fromRight ? footX + margin : g.screenW + margin - footX, g.rx));
|
|
327
|
+
const coarse = Array.from({ length: FAR_DOME_COARSE + 1 }, (_, k) => Math.sin(((k / FAR_DOME_COARSE) * Math.PI) / 2));
|
|
328
|
+
const fine = Array.from({ length: LINK_CURVE_SEGMENTS + 1 }, (_, k) => u0 + ((u1 - u0) * k) / LINK_CURVE_SEGMENTS);
|
|
329
|
+
return [
|
|
330
|
+
...coarse.filter(u => u < u0),
|
|
331
|
+
...fine,
|
|
332
|
+
...coarse.filter(u => u > u1),
|
|
333
|
+
].map(u => ({
|
|
334
|
+
x: footX + dir * 2 * g.rx * u * u,
|
|
335
|
+
y: yAt(g, 2 * g.ry * u * Math.sqrt(1 - u * u)),
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
function traceChords(ctx, points) {
|
|
339
|
+
ctx.moveTo(points[0].x, points[0].y);
|
|
340
|
+
for (let k = 1; k < points.length; k++) {
|
|
341
|
+
ctx.lineTo(points[k].x, points[k].y);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
268
344
|
function tracePath(ctx, g) {
|
|
269
345
|
const { baseY } = g;
|
|
270
346
|
if (g.kind === KIND_STEM) {
|
|
@@ -286,14 +362,14 @@ function tracePath(ctx, g) {
|
|
|
286
362
|
[right, 1],
|
|
287
363
|
[left, -1],
|
|
288
364
|
]) {
|
|
289
|
-
|
|
290
|
-
ctx.moveTo(points[0].x, points[0].y);
|
|
291
|
-
for (let k = 1; k < points.length; k++) {
|
|
292
|
-
ctx.lineTo(points[k].x, points[k].y);
|
|
293
|
-
}
|
|
365
|
+
traceChords(ctx, legPoints(g, footX, legDir));
|
|
294
366
|
}
|
|
295
367
|
return;
|
|
296
368
|
}
|
|
369
|
+
if (linkIsFar(g.rx, g.screenW)) {
|
|
370
|
+
traceChords(ctx, farDomePoints(g, left, right));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
297
373
|
const mid = (left + right) / 2;
|
|
298
374
|
if (g.reverse) {
|
|
299
375
|
ctx.moveTo(mid + g.rx, baseY);
|
|
@@ -458,7 +534,9 @@ function nearestRising(g, px, py) {
|
|
|
458
534
|
return { x, y: baseY, dist: Math.hypot(px - x, py - baseY) };
|
|
459
535
|
}
|
|
460
536
|
const near = ellipseNearest(px - mid, py - baseY, g.rx, g.ry);
|
|
461
|
-
|
|
537
|
+
// The drawn half rises from the baseline. A cursor on the baseline is as
|
|
538
|
+
// near the mirrored half, and the solve may name that one.
|
|
539
|
+
return { x: mid + near.x, y: baseY - Math.abs(near.y), dist: near.dist };
|
|
462
540
|
}
|
|
463
541
|
export const linkMark = {
|
|
464
542
|
id: 'link',
|
|
@@ -110,7 +110,7 @@ export declare function createMarkBackend<TRegion, TState extends FrameDimension
|
|
|
110
110
|
/**
|
|
111
111
|
* What the frame is cleared to, when transparent is the wrong answer. The
|
|
112
112
|
* GPU side hands it to `beginFrame` and the Canvas2D side fills it after
|
|
113
|
-
* `prepareCanvas`, so both backends composite over the same
|
|
113
|
+
* `prepareCanvas`, so both backends composite over the same color — which
|
|
114
114
|
* synteny needs, its indel wedges being pre-blended against the band's
|
|
115
115
|
* ground rather than composited over it.
|
|
116
116
|
*/
|
package/esm/marks/markBackend.js
CHANGED
|
@@ -63,7 +63,7 @@ export function drawPlannedPasses(hal, plan, regionKey) {
|
|
|
63
63
|
// its sampler unconditionally, and a textured pass missing a texture draws
|
|
64
64
|
// nothing on either GPU HAL. A mark declaring no `texture` at all is the same case —
|
|
65
65
|
// `pointMark` carries a sampler for the shapes that ramp, and a point of a
|
|
66
|
-
// constant
|
|
66
|
+
// constant color draws it without one.
|
|
67
67
|
const INERT_RAMP = new Uint8Array(COLOR_RAMP_LUT_ENTRIES * 4);
|
|
68
68
|
/**
|
|
69
69
|
* The texture each textured pass holds, by identity — the mirror of the one
|
package/esm/marks/markRamp.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { MarkColorScale, MarkThreshold } from './types.ts';
|
|
2
2
|
/**
|
|
3
|
-
* A
|
|
3
|
+
* A color channel as a shape reads it: `color`, the packed ABGR the worker
|
|
4
4
|
* resolved — one per instance, or one number for all of them — or
|
|
5
5
|
* `colorValue`, the raw values a frame's {@link MarkColorScale} turns into
|
|
6
|
-
*
|
|
6
|
+
* colors here. A shape reading a scale declares both optional and asks
|
|
7
7
|
* {@link colorBits} for the GPU and {@link paintColors} for Canvas2D.
|
|
8
8
|
*/
|
|
9
9
|
export interface ColorChannel {
|
|
@@ -19,13 +19,13 @@ interface RampBake {
|
|
|
19
19
|
scale: MarkColorScale;
|
|
20
20
|
colors: Uint32Array;
|
|
21
21
|
}
|
|
22
|
-
/** Whether a
|
|
22
|
+
/** Whether a color scale is a threshold rather than a ramp. */
|
|
23
23
|
export declare function isThreshold(scale: MarkColorScale): scale is MarkThreshold;
|
|
24
24
|
type Rgba = [number, number, number, number];
|
|
25
25
|
type Bands = [Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba, Rgba];
|
|
26
26
|
/**
|
|
27
|
-
* `markColor.slang`'s uniforms for a frame's
|
|
28
|
-
* mode, a ramp's domain and middle, and a threshold's cuts and band
|
|
27
|
+
* `markColor.slang`'s uniforms for a frame's color scale, or for none: the
|
|
28
|
+
* mode, a ramp's domain and middle, and a threshold's cuts and band colors.
|
|
29
29
|
* Every valued shape's uniform block carries the set.
|
|
30
30
|
*/
|
|
31
31
|
export declare function rampUniforms(scale: MarkColorScale | undefined): {
|
|
@@ -40,8 +40,8 @@ export declare function rampUniforms(scale: MarkColorScale | undefined): {
|
|
|
40
40
|
/**
|
|
41
41
|
* The 4-byte instance lane, for the packer. Under a scale it is the value's
|
|
42
42
|
* float32 bits viewed as the `uint` the attribute declares — the reinterpret
|
|
43
|
-
* `markColor.slang`'s `asfloat` undoes, and the reason a quantitative
|
|
44
|
-
* adds no lane. A constant
|
|
43
|
+
* `markColor.slang`'s `asfloat` undoes, and the reason a quantitative color
|
|
44
|
+
* adds no lane. A constant color fills a lane for the pack alone, which the
|
|
45
45
|
* payload never holds.
|
|
46
46
|
*/
|
|
47
47
|
export declare function colorBits(c: ColorChannel, count: number): ArrayLike<number>;
|
|
@@ -63,12 +63,12 @@ export declare function keepRampValues(values: Float32Array, keep: (value: numbe
|
|
|
63
63
|
*/
|
|
64
64
|
export declare function thresholdBandOf(value: number, cuts: readonly number[]): number;
|
|
65
65
|
/**
|
|
66
|
-
* The packed
|
|
66
|
+
* The packed colors a painter fills with. Under a scale the values are baked
|
|
67
67
|
* against it once and kept on the payload, so a repaint at an unchanged scale
|
|
68
68
|
* — every pan and every hover — walks no values and the painters' fill
|
|
69
|
-
* batching still sees runs of one
|
|
70
|
-
* scale type, the ramp's bytes or a threshold's cuts or
|
|
71
|
-
* constant
|
|
69
|
+
* batching still sees runs of one color. The bake reruns when the domain, the
|
|
70
|
+
* scale type, the ramp's bytes or a threshold's cuts or colors move. A
|
|
71
|
+
* constant color expands once and is kept the same way.
|
|
72
72
|
*/
|
|
73
73
|
export declare function paintColors(c: ColorChannel, count: number, scale: MarkColorScale | undefined): ArrayLike<number>;
|
|
74
74
|
export {};
|
package/esm/marks/markRamp.js
CHANGED
|
@@ -3,7 +3,7 @@ import { rampMidT } from '../shaders/colorRampLut.js.generated.js';
|
|
|
3
3
|
import { MAX_COLOR_BANDS, MAX_COLOR_CUTS, RAMP_LINEAR, RAMP_LOG, RAMP_NONE, RAMP_NOT_A_NUMBER_COLOR, RAMP_NO_VALUE_BITS, RAMP_NO_VALUE_COLOR, RAMP_THRESHOLD, } from '../shaders/markColor.generated.js';
|
|
4
4
|
import { normalizeScore } from '../shaders/scoreScale.js.generated.js';
|
|
5
5
|
const NO_COLORS = new Uint32Array(0);
|
|
6
|
-
/** Whether a
|
|
6
|
+
/** Whether a color scale is a threshold rather than a ramp. */
|
|
7
7
|
export function isThreshold(scale) {
|
|
8
8
|
return 'cuts' in scale;
|
|
9
9
|
}
|
|
@@ -31,8 +31,8 @@ function quad(values, from) {
|
|
|
31
31
|
];
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* `markColor.slang`'s uniforms for a frame's
|
|
35
|
-
* mode, a ramp's domain and middle, and a threshold's cuts and band
|
|
34
|
+
* `markColor.slang`'s uniforms for a frame's color scale, or for none: the
|
|
35
|
+
* mode, a ramp's domain and middle, and a threshold's cuts and band colors.
|
|
36
36
|
* Every valued shape's uniform block carries the set.
|
|
37
37
|
*/
|
|
38
38
|
export function rampUniforms(scale) {
|
|
@@ -69,8 +69,8 @@ export function rampUniforms(scale) {
|
|
|
69
69
|
/**
|
|
70
70
|
* The 4-byte instance lane, for the packer. Under a scale it is the value's
|
|
71
71
|
* float32 bits viewed as the `uint` the attribute declares — the reinterpret
|
|
72
|
-
* `markColor.slang`'s `asfloat` undoes, and the reason a quantitative
|
|
73
|
-
* adds no lane. A constant
|
|
72
|
+
* `markColor.slang`'s `asfloat` undoes, and the reason a quantitative color
|
|
73
|
+
* adds no lane. A constant color fills a lane for the pack alone, which the
|
|
74
74
|
* payload never holds.
|
|
75
75
|
*/
|
|
76
76
|
export function colorBits(c, count) {
|
|
@@ -129,12 +129,12 @@ function sameScale(a, b) {
|
|
|
129
129
|
midNormOf(a) === midNormOf(b));
|
|
130
130
|
}
|
|
131
131
|
/**
|
|
132
|
-
* The packed
|
|
132
|
+
* The packed colors a painter fills with. Under a scale the values are baked
|
|
133
133
|
* against it once and kept on the payload, so a repaint at an unchanged scale
|
|
134
134
|
* — every pan and every hover — walks no values and the painters' fill
|
|
135
|
-
* batching still sees runs of one
|
|
136
|
-
* scale type, the ramp's bytes or a threshold's cuts or
|
|
137
|
-
* constant
|
|
135
|
+
* batching still sees runs of one color. The bake reruns when the domain, the
|
|
136
|
+
* scale type, the ramp's bytes or a threshold's cuts or colors move. A
|
|
137
|
+
* constant color expands once and is kept the same way.
|
|
138
138
|
*/
|
|
139
139
|
export function paintColors(c, count, scale) {
|
|
140
140
|
const { colorValue, color } = c;
|
package/esm/marks/pointMark.d.ts
CHANGED
|
@@ -6,18 +6,21 @@ import type { MarkFrame, MarkColorScale, MarkShape } from './types.ts';
|
|
|
6
6
|
import type { MarkValueScale } from './valueScale.ts';
|
|
7
7
|
/**
|
|
8
8
|
* The `point` shape's channels: a glyph per instance at the centre of
|
|
9
|
-
* `x`..`x2`, on the `y` scale.
|
|
9
|
+
* `x`..`x2`, on the `y` scale, at 0 where `y` is absent. `glyph` is one per
|
|
10
|
+
* instance or one for all of them, as `color` is.
|
|
10
11
|
*/
|
|
11
12
|
export interface PointChannels extends ColorChannel, RowChannel {
|
|
12
13
|
x: Uint32Array;
|
|
13
14
|
x2: Uint32Array;
|
|
14
|
-
y
|
|
15
|
-
glyph: Uint8Array;
|
|
15
|
+
y?: Float32Array;
|
|
16
|
+
glyph: Uint8Array | number;
|
|
16
17
|
count: number;
|
|
17
18
|
}
|
|
18
|
-
/**
|
|
19
|
+
/** The channels cut down to instance `i`, for its own painter to trace alone. */
|
|
20
|
+
export declare function pointInstance(c: PointChannels, i: number): PointChannels;
|
|
21
|
+
/** What the point and rule shapes share: a value scale, rows and a color scale. */
|
|
19
22
|
export interface ValuedMarkParams extends RowParams, MarkValueScale {
|
|
20
|
-
/** The quantitative
|
|
23
|
+
/** The quantitative color scale, for a mark whose color is a ramp or a threshold. */
|
|
21
24
|
colorScale?: MarkColorScale;
|
|
22
25
|
/**
|
|
23
26
|
* How far inside the plot the value range ends, so a mark at a domain
|
|
@@ -29,6 +32,8 @@ export interface ValuedMarkParams extends RowParams, MarkValueScale {
|
|
|
29
32
|
export interface PointParams extends ValuedMarkParams {
|
|
30
33
|
/** Glyph diameter in CSS px. */
|
|
31
34
|
diameterPx: number;
|
|
35
|
+
/** The triangle's height in CSS px, where it is not `diameterPx`. */
|
|
36
|
+
triangleHeightPx?: number;
|
|
32
37
|
}
|
|
33
38
|
/**
|
|
34
39
|
* The point shader's uniforms, which the rule shape draws through too:
|
|
@@ -36,6 +41,7 @@ export interface PointParams extends ValuedMarkParams {
|
|
|
36
41
|
*/
|
|
37
42
|
export declare function writePointUniforms(scratch: ArrayBuffer, clip: BlockClipResult, block: RenderBlock, frame: MarkFrame, params: ValuedMarkParams, shape: {
|
|
38
43
|
radiusPx: number;
|
|
44
|
+
triangleRadiusYPx: number;
|
|
39
45
|
rule: boolean;
|
|
40
46
|
minWidthPx: number;
|
|
41
47
|
}): void;
|