@oh-just-another/renderer-canvas 0.59.0 → 0.61.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/CHANGELOG.md +108 -0
- package/README.md +10 -7
- package/dist/.tsbuildinfo +1 -1
- package/dist/canvas-target.d.ts +6 -1
- package/dist/canvas-target.d.ts.map +1 -1
- package/dist/canvas-target.js +12 -2
- package/dist/canvas-target.js.map +1 -1
- package/dist/constants.d.ts +49 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +49 -0
- package/dist/constants.js.map +1 -1
- package/dist/hi-dpi.d.ts +10 -0
- package/dist/hi-dpi.d.ts.map +1 -1
- package/dist/hi-dpi.js +12 -1
- package/dist/hi-dpi.js.map +1 -1
- package/dist/image-source.d.ts +11 -0
- package/dist/image-source.d.ts.map +1 -1
- package/dist/image-source.js +20 -0
- package/dist/image-source.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layered-canvas.d.ts +7 -1
- package/dist/layered-canvas.d.ts.map +1 -1
- package/dist/layered-canvas.js +6 -3
- package/dist/layered-canvas.js.map +1 -1
- package/dist/layered-surface.d.ts +16 -0
- package/dist/layered-surface.d.ts.map +1 -1
- package/dist/layered-surface.js +59 -14
- package/dist/layered-surface.js.map +1 -1
- package/dist/recording-target.d.ts +56 -13
- package/dist/recording-target.d.ts.map +1 -1
- package/dist/recording-target.js +229 -38
- package/dist/recording-target.js.map +1 -1
- package/dist/render-worker.js +19 -7
- package/dist/render-worker.js.map +1 -1
- package/dist/replay-codec.d.ts +56 -0
- package/dist/replay-codec.d.ts.map +1 -0
- package/dist/replay-codec.js +543 -0
- package/dist/replay-codec.js.map +1 -0
- package/dist/tile-compositor.d.ts +52 -1
- package/dist/tile-compositor.d.ts.map +1 -1
- package/dist/tile-compositor.js +82 -5
- package/dist/tile-compositor.js.map +1 -1
- package/dist/webgl2-curve.d.ts +12 -2
- package/dist/webgl2-curve.d.ts.map +1 -1
- package/dist/webgl2-curve.js +168 -40
- package/dist/webgl2-curve.js.map +1 -1
- package/dist/webgl2-ellipse.d.ts +1 -29
- package/dist/webgl2-ellipse.d.ts.map +1 -1
- package/dist/webgl2-ellipse.js +35 -22
- package/dist/webgl2-ellipse.js.map +1 -1
- package/dist/webgl2-msdf-text.d.ts +15 -2
- package/dist/webgl2-msdf-text.d.ts.map +1 -1
- package/dist/webgl2-msdf-text.js +101 -9
- package/dist/webgl2-msdf-text.js.map +1 -1
- package/dist/webgl2-rect-batch.d.ts +81 -0
- package/dist/webgl2-rect-batch.d.ts.map +1 -0
- package/dist/webgl2-rect-batch.js +201 -0
- package/dist/webgl2-rect-batch.js.map +1 -0
- package/dist/webgl2-stroke.d.ts +14 -35
- package/dist/webgl2-stroke.d.ts.map +1 -1
- package/dist/webgl2-stroke.js +27 -30
- package/dist/webgl2-stroke.js.map +1 -1
- package/dist/webgl2-target.d.ts +95 -13
- package/dist/webgl2-target.d.ts.map +1 -1
- package/dist/webgl2-target.js +423 -230
- package/dist/webgl2-target.js.map +1 -1
- package/package.json +4 -3
package/dist/constants.d.ts
CHANGED
|
@@ -70,6 +70,32 @@ export declare const OFFSCREEN_IMAGE_CACHE_CAP = 64;
|
|
|
70
70
|
* cost).
|
|
71
71
|
*/
|
|
72
72
|
export declare const WEBGL2_IMAGE_TEXTURE_CACHE_CAP = 64;
|
|
73
|
+
/**
|
|
74
|
+
* Cap applied to `window.devicePixelRatio` when sizing canvas bitmaps
|
|
75
|
+
* (`setupHiDpi`, `createLayeredSurface`). Mobile / hi-end displays report
|
|
76
|
+
* DPR 3–4; rendering the full ratio quadruples-to-sixteenfolds the pixel
|
|
77
|
+
* fill cost per layer for visual gains that are imperceptible in a
|
|
78
|
+
* diagram editor (thin strokes, flat fills). Capping at 2 keeps bitmap
|
|
79
|
+
* memory and raster time bounded — text and hairlines render very
|
|
80
|
+
* slightly softer on DPR-3 devices. Range: 1–4; hosts needing exact
|
|
81
|
+
* native sharpness can raise it via `CreateLayeredSurfaceOptions.maxDpr`
|
|
82
|
+
* or by passing an explicit `dpr` to `setupHiDpi`.
|
|
83
|
+
*/
|
|
84
|
+
export declare const MAX_DEVICE_PIXEL_RATIO = 2;
|
|
85
|
+
/**
|
|
86
|
+
* LRU cap on the Loop-Blinn triangulation cache in `webgl2-curve.ts`.
|
|
87
|
+
* Keyed by curve control-point content (renderers emit paths in
|
|
88
|
+
* element-local coordinates, so identical geometry — e.g. every
|
|
89
|
+
* same-size rounded rect — shares one entry, and pan / zoom / drag
|
|
90
|
+
* never invalidate it: the transform is applied in the vertex shader).
|
|
91
|
+
*
|
|
92
|
+
* Each entry stores the packed positions + uvs plus the key floats —
|
|
93
|
+
* a rounded rect (4 triangles) is ≈ 500 bytes, so the cap bounds the
|
|
94
|
+
* cache at a few MB worst-case. On overflow the least-recently-drawn
|
|
95
|
+
* geometry is evicted and re-triangulated on next draw (cheap, no GPU
|
|
96
|
+
* resources involved). Range: 512–16384.
|
|
97
|
+
*/
|
|
98
|
+
export declare const WEBGL2_CURVE_TRIANGULATION_CACHE_CAP = 4096;
|
|
73
99
|
/**
|
|
74
100
|
* Lower bound on the polygon approximation of an ellipse. Keeps small
|
|
75
101
|
* ellipses from collapsing to a coarse hexagon at far zoom. Range: 12–48.
|
|
@@ -81,4 +107,27 @@ export declare const ELLIPSE_MIN_SEGMENTS = 24;
|
|
|
81
107
|
* improvement. Range: 256–1024.
|
|
82
108
|
*/
|
|
83
109
|
export declare const ELLIPSE_MAX_SEGMENTS = 512;
|
|
110
|
+
/**
|
|
111
|
+
* Initial per-target capacity, in instances, of the sharp-rect instance
|
|
112
|
+
* batcher (`webgl2-rect-batch.ts` `RectBatch`). One frame's worth of
|
|
113
|
+
* same-run rect fills packs into this without a grow; capacity doubles
|
|
114
|
+
* on demand and never shrinks. 256 covers typical grid / background
|
|
115
|
+
* scenes at ~10 KB (40 bytes/instance). Range: 64–4096.
|
|
116
|
+
*/
|
|
117
|
+
export declare const INITIAL_RECT_BATCH_INSTANCES = 256;
|
|
118
|
+
/**
|
|
119
|
+
* LRU cap on the per-atlas MSDF run-width memo (`webgl2-msdf-text.ts`).
|
|
120
|
+
* The em-width of a text run (Σ advance/unitsPerEm) is immutable once its
|
|
121
|
+
* glyphs are cached, so it is memoized keyed by `(fontId, text)`: a
|
|
122
|
+
* repeat `measureText`, or a `measureText` after the same string was
|
|
123
|
+
* drawn, returns in O(1) instead of re-walking the codepoints. Caret
|
|
124
|
+
* positioning and selection geometry call `measureText` on the same
|
|
125
|
+
* label many times per frame, so the hit rate is high.
|
|
126
|
+
*
|
|
127
|
+
* Each entry is a single number keyed by the run string — cheap. 1024
|
|
128
|
+
* covers a large editing session's distinct labels with margin; on
|
|
129
|
+
* overflow the least-recently-measured run is evicted and re-walked on
|
|
130
|
+
* next measure (cheap, no GPU resources). Range: 256–8192.
|
|
131
|
+
*/
|
|
132
|
+
export declare const WEBGL2_MSDF_RUN_WIDTH_CACHE_CAP = 1024;
|
|
84
133
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oCAAoC,OAAO,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,+BAA+B,OAAO,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -70,6 +70,32 @@ export const OFFSCREEN_IMAGE_CACHE_CAP = 64;
|
|
|
70
70
|
* cost).
|
|
71
71
|
*/
|
|
72
72
|
export const WEBGL2_IMAGE_TEXTURE_CACHE_CAP = 64;
|
|
73
|
+
/**
|
|
74
|
+
* Cap applied to `window.devicePixelRatio` when sizing canvas bitmaps
|
|
75
|
+
* (`setupHiDpi`, `createLayeredSurface`). Mobile / hi-end displays report
|
|
76
|
+
* DPR 3–4; rendering the full ratio quadruples-to-sixteenfolds the pixel
|
|
77
|
+
* fill cost per layer for visual gains that are imperceptible in a
|
|
78
|
+
* diagram editor (thin strokes, flat fills). Capping at 2 keeps bitmap
|
|
79
|
+
* memory and raster time bounded — text and hairlines render very
|
|
80
|
+
* slightly softer on DPR-3 devices. Range: 1–4; hosts needing exact
|
|
81
|
+
* native sharpness can raise it via `CreateLayeredSurfaceOptions.maxDpr`
|
|
82
|
+
* or by passing an explicit `dpr` to `setupHiDpi`.
|
|
83
|
+
*/
|
|
84
|
+
export const MAX_DEVICE_PIXEL_RATIO = 2;
|
|
85
|
+
/**
|
|
86
|
+
* LRU cap on the Loop-Blinn triangulation cache in `webgl2-curve.ts`.
|
|
87
|
+
* Keyed by curve control-point content (renderers emit paths in
|
|
88
|
+
* element-local coordinates, so identical geometry — e.g. every
|
|
89
|
+
* same-size rounded rect — shares one entry, and pan / zoom / drag
|
|
90
|
+
* never invalidate it: the transform is applied in the vertex shader).
|
|
91
|
+
*
|
|
92
|
+
* Each entry stores the packed positions + uvs plus the key floats —
|
|
93
|
+
* a rounded rect (4 triangles) is ≈ 500 bytes, so the cap bounds the
|
|
94
|
+
* cache at a few MB worst-case. On overflow the least-recently-drawn
|
|
95
|
+
* geometry is evicted and re-triangulated on next draw (cheap, no GPU
|
|
96
|
+
* resources involved). Range: 512–16384.
|
|
97
|
+
*/
|
|
98
|
+
export const WEBGL2_CURVE_TRIANGULATION_CACHE_CAP = 4096;
|
|
73
99
|
/**
|
|
74
100
|
* Lower bound on the polygon approximation of an ellipse. Keeps small
|
|
75
101
|
* ellipses from collapsing to a coarse hexagon at far zoom. Range: 12–48.
|
|
@@ -81,4 +107,27 @@ export const ELLIPSE_MIN_SEGMENTS = 24;
|
|
|
81
107
|
* improvement. Range: 256–1024.
|
|
82
108
|
*/
|
|
83
109
|
export const ELLIPSE_MAX_SEGMENTS = 512;
|
|
110
|
+
/**
|
|
111
|
+
* Initial per-target capacity, in instances, of the sharp-rect instance
|
|
112
|
+
* batcher (`webgl2-rect-batch.ts` `RectBatch`). One frame's worth of
|
|
113
|
+
* same-run rect fills packs into this without a grow; capacity doubles
|
|
114
|
+
* on demand and never shrinks. 256 covers typical grid / background
|
|
115
|
+
* scenes at ~10 KB (40 bytes/instance). Range: 64–4096.
|
|
116
|
+
*/
|
|
117
|
+
export const INITIAL_RECT_BATCH_INSTANCES = 256;
|
|
118
|
+
/**
|
|
119
|
+
* LRU cap on the per-atlas MSDF run-width memo (`webgl2-msdf-text.ts`).
|
|
120
|
+
* The em-width of a text run (Σ advance/unitsPerEm) is immutable once its
|
|
121
|
+
* glyphs are cached, so it is memoized keyed by `(fontId, text)`: a
|
|
122
|
+
* repeat `measureText`, or a `measureText` after the same string was
|
|
123
|
+
* drawn, returns in O(1) instead of re-walking the codepoints. Caret
|
|
124
|
+
* positioning and selection geometry call `measureText` on the same
|
|
125
|
+
* label many times per frame, so the hit rate is high.
|
|
126
|
+
*
|
|
127
|
+
* Each entry is a single number keyed by the run string — cheap. 1024
|
|
128
|
+
* covers a large editing session's distinct labels with margin; on
|
|
129
|
+
* overflow the least-recently-measured run is evicted and re-walked on
|
|
130
|
+
* next measure (cheap, no GPU resources). Range: 256–8192.
|
|
131
|
+
*/
|
|
132
|
+
export const WEBGL2_MSDF_RUN_WIDTH_CACHE_CAP = 1024;
|
|
84
133
|
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,IAAI,CAAC;AAEzD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,IAAI,CAAC"}
|
package/dist/hi-dpi.d.ts
CHANGED
|
@@ -19,6 +19,16 @@
|
|
|
19
19
|
* subsequent `getContext("webgl2")` returns null. Use `false` for the WebGL2
|
|
20
20
|
* main canvas in `WebGL2LayeredSurface`; its viewport is set inside
|
|
21
21
|
* `WebGL2Target` after the GL context is obtained.
|
|
22
|
+
*
|
|
23
|
+
* The default `dpr` is `window.devicePixelRatio` capped at
|
|
24
|
+
* `MAX_DEVICE_PIXEL_RATIO` (see constants.ts). An explicit `dpr` argument
|
|
25
|
+
* is honoured as-is — pass the raw ratio to opt out of the cap.
|
|
22
26
|
*/
|
|
23
27
|
export declare const setupHiDpi: (canvas: HTMLCanvasElement, width: number, height: number, dpr?: number, setupContext?: boolean) => number;
|
|
28
|
+
/**
|
|
29
|
+
* The live `window.devicePixelRatio` clamped to `maxDpr` (SSR-safe:
|
|
30
|
+
* resolves to 1 when there is no `window`). Callers that re-read the DPR
|
|
31
|
+
* on resize (monitor changes) go through this instead of the raw ratio.
|
|
32
|
+
*/
|
|
33
|
+
export declare const cappedDpr: (maxDpr?: number) => number;
|
|
24
34
|
//# sourceMappingURL=hi-dpi.d.ts.map
|
package/dist/hi-dpi.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hi-dpi.d.ts","sourceRoot":"","sources":["../src/hi-dpi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hi-dpi.d.ts","sourceRoot":"","sources":["../src/hi-dpi.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,UAAU,GACrB,QAAQ,iBAAiB,EACzB,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,MAAK,MAAoB,EACzB,sBAAmB,KAClB,MAuBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,SAAQ,MAA+B,KAAG,MACgB,CAAC"}
|
package/dist/hi-dpi.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MAX_DEVICE_PIXEL_RATIO } from "./constants.js";
|
|
1
2
|
/**
|
|
2
3
|
* Configures a `<canvas>` for hi-DPI rendering. Sets the bitmap size to
|
|
3
4
|
* `width * dpr` × `height * dpr`, the CSS size to `width` × `height`, and
|
|
@@ -19,8 +20,12 @@
|
|
|
19
20
|
* subsequent `getContext("webgl2")` returns null. Use `false` for the WebGL2
|
|
20
21
|
* main canvas in `WebGL2LayeredSurface`; its viewport is set inside
|
|
21
22
|
* `WebGL2Target` after the GL context is obtained.
|
|
23
|
+
*
|
|
24
|
+
* The default `dpr` is `window.devicePixelRatio` capped at
|
|
25
|
+
* `MAX_DEVICE_PIXEL_RATIO` (see constants.ts). An explicit `dpr` argument
|
|
26
|
+
* is honoured as-is — pass the raw ratio to opt out of the cap.
|
|
22
27
|
*/
|
|
23
|
-
export const setupHiDpi = (canvas, width, height, dpr =
|
|
28
|
+
export const setupHiDpi = (canvas, width, height, dpr = cappedDpr(), setupContext = true) => {
|
|
24
29
|
const targetW = Math.round(width * dpr);
|
|
25
30
|
const targetH = Math.round(height * dpr);
|
|
26
31
|
const cssW = `${width}px`;
|
|
@@ -43,4 +48,10 @@ export const setupHiDpi = (canvas, width, height, dpr = window.devicePixelRatio
|
|
|
43
48
|
}
|
|
44
49
|
return dpr;
|
|
45
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* The live `window.devicePixelRatio` clamped to `maxDpr` (SSR-safe:
|
|
53
|
+
* resolves to 1 when there is no `window`). Callers that re-read the DPR
|
|
54
|
+
* on resize (monitor changes) go through this instead of the raw ratio.
|
|
55
|
+
*/
|
|
56
|
+
export const cappedDpr = (maxDpr = MAX_DEVICE_PIXEL_RATIO) => Math.min(typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1, maxDpr);
|
|
46
57
|
//# sourceMappingURL=hi-dpi.js.map
|
package/dist/hi-dpi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hi-dpi.js","sourceRoot":"","sources":["../src/hi-dpi.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hi-dpi.js","sourceRoot":"","sources":["../src/hi-dpi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,MAAyB,EACzB,KAAa,EACb,MAAc,EACd,MAAc,SAAS,EAAE,EACzB,YAAY,GAAG,IAAI,EACX,EAAE;IACV,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC;IAC3B,IACE,MAAM,CAAC,KAAK,KAAK,OAAO;QACxB,MAAM,CAAC,MAAM,KAAK,OAAO;QACzB,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI;QAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,EAC5B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;IACvB,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACzD,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,SAAiB,sBAAsB,EAAU,EAAE,CAC3E,IAAI,CAAC,GAAG,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC"}
|
package/dist/image-source.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
export declare const isDrawableImageSource: (value: unknown) => value is CanvasImageSource;
|
|
2
|
+
/**
|
|
3
|
+
* Intrinsic pixel size of a drawable image source, or `null` when it can't be
|
|
4
|
+
* determined. Handles the differing width/height accessors of the DOM image
|
|
5
|
+
* types (`naturalWidth` for `<img>`, `videoWidth` for `<video>`, plain
|
|
6
|
+
* `width`/`height` for bitmaps / canvases). Needed to turn a normalised crop
|
|
7
|
+
* (fractions) into a pixel source rectangle for `ctx.drawImage`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const intrinsicImageSize: (source: CanvasImageSource) => {
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly height: number;
|
|
12
|
+
} | null;
|
|
2
13
|
export declare const warnSkippedImage: (value: unknown) => void;
|
|
3
14
|
//# sourceMappingURL=image-source.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-source.d.ts","sourceRoot":"","sources":["../src/image-source.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,iBAa/D,CAAC;AAUF,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,IAoBjD,CAAC"}
|
|
1
|
+
{"version":3,"file":"image-source.d.ts","sourceRoot":"","sources":["../src/image-source.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,iBAa/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,iBAAiB,KACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAmBxD,CAAC;AAUF,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,IAoBjD,CAAC"}
|
package/dist/image-source.js
CHANGED
|
@@ -37,6 +37,26 @@ export const isDrawableImageSource = (value) => {
|
|
|
37
37
|
}
|
|
38
38
|
return false;
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Intrinsic pixel size of a drawable image source, or `null` when it can't be
|
|
42
|
+
* determined. Handles the differing width/height accessors of the DOM image
|
|
43
|
+
* types (`naturalWidth` for `<img>`, `videoWidth` for `<video>`, plain
|
|
44
|
+
* `width`/`height` for bitmaps / canvases). Needed to turn a normalised crop
|
|
45
|
+
* (fractions) into a pixel source rectangle for `ctx.drawImage`.
|
|
46
|
+
*/
|
|
47
|
+
export const intrinsicImageSize = (source) => {
|
|
48
|
+
const s = source;
|
|
49
|
+
if (typeof s.naturalWidth === "number" && s.naturalWidth > 0) {
|
|
50
|
+
return { width: s.naturalWidth, height: s.naturalHeight ?? s.naturalWidth };
|
|
51
|
+
}
|
|
52
|
+
if (typeof s.videoWidth === "number" && s.videoWidth > 0) {
|
|
53
|
+
return { width: s.videoWidth, height: s.videoHeight ?? s.videoWidth };
|
|
54
|
+
}
|
|
55
|
+
if (typeof s.width === "number" && s.width > 0 && typeof s.height === "number") {
|
|
56
|
+
return { width: s.width, height: s.height };
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
40
60
|
/**
|
|
41
61
|
* Warn (once per distinct kind) when an image draw is skipped because
|
|
42
62
|
* the handle isn't drawable. Throttled by a module-level `Set` so a
|
package/dist/image-source.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-source.js","sourceRoot":"","sources":["../src/image-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,mBAAmB,GAAG;IAC1B,kBAAkB;IAClB,mBAAmB;IACnB,kBAAkB;IAClB,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,YAAY;CACJ,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAA8B,EAAE;IAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACrB,IACE,OAAO,IAAI,KAAK,UAAU;YAC1B,KAAK,YAAa,IAA0C,EAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAQ,EAAE;IACvD,IAAI,OAAO,OAAO,KAAK,WAAW;QAAE,OAAO;IAC3C,MAAM,IAAI,GACR,OAAO,KAAK,KAAK,QAAQ;QACvB,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;YACzB,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,YAAY;QAChB,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YACrC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,cAAc,CAAC,CAAC,oCAAoC;IAC5D,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IACvC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE3B,OAAO,CAAC,IAAI,CACV,yDAAyD,IAAI,KAAK;QAChE,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,2CAA2C,CAC9C,CAAC;AACJ,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"image-source.js","sourceRoot":"","sources":["../src/image-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,mBAAmB,GAAG;IAC1B,kBAAkB;IAClB,mBAAmB;IACnB,kBAAkB;IAClB,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,YAAY;CACJ,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAA8B,EAAE;IAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACrB,IACE,OAAO,IAAI,KAAK,UAAU;YAC1B,KAAK,YAAa,IAA0C,EAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,MAAyB,EACmC,EAAE;IAC9D,MAAM,CAAC,GAAG,MAOT,CAAC;IACF,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;IAC9E,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/E,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAQ,EAAE;IACvD,IAAI,OAAO,OAAO,KAAK,WAAW;QAAE,OAAO;IAC3C,MAAM,IAAI,GACR,OAAO,KAAK,KAAK,QAAQ;QACvB,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;YACzB,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,YAAY;QAChB,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YACrC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,cAAc,CAAC,CAAC,oCAAoC;IAC5D,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IACvC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE3B,OAAO,CAAC,IAAI,CACV,yDAAyD,IAAI,KAAK;QAChE,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,2CAA2C,CAC9C,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { Canvas2DTarget } from "./canvas-target.js";
|
|
2
2
|
export { Canvas2DTextShaper } from "./canvas-text-shaper.js";
|
|
3
|
-
export { WebGL2Target } from "./webgl2-target.js";
|
|
3
|
+
export { WebGL2Target, type WebGL2TargetOptions } from "./webgl2-target.js";
|
|
4
4
|
export { renderViaTiles, type RenderViaTilesOptions } from "./tile-compositor.js";
|
|
5
|
-
export { setupHiDpi } from "./hi-dpi.js";
|
|
5
|
+
export { setupHiDpi, cappedDpr } from "./hi-dpi.js";
|
|
6
6
|
export { LayeredCanvas, type LayeredCanvasOptions } from "./layered-canvas.js";
|
|
7
7
|
export { supportsOffscreenCanvas, createOffscreenCanvas2DTarget, transferCanvasToWorker, } from "./offscreen.js";
|
|
8
8
|
export { createRenderWorker } from "./worker-factory.js";
|
|
@@ -10,7 +10,7 @@ export { WorkerPool, LayerWorkerPool } from "@oh-just-another/renderer-workers";
|
|
|
10
10
|
export { RecordingTarget, replayCommands, type RenderCommand } from "./recording-target.js";
|
|
11
11
|
export { createLayeredSurface, createLayeredSurfaceWithFallback, type LayeredSurface, type RendererBackend, type CreateLayeredSurfaceOptions, } from "./layered-surface.js";
|
|
12
12
|
export { isWebGPUAvailable, isWebGL2Available, pickAvailableBackend } from "./webgpu-detect.js";
|
|
13
|
-
export { LARGE_SCENE_WORKER_THRESHOLD } from "./constants.js";
|
|
13
|
+
export { LARGE_SCENE_WORKER_THRESHOLD, MAX_DEVICE_PIXEL_RATIO } from "./constants.js";
|
|
14
14
|
export { installBuiltinRenderers, wrapText } from "@oh-just-another/renderer-core";
|
|
15
15
|
export type { WrapOptions, WrappedLine } from "@oh-just-another/renderer-core";
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EACL,oBAAoB,EACpB,gCAAgC,EAChC,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,2BAA2B,GACjC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEtF,OAAO,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { Canvas2DTarget } from "./canvas-target.js";
|
|
|
2
2
|
export { Canvas2DTextShaper } from "./canvas-text-shaper.js";
|
|
3
3
|
export { WebGL2Target } from "./webgl2-target.js";
|
|
4
4
|
export { renderViaTiles } from "./tile-compositor.js";
|
|
5
|
-
export { setupHiDpi } from "./hi-dpi.js";
|
|
5
|
+
export { setupHiDpi, cappedDpr } from "./hi-dpi.js";
|
|
6
6
|
export { LayeredCanvas } from "./layered-canvas.js";
|
|
7
7
|
export { supportsOffscreenCanvas, createOffscreenCanvas2DTarget, transferCanvasToWorker, } from "./offscreen.js";
|
|
8
8
|
export { createRenderWorker } from "./worker-factory.js";
|
|
@@ -10,7 +10,7 @@ export { WorkerPool, LayerWorkerPool } from "@oh-just-another/renderer-workers";
|
|
|
10
10
|
export { RecordingTarget, replayCommands } from "./recording-target.js";
|
|
11
11
|
export { createLayeredSurface, createLayeredSurfaceWithFallback, } from "./layered-surface.js";
|
|
12
12
|
export { isWebGPUAvailable, isWebGL2Available, pickAvailableBackend } from "./webgpu-detect.js";
|
|
13
|
-
export { LARGE_SCENE_WORKER_THRESHOLD } from "./constants.js";
|
|
13
|
+
export { LARGE_SCENE_WORKER_THRESHOLD, MAX_DEVICE_PIXEL_RATIO } from "./constants.js";
|
|
14
14
|
export { installBuiltinRenderers, wrapText } from "@oh-just-another/renderer-core";
|
|
15
15
|
// `installBuiltinRenderers()` must be called once before built-in shapes
|
|
16
16
|
// can be drawn. It is not auto-invoked so this package stays
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAsB,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EACL,oBAAoB,EACpB,gCAAgC,GAIjC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEtF,OAAO,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAGnF,yEAAyE;AACzE,6DAA6D;AAC7D,sEAAsE;AACtE,oBAAoB"}
|
package/dist/layered-canvas.d.ts
CHANGED
|
@@ -3,8 +3,13 @@ import { Canvas2DTarget } from "./canvas-target.js";
|
|
|
3
3
|
export interface LayeredCanvasOptions {
|
|
4
4
|
/** Subset of layers to create. Defaults to all three. */
|
|
5
5
|
readonly layers?: readonly LayerName[];
|
|
6
|
-
/** Override `window.devicePixelRatio`. */
|
|
6
|
+
/** Override `window.devicePixelRatio`. Takes precedence over `maxDpr`. */
|
|
7
7
|
readonly dpr?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Cap applied to the live `window.devicePixelRatio` on create and every
|
|
10
|
+
* resize. Defaults to `MAX_DEVICE_PIXEL_RATIO`. Ignored when `dpr` is set.
|
|
11
|
+
*/
|
|
12
|
+
readonly maxDpr?: number;
|
|
8
13
|
}
|
|
9
14
|
/**
|
|
10
15
|
* Manages one stacked `<canvas>` per layer. The background canvas sits at the
|
|
@@ -22,6 +27,7 @@ export declare class LayeredCanvas {
|
|
|
22
27
|
private width;
|
|
23
28
|
private height;
|
|
24
29
|
private dprOverride;
|
|
30
|
+
private readonly maxDpr;
|
|
25
31
|
constructor(host: HTMLElement, width: number, height: number, options?: LayeredCanvasOptions);
|
|
26
32
|
/** Get the target for a layer. Throws if the layer was not created. */
|
|
27
33
|
get(name: LayerName): Canvas2DTarget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layered-canvas.d.ts","sourceRoot":"","sources":["../src/layered-canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"layered-canvas.d.ts","sourceRoot":"","sources":["../src/layered-canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IACrE,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAG9B,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB;IAmCpC,uEAAuE;IACvE,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc;IAMpC,yDAAyD;IACzD,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,iBAAiB;IAM7C;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAY3C,IAAI,IAAI,IAAI;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAE9D;IAED,8EAA8E;IAC9E,OAAO,IAAI,IAAI;CAKhB"}
|
package/dist/layered-canvas.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LAYER_ORDER } from "@oh-just-another/renderer-core";
|
|
2
2
|
import { Canvas2DTarget } from "./canvas-target.js";
|
|
3
|
-
import { setupHiDpi } from "./hi-dpi.js";
|
|
3
|
+
import { cappedDpr, setupHiDpi } from "./hi-dpi.js";
|
|
4
|
+
import { MAX_DEVICE_PIXEL_RATIO } from "./constants.js";
|
|
4
5
|
/**
|
|
5
6
|
* Manages one stacked `<canvas>` per layer. The background canvas sits at the
|
|
6
7
|
* bottom of the DOM stack and the overlay at the top, so drawing onto `main`
|
|
@@ -17,11 +18,13 @@ export class LayeredCanvas {
|
|
|
17
18
|
width;
|
|
18
19
|
height;
|
|
19
20
|
dprOverride;
|
|
21
|
+
maxDpr;
|
|
20
22
|
constructor(host, width, height, options = {}) {
|
|
21
23
|
this.host = host;
|
|
22
24
|
this.width = width;
|
|
23
25
|
this.height = height;
|
|
24
26
|
this.dprOverride = options.dpr;
|
|
27
|
+
this.maxDpr = options.maxDpr ?? MAX_DEVICE_PIXEL_RATIO;
|
|
25
28
|
if (getComputedStyle(host).position === "static") {
|
|
26
29
|
host.style.position = "relative";
|
|
27
30
|
}
|
|
@@ -37,7 +40,7 @@ export class LayeredCanvas {
|
|
|
37
40
|
canvas.style.inset = "0";
|
|
38
41
|
canvas.style.pointerEvents = name === "overlay" ? "auto" : "none";
|
|
39
42
|
host.appendChild(canvas);
|
|
40
|
-
const dpr = setupHiDpi(canvas, width, height, this.dprOverride);
|
|
43
|
+
const dpr = setupHiDpi(canvas, width, height, this.dprOverride ?? cappedDpr(this.maxDpr));
|
|
41
44
|
const ctx = canvas.getContext("2d");
|
|
42
45
|
if (!ctx)
|
|
43
46
|
throw new Error("Failed to obtain 2D context");
|
|
@@ -75,7 +78,7 @@ export class LayeredCanvas {
|
|
|
75
78
|
this.width = width;
|
|
76
79
|
this.height = height;
|
|
77
80
|
for (const [name, canvas] of this.canvases) {
|
|
78
|
-
const dpr = setupHiDpi(canvas, width, height, this.dprOverride);
|
|
81
|
+
const dpr = setupHiDpi(canvas, width, height, this.dprOverride ?? cappedDpr(this.maxDpr));
|
|
79
82
|
const layer = this.layers.get(name);
|
|
80
83
|
if (layer === undefined)
|
|
81
84
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layered-canvas.js","sourceRoot":"","sources":["../src/layered-canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"layered-canvas.js","sourceRoot":"","sources":["../src/layered-canvas.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,6 +54,22 @@ export interface CreateLayeredSurfaceOptions {
|
|
|
54
54
|
* always-safe `canvas2d` backend. Only the offscreen backend calls it.
|
|
55
55
|
*/
|
|
56
56
|
readonly onWorkerError?: (error: unknown) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Cap applied to `window.devicePixelRatio` when sizing layer bitmaps.
|
|
59
|
+
* Defaults to `MAX_DEVICE_PIXEL_RATIO` (2). Raise it for hosts that
|
|
60
|
+
* need native sharpness on DPR-3+ displays at the cost of 2–4× the
|
|
61
|
+
* raster work per layer.
|
|
62
|
+
*/
|
|
63
|
+
readonly maxDpr?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Forwarded to the `webgl2` backend's main-layer context. Defaults to
|
|
66
|
+
* `true`, which the incremental dirty-rect renderer requires (the rest
|
|
67
|
+
* of the previous frame must survive between composites). Set `false`
|
|
68
|
+
* only when the host redraws the whole frame every time — it removes a
|
|
69
|
+
* Safari/iOS full-recomposite-per-swap cost. Ignored by the `canvas2d`
|
|
70
|
+
* and `offscreen` backends. Does not affect PNG export / screenshots.
|
|
71
|
+
*/
|
|
72
|
+
readonly preserveDrawingBuffer?: boolean;
|
|
57
73
|
}
|
|
58
74
|
/**
|
|
59
75
|
* Factory entry point. Picks the right backend implementation, builds
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layered-surface.d.ts","sourceRoot":"","sources":["../src/layered-surface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"layered-surface.d.ts","sourceRoot":"","sources":["../src/layered-surface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAQhG;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,CAAC;IACnC,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,iBAAiB,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAAC;IAChB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IACnC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IACtC;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,WAAW,EACjB,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,UAAS,2BAAgC,KACxC,cA2BF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gCAAgC,GAC3C,MAAM,WAAW,EACjB,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,UAAS,2BAAgC,EACzC,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,KAC9D;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,gBAAgB,EAAE,eAAe,CAAA;CAe9D,CAAC"}
|
package/dist/layered-surface.js
CHANGED
|
@@ -2,7 +2,9 @@ import { LAYER_ORDER } from "@oh-just-another/renderer-core";
|
|
|
2
2
|
import { LayeredCanvas } from "./layered-canvas.js";
|
|
3
3
|
import { WebGL2Target } from "./webgl2-target.js";
|
|
4
4
|
import { RecordingTarget } from "./recording-target.js";
|
|
5
|
-
import {
|
|
5
|
+
import { packReplayFrame } from "./replay-codec.js";
|
|
6
|
+
import { cappedDpr, setupHiDpi } from "./hi-dpi.js";
|
|
7
|
+
import { MAX_DEVICE_PIXEL_RATIO } from "./constants.js";
|
|
6
8
|
/**
|
|
7
9
|
* Factory entry point. Picks the right backend implementation, builds
|
|
8
10
|
* it, and returns the common `LayeredSurface` interface. Canvas2D is
|
|
@@ -15,16 +17,21 @@ import { setupHiDpi } from "./hi-dpi.js";
|
|
|
15
17
|
*/
|
|
16
18
|
export const createLayeredSurface = (host, width, height, options = {}) => {
|
|
17
19
|
const backend = options.backend ?? "canvas2d";
|
|
20
|
+
const maxDpr = options.maxDpr ?? MAX_DEVICE_PIXEL_RATIO;
|
|
18
21
|
switch (backend) {
|
|
19
22
|
case "canvas2d":
|
|
20
|
-
return new Canvas2DLayeredSurface(host, width, height);
|
|
23
|
+
return new Canvas2DLayeredSurface(host, width, height, maxDpr);
|
|
21
24
|
case "webgl2":
|
|
22
|
-
return new WebGL2LayeredSurface(host, width, height
|
|
25
|
+
return new WebGL2LayeredSurface(host, width, height, maxDpr, {
|
|
26
|
+
...(options.preserveDrawingBuffer !== undefined
|
|
27
|
+
? { preserveDrawingBuffer: options.preserveDrawingBuffer }
|
|
28
|
+
: {}),
|
|
29
|
+
});
|
|
23
30
|
case "offscreen":
|
|
24
31
|
if (!options.workerFactory) {
|
|
25
32
|
throw new Error("createLayeredSurface: workerFactory is required for the offscreen backend");
|
|
26
33
|
}
|
|
27
|
-
return new OffscreenLayeredSurface(host, width, height, options.workerFactory, options.onWorkerError);
|
|
34
|
+
return new OffscreenLayeredSurface(host, width, height, options.workerFactory, options.onWorkerError, maxDpr);
|
|
28
35
|
}
|
|
29
36
|
};
|
|
30
37
|
/**
|
|
@@ -60,8 +67,8 @@ export const createLayeredSurfaceWithFallback = (host, width, height, options =
|
|
|
60
67
|
class Canvas2DLayeredSurface {
|
|
61
68
|
backend = "canvas2d";
|
|
62
69
|
inner;
|
|
63
|
-
constructor(host, width, height) {
|
|
64
|
-
this.inner = new LayeredCanvas(host, width, height);
|
|
70
|
+
constructor(host, width, height, maxDpr) {
|
|
71
|
+
this.inner = new LayeredCanvas(host, width, height, { maxDpr });
|
|
65
72
|
}
|
|
66
73
|
get(name) {
|
|
67
74
|
return this.inner.get(name);
|
|
@@ -102,13 +109,16 @@ class WebGL2LayeredSurface {
|
|
|
102
109
|
mainTarget;
|
|
103
110
|
_width;
|
|
104
111
|
_height;
|
|
105
|
-
|
|
112
|
+
maxDpr;
|
|
113
|
+
constructor(host, width, height, maxDpr, options = {}) {
|
|
106
114
|
this._width = width;
|
|
107
115
|
this._height = height;
|
|
116
|
+
this.maxDpr = maxDpr;
|
|
108
117
|
// Build the Canvas2D layers first; the WebGL2 main canvas is
|
|
109
118
|
// spliced into the same stack between background and overlay.
|
|
110
119
|
this.base = new LayeredCanvas(host, width, height, {
|
|
111
120
|
layers: LAYER_ORDER.filter((name) => name !== "main"),
|
|
121
|
+
maxDpr,
|
|
112
122
|
});
|
|
113
123
|
const overlay = this.base.getCanvas("overlay");
|
|
114
124
|
const canvas = host.ownerDocument.createElement("canvas");
|
|
@@ -123,10 +133,14 @@ class WebGL2LayeredSurface {
|
|
|
123
133
|
// exclusive — one canvas, one context kind, for the life of the
|
|
124
134
|
// element. `setupContext: false` sizes the bitmap without touching
|
|
125
135
|
// the context.
|
|
126
|
-
setupHiDpi(canvas, width, height,
|
|
136
|
+
setupHiDpi(canvas, width, height, cappedDpr(maxDpr), false);
|
|
127
137
|
try {
|
|
128
138
|
this.mainCanvas = canvas;
|
|
129
|
-
this.mainTarget = new WebGL2Target(canvas, width, height
|
|
139
|
+
this.mainTarget = new WebGL2Target(canvas, width, height, {
|
|
140
|
+
...(options.preserveDrawingBuffer !== undefined
|
|
141
|
+
? { preserveDrawingBuffer: options.preserveDrawingBuffer }
|
|
142
|
+
: {}),
|
|
143
|
+
});
|
|
130
144
|
}
|
|
131
145
|
catch (err) {
|
|
132
146
|
canvas.remove();
|
|
@@ -150,14 +164,17 @@ class WebGL2LayeredSurface {
|
|
|
150
164
|
this._width = width;
|
|
151
165
|
this._height = height;
|
|
152
166
|
this.base.resize(width, height);
|
|
153
|
-
setupHiDpi(this.mainCanvas, width, height,
|
|
167
|
+
setupHiDpi(this.mainCanvas, width, height, cappedDpr(this.maxDpr), false);
|
|
154
168
|
this.mainTarget.resize(width, height);
|
|
155
169
|
}
|
|
156
170
|
get size() {
|
|
157
171
|
return { width: this._width, height: this._height };
|
|
158
172
|
}
|
|
159
173
|
present() {
|
|
160
|
-
// Canvas2D
|
|
174
|
+
// Canvas2D paints synchronously; the WebGL2 main layer defers
|
|
175
|
+
// same-style sharp-rect fills into an instanced batch, so drain it
|
|
176
|
+
// here so trailing rects reach the framebuffer within this frame.
|
|
177
|
+
this.mainTarget.flushBatch();
|
|
161
178
|
}
|
|
162
179
|
dispose() {
|
|
163
180
|
this.mainTarget.dispose();
|
|
@@ -184,13 +201,21 @@ class OffscreenLayeredSurface {
|
|
|
184
201
|
canvases = new Map();
|
|
185
202
|
targets = new Map();
|
|
186
203
|
workers = new Map();
|
|
204
|
+
/**
|
|
205
|
+
* Content signature of the command stream last posted to each layer's
|
|
206
|
+
* worker. A frame whose flushed buffer matches its layer's entry replays
|
|
207
|
+
* to the same pixels the worker already shows, so `present()` skips the
|
|
208
|
+
* postMessage (clone) + replay entirely — e.g. a static grid / overlay
|
|
209
|
+
* while only the main layer's GIF advances.
|
|
210
|
+
*/
|
|
211
|
+
lastSentSig = new Map();
|
|
187
212
|
_width;
|
|
188
213
|
_height;
|
|
189
214
|
dpr;
|
|
190
|
-
constructor(host, width, height, workerFactory, onWorkerError) {
|
|
215
|
+
constructor(host, width, height, workerFactory, onWorkerError, maxDpr = MAX_DEVICE_PIXEL_RATIO) {
|
|
191
216
|
this._width = width;
|
|
192
217
|
this._height = height;
|
|
193
|
-
this.dpr =
|
|
218
|
+
this.dpr = cappedDpr(maxDpr);
|
|
194
219
|
if (getComputedStyle(host).position === "static") {
|
|
195
220
|
host.style.position = "relative";
|
|
196
221
|
}
|
|
@@ -258,6 +283,10 @@ class OffscreenLayeredSurface {
|
|
|
258
283
|
this.targets.get(name)?.resize(width, height);
|
|
259
284
|
this.workers.get(name)?.postMessage({ type: "resize", width, height });
|
|
260
285
|
}
|
|
286
|
+
// A resize clears each worker's OffscreenCanvas (its bitmap is re-sized),
|
|
287
|
+
// so the next frame must repost even if its content signature is
|
|
288
|
+
// unchanged — drop the cached signatures to force it.
|
|
289
|
+
this.lastSentSig.clear();
|
|
261
290
|
}
|
|
262
291
|
get size() {
|
|
263
292
|
return { width: this._width, height: this._height };
|
|
@@ -267,7 +296,23 @@ class OffscreenLayeredSurface {
|
|
|
267
296
|
const cmds = target.flush();
|
|
268
297
|
if (cmds.length === 0)
|
|
269
298
|
continue;
|
|
270
|
-
|
|
299
|
+
// Skip layers whose command stream is identical to the one already
|
|
300
|
+
// shipped: the worker retains its last frame between replays, so not
|
|
301
|
+
// reposting leaves the correct pixels in place and saves the pack +
|
|
302
|
+
// post + worker redraw. `defineImage` (first bitmap ship) and `resize` change
|
|
303
|
+
// the stream, so image / size updates never get skipped.
|
|
304
|
+
const sig = target.lastSignature;
|
|
305
|
+
if (this.lastSentSig.get(name) === sig)
|
|
306
|
+
continue;
|
|
307
|
+
this.lastSentSig.set(name, sig);
|
|
308
|
+
// Pack into a transferable frame: the numeric buffer moves for free
|
|
309
|
+
// (transfer list), the deduplicated string table is a cheap clone.
|
|
310
|
+
// Side bitmaps are deliberately NOT in the transfer list — the
|
|
311
|
+
// recorder's intern LRU still owns the sources, so postMessage must
|
|
312
|
+
// clone them, not detach them.
|
|
313
|
+
const { buffer, strings, bitmaps } = packReplayFrame(cmds);
|
|
314
|
+
const msg = { type: "replay", buffer, strings, bitmaps };
|
|
315
|
+
this.workers.get(name)?.postMessage(msg, [buffer]);
|
|
271
316
|
}
|
|
272
317
|
}
|
|
273
318
|
dispose() {
|