@vectojs/core 1.28.1 → 1.30.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.
@@ -88,6 +88,12 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
88
88
  * change at runtime (e.g. a window dragged between displays).
89
89
  */
90
90
 
91
+ /**
92
+ * The ratio the context is actually scaled by, i.e. the last value the
93
+ * constructor or {@link resize} applied. Backs {@link pixelRatio}; see there
94
+ * for why this is recorded rather than recomputed on read.
95
+ */
96
+ __init3() {this.appliedDPR = 1}
91
97
  /**
92
98
  * Max circles per batched `fill()`. A single Canvas 2D `fill()` over a path is
93
99
  * superlinear in sub-path count, so an unbounded batch is *slower* than many
@@ -97,23 +103,23 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
97
103
  static __initStatic() {this.MAX_BATCH = 64}
98
104
  // Order-preserving batch state for fillCircle(): a run of same-style circles
99
105
  // accumulates into one path and is committed by a single fill() on flush().
100
- __init3() {this.batchActive = false}
101
- __init4() {this.batchColor = ""}
102
- __init5() {this.batchAlpha = 1}
103
- __init6() {this.batchCount = 0}
104
- __init7() {this._cachedFont = ""}
105
- __init8() {this._cachedFill = ""}
106
+ __init4() {this.batchActive = false}
107
+ __init5() {this.batchColor = ""}
108
+ __init6() {this.batchAlpha = 1}
109
+ __init7() {this.batchCount = 0}
110
+ __init8() {this._cachedFont = ""}
111
+ __init9() {this._cachedFill = ""}
106
112
  /** Backend discriminator; see {@link IRenderer.kind}. */
107
- __init9() {this.kind = "canvas2d"}
113
+ __init10() {this.kind = "canvas2d"}
108
114
  /**
109
115
  * Draw counters, allocated only once counting is enabled.
110
116
  *
111
117
  * Null when off, so the guard on every op is a single null test and an inactive
112
118
  * renderer carries no counter object at all.
113
119
  */
114
- __init10() {this.counters = null}
120
+ __init11() {this.counters = null}
115
121
  /** Accumulated primitive area, kept separately so the ratio is derived on read. */
116
- __init11() {this.drawnArea = 0}
122
+ __init12() {this.drawnArea = 0}
117
123
  /**
118
124
  * @param canvas - The target canvas. Its backing store is resized to the
119
125
  * logical size × devicePixelRatio.
@@ -123,9 +129,10 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
123
129
  * set) so the canvas's own dimensions aren't clobbered by the window's.
124
130
  * @param maxDPR - See {@link maxDPR}.
125
131
  */
126
- constructor(canvas, size, maxDPR) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);
132
+ constructor(canvas, size, maxDPR) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);
127
133
  this.maxDPR = maxDPR;
128
134
  const dpr = this.effectiveDPR();
135
+ this.appliedDPR = dpr;
129
136
  this.width = _nullishCoalesce(_optionalChain([size, 'optionalAccess', _5 => _5.width]), () => ( (typeof window !== "undefined" ? window.innerWidth : canvas.width || 0)));
130
137
  this.height = _nullishCoalesce(_optionalChain([size, 'optionalAccess', _6 => _6.height]), () => ( (typeof window !== "undefined" ? window.innerHeight : canvas.height || 0)));
131
138
  canvas.width = this.width * dpr;
@@ -164,7 +171,9 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
164
171
  if (!ctx) return;
165
172
  this.ctx = ctx;
166
173
  ctx.setTransform(1, 0, 0, 1, 0, 0);
167
- ctx.scale(this.effectiveDPR(), this.effectiveDPR());
174
+ const restoredDPR = this.effectiveDPR();
175
+ this.appliedDPR = restoredDPR;
176
+ ctx.scale(restoredDPR, restoredDPR);
168
177
  this._cachedFont = "";
169
178
  this._cachedFill = "";
170
179
  this.batchActive = false;
@@ -187,6 +196,25 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
187
196
  const real = getDevicePixelRatio();
188
197
  return this.maxDPR !== void 0 ? Math.min(real, this.maxDPR) : real;
189
198
  }
199
+ /**
200
+ * @inheritdoc
201
+ *
202
+ * The ratio the context is **currently scaled by**, recorded by the constructor
203
+ * and {@link resize} — deliberately not a live `effectiveDPR()` call.
204
+ *
205
+ * The distinction is load-bearing rather than pedantic. `devicePixelRatio`
206
+ * changes the instant a zoom lands, but the backing store is only reallocated
207
+ * when something calls {@link resize} (in a `Scene`, the `(resolution: Ndppx)`
208
+ * media query). A live getter therefore reports the *future* ratio during that
209
+ * window, and a caller rasterizing pixels from it produces a texture that the
210
+ * still-old context scale resamples — the same defect this property exists to
211
+ * let callers avoid, merely inverted. Reporting the applied ratio means a
212
+ * cache keyed on it is always consistent with the pixels it is blitted into,
213
+ * and it simply re-keys on the next `resize`.
214
+ */
215
+ get pixelRatio() {
216
+ return this.appliedDPR;
217
+ }
190
218
  /**
191
219
  * Resize the backing canvas buffer and re-apply DPR scaling.
192
220
  *
@@ -197,6 +225,7 @@ var CanvasRenderer = (_class = class _CanvasRenderer {
197
225
  */
198
226
  resize(width, height) {
199
227
  const dpr = this.effectiveDPR();
228
+ this.appliedDPR = dpr;
200
229
  this.width = width;
201
230
  this.height = height;
202
231
  this.ctx.canvas.width = width * dpr;
@@ -501,42 +530,42 @@ function fontFamilyFromShorthand(font, sizeToken) {
501
530
  }
502
531
  var SVGRenderer = (_class2 = class {
503
532
  /** Backend discriminator; see {@link IRenderer.kind}. */
504
- __init12() {this.kind = "svg"}
533
+ __init13() {this.kind = "svg"}
505
534
 
506
535
 
507
- __init13() {this.buffer = []}
508
- __init14() {this.defsBuffer = []}
509
- __init15() {this.currentPath = []}
536
+ __init14() {this.buffer = []}
537
+ __init15() {this.defsBuffer = []}
538
+ __init16() {this.currentPath = []}
510
539
  // Inline matrix states (3x3 representation)
511
540
  // [a, b, c, d, e, f] corresponding to:
512
541
  // | a c e |
513
542
  // | b d f |
514
543
  // | 0 0 1 |
515
- __init16() {this.mStack = []}
516
- __init17() {this.ma = 1}
517
- __init18() {this.mb = 0}
518
- __init19() {this.mc = 0}
519
- __init20() {this.md = 1}
520
- __init21() {this.me = 0}
521
- __init22() {this.mf = 0}
544
+ __init17() {this.mStack = []}
545
+ __init18() {this.ma = 1}
546
+ __init19() {this.mb = 0}
547
+ __init20() {this.mc = 0}
548
+ __init21() {this.md = 1}
549
+ __init22() {this.me = 0}
550
+ __init23() {this.mf = 0}
522
551
  // Alpha stack
523
- __init23() {this.alphaStack = []}
524
- __init24() {this.globalAlpha = 1}
552
+ __init24() {this.alphaStack = []}
553
+ __init25() {this.globalAlpha = 1}
525
554
  // Clipping stack
526
- __init25() {this.clipDepthStack = []}
527
- __init26() {this.clipDepth = 0}
528
- __init27() {this.clipCounter = 0}
555
+ __init26() {this.clipDepthStack = []}
556
+ __init27() {this.clipDepth = 0}
557
+ __init28() {this.clipCounter = 0}
529
558
  // uniquely identifies clipPaths
530
559
  // Batch circles states (local coordinates)
531
- __init28() {this.batchCircles = []}
532
- __init29() {this.batchMatrix = [1, 0, 0, 1, 0, 0]}
533
- __init30() {this.batchColor = ""}
534
- __init31() {this.batchAlpha = 1}
535
- __init32() {this.batchActive = false}
560
+ __init29() {this.batchCircles = []}
561
+ __init30() {this.batchMatrix = [1, 0, 0, 1, 0, 0]}
562
+ __init31() {this.batchColor = ""}
563
+ __init32() {this.batchAlpha = 1}
564
+ __init33() {this.batchActive = false}
536
565
  // Cache for generated gradient defs
537
- __init33() {this.gradientCounter = 0}
538
- __init34() {this.gradientCache = /* @__PURE__ */ new Map()}
539
- constructor(width, height) {;_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);
566
+ __init34() {this.gradientCounter = 0}
567
+ __init35() {this.gradientCache = /* @__PURE__ */ new Map()}
568
+ constructor(width, height) {;_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);_class2.prototype.__init29.call(this);_class2.prototype.__init30.call(this);_class2.prototype.__init31.call(this);_class2.prototype.__init32.call(this);_class2.prototype.__init33.call(this);_class2.prototype.__init34.call(this);_class2.prototype.__init35.call(this);
540
569
  this.width = width;
541
570
  this.height = height;
542
571
  installRendererDevTraps(this, "SVGRenderer");
@@ -1908,11 +1937,11 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
1908
1937
  `;
1909
1938
  var WebGPUParticleSystemManager = (_class3 = class {
1910
1939
 
1911
- __init35() {this.computePipeline = null}
1912
- __init36() {this.renderPipeline = null}
1913
- __init37() {this.computeBindGroupLayout = null}
1914
- __init38() {this.renderBindGroupLayout = null}
1915
- constructor(device) {;_class3.prototype.__init35.call(this);_class3.prototype.__init36.call(this);_class3.prototype.__init37.call(this);_class3.prototype.__init38.call(this);
1940
+ __init36() {this.computePipeline = null}
1941
+ __init37() {this.renderPipeline = null}
1942
+ __init38() {this.computeBindGroupLayout = null}
1943
+ __init39() {this.renderBindGroupLayout = null}
1944
+ constructor(device) {;_class3.prototype.__init36.call(this);_class3.prototype.__init37.call(this);_class3.prototype.__init38.call(this);_class3.prototype.__init39.call(this);
1916
1945
  this.device = device;
1917
1946
  }
1918
1947
  initPipelines(format) {
@@ -2057,26 +2086,40 @@ var WebGPUParticleSystemManager = (_class3 = class {
2057
2086
  var HARD_MAX_SIZE = 8192;
2058
2087
  var PAD = 2;
2059
2088
  var GlyphRasterAtlas = (_class4 = class {
2060
- __init39() {this.slots = /* @__PURE__ */ new Map()}
2089
+ __init40() {this.slots = /* @__PURE__ */ new Map()}
2061
2090
 
2062
2091
 
2063
- __init40() {this.canvas = null}
2064
- __init41() {this.ctx = null}
2092
+ __init41() {this.canvas = null}
2093
+ __init42() {this.ctx = null}
2065
2094
  /**
2066
2095
  * Shelf packing: glyphs land left-to-right on a row, then a new row starts.
2067
2096
  * A monospace grid produces near-uniform widths, so shelves waste very little
2068
2097
  * and cost one comparison per insert — a real 2D packer would buy nothing here.
2069
2098
  */
2070
- __init42() {this.penX = PAD}
2071
- __init43() {this.penY = PAD}
2072
- __init44() {this.rowHeight = 0}
2073
- __init45() {this._hits = 0}
2074
- __init46() {this._misses = 0}
2075
- __init47() {this._resets = 0}
2076
- constructor(options = {}) {;_class4.prototype.__init39.call(this);_class4.prototype.__init40.call(this);_class4.prototype.__init41.call(this);_class4.prototype.__init42.call(this);_class4.prototype.__init43.call(this);_class4.prototype.__init44.call(this);_class4.prototype.__init45.call(this);_class4.prototype.__init46.call(this);_class4.prototype.__init47.call(this);
2099
+ __init43() {this.penX = PAD}
2100
+ __init44() {this.penY = PAD}
2101
+ __init45() {this.rowHeight = 0}
2102
+ __init46() {this._hits = 0}
2103
+ __init47() {this._misses = 0}
2104
+ __init48() {this._resets = 0}
2105
+ constructor(options = {}) {;_class4.prototype.__init40.call(this);_class4.prototype.__init41.call(this);_class4.prototype.__init42.call(this);_class4.prototype.__init43.call(this);_class4.prototype.__init44.call(this);_class4.prototype.__init45.call(this);_class4.prototype.__init46.call(this);_class4.prototype.__init47.call(this);_class4.prototype.__init48.call(this);
2077
2106
  this.dpr = Math.max(1, _nullishCoalesce(options.dpr, () => ( 1)));
2078
2107
  this.maxSize = Math.min(HARD_MAX_SIZE, Math.max(256, _nullishCoalesce(options.maxSize, () => ( 2048))));
2079
2108
  }
2109
+ /**
2110
+ * The device-pixel-ratio these slots were rasterized at.
2111
+ *
2112
+ * Immutable by design. Slot `sx`/`sy`/`sw`/`sh` are device pixels at *this*
2113
+ * ratio while `w`/`h` are CSS pixels, so changing it would invalidate every
2114
+ * resident slot — an atlas is therefore keyed by DPR and replaced on a change,
2115
+ * not mutated (see `Markdown`'s code atlas pool). Exposed so a caller can
2116
+ * compare it against {@link IRenderer.pixelRatio} and assert the blit is
2117
+ * 1:1 rather than resampled: `blitScale = renderer.pixelRatio / atlas.dpr`,
2118
+ * which must be 1 for the pixels to land crisp.
2119
+ */
2120
+ get pixelRatio() {
2121
+ return this.dpr;
2122
+ }
2080
2123
  /** Live instrumentation snapshot. */
2081
2124
  get stats() {
2082
2125
  return {
@@ -2241,13 +2284,13 @@ var GlyphRasterAtlas = (_class4 = class {
2241
2284
 
2242
2285
  // src/renderer/TextRasterCache.ts
2243
2286
  var TextRasterCache = (_class5 = class {
2244
- __init48() {this.cache = /* @__PURE__ */ new Map()}
2287
+ __init49() {this.cache = /* @__PURE__ */ new Map()}
2245
2288
 
2246
2289
 
2247
- __init49() {this.scratchCtx = null}
2248
- __init50() {this._hits = 0}
2249
- __init51() {this._misses = 0}
2250
- constructor(options = {}) {;_class5.prototype.__init48.call(this);_class5.prototype.__init49.call(this);_class5.prototype.__init50.call(this);_class5.prototype.__init51.call(this);
2290
+ __init50() {this.scratchCtx = null}
2291
+ __init51() {this._hits = 0}
2292
+ __init52() {this._misses = 0}
2293
+ constructor(options = {}) {;_class5.prototype.__init49.call(this);_class5.prototype.__init50.call(this);_class5.prototype.__init51.call(this);_class5.prototype.__init52.call(this);
2251
2294
  this.maxEntries = Math.max(1, _nullishCoalesce(options.maxEntries, () => ( 4096)));
2252
2295
  this.dpr = Math.max(1, _nullishCoalesce(options.dpr, () => ( 1)));
2253
2296
  }