@canvas-harness/core 0.1.3 → 0.1.4
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/index.cjs +23 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2097,7 +2097,13 @@ type CanvasSurface = {
|
|
|
2097
2097
|
/** Device pixels — backing-store size. */
|
|
2098
2098
|
dpr: number;
|
|
2099
2099
|
};
|
|
2100
|
-
|
|
2100
|
+
/**
|
|
2101
|
+
* Resolved DPR for the canvas backing store. Clamped by `maxDpr`
|
|
2102
|
+
* (consumer-supplied) and the absolute `HARD_MAX_DPR` ceiling. When
|
|
2103
|
+
* `maxDpr` is omitted, the tier-based default (see
|
|
2104
|
+
* `defaultMaxDprForSize`) is used — pass `cssW`/`cssH` to enable it.
|
|
2105
|
+
*/
|
|
2106
|
+
declare const getDpr: (maxDpr?: number, cssW?: number, cssH?: number) => number;
|
|
2101
2107
|
/**
|
|
2102
2108
|
* Builds a managed canvas surface. Caller pins the canvas element; we size
|
|
2103
2109
|
* it and reset the 2d context's transform to logical-pixel space.
|
|
@@ -2105,12 +2111,12 @@ declare const getDpr: () => number;
|
|
|
2105
2111
|
* Subsequent calls to `setSize` re-allocate the backing store if the new
|
|
2106
2112
|
* `cssW × cssH × DPR` differs from the current.
|
|
2107
2113
|
*/
|
|
2108
|
-
declare const setupSurface: (canvas: HTMLCanvasElement) => CanvasSurface;
|
|
2114
|
+
declare const setupSurface: (canvas: HTMLCanvasElement, _maxDpr?: number) => CanvasSurface;
|
|
2109
2115
|
/**
|
|
2110
2116
|
* Resizes the surface to a new CSS-pixel size, picking up the current DPR.
|
|
2111
2117
|
* Returns true if anything changed (caller should redraw).
|
|
2112
2118
|
*/
|
|
2113
|
-
declare const sizeSurface: (surface: CanvasSurface, cssW: number, cssH: number) => boolean;
|
|
2119
|
+
declare const sizeSurface: (surface: CanvasSurface, cssW: number, cssH: number, maxDpr?: number) => boolean;
|
|
2114
2120
|
/**
|
|
2115
2121
|
* Clears the entire backing store. Call before setting the camera transform.
|
|
2116
2122
|
*/
|
|
@@ -2202,6 +2208,18 @@ type RendererOptions = {
|
|
|
2202
2208
|
* fill tints via globalAlpha — no parsing needed.
|
|
2203
2209
|
*/
|
|
2204
2210
|
selectionColor?: string;
|
|
2211
|
+
/**
|
|
2212
|
+
* Cap on the canvas backing-store DPR (device-pixel ratio). At
|
|
2213
|
+
* native DPR on hi-DPI displays, the backing buffer can hit
|
|
2214
|
+
* 20-30 megapixels per frame; the GPU-upload step alone dominates
|
|
2215
|
+
* the frame budget. Defaults to `1` for consistent perf across
|
|
2216
|
+
* hardware. Bump to `2` (or `window.devicePixelRatio`) for
|
|
2217
|
+
* pixel-crisp rendering at the cost of FPS on hi-DPI displays.
|
|
2218
|
+
*
|
|
2219
|
+
* Text is unaffected — the text bitmap cache renders glyphs at
|
|
2220
|
+
* its own DPR-aware scale.
|
|
2221
|
+
*/
|
|
2222
|
+
maxDpr?: number;
|
|
2205
2223
|
/**
|
|
2206
2224
|
* Fires when the set of custom nodes that should be rendered in the DOM
|
|
2207
2225
|
* overlay changes. Consumers use this to mount/unmount React subtrees
|
package/dist/index.d.ts
CHANGED
|
@@ -2097,7 +2097,13 @@ type CanvasSurface = {
|
|
|
2097
2097
|
/** Device pixels — backing-store size. */
|
|
2098
2098
|
dpr: number;
|
|
2099
2099
|
};
|
|
2100
|
-
|
|
2100
|
+
/**
|
|
2101
|
+
* Resolved DPR for the canvas backing store. Clamped by `maxDpr`
|
|
2102
|
+
* (consumer-supplied) and the absolute `HARD_MAX_DPR` ceiling. When
|
|
2103
|
+
* `maxDpr` is omitted, the tier-based default (see
|
|
2104
|
+
* `defaultMaxDprForSize`) is used — pass `cssW`/`cssH` to enable it.
|
|
2105
|
+
*/
|
|
2106
|
+
declare const getDpr: (maxDpr?: number, cssW?: number, cssH?: number) => number;
|
|
2101
2107
|
/**
|
|
2102
2108
|
* Builds a managed canvas surface. Caller pins the canvas element; we size
|
|
2103
2109
|
* it and reset the 2d context's transform to logical-pixel space.
|
|
@@ -2105,12 +2111,12 @@ declare const getDpr: () => number;
|
|
|
2105
2111
|
* Subsequent calls to `setSize` re-allocate the backing store if the new
|
|
2106
2112
|
* `cssW × cssH × DPR` differs from the current.
|
|
2107
2113
|
*/
|
|
2108
|
-
declare const setupSurface: (canvas: HTMLCanvasElement) => CanvasSurface;
|
|
2114
|
+
declare const setupSurface: (canvas: HTMLCanvasElement, _maxDpr?: number) => CanvasSurface;
|
|
2109
2115
|
/**
|
|
2110
2116
|
* Resizes the surface to a new CSS-pixel size, picking up the current DPR.
|
|
2111
2117
|
* Returns true if anything changed (caller should redraw).
|
|
2112
2118
|
*/
|
|
2113
|
-
declare const sizeSurface: (surface: CanvasSurface, cssW: number, cssH: number) => boolean;
|
|
2119
|
+
declare const sizeSurface: (surface: CanvasSurface, cssW: number, cssH: number, maxDpr?: number) => boolean;
|
|
2114
2120
|
/**
|
|
2115
2121
|
* Clears the entire backing store. Call before setting the camera transform.
|
|
2116
2122
|
*/
|
|
@@ -2202,6 +2208,18 @@ type RendererOptions = {
|
|
|
2202
2208
|
* fill tints via globalAlpha — no parsing needed.
|
|
2203
2209
|
*/
|
|
2204
2210
|
selectionColor?: string;
|
|
2211
|
+
/**
|
|
2212
|
+
* Cap on the canvas backing-store DPR (device-pixel ratio). At
|
|
2213
|
+
* native DPR on hi-DPI displays, the backing buffer can hit
|
|
2214
|
+
* 20-30 megapixels per frame; the GPU-upload step alone dominates
|
|
2215
|
+
* the frame budget. Defaults to `1` for consistent perf across
|
|
2216
|
+
* hardware. Bump to `2` (or `window.devicePixelRatio`) for
|
|
2217
|
+
* pixel-crisp rendering at the cost of FPS on hi-DPI displays.
|
|
2218
|
+
*
|
|
2219
|
+
* Text is unaffected — the text bitmap cache renders glyphs at
|
|
2220
|
+
* its own DPR-aware scale.
|
|
2221
|
+
*/
|
|
2222
|
+
maxDpr?: number;
|
|
2205
2223
|
/**
|
|
2206
2224
|
* Fires when the set of custom nodes that should be rendered in the DOM
|
|
2207
2225
|
* overlay changes. Consumers use this to mount/unmount React subtrees
|
package/dist/index.js
CHANGED
|
@@ -855,23 +855,12 @@ var darkenHex = (hex) => {
|
|
|
855
855
|
|
|
856
856
|
// src/render/shapes/path-helpers.ts
|
|
857
857
|
var buildRectPath = (ctx, w, h, radius) => {
|
|
858
|
+
ctx.beginPath();
|
|
858
859
|
if (radius <= 0) {
|
|
859
|
-
ctx.beginPath();
|
|
860
860
|
ctx.rect(0, 0, w, h);
|
|
861
861
|
return;
|
|
862
862
|
}
|
|
863
|
-
|
|
864
|
-
ctx.beginPath();
|
|
865
|
-
ctx.moveTo(r, 0);
|
|
866
|
-
ctx.lineTo(w - r, 0);
|
|
867
|
-
ctx.quadraticCurveTo(w, 0, w, r);
|
|
868
|
-
ctx.lineTo(w, h - r);
|
|
869
|
-
ctx.quadraticCurveTo(w, h, w - r, h);
|
|
870
|
-
ctx.lineTo(r, h);
|
|
871
|
-
ctx.quadraticCurveTo(0, h, 0, h - r);
|
|
872
|
-
ctx.lineTo(0, r);
|
|
873
|
-
ctx.quadraticCurveTo(0, 0, r, 0);
|
|
874
|
-
ctx.closePath();
|
|
863
|
+
ctx.roundRect(0, 0, w, h, radius);
|
|
875
864
|
};
|
|
876
865
|
var buildEllipsePath = (ctx, w, h) => {
|
|
877
866
|
const rx = w / 2;
|
|
@@ -4253,13 +4242,21 @@ var storeToJSON = (store) => ({
|
|
|
4253
4242
|
});
|
|
4254
4243
|
|
|
4255
4244
|
// src/render/canvas-setup.ts
|
|
4256
|
-
var
|
|
4257
|
-
var
|
|
4245
|
+
var HARD_MAX_DPR = 3;
|
|
4246
|
+
var defaultMaxDprForSize = (cssW, cssH) => {
|
|
4247
|
+
const cssPx = cssW * cssH;
|
|
4248
|
+
if (cssPx >= 25e5) return 1;
|
|
4249
|
+
if (cssPx >= 15e5) return 1.5;
|
|
4250
|
+
return 2;
|
|
4251
|
+
};
|
|
4252
|
+
var getDpr = (maxDpr, cssW = 0, cssH = 0) => {
|
|
4258
4253
|
if (typeof window === "undefined") return 1;
|
|
4259
4254
|
const raw = window.devicePixelRatio || 1;
|
|
4260
|
-
|
|
4255
|
+
const resolvedMax = maxDpr === void 0 && cssW > 0 && cssH > 0 ? defaultMaxDprForSize(cssW, cssH) : maxDpr ?? 1;
|
|
4256
|
+
const cap = Math.max(1, Math.min(HARD_MAX_DPR, resolvedMax));
|
|
4257
|
+
return Math.max(1, Math.min(cap, raw));
|
|
4261
4258
|
};
|
|
4262
|
-
var setupSurface = (canvas) => {
|
|
4259
|
+
var setupSurface = (canvas, _maxDpr) => {
|
|
4263
4260
|
const ctx = canvas.getContext("2d");
|
|
4264
4261
|
if (!ctx) throw new Error("Canvas 2d context unavailable");
|
|
4265
4262
|
return {
|
|
@@ -4267,11 +4264,12 @@ var setupSurface = (canvas) => {
|
|
|
4267
4264
|
ctx,
|
|
4268
4265
|
cssWidth: 0,
|
|
4269
4266
|
cssHeight: 0,
|
|
4270
|
-
dpr:
|
|
4267
|
+
dpr: 1
|
|
4268
|
+
// placeholder; `sizeSurface` writes the real value
|
|
4271
4269
|
};
|
|
4272
4270
|
};
|
|
4273
|
-
var sizeSurface = (surface, cssW, cssH) => {
|
|
4274
|
-
const dpr = getDpr();
|
|
4271
|
+
var sizeSurface = (surface, cssW, cssH, maxDpr) => {
|
|
4272
|
+
const dpr = getDpr(maxDpr, cssW, cssH);
|
|
4275
4273
|
if (surface.cssWidth === cssW && surface.cssHeight === cssH && surface.dpr === dpr) {
|
|
4276
4274
|
return false;
|
|
4277
4275
|
}
|
|
@@ -4891,13 +4889,14 @@ var MIN_ON_SCREEN_SIZE_PX = 1.5;
|
|
|
4891
4889
|
var MIN_READABLE_FONT_PX = 3;
|
|
4892
4890
|
var createRenderer = (opts) => {
|
|
4893
4891
|
const { store, theme, onOverlayChange } = opts;
|
|
4892
|
+
const maxDpr = opts.maxDpr;
|
|
4894
4893
|
const staticSurface = setupSurface(opts.staticCanvas);
|
|
4895
4894
|
const interactiveSurface = setupSurface(opts.interactiveCanvas);
|
|
4896
4895
|
let background = opts.background;
|
|
4897
4896
|
let selectionColor = opts.selectionColor ?? DEFAULT_SELECTION_COLOR;
|
|
4898
4897
|
let hideFrames = false;
|
|
4899
|
-
sizeSurface(staticSurface, opts.width, opts.height);
|
|
4900
|
-
sizeSurface(interactiveSurface, opts.width, opts.height);
|
|
4898
|
+
sizeSurface(staticSurface, opts.width, opts.height, maxDpr);
|
|
4899
|
+
sizeSurface(interactiveSurface, opts.width, opts.height, maxDpr);
|
|
4901
4900
|
let staticDirty = true;
|
|
4902
4901
|
let interactiveDirty = false;
|
|
4903
4902
|
let overlaySet = /* @__PURE__ */ new Set();
|
|
@@ -5388,8 +5387,8 @@ var createRenderer = (opts) => {
|
|
|
5388
5387
|
loop.requestFrame();
|
|
5389
5388
|
},
|
|
5390
5389
|
setSize(cssW, cssH) {
|
|
5391
|
-
const a = sizeSurface(staticSurface, cssW, cssH);
|
|
5392
|
-
const b = sizeSurface(interactiveSurface, cssW, cssH);
|
|
5390
|
+
const a = sizeSurface(staticSurface, cssW, cssH, maxDpr);
|
|
5391
|
+
const b = sizeSurface(interactiveSurface, cssW, cssH, maxDpr);
|
|
5393
5392
|
if (a || b) {
|
|
5394
5393
|
staticDirty = true;
|
|
5395
5394
|
interactiveDirty = true;
|