@tradecanvas/core 1.10.0 → 1.11.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/dist/{WebGLSeriesRenderer-DQOPCwno.js → WebGLSeriesRenderer-DVJBHdfm.js} +266 -169
- package/dist/WebGLSeriesRenderer-DVJBHdfm.js.map +1 -0
- package/dist/WebGLSeriesRenderer-DjkYvHPQ.cjs +429 -0
- package/dist/WebGLSeriesRenderer-DjkYvHPQ.cjs.map +1 -0
- package/dist/charts/DepthHeatmapBuffer.d.ts +6 -3
- package/dist/charts/DepthHeatmapBuffer.d.ts.map +1 -1
- package/dist/charts/MarketProfileRenderer.d.ts +2 -0
- package/dist/charts/MarketProfileRenderer.d.ts.map +1 -1
- package/dist/charts/VolumeCandleRenderer.d.ts.map +1 -1
- package/dist/charts/pixelGrid.d.ts +10 -0
- package/dist/charts/pixelGrid.d.ts.map +1 -1
- package/dist/engine/RenderEngine.d.ts +10 -4
- package/dist/engine/RenderEngine.d.ts.map +1 -1
- package/dist/engine/gpu.d.ts +15 -2
- package/dist/engine/gpu.d.ts.map +1 -1
- package/dist/{gridLines-kFhXyH-u.js → gridLines-BJLaM2d7.js} +28 -24
- package/dist/gridLines-BJLaM2d7.js.map +1 -0
- package/dist/gridLines-CBmfrSCE.cjs +2 -0
- package/dist/gridLines-CBmfrSCE.cjs.map +1 -0
- package/dist/index.cjs +5 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +735 -709
- package/dist/index.js.map +1 -1
- package/dist/webgl/WebGLSeriesRenderer.d.ts +1 -0
- package/dist/webgl/WebGLSeriesRenderer.d.ts.map +1 -1
- package/dist/webgl/commandDrawer.d.ts.map +1 -1
- package/dist/webgl/recorder.d.ts +18 -1
- package/dist/webgl/recorder.d.ts.map +1 -1
- package/dist/webgl/shaders.d.ts +8 -7
- package/dist/webgl/shaders.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/WebGLSeriesRenderer-DQOPCwno.js.map +0 -1
- package/dist/WebGLSeriesRenderer-DspCYR38.cjs +0 -429
- package/dist/WebGLSeriesRenderer-DspCYR38.cjs.map +0 -1
- package/dist/gridLines-J41F0DQ6.cjs +0 -2
- package/dist/gridLines-J41F0DQ6.cjs.map +0 -1
- package/dist/gridLines-kFhXyH-u.js.map +0 -1
|
@@ -40,6 +40,7 @@ export declare class WebGLSeriesRenderer implements GpuRenderer {
|
|
|
40
40
|
render(frame: GpuFrame): GpuDrawn;
|
|
41
41
|
/** Volume and candles, clipped to the plot. */
|
|
42
42
|
private drawSeries;
|
|
43
|
+
private drawRecorded;
|
|
43
44
|
/** Recorded rectangles: device pixels, already clipped. */
|
|
44
45
|
private drawRecordedRects;
|
|
45
46
|
destroy(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebGLSeriesRenderer.d.ts","sourceRoot":"","sources":["../../src/webgl/WebGLSeriesRenderer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,QAAQ,EAAE,QAAQ,EAAW,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAuB7G;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IAqDjC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IApDtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,UAAU,CAAsC;IACxD,wFAAwF;IACxF,OAAO,CAAC,IAAI,CAAkD;IAC9D,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAA6B;IAEjD,0GAA0G;IAC1G,MAAM,CAAC,MAAM,CAAC,OAAO,GAAE;QAAE,4BAA4B,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,mBAAmB,GAAG,IAAI;IA8BnG,OAAO;IAkBP,mFAAmF;IACnF,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAUlC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,WAAW;IAI5E,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAmBjC,+CAA+C;IAC/C,OAAO,CAAC,UAAU;IA8BlB,2DAA2D;IAC3D,OAAO,CAAC,iBAAiB;IAWzB,OAAO,IAAI,IAAI;IAiBf,OAAO,CAAC,QAAQ,CAAC,UAAU,CAKzB;IAEF,OAAO,CAAC,UAAU;IAalB,0FAA0F;IAC1F,OAAO,CAAC,YAAY;IA0BpB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAoDtB,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,UAAU;IAsBlB,wFAAwF;IACxF,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,GAAG;IAoBX,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,GAAG;CAGZ"}
|
|
1
|
+
{"version":3,"file":"WebGLSeriesRenderer.d.ts","sourceRoot":"","sources":["../../src/webgl/WebGLSeriesRenderer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,QAAQ,EAAE,QAAQ,EAAW,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAuB7G;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IAqDjC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IApDtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,UAAU,CAAsC;IACxD,wFAAwF;IACxF,OAAO,CAAC,IAAI,CAAkD;IAC9D,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAA6B;IAEjD,0GAA0G;IAC1G,MAAM,CAAC,MAAM,CAAC,OAAO,GAAE;QAAE,4BAA4B,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,mBAAmB,GAAG,IAAI;IA8BnG,OAAO;IAkBP,mFAAmF;IACnF,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAUlC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,WAAW;IAI5E,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAmBjC,+CAA+C;IAC/C,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,YAAY;IAKpB,2DAA2D;IAC3D,OAAO,CAAC,iBAAiB;IAWzB,OAAO,IAAI,IAAI;IAiBf,OAAO,CAAC,QAAQ,CAAC,UAAU,CAKzB;IAEF,OAAO,CAAC,UAAU;IAalB,0FAA0F;IAC1F,OAAO,CAAC,YAAY;IA0BpB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAoDtB,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,UAAU;IAsBlB,wFAAwF;IACxF,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,GAAG;IAoBX,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,GAAG;CAGZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commandDrawer.d.ts","sourceRoot":"","sources":["../../src/webgl/commandDrawer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAO,UAAU,EAAY,MAAM,uBAAuB,CAAC;AAYvE,yFAAyF;AACzF,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAEtE;;;;;GAKG;AACH,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAER,GAAG,EAAE,KAAK;IAOvC,gGAAgG;IAChG,IAAI,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"commandDrawer.d.ts","sourceRoot":"","sources":["../../src/webgl/commandDrawer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAO,UAAU,EAAY,MAAM,uBAAuB,CAAC;AAYvE,yFAAyF;AACzF,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAEtE;;;;;GAKG;AACH,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAER,GAAG,EAAE,KAAK;IAOvC,gGAAgG;IAChG,IAAI,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAmB5F,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,MAAM;IASd,iFAAiF;IACjF,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,UAAU;IAclB,+CAA+C;IAC/C,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,KAAK;IAgBb,OAAO,CAAC,SAAS;CAQlB"}
|
package/dist/webgl/recorder.d.ts
CHANGED
|
@@ -10,12 +10,20 @@ declare class Recorder implements GpuRecorder {
|
|
|
10
10
|
readonly ctx: CanvasRenderingContext2D;
|
|
11
11
|
/** Where text goes: the region being recorded. */
|
|
12
12
|
private texts;
|
|
13
|
+
/** Whether the region being recorded takes text. */
|
|
14
|
+
private takesText;
|
|
13
15
|
private state;
|
|
14
16
|
private stack;
|
|
15
17
|
private path;
|
|
16
18
|
private ok;
|
|
19
|
+
/** Where the step being recorded starts in `commands`: rectangles merge into a command of this step only. */
|
|
20
|
+
private stepStart;
|
|
21
|
+
/** The last colour style parsed, premultiplied (charts fill many cells in one, at alphas of their own). */
|
|
22
|
+
private solid;
|
|
17
23
|
constructor(dpr: number, measure: CanvasRenderingContext2D | null);
|
|
18
|
-
region(clip: Rect
|
|
24
|
+
region(clip: Rect, options?: {
|
|
25
|
+
text?: boolean;
|
|
26
|
+
}): GpuRegion;
|
|
19
27
|
private reset;
|
|
20
28
|
private unsupported;
|
|
21
29
|
private copyState;
|
|
@@ -36,12 +44,21 @@ declare class Recorder implements GpuRecorder {
|
|
|
36
44
|
private withPath;
|
|
37
45
|
/** Run `use` on `path`'s shape instead of the current path. */
|
|
38
46
|
private onPath;
|
|
47
|
+
/** A colour style, premultiplied. */
|
|
48
|
+
private baseColor;
|
|
49
|
+
private alpha;
|
|
50
|
+
/** A colour style, premultiplied, at the global alpha. */
|
|
51
|
+
private solidColor;
|
|
39
52
|
/** The style as the GPU paints it, or null when it can't. */
|
|
40
53
|
private paint;
|
|
41
54
|
/** Whether the state draws as plain source-over paint (no shadow, filter or other blending). */
|
|
42
55
|
private plain;
|
|
43
56
|
private fill;
|
|
44
57
|
private fillRects;
|
|
58
|
+
/** A rectangle, clipped, in `color` at `alpha`, added to this step's last command when that holds rectangles too. */
|
|
59
|
+
private pushRect;
|
|
60
|
+
/** fillRect in a plain colour on an axis-aligned transform, straight to a rectangle; anything else through a path. */
|
|
61
|
+
private fillRect;
|
|
45
62
|
private stroke;
|
|
46
63
|
/** The dash pattern in device pixels as two on-off pairs, null for solid; undefined when the GPU can't dash these lines (it dashes single segments, butt-capped). */
|
|
47
64
|
private dash;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/webgl/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAsD,KAAK,UAAU,EAAiB,MAAM,uBAAuB,CAAC;AAI3H,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAyEnD,cAAM,QAAS,YAAW,WAAW;
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/webgl/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAsD,KAAK,UAAU,EAAiB,MAAM,uBAAuB,CAAC;AAI3H,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAyEnD,cAAM,QAAS,YAAW,WAAW;IAgBvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,OAAO;IAflE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAM;IACrC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,kDAAkD;IAClD,OAAO,CAAC,KAAK,CAAgB;IAC7B,oDAAoD;IACpD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,EAAE,CAAQ;IAClB,6GAA6G;IAC7G,OAAO,CAAC,SAAS,CAAK;IACtB,2GAA2G;IAC3G,OAAO,CAAC,KAAK,CAA+C;gBAE/B,GAAG,EAAE,MAAM,EAAmB,OAAO,EAAE,wBAAwB,GAAG,IAAI;IAKnG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS;IA2B3D,OAAO,CAAC,KAAK;IA6Bb,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;IAOjB,2EAA2E;IAC3E,OAAO,CAAC,WAAW;IAKnB,6FAA6F;IAC7F,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,IAAI;IAcZ,OAAO,CAAC,GAAG;IAyBX,sFAAsF;IACtF,OAAO,CAAC,KAAK;IAqBb,OAAO,CAAC,QAAQ;IAQhB,+DAA+D;IAC/D,OAAO,CAAC,MAAM;IAiBd,qCAAqC;IACrC,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,KAAK;IAIb,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAMlB,6DAA6D;IAC7D,OAAO,CAAC,KAAK;IAmBb,gGAAgG;IAChG,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,IAAI;IAiCZ,OAAO,CAAC,SAAS;IAIjB,qHAAqH;IACrH,OAAO,CAAC,QAAQ;IAWhB,sHAAsH;IACtH,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,MAAM;IAkBd,qKAAqK;IACrK,OAAO,CAAC,IAAI;IAUZ;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAYlB,iGAAiG;IACjG,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,OAAO;IA0Cf,OAAO,CAAC,KAAK;IAqBb,6EAA6E;IAC7E,OAAO,CAAC,OAAO;CAmBhB;AAoCD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,QAAQ,CAE9F;AAED,YAAY,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/webgl/shaders.d.ts
CHANGED
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
* The shaders. Each draws axis-aligned rectangles, one instance per
|
|
3
3
|
* rectangle under the bars, bar (or pixel column when zoomed out), placed on
|
|
4
4
|
* device pixels by the same rules as `charts/pixelGrid.ts`, so GPU bars line
|
|
5
|
-
* up with what the 2D layer draws over them (crosshair, drawings).
|
|
6
|
-
*
|
|
5
|
+
* up with what the 2D layer draws over them (crosshair, drawings). Rounding
|
|
6
|
+
* is `floor(v + PIXEL_ROUNDING)`, as `toPixel` there: GLSL's `round()` may
|
|
7
|
+
* round halves either way.
|
|
7
8
|
*/
|
|
8
9
|
/** Candles, a bar per instance: 6 vertices for the wick, then 6 for the body. */
|
|
9
|
-
export declare const CANDLE_BARS_VS
|
|
10
|
+
export declare const CANDLE_BARS_VS: string;
|
|
10
11
|
/** Volume, a bar per instance, under the candle bodies. */
|
|
11
|
-
export declare const VOLUME_BARS_VS
|
|
12
|
+
export declare const VOLUME_BARS_VS: string;
|
|
12
13
|
/**
|
|
13
14
|
* Zoomed out: a pixel column per instance, from the CPU (x, high, low,
|
|
14
15
|
* volume, up), reaching the next column with no gap.
|
|
15
16
|
*/
|
|
16
|
-
export declare const CANDLE_COLUMNS_VS
|
|
17
|
-
export declare const VOLUME_COLUMNS_VS
|
|
17
|
+
export declare const CANDLE_COLUMNS_VS: string;
|
|
18
|
+
export declare const VOLUME_COLUMNS_VS: string;
|
|
18
19
|
/**
|
|
19
20
|
* Rectangles under the bars (grid lines, session shading, break lines): one
|
|
20
21
|
* per instance, in CSS pixels (left, top, right, bottom), in a premultiplied
|
|
@@ -23,7 +24,7 @@ export declare const VOLUME_COLUMNS_VS = "#version 300 es\nprecision highp float
|
|
|
23
24
|
* out how much of each it covers, as Canvas 2D antialiases an edge at a
|
|
24
25
|
* fractional pixel ratio.
|
|
25
26
|
*/
|
|
26
|
-
export declare const RECT_VS
|
|
27
|
+
export declare const RECT_VS: string;
|
|
27
28
|
/**
|
|
28
29
|
* The colour times the share of the pixel covered. For the grid (u_union),
|
|
29
30
|
* coverage goes out as alpha, so that where lines cross the blend gives the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shaders.d.ts","sourceRoot":"","sources":["../../src/webgl/shaders.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shaders.d.ts","sourceRoot":"","sources":["../../src/webgl/shaders.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgDH,iFAAiF;AACjF,eAAO,MAAM,cAAc,QAyC1B,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,cAAc,QAsB1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAe7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAkB7B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,QAcnB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,mrCAiCnB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,wVAYnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradecanvas/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Canvas rendering engine for @tradecanvas/chart",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@tradecanvas/commons": "1.
|
|
37
|
+
"@tradecanvas/commons": "1.11.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"jsdom": "^25.0.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WebGLSeriesRenderer-DQOPCwno.js","names":[],"sources":["../src/webgl/seriesUploads.ts","../src/webgl/glColor.ts","../src/webgl/yMapping.ts","../src/webgl/glKit.ts","../src/webgl/polygonSpans.ts","../src/webgl/recordedShaders.ts","../src/webgl/commandDrawer.ts","../src/webgl/recordedCommands.ts","../src/webgl/recordedPath.ts","../src/webgl/strokeGeometry.ts","../src/webgl/recorder.ts","../src/webgl/shaders.ts","../src/webgl/WebGLSeriesRenderer.ts"],"sourcesContent":["import type { DataSeries, OHLCBar } from '@tradecanvas/commons';\n\n/** Floats per bar on the GPU: open, high, low, close (from the base price), volume, up (1) or down (0). */\nexport const FLOATS_PER_BAR = 6;\n\n/** The bars to write to the GPU buffer after a `sync`: `[from, to)`, or all of them. */\nexport interface SeriesChange {\n full: boolean;\n from: number;\n to: number;\n}\n\nconst same = (a: OHLCBar, b: OHLCBar) =>\n a.time === b.time && a.open === b.open && a.high === b.high && a.low === b.low && a.close === b.close && a.volume === b.volume;\n\n/**\n * The series as the GPU takes it, kept in step with the chart's bars at the\n * least cost. Prices are stored relative to a base price (float32 keeps 24\n * bits: 84,814.20 in absolute terms would lose its cents) and the direction\n * is stored as a flag, so a bar is never mistaken for up or down by float\n * rounding. The chart ticks and appends in the same array: a live tick\n * rewrites one bar and new bars are appended. A new array (new data, older\n * bars paged in) or a changed bar in a sample of the rest writes everything.\n */\nexport class SeriesUploads {\n private buffer = new Float32Array(0);\n private count = 0;\n private basePrice = 0;\n /**\n * Bars as they were written, to tell a tick from new history: the last\n * one, the one before it, and a sample spread over the rest.\n */\n private samples: { index: number; bar: OHLCBar }[] = [];\n private last: OHLCBar | null = null;\n /** The array last written: the chart ticks and appends in place, and replaces it for new history. */\n private source: DataSeries | null = null;\n\n get values(): Float32Array {\n return this.buffer;\n }\n\n get length(): number {\n return this.count;\n }\n\n get base(): number {\n return this.basePrice;\n }\n\n sync(data: DataSeries): SeriesChange {\n const n = data.length;\n if (n === 0) {\n this.reset();\n return { full: true, from: 0, to: 0 };\n }\n const prev = this.count;\n const continues = data === this.source && prev > 0 && n >= prev\n && this.samples.every(({ index, bar }) => same(data[index], bar));\n if (!continues) {\n this.basePrice = data[n - 1].close;\n this.ensure(n);\n this.write(data, 0, n);\n this.remember(data);\n return { full: true, from: 0, to: n };\n }\n // The last bar may have ticked; anything after it is new.\n const from = this.last !== null && same(data[prev - 1], this.last) ? prev : prev - 1;\n if (n > this.buffer.length / FLOATS_PER_BAR) {\n // Out of room: a bigger buffer, written whole.\n this.ensure(n);\n this.write(data, 0, n);\n this.remember(data);\n return { full: true, from: 0, to: n };\n }\n this.write(data, from, n);\n this.remember(data);\n return { full: false, from, to: n };\n }\n\n private reset(): void {\n this.count = 0;\n this.samples = [];\n this.last = null;\n this.source = null;\n }\n\n private ensure(n: number): void {\n if (n * FLOATS_PER_BAR <= this.buffer.length) return;\n // Room to grow: live bars append without a full rewrite for a while.\n this.buffer = new Float32Array(Math.max(n + 1024, Math.ceil(n * 1.25)) * FLOATS_PER_BAR);\n }\n\n private write(data: DataSeries, from: number, to: number): void {\n const v = this.buffer;\n const base = this.basePrice;\n for (let i = from; i < to; i++) {\n const b = data[i];\n const k = i * FLOATS_PER_BAR;\n v[k] = b.open - base;\n v[k + 1] = b.high - base;\n v[k + 2] = b.low - base;\n v[k + 3] = b.close - base;\n v[k + 4] = b.volume;\n v[k + 5] = b.close >= b.open ? 1 : 0;\n }\n this.count = to;\n }\n\n private remember(data: DataSeries): void {\n const n = data.length;\n // Every bar but the last (which may tick): the first, the one before the\n // last, and 14 between. A changed bar elsewhere is new history.\n const settled = n - 1;\n const picks = new Set<number>();\n if (settled > 0) {\n for (let k = 0; k < 16; k++) picks.add(Math.min(settled - 1, Math.round((k * (settled - 1)) / 15)));\n }\n this.samples = [...picks].map((index) => ({ index, bar: { ...data[index] } }));\n this.last = { ...data[n - 1] };\n this.source = data;\n }\n}\n","/** A colour as WebGL takes it: red, green, blue, alpha, each 0 to 1. */\nexport type RGBA = [number, number, number, number];\n\nconst cache = new Map<string, RGBA>();\nlet probe: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null | undefined;\n\nfunction channel(v: string, max: number): number {\n return v.endsWith('%') ? parseFloat(v) / 100 : parseFloat(v) / max;\n}\n\nfunction fromText(text: string): RGBA | null {\n const c = text.trim();\n if (c.toLowerCase() === 'transparent') return [0, 0, 0, 0];\n const hex = /^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(c);\n if (hex) {\n let h = hex[1];\n if (h.length <= 4) h = [...h].map((x) => x + x).join('');\n const n = (i: number) => parseInt(h.slice(i, i + 2), 16) / 255;\n return [n(0), n(2), n(4), h.length === 8 ? n(6) : 1];\n }\n const fn = /^rgba?\\(\\s*([\\d.]+%?)[\\s,]+([\\d.]+%?)[\\s,]+([\\d.]+%?)(?:\\s*[,/]\\s*([\\d.]+%?))?\\s*\\)$/i.exec(c);\n if (fn) {\n return [channel(fn[1], 255), channel(fn[2], 255), channel(fn[3], 255), fn[4] === undefined ? 1 : channel(fn[4], 1)];\n }\n return null;\n}\n\n/** A 2D context to let the browser read any CSS colour (names, hsl()…). */\nfunction browserProbe(): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null {\n if (probe !== undefined) return probe;\n try {\n if (typeof OffscreenCanvas !== 'undefined') probe = new OffscreenCanvas(1, 1).getContext('2d');\n else if (typeof document !== 'undefined') probe = document.createElement('canvas').getContext('2d');\n else probe = null;\n } catch {\n probe = null;\n }\n return probe;\n}\n\n/**\n * A colour as the browser reads it: names and hsl() come back as hex or\n * rgb(); oklch(), color() and the like are painted on a pixel and read back.\n * Null for what Canvas 2D would reject too (it then keeps its last style, so\n * two different starting styles tell).\n */\nfunction viaBrowser(color: string): RGBA | null {\n const ctx = browserProbe();\n if (!ctx) return null;\n ctx.fillStyle = '#000';\n ctx.fillStyle = color;\n const style = String(ctx.fillStyle);\n ctx.fillStyle = '#fff';\n ctx.fillStyle = color;\n if (String(ctx.fillStyle) !== style) return null;\n const text = fromText(style);\n if (text) return text;\n ctx.clearRect(0, 0, 1, 1);\n ctx.fillRect(0, 0, 1, 1);\n const d = ctx.getImageData(0, 0, 1, 1).data;\n return [d[0] / 255, d[1] / 255, d[2] / 255, d[3] / 255];\n}\n\nconst unreadable = new Set<string>();\n\n/** A CSS colour as WebGL takes it, or null when it can't be read (Canvas 2D ignores such a style). */\nexport function readColor(color: string): RGBA | null {\n const hit = cache.get(color);\n if (hit) return hit;\n if (unreadable.has(color)) return null;\n const out = fromText(color) ?? viaBrowser(color);\n if (cache.size > 256) cache.clear();\n if (unreadable.size > 256) unreadable.clear();\n if (out) cache.set(color, out);\n else unreadable.add(color);\n return out;\n}\n\n/**\n * Any CSS colour the chart's themes use, for WebGL. Hex and rgb() are read\n * directly; anything else goes through the browser. Unreadable colours come\n * back transparent, as Canvas 2D would leave them unpainted.\n */\nexport function parseColor(color: string): RGBA {\n return readColor(color) ?? [0, 0, 0, 0];\n}\n\n/** The colour multiplied by its alpha, the form the canvas blends in. */\nexport function premultiplied([r, g, b, a]: RGBA): RGBA {\n return [r * a, g * a, b * a, a];\n}\n","import type { ViewportState } from '@tradecanvas/commons';\n\n/**\n * Price-to-pixel uniforms for a frame, as `priceToYMapper` maps (linear or\n * log, upright or inverted). Prices reach the GPU relative to a base price.\n */\nexport interface YMapping {\n log: number;\n invert: number;\n /** Linear: y = yA + rel * yB. */\n yA: number;\n yB: number;\n /** Log: the base price less the lowest price, and the lowest price. */\n logOffset: number;\n min: number;\n /** Log: the smallest price ratio to the lowest price taken, as `priceToYMapper` floors prices at `Number.EPSILON`. */\n logFloor: number;\n logK: number;\n top: number;\n bottom: number;\n}\n\nexport function yMapping(viewport: ViewportState, base: number): YMapping {\n const { min, max } = viewport.priceRange;\n const { y: top, height } = viewport.chartRect;\n const invert = viewport.invertScale === true ? 1 : 0;\n const flat: YMapping = { log: 0, invert, yA: top + height / 2, yB: 0, logOffset: 0, min: 1, logFloor: 0, logK: 0, top, bottom: top + height };\n if (viewport.logScale && min > 0 && max > 0) {\n const logRange = Math.log(max) - Math.log(min);\n if (logRange === 0) return flat;\n return { ...flat, log: 1, logOffset: base - min, min, logFloor: Number.EPSILON / min, logK: height / logRange };\n }\n const range = max - min;\n if (range === 0) return flat;\n const k = height / range;\n return invert\n ? { ...flat, yA: top + (base - min) * k, yB: k }\n : { ...flat, yA: top + (max - base) * k, yB: -k };\n}\n\n/**\n * The CSS-pixel y the shaders compute for a price `rel` above the base\n * (`cssY` in shaders.ts), step by step; `f` rounds each step, as float32\n * does on the GPU (identity for double precision).\n *\n * Log scale goes through log(1 + (price − min) / min) rather than\n * log(price) − log(min): float32 keeps the small difference exactly where\n * the two large logarithms would lose it.\n */\nexport function mappedY(m: YMapping, rel: number, f: (x: number) => number = (x) => x): number {\n if (m.log === 1) {\n const ratio = f(1 + f(f(rel + m.logOffset) / m.min));\n const v = f(f(Math.log(Math.max(ratio, m.logFloor))) * m.logK);\n return m.invert === 1 ? f(m.top + v) : f(m.bottom - v);\n }\n return f(m.yA + f(rel * m.yB));\n}\n","/** A linked program, its vertex array, and the locations it was asked for. */\nexport interface Program {\n program: WebGLProgram;\n vao: WebGLVertexArrayObject;\n uniforms: Map<string, WebGLUniformLocation | null>;\n attribs: Map<string, number>;\n}\n\n/** The few WebGL 2 chores every program here needs: compile, link, bind, set. */\nexport class GlKit {\n constructor(readonly gl: WebGL2RenderingContext) {}\n\n program(vertexSource: string, fragmentSource: string, attribs: readonly string[]): Program {\n const gl = this.gl;\n const compile = (type: number, source: string) => {\n const shader = gl.createShader(type);\n if (!shader) throw new Error('WebGL: no shader');\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error(`WebGL shader: ${log}`);\n }\n return shader;\n };\n const vs = compile(gl.VERTEX_SHADER, vertexSource);\n const fs = compile(gl.FRAGMENT_SHADER, fragmentSource);\n const program = gl.createProgram();\n if (!program) throw new Error('WebGL: no program');\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error(`WebGL program: ${gl.getProgramInfoLog(program)}`);\n }\n const vao = gl.createVertexArray();\n if (!vao) throw new Error('WebGL: no vertex array');\n const locations = new Map<string, number>();\n for (const name of attribs) locations.set(name, gl.getAttribLocation(program, name));\n return { program, vao, uniforms: new Map(), attribs: locations };\n }\n\n buffer(): WebGLBuffer {\n const b = this.gl.createBuffer();\n if (!b) throw new Error('WebGL: no buffer');\n return b;\n }\n\n use(p: Program): Program {\n this.gl.useProgram(p.program);\n this.gl.bindVertexArray(p.vao);\n return p;\n }\n\n /** A float attribute read from the bound buffer; per instance unless `divisor` is 0. */\n attrib(p: Program, name: string, size: number, stride: number, offset: number, divisor = 1): void {\n const loc = p.attribs.get(name);\n if (loc === undefined || loc < 0) return;\n const gl = this.gl;\n gl.enableVertexAttribArray(loc);\n gl.vertexAttribPointer(loc, size, gl.FLOAT, false, stride, offset);\n gl.vertexAttribDivisor(loc, divisor);\n }\n\n int(p: Program, name: string, v: number): void {\n this.gl.uniform1i(this.loc(p, name), v);\n }\n\n float(p: Program, name: string, v: number): void {\n this.gl.uniform1f(this.loc(p, name), v);\n }\n\n vec2(p: Program, name: string, x: number, y: number): void {\n this.gl.uniform2f(this.loc(p, name), x, y);\n }\n\n vec4(p: Program, name: string, v: readonly number[]): void {\n this.gl.uniform4f(this.loc(p, name), v[0], v[1], v[2], v[3]);\n }\n\n loc(p: Program, name: string): WebGLUniformLocation | null {\n if (!p.uniforms.has(name)) p.uniforms.set(name, this.gl.getUniformLocation(p.program, name));\n return p.uniforms.get(name) ?? null;\n }\n\n deleteProgram(p: Program): void {\n this.gl.deleteVertexArray(p.vao);\n this.gl.deleteProgram(p.program);\n }\n\n /** Scissor to a box in device pixels (y down), widened to whole pixels. False when nothing is left. */\n scissor(x0: number, y0: number, x1: number, y1: number, canvasWidth: number, canvasHeight: number): boolean {\n const left = Math.max(0, Math.floor(x0));\n const top = Math.max(0, Math.floor(y0));\n const right = Math.min(canvasWidth, Math.ceil(x1));\n const bottom = Math.min(canvasHeight, Math.ceil(y1));\n if (!(right > left && bottom > top)) return false;\n const gl = this.gl;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(left, canvasHeight - bottom, right - left, bottom - top);\n return true;\n }\n}\n","/**\n * Polygons the chart fills, as spans the GPU fills straight (no stencil):\n * each pixel inside lies in exactly one span, so it is painted once, as\n * Canvas 2D paints a fill.\n *\n * The chart's fills are bands and areas: two chains running left to right\n * from the polygon's leftmost corner to its rightmost (a channel's upper and\n * lower lines, a line and its base, a cloud's two spans). Filled by winding,\n * nonzero or even-odd alike, such a polygon is what lies between its chains,\n * whichever is on top. So it goes column by column: between two corners'\n * x, each chain is one straight line, and the fill is between the two lines.\n * Any other shape gives null (Canvas 2D draws it).\n */\n\n/** Numbers per span: x0, x1, then chain a's y at x0 and x1, chain b's y at x0 and x1, then 1 if x0 is the polygon's left end, 1 if x1 is its right end. */\nexport const SPAN_FLOATS = 8;\n\n/** The spans filling the closed polygon `points` (x, y pairs); null when it isn't two left-to-right chains. */\nexport function polygonSpans(points: readonly number[]): number[] | null {\n const n = points.length / 2;\n if (n < 3) return [];\n let left = 0;\n let right = 0;\n for (let i = 1; i < n; i++) {\n if (points[2 * i] < points[2 * left]) left = i;\n if (points[2 * i] > points[2 * right]) right = i;\n }\n // No width, no area.\n if (points[2 * left] === points[2 * right]) return [];\n const a = chain(points, left, right, 1, n);\n const b = chain(points, left, right, -1, n);\n if (!a || !b) return null;\n return between(a, b);\n}\n\n/** The signed area of the closed polygon `points`: its sign is the way it winds. */\nexport function signedArea(points: readonly number[]): number {\n let s = 0;\n const n = points.length / 2;\n for (let i = 0; i < n; i++) {\n const j = (i + 1) % n;\n s += points[2 * i] * points[2 * j + 1] - points[2 * j] * points[2 * i + 1];\n }\n return s / 2;\n}\n\n/** The corners from `from` to `to` stepping by `step`, as x, y pairs; null if x ever goes back. */\nfunction chain(p: readonly number[], from: number, to: number, step: 1 | -1, n: number): number[] | null {\n const out = [p[2 * from], p[2 * from + 1]];\n for (let k = from; k !== to; ) {\n k = (k + step + n) % n;\n if (p[2 * k] < out[out.length - 2]) return null;\n out.push(p[2 * k], p[2 * k + 1]);\n }\n return out;\n}\n\n/** A chain's y over [x0, x1] (inside one of its sloping segments): at x0 and at x1. */\nclass Walker {\n private i = 0;\n constructor(private readonly c: readonly number[]) {}\n\n at(x0: number, x1: number): [number, number] {\n const c = this.c;\n // Past segments that end before x1, and upright ones (no width).\n while (this.i + 5 < c.length && (c[this.i + 2] < x1 || c[this.i + 2] === c[this.i])) this.i += 2;\n const ax = c[this.i], ay = c[this.i + 1], bx = c[this.i + 2], by = c[this.i + 3];\n const y = (x: number) => (bx === ax ? ay : ay + ((by - ay) * (x - ax)) / (bx - ax));\n return [y(x0), y(x1)];\n }\n}\n\nfunction between(a: readonly number[], b: readonly number[]): number[] {\n const xs = new Set<number>();\n for (let k = 0; k < a.length; k += 2) xs.add(a[k]);\n for (let k = 0; k < b.length; k += 2) xs.add(b[k]);\n const sorted = [...xs].sort((u, v) => u - v);\n const wa = new Walker(a);\n const wb = new Walker(b);\n const out: number[] = [];\n const last = sorted.length - 2;\n for (let k = 0; k <= last; k++) {\n const x0 = sorted[k];\n const x1 = sorted[k + 1];\n const [a0, a1] = wa.at(x0, x1);\n const [b0, b1] = wb.at(x0, x1);\n // Where the chains meet all along, nothing.\n if (a0 === b0 && a1 === b1) continue;\n out.push(x0, x1, a0, a1, b0, b1, k === 0 ? 1 : 0, k === last ? 1 : 0);\n }\n return out;\n}\n","/**\n * Shaders for drawing recorded Canvas 2D: strokes, filled polygons and\n * discs, in device pixels. Each fragment works out how much of its pixel the\n * shape covers, as Canvas 2D antialiasing does, times how much of it the\n * clip lets through.\n */\n\nconst COMMON = `#version 300 es\nprecision highp float;\nuniform vec2 u_canvas;\nuniform vec4 u_clip;\n\nvec4 toClip(vec2 dev) {\n return vec4(dev.x / u_canvas.x * 2.0 - 1.0, 1.0 - dev.y / u_canvas.y * 2.0, 0.0, 1.0);\n}\n`;\n\nconst CORNER = `\nvec2 corner(int k) {\n if (k == 0) return vec2(0.0, 0.0);\n if (k == 1 || k == 4) return vec2(1.0, 0.0);\n if (k == 2 || k == 3) return vec2(0.0, 1.0);\n return vec2(1.0, 1.0);\n}\nconst vec4 NOWHERE = vec4(-2.0, -2.0, 0.0, 1.0);\n`;\n\nconst PIXEL = `\n// This fragment's pixel centre in device pixels, y down.\nvec2 pixelCentre() { return vec2(gl_FragCoord.x, u_canvas.y - gl_FragCoord.y); }\n\n// The share of the pixel centred at p inside the clip.\nfloat clipCoverage(vec2 p) {\n vec2 lo = p - 0.5;\n vec2 c = clamp(min(lo + 1.0, u_clip.zw) - max(lo, u_clip.xy), 0.0, 1.0);\n return c.x * c.y;\n}\n`;\n\n/**\n * A stroke, one segment per instance: the segment's two points and two\n * neighbours either side (x, y, w, length along; w 1 drawn, 0 a neighbour\n * only, -1 none). The quad covers the segment and its round ends.\n */\nexport const STROKE_VS = `${COMMON}${CORNER}\nuniform float u_hw;\nin vec4 a_p0;\nin vec4 a_p1;\nin vec4 a_p2;\nin vec4 a_p3;\nin vec4 a_p4;\nin vec4 a_p5;\nflat out vec4 v_p0;\nflat out vec4 v_p1;\nflat out vec4 v_p2;\nflat out vec4 v_p3;\nflat out vec4 v_p4;\nflat out vec4 v_p5;\n\nvoid main() {\n v_p0 = a_p0; v_p1 = a_p1; v_p2 = a_p2; v_p3 = a_p3; v_p4 = a_p4; v_p5 = a_p5;\n if (a_p2.z < 0.5 || a_p3.z < 0.5) { gl_Position = NOWHERE; return; }\n vec2 a = a_p2.xy;\n vec2 b = a_p3.xy;\n vec2 d = b - a;\n float len = length(d);\n vec2 dir = len > 0.0 ? d / len : vec2(1.0, 0.0);\n vec2 n = vec2(-dir.y, dir.x);\n float m = u_hw + 1.0;\n vec2 cr = corner(gl_VertexID % 6);\n vec2 pos = mix(a - dir * m, b + dir * m, cr.x) + n * mix(-m, m, cr.y);\n gl_Position = toClip(pos);\n}\n`;\n\n/**\n * A stroke is the union of its segments, round where they join: each pixel\n * is drawn once, by the nearest segment of those around it, with the\n * coverage of the nearest distance. The line's own ends take its cap. A\n * dashed line goes segment by segment, its pattern counted along the line.\n */\nexport const STROKE_FS = `${COMMON}${PIXEL}\nuniform vec4 u_color;\nuniform float u_hw;\nuniform int u_cap;\nuniform vec4 u_dash;\nflat in vec4 v_p0;\nflat in vec4 v_p1;\nflat in vec4 v_p2;\nflat in vec4 v_p3;\nflat in vec4 v_p4;\nflat in vec4 v_p5;\nout vec4 outColor;\n\nfloat segDist(vec2 p, vec2 a, vec2 b) {\n vec2 ab = b - a;\n float l2 = dot(ab, ab);\n float t = l2 > 0.0 ? clamp(dot(p - a, ab) / l2, 0.0, 1.0) : 0.0;\n return length(p - a - t * ab);\n}\n\nbool joined(vec4 a, vec4 b) { return a.z > -0.5 && b.z > -0.5; }\n\n// The share of a pixel at distance d from the centre line inside a line hw either side.\nfloat across(float d) { return clamp(min(u_hw, d + 0.5) - max(-u_hw, d - 0.5), 0.0, 1.0); }\n\n// The share of [s - 0.5, s + 0.5] inside [lo, hi].\nfloat span(float s, float lo, float hi) { return clamp(min(s + 0.5, hi) - max(s - 0.5, lo), 0.0, 1.0); }\n\n// The share of [s - 0.5, s + 0.5] on a dash.\nfloat onDash(float s) {\n float period = u_dash.x + u_dash.y + u_dash.z + u_dash.w;\n float base = s - mod(s, period);\n float on = 0.0;\n for (int k = -1; k <= 1; k++) {\n float p0 = base + float(k) * period;\n on += span(s, p0, p0 + u_dash.x);\n on += span(s, p0 + u_dash.x + u_dash.y, p0 + u_dash.x + u_dash.y + u_dash.z);\n }\n return min(on, 1.0);\n}\n\nvoid main() {\n vec2 p = pixelCentre();\n float clipCov = clipCoverage(p);\n if (clipCov <= 0.0) discard;\n vec2 a = v_p2.xy;\n vec2 b = v_p3.xy;\n vec2 ab = b - a;\n float len = length(ab);\n vec2 dir = len > 0.0 ? ab / len : vec2(1.0, 0.0);\n float along = dot(p - a, dir);\n float perp = abs(dot(p - a, vec2(-dir.y, dir.x)));\n bool startEnd = v_p1.z < -0.5;\n bool finalEnd = v_p4.z < -0.5;\n\n float cov;\n if (u_dash.x + u_dash.y > 0.0) {\n cov = across(perp) * onDash(v_p2.w + along) * span(along, 0.0, len);\n } else {\n float self = segDist(p, a, b);\n float nearest = self;\n if (joined(v_p0, v_p1)) { float d = segDist(p, v_p0.xy, v_p1.xy); if (d <= self) discard; nearest = min(nearest, d); }\n if (joined(v_p1, v_p2)) { float d = segDist(p, v_p1.xy, v_p2.xy); if (d <= self) discard; nearest = min(nearest, d); }\n if (joined(v_p3, v_p4)) { float d = segDist(p, v_p3.xy, v_p4.xy); if (d < self) discard; nearest = min(nearest, d); }\n if (joined(v_p4, v_p5)) { float d = segDist(p, v_p4.xy, v_p5.xy); if (d < self) discard; nearest = min(nearest, d); }\n cov = across(nearest);\n // Past an end of the line: its cap, square-ended (butt or square) or round.\n float before = startEnd ? -along : -1e9;\n float after = finalEnd ? along - len : -1e9;\n if (u_cap != 1 && (before > -0.5 || after > -0.5)) {\n float reach = u_cap == 2 ? u_hw : 0.0;\n float lo = startEnd ? -reach : -1e9;\n float hi = finalEnd ? len + reach : 1e9;\n cov = across(perp) * span(along, lo, hi);\n }\n }\n if (cov <= 0.0) discard;\n outColor = u_color * (cov * clipCov);\n}\n`;\n\n/**\n * Filled polygons as spans (polygonSpans.ts), one per instance: between x0\n * and x1 the fill lies between two straight lines, a and b, whichever is on\n * top. The quad covers the span's box.\n */\nexport const SPAN_VS = `${COMMON}${CORNER}\nin vec2 a_x;\nin vec4 a_ab;\nin vec2 a_ends;\nflat out vec2 v_x;\nflat out vec4 v_ab;\nflat out vec2 v_ends;\n\nvoid main() {\n v_x = a_x;\n v_ab = a_ab;\n v_ends = a_ends;\n float lo = min(min(a_ab.x, a_ab.y), min(a_ab.z, a_ab.w));\n float hi = max(max(a_ab.x, a_ab.y), max(a_ab.z, a_ab.w));\n vec2 cr = corner(gl_VertexID % 6);\n gl_Position = toClip(mix(vec2(floor(a_x.x), floor(lo) - 1.0), vec2(ceil(a_x.y), ceil(hi) + 1.0), cr));\n}\n`;\n\n/**\n * The share of the pixel inside the span: across, the part of its column\n * between the two lines (at the pixel's centre); along, whole pixels by\n * their centre between neighbouring spans (so no seam where they meet), the\n * part inside at the polygon's own two ends. Then the paint: a colour, or a\n * linear gradient of up to four stops blended unpremultiplied, as Canvas 2D\n * blends them.\n */\nexport const SPAN_FS = `${COMMON}${PIXEL}\nuniform int u_kind;\nuniform vec4 u_color;\nuniform vec4 u_line;\nuniform vec4 u_offsets;\nuniform int u_stops;\nuniform vec4 u_stop0;\nuniform vec4 u_stop1;\nuniform vec4 u_stop2;\nuniform vec4 u_stop3;\nflat in vec2 v_x;\nflat in vec4 v_ab;\nflat in vec2 v_ends;\nout vec4 outColor;\n\nvec4 stopColor(int i) {\n if (i == 0) return u_stop0;\n if (i == 1) return u_stop1;\n if (i == 2) return u_stop2;\n return u_stop3;\n}\n\nvec4 gradient(vec2 p) {\n vec2 g = u_line.zw - u_line.xy;\n float l2 = dot(g, g);\n // A gradient of no length paints nothing.\n if (l2 <= 0.0) return vec4(0.0);\n float t = dot(p - u_line.xy, g) / l2;\n vec4 c = stopColor(0);\n for (int i = 1; i < 4; i++) {\n if (i >= u_stops) break;\n float o0 = u_offsets[i - 1];\n float o1 = u_offsets[i];\n if (t >= o1) c = stopColor(i);\n else if (t > o0) { c = mix(stopColor(i - 1), stopColor(i), (t - o0) / max(o1 - o0, 1e-6)); break; }\n else break;\n }\n return vec4(c.rgb * c.a, c.a);\n}\n\nvoid main() {\n vec2 p = pixelCentre();\n float x0 = v_x.x;\n float x1 = v_x.y;\n float left = v_ends.x > 0.5 ? clamp(p.x + 0.5 - x0, 0.0, 1.0) : (p.x >= x0 ? 1.0 : 0.0);\n float right = v_ends.y > 0.5 ? clamp(x1 - (p.x - 0.5), 0.0, 1.0) : (p.x < x1 ? 1.0 : 0.0);\n float along = v_ends.x > 0.5 && v_ends.y > 0.5\n ? clamp(min(p.x + 0.5, x1) - max(p.x - 0.5, x0), 0.0, 1.0)\n : min(left, right);\n float t = clamp((clamp(p.x, x0, x1) - x0) / max(x1 - x0, 1e-6), 0.0, 1.0);\n float ya = mix(v_ab.x, v_ab.y, t);\n float yb = mix(v_ab.z, v_ab.w, t);\n float across = clamp(min(p.y + 0.5, max(ya, yb)) - max(p.y - 0.5, min(ya, yb)), 0.0, 1.0);\n float cov = along * across * clipCoverage(p);\n if (cov <= 0.0) discard;\n vec4 color = u_kind == 1 ? gradient(p) : u_color;\n outColor = color * cov;\n}\n`;\n\n/** Discs, one per instance: centre, radius, premultiplied colour. */\nexport const DISC_VS = `${COMMON}${CORNER}\nin vec3 a_disc;\nin vec4 a_color;\nflat out vec3 v_disc;\nflat out vec4 v_color;\nvoid main() {\n v_disc = a_disc;\n v_color = a_color;\n float m = a_disc.z + 1.0;\n gl_Position = toClip(mix(a_disc.xy - m, a_disc.xy + m, corner(gl_VertexID % 6)));\n}\n`;\n\nexport const DISC_FS = `${COMMON}${PIXEL}\nflat in vec3 v_disc;\nflat in vec4 v_color;\nout vec4 outColor;\nvoid main() {\n vec2 p = pixelCentre();\n float cov = clamp(v_disc.z + 0.5 - length(p - v_disc.xy), 0.0, 1.0) * clipCoverage(p);\n if (cov <= 0.0) discard;\n outColor = v_color * cov;\n}\n`;\n","import type { GlKit, Program } from './glKit.js';\nimport type { Box, GpuCommand, GpuPaint } from './recordedCommands.js';\nimport { SPAN_FLOATS } from './polygonSpans.js';\nimport { DISC_FS, DISC_VS, SPAN_FS, SPAN_VS, STROKE_FS, STROKE_VS } from './recordedShaders.js';\n\n/** Floats per stroke point: x, y, w, length along. */\nconst POINT_FLOATS = 4;\nconst POINT_STRIDE = POINT_FLOATS * 4;\nconst SPAN_STRIDE = SPAN_FLOATS * 4;\n/** Floats per disc: x, y, radius, premultiplied colour. */\nconst DISC_FLOATS = 7;\nconst DISC_STRIDE = DISC_FLOATS * 4;\n\n/** How rectangles are drawn: the background's rectangle program, given its instances. */\nexport type DrawRects = (values: Float32Array, count: number) => void;\n\n/**\n * Draws recorded Canvas 2D commands, in order, over what the renderer drew\n * before: strokes, polygons (as spans that hold each pixel once), discs and\n * rectangles, their coverage worked out per pixel. No stencil: a stencil\n * buffer the size of the canvas costs a clear every frame, used or not.\n */\nexport class CommandDrawer {\n private readonly stroke: Program;\n private readonly span: Program;\n private readonly disc: Program;\n private readonly buffer: WebGLBuffer;\n\n constructor(private readonly kit: GlKit) {\n this.stroke = kit.program(STROKE_VS, STROKE_FS, ['a_p0', 'a_p1', 'a_p2', 'a_p3', 'a_p4', 'a_p5']);\n this.span = kit.program(SPAN_VS, SPAN_FS, ['a_x', 'a_ab', 'a_ends']);\n this.disc = kit.program(DISC_VS, DISC_FS, ['a_disc', 'a_color']);\n this.buffer = kit.buffer();\n }\n\n /** Draw `commands` on a canvas `width` × `height` device pixels; rectangles through `rects`. */\n draw(commands: readonly GpuCommand[], width: number, height: number, rects: DrawRects): void {\n const gl = this.kit.gl;\n gl.enable(gl.BLEND);\n for (const c of commands) {\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n gl.disable(gl.SCISSOR_TEST);\n if (c.type === 'rects') this.drawRects(c.values, rects);\n else if (c.type === 'stroke') this.drawStroke(c, width, height);\n else if (c.type === 'fill') this.drawFill(c, width, height);\n else this.drawDiscs(c.values, c.clip, width, height);\n }\n gl.disable(gl.SCISSOR_TEST);\n }\n\n destroy(): void {\n for (const p of [this.stroke, this.span, this.disc]) this.kit.deleteProgram(p);\n this.kit.gl.deleteBuffer(this.buffer);\n }\n\n private upload(values: Float32Array): void {\n const gl = this.kit.gl;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, values, gl.STREAM_DRAW);\n }\n\n private common(p: Program, clip: Box, width: number, height: number): boolean {\n const kit = this.kit;\n if (!kit.scissor(clip.x0, clip.y0, clip.x1, clip.y1, width, height)) return false;\n kit.use(p);\n kit.vec2(p, 'u_canvas', width, height);\n kit.vec4(p, 'u_clip', [clip.x0, clip.y0, Math.min(clip.x1, width), Math.min(clip.y1, height)]);\n return true;\n }\n\n /** Rectangles in the background program's layout: rectangle, colour, no dash. */\n private drawRects(values: readonly number[], rects: DrawRects): void {\n const count = values.length / 8;\n const out = new Float32Array(count * 10);\n for (let i = 0; i < count; i++) {\n for (let k = 0; k < 8; k++) out[i * 10 + k] = values[i * 8 + k];\n }\n rects(out, count);\n }\n\n private drawStroke(c: Extract<GpuCommand, { type: 'stroke' }>, width: number, height: number): void {\n const p = this.stroke;\n if (!this.common(p, c.clip, width, height)) return;\n const kit = this.kit;\n kit.vec4(p, 'u_color', c.color);\n kit.float(p, 'u_hw', c.width / 2);\n kit.int(p, 'u_cap', c.cap);\n kit.vec4(p, 'u_dash', c.dash ?? [0, 0, 0, 0]);\n this.upload(new Float32Array(c.points));\n for (let k = 0; k < 6; k++) kit.attrib(p, `a_p${k}`, 4, POINT_STRIDE, k * POINT_STRIDE);\n const segments = c.points.length / POINT_FLOATS - 5;\n if (segments > 0) kit.gl.drawArraysInstanced(kit.gl.TRIANGLES, 0, 6, segments);\n }\n\n /** A polygon's spans in its paint, clipped. */\n private drawFill(c: Extract<GpuCommand, { type: 'fill' }>, width: number, height: number): void {\n const kit = this.kit;\n const box = c.bounds;\n if (!kit.scissor(box.x0, box.y0, box.x1, box.y1, width, height)) return;\n const p = kit.use(this.span);\n kit.vec2(p, 'u_canvas', width, height);\n kit.vec4(p, 'u_clip', [c.clip.x0, c.clip.y0, Math.min(c.clip.x1, width), Math.min(c.clip.y1, height)]);\n this.upload(new Float32Array(c.spans));\n kit.attrib(p, 'a_x', 2, SPAN_STRIDE, 0);\n kit.attrib(p, 'a_ab', 4, SPAN_STRIDE, 8);\n kit.attrib(p, 'a_ends', 2, SPAN_STRIDE, 24);\n this.paint(p, c.paint);\n kit.gl.drawArraysInstanced(kit.gl.TRIANGLES, 0, 6, c.spans.length / SPAN_FLOATS);\n }\n\n private paint(p: Program, paint: GpuPaint): void {\n const kit = this.kit;\n if (paint.kind === 'solid') {\n kit.int(p, 'u_kind', 0);\n kit.vec4(p, 'u_color', paint.color);\n return;\n }\n kit.int(p, 'u_kind', 1);\n kit.vec4(p, 'u_line', [paint.x0, paint.y0, paint.x1, paint.y1]);\n const offsets = [0, 0, 0, 0];\n paint.stops.forEach((s, i) => { offsets[i] = s.offset; });\n kit.vec4(p, 'u_offsets', offsets);\n kit.int(p, 'u_stops', paint.stops.length);\n for (let i = 0; i < 4; i++) kit.vec4(p, `u_stop${i}`, (paint.stops[i] ?? paint.stops[paint.stops.length - 1]).color);\n }\n\n private drawDiscs(values: readonly number[], clip: Box, width: number, height: number): void {\n const p = this.disc;\n if (!this.common(p, clip, width, height)) return;\n this.upload(new Float32Array(values));\n this.kit.attrib(p, 'a_disc', 3, DISC_STRIDE, 0);\n this.kit.attrib(p, 'a_color', 4, DISC_STRIDE, 12);\n this.kit.gl.drawArraysInstanced(this.kit.gl.TRIANGLES, 0, 6, values.length / DISC_FLOATS);\n }\n}\n","import type { RGBA } from './glColor.js';\n\n/** A clip or bounds in device pixels. */\nexport interface Box {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\nexport type GpuPaint =\n /** Premultiplied, global alpha applied. */\n | { kind: 'solid'; color: RGBA }\n /**\n * Along (x0, y0) → (x1, y1) in device pixels. Stop colours are kept\n * unpremultiplied (global alpha applied to their alpha): Canvas 2D blends\n * between them so, and premultiplies after.\n */\n | { kind: 'linear'; x0: number; y0: number; x1: number; y1: number; stops: { offset: number; color: RGBA }[] };\n\nexport type GpuCommand =\n /** Axis-aligned rectangles, already clipped: left, top, right, bottom, then a premultiplied colour (8 numbers each). */\n | { type: 'rects'; values: number[] }\n /**\n * Polylines: x, y, w, cum per point (w 1 drawn, 0 a neighbour only, -1 a\n * break; cum the length along the line so far, for dashes), with two\n * points before the first segment and two after the last.\n */\n | { type: 'stroke'; points: number[]; color: RGBA; width: number; cap: 0 | 1 | 2; dash: number[] | null; clip: Box }\n /** Polygons as spans (see polygonSpans.ts), each pixel inside in one of them. */\n | { type: 'fill'; spans: number[]; bounds: Box; paint: GpuPaint; clip: Box }\n /** Discs: x, y, radius, then a premultiplied colour (7 numbers each). */\n | { type: 'circles'; values: number[]; clip: Box };\n\nexport const intersect = (a: Box, b: Box): Box => ({ x0: Math.max(a.x0, b.x0), y0: Math.max(a.y0, b.y0), x1: Math.min(a.x1, b.x1), y1: Math.min(a.y1, b.y1) });\n\nexport const isEmpty = (b: Box): boolean => !(b.x1 > b.x0 && b.y1 > b.y0);\n\n/** The box around x, y pairs, grown by `pad` each side. */\nexport function boundsOf(points: readonly number[], pad = 0): Box {\n let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;\n for (let i = 0; i < points.length; i += 2) {\n const x = points[i];\n const y = points[i + 1];\n if (x < x0) x0 = x;\n if (x > x1) x1 = x;\n if (y < y0) y0 = y;\n if (y > y1) y1 = y;\n }\n return { x0: x0 - pad, y0: y0 - pad, x1: x1 + pad, y1: y1 + pad };\n}\n\n/**\n * Whether any two boxes overlap over some area (touching doesn't count).\n * Canvas 2D paints the union of a path's pieces once; drawn one by one,\n * see-through or antialiased pieces that overlap would paint some pixels twice.\n */\nexport function anyOverlap(boxes: readonly Box[]): boolean {\n const sorted = [...boxes].sort((a, b) => a.x0 - b.x0);\n const open: Box[] = [];\n for (const b of sorted) {\n for (let i = open.length - 1; i >= 0; i--) if (open[i].x1 <= b.x0) open.splice(i, 1);\n for (const a of open) if (a.y0 < b.y1 && b.y0 < a.y1) return true;\n open.push(b);\n }\n return false;\n}\n","/** A gradient made on the recording context. */\nexport class RecordedGradient {\n readonly stops: { offset: number; color: string }[] = [];\n constructor(readonly x0: number, readonly y0: number, readonly x1: number, readonly y1: number) {}\n addColorStop(offset: number, color: string): void {\n if (!(offset >= 0 && offset <= 1)) throw new RangeError('offset out of range');\n this.stops.push({ offset, color });\n }\n}\n\n/** The browser's Path2D (a stand-in where there is none, as in tests). */\nconst NativePath2D: { new (path?: Path2D | string): Path2D } =\n typeof Path2D === 'function' ? Path2D : (class {} as unknown as { new (path?: Path2D | string): Path2D });\n\n/**\n * A Path2D made while a step records. It is a real Path2D too (a chart that\n * keeps one and draws it on a real context later still can), and remembers\n * its calls to play them back on the recording context when it's filled,\n * stroked or clipped (at the transform of that moment, as Canvas 2D does).\n * Calls the GPU can't follow (ellipses, SVG path data…) mark it, and the\n * step goes to Canvas 2D.\n */\nexport class RecordedPath extends NativePath2D {\n readonly calls: [string, number[]][] = [];\n unsupported = false;\n\n constructor(from?: Path2D | string) {\n super(from);\n if (from instanceof RecordedPath) {\n this.calls.push(...from.calls);\n this.unsupported = from.unsupported;\n } else if (from !== undefined) {\n this.unsupported = true;\n }\n }\n\n private note(name: string, args: number[], native: readonly unknown[] = args): void {\n this.calls.push([name, args]);\n const own = (NativePath2D.prototype as unknown as Record<string, ((...a: unknown[]) => void) | undefined>)[name];\n own?.apply(this, native as unknown[]);\n }\n\n /** A call the GPU can't follow: still made on the real path, and the step goes to Canvas 2D. */\n private unfollowed(name: string, args: readonly unknown[]): void {\n this.unsupported = true;\n this.note(name, [], args);\n }\n\n moveTo(x: number, y: number): void { this.note('moveTo', [x, y]); }\n lineTo(x: number, y: number): void { this.note('lineTo', [x, y]); }\n closePath(): void { this.note('closePath', []); }\n rect(x: number, y: number, w: number, h: number): void { this.note('rect', [x, y, w, h]); }\n arc(x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean): void { this.note('arc', [x, y, r, a0, a1, ccw ? 1 : 0]); }\n quadraticCurveTo(cx: number, cy: number, x: number, y: number): void { this.note('quadraticCurveTo', [cx, cy, x, y]); }\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void { this.note('bezierCurveTo', [c1x, c1y, c2x, c2y, x, y]); }\n\n arcTo(...a: Parameters<Path2D['arcTo']>): void { this.unfollowed('arcTo', a); }\n ellipse(...a: Parameters<Path2D['ellipse']>): void { this.unfollowed('ellipse', a); }\n roundRect(...a: Parameters<Path2D['roundRect']>): void { this.unfollowed('roundRect', a); }\n\n addPath(path: Path2D, transform?: DOMMatrix2DInit): void {\n if (!(path instanceof RecordedPath) || transform !== undefined) this.unsupported = true;\n else {\n this.calls.push(...path.calls);\n this.unsupported ||= path.unsupported;\n }\n (NativePath2D.prototype as unknown as { addPath?: (p: Path2D, t?: DOMMatrix2DInit) => void }).addPath?.call(this, path, transform);\n }\n}\n\n/**\n * Run `draw` with the global Path2D swapped for RecordedPath, so the paths\n * it makes record too; put back after, as it was (own property or none).\n */\nexport function withRecordedPaths(draw: () => void): void {\n const scope = globalThis as { Path2D?: unknown };\n const owned = Object.prototype.hasOwnProperty.call(scope, 'Path2D');\n const real = scope.Path2D;\n scope.Path2D = RecordedPath;\n try {\n draw();\n } finally {\n if (owned) scope.Path2D = real;\n else delete scope.Path2D;\n }\n}\n","/**\n * Strokes as the GPU draws them: round where segments join. Canvas 2D joins\n * by `lineJoin` (miter by default); the two differ only at the outside of a\n * turn, and only by a sliver until the turn gets sharp.\n */\n\n/** A line to stroke: x, y pairs in device pixels. */\nexport interface Polyline {\n points: number[];\n closed: boolean;\n}\n\n/** How far a join may differ from a round one and still pass for it, in device pixels. */\nconst JOIN_TOLERANCE = 0.25;\n\n/**\n * Whether a join of `line` turns sharply enough that a `join` join of half\n * width `hw` would visibly differ from a round one. A miter reaches\n * hw / cos(θ/2) out at a turn of θ (bevelled past `miterLimit`), a bevel\n * stops at hw·cos(θ/2); a round join reaches hw.\n */\nexport function hasSharpJoin(line: Polyline, hw: number, join: CanvasLineJoin, miterLimit: number): boolean {\n if (join === 'round') return false;\n const p = line.points;\n const n = p.length / 2;\n const first = line.closed ? 0 : 1;\n const last = line.closed ? n : n - 1;\n for (let i = first; i < last; i++) {\n const prev = (i - 1 + n) % n;\n const next = (i + 1) % n;\n const ax = p[2 * i] - p[2 * prev], ay = p[2 * i + 1] - p[2 * prev + 1];\n const bx = p[2 * next] - p[2 * i], by = p[2 * next + 1] - p[2 * i + 1];\n const la = Math.hypot(ax, ay);\n const lb = Math.hypot(bx, by);\n if (la === 0 || lb === 0) continue;\n // cos θ of the turn, then cos θ/2.\n const cos = Math.max(-1, Math.min(1, (ax * bx + ay * by) / (la * lb)));\n const half = Math.sqrt((1 + cos) / 2);\n const mitered = join === 'miter' && half > 0 && 1 / half <= miterLimit;\n const off = mitered ? hw * (1 / half - 1) : hw * (1 - half);\n if (off > JOIN_TOLERANCE) return true;\n }\n return false;\n}\n\n/** Whether some segment of `line` is shorter than `length`. */\nexport function hasShortSegment(line: Polyline, length: number): boolean {\n const p = line.points;\n for (let i = 2; i < p.length; i += 2) {\n if (Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]) < length) return true;\n }\n return false;\n}\n\n/**\n * The lines packed for the stroke shader: x, y, w, cum per point, where w is\n * 1 for a point of the line, 0 for a neighbour only (a closed line's corners\n * repeated around its seam), -1 for a break; cum is the length along the\n * line so far. Two points come before the first segment and two after the\n * last, so each segment sees two neighbours either side.\n */\nexport function packStroke(lines: readonly Polyline[]): number[] {\n const out: number[] = [];\n const sep = () => out.push(0, 0, -1, 0);\n sep();\n sep();\n for (const { points: p, closed: shut } of lines) {\n const n = p.length / 2;\n const closed = shut && n >= 3;\n if (closed) {\n // Neighbours of the first segment: the last two corners.\n out.push(p[2 * (n - 2)], p[2 * (n - 2) + 1], 0, 0, p[2 * (n - 1)], p[2 * (n - 1) + 1], 0, 0);\n }\n let cum = 0;\n for (let i = 0; i < n; i++) {\n if (i > 0) cum += Math.hypot(p[2 * i] - p[2 * i - 2], p[2 * i + 1] - p[2 * i - 1]);\n out.push(p[2 * i], p[2 * i + 1], 1, cum);\n }\n if (closed) {\n cum += Math.hypot(p[0] - p[2 * (n - 1)], p[1] - p[2 * (n - 1) + 1]);\n out.push(p[0], p[1], 1, cum);\n // Neighbours of the closing segment: the first two after the start.\n out.push(p[2], p[3], 0, 0, p[4], p[5], 0, 0);\n }\n sep();\n }\n sep();\n return out;\n}\n","import type { Rect } from '@tradecanvas/commons';\nimport type { GpuRecorder, GpuRegion } from '../engine/gpu.js';\nimport { parseColor, premultiplied, readColor, type RGBA } from './glColor.js';\nimport { polygonSpans, signedArea } from './polygonSpans.js';\nimport { anyOverlap, boundsOf, intersect, isEmpty, type Box, type GpuCommand, type GpuPaint } from './recordedCommands.js';\nimport { RecordedGradient, RecordedPath, withRecordedPaths } from './recordedPath.js';\nimport { hasSharpJoin, hasShortSegment, packStroke, type Polyline } from './strokeGeometry.js';\n\nexport type { Box, GpuCommand, GpuPaint } from './recordedCommands.js';\nexport { anyOverlap } from './recordedCommands.js';\n\n/**\n * Canvas 2D drawing recorded for the GPU. Chart code draws on `ctx` as on a\n * real 2D context; paths, fills and strokes become GPU commands in device\n * pixels (the context starts at the device-pixel-ratio transform, as a chart\n * canvas does). Text is kept to be drawn on the 2D canvas over it. A step\n * that uses anything the GPU can't draw the same (an image, a pattern, a\n * rotated or non-rectangular clip, a sharp mitered corner, shapes of one fill\n * that overlap…) is dropped whole, and the chart draws it with Canvas 2D.\n */\n\ntype Style = string | RecordedGradient;\ntype Matrix = [number, number, number, number, number, number];\n\ninterface State {\n fillStyle: Style;\n strokeStyle: Style;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n globalAlpha: number;\n globalCompositeOperation: string;\n lineDash: number[];\n lineDashOffset: number;\n font: string;\n textAlign: CanvasTextAlign;\n textBaseline: CanvasTextBaseline;\n direction: CanvasDirection;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n filter: string;\n /** Text settings beyond the font, replayed with the text. */\n textExtras: Record<string, unknown>;\n transform: Matrix;\n clip: Box;\n}\n\n/** A subpath: points in device pixels; a rectangle or full circle kept as one, for the fast paths. */\ninterface Subpath extends Polyline {\n rect?: Box;\n circle?: { x: number; y: number; r: number };\n}\n\ninterface TextOp {\n stroke: boolean;\n text: string;\n x: number;\n y: number;\n maxWidth: number | undefined;\n state: State;\n}\n\nconst TAU = Math.PI * 2;\n\n/** Points per arc flattened: fine enough to stay within a tenth of a pixel. */\nfunction arcSteps(radius: number, sweep: number): number {\n const step = 2 * Math.sqrt(Math.max(0.2 / Math.max(radius, 0.1), 1e-6));\n return Math.min(512, Math.max(4, Math.ceil(Math.abs(sweep) / Math.min(step, Math.PI / 4))));\n}\n\n/** State properties a step may read and set. */\nconst PROPS = new Set(['fillStyle', 'strokeStyle', 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', 'globalAlpha', 'globalCompositeOperation', 'lineDashOffset', 'font', 'textAlign', 'textBaseline', 'direction', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'filter']);\n/** Text settings kept with the text. */\nconst TEXT_EXTRAS = new Set(['fontKerning', 'fontStretch', 'fontVariantCaps', 'letterSpacing', 'wordSpacing', 'textRendering']);\n/** Settings that change nothing drawn here (no images). */\nconst IGNORED = new Set(['imageSmoothingEnabled', 'imageSmoothingQuality']);\n\nconst fillable = (s: Subpath) => !!(s.rect || s.circle) || s.points.length >= 6;\n\nclass Recorder implements GpuRecorder {\n readonly commands: GpuCommand[] = [];\n readonly ctx: CanvasRenderingContext2D;\n /** Where text goes: the region being recorded. */\n private texts: TextOp[] = [];\n private state!: State;\n private stack: State[] = [];\n private path: Subpath[] = [];\n private ok = true;\n\n constructor(private readonly dpr: number, private readonly measure: CanvasRenderingContext2D | null) {\n this.reset({ x0: 0, y0: 0, x1: Infinity, y1: Infinity });\n this.ctx = this.proxy();\n }\n\n region(clip: Rect): GpuRegion {\n const d = this.dpr;\n const box = { x0: clip.x * d, y0: clip.y * d, x1: (clip.x + clip.width) * d, y1: (clip.y + clip.height) * d };\n const texts: TextOp[] = [];\n return {\n step: (draw) => {\n this.reset(box);\n this.texts = texts;\n const marks = { commands: this.commands.length, texts: texts.length };\n this.ok = true;\n try {\n withRecordedPaths(() => draw(this.ctx));\n } catch {\n this.ok = false;\n }\n if (this.ok) return true;\n this.commands.length = marks.commands;\n texts.length = marks.texts;\n return false;\n },\n drawText: (c) => replayText(c, texts),\n };\n }\n\n private reset(clip: Box): void {\n this.state = {\n fillStyle: '#000000',\n strokeStyle: '#000000',\n lineWidth: 1,\n lineCap: 'butt',\n lineJoin: 'miter',\n miterLimit: 10,\n globalAlpha: 1,\n globalCompositeOperation: 'source-over',\n lineDash: [],\n lineDashOffset: 0,\n font: '10px sans-serif',\n textAlign: 'start',\n textBaseline: 'alphabetic',\n direction: 'inherit',\n shadowBlur: 0,\n shadowColor: 'rgba(0, 0, 0, 0)',\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n filter: 'none',\n textExtras: {},\n transform: [this.dpr, 0, 0, this.dpr, 0, 0],\n clip,\n };\n this.stack = [];\n this.path = [];\n }\n\n private unsupported(): void {\n this.ok = false;\n }\n\n private copyState(): State {\n const s = this.state;\n return { ...s, lineDash: [...s.lineDash], textExtras: { ...s.textExtras } };\n }\n\n // --- Transform -----------------------------------------------------------\n\n /** Whether the transform keeps axes axis-aligned (no rotation or skew). */\n private axisAligned(): boolean {\n const t = this.state.transform;\n return t[1] === 0 && t[2] === 0;\n }\n\n /** Axis-aligned and the same scale both ways: lines keep their width, circles stay round. */\n private uniform(): boolean {\n const t = this.state.transform;\n return this.axisAligned() && Math.abs(t[0]) === Math.abs(t[3]);\n }\n\n private setMatrix(m: Matrix): void {\n if (m.every(Number.isFinite)) this.state.transform = m;\n }\n\n private multiply(a: number, b: number, c: number, d: number, e: number, f: number): void {\n const [a0, b0, c0, d0, e0, f0] = this.state.transform;\n this.setMatrix([a0 * a + c0 * b, b0 * a + d0 * b, a0 * c + c0 * d, b0 * c + d0 * d, a0 * e + c0 * f + e0, b0 * e + d0 * f + f0]);\n }\n\n // --- Path ----------------------------------------------------------------\n\n private current(): Subpath | undefined {\n return this.path[this.path.length - 1];\n }\n\n private moveTo(x: number, y: number): void {\n if (!Number.isFinite(x) || !Number.isFinite(y)) return;\n const t = this.state.transform;\n this.path.push({ points: [t[0] * x + t[2] * y + t[4], t[1] * x + t[3] * y + t[5]], closed: false });\n }\n\n private lineTo(x: number, y: number): void {\n if (!Number.isFinite(x) || !Number.isFinite(y)) return;\n const sub = this.current();\n if (!sub || sub.closed) return this.moveTo(x, y);\n const t = this.state.transform;\n sub.points.push(t[0] * x + t[2] * y + t[4], t[1] * x + t[3] * y + t[5]);\n sub.rect = undefined;\n sub.circle = undefined;\n }\n\n private closePath(): void {\n const sub = this.current();\n if (!sub || sub.closed) return;\n sub.closed = true;\n // A new subpath starts where this one did.\n this.path.push({ points: [sub.points[0], sub.points[1]], closed: false });\n }\n\n private rect(x: number, y: number, w: number, h: number): void {\n if (![x, y, w, h].every(Number.isFinite)) return;\n const t = this.state.transform;\n const x0 = t[0] * x + t[2] * y + t[4], y0 = t[1] * x + t[3] * y + t[5];\n const x1 = t[0] * (x + w) + t[2] * y + t[4], y1 = t[1] * (x + w) + t[3] * y + t[5];\n const x2 = t[0] * (x + w) + t[2] * (y + h) + t[4], y2 = t[1] * (x + w) + t[3] * (y + h) + t[5];\n const x3 = t[0] * x + t[2] * (y + h) + t[4], y3 = t[1] * x + t[3] * (y + h) + t[5];\n const sub: Subpath = { points: [x0, y0, x1, y1, x2, y2, x3, y3], closed: true };\n if (this.axisAligned()) sub.rect = { x0: Math.min(x0, x2), y0: Math.min(y0, y2), x1: Math.max(x0, x2), y1: Math.max(y0, y2) };\n this.path.push(sub);\n // As in Canvas 2D: the next subpath starts at the rectangle's corner.\n this.path.push({ points: [x0, y0], closed: false });\n }\n\n private arc(x: number, y: number, r: number, start: number, end: number, ccw = false): void {\n if (![x, y, r, start, end].every(Number.isFinite)) return;\n if (r < 0) throw new DOMException('negative radius', 'IndexSizeError');\n let sweep = end - start;\n if (!ccw && sweep >= TAU) sweep = TAU;\n else if (ccw && -sweep >= TAU) sweep = -TAU;\n else if (!ccw) sweep = ((sweep % TAU) + TAU) % TAU;\n else sweep = -((((start - end) % TAU) + TAU) % TAU);\n const sub = this.current();\n const t = this.state.transform;\n const sx = x + r * Math.cos(start), sy = y + r * Math.sin(start);\n // Alone in its subpath (or just after a moveTo to where it starts): a circle the fast path can draw.\n const lonely = !sub || sub.closed\n || (sub.points.length === 2 && Math.abs(sub.points[0] - (t[0] * sx + t[2] * sy + t[4])) < 1e-6 && Math.abs(sub.points[1] - (t[1] * sx + t[3] * sy + t[5])) < 1e-6);\n const steps = arcSteps(r * Math.abs(t[0]), sweep);\n for (let k = 0; k <= steps; k++) {\n const angle = start + (sweep * k) / steps;\n this.lineTo(x + r * Math.cos(angle), y + r * Math.sin(angle));\n }\n const made = this.current();\n if (Math.abs(sweep) >= TAU - 1e-9 && lonely && this.uniform() && made) {\n made.circle = { x: t[0] * x + t[4], y: t[3] * y + t[5], r: r * Math.abs(t[0]) };\n }\n }\n\n /** A curve flattened into lines (the GPU draws only lines), finer as it is longer. */\n private curve(controls: number[], end: [number, number]): void {\n if (!this.current() || this.current()!.closed) this.moveTo(controls[0], controls[1]);\n const start = this.current();\n const t = this.state.transform;\n if (!start || !this.axisAligned() || t[0] === 0 || t[3] === 0) return this.unsupported();\n // Back to user space for the start point: inverse of an axis-aligned transform.\n const pts = [(start.points[start.points.length - 2] - t[4]) / t[0], (start.points[start.points.length - 1] - t[5]) / t[3], ...controls, ...end];\n let length = 0;\n for (let i = 2; i < pts.length; i += 2) length += Math.hypot((pts[i] - pts[i - 2]) * t[0], (pts[i + 1] - pts[i - 1]) * t[3]);\n const steps = Math.max(4, Math.min(64, Math.ceil(length / 3)));\n for (let k = 1; k <= steps; k++) {\n const u = k / steps;\n const w = pts.length === 6\n ? [(1 - u) ** 2, 2 * u * (1 - u), u * u]\n : [(1 - u) ** 3, 3 * u * (1 - u) ** 2, 3 * u * u * (1 - u), u ** 3];\n let x = 0, y = 0;\n w.forEach((wk, i) => { x += wk * pts[2 * i]; y += wk * pts[2 * i + 1]; });\n this.lineTo(x, y);\n }\n }\n\n private withPath(build: () => void, draw: () => void): void {\n const saved = this.path;\n this.path = [];\n build();\n draw();\n this.path = saved;\n }\n\n /** Run `use` on `path`'s shape instead of the current path. */\n private onPath(path: unknown, use: () => void): void {\n if (!(path instanceof RecordedPath) || path.unsupported) return this.unsupported();\n this.withPath(() => {\n for (const [name, a] of path.calls) {\n if (name === 'moveTo') this.moveTo(a[0], a[1]);\n else if (name === 'lineTo') this.lineTo(a[0], a[1]);\n else if (name === 'closePath') this.closePath();\n else if (name === 'rect') this.rect(a[0], a[1], a[2], a[3]);\n else if (name === 'arc') this.arc(a[0], a[1], a[2], a[3], a[4], !!a[5]);\n else if (name === 'quadraticCurveTo') this.curve([a[0], a[1]], [a[2], a[3]]);\n else if (name === 'bezierCurveTo') this.curve([a[0], a[1], a[2], a[3]], [a[4], a[5]]);\n }\n }, use);\n }\n\n // --- Paint ---------------------------------------------------------------\n\n /** The style as the GPU paints it, or null when it can't. */\n private paint(style: Style): GpuPaint | null {\n const alpha = Math.max(0, Math.min(1, this.state.globalAlpha));\n if (typeof style === 'string') {\n const c = premultiplied(parseColor(style));\n return { kind: 'solid', color: [c[0] * alpha, c[1] * alpha, c[2] * alpha, c[3] * alpha] };\n }\n if (!(style instanceof RecordedGradient)) return null;\n if (style.stops.length === 0) return { kind: 'solid', color: [0, 0, 0, 0] };\n if (style.stops.length > 4) return null;\n // Transformed end points carry the gradient over only while its lines\n // stay square to its axis: no rotation, and a uniform scale or an\n // axis-parallel gradient.\n const t = this.state.transform;\n const parallel = style.x0 === style.x1 || style.y0 === style.y1;\n if (!this.axisAligned() || (!this.uniform() && !parallel)) return null;\n const stops = [...style.stops].sort((a, b) => a.offset - b.offset).map((s) => {\n const c = parseColor(s.color);\n return { offset: s.offset, color: [c[0], c[1], c[2], c[3] * alpha] as RGBA };\n });\n return { kind: 'linear', x0: t[0] * style.x0 + t[4], y0: t[3] * style.y0 + t[5], x1: t[0] * style.x1 + t[4], y1: t[3] * style.y1 + t[5], stops };\n }\n\n /** Whether the state draws as plain source-over paint (no shadow, filter or other blending). */\n private plain(): boolean {\n const s = this.state;\n if (s.globalCompositeOperation !== 'source-over' || s.filter !== 'none') return false;\n return !(parseColor(s.shadowColor)[3] > 0 && (s.shadowBlur > 0 || s.shadowOffsetX !== 0 || s.shadowOffsetY !== 0));\n }\n\n // --- Fill ----------------------------------------------------------------\n\n private fill(rule: CanvasFillRule = 'nonzero'): void {\n if (!this.plain()) return this.unsupported();\n const paint = this.paint(this.state.fillStyle);\n if (!paint) return this.unsupported();\n const subs = this.path.filter(fillable);\n if (subs.length === 0 || (paint.kind === 'solid' && paint.color[3] === 0)) return;\n // Shapes of one fill that overlap: Canvas 2D paints where the winding\n // says, once. Drawn one by one, only opaque paint matches it, and only\n // where every shape winds the same way under the nonzero rule.\n if (subs.length > 1 && anyOverlap(subs.map((s) => boundsOf(s.points)))) {\n const opaque = paint.kind === 'solid' && paint.color[3] >= 1;\n const way = Math.sign(signedArea(subs[0].points));\n if (!opaque || rule !== 'nonzero' || subs.some((s) => Math.sign(signedArea(s.points)) !== way)) return this.unsupported();\n }\n if (paint.kind === 'solid' && subs.every((s) => s.rect)) return this.fillRects(subs, paint.color);\n if (paint.kind === 'solid' && subs.every((s) => s.circle)) {\n const values: number[] = [];\n for (const s of subs) values.push(s.circle!.x, s.circle!.y, s.circle!.r, ...paint.color);\n this.commands.push({ type: 'circles', values, clip: this.state.clip });\n return;\n }\n const spans: number[] = [];\n for (const s of subs) {\n // A shape other than bands, areas and the like: Canvas 2D fills it.\n const these = polygonSpans(s.points);\n if (!these) return this.unsupported();\n for (const v of these) spans.push(v);\n }\n const all = boundsOf(subs.flatMap((s) => s.points));\n const bounds = intersect({ x0: Math.floor(all.x0), y0: Math.floor(all.y0), x1: Math.ceil(all.x1), y1: Math.ceil(all.y1) }, this.state.clip);\n if (spans.length > 0 && !isEmpty(bounds)) this.commands.push({ type: 'fill', spans, bounds, paint, clip: this.state.clip });\n }\n\n private fillRects(subs: readonly Subpath[], color: RGBA): void {\n const values: number[] = [];\n for (const s of subs) {\n const r = intersect(s.rect!, this.state.clip);\n if (!isEmpty(r)) values.push(r.x0, r.y0, r.x1, r.y1, color[0], color[1], color[2], color[3]);\n }\n if (values.length) this.commands.push({ type: 'rects', values });\n }\n\n // --- Stroke --------------------------------------------------------------\n\n private stroke(): void {\n if (!this.plain()) return this.unsupported();\n const paint = this.paint(this.state.strokeStyle);\n // Line widths scale with the transform: only a uniform one keeps them round.\n if (!paint || paint.kind !== 'solid' || !this.uniform()) return this.unsupported();\n if (paint.color[3] === 0) return;\n const s = this.state;\n const scale = Math.abs(s.transform[0]);\n const width = s.lineWidth * scale;\n // A zero-length piece draws a dot with round or square caps, nothing with butt ones.\n const lines = this.path.filter((l) => l.points.length >= 4 && (s.lineCap !== 'butt' || l.points.some((v, i) => v !== l.points[i % 2])));\n if (lines.length === 0) return;\n const dash = this.dash(lines, scale);\n if (dash === undefined || !this.drawsAlike(lines, width, paint.color[3])) return this.unsupported();\n const cap = s.lineCap === 'round' ? 1 : s.lineCap === 'square' ? 2 : 0;\n this.commands.push({ type: 'stroke', points: packStroke(lines), color: paint.color, width, cap, dash, clip: s.clip });\n }\n\n /** The dash pattern in device pixels as two on-off pairs, null for solid; undefined when the GPU can't dash these lines (it dashes single segments, butt-capped). */\n private dash(lines: readonly Subpath[], scale: number): number[] | null | undefined {\n const s = this.state;\n if (s.lineDash.length === 0) return null;\n if (s.lineDash.length > 4 || s.lineDashOffset !== 0 || s.lineCap !== 'butt') return undefined;\n if (lines.some((l) => l.closed || l.points.length !== 4)) return undefined;\n const dash = s.lineDash.map((v) => v * scale);\n while (dash.length < 4) dash.push(...dash.slice(0, 4 - dash.length));\n return dash;\n }\n\n /**\n * Whether the GPU's stroke looks as Canvas 2D's would: joins round enough\n * to pass for the `lineJoin` asked for, pieces that don't overlap (Canvas\n * 2D paints their union once), and, see-through, no segment so short that\n * a pixel might be painted by more than the nearest few.\n */\n private drawsAlike(lines: readonly Subpath[], width: number, alpha: number): boolean {\n const s = this.state;\n const hw = width / 2;\n if (width > 1 && lines.some((l) => hasSharpJoin(l, hw, s.lineJoin, s.miterLimit))) return false;\n const reach = hw + (s.lineCap === 'butt' ? 0 : hw);\n if (lines.length > 1 && anyOverlap(lines.map((l) => boundsOf(l.points, reach)))) return false;\n if (alpha < 1 && lines.some((l) => hasShortSegment(l, width))) return false;\n return true;\n }\n\n // --- Clip and text -------------------------------------------------------\n\n /** Clip to the path: one axis-aligned rectangle (the winding rule makes no difference to it). */\n private clip(): void {\n const subs = this.path.filter(fillable);\n if (subs.length !== 1 || !subs[0].rect) return this.unsupported();\n this.state.clip = intersect(this.state.clip, subs[0].rect);\n }\n\n private text(stroke: boolean, text: string, x: number, y: number, maxWidth?: number): void {\n const style = stroke ? this.state.strokeStyle : this.state.fillStyle;\n if (typeof style !== 'string' || !this.plain()) return this.unsupported();\n this.texts.push({ stroke, text: String(text), x, y, maxWidth, state: this.copyState() });\n }\n\n private measureText(text: string): TextMetrics {\n const m = this.measure;\n if (!m) return { width: String(text).length * 6 } as TextMetrics;\n const font = m.font;\n m.font = this.state.font;\n const metrics = m.measureText(text);\n m.font = font;\n return metrics;\n }\n\n // --- The context ---------------------------------------------------------\n\n private methods(): Record<string, (...args: never[]) => unknown> {\n const st = () => this.state;\n const table: Record<string, (...args: never[]) => unknown> = Object.create(null);\n Object.assign(table, {\n save: () => { this.stack.push(this.copyState()); },\n restore: () => { const s = this.stack.pop(); if (s) this.state = s; },\n beginPath: () => { this.path = []; },\n moveTo: (x: number, y: number) => this.moveTo(x, y),\n lineTo: (x: number, y: number) => this.lineTo(x, y),\n closePath: () => this.closePath(),\n rect: (x: number, y: number, w: number, h: number) => this.rect(x, y, w, h),\n arc: (x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean) => this.arc(x, y, r, a0, a1, ccw),\n quadraticCurveTo: (cx: number, cy: number, x: number, y: number) => this.curve([cx, cy], [x, y]),\n bezierCurveTo: (c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number) => this.curve([c1x, c1y, c2x, c2y], [x, y]),\n fill: (a?: CanvasFillRule | Path2D, b?: CanvasFillRule) => (typeof a === 'object' ? this.onPath(a, () => this.fill(b)) : this.fill(a)),\n stroke: (path?: Path2D) => (path ? this.onPath(path, () => this.stroke()) : this.stroke()),\n clip: (a?: CanvasFillRule | Path2D) => (typeof a === 'object' ? this.onPath(a, () => this.clip()) : this.clip()),\n fillRect: (x: number, y: number, w: number, h: number) => this.withPath(() => this.rect(x, y, w, h), () => this.fill()),\n strokeRect: (x: number, y: number, w: number, h: number) => this.withPath(() => this.rect(x, y, w, h), () => this.stroke()),\n fillText: (text: string, x: number, y: number, maxWidth?: number) => this.text(false, text, x, y, maxWidth),\n strokeText: (text: string, x: number, y: number, maxWidth?: number) => this.text(true, text, x, y, maxWidth),\n measureText: (text: string) => this.measureText(text),\n setLineDash: (segments: number[]) => {\n if (segments.every((v) => Number.isFinite(v) && v >= 0)) st().lineDash = segments.length % 2 ? [...segments, ...segments] : [...segments];\n },\n getLineDash: () => [...st().lineDash],\n translate: (x: number, y: number) => this.multiply(1, 0, 0, 1, x, y),\n scale: (x: number, y: number) => this.multiply(x, 0, 0, y, 0, 0),\n rotate: (angle: number) => this.multiply(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0),\n transform: (a: number, b: number, c: number, d: number, e: number, f: number) => this.multiply(a, b, c, d, e, f),\n setTransform: (a?: number | DOMMatrix2DInit, b?: number, c?: number, d?: number, e?: number, f?: number) =>\n typeof a === 'number' ? this.setMatrix([a, b ?? 0, c ?? 0, d ?? 1, e ?? 0, f ?? 0]) : this.unsupported(),\n resetTransform: () => this.setMatrix([1, 0, 0, 1, 0, 0]),\n getTransform: () => {\n const [a, b, c, d, e, f] = st().transform;\n return { a, b, c, d, e, f, m11: a, m12: b, m21: c, m22: d, m41: e, m42: f, is2D: true, isIdentity: a === 1 && b === 0 && c === 0 && d === 1 && e === 0 && f === 0 };\n },\n createLinearGradient: (x0: number, y0: number, x1: number, y1: number) => new RecordedGradient(x0, y0, x1, y1),\n });\n return table;\n }\n\n private proxy(): CanvasRenderingContext2D {\n const methods = this.methods();\n return new Proxy({} as CanvasRenderingContext2D, {\n get: (_target, prop) => {\n if (typeof prop !== 'string') return undefined;\n if (prop in methods) return methods[prop];\n if (PROPS.has(prop)) return (this.state as unknown as Record<string, unknown>)[prop];\n if (TEXT_EXTRAS.has(prop)) return this.state.textExtras[prop];\n if (prop === 'canvas') return this.measure?.canvas;\n if (IGNORED.has(prop)) return undefined;\n // Anything else (images, patterns, pixels…): Canvas 2D draws this step.\n this.unsupported();\n return () => undefined;\n },\n set: (_target, prop, value) => {\n if (typeof prop === 'string') this.setProp(prop, value);\n return true;\n },\n });\n }\n\n /** A state property set as Canvas 2D sets it: invalid values are ignored. */\n private setProp(prop: string, value: unknown): void {\n const s = this.state as unknown as Record<string, unknown>;\n if (prop === 'lineWidth' || prop === 'miterLimit') {\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) s[prop] = value;\n } else if (prop === 'globalAlpha') {\n if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1) s.globalAlpha = value;\n } else if (prop === 'fillStyle' || prop === 'strokeStyle') {\n if (value instanceof RecordedGradient) s[prop] = value;\n else if (typeof value === 'string') {\n if (readColor(value)) s[prop] = value;\n } else this.unsupported();\n } else if (PROPS.has(prop)) {\n s[prop] = value;\n } else if (TEXT_EXTRAS.has(prop)) {\n this.state.textExtras[prop] = value;\n } else if (!IGNORED.has(prop)) {\n this.unsupported();\n }\n }\n}\n\n/** Draw recorded text on a real 2D context (at its device-pixel-ratio transform), each as it was set. */\nfunction replayText(c: CanvasRenderingContext2D, texts: readonly TextOp[]): void {\n for (const op of texts) {\n const s = op.state;\n // Clipped away entirely: nothing to draw.\n if (isEmpty(s.clip)) continue;\n c.save();\n // Device pixels: the recorded clip and transform are in them.\n c.setTransform(1, 0, 0, 1, 0, 0);\n if (Number.isFinite(s.clip.x1) && Number.isFinite(s.clip.y1)) {\n c.beginPath();\n c.rect(s.clip.x0, s.clip.y0, s.clip.x1 - s.clip.x0, s.clip.y1 - s.clip.y0);\n c.clip();\n }\n const [a, b, cc, d, e, f] = s.transform;\n c.setTransform(a, b, cc, d, e, f);\n c.font = s.font;\n c.textAlign = s.textAlign;\n c.textBaseline = s.textBaseline;\n c.direction = s.direction;\n c.globalAlpha = s.globalAlpha;\n Object.assign(c, s.textExtras);\n if (op.stroke) {\n c.strokeStyle = s.strokeStyle as string;\n c.lineWidth = s.lineWidth;\n c.strokeText(op.text, op.x, op.y, op.maxWidth);\n } else {\n c.fillStyle = s.fillStyle as string;\n c.fillText(op.text, op.x, op.y, op.maxWidth);\n }\n c.restore();\n }\n}\n\n/** A recorder for one frame at `dpr`; `measure` measures text (and lends its canvas). */\nexport function createRecorder(dpr: number, measure: CanvasRenderingContext2D | null): Recorder {\n return new Recorder(dpr, measure);\n}\n\nexport type { Recorder };\n","/**\n * The shaders. Each draws axis-aligned rectangles, one instance per\n * rectangle under the bars, bar (or pixel column when zoomed out), placed on\n * device pixels by the same rules as `charts/pixelGrid.ts`, so GPU bars line\n * up with what the 2D layer draws over them (crosshair, drawings). `floor(v + 0.5)` is used for\n * rounding: GLSL's `round()` may round halves either way, `Math.round` does not.\n */\n\nconst HEADER = `#version 300 es\nprecision highp float;\nuniform vec2 u_canvas;\nuniform float u_dpr;\nuniform int u_log;\nuniform int u_invert;\nuniform float u_yA;\nuniform float u_yB;\nuniform float u_logOffset;\nuniform float u_min;\nuniform float u_logFloor;\nuniform float u_logK;\nuniform float u_top;\nuniform float u_bottom;\nout vec4 v_color;\n\n// A price (relative to the base price) to a CSS-pixel y, as priceToYMapper\n// does; mappedY in yMapping.ts is the same steps in TypeScript.\nfloat cssY(float rel) {\n if (u_log == 1) {\n float v = log(max(1.0 + (rel + u_logOffset) / u_min, u_logFloor)) * u_logK;\n return u_invert == 1 ? u_top + v : u_bottom - v;\n }\n return u_yA + rel * u_yB;\n}\n\nfloat snap(float v) { return floor(v + 0.5); }\n\nvec4 toClip(vec2 dev) {\n return vec4(dev.x / u_canvas.x * 2.0 - 1.0, 1.0 - dev.y / u_canvas.y * 2.0, 0.0, 1.0);\n}\n\n// The corners of a quad as two triangles.\nvec2 corner(int k) {\n if (k == 0) return vec2(0.0, 0.0);\n if (k == 1 || k == 4) return vec2(1.0, 0.0);\n if (k == 2 || k == 3) return vec2(0.0, 1.0);\n return vec2(1.0, 1.0);\n}\n\n// Nothing to draw: every vertex at one point off the canvas.\nconst vec4 NOWHERE = vec4(-2.0, -2.0, 0.0, 1.0);\n`;\n\n/** Candles, a bar per instance: 6 vertices for the wick, then 6 for the body. */\nexport const CANDLE_BARS_VS = `${HEADER}\nin vec4 a_ohlc;\nin vec2 a_vd;\nuniform float u_x0;\nuniform float u_unit;\nuniform float u_wick;\nuniform float u_body;\nuniform vec4 u_upBody;\nuniform vec4 u_downBody;\nuniform vec4 u_upWick;\nuniform vec4 u_downWick;\n\nvoid main() {\n int vid = gl_VertexID % 12;\n vec2 cr = corner(vid % 6);\n bool up = a_vd.y > 0.5;\n float cx = (u_x0 + float(gl_InstanceID) * u_unit) * u_dpr;\n float wickLeft = snap(cx - u_wick * 0.5);\n float left;\n float width;\n float top;\n float height;\n if (vid < 6) {\n float h = snap(cssY(a_ohlc.y) * u_dpr);\n float l = snap(cssY(a_ohlc.z) * u_dpr);\n left = wickLeft;\n width = u_wick;\n top = min(h, l);\n height = max(abs(l - h), 1.0);\n v_color = up ? u_upWick : u_downWick;\n } else {\n float o = snap(cssY(a_ohlc.x) * u_dpr);\n float c = snap(cssY(a_ohlc.w) * u_dpr);\n left = wickLeft - (u_body - u_wick) * 0.5;\n width = u_body;\n top = min(o, c);\n height = max(abs(c - o), u_wick);\n v_color = up ? u_upBody : u_downBody;\n }\n gl_Position = toClip(vec2(left + cr.x * width, top + cr.y * height));\n}\n`;\n\n/** Volume, a bar per instance, under the candle bodies. */\nexport const VOLUME_BARS_VS = `${HEADER}\nin vec4 a_ohlc;\nin vec2 a_vd;\nuniform float u_x0;\nuniform float u_unit;\nuniform float u_wick;\nuniform float u_body;\nuniform float u_volBottom;\nuniform float u_volScale;\nuniform vec4 u_volUp;\nuniform vec4 u_volDown;\n\nvoid main() {\n vec2 cr = corner(gl_VertexID % 6);\n float cx = (u_x0 + float(gl_InstanceID) * u_unit) * u_dpr;\n float left = snap(cx - u_wick * 0.5) - (u_body - u_wick) * 0.5;\n float bottom = snap(u_volBottom * u_dpr);\n float top = snap((u_volBottom - a_vd.x * u_volScale) * u_dpr);\n if (bottom - top < 1.0) { gl_Position = NOWHERE; v_color = vec4(0.0); return; }\n v_color = a_vd.y > 0.5 ? u_volUp : u_volDown;\n gl_Position = toClip(vec2(left + cr.x * u_body, top + cr.y * (bottom - top)));\n}\n`;\n\n/**\n * Zoomed out: a pixel column per instance, from the CPU (x, high, low,\n * volume, up), reaching the next column with no gap.\n */\nexport const CANDLE_COLUMNS_VS = `${HEADER}\nin vec4 a_col;\nin float a_up;\nuniform vec4 u_upBody;\nuniform vec4 u_downBody;\n\nvoid main() {\n vec2 cr = corner(gl_VertexID % 6);\n float left = snap(a_col.x * u_dpr);\n float width = max(1.0, snap((a_col.x + 1.0) * u_dpr) - left);\n float t = snap(cssY(a_col.y) * u_dpr);\n float b = snap(cssY(a_col.z) * u_dpr);\n v_color = a_up > 0.5 ? u_upBody : u_downBody;\n gl_Position = toClip(vec2(left + cr.x * width, min(t, b) + cr.y * max(abs(b - t), 1.0)));\n}\n`;\n\nexport const VOLUME_COLUMNS_VS = `${HEADER}\nin vec4 a_col;\nin float a_up;\nuniform float u_volBottom;\nuniform float u_volScale;\nuniform vec4 u_volUp;\nuniform vec4 u_volDown;\n\nvoid main() {\n vec2 cr = corner(gl_VertexID % 6);\n float left = snap(a_col.x * u_dpr);\n float width = max(1.0, snap((a_col.x + 1.0) * u_dpr) - left);\n float bottom = snap(u_volBottom * u_dpr);\n float top = snap((u_volBottom - a_col.w * u_volScale) * u_dpr);\n if (bottom - top < 1.0) { gl_Position = NOWHERE; v_color = vec4(0.0); return; }\n v_color = a_up > 0.5 ? u_volUp : u_volDown;\n gl_Position = toClip(vec2(left + cr.x * width, top + cr.y * (bottom - top)));\n}\n`;\n\n/**\n * Rectangles under the bars (grid lines, session shading, break lines): one\n * per instance, in CSS pixels (left, top, right, bottom), in a premultiplied\n * colour, dashed down from the top when a_dash (on, off) is set. The quad\n * covers every device pixel the rectangle touches; the fragment shader works\n * out how much of each it covers, as Canvas 2D antialiases an edge at a\n * fractional pixel ratio.\n */\nexport const RECT_VS = `${HEADER}\nin vec4 a_rect;\nin vec4 a_color;\nin vec2 a_dash;\nflat out vec4 v_rect;\nflat out vec2 v_dash;\n\nvoid main() {\n vec2 cr = corner(gl_VertexID % 6);\n v_rect = a_rect * u_dpr;\n v_dash = a_dash * u_dpr;\n v_color = a_color;\n gl_Position = toClip(mix(floor(v_rect.xy), ceil(v_rect.zw), cr));\n}\n`;\n\n/**\n * The colour times the share of the pixel covered. For the grid (u_union),\n * coverage goes out as alpha, so that where lines cross the blend gives the\n * union of their coverage, as one 2D path does.\n */\nexport const RECT_FS = `#version 300 es\nprecision highp float;\nuniform vec2 u_canvas;\nuniform int u_union;\nin vec4 v_color;\nflat in vec4 v_rect;\nflat in vec2 v_dash;\nout vec4 outColor;\n\n// The share of rows [y, y + 1] inside the rectangle and, dashed, on a dash.\nfloat rows(float y) {\n float lo = max(y, v_rect.y);\n float hi = min(y + 1.0, v_rect.w);\n if (hi <= lo) return 0.0;\n if (v_dash.x <= 0.0) return hi - lo;\n // A dash period is longer than a device pixel, so the row meets the dash\n // of the period it starts in and the next (a third to spare).\n float period = v_dash.x + v_dash.y;\n float first = v_rect.y + floor((lo - v_rect.y) / period) * period;\n float on = 0.0;\n for (int i = 0; i < 3; i++) {\n float start = first + float(i) * period;\n on += max(0.0, min(hi, start + v_dash.x) - max(lo, start));\n }\n return on;\n}\n\nvoid main() {\n // This pixel's top-left corner in device pixels, y down.\n vec2 p = vec2(floor(gl_FragCoord.x), u_canvas.y - floor(gl_FragCoord.y) - 1.0);\n float coverage = clamp(min(p.x + 1.0, v_rect.z) - max(p.x, v_rect.x), 0.0, 1.0) * rows(p.y);\n outColor = u_union == 1 ? vec4(v_color.rgb * coverage, coverage) : v_color * coverage;\n}\n`;\n\n/**\n * Every bar program fills with its (premultiplied) colour, clipped to the\n * plot: a pixel the plot's edge cuts gets the share inside, as a 2D clip\n * antialiases an edge at a fractional pixel ratio.\n */\nexport const FILL_FS = `#version 300 es\nprecision highp float;\nuniform vec2 u_canvas;\nuniform vec4 u_clip;\nin vec4 v_color;\nout vec4 outColor;\n\nvoid main() {\n vec2 p = vec2(floor(gl_FragCoord.x), u_canvas.y - floor(gl_FragCoord.y) - 1.0);\n vec2 c = clamp(min(p + 1.0, u_clip.zw) - max(p, u_clip.xy), 0.0, 1.0);\n outColor = v_color * (c.x * c.y);\n}\n`;\n","import { resolveVolumeColors } from '@tradecanvas/commons';\nimport type { ViewportState } from '@tradecanvas/commons';\nimport type { GpuBackground, GpuDrawn, GpuFrame, GpuRect, GpuRecorder, GpuRenderer } from '../engine/gpu.js';\nimport { barColumns } from '../charts/pixelGrid.js';\nimport { gridLines } from '../axis/gridLines.js';\nimport { forEachPixelColumn, isDense } from '../charts/denseBars.js';\nimport { FLOATS_PER_BAR, SeriesUploads } from './seriesUploads.js';\nimport { parseColor, premultiplied, type RGBA } from './glColor.js';\nimport { yMapping } from './yMapping.js';\nimport { GlKit, type Program } from './glKit.js';\nimport { CommandDrawer } from './commandDrawer.js';\nimport { createRecorder, type Recorder } from './recorder.js';\nimport { CANDLE_BARS_VS, CANDLE_COLUMNS_VS, FILL_FS, RECT_FS, RECT_VS, VOLUME_BARS_VS, VOLUME_COLUMNS_VS } from './shaders.js';\n\nconst BAR_STRIDE = FLOATS_PER_BAR * 4;\n/** Floats per zoomed-out column: x, high, low, volume, up. */\nconst COLUMN_FLOATS = 5;\nconst COLUMN_STRIDE = COLUMN_FLOATS * 4;\n/** Floats per background rectangle: left, top, right, bottom, its premultiplied colour, then dash on and off (0 for solid). */\nconst RECT_FLOATS = 10;\nconst RECT_STRIDE = RECT_FLOATS * 4;\n\n/** Attributes the bar and rectangle programs read. */\nconst ATTRIBS = ['a_ohlc', 'a_vd', 'a_col', 'a_up', 'a_rect', 'a_color', 'a_dash'];\n\n/**\n * The background (grid, sessions), candles and volume on WebGL 2, on a\n * canvas of their own under the 2D scene, then whatever 2D drawing was\n * recorded for it (series of other kinds, indicators, panes). The series\n * lives in a GPU buffer, rewritten only where it changed; a frame sets a few\n * uniforms and makes a few draw calls. Zoomed out below a pixel per bar it\n * draws a column per pixel, like the 2D renderers.\n */\nexport class WebGLSeriesRenderer implements GpuRenderer {\n readonly label: string;\n private readonly gl: WebGL2RenderingContext;\n private readonly kit: GlKit;\n private readonly drawer: CommandDrawer;\n private readonly candleBars: Program;\n private readonly volumeBars: Program;\n private readonly candleColumns: Program;\n private readonly volumeColumns: Program;\n private readonly rects: Program;\n private readonly seriesBuffer: WebGLBuffer;\n private readonly columnBuffer: WebGLBuffer;\n private readonly rectBuffer: WebGLBuffer;\n private readonly uploads = new SeriesUploads();\n private gpuFloats = 0;\n private columns = new Float32Array(4096 * COLUMN_FLOATS);\n private rectValues = new Float32Array(64 * RECT_FLOATS);\n /** The plot in device pixels (left, top, right, bottom), for the bar programs' clip. */\n private clip: [number, number, number, number] = [0, 0, 0, 0];\n private lost = false;\n private lostCallback: (() => void) | null = null;\n\n /** A renderer on a new canvas, or null where WebGL 2 isn't there (or, asked for, only a software one). */\n static create(options: { failIfMajorPerformanceCaveat?: boolean } = {}): WebGLSeriesRenderer | null {\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n let gl: WebGL2RenderingContext | null = null;\n try {\n gl = canvas.getContext('webgl2', {\n alpha: true,\n premultipliedAlpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: false,\n failIfMajorPerformanceCaveat: options.failIfMajorPerformanceCaveat ?? false,\n });\n } catch (err) {\n warnUnavailable(err);\n return null;\n }\n // No WebGL 2 here: nothing to report, Canvas 2D it is.\n if (!gl) return null;\n try {\n return new WebGLSeriesRenderer(canvas, gl);\n } catch (err) {\n // A shader the driver won't compile, say: tell why, and let the context go.\n warnUnavailable(err);\n loseContext(gl);\n return null;\n }\n }\n\n private constructor(readonly canvas: HTMLCanvasElement, gl: WebGL2RenderingContext) {\n this.gl = gl;\n this.kit = new GlKit(gl);\n const info = gl.getExtension('WEBGL_debug_renderer_info');\n this.label = String(info ? gl.getParameter(info.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER));\n const kit = this.kit;\n this.candleBars = kit.program(CANDLE_BARS_VS, FILL_FS, ATTRIBS);\n this.volumeBars = kit.program(VOLUME_BARS_VS, FILL_FS, ATTRIBS);\n this.candleColumns = kit.program(CANDLE_COLUMNS_VS, FILL_FS, ATTRIBS);\n this.volumeColumns = kit.program(VOLUME_COLUMNS_VS, FILL_FS, ATTRIBS);\n this.rects = kit.program(RECT_VS, RECT_FS, ATTRIBS);\n this.seriesBuffer = kit.buffer();\n this.columnBuffer = kit.buffer();\n this.rectBuffer = kit.buffer();\n this.drawer = new CommandDrawer(kit);\n canvas.addEventListener('webglcontextlost', this.handleLost);\n }\n\n /** `callback` once the context is lost; soon (in a microtask) if it already is. */\n onLost(callback: () => void): void {\n this.lostCallback = callback;\n if (this.lost || this.gl.isContextLost()) {\n this.lost = true;\n queueMicrotask(() => {\n if (this.lostCallback === callback) callback();\n });\n }\n }\n\n recorder(dpr: number, measure: CanvasRenderingContext2D | null): GpuRecorder {\n return createRecorder(dpr, measure);\n }\n\n render(frame: GpuFrame): GpuDrawn {\n const gl = this.gl;\n if (this.lost || gl.isContextLost()) return { series: false, volume: false, background: false, recorded: false };\n const recorded = isRecorder(frame.recorded) ? frame.recorded : null;\n const drawn: GpuDrawn = { series: frame.candles, volume: frame.volume !== null, background: frame.background !== null, recorded: recorded !== null };\n gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n // A frame that failed half-way may have left the scissor on.\n gl.disable(gl.SCISSOR_TEST);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.enable(gl.BLEND);\n if (frame.background) this.drawBackground(frame, frame.background);\n this.drawSeries(frame);\n if (recorded && recorded.commands.length > 0) {\n this.drawer.draw(recorded.commands, this.canvas.width, this.canvas.height, (values, count) => this.drawRecordedRects(frame, values, count));\n }\n return drawn;\n }\n\n /** Volume and candles, clipped to the plot. */\n private drawSeries(frame: GpuFrame): void {\n const gl = this.gl;\n const { data, viewport, dpr } = frame;\n if (data.length === 0 || (!frame.candles && !frame.volume)) return;\n this.syncSeries(frame);\n\n const from = Math.max(0, viewport.visibleRange.from);\n const to = Math.min(viewport.visibleRange.to, data.length - 1);\n if (to < from) return;\n\n // The series is clipped to the plot, as the 2D renderers are: the\n // scissor to the pixels it touches, the shader to the share of each.\n const { chartRect } = viewport;\n this.clip = [chartRect.x * dpr, chartRect.y * dpr, (chartRect.x + chartRect.width) * dpr, (chartRect.y + chartRect.height) * dpr];\n const left = Math.floor(this.clip[0]);\n const top = Math.floor(this.clip[1]);\n const width = Math.ceil(this.clip[2]) - left;\n const height = Math.ceil(this.clip[3]) - top;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(left, this.canvas.height - top - height, Math.max(0, width), Math.max(0, height));\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n const dense = isDense(viewport);\n const columnCount = dense ? this.buildColumns(frame, from, to) : 0;\n if (frame.volume) this.drawVolume(frame, from, to, dense, columnCount);\n const { min, max } = viewport.priceRange;\n if (frame.candles && max - min !== 0) this.drawCandles(frame, from, to, dense, columnCount);\n gl.disable(gl.SCISSOR_TEST);\n }\n\n /** Recorded rectangles: device pixels, already clipped. */\n private drawRecordedRects(frame: GpuFrame, values: Float32Array, count: number): void {\n const gl = this.gl;\n const p = this.use(this.rects, frame);\n this.kit.float(p, 'u_dpr', 1);\n this.kit.int(p, 'u_union', 0);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.rectBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, values, gl.STREAM_DRAW);\n this.bindRects(p, 0);\n gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, count);\n }\n\n destroy(): void {\n this.canvas.removeEventListener('webglcontextlost', this.handleLost);\n this.lostCallback = null;\n const gl = this.gl;\n if (!gl.isContextLost()) {\n for (const p of [this.candleBars, this.volumeBars, this.candleColumns, this.volumeColumns, this.rects]) this.kit.deleteProgram(p);\n this.drawer.destroy();\n gl.deleteBuffer(this.seriesBuffer);\n gl.deleteBuffer(this.columnBuffer);\n gl.deleteBuffer(this.rectBuffer);\n // Hand the context back now, not at garbage collection: a page keeps\n // only so many, and the browser drops the oldest (maybe a live chart's).\n loseContext(gl);\n }\n this.canvas.remove();\n }\n\n private readonly handleLost = (e: Event) => {\n e.preventDefault();\n if (this.lost) return;\n this.lost = true;\n this.lostCallback?.();\n };\n\n private syncSeries(frame: GpuFrame): void {\n const gl = this.gl;\n const change = this.uploads.sync(frame.data);\n const values = this.uploads.values;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.seriesBuffer);\n if (change.full || values.length !== this.gpuFloats) {\n gl.bufferData(gl.ARRAY_BUFFER, values, gl.DYNAMIC_DRAW);\n this.gpuFloats = values.length;\n } else if (change.to > change.from) {\n gl.bufferSubData(gl.ARRAY_BUFFER, change.from * BAR_STRIDE, values, change.from * FLOATS_PER_BAR, (change.to - change.from) * FLOATS_PER_BAR);\n }\n }\n\n /** Zoomed out: the bars merged per pixel column, as the 2D dense renderers merge them. */\n private buildColumns(frame: GpuFrame, from: number, to: number): number {\n const { viewport, data } = frame;\n const barUnit = viewport.barWidth + viewport.barSpacing;\n const offsetX = -viewport.offset + viewport.chartRect.x + viewport.barWidth / 2;\n const base = this.uploads.base;\n let n = 0;\n forEachPixelColumn(data, from, to, (i) => i * barUnit + offsetX, (c) => {\n if ((n + 1) * COLUMN_FLOATS > this.columns.length) {\n const bigger = new Float32Array(this.columns.length * 2);\n bigger.set(this.columns);\n this.columns = bigger;\n }\n const k = n * COLUMN_FLOATS;\n this.columns[k] = c.x;\n this.columns[k + 1] = c.high - base;\n this.columns[k + 2] = c.low - base;\n this.columns[k + 3] = c.volume;\n this.columns[k + 4] = c.close >= c.open ? 1 : 0;\n n++;\n });\n const gl = this.gl;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.columnBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, this.columns.subarray(0, n * COLUMN_FLOATS), gl.STREAM_DRAW);\n return n;\n }\n\n /**\n * The grid, then the other rectangles, unclipped like the 2D background.\n * The grid's coverage blends as the union of its lines: colour weighted by\n * coverage, alpha by the colour's own alpha (the blend constant) times\n * coverage. The rest blend as Canvas 2D fills do.\n */\n private drawBackground(frame: GpuFrame, background: GpuBackground): void {\n const { viewport, theme } = frame;\n const lines = background.grid ? gridLines(viewport) : { horizontal: [], vertical: [] };\n const gridCount = lines.horizontal.length + lines.vertical.length;\n const total = gridCount + background.rects.length;\n if (total === 0) return;\n if (this.rectValues.length < total * RECT_FLOATS) this.rectValues = new Float32Array(total * RECT_FLOATS * 2);\n const values = this.rectValues;\n let k = 0;\n const put = (left: number, top: number, right: number, bottom: number, color: RGBA, alpha: number, dash?: GpuRect['dash']) => {\n values[k++] = left;\n values[k++] = top;\n values[k++] = right;\n values[k++] = bottom;\n for (let i = 0; i < 4; i++) values[k++] = color[i] * alpha;\n values[k++] = dash ? dash[0] : 0;\n values[k++] = dash ? dash[1] : 0;\n };\n const gridColor = premultiplied(parseColor(theme.grid));\n const { chartRect } = viewport;\n for (const y of lines.horizontal) put(chartRect.x, y - 0.5, chartRect.x + chartRect.width, y + 0.5, gridColor, 1);\n for (const x of lines.vertical) put(x - 0.5, chartRect.y, x + 0.5, chartRect.y + chartRect.height, gridColor, 1);\n // The rectangles mostly share a colour or two.\n let lastColor = '';\n let color = gridColor;\n for (const r of background.rects) {\n if (r.color !== lastColor) {\n lastColor = r.color;\n color = premultiplied(parseColor(r.color));\n }\n put(r.x, r.y, r.x + r.width, r.y + r.height, color, r.alpha, r.dash);\n }\n\n const gl = this.gl;\n const p = this.use(this.rects, frame);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.rectBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, values.subarray(0, k), gl.STREAM_DRAW);\n if (gridCount > 0) {\n gl.uniform1i(this.loc(p, 'u_union'), 1);\n gl.blendColor(0, 0, 0, gridColor[3]);\n gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.CONSTANT_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n this.bindRects(p, 0);\n gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, gridCount);\n }\n if (background.rects.length > 0) {\n gl.uniform1i(this.loc(p, 'u_union'), 0);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n this.bindRects(p, gridCount);\n gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, background.rects.length);\n }\n }\n\n private drawCandles(frame: GpuFrame, from: number, to: number, dense: boolean, columns: number): void {\n const { theme, viewport, dpr } = frame;\n const up = premultiplied(parseColor(theme.candleUp));\n const down = premultiplied(parseColor(theme.candleDown));\n if (dense) {\n const p = this.use(this.candleColumns, frame);\n this.vec4(p, 'u_upBody', up);\n this.vec4(p, 'u_downBody', down);\n this.bindColumns(p);\n this.gl.drawArraysInstanced(this.gl.TRIANGLES, 0, 6, columns);\n return;\n }\n const p = this.use(this.candleBars, frame);\n this.barUniforms(p, viewport, from, dpr);\n this.vec4(p, 'u_upBody', up);\n this.vec4(p, 'u_downBody', down);\n this.vec4(p, 'u_upWick', premultiplied(parseColor(theme.candleUpWick)));\n this.vec4(p, 'u_downWick', premultiplied(parseColor(theme.candleDownWick)));\n this.bindBars(p, from);\n this.gl.drawArraysInstanced(this.gl.TRIANGLES, 0, 12, to - from + 1);\n }\n\n private drawVolume(frame: GpuFrame, from: number, to: number, dense: boolean, columns: number): void {\n const { data, viewport, theme, dpr } = frame;\n let maxVol = 0;\n for (let i = from; i <= to; i++) if (data[i].volume > maxVol) maxVol = data[i].volume;\n if (maxVol === 0) return;\n const { chartRect } = viewport;\n const colors = resolveVolumeColors(theme);\n const p = this.use(dense ? this.volumeColumns : this.volumeBars, frame);\n this.float(p, 'u_volBottom', chartRect.y + chartRect.height);\n this.float(p, 'u_volScale', (chartRect.height * (frame.volume?.heightRatio ?? 0.15)) / maxVol);\n this.vec4(p, 'u_volUp', premultiplied(parseColor(colors.up)));\n this.vec4(p, 'u_volDown', premultiplied(parseColor(colors.down)));\n if (dense) {\n this.bindColumns(p);\n this.gl.drawArraysInstanced(this.gl.TRIANGLES, 0, 6, columns);\n return;\n }\n this.barUniforms(p, viewport, from, dpr);\n this.bindBars(p, from);\n this.gl.drawArraysInstanced(this.gl.TRIANGLES, 0, 6, to - from + 1);\n }\n\n /** Where bar `from` is, the bar step, and the wick and body widths in device pixels. */\n private barUniforms(p: Program, viewport: ViewportState, from: number, dpr: number): void {\n const barUnit = viewport.barWidth + viewport.barSpacing;\n const offsetX = -viewport.offset + viewport.chartRect.x + viewport.barWidth / 2;\n const { body, wick } = barColumns(viewport.barWidth, dpr);\n this.float(p, 'u_x0', from * barUnit + offsetX);\n this.float(p, 'u_unit', barUnit);\n this.float(p, 'u_wick', wick);\n this.float(p, 'u_body', body);\n }\n\n private use(p: Program, frame: GpuFrame): Program {\n const gl = this.gl;\n this.kit.use(p);\n gl.uniform2f(this.loc(p, 'u_canvas'), this.canvas.width, this.canvas.height);\n this.vec4(p, 'u_clip', this.clip);\n this.float(p, 'u_dpr', frame.dpr);\n const y = yMapping(frame.viewport, this.uploads.base);\n gl.uniform1i(this.loc(p, 'u_log'), y.log);\n gl.uniform1i(this.loc(p, 'u_invert'), y.invert);\n this.float(p, 'u_yA', y.yA);\n this.float(p, 'u_yB', y.yB);\n this.float(p, 'u_logOffset', y.logOffset);\n this.float(p, 'u_min', y.min);\n this.float(p, 'u_logFloor', y.logFloor);\n this.float(p, 'u_logK', y.logK);\n this.float(p, 'u_top', y.top);\n this.float(p, 'u_bottom', y.bottom);\n return p;\n }\n\n private bindBars(p: Program, from: number): void {\n const gl = this.gl;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.seriesBuffer);\n this.attrib(p, 'a_ohlc', 4, BAR_STRIDE, from * BAR_STRIDE);\n this.attrib(p, 'a_vd', 2, BAR_STRIDE, from * BAR_STRIDE + 16);\n }\n\n private bindRects(p: Program, from: number): void {\n this.attrib(p, 'a_rect', 4, RECT_STRIDE, from * RECT_STRIDE);\n this.attrib(p, 'a_color', 4, RECT_STRIDE, from * RECT_STRIDE + 16);\n this.attrib(p, 'a_dash', 2, RECT_STRIDE, from * RECT_STRIDE + 32);\n }\n\n private bindColumns(p: Program): void {\n const gl = this.gl;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.columnBuffer);\n this.attrib(p, 'a_col', 4, COLUMN_STRIDE, 0);\n this.attrib(p, 'a_up', 1, COLUMN_STRIDE, 16);\n }\n\n private attrib(p: Program, name: string, size: number, stride: number, offset: number): void {\n this.kit.attrib(p, name, size, stride, offset);\n }\n\n private float(p: Program, name: string, v: number): void {\n this.kit.float(p, name, v);\n }\n\n private vec4(p: Program, name: string, v: readonly number[]): void {\n this.kit.vec4(p, name, v);\n }\n\n private loc(p: Program, name: string): WebGLUniformLocation | null {\n return this.kit.loc(p, name);\n }\n}\n\n/** A recorder of this renderer's own making. */\nfunction isRecorder(r: unknown): r is Recorder {\n return typeof r === 'object' && r !== null && Array.isArray((r as Recorder).commands);\n}\n\n/** Let a context go now rather than at garbage collection. */\nfunction loseContext(gl: WebGL2RenderingContext): void {\n gl.getExtension('WEBGL_lose_context')?.loseContext();\n}\n\nfunction warnUnavailable(err: unknown): void {\n console.warn('TradeCanvas: WebGL renderer unavailable, drawing with Canvas 2D.', err);\n}\n"],"mappings":"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"}
|