diff --git "a/src/backend/gradio_polygonannotator/templates/component/Index-CzQ497_5.js" "b/src/backend/gradio_polygonannotator/templates/component/Index-CzQ497_5.js" new file mode 100644--- /dev/null +++ "b/src/backend/gradio_polygonannotator/templates/component/Index-CzQ497_5.js" @@ -0,0 +1,26086 @@ +var wh = Object.defineProperty; +var _r = (i) => { + throw TypeError(i); +}; +var vh = (i, e, t) => e in i ? wh(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t; +var ie = (i, e, t) => vh(i, typeof e != "symbol" ? e + "" : e, t), Ch = (i, e, t) => e.has(i) || _r("Cannot " + t); +var mr = (i, e, t) => e.has(i) ? _r("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(i) : e.set(i, t); +var Nn = (i, e, t) => (Ch(i, e, "access private method"), t); +var Q = /* @__PURE__ */ ((i) => (i.Application = "application", i.WebGLPipes = "webgl-pipes", i.WebGLPipesAdaptor = "webgl-pipes-adaptor", i.WebGLSystem = "webgl-system", i.WebGPUPipes = "webgpu-pipes", i.WebGPUPipesAdaptor = "webgpu-pipes-adaptor", i.WebGPUSystem = "webgpu-system", i.CanvasSystem = "canvas-system", i.CanvasPipesAdaptor = "canvas-pipes-adaptor", i.CanvasPipes = "canvas-pipes", i.Asset = "asset", i.LoadParser = "load-parser", i.ResolveParser = "resolve-parser", i.CacheParser = "cache-parser", i.DetectionParser = "detection-parser", i.MaskEffect = "mask-effect", i.BlendMode = "blend-mode", i.TextureSource = "texture-source", i.Environment = "environment", i.ShapeBuilder = "shape-builder", i.Batcher = "batcher", i))(Q || {}); +const ds = (i) => { + if (typeof i == "function" || typeof i == "object" && i.extension) { + if (!i.extension) + throw new Error("Extension class must have an extension object"); + i = { ...typeof i.extension != "object" ? { type: i.extension } : i.extension, ref: i }; + } + if (typeof i == "object") + i = { ...i }; + else + throw new Error("Invalid extension type"); + return typeof i.type == "string" && (i.type = [i.type]), i; +}, Gn = (i, e) => ds(i).priority ?? e, Qe = { + /** @ignore */ + _addHandlers: {}, + /** @ignore */ + _removeHandlers: {}, + /** @ignore */ + _queue: {}, + /** + * Remove extensions from PixiJS. + * @param extensions - Extensions to be removed. Can be: + * - Extension class with static `extension` property + * - Extension format object with `type` and `ref` + * - Multiple extensions as separate arguments + * @returns {extensions} this for chaining + * @example + * ```ts + * // Remove a single extension + * extensions.remove(MyRendererPlugin); + * + * // Remove multiple extensions + * extensions.remove( + * MyRendererPlugin, + * MySystemPlugin + * ); + * ``` + * @see {@link ExtensionType} For available extension types + * @see {@link ExtensionFormat} For extension format details + */ + remove(...i) { + return i.map(ds).forEach((e) => { + e.type.forEach((t) => { + var n, s; + return (s = (n = this._removeHandlers)[t]) == null ? void 0 : s.call(n, e); + }); + }), this; + }, + /** + * Register new extensions with PixiJS. Extensions can be registered in multiple formats: + * - As a class with a static `extension` property + * - As an extension format object + * - As multiple extensions passed as separate arguments + * @param extensions - Extensions to add to PixiJS. Each can be: + * - A class with static `extension` property + * - An extension format object with `type` and `ref` + * - Multiple extensions as separate arguments + * @returns This extensions instance for chaining + * @example + * ```ts + * // Register a simple extension + * extensions.add(MyRendererPlugin); + * + * // Register multiple extensions + * extensions.add( + * MyRendererPlugin, + * MySystemPlugin, + * }); + * ``` + * @see {@link ExtensionType} For available extension types + * @see {@link ExtensionFormat} For extension format details + * @see {@link extensions.remove} For removing registered extensions + */ + add(...i) { + return i.map(ds).forEach((e) => { + e.type.forEach((t) => { + var r, a; + const n = this._addHandlers, s = this._queue; + n[t] ? (a = n[t]) == null || a.call(n, e) : (s[t] = s[t] || [], (r = s[t]) == null || r.push(e)); + }); + }), this; + }, + /** + * Internal method to handle extensions by name. + * @param type - The extension type. + * @param onAdd - Function handler when extensions are added/registered {@link StrictExtensionFormat}. + * @param onRemove - Function handler when extensions are removed/unregistered {@link StrictExtensionFormat}. + * @returns this for chaining. + * @internal + * @ignore + */ + handle(i, e, t) { + var a; + const n = this._addHandlers, s = this._removeHandlers; + if (n[i] || s[i]) + throw new Error(`Extension type ${i} already has a handler`); + n[i] = e, s[i] = t; + const r = this._queue; + return r[i] && ((a = r[i]) == null || a.forEach((o) => e(o)), delete r[i]), this; + }, + /** + * Handle a type, but using a map by `name` property. + * @param type - Type of extension to handle. + * @param map - The object map of named extensions. + * @returns this for chaining. + * @ignore + */ + handleByMap(i, e) { + return this.handle( + i, + (t) => { + t.name && (e[t.name] = t.ref); + }, + (t) => { + t.name && delete e[t.name]; + } + ); + }, + /** + * Handle a type, but using a list of extensions with a `name` property. + * @param type - Type of extension to handle. + * @param map - The array of named extensions. + * @param defaultPriority - Fallback priority if none is defined. + * @returns this for chaining. + * @ignore + */ + handleByNamedList(i, e, t = -1) { + return this.handle( + i, + (n) => { + e.findIndex((r) => r.name === n.name) >= 0 || (e.push({ name: n.name, value: n.ref }), e.sort((r, a) => Gn(a.value, t) - Gn(r.value, t))); + }, + (n) => { + const s = e.findIndex((r) => r.name === n.name); + s !== -1 && e.splice(s, 1); + } + ); + }, + /** + * Handle a type, but using a list of extensions. + * @param type - Type of extension to handle. + * @param list - The list of extensions. + * @param defaultPriority - The default priority to use if none is specified. + * @returns this for chaining. + * @ignore + */ + handleByList(i, e, t = -1) { + return this.handle( + i, + (n) => { + e.includes(n.ref) || (e.push(n.ref), e.sort((s, r) => Gn(r, t) - Gn(s, t))); + }, + (n) => { + const s = e.indexOf(n.ref); + s !== -1 && e.splice(s, 1); + } + ); + }, + /** + * Mixin the source object(s) properties into the target class's prototype. + * Copies all property descriptors from source objects to the target's prototype. + * @param Target - The target class to mix properties into + * @param sources - One or more source objects containing properties to mix in + * @example + * ```ts + * // Create a mixin with shared properties + * const moveable = { + * x: 0, + * y: 0, + * move(x: number, y: number) { + * this.x += x; + * this.y += y; + * } + * }; + * + * // Create a mixin with computed properties + * const scalable = { + * scale: 1, + * get scaled() { + * return this.scale > 1; + * } + * }; + * + * // Apply mixins to a class + * extensions.mixin(Sprite, moveable, scalable); + * + * // Use mixed-in properties + * const sprite = new Sprite(); + * sprite.move(10, 20); + * console.log(sprite.x, sprite.y); // 10, 20 + * ``` + * @remarks + * - Copies all properties including getters/setters + * - Does not modify source objects + * - Preserves property descriptors + * @see {@link Object.defineProperties} For details on property descriptors + * @see {@link Object.getOwnPropertyDescriptors} For details on property copying + */ + mixin(i, ...e) { + for (const t of e) + Object.defineProperties(i.prototype, Object.getOwnPropertyDescriptors(t)); + } +}, Sh = { + extension: { + type: Q.Environment, + name: "browser", + priority: -1 + }, + test: () => !0, + load: async () => { + await import("./browserAll-BoGsSDHg.js"); + } +}, kh = { + extension: { + type: Q.Environment, + name: "webworker", + priority: 0 + }, + test: () => typeof self < "u" && self.WorkerGlobalScope !== void 0, + load: async () => { + await import("./webworkerAll-BMMxBtBd.js"); + } +}; +class Ce { + /** + * Creates a new `ObservablePoint` + * @param observer - Observer to pass to listen for change events. + * @param {number} [x=0] - position of the point on the x axis + * @param {number} [y=0] - position of the point on the y axis + */ + constructor(e, t, n) { + this._x = t || 0, this._y = n || 0, this._observer = e; + } + /** + * Creates a clone of this point. + * @example + * ```ts + * // Basic cloning + * const point = new ObservablePoint(observer, 100, 200); + * const copy = point.clone(); + * + * // Clone with new observer + * const newObserver = { + * _onUpdate: (p) => console.log(`Clone updated: (${p.x}, ${p.y})`) + * }; + * const watched = point.clone(newObserver); + * + * // Verify independence + * watched.set(300, 400); // Only triggers new observer + * ``` + * @param observer - Optional observer to pass to the new observable point + * @returns A copy of this observable point + * @see {@link ObservablePoint.copyFrom} For copying into existing point + * @see {@link Observer} For observer interface details + */ + clone(e) { + return new Ce(e ?? this._observer, this._x, this._y); + } + /** + * Sets the point to a new x and y position. + * + * If y is omitted, both x and y will be set to x. + * @example + * ```ts + * // Basic position setting + * const point = new ObservablePoint(observer); + * point.set(100, 200); + * + * // Set both x and y to same value + * point.set(50); // x=50, y=50 + * ``` + * @param x - Position on the x axis + * @param y - Position on the y axis, defaults to x + * @returns The point instance itself + * @see {@link ObservablePoint.copyFrom} For copying from another point + * @see {@link ObservablePoint.equals} For comparing positions + */ + set(e = 0, t = e) { + return (this._x !== e || this._y !== t) && (this._x = e, this._y = t, this._observer._onUpdate(this)), this; + } + /** + * Copies x and y from the given point into this point. + * @example + * ```ts + * // Basic copying + * const source = new ObservablePoint(observer, 100, 200); + * const target = new ObservablePoint(); + * target.copyFrom(source); + * + * // Copy and chain operations + * const point = new ObservablePoint() + * .copyFrom(source) + * .set(x + 50, y + 50); + * + * // Copy from any PointData + * const data = { x: 10, y: 20 }; + * point.copyFrom(data); + * ``` + * @param p - The point to copy from + * @returns The point instance itself + * @see {@link ObservablePoint.copyTo} For copying to another point + * @see {@link ObservablePoint.clone} For creating new point copy + */ + copyFrom(e) { + return (this._x !== e.x || this._y !== e.y) && (this._x = e.x, this._y = e.y, this._observer._onUpdate(this)), this; + } + /** + * Copies this point's x and y into the given point. + * @example + * ```ts + * // Basic copying + * const source = new ObservablePoint(100, 200); + * const target = new ObservablePoint(); + * source.copyTo(target); + * ``` + * @param p - The point to copy to. Can be any type that is or extends `PointLike` + * @returns The point (`p`) with values updated + * @see {@link ObservablePoint.copyFrom} For copying from another point + * @see {@link ObservablePoint.clone} For creating new point copy + */ + copyTo(e) { + return e.set(this._x, this._y), e; + } + /** + * Checks if another point is equal to this point. + * + * Compares x and y values using strict equality. + * @example + * ```ts + * // Basic equality check + * const p1 = new ObservablePoint(100, 200); + * const p2 = new ObservablePoint(100, 200); + * console.log(p1.equals(p2)); // true + * + * // Compare with PointData + * const data = { x: 100, y: 200 }; + * console.log(p1.equals(data)); // true + * + * // Check different points + * const p3 = new ObservablePoint(200, 300); + * console.log(p1.equals(p3)); // false + * ``` + * @param p - The point to check + * @returns `true` if both `x` and `y` are equal + * @see {@link ObservablePoint.copyFrom} For making points equal + * @see {@link PointData} For point data interface + */ + equals(e) { + return e.x === this._x && e.y === this._y; + } + toString() { + return `[pixi.js/math:ObservablePoint x=${this._x} y=${this._y} scope=${this._observer}]`; + } + /** + * Position of the observable point on the x axis. + * Triggers observer callback when value changes. + * @example + * ```ts + * // Basic x position + * const point = new ObservablePoint(observer); + * point.x = 100; // Triggers observer + * + * // Use in calculations + * const width = rightPoint.x - leftPoint.x; + * ``` + * @default 0 + */ + get x() { + return this._x; + } + set x(e) { + this._x !== e && (this._x = e, this._observer._onUpdate(this)); + } + /** + * Position of the observable point on the y axis. + * Triggers observer callback when value changes. + * @example + * ```ts + * // Basic y position + * const point = new ObservablePoint(observer); + * point.y = 200; // Triggers observer + * + * // Use in calculations + * const height = bottomPoint.y - topPoint.y; + * ``` + * @default 0 + */ + get y() { + return this._y; + } + set y(e) { + this._y !== e && (this._y = e, this._observer._onUpdate(this)); + } +} +var gr = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; +function Co(i) { + return i && i.__esModule && Object.prototype.hasOwnProperty.call(i, "default") ? i.default : i; +} +var So = { exports: {} }; +(function(i) { + var e = Object.prototype.hasOwnProperty, t = "~"; + function n() { + } + Object.create && (n.prototype = /* @__PURE__ */ Object.create(null), new n().__proto__ || (t = !1)); + function s(l, h, u) { + this.fn = l, this.context = h, this.once = u || !1; + } + function r(l, h, u, c, d) { + if (typeof u != "function") + throw new TypeError("The listener must be a function"); + var f = new s(u, c || l, d), _ = t ? t + h : h; + return l._events[_] ? l._events[_].fn ? l._events[_] = [l._events[_], f] : l._events[_].push(f) : (l._events[_] = f, l._eventsCount++), l; + } + function a(l, h) { + --l._eventsCount === 0 ? l._events = new n() : delete l._events[h]; + } + function o() { + this._events = new n(), this._eventsCount = 0; + } + o.prototype.eventNames = function() { + var h = [], u, c; + if (this._eventsCount === 0) return h; + for (c in u = this._events) + e.call(u, c) && h.push(t ? c.slice(1) : c); + return Object.getOwnPropertySymbols ? h.concat(Object.getOwnPropertySymbols(u)) : h; + }, o.prototype.listeners = function(h) { + var u = t ? t + h : h, c = this._events[u]; + if (!c) return []; + if (c.fn) return [c.fn]; + for (var d = 0, f = c.length, _ = new Array(f); d < f; d++) + _[d] = c[d].fn; + return _; + }, o.prototype.listenerCount = function(h) { + var u = t ? t + h : h, c = this._events[u]; + return c ? c.fn ? 1 : c.length : 0; + }, o.prototype.emit = function(h, u, c, d, f, _) { + var b = t ? t + h : h; + if (!this._events[b]) return !1; + var m = this._events[b], x = arguments.length, g, p; + if (m.fn) { + switch (m.once && this.removeListener(h, m.fn, void 0, !0), x) { + case 1: + return m.fn.call(m.context), !0; + case 2: + return m.fn.call(m.context, u), !0; + case 3: + return m.fn.call(m.context, u, c), !0; + case 4: + return m.fn.call(m.context, u, c, d), !0; + case 5: + return m.fn.call(m.context, u, c, d, f), !0; + case 6: + return m.fn.call(m.context, u, c, d, f, _), !0; + } + for (p = 1, g = new Array(x - 1); p < x; p++) + g[p - 1] = arguments[p]; + m.fn.apply(m.context, g); + } else { + var y = m.length, C; + for (p = 0; p < y; p++) + switch (m[p].once && this.removeListener(h, m[p].fn, void 0, !0), x) { + case 1: + m[p].fn.call(m[p].context); + break; + case 2: + m[p].fn.call(m[p].context, u); + break; + case 3: + m[p].fn.call(m[p].context, u, c); + break; + case 4: + m[p].fn.call(m[p].context, u, c, d); + break; + default: + if (!g) for (C = 1, g = new Array(x - 1); C < x; C++) + g[C - 1] = arguments[C]; + m[p].fn.apply(m[p].context, g); + } + } + return !0; + }, o.prototype.on = function(h, u, c) { + return r(this, h, u, c, !1); + }, o.prototype.once = function(h, u, c) { + return r(this, h, u, c, !0); + }, o.prototype.removeListener = function(h, u, c, d) { + var f = t ? t + h : h; + if (!this._events[f]) return this; + if (!u) + return a(this, f), this; + var _ = this._events[f]; + if (_.fn) + _.fn === u && (!d || _.once) && (!c || _.context === c) && a(this, f); + else { + for (var b = 0, m = [], x = _.length; b < x; b++) + (_[b].fn !== u || d && !_[b].once || c && _[b].context !== c) && m.push(_[b]); + m.length ? this._events[f] = m.length === 1 ? m[0] : m : a(this, f); + } + return this; + }, o.prototype.removeAllListeners = function(h) { + var u; + return h ? (u = t ? t + h : h, this._events[u] && a(this, u)) : (this._events = new n(), this._eventsCount = 0), this; + }, o.prototype.off = o.prototype.removeListener, o.prototype.addListener = o.prototype.on, o.prefixed = t, o.EventEmitter = o, i.exports = o; +})(So); +var Ah = So.exports; +const xt = /* @__PURE__ */ Co(Ah), Dh = Math.PI * 2, Eh = 180 / Math.PI, Fh = Math.PI / 180; +class Ae { + /** + * Creates a new `Point` + * @param {number} [x=0] - position of the point on the x axis + * @param {number} [y=0] - position of the point on the y axis + */ + constructor(e = 0, t = 0) { + this.x = 0, this.y = 0, this.x = e, this.y = t; + } + /** + * Creates a clone of this point, which is a new instance with the same `x` and `y` values. + * @example + * ```ts + * // Basic point cloning + * const original = new Point(100, 200); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.set(300, 400); + * + * // Verify independence + * console.log(original); // Point(100, 200) + * console.log(modified); // Point(300, 400) + * ``` + * @remarks + * - Creates new Point instance + * - Deep copies x and y values + * - Independent from original + * - Useful for preserving values + * @returns A clone of this point + * @see {@link Point.copyFrom} For copying into existing point + * @see {@link Point.copyTo} For copying to existing point + */ + clone() { + return new Ae(this.x, this.y); + } + /** + * Copies x and y from the given point into this point. + * @example + * ```ts + * // Basic copying + * const source = new Point(100, 200); + * const target = new Point(); + * target.copyFrom(source); + * + * // Copy and chain operations + * const point = new Point() + * .copyFrom(source) + * .set(x + 50, y + 50); + * + * // Copy from any PointData + * const data = { x: 10, y: 20 }; + * point.copyFrom(data); + * ``` + * @param p - The point to copy from + * @returns The point instance itself + * @see {@link Point.copyTo} For copying to another point + * @see {@link Point.clone} For creating new point copy + */ + copyFrom(e) { + return this.set(e.x, e.y), this; + } + /** + * Copies this point's x and y into the given point. + * @example + * ```ts + * // Basic copying + * const source = new Point(100, 200); + * const target = new Point(); + * source.copyTo(target); + * ``` + * @param p - The point to copy to. Can be any type that is or extends `PointLike` + * @returns The point (`p`) with values updated + * @see {@link Point.copyFrom} For copying from another point + * @see {@link Point.clone} For creating new point copy + */ + copyTo(e) { + return e.set(this.x, this.y), e; + } + /** + * Checks if another point is equal to this point. + * + * Compares x and y values using strict equality. + * @example + * ```ts + * // Basic equality check + * const p1 = new Point(100, 200); + * const p2 = new Point(100, 200); + * console.log(p1.equals(p2)); // true + * + * // Compare with PointData + * const data = { x: 100, y: 200 }; + * console.log(p1.equals(data)); // true + * + * // Check different points + * const p3 = new Point(200, 300); + * console.log(p1.equals(p3)); // false + * ``` + * @param p - The point to check + * @returns `true` if both `x` and `y` are equal + * @see {@link Point.copyFrom} For making points equal + * @see {@link PointData} For point data interface + */ + equals(e) { + return e.x === this.x && e.y === this.y; + } + /** + * Sets the point to a new x and y position. + * + * If y is omitted, both x and y will be set to x. + * @example + * ```ts + * // Basic position setting + * const point = new Point(); + * point.set(100, 200); + * + * // Set both x and y to same value + * point.set(50); // x=50, y=50 + * + * // Chain with other operations + * point + * .set(10, 20) + * .copyTo(otherPoint); + * ``` + * @param x - Position on the x axis + * @param y - Position on the y axis, defaults to x + * @returns The point instance itself + * @see {@link Point.copyFrom} For copying from another point + * @see {@link Point.equals} For comparing positions + */ + set(e = 0, t = e) { + return this.x = e, this.y = t, this; + } + toString() { + return `[pixi.js/math:Point x=${this.x} y=${this.y}]`; + } + /** + * A static Point object with `x` and `y` values of `0`. + * + * This shared instance is reset to zero values when accessed. + * + * > [!IMPORTANT] This point is shared and temporary. Do not store references to it. + * @example + * ```ts + * // Use for temporary calculations + * const tempPoint = Point.shared; + * tempPoint.set(100, 200); + * matrix.apply(tempPoint); + * + * // Will be reset to (0,0) on next access + * const fresh = Point.shared; // x=0, y=0 + * ``` + * @readonly + * @returns A fresh zeroed point for temporary use + * @see {@link Point.constructor} For creating new points + * @see {@link PointData} For basic point interface + */ + static get shared() { + return Mi.x = 0, Mi.y = 0, Mi; + } +} +const Mi = new Ae(); +class H { + /** + * @param a - x scale + * @param b - y skew + * @param c - x skew + * @param d - y scale + * @param tx - x translation + * @param ty - y translation + */ + constructor(e = 1, t = 0, n = 0, s = 1, r = 0, a = 0) { + this.array = null, this.a = e, this.b = t, this.c = n, this.d = s, this.tx = r, this.ty = a; + } + /** + * Creates a Matrix object based on the given array. + * Populates matrix components from a flat array in column-major order. + * + * > [!NOTE] Array mapping order: + * > ``` + * > array[0] = a (x scale) + * > array[1] = b (y skew) + * > array[2] = tx (x translation) + * > array[3] = c (x skew) + * > array[4] = d (y scale) + * > array[5] = ty (y translation) + * > ``` + * @example + * ```ts + * // Create matrix from array + * const matrix = new Matrix(); + * matrix.fromArray([ + * 2, 0, 100, // a, b, tx + * 0, 2, 100 // c, d, ty + * ]); + * + * // Create matrix from typed array + * const float32Array = new Float32Array([ + * 1, 0, 0, // Scale x1, no skew + * 0, 1, 0 // No skew, scale x1 + * ]); + * matrix.fromArray(float32Array); + * ``` + * @param array - The array to populate the matrix from + * @see {@link Matrix.toArray} For converting matrix to array + * @see {@link Matrix.set} For setting values directly + */ + fromArray(e) { + this.a = e[0], this.b = e[1], this.c = e[3], this.d = e[4], this.tx = e[2], this.ty = e[5]; + } + /** + * Sets the matrix properties directly. + * All matrix components can be set in one call. + * @example + * ```ts + * // Set to identity matrix + * matrix.set(1, 0, 0, 1, 0, 0); + * + * // Set to scale matrix + * matrix.set(2, 0, 0, 2, 0, 0); // Scale 2x + * + * // Set to translation matrix + * matrix.set(1, 0, 0, 1, 100, 50); // Move 100,50 + * ``` + * @param a - Scale on x axis + * @param b - Shear on y axis + * @param c - Shear on x axis + * @param d - Scale on y axis + * @param tx - Translation on x axis + * @param ty - Translation on y axis + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.identity} For resetting to identity + * @see {@link Matrix.fromArray} For setting from array + */ + set(e, t, n, s, r, a) { + return this.a = e, this.b = t, this.c = n, this.d = s, this.tx = r, this.ty = a, this; + } + /** + * Creates an array from the current Matrix object. + * + * > [!NOTE] The array format is: + * > ``` + * > Non-transposed: + * > [a, c, tx, + * > b, d, ty, + * > 0, 0, 1] + * > + * > Transposed: + * > [a, b, 0, + * > c, d, 0, + * > tx,ty,1] + * > ``` + * @example + * ```ts + * // Basic array conversion + * const matrix = new Matrix(2, 0, 0, 2, 100, 100); + * const array = matrix.toArray(); + * + * // Using existing array + * const float32Array = new Float32Array(9); + * matrix.toArray(false, float32Array); + * + * // Get transposed array + * const transposed = matrix.toArray(true); + * ``` + * @param transpose - Whether to transpose the matrix + * @param out - Optional Float32Array to store the result + * @returns The array containing the matrix values + * @see {@link Matrix.fromArray} For creating matrix from array + * @see {@link Matrix.array} For cached array storage + */ + toArray(e, t) { + this.array || (this.array = new Float32Array(9)); + const n = t || this.array; + return e ? (n[0] = this.a, n[1] = this.b, n[2] = 0, n[3] = this.c, n[4] = this.d, n[5] = 0, n[6] = this.tx, n[7] = this.ty, n[8] = 1) : (n[0] = this.a, n[1] = this.c, n[2] = this.tx, n[3] = this.b, n[4] = this.d, n[5] = this.ty, n[6] = 0, n[7] = 0, n[8] = 1), n; + } + /** + * Get a new position with the current transformation applied. + * + * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering) + * @example + * ```ts + * // Basic point transformation + * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4); + * const point = new Point(10, 20); + * const transformed = matrix.apply(point); + * + * // Reuse existing point + * const output = new Point(); + * matrix.apply(point, output); + * ``` + * @param pos - The origin point to transform + * @param newPos - Optional point to store the result + * @returns The transformed point + * @see {@link Matrix.applyInverse} For inverse transformation + * @see {@link Point} For point operations + */ + apply(e, t) { + t = t || new Ae(); + const n = e.x, s = e.y; + return t.x = this.a * n + this.c * s + this.tx, t.y = this.b * n + this.d * s + this.ty, t; + } + /** + * Get a new position with the inverse of the current transformation applied. + * + * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input) + * @example + * ```ts + * // Basic inverse transformation + * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4); + * const worldPoint = new Point(150, 100); + * const localPoint = matrix.applyInverse(worldPoint); + * + * // Reuse existing point + * const output = new Point(); + * matrix.applyInverse(worldPoint, output); + * + * // Convert mouse position to local space + * const mousePoint = new Point(mouseX, mouseY); + * const localMouse = matrix.applyInverse(mousePoint); + * ``` + * @param pos - The origin point to inverse-transform + * @param newPos - Optional point to store the result + * @returns The inverse-transformed point + * @see {@link Matrix.apply} For forward transformation + * @see {@link Matrix.invert} For getting inverse matrix + */ + applyInverse(e, t) { + t = t || new Ae(); + const n = this.a, s = this.b, r = this.c, a = this.d, o = this.tx, l = this.ty, h = 1 / (n * a + r * -s), u = e.x, c = e.y; + return t.x = a * h * u + -r * h * c + (l * r - o * a) * h, t.y = n * h * c + -s * h * u + (-l * n + o * s) * h, t; + } + /** + * Translates the matrix on the x and y axes. + * Adds to the position values while preserving scale, rotation and skew. + * @example + * ```ts + * // Basic translation + * const matrix = new Matrix(); + * matrix.translate(100, 50); // Move right 100, down 50 + * + * // Chain with other transformations + * matrix + * .scale(2, 2) + * .translate(100, 0) + * .rotate(Math.PI / 4); + * ``` + * @param x - How much to translate on the x axis + * @param y - How much to translate on the y axis + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.set} For setting position directly + * @see {@link Matrix.setTransform} For complete transform setup + */ + translate(e, t) { + return this.tx += e, this.ty += t, this; + } + /** + * Applies a scale transformation to the matrix. + * Multiplies the scale values with existing matrix components. + * @example + * ```ts + * // Basic scaling + * const matrix = new Matrix(); + * matrix.scale(2, 3); // Scale 2x horizontally, 3x vertically + * + * // Chain with other transformations + * matrix + * .translate(100, 100) + * .scale(2, 2) // Scales after translation + * .rotate(Math.PI / 4); + * ``` + * @param x - The amount to scale horizontally + * @param y - The amount to scale vertically + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.setTransform} For setting scale directly + * @see {@link Matrix.append} For combining transformations + */ + scale(e, t) { + return this.a *= e, this.d *= t, this.c *= e, this.b *= t, this.tx *= e, this.ty *= t, this; + } + /** + * Applies a rotation transformation to the matrix. + * + * Rotates around the origin (0,0) by the given angle in radians. + * @example + * ```ts + * // Basic rotation + * const matrix = new Matrix(); + * matrix.rotate(Math.PI / 4); // Rotate 45 degrees + * + * // Chain with other transformations + * matrix + * .translate(100, 100) // Move to rotation center + * .rotate(Math.PI) // Rotate 180 degrees + * .scale(2, 2); // Scale after rotation + * + * // Common angles + * matrix.rotate(Math.PI / 2); // 90 degrees + * matrix.rotate(Math.PI); // 180 degrees + * matrix.rotate(Math.PI * 2); // 360 degrees + * ``` + * @remarks + * - Rotates around origin point (0,0) + * - Affects position if translation was set + * - Uses counter-clockwise rotation + * - Order of operations matters when chaining + * @param angle - The angle in radians + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.setTransform} For setting rotation directly + * @see {@link Matrix.append} For combining transformations + */ + rotate(e) { + const t = Math.cos(e), n = Math.sin(e), s = this.a, r = this.c, a = this.tx; + return this.a = s * t - this.b * n, this.b = s * n + this.b * t, this.c = r * t - this.d * n, this.d = r * n + this.d * t, this.tx = a * t - this.ty * n, this.ty = a * n + this.ty * t, this; + } + /** + * Appends the given Matrix to this Matrix. + * Combines two matrices by multiplying them together: this = this * matrix + * @example + * ```ts + * // Basic matrix combination + * const matrix = new Matrix(); + * const other = new Matrix().translate(100, 0).rotate(Math.PI / 4); + * matrix.append(other); + * ``` + * @remarks + * - Order matters: A.append(B) !== B.append(A) + * - Modifies current matrix + * - Preserves transformation order + * - Commonly used for combining transforms + * @param matrix - The matrix to append + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.prepend} For prepending transformations + * @see {@link Matrix.appendFrom} For appending two external matrices + */ + append(e) { + const t = this.a, n = this.b, s = this.c, r = this.d; + return this.a = e.a * t + e.b * s, this.b = e.a * n + e.b * r, this.c = e.c * t + e.d * s, this.d = e.c * n + e.d * r, this.tx = e.tx * t + e.ty * s + this.tx, this.ty = e.tx * n + e.ty * r + this.ty, this; + } + /** + * Appends two matrices and sets the result to this matrix. + * Performs matrix multiplication: this = A * B + * @example + * ```ts + * // Basic matrix multiplication + * const result = new Matrix(); + * const matrixA = new Matrix().scale(2, 2); + * const matrixB = new Matrix().rotate(Math.PI / 4); + * result.appendFrom(matrixA, matrixB); + * ``` + * @remarks + * - Order matters: A * B !== B * A + * - Creates a new transformation from two others + * - More efficient than append() for multiple operations + * - Does not modify input matrices + * @param a - The first matrix to multiply + * @param b - The second matrix to multiply + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.append} For single matrix combination + * @see {@link Matrix.prepend} For reverse order multiplication + */ + appendFrom(e, t) { + const n = e.a, s = e.b, r = e.c, a = e.d, o = e.tx, l = e.ty, h = t.a, u = t.b, c = t.c, d = t.d; + return this.a = n * h + s * c, this.b = n * u + s * d, this.c = r * h + a * c, this.d = r * u + a * d, this.tx = o * h + l * c + t.tx, this.ty = o * u + l * d + t.ty, this; + } + /** + * Sets the matrix based on all the available properties. + * Combines position, scale, rotation, skew and pivot in a single operation. + * @example + * ```ts + * // Basic transform setup + * const matrix = new Matrix(); + * matrix.setTransform( + * 100, 100, // position + * 0, 0, // pivot + * 2, 2, // scale + * Math.PI / 4, // rotation (45 degrees) + * 0, 0 // skew + * ); + * ``` + * @remarks + * - Updates all matrix components at once + * - More efficient than separate transform calls + * - Uses radians for rotation and skew + * - Pivot affects rotation center + * @param x - Position on the x axis + * @param y - Position on the y axis + * @param pivotX - Pivot on the x axis + * @param pivotY - Pivot on the y axis + * @param scaleX - Scale on the x axis + * @param scaleY - Scale on the y axis + * @param rotation - Rotation in radians + * @param skewX - Skew on the x axis + * @param skewY - Skew on the y axis + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.decompose} For extracting transform properties + * @see {@link TransformableObject} For transform data structure + */ + setTransform(e, t, n, s, r, a, o, l, h) { + return this.a = Math.cos(o + h) * r, this.b = Math.sin(o + h) * r, this.c = -Math.sin(o - l) * a, this.d = Math.cos(o - l) * a, this.tx = e - (n * this.a + s * this.c), this.ty = t - (n * this.b + s * this.d), this; + } + /** + * Prepends the given Matrix to this Matrix. + * Combines two matrices by multiplying them together: this = matrix * this + * @example + * ```ts + * // Basic matrix prepend + * const matrix = new Matrix().scale(2, 2); + * const other = new Matrix().translate(100, 0); + * matrix.prepend(other); // Translation happens before scaling + * ``` + * @remarks + * - Order matters: A.prepend(B) !== B.prepend(A) + * - Modifies current matrix + * - Reverses transformation order compared to append() + * @param matrix - The matrix to prepend + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.append} For appending transformations + * @see {@link Matrix.appendFrom} For combining external matrices + */ + prepend(e) { + const t = this.tx; + if (e.a !== 1 || e.b !== 0 || e.c !== 0 || e.d !== 1) { + const n = this.a, s = this.c; + this.a = n * e.a + this.b * e.c, this.b = n * e.b + this.b * e.d, this.c = s * e.a + this.d * e.c, this.d = s * e.b + this.d * e.d; + } + return this.tx = t * e.a + this.ty * e.c + e.tx, this.ty = t * e.b + this.ty * e.d + e.ty, this; + } + /** + * Decomposes the matrix into its individual transform components. + * Extracts position, scale, rotation and skew values from the matrix. + * @example + * ```ts + * // Basic decomposition + * const matrix = new Matrix() + * .translate(100, 100) + * .rotate(Math.PI / 4) + * .scale(2, 2); + * + * const transform = { + * position: new Point(), + * scale: new Point(), + * pivot: new Point(), + * skew: new Point(), + * rotation: 0 + * }; + * + * matrix.decompose(transform); + * console.log(transform.position); // Point(100, 100) + * console.log(transform.rotation); // ~0.785 (PI/4) + * console.log(transform.scale); // Point(2, 2) + * ``` + * @remarks + * - Handles combined transformations + * - Accounts for pivot points + * - Chooses between rotation/skew based on transform type + * - Uses radians for rotation and skew + * @param transform - The transform object to store the decomposed values + * @returns The transform with the newly applied properties + * @see {@link Matrix.setTransform} For composing from components + * @see {@link TransformableObject} For transform structure + */ + decompose(e) { + const t = this.a, n = this.b, s = this.c, r = this.d, a = e.pivot, o = -Math.atan2(-s, r), l = Math.atan2(n, t), h = Math.abs(o + l); + return h < 1e-5 || Math.abs(Dh - h) < 1e-5 ? (e.rotation = l, e.skew.x = e.skew.y = 0) : (e.rotation = 0, e.skew.x = o, e.skew.y = l), e.scale.x = Math.sqrt(t * t + n * n), e.scale.y = Math.sqrt(s * s + r * r), e.position.x = this.tx + (a.x * t + a.y * s), e.position.y = this.ty + (a.x * n + a.y * r), e; + } + /** + * Inverts this matrix. + * Creates the matrix that when multiplied with this matrix results in an identity matrix. + * @example + * ```ts + * // Basic matrix inversion + * const matrix = new Matrix() + * .translate(100, 50) + * .scale(2, 2); + * + * matrix.invert(); // Now transforms in opposite direction + * + * // Verify inversion + * const point = new Point(50, 50); + * const transformed = matrix.apply(point); + * const original = matrix.invert().apply(transformed); + * // original ≈ point + * ``` + * @remarks + * - Modifies the current matrix + * - Useful for reversing transformations + * - Cannot invert matrices with zero determinant + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.identity} For resetting to identity + * @see {@link Matrix.applyInverse} For inverse transformations + */ + invert() { + const e = this.a, t = this.b, n = this.c, s = this.d, r = this.tx, a = e * s - t * n; + return this.a = s / a, this.b = -t / a, this.c = -n / a, this.d = e / a, this.tx = (n * this.ty - s * r) / a, this.ty = -(e * this.ty - t * r) / a, this; + } + /** + * Checks if this matrix is an identity matrix. + * + * An identity matrix has no transformations applied (default state). + * @example + * ```ts + * // Check if matrix is identity + * const matrix = new Matrix(); + * console.log(matrix.isIdentity()); // true + * + * // Check after transformations + * matrix.translate(100, 0); + * console.log(matrix.isIdentity()); // false + * + * // Reset and verify + * matrix.identity(); + * console.log(matrix.isIdentity()); // true + * ``` + * @remarks + * - Verifies a = 1, d = 1 (no scale) + * - Verifies b = 0, c = 0 (no skew) + * - Verifies tx = 0, ty = 0 (no translation) + * @returns True if matrix has no transformations + * @see {@link Matrix.identity} For resetting to identity + * @see {@link Matrix.IDENTITY} For constant identity matrix + */ + isIdentity() { + return this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.tx === 0 && this.ty === 0; + } + /** + * Resets this Matrix to an identity (default) matrix. + * Sets all components to their default values: scale=1, no skew, no translation. + * @example + * ```ts + * // Reset transformed matrix + * const matrix = new Matrix() + * .scale(2, 2) + * .rotate(Math.PI / 4); + * matrix.identity(); // Back to default state + * + * // Chain after reset + * matrix + * .identity() + * .translate(100, 100) + * .scale(2, 2); + * + * // Compare with identity constant + * const isDefault = matrix.equals(Matrix.IDENTITY); + * ``` + * @remarks + * - Sets a=1, d=1 (default scale) + * - Sets b=0, c=0 (no skew) + * - Sets tx=0, ty=0 (no translation) + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.IDENTITY} For constant identity matrix + * @see {@link Matrix.isIdentity} For checking identity state + */ + identity() { + return this.a = 1, this.b = 0, this.c = 0, this.d = 1, this.tx = 0, this.ty = 0, this; + } + /** + * Creates a new Matrix object with the same values as this one. + * @returns A copy of this matrix. Good for chaining method calls. + */ + clone() { + const e = new H(); + return e.a = this.a, e.b = this.b, e.c = this.c, e.d = this.d, e.tx = this.tx, e.ty = this.ty, e; + } + /** + * Creates a new Matrix object with the same values as this one. + * @param matrix + * @example + * ```ts + * // Basic matrix cloning + * const matrix = new Matrix() + * .translate(100, 100) + * .rotate(Math.PI / 4); + * const copy = matrix.clone(); + * + * // Clone and modify + * const modified = matrix.clone() + * .scale(2, 2); + * + * // Compare matrices + * console.log(matrix.equals(copy)); // true + * console.log(matrix.equals(modified)); // false + * ``` + * @returns A copy of this matrix. Good for chaining method calls. + * @see {@link Matrix.copyTo} For copying to existing matrix + * @see {@link Matrix.copyFrom} For copying from another matrix + */ + copyTo(e) { + return e.a = this.a, e.b = this.b, e.c = this.c, e.d = this.d, e.tx = this.tx, e.ty = this.ty, e; + } + /** + * Changes the values of the matrix to be the same as the ones in given matrix. + * @example + * ```ts + * // Basic matrix copying + * const source = new Matrix() + * .translate(100, 100) + * .rotate(Math.PI / 4); + * const target = new Matrix(); + * target.copyFrom(source); + * ``` + * @param matrix - The matrix to copy from + * @returns This matrix. Good for chaining method calls. + * @see {@link Matrix.clone} For creating new matrix copy + * @see {@link Matrix.copyTo} For copying to another matrix + */ + copyFrom(e) { + return this.a = e.a, this.b = e.b, this.c = e.c, this.d = e.d, this.tx = e.tx, this.ty = e.ty, this; + } + /** + * Checks if this matrix equals another matrix. + * Compares all components for exact equality. + * @example + * ```ts + * // Basic equality check + * const m1 = new Matrix(); + * const m2 = new Matrix(); + * console.log(m1.equals(m2)); // true + * + * // Compare transformed matrices + * const transform = new Matrix() + * .translate(100, 100) + * const clone = new Matrix() + * .scale(2, 2); + * console.log(transform.equals(clone)); // false + * ``` + * @param matrix - The matrix to compare to + * @returns True if matrices are identical + * @see {@link Matrix.copyFrom} For copying matrix values + * @see {@link Matrix.isIdentity} For identity comparison + */ + equals(e) { + return e.a === this.a && e.b === this.b && e.c === this.c && e.d === this.d && e.tx === this.tx && e.ty === this.ty; + } + toString() { + return `[pixi.js:Matrix a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`; + } + /** + * A default (identity) matrix with no transformations applied. + * + * > [!IMPORTANT] This is a shared read-only object. Create a new Matrix if you need to modify it. + * @example + * ```ts + * // Get identity matrix reference + * const identity = Matrix.IDENTITY; + * console.log(identity.isIdentity()); // true + * + * // Compare with identity + * const matrix = new Matrix(); + * console.log(matrix.equals(Matrix.IDENTITY)); // true + * + * // Create new matrix instead of modifying IDENTITY + * const transform = new Matrix() + * .copyFrom(Matrix.IDENTITY) + * .translate(100, 100); + * ``` + * @readonly + * @returns A read-only identity matrix + * @see {@link Matrix.shared} For temporary calculations + * @see {@link Matrix.identity} For resetting matrices + */ + static get IDENTITY() { + return Th.identity(); + } + /** + * A static Matrix that can be used to avoid creating new objects. + * Will always ensure the matrix is reset to identity when requested. + * + * > [!IMPORTANT] This matrix is shared and temporary. Do not store references to it. + * @example + * ```ts + * // Use for temporary calculations + * const tempMatrix = Matrix.shared; + * tempMatrix.translate(100, 100).rotate(Math.PI / 4); + * const point = tempMatrix.apply({ x: 10, y: 20 }); + * + * // Will be reset to identity on next access + * const fresh = Matrix.shared; // Back to identity + * ``` + * @remarks + * - Always returns identity matrix + * - Safe to modify temporarily + * - Not safe to store references + * - Useful for one-off calculations + * @readonly + * @returns A fresh identity matrix for temporary use + * @see {@link Matrix.IDENTITY} For immutable identity matrix + * @see {@link Matrix.identity} For resetting matrices + */ + static get shared() { + return $h.identity(); + } +} +const $h = new H(), Th = new H(), It = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1], Rt = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1], Bt = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1], Lt = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1], fs = [], ko = [], qn = Math.sign; +function Mh() { + for (let i = 0; i < 16; i++) { + const e = []; + fs.push(e); + for (let t = 0; t < 16; t++) { + const n = qn(It[i] * It[t] + Bt[i] * Rt[t]), s = qn(Rt[i] * It[t] + Lt[i] * Rt[t]), r = qn(It[i] * Bt[t] + Bt[i] * Lt[t]), a = qn(Rt[i] * Bt[t] + Lt[i] * Lt[t]); + for (let o = 0; o < 16; o++) + if (It[o] === n && Rt[o] === s && Bt[o] === r && Lt[o] === a) { + e.push(o); + break; + } + } + } + for (let i = 0; i < 16; i++) { + const e = new H(); + e.set(It[i], Rt[i], Bt[i], Lt[i], 0, 0), ko.push(e); + } +} +Mh(); +const te = { + /** + * | Rotation | Direction | + * |----------|-----------| + * | 0° | East | + * @group groupD8 + * @type {GD8Symmetry} + */ + E: 0, + /** + * | Rotation | Direction | + * |----------|-----------| + * | 45°↻ | Southeast | + * @group groupD8 + * @type {GD8Symmetry} + */ + SE: 1, + /** + * | Rotation | Direction | + * |----------|-----------| + * | 90°↻ | South | + * @group groupD8 + * @type {GD8Symmetry} + */ + S: 2, + /** + * | Rotation | Direction | + * |----------|-----------| + * | 135°↻ | Southwest | + * @group groupD8 + * @type {GD8Symmetry} + */ + SW: 3, + /** + * | Rotation | Direction | + * |----------|-----------| + * | 180° | West | + * @group groupD8 + * @type {GD8Symmetry} + */ + W: 4, + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -135°/225°↻ | Northwest | + * @group groupD8 + * @type {GD8Symmetry} + */ + NW: 5, + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -90°/270°↻ | North | + * @group groupD8 + * @type {GD8Symmetry} + */ + N: 6, + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -45°/315°↻ | Northeast | + * @group groupD8 + * @type {GD8Symmetry} + */ + NE: 7, + /** + * Reflection about Y-axis. + * @group groupD8 + * @type {GD8Symmetry} + */ + MIRROR_VERTICAL: 8, + /** + * Reflection about the main diagonal. + * @group groupD8 + * @type {GD8Symmetry} + */ + MAIN_DIAGONAL: 10, + /** + * Reflection about X-axis. + * @group groupD8 + * @type {GD8Symmetry} + */ + MIRROR_HORIZONTAL: 12, + /** + * Reflection about reverse diagonal. + * @group groupD8 + * @type {GD8Symmetry} + */ + REVERSE_DIAGONAL: 14, + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The X-component of the U-axis + * after rotating the axes. + */ + uX: (i) => It[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The Y-component of the U-axis + * after rotating the axes. + */ + uY: (i) => Rt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The X-component of the V-axis + * after rotating the axes. + */ + vX: (i) => Bt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The Y-component of the V-axis + * after rotating the axes. + */ + vY: (i) => Lt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} rotation - symmetry whose opposite + * is needed. Only rotations have opposite symmetries while + * reflections don't. + * @returns {GD8Symmetry} The opposite symmetry of `rotation` + */ + inv: (i) => i & 8 ? i & 15 : -i & 7, + /** + * Composes the two D8 operations. + * + * Taking `^` as reflection: + * + * | | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 | + * |-------|-----|-----|-----|-----|------|-------|-------|-------| + * | E=0 | E | S | W | N | E^ | S^ | W^ | N^ | + * | S=2 | S | W | N | E | S^ | W^ | N^ | E^ | + * | W=4 | W | N | E | S | W^ | N^ | E^ | S^ | + * | N=6 | N | E | S | W | N^ | E^ | S^ | W^ | + * | E^=8 | E^ | N^ | W^ | S^ | E | N | W | S | + * | S^=10 | S^ | E^ | N^ | W^ | S | E | N | W | + * | W^=12 | W^ | S^ | E^ | N^ | W | S | E | N | + * | N^=14 | N^ | W^ | S^ | E^ | N | W | S | E | + * + * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table} + * @group groupD8 + * @param {GD8Symmetry} rotationSecond - Second operation, which + * is the row in the above cayley table. + * @param {GD8Symmetry} rotationFirst - First operation, which + * is the column in the above cayley table. + * @returns {GD8Symmetry} Composed operation + */ + add: (i, e) => fs[i][e], + /** + * Reverse of `add`. + * @group groupD8 + * @param {GD8Symmetry} rotationSecond - Second operation + * @param {GD8Symmetry} rotationFirst - First operation + * @returns {GD8Symmetry} Result + */ + sub: (i, e) => fs[i][te.inv(e)], + /** + * Adds 180 degrees to rotation, which is a commutative + * operation. + * @group groupD8 + * @param {number} rotation - The number to rotate. + * @returns {number} Rotated number + */ + rotate180: (i) => i ^ 4, + /** + * Checks if the rotation angle is vertical, i.e. south + * or north. It doesn't work for reflections. + * @group groupD8 + * @param {GD8Symmetry} rotation - The number to check. + * @returns {boolean} Whether or not the direction is vertical + */ + isVertical: (i) => (i & 3) === 2, + // rotation % 4 === 2 + /** + * Approximates the vector `V(dx,dy)` into one of the + * eight directions provided by `groupD8`. + * @group groupD8 + * @param {number} dx - X-component of the vector + * @param {number} dy - Y-component of the vector + * @returns {GD8Symmetry} Approximation of the vector into + * one of the eight symmetries. + */ + byDirection: (i, e) => Math.abs(i) * 2 <= Math.abs(e) ? e >= 0 ? te.S : te.N : Math.abs(e) * 2 <= Math.abs(i) ? i > 0 ? te.E : te.W : e > 0 ? i > 0 ? te.SE : te.SW : i > 0 ? te.NE : te.NW, + /** + * Helps sprite to compensate texture packer rotation. + * @group groupD8 + * @param {Matrix} matrix - sprite world matrix + * @param {GD8Symmetry} rotation - The rotation factor to use. + * @param {number} tx - sprite anchoring + * @param {number} ty - sprite anchoring + */ + matrixAppendRotationInv: (i, e, t = 0, n = 0) => { + const s = ko[te.inv(e)]; + s.tx = t, s.ty = n, i.append(s); + }, + /** + * Transforms rectangle coordinates based on texture packer rotation. + * Used when texture atlas pages are rotated and coordinates need to be adjusted. + * @group groupD8 + * @param {RectangleLike} rect - Rectangle with original coordinates to transform + * @param {RectangleLike} sourceFrame - Source texture frame (includes offset and dimensions) + * @param {GD8Symmetry} rotation - The groupD8 rotation value + * @param {Rectangle} out - Rectangle to store the result + * @returns {Rectangle} Transformed coordinates (includes source frame offset) + */ + transformRectCoords: (i, e, t, n) => { + const { x: s, y: r, width: a, height: o } = i, { x: l, y: h, width: u, height: c } = e; + return t === te.E ? (n.set(s + l, r + h, a, o), n) : t === te.S ? n.set( + u - r - o + l, + s + h, + o, + a + ) : t === te.W ? n.set( + u - s - a + l, + c - r - o + h, + a, + o + ) : t === te.N ? n.set( + r + l, + c - s - a + h, + o, + a + ) : n.set(s + l, r + h, a, o); + } +}, Un = [new Ae(), new Ae(), new Ae(), new Ae()]; +class de { + /** + * @param x - The X coordinate of the upper-left corner of the rectangle + * @param y - The Y coordinate of the upper-left corner of the rectangle + * @param width - The overall width of the rectangle + * @param height - The overall height of the rectangle + */ + constructor(e = 0, t = 0, n = 0, s = 0) { + this.type = "rectangle", this.x = Number(e), this.y = Number(t), this.width = Number(n), this.height = Number(s); + } + /** + * Returns the left edge (x-coordinate) of the rectangle. + * @example + * ```ts + * // Get left edge position + * const rect = new Rectangle(100, 100, 200, 150); + * console.log(rect.left); // 100 + * + * // Use in alignment calculations + * sprite.x = rect.left + padding; + * + * // Compare positions + * if (point.x > rect.left) { + * console.log('Point is right of rectangle'); + * } + * ``` + * @readonly + * @returns The x-coordinate of the left edge + * @see {@link Rectangle.right} For right edge position + * @see {@link Rectangle.x} For direct x-coordinate access + */ + get left() { + return this.x; + } + /** + * Returns the right edge (x + width) of the rectangle. + * @example + * ```ts + * // Get right edge position + * const rect = new Rectangle(100, 100, 200, 150); + * console.log(rect.right); // 300 + * + * // Align to right edge + * sprite.x = rect.right - sprite.width; + * + * // Check boundaries + * if (point.x < rect.right) { + * console.log('Point is inside right bound'); + * } + * ``` + * @readonly + * @returns The x-coordinate of the right edge + * @see {@link Rectangle.left} For left edge position + * @see {@link Rectangle.width} For width value + */ + get right() { + return this.x + this.width; + } + /** + * Returns the top edge (y-coordinate) of the rectangle. + * @example + * ```ts + * // Get top edge position + * const rect = new Rectangle(100, 100, 200, 150); + * console.log(rect.top); // 100 + * + * // Position above rectangle + * sprite.y = rect.top - sprite.height; + * + * // Check vertical position + * if (point.y > rect.top) { + * console.log('Point is below top edge'); + * } + * ``` + * @readonly + * @returns The y-coordinate of the top edge + * @see {@link Rectangle.bottom} For bottom edge position + * @see {@link Rectangle.y} For direct y-coordinate access + */ + get top() { + return this.y; + } + /** + * Returns the bottom edge (y + height) of the rectangle. + * @example + * ```ts + * // Get bottom edge position + * const rect = new Rectangle(100, 100, 200, 150); + * console.log(rect.bottom); // 250 + * + * // Stack below rectangle + * sprite.y = rect.bottom + margin; + * + * // Check vertical bounds + * if (point.y < rect.bottom) { + * console.log('Point is above bottom edge'); + * } + * ``` + * @readonly + * @returns The y-coordinate of the bottom edge + * @see {@link Rectangle.top} For top edge position + * @see {@link Rectangle.height} For height value + */ + get bottom() { + return this.y + this.height; + } + /** + * Determines whether the Rectangle is empty (has no area). + * @example + * ```ts + * // Check zero dimensions + * const rect = new Rectangle(100, 100, 0, 50); + * console.log(rect.isEmpty()); // true + * ``` + * @returns True if the rectangle has no area + * @see {@link Rectangle.width} For width value + * @see {@link Rectangle.height} For height value + */ + isEmpty() { + return this.left === this.right || this.top === this.bottom; + } + /** + * A constant empty rectangle. This is a new object every time the property is accessed. + * @example + * ```ts + * // Get fresh empty rectangle + * const empty = Rectangle.EMPTY; + * console.log(empty.isEmpty()); // true + * ``` + * @returns A new empty rectangle instance + * @see {@link Rectangle.isEmpty} For empty state testing + */ + static get EMPTY() { + return new de(0, 0, 0, 0); + } + /** + * Creates a clone of this Rectangle + * @example + * ```ts + * // Basic cloning + * const original = new Rectangle(100, 100, 200, 150); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.width *= 2; + * modified.height += 50; + * + * // Verify independence + * console.log(original.width); // 200 + * console.log(modified.width); // 400 + * ``` + * @returns A copy of the rectangle + * @see {@link Rectangle.copyFrom} For copying into existing rectangle + * @see {@link Rectangle.copyTo} For copying to another rectangle + */ + clone() { + return new de(this.x, this.y, this.width, this.height); + } + /** + * Converts a Bounds object to a Rectangle object. + * @example + * ```ts + * // Convert bounds to rectangle + * const bounds = container.getBounds(); + * const rect = new Rectangle().copyFromBounds(bounds); + * ``` + * @param bounds - The bounds to copy and convert to a rectangle + * @returns Returns itself + * @see {@link Bounds} For bounds object structure + * @see {@link Rectangle.getBounds} For getting rectangle bounds + */ + copyFromBounds(e) { + return this.x = e.minX, this.y = e.minY, this.width = e.maxX - e.minX, this.height = e.maxY - e.minY, this; + } + /** + * Copies another rectangle to this one. + * @example + * ```ts + * // Basic copying + * const source = new Rectangle(100, 100, 200, 150); + * const target = new Rectangle(); + * target.copyFrom(source); + * + * // Chain with other operations + * const rect = new Rectangle() + * .copyFrom(source) + * .pad(10); + * ``` + * @param rectangle - The rectangle to copy from + * @returns Returns itself + * @see {@link Rectangle.copyTo} For copying to another rectangle + * @see {@link Rectangle.clone} For creating new rectangle copy + */ + copyFrom(e) { + return this.x = e.x, this.y = e.y, this.width = e.width, this.height = e.height, this; + } + /** + * Copies this rectangle to another one. + * @example + * ```ts + * // Basic copying + * const source = new Rectangle(100, 100, 200, 150); + * const target = new Rectangle(); + * source.copyTo(target); + * + * // Chain with other operations + * const result = source + * .copyTo(new Rectangle()) + * .getBounds(); + * ``` + * @param rectangle - The rectangle to copy to + * @returns Returns given parameter + * @see {@link Rectangle.copyFrom} For copying from another rectangle + * @see {@link Rectangle.clone} For creating new rectangle copy + */ + copyTo(e) { + return e.copyFrom(this), e; + } + /** + * Checks whether the x and y coordinates given are contained within this Rectangle + * @example + * ```ts + * // Basic containment check + * const rect = new Rectangle(100, 100, 200, 150); + * const isInside = rect.contains(150, 125); // true + * // Check edge cases + * console.log(rect.contains(100, 100)); // true (on edge) + * console.log(rect.contains(300, 250)); // false (outside) + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @returns Whether the x/y coordinates are within this Rectangle + * @see {@link Rectangle.containsRect} For rectangle containment + * @see {@link Rectangle.strokeContains} For checking stroke intersection + */ + contains(e, t) { + return this.width <= 0 || this.height <= 0 ? !1 : e >= this.x && e < this.x + this.width && t >= this.y && t < this.y + this.height; + } + /** + * Checks whether the x and y coordinates given are contained within this rectangle including the stroke. + * @example + * ```ts + * // Basic stroke check + * const rect = new Rectangle(100, 100, 200, 150); + * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width + * + * // Check with different alignments + * const innerStroke = rect.strokeContains(150, 100, 4, 1); // Inside + * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered + * const outerStroke = rect.strokeContains(150, 100, 4, 0); // Outside + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @param strokeWidth - The width of the line to check + * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer) + * @returns Whether the x/y coordinates are within this rectangle's stroke + * @see {@link Rectangle.contains} For checking fill containment + * @see {@link Rectangle.getBounds} For getting stroke bounds + */ + strokeContains(e, t, n, s = 0.5) { + const { width: r, height: a } = this; + if (r <= 0 || a <= 0) + return !1; + const o = this.x, l = this.y, h = n * (1 - s), u = n - h, c = o - h, d = o + r + h, f = l - h, _ = l + a + h, b = o + u, m = o + r - u, x = l + u, g = l + a - u; + return e >= c && e <= d && t >= f && t <= _ && !(e > b && e < m && t > x && t < g); + } + /** + * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object. + * Returns true only if the area of the intersection is >0, this means that Rectangles + * sharing a side are not overlapping. Another side effect is that an arealess rectangle + * (width or height equal to zero) can't intersect any other rectangle. + * @param {Rectangle} other - The Rectangle to intersect with `this`. + * @param {Matrix} transform - The transformation matrix of `other`. + * @returns {boolean} A value of `true` if the transformed `other` Rectangle intersects with `this`; otherwise `false`. + */ + /** + * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object. + * + * Returns true only if the area of the intersection is greater than 0. + * This means that rectangles sharing only a side are not considered intersecting. + * @example + * ```ts + * // Basic intersection check + * const rect1 = new Rectangle(0, 0, 100, 100); + * const rect2 = new Rectangle(50, 50, 100, 100); + * console.log(rect1.intersects(rect2)); // true + * + * // With transformation matrix + * const matrix = new Matrix(); + * matrix.rotate(Math.PI / 4); // 45 degrees + * console.log(rect1.intersects(rect2, matrix)); // Checks with rotation + * + * // Edge cases + * const zeroWidth = new Rectangle(0, 0, 0, 100); + * console.log(rect1.intersects(zeroWidth)); // false (no area) + * ``` + * @remarks + * - Returns true only if intersection area is > 0 + * - Rectangles sharing only a side are not intersecting + * - Zero-area rectangles cannot intersect anything + * - Supports optional transformation matrix + * @param other - The Rectangle to intersect with `this` + * @param transform - Optional transformation matrix of `other` + * @returns True if the transformed `other` Rectangle intersects with `this` + * @see {@link Rectangle.containsRect} For containment testing + * @see {@link Rectangle.contains} For point testing + */ + intersects(e, t) { + if (!t) { + const D = this.x < e.x ? e.x : this.x; + if ((this.right > e.right ? e.right : this.right) <= D) + return !1; + const A = this.y < e.y ? e.y : this.y; + return (this.bottom > e.bottom ? e.bottom : this.bottom) > A; + } + const n = this.left, s = this.right, r = this.top, a = this.bottom; + if (s <= n || a <= r) + return !1; + const o = Un[0].set(e.left, e.top), l = Un[1].set(e.left, e.bottom), h = Un[2].set(e.right, e.top), u = Un[3].set(e.right, e.bottom); + if (h.x <= o.x || l.y <= o.y) + return !1; + const c = Math.sign(t.a * t.d - t.b * t.c); + if (c === 0 || (t.apply(o, o), t.apply(l, l), t.apply(h, h), t.apply(u, u), Math.max(o.x, l.x, h.x, u.x) <= n || Math.min(o.x, l.x, h.x, u.x) >= s || Math.max(o.y, l.y, h.y, u.y) <= r || Math.min(o.y, l.y, h.y, u.y) >= a)) + return !1; + const d = c * (l.y - o.y), f = c * (o.x - l.x), _ = d * n + f * r, b = d * s + f * r, m = d * n + f * a, x = d * s + f * a; + if (Math.max(_, b, m, x) <= d * o.x + f * o.y || Math.min(_, b, m, x) >= d * u.x + f * u.y) + return !1; + const g = c * (o.y - h.y), p = c * (h.x - o.x), y = g * n + p * r, C = g * s + p * r, w = g * n + p * a, v = g * s + p * a; + return !(Math.max(y, C, w, v) <= g * o.x + p * o.y || Math.min(y, C, w, v) >= g * u.x + p * u.y); + } + /** + * Pads the rectangle making it grow in all directions. + * + * If paddingY is omitted, both paddingX and paddingY will be set to paddingX. + * @example + * ```ts + * // Basic padding + * const rect = new Rectangle(100, 100, 200, 150); + * rect.pad(10); // Adds 10px padding on all sides + * + * // Different horizontal and vertical padding + * const uiRect = new Rectangle(0, 0, 100, 50); + * uiRect.pad(20, 10); // 20px horizontal, 10px vertical + * ``` + * @remarks + * - Adjusts x/y by subtracting padding + * - Increases width/height by padding * 2 + * - Common in UI layout calculations + * - Chainable with other methods + * @param paddingX - The horizontal padding amount + * @param paddingY - The vertical padding amount + * @returns Returns itself + * @see {@link Rectangle.enlarge} For growing to include another rectangle + * @see {@link Rectangle.fit} For shrinking to fit within another rectangle + */ + pad(e = 0, t = e) { + return this.x -= e, this.y -= t, this.width += e * 2, this.height += t * 2, this; + } + /** + * Fits this rectangle around the passed one. + * @example + * ```ts + * // Basic fitting + * const container = new Rectangle(0, 0, 100, 100); + * const content = new Rectangle(25, 25, 200, 200); + * content.fit(container); // Clips to container bounds + * ``` + * @param rectangle - The rectangle to fit around + * @returns Returns itself + * @see {@link Rectangle.enlarge} For growing to include another rectangle + * @see {@link Rectangle.pad} For adding padding around the rectangle + */ + fit(e) { + const t = Math.max(this.x, e.x), n = Math.min(this.x + this.width, e.x + e.width), s = Math.max(this.y, e.y), r = Math.min(this.y + this.height, e.y + e.height); + return this.x = t, this.width = Math.max(n - t, 0), this.y = s, this.height = Math.max(r - s, 0), this; + } + /** + * Enlarges rectangle so that its corners lie on a grid defined by resolution. + * @example + * ```ts + * // Basic grid alignment + * const rect = new Rectangle(10.2, 10.6, 100.8, 100.4); + * rect.ceil(); // Aligns to whole pixels + * + * // Custom resolution grid + * const uiRect = new Rectangle(5.3, 5.7, 50.2, 50.8); + * uiRect.ceil(0.5); // Aligns to half pixels + * + * // Use with precision value + * const preciseRect = new Rectangle(20.001, 20.999, 100.001, 100.999); + * preciseRect.ceil(1, 0.01); // Handles small decimal variations + * ``` + * @param resolution - The grid size to align to (1 = whole pixels) + * @param eps - Small number to prevent floating point errors + * @returns Returns itself + * @see {@link Rectangle.fit} For constraining to bounds + * @see {@link Rectangle.enlarge} For growing dimensions + */ + ceil(e = 1, t = 1e-3) { + const n = Math.ceil((this.x + this.width - t) * e) / e, s = Math.ceil((this.y + this.height - t) * e) / e; + return this.x = Math.floor((this.x + t) * e) / e, this.y = Math.floor((this.y + t) * e) / e, this.width = n - this.x, this.height = s - this.y, this; + } + /** + * Scales the rectangle's dimensions and position by the specified factors. + * @example + * ```ts + * const rect = new Rectangle(50, 50, 100, 100); + * + * // Scale uniformly + * rect.scale(0.5, 0.5); + * // rect is now: x=25, y=25, width=50, height=50 + * + * // non-uniformly + * rect.scale(0.5, 1); + * // rect is now: x=25, y=50, width=50, height=100 + * ``` + * @param x - The factor by which to scale the horizontal properties (x, width). + * @param y - The factor by which to scale the vertical properties (y, height). + * @returns Returns itself + */ + scale(e, t = e) { + return this.x *= e, this.y *= t, this.width *= e, this.height *= t, this; + } + /** + * Enlarges this rectangle to include the passed rectangle. + * @example + * ```ts + * // Basic enlargement + * const rect = new Rectangle(50, 50, 100, 100); + * const other = new Rectangle(0, 0, 200, 75); + * rect.enlarge(other); + * // rect is now: x=0, y=0, width=200, height=150 + * + * // Use for bounding box calculation + * const bounds = new Rectangle(); + * objects.forEach((obj) => { + * bounds.enlarge(obj.getBounds()); + * }); + * ``` + * @param rectangle - The rectangle to include + * @returns Returns itself + * @see {@link Rectangle.fit} For shrinking to fit within another rectangle + * @see {@link Rectangle.pad} For adding padding around the rectangle + */ + enlarge(e) { + const t = Math.min(this.x, e.x), n = Math.max(this.x + this.width, e.x + e.width), s = Math.min(this.y, e.y), r = Math.max(this.y + this.height, e.y + e.height); + return this.x = t, this.width = n - t, this.y = s, this.height = r - s, this; + } + /** + * Returns the framing rectangle of the rectangle as a Rectangle object + * @example + * ```ts + * // Basic bounds retrieval + * const rect = new Rectangle(100, 100, 200, 150); + * const bounds = rect.getBounds(); + * + * // Reuse existing rectangle + * const out = new Rectangle(); + * rect.getBounds(out); + * ``` + * @param out - Optional rectangle to store the result + * @returns The framing rectangle + * @see {@link Rectangle.copyFrom} For direct copying + * @see {@link Rectangle.clone} For creating new copy + */ + getBounds(e) { + return e || (e = new de()), e.copyFrom(this), e; + } + /** + * Determines whether another Rectangle is fully contained within this Rectangle. + * + * Rectangles that occupy the same space are considered to be containing each other. + * + * Rectangles without area (width or height equal to zero) can't contain anything, + * not even other arealess rectangles. + * @example + * ```ts + * // Check if one rectangle contains another + * const container = new Rectangle(0, 0, 100, 100); + * const inner = new Rectangle(25, 25, 50, 50); + * + * console.log(container.containsRect(inner)); // true + * + * // Check overlapping rectangles + * const partial = new Rectangle(75, 75, 50, 50); + * console.log(container.containsRect(partial)); // false + * + * // Zero-area rectangles + * const empty = new Rectangle(0, 0, 0, 100); + * console.log(container.containsRect(empty)); // false + * ``` + * @param other - The Rectangle to check for containment + * @returns True if other is fully contained within this Rectangle + * @see {@link Rectangle.contains} For point containment + * @see {@link Rectangle.intersects} For overlap testing + */ + containsRect(e) { + if (this.width <= 0 || this.height <= 0) + return !1; + const t = e.x, n = e.y, s = e.x + e.width, r = e.y + e.height; + return t >= this.x && t < this.x + this.width && n >= this.y && n < this.y + this.height && s >= this.x && s < this.x + this.width && r >= this.y && r < this.y + this.height; + } + /** + * Sets the position and dimensions of the rectangle. + * @example + * ```ts + * // Basic usage + * const rect = new Rectangle(); + * rect.set(100, 100, 200, 150); + * + * // Chain with other operations + * const bounds = new Rectangle() + * .set(0, 0, 100, 100) + * .pad(10); + * ``` + * @param x - The X coordinate of the upper-left corner of the rectangle + * @param y - The Y coordinate of the upper-left corner of the rectangle + * @param width - The overall width of the rectangle + * @param height - The overall height of the rectangle + * @returns Returns itself for method chaining + * @see {@link Rectangle.copyFrom} For copying from another rectangle + * @see {@link Rectangle.clone} For creating a new copy + */ + set(e, t, n, s) { + return this.x = e, this.y = t, this.width = n, this.height = s, this; + } + toString() { + return `[pixi.js/math:Rectangle x=${this.x} y=${this.y} width=${this.width} height=${this.height}]`; + } +} +const Pi = { + default: -1 +}; +function ue(i = "default") { + return Pi[i] === void 0 && (Pi[i] = -1), ++Pi[i]; +} +const yr = /* @__PURE__ */ new Set(), he = "8.0.0", Ph = "8.3.4", Qt = { + quiet: !1, + noColor: !1 +}, W = (i, e, t = 3) => { + if (Qt.quiet || yr.has(e)) + return; + let n = new Error().stack; + const s = `${e} +Deprecated since v${i}`, r = typeof console.groupCollapsed == "function" && !Qt.noColor; + typeof n > "u" ? console.warn("PixiJS Deprecation Warning: ", s) : (n = n.split(` +`).splice(t).join(` +`), r ? (console.groupCollapsed( + "%cPixiJS Deprecation Warning: %c%s", + "color:#614108;background:#fffbe6", + "font-weight:normal;color:#614108;background:#fffbe6", + s + ), console.warn(n), console.groupEnd()) : (console.warn("PixiJS Deprecation Warning: ", s), console.warn(n))), yr.add(e); +}; +Object.defineProperties(W, { + quiet: { + get: () => Qt.quiet, + set: (i) => { + Qt.quiet = i; + }, + enumerable: !0, + configurable: !1 + }, + noColor: { + get: () => Qt.noColor, + set: (i) => { + Qt.noColor = i; + }, + enumerable: !0, + configurable: !1 + } +}); +const Ao = () => { +}; +function tn(i) { + return i += i === 0 ? 1 : 0, --i, i |= i >>> 1, i |= i >>> 2, i |= i >>> 4, i |= i >>> 8, i |= i >>> 16, i + 1; +} +function br(i) { + return !(i & i - 1) && !!i; +} +function Do(i) { + const e = {}; + for (const t in i) + i[t] !== void 0 && (e[t] = i[t]); + return e; +} +const xr = /* @__PURE__ */ Object.create(null); +function Ih(i) { + const e = xr[i]; + return e === void 0 && (xr[i] = ue("resource")), e; +} +const Eo = class Fo extends xt { + /** + * @param options - options for the style + */ + constructor(e = {}) { + super(), this._resourceType = "textureSampler", this._touched = 0, this._maxAnisotropy = 1, this.destroyed = !1, e = { ...Fo.defaultOptions, ...e }, this.addressMode = e.addressMode, this.addressModeU = e.addressModeU ?? this.addressModeU, this.addressModeV = e.addressModeV ?? this.addressModeV, this.addressModeW = e.addressModeW ?? this.addressModeW, this.scaleMode = e.scaleMode, this.magFilter = e.magFilter ?? this.magFilter, this.minFilter = e.minFilter ?? this.minFilter, this.mipmapFilter = e.mipmapFilter ?? this.mipmapFilter, this.lodMinClamp = e.lodMinClamp, this.lodMaxClamp = e.lodMaxClamp, this.compare = e.compare, this.maxAnisotropy = e.maxAnisotropy ?? 1; + } + set addressMode(e) { + this.addressModeU = e, this.addressModeV = e, this.addressModeW = e; + } + /** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */ + get addressMode() { + return this.addressModeU; + } + set wrapMode(e) { + W(he, "TextureStyle.wrapMode is now TextureStyle.addressMode"), this.addressMode = e; + } + get wrapMode() { + return this.addressMode; + } + set scaleMode(e) { + this.magFilter = e, this.minFilter = e, this.mipmapFilter = e; + } + /** setting this will set magFilter,minFilter and mipmapFilter all at once! */ + get scaleMode() { + return this.magFilter; + } + /** Specifies the maximum anisotropy value clamp used by the sampler. */ + set maxAnisotropy(e) { + this._maxAnisotropy = Math.min(e, 16), this._maxAnisotropy > 1 && (this.scaleMode = "linear"); + } + get maxAnisotropy() { + return this._maxAnisotropy; + } + // TODO - move this to WebGL? + get _resourceId() { + return this._sharedResourceId || this._generateResourceId(); + } + update() { + this.emit("change", this), this._sharedResourceId = null; + } + _generateResourceId() { + const e = `${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`; + return this._sharedResourceId = Ih(e), this._resourceId; + } + /** Destroys the style */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this.removeAllListeners(); + } +}; +Eo.defaultOptions = { + addressMode: "clamp-to-edge", + scaleMode: "linear" +}; +let _i = Eo; +const $o = class To extends xt { + /** + * @param options - options for creating a new TextureSource + */ + constructor(e = {}) { + super(), this.options = e, this.uid = ue("textureSource"), this._resourceType = "textureSource", this._resourceId = ue("resource"), this.uploadMethodId = "unknown", this._resolution = 1, this.pixelWidth = 1, this.pixelHeight = 1, this.width = 1, this.height = 1, this.sampleCount = 1, this.mipLevelCount = 1, this.autoGenerateMipmaps = !1, this.format = "rgba8unorm", this.dimension = "2d", this.antialias = !1, this._touched = 0, this._batchTick = -1, this._textureBindLocation = -1, e = { ...To.defaultOptions, ...e }, this.label = e.label ?? "", this.resource = e.resource, this.autoGarbageCollect = e.autoGarbageCollect, this._resolution = e.resolution, e.width ? this.pixelWidth = e.width * this._resolution : this.pixelWidth = this.resource ? this.resourceWidth ?? 1 : 1, e.height ? this.pixelHeight = e.height * this._resolution : this.pixelHeight = this.resource ? this.resourceHeight ?? 1 : 1, this.width = this.pixelWidth / this._resolution, this.height = this.pixelHeight / this._resolution, this.format = e.format, this.dimension = e.dimensions, this.mipLevelCount = e.mipLevelCount, this.autoGenerateMipmaps = e.autoGenerateMipmaps, this.sampleCount = e.sampleCount, this.antialias = e.antialias, this.alphaMode = e.alphaMode, this.style = new _i(Do(e)), this.destroyed = !1, this._refreshPOT(); + } + /** returns itself */ + get source() { + return this; + } + /** the style of the texture */ + get style() { + return this._style; + } + set style(e) { + var t, n; + this.style !== e && ((t = this._style) == null || t.off("change", this._onStyleChange, this), this._style = e, (n = this._style) == null || n.on("change", this._onStyleChange, this), this._onStyleChange()); + } + /** Specifies the maximum anisotropy value clamp used by the sampler. */ + set maxAnisotropy(e) { + this._style.maxAnisotropy = e; + } + get maxAnisotropy() { + return this._style.maxAnisotropy; + } + /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */ + get addressMode() { + return this._style.addressMode; + } + set addressMode(e) { + this._style.addressMode = e; + } + /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */ + get repeatMode() { + return this._style.addressMode; + } + set repeatMode(e) { + this._style.addressMode = e; + } + /** Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel. */ + get magFilter() { + return this._style.magFilter; + } + set magFilter(e) { + this._style.magFilter = e; + } + /** Specifies the sampling behavior when the sample footprint is larger than one texel. */ + get minFilter() { + return this._style.minFilter; + } + set minFilter(e) { + this._style.minFilter = e; + } + /** Specifies behavior for sampling between mipmap levels. */ + get mipmapFilter() { + return this._style.mipmapFilter; + } + set mipmapFilter(e) { + this._style.mipmapFilter = e; + } + /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */ + get lodMinClamp() { + return this._style.lodMinClamp; + } + set lodMinClamp(e) { + this._style.lodMinClamp = e; + } + /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */ + get lodMaxClamp() { + return this._style.lodMaxClamp; + } + set lodMaxClamp(e) { + this._style.lodMaxClamp = e; + } + _onStyleChange() { + this.emit("styleChange", this); + } + /** call this if you have modified the texture outside of the constructor */ + update() { + if (this.resource) { + const e = this._resolution; + if (this.resize(this.resourceWidth / e, this.resourceHeight / e)) + return; + } + this.emit("update", this); + } + /** Destroys this texture source */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this._style && (this._style.destroy(), this._style = null), this.uploadMethodId = null, this.resource = null, this.removeAllListeners(); + } + /** + * This will unload the Texture source from the GPU. This will free up the GPU memory + * As soon as it is required fore rendering, it will be re-uploaded. + */ + unload() { + this._resourceId = ue("resource"), this.emit("change", this), this.emit("unload", this); + } + /** the width of the resource. This is the REAL pure number, not accounting resolution */ + get resourceWidth() { + const { resource: e } = this; + return e.naturalWidth || e.videoWidth || e.displayWidth || e.width; + } + /** the height of the resource. This is the REAL pure number, not accounting resolution */ + get resourceHeight() { + const { resource: e } = this; + return e.naturalHeight || e.videoHeight || e.displayHeight || e.height; + } + /** + * the resolution of the texture. Changing this number, will not change the number of pixels in the actual texture + * but will the size of the texture when rendered. + * + * changing the resolution of this texture to 2 for example will make it appear twice as small when rendered (as pixel + * density will have increased) + */ + get resolution() { + return this._resolution; + } + set resolution(e) { + this._resolution !== e && (this._resolution = e, this.width = this.pixelWidth / e, this.height = this.pixelHeight / e); + } + /** + * Resize the texture, this is handy if you want to use the texture as a render texture + * @param width - the new width of the texture + * @param height - the new height of the texture + * @param resolution - the new resolution of the texture + * @returns - if the texture was resized + */ + resize(e, t, n) { + n || (n = this._resolution), e || (e = this.width), t || (t = this.height); + const s = Math.round(e * n), r = Math.round(t * n); + return this.width = s / n, this.height = r / n, this._resolution = n, this.pixelWidth === s && this.pixelHeight === r ? !1 : (this._refreshPOT(), this.pixelWidth = s, this.pixelHeight = r, this.emit("resize", this), this._resourceId = ue("resource"), this.emit("change", this), !0); + } + /** + * Lets the renderer know that this texture has been updated and its mipmaps should be re-generated. + * This is only important for RenderTexture instances, as standard Texture instances will have their + * mipmaps generated on upload. You should call this method after you make any change to the texture + * + * The reason for this is is can be quite expensive to update mipmaps for a texture. So by default, + * We want you, the developer to specify when this action should happen. + * + * Generally you don't want to have mipmaps generated on Render targets that are changed every frame, + */ + updateMipmaps() { + this.autoGenerateMipmaps && this.mipLevelCount > 1 && this.emit("updateMipmaps", this); + } + set wrapMode(e) { + this._style.wrapMode = e; + } + get wrapMode() { + return this._style.wrapMode; + } + set scaleMode(e) { + this._style.scaleMode = e; + } + /** setting this will set magFilter,minFilter and mipmapFilter all at once! */ + get scaleMode() { + return this._style.scaleMode; + } + /** + * Refresh check for isPowerOfTwo texture based on size + * @private + */ + _refreshPOT() { + this.isPowerOfTwo = br(this.pixelWidth) && br(this.pixelHeight); + } + static test(e) { + throw new Error("Unimplemented"); + } +}; +$o.defaultOptions = { + resolution: 1, + format: "bgra8unorm", + alphaMode: "premultiply-alpha-on-upload", + dimensions: "2d", + mipLevelCount: 1, + autoGenerateMipmaps: !1, + sampleCount: 1, + antialias: !1, + autoGarbageCollect: !1 +}; +let ut = $o; +class Hs extends ut { + constructor(e) { + const t = e.resource || new Float32Array(e.width * e.height * 4); + let n = e.format; + n || (t instanceof Float32Array ? n = "rgba32float" : t instanceof Int32Array || t instanceof Uint32Array ? n = "rgba32uint" : t instanceof Int16Array || t instanceof Uint16Array ? n = "rgba16uint" : (t instanceof Int8Array, n = "bgra8unorm")), super({ + ...e, + resource: t, + format: n + }), this.uploadMethodId = "buffer"; + } + static test(e) { + return e instanceof Int8Array || e instanceof Uint8Array || e instanceof Uint8ClampedArray || e instanceof Int16Array || e instanceof Uint16Array || e instanceof Int32Array || e instanceof Uint32Array || e instanceof Float32Array; + } +} +Hs.extension = Q.TextureSource; +const wr = new H(); +class Rh { + /** + * @param texture - observed texture + * @param clampMargin - Changes frame clamping, 0.5 by default. Use -0.5 for extra border. + */ + constructor(e, t) { + this.mapCoord = new H(), this.uClampFrame = new Float32Array(4), this.uClampOffset = new Float32Array(2), this._textureID = -1, this._updateID = 0, this.clampOffset = 0, typeof t > "u" ? this.clampMargin = e.width < 10 ? 0 : 0.5 : this.clampMargin = t, this.isSimple = !1, this.texture = e; + } + /** Texture property. */ + get texture() { + return this._texture; + } + set texture(e) { + var t; + this.texture !== e && ((t = this._texture) == null || t.removeListener("update", this.update, this), this._texture = e, this._texture.addListener("update", this.update, this), this.update()); + } + /** + * Multiplies uvs array to transform + * @param uvs - mesh uvs + * @param [out=uvs] - output + * @returns - output + */ + multiplyUvs(e, t) { + t === void 0 && (t = e); + const n = this.mapCoord; + for (let s = 0; s < e.length; s += 2) { + const r = e[s], a = e[s + 1]; + t[s] = r * n.a + a * n.c + n.tx, t[s + 1] = r * n.b + a * n.d + n.ty; + } + return t; + } + /** + * Updates matrices if texture was changed + * @returns - whether or not it was updated + */ + update() { + const e = this._texture; + this._updateID++; + const t = e.uvs; + this.mapCoord.set(t.x1 - t.x0, t.y1 - t.y0, t.x3 - t.x0, t.y3 - t.y0, t.x0, t.y0); + const n = e.orig, s = e.trim; + s && (wr.set( + n.width / s.width, + 0, + 0, + n.height / s.height, + -s.x / s.width, + -s.y / s.height + ), this.mapCoord.append(wr)); + const r = e.source, a = this.uClampFrame, o = this.clampMargin / r._resolution, l = this.clampOffset / r._resolution; + return a[0] = (e.frame.x + o + l) / r.width, a[1] = (e.frame.y + o + l) / r.height, a[2] = (e.frame.x + e.frame.width - o + l) / r.width, a[3] = (e.frame.y + e.frame.height - o + l) / r.height, this.uClampOffset[0] = this.clampOffset / r.pixelWidth, this.uClampOffset[1] = this.clampOffset / r.pixelHeight, this.isSimple = e.frame.width === r.width && e.frame.height === r.height && e.rotate === 0, !0; + } +} +class K extends xt { + /** + * @param {TextureOptions} options - Options for the texture + */ + constructor({ + source: e, + label: t, + frame: n, + orig: s, + trim: r, + defaultAnchor: a, + defaultBorders: o, + rotate: l, + dynamic: h + } = {}) { + if (super(), this.uid = ue("texture"), this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 }, this.frame = new de(), this.noFrame = !1, this.dynamic = !1, this.isTexture = !0, this.label = t, this.source = (e == null ? void 0 : e.source) ?? new ut(), this.noFrame = !n, n) + this.frame.copyFrom(n); + else { + const { width: u, height: c } = this._source; + this.frame.width = u, this.frame.height = c; + } + this.orig = s || this.frame, this.trim = r, this.rotate = l ?? 0, this.defaultAnchor = a, this.defaultBorders = o, this.destroyed = !1, this.dynamic = h || !1, this.updateUvs(); + } + set source(e) { + this._source && this._source.off("resize", this.update, this), this._source = e, e.on("resize", this.update, this), this.emit("update", this); + } + /** the underlying source of the texture (equivalent of baseTexture in v7) */ + get source() { + return this._source; + } + /** returns a TextureMatrix instance for this texture. By default, that object is not created because its heavy. */ + get textureMatrix() { + return this._textureMatrix || (this._textureMatrix = new Rh(this)), this._textureMatrix; + } + /** The width of the Texture in pixels. */ + get width() { + return this.orig.width; + } + /** The height of the Texture in pixels. */ + get height() { + return this.orig.height; + } + /** Call this function when you have modified the frame of this texture. */ + updateUvs() { + const { uvs: e, frame: t } = this, { width: n, height: s } = this._source, r = t.x / n, a = t.y / s, o = t.width / n, l = t.height / s; + let h = this.rotate; + if (h) { + const u = o / 2, c = l / 2, d = r + u, f = a + c; + h = te.add(h, te.NW), e.x0 = d + u * te.uX(h), e.y0 = f + c * te.uY(h), h = te.add(h, 2), e.x1 = d + u * te.uX(h), e.y1 = f + c * te.uY(h), h = te.add(h, 2), e.x2 = d + u * te.uX(h), e.y2 = f + c * te.uY(h), h = te.add(h, 2), e.x3 = d + u * te.uX(h), e.y3 = f + c * te.uY(h); + } else + e.x0 = r, e.y0 = a, e.x1 = r + o, e.y1 = a, e.x2 = r + o, e.y2 = a + l, e.x3 = r, e.y3 = a + l; + } + /** + * Destroys this texture + * @param destroySource - Destroy the source when the texture is destroyed. + */ + destroy(e = !1) { + this._source && e && (this._source.destroy(), this._source = null), this._textureMatrix = null, this.destroyed = !0, this.emit("destroy", this), this.removeAllListeners(); + } + /** + * Call this if you have modified the `texture outside` of the constructor. + * + * If you have modified this texture's source, you must separately call `texture.source.update()` to see those changes. + */ + update() { + this.noFrame && (this.frame.width = this._source.width, this.frame.height = this._source.height), this.updateUvs(), this.emit("update", this); + } + /** @deprecated since 8.0.0 */ + get baseTexture() { + return W(he, "Texture.baseTexture is now Texture.source"), this._source; + } +} +K.EMPTY = new K({ + label: "EMPTY", + source: new ut({ + label: "EMPTY" + }) +}); +K.EMPTY.destroy = Ao; +K.WHITE = new K({ + source: new Hs({ + resource: new Uint8Array([255, 255, 255, 255]), + width: 1, + height: 1, + alphaMode: "premultiply-alpha-on-upload", + label: "WHITE" + }), + label: "WHITE" +}); +K.WHITE.destroy = Ao; +function Bh(i, e, t) { + const { width: n, height: s } = t.orig, r = t.trim; + if (r) { + const a = r.width, o = r.height; + i.minX = r.x - e._x * n, i.maxX = i.minX + a, i.minY = r.y - e._y * s, i.maxY = i.minY + o; + } else + i.minX = -e._x * n, i.maxX = i.minX + n, i.minY = -e._y * s, i.maxY = i.minY + s; +} +const vr = new H(); +class ht { + /** + * Creates a new Bounds object. + * @param minX - The minimum X coordinate of the bounds. + * @param minY - The minimum Y coordinate of the bounds. + * @param maxX - The maximum X coordinate of the bounds. + * @param maxY - The maximum Y coordinate of the bounds. + */ + constructor(e = 1 / 0, t = 1 / 0, n = -1 / 0, s = -1 / 0) { + this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = vr, this.minX = e, this.minY = t, this.maxX = n, this.maxY = s; + } + /** + * Checks if bounds are empty, meaning either width or height is zero or negative. + * Empty bounds occur when min values exceed max values on either axis. + * @example + * ```ts + * const bounds = new Bounds(); + * + * // Check if newly created bounds are empty + * console.log(bounds.isEmpty()); // true, default bounds are empty + * + * // Add frame and check again + * bounds.addFrame(0, 0, 100, 100); + * console.log(bounds.isEmpty()); // false, bounds now have area + * + * // Clear bounds + * bounds.clear(); + * console.log(bounds.isEmpty()); // true, bounds are empty again + * ``` + * @returns True if bounds are empty (have no area) + * @see {@link Bounds#clear} For resetting bounds + * @see {@link Bounds#isValid} For checking validity + */ + isEmpty() { + return this.minX > this.maxX || this.minY > this.maxY; + } + /** + * The bounding rectangle representation of these bounds. + * Lazily creates and updates a Rectangle instance based on the current bounds. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * + * // Get rectangle representation + * const rect = bounds.rectangle; + * console.log(rect.x, rect.y, rect.width, rect.height); + * + * // Use for hit testing + * if (bounds.rectangle.contains(mouseX, mouseY)) { + * console.log('Mouse is inside bounds!'); + * } + * ``` + * @see {@link Rectangle} For rectangle methods + * @see {@link Bounds.isEmpty} For bounds validation + */ + get rectangle() { + this._rectangle || (this._rectangle = new de()); + const e = this._rectangle; + return this.minX > this.maxX || this.minY > this.maxY ? (e.x = 0, e.y = 0, e.width = 0, e.height = 0) : e.copyFromBounds(this), e; + } + /** + * Clears the bounds and resets all coordinates to their default values. + * Resets the transformation matrix back to identity. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * console.log(bounds.isEmpty()); // false + * // Clear the bounds + * bounds.clear(); + * console.log(bounds.isEmpty()); // true + * ``` + * @returns This bounds object for chaining + */ + clear() { + return this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = vr, this; + } + /** + * Sets the bounds directly using coordinate values. + * Provides a way to set all bounds values at once. + * @example + * ```ts + * const bounds = new Bounds(); + * bounds.set(0, 0, 100, 100); + * ``` + * @param x0 - Left X coordinate of frame + * @param y0 - Top Y coordinate of frame + * @param x1 - Right X coordinate of frame + * @param y1 - Bottom Y coordinate of frame + * @see {@link Bounds#addFrame} For matrix-aware bounds setting + * @see {@link Bounds#clear} For resetting bounds + */ + set(e, t, n, s) { + this.minX = e, this.minY = t, this.maxX = n, this.maxY = s; + } + /** + * Adds a rectangular frame to the bounds, optionally transformed by a matrix. + * Updates the bounds to encompass the new frame coordinates. + * @example + * ```ts + * const bounds = new Bounds(); + * bounds.addFrame(0, 0, 100, 100); + * + * // Add transformed frame + * const matrix = new Matrix() + * .translate(50, 50) + * .rotate(Math.PI / 4); + * bounds.addFrame(0, 0, 100, 100, matrix); + * ``` + * @param x0 - Left X coordinate of frame + * @param y0 - Top Y coordinate of frame + * @param x1 - Right X coordinate of frame + * @param y1 - Bottom Y coordinate of frame + * @param matrix - Optional transformation matrix + * @see {@link Bounds#addRect} For adding Rectangle objects + * @see {@link Bounds#addBounds} For adding other Bounds + */ + addFrame(e, t, n, s, r) { + r || (r = this.matrix); + const a = r.a, o = r.b, l = r.c, h = r.d, u = r.tx, c = r.ty; + let d = this.minX, f = this.minY, _ = this.maxX, b = this.maxY, m = a * e + l * t + u, x = o * e + h * t + c; + m < d && (d = m), x < f && (f = x), m > _ && (_ = m), x > b && (b = x), m = a * n + l * t + u, x = o * n + h * t + c, m < d && (d = m), x < f && (f = x), m > _ && (_ = m), x > b && (b = x), m = a * e + l * s + u, x = o * e + h * s + c, m < d && (d = m), x < f && (f = x), m > _ && (_ = m), x > b && (b = x), m = a * n + l * s + u, x = o * n + h * s + c, m < d && (d = m), x < f && (f = x), m > _ && (_ = m), x > b && (b = x), this.minX = d, this.minY = f, this.maxX = _, this.maxY = b; + } + /** + * Adds a rectangle to the bounds, optionally transformed by a matrix. + * Updates the bounds to encompass the given rectangle. + * @example + * ```ts + * const bounds = new Bounds(); + * // Add simple rectangle + * const rect = new Rectangle(0, 0, 100, 100); + * bounds.addRect(rect); + * + * // Add transformed rectangle + * const matrix = new Matrix() + * .translate(50, 50) + * .rotate(Math.PI / 4); + * bounds.addRect(rect, matrix); + * ``` + * @param rect - The rectangle to be added + * @param matrix - Optional transformation matrix + * @see {@link Bounds#addFrame} For adding raw coordinates + * @see {@link Bounds#addBounds} For adding other bounds + */ + addRect(e, t) { + this.addFrame(e.x, e.y, e.x + e.width, e.y + e.height, t); + } + /** + * Adds another bounds object to this one, optionally transformed by a matrix. + * Expands the bounds to include the given bounds' area. + * @example + * ```ts + * const bounds = new Bounds(); + * + * // Add child bounds + * const childBounds = sprite.getBounds(); + * bounds.addBounds(childBounds); + * + * // Add transformed bounds + * const matrix = new Matrix() + * .scale(2, 2); + * bounds.addBounds(childBounds, matrix); + * ``` + * @param bounds - The bounds to be added + * @param matrix - Optional transformation matrix + * @see {@link Bounds#addFrame} For adding raw coordinates + * @see {@link Bounds#addRect} For adding rectangles + */ + addBounds(e, t) { + this.addFrame(e.minX, e.minY, e.maxX, e.maxY, t); + } + /** + * Adds other Bounds as a mask, creating an intersection of the two bounds. + * Only keeps the overlapping region between current bounds and mask bounds. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Create mask bounds + * const mask = new Bounds(); + * mask.addFrame(50, 50, 150, 150); + * // Apply mask - results in bounds of (50,50,100,100) + * bounds.addBoundsMask(mask); + * ``` + * @param mask - The Bounds to use as a mask + * @see {@link Bounds#addBounds} For union operation + * @see {@link Bounds#fit} For fitting to rectangle + */ + addBoundsMask(e) { + this.minX = this.minX > e.minX ? this.minX : e.minX, this.minY = this.minY > e.minY ? this.minY : e.minY, this.maxX = this.maxX < e.maxX ? this.maxX : e.maxX, this.maxY = this.maxY < e.maxY ? this.maxY : e.maxY; + } + /** + * Applies a transformation matrix to the bounds, updating its coordinates. + * Transforms all corners of the bounds using the given matrix. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Apply translation + * const translateMatrix = new Matrix() + * .translate(50, 50); + * bounds.applyMatrix(translateMatrix); + * ``` + * @param matrix - The matrix to apply to the bounds + * @see {@link Matrix} For matrix operations + * @see {@link Bounds#addFrame} For adding transformed frames + */ + applyMatrix(e) { + const t = this.minX, n = this.minY, s = this.maxX, r = this.maxY, { a, b: o, c: l, d: h, tx: u, ty: c } = e; + let d = a * t + l * n + u, f = o * t + h * n + c; + this.minX = d, this.minY = f, this.maxX = d, this.maxY = f, d = a * s + l * n + u, f = o * s + h * n + c, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY, d = a * t + l * r + u, f = o * t + h * r + c, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY, d = a * s + l * r + u, f = o * s + h * r + c, this.minX = d < this.minX ? d : this.minX, this.minY = f < this.minY ? f : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = f > this.maxY ? f : this.maxY; + } + /** + * Resizes the bounds object to fit within the given rectangle. + * Clips the bounds if they extend beyond the rectangle's edges. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 200, 200); + * // Fit within viewport + * const viewport = new Rectangle(50, 50, 100, 100); + * bounds.fit(viewport); + * // bounds are now (50, 50, 150, 150) + * ``` + * @param rect - The rectangle to fit within + * @returns This bounds object for chaining + * @see {@link Bounds#addBoundsMask} For intersection + * @see {@link Bounds#pad} For expanding bounds + */ + fit(e) { + return this.minX < e.left && (this.minX = e.left), this.maxX > e.right && (this.maxX = e.right), this.minY < e.top && (this.minY = e.top), this.maxY > e.bottom && (this.maxY = e.bottom), this; + } + /** + * Resizes the bounds object to include the given bounds. + * Similar to fit() but works with raw coordinate values instead of a Rectangle. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 200, 200); + * // Fit to specific coordinates + * bounds.fitBounds(50, 150, 50, 150); + * // bounds are now (50, 50, 150, 150) + * ``` + * @param left - The left value of the bounds + * @param right - The right value of the bounds + * @param top - The top value of the bounds + * @param bottom - The bottom value of the bounds + * @returns This bounds object for chaining + * @see {@link Bounds#fit} For fitting to Rectangle + * @see {@link Bounds#addBoundsMask} For intersection + */ + fitBounds(e, t, n, s) { + return this.minX < e && (this.minX = e), this.maxX > t && (this.maxX = t), this.minY < n && (this.minY = n), this.maxY > s && (this.maxY = s), this; + } + /** + * Pads bounds object, making it grow in all directions. + * If paddingY is omitted, both paddingX and paddingY will be set to paddingX. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * + * // Add equal padding + * bounds.pad(10); + * // bounds are now (-10, -10, 110, 110) + * + * // Add different padding for x and y + * bounds.pad(20, 10); + * // bounds are now (-30, -20, 130, 120) + * ``` + * @param paddingX - The horizontal padding amount + * @param paddingY - The vertical padding amount + * @returns This bounds object for chaining + * @see {@link Bounds#fit} For constraining bounds + * @see {@link Bounds#scale} For uniform scaling + */ + pad(e, t = e) { + return this.minX -= e, this.maxX += e, this.minY -= t, this.maxY += t, this; + } + /** + * Ceils the bounds by rounding up max values and rounding down min values. + * Useful for pixel-perfect calculations and avoiding fractional pixels. + * @example + * ```ts + * const bounds = new Bounds(); + * bounds.set(10.2, 10.9, 50.1, 50.8); + * + * // Round to whole pixels + * bounds.ceil(); + * // bounds are now (10, 10, 51, 51) + * ``` + * @returns This bounds object for chaining + * @see {@link Bounds#scale} For size adjustments + * @see {@link Bounds#fit} For constraining bounds + */ + ceil() { + return this.minX = Math.floor(this.minX), this.minY = Math.floor(this.minY), this.maxX = Math.ceil(this.maxX), this.maxY = Math.ceil(this.maxY), this; + } + /** + * Creates a new Bounds instance with the same values. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * + * // Create a copy + * const copy = bounds.clone(); + * + * // Original and copy are independent + * bounds.pad(10); + * console.log(copy.width === bounds.width); // false + * ``` + * @returns A new Bounds instance with the same values + * @see {@link Bounds#copyFrom} For reusing existing bounds + */ + clone() { + return new ht(this.minX, this.minY, this.maxX, this.maxY); + } + /** + * Scales the bounds by the given values, adjusting all edges proportionally. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * + * // Scale uniformly + * bounds.scale(2); + * // bounds are now (0, 0, 200, 200) + * + * // Scale non-uniformly + * bounds.scale(0.5, 2); + * // bounds are now (0, 0, 100, 400) + * ``` + * @param x - The X value to scale by + * @param y - The Y value to scale by (defaults to x) + * @returns This bounds object for chaining + * @see {@link Bounds#pad} For adding padding + * @see {@link Bounds#fit} For constraining size + */ + scale(e, t = e) { + return this.minX *= e, this.minY *= t, this.maxX *= e, this.maxY *= t, this; + } + /** + * The x position of the bounds in local space. + * Setting this value will move the bounds while maintaining its width. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Get x position + * console.log(bounds.x); // 0 + * + * // Move bounds horizontally + * bounds.x = 50; + * console.log(bounds.minX, bounds.maxX); // 50, 150 + * + * // Width stays the same + * console.log(bounds.width); // Still 100 + * ``` + */ + get x() { + return this.minX; + } + set x(e) { + const t = this.maxX - this.minX; + this.minX = e, this.maxX = e + t; + } + /** + * The y position of the bounds in local space. + * Setting this value will move the bounds while maintaining its height. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Get y position + * console.log(bounds.y); // 0 + * + * // Move bounds vertically + * bounds.y = 50; + * console.log(bounds.minY, bounds.maxY); // 50, 150 + * + * // Height stays the same + * console.log(bounds.height); // Still 100 + * ``` + */ + get y() { + return this.minY; + } + set y(e) { + const t = this.maxY - this.minY; + this.minY = e, this.maxY = e + t; + } + /** + * The width value of the bounds. + * Represents the distance between minX and maxX coordinates. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Get width + * console.log(bounds.width); // 100 + * // Resize width + * bounds.width = 200; + * console.log(bounds.maxX - bounds.minX); // 200 + * ``` + */ + get width() { + return this.maxX - this.minX; + } + set width(e) { + this.maxX = this.minX + e; + } + /** + * The height value of the bounds. + * Represents the distance between minY and maxY coordinates. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Get height + * console.log(bounds.height); // 100 + * // Resize height + * bounds.height = 150; + * console.log(bounds.maxY - bounds.minY); // 150 + * ``` + */ + get height() { + return this.maxY - this.minY; + } + set height(e) { + this.maxY = this.minY + e; + } + /** + * The left edge coordinate of the bounds. + * Alias for minX. + * @example + * ```ts + * const bounds = new Bounds(50, 0, 150, 100); + * console.log(bounds.left); // 50 + * console.log(bounds.left === bounds.minX); // true + * ``` + * @readonly + */ + get left() { + return this.minX; + } + /** + * The right edge coordinate of the bounds. + * Alias for maxX. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * console.log(bounds.right); // 100 + * console.log(bounds.right === bounds.maxX); // true + * ``` + * @readonly + */ + get right() { + return this.maxX; + } + /** + * The top edge coordinate of the bounds. + * Alias for minY. + * @example + * ```ts + * const bounds = new Bounds(0, 25, 100, 125); + * console.log(bounds.top); // 25 + * console.log(bounds.top === bounds.minY); // true + * ``` + * @readonly + */ + get top() { + return this.minY; + } + /** + * The bottom edge coordinate of the bounds. + * Alias for maxY. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 200); + * console.log(bounds.bottom); // 200 + * console.log(bounds.bottom === bounds.maxY); // true + * ``` + * @readonly + */ + get bottom() { + return this.maxY; + } + /** + * Whether the bounds has positive width and height. + * Checks if both dimensions are greater than zero. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Check if bounds are positive + * console.log(bounds.isPositive); // true + * + * // Negative bounds + * bounds.maxX = bounds.minX; + * console.log(bounds.isPositive); // false, width is 0 + * ``` + * @readonly + * @see {@link Bounds#isEmpty} For checking empty state + * @see {@link Bounds#isValid} For checking validity + */ + get isPositive() { + return this.maxX - this.minX > 0 && this.maxY - this.minY > 0; + } + /** + * Whether the bounds has valid coordinates. + * Checks if the bounds has been initialized with real values. + * @example + * ```ts + * const bounds = new Bounds(); + * console.log(bounds.isValid); // false, default state + * + * // Set valid bounds + * bounds.addFrame(0, 0, 100, 100); + * console.log(bounds.isValid); // true + * ``` + * @readonly + * @see {@link Bounds#isEmpty} For checking empty state + * @see {@link Bounds#isPositive} For checking dimensions + */ + get isValid() { + return this.minX + this.minY !== 1 / 0; + } + /** + * Adds vertices from a Float32Array to the bounds, optionally transformed by a matrix. + * Used for efficiently updating bounds from raw vertex data. + * @example + * ```ts + * const bounds = new Bounds(); + * + * // Add vertices from geometry + * const vertices = new Float32Array([ + * 0, 0, // Vertex 1 + * 100, 0, // Vertex 2 + * 100, 100 // Vertex 3 + * ]); + * bounds.addVertexData(vertices, 0, 6); + * + * // Add transformed vertices + * const matrix = new Matrix() + * .translate(50, 50) + * .rotate(Math.PI / 4); + * bounds.addVertexData(vertices, 0, 6, matrix); + * + * // Add subset of vertices + * bounds.addVertexData(vertices, 2, 4); // Only second vertex + * ``` + * @param vertexData - The array of vertices to add + * @param beginOffset - Starting index in the vertex array + * @param endOffset - Ending index in the vertex array (excluded) + * @param matrix - Optional transformation matrix + * @see {@link Bounds#addFrame} For adding rectangular frames + * @see {@link Matrix} For transformation details + */ + addVertexData(e, t, n, s) { + let r = this.minX, a = this.minY, o = this.maxX, l = this.maxY; + s || (s = this.matrix); + const h = s.a, u = s.b, c = s.c, d = s.d, f = s.tx, _ = s.ty; + for (let b = t; b < n; b += 2) { + const m = e[b], x = e[b + 1], g = h * m + c * x + f, p = u * m + d * x + _; + r = g < r ? g : r, a = p < a ? p : a, o = g > o ? g : o, l = p > l ? p : l; + } + this.minX = r, this.minY = a, this.maxX = o, this.maxY = l; + } + /** + * Checks if a point is contained within the bounds. + * Returns true if the point's coordinates fall within the bounds' area. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * // Basic point check + * console.log(bounds.containsPoint(50, 50)); // true + * console.log(bounds.containsPoint(150, 150)); // false + * + * // Check edges + * console.log(bounds.containsPoint(0, 0)); // true, includes edges + * console.log(bounds.containsPoint(100, 100)); // true, includes edges + * ``` + * @param x - x coordinate to check + * @param y - y coordinate to check + * @returns True if the point is inside the bounds + * @see {@link Bounds#isPositive} For valid bounds check + * @see {@link Bounds#rectangle} For Rectangle representation + */ + containsPoint(e, t) { + return this.minX <= e && this.minY <= t && this.maxX >= e && this.maxY >= t; + } + /** + * Returns a string representation of the bounds. + * Useful for debugging and logging bounds information. + * @example + * ```ts + * const bounds = new Bounds(0, 0, 100, 100); + * console.log(bounds.toString()); // "[pixi.js:Bounds minX=0 minY=0 maxX=100 maxY=100 width=100 height=100]" + * ``` + * @returns A string describing the bounds + * @see {@link Bounds#copyFrom} For copying bounds + * @see {@link Bounds#clone} For creating a new instance + */ + toString() { + return `[pixi.js:Bounds minX=${this.minX} minY=${this.minY} maxX=${this.maxX} maxY=${this.maxY} width=${this.width} height=${this.height}]`; + } + /** + * Copies the bounds from another bounds object. + * Useful for reusing bounds objects and avoiding allocations. + * @example + * ```ts + * const sourceBounds = new Bounds(0, 0, 100, 100); + * // Copy bounds + * const targetBounds = new Bounds(); + * targetBounds.copyFrom(sourceBounds); + * ``` + * @param bounds - The bounds to copy from + * @returns This bounds object for chaining + * @see {@link Bounds#clone} For creating new instances + */ + copyFrom(e) { + return this.minX = e.minX, this.minY = e.minY, this.maxX = e.maxX, this.maxY = e.maxY, this; + } +} +var Lh = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, vt = function(i) { + return typeof i == "string" ? i.length > 0 : typeof i == "number"; +}, xe = function(i, e, t) { + return e === void 0 && (e = 0), t === void 0 && (t = Math.pow(10, e)), Math.round(t * i) / t + 0; +}, Ve = function(i, e, t) { + return e === void 0 && (e = 0), t === void 0 && (t = 1), i > t ? t : i > e ? i : e; +}, Mo = function(i) { + return (i = isFinite(i) ? i % 360 : 0) > 0 ? i : i + 360; +}, Cr = function(i) { + return { r: Ve(i.r, 0, 255), g: Ve(i.g, 0, 255), b: Ve(i.b, 0, 255), a: Ve(i.a) }; +}, Ii = function(i) { + return { r: xe(i.r), g: xe(i.g), b: xe(i.b), a: xe(i.a, 3) }; +}, Oh = /^#([0-9a-f]{3,8})$/i, Hn = function(i) { + var e = i.toString(16); + return e.length < 2 ? "0" + e : e; +}, Po = function(i) { + var e = i.r, t = i.g, n = i.b, s = i.a, r = Math.max(e, t, n), a = r - Math.min(e, t, n), o = a ? r === e ? (t - n) / a : r === t ? 2 + (n - e) / a : 4 + (e - t) / a : 0; + return { h: 60 * (o < 0 ? o + 6 : o), s: r ? a / r * 100 : 0, v: r / 255 * 100, a: s }; +}, Io = function(i) { + var e = i.h, t = i.s, n = i.v, s = i.a; + e = e / 360 * 6, t /= 100, n /= 100; + var r = Math.floor(e), a = n * (1 - t), o = n * (1 - (e - r) * t), l = n * (1 - (1 - e + r) * t), h = r % 6; + return { r: 255 * [n, o, a, a, l, n][h], g: 255 * [l, n, n, o, a, a][h], b: 255 * [a, a, l, n, n, o][h], a: s }; +}, Sr = function(i) { + return { h: Mo(i.h), s: Ve(i.s, 0, 100), l: Ve(i.l, 0, 100), a: Ve(i.a) }; +}, kr = function(i) { + return { h: xe(i.h), s: xe(i.s), l: xe(i.l), a: xe(i.a, 3) }; +}, Ar = function(i) { + return Io((t = (e = i).s, { h: e.h, s: (t *= ((n = e.l) < 50 ? n : 100 - n) / 100) > 0 ? 2 * t / (n + t) * 100 : 0, v: n + t, a: e.a })); + var e, t, n; +}, wn = function(i) { + return { h: (e = Po(i)).h, s: (s = (200 - (t = e.s)) * (n = e.v) / 100) > 0 && s < 200 ? t * n / 100 / (s <= 100 ? s : 200 - s) * 100 : 0, l: s / 2, a: e.a }; + var e, t, n, s; +}, zh = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Nh = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Gh = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, qh = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, ps = { string: [[function(i) { + var e = Oh.exec(i); + return e ? (i = e[1]).length <= 4 ? { r: parseInt(i[0] + i[0], 16), g: parseInt(i[1] + i[1], 16), b: parseInt(i[2] + i[2], 16), a: i.length === 4 ? xe(parseInt(i[3] + i[3], 16) / 255, 2) : 1 } : i.length === 6 || i.length === 8 ? { r: parseInt(i.substr(0, 2), 16), g: parseInt(i.substr(2, 2), 16), b: parseInt(i.substr(4, 2), 16), a: i.length === 8 ? xe(parseInt(i.substr(6, 2), 16) / 255, 2) : 1 } : null : null; +}, "hex"], [function(i) { + var e = Gh.exec(i) || qh.exec(i); + return e ? e[2] !== e[4] || e[4] !== e[6] ? null : Cr({ r: Number(e[1]) / (e[2] ? 100 / 255 : 1), g: Number(e[3]) / (e[4] ? 100 / 255 : 1), b: Number(e[5]) / (e[6] ? 100 / 255 : 1), a: e[7] === void 0 ? 1 : Number(e[7]) / (e[8] ? 100 : 1) }) : null; +}, "rgb"], [function(i) { + var e = zh.exec(i) || Nh.exec(i); + if (!e) return null; + var t, n, s = Sr({ h: (t = e[1], n = e[2], n === void 0 && (n = "deg"), Number(t) * (Lh[n] || 1)), s: Number(e[3]), l: Number(e[4]), a: e[5] === void 0 ? 1 : Number(e[5]) / (e[6] ? 100 : 1) }); + return Ar(s); +}, "hsl"]], object: [[function(i) { + var e = i.r, t = i.g, n = i.b, s = i.a, r = s === void 0 ? 1 : s; + return vt(e) && vt(t) && vt(n) ? Cr({ r: Number(e), g: Number(t), b: Number(n), a: Number(r) }) : null; +}, "rgb"], [function(i) { + var e = i.h, t = i.s, n = i.l, s = i.a, r = s === void 0 ? 1 : s; + if (!vt(e) || !vt(t) || !vt(n)) return null; + var a = Sr({ h: Number(e), s: Number(t), l: Number(n), a: Number(r) }); + return Ar(a); +}, "hsl"], [function(i) { + var e = i.h, t = i.s, n = i.v, s = i.a, r = s === void 0 ? 1 : s; + if (!vt(e) || !vt(t) || !vt(n)) return null; + var a = function(o) { + return { h: Mo(o.h), s: Ve(o.s, 0, 100), v: Ve(o.v, 0, 100), a: Ve(o.a) }; + }({ h: Number(e), s: Number(t), v: Number(n), a: Number(r) }); + return Io(a); +}, "hsv"]] }, Dr = function(i, e) { + for (var t = 0; t < e.length; t++) { + var n = e[t][0](i); + if (n) return [n, e[t][1]]; + } + return [null, void 0]; +}, Uh = function(i) { + return typeof i == "string" ? Dr(i.trim(), ps.string) : typeof i == "object" && i !== null ? Dr(i, ps.object) : [null, void 0]; +}, Ri = function(i, e) { + var t = wn(i); + return { h: t.h, s: Ve(t.s + 100 * e, 0, 100), l: t.l, a: t.a }; +}, Bi = function(i) { + return (299 * i.r + 587 * i.g + 114 * i.b) / 1e3 / 255; +}, Er = function(i, e) { + var t = wn(i); + return { h: t.h, s: t.s, l: Ve(t.l + 100 * e, 0, 100), a: t.a }; +}, _s = function() { + function i(e) { + this.parsed = Uh(e)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 }; + } + return i.prototype.isValid = function() { + return this.parsed !== null; + }, i.prototype.brightness = function() { + return xe(Bi(this.rgba), 2); + }, i.prototype.isDark = function() { + return Bi(this.rgba) < 0.5; + }, i.prototype.isLight = function() { + return Bi(this.rgba) >= 0.5; + }, i.prototype.toHex = function() { + return e = Ii(this.rgba), t = e.r, n = e.g, s = e.b, a = (r = e.a) < 1 ? Hn(xe(255 * r)) : "", "#" + Hn(t) + Hn(n) + Hn(s) + a; + var e, t, n, s, r, a; + }, i.prototype.toRgb = function() { + return Ii(this.rgba); + }, i.prototype.toRgbString = function() { + return e = Ii(this.rgba), t = e.r, n = e.g, s = e.b, (r = e.a) < 1 ? "rgba(" + t + ", " + n + ", " + s + ", " + r + ")" : "rgb(" + t + ", " + n + ", " + s + ")"; + var e, t, n, s, r; + }, i.prototype.toHsl = function() { + return kr(wn(this.rgba)); + }, i.prototype.toHslString = function() { + return e = kr(wn(this.rgba)), t = e.h, n = e.s, s = e.l, (r = e.a) < 1 ? "hsla(" + t + ", " + n + "%, " + s + "%, " + r + ")" : "hsl(" + t + ", " + n + "%, " + s + "%)"; + var e, t, n, s, r; + }, i.prototype.toHsv = function() { + return e = Po(this.rgba), { h: xe(e.h), s: xe(e.s), v: xe(e.v), a: xe(e.a, 3) }; + var e; + }, i.prototype.invert = function() { + return _t({ r: 255 - (e = this.rgba).r, g: 255 - e.g, b: 255 - e.b, a: e.a }); + var e; + }, i.prototype.saturate = function(e) { + return e === void 0 && (e = 0.1), _t(Ri(this.rgba, e)); + }, i.prototype.desaturate = function(e) { + return e === void 0 && (e = 0.1), _t(Ri(this.rgba, -e)); + }, i.prototype.grayscale = function() { + return _t(Ri(this.rgba, -1)); + }, i.prototype.lighten = function(e) { + return e === void 0 && (e = 0.1), _t(Er(this.rgba, e)); + }, i.prototype.darken = function(e) { + return e === void 0 && (e = 0.1), _t(Er(this.rgba, -e)); + }, i.prototype.rotate = function(e) { + return e === void 0 && (e = 15), this.hue(this.hue() + e); + }, i.prototype.alpha = function(e) { + return typeof e == "number" ? _t({ r: (t = this.rgba).r, g: t.g, b: t.b, a: e }) : xe(this.rgba.a, 3); + var t; + }, i.prototype.hue = function(e) { + var t = wn(this.rgba); + return typeof e == "number" ? _t({ h: e, s: t.s, l: t.l, a: t.a }) : xe(t.h); + }, i.prototype.isEqual = function(e) { + return this.toHex() === _t(e).toHex(); + }, i; +}(), _t = function(i) { + return i instanceof _s ? i : new _s(i); +}, Fr = [], Hh = function(i) { + i.forEach(function(e) { + Fr.indexOf(e) < 0 && (e(_s, ps), Fr.push(e)); + }); +}; +function Vh(i, e) { + var t = { white: "#ffffff", bisque: "#ffe4c4", blue: "#0000ff", cadetblue: "#5f9ea0", chartreuse: "#7fff00", chocolate: "#d2691e", coral: "#ff7f50", antiquewhite: "#faebd7", aqua: "#00ffff", azure: "#f0ffff", whitesmoke: "#f5f5f5", papayawhip: "#ffefd5", plum: "#dda0dd", blanchedalmond: "#ffebcd", black: "#000000", gold: "#ffd700", goldenrod: "#daa520", gainsboro: "#dcdcdc", cornsilk: "#fff8dc", cornflowerblue: "#6495ed", burlywood: "#deb887", aquamarine: "#7fffd4", beige: "#f5f5dc", crimson: "#dc143c", cyan: "#00ffff", darkblue: "#00008b", darkcyan: "#008b8b", darkgoldenrod: "#b8860b", darkkhaki: "#bdb76b", darkgray: "#a9a9a9", darkgreen: "#006400", darkgrey: "#a9a9a9", peachpuff: "#ffdab9", darkmagenta: "#8b008b", darkred: "#8b0000", darkorchid: "#9932cc", darkorange: "#ff8c00", darkslateblue: "#483d8b", gray: "#808080", darkslategray: "#2f4f4f", darkslategrey: "#2f4f4f", deeppink: "#ff1493", deepskyblue: "#00bfff", wheat: "#f5deb3", firebrick: "#b22222", floralwhite: "#fffaf0", ghostwhite: "#f8f8ff", darkviolet: "#9400d3", magenta: "#ff00ff", green: "#008000", dodgerblue: "#1e90ff", grey: "#808080", honeydew: "#f0fff0", hotpink: "#ff69b4", blueviolet: "#8a2be2", forestgreen: "#228b22", lawngreen: "#7cfc00", indianred: "#cd5c5c", indigo: "#4b0082", fuchsia: "#ff00ff", brown: "#a52a2a", maroon: "#800000", mediumblue: "#0000cd", lightcoral: "#f08080", darkturquoise: "#00ced1", lightcyan: "#e0ffff", ivory: "#fffff0", lightyellow: "#ffffe0", lightsalmon: "#ffa07a", lightseagreen: "#20b2aa", linen: "#faf0e6", mediumaquamarine: "#66cdaa", lemonchiffon: "#fffacd", lime: "#00ff00", khaki: "#f0e68c", mediumseagreen: "#3cb371", limegreen: "#32cd32", mediumspringgreen: "#00fa9a", lightskyblue: "#87cefa", lightblue: "#add8e6", midnightblue: "#191970", lightpink: "#ffb6c1", mistyrose: "#ffe4e1", moccasin: "#ffe4b5", mintcream: "#f5fffa", lightslategray: "#778899", lightslategrey: "#778899", navajowhite: "#ffdead", navy: "#000080", mediumvioletred: "#c71585", powderblue: "#b0e0e6", palegoldenrod: "#eee8aa", oldlace: "#fdf5e6", paleturquoise: "#afeeee", mediumturquoise: "#48d1cc", mediumorchid: "#ba55d3", rebeccapurple: "#663399", lightsteelblue: "#b0c4de", mediumslateblue: "#7b68ee", thistle: "#d8bfd8", tan: "#d2b48c", orchid: "#da70d6", mediumpurple: "#9370db", purple: "#800080", pink: "#ffc0cb", skyblue: "#87ceeb", springgreen: "#00ff7f", palegreen: "#98fb98", red: "#ff0000", yellow: "#ffff00", slateblue: "#6a5acd", lavenderblush: "#fff0f5", peru: "#cd853f", palevioletred: "#db7093", violet: "#ee82ee", teal: "#008080", slategray: "#708090", slategrey: "#708090", aliceblue: "#f0f8ff", darkseagreen: "#8fbc8f", darkolivegreen: "#556b2f", greenyellow: "#adff2f", seagreen: "#2e8b57", seashell: "#fff5ee", tomato: "#ff6347", silver: "#c0c0c0", sienna: "#a0522d", lavender: "#e6e6fa", lightgreen: "#90ee90", orange: "#ffa500", orangered: "#ff4500", steelblue: "#4682b4", royalblue: "#4169e1", turquoise: "#40e0d0", yellowgreen: "#9acd32", salmon: "#fa8072", saddlebrown: "#8b4513", sandybrown: "#f4a460", rosybrown: "#bc8f8f", darksalmon: "#e9967a", lightgoldenrodyellow: "#fafad2", snow: "#fffafa", lightgrey: "#d3d3d3", lightgray: "#d3d3d3", dimgray: "#696969", dimgrey: "#696969", olivedrab: "#6b8e23", olive: "#808000" }, n = {}; + for (var s in t) n[t[s]] = s; + var r = {}; + i.prototype.toName = function(a) { + if (!(this.rgba.a || this.rgba.r || this.rgba.g || this.rgba.b)) return "transparent"; + var o, l, h = n[this.toHex()]; + if (h) return h; + if (a != null && a.closest) { + var u = this.toRgb(), c = 1 / 0, d = "black"; + if (!r.length) for (var f in t) r[f] = new i(t[f]).toRgb(); + for (var _ in t) { + var b = (o = u, l = r[_], Math.pow(o.r - l.r, 2) + Math.pow(o.g - l.g, 2) + Math.pow(o.b - l.b, 2)); + b < c && (c = b, d = _); + } + return d; + } + }, e.string.push([function(a) { + var o = a.toLowerCase(), l = o === "transparent" ? "#0000" : t[o]; + return l ? new i(l).toRgb() : null; + }, "name"]); +} +Hh([Vh]); +const nn = class gn { + /** + * @param {ColorSource} value - Optional value to use, if not provided, white is used. + */ + constructor(e = 16777215) { + this._value = null, this._components = new Float32Array(4), this._components.fill(1), this._int = 16777215, this.value = e; + } + /** + * Get the red component of the color, normalized between 0 and 1. + * @example + * ```ts + * const color = new Color('red'); + * console.log(color.red); // 1 + * + * const green = new Color('#00ff00'); + * console.log(green.red); // 0 + * ``` + */ + get red() { + return this._components[0]; + } + /** + * Get the green component of the color, normalized between 0 and 1. + * @example + * ```ts + * const color = new Color('lime'); + * console.log(color.green); // 1 + * + * const red = new Color('#ff0000'); + * console.log(red.green); // 0 + * ``` + */ + get green() { + return this._components[1]; + } + /** + * Get the blue component of the color, normalized between 0 and 1. + * @example + * ```ts + * const color = new Color('blue'); + * console.log(color.blue); // 1 + * + * const yellow = new Color('#ffff00'); + * console.log(yellow.blue); // 0 + * ``` + */ + get blue() { + return this._components[2]; + } + /** + * Get the alpha component of the color, normalized between 0 and 1. + * @example + * ```ts + * const color = new Color('red'); + * console.log(color.alpha); // 1 (fully opaque) + * + * const transparent = new Color('rgba(255, 0, 0, 0.5)'); + * console.log(transparent.alpha); // 0.5 (semi-transparent) + * ``` + */ + get alpha() { + return this._components[3]; + } + /** + * Sets the color value and returns the instance for chaining. + * + * This is a chainable version of setting the `value` property. + * @param value - The color to set. Accepts various formats: + * - Hex strings/numbers (e.g., '#ff0000', 0xff0000) + * - RGB/RGBA values (arrays, objects) + * - CSS color names + * - HSL/HSLA values + * - HSV/HSVA values + * @returns The Color instance for chaining + * @example + * ```ts + * // Basic usage + * const color = new Color(); + * color.setValue('#ff0000') + * .setAlpha(0.5) + * .premultiply(0.8); + * + * // Different formats + * color.setValue(0xff0000); // Hex number + * color.setValue('#ff0000'); // Hex string + * color.setValue([1, 0, 0]); // RGB array + * color.setValue([1, 0, 0, 0.5]); // RGBA array + * color.setValue({ r: 1, g: 0, b: 0 }); // RGB object + * + * // Copy from another color + * const red = new Color('red'); + * color.setValue(red); + * ``` + * @throws {Error} If the color value is invalid or null + * @see {@link Color.value} For the underlying value property + */ + setValue(e) { + return this.value = e, this; + } + /** + * The current color source. This property allows getting and setting the color value + * while preserving the original format where possible. + * @remarks + * When setting: + * - Setting to a `Color` instance copies its source and components + * - Setting to other valid sources normalizes and stores the value + * - Setting to `null` throws an Error + * - The color remains unchanged if normalization fails + * + * When getting: + * - Returns `null` if color was modified by {@link Color.multiply} or {@link Color.premultiply} + * - Otherwise returns the original color source + * @example + * ```ts + * // Setting different color formats + * const color = new Color(); + * + * color.value = 0xff0000; // Hex number + * color.value = '#ff0000'; // Hex string + * color.value = [1, 0, 0]; // RGB array + * color.value = [1, 0, 0, 0.5]; // RGBA array + * color.value = { r: 1, g: 0, b: 0 }; // RGB object + * + * // Copying from another color + * const red = new Color('red'); + * color.value = red; // Copies red's components + * + * // Getting the value + * console.log(color.value); // Returns original format + * + * // After modifications + * color.multiply([0.5, 0.5, 0.5]); + * console.log(color.value); // Returns null + * ``` + * @throws {Error} When attempting to set `null` + */ + set value(e) { + if (e instanceof gn) + this._value = this._cloneSource(e._value), this._int = e._int, this._components.set(e._components); + else { + if (e === null) + throw new Error("Cannot set Color#value to null"); + (this._value === null || !this._isSourceEqual(this._value, e)) && (this._value = this._cloneSource(e), this._normalize(this._value)); + } + } + get value() { + return this._value; + } + /** + * Copy a color source internally. + * @param value - Color source + */ + _cloneSource(e) { + return typeof e == "string" || typeof e == "number" || e instanceof Number || e === null ? e : Array.isArray(e) || ArrayBuffer.isView(e) ? e.slice(0) : typeof e == "object" && e !== null ? { ...e } : e; + } + /** + * Equality check for color sources. + * @param value1 - First color source + * @param value2 - Second color source + * @returns `true` if the color sources are equal, `false` otherwise. + */ + _isSourceEqual(e, t) { + const n = typeof e; + if (n !== typeof t) + return !1; + if (n === "number" || n === "string" || e instanceof Number) + return e === t; + if (Array.isArray(e) && Array.isArray(t) || ArrayBuffer.isView(e) && ArrayBuffer.isView(t)) + return e.length !== t.length ? !1 : e.every((r, a) => r === t[a]); + if (e !== null && t !== null) { + const r = Object.keys(e), a = Object.keys(t); + return r.length !== a.length ? !1 : r.every((o) => e[o] === t[o]); + } + return e === t; + } + /** + * Convert to a RGBA color object with normalized components (0-1). + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Convert colors to RGBA objects + * new Color('white').toRgba(); // returns { r: 1, g: 1, b: 1, a: 1 } + * new Color('#ff0000').toRgba(); // returns { r: 1, g: 0, b: 0, a: 1 } + * + * // With transparency + * new Color('rgba(255,0,0,0.5)').toRgba(); // returns { r: 1, g: 0, b: 0, a: 0.5 } + * ``` + * @returns An RGBA object with normalized components + */ + toRgba() { + const [e, t, n, s] = this._components; + return { r: e, g: t, b: n, a: s }; + } + /** + * Convert to a RGB color object with normalized components (0-1). + * + * Alpha component is omitted in the output. + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Convert colors to RGB objects + * new Color('white').toRgb(); // returns { r: 1, g: 1, b: 1 } + * new Color('#ff0000').toRgb(); // returns { r: 1, g: 0, b: 0 } + * + * // Alpha is ignored + * new Color('rgba(255,0,0,0.5)').toRgb(); // returns { r: 1, g: 0, b: 0 } + * ``` + * @returns An RGB object with normalized components + */ + toRgb() { + const [e, t, n] = this._components; + return { r: e, g: t, b: n }; + } + /** + * Convert to a CSS-style rgba string representation. + * + * RGB components are scaled to 0-255 range, alpha remains 0-1. + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Convert colors to RGBA strings + * new Color('white').toRgbaString(); // returns "rgba(255,255,255,1)" + * new Color('#ff0000').toRgbaString(); // returns "rgba(255,0,0,1)" + * + * // With transparency + * new Color([1, 0, 0, 0.5]).toRgbaString(); // returns "rgba(255,0,0,0.5)" + * ``` + * @returns A CSS-compatible rgba string + */ + toRgbaString() { + const [e, t, n] = this.toUint8RgbArray(); + return `rgba(${e},${t},${n},${this.alpha})`; + } + /** + * Convert to an [R, G, B] array of clamped uint8 values (0 to 255). + * @param {number[]|Uint8Array|Uint8ClampedArray} [out] - Optional output array. If not provided, + * a cached array will be used and returned. + * @returns Array containing RGB components as integers between 0-255 + * @example + * ```ts + * // Basic usage + * new Color('white').toUint8RgbArray(); // returns [255, 255, 255] + * new Color('#ff0000').toUint8RgbArray(); // returns [255, 0, 0] + * + * // Using custom output array + * const rgb = new Uint8Array(3); + * new Color('blue').toUint8RgbArray(rgb); // rgb is now [0, 0, 255] + * + * // Using different array types + * new Color('red').toUint8RgbArray(new Uint8ClampedArray(3)); // [255, 0, 0] + * new Color('red').toUint8RgbArray([]); // [255, 0, 0] + * ``` + * @remarks + * - Output values are always clamped between 0-255 + * - Alpha component is not included in output + * - Reuses internal cache array if no output array provided + */ + toUint8RgbArray(e) { + const [t, n, s] = this._components; + return this._arrayRgb || (this._arrayRgb = []), e || (e = this._arrayRgb), e[0] = Math.round(t * 255), e[1] = Math.round(n * 255), e[2] = Math.round(s * 255), e; + } + /** + * Convert to an [R, G, B, A] array of normalized floats (numbers from 0.0 to 1.0). + * @param {number[]|Float32Array} [out] - Optional output array. If not provided, + * a cached array will be used and returned. + * @returns Array containing RGBA components as floats between 0-1 + * @example + * ```ts + * // Basic usage + * new Color('white').toArray(); // returns [1, 1, 1, 1] + * new Color('red').toArray(); // returns [1, 0, 0, 1] + * + * // With alpha + * new Color('rgba(255,0,0,0.5)').toArray(); // returns [1, 0, 0, 0.5] + * + * // Using custom output array + * const rgba = new Float32Array(4); + * new Color('blue').toArray(rgba); // rgba is now [0, 0, 1, 1] + * ``` + * @remarks + * - Output values are normalized between 0-1 + * - Includes alpha component as the fourth value + * - Reuses internal cache array if no output array provided + */ + toArray(e) { + this._arrayRgba || (this._arrayRgba = []), e || (e = this._arrayRgba); + const [t, n, s, r] = this._components; + return e[0] = t, e[1] = n, e[2] = s, e[3] = r, e; + } + /** + * Convert to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0). + * @param {number[]|Float32Array} [out] - Optional output array. If not provided, + * a cached array will be used and returned. + * @returns Array containing RGB components as floats between 0-1 + * @example + * ```ts + * // Basic usage + * new Color('white').toRgbArray(); // returns [1, 1, 1] + * new Color('red').toRgbArray(); // returns [1, 0, 0] + * + * // Using custom output array + * const rgb = new Float32Array(3); + * new Color('blue').toRgbArray(rgb); // rgb is now [0, 0, 1] + * ``` + * @remarks + * - Output values are normalized between 0-1 + * - Alpha component is omitted from output + * - Reuses internal cache array if no output array provided + */ + toRgbArray(e) { + this._arrayRgb || (this._arrayRgb = []), e || (e = this._arrayRgb); + const [t, n, s] = this._components; + return e[0] = t, e[1] = n, e[2] = s, e; + } + /** + * Convert to a hexadecimal number. + * @returns The color as a 24-bit RGB integer + * @example + * ```ts + * // Basic usage + * new Color('white').toNumber(); // returns 0xffffff + * new Color('red').toNumber(); // returns 0xff0000 + * + * // Store as hex + * const color = new Color('blue'); + * const hex = color.toNumber(); // 0x0000ff + * ``` + */ + toNumber() { + return this._int; + } + /** + * Convert to a BGR number. + * + * Useful for platforms that expect colors in BGR format. + * @returns The color as a 24-bit BGR integer + * @example + * ```ts + * // Convert RGB to BGR + * new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff + * + * // Common use case: platform-specific color format + * const color = new Color('orange'); + * const bgrColor = color.toBgrNumber(); // Color with swapped R/B channels + * ``` + * @remarks + * This swaps the red and blue channels compared to the normal RGB format: + * - RGB 0xRRGGBB becomes BGR 0xBBGGRR + */ + toBgrNumber() { + const [e, t, n] = this.toUint8RgbArray(); + return (n << 16) + (t << 8) + e; + } + /** + * Convert to a hexadecimal number in little endian format (e.g., BBGGRR). + * + * Useful for platforms that expect colors in little endian byte order. + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Convert RGB color to little endian format + * new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff + * + * // Common use cases: + * const color = new Color('orange'); + * const leColor = color.toLittleEndianNumber(); // Swaps byte order for LE systems + * + * // Multiple conversions + * const colors = { + * normal: 0xffcc99, + * littleEndian: new Color(0xffcc99).toLittleEndianNumber(), // 0x99ccff + * backToNormal: new Color(0x99ccff).toLittleEndianNumber() // 0xffcc99 + * }; + * ``` + * @remarks + * - Swaps R and B channels in the color value + * - RGB 0xRRGGBB becomes 0xBBGGRR + * - Useful for systems that use little endian byte order + * - Can be used to convert back and forth between formats + * @returns The color as a number in little endian format (BBGGRR) + * @see {@link Color.toBgrNumber} For BGR format without byte swapping + */ + toLittleEndianNumber() { + const e = this._int; + return (e >> 16) + (e & 65280) + ((e & 255) << 16); + } + /** + * Multiply with another color. + * + * This action is destructive and modifies the original color. + * @param {ColorSource} value - The color to multiply by. Accepts any valid color format: + * - Hex strings/numbers (e.g., '#ff0000', 0xff0000) + * - RGB/RGBA arrays ([1, 0, 0], [1, 0, 0, 1]) + * - Color objects ({ r: 1, g: 0, b: 0 }) + * - CSS color names ('red', 'blue') + * @returns this - The Color instance for chaining + * @example + * ```ts + * // Basic multiplication + * const color = new Color('#ff0000'); + * color.multiply(0x808080); // 50% darker red + * + * // With transparency + * color.multiply([1, 1, 1, 0.5]); // 50% transparent + * + * // Chain operations + * color + * .multiply('#808080') + * .multiply({ r: 1, g: 1, b: 1, a: 0.5 }); + * ``` + * @remarks + * - Multiplies each RGB component and alpha separately + * - Values are clamped between 0-1 + * - Original color format is lost (value becomes null) + * - Operation cannot be undone + */ + multiply(e) { + const [t, n, s, r] = gn._temp.setValue(e)._components; + return this._components[0] *= t, this._components[1] *= n, this._components[2] *= s, this._components[3] *= r, this._refreshInt(), this._value = null, this; + } + /** + * Converts color to a premultiplied alpha format. + * + * This action is destructive and modifies the original color. + * @param alpha - The alpha value to multiply by (0-1) + * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels + * @returns {Color} The Color instance for chaining + * @example + * ```ts + * // Basic premultiplication + * const color = new Color('red'); + * color.premultiply(0.5); // 50% transparent red with premultiplied RGB + * + * // Alpha only (RGB unchanged) + * color.premultiply(0.5, false); // 50% transparent, original RGB + * + * // Chain with other operations + * color + * .multiply(0x808080) + * .premultiply(0.5) + * .toNumber(); + * ``` + * @remarks + * - RGB channels are multiplied by alpha when applyToRGB is true + * - Alpha is always set to the provided value + * - Values are clamped between 0-1 + * - Original color format is lost (value becomes null) + * - Operation cannot be undone + */ + premultiply(e, t = !0) { + return t && (this._components[0] *= e, this._components[1] *= e, this._components[2] *= e), this._components[3] = e, this._refreshInt(), this._value = null, this; + } + /** + * Returns the color as a 32-bit premultiplied alpha integer. + * + * Format: 0xAARRGGBB + * @param {number} alpha - The alpha value to multiply by (0-1) + * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels + * @returns {number} The premultiplied color as a 32-bit integer + * @example + * ```ts + * // Convert to premultiplied format + * const color = new Color('red'); + * + * // Full opacity (0xFFRRGGBB) + * color.toPremultiplied(1.0); // 0xFFFF0000 + * + * // 50% transparency with premultiplied RGB + * color.toPremultiplied(0.5); // 0x7F7F0000 + * + * // 50% transparency without RGB premultiplication + * color.toPremultiplied(0.5, false); // 0x7FFF0000 + * ``` + * @remarks + * - Returns full opacity (0xFF000000) when alpha is 1.0 + * - Returns 0 when alpha is 0.0 and applyToRGB is true + * - RGB values are rounded during premultiplication + */ + toPremultiplied(e, t = !0) { + if (e === 1) + return (255 << 24) + this._int; + if (e === 0) + return t ? 0 : this._int; + let n = this._int >> 16 & 255, s = this._int >> 8 & 255, r = this._int & 255; + return t && (n = n * e + 0.5 | 0, s = s * e + 0.5 | 0, r = r * e + 0.5 | 0), (e * 255 << 24) + (n << 16) + (s << 8) + r; + } + /** + * Convert to a hexadecimal string (6 characters). + * @returns A CSS-compatible hex color string (e.g., "#ff0000") + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Basic colors + * new Color('red').toHex(); // returns "#ff0000" + * new Color('white').toHex(); // returns "#ffffff" + * new Color('black').toHex(); // returns "#000000" + * + * // From different formats + * new Color(0xff0000).toHex(); // returns "#ff0000" + * new Color([1, 0, 0]).toHex(); // returns "#ff0000" + * new Color({ r: 1, g: 0, b: 0 }).toHex(); // returns "#ff0000" + * ``` + * @remarks + * - Always returns a 6-character hex string + * - Includes leading "#" character + * - Alpha channel is ignored + * - Values are rounded to nearest hex value + */ + toHex() { + const e = this._int.toString(16); + return `#${"000000".substring(0, 6 - e.length) + e}`; + } + /** + * Convert to a hexadecimal string with alpha (8 characters). + * @returns A CSS-compatible hex color string with alpha (e.g., "#ff0000ff") + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // Fully opaque colors + * new Color('red').toHexa(); // returns "#ff0000ff" + * new Color('white').toHexa(); // returns "#ffffffff" + * + * // With transparency + * new Color('rgba(255, 0, 0, 0.5)').toHexa(); // returns "#ff00007f" + * new Color([1, 0, 0, 0]).toHexa(); // returns "#ff000000" + * ``` + * @remarks + * - Returns an 8-character hex string + * - Includes leading "#" character + * - Alpha is encoded in last two characters + * - Values are rounded to nearest hex value + */ + toHexa() { + const t = Math.round(this._components[3] * 255).toString(16); + return this.toHex() + "00".substring(0, 2 - t.length) + t; + } + /** + * Set alpha (transparency) value while preserving color components. + * + * Provides a chainable interface for setting alpha. + * @param alpha - Alpha value between 0 (fully transparent) and 1 (fully opaque) + * @returns The Color instance for chaining + * @example + * ```ts + * // Basic alpha setting + * const color = new Color('red'); + * color.setAlpha(0.5); // 50% transparent red + * + * // Chain with other operations + * color + * .setValue('#ff0000') + * .setAlpha(0.8) // 80% opaque + * .premultiply(0.5); // Further modify alpha + * + * // Reset to fully opaque + * color.setAlpha(1); + * ``` + * @remarks + * - Alpha value is clamped between 0-1 + * - Can be chained with other color operations + */ + setAlpha(e) { + return this._components[3] = this._clamp(e), this; + } + /** + * Normalize the input value into rgba + * @param value - Input value + */ + _normalize(e) { + let t, n, s, r; + if ((typeof e == "number" || e instanceof Number) && e >= 0 && e <= 16777215) { + const a = e; + t = (a >> 16 & 255) / 255, n = (a >> 8 & 255) / 255, s = (a & 255) / 255, r = 1; + } else if ((Array.isArray(e) || e instanceof Float32Array) && e.length >= 3 && e.length <= 4) + e = this._clamp(e), [t, n, s, r = 1] = e; + else if ((e instanceof Uint8Array || e instanceof Uint8ClampedArray) && e.length >= 3 && e.length <= 4) + e = this._clamp(e, 0, 255), [t, n, s, r = 255] = e, t /= 255, n /= 255, s /= 255, r /= 255; + else if (typeof e == "string" || typeof e == "object") { + if (typeof e == "string") { + const o = gn.HEX_PATTERN.exec(e); + o && (e = `#${o[2]}`); + } + const a = _t(e); + a.isValid() && ({ r: t, g: n, b: s, a: r } = a.rgba, t /= 255, n /= 255, s /= 255); + } + if (t !== void 0) + this._components[0] = t, this._components[1] = n, this._components[2] = s, this._components[3] = r, this._refreshInt(); + else + throw new Error(`Unable to convert color ${e}`); + } + /** Refresh the internal color rgb number */ + _refreshInt() { + this._clamp(this._components); + const [e, t, n] = this._components; + this._int = (e * 255 << 16) + (t * 255 << 8) + (n * 255 | 0); + } + /** + * Clamps values to a range. Will override original values + * @param value - Value(s) to clamp + * @param min - Minimum value + * @param max - Maximum value + */ + _clamp(e, t = 0, n = 1) { + return typeof e == "number" ? Math.min(Math.max(e, t), n) : (e.forEach((s, r) => { + e[r] = Math.min(Math.max(s, t), n); + }), e); + } + /** + * Check if a value can be interpreted as a valid color format. + * Supports all color formats that can be used with the Color class. + * @param value - Value to check + * @returns True if the value can be used as a color + * @example + * ```ts + * import { Color } from 'pixi.js'; + * + * // CSS colors and hex values + * Color.isColorLike('red'); // true + * Color.isColorLike('#ff0000'); // true + * Color.isColorLike(0xff0000); // true + * + * // Arrays (RGB/RGBA) + * Color.isColorLike([1, 0, 0]); // true + * Color.isColorLike([1, 0, 0, 0.5]); // true + * + * // TypedArrays + * Color.isColorLike(new Float32Array([1, 0, 0])); // true + * Color.isColorLike(new Uint8Array([255, 0, 0])); // true + * Color.isColorLike(new Uint8ClampedArray([255, 0, 0])); // true + * + * // Object formats + * Color.isColorLike({ r: 1, g: 0, b: 0 }); // true (RGB) + * Color.isColorLike({ r: 1, g: 0, b: 0, a: 0.5 }); // true (RGBA) + * Color.isColorLike({ h: 0, s: 100, l: 50 }); // true (HSL) + * Color.isColorLike({ h: 0, s: 100, l: 50, a: 0.5 }); // true (HSLA) + * Color.isColorLike({ h: 0, s: 100, v: 100 }); // true (HSV) + * Color.isColorLike({ h: 0, s: 100, v: 100, a: 0.5 });// true (HSVA) + * + * // Color instances + * Color.isColorLike(new Color('red')); // true + * + * // Invalid values + * Color.isColorLike(null); // false + * Color.isColorLike(undefined); // false + * Color.isColorLike({}); // false + * Color.isColorLike([]); // false + * Color.isColorLike('not-a-color'); // false + * ``` + * @remarks + * Checks for the following formats: + * - Numbers (0x000000 to 0xffffff) + * - CSS color strings + * - RGB/RGBA arrays and objects + * - HSL/HSLA objects + * - HSV/HSVA objects + * - TypedArrays (Float32Array, Uint8Array, Uint8ClampedArray) + * - Color instances + * @see {@link ColorSource} For supported color format types + * @see {@link Color.setValue} For setting color values + * @category utility + */ + static isColorLike(e) { + return typeof e == "number" || typeof e == "string" || e instanceof Number || e instanceof gn || Array.isArray(e) || e instanceof Uint8Array || e instanceof Uint8ClampedArray || e instanceof Float32Array || e.r !== void 0 && e.g !== void 0 && e.b !== void 0 || e.r !== void 0 && e.g !== void 0 && e.b !== void 0 && e.a !== void 0 || e.h !== void 0 && e.s !== void 0 && e.l !== void 0 || e.h !== void 0 && e.s !== void 0 && e.l !== void 0 && e.a !== void 0 || e.h !== void 0 && e.s !== void 0 && e.v !== void 0 || e.h !== void 0 && e.s !== void 0 && e.v !== void 0 && e.a !== void 0; + } +}; +nn.shared = new nn(); +nn._temp = new nn(); +nn.HEX_PATTERN = /^(#|0x)?(([a-f0-9]{3}){1,2}([a-f0-9]{2})?)$/i; +let pe = nn; +const Wh = { + cullArea: null, + cullable: !1, + cullableChildren: !0 +}; +let Li = 0; +const $r = 500; +function $e(...i) { + Li !== $r && (Li++, Li === $r ? console.warn("PixiJS Warning: too many warnings, no more warnings will be reported to the console by PixiJS.") : console.warn("PixiJS Warning: ", ...i)); +} +const Bn = { + /** + * Set of registered pools and cleanable objects. + * @private + */ + _registeredResources: /* @__PURE__ */ new Set(), + /** + * Registers a pool or cleanable object for cleanup. + * @param {Cleanable} pool - The pool or object to register. + */ + register(i) { + this._registeredResources.add(i); + }, + /** + * Unregisters a pool or cleanable object from cleanup. + * @param {Cleanable} pool - The pool or object to unregister. + */ + unregister(i) { + this._registeredResources.delete(i); + }, + /** Clears all registered pools and cleanable objects. This will call clear() on each registered item. */ + release() { + this._registeredResources.forEach((i) => i.clear()); + }, + /** + * Gets the number of registered pools and cleanable objects. + * @returns {number} The count of registered items. + */ + get registeredCount() { + return this._registeredResources.size; + }, + /** + * Checks if a specific pool or cleanable object is registered. + * @param {Cleanable} pool - The pool or object to check. + * @returns {boolean} True if the item is registered, false otherwise. + */ + isRegistered(i) { + return this._registeredResources.has(i); + }, + /** + * Removes all registrations without clearing the pools. + * Useful if you want to reset the collector without affecting the pools. + */ + reset() { + this._registeredResources.clear(); + } +}; +class Yh { + /** + * Constructs a new Pool. + * @param ClassType - The constructor of the items in the pool. + * @param {number} [initialSize] - The initial size of the pool. + */ + constructor(e, t) { + this._pool = [], this._count = 0, this._index = 0, this._classType = e, t && this.prepopulate(t); + } + /** + * Prepopulates the pool with a given number of items. + * @param total - The number of items to add to the pool. + */ + prepopulate(e) { + for (let t = 0; t < e; t++) + this._pool[this._index++] = new this._classType(); + this._count += e; + } + /** + * Gets an item from the pool. Calls the item's `init` method if it exists. + * If there are no items left in the pool, a new one will be created. + * @param {unknown} [data] - Optional data to pass to the item's constructor. + * @returns {T} The item from the pool. + */ + get(e) { + var n; + let t; + return this._index > 0 ? t = this._pool[--this._index] : t = new this._classType(), (n = t.init) == null || n.call(t, e), t; + } + /** + * Returns an item to the pool. Calls the item's `reset` method if it exists. + * @param {T} item - The item to return to the pool. + */ + return(e) { + var t; + (t = e.reset) == null || t.call(e), this._pool[this._index++] = e; + } + /** + * Gets the number of items in the pool. + * @readonly + */ + get totalSize() { + return this._count; + } + /** + * Gets the number of items in the pool that are free to use without needing to create more. + * @readonly + */ + get totalFree() { + return this._index; + } + /** + * Gets the number of items in the pool that are currently in use. + * @readonly + */ + get totalUsed() { + return this._count - this._index; + } + /** clears the pool */ + clear() { + if (this._pool.length > 0 && this._pool[0].destroy) + for (let e = 0; e < this._index; e++) + this._pool[e].destroy(); + this._pool.length = 0, this._count = 0, this._index = 0; + } +} +class Xh { + constructor() { + this._poolsByClass = /* @__PURE__ */ new Map(); + } + /** + * Prepopulates a specific pool with a given number of items. + * @template T The type of items in the pool. Must extend PoolItem. + * @param {PoolItemConstructor} Class - The constructor of the items in the pool. + * @param {number} total - The number of items to add to the pool. + */ + prepopulate(e, t) { + this.getPool(e).prepopulate(t); + } + /** + * Gets an item from a specific pool. + * @template T The type of items in the pool. Must extend PoolItem. + * @param {PoolItemConstructor} Class - The constructor of the items in the pool. + * @param {unknown} [data] - Optional data to pass to the item's constructor. + * @returns {T} The item from the pool. + */ + get(e, t) { + return this.getPool(e).get(t); + } + /** + * Returns an item to its respective pool. + * @param {PoolItem} item - The item to return to the pool. + */ + return(e) { + this.getPool(e.constructor).return(e); + } + /** + * Gets a specific pool based on the class type. + * @template T The type of items in the pool. Must extend PoolItem. + * @param {PoolItemConstructor} ClassType - The constructor of the items in the pool. + * @returns {Pool} The pool of the given class type. + */ + getPool(e) { + return this._poolsByClass.has(e) || this._poolsByClass.set(e, new Yh(e)), this._poolsByClass.get(e); + } + /** gets the usage stats of each pool in the system */ + stats() { + const e = {}; + return this._poolsByClass.forEach((t) => { + const n = e[t._classType.name] ? t._classType.name + t._classType.ID : t._classType.name; + e[n] = { + free: t.totalFree, + used: t.totalUsed, + size: t.totalSize + }; + }), e; + } + /** Clears all pools in the group. This will reset all pools and free their resources. */ + clear() { + this._poolsByClass.forEach((e) => e.clear()), this._poolsByClass.clear(); + } +} +const Ze = new Xh(); +Bn.register(Ze); +const jh = { + get isCachedAsTexture() { + var i; + return !!((i = this.renderGroup) != null && i.isCachedAsTexture); + }, + cacheAsTexture(i) { + typeof i == "boolean" && i === !1 ? this.disableRenderGroup() : (this.enableRenderGroup(), this.renderGroup.enableCacheAsTexture(i === !0 ? {} : i)); + }, + updateCacheTexture() { + var i; + (i = this.renderGroup) == null || i.updateCacheTexture(); + }, + get cacheAsBitmap() { + return this.isCachedAsTexture; + }, + set cacheAsBitmap(i) { + W("v8.6.0", "cacheAsBitmap is deprecated, use cacheAsTexture instead."), this.cacheAsTexture(i); + } +}; +function Zh(i, e, t) { + const n = i.length; + let s; + if (e >= n || t === 0) + return; + t = e + t > n ? n - e : t; + const r = n - t; + for (s = e; s < r; ++s) + i[s] = i[s + t]; + i.length = r; +} +const Kh = { + allowChildren: !0, + removeChildren(i = 0, e) { + var r; + const t = e ?? this.children.length, n = t - i, s = []; + if (n > 0 && n <= t) { + for (let o = t - 1; o >= i; o--) { + const l = this.children[o]; + l && (s.push(l), l.parent = null); + } + Zh(this.children, i, t); + const a = this.renderGroup || this.parentRenderGroup; + a && a.removeChildren(s); + for (let o = 0; o < s.length; ++o) { + const l = s[o]; + (r = l.parentRenderLayer) == null || r.detach(l), this.emit("childRemoved", l, this, o), s[o].emit("removed", this); + } + return s.length > 0 && this._didViewChangeTick++, s; + } else if (n === 0 && this.children.length === 0) + return s; + throw new RangeError("removeChildren: numeric values are outside the acceptable range."); + }, + removeChildAt(i) { + const e = this.getChildAt(i); + return this.removeChild(e); + }, + getChildAt(i) { + if (i < 0 || i >= this.children.length) + throw new Error(`getChildAt: Index (${i}) does not exist.`); + return this.children[i]; + }, + setChildIndex(i, e) { + if (e < 0 || e >= this.children.length) + throw new Error(`The index ${e} supplied is out of bounds ${this.children.length}`); + this.getChildIndex(i), this.addChildAt(i, e); + }, + getChildIndex(i) { + const e = this.children.indexOf(i); + if (e === -1) + throw new Error("The supplied Container must be a child of the caller"); + return e; + }, + addChildAt(i, e) { + this.allowChildren || W(he, "addChildAt: Only Containers will be allowed to add children in v8.0.0"); + const { children: t } = this; + if (e < 0 || e > t.length) + throw new Error(`${i}addChildAt: The index ${e} supplied is out of bounds ${t.length}`); + if (i.parent) { + const s = i.parent.children.indexOf(i); + if (i.parent === this && s === e) + return i; + s !== -1 && i.parent.children.splice(s, 1); + } + e === t.length ? t.push(i) : t.splice(e, 0, i), i.parent = this, i.didChange = !0, i._updateFlags = 15; + const n = this.renderGroup || this.parentRenderGroup; + return n && n.addChild(i), this.sortableChildren && (this.sortDirty = !0), this.emit("childAdded", i, this, e), i.emit("added", this), i; + }, + swapChildren(i, e) { + if (i === e) + return; + const t = this.getChildIndex(i), n = this.getChildIndex(e); + this.children[t] = e, this.children[n] = i; + const s = this.renderGroup || this.parentRenderGroup; + s && (s.structureDidChange = !0), this._didContainerChangeTick++; + }, + removeFromParent() { + var i; + (i = this.parent) == null || i.removeChild(this); + }, + reparentChild(...i) { + return i.length === 1 ? this.reparentChildAt(i[0], this.children.length) : (i.forEach((e) => this.reparentChildAt(e, this.children.length)), i[0]); + }, + reparentChildAt(i, e) { + if (i.parent === this) + return this.setChildIndex(i, e), i; + const t = i.worldTransform.clone(); + i.removeFromParent(), this.addChildAt(i, e); + const n = this.worldTransform.clone(); + return n.invert(), t.prepend(n), i.setFromMatrix(t), i; + }, + replaceChild(i, e) { + i.updateLocalTransform(), this.addChildAt(e, this.getChildIndex(i)), e.setFromMatrix(i.localTransform), e.updateLocalTransform(), this.removeChild(i); + } +}, Qh = { + collectRenderables(i, e, t) { + this.parentRenderLayer && this.parentRenderLayer !== t || this.globalDisplayStatus < 7 || !this.includeInBuild || (this.sortableChildren && this.sortChildren(), this.isSimple ? this.collectRenderablesSimple(i, e, t) : this.renderGroup ? e.renderPipes.renderGroup.addRenderGroup(this.renderGroup, i) : this.collectRenderablesWithEffects(i, e, t)); + }, + collectRenderablesSimple(i, e, t) { + const n = this.children, s = n.length; + for (let r = 0; r < s; r++) + n[r].collectRenderables(i, e, t); + }, + collectRenderablesWithEffects(i, e, t) { + const { renderPipes: n } = e; + for (let s = 0; s < this.effects.length; s++) { + const r = this.effects[s]; + n[r.pipe].push(r, this, i); + } + this.collectRenderablesSimple(i, e, t); + for (let s = this.effects.length - 1; s >= 0; s--) { + const r = this.effects[s]; + n[r.pipe].pop(r, this, i); + } + } +}; +class Tr { + constructor() { + this.pipe = "filter", this.priority = 1; + } + destroy() { + for (let e = 0; e < this.filters.length; e++) + this.filters[e].destroy(); + this.filters = null, this.filterArea = null; + } +} +class Jh { + constructor() { + this._effectClasses = [], this._tests = [], this._initialized = !1; + } + init() { + this._initialized || (this._initialized = !0, this._effectClasses.forEach((e) => { + this.add({ + test: e.test, + maskClass: e + }); + })); + } + add(e) { + this._tests.push(e); + } + getMaskEffect(e) { + this._initialized || this.init(); + for (let t = 0; t < this._tests.length; t++) { + const n = this._tests[t]; + if (n.test(e)) + return Ze.get(n.maskClass, e); + } + return e; + } + returnMaskEffect(e) { + Ze.return(e); + } +} +const ms = new Jh(); +Qe.handleByList(Q.MaskEffect, ms._effectClasses); +const eu = { + _maskEffect: null, + _maskOptions: { + inverse: !1 + }, + _filterEffect: null, + effects: [], + _markStructureAsChanged() { + const i = this.renderGroup || this.parentRenderGroup; + i && (i.structureDidChange = !0); + }, + addEffect(i) { + this.effects.indexOf(i) === -1 && (this.effects.push(i), this.effects.sort((t, n) => t.priority - n.priority), this._markStructureAsChanged(), this._updateIsSimple()); + }, + removeEffect(i) { + const e = this.effects.indexOf(i); + e !== -1 && (this.effects.splice(e, 1), this._markStructureAsChanged(), this._updateIsSimple()); + }, + set mask(i) { + const e = this._maskEffect; + (e == null ? void 0 : e.mask) !== i && (e && (this.removeEffect(e), ms.returnMaskEffect(e), this._maskEffect = null), i != null && (this._maskEffect = ms.getMaskEffect(i), this.addEffect(this._maskEffect))); + }, + get mask() { + var i; + return (i = this._maskEffect) == null ? void 0 : i.mask; + }, + setMask(i) { + this._maskOptions = { + ...this._maskOptions, + ...i + }, i.mask && (this.mask = i.mask), this._markStructureAsChanged(); + }, + set filters(i) { + var r; + !Array.isArray(i) && i && (i = [i]); + const e = this._filterEffect || (this._filterEffect = new Tr()); + i = i; + const t = (i == null ? void 0 : i.length) > 0, n = ((r = e.filters) == null ? void 0 : r.length) > 0, s = t !== n; + i = Array.isArray(i) ? i.slice(0) : i, e.filters = Object.freeze(i), s && (t ? this.addEffect(e) : (this.removeEffect(e), e.filters = i ?? null)); + }, + get filters() { + var i; + return (i = this._filterEffect) == null ? void 0 : i.filters; + }, + set filterArea(i) { + this._filterEffect || (this._filterEffect = new Tr()), this._filterEffect.filterArea = i; + }, + get filterArea() { + var i; + return (i = this._filterEffect) == null ? void 0 : i.filterArea; + } +}, tu = { + label: null, + get name() { + return W(he, "Container.name property has been removed, use Container.label instead"), this.label; + }, + set name(i) { + W(he, "Container.name property has been removed, use Container.label instead"), this.label = i; + }, + getChildByName(i, e = !1) { + return this.getChildByLabel(i, e); + }, + getChildByLabel(i, e = !1) { + const t = this.children; + for (let n = 0; n < t.length; n++) { + const s = t[n]; + if (s.label === i || i instanceof RegExp && i.test(s.label)) + return s; + } + if (e) + for (let n = 0; n < t.length; n++) { + const r = t[n].getChildByLabel(i, !0); + if (r) + return r; + } + return null; + }, + getChildrenByLabel(i, e = !1, t = []) { + const n = this.children; + for (let s = 0; s < n.length; s++) { + const r = n[s]; + (r.label === i || i instanceof RegExp && i.test(r.label)) && t.push(r); + } + if (e) + for (let s = 0; s < n.length; s++) + n[s].getChildrenByLabel(i, !0, t); + return t; + } +}, Fe = Ze.getPool(H), kt = Ze.getPool(ht), nu = new H(), iu = { + getFastGlobalBounds(i, e) { + e || (e = new ht()), e.clear(), this._getGlobalBoundsRecursive(!!i, e, this.parentRenderLayer), e.isValid || e.set(0, 0, 0, 0); + const t = this.renderGroup || this.parentRenderGroup; + return e.applyMatrix(t.worldTransform), e; + }, + _getGlobalBoundsRecursive(i, e, t) { + let n = e; + if (i && this.parentRenderLayer && this.parentRenderLayer !== t || this.localDisplayStatus !== 7 || !this.measurable) + return; + const s = !!this.effects.length; + if ((this.renderGroup || s) && (n = kt.get().clear()), this.boundsArea) + e.addRect(this.boundsArea, this.worldTransform); + else { + if (this.renderPipeId) { + const a = this.bounds; + n.addFrame( + a.minX, + a.minY, + a.maxX, + a.maxY, + this.groupTransform + ); + } + const r = this.children; + for (let a = 0; a < r.length; a++) + r[a]._getGlobalBoundsRecursive(i, n, t); + } + if (s) { + let r = !1; + const a = this.renderGroup || this.parentRenderGroup; + for (let o = 0; o < this.effects.length; o++) + this.effects[o].addBounds && (r || (r = !0, n.applyMatrix(a.worldTransform)), this.effects[o].addBounds(n, !0)); + r && n.applyMatrix(a.worldTransform.copyTo(nu).invert()), e.addBounds(n), kt.return(n); + } else this.renderGroup && (e.addBounds(n, this.relativeGroupTransform), kt.return(n)); + } +}; +function Ro(i, e, t) { + t.clear(); + let n, s; + return i.parent ? e ? n = i.parent.worldTransform : (s = Fe.get().identity(), n = Vs(i, s)) : n = H.IDENTITY, Bo(i, t, n, e), s && Fe.return(s), t.isValid || t.set(0, 0, 0, 0), t; +} +function Bo(i, e, t, n) { + var o, l; + if (!i.visible || !i.measurable) + return; + let s; + n ? s = i.worldTransform : (i.updateLocalTransform(), s = Fe.get(), s.appendFrom(i.localTransform, t)); + const r = e, a = !!i.effects.length; + if (a && (e = kt.get().clear()), i.boundsArea) + e.addRect(i.boundsArea, s); + else { + const h = i.bounds; + h && !h.isEmpty() && (e.matrix = s, e.addBounds(h)); + for (let u = 0; u < i.children.length; u++) + Bo(i.children[u], e, s, n); + } + if (a) { + for (let h = 0; h < i.effects.length; h++) + (l = (o = i.effects[h]).addBounds) == null || l.call(o, e); + r.addBounds(e, H.IDENTITY), kt.return(e); + } + n || Fe.return(s); +} +function Vs(i, e) { + const t = i.parent; + return t && (Vs(t, e), t.updateLocalTransform(), e.append(t.localTransform)), e; +} +function Lo(i, e) { + if (i === 16777215 || !e) + return e; + if (e === 16777215 || !i) + return i; + const t = i >> 16 & 255, n = i >> 8 & 255, s = i & 255, r = e >> 16 & 255, a = e >> 8 & 255, o = e & 255, l = t * r / 255 | 0, h = n * a / 255 | 0, u = s * o / 255 | 0; + return (l << 16) + (h << 8) + u; +} +const Mr = 16777215; +function Pr(i, e) { + return i === Mr ? e : e === Mr ? i : Lo(i, e); +} +function ci(i) { + return ((i & 255) << 16) + (i & 65280) + (i >> 16 & 255); +} +const su = { + getGlobalAlpha(i) { + if (i) + return this.renderGroup ? this.renderGroup.worldAlpha : this.parentRenderGroup ? this.parentRenderGroup.worldAlpha * this.alpha : this.alpha; + let e = this.alpha, t = this.parent; + for (; t; ) + e *= t.alpha, t = t.parent; + return e; + }, + getGlobalTransform(i = new H(), e) { + if (e) + return i.copyFrom(this.worldTransform); + this.updateLocalTransform(); + const t = Vs(this, Fe.get().identity()); + return i.appendFrom(this.localTransform, t), Fe.return(t), i; + }, + getGlobalTint(i) { + if (i) + return this.renderGroup ? ci(this.renderGroup.worldColor) : this.parentRenderGroup ? ci( + Pr(this.localColor, this.parentRenderGroup.worldColor) + ) : this.tint; + let e = this.localColor, t = this.parent; + for (; t; ) + e = Pr(e, t.localColor), t = t.parent; + return ci(e); + } +}; +function Oo(i, e, t) { + return e.clear(), t || (t = H.IDENTITY), zo(i, e, t, i, !0), e.isValid || e.set(0, 0, 0, 0), e; +} +function zo(i, e, t, n, s) { + var l, h; + let r; + if (s) + r = Fe.get(), r = t.copyTo(r); + else { + if (!i.visible || !i.measurable) + return; + i.updateLocalTransform(); + const u = i.localTransform; + r = Fe.get(), r.appendFrom(u, t); + } + const a = e, o = !!i.effects.length; + if (o && (e = kt.get().clear()), i.boundsArea) + e.addRect(i.boundsArea, r); + else { + i.renderPipeId && (e.matrix = r, e.addBounds(i.bounds)); + const u = i.children; + for (let c = 0; c < u.length; c++) + zo(u[c], e, r, n, !1); + } + if (o) { + for (let u = 0; u < i.effects.length; u++) + (h = (l = i.effects[u]).addLocalBounds) == null || h.call(l, e, n); + a.addBounds(e, H.IDENTITY), kt.return(e); + } + Fe.return(r); +} +function No(i, e) { + const t = i.children; + for (let n = 0; n < t.length; n++) { + const s = t[n], r = s.uid, a = (s._didViewChangeTick & 65535) << 16 | s._didContainerChangeTick & 65535, o = e.index; + (e.data[o] !== r || e.data[o + 1] !== a) && (e.data[e.index] = r, e.data[e.index + 1] = a, e.didChange = !0), e.index = o + 2, s.children.length && No(s, e); + } + return e.didChange; +} +const ru = new H(), au = { + _localBoundsCacheId: -1, + _localBoundsCacheData: null, + _setWidth(i, e) { + const t = Math.sign(this.scale.x) || 1; + e !== 0 ? this.scale.x = i / e * t : this.scale.x = t; + }, + _setHeight(i, e) { + const t = Math.sign(this.scale.y) || 1; + e !== 0 ? this.scale.y = i / e * t : this.scale.y = t; + }, + getLocalBounds() { + this._localBoundsCacheData || (this._localBoundsCacheData = { + data: [], + index: 1, + didChange: !1, + localBounds: new ht() + }); + const i = this._localBoundsCacheData; + return i.index = 1, i.didChange = !1, i.data[0] !== this._didViewChangeTick && (i.didChange = !0, i.data[0] = this._didViewChangeTick), No(this, i), i.didChange && Oo(this, i.localBounds, ru), i.localBounds; + }, + getBounds(i, e) { + return Ro(this, i, e || new ht()); + } +}, ou = { + _onRender: null, + set onRender(i) { + const e = this.renderGroup || this.parentRenderGroup; + if (!i) { + this._onRender && (e == null || e.removeOnRender(this)), this._onRender = null; + return; + } + this._onRender || e == null || e.addOnRender(this), this._onRender = i; + }, + get onRender() { + return this._onRender; + } +}, lu = { + _zIndex: 0, + sortDirty: !1, + sortableChildren: !1, + get zIndex() { + return this._zIndex; + }, + set zIndex(i) { + this._zIndex !== i && (this._zIndex = i, this.depthOfChildModified()); + }, + depthOfChildModified() { + this.parent && (this.parent.sortableChildren = !0, this.parent.sortDirty = !0), this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0); + }, + sortChildren() { + this.sortDirty && (this.sortDirty = !1, this.children.sort(hu)); + } +}; +function hu(i, e) { + return i._zIndex - e._zIndex; +} +const uu = { + getGlobalPosition(i = new Ae(), e = !1) { + return this.parent ? this.parent.toGlobal(this._position, i, e) : (i.x = this._position.x, i.y = this._position.y), i; + }, + toGlobal(i, e, t = !1) { + const n = this.getGlobalTransform(Fe.get(), t); + return e = n.apply(i, e), Fe.return(n), e; + }, + toLocal(i, e, t, n) { + e && (i = e.toGlobal(i, t, n)); + const s = this.getGlobalTransform(Fe.get(), n); + return t = s.applyInverse(i, t), Fe.return(s), t; + } +}; +class Go { + constructor() { + this.uid = ue("instructionSet"), this.instructions = [], this.instructionSize = 0, this.renderables = [], this.gcTick = 0; + } + /** reset the instruction set so it can be reused set size back to 0 */ + reset() { + this.instructionSize = 0; + } + /** + * Destroy the instruction set, clearing the instructions and renderables. + * @internal + */ + destroy() { + this.instructions.length = 0, this.renderables.length = 0, this.renderPipes = null, this.gcTick = 0; + } + /** + * Add an instruction to the set + * @param instruction - add an instruction to the set + */ + add(e) { + this.instructions[this.instructionSize++] = e; + } + /** + * Log the instructions to the console (for debugging) + * @internal + */ + log() { + this.instructions.length = this.instructionSize, console.table(this.instructions, ["type", "action"]); + } +} +let cu = 0; +class du { + /** + * @param textureOptions - options that will be passed to BaseRenderTexture constructor + * @param {SCALE_MODE} [textureOptions.scaleMode] - See {@link SCALE_MODE} for possible values. + */ + constructor(e) { + this._poolKeyHash = /* @__PURE__ */ Object.create(null), this._texturePool = {}, this.textureOptions = e || {}, this.enableFullScreen = !1, this.textureStyle = new _i(this.textureOptions); + } + /** + * Creates texture with params that were specified in pool constructor. + * @param pixelWidth - Width of texture in pixels. + * @param pixelHeight - Height of texture in pixels. + * @param antialias + */ + createTexture(e, t, n) { + const s = new ut({ + ...this.textureOptions, + width: e, + height: t, + resolution: 1, + antialias: n, + autoGarbageCollect: !1 + }); + return new K({ + source: s, + label: `texturePool_${cu++}` + }); + } + /** + * Gets a Power-of-Two render texture or fullScreen texture + * @param frameWidth - The minimum width of the render texture. + * @param frameHeight - The minimum height of the render texture. + * @param resolution - The resolution of the render texture. + * @param antialias + * @returns The new render texture. + */ + getOptimalTexture(e, t, n = 1, s) { + let r = Math.ceil(e * n - 1e-6), a = Math.ceil(t * n - 1e-6); + r = tn(r), a = tn(a); + const o = (r << 17) + (a << 1) + (s ? 1 : 0); + this._texturePool[o] || (this._texturePool[o] = []); + let l = this._texturePool[o].pop(); + return l || (l = this.createTexture(r, a, s)), l.source._resolution = n, l.source.width = r / n, l.source.height = a / n, l.source.pixelWidth = r, l.source.pixelHeight = a, l.frame.x = 0, l.frame.y = 0, l.frame.width = e, l.frame.height = t, l.updateUvs(), this._poolKeyHash[l.uid] = o, l; + } + /** + * Gets extra texture of the same size as input renderTexture + * @param texture - The texture to check what size it is. + * @param antialias - Whether to use antialias. + * @returns A texture that is a power of two + */ + getSameSizeTexture(e, t = !1) { + const n = e.source; + return this.getOptimalTexture(e.width, e.height, n._resolution, t); + } + /** + * Place a render texture back into the pool. Optionally reset the style of the texture to the default texture style. + * useful if you modified the style of the texture after getting it from the pool. + * @param renderTexture - The renderTexture to free + * @param resetStyle - Whether to reset the style of the texture to the default texture style + */ + returnTexture(e, t = !1) { + const n = this._poolKeyHash[e.uid]; + t && (e.source.style = this.textureStyle), this._texturePool[n].push(e); + } + /** + * Clears the pool. + * @param destroyTextures - Destroy all stored textures. + */ + clear(e) { + if (e = e !== !1, e) + for (const t in this._texturePool) { + const n = this._texturePool[t]; + if (n) + for (let s = 0; s < n.length; s++) + n[s].destroy(!0); + } + this._texturePool = {}; + } +} +const qo = new du(); +Bn.register(qo); +class fu { + constructor() { + this.renderPipeId = "renderGroup", this.root = null, this.canBundle = !1, this.renderGroupParent = null, this.renderGroupChildren = [], this.worldTransform = new H(), this.worldColorAlpha = 4294967295, this.worldColor = 16777215, this.worldAlpha = 1, this.childrenToUpdate = /* @__PURE__ */ Object.create(null), this.updateTick = 0, this.gcTick = 0, this.childrenRenderablesToUpdate = { list: [], index: 0 }, this.structureDidChange = !0, this.instructionSet = new Go(), this._onRenderContainers = [], this.textureNeedsUpdate = !0, this.isCachedAsTexture = !1, this._matrixDirty = 7; + } + init(e) { + this.root = e, e._onRender && this.addOnRender(e), e.didChange = !0; + const t = e.children; + for (let n = 0; n < t.length; n++) { + const s = t[n]; + s._updateFlags = 15, this.addChild(s); + } + } + enableCacheAsTexture(e = {}) { + this.textureOptions = e, this.isCachedAsTexture = !0, this.textureNeedsUpdate = !0; + } + disableCacheAsTexture() { + this.isCachedAsTexture = !1, this.texture && (qo.returnTexture(this.texture, !0), this.texture = null); + } + updateCacheTexture() { + this.textureNeedsUpdate = !0; + const e = this._parentCacheAsTextureRenderGroup; + e && !e.textureNeedsUpdate && e.updateCacheTexture(); + } + reset() { + this.renderGroupChildren.length = 0; + for (const e in this.childrenToUpdate) { + const t = this.childrenToUpdate[e]; + t.list.fill(null), t.index = 0; + } + this.childrenRenderablesToUpdate.index = 0, this.childrenRenderablesToUpdate.list.fill(null), this.root = null, this.updateTick = 0, this.structureDidChange = !0, this._onRenderContainers.length = 0, this.renderGroupParent = null, this.disableCacheAsTexture(); + } + get localTransform() { + return this.root.localTransform; + } + addRenderGroupChild(e) { + e.renderGroupParent && e.renderGroupParent._removeRenderGroupChild(e), e.renderGroupParent = this, this.renderGroupChildren.push(e); + } + _removeRenderGroupChild(e) { + const t = this.renderGroupChildren.indexOf(e); + t > -1 && this.renderGroupChildren.splice(t, 1), e.renderGroupParent = null; + } + addChild(e) { + if (this.structureDidChange = !0, e.parentRenderGroup = this, e.updateTick = -1, e.parent === this.root ? e.relativeRenderGroupDepth = 1 : e.relativeRenderGroupDepth = e.parent.relativeRenderGroupDepth + 1, e.didChange = !0, this.onChildUpdate(e), e.renderGroup) { + this.addRenderGroupChild(e.renderGroup); + return; + } + e._onRender && this.addOnRender(e); + const t = e.children; + for (let n = 0; n < t.length; n++) + this.addChild(t[n]); + } + removeChild(e) { + if (this.structureDidChange = !0, e._onRender && (e.renderGroup || this.removeOnRender(e)), e.parentRenderGroup = null, e.renderGroup) { + this._removeRenderGroupChild(e.renderGroup); + return; + } + const t = e.children; + for (let n = 0; n < t.length; n++) + this.removeChild(t[n]); + } + removeChildren(e) { + for (let t = 0; t < e.length; t++) + this.removeChild(e[t]); + } + onChildUpdate(e) { + let t = this.childrenToUpdate[e.relativeRenderGroupDepth]; + t || (t = this.childrenToUpdate[e.relativeRenderGroupDepth] = { + index: 0, + list: [] + }), t.list[t.index++] = e; + } + updateRenderable(e) { + e.globalDisplayStatus < 7 || (this.instructionSet.renderPipes[e.renderPipeId].updateRenderable(e), e.didViewUpdate = !1); + } + onChildViewUpdate(e) { + this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = e; + } + get isRenderable() { + return this.root.localDisplayStatus === 7 && this.worldAlpha > 0; + } + /** + * adding a container to the onRender list will make sure the user function + * passed in to the user defined 'onRender` callBack + * @param container - the container to add to the onRender list + */ + addOnRender(e) { + this._onRenderContainers.push(e); + } + removeOnRender(e) { + this._onRenderContainers.splice(this._onRenderContainers.indexOf(e), 1); + } + runOnRender(e) { + for (let t = 0; t < this._onRenderContainers.length; t++) + this._onRenderContainers[t]._onRender(e); + } + destroy() { + this.disableCacheAsTexture(), this.renderGroupParent = null, this.root = null, this.childrenRenderablesToUpdate = null, this.childrenToUpdate = null, this.renderGroupChildren = null, this._onRenderContainers = null, this.instructionSet = null; + } + getChildren(e = []) { + const t = this.root.children; + for (let n = 0; n < t.length; n++) + this._getChildren(t[n], e); + return e; + } + _getChildren(e, t = []) { + if (t.push(e), e.renderGroup) + return t; + const n = e.children; + for (let s = 0; s < n.length; s++) + this._getChildren(n[s], t); + return t; + } + invalidateMatrices() { + this._matrixDirty = 7; + } + /** + * Returns the inverse of the world transform matrix. + * @returns {Matrix} The inverse of the world transform matrix. + */ + get inverseWorldTransform() { + return this._matrixDirty & 1 ? (this._matrixDirty &= -2, this._inverseWorldTransform || (this._inverseWorldTransform = new H()), this._inverseWorldTransform.copyFrom(this.worldTransform).invert()) : this._inverseWorldTransform; + } + /** + * Returns the inverse of the texture offset transform matrix. + * @returns {Matrix} The inverse of the texture offset transform matrix. + */ + get textureOffsetInverseTransform() { + return this._matrixDirty & 2 ? (this._matrixDirty &= -3, this._textureOffsetInverseTransform || (this._textureOffsetInverseTransform = new H()), this._textureOffsetInverseTransform.copyFrom(this.inverseWorldTransform).translate( + -this._textureBounds.x, + -this._textureBounds.y + )) : this._textureOffsetInverseTransform; + } + /** + * Returns the inverse of the parent texture transform matrix. + * This is used to properly transform coordinates when rendering into cached textures. + * @returns {Matrix} The inverse of the parent texture transform matrix. + */ + get inverseParentTextureTransform() { + if (!(this._matrixDirty & 4)) + return this._inverseParentTextureTransform; + this._matrixDirty &= -5; + const e = this._parentCacheAsTextureRenderGroup; + return e ? (this._inverseParentTextureTransform || (this._inverseParentTextureTransform = new H()), this._inverseParentTextureTransform.copyFrom(this.worldTransform).prepend(e.inverseWorldTransform).translate( + -e._textureBounds.x, + -e._textureBounds.y + )) : this.worldTransform; + } + /** + * Returns a matrix that transforms coordinates to the correct coordinate space of the texture being rendered to. + * This is the texture offset inverse transform of the closest parent RenderGroup that is cached as a texture. + * @returns {Matrix | null} The transform matrix for the cached texture coordinate space, + * or null if no parent is cached as texture. + */ + get cacheToLocalTransform() { + return this.isCachedAsTexture ? this.textureOffsetInverseTransform : this._parentCacheAsTextureRenderGroup ? this._parentCacheAsTextureRenderGroup.textureOffsetInverseTransform : null; + } +} +function pu(i, e, t = {}) { + for (const n in e) + !t[n] && e[n] !== void 0 && (i[n] = e[n]); +} +const Oi = new Ce(null), Vn = new Ce(null), zi = new Ce(null, 1, 1), Wn = new Ce(null), Ir = 1, _u = 2, Ni = 4; +class Dt extends xt { + constructor(e = {}) { + var t, n; + super(), this.uid = ue("renderable"), this._updateFlags = 15, this.renderGroup = null, this.parentRenderGroup = null, this.parentRenderGroupIndex = 0, this.didChange = !1, this.didViewUpdate = !1, this.relativeRenderGroupDepth = 0, this.children = [], this.parent = null, this.includeInBuild = !0, this.measurable = !0, this.isSimple = !0, this.updateTick = -1, this.localTransform = new H(), this.relativeGroupTransform = new H(), this.groupTransform = this.relativeGroupTransform, this.destroyed = !1, this._position = new Ce(this, 0, 0), this._scale = zi, this._pivot = Vn, this._origin = Wn, this._skew = Oi, this._cx = 1, this._sx = 0, this._cy = 0, this._sy = 1, this._rotation = 0, this.localColor = 16777215, this.localAlpha = 1, this.groupAlpha = 1, this.groupColor = 16777215, this.groupColorAlpha = 4294967295, this.localBlendMode = "inherit", this.groupBlendMode = "normal", this.localDisplayStatus = 7, this.globalDisplayStatus = 7, this._didContainerChangeTick = 0, this._didViewChangeTick = 0, this._didLocalTransformChangeId = -1, this.effects = [], pu(this, e, { + children: !0, + parent: !0, + effects: !0 + }), (t = e.children) == null || t.forEach((s) => this.addChild(s)), (n = e.parent) == null || n.addChild(this); + } + /** + * Mixes all enumerable properties and methods from a source object to Container. + * @param source - The source of properties and methods to mix in. + * @deprecated since 8.8.0 + */ + static mixin(e) { + W("8.8.0", "Container.mixin is deprecated, please use extensions.mixin instead."), Qe.mixin(Dt, e); + } + // = 'default'; + /** + * We now use the _didContainerChangeTick and _didViewChangeTick to track changes + * @deprecated since 8.2.6 + * @ignore + */ + set _didChangeId(e) { + this._didViewChangeTick = e >> 12 & 4095, this._didContainerChangeTick = e & 4095; + } + /** @ignore */ + get _didChangeId() { + return this._didContainerChangeTick & 4095 | (this._didViewChangeTick & 4095) << 12; + } + /** + * Adds one or more children to the container. + * The children will be rendered as part of this container's display list. + * @example + * ```ts + * // Add a single child + * container.addChild(sprite); + * + * // Add multiple children + * container.addChild(background, player, foreground); + * + * // Add with type checking + * const sprite = container.addChild(new Sprite(texture)); + * sprite.tint = 'red'; + * ``` + * @param children - The Container(s) to add to the container + * @returns The first child that was added + * @see {@link Container#removeChild} For removing children + * @see {@link Container#addChildAt} For adding at specific index + */ + addChild(...e) { + if (this.allowChildren || W(he, "addChild: Only Containers will be allowed to add children in v8.0.0"), e.length > 1) { + for (let s = 0; s < e.length; s++) + this.addChild(e[s]); + return e[0]; + } + const t = e[0], n = this.renderGroup || this.parentRenderGroup; + return t.parent === this ? (this.children.splice(this.children.indexOf(t), 1), this.children.push(t), n && (n.structureDidChange = !0), t) : (t.parent && t.parent.removeChild(t), this.children.push(t), this.sortableChildren && (this.sortDirty = !0), t.parent = this, t.didChange = !0, t._updateFlags = 15, n && n.addChild(t), this.emit("childAdded", t, this, this.children.length - 1), t.emit("added", this), this._didViewChangeTick++, t._zIndex !== 0 && t.depthOfChildModified(), t); + } + /** + * Removes one or more children from the container. + * When removing multiple children, events will be triggered for each child in sequence. + * @example + * ```ts + * // Remove a single child + * const removed = container.removeChild(sprite); + * + * // Remove multiple children + * const bg = container.removeChild(background, player, userInterface); + * + * // Remove with type checking + * const sprite = container.removeChild(childSprite); + * sprite.texture = newTexture; + * ``` + * @param children - The Container(s) to remove + * @returns The first child that was removed + * @see {@link Container#addChild} For adding children + * @see {@link Container#removeChildren} For removing multiple children + */ + removeChild(...e) { + if (e.length > 1) { + for (let s = 0; s < e.length; s++) + this.removeChild(e[s]); + return e[0]; + } + const t = e[0], n = this.children.indexOf(t); + return n > -1 && (this._didViewChangeTick++, this.children.splice(n, 1), this.renderGroup ? this.renderGroup.removeChild(t) : this.parentRenderGroup && this.parentRenderGroup.removeChild(t), t.parentRenderLayer && t.parentRenderLayer.detach(t), t.parent = null, this.emit("childRemoved", t, this, n), t.emit("removed", this)), t; + } + /** @ignore */ + _onUpdate(e) { + e && e === this._skew && this._updateSkew(), this._didContainerChangeTick++, !this.didChange && (this.didChange = !0, this.parentRenderGroup && this.parentRenderGroup.onChildUpdate(this)); + } + set isRenderGroup(e) { + !!this.renderGroup !== e && (e ? this.enableRenderGroup() : this.disableRenderGroup()); + } + /** + * Returns true if this container is a render group. + * This means that it will be rendered as a separate pass, with its own set of instructions + * @advanced + */ + get isRenderGroup() { + return !!this.renderGroup; + } + /** + * Calling this enables a render group for this container. + * This means it will be rendered as a separate set of instructions. + * The transform of the container will also be handled on the GPU rather than the CPU. + * @advanced + */ + enableRenderGroup() { + if (this.renderGroup) + return; + const e = this.parentRenderGroup; + e == null || e.removeChild(this), this.renderGroup = Ze.get(fu, this), this.groupTransform = H.IDENTITY, e == null || e.addChild(this), this._updateIsSimple(); + } + /** + * This will disable the render group for this container. + * @advanced + */ + disableRenderGroup() { + if (!this.renderGroup) + return; + const e = this.parentRenderGroup; + e == null || e.removeChild(this), Ze.return(this.renderGroup), this.renderGroup = null, this.groupTransform = this.relativeGroupTransform, e == null || e.addChild(this), this._updateIsSimple(); + } + /** @ignore */ + _updateIsSimple() { + this.isSimple = !this.renderGroup && this.effects.length === 0; + } + /** + * Current transform of the object based on world (parent) factors. + * + * This matrix represents the absolute transformation in the scene graph. + * @example + * ```ts + * // Get world position + * const worldPos = container.worldTransform; + * console.log(`World position: (${worldPos.tx}, ${worldPos.ty})`); + * ``` + * @readonly + * @see {@link Container#localTransform} For local space transform + */ + get worldTransform() { + return this._worldTransform || (this._worldTransform = new H()), this.renderGroup ? this._worldTransform.copyFrom(this.renderGroup.worldTransform) : this.parentRenderGroup && this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform), this._worldTransform; + } + /** + * The position of the container on the x axis relative to the local coordinates of the parent. + * + * An alias to position.x + * @example + * ```ts + * // Basic position + * container.x = 100; + * ``` + */ + get x() { + return this._position.x; + } + set x(e) { + this._position.x = e; + } + /** + * The position of the container on the y axis relative to the local coordinates of the parent. + * + * An alias to position.y + * @example + * ```ts + * // Basic position + * container.y = 200; + * ``` + */ + get y() { + return this._position.y; + } + set y(e) { + this._position.y = e; + } + /** + * The coordinate of the object relative to the local coordinates of the parent. + * @example + * ```ts + * // Basic position setting + * container.position.set(100, 200); + * container.position.set(100); // Sets both x and y to 100 + * // Using point data + * container.position = { x: 50, y: 75 }; + * ``` + * @since 4.0.0 + */ + get position() { + return this._position; + } + set position(e) { + this._position.copyFrom(e); + } + /** + * The rotation of the object in radians. + * + * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object; + * > rotation is in radians, angle is in degrees. + * @example + * ```ts + * // Basic rotation + * container.rotation = Math.PI / 4; // 45 degrees + * + * // Convert from degrees + * const degrees = 45; + * container.rotation = degrees * Math.PI / 180; + * + * // Rotate around center + * container.pivot.set(container.width / 2, container.height / 2); + * container.rotation = Math.PI; // 180 degrees + * + * // Rotate around center with origin + * container.origin.set(container.width / 2, container.height / 2); + * container.rotation = Math.PI; // 180 degrees + * ``` + */ + get rotation() { + return this._rotation; + } + set rotation(e) { + this._rotation !== e && (this._rotation = e, this._onUpdate(this._skew)); + } + /** + * The angle of the object in degrees. + * + * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object; + * > rotation is in radians, angle is in degrees. + * @example + * ```ts + * // Basic angle rotation + * sprite.angle = 45; // 45 degrees + * + * // Rotate around center + * sprite.pivot.set(sprite.width / 2, sprite.height / 2); + * sprite.angle = 180; // Half rotation + * + * // Rotate around center with origin + * sprite.origin.set(sprite.width / 2, sprite.height / 2); + * sprite.angle = 180; // Half rotation + * + * // Reset rotation + * sprite.angle = 0; + * ``` + */ + get angle() { + return this.rotation * Eh; + } + set angle(e) { + this.rotation = e * Fh; + } + /** + * The center of rotation, scaling, and skewing for this display object in its local space. + * The `position` is the projection of `pivot` in the parent's local space. + * + * By default, the pivot is the origin (0, 0). + * @example + * ```ts + * // Rotate around center + * container.pivot.set(container.width / 2, container.height / 2); + * container.rotation = Math.PI; // Rotates around center + * ``` + * @since 4.0.0 + */ + get pivot() { + return this._pivot === Vn && (this._pivot = new Ce(this, 0, 0)), this._pivot; + } + set pivot(e) { + this._pivot === Vn && (this._pivot = new Ce(this, 0, 0), this._origin !== Wn && $e("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof e == "number" ? this._pivot.set(e) : this._pivot.copyFrom(e); + } + /** + * The skew factor for the object in radians. Skewing is a transformation that distorts + * the object by rotating it differently at each point, creating a non-uniform shape. + * @example + * ```ts + * // Basic skewing + * container.skew.set(0.5, 0); // Skew horizontally + * container.skew.set(0, 0.5); // Skew vertically + * + * // Skew with point data + * container.skew = { x: 0.3, y: 0.3 }; // Diagonal skew + * + * // Reset skew + * container.skew.set(0, 0); + * + * // Animate skew + * app.ticker.add(() => { + * // Create wave effect + * container.skew.x = Math.sin(Date.now() / 1000) * 0.3; + * }); + * + * // Combine with rotation + * container.rotation = Math.PI / 4; // 45 degrees + * container.skew.set(0.2, 0.2); // Skew the rotated object + * ``` + * @since 4.0.0 + * @type {ObservablePoint} Point-like object with x/y properties in radians + * @default {x: 0, y: 0} + */ + get skew() { + return this._skew === Oi && (this._skew = new Ce(this, 0, 0)), this._skew; + } + set skew(e) { + this._skew === Oi && (this._skew = new Ce(this, 0, 0)), this._skew.copyFrom(e); + } + /** + * The scale factors of this object along the local coordinate axes. + * + * The default scale is (1, 1). + * @example + * ```ts + * // Basic scaling + * container.scale.set(2, 2); // Scales to double size + * container.scale.set(2); // Scales uniformly to double size + * container.scale = 2; // Scales uniformly to double size + * // Scale to a specific width and height + * container.setSize(200, 100); // Sets width to 200 and height to 100 + * ``` + * @since 4.0.0 + */ + get scale() { + return this._scale === zi && (this._scale = new Ce(this, 1, 1)), this._scale; + } + set scale(e) { + this._scale === zi && (this._scale = new Ce(this, 0, 0)), typeof e == "string" && (e = parseFloat(e)), typeof e == "number" ? this._scale.set(e) : this._scale.copyFrom(e); + } + /** + * @experimental + * The origin point around which the container rotates and scales without affecting its position. + * Unlike pivot, changing the origin will not move the container's position. + * @example + * ```ts + * // Rotate around center point + * container.origin.set(container.width / 2, container.height / 2); + * container.rotation = Math.PI; // Rotates around center + * + * // Reset origin + * container.origin.set(0, 0); + * ``` + */ + get origin() { + return this._origin === Wn && (this._origin = new Ce(this, 0, 0)), this._origin; + } + set origin(e) { + this._origin === Wn && (this._origin = new Ce(this, 0, 0), this._pivot !== Vn && $e("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof e == "number" ? this._origin.set(e) : this._origin.copyFrom(e); + } + /** + * The width of the Container, setting this will actually modify the scale to achieve the value set. + * > [!NOTE] Changing the width will adjust the scale.x property of the container while maintaining its aspect ratio. + * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize} + * as it is more optimized by not recalculating the local bounds twice. + * @example + * ```ts + * // Basic width setting + * container.width = 100; + * // Optimized width setting + * container.setSize(100, 100); + * ``` + */ + get width() { + return Math.abs(this.scale.x * this.getLocalBounds().width); + } + set width(e) { + const t = this.getLocalBounds().width; + this._setWidth(e, t); + } + /** + * The height of the Container, + * > [!NOTE] Changing the height will adjust the scale.y property of the container while maintaining its aspect ratio. + * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize} + * as it is more optimized by not recalculating the local bounds twice. + * @example + * ```ts + * // Basic height setting + * container.height = 200; + * // Optimized height setting + * container.setSize(100, 200); + * ``` + */ + get height() { + return Math.abs(this.scale.y * this.getLocalBounds().height); + } + set height(e) { + const t = this.getLocalBounds().height; + this._setHeight(e, t); + } + /** + * Retrieves the size of the container as a [Size]{@link Size} object. + * + * This is faster than get the width and height separately. + * @example + * ```ts + * // Basic size retrieval + * const size = container.getSize(); + * console.log(`Size: ${size.width}x${size.height}`); + * + * // Reuse existing size object + * const reuseSize = { width: 0, height: 0 }; + * container.getSize(reuseSize); + * ``` + * @param out - Optional object to store the size in. + * @returns The size of the container. + */ + getSize(e) { + e || (e = {}); + const t = this.getLocalBounds(); + return e.width = Math.abs(this.scale.x * t.width), e.height = Math.abs(this.scale.y * t.height), e; + } + /** + * Sets the size of the container to the specified width and height. + * This is more efficient than setting width and height separately as it only recalculates bounds once. + * @example + * ```ts + * // Basic size setting + * container.setSize(100, 200); + * + * // Set uniform size + * container.setSize(100); // Sets both width and height to 100 + * ``` + * @param value - This can be either a number or a [Size]{@link Size} object. + * @param height - The height to set. Defaults to the value of `width` if not provided. + */ + setSize(e, t) { + const n = this.getLocalBounds(); + typeof e == "object" ? (t = e.height ?? e.width, e = e.width) : t ?? (t = e), e !== void 0 && this._setWidth(e, n.width), t !== void 0 && this._setHeight(t, n.height); + } + /** Called when the skew or the rotation changes. */ + _updateSkew() { + const e = this._rotation, t = this._skew; + this._cx = Math.cos(e + t._y), this._sx = Math.sin(e + t._y), this._cy = -Math.sin(e - t._x), this._sy = Math.cos(e - t._x); + } + /** + * Updates the transform properties of the container. + * Allows partial updates of transform properties for optimized manipulation. + * @example + * ```ts + * // Basic transform update + * container.updateTransform({ + * x: 100, + * y: 200, + * rotation: Math.PI / 4 + * }); + * + * // Scale and rotate around center + * sprite.updateTransform({ + * pivotX: sprite.width / 2, + * pivotY: sprite.height / 2, + * scaleX: 2, + * scaleY: 2, + * rotation: Math.PI + * }); + * + * // Update position only + * button.updateTransform({ + * x: button.x + 10, // Move right + * y: button.y // Keep same y + * }); + * ``` + * @param opts - Transform options to update + * @param opts.x - The x position + * @param opts.y - The y position + * @param opts.scaleX - The x-axis scale factor + * @param opts.scaleY - The y-axis scale factor + * @param opts.rotation - The rotation in radians + * @param opts.skewX - The x-axis skew factor + * @param opts.skewY - The y-axis skew factor + * @param opts.pivotX - The x-axis pivot point + * @param opts.pivotY - The y-axis pivot point + * @returns This container, for chaining + * @see {@link Container#setFromMatrix} For matrix-based transforms + * @see {@link Container#position} For direct position access + */ + updateTransform(e) { + return this.position.set( + typeof e.x == "number" ? e.x : this.position.x, + typeof e.y == "number" ? e.y : this.position.y + ), this.scale.set( + typeof e.scaleX == "number" ? e.scaleX || 1 : this.scale.x, + typeof e.scaleY == "number" ? e.scaleY || 1 : this.scale.y + ), this.rotation = typeof e.rotation == "number" ? e.rotation : this.rotation, this.skew.set( + typeof e.skewX == "number" ? e.skewX : this.skew.x, + typeof e.skewY == "number" ? e.skewY : this.skew.y + ), this.pivot.set( + typeof e.pivotX == "number" ? e.pivotX : this.pivot.x, + typeof e.pivotY == "number" ? e.pivotY : this.pivot.y + ), this.origin.set( + typeof e.originX == "number" ? e.originX : this.origin.x, + typeof e.originY == "number" ? e.originY : this.origin.y + ), this; + } + /** + * Updates the local transform properties by decomposing the given matrix. + * Extracts position, scale, rotation, and skew from a transformation matrix. + * @example + * ```ts + * // Basic matrix transform + * const matrix = new Matrix() + * .translate(100, 100) + * .rotate(Math.PI / 4) + * .scale(2, 2); + * + * container.setFromMatrix(matrix); + * + * // Copy transform from another container + * const source = new Container(); + * source.position.set(100, 100); + * source.rotation = Math.PI / 2; + * + * target.setFromMatrix(source.localTransform); + * + * // Reset transform + * container.setFromMatrix(Matrix.IDENTITY); + * ``` + * @param matrix - The matrix to use for updating the transform + * @see {@link Container#updateTransform} For property-based updates + * @see {@link Matrix#decompose} For matrix decomposition details + */ + setFromMatrix(e) { + e.decompose(this); + } + /** Updates the local transform. */ + updateLocalTransform() { + const e = this._didContainerChangeTick; + if (this._didLocalTransformChangeId === e) + return; + this._didLocalTransformChangeId = e; + const t = this.localTransform, n = this._scale, s = this._pivot, r = this._origin, a = this._position, o = n._x, l = n._y, h = s._x, u = s._y, c = -r._x, d = -r._y; + t.a = this._cx * o, t.b = this._sx * o, t.c = this._cy * l, t.d = this._sy * l, t.tx = a._x - (h * t.a + u * t.c) + (c * t.a + d * t.c) - c, t.ty = a._y - (h * t.b + u * t.d) + (c * t.b + d * t.d) - d; + } + // / ///// color related stuff + set alpha(e) { + e !== this.localAlpha && (this.localAlpha = e, this._updateFlags |= Ir, this._onUpdate()); + } + /** + * The opacity of the object relative to its parent's opacity. + * Value ranges from 0 (fully transparent) to 1 (fully opaque). + * @example + * ```ts + * // Basic transparency + * sprite.alpha = 0.5; // 50% opacity + * + * // Inherited opacity + * container.alpha = 0.5; + * const child = new Sprite(texture); + * child.alpha = 0.5; + * container.addChild(child); + * // child's effective opacity is 0.25 (0.5 * 0.5) + * ``` + * @default 1 + * @see {@link Container#visible} For toggling visibility + * @see {@link Container#renderable} For render control + */ + get alpha() { + return this.localAlpha; + } + set tint(e) { + const n = pe.shared.setValue(e ?? 16777215).toBgrNumber(); + n !== this.localColor && (this.localColor = n, this._updateFlags |= Ir, this._onUpdate()); + } + /** + * The tint applied to the sprite. + * + * This can be any valid {@link ColorSource}. + * @example + * ```ts + * // Basic color tinting + * container.tint = 0xff0000; // Red tint + * container.tint = 'red'; // Same as above + * container.tint = '#00ff00'; // Green + * container.tint = 'rgb(0,0,255)'; // Blue + * + * // Remove tint + * container.tint = 0xffffff; // White = no tint + * container.tint = null; // Also removes tint + * ``` + * @default 0xFFFFFF + * @see {@link Container#alpha} For transparency + * @see {@link Container#visible} For visibility control + */ + get tint() { + return ci(this.localColor); + } + // / //////////////// blend related stuff + set blendMode(e) { + this.localBlendMode !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= _u, this.localBlendMode = e, this._onUpdate()); + } + /** + * The blend mode to be applied to the sprite. Controls how pixels are blended when rendering. + * + * Setting to 'normal' will reset to default blending. + * > [!NOTE] More blend modes are available after importing the `pixi.js/advanced-blend-modes` sub-export. + * @example + * ```ts + * // Basic blend modes + * sprite.blendMode = 'add'; // Additive blending + * sprite.blendMode = 'multiply'; // Multiply colors + * sprite.blendMode = 'screen'; // Screen blend + * + * // Reset blend mode + * sprite.blendMode = 'normal'; // Normal blending + * ``` + * @default 'normal' + * @see {@link Container#alpha} For transparency + * @see {@link Container#tint} For color adjustments + */ + get blendMode() { + return this.localBlendMode; + } + // / ///////// VISIBILITY / RENDERABLE ///////////////// + /** + * The visibility of the object. If false the object will not be drawn, + * and the transform will not be updated. + * @example + * ```ts + * // Basic visibility toggle + * sprite.visible = false; // Hide sprite + * sprite.visible = true; // Show sprite + * ``` + * @default true + * @see {@link Container#renderable} For render-only control + * @see {@link Container#alpha} For transparency + */ + get visible() { + return !!(this.localDisplayStatus & 2); + } + set visible(e) { + const t = e ? 2 : 0; + (this.localDisplayStatus & 2) !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Ni, this.localDisplayStatus ^= 2, this._onUpdate()); + } + /** @ignore */ + get culled() { + return !(this.localDisplayStatus & 4); + } + /** @ignore */ + set culled(e) { + const t = e ? 0 : 4; + (this.localDisplayStatus & 4) !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Ni, this.localDisplayStatus ^= 4, this._onUpdate()); + } + /** + * Controls whether this object can be rendered. If false the object will not be drawn, + * but the transform will still be updated. This is different from visible, which skips + * transform updates. + * @example + * ```ts + * // Basic render control + * sprite.renderable = false; // Skip rendering + * sprite.renderable = true; // Enable rendering + * ``` + * @default true + * @see {@link Container#visible} For skipping transform updates + * @see {@link Container#alpha} For transparency + */ + get renderable() { + return !!(this.localDisplayStatus & 1); + } + set renderable(e) { + const t = e ? 1 : 0; + (this.localDisplayStatus & 1) !== t && (this._updateFlags |= Ni, this.localDisplayStatus ^= 1, this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._onUpdate()); + } + /** + * Whether or not the object should be rendered. + * @advanced + */ + get isRenderable() { + return this.localDisplayStatus === 7 && this.groupAlpha > 0; + } + /** + * Removes all internal references and listeners as well as removes children from the display list. + * Do not use a Container after calling `destroy`. + * @param options - Options parameter. A boolean will act as if all options + * have been set to that value + * @example + * ```ts + * container.destroy(); + * container.destroy(true); + * container.destroy({ children: true }); + * container.destroy({ children: true, texture: true, textureSource: true }); + * ``` + */ + destroy(e = !1) { + var s; + if (this.destroyed) + return; + this.destroyed = !0; + let t; + if (this.children.length && (t = this.removeChildren(0, this.children.length)), this.removeFromParent(), this.parent = null, this._maskEffect = null, this._filterEffect = null, this.effects = null, this._position = null, this._scale = null, this._pivot = null, this._origin = null, this._skew = null, this.emit("destroyed", this), this.removeAllListeners(), (typeof e == "boolean" ? e : e == null ? void 0 : e.children) && t) + for (let r = 0; r < t.length; ++r) + t[r].destroy(e); + (s = this.renderGroup) == null || s.destroy(), this.renderGroup = null; + } +} +Qe.mixin( + Dt, + Kh, + iu, + uu, + ou, + au, + eu, + tu, + lu, + Wh, + jh, + su, + Qh +); +class Ws extends Dt { + // eslint-disable-next-line @typescript-eslint/no-useless-constructor + constructor(e) { + super(e), this.canBundle = !0, this.allowChildren = !1, this._roundPixels = 0, this._lastUsed = -1, this._gpuData = /* @__PURE__ */ Object.create(null), this._bounds = new ht(0, 1, 0, 0), this._boundsDirty = !0; + } + /** + * The local bounds of the view in its own coordinate space. + * Bounds are automatically updated when the view's content changes. + * @example + * ```ts + * // Get bounds dimensions + * const bounds = view.bounds; + * console.log(`Width: ${bounds.maxX - bounds.minX}`); + * console.log(`Height: ${bounds.maxY - bounds.minY}`); + * ``` + * @returns The rectangular bounds of the view + * @see {@link Bounds} For bounds operations + */ + get bounds() { + return this._boundsDirty ? (this.updateBounds(), this._boundsDirty = !1, this._bounds) : this._bounds; + } + /** + * Whether or not to round the x/y position of the sprite. + * @example + * ```ts + * // Enable pixel rounding for crisp rendering + * view.roundPixels = true; + * ``` + * @default false + */ + get roundPixels() { + return !!this._roundPixels; + } + set roundPixels(e) { + this._roundPixels = e ? 1 : 0; + } + /** + * Checks if the object contains the given point in local coordinates. + * Uses the view's bounds for hit testing. + * @example + * ```ts + * // Basic point check + * const localPoint = { x: 50, y: 25 }; + * const contains = view.containsPoint(localPoint); + * console.log('Point is inside:', contains); + * ``` + * @param point - The point to check in local coordinates + * @returns True if the point is within the view's bounds + * @see {@link ViewContainer#bounds} For the bounds used in hit testing + * @see {@link Container#toLocal} For converting global coordinates to local + */ + containsPoint(e) { + const t = this.bounds, { x: n, y: s } = e; + return n >= t.minX && n <= t.maxX && s >= t.minY && s <= t.maxY; + } + /** @private */ + onViewUpdate() { + if (this._didViewChangeTick++, this._boundsDirty = !0, this.didViewUpdate) + return; + this.didViewUpdate = !0; + const e = this.renderGroup || this.parentRenderGroup; + e && e.onChildViewUpdate(this); + } + destroy(e) { + var t, n; + super.destroy(e), this._bounds = null; + for (const s in this._gpuData) + (n = (t = this._gpuData[s]).destroy) == null || n.call(t); + this._gpuData = null; + } + /** + * Collects renderables for the view container. + * @param instructionSet - The instruction set to collect renderables for. + * @param renderer - The renderer to collect renderables for. + * @param currentLayer - The current render layer. + * @internal + */ + collectRenderablesSimple(e, t, n) { + const { renderPipes: s } = t; + s.blendMode.pushBlendMode(this, this.groupBlendMode, e), s[this.renderPipeId].addRenderable(this, e), this.didViewUpdate = !1; + const a = this.children, o = a.length; + for (let l = 0; l < o; l++) + a[l].collectRenderables(e, t, n); + s.blendMode.popBlendMode(e); + } +} +class sn extends Ws { + /** + * @param options - The options for creating the sprite. + */ + constructor(e = K.EMPTY) { + e instanceof K && (e = { texture: e }); + const { texture: t = K.EMPTY, anchor: n, roundPixels: s, width: r, height: a, ...o } = e; + super({ + label: "Sprite", + ...o + }), this.renderPipeId = "sprite", this.batched = !0, this._visualBounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 }, this._anchor = new Ce( + { + _onUpdate: () => { + this.onViewUpdate(); + } + } + ), n ? this.anchor = n : t.defaultAnchor && (this.anchor = t.defaultAnchor), this.texture = t, this.allowChildren = !1, this.roundPixels = s ?? !1, r !== void 0 && (this.width = r), a !== void 0 && (this.height = a); + } + /** + * Creates a new sprite based on a source texture, image, video, or canvas element. + * This is a convenience method that automatically creates and manages textures. + * @example + * ```ts + * // Create from path or URL + * const sprite = Sprite.from('assets/image.png'); + * + * // Create from existing texture + * const sprite = Sprite.from(texture); + * + * // Create from canvas + * const canvas = document.createElement('canvas'); + * const sprite = Sprite.from(canvas, true); // Skip caching new texture + * ``` + * @param source - The source to create the sprite from. Can be a path to an image, a texture, + * or any valid texture source (canvas, video, etc.) + * @param skipCache - Whether to skip adding to the texture cache when creating a new texture + * @returns A new sprite based on the source + * @see {@link Texture.from} For texture creation details + * @see {@link Assets} For asset loading and management + */ + static from(e, t = !1) { + return e instanceof K ? new sn(e) : new sn(K.from(e, t)); + } + set texture(e) { + e || (e = K.EMPTY); + const t = this._texture; + t !== e && (t && t.dynamic && t.off("update", this.onViewUpdate, this), e.dynamic && e.on("update", this.onViewUpdate, this), this._texture = e, this._width && this._setWidth(this._width, this._texture.orig.width), this._height && this._setHeight(this._height, this._texture.orig.height), this.onViewUpdate()); + } + /** + * The texture that is displayed by the sprite. When changed, automatically updates + * the sprite dimensions and manages texture event listeners. + * @example + * ```ts + * // Create sprite with texture + * const sprite = new Sprite({ + * texture: Texture.from('sprite.png') + * }); + * + * // Update texture + * sprite.texture = Texture.from('newSprite.png'); + * + * // Use texture from spritesheet + * const sheet = await Assets.load('spritesheet.json'); + * sprite.texture = sheet.textures['frame1.png']; + * + * // Reset to empty texture + * sprite.texture = Texture.EMPTY; + * ``` + * @see {@link Texture} For texture creation and management + * @see {@link Assets} For asset loading + */ + get texture() { + return this._texture; + } + /** + * The bounds of the sprite, taking into account the texture's trim area. + * @example + * ```ts + * const texture = new Texture({ + * source: new TextureSource({ width: 300, height: 300 }), + * frame: new Rectangle(196, 66, 58, 56), + * trim: new Rectangle(4, 4, 58, 56), + * orig: new Rectangle(0, 0, 64, 64), + * rotate: 2, + * }); + * const sprite = new Sprite(texture); + * const visualBounds = sprite.visualBounds; + * // console.log(visualBounds); // { minX: -4, maxX: 62, minY: -4, maxY: 60 } + */ + get visualBounds() { + return Bh(this._visualBounds, this._anchor, this._texture), this._visualBounds; + } + /** + * @deprecated + * @ignore + */ + get sourceBounds() { + return W("8.6.1", "Sprite.sourceBounds is deprecated, use visualBounds instead."), this.visualBounds; + } + /** @private */ + updateBounds() { + const e = this._anchor, t = this._texture, n = this._bounds, { width: s, height: r } = t.orig; + n.minX = -e._x * s, n.maxX = n.minX + s, n.minY = -e._y * r, n.maxY = n.minY + r; + } + /** + * Destroys this sprite renderable and optionally its texture. + * @param options - Options parameter. A boolean will act as if all options + * have been set to that value + * @example + * sprite.destroy(); + * sprite.destroy(true); + * sprite.destroy({ texture: true, textureSource: true }); + */ + destroy(e = !1) { + if (super.destroy(e), typeof e == "boolean" ? e : e == null ? void 0 : e.texture) { + const n = typeof e == "boolean" ? e : e == null ? void 0 : e.textureSource; + this._texture.destroy(n); + } + this._texture = null, this._visualBounds = null, this._bounds = null, this._anchor = null, this._gpuData = null; + } + /** + * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture} + * and passed to the constructor. + * + * - The default is `(0,0)`, this means the sprite's origin is the top left. + * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered. + * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner. + * + * If you pass only single parameter, it will set both x and y to the same value as shown in the example below. + * @example + * ```ts + * // Center the anchor point + * sprite.anchor = 0.5; // Sets both x and y to 0.5 + * sprite.position.set(400, 300); // Sprite will be centered at this position + * + * // Set specific x/y anchor points + * sprite.anchor = { + * x: 1, // Right edge + * y: 0 // Top edge + * }; + * + * // Using individual coordinates + * sprite.anchor.set(0.5, 1); // Center-bottom + * + * // For rotation around center + * sprite.anchor.set(0.5); + * sprite.rotation = Math.PI / 4; // 45 degrees around center + * + * // For scaling from center + * sprite.anchor.set(0.5); + * sprite.scale.set(2); // Scales from center point + * ``` + */ + get anchor() { + return this._anchor; + } + set anchor(e) { + typeof e == "number" ? this._anchor.set(e) : this._anchor.copyFrom(e); + } + /** + * The width of the sprite, setting this will actually modify the scale to achieve the value set. + * @example + * ```ts + * // Set width directly + * sprite.width = 200; + * console.log(sprite.scale.x); // Scale adjusted to match width + * + * // Set width while preserving aspect ratio + * const ratio = sprite.height / sprite.width; + * sprite.width = 300; + * sprite.height = 300 * ratio; + * + * // For better performance when setting both width and height + * sprite.setSize(300, 400); // Avoids recalculating bounds twice + * + * // Reset to original texture size + * sprite.width = sprite.texture.orig.width; + * ``` + */ + get width() { + return Math.abs(this.scale.x) * this._texture.orig.width; + } + set width(e) { + this._setWidth(e, this._texture.orig.width), this._width = e; + } + /** + * The height of the sprite, setting this will actually modify the scale to achieve the value set. + * @example + * ```ts + * // Set height directly + * sprite.height = 150; + * console.log(sprite.scale.y); // Scale adjusted to match height + * + * // Set height while preserving aspect ratio + * const ratio = sprite.width / sprite.height; + * sprite.height = 200; + * sprite.width = 200 * ratio; + * + * // For better performance when setting both width and height + * sprite.setSize(300, 400); // Avoids recalculating bounds twice + * + * // Reset to original texture size + * sprite.height = sprite.texture.orig.height; + * ``` + */ + get height() { + return Math.abs(this.scale.y) * this._texture.orig.height; + } + set height(e) { + this._setHeight(e, this._texture.orig.height), this._height = e; + } + /** + * Retrieves the size of the Sprite as a [Size]{@link Size} object based on the texture dimensions and scale. + * This is faster than getting width and height separately as it only calculates the bounds once. + * @example + * ```ts + * // Basic size retrieval + * const sprite = new Sprite(Texture.from('sprite.png')); + * const size = sprite.getSize(); + * console.log(`Size: ${size.width}x${size.height}`); + * + * // Reuse existing size object + * const reuseSize = { width: 0, height: 0 }; + * sprite.getSize(reuseSize); + * ``` + * @param out - Optional object to store the size in, to avoid allocating a new object + * @returns The size of the Sprite + * @see {@link Sprite#width} For getting just the width + * @see {@link Sprite#height} For getting just the height + * @see {@link Sprite#setSize} For setting both width and height + */ + getSize(e) { + return e || (e = {}), e.width = Math.abs(this.scale.x) * this._texture.orig.width, e.height = Math.abs(this.scale.y) * this._texture.orig.height, e; + } + /** + * Sets the size of the Sprite to the specified width and height. + * This is faster than setting width and height separately as it only recalculates bounds once. + * @example + * ```ts + * // Basic size setting + * const sprite = new Sprite(Texture.from('sprite.png')); + * sprite.setSize(100, 200); // Width: 100, Height: 200 + * + * // Set uniform size + * sprite.setSize(100); // Sets both width and height to 100 + * + * // Set size with object + * sprite.setSize({ + * width: 200, + * height: 300 + * }); + * + * // Reset to texture size + * sprite.setSize( + * sprite.texture.orig.width, + * sprite.texture.orig.height + * ); + * ``` + * @param value - This can be either a number or a {@link Size} object + * @param height - The height to set. Defaults to the value of `width` if not provided + * @see {@link Sprite#width} For setting width only + * @see {@link Sprite#height} For setting height only + * @see {@link Sprite#texture} For the source dimensions + */ + setSize(e, t) { + typeof e == "object" ? (t = e.height ?? e.width, e = e.width) : t ?? (t = e), e !== void 0 && this._setWidth(e, this._texture.orig.width), t !== void 0 && this._setHeight(t, this._texture.orig.height); + } +} +const mu = new ht(); +function Uo(i, e, t) { + const n = mu; + i.measurable = !0, Ro(i, t, n), e.addBoundsMask(n), i.measurable = !1; +} +function Ho(i, e, t) { + const n = kt.get(); + i.measurable = !0; + const s = Fe.get().identity(), r = Vo(i, t, s); + Oo(i, n, r), i.measurable = !1, e.addBoundsMask(n), Fe.return(s), kt.return(n); +} +function Vo(i, e, t) { + return i ? (i !== e && (Vo(i.parent, e, t), i.updateLocalTransform(), t.append(i.localTransform)), t) : ($e("Mask bounds, renderable is not inside the root container"), t); +} +class Wo { + constructor(e) { + this.priority = 0, this.inverse = !1, this.pipe = "alphaMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e, this.renderMaskToTexture = !(e instanceof sn), this.mask.renderable = this.renderMaskToTexture, this.mask.includeInBuild = !this.renderMaskToTexture, this.mask.measurable = !1; + } + reset() { + this.mask.measurable = !0, this.mask = null; + } + addBounds(e, t) { + this.inverse || Uo(this.mask, e, t); + } + addLocalBounds(e, t) { + Ho(this.mask, e, t); + } + containsPoint(e, t) { + const n = this.mask; + return t(n, e); + } + destroy() { + this.reset(); + } + static test(e) { + return e instanceof sn; + } +} +Wo.extension = Q.MaskEffect; +class Yo { + constructor(e) { + this.priority = 0, this.pipe = "colorMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e; + } + destroy() { + } + static test(e) { + return typeof e == "number"; + } +} +Yo.extension = Q.MaskEffect; +class Xo { + constructor(e) { + this.priority = 0, this.pipe = "stencilMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e, this.mask.includeInBuild = !1, this.mask.measurable = !1; + } + reset() { + this.mask.measurable = !0, this.mask.includeInBuild = !0, this.mask = null; + } + addBounds(e, t) { + Uo(this.mask, e, t); + } + addLocalBounds(e, t) { + Ho(this.mask, e, t); + } + containsPoint(e, t) { + const n = this.mask; + return t(n, e); + } + destroy() { + this.reset(); + } + static test(e) { + return e instanceof Dt; + } +} +Xo.extension = Q.MaskEffect; +const gu = { + createCanvas: (i, e) => { + const t = document.createElement("canvas"); + return t.width = i, t.height = e, t; + }, + createImage: () => new Image(), + getCanvasRenderingContext2D: () => CanvasRenderingContext2D, + getWebGLRenderingContext: () => WebGLRenderingContext, + getNavigator: () => navigator, + getBaseUrl: () => document.baseURI ?? window.location.href, + getFontFaceSet: () => document.fonts, + fetch: (i, e) => fetch(i, e), + parseXML: (i) => new DOMParser().parseFromString(i, "text/xml") +}; +let Rr = gu; +const Ge = { + /** + * Returns the current adapter. + * @returns {environment.Adapter} The current adapter. + */ + get() { + return Rr; + }, + /** + * Sets the current adapter. + * @param adapter - The new adapter. + */ + set(i) { + Rr = i; + } +}; +class jo extends ut { + constructor(e) { + e.resource || (e.resource = Ge.get().createCanvas()), e.width || (e.width = e.resource.width, e.autoDensity || (e.width /= e.resolution)), e.height || (e.height = e.resource.height, e.autoDensity || (e.height /= e.resolution)), super(e), this.uploadMethodId = "image", this.autoDensity = e.autoDensity, this.resizeCanvas(), this.transparent = !!e.transparent; + } + resizeCanvas() { + this.autoDensity && "style" in this.resource && (this.resource.style.width = `${this.width}px`, this.resource.style.height = `${this.height}px`), (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) && (this.resource.width = this.pixelWidth, this.resource.height = this.pixelHeight); + } + resize(e = this.width, t = this.height, n = this._resolution) { + const s = super.resize(e, t, n); + return s && this.resizeCanvas(), s; + } + static test(e) { + return globalThis.HTMLCanvasElement && e instanceof HTMLCanvasElement || globalThis.OffscreenCanvas && e instanceof OffscreenCanvas; + } + /** + * Returns the 2D rendering context for the canvas. + * Caches the context after creating it. + * @returns The 2D rendering context of the canvas. + */ + get context2D() { + return this._context2D || (this._context2D = this.resource.getContext("2d")); + } +} +jo.extension = Q.TextureSource; +class mi extends ut { + constructor(e) { + super(e), this.uploadMethodId = "image", this.autoGarbageCollect = !0; + } + static test(e) { + return globalThis.HTMLImageElement && e instanceof HTMLImageElement || typeof ImageBitmap < "u" && e instanceof ImageBitmap || globalThis.VideoFrame && e instanceof VideoFrame; + } +} +mi.extension = Q.TextureSource; +var gs = /* @__PURE__ */ ((i) => (i[i.INTERACTION = 50] = "INTERACTION", i[i.HIGH = 25] = "HIGH", i[i.NORMAL = 0] = "NORMAL", i[i.LOW = -25] = "LOW", i[i.UTILITY = -50] = "UTILITY", i))(gs || {}); +class Gi { + /** + * Constructor + * @private + * @param fn - The listener function to be added for one update + * @param context - The listener context + * @param priority - The priority for emitting + * @param once - If the handler should fire once + */ + constructor(e, t = null, n = 0, s = !1) { + this.next = null, this.previous = null, this._destroyed = !1, this._fn = e, this._context = t, this.priority = n, this._once = s; + } + /** + * Simple compare function to figure out if a function and context match. + * @param fn - The listener function to be added for one update + * @param context - The listener context + * @returns `true` if the listener match the arguments + */ + match(e, t = null) { + return this._fn === e && this._context === t; + } + /** + * Emit by calling the current function. + * @param ticker - The ticker emitting. + * @returns Next ticker + */ + emit(e) { + this._fn && (this._context ? this._fn.call(this._context, e) : this._fn(e)); + const t = this.next; + return this._once && this.destroy(!0), this._destroyed && (this.next = null), t; + } + /** + * Connect to the list. + * @param previous - Input node, previous listener + */ + connect(e) { + this.previous = e, e.next && (e.next.previous = this), this.next = e.next, e.next = this; + } + /** + * Destroy and don't use after this. + * @param hard - `true` to remove the `next` reference, this + * is considered a hard destroy. Soft destroy maintains the next reference. + * @returns The listener to redirect while emitting or removing. + */ + destroy(e = !1) { + this._destroyed = !0, this._fn = null, this._context = null, this.previous && (this.previous.next = this.next), this.next && (this.next.previous = this.previous); + const t = this.next; + return this.next = e ? null : t, this.previous = null, t; + } +} +const Zo = class Oe { + constructor() { + this.autoStart = !1, this.deltaTime = 1, this.lastTime = -1, this.speed = 1, this.started = !1, this._requestId = null, this._maxElapsedMS = 100, this._minElapsedMS = 0, this._protected = !1, this._lastFrame = -1, this._head = new Gi(null, null, 1 / 0), this.deltaMS = 1 / Oe.targetFPMS, this.elapsedMS = 1 / Oe.targetFPMS, this._tick = (e) => { + this._requestId = null, this.started && (this.update(e), this.started && this._requestId === null && this._head.next && (this._requestId = requestAnimationFrame(this._tick))); + }; + } + /** + * Conditionally requests a new animation frame. + * If a frame has not already been requested, and if the internal + * emitter has listeners, a new frame is requested. + */ + _requestIfNeeded() { + this._requestId === null && this._head.next && (this.lastTime = performance.now(), this._lastFrame = this.lastTime, this._requestId = requestAnimationFrame(this._tick)); + } + /** Conditionally cancels a pending animation frame. */ + _cancelIfNeeded() { + this._requestId !== null && (cancelAnimationFrame(this._requestId), this._requestId = null); + } + /** + * Conditionally requests a new animation frame. + * If the ticker has been started it checks if a frame has not already + * been requested, and if the internal emitter has listeners. If these + * conditions are met, a new frame is requested. If the ticker has not + * been started, but autoStart is `true`, then the ticker starts now, + * and continues with the previous conditions to request a new frame. + */ + _startIfPossible() { + this.started ? this._requestIfNeeded() : this.autoStart && this.start(); + } + /** + * Register a handler for tick events. + * @param fn - The listener function to add. Receives the Ticker instance as parameter + * @param context - The context for the listener + * @param priority - The priority of the listener + * @example + * ```ts + * // Access time properties through the ticker parameter + * ticker.add((ticker) => { + * // Use deltaTime (dimensionless scalar) for frame-independent animations + * sprite.rotation += 0.1 * ticker.deltaTime; + * + * // Use deltaMS (milliseconds) for time-based calculations + * const progress = ticker.deltaMS / animationDuration; + * + * // Use elapsedMS for raw timing measurements + * console.log(`Raw frame time: ${ticker.elapsedMS}ms`); + * }); + * ``` + */ + add(e, t, n = gs.NORMAL) { + return this._addListener(new Gi(e, t, n)); + } + /** + * Add a handler for the tick event which is only executed once on the next frame. + * @example + * ```ts + * // Basic one-time update + * ticker.addOnce(() => { + * console.log('Runs next frame only'); + * }); + * + * // With specific context + * const game = { + * init(ticker) { + * this.loadResources(); + * console.log('Game initialized'); + * } + * }; + * ticker.addOnce(game.init, game); + * + * // With priority + * ticker.addOnce( + * () => { + * // High priority one-time setup + * physics.init(); + * }, + * undefined, + * UPDATE_PRIORITY.HIGH + * ); + * ``` + * @param fn - The listener function to be added for one update + * @param context - The listener context + * @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL) + * @returns This instance of a ticker + * @see {@link Ticker#add} For continuous updates + * @see {@link Ticker#remove} For removing handlers + */ + addOnce(e, t, n = gs.NORMAL) { + return this._addListener(new Gi(e, t, n, !0)); + } + /** + * Internally adds the event handler so that it can be sorted by priority. + * Priority allows certain handler (user, AnimatedSprite, Interaction) to be run + * before the rendering. + * @private + * @param listener - Current listener being added. + * @returns This instance of a ticker + */ + _addListener(e) { + let t = this._head.next, n = this._head; + if (!t) + e.connect(n); + else { + for (; t; ) { + if (e.priority > t.priority) { + e.connect(n); + break; + } + n = t, t = t.next; + } + e.previous || e.connect(n); + } + return this._startIfPossible(), this; + } + /** + * Removes any handlers matching the function and context parameters. + * If no handlers are left after removing, then it cancels the animation frame. + * @example + * ```ts + * // Basic removal + * const onTick = () => { + * sprite.rotation += 0.1; + * }; + * ticker.add(onTick); + * ticker.remove(onTick); + * + * // Remove with context + * const game = { + * update(ticker) { + * this.physics.update(ticker.deltaTime); + * } + * }; + * ticker.add(game.update, game); + * ticker.remove(game.update, game); + * + * // Remove all matching handlers + * // (if same function was added multiple times) + * ticker.add(onTick); + * ticker.add(onTick); + * ticker.remove(onTick); // Removes all instances + * ``` + * @param fn - The listener function to be removed + * @param context - The listener context to be removed + * @returns This instance of a ticker + * @see {@link Ticker#add} For adding handlers + * @see {@link Ticker#addOnce} For one-time handlers + */ + remove(e, t) { + let n = this._head.next; + for (; n; ) + n.match(e, t) ? n = n.destroy() : n = n.next; + return this._head.next || this._cancelIfNeeded(), this; + } + /** + * The number of listeners on this ticker, calculated by walking through linked list. + * @example + * ```ts + * // Check number of active listeners + * const ticker = new Ticker(); + * console.log(ticker.count); // 0 + * + * // Add some listeners + * ticker.add(() => {}); + * ticker.add(() => {}); + * console.log(ticker.count); // 2 + * + * // Check after cleanup + * ticker.destroy(); + * console.log(ticker.count); // 0 + * ``` + * @readonly + * @see {@link Ticker#add} For adding listeners + * @see {@link Ticker#remove} For removing listeners + */ + get count() { + if (!this._head) + return 0; + let e = 0, t = this._head; + for (; t = t.next; ) + e++; + return e; + } + /** + * Starts the ticker. If the ticker has listeners a new animation frame is requested at this point. + * @example + * ```ts + * // Basic manual start + * const ticker = new Ticker(); + * ticker.add(() => { + * // Animation code here + * }); + * ticker.start(); + * ``` + * @see {@link Ticker#stop} For stopping the ticker + * @see {@link Ticker#autoStart} For automatic starting + * @see {@link Ticker#started} For checking ticker state + */ + start() { + this.started || (this.started = !0, this._requestIfNeeded()); + } + /** + * Stops the ticker. If the ticker has requested an animation frame it is canceled at this point. + * @example + * ```ts + * // Basic stop + * const ticker = new Ticker(); + * ticker.stop(); + * ``` + * @see {@link Ticker#start} For starting the ticker + * @see {@link Ticker#started} For checking ticker state + * @see {@link Ticker#destroy} For cleaning up the ticker + */ + stop() { + this.started && (this.started = !1, this._cancelIfNeeded()); + } + /** + * Destroy the ticker and don't use after this. Calling this method removes all references to internal events. + * @example + * ```ts + * // Clean up with active listeners + * const ticker = new Ticker(); + * ticker.add(() => {}); + * ticker.destroy(); // Removes all listeners + * ``` + * @see {@link Ticker#stop} For stopping without destroying + * @see {@link Ticker#remove} For removing specific listeners + */ + destroy() { + if (!this._protected) { + this.stop(); + let e = this._head.next; + for (; e; ) + e = e.destroy(!0); + this._head.destroy(), this._head = null; + } + } + /** + * Triggers an update. + * + * An update entails setting the + * current {@link Ticker#elapsedMS|elapsedMS}, + * the current {@link Ticker#deltaTime|deltaTime}, + * invoking all listeners with current deltaTime, + * and then finally setting {@link Ticker#lastTime|lastTime} + * with the value of currentTime that was provided. + * + * This method will be called automatically by animation + * frame callbacks if the ticker instance has been started + * and listeners are added. + * @example + * ```ts + * // Basic manual update + * const ticker = new Ticker(); + * ticker.update(performance.now()); + * ``` + * @param currentTime - The current time of execution (defaults to performance.now()) + * @see {@link Ticker#deltaTime} For frame delta value + * @see {@link Ticker#elapsedMS} For raw elapsed time + */ + update(e = performance.now()) { + let t; + if (e > this.lastTime) { + if (t = this.elapsedMS = e - this.lastTime, t > this._maxElapsedMS && (t = this._maxElapsedMS), t *= this.speed, this._minElapsedMS) { + const r = e - this._lastFrame | 0; + if (r < this._minElapsedMS) + return; + this._lastFrame = e - r % this._minElapsedMS; + } + this.deltaMS = t, this.deltaTime = this.deltaMS * Oe.targetFPMS; + const n = this._head; + let s = n.next; + for (; s; ) + s = s.emit(this); + n.next || this._cancelIfNeeded(); + } else + this.deltaTime = this.deltaMS = this.elapsedMS = 0; + this.lastTime = e; + } + /** + * The frames per second at which this ticker is running. + * The default is approximately 60 in most modern browsers. + * > [!NOTE] This does not factor in the value of + * > {@link Ticker#speed|speed}, which is specific + * > to scaling {@link Ticker#deltaTime|deltaTime}. + * @example + * ```ts + * // Basic FPS monitoring + * ticker.add(() => { + * console.log(`Current FPS: ${Math.round(ticker.FPS)}`); + * }); + * ``` + * @readonly + */ + get FPS() { + return 1e3 / this.elapsedMS; + } + /** + * Manages the maximum amount of milliseconds allowed to + * elapse between invoking {@link Ticker#update|update}. + * + * This value is used to cap {@link Ticker#deltaTime|deltaTime}, + * but does not effect the measured value of {@link Ticker#FPS|FPS}. + * + * When setting this property it is clamped to a value between + * `0` and `Ticker.targetFPMS * 1000`. + * @example + * ```ts + * // Set minimum acceptable frame rate + * const ticker = new Ticker(); + * ticker.minFPS = 30; // Never go below 30 FPS + * + * // Use with maxFPS for frame rate clamping + * ticker.minFPS = 30; + * ticker.maxFPS = 60; + * + * // Monitor delta capping + * ticker.add(() => { + * // Delta time will be capped based on minFPS + * console.log(`Delta time: ${ticker.deltaTime}`); + * }); + * ``` + * @default 10 + */ + get minFPS() { + return 1e3 / this._maxElapsedMS; + } + set minFPS(e) { + const t = Math.min(this.maxFPS, e), n = Math.min(Math.max(0, t) / 1e3, Oe.targetFPMS); + this._maxElapsedMS = 1 / n; + } + /** + * Manages the minimum amount of milliseconds required to + * elapse between invoking {@link Ticker#update|update}. + * + * This will effect the measured value of {@link Ticker#FPS|FPS}. + * + * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can. + * Otherwise it will be at least `minFPS` + * @example + * ```ts + * // Set minimum acceptable frame rate + * const ticker = new Ticker(); + * ticker.maxFPS = 60; // Never go above 60 FPS + * + * // Use with maxFPS for frame rate clamping + * ticker.minFPS = 30; + * ticker.maxFPS = 60; + * + * // Monitor delta capping + * ticker.add(() => { + * // Delta time will be capped based on maxFPS + * console.log(`Delta time: ${ticker.deltaTime}`); + * }); + * ``` + * @default 0 + */ + get maxFPS() { + return this._minElapsedMS ? Math.round(1e3 / this._minElapsedMS) : 0; + } + set maxFPS(e) { + if (e === 0) + this._minElapsedMS = 0; + else { + const t = Math.max(this.minFPS, e); + this._minElapsedMS = 1 / (t / 1e3); + } + } + /** + * The shared ticker instance used by {@link AnimatedSprite} and by + * {@link VideoSource} to update animation frames / video textures. + * + * It may also be used by {@link Application} if created with the `sharedTicker` option property set to true. + * + * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance. + * Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker. + * @example + * import { Ticker } from 'pixi.js'; + * + * const ticker = Ticker.shared; + * // Set this to prevent starting this ticker when listeners are added. + * // By default this is true only for the Ticker.shared instance. + * ticker.autoStart = false; + * + * // FYI, call this to ensure the ticker is stopped. It should be stopped + * // if you have not attempted to render anything yet. + * ticker.stop(); + * + * // Call this when you are ready for a running shared ticker. + * ticker.start(); + * @example + * import { autoDetectRenderer, Container } from 'pixi.js'; + * + * // You may use the shared ticker to render... + * const renderer = autoDetectRenderer(); + * const stage = new Container(); + * document.body.appendChild(renderer.view); + * ticker.add((time) => renderer.render(stage)); + * + * // Or you can just update it manually. + * ticker.autoStart = false; + * ticker.stop(); + * const animate = (time) => { + * ticker.update(time); + * renderer.render(stage); + * requestAnimationFrame(animate); + * }; + * animate(performance.now()); + * @type {Ticker} + * @readonly + */ + static get shared() { + if (!Oe._shared) { + const e = Oe._shared = new Oe(); + e.autoStart = !0, e._protected = !0; + } + return Oe._shared; + } + /** + * The system ticker instance used by {@link PrepareBase} for core timing + * functionality that shouldn't usually need to be paused, unlike the `shared` + * ticker which drives visual animations and rendering which may want to be paused. + * + * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance. + * @type {Ticker} + * @readonly + * @advanced + */ + static get system() { + if (!Oe._system) { + const e = Oe._system = new Oe(); + e.autoStart = !0, e._protected = !0; + } + return Oe._system; + } +}; +Zo.targetFPMS = 0.06; +let Yn = Zo, qi; +async function yu() { + return qi ?? (qi = (async () => { + var a; + const e = Ge.get().createCanvas(1, 1).getContext("webgl"); + if (!e) + return "premultiply-alpha-on-upload"; + const t = await new Promise((o) => { + const l = document.createElement("video"); + l.onloadeddata = () => o(l), l.onerror = () => o(null), l.autoplay = !1, l.crossOrigin = "anonymous", l.preload = "auto", l.src = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHTEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggEXTbuMU6uEHFO7a1OsggG97AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQkBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua8yuAQAAAAAAAEPXgQFzxYgAAAAAAAAAAZyBACK1nIN1bmSIgQCGhVZfVlA5g4EBI+ODhAJiWgDglLCBArqBApqBAlPAgQFVsIRVuYEBElTDZ9Vzc9JjwItjxYgAAAAAAAAAAWfInEWjh0VOQ09ERVJEh49MYXZjIGxpYnZweC12cDlnyKJFo4hEVVJBVElPTkSHlDAwOjAwOjAwLjA0MDAwMDAwMAAAH0O2dcfngQCgwqGggQAAAIJJg0IAABAAFgA4JBwYSgAAICAAEb///4r+AAB1oZ2mm+6BAaWWgkmDQgAAEAAWADgkHBhKAAAgIABIQBxTu2uRu4+zgQC3iveBAfGCAXHwgQM=", l.load(); + }); + if (!t) + return "premultiply-alpha-on-upload"; + const n = e.createTexture(); + e.bindTexture(e.TEXTURE_2D, n); + const s = e.createFramebuffer(); + e.bindFramebuffer(e.FRAMEBUFFER, s), e.framebufferTexture2D( + e.FRAMEBUFFER, + e.COLOR_ATTACHMENT0, + e.TEXTURE_2D, + n, + 0 + ), e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL, e.NONE), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, t); + const r = new Uint8Array(4); + return e.readPixels(0, 0, 1, 1, e.RGBA, e.UNSIGNED_BYTE, r), e.deleteFramebuffer(s), e.deleteTexture(n), (a = e.getExtension("WEBGL_lose_context")) == null || a.loseContext(), r[0] <= r[3] ? "premultiplied-alpha" : "premultiply-alpha-on-upload"; + })()), qi; +} +const Ai = class Ko extends ut { + constructor(e) { + super(e), this.isReady = !1, this.uploadMethodId = "video", e = { + ...Ko.defaultOptions, + ...e + }, this._autoUpdate = !0, this._isConnectedToTicker = !1, this._updateFPS = e.updateFPS || 0, this._msToNextUpdate = 0, this.autoPlay = e.autoPlay !== !1, this.alphaMode = e.alphaMode ?? "premultiply-alpha-on-upload", this._videoFrameRequestCallback = this._videoFrameRequestCallback.bind(this), this._videoFrameRequestCallbackHandle = null, this._load = null, this._resolve = null, this._reject = null, this._onCanPlay = this._onCanPlay.bind(this), this._onCanPlayThrough = this._onCanPlayThrough.bind(this), this._onError = this._onError.bind(this), this._onPlayStart = this._onPlayStart.bind(this), this._onPlayStop = this._onPlayStop.bind(this), this._onSeeked = this._onSeeked.bind(this), e.autoLoad !== !1 && this.load(); + } + /** Update the video frame if the source is not destroyed and meets certain conditions. */ + updateFrame() { + if (!this.destroyed) { + if (this._updateFPS) { + const e = Yn.shared.elapsedMS * this.resource.playbackRate; + this._msToNextUpdate = Math.floor(this._msToNextUpdate - e); + } + (!this._updateFPS || this._msToNextUpdate <= 0) && (this._msToNextUpdate = this._updateFPS ? Math.floor(1e3 / this._updateFPS) : 0), this.isValid && this.update(); + } + } + /** Callback to update the video frame and potentially request the next frame update. */ + _videoFrameRequestCallback() { + this.updateFrame(), this.destroyed ? this._videoFrameRequestCallbackHandle = null : this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback( + this._videoFrameRequestCallback + ); + } + /** + * Checks if the resource has valid dimensions. + * @returns {boolean} True if width and height are set, otherwise false. + */ + get isValid() { + return !!this.resource.videoWidth && !!this.resource.videoHeight; + } + /** + * Start preloading the video resource. + * @returns {Promise} Handle the validate event + */ + async load() { + if (this._load) + return this._load; + const e = this.resource, t = this.options; + return (e.readyState === e.HAVE_ENOUGH_DATA || e.readyState === e.HAVE_FUTURE_DATA) && e.width && e.height && (e.complete = !0), e.addEventListener("play", this._onPlayStart), e.addEventListener("pause", this._onPlayStop), e.addEventListener("seeked", this._onSeeked), this._isSourceReady() ? this._mediaReady() : (t.preload || e.addEventListener("canplay", this._onCanPlay), e.addEventListener("canplaythrough", this._onCanPlayThrough), e.addEventListener("error", this._onError, !0)), this.alphaMode = await yu(), this._load = new Promise((n, s) => { + this.isValid ? n(this) : (this._resolve = n, this._reject = s, t.preloadTimeoutMs !== void 0 && (this._preloadTimeout = setTimeout(() => { + this._onError(new ErrorEvent(`Preload exceeded timeout of ${t.preloadTimeoutMs}ms`)); + })), e.load()); + }), this._load; + } + /** + * Handle video error events. + * @param event - The error event + */ + _onError(e) { + this.resource.removeEventListener("error", this._onError, !0), this.emit("error", e), this._reject && (this._reject(e), this._reject = null, this._resolve = null); + } + /** + * Checks if the underlying source is playing. + * @returns True if playing. + */ + _isSourcePlaying() { + const e = this.resource; + return !e.paused && !e.ended; + } + /** + * Checks if the underlying source is ready for playing. + * @returns True if ready. + */ + _isSourceReady() { + return this.resource.readyState > 2; + } + /** Runs the update loop when the video is ready to play. */ + _onPlayStart() { + this.isValid || this._mediaReady(), this._configureAutoUpdate(); + } + /** Stops the update loop when a pause event is triggered. */ + _onPlayStop() { + this._configureAutoUpdate(); + } + /** Handles behavior when the video completes seeking to the current playback position. */ + _onSeeked() { + this._autoUpdate && !this._isSourcePlaying() && (this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0); + } + _onCanPlay() { + this.resource.removeEventListener("canplay", this._onCanPlay), this._mediaReady(); + } + _onCanPlayThrough() { + this.resource.removeEventListener("canplaythrough", this._onCanPlay), this._preloadTimeout && (clearTimeout(this._preloadTimeout), this._preloadTimeout = void 0), this._mediaReady(); + } + /** Fired when the video is loaded and ready to play. */ + _mediaReady() { + const e = this.resource; + this.isValid && (this.isReady = !0, this.resize(e.videoWidth, e.videoHeight)), this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0, this._resolve && (this._resolve(this), this._resolve = null, this._reject = null), this._isSourcePlaying() ? this._onPlayStart() : this.autoPlay && this.resource.play(); + } + /** Cleans up resources and event listeners associated with this texture. */ + destroy() { + this._configureAutoUpdate(); + const e = this.resource; + e && (e.removeEventListener("play", this._onPlayStart), e.removeEventListener("pause", this._onPlayStop), e.removeEventListener("seeked", this._onSeeked), e.removeEventListener("canplay", this._onCanPlay), e.removeEventListener("canplaythrough", this._onCanPlayThrough), e.removeEventListener("error", this._onError, !0), e.pause(), e.src = "", e.load()), super.destroy(); + } + /** Should the base texture automatically update itself, set to true by default. */ + get autoUpdate() { + return this._autoUpdate; + } + set autoUpdate(e) { + e !== this._autoUpdate && (this._autoUpdate = e, this._configureAutoUpdate()); + } + /** + * How many times a second to update the texture from the video. + * Leave at 0 to update at every render. + * A lower fps can help performance, as updating the texture at 60fps on a 30ps video may not be efficient. + */ + get updateFPS() { + return this._updateFPS; + } + set updateFPS(e) { + e !== this._updateFPS && (this._updateFPS = e, this._configureAutoUpdate()); + } + /** + * Configures the updating mechanism based on the current state and settings. + * + * This method decides between using the browser's native video frame callback or a custom ticker + * for updating the video frame. It ensures optimal performance and responsiveness + * based on the video's state, playback status, and the desired frames-per-second setting. + * + * - If `_autoUpdate` is enabled and the video source is playing: + * - It will prefer the native video frame callback if available and no specific FPS is set. + * - Otherwise, it will use a custom ticker for manual updates. + * - If `_autoUpdate` is disabled or the video isn't playing, any active update mechanisms are halted. + */ + _configureAutoUpdate() { + this._autoUpdate && this._isSourcePlaying() ? !this._updateFPS && this.resource.requestVideoFrameCallback ? (this._isConnectedToTicker && (Yn.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0), this._videoFrameRequestCallbackHandle === null && (this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback( + this._videoFrameRequestCallback + ))) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker || (Yn.shared.add(this.updateFrame, this), this._isConnectedToTicker = !0, this._msToNextUpdate = 0)) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker && (Yn.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0)); + } + static test(e) { + return globalThis.HTMLVideoElement && e instanceof HTMLVideoElement; + } +}; +Ai.extension = Q.TextureSource; +Ai.defaultOptions = { + ...ut.defaultOptions, + /** If true, the video will start loading immediately. */ + autoLoad: !0, + /** If true, the video will start playing as soon as it is loaded. */ + autoPlay: !0, + /** The number of times a second to update the texture from the video. Leave at 0 to update at every render. */ + updateFPS: 0, + /** If true, the video will be loaded with the `crossorigin` attribute. */ + crossorigin: !0, + /** If true, the video will loop when it ends. */ + loop: !1, + /** If true, the video will be muted. */ + muted: !0, + /** If true, the video will play inline. */ + playsinline: !0, + /** If true, the video will be preloaded. */ + preload: !1 +}; +Ai.MIME_TYPES = { + ogv: "video/ogg", + mov: "video/quicktime", + m4v: "video/mp4" +}; +let bu = Ai; +const Xt = (i, e, t = !1) => (Array.isArray(i) || (i = [i]), e ? i.map((n) => typeof n == "string" || t ? e(n) : n) : i); +class xu { + constructor() { + this._parsers = [], this._cache = /* @__PURE__ */ new Map(), this._cacheMap = /* @__PURE__ */ new Map(); + } + /** Clear all entries. */ + reset() { + this._cacheMap.clear(), this._cache.clear(); + } + /** + * Check if the key exists + * @param key - The key to check + */ + has(e) { + return this._cache.has(e); + } + /** + * Fetch entry by key + * @param key - The key of the entry to get + */ + get(e) { + const t = this._cache.get(e); + return t || $e(`[Assets] Asset id ${e} was not found in the Cache`), t; + } + /** + * Set a value by key or keys name + * @param key - The key or keys to set + * @param value - The value to store in the cache or from which cacheable assets will be derived. + */ + set(e, t) { + const n = Xt(e); + let s; + for (let l = 0; l < this.parsers.length; l++) { + const h = this.parsers[l]; + if (h.test(t)) { + s = h.getCacheableAssets(n, t); + break; + } + } + const r = new Map(Object.entries(s || {})); + s || n.forEach((l) => { + r.set(l, t); + }); + const a = [...r.keys()], o = { + cacheKeys: a, + keys: n + }; + n.forEach((l) => { + this._cacheMap.set(l, o); + }), a.forEach((l) => { + const h = s ? s[l] : t; + this._cache.has(l) && this._cache.get(l) !== h && $e("[Cache] already has key:", l), this._cache.set(l, r.get(l)); + }); + } + /** + * Remove entry by key + * + * This function will also remove any associated alias from the cache also. + * @param key - The key of the entry to remove + */ + remove(e) { + if (!this._cacheMap.has(e)) { + $e(`[Assets] Asset id ${e} was not found in the Cache`); + return; + } + const t = this._cacheMap.get(e); + t.cacheKeys.forEach((s) => { + this._cache.delete(s); + }), t.keys.forEach((s) => { + this._cacheMap.delete(s); + }); + } + /** + * All loader parsers registered + * @advanced + */ + get parsers() { + return this._parsers; + } +} +const jt = new xu(), ys = []; +Qe.handleByList(Q.TextureSource, ys); +function Qo(i = {}) { + const e = i && i.resource, t = e ? i.resource : i, n = e ? i : { resource: i }; + for (let s = 0; s < ys.length; s++) { + const r = ys[s]; + if (r.test(t)) + return new r(n); + } + throw new Error(`Could not find a source type for resource: ${n.resource}`); +} +function wu(i = {}, e = !1) { + const t = i && i.resource, n = t ? i.resource : i, s = t ? i : { resource: i }; + if (!e && jt.has(n)) + return jt.get(n); + const r = new K({ source: Qo(s) }); + return r.on("destroy", () => { + jt.has(n) && jt.remove(n); + }), e || jt.set(n, r), r; +} +function vu(i, e = !1) { + return typeof i == "string" ? jt.get(i) : i instanceof ut ? new K({ source: i }) : wu(i, e); +} +K.from = vu; +ut.from = Qo; +Qe.add(Wo, Yo, Xo, bu, mi, jo, Hs); +var Jo = /* @__PURE__ */ ((i) => (i[i.Low = 0] = "Low", i[i.Normal = 1] = "Normal", i[i.High = 2] = "High", i))(Jo || {}); +function nt(i) { + if (typeof i != "string") + throw new TypeError(`Path must be a string. Received ${JSON.stringify(i)}`); +} +function on(i) { + return i.split("?")[0].split("#")[0]; +} +function Cu(i) { + return i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +function Su(i, e, t) { + return i.replace(new RegExp(Cu(e), "g"), t); +} +function ku(i, e) { + let t = "", n = 0, s = -1, r = 0, a = -1; + for (let o = 0; o <= i.length; ++o) { + if (o < i.length) + a = i.charCodeAt(o); + else { + if (a === 47) + break; + a = 47; + } + if (a === 47) { + if (!(s === o - 1 || r === 1)) if (s !== o - 1 && r === 2) { + if (t.length < 2 || n !== 2 || t.charCodeAt(t.length - 1) !== 46 || t.charCodeAt(t.length - 2) !== 46) { + if (t.length > 2) { + const l = t.lastIndexOf("/"); + if (l !== t.length - 1) { + l === -1 ? (t = "", n = 0) : (t = t.slice(0, l), n = t.length - 1 - t.lastIndexOf("/")), s = o, r = 0; + continue; + } + } else if (t.length === 2 || t.length === 1) { + t = "", n = 0, s = o, r = 0; + continue; + } + } + } else + t.length > 0 ? t += `/${i.slice(s + 1, o)}` : t = i.slice(s + 1, o), n = o - s - 1; + s = o, r = 0; + } else a === 46 && r !== -1 ? ++r : r = -1; + } + return t; +} +const Fn = { + /** + * Converts a path to posix format. + * @param path - The path to convert to posix + * @example + * ```ts + * // Convert a Windows path to POSIX format + * path.toPosix('C:\\Users\\User\\Documents\\file.txt'); + * // -> 'C:/Users/User/Documents/file.txt' + * ``` + */ + toPosix(i) { + return Su(i, "\\", "/"); + }, + /** + * Checks if the path is a URL e.g. http://, https:// + * @param path - The path to check + * @example + * ```ts + * // Check if a path is a URL + * path.isUrl('http://www.example.com'); + * // -> true + * path.isUrl('C:/Users/User/Documents/file.txt'); + * // -> false + * ``` + */ + isUrl(i) { + return /^https?:/.test(this.toPosix(i)); + }, + /** + * Checks if the path is a data URL + * @param path - The path to check + * @example + * ```ts + * // Check if a path is a data URL + * path.isDataUrl('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...'); + * // -> true + * ``` + */ + isDataUrl(i) { + return /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i.test(i); + }, + /** + * Checks if the path is a blob URL + * @param path - The path to check + * @example + * ```ts + * // Check if a path is a blob URL + * path.isBlobUrl('blob:http://www.example.com/12345678-1234-1234-1234-123456789012'); + * // -> true + * ``` + */ + isBlobUrl(i) { + return i.startsWith("blob:"); + }, + /** + * Checks if the path has a protocol e.g. http://, https://, file:///, data:, blob:, C:/ + * This will return true for windows file paths + * @param path - The path to check + * @example + * ```ts + * // Check if a path has a protocol + * path.hasProtocol('http://www.example.com'); + * // -> true + * path.hasProtocol('C:/Users/User/Documents/file.txt'); + * // -> true + * ``` + */ + hasProtocol(i) { + return /^[^/:]+:/.test(this.toPosix(i)); + }, + /** + * Returns the protocol of the path e.g. http://, https://, file:///, data:, blob:, C:/ + * @param path - The path to get the protocol from + * @example + * ```ts + * // Get the protocol from a URL + * path.getProtocol('http://www.example.com/path/to/resource'); + * // -> 'http://' + * // Get the protocol from a file path + * path.getProtocol('C:/Users/User/Documents/file.txt'); + * // -> 'C:/' + * ``` + */ + getProtocol(i) { + nt(i), i = this.toPosix(i); + const e = /^file:\/\/\//.exec(i); + if (e) + return e[0]; + const t = /^[^/:]+:\/{0,2}/.exec(i); + return t ? t[0] : ""; + }, + /** + * Converts URL to an absolute path. + * When loading from a Web Worker, we must use absolute paths. + * If the URL is already absolute we return it as is + * If it's not, we convert it + * @param url - The URL to test + * @param customBaseUrl - The base URL to use + * @param customRootUrl - The root URL to use + * @example + * ```ts + * // Convert a relative URL to an absolute path + * path.toAbsolute('images/texture.png', 'http://example.com/assets/'); + * // -> 'http://example.com/assets/images/texture.png' + * ``` + */ + toAbsolute(i, e, t) { + if (nt(i), this.isDataUrl(i) || this.isBlobUrl(i)) + return i; + const n = on(this.toPosix(e ?? Ge.get().getBaseUrl())), s = on(this.toPosix(t ?? this.rootname(n))); + return i = this.toPosix(i), i.startsWith("/") ? Fn.join(s, i.slice(1)) : this.isAbsolute(i) ? i : this.join(n, i); + }, + /** + * Normalizes the given path, resolving '..' and '.' segments + * @param path - The path to normalize + * @example + * ```ts + * // Normalize a path with relative segments + * path.normalize('http://www.example.com/foo/bar/../baz'); + * // -> 'http://www.example.com/foo/baz' + * // Normalize a file path with relative segments + * path.normalize('C:\\Users\\User\\Documents\\..\\file.txt'); + * // -> 'C:/Users/User/file.txt' + * ``` + */ + normalize(i) { + if (nt(i), i.length === 0) + return "."; + if (this.isDataUrl(i) || this.isBlobUrl(i)) + return i; + i = this.toPosix(i); + let e = ""; + const t = i.startsWith("/"); + this.hasProtocol(i) && (e = this.rootname(i), i = i.slice(e.length)); + const n = i.endsWith("/"); + return i = ku(i), i.length > 0 && n && (i += "/"), t ? `/${i}` : e + i; + }, + /** + * Determines if path is an absolute path. + * Absolute paths can be urls, data urls, or paths on disk + * @param path - The path to test + * @example + * ```ts + * // Check if a path is absolute + * path.isAbsolute('http://www.example.com/foo/bar'); + * // -> true + * path.isAbsolute('C:/Users/User/Documents/file.txt'); + * // -> true + * ``` + */ + isAbsolute(i) { + return nt(i), i = this.toPosix(i), this.hasProtocol(i) ? !0 : i.startsWith("/"); + }, + /** + * Joins all given path segments together using the platform-specific separator as a delimiter, + * then normalizes the resulting path + * @param segments - The segments of the path to join + * @example + * ```ts + * // Join multiple path segments + * path.join('assets', 'images', 'sprite.png'); + * // -> 'assets/images/sprite.png' + * // Join with relative segments + * path.join('assets', 'images', '../textures', 'sprite.png'); + * // -> 'assets/textures/sprite.png' + * ``` + */ + join(...i) { + if (i.length === 0) + return "."; + let e; + for (let t = 0; t < i.length; ++t) { + const n = i[t]; + if (nt(n), n.length > 0) + if (e === void 0) + e = n; + else { + const s = i[t - 1] ?? ""; + this.joinExtensions.includes(this.extname(s).toLowerCase()) ? e += `/../${n}` : e += `/${n}`; + } + } + return e === void 0 ? "." : this.normalize(e); + }, + /** + * Returns the directory name of a path + * @param path - The path to parse + * @example + * ```ts + * // Get the directory name of a path + * path.dirname('http://www.example.com/foo/bar/baz.png'); + * // -> 'http://www.example.com/foo/bar' + * // Get the directory name of a file path + * path.dirname('C:/Users/User/Documents/file.txt'); + * // -> 'C:/Users/User/Documents' + * ``` + */ + dirname(i) { + if (nt(i), i.length === 0) + return "."; + i = this.toPosix(i); + let e = i.charCodeAt(0); + const t = e === 47; + let n = -1, s = !0; + const r = this.getProtocol(i), a = i; + i = i.slice(r.length); + for (let o = i.length - 1; o >= 1; --o) + if (e = i.charCodeAt(o), e === 47) { + if (!s) { + n = o; + break; + } + } else + s = !1; + return n === -1 ? t ? "/" : this.isUrl(a) ? r + i : r : t && n === 1 ? "//" : r + i.slice(0, n); + }, + /** + * Returns the root of the path e.g. /, C:/, file:///, http://domain.com/ + * @param path - The path to parse + * @example + * ```ts + * // Get the root of a URL + * path.rootname('http://www.example.com/foo/bar/baz.png'); + * // -> 'http://www.example.com/' + * // Get the root of a file path + * path.rootname('C:/Users/User/Documents/file.txt'); + * // -> 'C:/' + * ``` + */ + rootname(i) { + nt(i), i = this.toPosix(i); + let e = ""; + if (i.startsWith("/") ? e = "/" : e = this.getProtocol(i), this.isUrl(i)) { + const t = i.indexOf("/", e.length); + t !== -1 ? e = i.slice(0, t) : e = i, e.endsWith("/") || (e += "/"); + } + return e; + }, + /** + * Returns the last portion of a path + * @param path - The path to test + * @param ext - Optional extension to remove + * @example + * ```ts + * // Get the basename of a URL + * path.basename('http://www.example.com/foo/bar/baz.png'); + * // -> 'baz.png' + * // Get the basename of a file path + * path.basename('C:/Users/User/Documents/file.txt'); + * // -> 'file.txt' + * ``` + */ + basename(i, e) { + nt(i), e && nt(e), i = on(this.toPosix(i)); + let t = 0, n = -1, s = !0, r; + if (e !== void 0 && e.length > 0 && e.length <= i.length) { + if (e.length === i.length && e === i) + return ""; + let a = e.length - 1, o = -1; + for (r = i.length - 1; r >= 0; --r) { + const l = i.charCodeAt(r); + if (l === 47) { + if (!s) { + t = r + 1; + break; + } + } else + o === -1 && (s = !1, o = r + 1), a >= 0 && (l === e.charCodeAt(a) ? --a === -1 && (n = r) : (a = -1, n = o)); + } + return t === n ? n = o : n === -1 && (n = i.length), i.slice(t, n); + } + for (r = i.length - 1; r >= 0; --r) + if (i.charCodeAt(r) === 47) { + if (!s) { + t = r + 1; + break; + } + } else n === -1 && (s = !1, n = r + 1); + return n === -1 ? "" : i.slice(t, n); + }, + /** + * Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last + * portion of the path. If there is no . in the last portion of the path, or if there are no . characters other than + * the first character of the basename of path, an empty string is returned. + * @param path - The path to parse + * @example + * ```ts + * // Get the extension of a URL + * path.extname('http://www.example.com/foo/bar/baz.png'); + * // -> '.png' + * // Get the extension of a file path + * path.extname('C:/Users/User/Documents/file.txt'); + * // -> '.txt' + * ``` + */ + extname(i) { + nt(i), i = on(this.toPosix(i)); + let e = -1, t = 0, n = -1, s = !0, r = 0; + for (let a = i.length - 1; a >= 0; --a) { + const o = i.charCodeAt(a); + if (o === 47) { + if (!s) { + t = a + 1; + break; + } + continue; + } + n === -1 && (s = !1, n = a + 1), o === 46 ? e === -1 ? e = a : r !== 1 && (r = 1) : e !== -1 && (r = -1); + } + return e === -1 || n === -1 || r === 0 || r === 1 && e === n - 1 && e === t + 1 ? "" : i.slice(e, n); + }, + /** + * Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties. + * @param path - The path to parse + * @example + * ```ts + * // Parse a URL + * const parsed = path.parse('http://www.example.com/foo/bar/baz.png'); + * // -> { + * // root: 'http://www.example.com/', + * // dir: 'http://www.example.com/foo/bar', + * // base: 'baz.png', + * // ext: '.png', + * // name: 'baz' + * // } + * // Parse a file path + * const parsedFile = path.parse('C:/Users/User/Documents/file.txt'); + * // -> { + * // root: 'C:/', + * // dir: 'C:/Users/User/Documents', + * // base: 'file.txt', + * // ext: '.txt', + * // name: 'file' + * // } + * ``` + */ + parse(i) { + nt(i); + const e = { root: "", dir: "", base: "", ext: "", name: "" }; + if (i.length === 0) + return e; + i = on(this.toPosix(i)); + let t = i.charCodeAt(0); + const n = this.isAbsolute(i); + let s; + e.root = this.rootname(i), n || this.hasProtocol(i) ? s = 1 : s = 0; + let r = -1, a = 0, o = -1, l = !0, h = i.length - 1, u = 0; + for (; h >= s; --h) { + if (t = i.charCodeAt(h), t === 47) { + if (!l) { + a = h + 1; + break; + } + continue; + } + o === -1 && (l = !1, o = h + 1), t === 46 ? r === -1 ? r = h : u !== 1 && (u = 1) : r !== -1 && (u = -1); + } + return r === -1 || o === -1 || u === 0 || u === 1 && r === o - 1 && r === a + 1 ? o !== -1 && (a === 0 && n ? e.base = e.name = i.slice(1, o) : e.base = e.name = i.slice(a, o)) : (a === 0 && n ? (e.name = i.slice(1, r), e.base = i.slice(1, o)) : (e.name = i.slice(a, r), e.base = i.slice(a, o)), e.ext = i.slice(r, o)), e.dir = this.dirname(i), e; + }, + sep: "/", + delimiter: ":", + joinExtensions: [".html"] +}; +function el(i, e, t, n, s) { + const r = e[t]; + for (let a = 0; a < r.length; a++) { + const o = r[a]; + t < e.length - 1 ? el(i.replace(n[t], o), e, t + 1, n, s) : s.push(i.replace(n[t], o)); + } +} +function Au(i) { + const e = /\{(.*?)\}/g, t = i.match(e), n = []; + if (t) { + const s = []; + t.forEach((r) => { + const a = r.substring(1, r.length - 1).split(","); + s.push(a); + }), el(i, s, 0, t, n); + } else + n.push(i); + return n; +} +const Br = (i) => !Array.isArray(i); +class tl { + constructor() { + this._defaultBundleIdentifierOptions = { + connector: "-", + createBundleAssetId: (e, t) => `${e}${this._bundleIdConnector}${t}`, + extractAssetIdFromBundle: (e, t) => t.replace(`${e}${this._bundleIdConnector}`, "") + }, this._bundleIdConnector = this._defaultBundleIdentifierOptions.connector, this._createBundleAssetId = this._defaultBundleIdentifierOptions.createBundleAssetId, this._extractAssetIdFromBundle = this._defaultBundleIdentifierOptions.extractAssetIdFromBundle, this._assetMap = {}, this._preferredOrder = [], this._parsers = [], this._resolverHash = {}, this._bundles = {}; + } + /** + * Override how the resolver deals with generating bundle ids. + * must be called before any bundles are added + * @param bundleIdentifier - the bundle identifier options + */ + setBundleIdentifier(e) { + if (this._bundleIdConnector = e.connector ?? this._bundleIdConnector, this._createBundleAssetId = e.createBundleAssetId ?? this._createBundleAssetId, this._extractAssetIdFromBundle = e.extractAssetIdFromBundle ?? this._extractAssetIdFromBundle, this._extractAssetIdFromBundle("foo", this._createBundleAssetId("foo", "bar")) !== "bar") + throw new Error("[Resolver] GenerateBundleAssetId are not working correctly"); + } + /** + * Let the resolver know which assets you prefer to use when resolving assets. + * Multiple prefer user defined rules can be added. + * @example + * resolver.prefer({ + * // first look for something with the correct format, and then then correct resolution + * priority: ['format', 'resolution'], + * params:{ + * format:'webp', // prefer webp images + * resolution: 2, // prefer a resolution of 2 + * } + * }) + * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']); + * resolver.resolveUrl('foo') // => 'bar@2x.webp' + * @param preferOrders - the prefer options + */ + prefer(...e) { + e.forEach((t) => { + this._preferredOrder.push(t), t.priority || (t.priority = Object.keys(t.params)); + }), this._resolverHash = {}; + } + /** + * Set the base path to prepend to all urls when resolving + * @example + * resolver.basePath = 'https://home.com/'; + * resolver.add('foo', 'bar.ong'); + * resolver.resolveUrl('foo', 'bar.png'); // => 'https://home.com/bar.png' + * @param basePath - the base path to use + */ + set basePath(e) { + this._basePath = e; + } + get basePath() { + return this._basePath; + } + /** + * Set the root path for root-relative URLs. By default the `basePath`'s root is used. If no `basePath` is set, then the + * default value for browsers is `window.location.origin` + * @example + * // Application hosted on https://home.com/some-path/index.html + * resolver.basePath = 'https://home.com/some-path/'; + * resolver.rootPath = 'https://home.com/'; + * resolver.add('foo', '/bar.png'); + * resolver.resolveUrl('foo', '/bar.png'); // => 'https://home.com/bar.png' + * @param rootPath - the root path to use + */ + set rootPath(e) { + this._rootPath = e; + } + get rootPath() { + return this._rootPath; + } + /** + * All the active URL parsers that help the parser to extract information and create + * an asset object-based on parsing the URL itself. + * + * Can be added using the extensions API + * @example + * resolver.add('foo', [ + * { + * resolution: 2, + * format: 'png', + * src: 'image@2x.png', + * }, + * { + * resolution:1, + * format:'png', + * src: 'image.png', + * }, + * ]); + * + * // With a url parser the information such as resolution and file format could extracted from the url itself: + * extensions.add({ + * extension: ExtensionType.ResolveParser, + * test: loadTextures.test, // test if url ends in an image + * parse: (value: string) => + * ({ + * resolution: parseFloat(Resolver.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + * format: value.split('.').pop(), + * src: value, + * }), + * }); + * + * // Now resolution and format can be extracted from the url + * resolver.add('foo', [ + * 'image@2x.png', + * 'image.png', + * ]); + */ + get parsers() { + return this._parsers; + } + /** Used for testing, this resets the resolver to its initial state */ + reset() { + this.setBundleIdentifier(this._defaultBundleIdentifierOptions), this._assetMap = {}, this._preferredOrder = [], this._resolverHash = {}, this._rootPath = null, this._basePath = null, this._manifest = null, this._bundles = {}, this._defaultSearchParams = null; + } + /** + * Sets the default URL search parameters for the URL resolver. The urls can be specified as a string or an object. + * @param searchParams - the default url parameters to append when resolving urls + */ + setDefaultSearchParams(e) { + if (typeof e == "string") + this._defaultSearchParams = e; + else { + const t = e; + this._defaultSearchParams = Object.keys(t).map((n) => `${encodeURIComponent(n)}=${encodeURIComponent(t[n])}`).join("&"); + } + } + /** + * Returns the aliases for a given asset + * @param asset - the asset to get the aliases for + */ + getAlias(e) { + const { alias: t, src: n } = e; + return Xt( + t || n, + (r) => typeof r == "string" ? r : Array.isArray(r) ? r.map((a) => (a == null ? void 0 : a.src) ?? a) : r != null && r.src ? r.src : r, + !0 + ); + } + /** + * Add a manifest to the asset resolver. This is a nice way to add all the asset information in one go. + * generally a manifest would be built using a tool. + * @param manifest - the manifest to add to the resolver + */ + addManifest(e) { + this._manifest && $e("[Resolver] Manifest already exists, this will be overwritten"), this._manifest = e, e.bundles.forEach((t) => { + this.addBundle(t.name, t.assets); + }); + } + /** + * This adds a bundle of assets in one go so that you can resolve them as a group. + * For example you could add a bundle for each screen in you pixi app + * @example + * resolver.addBundle('animals', [ + * { alias: 'bunny', src: 'bunny.png' }, + * { alias: 'chicken', src: 'chicken.png' }, + * { alias: 'thumper', src: 'thumper.png' }, + * ]); + * // or + * resolver.addBundle('animals', { + * bunny: 'bunny.png', + * chicken: 'chicken.png', + * thumper: 'thumper.png', + * }); + * + * const resolvedAssets = await resolver.resolveBundle('animals'); + * @param bundleId - The id of the bundle to add + * @param assets - A record of the asset or assets that will be chosen from when loading via the specified key + */ + addBundle(e, t) { + const n = []; + let s = t; + Array.isArray(t) || (s = Object.entries(t).map(([r, a]) => typeof a == "string" || Array.isArray(a) ? { alias: r, src: a } : { alias: r, ...a })), s.forEach((r) => { + const a = r.src, o = r.alias; + let l; + if (typeof o == "string") { + const h = this._createBundleAssetId(e, o); + n.push(h), l = [o, h]; + } else { + const h = o.map((u) => this._createBundleAssetId(e, u)); + n.push(...h), l = [...o, ...h]; + } + this.add({ + ...r, + alias: l, + src: a + }); + }), this._bundles[e] = n; + } + /** + * Tells the resolver what keys are associated with witch asset. + * The most important thing the resolver does + * @example + * // Single key, single asset: + * resolver.add({alias: 'foo', src: 'bar.png'); + * resolver.resolveUrl('foo') // => 'bar.png' + * + * // Multiple keys, single asset: + * resolver.add({alias: ['foo', 'boo'], src: 'bar.png'}); + * resolver.resolveUrl('foo') // => 'bar.png' + * resolver.resolveUrl('boo') // => 'bar.png' + * + * // Multiple keys, multiple assets: + * resolver.add({alias: ['foo', 'boo'], src: ['bar.png', 'bar.webp']}); + * resolver.resolveUrl('foo') // => 'bar.png' + * + * // Add custom data attached to the resolver + * Resolver.add({ + * alias: 'bunnyBooBooSmooth', + * src: 'bunny{png,webp}', + * data: { scaleMode:SCALE_MODES.NEAREST }, // Base texture options + * }); + * + * resolver.resolve('bunnyBooBooSmooth') // => { src: 'bunny.png', data: { scaleMode: SCALE_MODES.NEAREST } } + * @param aliases - the UnresolvedAsset or array of UnresolvedAssets to add to the resolver + */ + add(e) { + const t = []; + Array.isArray(e) ? t.push(...e) : t.push(e); + let n; + n = (r) => { + this.hasKey(r) && $e(`[Resolver] already has key: ${r} overwriting`); + }, Xt(t).forEach((r) => { + const { src: a } = r; + let { data: o, format: l, loadParser: h, parser: u } = r; + const c = Xt(a).map((_) => typeof _ == "string" ? Au(_) : Array.isArray(_) ? _ : [_]), d = this.getAlias(r); + Array.isArray(d) ? d.forEach(n) : n(d); + const f = []; + c.forEach((_) => { + _.forEach((b) => { + let m = {}; + if (typeof b != "object") { + m.src = b; + for (let x = 0; x < this._parsers.length; x++) { + const g = this._parsers[x]; + if (g.test(b)) { + m = g.parse(b); + break; + } + } + } else + o = b.data ?? o, l = b.format ?? l, (b.loadParser || b.parser) && (h = b.loadParser ?? h, u = b.parser ?? u), m = { + ...m, + ...b + }; + if (!d) + throw new Error(`[Resolver] alias is undefined for this asset: ${m.src}`); + m = this._buildResolvedAsset(m, { + aliases: d, + data: o, + format: l, + loadParser: h, + parser: u + }), f.push(m); + }); + }), d.forEach((_) => { + this._assetMap[_] = f; + }); + }); + } + // TODO: this needs an overload like load did in Assets + /** + * If the resolver has had a manifest set via setManifest, this will return the assets urls for + * a given bundleId or bundleIds. + * @example + * // Manifest Example + * const manifest = { + * bundles: [ + * { + * name: 'load-screen', + * assets: [ + * { + * alias: 'background', + * src: 'sunset.png', + * }, + * { + * alias: 'bar', + * src: 'load-bar.{png,webp}', + * }, + * ], + * }, + * { + * name: 'game-screen', + * assets: [ + * { + * alias: 'character', + * src: 'robot.png', + * }, + * { + * alias: 'enemy', + * src: 'bad-guy.png', + * }, + * ], + * }, + * ] + * }; + * + * resolver.setManifest(manifest); + * const resolved = resolver.resolveBundle('load-screen'); + * @param bundleIds - The bundle ids to resolve + * @returns All the bundles assets or a hash of assets for each bundle specified + */ + resolveBundle(e) { + const t = Br(e); + e = Xt(e); + const n = {}; + return e.forEach((s) => { + const r = this._bundles[s]; + if (r) { + const a = this.resolve(r), o = {}; + for (const l in a) { + const h = a[l]; + o[this._extractAssetIdFromBundle(s, l)] = h; + } + n[s] = o; + } + }), t ? n[e[0]] : n; + } + /** + * Does exactly what resolve does, but returns just the URL rather than the whole asset object + * @param key - The key or keys to resolve + * @returns - The URLs associated with the key(s) + */ + resolveUrl(e) { + const t = this.resolve(e); + if (typeof e != "string") { + const n = {}; + for (const s in t) + n[s] = t[s].src; + return n; + } + return t.src; + } + resolve(e) { + const t = Br(e); + e = Xt(e); + const n = {}; + return e.forEach((s) => { + if (!this._resolverHash[s]) + if (this._assetMap[s]) { + let r = this._assetMap[s]; + const a = this._getPreferredOrder(r); + a == null || a.priority.forEach((o) => { + a.params[o].forEach((l) => { + const h = r.filter((u) => u[o] ? u[o] === l : !1); + h.length && (r = h); + }); + }), this._resolverHash[s] = r[0]; + } else + this._resolverHash[s] = this._buildResolvedAsset({ + alias: [s], + src: s + }, {}); + n[s] = this._resolverHash[s]; + }), t ? n[e[0]] : n; + } + /** + * Checks if an asset with a given key exists in the resolver + * @param key - The key of the asset + */ + hasKey(e) { + return !!this._assetMap[e]; + } + /** + * Checks if a bundle with the given key exists in the resolver + * @param key - The key of the bundle + */ + hasBundle(e) { + return !!this._bundles[e]; + } + /** + * Internal function for figuring out what prefer criteria an asset should use. + * @param assets + */ + _getPreferredOrder(e) { + for (let t = 0; t < e.length; t++) { + const n = e[t], s = this._preferredOrder.find((r) => r.params.format.includes(n.format)); + if (s) + return s; + } + return this._preferredOrder[0]; + } + /** + * Appends the default url parameters to the url + * @param url - The url to append the default parameters to + * @returns - The url with the default parameters appended + */ + _appendDefaultSearchParams(e) { + if (!this._defaultSearchParams) + return e; + const t = /\?/.test(e) ? "&" : "?"; + return `${e}${t}${this._defaultSearchParams}`; + } + _buildResolvedAsset(e, t) { + const { aliases: n, data: s, loadParser: r, parser: a, format: o } = t; + return (this._basePath || this._rootPath) && (e.src = Fn.toAbsolute(e.src, this._basePath, this._rootPath)), e.alias = n ?? e.alias ?? [e.src], e.src = this._appendDefaultSearchParams(e.src), e.data = { ...s || {}, ...e.data }, e.loadParser = r ?? e.loadParser, e.parser = a ?? e.parser, e.format = o ?? e.format ?? Du(e.src), e; + } +} +tl.RETINA_PREFIX = /@([0-9\.]+)x/; +function Du(i) { + return i.split(".").pop().split("?").shift().split("#").shift(); +} +const Lr = (i, e) => { + const t = e.split("?")[1]; + return t && (i += `?${t}`), i; +}, nl = class yn { + constructor(e, t) { + this.linkedSheets = []; + let n = e; + (e == null ? void 0 : e.source) instanceof ut && (n = { + texture: e, + data: t + }); + const { texture: s, data: r, cachePrefix: a = "" } = n; + this.cachePrefix = a, this._texture = s instanceof K ? s : null, this.textureSource = s.source, this.textures = {}, this.animations = {}, this.data = r; + const o = parseFloat(r.meta.scale); + o ? (this.resolution = o, s.source.resolution = this.resolution) : this.resolution = s.source._resolution, this._frames = this.data.frames, this._frameKeys = Object.keys(this._frames), this._batchIndex = 0, this._callback = null; + } + /** + * Parser spritesheet from loaded data. This is done asynchronously + * to prevent creating too many Texture within a single process. + */ + parse() { + return new Promise((e) => { + this._callback = e, this._batchIndex = 0, this._frameKeys.length <= yn.BATCH_SIZE ? (this._processFrames(0), this._processAnimations(), this._parseComplete()) : this._nextBatch(); + }); + } + /** + * Process a batch of frames + * @param initialFrameIndex - The index of frame to start. + */ + _processFrames(e) { + let t = e; + const n = yn.BATCH_SIZE; + for (; t - e < n && t < this._frameKeys.length; ) { + const s = this._frameKeys[t], r = this._frames[s], a = r.frame; + if (a) { + let o = null, l = null; + const h = r.trimmed !== !1 && r.sourceSize ? r.sourceSize : r.frame, u = new de( + 0, + 0, + Math.floor(h.w) / this.resolution, + Math.floor(h.h) / this.resolution + ); + r.rotated ? o = new de( + Math.floor(a.x) / this.resolution, + Math.floor(a.y) / this.resolution, + Math.floor(a.h) / this.resolution, + Math.floor(a.w) / this.resolution + ) : o = new de( + Math.floor(a.x) / this.resolution, + Math.floor(a.y) / this.resolution, + Math.floor(a.w) / this.resolution, + Math.floor(a.h) / this.resolution + ), r.trimmed !== !1 && r.spriteSourceSize && (l = new de( + Math.floor(r.spriteSourceSize.x) / this.resolution, + Math.floor(r.spriteSourceSize.y) / this.resolution, + Math.floor(a.w) / this.resolution, + Math.floor(a.h) / this.resolution + )), this.textures[s] = new K({ + source: this.textureSource, + frame: o, + orig: u, + trim: l, + rotate: r.rotated ? 2 : 0, + defaultAnchor: r.anchor, + defaultBorders: r.borders, + label: s.toString() + }); + } + t++; + } + } + /** Parse animations config. */ + _processAnimations() { + const e = this.data.animations || {}; + for (const t in e) { + this.animations[t] = []; + for (let n = 0; n < e[t].length; n++) { + const s = e[t][n]; + this.animations[t].push(this.textures[s]); + } + } + } + /** The parse has completed. */ + _parseComplete() { + const e = this._callback; + this._callback = null, this._batchIndex = 0, e.call(this, this.textures); + } + /** Begin the next batch of textures. */ + _nextBatch() { + this._processFrames(this._batchIndex * yn.BATCH_SIZE), this._batchIndex++, setTimeout(() => { + this._batchIndex * yn.BATCH_SIZE < this._frameKeys.length ? this._nextBatch() : (this._processAnimations(), this._parseComplete()); + }, 0); + } + /** + * Destroy Spritesheet and don't use after this. + * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well + */ + destroy(e = !1) { + var t; + for (const n in this.textures) + this.textures[n].destroy(); + this._frames = null, this._frameKeys = null, this.data = null, this.textures = null, e && ((t = this._texture) == null || t.destroy(), this.textureSource.destroy()), this._texture = null, this.textureSource = null, this.linkedSheets = []; + } +}; +nl.BATCH_SIZE = 1e3; +let Or = nl; +const Eu = [ + "jpg", + "png", + "jpeg", + "avif", + "webp", + "basis", + "etc2", + "bc7", + "bc6h", + "bc5", + "bc4", + "bc3", + "bc2", + "bc1", + "eac", + "astc" +]; +function il(i, e, t) { + const n = {}; + if (i.forEach((s) => { + n[s] = e; + }), Object.keys(e.textures).forEach((s) => { + n[`${e.cachePrefix}${s}`] = e.textures[s]; + }), !t) { + const s = Fn.dirname(i[0]); + e.linkedSheets.forEach((r, a) => { + const o = il([`${s}/${e.data.meta.related_multi_packs[a]}`], r, !0); + Object.assign(n, o); + }); + } + return n; +} +const Fu = { + extension: Q.Asset, + /** Handle the caching of the related Spritesheet Textures */ + cache: { + test: (i) => i instanceof Or, + getCacheableAssets: (i, e) => il(i, e, !1) + }, + /** Resolve the resolution of the asset. */ + resolver: { + extension: { + type: Q.ResolveParser, + name: "resolveSpritesheet" + }, + test: (i) => { + const t = i.split("?")[0].split("."), n = t.pop(), s = t.pop(); + return n === "json" && Eu.includes(s); + }, + parse: (i) => { + var t; + const e = i.split("."); + return { + resolution: parseFloat(((t = tl.RETINA_PREFIX.exec(i)) == null ? void 0 : t[1]) ?? "1"), + format: e[e.length - 2], + src: i + }; + } + }, + /** + * Loader plugin that parses sprite sheets! + * once the JSON has been loaded this checks to see if the JSON is spritesheet data. + * If it is, we load the spritesheets image and parse the data into Spritesheet + * All textures in the sprite sheet are then added to the cache + */ + loader: { + /** used for deprecation purposes */ + name: "spritesheetLoader", + id: "spritesheet", + extension: { + type: Q.LoadParser, + priority: Jo.Normal, + name: "spritesheetLoader" + }, + async testParse(i, e) { + return Fn.extname(e.src).toLowerCase() === ".json" && !!i.frames; + }, + async parse(i, e, t) { + var c, d; + const { + texture: n, + // if user need to use preloaded texture + imageFilename: s, + // if user need to use custom filename (not from jsonFile.meta.image) + textureOptions: r, + // if user need to set texture options on texture + cachePrefix: a + // if user need to use custom cache prefix + } = (e == null ? void 0 : e.data) ?? {}; + let o = Fn.dirname(e.src); + o && o.lastIndexOf("/") !== o.length - 1 && (o += "/"); + let l; + if (n instanceof K) + l = n; + else { + const f = Lr(o + (s ?? i.meta.image), e.src); + l = (await t.load([{ src: f, data: r }]))[f]; + } + const h = new Or({ + texture: l.source, + data: i, + cachePrefix: a + }); + await h.parse(); + const u = (c = i == null ? void 0 : i.meta) == null ? void 0 : c.related_multi_packs; + if (Array.isArray(u)) { + const f = []; + for (const b of u) { + if (typeof b != "string") + continue; + let m = o + b; + (d = e.data) != null && d.ignoreMultiPack || (m = Lr(m, e.src), f.push(t.load({ + src: m, + data: { + textureOptions: r, + ignoreMultiPack: !0 + } + }))); + } + const _ = await Promise.all(f); + h.linkedSheets = _, _.forEach((b) => { + b.linkedSheets = [h].concat(h.linkedSheets.filter((m) => m !== b)); + }); + } + return h; + }, + async unload(i, e, t) { + await t.unload(i.textureSource._sourceOrigin), i.destroy(!1); + } + } +}; +Qe.add(Fu); +const Ui = /* @__PURE__ */ Object.create(null), zr = /* @__PURE__ */ Object.create(null); +function Ys(i, e) { + let t = zr[i]; + return t === void 0 && (Ui[e] === void 0 && (Ui[e] = 1), zr[i] = t = Ui[e]++), t; +} +let Ut; +function sl() { + return (!Ut || Ut != null && Ut.isContextLost()) && (Ut = Ge.get().createCanvas().getContext("webgl", {})), Ut; +} +let Xn; +function $u() { + if (!Xn) { + Xn = "mediump"; + const i = sl(); + i && i.getShaderPrecisionFormat && (Xn = i.getShaderPrecisionFormat(i.FRAGMENT_SHADER, i.HIGH_FLOAT).precision ? "highp" : "mediump"); + } + return Xn; +} +function Tu(i, e, t) { + return e ? i : t ? (i = i.replace("out vec4 finalColor;", ""), ` + + #ifdef GL_ES // This checks if it is WebGL1 + #define in varying + #define finalColor gl_FragColor + #define texture texture2D + #endif + ${i} + `) : ` + + #ifdef GL_ES // This checks if it is WebGL1 + #define in attribute + #define out varying + #endif + ${i} + `; +} +function Mu(i, e, t) { + const n = t ? e.maxSupportedFragmentPrecision : e.maxSupportedVertexPrecision; + if (i.substring(0, 9) !== "precision") { + let s = t ? e.requestedFragmentPrecision : e.requestedVertexPrecision; + return s === "highp" && n !== "highp" && (s = "mediump"), `precision ${s} float; +${i}`; + } else if (n !== "highp" && i.substring(0, 15) === "precision highp") + return i.replace("precision highp", "precision mediump"); + return i; +} +function Pu(i, e) { + return e ? `#version 300 es +${i}` : i; +} +const Iu = {}, Ru = {}; +function Bu(i, { name: e = "pixi-program" }, t = !0) { + e = e.replace(/\s+/g, "-"), e += t ? "-fragment" : "-vertex"; + const n = t ? Iu : Ru; + return n[e] ? (n[e]++, e += `-${n[e]}`) : n[e] = 1, i.indexOf("#define SHADER_NAME") !== -1 ? i : `${`#define SHADER_NAME ${e}`} +${i}`; +} +function Lu(i, e) { + return e ? i.replace("#version 300 es", "") : i; +} +const Hi = { + // strips any version headers.. + stripVersion: Lu, + // adds precision string if not already present + ensurePrecision: Mu, + // add some defines if WebGL1 to make it more compatible with WebGL2 shaders + addProgramDefines: Tu, + // add the program name to the shader + setProgramName: Bu, + // add the version string to the shader header + insertVersion: Pu +}, ln = /* @__PURE__ */ Object.create(null), rl = class bs { + /** + * Creates a shiny new GlProgram. Used by WebGL renderer. + * @param options - The options for the program. + */ + constructor(e) { + e = { ...bs.defaultOptions, ...e }; + const t = e.fragment.indexOf("#version 300 es") !== -1, n = { + stripVersion: t, + ensurePrecision: { + requestedFragmentPrecision: e.preferredFragmentPrecision, + requestedVertexPrecision: e.preferredVertexPrecision, + maxSupportedVertexPrecision: "highp", + maxSupportedFragmentPrecision: $u() + }, + setProgramName: { + name: e.name + }, + addProgramDefines: t, + insertVersion: t + }; + let s = e.fragment, r = e.vertex; + Object.keys(Hi).forEach((a) => { + const o = n[a]; + s = Hi[a](s, o, !0), r = Hi[a](r, o, !1); + }), this.fragment = s, this.vertex = r, this.transformFeedbackVaryings = e.transformFeedbackVaryings, this._key = Ys(`${this.vertex}:${this.fragment}`, "gl-program"); + } + /** destroys the program */ + destroy() { + this.fragment = null, this.vertex = null, this._attributeData = null, this._uniformData = null, this._uniformBlockData = null, this.transformFeedbackVaryings = null, ln[this._cacheKey] = null; + } + /** + * Helper function that creates a program for a given source. + * It will check the program cache if the program has already been created. + * If it has that one will be returned, if not a new one will be created and cached. + * @param options - The options for the program. + * @returns A program using the same source + */ + static from(e) { + const t = `${e.vertex}:${e.fragment}`; + return ln[t] || (ln[t] = new bs(e), ln[t]._cacheKey = t), ln[t]; + } +}; +rl.defaultOptions = { + preferredVertexPrecision: "highp", + preferredFragmentPrecision: "mediump" +}; +let al = rl; +const Nr = { + uint8x2: { size: 2, stride: 2, normalised: !1 }, + uint8x4: { size: 4, stride: 4, normalised: !1 }, + sint8x2: { size: 2, stride: 2, normalised: !1 }, + sint8x4: { size: 4, stride: 4, normalised: !1 }, + unorm8x2: { size: 2, stride: 2, normalised: !0 }, + unorm8x4: { size: 4, stride: 4, normalised: !0 }, + snorm8x2: { size: 2, stride: 2, normalised: !0 }, + snorm8x4: { size: 4, stride: 4, normalised: !0 }, + uint16x2: { size: 2, stride: 4, normalised: !1 }, + uint16x4: { size: 4, stride: 8, normalised: !1 }, + sint16x2: { size: 2, stride: 4, normalised: !1 }, + sint16x4: { size: 4, stride: 8, normalised: !1 }, + unorm16x2: { size: 2, stride: 4, normalised: !0 }, + unorm16x4: { size: 4, stride: 8, normalised: !0 }, + snorm16x2: { size: 2, stride: 4, normalised: !0 }, + snorm16x4: { size: 4, stride: 8, normalised: !0 }, + float16x2: { size: 2, stride: 4, normalised: !1 }, + float16x4: { size: 4, stride: 8, normalised: !1 }, + float32: { size: 1, stride: 4, normalised: !1 }, + float32x2: { size: 2, stride: 8, normalised: !1 }, + float32x3: { size: 3, stride: 12, normalised: !1 }, + float32x4: { size: 4, stride: 16, normalised: !1 }, + uint32: { size: 1, stride: 4, normalised: !1 }, + uint32x2: { size: 2, stride: 8, normalised: !1 }, + uint32x3: { size: 3, stride: 12, normalised: !1 }, + uint32x4: { size: 4, stride: 16, normalised: !1 }, + sint32: { size: 1, stride: 4, normalised: !1 }, + sint32x2: { size: 2, stride: 8, normalised: !1 }, + sint32x3: { size: 3, stride: 12, normalised: !1 }, + sint32x4: { size: 4, stride: 16, normalised: !1 } +}; +function Ou(i) { + return Nr[i] ?? Nr.float32; +} +const zu = { + f32: "float32", + "vec2": "float32x2", + "vec3": "float32x3", + "vec4": "float32x4", + vec2f: "float32x2", + vec3f: "float32x3", + vec4f: "float32x4", + i32: "sint32", + "vec2": "sint32x2", + "vec3": "sint32x3", + "vec4": "sint32x4", + u32: "uint32", + "vec2": "uint32x2", + "vec3": "uint32x3", + "vec4": "uint32x4", + bool: "uint32", + "vec2": "uint32x2", + "vec3": "uint32x3", + "vec4": "uint32x4" +}; +function Nu({ source: i, entryPoint: e }) { + const t = {}, n = i.indexOf(`fn ${e}`); + if (n !== -1) { + const s = i.indexOf("->", n); + if (s !== -1) { + const r = i.substring(n, s), a = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g; + let o; + for (; (o = a.exec(r)) !== null; ) { + const l = zu[o[3]] ?? "float32"; + t[o[2]] = { + location: parseInt(o[1], 10), + format: l, + stride: Ou(l).stride, + offset: 0, + instance: !1, + start: 0 + }; + } + } + } + return t; +} +function Vi(i) { + var c, d; + const e = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g, t = /@group\((\d+)\)/, n = /@binding\((\d+)\)/, s = /var(<[^>]+>)? (\w+)/, r = /:\s*(\w+)/, a = /struct\s+(\w+)\s*{([^}]+)}/g, o = /(\w+)\s*:\s*([\w\<\>]+)/g, l = /struct\s+(\w+)/, h = (c = i.match(e)) == null ? void 0 : c.map((f) => ({ + group: parseInt(f.match(t)[1], 10), + binding: parseInt(f.match(n)[1], 10), + name: f.match(s)[2], + isUniform: f.match(s)[1] === "", + type: f.match(r)[1] + })); + if (!h) + return { + groups: [], + structs: [] + }; + const u = ((d = i.match(a)) == null ? void 0 : d.map((f) => { + const _ = f.match(l)[1], b = f.match(o).reduce((m, x) => { + const [g, p] = x.split(":"); + return m[g.trim()] = p.trim(), m; + }, {}); + return b ? { name: _, members: b } : null; + }).filter(({ name: f }) => h.some((_) => _.type === f))) ?? []; + return { + groups: h, + structs: u + }; +} +var bn = /* @__PURE__ */ ((i) => (i[i.VERTEX = 1] = "VERTEX", i[i.FRAGMENT = 2] = "FRAGMENT", i[i.COMPUTE = 4] = "COMPUTE", i))(bn || {}); +function Gu({ groups: i }) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t]; + e[n.group] || (e[n.group] = []), n.isUniform ? e[n.group].push({ + binding: n.binding, + visibility: bn.VERTEX | bn.FRAGMENT, + buffer: { + type: "uniform" + } + }) : n.type === "sampler" ? e[n.group].push({ + binding: n.binding, + visibility: bn.FRAGMENT, + sampler: { + type: "filtering" + } + }) : n.type === "texture_2d" && e[n.group].push({ + binding: n.binding, + visibility: bn.FRAGMENT, + texture: { + sampleType: "float", + viewDimension: "2d", + multisampled: !1 + } + }); + } + return e; +} +function qu({ groups: i }) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t]; + e[n.group] || (e[n.group] = {}), e[n.group][n.name] = n.binding; + } + return e; +} +function Uu(i, e) { + const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), s = [...i.structs, ...e.structs].filter((a) => t.has(a.name) ? !1 : (t.add(a.name), !0)), r = [...i.groups, ...e.groups].filter((a) => { + const o = `${a.name}-${a.binding}`; + return n.has(o) ? !1 : (n.add(o), !0); + }); + return { structs: s, groups: r }; +} +const hn = /* @__PURE__ */ Object.create(null); +class Di { + /** + * Create a new GpuProgram + * @param options - The options for the gpu program + */ + constructor(e) { + var o, l; + this._layoutKey = 0, this._attributeLocationsKey = 0; + const { fragment: t, vertex: n, layout: s, gpuLayout: r, name: a } = e; + if (this.name = a, this.fragment = t, this.vertex = n, t.source === n.source) { + const h = Vi(t.source); + this.structsAndGroups = h; + } else { + const h = Vi(n.source), u = Vi(t.source); + this.structsAndGroups = Uu(h, u); + } + this.layout = s ?? qu(this.structsAndGroups), this.gpuLayout = r ?? Gu(this.structsAndGroups), this.autoAssignGlobalUniforms = ((o = this.layout[0]) == null ? void 0 : o.globalUniforms) !== void 0, this.autoAssignLocalUniforms = ((l = this.layout[1]) == null ? void 0 : l.localUniforms) !== void 0, this._generateProgramKey(); + } + // TODO maker this pure + _generateProgramKey() { + const { vertex: e, fragment: t } = this, n = e.source + t.source + e.entryPoint + t.entryPoint; + this._layoutKey = Ys(n, "program"); + } + get attributeData() { + return this._attributeData ?? (this._attributeData = Nu(this.vertex)), this._attributeData; + } + /** destroys the program */ + destroy() { + this.gpuLayout = null, this.layout = null, this.structsAndGroups = null, this.fragment = null, this.vertex = null, hn[this._cacheKey] = null; + } + /** + * Helper function that creates a program for a given source. + * It will check the program cache if the program has already been created. + * If it has that one will be returned, if not a new one will be created and cached. + * @param options - The options for the program. + * @returns A program using the same source + */ + static from(e) { + const t = `${e.vertex.source}:${e.fragment.source}:${e.fragment.entryPoint}:${e.vertex.entryPoint}`; + return hn[t] || (hn[t] = new Di(e), hn[t]._cacheKey = t), hn[t]; + } +} +const ol = [ + "f32", + "i32", + "vec2", + "vec3", + "vec4", + "mat2x2", + "mat3x3", + "mat4x4", + "mat3x2", + "mat4x2", + "mat2x3", + "mat4x3", + "mat2x4", + "mat3x4", + "vec2", + "vec3", + "vec4" +], Hu = ol.reduce((i, e) => (i[e] = !0, i), {}); +function Vu(i, e) { + switch (i) { + case "f32": + return 0; + case "vec2": + return new Float32Array(2 * e); + case "vec3": + return new Float32Array(3 * e); + case "vec4": + return new Float32Array(4 * e); + case "mat2x2": + return new Float32Array([ + 1, + 0, + 0, + 1 + ]); + case "mat3x3": + return new Float32Array([ + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 + ]); + case "mat4x4": + return new Float32Array([ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ]); + } + return null; +} +const ll = class hl { + /** + * Create a new Uniform group + * @param uniformStructures - The structures of the uniform group + * @param options - The optional parameters of this uniform group + */ + constructor(e, t) { + this._touched = 0, this.uid = ue("uniform"), this._resourceType = "uniformGroup", this._resourceId = ue("resource"), this.isUniformGroup = !0, this._dirtyId = 0, this.destroyed = !1, t = { ...hl.defaultOptions, ...t }, this.uniformStructures = e; + const n = {}; + for (const s in e) { + const r = e[s]; + if (r.name = s, r.size = r.size ?? 1, !Hu[r.type]) { + const a = r.type.match(/^array<(\w+(?:<\w+>)?),\s*(\d+)>$/); + if (a) { + const [, o, l] = a; + throw new Error( + `Uniform type ${r.type} is not supported. Use type: '${o}', size: ${l} instead.` + ); + } + throw new Error(`Uniform type ${r.type} is not supported. Supported uniform types are: ${ol.join(", ")}`); + } + r.value ?? (r.value = Vu(r.type, r.size)), n[s] = r.value; + } + this.uniforms = n, this._dirtyId = 1, this.ubo = t.ubo, this.isStatic = t.isStatic, this._signature = Ys(Object.keys(n).map( + (s) => `${s}-${e[s].type}` + ).join("-"), "uniform-group"); + } + /** Call this if you want the uniform groups data to be uploaded to the GPU only useful if `isStatic` is true. */ + update() { + this._dirtyId++; + } +}; +ll.defaultOptions = { + /** if true the UniformGroup is handled as an Uniform buffer object. */ + ubo: !1, + /** if true, then you are responsible for when the data is uploaded to the GPU by calling `update()` */ + isStatic: !1 +}; +let ul = ll; +class di { + /** + * Create a new instance eof the Bind Group. + * @param resources - The resources that are bound together for use by a shader. + */ + constructor(e) { + this.resources = /* @__PURE__ */ Object.create(null), this._dirty = !0; + let t = 0; + for (const n in e) { + const s = e[n]; + this.setResource(s, t++); + } + this._updateKey(); + } + /** + * Updates the key if its flagged as dirty. This is used internally to + * match this bind group to a WebGPU BindGroup. + * @internal + */ + _updateKey() { + if (!this._dirty) + return; + this._dirty = !1; + const e = []; + let t = 0; + for (const n in this.resources) + e[t++] = this.resources[n]._resourceId; + this._key = e.join("|"); + } + /** + * Set a resource at a given index. this function will + * ensure that listeners will be removed from the current resource + * and added to the new resource. + * @param resource - The resource to set. + * @param index - The index to set the resource at. + */ + setResource(e, t) { + var s, r; + const n = this.resources[t]; + e !== n && (n && ((s = e.off) == null || s.call(e, "change", this.onResourceChange, this)), (r = e.on) == null || r.call(e, "change", this.onResourceChange, this), this.resources[t] = e, this._dirty = !0); + } + /** + * Returns the resource at the current specified index. + * @param index - The index of the resource to get. + * @returns - The resource at the specified index. + */ + getResource(e) { + return this.resources[e]; + } + /** + * Used internally to 'touch' each resource, to ensure that the GC + * knows that all resources in this bind group are still being used. + * @param tick - The current tick. + * @internal + */ + _touch(e) { + const t = this.resources; + for (const n in t) + t[n]._touched = e; + } + /** Destroys this bind group and removes all listeners. */ + destroy() { + var t; + const e = this.resources; + for (const n in e) { + const s = e[n]; + (t = s == null ? void 0 : s.off) == null || t.call(s, "change", this.onResourceChange, this); + } + this.resources = null; + } + onResourceChange(e) { + if (this._dirty = !0, e.destroyed) { + const t = this.resources; + for (const n in t) + t[n] === e && (t[n] = null); + } else + this._updateKey(); + } +} +var xs = /* @__PURE__ */ ((i) => (i[i.WEBGL = 1] = "WEBGL", i[i.WEBGPU = 2] = "WEBGPU", i[i.BOTH = 3] = "BOTH", i))(xs || {}); +class Xs extends xt { + constructor(e) { + super(), this.uid = ue("shader"), this._uniformBindMap = /* @__PURE__ */ Object.create(null), this._ownedBindGroups = []; + let { + gpuProgram: t, + glProgram: n, + groups: s, + resources: r, + compatibleRenderers: a, + groupMap: o + } = e; + this.gpuProgram = t, this.glProgram = n, a === void 0 && (a = 0, t && (a |= xs.WEBGPU), n && (a |= xs.WEBGL)), this.compatibleRenderers = a; + const l = {}; + if (!r && !s && (r = {}), r && s) + throw new Error("[Shader] Cannot have both resources and groups"); + if (!t && s && !o) + throw new Error("[Shader] No group map or WebGPU shader provided - consider using resources instead."); + if (!t && s && o) + for (const h in o) + for (const u in o[h]) { + const c = o[h][u]; + l[c] = { + group: h, + binding: u, + name: c + }; + } + else if (t && s && !o) { + const h = t.structsAndGroups.groups; + o = {}, h.forEach((u) => { + o[u.group] = o[u.group] || {}, o[u.group][u.binding] = u.name, l[u.name] = u; + }); + } else if (r) { + s = {}, o = {}, t && t.structsAndGroups.groups.forEach((c) => { + o[c.group] = o[c.group] || {}, o[c.group][c.binding] = c.name, l[c.name] = c; + }); + let h = 0; + for (const u in r) + l[u] || (s[99] || (s[99] = new di(), this._ownedBindGroups.push(s[99])), l[u] = { group: 99, binding: h, name: u }, o[99] = o[99] || {}, o[99][h] = u, h++); + for (const u in r) { + const c = u; + let d = r[u]; + !d.source && !d._resourceType && (d = new ul(d)); + const f = l[c]; + f && (s[f.group] || (s[f.group] = new di(), this._ownedBindGroups.push(s[f.group])), s[f.group].setResource(d, f.binding)); + } + } + this.groups = s, this._uniformBindMap = o, this.resources = this._buildResourceAccessor(s, l); + } + /** + * Sometimes a resource group will be provided later (for example global uniforms) + * In such cases, this method can be used to let the shader know about the group. + * @param name - the name of the resource group + * @param groupIndex - the index of the group (should match the webGPU shader group location) + * @param bindIndex - the index of the bind point (should match the webGPU shader bind point) + */ + addResource(e, t, n) { + var s, r; + (s = this._uniformBindMap)[t] || (s[t] = {}), (r = this._uniformBindMap[t])[n] || (r[n] = e), this.groups[t] || (this.groups[t] = new di(), this._ownedBindGroups.push(this.groups[t])); + } + _buildResourceAccessor(e, t) { + const n = {}; + for (const s in t) { + const r = t[s]; + Object.defineProperty(n, r.name, { + get() { + return e[r.group].getResource(r.binding); + }, + set(a) { + e[r.group].setResource(a, r.binding); + } + }); + } + return n; + } + /** + * Use to destroy the shader when its not longer needed. + * It will destroy the resources and remove listeners. + * @param destroyPrograms - if the programs should be destroyed as well. + * Make sure its not being used by other shaders! + */ + destroy(e = !1) { + var t, n; + this.emit("destroy", this), e && ((t = this.gpuProgram) == null || t.destroy(), (n = this.glProgram) == null || n.destroy()), this.gpuProgram = null, this.glProgram = null, this.removeAllListeners(), this._uniformBindMap = null, this._ownedBindGroups.forEach((s) => { + s.destroy(); + }), this._ownedBindGroups = null, this.resources = null, this.groups = null; + } + static from(e) { + const { gpu: t, gl: n, ...s } = e; + let r, a; + return t && (r = Di.from(t)), n && (a = al.from(n)), new Xs({ + gpuProgram: r, + glProgram: a, + ...s + }); + } +} +const ws = []; +Qe.handleByNamedList(Q.Environment, ws); +async function Wu(i) { + if (!i) + for (let e = 0; e < ws.length; e++) { + const t = ws[e]; + if (t.value.test()) { + await t.value.load(); + return; + } + } +} +let un; +function Yu() { + if (typeof un == "boolean") + return un; + try { + un = new Function("param1", "param2", "param3", "return param1[param2] === param3;")({ a: "b" }, "a", "b") === !0; + } catch { + un = !1; + } + return un; +} +function Gr(i, e, t = 2) { + const n = e && e.length, s = n ? e[0] * t : i.length; + let r = cl(i, 0, s, t, !0); + const a = []; + if (!r || r.next === r.prev) return a; + let o, l, h; + if (n && (r = Qu(i, e, r, t)), i.length > 80 * t) { + o = i[0], l = i[1]; + let u = o, c = l; + for (let d = t; d < s; d += t) { + const f = i[d], _ = i[d + 1]; + f < o && (o = f), _ < l && (l = _), f > u && (u = f), _ > c && (c = _); + } + h = Math.max(u - o, c - l), h = h !== 0 ? 32767 / h : 0; + } + return $n(r, a, t, o, l, h, 0), a; +} +function cl(i, e, t, n, s) { + let r; + if (s === hc(i, e, t, n) > 0) + for (let a = e; a < t; a += n) r = qr(a / n | 0, i[a], i[a + 1], r); + else + for (let a = t - n; a >= e; a -= n) r = qr(a / n | 0, i[a], i[a + 1], r); + return r && rn(r, r.next) && (Mn(r), r = r.next), r; +} +function zt(i, e) { + if (!i) return i; + e || (e = i); + let t = i, n; + do + if (n = !1, !t.steiner && (rn(t, t.next) || oe(t.prev, t, t.next) === 0)) { + if (Mn(t), t = e = t.prev, t === t.next) break; + n = !0; + } else + t = t.next; + while (n || t !== e); + return e; +} +function $n(i, e, t, n, s, r, a) { + if (!i) return; + !a && r && ic(i, n, s, r); + let o = i; + for (; i.prev !== i.next; ) { + const l = i.prev, h = i.next; + if (r ? ju(i, n, s, r) : Xu(i)) { + e.push(l.i, i.i, h.i), Mn(i), i = h.next, o = h.next; + continue; + } + if (i = h, i === o) { + a ? a === 1 ? (i = Zu(zt(i), e), $n(i, e, t, n, s, r, 2)) : a === 2 && Ku(i, e, t, n, s, r) : $n(zt(i), e, t, n, s, r, 1); + break; + } + } +} +function Xu(i) { + const e = i.prev, t = i, n = i.next; + if (oe(e, t, n) >= 0) return !1; + const s = e.x, r = t.x, a = n.x, o = e.y, l = t.y, h = n.y, u = Math.min(s, r, a), c = Math.min(o, l, h), d = Math.max(s, r, a), f = Math.max(o, l, h); + let _ = n.next; + for (; _ !== e; ) { + if (_.x >= u && _.x <= d && _.y >= c && _.y <= f && xn(s, o, r, l, a, h, _.x, _.y) && oe(_.prev, _, _.next) >= 0) return !1; + _ = _.next; + } + return !0; +} +function ju(i, e, t, n) { + const s = i.prev, r = i, a = i.next; + if (oe(s, r, a) >= 0) return !1; + const o = s.x, l = r.x, h = a.x, u = s.y, c = r.y, d = a.y, f = Math.min(o, l, h), _ = Math.min(u, c, d), b = Math.max(o, l, h), m = Math.max(u, c, d), x = vs(f, _, e, t, n), g = vs(b, m, e, t, n); + let p = i.prevZ, y = i.nextZ; + for (; p && p.z >= x && y && y.z <= g; ) { + if (p.x >= f && p.x <= b && p.y >= _ && p.y <= m && p !== s && p !== a && xn(o, u, l, c, h, d, p.x, p.y) && oe(p.prev, p, p.next) >= 0 || (p = p.prevZ, y.x >= f && y.x <= b && y.y >= _ && y.y <= m && y !== s && y !== a && xn(o, u, l, c, h, d, y.x, y.y) && oe(y.prev, y, y.next) >= 0)) return !1; + y = y.nextZ; + } + for (; p && p.z >= x; ) { + if (p.x >= f && p.x <= b && p.y >= _ && p.y <= m && p !== s && p !== a && xn(o, u, l, c, h, d, p.x, p.y) && oe(p.prev, p, p.next) >= 0) return !1; + p = p.prevZ; + } + for (; y && y.z <= g; ) { + if (y.x >= f && y.x <= b && y.y >= _ && y.y <= m && y !== s && y !== a && xn(o, u, l, c, h, d, y.x, y.y) && oe(y.prev, y, y.next) >= 0) return !1; + y = y.nextZ; + } + return !0; +} +function Zu(i, e) { + let t = i; + do { + const n = t.prev, s = t.next.next; + !rn(n, s) && fl(n, t, t.next, s) && Tn(n, s) && Tn(s, n) && (e.push(n.i, t.i, s.i), Mn(t), Mn(t.next), t = i = s), t = t.next; + } while (t !== i); + return zt(t); +} +function Ku(i, e, t, n, s, r) { + let a = i; + do { + let o = a.next.next; + for (; o !== a.prev; ) { + if (a.i !== o.i && ac(a, o)) { + let l = pl(a, o); + a = zt(a, a.next), l = zt(l, l.next), $n(a, e, t, n, s, r, 0), $n(l, e, t, n, s, r, 0); + return; + } + o = o.next; + } + a = a.next; + } while (a !== i); +} +function Qu(i, e, t, n) { + const s = []; + for (let r = 0, a = e.length; r < a; r++) { + const o = e[r] * n, l = r < a - 1 ? e[r + 1] * n : i.length, h = cl(i, o, l, n, !1); + h === h.next && (h.steiner = !0), s.push(rc(h)); + } + s.sort(Ju); + for (let r = 0; r < s.length; r++) + t = ec(s[r], t); + return t; +} +function Ju(i, e) { + let t = i.x - e.x; + if (t === 0 && (t = i.y - e.y, t === 0)) { + const n = (i.next.y - i.y) / (i.next.x - i.x), s = (e.next.y - e.y) / (e.next.x - e.x); + t = n - s; + } + return t; +} +function ec(i, e) { + const t = tc(i, e); + if (!t) + return e; + const n = pl(t, i); + return zt(n, n.next), zt(t, t.next); +} +function tc(i, e) { + let t = e; + const n = i.x, s = i.y; + let r = -1 / 0, a; + if (rn(i, t)) return t; + do { + if (rn(i, t.next)) return t.next; + if (s <= t.y && s >= t.next.y && t.next.y !== t.y) { + const c = t.x + (s - t.y) * (t.next.x - t.x) / (t.next.y - t.y); + if (c <= n && c > r && (r = c, a = t.x < t.next.x ? t : t.next, c === n)) + return a; + } + t = t.next; + } while (t !== e); + if (!a) return null; + const o = a, l = a.x, h = a.y; + let u = 1 / 0; + t = a; + do { + if (n >= t.x && t.x >= l && n !== t.x && dl(s < h ? n : r, s, l, h, s < h ? r : n, s, t.x, t.y)) { + const c = Math.abs(s - t.y) / (n - t.x); + Tn(t, i) && (c < u || c === u && (t.x > a.x || t.x === a.x && nc(a, t))) && (a = t, u = c); + } + t = t.next; + } while (t !== o); + return a; +} +function nc(i, e) { + return oe(i.prev, i, e.prev) < 0 && oe(e.next, i, i.next) < 0; +} +function ic(i, e, t, n) { + let s = i; + do + s.z === 0 && (s.z = vs(s.x, s.y, e, t, n)), s.prevZ = s.prev, s.nextZ = s.next, s = s.next; + while (s !== i); + s.prevZ.nextZ = null, s.prevZ = null, sc(s); +} +function sc(i) { + let e, t = 1; + do { + let n = i, s; + i = null; + let r = null; + for (e = 0; n; ) { + e++; + let a = n, o = 0; + for (let h = 0; h < t && (o++, a = a.nextZ, !!a); h++) + ; + let l = t; + for (; o > 0 || l > 0 && a; ) + o !== 0 && (l === 0 || !a || n.z <= a.z) ? (s = n, n = n.nextZ, o--) : (s = a, a = a.nextZ, l--), r ? r.nextZ = s : i = s, s.prevZ = r, r = s; + n = a; + } + r.nextZ = null, t *= 2; + } while (e > 1); + return i; +} +function vs(i, e, t, n, s) { + return i = (i - t) * s | 0, e = (e - n) * s | 0, i = (i | i << 8) & 16711935, i = (i | i << 4) & 252645135, i = (i | i << 2) & 858993459, i = (i | i << 1) & 1431655765, e = (e | e << 8) & 16711935, e = (e | e << 4) & 252645135, e = (e | e << 2) & 858993459, e = (e | e << 1) & 1431655765, i | e << 1; +} +function rc(i) { + let e = i, t = i; + do + (e.x < t.x || e.x === t.x && e.y < t.y) && (t = e), e = e.next; + while (e !== i); + return t; +} +function dl(i, e, t, n, s, r, a, o) { + return (s - a) * (e - o) >= (i - a) * (r - o) && (i - a) * (n - o) >= (t - a) * (e - o) && (t - a) * (r - o) >= (s - a) * (n - o); +} +function xn(i, e, t, n, s, r, a, o) { + return !(i === a && e === o) && dl(i, e, t, n, s, r, a, o); +} +function ac(i, e) { + return i.next.i !== e.i && i.prev.i !== e.i && !oc(i, e) && // doesn't intersect other edges + (Tn(i, e) && Tn(e, i) && lc(i, e) && // locally visible + (oe(i.prev, i, e.prev) || oe(i, e.prev, e)) || // does not create opposite-facing sectors + rn(i, e) && oe(i.prev, i, i.next) > 0 && oe(e.prev, e, e.next) > 0); +} +function oe(i, e, t) { + return (e.y - i.y) * (t.x - e.x) - (e.x - i.x) * (t.y - e.y); +} +function rn(i, e) { + return i.x === e.x && i.y === e.y; +} +function fl(i, e, t, n) { + const s = Zn(oe(i, e, t)), r = Zn(oe(i, e, n)), a = Zn(oe(t, n, i)), o = Zn(oe(t, n, e)); + return !!(s !== r && a !== o || s === 0 && jn(i, t, e) || r === 0 && jn(i, n, e) || a === 0 && jn(t, i, n) || o === 0 && jn(t, e, n)); +} +function jn(i, e, t) { + return e.x <= Math.max(i.x, t.x) && e.x >= Math.min(i.x, t.x) && e.y <= Math.max(i.y, t.y) && e.y >= Math.min(i.y, t.y); +} +function Zn(i) { + return i > 0 ? 1 : i < 0 ? -1 : 0; +} +function oc(i, e) { + let t = i; + do { + if (t.i !== i.i && t.next.i !== i.i && t.i !== e.i && t.next.i !== e.i && fl(t, t.next, i, e)) return !0; + t = t.next; + } while (t !== i); + return !1; +} +function Tn(i, e) { + return oe(i.prev, i, i.next) < 0 ? oe(i, e, i.next) >= 0 && oe(i, i.prev, e) >= 0 : oe(i, e, i.prev) < 0 || oe(i, i.next, e) < 0; +} +function lc(i, e) { + let t = i, n = !1; + const s = (i.x + e.x) / 2, r = (i.y + e.y) / 2; + do + t.y > r != t.next.y > r && t.next.y !== t.y && s < (t.next.x - t.x) * (r - t.y) / (t.next.y - t.y) + t.x && (n = !n), t = t.next; + while (t !== i); + return n; +} +function pl(i, e) { + const t = Cs(i.i, i.x, i.y), n = Cs(e.i, e.x, e.y), s = i.next, r = e.prev; + return i.next = e, e.prev = i, t.next = s, s.prev = t, n.next = t, t.prev = n, r.next = n, n.prev = r, n; +} +function qr(i, e, t, n) { + const s = Cs(i, e, t); + return n ? (s.next = n.next, s.prev = n, n.next.prev = s, n.next = s) : (s.prev = s, s.next = s), s; +} +function Mn(i) { + i.next.prev = i.prev, i.prev.next = i.next, i.prevZ && (i.prevZ.nextZ = i.nextZ), i.nextZ && (i.nextZ.prevZ = i.prevZ); +} +function Cs(i, e, t) { + return { + i, + // vertex index in coordinates array + x: e, + y: t, + // vertex coordinates + prev: null, + // previous and next vertex nodes in a polygon ring + next: null, + z: 0, + // z-order curve value + prevZ: null, + // previous and next nodes in z-order + nextZ: null, + steiner: !1 + // indicates whether this is a steiner point + }; +} +function hc(i, e, t, n) { + let s = 0; + for (let r = e, a = t - n; r < t; r += n) + s += (i[a] - i[r]) * (i[r + 1] + i[a + 1]), a = r; + return s; +} +const uc = Gr.default || Gr; +var _l = /* @__PURE__ */ ((i) => (i[i.NONE = 0] = "NONE", i[i.COLOR = 16384] = "COLOR", i[i.STENCIL = 1024] = "STENCIL", i[i.DEPTH = 256] = "DEPTH", i[i.COLOR_DEPTH = 16640] = "COLOR_DEPTH", i[i.COLOR_STENCIL = 17408] = "COLOR_STENCIL", i[i.DEPTH_STENCIL = 1280] = "DEPTH_STENCIL", i[i.ALL = 17664] = "ALL", i))(_l || {}); +class cc { + /** + * @param name - The function name that will be executed on the listeners added to this Runner. + */ + constructor(e) { + this.items = [], this._name = e; + } + /* jsdoc/check-param-names */ + /** + * Dispatch/Broadcast Runner to all listeners added to the queue. + * @param {...any} params - (optional) parameters to pass to each listener + */ + /* jsdoc/check-param-names */ + emit(e, t, n, s, r, a, o, l) { + const { name: h, items: u } = this; + for (let c = 0, d = u.length; c < d; c++) + u[c][h](e, t, n, s, r, a, o, l); + return this; + } + /** + * Add a listener to the Runner + * + * Runners do not need to have scope or functions passed to them. + * All that is required is to pass the listening object and ensure that it has contains a function that has the same name + * as the name provided to the Runner when it was created. + * + * Eg A listener passed to this Runner will require a 'complete' function. + * + * ```ts + * import { Runner } from 'pixi.js'; + * + * const complete = new Runner('complete'); + * ``` + * + * The scope used will be the object itself. + * @param {any} item - The object that will be listening. + */ + add(e) { + return e[this._name] && (this.remove(e), this.items.push(e)), this; + } + /** + * Remove a single listener from the dispatch queue. + * @param {any} item - The listener that you would like to remove. + */ + remove(e) { + const t = this.items.indexOf(e); + return t !== -1 && this.items.splice(t, 1), this; + } + /** + * Check to see if the listener is already in the Runner + * @param {any} item - The listener that you would like to check. + */ + contains(e) { + return this.items.indexOf(e) !== -1; + } + /** Remove all listeners from the Runner */ + removeAll() { + return this.items.length = 0, this; + } + /** Remove all references, don't use after this. */ + destroy() { + this.removeAll(), this.items = null, this._name = null; + } + /** + * `true` if there are no this Runner contains no listeners + * @readonly + */ + get empty() { + return this.items.length === 0; + } + /** + * The name of the runner. + * @readonly + */ + get name() { + return this._name; + } +} +const dc = [ + "init", + "destroy", + "contextChange", + "resolutionChange", + "resetState", + "renderEnd", + "renderStart", + "render", + "update", + "postrender", + "prerender" +], ml = class gl extends xt { + /** + * Set up a system with a collection of SystemClasses and runners. + * Systems are attached dynamically to this class when added. + * @param config - the config for the system manager + */ + constructor(e) { + super(), this.uid = ue("renderer"), this.runners = /* @__PURE__ */ Object.create(null), this.renderPipes = /* @__PURE__ */ Object.create(null), this._initOptions = {}, this._systemsHash = /* @__PURE__ */ Object.create(null), this.type = e.type, this.name = e.name, this.config = e; + const t = [...dc, ...this.config.runners ?? []]; + this._addRunners(...t), this._unsafeEvalCheck(); + } + /** + * Initialize the renderer. + * @param options - The options to use to create the renderer. + */ + async init(e = {}) { + const t = e.skipExtensionImports === !0 ? !0 : e.manageImports === !1; + await Wu(t), this._addSystems(this.config.systems), this._addPipes(this.config.renderPipes, this.config.renderPipeAdaptors); + for (const n in this._systemsHash) + e = { ...this._systemsHash[n].constructor.defaultOptions, ...e }; + e = { ...gl.defaultOptions, ...e }, this._roundPixels = e.roundPixels ? 1 : 0; + for (let n = 0; n < this.runners.init.items.length; n++) + await this.runners.init.items[n].init(e); + this._initOptions = e; + } + render(e, t) { + let n = e; + if (n instanceof Dt && (n = { container: n }, t && (W(he, "passing a second argument is deprecated, please use render options instead"), n.target = t.renderTexture)), n.target || (n.target = this.view.renderTarget), n.target === this.view.renderTarget && (this._lastObjectRendered = n.container, n.clearColor ?? (n.clearColor = this.background.colorRgba), n.clear ?? (n.clear = this.background.clearBeforeRender)), n.clearColor) { + const s = Array.isArray(n.clearColor) && n.clearColor.length === 4; + n.clearColor = s ? n.clearColor : pe.shared.setValue(n.clearColor).toArray(); + } + n.transform || (n.container.updateLocalTransform(), n.transform = n.container.localTransform), n.container.visible && (n.container.enableRenderGroup(), this.runners.prerender.emit(n), this.runners.renderStart.emit(n), this.runners.render.emit(n), this.runners.renderEnd.emit(n), this.runners.postrender.emit(n)); + } + /** + * Resizes the WebGL view to the specified width and height. + * @param desiredScreenWidth - The desired width of the screen. + * @param desiredScreenHeight - The desired height of the screen. + * @param resolution - The resolution / device pixel ratio of the renderer. + */ + resize(e, t, n) { + const s = this.view.resolution; + this.view.resize(e, t, n), this.emit("resize", this.view.screen.width, this.view.screen.height, this.view.resolution), n !== void 0 && n !== s && this.runners.resolutionChange.emit(n); + } + /** + * Clears the render target. + * @param options - The options to use when clearing the render target. + * @param options.target - The render target to clear. + * @param options.clearColor - The color to clear with. + * @param options.clear - The clear mode to use. + * @advanced + */ + clear(e = {}) { + const t = this; + e.target || (e.target = t.renderTarget.renderTarget), e.clearColor || (e.clearColor = this.background.colorRgba), e.clear ?? (e.clear = _l.ALL); + const { clear: n, clearColor: s, target: r } = e; + pe.shared.setValue(s ?? this.background.colorRgba), t.renderTarget.clear(r, n, pe.shared.toArray()); + } + /** The resolution / device pixel ratio of the renderer. */ + get resolution() { + return this.view.resolution; + } + set resolution(e) { + this.view.resolution = e, this.runners.resolutionChange.emit(e); + } + /** + * Same as view.width, actual number of pixels in the canvas by horizontal. + * @type {number} + * @readonly + * @default 800 + */ + get width() { + return this.view.texture.frame.width; + } + /** + * Same as view.height, actual number of pixels in the canvas by vertical. + * @default 600 + */ + get height() { + return this.view.texture.frame.height; + } + // NOTE: this was `view` in v7 + /** + * The canvas element that everything is drawn to. + * @type {environment.ICanvas} + */ + get canvas() { + return this.view.canvas; + } + /** + * the last object rendered by the renderer. Useful for other plugins like interaction managers + * @readonly + */ + get lastObjectRendered() { + return this._lastObjectRendered; + } + /** + * Flag if we are rendering to the screen vs renderTexture + * @readonly + * @default true + */ + get renderingToScreen() { + return this.renderTarget.renderingToScreen; + } + /** + * Measurements of the screen. (0, 0, screenWidth, screenHeight). + * + * Its safe to use as filterArea or hitArea for the whole stage. + */ + get screen() { + return this.view.screen; + } + /** + * Create a bunch of runners based of a collection of ids + * @param runnerIds - the runner ids to add + */ + _addRunners(...e) { + e.forEach((t) => { + this.runners[t] = new cc(t); + }); + } + _addSystems(e) { + let t; + for (t in e) { + const n = e[t]; + this._addSystem(n.value, n.name); + } + } + /** + * Add a new system to the renderer. + * @param ClassRef - Class reference + * @param name - Property name for system, if not specified + * will use a static `name` property on the class itself. This + * name will be assigned as s property on the Renderer so make + * sure it doesn't collide with properties on Renderer. + * @returns Return instance of renderer + */ + _addSystem(e, t) { + const n = new e(this); + if (this[t]) + throw new Error(`Whoops! The name "${t}" is already in use`); + this[t] = n, this._systemsHash[t] = n; + for (const s in this.runners) + this.runners[s].add(n); + return this; + } + _addPipes(e, t) { + const n = t.reduce((s, r) => (s[r.name] = r.value, s), {}); + e.forEach((s) => { + const r = s.value, a = s.name, o = n[a]; + this.renderPipes[a] = new r( + this, + o ? new o() : null + ), this.runners.destroy.add(this.renderPipes[a]); + }); + } + destroy(e = !1) { + this.runners.destroy.items.reverse(), this.runners.destroy.emit(e), Object.values(this.runners).forEach((t) => { + t.destroy(); + }), (e === !0 || typeof e == "object" && e.releaseGlobalResources) && Bn.release(), this._systemsHash = null, this.renderPipes = null; + } + /** + * Generate a texture from a container. + * @param options - options or container target to use when generating the texture + * @returns a texture + */ + generateTexture(e) { + return this.textureGenerator.generateTexture(e); + } + /** + * Whether the renderer will round coordinates to whole pixels when rendering. + * Can be overridden on a per scene item basis. + */ + get roundPixels() { + return !!this._roundPixels; + } + /** + * Overridable function by `pixi.js/unsafe-eval` to silence + * throwing an error if platform doesn't support unsafe-evals. + * @private + * @ignore + */ + _unsafeEvalCheck() { + if (!Yu()) + throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support."); + } + /** + * Resets the rendering state of the renderer. + * This is useful when you want to use the WebGL context directly and need to ensure PixiJS's internal state + * stays synchronized. When modifying the WebGL context state externally, calling this method before the next Pixi + * render will reset all internal caches and ensure it executes correctly. + * + * This is particularly useful when combining PixiJS with other rendering engines like Three.js: + * ```js + * // Reset Three.js state + * threeRenderer.resetState(); + * + * // Render a Three.js scene + * threeRenderer.render(threeScene, threeCamera); + * + * // Reset PixiJS state since Three.js modified the WebGL context + * pixiRenderer.resetState(); + * + * // Now render Pixi content + * pixiRenderer.render(pixiScene); + * ``` + * @advanced + */ + resetState() { + this.runners.resetState.emit(); + } +}; +ml.defaultOptions = { + /** + * Default resolution / device pixel ratio of the renderer. + * @default 1 + */ + resolution: 1, + /** + * Should the `failIfMajorPerformanceCaveat` flag be enabled as a context option used in the `isWebGLSupported` + * function. If set to true, a WebGL renderer can fail to be created if the browser thinks there could be + * performance issues when using WebGL. + * + * In PixiJS v6 this has changed from true to false by default, to allow WebGL to work in as many + * scenarios as possible. However, some users may have a poor experience, for example, if a user has a gpu or + * driver version blacklisted by the + * browser. + * + * If your application requires high performance rendering, you may wish to set this to false. + * We recommend one of two options if you decide to set this flag to false: + * + * 1: Use the Canvas renderer as a fallback in case high performance WebGL is + * not supported. + * + * 2: Call `isWebGLSupported` (which if found in the utils package) in your code before attempting to create a + * PixiJS renderer, and show an error message to the user if the function returns false, explaining that their + * device & browser combination does not support high performance WebGL. + * This is a much better strategy than trying to create a PixiJS renderer and finding it then fails. + * @default false + */ + failIfMajorPerformanceCaveat: !1, + /** + * Should round pixels be forced when rendering? + * @default false + */ + roundPixels: !1 +}; +let yl = ml, Kn; +function fc(i) { + return Kn !== void 0 || (Kn = (() => { + var t; + const e = { + stencil: !0, + failIfMajorPerformanceCaveat: i ?? yl.defaultOptions.failIfMajorPerformanceCaveat + }; + try { + if (!Ge.get().getWebGLRenderingContext()) + return !1; + let s = Ge.get().createCanvas().getContext("webgl", e); + const r = !!((t = s == null ? void 0 : s.getContextAttributes()) != null && t.stencil); + if (s) { + const a = s.getExtension("WEBGL_lose_context"); + a && a.loseContext(); + } + return s = null, r; + } catch { + return !1; + } + })()), Kn; +} +let Qn; +async function pc(i = {}) { + return Qn !== void 0 || (Qn = await (async () => { + const e = Ge.get().getNavigator().gpu; + if (!e) + return !1; + try { + return await (await e.requestAdapter(i)).requestDevice(), !0; + } catch { + return !1; + } + })()), Qn; +} +const Ur = ["webgl", "webgpu", "canvas"]; +async function _c(i) { + let e = []; + i.preference ? (e.push(i.preference), Ur.forEach((r) => { + r !== i.preference && e.push(r); + })) : e = Ur.slice(); + let t, n = {}; + for (let r = 0; r < e.length; r++) { + const a = e[r]; + if (a === "webgpu" && await pc()) { + const { WebGPURenderer: o } = await import("./WebGPURenderer-CLzW5yah.js"); + t = o, n = { ...i, ...i.webgpu }; + break; + } else if (a === "webgl" && fc( + i.failIfMajorPerformanceCaveat ?? yl.defaultOptions.failIfMajorPerformanceCaveat + )) { + const { WebGLRenderer: o } = await import("./WebGLRenderer-CcnJ7_Ew.js"); + t = o, n = { ...i, ...i.webgl }; + break; + } else if (a === "canvas") + throw n = { ...i }, new Error("CanvasRenderer is not yet implemented"); + } + if (delete n.webgpu, delete n.webgl, !t) + throw new Error("No available renderer for the current environment"); + const s = new t(); + return await s.init(n), s; +} +const bl = "8.13.2"; +class xl { + static init() { + var e; + (e = globalThis.__PIXI_APP_INIT__) == null || e.call(globalThis, this, bl); + } + static destroy() { + } +} +xl.extension = Q.Application; +class mc { + constructor(e) { + this._renderer = e; + } + init() { + var e; + (e = globalThis.__PIXI_RENDERER_INIT__) == null || e.call(globalThis, this._renderer, bl); + } + destroy() { + this._renderer = null; + } +} +mc.extension = { + type: [ + Q.WebGLSystem, + Q.WebGPUSystem + ], + name: "initHook", + priority: -10 +}; +const wl = class Ss { + constructor(...e) { + this.stage = new Dt(), e[0] !== void 0 && W(he, "Application constructor options are deprecated, please use Application.init() instead."); + } + /** + * Initializes the PixiJS application with the specified options. + * + * This method must be called after creating a new Application instance. + * @param options - Configuration options for the application and renderer + * @returns A promise that resolves when initialization is complete + * @example + * ```js + * const app = new Application(); + * + * // Initialize with custom options + * await app.init({ + * width: 800, + * height: 600, + * backgroundColor: 0x1099bb, + * preference: 'webgl', // or 'webgpu' + * }); + * ``` + */ + async init(e) { + e = { ...e }, this.renderer = await _c(e), Ss._plugins.forEach((t) => { + t.init.call(this, e); + }); + } + /** + * Renders the current stage to the screen. + * + * When using the default setup with {@link TickerPlugin} (enabled by default), you typically don't need to call + * this method directly as rendering is handled automatically. + * + * Only use this method if you've disabled the {@link TickerPlugin} or need custom + * render timing control. + * @example + * ```js + * // Example 1: Default setup (TickerPlugin handles rendering) + * const app = new Application(); + * await app.init(); + * // No need to call render() - TickerPlugin handles it + * + * // Example 2: Custom rendering loop (if TickerPlugin is disabled) + * const app = new Application(); + * await app.init({ autoStart: false }); // Disable automatic rendering + * + * function animate() { + * app.render(); + * requestAnimationFrame(animate); + * } + * animate(); + * ``` + */ + render() { + this.renderer.render({ container: this.stage }); + } + /** + * Reference to the renderer's canvas element. This is the HTML element + * that displays your application's graphics. + * @readonly + * @type {HTMLCanvasElement} + * @example + * ```js + * // Create a new application + * const app = new Application(); + * // Initialize the application + * await app.init({...}); + * // Add canvas to the page + * document.body.appendChild(app.canvas); + * + * // Access the canvas directly + * console.log(app.canvas); // HTMLCanvasElement + * ``` + */ + get canvas() { + return this.renderer.canvas; + } + /** + * Reference to the renderer's canvas element. + * @type {HTMLCanvasElement} + * @deprecated since 8.0.0 + * @see {@link Application#canvas} + */ + get view() { + return W(he, "Application.view is deprecated, please use Application.canvas instead."), this.renderer.canvas; + } + /** + * Reference to the renderer's screen rectangle. This represents the visible area of your application. + * + * It's commonly used for: + * - Setting filter areas for full-screen effects + * - Defining hit areas for screen-wide interaction + * - Determining the visible bounds of your application + * @readonly + * @example + * ```js + * // Use as filter area for a full-screen effect + * const blurFilter = new BlurFilter(); + * sprite.filterArea = app.screen; + * + * // Use as hit area for screen-wide interaction + * const screenSprite = new Sprite(); + * screenSprite.hitArea = app.screen; + * + * // Get screen dimensions + * console.log(app.screen.width, app.screen.height); + * ``` + * @see {@link Rectangle} For all available properties and methods + */ + get screen() { + return this.renderer.screen; + } + /** + * Destroys the application and all of its resources. + * + * This method should be called when you want to completely + * clean up the application and free all associated memory. + * @param rendererDestroyOptions - Options for destroying the renderer: + * - `false` or `undefined`: Preserves the canvas element (default) + * - `true`: Removes the canvas element + * - `{ removeView: boolean }`: Object with removeView property to control canvas removal + * @param options - Options for destroying the application: + * - `false` or `undefined`: Basic cleanup (default) + * - `true`: Complete cleanup including children + * - Detailed options object: + * - `children`: Remove children + * - `texture`: Destroy textures + * - `textureSource`: Destroy texture sources + * - `context`: Destroy WebGL context + * @example + * ```js + * // Basic cleanup + * app.destroy(); + * + * // Remove canvas and do complete cleanup + * app.destroy(true, true); + * + * // Remove canvas with explicit options + * app.destroy({ removeView: true }, true); + * + * // Detailed cleanup with specific options + * app.destroy( + * { removeView: true }, + * { + * children: true, + * texture: true, + * textureSource: true, + * context: true + * } + * ); + * ``` + * > [!WARNING] After calling destroy, the application instance should no longer be used. + * > All properties will be null and further operations will throw errors. + */ + destroy(e = !1, t = !1) { + const n = Ss._plugins.slice(0); + n.reverse(), n.forEach((s) => { + s.destroy.call(this); + }), this.stage.destroy(t), this.stage = null, this.renderer.destroy(e), this.renderer = null; + } +}; +wl._plugins = []; +let vl = wl; +Qe.handleByList(Q.Application, vl._plugins); +Qe.add(xl); +/** + * tiny-lru + * + * @copyright 2025 Jason Mulligan + * @license BSD-3-Clause + * @version 11.4.5 + */ +class gc { + /** + * Creates a new LRU cache instance. + * Note: Constructor does not validate parameters. Use lru() factory function for parameter validation. + * + * @constructor + * @param {number} [max=0] - Maximum number of items to store. 0 means unlimited. + * @param {number} [ttl=0] - Time to live in milliseconds. 0 means no expiration. + * @param {boolean} [resetTtl=false] - Whether to reset TTL when accessing existing items via get(). + * @example + * const cache = new LRU(1000, 60000, true); // 1000 items, 1 minute TTL, reset on access + * @see {@link lru} For parameter validation + * @since 1.0.0 + */ + constructor(e = 0, t = 0, n = !1) { + this.first = null, this.items = /* @__PURE__ */ Object.create(null), this.last = null, this.max = e, this.resetTtl = n, this.size = 0, this.ttl = t; + } + /** + * Removes all items from the cache. + * + * @method clear + * @memberof LRU + * @returns {LRU} The LRU instance for method chaining. + * @example + * cache.clear(); + * console.log(cache.size); // 0 + * @since 1.0.0 + */ + clear() { + return this.first = null, this.items = /* @__PURE__ */ Object.create(null), this.last = null, this.size = 0, this; + } + /** + * Removes an item from the cache by key. + * + * @method delete + * @memberof LRU + * @param {string} key - The key of the item to delete. + * @returns {LRU} The LRU instance for method chaining. + * @example + * cache.set('key1', 'value1'); + * cache.delete('key1'); + * console.log(cache.has('key1')); // false + * @see {@link LRU#has} + * @see {@link LRU#clear} + * @since 1.0.0 + */ + delete(e) { + if (this.has(e)) { + const t = this.items[e]; + delete this.items[e], this.size--, t.prev !== null && (t.prev.next = t.next), t.next !== null && (t.next.prev = t.prev), this.first === t && (this.first = t.next), this.last === t && (this.last = t.prev); + } + return this; + } + /** + * Returns an array of [key, value] pairs for the specified keys. + * Order follows LRU order (least to most recently used). + * + * @method entries + * @memberof LRU + * @param {string[]} [keys=this.keys()] - Array of keys to get entries for. Defaults to all keys. + * @returns {Array>} Array of [key, value] pairs in LRU order. + * @example + * cache.set('a', 1).set('b', 2); + * console.log(cache.entries()); // [['a', 1], ['b', 2]] + * console.log(cache.entries(['a'])); // [['a', 1]] + * @see {@link LRU#keys} + * @see {@link LRU#values} + * @since 11.1.0 + */ + entries(e = this.keys()) { + return e.map((t) => [t, this.get(t)]); + } + /** + * Removes the least recently used item from the cache. + * + * @method evict + * @memberof LRU + * @param {boolean} [bypass=false] - Whether to force eviction even when cache is empty. + * @returns {LRU} The LRU instance for method chaining. + * @example + * cache.set('old', 'value').set('new', 'value'); + * cache.evict(); // Removes 'old' item + * @see {@link LRU#setWithEvicted} + * @since 1.0.0 + */ + evict(e = !1) { + if (e || this.size > 0) { + const t = this.first; + delete this.items[t.key], --this.size === 0 ? (this.first = null, this.last = null) : (this.first = t.next, this.first.prev = null); + } + return this; + } + /** + * Returns the expiration timestamp for a given key. + * + * @method expiresAt + * @memberof LRU + * @param {string} key - The key to check expiration for. + * @returns {number|undefined} The expiration timestamp in milliseconds, or undefined if key doesn't exist. + * @example + * const cache = new LRU(100, 5000); // 5 second TTL + * cache.set('key1', 'value1'); + * console.log(cache.expiresAt('key1')); // timestamp 5 seconds from now + * @see {@link LRU#get} + * @see {@link LRU#has} + * @since 1.0.0 + */ + expiresAt(e) { + let t; + return this.has(e) && (t = this.items[e].expiry), t; + } + /** + * Retrieves a value from the cache by key. Updates the item's position to most recently used. + * + * @method get + * @memberof LRU + * @param {string} key - The key to retrieve. + * @returns {*} The value associated with the key, or undefined if not found or expired. + * @example + * cache.set('key1', 'value1'); + * console.log(cache.get('key1')); // 'value1' + * console.log(cache.get('nonexistent')); // undefined + * @see {@link LRU#set} + * @see {@link LRU#has} + * @since 1.0.0 + */ + get(e) { + const t = this.items[e]; + if (t !== void 0) { + if (this.ttl > 0 && t.expiry <= Date.now()) { + this.delete(e); + return; + } + return this.moveToEnd(t), t.value; + } + } + /** + * Checks if a key exists in the cache. + * + * @method has + * @memberof LRU + * @param {string} key - The key to check for. + * @returns {boolean} True if the key exists, false otherwise. + * @example + * cache.set('key1', 'value1'); + * console.log(cache.has('key1')); // true + * console.log(cache.has('nonexistent')); // false + * @see {@link LRU#get} + * @see {@link LRU#delete} + * @since 9.0.0 + */ + has(e) { + return e in this.items; + } + /** + * Efficiently moves an item to the end of the LRU list (most recently used position). + * This is an internal optimization method that avoids the overhead of the full set() operation + * when only LRU position needs to be updated. + * + * @method moveToEnd + * @memberof LRU + * @param {Object} item - The cache item with prev/next pointers to reposition. + * @private + * @since 11.3.5 + */ + moveToEnd(e) { + this.last !== e && (e.prev !== null && (e.prev.next = e.next), e.next !== null && (e.next.prev = e.prev), this.first === e && (this.first = e.next), e.prev = this.last, e.next = null, this.last !== null && (this.last.next = e), this.last = e, this.first === null && (this.first = e)); + } + /** + * Returns an array of all keys in the cache, ordered from least to most recently used. + * + * @method keys + * @memberof LRU + * @returns {string[]} Array of keys in LRU order. + * @example + * cache.set('a', 1).set('b', 2); + * cache.get('a'); // Move 'a' to most recent + * console.log(cache.keys()); // ['b', 'a'] + * @see {@link LRU#values} + * @see {@link LRU#entries} + * @since 9.0.0 + */ + keys() { + const e = []; + let t = this.first; + for (; t !== null; ) + e.push(t.key), t = t.next; + return e; + } + /** + * Sets a value in the cache and returns any evicted item. + * + * @method setWithEvicted + * @memberof LRU + * @param {string} key - The key to set. + * @param {*} value - The value to store. + * @param {boolean} [resetTtl=this.resetTtl] - Whether to reset the TTL for this operation. + * @returns {Object|null} The evicted item (if any) with shape {key, value, expiry, prev, next}, or null. + * @example + * const cache = new LRU(2); + * cache.set('a', 1).set('b', 2); + * const evicted = cache.setWithEvicted('c', 3); // evicted = {key: 'a', value: 1, ...} + * @see {@link LRU#set} + * @see {@link LRU#evict} + * @since 11.3.0 + */ + setWithEvicted(e, t, n = this.resetTtl) { + let s = null; + if (this.has(e)) + this.set(e, t, !0, n); + else { + this.max > 0 && this.size === this.max && (s = { ...this.first }, this.evict(!0)); + let r = this.items[e] = { + expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl, + key: e, + prev: this.last, + next: null, + value: t + }; + ++this.size === 1 ? this.first = r : this.last.next = r, this.last = r; + } + return s; + } + /** + * Sets a value in the cache. Updates the item's position to most recently used. + * + * @method set + * @memberof LRU + * @param {string} key - The key to set. + * @param {*} value - The value to store. + * @param {boolean} [bypass=false] - Internal parameter for setWithEvicted method. + * @param {boolean} [resetTtl=this.resetTtl] - Whether to reset the TTL for this operation. + * @returns {LRU} The LRU instance for method chaining. + * @example + * cache.set('key1', 'value1') + * .set('key2', 'value2') + * .set('key3', 'value3'); + * @see {@link LRU#get} + * @see {@link LRU#setWithEvicted} + * @since 1.0.0 + */ + set(e, t, n = !1, s = this.resetTtl) { + let r = this.items[e]; + return n || r !== void 0 ? (r.value = t, n === !1 && s && (r.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl), this.moveToEnd(r)) : (this.max > 0 && this.size === this.max && this.evict(!0), r = this.items[e] = { + expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl, + key: e, + prev: this.last, + next: null, + value: t + }, ++this.size === 1 ? this.first = r : this.last.next = r, this.last = r), this; + } + /** + * Returns an array of all values in the cache for the specified keys. + * Order follows LRU order (least to most recently used). + * + * @method values + * @memberof LRU + * @param {string[]} [keys=this.keys()] - Array of keys to get values for. Defaults to all keys. + * @returns {Array<*>} Array of values corresponding to the keys in LRU order. + * @example + * cache.set('a', 1).set('b', 2); + * console.log(cache.values()); // [1, 2] + * console.log(cache.values(['a'])); // [1] + * @see {@link LRU#keys} + * @see {@link LRU#entries} + * @since 11.1.0 + */ + values(e = this.keys()) { + return e.map((t) => this.get(t)); + } +} +function yc(i = 1e3, e = 0, t = !1) { + if (isNaN(i) || i < 0) + throw new TypeError("Invalid max value"); + if (isNaN(e) || e < 0) + throw new TypeError("Invalid ttl value"); + if (typeof t != "boolean") + throw new TypeError("Invalid resetTtl value"); + return new gc(i, e, t); +} +const bc = [ + "serif", + "sans-serif", + "monospace", + "cursive", + "fantasy", + "system-ui" +]; +function Cl(i) { + const e = typeof i.fontSize == "number" ? `${i.fontSize}px` : i.fontSize; + let t = i.fontFamily; + Array.isArray(i.fontFamily) || (t = i.fontFamily.split(",")); + for (let n = t.length - 1; n >= 0; n--) { + let s = t[n].trim(); + !/([\"\'])[^\'\"]+\1/.test(s) && !bc.includes(s) && (s = `"${s}"`), t[n] = s; + } + return `${i.fontStyle} ${i.fontVariant} ${i.fontWeight} ${e} ${t.join(",")}`; +} +const Wi = { + // TextMetrics requires getImageData readback for measuring fonts. + willReadFrequently: !0 +}, ct = class P { + /** + * Checking that we can use modern canvas 2D API. + * + * Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`. + * @see TextMetrics.experimentalLetterSpacing + * @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing + * @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441 + */ + static get experimentalLetterSpacingSupported() { + let e = P._experimentalLetterSpacingSupported; + if (e === void 0) { + const t = Ge.get().getCanvasRenderingContext2D().prototype; + e = P._experimentalLetterSpacingSupported = "letterSpacing" in t || "textLetterSpacing" in t; + } + return e; + } + /** + * @param text - the text that was measured + * @param style - the style that was measured + * @param width - the measured width of the text + * @param height - the measured height of the text + * @param lines - an array of the lines of text broken by new lines and wrapping if specified in style + * @param lineWidths - an array of the line widths for each line matched to `lines` + * @param lineHeight - the measured line height for this style + * @param maxLineWidth - the maximum line width for all measured lines + * @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont + */ + constructor(e, t, n, s, r, a, o, l, h) { + this.text = e, this.style = t, this.width = n, this.height = s, this.lines = r, this.lineWidths = a, this.lineHeight = o, this.maxLineWidth = l, this.fontProperties = h; + } + /** + * Measures the supplied string of text and returns a Rectangle. + * @param text - The text to measure. + * @param style - The text style to use for measuring + * @param canvas - optional specification of the canvas to use for measuring. + * @param wordWrap + * @returns Measured width and height of the text. + */ + static measureText(e = " ", t, n = P._canvas, s = t.wordWrap) { + var g; + const r = `${e}-${t.styleKey}-wordWrap-${s}`; + if (P._measurementCache.has(r)) + return P._measurementCache.get(r); + const a = Cl(t), o = P.measureFont(a); + o.fontSize === 0 && (o.fontSize = t.fontSize, o.ascent = t.fontSize); + const l = P.__context; + l.font = a; + const u = (s ? P._wordWrap(e, t, n) : e).split(/(?:\r\n|\r|\n)/), c = new Array(u.length); + let d = 0; + for (let p = 0; p < u.length; p++) { + const y = P._measureText(u[p], t.letterSpacing, l); + c[p] = y, d = Math.max(d, y); + } + const f = ((g = t._stroke) == null ? void 0 : g.width) || 0; + let _ = d + f; + t.dropShadow && (_ += t.dropShadow.distance); + const b = t.lineHeight || o.fontSize; + let m = Math.max(b, o.fontSize + f) + (u.length - 1) * (b + t.leading); + t.dropShadow && (m += t.dropShadow.distance); + const x = new P( + e, + t, + _, + m, + u, + c, + b + t.leading, + d, + o + ); + return P._measurementCache.set(r, x), x; + } + static _measureText(e, t, n) { + let s = !1; + P.experimentalLetterSpacingSupported && (P.experimentalLetterSpacing ? (n.letterSpacing = `${t}px`, n.textLetterSpacing = `${t}px`, s = !0) : (n.letterSpacing = "0px", n.textLetterSpacing = "0px")); + const r = n.measureText(e); + let a = r.width; + const o = -r.actualBoundingBoxLeft; + let h = r.actualBoundingBoxRight - o; + if (a > 0) + if (s) + a -= t, h -= t; + else { + const u = (P.graphemeSegmenter(e).length - 1) * t; + a += u, h += u; + } + return Math.max(a, h); + } + /** + * Applies newlines to a string to have it optimally fit into the horizontal + * bounds set by the Text object's wordWrapWidth property. + * @param text - String to apply word wrapping to + * @param style - the style to use when wrapping + * @param canvas - optional specification of the canvas to use for measuring. + * @returns New string with new lines applied where required + */ + static _wordWrap(e, t, n = P._canvas) { + const s = n.getContext("2d", Wi); + let r = 0, a = "", o = ""; + const l = /* @__PURE__ */ Object.create(null), { letterSpacing: h, whiteSpace: u } = t, c = P._collapseSpaces(u), d = P._collapseNewlines(u); + let f = !c; + const _ = t.wordWrapWidth + h, b = P._tokenize(e); + for (let m = 0; m < b.length; m++) { + let x = b[m]; + if (P._isNewline(x)) { + if (!d) { + o += P._addLine(a), f = !c, a = "", r = 0; + continue; + } + x = " "; + } + if (c) { + const p = P.isBreakingSpace(x), y = P.isBreakingSpace(a[a.length - 1]); + if (p && y) + continue; + } + const g = P._getFromCache(x, h, l, s); + if (g > _) + if (a !== "" && (o += P._addLine(a), a = "", r = 0), P.canBreakWords(x, t.breakWords)) { + const p = P.wordWrapSplit(x); + for (let y = 0; y < p.length; y++) { + let C = p[y], w = C, v = 1; + for (; p[y + v]; ) { + const S = p[y + v]; + if (!P.canBreakChars(w, S, x, y, t.breakWords)) + C += S; + else + break; + w = S, v++; + } + y += v - 1; + const D = P._getFromCache(C, h, l, s); + D + r > _ && (o += P._addLine(a), f = !1, a = "", r = 0), a += C, r += D; + } + } else { + a.length > 0 && (o += P._addLine(a), a = "", r = 0); + const p = m === b.length - 1; + o += P._addLine(x, !p), f = !1, a = "", r = 0; + } + else + g + r > _ && (f = !1, o += P._addLine(a), a = "", r = 0), (a.length > 0 || !P.isBreakingSpace(x) || f) && (a += x, r += g); + } + return o += P._addLine(a, !1), o; + } + /** + * Convenience function for logging each line added during the wordWrap method. + * @param line - The line of text to add + * @param newLine - Add new line character to end + * @returns A formatted line + */ + static _addLine(e, t = !0) { + return e = P._trimRight(e), e = t ? `${e} +` : e, e; + } + /** + * Gets & sets the widths of calculated characters in a cache object + * @param key - The key + * @param letterSpacing - The letter spacing + * @param cache - The cache + * @param context - The canvas context + * @returns The from cache. + */ + static _getFromCache(e, t, n, s) { + let r = n[e]; + return typeof r != "number" && (r = P._measureText(e, t, s) + t, n[e] = r), r; + } + /** + * Determines whether we should collapse breaking spaces. + * @param whiteSpace - The TextStyle property whiteSpace + * @returns Should collapse + */ + static _collapseSpaces(e) { + return e === "normal" || e === "pre-line"; + } + /** + * Determines whether we should collapse newLine chars. + * @param whiteSpace - The white space + * @returns should collapse + */ + static _collapseNewlines(e) { + return e === "normal"; + } + /** + * Trims breaking whitespaces from string. + * @param text - The text + * @returns Trimmed string + */ + static _trimRight(e) { + if (typeof e != "string") + return ""; + for (let t = e.length - 1; t >= 0; t--) { + const n = e[t]; + if (!P.isBreakingSpace(n)) + break; + e = e.slice(0, -1); + } + return e; + } + /** + * Determines if char is a newline. + * @param char - The character + * @returns True if newline, False otherwise. + */ + static _isNewline(e) { + return typeof e != "string" ? !1 : P._newlines.includes(e.charCodeAt(0)); + } + /** + * Determines if char is a breaking whitespace. + * + * It allows one to determine whether char should be a breaking whitespace + * For example certain characters in CJK langs or numbers. + * It must return a boolean. + * @param char - The character + * @param [_nextChar] - The next character + * @returns True if whitespace, False otherwise. + */ + static isBreakingSpace(e, t) { + return typeof e != "string" ? !1 : P._breakingSpaces.includes(e.charCodeAt(0)); + } + /** + * Splits a string into words, breaking-spaces and newLine characters + * @param text - The text + * @returns A tokenized array + */ + static _tokenize(e) { + const t = []; + let n = ""; + if (typeof e != "string") + return t; + for (let s = 0; s < e.length; s++) { + const r = e[s], a = e[s + 1]; + if (P.isBreakingSpace(r, a) || P._isNewline(r)) { + n !== "" && (t.push(n), n = ""), r === "\r" && a === ` +` ? (t.push(`\r +`), s++) : t.push(r); + continue; + } + n += r; + } + return n !== "" && t.push(n), t; + } + /** + * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior. + * + * It allows one to customise which words should break + * Examples are if the token is CJK or numbers. + * It must return a boolean. + * @param _token - The token + * @param breakWords - The style attr break words + * @returns Whether to break word or not + */ + static canBreakWords(e, t) { + return t; + } + /** + * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior. + * + * It allows one to determine whether a pair of characters + * should be broken by newlines + * For example certain characters in CJK langs or numbers. + * It must return a boolean. + * @param _char - The character + * @param _nextChar - The next character + * @param _token - The token/word the characters are from + * @param _index - The index in the token of the char + * @param _breakWords - The style attr break words + * @returns whether to break word or not + */ + static canBreakChars(e, t, n, s, r) { + return !0; + } + /** + * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior. + * + * It is called when a token (usually a word) has to be split into separate pieces + * in order to determine the point to break a word. + * It must return an array of characters. + * @param token - The token to split + * @returns The characters of the token + * @see CanvasTextMetrics.graphemeSegmenter + */ + static wordWrapSplit(e) { + return P.graphemeSegmenter(e); + } + /** + * Calculates the ascent, descent and fontSize of a given font-style + * @param font - String representing the style of the font + * @returns Font properties object + */ + static measureFont(e) { + if (P._fonts[e]) + return P._fonts[e]; + const t = P._context; + t.font = e; + const n = t.measureText(P.METRICS_STRING + P.BASELINE_SYMBOL), s = { + ascent: n.actualBoundingBoxAscent, + descent: n.actualBoundingBoxDescent, + fontSize: n.actualBoundingBoxAscent + n.actualBoundingBoxDescent + }; + return P._fonts[e] = s, s; + } + /** + * Clear font metrics in metrics cache. + * @param {string} [font] - font name. If font name not set then clear cache for all fonts. + */ + static clearMetrics(e = "") { + e ? delete P._fonts[e] : P._fonts = {}; + } + /** + * Cached canvas element for measuring text + * TODO: this should be private, but isn't because of backward compat, will fix later. + * @ignore + */ + static get _canvas() { + if (!P.__canvas) { + let e; + try { + const t = new OffscreenCanvas(0, 0), n = t.getContext("2d", Wi); + if (n != null && n.measureText) + return P.__canvas = t, t; + e = Ge.get().createCanvas(); + } catch { + e = Ge.get().createCanvas(); + } + e.width = e.height = 10, P.__canvas = e; + } + return P.__canvas; + } + /** + * TODO: this should be private, but isn't because of backward compat, will fix later. + * @ignore + */ + static get _context() { + return P.__context || (P.__context = P._canvas.getContext("2d", Wi)), P.__context; + } +}; +ct.METRICS_STRING = "|ÉqÅ"; +ct.BASELINE_SYMBOL = "M"; +ct.BASELINE_MULTIPLIER = 1.4; +ct.HEIGHT_MULTIPLIER = 2; +ct.graphemeSegmenter = (() => { + if (typeof (Intl == null ? void 0 : Intl.Segmenter) == "function") { + const i = new Intl.Segmenter(); + return (e) => { + const t = i.segment(e), n = []; + let s = 0; + for (const r of t) + n[s++] = r.segment; + return n; + }; + } + return (i) => [...i]; +})(); +ct.experimentalLetterSpacing = !1; +ct._fonts = {}; +ct._newlines = [ + 10, + // line feed + 13 + // carriage return +]; +ct._breakingSpaces = [ + 9, + // character tabulation + 32, + // space + 8192, + // en quad + 8193, + // em quad + 8194, + // en space + 8195, + // em space + 8196, + // three-per-em space + 8197, + // four-per-em space + 8198, + // six-per-em space + 8200, + // punctuation space + 8201, + // thin space + 8202, + // hair space + 8287, + // medium mathematical space + 12288 + // ideographic space +]; +ct._measurementCache = yc(1e3); +let Zt = ct; +const Hr = [{ offset: 0, color: "white" }, { offset: 1, color: "black" }], js = class ks { + constructor(...e) { + this.uid = ue("fillGradient"), this._tick = 0, this.type = "linear", this.colorStops = []; + let t = xc(e); + t = { ...t.type === "radial" ? ks.defaultRadialOptions : ks.defaultLinearOptions, ...Do(t) }, this._textureSize = t.textureSize, this._wrapMode = t.wrapMode, t.type === "radial" ? (this.center = t.center, this.outerCenter = t.outerCenter ?? this.center, this.innerRadius = t.innerRadius, this.outerRadius = t.outerRadius, this.scale = t.scale, this.rotation = t.rotation) : (this.start = t.start, this.end = t.end), this.textureSpace = t.textureSpace, this.type = t.type, t.colorStops.forEach((s) => { + this.addColorStop(s.offset, s.color); + }); + } + /** + * Adds a color stop to the gradient + * @param offset - Position of the stop (0-1) + * @param color - Color of the stop + * @returns This gradient instance for chaining + */ + addColorStop(e, t) { + return this.colorStops.push({ offset: e, color: pe.shared.setValue(t).toHexa() }), this; + } + /** + * Builds the internal texture and transform for the gradient. + * Called automatically when the gradient is first used. + * @internal + */ + buildLinearGradient() { + if (this.texture) + return; + let { x: e, y: t } = this.start, { x: n, y: s } = this.end, r = n - e, a = s - t; + const o = r < 0 || a < 0; + if (this._wrapMode === "clamp-to-edge") { + if (r < 0) { + const m = e; + e = n, n = m, r *= -1; + } + if (a < 0) { + const m = t; + t = s, s = m, a *= -1; + } + } + const l = this.colorStops.length ? this.colorStops : Hr, h = this._textureSize, { canvas: u, context: c } = Wr(h, 1), d = o ? c.createLinearGradient(this._textureSize, 0, 0, 0) : c.createLinearGradient(0, 0, this._textureSize, 0); + Vr(d, l), c.fillStyle = d, c.fillRect(0, 0, h, 1), this.texture = new K({ + source: new mi({ + resource: u, + addressMode: this._wrapMode + }) + }); + const f = Math.sqrt(r * r + a * a), _ = Math.atan2(a, r), b = new H(); + b.scale(f / h, 1), b.rotate(_), b.translate(e, t), this.textureSpace === "local" && b.scale(h, h), this.transform = b; + } + /** + * Builds the internal texture and transform for the gradient. + * Called automatically when the gradient is first used. + * @internal + */ + buildGradient() { + this.texture || this._tick++, this.type === "linear" ? this.buildLinearGradient() : this.buildRadialGradient(); + } + /** + * Builds the internal texture and transform for the radial gradient. + * Called automatically when the gradient is first used. + * @internal + */ + buildRadialGradient() { + if (this.texture) + return; + const e = this.colorStops.length ? this.colorStops : Hr, t = this._textureSize, { canvas: n, context: s } = Wr(t, t), { x: r, y: a } = this.center, { x: o, y: l } = this.outerCenter, h = this.innerRadius, u = this.outerRadius, c = o - u, d = l - u, f = t / (u * 2), _ = (r - c) * f, b = (a - d) * f, m = s.createRadialGradient( + _, + b, + h * f, + (o - c) * f, + (l - d) * f, + u * f + ); + Vr(m, e), s.fillStyle = e[e.length - 1].color, s.fillRect(0, 0, t, t), s.fillStyle = m, s.translate(_, b), s.rotate(this.rotation), s.scale(1, this.scale), s.translate(-_, -b), s.fillRect(0, 0, t, t), this.texture = new K({ + source: new mi({ + resource: n, + addressMode: this._wrapMode + }) + }); + const x = new H(); + x.scale(1 / f, 1 / f), x.translate(c, d), this.textureSpace === "local" && x.scale(t, t), this.transform = x; + } + /** Destroys the gradient, releasing resources. This will also destroy the internal texture. */ + destroy() { + var e; + (e = this.texture) == null || e.destroy(!0), this.texture = null, this.transform = null, this.colorStops = [], this.start = null, this.end = null, this.center = null, this.outerCenter = null; + } + /** + * Returns a unique key for this gradient instance. + * This key is used for caching and texture management. + * @returns {string} Unique key for the gradient + */ + get styleKey() { + return `fill-gradient-${this.uid}-${this._tick}`; + } +}; +js.defaultLinearOptions = { + start: { x: 0, y: 0 }, + end: { x: 0, y: 1 }, + colorStops: [], + textureSpace: "local", + type: "linear", + textureSize: 256, + wrapMode: "clamp-to-edge" +}; +js.defaultRadialOptions = { + center: { x: 0.5, y: 0.5 }, + innerRadius: 0, + outerRadius: 0.5, + colorStops: [], + scale: 1, + textureSpace: "local", + type: "radial", + textureSize: 256, + wrapMode: "clamp-to-edge" +}; +let Et = js; +function Vr(i, e) { + for (let t = 0; t < e.length; t++) { + const n = e[t]; + i.addColorStop(n.offset, n.color); + } +} +function Wr(i, e) { + const t = Ge.get().createCanvas(i, e), n = t.getContext("2d"); + return { canvas: t, context: n }; +} +function xc(i) { + let e = i[0] ?? {}; + return (typeof e == "number" || i[1]) && (W("8.5.2", "use options object instead"), e = { + type: "linear", + start: { x: i[0], y: i[1] }, + end: { x: i[2], y: i[3] }, + textureSpace: i[4], + textureSize: i[5] ?? Et.defaultLinearOptions.textureSize + }), e; +} +const Yr = { + repeat: { + addressModeU: "repeat", + addressModeV: "repeat" + }, + "repeat-x": { + addressModeU: "repeat", + addressModeV: "clamp-to-edge" + }, + "repeat-y": { + addressModeU: "clamp-to-edge", + addressModeV: "repeat" + }, + "no-repeat": { + addressModeU: "clamp-to-edge", + addressModeV: "clamp-to-edge" + } +}; +class Ei { + constructor(e, t) { + this.uid = ue("fillPattern"), this._tick = 0, this.transform = new H(), this.texture = e, this.transform.scale( + 1 / e.frame.width, + 1 / e.frame.height + ), t && (e.source.style.addressModeU = Yr[t].addressModeU, e.source.style.addressModeV = Yr[t].addressModeV); + } + /** + * Sets the transform for the pattern + * @param transform - The transform matrix to apply to the pattern. + * If not provided, the pattern will use the default transform. + */ + setTransform(e) { + const t = this.texture; + this.transform.copyFrom(e), this.transform.invert(), this.transform.scale( + 1 / t.frame.width, + 1 / t.frame.height + ), this._tick++; + } + /** Internal texture used to render the gradient */ + get texture() { + return this._texture; + } + set texture(e) { + this._texture !== e && (this._texture = e, this._tick++); + } + /** + * Returns a unique key for this instance. + * This key is used for caching. + * @returns {string} Unique key for the instance + */ + get styleKey() { + return `fill-pattern-${this.uid}-${this._tick}`; + } + /** Destroys the fill pattern, releasing resources. This will also destroy the internal texture. */ + destroy() { + this.texture.destroy(!0), this.texture = null; + } +} +var wc = Cc, Yi = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }, vc = /([astvzqmhlc])([^astvzqmhlc]*)/ig; +function Cc(i) { + var e = []; + return i.replace(vc, function(t, n, s) { + var r = n.toLowerCase(); + for (s = kc(s), r == "m" && s.length > 2 && (e.push([n].concat(s.splice(0, 2))), r = "l", n = n == "m" ? "l" : "L"); ; ) { + if (s.length == Yi[r]) + return s.unshift(n), e.push(s); + if (s.length < Yi[r]) throw new Error("malformed path data"); + e.push([n].concat(s.splice(0, Yi[r]))); + } + }), e; +} +var Sc = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig; +function kc(i) { + var e = i.match(Sc); + return e ? e.map(Number) : []; +} +const Ac = /* @__PURE__ */ Co(wc); +function Dc(i, e) { + const t = Ac(i), n = []; + let s = null, r = 0, a = 0; + for (let o = 0; o < t.length; o++) { + const l = t[o], h = l[0], u = l; + switch (h) { + case "M": + r = u[1], a = u[2], e.moveTo(r, a); + break; + case "m": + r += u[1], a += u[2], e.moveTo(r, a); + break; + case "H": + r = u[1], e.lineTo(r, a); + break; + case "h": + r += u[1], e.lineTo(r, a); + break; + case "V": + a = u[1], e.lineTo(r, a); + break; + case "v": + a += u[1], e.lineTo(r, a); + break; + case "L": + r = u[1], a = u[2], e.lineTo(r, a); + break; + case "l": + r += u[1], a += u[2], e.lineTo(r, a); + break; + case "C": + r = u[5], a = u[6], e.bezierCurveTo( + u[1], + u[2], + // First control point + u[3], + u[4], + // Second control point + r, + a + // End point + ); + break; + case "c": + e.bezierCurveTo( + r + u[1], + a + u[2], + // First control point + r + u[3], + a + u[4], + // Second control point + r + u[5], + a + u[6] + // End point + ), r += u[5], a += u[6]; + break; + case "S": + r = u[3], a = u[4], e.bezierCurveToShort( + u[1], + u[2], + // Control point + r, + a + // End point + ); + break; + case "s": + e.bezierCurveToShort( + r + u[1], + a + u[2], + // Control point + r + u[3], + a + u[4] + // End point + ), r += u[3], a += u[4]; + break; + case "Q": + r = u[3], a = u[4], e.quadraticCurveTo( + u[1], + u[2], + // Control point + r, + a + // End point + ); + break; + case "q": + e.quadraticCurveTo( + r + u[1], + a + u[2], + // Control point + r + u[3], + a + u[4] + // End point + ), r += u[3], a += u[4]; + break; + case "T": + r = u[1], a = u[2], e.quadraticCurveToShort( + r, + a + // End point + ); + break; + case "t": + r += u[1], a += u[2], e.quadraticCurveToShort( + r, + a + // End point + ); + break; + case "A": + r = u[6], a = u[7], e.arcToSvg( + u[1], + // rx + u[2], + // ry + u[3], + // x-axis-rotation + u[4], + // large-arc-flag + u[5], + // sweep-flag + r, + a + // End point + ); + break; + case "a": + r += u[6], a += u[7], e.arcToSvg( + u[1], + // rx + u[2], + // ry + u[3], + // x-axis-rotation + u[4], + // large-arc-flag + u[5], + // sweep-flag + r, + a + // End point + ); + break; + case "Z": + case "z": + e.closePath(), n.length > 0 && (s = n.pop(), s ? (r = s.startX, a = s.startY) : (r = 0, a = 0)), s = null; + break; + default: + $e(`Unknown SVG path command: ${h}`); + } + h !== "Z" && h !== "z" && s === null && (s = { startX: r, startY: a }, n.push(s)); + } + return e; +} +class Zs { + /** + * @param x - The X coordinate of the center of this circle + * @param y - The Y coordinate of the center of this circle + * @param radius - The radius of the circle + */ + constructor(e = 0, t = 0, n = 0) { + this.type = "circle", this.x = e, this.y = t, this.radius = n; + } + /** + * Creates a clone of this Circle instance. + * @example + * ```ts + * // Basic circle cloning + * const original = new Circle(100, 100, 50); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.radius = 75; + * + * // Verify independence + * console.log(original.radius); // 50 + * console.log(modified.radius); // 75 + * ``` + * @returns A copy of the Circle + * @see {@link Circle.copyFrom} For copying into existing circle + * @see {@link Circle.copyTo} For copying to another circle + */ + clone() { + return new Zs(this.x, this.y, this.radius); + } + /** + * Checks whether the x and y coordinates given are contained within this circle. + * + * Uses the distance formula to determine if a point is inside the circle's radius. + * + * Commonly used for hit testing in PixiJS events and graphics. + * @example + * ```ts + * // Basic containment check + * const circle = new Circle(100, 100, 50); + * const isInside = circle.contains(120, 120); + * + * // Check mouse position + * const circle = new Circle(0, 0, 100); + * container.hitArea = circle; + * container.on('pointermove', (e) => { + * // only called if pointer is within circle + * }); + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @returns Whether the x/y coordinates are within this Circle + * @see {@link Circle.strokeContains} For checking stroke intersection + * @see {@link Circle.getBounds} For getting bounding box + */ + contains(e, t) { + if (this.radius <= 0) + return !1; + const n = this.radius * this.radius; + let s = this.x - e, r = this.y - t; + return s *= s, r *= r, s + r <= n; + } + /** + * Checks whether the x and y coordinates given are contained within this circle including the stroke. + * @example + * ```ts + * // Basic stroke check + * const circle = new Circle(100, 100, 50); + * const isOnStroke = circle.strokeContains(150, 100, 4); // 4px line width + * + * // Check with different alignments + * const innerStroke = circle.strokeContains(150, 100, 4, 1); // Inside + * const centerStroke = circle.strokeContains(150, 100, 4, 0.5); // Centered + * const outerStroke = circle.strokeContains(150, 100, 4, 0); // Outside + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @param width - The width of the line to check + * @param alignment - The alignment of the stroke, 0.5 by default + * @returns Whether the x/y coordinates are within this Circle's stroke + * @see {@link Circle.contains} For checking fill containment + * @see {@link Circle.getBounds} For getting stroke bounds + */ + strokeContains(e, t, n, s = 0.5) { + if (this.radius === 0) + return !1; + const r = this.x - e, a = this.y - t, o = this.radius, l = (1 - s) * n, h = Math.sqrt(r * r + a * a); + return h <= o + l && h > o - (n - l); + } + /** + * Returns the framing rectangle of the circle as a Rectangle object. + * @example + * ```ts + * // Basic bounds calculation + * const circle = new Circle(100, 100, 50); + * const bounds = circle.getBounds(); + * // bounds: x=50, y=50, width=100, height=100 + * + * // Reuse existing rectangle + * const rect = new Rectangle(); + * circle.getBounds(rect); + * ``` + * @param out - Optional Rectangle object to store the result + * @returns The framing rectangle + * @see {@link Rectangle} For rectangle properties + * @see {@link Circle.contains} For point containment + */ + getBounds(e) { + return e || (e = new de()), e.x = this.x - this.radius, e.y = this.y - this.radius, e.width = this.radius * 2, e.height = this.radius * 2, e; + } + /** + * Copies another circle to this one. + * @example + * ```ts + * // Basic copying + * const source = new Circle(100, 100, 50); + * const target = new Circle(); + * target.copyFrom(source); + * ``` + * @param circle - The circle to copy from + * @returns Returns itself + * @see {@link Circle.copyTo} For copying to another circle + * @see {@link Circle.clone} For creating new circle copy + */ + copyFrom(e) { + return this.x = e.x, this.y = e.y, this.radius = e.radius, this; + } + /** + * Copies this circle to another one. + * @example + * ```ts + * // Basic copying + * const source = new Circle(100, 100, 50); + * const target = new Circle(); + * source.copyTo(target); + * ``` + * @param circle - The circle to copy to + * @returns Returns given parameter + * @see {@link Circle.copyFrom} For copying from another circle + * @see {@link Circle.clone} For creating new circle copy + */ + copyTo(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:Circle x=${this.x} y=${this.y} radius=${this.radius}]`; + } +} +class Ks { + /** + * @param x - The X coordinate of the center of this ellipse + * @param y - The Y coordinate of the center of this ellipse + * @param halfWidth - The half width of this ellipse + * @param halfHeight - The half height of this ellipse + */ + constructor(e = 0, t = 0, n = 0, s = 0) { + this.type = "ellipse", this.x = e, this.y = t, this.halfWidth = n, this.halfHeight = s; + } + /** + * Creates a clone of this Ellipse instance. + * @example + * ```ts + * // Basic cloning + * const original = new Ellipse(100, 100, 50, 25); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.halfWidth *= 2; + * modified.halfHeight *= 2; + * + * // Verify independence + * console.log(original.halfWidth); // 50 + * console.log(modified.halfWidth); // 100 + * ``` + * @returns A copy of the ellipse + * @see {@link Ellipse.copyFrom} For copying into existing ellipse + * @see {@link Ellipse.copyTo} For copying to another ellipse + */ + clone() { + return new Ks(this.x, this.y, this.halfWidth, this.halfHeight); + } + /** + * Checks whether the x and y coordinates given are contained within this ellipse. + * Uses normalized coordinates and the ellipse equation to determine containment. + * @example + * ```ts + * // Basic containment check + * const ellipse = new Ellipse(100, 100, 50, 25); + * const isInside = ellipse.contains(120, 110); + * ``` + * @remarks + * - Uses ellipse equation (x²/a² + y²/b² ≤ 1) + * - Returns false if dimensions are 0 or negative + * - Normalized to center (0,0) for calculation + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @returns Whether the x/y coords are within this ellipse + * @see {@link Ellipse.strokeContains} For checking stroke intersection + * @see {@link Ellipse.getBounds} For getting containing rectangle + */ + contains(e, t) { + if (this.halfWidth <= 0 || this.halfHeight <= 0) + return !1; + let n = (e - this.x) / this.halfWidth, s = (t - this.y) / this.halfHeight; + return n *= n, s *= s, n + s <= 1; + } + /** + * Checks whether the x and y coordinates given are contained within this ellipse including stroke. + * @example + * ```ts + * // Basic stroke check + * const ellipse = new Ellipse(100, 100, 50, 25); + * const isOnStroke = ellipse.strokeContains(150, 100, 4); // 4px line width + * + * // Check with different alignments + * const innerStroke = ellipse.strokeContains(150, 100, 4, 1); // Inside + * const centerStroke = ellipse.strokeContains(150, 100, 4, 0.5); // Centered + * const outerStroke = ellipse.strokeContains(150, 100, 4, 0); // Outside + * ``` + * @remarks + * - Uses normalized ellipse equations + * - Considers stroke alignment + * - Returns false if dimensions are 0 + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @param strokeWidth - The width of the line to check + * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer) + * @returns Whether the x/y coords are within this ellipse's stroke + * @see {@link Ellipse.contains} For checking fill containment + * @see {@link Ellipse.getBounds} For getting stroke bounds + */ + strokeContains(e, t, n, s = 0.5) { + const { halfWidth: r, halfHeight: a } = this; + if (r <= 0 || a <= 0) + return !1; + const o = n * (1 - s), l = n - o, h = r - l, u = a - l, c = r + o, d = a + o, f = e - this.x, _ = t - this.y, b = f * f / (h * h) + _ * _ / (u * u), m = f * f / (c * c) + _ * _ / (d * d); + return b > 1 && m <= 1; + } + /** + * Returns the framing rectangle of the ellipse as a Rectangle object. + * @example + * ```ts + * // Basic bounds calculation + * const ellipse = new Ellipse(100, 100, 50, 25); + * const bounds = ellipse.getBounds(); + * // bounds: x=50, y=75, width=100, height=50 + * + * // Reuse existing rectangle + * const rect = new Rectangle(); + * ellipse.getBounds(rect); + * ``` + * @remarks + * - Creates Rectangle if none provided + * - Top-left is (x-halfWidth, y-halfHeight) + * - Width is halfWidth * 2 + * - Height is halfHeight * 2 + * @param out - Optional Rectangle object to store the result + * @returns The framing rectangle + * @see {@link Rectangle} For rectangle properties + * @see {@link Ellipse.contains} For checking if a point is inside + */ + getBounds(e) { + return e || (e = new de()), e.x = this.x - this.halfWidth, e.y = this.y - this.halfHeight, e.width = this.halfWidth * 2, e.height = this.halfHeight * 2, e; + } + /** + * Copies another ellipse to this one. + * @example + * ```ts + * // Basic copying + * const source = new Ellipse(100, 100, 50, 25); + * const target = new Ellipse(); + * target.copyFrom(source); + * ``` + * @param ellipse - The ellipse to copy from + * @returns Returns itself + * @see {@link Ellipse.copyTo} For copying to another ellipse + * @see {@link Ellipse.clone} For creating new ellipse copy + */ + copyFrom(e) { + return this.x = e.x, this.y = e.y, this.halfWidth = e.halfWidth, this.halfHeight = e.halfHeight, this; + } + /** + * Copies this ellipse to another one. + * @example + * ```ts + * // Basic copying + * const source = new Ellipse(100, 100, 50, 25); + * const target = new Ellipse(); + * source.copyTo(target); + * ``` + * @param ellipse - The ellipse to copy to + * @returns Returns given parameter + * @see {@link Ellipse.copyFrom} For copying from another ellipse + * @see {@link Ellipse.clone} For creating new ellipse copy + */ + copyTo(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:Ellipse x=${this.x} y=${this.y} halfWidth=${this.halfWidth} halfHeight=${this.halfHeight}]`; + } +} +function Ec(i, e, t, n, s, r) { + const a = i - t, o = e - n, l = s - t, h = r - n, u = a * l + o * h, c = l * l + h * h; + let d = -1; + c !== 0 && (d = u / c); + let f, _; + d < 0 ? (f = t, _ = n) : d > 1 ? (f = s, _ = r) : (f = t + d * l, _ = n + d * h); + const b = i - f, m = e - _; + return b * b + m * m; +} +let Fc, $c; +class vn { + /** + * @param points - This can be an array of Points + * that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...], or + * the arguments passed can be all the points of the polygon e.g. + * `new Polygon(new Point(), new Point(), ...)`, or the arguments passed can be flat + * x,y values e.g. `new Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are Numbers. + */ + constructor(...e) { + this.type = "polygon"; + let t = Array.isArray(e[0]) ? e[0] : e; + if (typeof t[0] != "number") { + const n = []; + for (let s = 0, r = t.length; s < r; s++) + n.push(t[s].x, t[s].y); + t = n; + } + this.points = t, this.closePath = !0; + } + /** + * Determines whether the polygon's points are arranged in a clockwise direction. + * Uses the shoelace formula (surveyor's formula) to calculate the signed area. + * + * A positive area indicates clockwise winding, while negative indicates counter-clockwise. + * + * The formula sums up the cross products of adjacent vertices: + * For each pair of adjacent points (x1,y1) and (x2,y2), we calculate (x1*y2 - x2*y1) + * The final sum divided by 2 gives the signed area - positive for clockwise. + * @example + * ```ts + * // Check polygon winding + * const polygon = new Polygon([0, 0, 100, 0, 50, 100]); + * console.log(polygon.isClockwise()); // Check direction + * + * // Use in path construction + * const hole = new Polygon([25, 25, 75, 25, 75, 75, 25, 75]); + * if (hole.isClockwise() === shape.isClockwise()) { + * hole.points.reverse(); // Reverse for proper hole winding + * } + * ``` + * @returns `true` if the polygon's points are arranged clockwise, `false` if counter-clockwise + */ + isClockwise() { + let e = 0; + const t = this.points, n = t.length; + for (let s = 0; s < n; s += 2) { + const r = t[s], a = t[s + 1], o = t[(s + 2) % n], l = t[(s + 3) % n]; + e += (o - r) * (l + a); + } + return e < 0; + } + /** + * Checks if this polygon completely contains another polygon. + * Used for detecting holes in shapes, like when parsing SVG paths. + * @example + * ```ts + * // Basic containment check + * const outerSquare = new Polygon([0,0, 100,0, 100,100, 0,100]); // A square + * const innerSquare = new Polygon([25,25, 75,25, 75,75, 25,75]); // A smaller square inside + * + * outerSquare.containsPolygon(innerSquare); // Returns true + * innerSquare.containsPolygon(outerSquare); // Returns false + * ``` + * @remarks + * - Uses bounds check for quick rejection + * - Tests all points for containment + * @param polygon - The polygon to test for containment + * @returns True if this polygon completely contains the other polygon + * @see {@link Polygon.contains} For single point testing + * @see {@link Polygon.getBounds} For bounds calculation + */ + containsPolygon(e) { + const t = this.getBounds(Fc), n = e.getBounds($c); + if (!t.containsRect(n)) + return !1; + const s = e.points; + for (let r = 0; r < s.length; r += 2) { + const a = s[r], o = s[r + 1]; + if (!this.contains(a, o)) + return !1; + } + return !0; + } + /** + * Creates a clone of this polygon. + * @example + * ```ts + * // Basic cloning + * const original = new Polygon([0, 0, 100, 0, 50, 100]); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.points[0] = 10; // Modify first x coordinate + * ``` + * @returns A copy of the polygon + * @see {@link Polygon.copyFrom} For copying into existing polygon + * @see {@link Polygon.copyTo} For copying to another polygon + */ + clone() { + const e = this.points.slice(), t = new vn(e); + return t.closePath = this.closePath, t; + } + /** + * Checks whether the x and y coordinates passed to this function are contained within this polygon. + * Uses raycasting algorithm for point-in-polygon testing. + * @example + * ```ts + * // Basic containment check + * const polygon = new Polygon([0, 0, 100, 0, 50, 100]); + * const isInside = polygon.contains(25, 25); // true + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @returns Whether the x/y coordinates are within this polygon + * @see {@link Polygon.strokeContains} For checking stroke intersection + * @see {@link Polygon.containsPolygon} For polygon-in-polygon testing + */ + contains(e, t) { + let n = !1; + const s = this.points.length / 2; + for (let r = 0, a = s - 1; r < s; a = r++) { + const o = this.points[r * 2], l = this.points[r * 2 + 1], h = this.points[a * 2], u = this.points[a * 2 + 1]; + l > t != u > t && e < (h - o) * ((t - l) / (u - l)) + o && (n = !n); + } + return n; + } + /** + * Checks whether the x and y coordinates given are contained within this polygon including the stroke. + * @example + * ```ts + * // Basic stroke check + * const polygon = new Polygon([0, 0, 100, 0, 50, 100]); + * const isOnStroke = polygon.strokeContains(25, 25, 4); // 4px line width + * + * // Check with different alignments + * const innerStroke = polygon.strokeContains(25, 25, 4, 1); // Inside + * const centerStroke = polygon.strokeContains(25, 25, 4, 0.5); // Centered + * const outerStroke = polygon.strokeContains(25, 25, 4, 0); // Outside + * ``` + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @param strokeWidth - The width of the line to check + * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer) + * @returns Whether the x/y coordinates are within this polygon's stroke + * @see {@link Polygon.contains} For checking fill containment + * @see {@link Polygon.getBounds} For getting stroke bounds + */ + strokeContains(e, t, n, s = 0.5) { + const r = n * n, a = r * (1 - s), o = r - a, { points: l } = this, h = l.length - (this.closePath ? 0 : 2); + for (let u = 0; u < h; u += 2) { + const c = l[u], d = l[u + 1], f = l[(u + 2) % l.length], _ = l[(u + 3) % l.length], b = Ec(e, t, c, d, f, _), m = Math.sign((f - c) * (t - d) - (_ - d) * (e - c)); + if (b <= (m < 0 ? o : a)) + return !0; + } + return !1; + } + /** + * Returns the framing rectangle of the polygon as a Rectangle object. + * @example + * ```ts + * // Basic bounds calculation + * const polygon = new Polygon([0, 0, 100, 0, 50, 100]); + * const bounds = polygon.getBounds(); + * // bounds: x=0, y=0, width=100, height=100 + * + * // Reuse existing rectangle + * const rect = new Rectangle(); + * polygon.getBounds(rect); + * ``` + * @param out - Optional rectangle to store the result + * @returns The framing rectangle + * @see {@link Rectangle} For rectangle properties + * @see {@link Polygon.contains} For checking if a point is inside + */ + getBounds(e) { + e || (e = new de()); + const t = this.points; + let n = 1 / 0, s = -1 / 0, r = 1 / 0, a = -1 / 0; + for (let o = 0, l = t.length; o < l; o += 2) { + const h = t[o], u = t[o + 1]; + n = h < n ? h : n, s = h > s ? h : s, r = u < r ? u : r, a = u > a ? u : a; + } + return e.x = n, e.width = s - n, e.y = r, e.height = a - r, e; + } + /** + * Copies another polygon to this one. + * @example + * ```ts + * // Basic copying + * const source = new Polygon([0, 0, 100, 0, 50, 100]); + * const target = new Polygon(); + * target.copyFrom(source); + * ``` + * @param polygon - The polygon to copy from + * @returns Returns itself + * @see {@link Polygon.copyTo} For copying to another polygon + * @see {@link Polygon.clone} For creating new polygon copy + */ + copyFrom(e) { + return this.points = e.points.slice(), this.closePath = e.closePath, this; + } + /** + * Copies this polygon to another one. + * @example + * ```ts + * // Basic copying + * const source = new Polygon([0, 0, 100, 0, 50, 100]); + * const target = new Polygon(); + * source.copyTo(target); + * ``` + * @param polygon - The polygon to copy to + * @returns Returns given parameter + * @see {@link Polygon.copyFrom} For copying from another polygon + * @see {@link Polygon.clone} For creating new polygon copy + */ + copyTo(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:PolygoncloseStroke=${this.closePath}points=${this.points.reduce((e, t) => `${e}, ${t}`, "")}]`; + } + /** + * Get the last X coordinate of the polygon. + * @example + * ```ts + * // Basic coordinate access + * const polygon = new Polygon([0, 0, 100, 200, 300, 400]); + * console.log(polygon.lastX); // 300 + * ``` + * @readonly + * @returns The x-coordinate of the last vertex + * @see {@link Polygon.lastY} For last Y coordinate + * @see {@link Polygon.points} For raw points array + */ + get lastX() { + return this.points[this.points.length - 2]; + } + /** + * Get the last Y coordinate of the polygon. + * @example + * ```ts + * // Basic coordinate access + * const polygon = new Polygon([0, 0, 100, 200, 300, 400]); + * console.log(polygon.lastY); // 400 + * ``` + * @readonly + * @returns The y-coordinate of the last vertex + * @see {@link Polygon.lastX} For last X coordinate + * @see {@link Polygon.points} For raw points array + */ + get lastY() { + return this.points[this.points.length - 1]; + } + /** + * Get the last X coordinate of the polygon. + * @readonly + * @deprecated since 8.11.0, use {@link Polygon.lastX} instead. + */ + get x() { + return W("8.11.0", "Polygon.lastX is deprecated, please use Polygon.lastX instead."), this.points[this.points.length - 2]; + } + /** + * Get the last Y coordinate of the polygon. + * @readonly + * @deprecated since 8.11.0, use {@link Polygon.lastY} instead. + */ + get y() { + return W("8.11.0", "Polygon.y is deprecated, please use Polygon.lastY instead."), this.points[this.points.length - 1]; + } + /** + * Get the first X coordinate of the polygon. + * @example + * ```ts + * // Basic coordinate access + * const polygon = new Polygon([0, 0, 100, 200, 300, 400]); + * console.log(polygon.x); // 0 + * ``` + * @readonly + * @returns The x-coordinate of the first vertex + * @see {@link Polygon.startY} For first Y coordinate + * @see {@link Polygon.points} For raw points array + */ + get startX() { + return this.points[0]; + } + /** + * Get the first Y coordinate of the polygon. + * @example + * ```ts + * // Basic coordinate access + * const polygon = new Polygon([0, 0, 100, 200, 300, 400]); + * console.log(polygon.y); // 0 + * ``` + * @readonly + * @returns The y-coordinate of the first vertex + * @see {@link Polygon.startX} For first X coordinate + * @see {@link Polygon.points} For raw points array + */ + get startY() { + return this.points[1]; + } +} +const Jn = (i, e, t, n, s, r, a) => { + const o = i - t, l = e - n, h = Math.sqrt(o * o + l * l); + return h >= s - r && h <= s + a; +}; +class Qs { + /** + * @param x - The X coordinate of the upper-left corner of the rounded rectangle + * @param y - The Y coordinate of the upper-left corner of the rounded rectangle + * @param width - The overall width of this rounded rectangle + * @param height - The overall height of this rounded rectangle + * @param radius - Controls the radius of the rounded corners + */ + constructor(e = 0, t = 0, n = 0, s = 0, r = 20) { + this.type = "roundedRectangle", this.x = e, this.y = t, this.width = n, this.height = s, this.radius = r; + } + /** + * Returns the framing rectangle of the rounded rectangle as a Rectangle object + * @example + * ```ts + * // Basic bounds calculation + * const rect = new RoundedRectangle(100, 100, 200, 150, 20); + * const bounds = rect.getBounds(); + * // bounds: x=100, y=100, width=200, height=150 + * + * // Reuse existing rectangle + * const out = new Rectangle(); + * rect.getBounds(out); + * ``` + * @remarks + * - Rectangle matches outer dimensions + * - Ignores corner radius + * @param out - Optional rectangle to store the result + * @returns The framing rectangle + * @see {@link Rectangle} For rectangle properties + * @see {@link RoundedRectangle.contains} For checking if a point is inside + */ + getBounds(e) { + return e || (e = new de()), e.x = this.x, e.y = this.y, e.width = this.width, e.height = this.height, e; + } + /** + * Creates a clone of this Rounded Rectangle. + * @example + * ```ts + * // Basic cloning + * const original = new RoundedRectangle(100, 100, 200, 150, 20); + * const copy = original.clone(); + * + * // Clone and modify + * const modified = original.clone(); + * modified.radius = 30; + * modified.width *= 2; + * + * // Verify independence + * console.log(original.radius); // 20 + * console.log(modified.radius); // 30 + * ``` + * @returns A copy of the rounded rectangle + * @see {@link RoundedRectangle.copyFrom} For copying into existing rectangle + * @see {@link RoundedRectangle.copyTo} For copying to another rectangle + */ + clone() { + return new Qs(this.x, this.y, this.width, this.height, this.radius); + } + /** + * Copies another rectangle to this one. + * @example + * ```ts + * // Basic copying + * const source = new RoundedRectangle(100, 100, 200, 150, 20); + * const target = new RoundedRectangle(); + * target.copyFrom(source); + * + * // Chain with other operations + * const rect = new RoundedRectangle() + * .copyFrom(source) + * .getBounds(rect); + * ``` + * @param rectangle - The rectangle to copy from + * @returns Returns itself + * @see {@link RoundedRectangle.copyTo} For copying to another rectangle + * @see {@link RoundedRectangle.clone} For creating new rectangle copy + */ + copyFrom(e) { + return this.x = e.x, this.y = e.y, this.width = e.width, this.height = e.height, this; + } + /** + * Copies this rectangle to another one. + * @example + * ```ts + * // Basic copying + * const source = new RoundedRectangle(100, 100, 200, 150, 20); + * const target = new RoundedRectangle(); + * source.copyTo(target); + * + * // Chain with other operations + * const result = source + * .copyTo(new RoundedRectangle()) + * .getBounds(); + * ``` + * @param rectangle - The rectangle to copy to + * @returns Returns given parameter + * @see {@link RoundedRectangle.copyFrom} For copying from another rectangle + * @see {@link RoundedRectangle.clone} For creating new rectangle copy + */ + copyTo(e) { + return e.copyFrom(this), e; + } + /** + * Checks whether the x and y coordinates given are contained within this Rounded Rectangle + * @example + * ```ts + * // Basic containment check + * const rect = new RoundedRectangle(100, 100, 200, 150, 20); + * const isInside = rect.contains(150, 125); // true + * // Check corner radius + * const corner = rect.contains(100, 100); // false if within corner curve + * ``` + * @remarks + * - Returns false if width/height is 0 or negative + * - Handles rounded corners with radius check + * @param x - The X coordinate of the point to test + * @param y - The Y coordinate of the point to test + * @returns Whether the x/y coordinates are within this Rounded Rectangle + * @see {@link RoundedRectangle.strokeContains} For checking stroke intersection + * @see {@link RoundedRectangle.getBounds} For getting containing rectangle + */ + contains(e, t) { + if (this.width <= 0 || this.height <= 0) + return !1; + if (e >= this.x && e <= this.x + this.width && t >= this.y && t <= this.y + this.height) { + const n = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2)); + if (t >= this.y + n && t <= this.y + this.height - n || e >= this.x + n && e <= this.x + this.width - n) + return !0; + let s = e - (this.x + n), r = t - (this.y + n); + const a = n * n; + if (s * s + r * r <= a || (s = e - (this.x + this.width - n), s * s + r * r <= a) || (r = t - (this.y + this.height - n), s * s + r * r <= a) || (s = e - (this.x + n), s * s + r * r <= a)) + return !0; + } + return !1; + } + /** + * Checks whether the x and y coordinates given are contained within this rectangle including the stroke. + * @example + * ```ts + * // Basic stroke check + * const rect = new RoundedRectangle(100, 100, 200, 150, 20); + * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width + * + * // Check with different alignments + * const innerStroke = rect.strokeContains(150, 100, 4, 1); // Inside + * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered + * const outerStroke = rect.strokeContains(150, 100, 4, 0); // Outside + * ``` + * @param pX - The X coordinate of the point to test + * @param pY - The Y coordinate of the point to test + * @param strokeWidth - The width of the line to check + * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer) + * @returns Whether the x/y coordinates are within this rectangle's stroke + * @see {@link RoundedRectangle.contains} For checking fill containment + * @see {@link RoundedRectangle.getBounds} For getting stroke bounds + */ + strokeContains(e, t, n, s = 0.5) { + const { x: r, y: a, width: o, height: l, radius: h } = this, u = n * (1 - s), c = n - u, d = r + h, f = a + h, _ = o - h * 2, b = l - h * 2, m = r + o, x = a + l; + return (e >= r - u && e <= r + c || e >= m - c && e <= m + u) && t >= f && t <= f + b || (t >= a - u && t <= a + c || t >= x - c && t <= x + u) && e >= d && e <= d + _ ? !0 : ( + // Top-left + e < d && t < f && Jn( + e, + t, + d, + f, + h, + c, + u + ) || e > m - h && t < f && Jn( + e, + t, + m - h, + f, + h, + c, + u + ) || e > m - h && t > x - h && Jn( + e, + t, + m - h, + x - h, + h, + c, + u + ) || e < d && t > x - h && Jn( + e, + t, + d, + x - h, + h, + c, + u + ) + ); + } + toString() { + return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`; + } +} +const Sl = {}; +function Tc(i, e, t) { + let n = 2166136261; + for (let s = 0; s < e; s++) + n ^= i[s].uid, n = Math.imul(n, 16777619), n >>>= 0; + return Sl[n] || Mc(i, e, n, t); +} +function Mc(i, e, t, n) { + const s = {}; + let r = 0; + for (let o = 0; o < n; o++) { + const l = o < e ? i[o] : K.EMPTY.source; + s[r++] = l.source, s[r++] = l.style; + } + const a = new di(s); + return Sl[t] = a, a; +} +class Xr { + constructor(e) { + typeof e == "number" ? this.rawBinaryData = new ArrayBuffer(e) : e instanceof Uint8Array ? this.rawBinaryData = e.buffer : this.rawBinaryData = e, this.uint32View = new Uint32Array(this.rawBinaryData), this.float32View = new Float32Array(this.rawBinaryData), this.size = this.rawBinaryData.byteLength; + } + /** View on the raw binary data as a `Int8Array`. */ + get int8View() { + return this._int8View || (this._int8View = new Int8Array(this.rawBinaryData)), this._int8View; + } + /** View on the raw binary data as a `Uint8Array`. */ + get uint8View() { + return this._uint8View || (this._uint8View = new Uint8Array(this.rawBinaryData)), this._uint8View; + } + /** View on the raw binary data as a `Int16Array`. */ + get int16View() { + return this._int16View || (this._int16View = new Int16Array(this.rawBinaryData)), this._int16View; + } + /** View on the raw binary data as a `Int32Array`. */ + get int32View() { + return this._int32View || (this._int32View = new Int32Array(this.rawBinaryData)), this._int32View; + } + /** View on the raw binary data as a `Float64Array`. */ + get float64View() { + return this._float64Array || (this._float64Array = new Float64Array(this.rawBinaryData)), this._float64Array; + } + /** View on the raw binary data as a `BigUint64Array`. */ + get bigUint64View() { + return this._bigUint64Array || (this._bigUint64Array = new BigUint64Array(this.rawBinaryData)), this._bigUint64Array; + } + /** + * Returns the view of the given type. + * @param type - One of `int8`, `uint8`, `int16`, + * `uint16`, `int32`, `uint32`, and `float32`. + * @returns - typed array of given type + */ + view(e) { + return this[`${e}View`]; + } + /** Destroys all buffer references. Do not use after calling this. */ + destroy() { + this.rawBinaryData = null, this._int8View = null, this._uint8View = null, this._int16View = null, this.uint16View = null, this._int32View = null, this.uint32View = null, this.float32View = null; + } + /** + * Returns the size of the given type in bytes. + * @param type - One of `int8`, `uint8`, `int16`, + * `uint16`, `int32`, `uint32`, and `float32`. + * @returns - size of the type in bytes + */ + static sizeOf(e) { + switch (e) { + case "int8": + case "uint8": + return 1; + case "int16": + case "uint16": + return 2; + case "int32": + case "uint32": + case "float32": + return 4; + default: + throw new Error(`${e} isn't a valid view type`); + } + } +} +function jr(i, e) { + const t = i.byteLength / 8 | 0, n = new Float64Array(i, 0, t); + new Float64Array(e, 0, t).set(n); + const r = i.byteLength - t * 8; + if (r > 0) { + const a = new Uint8Array(i, t * 8, r); + new Uint8Array(e, t * 8, r).set(a); + } +} +const Pc = { + normal: "normal-npm", + add: "add-npm", + screen: "screen-npm" +}; +var Ic = /* @__PURE__ */ ((i) => (i[i.DISABLED = 0] = "DISABLED", i[i.RENDERING_MASK_ADD = 1] = "RENDERING_MASK_ADD", i[i.MASK_ACTIVE = 2] = "MASK_ACTIVE", i[i.INVERSE_MASK_ACTIVE = 3] = "INVERSE_MASK_ACTIVE", i[i.RENDERING_MASK_REMOVE = 4] = "RENDERING_MASK_REMOVE", i[i.NONE = 5] = "NONE", i))(Ic || {}); +function Zr(i, e) { + return e.alphaMode === "no-premultiply-alpha" && Pc[i] || i; +} +const Rc = [ + "precision mediump float;", + "void main(void){", + "float test = 0.1;", + "%forloop%", + "gl_FragColor = vec4(0.0);", + "}" +].join(` +`); +function Bc(i) { + let e = ""; + for (let t = 0; t < i; ++t) + t > 0 && (e += ` +else `), t < i - 1 && (e += `if(test == ${t}.0){}`); + return e; +} +function Lc(i, e) { + if (i === 0) + throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`"); + const t = e.createShader(e.FRAGMENT_SHADER); + try { + for (; ; ) { + const n = Rc.replace(/%forloop%/gi, Bc(i)); + if (e.shaderSource(t, n), e.compileShader(t), !e.getShaderParameter(t, e.COMPILE_STATUS)) + i = i / 2 | 0; + else + break; + } + } finally { + e.deleteShader(t); + } + return i; +} +let Ht = null; +function Oc() { + var e; + if (Ht) + return Ht; + const i = sl(); + return Ht = i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS), Ht = Lc( + Ht, + i + ), (e = i.getExtension("WEBGL_lose_context")) == null || e.loseContext(), Ht; +} +class zc { + constructor() { + this.ids = /* @__PURE__ */ Object.create(null), this.textures = [], this.count = 0; + } + /** Clear the textures and their locations. */ + clear() { + for (let e = 0; e < this.count; e++) { + const t = this.textures[e]; + this.textures[e] = null, this.ids[t.uid] = null; + } + this.count = 0; + } +} +class Nc { + constructor() { + this.renderPipeId = "batch", this.action = "startBatch", this.start = 0, this.size = 0, this.textures = new zc(), this.blendMode = "normal", this.topology = "triangle-strip", this.canBundle = !0; + } + destroy() { + this.textures = null, this.gpuBindGroup = null, this.bindGroup = null, this.batcher = null; + } +} +const Cn = []; +let gi = 0; +Bn.register({ + clear: () => { + if (Cn.length > 0) + for (const i of Cn) + i && i.destroy(); + Cn.length = 0, gi = 0; + } +}); +function Kr() { + return gi > 0 ? Cn[--gi] : new Nc(); +} +function Qr(i) { + Cn[gi++] = i; +} +let cn = 0; +const kl = class Al { + constructor(e) { + this.uid = ue("batcher"), this.dirty = !0, this.batchIndex = 0, this.batches = [], this._elements = [], e = { ...Al.defaultOptions, ...e }, e.maxTextures || (W("v8.8.0", "maxTextures is a required option for Batcher now, please pass it in the options"), e.maxTextures = Oc()); + const { maxTextures: t, attributesInitialSize: n, indicesInitialSize: s } = e; + this.attributeBuffer = new Xr(n * 4), this.indexBuffer = new Uint16Array(s), this.maxTextures = t; + } + begin() { + this.elementSize = 0, this.elementStart = 0, this.indexSize = 0, this.attributeSize = 0; + for (let e = 0; e < this.batchIndex; e++) + Qr(this.batches[e]); + this.batchIndex = 0, this._batchIndexStart = 0, this._batchIndexSize = 0, this.dirty = !0; + } + add(e) { + this._elements[this.elementSize++] = e, e._indexStart = this.indexSize, e._attributeStart = this.attributeSize, e._batcher = this, this.indexSize += e.indexSize, this.attributeSize += e.attributeSize * this.vertexSize; + } + checkAndUpdateTexture(e, t) { + const n = e._batch.textures.ids[t._source.uid]; + return !n && n !== 0 ? !1 : (e._textureId = n, e.texture = t, !0); + } + updateElement(e) { + this.dirty = !0; + const t = this.attributeBuffer; + e.packAsQuad ? this.packQuadAttributes( + e, + t.float32View, + t.uint32View, + e._attributeStart, + e._textureId + ) : this.packAttributes( + e, + t.float32View, + t.uint32View, + e._attributeStart, + e._textureId + ); + } + /** + * breaks the batcher. This happens when a batch gets too big, + * or we need to switch to a different type of rendering (a filter for example) + * @param instructionSet + */ + break(e) { + const t = this._elements; + if (!t[this.elementStart]) + return; + let n = Kr(), s = n.textures; + s.clear(); + const r = t[this.elementStart]; + let a = Zr(r.blendMode, r.texture._source), o = r.topology; + this.attributeSize * 4 > this.attributeBuffer.size && this._resizeAttributeBuffer(this.attributeSize * 4), this.indexSize > this.indexBuffer.length && this._resizeIndexBuffer(this.indexSize); + const l = this.attributeBuffer.float32View, h = this.attributeBuffer.uint32View, u = this.indexBuffer; + let c = this._batchIndexSize, d = this._batchIndexStart, f = "startBatch"; + const _ = this.maxTextures; + for (let b = this.elementStart; b < this.elementSize; ++b) { + const m = t[b]; + t[b] = null; + const g = m.texture._source, p = Zr(m.blendMode, g), y = a !== p || o !== m.topology; + if (g._batchTick === cn && !y) { + m._textureId = g._textureBindLocation, c += m.indexSize, m.packAsQuad ? (this.packQuadAttributes( + m, + l, + h, + m._attributeStart, + m._textureId + ), this.packQuadIndex( + u, + m._indexStart, + m._attributeStart / this.vertexSize + )) : (this.packAttributes( + m, + l, + h, + m._attributeStart, + m._textureId + ), this.packIndex( + m, + u, + m._indexStart, + m._attributeStart / this.vertexSize + )), m._batch = n; + continue; + } + g._batchTick = cn, (s.count >= _ || y) && (this._finishBatch( + n, + d, + c - d, + s, + a, + o, + e, + f + ), f = "renderBatch", d = c, a = p, o = m.topology, n = Kr(), s = n.textures, s.clear(), ++cn), m._textureId = g._textureBindLocation = s.count, s.ids[g.uid] = s.count, s.textures[s.count++] = g, m._batch = n, c += m.indexSize, m.packAsQuad ? (this.packQuadAttributes( + m, + l, + h, + m._attributeStart, + m._textureId + ), this.packQuadIndex( + u, + m._indexStart, + m._attributeStart / this.vertexSize + )) : (this.packAttributes( + m, + l, + h, + m._attributeStart, + m._textureId + ), this.packIndex( + m, + u, + m._indexStart, + m._attributeStart / this.vertexSize + )); + } + s.count > 0 && (this._finishBatch( + n, + d, + c - d, + s, + a, + o, + e, + f + ), d = c, ++cn), this.elementStart = this.elementSize, this._batchIndexStart = d, this._batchIndexSize = c; + } + _finishBatch(e, t, n, s, r, a, o, l) { + e.gpuBindGroup = null, e.bindGroup = null, e.action = l, e.batcher = this, e.textures = s, e.blendMode = r, e.topology = a, e.start = t, e.size = n, ++cn, this.batches[this.batchIndex++] = e, o.add(e); + } + finish(e) { + this.break(e); + } + /** + * Resizes the attribute buffer to the given size (1 = 1 float32) + * @param size - the size in vertices to ensure (not bytes!) + */ + ensureAttributeBuffer(e) { + e * 4 <= this.attributeBuffer.size || this._resizeAttributeBuffer(e * 4); + } + /** + * Resizes the index buffer to the given size (1 = 1 float32) + * @param size - the size in vertices to ensure (not bytes!) + */ + ensureIndexBuffer(e) { + e <= this.indexBuffer.length || this._resizeIndexBuffer(e); + } + _resizeAttributeBuffer(e) { + const t = Math.max(e, this.attributeBuffer.size * 2), n = new Xr(t); + jr(this.attributeBuffer.rawBinaryData, n.rawBinaryData), this.attributeBuffer = n; + } + _resizeIndexBuffer(e) { + const t = this.indexBuffer; + let n = Math.max(e, t.length * 1.5); + n += n % 2; + const s = n > 65535 ? new Uint32Array(n) : new Uint16Array(n); + if (s.BYTES_PER_ELEMENT !== t.BYTES_PER_ELEMENT) + for (let r = 0; r < t.length; r++) + s[r] = t[r]; + else + jr(t.buffer, s.buffer); + this.indexBuffer = s; + } + packQuadIndex(e, t, n) { + e[t] = n + 0, e[t + 1] = n + 1, e[t + 2] = n + 2, e[t + 3] = n + 0, e[t + 4] = n + 2, e[t + 5] = n + 3; + } + packIndex(e, t, n, s) { + const r = e.indices, a = e.indexSize, o = e.indexOffset, l = e.attributeOffset; + for (let h = 0; h < a; h++) + t[n++] = s + r[h + o] - l; + } + destroy() { + if (this.batches !== null) { + for (let e = 0; e < this.batches.length; e++) + Qr(this.batches[e]); + this.batches = null; + for (let e = 0; e < this._elements.length; e++) + this._elements[e] && (this._elements[e]._batch = null); + this._elements = null, this.indexBuffer = null, this.attributeBuffer.destroy(), this.attributeBuffer = null; + } + } +}; +kl.defaultOptions = { + maxTextures: null, + attributesInitialSize: 4, + indicesInitialSize: 6 +}; +let Gc = kl; +var Me = /* @__PURE__ */ ((i) => (i[i.MAP_READ = 1] = "MAP_READ", i[i.MAP_WRITE = 2] = "MAP_WRITE", i[i.COPY_SRC = 4] = "COPY_SRC", i[i.COPY_DST = 8] = "COPY_DST", i[i.INDEX = 16] = "INDEX", i[i.VERTEX = 32] = "VERTEX", i[i.UNIFORM = 64] = "UNIFORM", i[i.STORAGE = 128] = "STORAGE", i[i.INDIRECT = 256] = "INDIRECT", i[i.QUERY_RESOLVE = 512] = "QUERY_RESOLVE", i[i.STATIC = 1024] = "STATIC", i))(Me || {}); +class Pn extends xt { + /** + * Creates a new Buffer with the given options + * @param options - the options for the buffer + */ + constructor(e) { + let { data: t, size: n } = e; + const { usage: s, label: r, shrinkToFit: a } = e; + super(), this.uid = ue("buffer"), this._resourceType = "buffer", this._resourceId = ue("resource"), this._touched = 0, this._updateID = 1, this._dataInt32 = null, this.shrinkToFit = !0, this.destroyed = !1, t instanceof Array && (t = new Float32Array(t)), this._data = t, n ?? (n = t == null ? void 0 : t.byteLength); + const o = !!t; + this.descriptor = { + size: n, + usage: s, + mappedAtCreation: o, + label: r + }, this.shrinkToFit = a ?? !0; + } + /** the data in the buffer */ + get data() { + return this._data; + } + set data(e) { + this.setDataWithSize(e, e.length, !0); + } + get dataInt32() { + return this._dataInt32 || (this._dataInt32 = new Int32Array(this.data.buffer)), this._dataInt32; + } + /** whether the buffer is static or not */ + get static() { + return !!(this.descriptor.usage & Me.STATIC); + } + set static(e) { + e ? this.descriptor.usage |= Me.STATIC : this.descriptor.usage &= ~Me.STATIC; + } + /** + * Sets the data in the buffer to the given value. This will immediately update the buffer on the GPU. + * If you only want to update a subset of the buffer, you can pass in the size of the data. + * @param value - the data to set + * @param size - the size of the data in bytes + * @param syncGPU - should the buffer be updated on the GPU immediately? + */ + setDataWithSize(e, t, n) { + if (this._updateID++, this._updateSize = t * e.BYTES_PER_ELEMENT, this._data === e) { + n && this.emit("update", this); + return; + } + const s = this._data; + if (this._data = e, this._dataInt32 = null, !s || s.length !== e.length) { + !this.shrinkToFit && s && e.byteLength < s.byteLength ? n && this.emit("update", this) : (this.descriptor.size = e.byteLength, this._resourceId = ue("resource"), this.emit("change", this)); + return; + } + n && this.emit("update", this); + } + /** + * updates the buffer on the GPU to reflect the data in the buffer. + * By default it will update the entire buffer. If you only want to update a subset of the buffer, + * you can pass in the size of the buffer to update. + * @param sizeInBytes - the new size of the buffer in bytes + */ + update(e) { + this._updateSize = e ?? this._updateSize, this._updateID++, this.emit("update", this); + } + /** Destroys the buffer */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this._data = null, this.descriptor = null, this.removeAllListeners(); + } +} +function Dl(i, e) { + if (!(i instanceof Pn)) { + let t = e ? Me.INDEX : Me.VERTEX; + i instanceof Array && (e ? (i = new Uint32Array(i), t = Me.INDEX | Me.COPY_DST) : (i = new Float32Array(i), t = Me.VERTEX | Me.COPY_DST)), i = new Pn({ + data: i, + label: e ? "index-mesh-buffer" : "vertex-mesh-buffer", + usage: t + }); + } + return i; +} +function qc(i, e, t) { + const n = i.getAttribute(e); + if (!n) + return t.minX = 0, t.minY = 0, t.maxX = 0, t.maxY = 0, t; + const s = n.buffer.data; + let r = 1 / 0, a = 1 / 0, o = -1 / 0, l = -1 / 0; + const h = s.BYTES_PER_ELEMENT, u = (n.offset || 0) / h, c = (n.stride || 2 * 4) / h; + for (let d = u; d < s.length; d += c) { + const f = s[d], _ = s[d + 1]; + f > o && (o = f), _ > l && (l = _), f < r && (r = f), _ < a && (a = _); + } + return t.minX = r, t.minY = a, t.maxX = o, t.maxY = l, t; +} +function Uc(i) { + return (i instanceof Pn || Array.isArray(i) || i.BYTES_PER_ELEMENT) && (i = { + buffer: i + }), i.buffer = Dl(i.buffer, !1), i; +} +class Hc extends xt { + /** + * Create a new instance of a geometry + * @param options - The options for the geometry. + */ + constructor(e = {}) { + super(), this.uid = ue("geometry"), this._layoutKey = 0, this.instanceCount = 1, this._bounds = new ht(), this._boundsDirty = !0; + const { attributes: t, indexBuffer: n, topology: s } = e; + if (this.buffers = [], this.attributes = {}, t) + for (const r in t) + this.addAttribute(r, t[r]); + this.instanceCount = e.instanceCount ?? 1, n && this.addIndex(n), this.topology = s || "triangle-list"; + } + onBufferUpdate() { + this._boundsDirty = !0, this.emit("update", this); + } + /** + * Returns the requested attribute. + * @param id - The name of the attribute required + * @returns - The attribute requested. + */ + getAttribute(e) { + return this.attributes[e]; + } + /** + * Returns the index buffer + * @returns - The index buffer. + */ + getIndex() { + return this.indexBuffer; + } + /** + * Returns the requested buffer. + * @param id - The name of the buffer required. + * @returns - The buffer requested. + */ + getBuffer(e) { + return this.getAttribute(e).buffer; + } + /** + * Used to figure out how many vertices there are in this geometry + * @returns the number of vertices in the geometry + */ + getSize() { + for (const e in this.attributes) { + const t = this.attributes[e]; + return t.buffer.data.length / (t.stride / 4 || t.size); + } + return 0; + } + /** + * Adds an attribute to the geometry. + * @param name - The name of the attribute to add. + * @param attributeOption - The attribute option to add. + */ + addAttribute(e, t) { + const n = Uc(t); + this.buffers.indexOf(n.buffer) === -1 && (this.buffers.push(n.buffer), n.buffer.on("update", this.onBufferUpdate, this), n.buffer.on("change", this.onBufferUpdate, this)), this.attributes[e] = n; + } + /** + * Adds an index buffer to the geometry. + * @param indexBuffer - The index buffer to add. Can be a Buffer, TypedArray, or an array of numbers. + */ + addIndex(e) { + this.indexBuffer = Dl(e, !0), this.buffers.push(this.indexBuffer); + } + /** Returns the bounds of the geometry. */ + get bounds() { + return this._boundsDirty ? (this._boundsDirty = !1, qc(this, "aPosition", this._bounds)) : this._bounds; + } + /** + * destroys the geometry. + * @param destroyBuffers - destroy the buffers associated with this geometry + */ + destroy(e = !1) { + this.emit("destroy", this), this.removeAllListeners(), e && this.buffers.forEach((t) => t.destroy()), this.attributes = null, this.buffers = null, this.indexBuffer = null, this._bounds = null; + } +} +const Vc = new Float32Array(1), Wc = new Uint32Array(1); +class Yc extends Hc { + constructor() { + const t = new Pn({ + data: Vc, + label: "attribute-batch-buffer", + usage: Me.VERTEX | Me.COPY_DST, + shrinkToFit: !1 + }), n = new Pn({ + data: Wc, + label: "index-batch-buffer", + usage: Me.INDEX | Me.COPY_DST, + // | BufferUsage.STATIC, + shrinkToFit: !1 + }), s = 6 * 4; + super({ + attributes: { + aPosition: { + buffer: t, + format: "float32x2", + stride: s, + offset: 0 + }, + aUV: { + buffer: t, + format: "float32x2", + stride: s, + offset: 2 * 4 + }, + aColor: { + buffer: t, + format: "unorm8x4", + stride: s, + offset: 4 * 4 + }, + aTextureIdAndRound: { + buffer: t, + format: "uint16x2", + stride: s, + offset: 5 * 4 + } + }, + indexBuffer: n + }); + } +} +function Jr(i, e, t) { + if (i) + for (const n in i) { + const s = n.toLocaleLowerCase(), r = e[s]; + if (r) { + let a = i[n]; + n === "header" && (a = a.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "")), t && r.push(`//----${t}----//`), r.push(a); + } else + $e(`${n} placement hook does not exist in shader`); + } +} +const Xc = /\{\{(.*?)\}\}/g; +function ea(i) { + var n; + const e = {}; + return (((n = i.match(Xc)) == null ? void 0 : n.map((s) => s.replace(/[{()}]/g, ""))) ?? []).forEach((s) => { + e[s] = []; + }), e; +} +function ta(i, e) { + let t; + const n = /@in\s+([^;]+);/g; + for (; (t = n.exec(i)) !== null; ) + e.push(t[1]); +} +function na(i, e, t = !1) { + const n = []; + ta(e, n), i.forEach((o) => { + o.header && ta(o.header, n); + }); + const s = n; + t && s.sort(); + const r = s.map((o, l) => ` @location(${l}) ${o},`).join(` +`); + let a = e.replace(/@in\s+[^;]+;\s*/g, ""); + return a = a.replace("{{in}}", ` +${r} +`), a; +} +function ia(i, e) { + let t; + const n = /@out\s+([^;]+);/g; + for (; (t = n.exec(i)) !== null; ) + e.push(t[1]); +} +function jc(i) { + const t = /\b(\w+)\s*:/g.exec(i); + return t ? t[1] : ""; +} +function Zc(i) { + const e = /@.*?\s+/g; + return i.replace(e, ""); +} +function Kc(i, e) { + const t = []; + ia(e, t), i.forEach((l) => { + l.header && ia(l.header, t); + }); + let n = 0; + const s = t.sort().map((l) => l.indexOf("builtin") > -1 ? l : `@location(${n++}) ${l}`).join(`, +`), r = t.sort().map((l) => ` var ${Zc(l)};`).join(` +`), a = `return VSOutput( + ${t.sort().map((l) => ` ${jc(l)}`).join(`, +`)});`; + let o = e.replace(/@out\s+[^;]+;\s*/g, ""); + return o = o.replace("{{struct}}", ` +${s} +`), o = o.replace("{{start}}", ` +${r} +`), o = o.replace("{{return}}", ` +${a} +`), o; +} +function sa(i, e) { + let t = i; + for (const n in e) { + const s = e[n]; + s.join(` +`).length ? t = t.replace(`{{${n}}}`, `//-----${n} START-----// +${s.join(` +`)} +//----${n} FINISH----//`) : t = t.replace(`{{${n}}}`, ""); + } + return t; +} +const $t = /* @__PURE__ */ Object.create(null), Xi = /* @__PURE__ */ new Map(); +let Qc = 0; +function Jc({ + template: i, + bits: e +}) { + const t = El(i, e); + if ($t[t]) + return $t[t]; + const { vertex: n, fragment: s } = td(i, e); + return $t[t] = Fl(n, s, e), $t[t]; +} +function ed({ + template: i, + bits: e +}) { + const t = El(i, e); + return $t[t] || ($t[t] = Fl(i.vertex, i.fragment, e)), $t[t]; +} +function td(i, e) { + const t = e.map((a) => a.vertex).filter((a) => !!a), n = e.map((a) => a.fragment).filter((a) => !!a); + let s = na(t, i.vertex, !0); + s = Kc(t, s); + const r = na(n, i.fragment, !0); + return { + vertex: s, + fragment: r + }; +} +function El(i, e) { + return e.map((t) => (Xi.has(t) || Xi.set(t, Qc++), Xi.get(t))).sort((t, n) => t - n).join("-") + i.vertex + i.fragment; +} +function Fl(i, e, t) { + const n = ea(i), s = ea(e); + return t.forEach((r) => { + Jr(r.vertex, n, r.name), Jr(r.fragment, s, r.name); + }), { + vertex: sa(i, n), + fragment: sa(e, s) + }; +} +const nd = ( + /* wgsl */ + ` + @in aPosition: vec2; + @in aUV: vec2; + + @out @builtin(position) vPosition: vec4; + @out vUV : vec2; + @out vColor : vec4; + + {{header}} + + struct VSOutput { + {{struct}} + }; + + @vertex + fn main( {{in}} ) -> VSOutput { + + var worldTransformMatrix = globalUniforms.uWorldTransformMatrix; + var modelMatrix = mat3x3( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + var position = aPosition; + var uv = aUV; + + {{start}} + + vColor = vec4(1., 1., 1., 1.); + + {{main}} + + vUV = uv; + + var modelViewProjectionMatrix = globalUniforms.uProjectionMatrix * worldTransformMatrix * modelMatrix; + + vPosition = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0); + + vColor *= globalUniforms.uWorldColorAlpha; + + {{end}} + + {{return}} + }; +` +), id = ( + /* wgsl */ + ` + @in vUV : vec2; + @in vColor : vec4; + + {{header}} + + @fragment + fn main( + {{in}} + ) -> @location(0) vec4 { + + {{start}} + + var outColor:vec4; + + {{main}} + + var finalColor:vec4 = outColor * vColor; + + {{end}} + + return finalColor; + }; +` +), sd = ( + /* glsl */ + ` + in vec2 aPosition; + in vec2 aUV; + + out vec4 vColor; + out vec2 vUV; + + {{header}} + + void main(void){ + + mat3 worldTransformMatrix = uWorldTransformMatrix; + mat3 modelMatrix = mat3( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + vec2 position = aPosition; + vec2 uv = aUV; + + {{start}} + + vColor = vec4(1.); + + {{main}} + + vUV = uv; + + mat3 modelViewProjectionMatrix = uProjectionMatrix * worldTransformMatrix * modelMatrix; + + gl_Position = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0); + + vColor *= uWorldColorAlpha; + + {{end}} + } +` +), rd = ( + /* glsl */ + ` + + in vec4 vColor; + in vec2 vUV; + + out vec4 finalColor; + + {{header}} + + void main(void) { + + {{start}} + + vec4 outColor; + + {{main}} + + finalColor = outColor * vColor; + + {{end}} + } +` +), ad = { + name: "global-uniforms-bit", + vertex: { + header: ( + /* wgsl */ + ` + struct GlobalUniforms { + uProjectionMatrix:mat3x3, + uWorldTransformMatrix:mat3x3, + uWorldColorAlpha: vec4, + uResolution: vec2, + } + + @group(0) @binding(0) var globalUniforms : GlobalUniforms; + ` + ) + } +}, od = { + name: "global-uniforms-bit", + vertex: { + header: ( + /* glsl */ + ` + uniform mat3 uProjectionMatrix; + uniform mat3 uWorldTransformMatrix; + uniform vec4 uWorldColorAlpha; + uniform vec2 uResolution; + ` + ) + } +}; +function ld({ bits: i, name: e }) { + const t = Jc({ + template: { + fragment: id, + vertex: nd + }, + bits: [ + ad, + ...i + ] + }); + return Di.from({ + name: e, + vertex: { + source: t.vertex, + entryPoint: "main" + }, + fragment: { + source: t.fragment, + entryPoint: "main" + } + }); +} +function hd({ bits: i, name: e }) { + return new al({ + name: e, + ...ed({ + template: { + vertex: sd, + fragment: rd + }, + bits: [ + od, + ...i + ] + }) + }); +} +const ud = { + name: "color-bit", + vertex: { + header: ( + /* wgsl */ + ` + @in aColor: vec4; + ` + ), + main: ( + /* wgsl */ + ` + vColor *= vec4(aColor.rgb * aColor.a, aColor.a); + ` + ) + } +}, cd = { + name: "color-bit", + vertex: { + header: ( + /* glsl */ + ` + in vec4 aColor; + ` + ), + main: ( + /* glsl */ + ` + vColor *= vec4(aColor.rgb * aColor.a, aColor.a); + ` + ) + } +}, ji = {}; +function dd(i) { + const e = []; + if (i === 1) + e.push("@group(1) @binding(0) var textureSource1: texture_2d;"), e.push("@group(1) @binding(1) var textureSampler1: sampler;"); + else { + let t = 0; + for (let n = 0; n < i; n++) + e.push(`@group(1) @binding(${t++}) var textureSource${n + 1}: texture_2d;`), e.push(`@group(1) @binding(${t++}) var textureSampler${n + 1}: sampler;`); + } + return e.join(` +`); +} +function fd(i) { + const e = []; + if (i === 1) + e.push("outColor = textureSampleGrad(textureSource1, textureSampler1, vUV, uvDx, uvDy);"); + else { + e.push("switch vTextureId {"); + for (let t = 0; t < i; t++) + t === i - 1 ? e.push(" default:{") : e.push(` case ${t}:{`), e.push(` outColor = textureSampleGrad(textureSource${t + 1}, textureSampler${t + 1}, vUV, uvDx, uvDy);`), e.push(" break;}"); + e.push("}"); + } + return e.join(` +`); +} +function pd(i) { + return ji[i] || (ji[i] = { + name: "texture-batch-bit", + vertex: { + header: ` + @in aTextureIdAndRound: vec2; + @out @interpolate(flat) vTextureId : u32; + `, + main: ` + vTextureId = aTextureIdAndRound.y; + `, + end: ` + if(aTextureIdAndRound.x == 1) + { + vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw); + } + ` + }, + fragment: { + header: ` + @in @interpolate(flat) vTextureId: u32; + + ${dd(i)} + `, + main: ` + var uvDx = dpdx(vUV); + var uvDy = dpdy(vUV); + + ${fd(i)} + ` + } + }), ji[i]; +} +const Zi = {}; +function _d(i) { + const e = []; + for (let t = 0; t < i; t++) + t > 0 && e.push("else"), t < i - 1 && e.push(`if(vTextureId < ${t}.5)`), e.push("{"), e.push(` outColor = texture(uTextures[${t}], vUV);`), e.push("}"); + return e.join(` +`); +} +function md(i) { + return Zi[i] || (Zi[i] = { + name: "texture-batch-bit", + vertex: { + header: ` + in vec2 aTextureIdAndRound; + out float vTextureId; + + `, + main: ` + vTextureId = aTextureIdAndRound.y; + `, + end: ` + if(aTextureIdAndRound.x == 1.) + { + gl_Position.xy = roundPixels(gl_Position.xy, uResolution); + } + ` + }, + fragment: { + header: ` + in float vTextureId; + + uniform sampler2D uTextures[${i}]; + + `, + main: ` + + ${_d(i)} + ` + } + }), Zi[i]; +} +const gd = { + name: "round-pixels-bit", + vertex: { + header: ( + /* wgsl */ + ` + fn roundPixels(position: vec2, targetSize: vec2) -> vec2 + { + return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0; + } + ` + ) + } +}, yd = { + name: "round-pixels-bit", + vertex: { + header: ( + /* glsl */ + ` + vec2 roundPixels(vec2 position, vec2 targetSize) + { + return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0; + } + ` + ) + } +}, ra = {}; +function bd(i) { + let e = ra[i]; + if (e) + return e; + const t = new Int32Array(i); + for (let n = 0; n < i; n++) + t[n] = n; + return e = ra[i] = new ul({ + uTextures: { value: t, type: "i32", size: i } + }, { isStatic: !0 }), e; +} +class xd extends Xs { + constructor(e) { + const t = hd({ + name: "batch", + bits: [ + cd, + md(e), + yd + ] + }), n = ld({ + name: "batch", + bits: [ + ud, + pd(e), + gd + ] + }); + super({ + glProgram: t, + gpuProgram: n, + resources: { + batchSamplers: bd(e) + } + }); + } +} +let Ki = null; +const $l = class Tl extends Gc { + constructor(e) { + super(e), this.geometry = new Yc(), this.name = Tl.extension.name, this.vertexSize = 6, Ki ?? (Ki = new xd(e.maxTextures)), this.shader = Ki; + } + /** + * Packs the attributes of a DefaultBatchableMeshElement into the provided views. + * @param element - The DefaultBatchableMeshElement to pack. + * @param float32View - The Float32Array view to pack into. + * @param uint32View - The Uint32Array view to pack into. + * @param index - The starting index in the views. + * @param textureId - The texture ID to use. + */ + packAttributes(e, t, n, s, r) { + const a = r << 16 | e.roundPixels & 65535, o = e.transform, l = o.a, h = o.b, u = o.c, c = o.d, d = o.tx, f = o.ty, { positions: _, uvs: b } = e, m = e.color, x = e.attributeOffset, g = x + e.attributeSize; + for (let p = x; p < g; p++) { + const y = p * 2, C = _[y], w = _[y + 1]; + t[s++] = l * C + u * w + d, t[s++] = c * w + h * C + f, t[s++] = b[y], t[s++] = b[y + 1], n[s++] = m, n[s++] = a; + } + } + /** + * Packs the attributes of a DefaultBatchableQuadElement into the provided views. + * @param element - The DefaultBatchableQuadElement to pack. + * @param float32View - The Float32Array view to pack into. + * @param uint32View - The Uint32Array view to pack into. + * @param index - The starting index in the views. + * @param textureId - The texture ID to use. + */ + packQuadAttributes(e, t, n, s, r) { + const a = e.texture, o = e.transform, l = o.a, h = o.b, u = o.c, c = o.d, d = o.tx, f = o.ty, _ = e.bounds, b = _.maxX, m = _.minX, x = _.maxY, g = _.minY, p = a.uvs, y = e.color, C = r << 16 | e.roundPixels & 65535; + t[s + 0] = l * m + u * g + d, t[s + 1] = c * g + h * m + f, t[s + 2] = p.x0, t[s + 3] = p.y0, n[s + 4] = y, n[s + 5] = C, t[s + 6] = l * b + u * g + d, t[s + 7] = c * g + h * b + f, t[s + 8] = p.x1, t[s + 9] = p.y1, n[s + 10] = y, n[s + 11] = C, t[s + 12] = l * b + u * x + d, t[s + 13] = c * x + h * b + f, t[s + 14] = p.x2, t[s + 15] = p.y2, n[s + 16] = y, n[s + 17] = C, t[s + 18] = l * m + u * x + d, t[s + 19] = c * x + h * m + f, t[s + 20] = p.x3, t[s + 21] = p.y3, n[s + 22] = y, n[s + 23] = C; + } +}; +$l.extension = { + type: [ + Q.Batcher + ], + name: "default" +}; +let wd = $l; +function vd(i, e, t, n, s, r, a, o = null) { + let l = 0; + t *= e, s *= r; + const h = o.a, u = o.b, c = o.c, d = o.d, f = o.tx, _ = o.ty; + for (; l < a; ) { + const b = i[t], m = i[t + 1]; + n[s] = h * b + c * m + f, n[s + 1] = u * b + d * m + _, s += r, t += e, l++; + } +} +function Cd(i, e, t, n) { + let s = 0; + for (e *= t; s < n; ) + i[e] = 0, i[e + 1] = 0, e += t, s++; +} +function Ml(i, e, t, n, s) { + const r = e.a, a = e.b, o = e.c, l = e.d, h = e.tx, u = e.ty; + t || (t = 0), n || (n = 2), s || (s = i.length / n - t); + let c = t * n; + for (let d = 0; d < s; d++) { + const f = i[c], _ = i[c + 1]; + i[c] = r * f + o * _ + h, i[c + 1] = a * f + l * _ + u, c += n; + } +} +const Sd = new H(); +class Pl { + constructor() { + this.packAsQuad = !1, this.batcherName = "default", this.topology = "triangle-list", this.applyTransform = !0, this.roundPixels = 0, this._batcher = null, this._batch = null; + } + get uvs() { + return this.geometryData.uvs; + } + get positions() { + return this.geometryData.vertices; + } + get indices() { + return this.geometryData.indices; + } + get blendMode() { + return this.renderable && this.applyTransform ? this.renderable.groupBlendMode : "normal"; + } + get color() { + const e = this.baseColor, t = e >> 16 | e & 65280 | (e & 255) << 16, n = this.renderable; + return n ? Lo(t, n.groupColor) + (this.alpha * n.groupAlpha * 255 << 24) : t + (this.alpha * 255 << 24); + } + get transform() { + var e; + return ((e = this.renderable) == null ? void 0 : e.groupTransform) || Sd; + } + copyTo(e) { + e.indexOffset = this.indexOffset, e.indexSize = this.indexSize, e.attributeOffset = this.attributeOffset, e.attributeSize = this.attributeSize, e.baseColor = this.baseColor, e.alpha = this.alpha, e.texture = this.texture, e.geometryData = this.geometryData, e.topology = this.topology; + } + reset() { + this.applyTransform = !0, this.renderable = null, this.topology = "triangle-list"; + } + destroy() { + this.renderable = null, this.texture = null, this.geometryData = null, this._batcher = null, this._batch = null; + } +} +const In = { + extension: { + type: Q.ShapeBuilder, + name: "circle" + }, + build(i, e) { + let t, n, s, r, a, o; + if (i.type === "circle") { + const y = i; + if (a = o = y.radius, a <= 0) + return !1; + t = y.x, n = y.y, s = r = 0; + } else if (i.type === "ellipse") { + const y = i; + if (a = y.halfWidth, o = y.halfHeight, a <= 0 || o <= 0) + return !1; + t = y.x, n = y.y, s = r = 0; + } else { + const y = i, C = y.width / 2, w = y.height / 2; + t = y.x + C, n = y.y + w, a = o = Math.max(0, Math.min(y.radius, Math.min(C, w))), s = C - a, r = w - o; + } + if (s < 0 || r < 0) + return !1; + const l = Math.ceil(2.3 * Math.sqrt(a + o)), h = l * 8 + (s ? 4 : 0) + (r ? 4 : 0); + if (h === 0) + return !1; + if (l === 0) + return e[0] = e[6] = t + s, e[1] = e[3] = n + r, e[2] = e[4] = t - s, e[5] = e[7] = n - r, !0; + let u = 0, c = l * 4 + (s ? 2 : 0) + 2, d = c, f = h, _ = s + a, b = r, m = t + _, x = t - _, g = n + b; + if (e[u++] = m, e[u++] = g, e[--c] = g, e[--c] = x, r) { + const y = n - b; + e[d++] = x, e[d++] = y, e[--f] = y, e[--f] = m; + } + for (let y = 1; y < l; y++) { + const C = Math.PI / 2 * (y / l), w = s + Math.cos(C) * a, v = r + Math.sin(C) * o, D = t + w, S = t - w, A = n + v, E = n - v; + e[u++] = D, e[u++] = A, e[--c] = A, e[--c] = S, e[d++] = S, e[d++] = E, e[--f] = E, e[--f] = D; + } + _ = s, b = r + o, m = t + _, x = t - _, g = n + b; + const p = n - b; + return e[u++] = m, e[u++] = g, e[--f] = p, e[--f] = m, s && (e[u++] = x, e[u++] = g, e[--f] = p, e[--f] = x), !0; + }, + triangulate(i, e, t, n, s, r) { + if (i.length === 0) + return; + let a = 0, o = 0; + for (let u = 0; u < i.length; u += 2) + a += i[u], o += i[u + 1]; + a /= i.length / 2, o /= i.length / 2; + let l = n; + e[l * t] = a, e[l * t + 1] = o; + const h = l++; + for (let u = 0; u < i.length; u += 2) + e[l * t] = i[u], e[l * t + 1] = i[u + 1], u > 0 && (s[r++] = l, s[r++] = h, s[r++] = l - 1), l++; + s[r++] = h + 1, s[r++] = h, s[r++] = l - 1; + } +}, kd = { ...In, extension: { ...In.extension, name: "ellipse" } }, Ad = { ...In, extension: { ...In.extension, name: "roundedRectangle" } }, Il = 1e-4, aa = 1e-4; +function Dd(i) { + const e = i.length; + if (e < 6) + return 1; + let t = 0; + for (let n = 0, s = i[e - 2], r = i[e - 1]; n < e; n += 2) { + const a = i[n], o = i[n + 1]; + t += (a - s) * (o + r), s = a, r = o; + } + return t < 0 ? -1 : 1; +} +function oa(i, e, t, n, s, r, a, o) { + const l = i - t * s, h = e - n * s, u = i + t * r, c = e + n * r; + let d, f; + a ? (d = n, f = -t) : (d = -n, f = t); + const _ = l + d, b = h + f, m = u + d, x = c + f; + return o.push(_, b), o.push(m, x), 2; +} +function Mt(i, e, t, n, s, r, a, o) { + const l = t - i, h = n - e; + let u = Math.atan2(l, h), c = Math.atan2(s - i, r - e); + o && u < c ? u += Math.PI * 2 : !o && u > c && (c += Math.PI * 2); + let d = u; + const f = c - u, _ = Math.abs(f), b = Math.sqrt(l * l + h * h), m = (15 * _ * Math.sqrt(b) / Math.PI >> 0) + 1, x = f / m; + if (d += x, o) { + a.push(i, e), a.push(t, n); + for (let g = 1, p = d; g < m; g++, p += x) + a.push(i, e), a.push( + i + Math.sin(p) * b, + e + Math.cos(p) * b + ); + a.push(i, e), a.push(s, r); + } else { + a.push(t, n), a.push(i, e); + for (let g = 1, p = d; g < m; g++, p += x) + a.push( + i + Math.sin(p) * b, + e + Math.cos(p) * b + ), a.push(i, e); + a.push(s, r), a.push(i, e); + } + return m * 2; +} +function Ed(i, e, t, n, s, r) { + const a = Il; + if (i.length === 0) + return; + const o = e; + let l = o.alignment; + if (e.alignment !== 0.5) { + let O = Dd(i); + l = (l - 0.5) * O + 0.5; + } + const h = new Ae(i[0], i[1]), u = new Ae(i[i.length - 2], i[i.length - 1]), c = n, d = Math.abs(h.x - u.x) < a && Math.abs(h.y - u.y) < a; + if (c) { + i = i.slice(), d && (i.pop(), i.pop(), u.set(i[i.length - 2], i[i.length - 1])); + const O = (h.x + u.x) * 0.5, ce = (u.y + h.y) * 0.5; + i.unshift(O, ce), i.push(O, ce); + } + const f = s, _ = i.length / 2; + let b = i.length; + const m = f.length / 2, x = o.width / 2, g = x * x, p = o.miterLimit * o.miterLimit; + let y = i[0], C = i[1], w = i[2], v = i[3], D = 0, S = 0, A = -(C - v), E = y - w, I = 0, B = 0, N = Math.sqrt(A * A + E * E); + A /= N, E /= N, A *= x, E *= x; + const Y = l, F = (1 - Y) * 2, T = Y * 2; + c || (o.cap === "round" ? b += Mt( + y - A * (F - T) * 0.5, + C - E * (F - T) * 0.5, + y - A * F, + C - E * F, + y + A * T, + C + E * T, + f, + !0 + ) + 2 : o.cap === "square" && (b += oa(y, C, A, E, F, T, !0, f))), f.push( + y - A * F, + C - E * F + ), f.push( + y + A * T, + C + E * T + ); + for (let O = 1; O < _ - 1; ++O) { + y = i[(O - 1) * 2], C = i[(O - 1) * 2 + 1], w = i[O * 2], v = i[O * 2 + 1], D = i[(O + 1) * 2], S = i[(O + 1) * 2 + 1], A = -(C - v), E = y - w, N = Math.sqrt(A * A + E * E), A /= N, E /= N, A *= x, E *= x, I = -(v - S), B = w - D, N = Math.sqrt(I * I + B * B), I /= N, B /= N, I *= x, B *= x; + const ce = w - y, $ = C - v, ne = w - D, we = S - v, _e = ce * ne + $ * we, ve = $ * ne - we * ce, me = ve < 0; + if (Math.abs(ve) < 1e-3 * Math.abs(_e)) { + f.push( + w - A * F, + v - E * F + ), f.push( + w + A * T, + v + E * T + ), _e >= 0 && (o.join === "round" ? b += Mt( + w, + v, + w - A * F, + v - E * F, + w - I * F, + v - B * F, + f, + !1 + ) + 4 : b += 2, f.push( + w - I * T, + v - B * T + ), f.push( + w + I * F, + v + B * F + )); + continue; + } + const Je = (-A + y) * (-E + v) - (-A + w) * (-E + C), M = (-I + D) * (-B + v) - (-I + w) * (-B + S), Re = (ce * M - ne * Je) / ve, dt = (we * Je - $ * M) / ve, ft = (Re - w) * (Re - w) + (dt - v) * (dt - v), et = w + (Re - w) * F, k = v + (dt - v) * F, R = w - (Re - w) * T, G = v - (dt - v) * T, X = Math.min(ce * ce + $ * $, ne * ne + we * we), q = me ? F : T, ae = X + q * q * g; + ft <= ae ? o.join === "bevel" || ft / g > p ? (me ? (f.push(et, k), f.push(w + A * T, v + E * T), f.push(et, k), f.push(w + I * T, v + B * T)) : (f.push(w - A * F, v - E * F), f.push(R, G), f.push(w - I * F, v - B * F), f.push(R, G)), b += 2) : o.join === "round" ? me ? (f.push(et, k), f.push(w + A * T, v + E * T), b += Mt( + w, + v, + w + A * T, + v + E * T, + w + I * T, + v + B * T, + f, + !0 + ) + 4, f.push(et, k), f.push(w + I * T, v + B * T)) : (f.push(w - A * F, v - E * F), f.push(R, G), b += Mt( + w, + v, + w - A * F, + v - E * F, + w - I * F, + v - B * F, + f, + !1 + ) + 4, f.push(w - I * F, v - B * F), f.push(R, G)) : (f.push(et, k), f.push(R, G)) : (f.push(w - A * F, v - E * F), f.push(w + A * T, v + E * T), o.join === "round" ? me ? b += Mt( + w, + v, + w + A * T, + v + E * T, + w + I * T, + v + B * T, + f, + !0 + ) + 2 : b += Mt( + w, + v, + w - A * F, + v - E * F, + w - I * F, + v - B * F, + f, + !1 + ) + 2 : o.join === "miter" && ft / g <= p && (me ? (f.push(R, G), f.push(R, G)) : (f.push(et, k), f.push(et, k)), b += 2), f.push(w - I * F, v - B * F), f.push(w + I * T, v + B * T), b += 2); + } + y = i[(_ - 2) * 2], C = i[(_ - 2) * 2 + 1], w = i[(_ - 1) * 2], v = i[(_ - 1) * 2 + 1], A = -(C - v), E = y - w, N = Math.sqrt(A * A + E * E), A /= N, E /= N, A *= x, E *= x, f.push(w - A * F, v - E * F), f.push(w + A * T, v + E * T), c || (o.cap === "round" ? b += Mt( + w - A * (F - T) * 0.5, + v - E * (F - T) * 0.5, + w - A * F, + v - E * F, + w + A * T, + v + E * T, + f, + !1 + ) + 2 : o.cap === "square" && (b += oa(w, v, A, E, F, T, !1, f))); + const U = aa * aa; + for (let O = m; O < b + m - 2; ++O) + y = f[O * 2], C = f[O * 2 + 1], w = f[(O + 1) * 2], v = f[(O + 1) * 2 + 1], D = f[(O + 2) * 2], S = f[(O + 2) * 2 + 1], !(Math.abs(y * (v - S) + w * (S - C) + D * (C - v)) < U) && r.push(O, O + 1, O + 2); +} +function Fd(i, e, t, n) { + const s = Il; + if (i.length === 0) + return; + const r = i[0], a = i[1], o = i[i.length - 2], l = i[i.length - 1], h = e || Math.abs(r - o) < s && Math.abs(a - l) < s, u = t, c = i.length / 2, d = u.length / 2; + for (let f = 0; f < c; f++) + u.push(i[f * 2]), u.push(i[f * 2 + 1]); + for (let f = 0; f < c - 1; f++) + n.push(d + f, d + f + 1); + h && n.push(d + c - 1, d); +} +function Rl(i, e, t, n, s, r, a) { + const o = uc(i, e, 2); + if (!o) + return; + for (let h = 0; h < o.length; h += 3) + r[a++] = o[h] + s, r[a++] = o[h + 1] + s, r[a++] = o[h + 2] + s; + let l = s * n; + for (let h = 0; h < i.length; h += 2) + t[l] = i[h], t[l + 1] = i[h + 1], l += n; +} +const $d = [], Td = { + extension: { + type: Q.ShapeBuilder, + name: "polygon" + }, + build(i, e) { + for (let t = 0; t < i.points.length; t++) + e[t] = i.points[t]; + return !0; + }, + triangulate(i, e, t, n, s, r) { + Rl(i, $d, e, t, n, s, r); + } +}, Md = { + extension: { + type: Q.ShapeBuilder, + name: "rectangle" + }, + build(i, e) { + const t = i, n = t.x, s = t.y, r = t.width, a = t.height; + return r > 0 && a > 0 ? (e[0] = n, e[1] = s, e[2] = n + r, e[3] = s, e[4] = n + r, e[5] = s + a, e[6] = n, e[7] = s + a, !0) : !1; + }, + triangulate(i, e, t, n, s, r) { + let a = 0; + n *= t, e[n + a] = i[0], e[n + a + 1] = i[1], a += t, e[n + a] = i[2], e[n + a + 1] = i[3], a += t, e[n + a] = i[6], e[n + a + 1] = i[7], a += t, e[n + a] = i[4], e[n + a + 1] = i[5], a += t; + const o = n / t; + s[r++] = o, s[r++] = o + 1, s[r++] = o + 2, s[r++] = o + 1, s[r++] = o + 3, s[r++] = o + 2; + } +}, Pd = { + extension: { + type: Q.ShapeBuilder, + name: "triangle" + }, + build(i, e) { + return e[0] = i.x, e[1] = i.y, e[2] = i.x2, e[3] = i.y2, e[4] = i.x3, e[5] = i.y3, !0; + }, + triangulate(i, e, t, n, s, r) { + let a = 0; + n *= t, e[n + a] = i[0], e[n + a + 1] = i[1], a += t, e[n + a] = i[2], e[n + a + 1] = i[3], a += t, e[n + a] = i[4], e[n + a + 1] = i[5]; + const o = n / t; + s[r++] = o, s[r++] = o + 1, s[r++] = o + 2; + } +}, Id = new H(), Rd = new de(); +function Bd(i, e, t, n) { + const s = e.matrix ? i.copyFrom(e.matrix).invert() : i.identity(); + if (e.textureSpace === "local") { + const a = t.getBounds(Rd); + e.width && a.pad(e.width); + const { x: o, y: l } = a, h = 1 / a.width, u = 1 / a.height, c = -o * h, d = -l * u, f = s.a, _ = s.b, b = s.c, m = s.d; + s.a *= h, s.b *= h, s.c *= u, s.d *= u, s.tx = c * f + d * b + s.tx, s.ty = c * _ + d * m + s.ty; + } else + s.translate(e.texture.frame.x, e.texture.frame.y), s.scale(1 / e.texture.source.width, 1 / e.texture.source.height); + const r = e.texture.source.style; + return !(e.fill instanceof Et) && r.addressMode === "clamp-to-edge" && (r.addressMode = "repeat", r.update()), n && s.append(Id.copyFrom(n).invert()), s; +} +const Fi = {}; +Qe.handleByMap(Q.ShapeBuilder, Fi); +Qe.add(Md, Td, Pd, In, kd, Ad); +const Ld = new de(), Od = new H(); +function zd(i, e) { + const { geometryData: t, batches: n } = e; + n.length = 0, t.indices.length = 0, t.vertices.length = 0, t.uvs.length = 0; + for (let s = 0; s < i.instructions.length; s++) { + const r = i.instructions[s]; + if (r.action === "texture") + Nd(r.data, n, t); + else if (r.action === "fill" || r.action === "stroke") { + const a = r.action === "stroke", o = r.data.path.shapePath, l = r.data.style, h = r.data.hole; + a && h && la(h.shapePath, l, !0, n, t), h && (o.shapePrimitives[o.shapePrimitives.length - 1].holes = h.shapePath.shapePrimitives), la(o, l, a, n, t); + } + } +} +function Nd(i, e, t) { + const n = [], s = Fi.rectangle, r = Ld; + r.x = i.dx, r.y = i.dy, r.width = i.dw, r.height = i.dh; + const a = i.transform; + if (!s.build(r, n)) + return; + const { vertices: o, uvs: l, indices: h } = t, u = h.length, c = o.length / 2; + a && Ml(n, a), s.triangulate(n, o, 2, c, h, u); + const d = i.image, f = d.uvs; + l.push( + f.x0, + f.y0, + f.x1, + f.y1, + f.x3, + f.y3, + f.x2, + f.y2 + ); + const _ = Ze.get(Pl); + _.indexOffset = u, _.indexSize = h.length - u, _.attributeOffset = c, _.attributeSize = o.length / 2 - c, _.baseColor = i.style, _.alpha = i.alpha, _.texture = d, _.geometryData = t, e.push(_); +} +function la(i, e, t, n, s) { + const { vertices: r, uvs: a, indices: o } = s; + i.shapePrimitives.forEach(({ shape: l, transform: h, holes: u }) => { + const c = [], d = Fi[l.type]; + if (!d.build(l, c)) + return; + const f = o.length, _ = r.length / 2; + let b = "triangle-list"; + if (h && Ml(c, h), t) { + const p = l.closePath ?? !0, y = e; + y.pixelLine ? (Fd(c, p, r, o), b = "line-list") : Ed(c, y, !1, p, r, o); + } else if (u) { + const p = [], y = c.slice(); + Gd(u).forEach((w) => { + p.push(y.length / 2), y.push(...w); + }), Rl(y, p, r, 2, _, o, f); + } else + d.triangulate(c, r, 2, _, o, f); + const m = a.length / 2, x = e.texture; + if (x !== K.WHITE) { + const p = Bd(Od, e, l, h); + vd(r, 2, _, a, m, 2, r.length / 2 - _, p); + } else + Cd(a, m, 2, r.length / 2 - _); + const g = Ze.get(Pl); + g.indexOffset = f, g.indexSize = o.length - f, g.attributeOffset = _, g.attributeSize = r.length / 2 - _, g.baseColor = e.color, g.alpha = e.alpha, g.texture = x, g.geometryData = s, g.topology = b, n.push(g); + }); +} +function Gd(i) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t].shape, s = []; + Fi[n.type].build(n, s) && e.push(s); + } + return e; +} +class qd { + constructor() { + this.batches = [], this.geometryData = { + vertices: [], + uvs: [], + indices: [] + }; + } +} +class Ud { + constructor() { + this.instructions = new Go(); + } + init(e) { + this.batcher = new wd({ + maxTextures: e + }), this.instructions.reset(); + } + /** + * @deprecated since version 8.0.0 + * Use `batcher.geometry` instead. + * @see {Batcher#geometry} + */ + get geometry() { + return W(Ph, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead."), this.batcher.geometry; + } + destroy() { + this.batcher.destroy(), this.instructions.destroy(), this.batcher = null, this.instructions = null; + } +} +const Js = class As { + constructor(e) { + this._gpuContextHash = {}, this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null), this._renderer = e, e.renderableGC.addManagedHash(this, "_gpuContextHash"), e.renderableGC.addManagedHash(this, "_graphicsDataContextHash"); + } + /** + * Runner init called, update the default options + * @ignore + */ + init(e) { + As.defaultOptions.bezierSmoothness = (e == null ? void 0 : e.bezierSmoothness) ?? As.defaultOptions.bezierSmoothness; + } + /** + * Returns the render data for a given GraphicsContext. + * @param context - The GraphicsContext to get the render data for. + * @internal + */ + getContextRenderData(e) { + return this._graphicsDataContextHash[e.uid] || this._initContextRenderData(e); + } + /** + * Updates the GPU context for a given GraphicsContext. + * If the context is dirty, it will rebuild the batches and geometry data. + * @param context - The GraphicsContext to update. + * @returns The updated GpuGraphicsContext. + * @internal + */ + updateGpuContext(e) { + let t = this._gpuContextHash[e.uid] || this._initContext(e); + if (e.dirty) { + t ? this._cleanGraphicsContextData(e) : t = this._initContext(e), zd(e, t); + const n = e.batchMode; + e.customShader || n === "no-batch" ? t.isBatchable = !1 : n === "auto" ? t.isBatchable = t.geometryData.vertices.length < 400 : t.isBatchable = !0, e.dirty = !1; + } + return t; + } + /** + * Returns the GpuGraphicsContext for a given GraphicsContext. + * If it does not exist, it will initialize a new one. + * @param context - The GraphicsContext to get the GpuGraphicsContext for. + * @returns The GpuGraphicsContext for the given GraphicsContext. + * @internal + */ + getGpuContext(e) { + return this._gpuContextHash[e.uid] || this._initContext(e); + } + _initContextRenderData(e) { + const t = Ze.get(Ud, { + maxTextures: this._renderer.limits.maxBatchableTextures + }), { batches: n, geometryData: s } = this._gpuContextHash[e.uid], r = s.vertices.length, a = s.indices.length; + for (let u = 0; u < n.length; u++) + n[u].applyTransform = !1; + const o = t.batcher; + o.ensureAttributeBuffer(r), o.ensureIndexBuffer(a), o.begin(); + for (let u = 0; u < n.length; u++) { + const c = n[u]; + o.add(c); + } + o.finish(t.instructions); + const l = o.geometry; + l.indexBuffer.setDataWithSize(o.indexBuffer, o.indexSize, !0), l.buffers[0].setDataWithSize(o.attributeBuffer.float32View, o.attributeSize, !0); + const h = o.batches; + for (let u = 0; u < h.length; u++) { + const c = h[u]; + c.bindGroup = Tc( + c.textures.textures, + c.textures.count, + this._renderer.limits.maxBatchableTextures + ); + } + return this._graphicsDataContextHash[e.uid] = t, t; + } + _initContext(e) { + const t = new qd(); + return t.context = e, this._gpuContextHash[e.uid] = t, e.on("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[e.uid]; + } + onGraphicsContextDestroy(e) { + this._cleanGraphicsContextData(e), e.off("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[e.uid] = null; + } + _cleanGraphicsContextData(e) { + const t = this._gpuContextHash[e.uid]; + t.isBatchable || this._graphicsDataContextHash[e.uid] && (Ze.return(this.getContextRenderData(e)), this._graphicsDataContextHash[e.uid] = null), t.batches && t.batches.forEach((n) => { + Ze.return(n); + }); + } + destroy() { + for (const e in this._gpuContextHash) + this._gpuContextHash[e] && this.onGraphicsContextDestroy(this._gpuContextHash[e].context); + } +}; +Js.extension = { + type: [ + Q.WebGLSystem, + Q.WebGPUSystem, + Q.CanvasSystem + ], + name: "graphicsContext" +}; +Js.defaultOptions = { + /** + * A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother) + * @default 0.5 + */ + bezierSmoothness: 0.5 +}; +let Bl = Js; +const Hd = 8, ei = 11920929e-14, Vd = 1; +function Ll(i, e, t, n, s, r, a, o, l, h) { + const c = Math.min( + 0.99, + // a value of 1.0 actually inverts smoothing, so we cap it at 0.99 + Math.max(0, h ?? Bl.defaultOptions.bezierSmoothness) + ); + let d = (Vd - c) / 1; + return d *= d, Wd(e, t, n, s, r, a, o, l, i, d), i; +} +function Wd(i, e, t, n, s, r, a, o, l, h) { + Ds(i, e, t, n, s, r, a, o, l, h, 0), l.push(a, o); +} +function Ds(i, e, t, n, s, r, a, o, l, h, u) { + if (u > Hd) + return; + const c = (i + t) / 2, d = (e + n) / 2, f = (t + s) / 2, _ = (n + r) / 2, b = (s + a) / 2, m = (r + o) / 2, x = (c + f) / 2, g = (d + _) / 2, p = (f + b) / 2, y = (_ + m) / 2, C = (x + p) / 2, w = (g + y) / 2; + if (u > 0) { + let v = a - i, D = o - e; + const S = Math.abs((t - a) * D - (n - o) * v), A = Math.abs((s - a) * D - (r - o) * v); + if (S > ei && A > ei) { + if ((S + A) * (S + A) <= h * (v * v + D * D)) { + l.push(C, w); + return; + } + } else if (S > ei) { + if (S * S <= h * (v * v + D * D)) { + l.push(C, w); + return; + } + } else if (A > ei) { + if (A * A <= h * (v * v + D * D)) { + l.push(C, w); + return; + } + } else if (v = C - (i + a) / 2, D = w - (e + o) / 2, v * v + D * D <= h) { + l.push(C, w); + return; + } + } + Ds(i, e, c, d, x, g, C, w, l, h, u + 1), Ds(C, w, p, y, b, m, a, o, l, h, u + 1); +} +const Yd = 8, Xd = 11920929e-14, jd = 1; +function Zd(i, e, t, n, s, r, a, o) { + const h = Math.min( + 0.99, + // a value of 1.0 actually inverts smoothing, so we cap it at 0.99 + Math.max(0, o ?? Bl.defaultOptions.bezierSmoothness) + ); + let u = (jd - h) / 1; + return u *= u, Kd(e, t, n, s, r, a, i, u), i; +} +function Kd(i, e, t, n, s, r, a, o) { + Es(a, i, e, t, n, s, r, o, 0), a.push(s, r); +} +function Es(i, e, t, n, s, r, a, o, l) { + if (l > Yd) + return; + const h = (e + n) / 2, u = (t + s) / 2, c = (n + r) / 2, d = (s + a) / 2, f = (h + c) / 2, _ = (u + d) / 2; + let b = r - e, m = a - t; + const x = Math.abs((n - r) * m - (s - a) * b); + if (x > Xd) { + if (x * x <= o * (b * b + m * m)) { + i.push(f, _); + return; + } + } else if (b = f - (e + r) / 2, m = _ - (t + a) / 2, b * b + m * m <= o) { + i.push(f, _); + return; + } + Es(i, e, t, h, u, f, _, o, l + 1), Es(i, f, _, c, d, r, a, o, l + 1); +} +function Ol(i, e, t, n, s, r, a, o) { + let l = Math.abs(s - r); + (!a && s > r || a && r > s) && (l = 2 * Math.PI - l), o || (o = Math.max(6, Math.floor(6 * Math.pow(n, 1 / 3) * (l / Math.PI)))), o = Math.max(o, 3); + let h = l / o, u = s; + h *= a ? -1 : 1; + for (let c = 0; c < o + 1; c++) { + const d = Math.cos(u), f = Math.sin(u), _ = e + d * n, b = t + f * n; + i.push(_, b), u += h; + } +} +function Qd(i, e, t, n, s, r) { + const a = i[i.length - 2], l = i[i.length - 1] - t, h = a - e, u = s - t, c = n - e, d = Math.abs(l * c - h * u); + if (d < 1e-8 || r === 0) { + (i[i.length - 2] !== e || i[i.length - 1] !== t) && i.push(e, t); + return; + } + const f = l * l + h * h, _ = u * u + c * c, b = l * u + h * c, m = r * Math.sqrt(f) / d, x = r * Math.sqrt(_) / d, g = m * b / f, p = x * b / _, y = m * c + x * h, C = m * u + x * l, w = h * (x + g), v = l * (x + g), D = c * (m + p), S = u * (m + p), A = Math.atan2(v - C, w - y), E = Math.atan2(S - C, D - y); + Ol( + i, + y + e, + C + t, + r, + A, + E, + h * u > c * l + ); +} +const Sn = Math.PI * 2, Qi = { + centerX: 0, + centerY: 0, + ang1: 0, + ang2: 0 +}, Ji = ({ x: i, y: e }, t, n, s, r, a, o, l) => { + i *= t, e *= n; + const h = s * i - r * e, u = r * i + s * e; + return l.x = h + a, l.y = u + o, l; +}; +function Jd(i, e) { + const t = e === -1.5707963267948966 ? -0.551915024494 : 1.3333333333333333 * Math.tan(e / 4), n = e === 1.5707963267948966 ? 0.551915024494 : t, s = Math.cos(i), r = Math.sin(i), a = Math.cos(i + e), o = Math.sin(i + e); + return [ + { + x: s - r * n, + y: r + s * n + }, + { + x: a + o * n, + y: o - a * n + }, + { + x: a, + y: o + } + ]; +} +const ha = (i, e, t, n) => { + const s = i * n - e * t < 0 ? -1 : 1; + let r = i * t + e * n; + return r > 1 && (r = 1), r < -1 && (r = -1), s * Math.acos(r); +}, ef = (i, e, t, n, s, r, a, o, l, h, u, c, d) => { + const f = Math.pow(s, 2), _ = Math.pow(r, 2), b = Math.pow(u, 2), m = Math.pow(c, 2); + let x = f * _ - f * m - _ * b; + x < 0 && (x = 0), x /= f * m + _ * b, x = Math.sqrt(x) * (a === o ? -1 : 1); + const g = x * s / r * c, p = x * -r / s * u, y = h * g - l * p + (i + t) / 2, C = l * g + h * p + (e + n) / 2, w = (u - g) / s, v = (c - p) / r, D = (-u - g) / s, S = (-c - p) / r, A = ha(1, 0, w, v); + let E = ha(w, v, D, S); + o === 0 && E > 0 && (E -= Sn), o === 1 && E < 0 && (E += Sn), d.centerX = y, d.centerY = C, d.ang1 = A, d.ang2 = E; +}; +function tf(i, e, t, n, s, r, a, o = 0, l = 0, h = 0) { + if (r === 0 || a === 0) + return; + const u = Math.sin(o * Sn / 360), c = Math.cos(o * Sn / 360), d = c * (e - n) / 2 + u * (t - s) / 2, f = -u * (e - n) / 2 + c * (t - s) / 2; + if (d === 0 && f === 0) + return; + r = Math.abs(r), a = Math.abs(a); + const _ = Math.pow(d, 2) / Math.pow(r, 2) + Math.pow(f, 2) / Math.pow(a, 2); + _ > 1 && (r *= Math.sqrt(_), a *= Math.sqrt(_)), ef( + e, + t, + n, + s, + r, + a, + l, + h, + u, + c, + d, + f, + Qi + ); + let { ang1: b, ang2: m } = Qi; + const { centerX: x, centerY: g } = Qi; + let p = Math.abs(m) / (Sn / 4); + Math.abs(1 - p) < 1e-7 && (p = 1); + const y = Math.max(Math.ceil(p), 1); + m /= y; + let C = i[i.length - 2], w = i[i.length - 1]; + const v = { x: 0, y: 0 }; + for (let D = 0; D < y; D++) { + const S = Jd(b, m), { x: A, y: E } = Ji(S[0], r, a, c, u, x, g, v), { x: I, y: B } = Ji(S[1], r, a, c, u, x, g, v), { x: N, y: Y } = Ji(S[2], r, a, c, u, x, g, v); + Ll( + i, + C, + w, + A, + E, + I, + B, + N, + Y + ), C = N, w = Y, b += m; + } +} +function nf(i, e, t) { + const n = (a, o) => { + const l = o.x - a.x, h = o.y - a.y, u = Math.sqrt(l * l + h * h), c = l / u, d = h / u; + return { len: u, nx: c, ny: d }; + }, s = (a, o) => { + a === 0 ? i.moveTo(o.x, o.y) : i.lineTo(o.x, o.y); + }; + let r = e[e.length - 1]; + for (let a = 0; a < e.length; a++) { + const o = e[a % e.length], l = o.radius ?? t; + if (l <= 0) { + s(a, o), r = o; + continue; + } + const h = e[(a + 1) % e.length], u = n(o, r), c = n(o, h); + if (u.len < 1e-4 || c.len < 1e-4) { + s(a, o), r = o; + continue; + } + let d = Math.asin(u.nx * c.ny - u.ny * c.nx), f = 1, _ = !1; + u.nx * c.nx - u.ny * -c.ny < 0 ? d < 0 ? d = Math.PI + d : (d = Math.PI - d, f = -1, _ = !0) : d > 0 && (f = -1, _ = !0); + const b = d / 2; + let m, x = Math.abs( + Math.cos(b) * l / Math.sin(b) + ); + x > Math.min(u.len / 2, c.len / 2) ? (x = Math.min(u.len / 2, c.len / 2), m = Math.abs(x * Math.sin(b) / Math.cos(b))) : m = l; + const g = o.x + c.nx * x + -c.ny * m * f, p = o.y + c.ny * x + c.nx * m * f, y = Math.atan2(u.ny, u.nx) + Math.PI / 2 * f, C = Math.atan2(c.ny, c.nx) - Math.PI / 2 * f; + a === 0 && i.moveTo( + g + Math.cos(y) * m, + p + Math.sin(y) * m + ), i.arc(g, p, m, y, C, _), r = o; + } +} +function sf(i, e, t, n) { + const s = (o, l) => Math.sqrt((o.x - l.x) ** 2 + (o.y - l.y) ** 2), r = (o, l, h) => ({ + x: o.x + (l.x - o.x) * h, + y: o.y + (l.y - o.y) * h + }), a = e.length; + for (let o = 0; o < a; o++) { + const l = e[(o + 1) % a], h = l.radius ?? t; + if (h <= 0) { + o === 0 ? i.moveTo(l.x, l.y) : i.lineTo(l.x, l.y); + continue; + } + const u = e[o], c = e[(o + 2) % a], d = s(u, l); + let f; + if (d < 1e-4) + f = l; + else { + const m = Math.min(d / 2, h); + f = r( + l, + u, + m / d + ); + } + const _ = s(c, l); + let b; + if (_ < 1e-4) + b = l; + else { + const m = Math.min(_ / 2, h); + b = r( + l, + c, + m / _ + ); + } + o === 0 ? i.moveTo(f.x, f.y) : i.lineTo(f.x, f.y), i.quadraticCurveTo(l.x, l.y, b.x, b.y, n); + } +} +const rf = new de(); +class af { + constructor(e) { + this.shapePrimitives = [], this._currentPoly = null, this._bounds = new ht(), this._graphicsPath2D = e, this.signed = e.checkForHoles; + } + /** + * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path. + * @param x - The x-coordinate for the starting point. + * @param y - The y-coordinate for the starting point. + * @returns The instance of the current object for chaining. + */ + moveTo(e, t) { + return this.startPoly(e, t), this; + } + /** + * Connects the current point to a new point with a straight line. This method updates the current path. + * @param x - The x-coordinate of the new point to connect to. + * @param y - The y-coordinate of the new point to connect to. + * @returns The instance of the current object for chaining. + */ + lineTo(e, t) { + this._ensurePoly(); + const n = this._currentPoly.points, s = n[n.length - 2], r = n[n.length - 1]; + return (s !== e || r !== t) && n.push(e, t), this; + } + /** + * Adds an arc to the path. The arc is centered at (x, y) + * position with radius `radius` starting at `startAngle` and ending at `endAngle`. + * @param x - The x-coordinate of the arc's center. + * @param y - The y-coordinate of the arc's center. + * @param radius - The radius of the arc. + * @param startAngle - The starting angle of the arc, in radians. + * @param endAngle - The ending angle of the arc, in radians. + * @param counterclockwise - Specifies whether the arc should be drawn in the anticlockwise direction. False by default. + * @returns The instance of the current object for chaining. + */ + arc(e, t, n, s, r, a) { + this._ensurePoly(!1); + const o = this._currentPoly.points; + return Ol(o, e, t, n, s, r, a), this; + } + /** + * Adds an arc to the path with the arc tangent to the line joining two specified points. + * The arc radius is specified by `radius`. + * @param x1 - The x-coordinate of the first point. + * @param y1 - The y-coordinate of the first point. + * @param x2 - The x-coordinate of the second point. + * @param y2 - The y-coordinate of the second point. + * @param radius - The radius of the arc. + * @returns The instance of the current object for chaining. + */ + arcTo(e, t, n, s, r) { + this._ensurePoly(); + const a = this._currentPoly.points; + return Qd(a, e, t, n, s, r), this; + } + /** + * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec. + * @param rx - The x-radius of the ellipse. + * @param ry - The y-radius of the ellipse. + * @param xAxisRotation - The rotation of the ellipse's x-axis relative + * to the x-axis of the coordinate system, in degrees. + * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees. + * @param sweepFlag - Determines if the arc should be swept in a positive angle direction. + * @param x - The x-coordinate of the arc's end point. + * @param y - The y-coordinate of the arc's end point. + * @returns The instance of the current object for chaining. + */ + arcToSvg(e, t, n, s, r, a, o) { + const l = this._currentPoly.points; + return tf( + l, + this._currentPoly.lastX, + this._currentPoly.lastY, + a, + o, + e, + t, + n, + s, + r + ), this; + } + /** + * Adds a cubic Bezier curve to the path. + * It requires three points: the first two are control points and the third one is the end point. + * The starting point is the last point in the current path. + * @param cp1x - The x-coordinate of the first control point. + * @param cp1y - The y-coordinate of the first control point. + * @param cp2x - The x-coordinate of the second control point. + * @param cp2y - The y-coordinate of the second control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothness - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + bezierCurveTo(e, t, n, s, r, a, o) { + this._ensurePoly(); + const l = this._currentPoly; + return Ll( + this._currentPoly.points, + l.lastX, + l.lastY, + e, + t, + n, + s, + r, + a, + o + ), this; + } + /** + * Adds a quadratic curve to the path. It requires two points: the control point and the end point. + * The starting point is the last point in the current path. + * @param cp1x - The x-coordinate of the control point. + * @param cp1y - The y-coordinate of the control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothing - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + quadraticCurveTo(e, t, n, s, r) { + this._ensurePoly(); + const a = this._currentPoly; + return Zd( + this._currentPoly.points, + a.lastX, + a.lastY, + e, + t, + n, + s, + r + ), this; + } + /** + * Closes the current path by drawing a straight line back to the start. + * If the shape is already closed or there are no points in the path, this method does nothing. + * @returns The instance of the current object for chaining. + */ + closePath() { + return this.endPoly(!0), this; + } + /** + * Adds another path to the current path. This method allows for the combination of multiple paths into one. + * @param path - The `GraphicsPath` object representing the path to add. + * @param transform - An optional `Matrix` object to apply a transformation to the path before adding it. + * @returns The instance of the current object for chaining. + */ + addPath(e, t) { + this.endPoly(), t && !t.isIdentity() && (e = e.clone(!0), e.transform(t)); + const n = this.shapePrimitives, s = n.length; + for (let r = 0; r < e.instructions.length; r++) { + const a = e.instructions[r]; + this[a.action](...a.data); + } + if (e.checkForHoles && n.length - s > 1) { + let r = null; + for (let a = s; a < n.length; a++) { + const o = n[a]; + if (o.shape.type === "polygon") { + const l = o.shape, h = r == null ? void 0 : r.shape; + h && h.containsPolygon(l) ? (r.holes || (r.holes = []), r.holes.push(o), n.copyWithin(a, a + 1), n.length--, a--) : r = o; + } + } + } + return this; + } + /** + * Finalizes the drawing of the current path. Optionally, it can close the path. + * @param closePath - A boolean indicating whether to close the path after finishing. False by default. + */ + finish(e = !1) { + this.endPoly(e); + } + /** + * Draws a rectangle shape. This method adds a new rectangle path to the current drawing. + * @param x - The x-coordinate of the top-left corner of the rectangle. + * @param y - The y-coordinate of the top-left corner of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @param transform - An optional `Matrix` object to apply a transformation to the rectangle. + * @returns The instance of the current object for chaining. + */ + rect(e, t, n, s, r) { + return this.drawShape(new de(e, t, n, s), r), this; + } + /** + * Draws a circle shape. This method adds a new circle path to the current drawing. + * @param x - The x-coordinate of the center of the circle. + * @param y - The y-coordinate of the center of the circle. + * @param radius - The radius of the circle. + * @param transform - An optional `Matrix` object to apply a transformation to the circle. + * @returns The instance of the current object for chaining. + */ + circle(e, t, n, s) { + return this.drawShape(new Zs(e, t, n), s), this; + } + /** + * Draws a polygon shape. This method allows for the creation of complex polygons by specifying a sequence of points. + * @param points - An array of numbers, or or an array of PointData objects eg [{x,y}, {x,y}, {x,y}] + * representing the x and y coordinates of the polygon's vertices, in sequence. + * @param close - A boolean indicating whether to close the polygon path. True by default. + * @param transform - An optional `Matrix` object to apply a transformation to the polygon. + * @returns The instance of the current object for chaining. + */ + poly(e, t, n) { + const s = new vn(e); + return s.closePath = t, this.drawShape(s, n), this; + } + /** + * Draws a regular polygon with a specified number of sides. All sides and angles are equal. + * @param x - The x-coordinate of the center of the polygon. + * @param y - The y-coordinate of the center of the polygon. + * @param radius - The radius of the circumscribed circle of the polygon. + * @param sides - The number of sides of the polygon. Must be 3 or more. + * @param rotation - The rotation angle of the polygon, in radians. Zero by default. + * @param transform - An optional `Matrix` object to apply a transformation to the polygon. + * @returns The instance of the current object for chaining. + */ + regularPoly(e, t, n, s, r = 0, a) { + s = Math.max(s | 0, 3); + const o = -1 * Math.PI / 2 + r, l = Math.PI * 2 / s, h = []; + for (let u = 0; u < s; u++) { + const c = o - u * l; + h.push( + e + n * Math.cos(c), + t + n * Math.sin(c) + ); + } + return this.poly(h, !0, a), this; + } + /** + * Draws a polygon with rounded corners. + * Similar to `regularPoly` but with the ability to round the corners of the polygon. + * @param x - The x-coordinate of the center of the polygon. + * @param y - The y-coordinate of the center of the polygon. + * @param radius - The radius of the circumscribed circle of the polygon. + * @param sides - The number of sides of the polygon. Must be 3 or more. + * @param corner - The radius of the rounding of the corners. + * @param rotation - The rotation angle of the polygon, in radians. Zero by default. + * @param smoothness - Optional parameter to adjust the smoothness of the rounding. + * @returns The instance of the current object for chaining. + */ + roundPoly(e, t, n, s, r, a = 0, o) { + if (s = Math.max(s | 0, 3), r <= 0) + return this.regularPoly(e, t, n, s, a); + const l = n * Math.sin(Math.PI / s) - 1e-3; + r = Math.min(r, l); + const h = -1 * Math.PI / 2 + a, u = Math.PI * 2 / s, c = (s - 2) * Math.PI / s / 2; + for (let d = 0; d < s; d++) { + const f = d * u + h, _ = e + n * Math.cos(f), b = t + n * Math.sin(f), m = f + Math.PI + c, x = f - Math.PI - c, g = _ + r * Math.cos(m), p = b + r * Math.sin(m), y = _ + r * Math.cos(x), C = b + r * Math.sin(x); + d === 0 ? this.moveTo(g, p) : this.lineTo(g, p), this.quadraticCurveTo(_, b, y, C, o); + } + return this.closePath(); + } + /** + * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape. + * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic. + * @param points - An array of `RoundedPoint` representing the corners of the shape to draw. + * A minimum of 3 points is required. + * @param radius - The default radius for the corners. + * This radius is applied to all corners unless overridden in `points`. + * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve + * method instead of an arc method. Defaults to false. + * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true. + * Higher values make the curve smoother. + * @returns The instance of the current object for chaining. + */ + roundShape(e, t, n = !1, s) { + return e.length < 3 ? this : (n ? sf(this, e, t, s) : nf(this, e, t), this.closePath()); + } + /** + * Draw Rectangle with fillet corners. This is much like rounded rectangle + * however it support negative numbers as well for the corner radius. + * @param x - Upper left corner of rect + * @param y - Upper right corner of rect + * @param width - Width of rect + * @param height - Height of rect + * @param fillet - accept negative or positive values + */ + filletRect(e, t, n, s, r) { + if (r === 0) + return this.rect(e, t, n, s); + const a = Math.min(n, s) / 2, o = Math.min(a, Math.max(-a, r)), l = e + n, h = t + s, u = o < 0 ? -o : 0, c = Math.abs(o); + return this.moveTo(e, t + c).arcTo(e + u, t + u, e + c, t, c).lineTo(l - c, t).arcTo(l - u, t + u, l, t + c, c).lineTo(l, h - c).arcTo(l - u, h - u, e + n - c, h, c).lineTo(e + c, h).arcTo(e + u, h - u, e, h - c, c).closePath(); + } + /** + * Draw Rectangle with chamfer corners. These are angled corners. + * @param x - Upper left corner of rect + * @param y - Upper right corner of rect + * @param width - Width of rect + * @param height - Height of rect + * @param chamfer - non-zero real number, size of corner cutout + * @param transform + */ + chamferRect(e, t, n, s, r, a) { + if (r <= 0) + return this.rect(e, t, n, s); + const o = Math.min(r, Math.min(n, s) / 2), l = e + n, h = t + s, u = [ + e + o, + t, + l - o, + t, + l, + t + o, + l, + h - o, + l - o, + h, + e + o, + h, + e, + h - o, + e, + t + o + ]; + for (let c = u.length - 1; c >= 2; c -= 2) + u[c] === u[c - 2] && u[c - 1] === u[c - 3] && u.splice(c - 1, 2); + return this.poly(u, !0, a); + } + /** + * Draws an ellipse at the specified location and with the given x and y radii. + * An optional transformation can be applied, allowing for rotation, scaling, and translation. + * @param x - The x-coordinate of the center of the ellipse. + * @param y - The y-coordinate of the center of the ellipse. + * @param radiusX - The horizontal radius of the ellipse. + * @param radiusY - The vertical radius of the ellipse. + * @param transform - An optional `Matrix` object to apply a transformation to the ellipse. This can include rotations. + * @returns The instance of the current object for chaining. + */ + ellipse(e, t, n, s, r) { + return this.drawShape(new Ks(e, t, n, s), r), this; + } + /** + * Draws a rectangle with rounded corners. + * The corner radius can be specified to determine how rounded the corners should be. + * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle. + * @param x - The x-coordinate of the top-left corner of the rectangle. + * @param y - The y-coordinate of the top-left corner of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp. + * @param transform - An optional `Matrix` object to apply a transformation to the rectangle. + * @returns The instance of the current object for chaining. + */ + roundRect(e, t, n, s, r, a) { + return this.drawShape(new Qs(e, t, n, s, r), a), this; + } + /** + * Draws a given shape on the canvas. + * This is a generic method that can draw any type of shape specified by the `ShapePrimitive` parameter. + * An optional transformation matrix can be applied to the shape, allowing for complex transformations. + * @param shape - The shape to draw, defined as a `ShapePrimitive` object. + * @param matrix - An optional `Matrix` for transforming the shape. This can include rotations, + * scaling, and translations. + * @returns The instance of the current object for chaining. + */ + drawShape(e, t) { + return this.endPoly(), this.shapePrimitives.push({ shape: e, transform: t }), this; + } + /** + * Starts a new polygon path from the specified starting point. + * This method initializes a new polygon or ends the current one if it exists. + * @param x - The x-coordinate of the starting point of the new polygon. + * @param y - The y-coordinate of the starting point of the new polygon. + * @returns The instance of the current object for chaining. + */ + startPoly(e, t) { + let n = this._currentPoly; + return n && this.endPoly(), n = new vn(), n.points.push(e, t), this._currentPoly = n, this; + } + /** + * Ends the current polygon path. If `closePath` is set to true, + * the path is closed by connecting the last point to the first one. + * This method finalizes the current polygon and prepares it for drawing or adding to the shape primitives. + * @param closePath - A boolean indicating whether to close the polygon by connecting the last point + * back to the starting point. False by default. + * @returns The instance of the current object for chaining. + */ + endPoly(e = !1) { + const t = this._currentPoly; + return t && t.points.length > 2 && (t.closePath = e, this.shapePrimitives.push({ shape: t })), this._currentPoly = null, this; + } + _ensurePoly(e = !0) { + if (!this._currentPoly && (this._currentPoly = new vn(), e)) { + const t = this.shapePrimitives[this.shapePrimitives.length - 1]; + if (t) { + let n = t.shape.x, s = t.shape.y; + if (t.transform && !t.transform.isIdentity()) { + const r = t.transform, a = n; + n = r.a * n + r.c * s + r.tx, s = r.b * a + r.d * s + r.ty; + } + this._currentPoly.points.push(n, s); + } else + this._currentPoly.points.push(0, 0); + } + } + /** Builds the path. */ + buildPath() { + const e = this._graphicsPath2D; + this.shapePrimitives.length = 0, this._currentPoly = null; + for (let t = 0; t < e.instructions.length; t++) { + const n = e.instructions[t]; + this[n.action](...n.data); + } + this.finish(); + } + /** Gets the bounds of the path. */ + get bounds() { + const e = this._bounds; + e.clear(); + const t = this.shapePrimitives; + for (let n = 0; n < t.length; n++) { + const s = t[n], r = s.shape.getBounds(rf); + s.transform ? e.addRect(r, s.transform) : e.addRect(r); + } + return e; + } +} +class At { + /** + * Creates a `GraphicsPath` instance optionally from an SVG path string or an array of `PathInstruction`. + * @param instructions - An SVG path string or an array of `PathInstruction` objects. + * @param signed + */ + constructor(e, t = !1) { + this.instructions = [], this.uid = ue("graphicsPath"), this._dirty = !0, this.checkForHoles = t, typeof e == "string" ? Dc(e, this) : this.instructions = (e == null ? void 0 : e.slice()) ?? []; + } + /** + * Provides access to the internal shape path, ensuring it is up-to-date with the current instructions. + * @returns The `ShapePath` instance associated with this `GraphicsPath`. + */ + get shapePath() { + return this._shapePath || (this._shapePath = new af(this)), this._dirty && (this._dirty = !1, this._shapePath.buildPath()), this._shapePath; + } + /** + * Adds another `GraphicsPath` to this path, optionally applying a transformation. + * @param path - The `GraphicsPath` to add. + * @param transform - An optional transformation to apply to the added path. + * @returns The instance of the current object for chaining. + */ + addPath(e, t) { + return e = e.clone(), this.instructions.push({ action: "addPath", data: [e, t] }), this._dirty = !0, this; + } + arc(...e) { + return this.instructions.push({ action: "arc", data: e }), this._dirty = !0, this; + } + arcTo(...e) { + return this.instructions.push({ action: "arcTo", data: e }), this._dirty = !0, this; + } + arcToSvg(...e) { + return this.instructions.push({ action: "arcToSvg", data: e }), this._dirty = !0, this; + } + bezierCurveTo(...e) { + return this.instructions.push({ action: "bezierCurveTo", data: e }), this._dirty = !0, this; + } + /** + * Adds a cubic Bezier curve to the path. + * It requires two points: the second control point and the end point. The first control point is assumed to be + * The starting point is the last point in the current path. + * @param cp2x - The x-coordinate of the second control point. + * @param cp2y - The y-coordinate of the second control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothness - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + bezierCurveToShort(e, t, n, s, r) { + const a = this.instructions[this.instructions.length - 1], o = this.getLastPoint(Ae.shared); + let l = 0, h = 0; + if (!a || a.action !== "bezierCurveTo") + l = o.x, h = o.y; + else { + l = a.data[2], h = a.data[3]; + const u = o.x, c = o.y; + l = u + (u - l), h = c + (c - h); + } + return this.instructions.push({ action: "bezierCurveTo", data: [l, h, e, t, n, s, r] }), this._dirty = !0, this; + } + /** + * Closes the current path by drawing a straight line back to the start. + * If the shape is already closed or there are no points in the path, this method does nothing. + * @returns The instance of the current object for chaining. + */ + closePath() { + return this.instructions.push({ action: "closePath", data: [] }), this._dirty = !0, this; + } + ellipse(...e) { + return this.instructions.push({ action: "ellipse", data: e }), this._dirty = !0, this; + } + lineTo(...e) { + return this.instructions.push({ action: "lineTo", data: e }), this._dirty = !0, this; + } + moveTo(...e) { + return this.instructions.push({ action: "moveTo", data: e }), this; + } + quadraticCurveTo(...e) { + return this.instructions.push({ action: "quadraticCurveTo", data: e }), this._dirty = !0, this; + } + /** + * Adds a quadratic curve to the path. It uses the previous point as the control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothness - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + quadraticCurveToShort(e, t, n) { + const s = this.instructions[this.instructions.length - 1], r = this.getLastPoint(Ae.shared); + let a = 0, o = 0; + if (!s || s.action !== "quadraticCurveTo") + a = r.x, o = r.y; + else { + a = s.data[0], o = s.data[1]; + const l = r.x, h = r.y; + a = l + (l - a), o = h + (h - o); + } + return this.instructions.push({ action: "quadraticCurveTo", data: [a, o, e, t, n] }), this._dirty = !0, this; + } + /** + * Draws a rectangle shape. This method adds a new rectangle path to the current drawing. + * @param x - The x-coordinate of the top-left corner of the rectangle. + * @param y - The y-coordinate of the top-left corner of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @param transform - An optional `Matrix` object to apply a transformation to the rectangle. + * @returns The instance of the current object for chaining. + */ + rect(e, t, n, s, r) { + return this.instructions.push({ action: "rect", data: [e, t, n, s, r] }), this._dirty = !0, this; + } + /** + * Draws a circle shape. This method adds a new circle path to the current drawing. + * @param x - The x-coordinate of the center of the circle. + * @param y - The y-coordinate of the center of the circle. + * @param radius - The radius of the circle. + * @param transform - An optional `Matrix` object to apply a transformation to the circle. + * @returns The instance of the current object for chaining. + */ + circle(e, t, n, s) { + return this.instructions.push({ action: "circle", data: [e, t, n, s] }), this._dirty = !0, this; + } + roundRect(...e) { + return this.instructions.push({ action: "roundRect", data: e }), this._dirty = !0, this; + } + poly(...e) { + return this.instructions.push({ action: "poly", data: e }), this._dirty = !0, this; + } + regularPoly(...e) { + return this.instructions.push({ action: "regularPoly", data: e }), this._dirty = !0, this; + } + roundPoly(...e) { + return this.instructions.push({ action: "roundPoly", data: e }), this._dirty = !0, this; + } + roundShape(...e) { + return this.instructions.push({ action: "roundShape", data: e }), this._dirty = !0, this; + } + filletRect(...e) { + return this.instructions.push({ action: "filletRect", data: e }), this._dirty = !0, this; + } + chamferRect(...e) { + return this.instructions.push({ action: "chamferRect", data: e }), this._dirty = !0, this; + } + /** + * Draws a star shape centered at a specified location. This method allows for the creation + * of stars with a variable number of points, outer radius, optional inner radius, and rotation. + * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points. + * An optional transformation can be applied to scale, rotate, or translate the star as needed. + * @param x - The x-coordinate of the center of the star. + * @param y - The y-coordinate of the center of the star. + * @param points - The number of points of the star. + * @param radius - The outer radius of the star (distance from the center to the outer points). + * @param innerRadius - Optional. The inner radius of the star + * (distance from the center to the inner points between the outer points). + * If not provided, defaults to half of the `radius`. + * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis. + * Defaults to 0, meaning one point is directly upward. + * @param transform - An optional `Matrix` object to apply a transformation to the star. + * This can include rotations, scaling, and translations. + * @returns The instance of the current object for chaining further drawing commands. + */ + // eslint-disable-next-line max-len + star(e, t, n, s, r, a, o) { + r || (r = s / 2); + const l = -1 * Math.PI / 2 + a, h = n * 2, u = Math.PI * 2 / h, c = []; + for (let d = 0; d < h; d++) { + const f = d % 2 ? r : s, _ = d * u + l; + c.push( + e + f * Math.cos(_), + t + f * Math.sin(_) + ); + } + return this.poly(c, !0, o), this; + } + /** + * Creates a copy of the current `GraphicsPath` instance. This method supports both shallow and deep cloning. + * A shallow clone copies the reference of the instructions array, while a deep clone creates a new array and + * copies each instruction individually, ensuring that modifications to the instructions of the cloned `GraphicsPath` + * do not affect the original `GraphicsPath` and vice versa. + * @param deep - A boolean flag indicating whether the clone should be deep. + * @returns A new `GraphicsPath` instance that is a clone of the current instance. + */ + clone(e = !1) { + const t = new At(); + if (t.checkForHoles = this.checkForHoles, !e) + t.instructions = this.instructions.slice(); + else + for (let n = 0; n < this.instructions.length; n++) { + const s = this.instructions[n]; + t.instructions.push({ action: s.action, data: s.data.slice() }); + } + return t; + } + clear() { + return this.instructions.length = 0, this._dirty = !0, this; + } + /** + * Applies a transformation matrix to all drawing instructions within the `GraphicsPath`. + * This method enables the modification of the path's geometry according to the provided + * transformation matrix, which can include translations, rotations, scaling, and skewing. + * + * Each drawing instruction in the path is updated to reflect the transformation, + * ensuring the visual representation of the path is consistent with the applied matrix. + * + * Note: The transformation is applied directly to the coordinates and control points of the drawing instructions, + * not to the path as a whole. This means the transformation's effects are baked into the individual instructions, + * allowing for fine-grained control over the path's appearance. + * @param matrix - A `Matrix` object representing the transformation to apply. + * @returns The instance of the current object for chaining further operations. + */ + transform(e) { + if (e.isIdentity()) + return this; + const t = e.a, n = e.b, s = e.c, r = e.d, a = e.tx, o = e.ty; + let l = 0, h = 0, u = 0, c = 0, d = 0, f = 0, _ = 0, b = 0; + for (let m = 0; m < this.instructions.length; m++) { + const x = this.instructions[m], g = x.data; + switch (x.action) { + case "moveTo": + case "lineTo": + l = g[0], h = g[1], g[0] = t * l + s * h + a, g[1] = n * l + r * h + o; + break; + case "bezierCurveTo": + u = g[0], c = g[1], d = g[2], f = g[3], l = g[4], h = g[5], g[0] = t * u + s * c + a, g[1] = n * u + r * c + o, g[2] = t * d + s * f + a, g[3] = n * d + r * f + o, g[4] = t * l + s * h + a, g[5] = n * l + r * h + o; + break; + case "quadraticCurveTo": + u = g[0], c = g[1], l = g[2], h = g[3], g[0] = t * u + s * c + a, g[1] = n * u + r * c + o, g[2] = t * l + s * h + a, g[3] = n * l + r * h + o; + break; + case "arcToSvg": + l = g[5], h = g[6], _ = g[0], b = g[1], g[0] = t * _ + s * b, g[1] = n * _ + r * b, g[5] = t * l + s * h + a, g[6] = n * l + r * h + o; + break; + case "circle": + g[4] = dn(g[3], e); + break; + case "rect": + g[4] = dn(g[4], e); + break; + case "ellipse": + g[8] = dn(g[8], e); + break; + case "roundRect": + g[5] = dn(g[5], e); + break; + case "addPath": + g[0].transform(e); + break; + case "poly": + g[2] = dn(g[2], e); + break; + default: + $e("unknown transform action", x.action); + break; + } + } + return this._dirty = !0, this; + } + get bounds() { + return this.shapePath.bounds; + } + /** + * Retrieves the last point from the current drawing instructions in the `GraphicsPath`. + * This method is useful for operations that depend on the path's current endpoint, + * such as connecting subsequent shapes or paths. It supports various drawing instructions, + * ensuring the last point's position is accurately determined regardless of the path's complexity. + * + * If the last instruction is a `closePath`, the method iterates backward through the instructions + * until it finds an actionable instruction that defines a point (e.g., `moveTo`, `lineTo`, + * `quadraticCurveTo`, etc.). For compound paths added via `addPath`, it recursively retrieves + * the last point from the nested path. + * @param out - A `Point` object where the last point's coordinates will be stored. + * This object is modified directly to contain the result. + * @returns The `Point` object containing the last point's coordinates. + */ + getLastPoint(e) { + let t = this.instructions.length - 1, n = this.instructions[t]; + if (!n) + return e.x = 0, e.y = 0, e; + for (; n.action === "closePath"; ) { + if (t--, t < 0) + return e.x = 0, e.y = 0, e; + n = this.instructions[t]; + } + switch (n.action) { + case "moveTo": + case "lineTo": + e.x = n.data[0], e.y = n.data[1]; + break; + case "quadraticCurveTo": + e.x = n.data[2], e.y = n.data[3]; + break; + case "bezierCurveTo": + e.x = n.data[4], e.y = n.data[5]; + break; + case "arc": + case "arcToSvg": + e.x = n.data[5], e.y = n.data[6]; + break; + case "addPath": + n.data[0].getLastPoint(e); + break; + } + return e; + } +} +function dn(i, e) { + return i ? i.prepend(e) : e.clone(); +} +function le(i, e, t) { + const n = i.getAttribute(e); + return n ? Number(n) : t; +} +function of(i, e) { + const t = i.querySelectorAll("defs"); + for (let n = 0; n < t.length; n++) { + const s = t[n]; + for (let r = 0; r < s.children.length; r++) { + const a = s.children[r]; + switch (a.nodeName.toLowerCase()) { + case "lineargradient": + e.defs[a.id] = lf(a); + break; + case "radialgradient": + e.defs[a.id] = hf(); + break; + } + } + } +} +function lf(i) { + const e = le(i, "x1", 0), t = le(i, "y1", 0), n = le(i, "x2", 1), s = le(i, "y2", 0), r = i.getAttribute("gradientUnits") || "objectBoundingBox", a = new Et( + e, + t, + n, + s, + r === "objectBoundingBox" ? "local" : "global" + ); + for (let o = 0; o < i.children.length; o++) { + const l = i.children[o], h = le(l, "offset", 0), u = pe.shared.setValue(l.getAttribute("stop-color")).toNumber(); + a.addColorStop(h, u); + } + return a; +} +function hf(i) { + return $e("[SVG Parser] Radial gradients are not yet supported"), new Et(0, 0, 1, 0); +} +function ua(i) { + const e = i.match(/url\s*\(\s*['"]?\s*#([^'"\s)]+)\s*['"]?\s*\)/i); + return e ? e[1] : ""; +} +const ca = { + // Fill properties + fill: { type: "paint", default: 0 }, + // Fill color/gradient + "fill-opacity": { type: "number", default: 1 }, + // Fill transparency + // Stroke properties + stroke: { type: "paint", default: 0 }, + // Stroke color/gradient + "stroke-width": { type: "number", default: 1 }, + // Width of stroke + "stroke-opacity": { type: "number", default: 1 }, + // Stroke transparency + "stroke-linecap": { type: "string", default: "butt" }, + // End cap style: butt, round, square + "stroke-linejoin": { type: "string", default: "miter" }, + // Join style: miter, round, bevel + "stroke-miterlimit": { type: "number", default: 10 }, + // Limit on miter join sharpness + "stroke-dasharray": { type: "string", default: "none" }, + // Dash pattern + "stroke-dashoffset": { type: "number", default: 0 }, + // Offset for dash pattern + // Global properties + opacity: { type: "number", default: 1 } + // Overall opacity +}; +function zl(i, e) { + const t = i.getAttribute("style"), n = {}, s = {}, r = { + strokeStyle: n, + fillStyle: s, + useFill: !1, + useStroke: !1 + }; + for (const a in ca) { + const o = i.getAttribute(a); + o && da(e, r, a, o.trim()); + } + if (t) { + const a = t.split(";"); + for (let o = 0; o < a.length; o++) { + const l = a[o].trim(), [h, u] = l.split(":"); + ca[h] && da(e, r, h, u.trim()); + } + } + return { + strokeStyle: r.useStroke ? n : null, + fillStyle: r.useFill ? s : null, + useFill: r.useFill, + useStroke: r.useStroke + }; +} +function da(i, e, t, n) { + switch (t) { + case "stroke": + if (n !== "none") { + if (n.startsWith("url(")) { + const s = ua(n); + e.strokeStyle.fill = i.defs[s]; + } else + e.strokeStyle.color = pe.shared.setValue(n).toNumber(); + e.useStroke = !0; + } + break; + case "stroke-width": + e.strokeStyle.width = Number(n); + break; + case "fill": + if (n !== "none") { + if (n.startsWith("url(")) { + const s = ua(n); + e.fillStyle.fill = i.defs[s]; + } else + e.fillStyle.color = pe.shared.setValue(n).toNumber(); + e.useFill = !0; + } + break; + case "fill-opacity": + e.fillStyle.alpha = Number(n); + break; + case "stroke-opacity": + e.strokeStyle.alpha = Number(n); + break; + case "opacity": + e.fillStyle.alpha = Number(n), e.strokeStyle.alpha = Number(n); + break; + } +} +function uf(i) { + if (i.length <= 2) + return !0; + const e = i.map((o) => o.area).sort((o, l) => l - o), [t, n] = e, s = e[e.length - 1], r = t / n, a = n / s; + return !(r > 3 && a < 2); +} +function cf(i) { + return i.split(/(?=[Mm])/).filter((n) => n.trim().length > 0); +} +function df(i) { + const e = i.match(/[-+]?[0-9]*\.?[0-9]+/g); + if (!e || e.length < 4) + return 0; + const t = e.map(Number), n = [], s = []; + for (let u = 0; u < t.length; u += 2) + u + 1 < t.length && (n.push(t[u]), s.push(t[u + 1])); + if (n.length === 0 || s.length === 0) + return 0; + const r = Math.min(...n), a = Math.max(...n), o = Math.min(...s), l = Math.max(...s); + return (a - r) * (l - o); +} +function fa(i, e) { + const t = new At(i, !1); + for (const n of t.instructions) + e.instructions.push(n); +} +function ff(i, e) { + if (typeof i == "string") { + const a = document.createElement("div"); + a.innerHTML = i.trim(), i = a.querySelector("svg"); + } + const t = { + context: e, + defs: {}, + path: new At() + }; + of(i, t); + const n = i.children, { fillStyle: s, strokeStyle: r } = zl(i, t); + for (let a = 0; a < n.length; a++) { + const o = n[a]; + o.nodeName.toLowerCase() !== "defs" && Nl(o, t, s, r); + } + return e; +} +function Nl(i, e, t, n) { + const s = i.children, { fillStyle: r, strokeStyle: a } = zl(i, e); + r && t ? t = { ...t, ...r } : r && (t = r), a && n ? n = { ...n, ...a } : a && (n = a); + const o = !t && !n; + o && (t = { color: 0 }); + let l, h, u, c, d, f, _, b, m, x, g, p, y, C, w, v, D; + switch (i.nodeName.toLowerCase()) { + case "path": { + C = i.getAttribute("d"); + const S = i.getAttribute("fill-rule"), A = cf(C), E = S === "evenodd", I = A.length > 1; + if (E && I) { + const N = A.map((F) => ({ + path: F, + area: df(F) + })); + if (N.sort((F, T) => T.area - F.area), A.length > 3 || !uf(N)) + for (let F = 0; F < N.length; F++) { + const T = N[F], U = F === 0; + e.context.beginPath(); + const O = new At(void 0, !0); + fa(T.path, O), e.context.path(O), U ? (t && e.context.fill(t), n && e.context.stroke(n)) : e.context.cut(); + } + else + for (let F = 0; F < N.length; F++) { + const T = N[F], U = F % 2 === 1; + e.context.beginPath(); + const O = new At(void 0, !0); + fa(T.path, O), e.context.path(O), U ? e.context.cut() : (t && e.context.fill(t), n && e.context.stroke(n)); + } + } else { + const N = S ? S === "evenodd" : !0; + w = new At(C, N), e.context.path(w), t && e.context.fill(t), n && e.context.stroke(n); + } + break; + } + case "circle": + _ = le(i, "cx", 0), b = le(i, "cy", 0), m = le(i, "r", 0), e.context.ellipse(_, b, m, m), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "rect": + l = le(i, "x", 0), h = le(i, "y", 0), v = le(i, "width", 0), D = le(i, "height", 0), x = le(i, "rx", 0), g = le(i, "ry", 0), x || g ? e.context.roundRect(l, h, v, D, x || g) : e.context.rect(l, h, v, D), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "ellipse": + _ = le(i, "cx", 0), b = le(i, "cy", 0), x = le(i, "rx", 0), g = le(i, "ry", 0), e.context.beginPath(), e.context.ellipse(_, b, x, g), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "line": + u = le(i, "x1", 0), c = le(i, "y1", 0), d = le(i, "x2", 0), f = le(i, "y2", 0), e.context.beginPath(), e.context.moveTo(u, c), e.context.lineTo(d, f), n && e.context.stroke(n); + break; + case "polygon": + y = i.getAttribute("points"), p = y.match(/\d+/g).map((S) => parseInt(S, 10)), e.context.poly(p, !0), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "polyline": + y = i.getAttribute("points"), p = y.match(/\d+/g).map((S) => parseInt(S, 10)), e.context.poly(p, !1), n && e.context.stroke(n); + break; + case "g": + case "svg": + break; + default: { + $e(`[SVG parser] <${i.nodeName}> elements unsupported`); + break; + } + } + o && (t = null); + for (let S = 0; S < s.length; S++) + Nl(s[S], e, t, n); +} +function pf(i) { + return pe.isColorLike(i); +} +function pa(i) { + return i instanceof Ei; +} +function _a(i) { + return i instanceof Et; +} +function _f(i) { + return i instanceof K; +} +function mf(i, e, t) { + const n = pe.shared.setValue(e ?? 0); + return i.color = n.toNumber(), i.alpha = n.alpha === 1 ? t.alpha : n.alpha, i.texture = K.WHITE, { ...t, ...i }; +} +function gf(i, e, t) { + return i.texture = e, { ...t, ...i }; +} +function ma(i, e, t) { + return i.fill = e, i.color = 16777215, i.texture = e.texture, i.matrix = e.transform, { ...t, ...i }; +} +function ga(i, e, t) { + return e.buildGradient(), i.fill = e, i.color = 16777215, i.texture = e.texture, i.matrix = e.transform, i.textureSpace = e.textureSpace, { ...t, ...i }; +} +function yf(i, e) { + const t = { ...e, ...i }, n = pe.shared.setValue(t.color); + return t.alpha *= n.alpha, t.color = n.toNumber(), t; +} +function Ot(i, e) { + if (i == null) + return null; + const t = {}, n = i; + return pf(i) ? mf(t, i, e) : _f(i) ? gf(t, i, e) : pa(i) ? ma(t, i, e) : _a(i) ? ga(t, i, e) : n.fill && pa(n.fill) ? ma(n, n.fill, e) : n.fill && _a(n.fill) ? ga(n, n.fill, e) : yf(n, e); +} +function yi(i, e) { + const { width: t, alignment: n, miterLimit: s, cap: r, join: a, pixelLine: o, ...l } = e, h = Ot(i, l); + return h ? { + width: t, + alignment: n, + miterLimit: s, + cap: r, + join: a, + pixelLine: o, + ...h + } : null; +} +const bf = new Ae(), ya = new H(), er = class mt extends xt { + constructor() { + super(...arguments), this.uid = ue("graphicsContext"), this.dirty = !0, this.batchMode = "auto", this.instructions = [], this._activePath = new At(), this._transform = new H(), this._fillStyle = { ...mt.defaultFillStyle }, this._strokeStyle = { ...mt.defaultStrokeStyle }, this._stateStack = [], this._tick = 0, this._bounds = new ht(), this._boundsDirty = !0; + } + /** + * Creates a new GraphicsContext object that is a clone of this instance, copying all properties, + * including the current drawing state, transformations, styles, and instructions. + * @returns A new GraphicsContext instance with the same properties and state as this one. + */ + clone() { + const e = new mt(); + return e.batchMode = this.batchMode, e.instructions = this.instructions.slice(), e._activePath = this._activePath.clone(), e._transform = this._transform.clone(), e._fillStyle = { ...this._fillStyle }, e._strokeStyle = { ...this._strokeStyle }, e._stateStack = this._stateStack.slice(), e._bounds = this._bounds.clone(), e._boundsDirty = !0, e; + } + /** + * The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object. + */ + get fillStyle() { + return this._fillStyle; + } + set fillStyle(e) { + this._fillStyle = Ot(e, mt.defaultFillStyle); + } + /** + * The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object. + */ + get strokeStyle() { + return this._strokeStyle; + } + set strokeStyle(e) { + this._strokeStyle = yi(e, mt.defaultStrokeStyle); + } + /** + * Sets the current fill style of the graphics context. The fill style can be a color, gradient, + * pattern, or a more complex style defined by a FillStyle object. + * @param style - The fill style to apply. This can be a simple color, a gradient or pattern object, + * or a FillStyle or ConvertedFillStyle object. + * @returns The instance of the current GraphicsContext for method chaining. + */ + setFillStyle(e) { + return this._fillStyle = Ot(e, mt.defaultFillStyle), this; + } + /** + * Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can + * encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object. + * @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern, + * or a StrokeStyle or ConvertedStrokeStyle object. + * @returns The instance of the current GraphicsContext for method chaining. + */ + setStrokeStyle(e) { + return this._strokeStyle = Ot(e, mt.defaultStrokeStyle), this; + } + texture(e, t, n, s, r, a) { + return this.instructions.push({ + action: "texture", + data: { + image: e, + dx: n || 0, + dy: s || 0, + dw: r || e.frame.width, + dh: a || e.frame.height, + transform: this._transform.clone(), + alpha: this._fillStyle.alpha, + style: t ? pe.shared.setValue(t).toNumber() : 16777215 + } + }), this.onUpdate(), this; + } + /** + * Resets the current path. Any previous path and its commands are discarded and a new path is + * started. This is typically called before beginning a new shape or series of drawing commands. + * @returns The instance of the current GraphicsContext for method chaining. + */ + beginPath() { + return this._activePath = new At(), this; + } + fill(e, t) { + let n; + const s = this.instructions[this.instructions.length - 1]; + return this._tick === 0 && s && s.action === "stroke" ? n = s.data.path : n = this._activePath.clone(), n ? (e != null && (t !== void 0 && typeof e == "number" && (W(he, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead"), e = { color: e, alpha: t }), this._fillStyle = Ot(e, mt.defaultFillStyle)), this.instructions.push({ + action: "fill", + // TODO copy fill style! + data: { style: this.fillStyle, path: n } + }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this; + } + _initNextPathLocation() { + const { x: e, y: t } = this._activePath.getLastPoint(Ae.shared); + this._activePath.clear(), this._activePath.moveTo(e, t); + } + /** + * Strokes the current path with the current stroke style. This method can take an optional + * FillInput parameter to define the stroke's appearance, including its color, width, and other properties. + * @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style. + * @returns The instance of the current GraphicsContext for method chaining. + */ + stroke(e) { + let t; + const n = this.instructions[this.instructions.length - 1]; + return this._tick === 0 && n && n.action === "fill" ? t = n.data.path : t = this._activePath.clone(), t ? (e != null && (this._strokeStyle = yi(e, mt.defaultStrokeStyle)), this.instructions.push({ + action: "stroke", + // TODO copy fill style! + data: { style: this.strokeStyle, path: t } + }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this; + } + /** + * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by + * subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will + * fail to cut correctly! + * @returns The instance of the current GraphicsContext for method chaining. + */ + cut() { + for (let e = 0; e < 2; e++) { + const t = this.instructions[this.instructions.length - 1 - e], n = this._activePath.clone(); + if (t && (t.action === "stroke" || t.action === "fill")) + if (t.data.hole) + t.data.hole.addPath(n); + else { + t.data.hole = n; + break; + } + } + return this._initNextPathLocation(), this; + } + /** + * Adds an arc to the current path, which is centered at (x, y) with the specified radius, + * starting and ending angles, and direction. + * @param x - The x-coordinate of the arc's center. + * @param y - The y-coordinate of the arc's center. + * @param radius - The arc's radius. + * @param startAngle - The starting angle, in radians. + * @param endAngle - The ending angle, in radians. + * @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false. + * @returns The instance of the current GraphicsContext for method chaining. + */ + arc(e, t, n, s, r, a) { + this._tick++; + const o = this._transform; + return this._activePath.arc( + o.a * e + o.c * t + o.tx, + o.b * e + o.d * t + o.ty, + n, + s, + r, + a + ), this; + } + /** + * Adds an arc to the current path with the given control points and radius, connected to the previous point + * by a straight line if necessary. + * @param x1 - The x-coordinate of the first control point. + * @param y1 - The y-coordinate of the first control point. + * @param x2 - The x-coordinate of the second control point. + * @param y2 - The y-coordinate of the second control point. + * @param radius - The arc's radius. + * @returns The instance of the current GraphicsContext for method chaining. + */ + arcTo(e, t, n, s, r) { + this._tick++; + const a = this._transform; + return this._activePath.arcTo( + a.a * e + a.c * t + a.tx, + a.b * e + a.d * t + a.ty, + a.a * n + a.c * s + a.tx, + a.b * n + a.d * s + a.ty, + r + ), this; + } + /** + * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec. + * @param rx - The x-radius of the ellipse. + * @param ry - The y-radius of the ellipse. + * @param xAxisRotation - The rotation of the ellipse's x-axis relative + * to the x-axis of the coordinate system, in degrees. + * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees. + * @param sweepFlag - Determines if the arc should be swept in a positive angle direction. + * @param x - The x-coordinate of the arc's end point. + * @param y - The y-coordinate of the arc's end point. + * @returns The instance of the current object for chaining. + */ + arcToSvg(e, t, n, s, r, a, o) { + this._tick++; + const l = this._transform; + return this._activePath.arcToSvg( + e, + t, + n, + // should we rotate this with transform?? + s, + r, + l.a * a + l.c * o + l.tx, + l.b * a + l.d * o + l.ty + ), this; + } + /** + * Adds a cubic Bezier curve to the path. + * It requires three points: the first two are control points and the third one is the end point. + * The starting point is the last point in the current path. + * @param cp1x - The x-coordinate of the first control point. + * @param cp1y - The y-coordinate of the first control point. + * @param cp2x - The x-coordinate of the second control point. + * @param cp2y - The y-coordinate of the second control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothness - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + bezierCurveTo(e, t, n, s, r, a, o) { + this._tick++; + const l = this._transform; + return this._activePath.bezierCurveTo( + l.a * e + l.c * t + l.tx, + l.b * e + l.d * t + l.ty, + l.a * n + l.c * s + l.tx, + l.b * n + l.d * s + l.ty, + l.a * r + l.c * a + l.tx, + l.b * r + l.d * a + l.ty, + o + ), this; + } + /** + * Closes the current path by drawing a straight line back to the start. + * If the shape is already closed or there are no points in the path, this method does nothing. + * @returns The instance of the current object for chaining. + */ + closePath() { + var e; + return this._tick++, (e = this._activePath) == null || e.closePath(), this; + } + /** + * Draws an ellipse at the specified location and with the given x and y radii. + * An optional transformation can be applied, allowing for rotation, scaling, and translation. + * @param x - The x-coordinate of the center of the ellipse. + * @param y - The y-coordinate of the center of the ellipse. + * @param radiusX - The horizontal radius of the ellipse. + * @param radiusY - The vertical radius of the ellipse. + * @returns The instance of the current object for chaining. + */ + ellipse(e, t, n, s) { + return this._tick++, this._activePath.ellipse(e, t, n, s, this._transform.clone()), this; + } + /** + * Draws a circle shape. This method adds a new circle path to the current drawing. + * @param x - The x-coordinate of the center of the circle. + * @param y - The y-coordinate of the center of the circle. + * @param radius - The radius of the circle. + * @returns The instance of the current object for chaining. + */ + circle(e, t, n) { + return this._tick++, this._activePath.circle(e, t, n, this._transform.clone()), this; + } + /** + * Adds another `GraphicsPath` to this path, optionally applying a transformation. + * @param path - The `GraphicsPath` to add. + * @returns The instance of the current object for chaining. + */ + path(e) { + return this._tick++, this._activePath.addPath(e, this._transform.clone()), this; + } + /** + * Connects the current point to a new point with a straight line. This method updates the current path. + * @param x - The x-coordinate of the new point to connect to. + * @param y - The y-coordinate of the new point to connect to. + * @returns The instance of the current object for chaining. + */ + lineTo(e, t) { + this._tick++; + const n = this._transform; + return this._activePath.lineTo( + n.a * e + n.c * t + n.tx, + n.b * e + n.d * t + n.ty + ), this; + } + /** + * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path. + * @param x - The x-coordinate for the starting point. + * @param y - The y-coordinate for the starting point. + * @returns The instance of the current object for chaining. + */ + moveTo(e, t) { + this._tick++; + const n = this._transform, s = this._activePath.instructions, r = n.a * e + n.c * t + n.tx, a = n.b * e + n.d * t + n.ty; + return s.length === 1 && s[0].action === "moveTo" ? (s[0].data[0] = r, s[0].data[1] = a, this) : (this._activePath.moveTo( + r, + a + ), this); + } + /** + * Adds a quadratic curve to the path. It requires two points: the control point and the end point. + * The starting point is the last point in the current path. + * @param cpx - The x-coordinate of the control point. + * @param cpy - The y-coordinate of the control point. + * @param x - The x-coordinate of the end point. + * @param y - The y-coordinate of the end point. + * @param smoothness - Optional parameter to adjust the smoothness of the curve. + * @returns The instance of the current object for chaining. + */ + quadraticCurveTo(e, t, n, s, r) { + this._tick++; + const a = this._transform; + return this._activePath.quadraticCurveTo( + a.a * e + a.c * t + a.tx, + a.b * e + a.d * t + a.ty, + a.a * n + a.c * s + a.tx, + a.b * n + a.d * s + a.ty, + r + ), this; + } + /** + * Draws a rectangle shape. This method adds a new rectangle path to the current drawing. + * @param x - The x-coordinate of the top-left corner of the rectangle. + * @param y - The y-coordinate of the top-left corner of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @returns The instance of the current object for chaining. + */ + rect(e, t, n, s) { + return this._tick++, this._activePath.rect(e, t, n, s, this._transform.clone()), this; + } + /** + * Draws a rectangle with rounded corners. + * The corner radius can be specified to determine how rounded the corners should be. + * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle. + * @param x - The x-coordinate of the top-left corner of the rectangle. + * @param y - The y-coordinate of the top-left corner of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp. + * @returns The instance of the current object for chaining. + */ + roundRect(e, t, n, s, r) { + return this._tick++, this._activePath.roundRect(e, t, n, s, r, this._transform.clone()), this; + } + /** + * Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons, + * which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled, + * rotated, or translated as needed. + * @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}] + * representing the x and y coordinates, of the polygon's vertices, in sequence. + * @param close - A boolean indicating whether to close the polygon path. True by default. + */ + poly(e, t) { + return this._tick++, this._activePath.poly(e, t, this._transform.clone()), this; + } + /** + * Draws a regular polygon with a specified number of sides. All sides and angles are equal. + * @param x - The x-coordinate of the center of the polygon. + * @param y - The y-coordinate of the center of the polygon. + * @param radius - The radius of the circumscribed circle of the polygon. + * @param sides - The number of sides of the polygon. Must be 3 or more. + * @param rotation - The rotation angle of the polygon, in radians. Zero by default. + * @param transform - An optional `Matrix` object to apply a transformation to the polygon. + * @returns The instance of the current object for chaining. + */ + regularPoly(e, t, n, s, r = 0, a) { + return this._tick++, this._activePath.regularPoly(e, t, n, s, r, a), this; + } + /** + * Draws a polygon with rounded corners. + * Similar to `regularPoly` but with the ability to round the corners of the polygon. + * @param x - The x-coordinate of the center of the polygon. + * @param y - The y-coordinate of the center of the polygon. + * @param radius - The radius of the circumscribed circle of the polygon. + * @param sides - The number of sides of the polygon. Must be 3 or more. + * @param corner - The radius of the rounding of the corners. + * @param rotation - The rotation angle of the polygon, in radians. Zero by default. + * @returns The instance of the current object for chaining. + */ + roundPoly(e, t, n, s, r, a) { + return this._tick++, this._activePath.roundPoly(e, t, n, s, r, a), this; + } + /** + * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape. + * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic. + * @param points - An array of `RoundedPoint` representing the corners of the shape to draw. + * A minimum of 3 points is required. + * @param radius - The default radius for the corners. + * This radius is applied to all corners unless overridden in `points`. + * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve + * method instead of an arc method. Defaults to false. + * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true. + * Higher values make the curve smoother. + * @returns The instance of the current object for chaining. + */ + roundShape(e, t, n, s) { + return this._tick++, this._activePath.roundShape(e, t, n, s), this; + } + /** + * Draw Rectangle with fillet corners. This is much like rounded rectangle + * however it support negative numbers as well for the corner radius. + * @param x - Upper left corner of rect + * @param y - Upper right corner of rect + * @param width - Width of rect + * @param height - Height of rect + * @param fillet - accept negative or positive values + */ + filletRect(e, t, n, s, r) { + return this._tick++, this._activePath.filletRect(e, t, n, s, r), this; + } + /** + * Draw Rectangle with chamfer corners. These are angled corners. + * @param x - Upper left corner of rect + * @param y - Upper right corner of rect + * @param width - Width of rect + * @param height - Height of rect + * @param chamfer - non-zero real number, size of corner cutout + * @param transform + */ + chamferRect(e, t, n, s, r, a) { + return this._tick++, this._activePath.chamferRect(e, t, n, s, r, a), this; + } + /** + * Draws a star shape centered at a specified location. This method allows for the creation + * of stars with a variable number of points, outer radius, optional inner radius, and rotation. + * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points. + * An optional transformation can be applied to scale, rotate, or translate the star as needed. + * @param x - The x-coordinate of the center of the star. + * @param y - The y-coordinate of the center of the star. + * @param points - The number of points of the star. + * @param radius - The outer radius of the star (distance from the center to the outer points). + * @param innerRadius - Optional. The inner radius of the star + * (distance from the center to the inner points between the outer points). + * If not provided, defaults to half of the `radius`. + * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis. + * Defaults to 0, meaning one point is directly upward. + * @returns The instance of the current object for chaining further drawing commands. + */ + star(e, t, n, s, r = 0, a = 0) { + return this._tick++, this._activePath.star(e, t, n, s, r, a, this._transform.clone()), this; + } + /** + * Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths + * defined in SVG format to be drawn within the graphics context. + * @param svg - The SVG string to be parsed and rendered. + */ + svg(e) { + return this._tick++, ff(e, this), this; + } + /** + * Restores the most recently saved graphics state by popping the top of the graphics state stack. + * This includes transformations, fill styles, and stroke styles. + */ + restore() { + const e = this._stateStack.pop(); + return e && (this._transform = e.transform, this._fillStyle = e.fillStyle, this._strokeStyle = e.strokeStyle), this; + } + /** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */ + save() { + return this._stateStack.push({ + transform: this._transform.clone(), + fillStyle: { ...this._fillStyle }, + strokeStyle: { ...this._strokeStyle } + }), this; + } + /** + * Returns the current transformation matrix of the graphics context. + * @returns The current transformation matrix. + */ + getTransform() { + return this._transform; + } + /** + * Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied. + * @returns The instance of the current GraphicsContext for method chaining. + */ + resetTransform() { + return this._transform.identity(), this; + } + /** + * Applies a rotation transformation to the graphics context around the current origin. + * @param angle - The angle of rotation in radians. + * @returns The instance of the current GraphicsContext for method chaining. + */ + rotate(e) { + return this._transform.rotate(e), this; + } + /** + * Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically. + * @param x - The scale factor in the horizontal direction. + * @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions. + * @returns The instance of the current GraphicsContext for method chaining. + */ + scale(e, t = e) { + return this._transform.scale(e, t), this; + } + setTransform(e, t, n, s, r, a) { + return e instanceof H ? (this._transform.set(e.a, e.b, e.c, e.d, e.tx, e.ty), this) : (this._transform.set(e, t, n, s, r, a), this); + } + transform(e, t, n, s, r, a) { + return e instanceof H ? (this._transform.append(e), this) : (ya.set(e, t, n, s, r, a), this._transform.append(ya), this); + } + /** + * Applies a translation transformation to the graphics context, moving the origin by the specified amounts. + * @param x - The amount to translate in the horizontal direction. + * @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions. + * @returns The instance of the current GraphicsContext for method chaining. + */ + translate(e, t = e) { + return this._transform.translate(e, t), this; + } + /** + * Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path, + * and optionally resetting transformations to the identity matrix. + * @returns The instance of the current GraphicsContext for method chaining. + */ + clear() { + return this._activePath.clear(), this.instructions.length = 0, this.resetTransform(), this.onUpdate(), this; + } + onUpdate() { + this._boundsDirty = !0, !this.dirty && (this.emit("update", this, 16), this.dirty = !0); + } + /** The bounds of the graphic shape. */ + get bounds() { + if (!this._boundsDirty) + return this._bounds; + this._boundsDirty = !1; + const e = this._bounds; + e.clear(); + for (let t = 0; t < this.instructions.length; t++) { + const n = this.instructions[t], s = n.action; + if (s === "fill") { + const r = n.data; + e.addBounds(r.path.bounds); + } else if (s === "texture") { + const r = n.data; + e.addFrame(r.dx, r.dy, r.dx + r.dw, r.dy + r.dh, r.transform); + } + if (s === "stroke") { + const r = n.data, a = r.style.alignment, o = r.style.width * (1 - a), l = r.path.bounds; + e.addFrame( + l.minX - o, + l.minY - o, + l.maxX + o, + l.maxY + o + ); + } + } + return e; + } + /** + * Check to see if a point is contained within this geometry. + * @param point - Point to check if it's contained. + * @returns {boolean} `true` if the point is contained within geometry. + */ + containsPoint(e) { + var s; + if (!this.bounds.containsPoint(e.x, e.y)) + return !1; + const t = this.instructions; + let n = !1; + for (let r = 0; r < t.length; r++) { + const a = t[r], o = a.data, l = o.path; + if (!a.action || !l) + continue; + const h = o.style, u = l.shapePath.shapePrimitives; + for (let c = 0; c < u.length; c++) { + const d = u[c].shape; + if (!h || !d) + continue; + const f = u[c].transform, _ = f ? f.applyInverse(e, bf) : e; + if (a.action === "fill") + n = d.contains(_.x, _.y); + else { + const m = h; + n = d.strokeContains(_.x, _.y, m.width, m.alignment); + } + const b = o.hole; + if (b) { + const m = (s = b.shapePath) == null ? void 0 : s.shapePrimitives; + if (m) + for (let x = 0; x < m.length; x++) + m[x].shape.contains(_.x, _.y) && (n = !1); + } + if (n) + return !0; + } + } + return n; + } + /** + * Destroys the GraphicsData object. + * @param options - Options parameter. A boolean will act as if all options + * have been set to that value + * @example + * context.destroy(); + * context.destroy(true); + * context.destroy({ texture: true, textureSource: true }); + */ + destroy(e = !1) { + if (this._stateStack.length = 0, this._transform = null, this.emit("destroy", this), this.removeAllListeners(), typeof e == "boolean" ? e : e == null ? void 0 : e.texture) { + const n = typeof e == "boolean" ? e : e == null ? void 0 : e.textureSource; + this._fillStyle.texture && (this._fillStyle.fill && "uid" in this._fillStyle.fill ? this._fillStyle.fill.destroy() : this._fillStyle.texture.destroy(n)), this._strokeStyle.texture && (this._strokeStyle.fill && "uid" in this._strokeStyle.fill ? this._strokeStyle.fill.destroy() : this._strokeStyle.texture.destroy(n)); + } + this._fillStyle = null, this._strokeStyle = null, this.instructions = null, this._activePath = null, this._bounds = null, this._stateStack = null, this.customShader = null, this._transform = null; + } +}; +er.defaultFillStyle = { + /** The color to use for the fill. */ + color: 16777215, + /** The alpha value to use for the fill. */ + alpha: 1, + /** The texture to use for the fill. */ + texture: K.WHITE, + /** The matrix to apply. */ + matrix: null, + /** The fill pattern to use. */ + fill: null, + /** Whether coordinates are 'global' or 'local' */ + textureSpace: "local" +}; +er.defaultStrokeStyle = { + /** The width of the stroke. */ + width: 1, + /** The color to use for the stroke. */ + color: 16777215, + /** The alpha value to use for the stroke. */ + alpha: 1, + /** The alignment of the stroke. */ + alignment: 0.5, + /** The miter limit to use. */ + miterLimit: 10, + /** The line cap style to use. */ + cap: "butt", + /** The line join style to use. */ + join: "miter", + /** The texture to use for the fill. */ + texture: K.WHITE, + /** The matrix to apply. */ + matrix: null, + /** The fill pattern to use. */ + fill: null, + /** Whether coordinates are 'global' or 'local' */ + textureSpace: "local", + /** If the stroke is a pixel line. */ + pixelLine: !1 +}; +let ot = er; +const tr = class Kt extends xt { + constructor(e = {}) { + super(), this.uid = ue("textStyle"), this._tick = 0, xf(e); + const t = { ...Kt.defaultTextStyle, ...e }; + for (const n in t) { + const s = n; + this[s] = t[n]; + } + this.update(), this._tick = 0; + } + /** + * Alignment for multiline text, does not affect single line text. + * @type {'left'|'center'|'right'|'justify'} + */ + get align() { + return this._align; + } + set align(e) { + this._align = e, this.update(); + } + /** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */ + get breakWords() { + return this._breakWords; + } + set breakWords(e) { + this._breakWords = e, this.update(); + } + /** Set a drop shadow for the text. */ + get dropShadow() { + return this._dropShadow; + } + set dropShadow(e) { + e !== null && typeof e == "object" ? this._dropShadow = this._createProxy({ ...Kt.defaultDropShadow, ...e }) : this._dropShadow = e ? this._createProxy({ ...Kt.defaultDropShadow }) : null, this.update(); + } + /** The font family, can be a single font name, or a list of names where the first is the preferred font. */ + get fontFamily() { + return this._fontFamily; + } + set fontFamily(e) { + this._fontFamily = e, this.update(); + } + /** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */ + get fontSize() { + return this._fontSize; + } + set fontSize(e) { + typeof e == "string" ? this._fontSize = parseInt(e, 10) : this._fontSize = e, this.update(); + } + /** + * The font style. + * @type {'normal'|'italic'|'oblique'} + */ + get fontStyle() { + return this._fontStyle; + } + set fontStyle(e) { + this._fontStyle = e.toLowerCase(), this.update(); + } + /** + * The font variant. + * @type {'normal'|'small-caps'} + */ + get fontVariant() { + return this._fontVariant; + } + set fontVariant(e) { + this._fontVariant = e, this.update(); + } + /** + * The font weight. + * @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'} + */ + get fontWeight() { + return this._fontWeight; + } + set fontWeight(e) { + this._fontWeight = e, this.update(); + } + /** The space between lines. */ + get leading() { + return this._leading; + } + set leading(e) { + this._leading = e, this.update(); + } + /** The amount of spacing between letters, default is 0. */ + get letterSpacing() { + return this._letterSpacing; + } + set letterSpacing(e) { + this._letterSpacing = e, this.update(); + } + /** The line height, a number that represents the vertical space that a letter uses. */ + get lineHeight() { + return this._lineHeight; + } + set lineHeight(e) { + this._lineHeight = e, this.update(); + } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * > [!NOTE] This will NOT affect the positioning or bounds of the text. + */ + get padding() { + return this._padding; + } + set padding(e) { + this._padding = e, this.update(); + } + /** + * An optional filter or array of filters to apply to the text, allowing for advanced visual effects. + * These filters will be applied to the text as it is created, resulting in faster rendering for static text + * compared to applying the filter directly to the text object (which would be applied at run time). + * @default null + */ + get filters() { + return this._filters; + } + set filters(e) { + this._filters = Object.freeze(e), this.update(); + } + /** + * Trim transparent borders from the text texture. + * > [!IMPORTANT] PERFORMANCE WARNING: + * > This is a costly operation as it requires scanning pixel alpha values. + * > Avoid using `trim: true` for dynamic text, as it could significantly impact performance. + */ + get trim() { + return this._trim; + } + set trim(e) { + this._trim = e, this.update(); + } + /** + * The baseline of the text that is rendered. + * @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'} + */ + get textBaseline() { + return this._textBaseline; + } + set textBaseline(e) { + this._textBaseline = e, this.update(); + } + /** + * How newlines and spaces should be handled. + * Default is 'pre' (preserve, preserve). + * + * value | New lines | Spaces + * --- | --- | --- + * 'normal' | Collapse | Collapse + * 'pre' | Preserve | Preserve + * 'pre-line' | Preserve | Collapse + * @type {'normal'|'pre'|'pre-line'} + */ + get whiteSpace() { + return this._whiteSpace; + } + set whiteSpace(e) { + this._whiteSpace = e, this.update(); + } + /** Indicates if word wrap should be used. */ + get wordWrap() { + return this._wordWrap; + } + set wordWrap(e) { + this._wordWrap = e, this.update(); + } + /** The width at which text will wrap, it needs wordWrap to be set to true. */ + get wordWrapWidth() { + return this._wordWrapWidth; + } + set wordWrapWidth(e) { + this._wordWrapWidth = e, this.update(); + } + /** + * The fill style that will be used to color the text. + * This can be: + * - A color string like 'red', '#00FF00', or 'rgba(255,0,0,0.5)' + * - A hex number like 0xff0000 for red + * - A FillStyle object with properties like { color: 0xff0000, alpha: 0.5 } + * - A FillGradient for gradient fills + * - A FillPattern for pattern/texture fills + * + * When using a FillGradient, vertical gradients (angle of 90 degrees) are applied per line of text, + * while gradients at any other angle are spread across the entire text body as a whole. + * @example + * // Vertical gradient applied per line + * const verticalGradient = new FillGradient(0, 0, 0, 1) + * .addColorStop(0, 0xff0000) + * .addColorStop(1, 0x0000ff); + * + * const text = new Text({ + * text: 'Line 1\nLine 2', + * style: { fill: verticalGradient } + * }); + * + * To manage the gradient in a global scope, set the textureSpace property of the FillGradient to 'global'. + * @type {string|number|FillStyle|FillGradient|FillPattern} + */ + get fill() { + return this._originalFill; + } + set fill(e) { + e !== this._originalFill && (this._originalFill = e, this._isFillStyle(e) && (this._originalFill = this._createProxy({ ...ot.defaultFillStyle, ...e }, () => { + this._fill = Ot( + { ...this._originalFill }, + ot.defaultFillStyle + ); + })), this._fill = Ot( + e === 0 ? "black" : e, + ot.defaultFillStyle + ), this.update()); + } + /** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */ + get stroke() { + return this._originalStroke; + } + set stroke(e) { + e !== this._originalStroke && (this._originalStroke = e, this._isFillStyle(e) && (this._originalStroke = this._createProxy({ ...ot.defaultStrokeStyle, ...e }, () => { + this._stroke = yi( + { ...this._originalStroke }, + ot.defaultStrokeStyle + ); + })), this._stroke = yi(e, ot.defaultStrokeStyle), this.update()); + } + update() { + this._tick++, this.emit("update", this); + } + /** Resets all properties to the default values */ + reset() { + const e = Kt.defaultTextStyle; + for (const t in e) + this[t] = e[t]; + } + /** + * Returns a unique key for this instance. + * This key is used for caching. + * @returns {string} Unique key for the instance + */ + get styleKey() { + return `${this.uid}-${this._tick}`; + } + /** + * Creates a new TextStyle object with the same values as this one. + * @returns New cloned TextStyle object + */ + clone() { + return new Kt({ + align: this.align, + breakWords: this.breakWords, + dropShadow: this._dropShadow ? { ...this._dropShadow } : null, + fill: this._fill, + fontFamily: this.fontFamily, + fontSize: this.fontSize, + fontStyle: this.fontStyle, + fontVariant: this.fontVariant, + fontWeight: this.fontWeight, + leading: this.leading, + letterSpacing: this.letterSpacing, + lineHeight: this.lineHeight, + padding: this.padding, + stroke: this._stroke, + textBaseline: this.textBaseline, + whiteSpace: this.whiteSpace, + wordWrap: this.wordWrap, + wordWrapWidth: this.wordWrapWidth, + filters: this._filters ? [...this._filters] : void 0 + }); + } + /** + * Returns the final padding for the text style, taking into account any filters applied. + * Used internally for correct measurements + * @internal + * @returns {number} The final padding for the text style. + */ + _getFinalPadding() { + let e = 0; + if (this._filters) + for (let t = 0; t < this._filters.length; t++) + e += this._filters[t].padding; + return Math.max(this._padding, e); + } + /** + * Destroys this text style. + * @param options - Options parameter. A boolean will act as if all options + * have been set to that value + * @example + * // Destroy the text style and its textures + * textStyle.destroy({ texture: true, textureSource: true }); + * textStyle.destroy(true); + */ + destroy(e = !1) { + var n, s, r, a; + if (this.removeAllListeners(), typeof e == "boolean" ? e : e == null ? void 0 : e.texture) { + const o = typeof e == "boolean" ? e : e == null ? void 0 : e.textureSource; + (n = this._fill) != null && n.texture && this._fill.texture.destroy(o), (s = this._originalFill) != null && s.texture && this._originalFill.texture.destroy(o), (r = this._stroke) != null && r.texture && this._stroke.texture.destroy(o), (a = this._originalStroke) != null && a.texture && this._originalStroke.texture.destroy(o); + } + this._fill = null, this._stroke = null, this.dropShadow = null, this._originalStroke = null, this._originalFill = null; + } + _createProxy(e, t) { + return new Proxy(e, { + set: (n, s, r) => (n[s] = r, t == null || t(s, r), this.update(), !0) + }); + } + _isFillStyle(e) { + return (e ?? null) !== null && !(pe.isColorLike(e) || e instanceof Et || e instanceof Ei); + } +}; +tr.defaultDropShadow = { + alpha: 1, + angle: Math.PI / 6, + blur: 0, + color: "black", + distance: 5 +}; +tr.defaultTextStyle = { + align: "left", + breakWords: !1, + dropShadow: null, + fill: "black", + fontFamily: "Arial", + fontSize: 26, + fontStyle: "normal", + fontVariant: "normal", + fontWeight: "normal", + leading: 0, + letterSpacing: 0, + lineHeight: 0, + padding: 0, + stroke: null, + textBaseline: "alphabetic", + trim: !1, + whiteSpace: "pre", + wordWrap: !1, + wordWrapWidth: 100 +}; +let nr = tr; +function xf(i) { + const e = i; + if (typeof e.dropShadow == "boolean" && e.dropShadow) { + const t = nr.defaultDropShadow; + i.dropShadow = { + alpha: e.dropShadowAlpha ?? t.alpha, + angle: e.dropShadowAngle ?? t.angle, + blur: e.dropShadowBlur ?? t.blur, + color: e.dropShadowColor ?? t.color, + distance: e.dropShadowDistance ?? t.distance + }; + } + if (e.strokeThickness !== void 0) { + W(he, "strokeThickness is now a part of stroke"); + const t = e.stroke; + let n = {}; + if (pe.isColorLike(t)) + n.color = t; + else if (t instanceof Et || t instanceof Ei) + n.fill = t; + else if (Object.hasOwnProperty.call(t, "color") || Object.hasOwnProperty.call(t, "fill")) + n = t; + else + throw new Error("Invalid stroke value."); + i.stroke = { + ...n, + width: e.strokeThickness + }; + } + if (Array.isArray(e.fillGradientStops)) { + if (W(he, "gradient fill is now a fill pattern: `new FillGradient(...)`"), !Array.isArray(e.fill) || e.fill.length === 0) + throw new Error("Invalid fill value. Expected an array of colors for gradient fill."); + e.fill.length !== e.fillGradientStops.length && $e("The number of fill colors must match the number of fill gradient stops."); + const t = new Et({ + start: { x: 0, y: 0 }, + end: { x: 0, y: 1 }, + textureSpace: "local" + }), n = e.fillGradientStops.slice(), s = e.fill.map((r) => pe.shared.setValue(r).toNumber()); + n.forEach((r, a) => { + t.addColorStop(r, s[a]); + }), i.fill = { + fill: t + }; + } +} +class wf { + constructor(e) { + this._canvasPool = /* @__PURE__ */ Object.create(null), this.canvasOptions = e || {}, this.enableFullScreen = !1; + } + /** + * Creates texture with params that were specified in pool constructor. + * @param pixelWidth - Width of texture in pixels. + * @param pixelHeight - Height of texture in pixels. + */ + _createCanvasAndContext(e, t) { + const n = Ge.get().createCanvas(); + n.width = e, n.height = t; + const s = n.getContext("2d"); + return { canvas: n, context: s }; + } + /** + * Gets a Power-of-Two render texture or fullScreen texture + * @param minWidth - The minimum width of the render texture. + * @param minHeight - The minimum height of the render texture. + * @param resolution - The resolution of the render texture. + * @returns The new render texture. + */ + getOptimalCanvasAndContext(e, t, n = 1) { + e = Math.ceil(e * n - 1e-6), t = Math.ceil(t * n - 1e-6), e = tn(e), t = tn(t); + const s = (e << 17) + (t << 1); + this._canvasPool[s] || (this._canvasPool[s] = []); + let r = this._canvasPool[s].pop(); + return r || (r = this._createCanvasAndContext(e, t)), r; + } + /** + * Place a render texture back into the pool. + * @param canvasAndContext + */ + returnCanvasAndContext(e) { + const t = e.canvas, { width: n, height: s } = t, r = (n << 17) + (s << 1); + e.context.resetTransform(), e.context.clearRect(0, 0, n, s), this._canvasPool[r].push(e); + } + clear() { + this._canvasPool = {}; + } +} +const Fs = new wf(); +Bn.register(Fs); +const ba = 1e5; +function xa(i, e, t, n = 0) { + if (i.texture === K.WHITE && !i.fill) + return pe.shared.setValue(i.color).setAlpha(i.alpha ?? 1).toHexa(); + if (i.fill) { + if (i.fill instanceof Ei) { + const s = i.fill, r = e.createPattern(s.texture.source.resource, "repeat"), a = s.transform.copyTo(H.shared); + return a.scale( + s.texture.frame.width, + s.texture.frame.height + ), r.setTransform(a), r; + } else if (i.fill instanceof Et) { + const s = i.fill, r = s.type === "linear", a = s.textureSpace === "local"; + let o = 1, l = 1; + a && t && (o = t.width + n, l = t.height + n); + let h, u = !1; + if (r) { + const { start: c, end: d } = s; + h = e.createLinearGradient( + c.x * o, + c.y * l, + d.x * o, + d.y * l + ), u = Math.abs(d.x - c.x) < Math.abs((d.y - c.y) * 0.1); + } else { + const { center: c, innerRadius: d, outerCenter: f, outerRadius: _ } = s; + h = e.createRadialGradient( + c.x * o, + c.y * l, + d * o, + f.x * o, + f.y * l, + _ * o + ); + } + if (u && a && t) { + const c = t.lineHeight / l; + for (let d = 0; d < t.lines.length; d++) { + const f = (d * t.lineHeight + n / 2) / l; + s.colorStops.forEach((_) => { + const b = f + _.offset * c; + h.addColorStop( + // fix to 5 decimal places to avoid floating point precision issues + Math.floor(b * ba) / ba, + pe.shared.setValue(_.color).toHex() + ); + }); + } + } else + s.colorStops.forEach((c) => { + h.addColorStop(c.offset, pe.shared.setValue(c.color).toHex()); + }); + return h; + } + } else { + const s = e.createPattern(i.texture.source.resource, "repeat"), r = i.matrix.copyTo(H.shared); + return r.scale(i.texture.frame.width, i.texture.frame.height), s.setTransform(r), s; + } + return $e("FillStyle not recognised", i), "red"; +} +class bi extends Ws { + /** + * Creates a new Graphics object. + * @param options - Options for the Graphics. + */ + constructor(e) { + e instanceof ot && (e = { context: e }); + const { context: t, roundPixels: n, ...s } = e || {}; + super({ + label: "Graphics", + ...s + }), this.renderPipeId = "graphics", t ? this._context = t : this._context = this._ownedContext = new ot(), this._context.on("update", this.onViewUpdate, this), this.didViewUpdate = !0, this.allowChildren = !1, this.roundPixels = n ?? !1; + } + set context(e) { + e !== this._context && (this._context.off("update", this.onViewUpdate, this), this._context = e, this._context.on("update", this.onViewUpdate, this), this.onViewUpdate()); + } + /** + * The underlying graphics context used for drawing operations. + * Controls how shapes and paths are rendered. + * @example + * ```ts + * // Create a shared context + * const sharedContext = new GraphicsContext(); + * + * // Create graphics objects sharing the same context + * const graphics1 = new Graphics(); + * const graphics2 = new Graphics(); + * + * // Assign shared context + * graphics1.context = sharedContext; + * graphics2.context = sharedContext; + * + * // Both graphics will show the same shapes + * sharedContext + * .rect(0, 0, 100, 100) + * .fill({ color: 0xff0000 }); + * ``` + * @see {@link GraphicsContext} For drawing operations + * @see {@link GraphicsOptions} For context configuration + */ + get context() { + return this._context; + } + /** + * The local bounds of the graphics object. + * Returns the boundaries after all graphical operations but before any transforms. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Draw a shape + * graphics + * .rect(0, 0, 100, 100) + * .fill({ color: 0xff0000 }); + * + * // Get bounds information + * const bounds = graphics.bounds; + * console.log(bounds.width); // 100 + * console.log(bounds.height); // 100 + * ``` + * @readonly + * @see {@link Bounds} For bounds operations + * @see {@link Container#getBounds} For transformed bounds + */ + get bounds() { + return this._context.bounds; + } + /** + * Graphics objects do not need to update their bounds as the context handles this. + * @private + */ + updateBounds() { + } + /** + * Checks if the object contains the given point. + * Returns true if the point lies within the Graphics object's rendered area. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Draw a shape + * graphics + * .rect(0, 0, 100, 100) + * .fill({ color: 0xff0000 }); + * + * // Check point intersection + * if (graphics.containsPoint({ x: 50, y: 50 })) { + * console.log('Point is inside rectangle!'); + * } + * ``` + * @param point - The point to check in local coordinates + * @returns True if the point is inside the Graphics object + * @see {@link Graphics#bounds} For bounding box checks + * @see {@link PointData} For point data structure + */ + containsPoint(e) { + return this._context.containsPoint(e); + } + /** + * Destroys this graphics renderable and optionally its context. + * @param options - Options parameter. A boolean will act as if all options + * + * If the context was created by this graphics and `destroy(false)` or `destroy()` is called + * then the context will still be destroyed. + * + * If you want to explicitly not destroy this context that this graphics created, + * then you should pass destroy({ context: false }) + * + * If the context was passed in as an argument to the constructor then it will not be destroyed + * @example + * ```ts + * // Destroy the graphics and its context + * graphics.destroy(); + * graphics.destroy(true); + * graphics.destroy({ context: true, texture: true, textureSource: true }); + * ``` + */ + destroy(e) { + this._ownedContext && !e ? this._ownedContext.destroy(e) : (e === !0 || (e == null ? void 0 : e.context) === !0) && this._context.destroy(e), this._ownedContext = null, this._context = null, super.destroy(e); + } + _callContextMethod(e, t) { + return this.context[e](...t), this; + } + // --------------------------------------- GraphicsContext methods --------------------------------------- + /** + * Sets the current fill style of the graphics context. + * The fill style can be a color, gradient, pattern, or a complex style object. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Basic color fill + * graphics + * .setFillStyle({ color: 0xff0000 }) // Red fill + * .rect(0, 0, 100, 100) + * .fill(); + * + * // Gradient fill + * const gradient = new FillGradient({ + * end: { x: 1, y: 0 }, + * colorStops: [ + * { offset: 0, color: 0xff0000 }, // Red at start + * { offset: 0.5, color: 0x00ff00 }, // Green at middle + * { offset: 1, color: 0x0000ff }, // Blue at end + * ], + * }); + * + * graphics + * .setFillStyle(gradient) + * .circle(100, 100, 50) + * .fill(); + * + * // Pattern fill + * const pattern = new FillPattern(texture); + * graphics + * .setFillStyle({ + * fill: pattern, + * alpha: 0.5 + * }) + * .rect(0, 0, 200, 200) + * .fill(); + * ``` + * @param {FillInput} args - The fill style to apply + * @returns The Graphics instance for chaining + * @see {@link FillStyle} For fill style options + * @see {@link FillGradient} For gradient fills + * @see {@link FillPattern} For pattern fills + */ + setFillStyle(...e) { + return this._callContextMethod("setFillStyle", e); + } + /** + * Sets the current stroke style of the graphics context. + * Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Basic color stroke + * graphics + * .setStrokeStyle({ + * width: 2, + * color: 0x000000 + * }) + * .rect(0, 0, 100, 100) + * .stroke(); + * + * // Complex stroke style + * graphics + * .setStrokeStyle({ + * width: 4, + * color: 0xff0000, + * alpha: 0.5, + * join: 'round', + * cap: 'round', + * alignment: 0.5 + * }) + * .circle(100, 100, 50) + * .stroke(); + * + * // Gradient stroke + * const gradient = new FillGradient({ + * end: { x: 1, y: 0 }, + * colorStops: [ + * { offset: 0, color: 0xff0000 }, // Red at start + * { offset: 0.5, color: 0x00ff00 }, // Green at middle + * { offset: 1, color: 0x0000ff }, // Blue at end + * ], + * }); + * + * graphics + * .setStrokeStyle({ + * width: 10, + * fill: gradient + * }) + * .poly([0,0, 100,50, 0,100]) + * .stroke(); + * ``` + * @param {StrokeInput} args - The stroke style to apply + * @returns The Graphics instance for chaining + * @see {@link StrokeStyle} For stroke style options + * @see {@link FillGradient} For gradient strokes + * @see {@link FillPattern} For pattern strokes + */ + setStrokeStyle(...e) { + return this._callContextMethod("setStrokeStyle", e); + } + fill(...e) { + return this._callContextMethod("fill", e); + } + /** + * Strokes the current path with the current stroke style or specified style. + * Outlines the shape using the stroke settings. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Stroke with direct color + * graphics + * .circle(50, 50, 25) + * .stroke({ + * width: 2, + * color: 0xff0000 + * }); // 2px red stroke + * + * // Fill with texture + * graphics + * .rect(0, 0, 100, 100) + * .stroke(myTexture); // Fill with texture + * + * // Stroke with gradient + * const gradient = new FillGradient({ + * end: { x: 1, y: 0 }, + * colorStops: [ + * { offset: 0, color: 0xff0000 }, + * { offset: 0.5, color: 0x00ff00 }, + * { offset: 1, color: 0x0000ff }, + * ], + * }); + * + * graphics + * .rect(0, 0, 100, 100) + * .stroke({ + * width: 4, + * fill: gradient, + * alignment: 0.5, + * join: 'round' + * }); + * ``` + * @param {StrokeStyle} args - Optional stroke style to apply. Can be: + * - A stroke style object with width, color, etc. + * - A gradient + * - A pattern + * If omitted, uses current stroke style. + * @returns The Graphics instance for chaining + * @see {@link StrokeStyle} For stroke style options + * @see {@link FillGradient} For gradient strokes + * @see {@link setStrokeStyle} For setting default stroke style + */ + stroke(...e) { + return this._callContextMethod("stroke", e); + } + texture(...e) { + return this._callContextMethod("texture", e); + } + /** + * Resets the current path. Any previous path and its commands are discarded and a new path is + * started. This is typically called before beginning a new shape or series of drawing commands. + * @example + * ```ts + * const graphics = new Graphics(); + * graphics + * .circle(150, 150, 50) + * .fill({ color: 0x00ff00 }) + * .beginPath() // Starts a new path + * .circle(250, 150, 50) + * .fill({ color: 0x0000ff }); + * ``` + * @returns The Graphics instance for chaining + * @see {@link Graphics#moveTo} For starting a new subpath + * @see {@link Graphics#closePath} For closing the current path + */ + beginPath() { + return this._callContextMethod("beginPath", []); + } + /** + * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by + * subtracting a path from the previously drawn path. + * + * If a hole is not completely in a shape, it will fail to cut correctly. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Draw outer circle + * graphics + * .circle(100, 100, 50) + * .fill({ color: 0xff0000 }); + * .circle(100, 100, 25) // Inner circle + * .cut() // Cuts out the inner circle from the outer circle + * ``` + */ + cut() { + return this._callContextMethod("cut", []); + } + arc(...e) { + return this._callContextMethod("arc", e); + } + arcTo(...e) { + return this._callContextMethod("arcTo", e); + } + arcToSvg(...e) { + return this._callContextMethod("arcToSvg", e); + } + bezierCurveTo(...e) { + return this._callContextMethod("bezierCurveTo", e); + } + /** + * Closes the current path by drawing a straight line back to the start point. + * + * This is useful for completing shapes and ensuring they are properly closed for fills. + * @example + * ```ts + * // Create a triangle with closed path + * const graphics = new Graphics(); + * graphics + * .moveTo(50, 50) + * .lineTo(100, 100) + * .lineTo(0, 100) + * .closePath() + * ``` + * @returns The Graphics instance for method chaining + * @see {@link Graphics#beginPath} For starting a new path + * @see {@link Graphics#fill} For filling closed paths + * @see {@link Graphics#stroke} For stroking paths + */ + closePath() { + return this._callContextMethod("closePath", []); + } + ellipse(...e) { + return this._callContextMethod("ellipse", e); + } + circle(...e) { + return this._callContextMethod("circle", e); + } + path(...e) { + return this._callContextMethod("path", e); + } + lineTo(...e) { + return this._callContextMethod("lineTo", e); + } + moveTo(...e) { + return this._callContextMethod("moveTo", e); + } + quadraticCurveTo(...e) { + return this._callContextMethod("quadraticCurveTo", e); + } + rect(...e) { + return this._callContextMethod("rect", e); + } + roundRect(...e) { + return this._callContextMethod("roundRect", e); + } + poly(...e) { + return this._callContextMethod("poly", e); + } + regularPoly(...e) { + return this._callContextMethod("regularPoly", e); + } + roundPoly(...e) { + return this._callContextMethod("roundPoly", e); + } + roundShape(...e) { + return this._callContextMethod("roundShape", e); + } + filletRect(...e) { + return this._callContextMethod("filletRect", e); + } + chamferRect(...e) { + return this._callContextMethod("chamferRect", e); + } + star(...e) { + return this._callContextMethod("star", e); + } + svg(...e) { + return this._callContextMethod("svg", e); + } + restore(...e) { + return this._callContextMethod("restore", e); + } + /** + * Saves the current graphics state onto a stack. The state includes: + * - Current transformation matrix + * - Current fill style + * - Current stroke style + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Save state before complex operations + * graphics.save(); + * + * // Create transformed and styled shape + * graphics + * .translateTransform(100, 100) + * .rotateTransform(Math.PI / 4) + * .setFillStyle({ + * color: 0xff0000, + * alpha: 0.5 + * }) + * .rect(-25, -25, 50, 50) + * .fill(); + * + * // Restore to original state + * graphics.restore(); + * + * // Continue drawing with previous state + * graphics + * .circle(50, 50, 25) + * .fill(); + * ``` + * @returns The Graphics instance for method chaining + * @see {@link Graphics#restore} For restoring the saved state + * @see {@link Graphics#setTransform} For setting transformations + */ + save() { + return this._callContextMethod("save", []); + } + /** + * Returns the current transformation matrix of the graphics context. + * This matrix represents all accumulated transformations including translate, scale, and rotate. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Apply some transformations + * graphics + * .translateTransform(100, 100) + * .rotateTransform(Math.PI / 4); + * + * // Get the current transform matrix + * const matrix = graphics.getTransform(); + * console.log(matrix.tx, matrix.ty); // 100, 100 + * + * // Use the matrix for other operations + * graphics + * .setTransform(matrix) + * .circle(0, 0, 50) + * .fill({ color: 0xff0000 }); + * ``` + * @returns The current transformation matrix. + * @see {@link Graphics#setTransform} For setting the transform matrix + * @see {@link Matrix} For matrix operations + */ + getTransform() { + return this.context.getTransform(); + } + /** + * Resets the current transformation matrix to the identity matrix, effectively removing + * any transformations (rotation, scaling, translation) previously applied. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Apply transformations + * graphics + * .translateTransform(100, 100) + * .scaleTransform(2, 2) + * .circle(0, 0, 25) + * .fill({ color: 0xff0000 }); + * // Reset transform to default state + * graphics + * .resetTransform() + * .circle(50, 50, 25) // Will draw at actual coordinates + * .fill({ color: 0x00ff00 }); + * ``` + * @returns The Graphics instance for method chaining + * @see {@link Graphics#getTransform} For getting the current transform + * @see {@link Graphics#setTransform} For setting a specific transform + * @see {@link Graphics#save} For saving the current transform state + * @see {@link Graphics#restore} For restoring a previous transform state + */ + resetTransform() { + return this._callContextMethod("resetTransform", []); + } + rotateTransform(...e) { + return this._callContextMethod("rotate", e); + } + scaleTransform(...e) { + return this._callContextMethod("scale", e); + } + setTransform(...e) { + return this._callContextMethod("setTransform", e); + } + transform(...e) { + return this._callContextMethod("transform", e); + } + translateTransform(...e) { + return this._callContextMethod("translate", e); + } + /** + * Clears all drawing commands from the graphics context, effectively resetting it. + * This includes clearing the current path, fill style, stroke style, and transformations. + * + * > [!NOTE] Graphics objects are not designed to be continuously cleared and redrawn. + * > Instead, they are intended to be used for static or semi-static graphics that + * > can be redrawn as needed. Frequent clearing and redrawing may lead to performance issues. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Draw some shapes + * graphics + * .circle(100, 100, 50) + * .fill({ color: 0xff0000 }) + * .rect(200, 100, 100, 50) + * .fill({ color: 0x00ff00 }); + * + * // Clear all graphics + * graphics.clear(); + * + * // Start fresh with new shapes + * graphics + * .circle(150, 150, 30) + * .fill({ color: 0x0000ff }); + * ``` + * @returns The Graphics instance for method chaining + * @see {@link Graphics#beginPath} For starting a new path without clearing styles + * @see {@link Graphics#save} For saving the current state + * @see {@link Graphics#restore} For restoring a previous state + */ + clear() { + return this._callContextMethod("clear", []); + } + /** + * Gets or sets the current fill style for the graphics context. The fill style determines + * how shapes are filled when using the fill() method. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Basic color fill + * graphics.fillStyle = { + * color: 0xff0000, // Red + * alpha: 1 + * }; + * + * // Using gradients + * const gradient = new FillGradient({ + * end: { x: 0, y: 1 }, // Vertical gradient + * stops: [ + * { offset: 0, color: 0xff0000, alpha: 1 }, // Start color + * { offset: 1, color: 0x0000ff, alpha: 1 } // End color + * ] + * }); + * + * graphics.fillStyle = { + * fill: gradient, + * alpha: 0.8 + * }; + * + * // Using patterns + * graphics.fillStyle = { + * texture: myTexture, + * alpha: 1, + * matrix: new Matrix() + * .scale(0.5, 0.5) + * .rotate(Math.PI / 4) + * }; + * ``` + * @type {ConvertedFillStyle} + * @see {@link FillStyle} For all available fill style options + * @see {@link FillGradient} For creating gradient fills + * @see {@link Graphics#fill} For applying the fill to paths + */ + get fillStyle() { + return this._context.fillStyle; + } + set fillStyle(e) { + this._context.fillStyle = e; + } + /** + * Gets or sets the current stroke style for the graphics context. The stroke style determines + * how paths are outlined when using the stroke() method. + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Basic stroke style + * graphics.strokeStyle = { + * width: 2, + * color: 0xff0000, + * alpha: 1 + * }; + * + * // Using with gradients + * const gradient = new FillGradient({ + * end: { x: 0, y: 1 }, + * stops: [ + * { offset: 0, color: 0xff0000, alpha: 1 }, + * { offset: 1, color: 0x0000ff, alpha: 1 } + * ] + * }); + * + * graphics.strokeStyle = { + * width: 4, + * fill: gradient, + * alignment: 0.5, + * join: 'round', + * cap: 'round' + * }; + * + * // Complex stroke settings + * graphics.strokeStyle = { + * width: 6, + * color: 0x00ff00, + * alpha: 0.5, + * join: 'miter', + * miterLimit: 10, + * }; + * ``` + * @see {@link StrokeStyle} For all available stroke style options + * @see {@link Graphics#stroke} For applying the stroke to paths + */ + get strokeStyle() { + return this._context.strokeStyle; + } + set strokeStyle(e) { + this._context.strokeStyle = e; + } + /** + * Creates a new Graphics object that copies the current graphics content. + * The clone can either share the same context (shallow clone) or have its own independent + * context (deep clone). + * @example + * ```ts + * const graphics = new Graphics(); + * + * // Create original graphics content + * graphics + * .circle(100, 100, 50) + * .fill({ color: 0xff0000 }); + * + * // Create a shallow clone (shared context) + * const shallowClone = graphics.clone(); + * + * // Changes to original affect the clone + * graphics + * .circle(200, 100, 30) + * .fill({ color: 0x00ff00 }); + * + * // Create a deep clone (independent context) + * const deepClone = graphics.clone(true); + * + * // Modify deep clone independently + * deepClone + * .translateTransform(100, 100) + * .circle(0, 0, 40) + * .fill({ color: 0x0000ff }); + * ``` + * @param deep - Whether to create a deep clone of the graphics object. + * If false (default), the context will be shared between objects. + * If true, creates an independent copy of the context. + * @returns A new Graphics instance with either shared or copied context + * @see {@link Graphics#context} For accessing the underlying graphics context + * @see {@link GraphicsContext} For understanding the shared context behavior + */ + clone(e = !1) { + return e ? new bi(this._context.clone()) : (this._ownedContext = null, new bi(this._context)); + } + // -------- v7 deprecations --------- + /** + * @param width + * @param color + * @param alpha + * @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead + */ + lineStyle(e, t, n) { + W(he, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style."); + const s = {}; + return e && (s.width = e), t && (s.color = t), n && (s.alpha = n), this.context.strokeStyle = s, this; + } + /** + * @param color + * @param alpha + * @deprecated since 8.0.0 Use {@link Graphics#fill} instead + */ + beginFill(e, t) { + W(he, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."); + const n = {}; + return e !== void 0 && (n.color = e), t !== void 0 && (n.alpha = t), this.context.fillStyle = n, this; + } + /** + * @deprecated since 8.0.0 Use {@link Graphics#fill} instead + */ + endFill() { + W(he, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."), this.context.fill(); + const e = this.context.strokeStyle; + return (e.width !== ot.defaultStrokeStyle.width || e.color !== ot.defaultStrokeStyle.color || e.alpha !== ot.defaultStrokeStyle.alpha) && this.context.stroke(), this; + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#circle} instead + */ + drawCircle(...e) { + return W(he, "Graphics#drawCircle has been renamed to Graphics#circle"), this._callContextMethod("circle", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead + */ + drawEllipse(...e) { + return W(he, "Graphics#drawEllipse has been renamed to Graphics#ellipse"), this._callContextMethod("ellipse", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#poly} instead + */ + drawPolygon(...e) { + return W(he, "Graphics#drawPolygon has been renamed to Graphics#poly"), this._callContextMethod("poly", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#rect} instead + */ + drawRect(...e) { + return W(he, "Graphics#drawRect has been renamed to Graphics#rect"), this._callContextMethod("rect", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead + */ + drawRoundedRect(...e) { + return W(he, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect"), this._callContextMethod("roundRect", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#star} instead + */ + drawStar(...e) { + return W(he, "Graphics#drawStar has been renamed to Graphics#star"), this._callContextMethod("star", e); + } +} +class vf extends Ws { + constructor(e, t) { + const { text: n, resolution: s, style: r, anchor: a, width: o, height: l, roundPixels: h, ...u } = e; + super({ + ...u + }), this.batched = !0, this._resolution = null, this._autoResolution = !0, this._didTextUpdate = !0, this._styleClass = t, this.text = n ?? "", this.style = r, this.resolution = s ?? null, this.allowChildren = !1, this._anchor = new Ce( + { + _onUpdate: () => { + this.onViewUpdate(); + } + } + ), a && (this.anchor = a), this.roundPixels = h ?? !1, o !== void 0 && (this.width = o), l !== void 0 && (this.height = l); + } + /** + * The anchor point of the text that controls the origin point for positioning and rotation. + * Can be a number (same value for x/y) or a PointData object. + * - (0,0) is top-left + * - (0.5,0.5) is center + * - (1,1) is bottom-right + * ```ts + * // Set anchor to center + * const text = new Text({ + * text: 'Hello Pixi!', + * anchor: 0.5 // Same as { x: 0.5, y: 0.5 } + * }); + * // Set anchor to top-left + * const text2 = new Text({ + * text: 'Hello Pixi!', + * anchor: { x: 0, y: 0 } // Top-left corner + * }); + * // Set anchor to bottom-right + * const text3 = new Text({ + * text: 'Hello Pixi!', + * anchor: { x: 1, y: 1 } // Bottom-right corner + * }); + * ``` + * @default { x: 0, y: 0 } + */ + get anchor() { + return this._anchor; + } + set anchor(e) { + typeof e == "number" ? this._anchor.set(e) : this._anchor.copyFrom(e); + } + /** + * The text content to display. Use '\n' for line breaks. + * Accepts strings, numbers, or objects with toString() method. + * @example + * ```ts + * const text = new Text({ + * text: 'Hello Pixi!', + * }); + * const multilineText = new Text({ + * text: 'Line 1\nLine 2\nLine 3', + * }); + * const numberText = new Text({ + * text: 12345, // Will be converted to '12345' + * }); + * const objectText = new Text({ + * text: { toString: () => 'Object Text' }, // Custom toString + * }); + * + * // Update text dynamically + * text.text = 'Updated Text'; // Re-renders with new text + * text.text = 67890; // Updates to '67890' + * text.text = { toString: () => 'Dynamic Text' }; // Uses custom toString method + * // Clear text + * text.text = ''; // Clears the text + * ``` + * @default '' + */ + set text(e) { + e = e.toString(), this._text !== e && (this._text = e, this.onViewUpdate()); + } + get text() { + return this._text; + } + /** + * The resolution/device pixel ratio for rendering. + * Higher values result in sharper text at the cost of performance. + * Set to null for auto-resolution based on device. + * @example + * ```ts + * const text = new Text({ + * text: 'Hello Pixi!', + * resolution: 2 // High DPI for sharper text + * }); + * const autoResText = new Text({ + * text: 'Auto Resolution', + * resolution: null // Use device's pixel ratio + * }); + * ``` + * @default null + */ + set resolution(e) { + this._autoResolution = e === null, this._resolution = e, this.onViewUpdate(); + } + get resolution() { + return this._resolution; + } + get style() { + return this._style; + } + /** + * The style configuration for the text. + * Can be a TextStyle instance or a configuration object. + * Supports canvas text styles, HTML text styles, and bitmap text styles. + * @example + * ```ts + * const text = new Text({ + * text: 'Styled Text', + * style: { + * fontSize: 24, + * fill: 0xff1010, // Red color + * fontFamily: 'Arial', + * align: 'center', // Center alignment + * stroke: { color: '#4a1850', width: 5 }, // Purple stroke + * dropShadow: { + * color: '#000000', // Black shadow + * blur: 4, // Shadow blur + * distance: 6 // Shadow distance + * } + * } + * }); + * const htmlText = new HTMLText({ + * text: 'HTML Styled Text', + * style: { + * fontSize: '20px', + * fill: 'blue', + * fontFamily: 'Verdana', + * } + * }); + * const bitmapText = new BitmapText({ + * text: 'Bitmap Styled Text', + * style: { + * fontName: 'Arial', + * fontSize: 32, + * } + * }) + * + * // Update style dynamically + * text.style = { + * fontSize: 30, // Change font size + * fill: 0x00ff00, // Change color to green + * align: 'right', // Change alignment to right + * stroke: { color: '#000000', width: 2 }, // Add black stroke + * } + */ + set style(e) { + var t; + e || (e = {}), (t = this._style) == null || t.off("update", this.onViewUpdate, this), e instanceof this._styleClass ? this._style = e : this._style = new this._styleClass(e), this._style.on("update", this.onViewUpdate, this), this.onViewUpdate(); + } + /** + * The width of the sprite, setting this will actually modify the scale to achieve the value set. + * @example + * ```ts + * // Set width directly + * texture.width = 200; + * console.log(texture.scale.x); // Scale adjusted to match width + * + * // For better performance when setting both width and height + * texture.setSize(300, 400); // Avoids recalculating bounds twice + * ``` + */ + get width() { + return Math.abs(this.scale.x) * this.bounds.width; + } + set width(e) { + this._setWidth(e, this.bounds.width); + } + /** + * The height of the sprite, setting this will actually modify the scale to achieve the value set. + * @example + * ```ts + * // Set height directly + * texture.height = 200; + * console.log(texture.scale.y); // Scale adjusted to match height + * + * // For better performance when setting both width and height + * texture.setSize(300, 400); // Avoids recalculating bounds twice + * ``` + */ + get height() { + return Math.abs(this.scale.y) * this.bounds.height; + } + set height(e) { + this._setHeight(e, this.bounds.height); + } + /** + * Retrieves the size of the Text as a [Size]{@link Size} object based on the texture dimensions and scale. + * This is faster than getting width and height separately as it only calculates the bounds once. + * @example + * ```ts + * // Basic size retrieval + * const text = new Text({ + * text: 'Hello Pixi!', + * style: { fontSize: 24 } + * }); + * const size = text.getSize(); + * console.log(`Size: ${size.width}x${size.height}`); + * + * // Reuse existing size object + * const reuseSize = { width: 0, height: 0 }; + * text.getSize(reuseSize); + * ``` + * @param out - Optional object to store the size in, to avoid allocating a new object + * @returns The size of the Sprite + * @see {@link Text#width} For getting just the width + * @see {@link Text#height} For getting just the height + * @see {@link Text#setSize} For setting both width and height + */ + getSize(e) { + return e || (e = {}), e.width = Math.abs(this.scale.x) * this.bounds.width, e.height = Math.abs(this.scale.y) * this.bounds.height, e; + } + /** + * Sets the size of the Text to the specified width and height. + * This is faster than setting width and height separately as it only recalculates bounds once. + * @example + * ```ts + * // Basic size setting + * const text = new Text({ + * text: 'Hello Pixi!', + * style: { fontSize: 24 } + * }); + * text.setSize(100, 200); // Width: 100, Height: 200 + * + * // Set uniform size + * text.setSize(100); // Sets both width and height to 100 + * + * // Set size with object + * text.setSize({ + * width: 200, + * height: 300 + * }); + * ``` + * @param value - This can be either a number or a {@link Size} object + * @param height - The height to set. Defaults to the value of `width` if not provided + * @see {@link Text#width} For setting width only + * @see {@link Text#height} For setting height only + */ + setSize(e, t) { + typeof e == "object" ? (t = e.height ?? e.width, e = e.width) : t ?? (t = e), e !== void 0 && this._setWidth(e, this.bounds.width), t !== void 0 && this._setHeight(t, this.bounds.height); + } + /** + * Checks if the object contains the given point in local coordinates. + * Uses the text's bounds for hit testing. + * @example + * ```ts + * // Basic point check + * const localPoint = { x: 50, y: 25 }; + * const contains = text.containsPoint(localPoint); + * console.log('Point is inside:', contains); + * ``` + * @param point - The point to check in local coordinates + * @returns True if the point is within the text's bounds + * @see {@link Container#toLocal} For converting global coordinates to local + */ + containsPoint(e) { + const t = this.bounds.width, n = this.bounds.height, s = -t * this.anchor.x; + let r = 0; + return e.x >= s && e.x <= s + t && (r = -n * this.anchor.y, e.y >= r && e.y <= r + n); + } + /** @internal */ + onViewUpdate() { + this.didViewUpdate || (this._didTextUpdate = !0), super.onViewUpdate(); + } + /** + * Destroys this text renderable and optionally its style texture. + * @param options - Options parameter. A boolean will act as if all options + * have been set to that value + * @example + * // Destroys the text and its style + * text.destroy({ style: true, texture: true, textureSource: true }); + * text.destroy(true); + * text.destroy() // Destroys the text, but not its style + */ + destroy(e = !1) { + super.destroy(e), this.owner = null, this._bounds = null, this._anchor = null, (typeof e == "boolean" ? e : e != null && e.style) && this._style.destroy(e), this._style = null, this._text = null; + } + /** + * Returns a unique key for this instance. + * This key is used for caching. + * @returns {string} Unique key for the instance + */ + get styleKey() { + return `${this._text}:${this._style.styleKey}:${this._resolution}`; + } +} +function Cf(i, e) { + let t = i[0] ?? {}; + return (typeof t == "string" || i[1]) && (W(he, `use new ${e}({ text: "hi!", style }) instead`), t = { + text: t, + style: i[1] + }), t; +} +let Pt = null, St = null; +function Sf(i, e) { + Pt || (Pt = Ge.get().createCanvas(256, 128), St = Pt.getContext("2d", { willReadFrequently: !0 }), St.globalCompositeOperation = "copy", St.globalAlpha = 1), (Pt.width < i || Pt.height < e) && (Pt.width = tn(i), Pt.height = tn(e)); +} +function wa(i, e, t) { + for (let n = 0, s = 4 * t * e; n < e; ++n, s += 4) + if (i[s + 3] !== 0) + return !1; + return !0; +} +function va(i, e, t, n, s) { + const r = 4 * e; + for (let a = n, o = n * r + 4 * t; a <= s; ++a, o += r) + if (i[o + 3] !== 0) + return !1; + return !0; +} +function kf(...i) { + let e = i[0]; + e.canvas || (e = { canvas: i[0], resolution: i[1] }); + const { canvas: t } = e, n = Math.min(e.resolution ?? 1, 1), s = e.width ?? t.width, r = e.height ?? t.height; + let a = e.output; + if (Sf(s, r), !St) + throw new TypeError("Failed to get canvas 2D context"); + St.drawImage( + t, + 0, + 0, + s, + r, + 0, + 0, + s * n, + r * n + ); + const l = St.getImageData(0, 0, s, r).data; + let h = 0, u = 0, c = s - 1, d = r - 1; + for (; u < r && wa(l, s, u); ) + ++u; + if (u === r) + return de.EMPTY; + for (; wa(l, s, d); ) + --d; + for (; va(l, s, h, u, d); ) + ++h; + for (; va(l, s, c, u, d); ) + --c; + return ++c, ++d, St.globalCompositeOperation = "source-over", St.strokeRect(h, u, c - h, d - u), St.globalCompositeOperation = "copy", a ?? (a = new de()), a.set(h / n, u / n, (c - h) / n, (d - u) / n), a; +} +const Ca = new de(); +class Af { + /** + * Creates a canvas with the specified text rendered to it. + * + * Generates a canvas of appropriate size, renders the text with the provided style, + * and returns both the canvas/context and a Rectangle representing the text bounds. + * + * When trim is enabled in the style, the frame will represent the bounds of the + * non-transparent pixels, which can be smaller than the full canvas. + * @param options - The options for generating the text canvas + * @param options.text - The text to render + * @param options.style - The style to apply to the text + * @param options.resolution - The resolution of the canvas (defaults to 1) + * @param options.padding + * @returns An object containing the canvas/context and the frame (bounds) of the text + */ + getCanvasAndContext(e) { + const { text: t, style: n, resolution: s = 1 } = e, r = n._getFinalPadding(), a = Zt.measureText(t || " ", n), o = Math.ceil(Math.ceil(Math.max(1, a.width) + r * 2) * s), l = Math.ceil(Math.ceil(Math.max(1, a.height) + r * 2) * s), h = Fs.getOptimalCanvasAndContext(o, l); + this._renderTextToCanvas(t, n, r, s, h); + const u = n.trim ? kf({ canvas: h.canvas, width: o, height: l, resolution: 1, output: Ca }) : Ca.set(0, 0, o, l); + return { + canvasAndContext: h, + frame: u + }; + } + /** + * Returns a canvas and context to the pool. + * + * This should be called when you're done with the canvas to allow reuse + * and prevent memory leaks. + * @param canvasAndContext - The canvas and context to return to the pool + */ + returnCanvasAndContext(e) { + Fs.returnCanvasAndContext(e); + } + /** + * Renders text to its canvas, and updates its texture. + * @param text - The text to render + * @param style - The style of the text + * @param padding - The padding of the text + * @param resolution - The resolution of the text + * @param canvasAndContext - The canvas and context to render the text to + */ + _renderTextToCanvas(e, t, n, s, r) { + var p, y, C, w; + const { canvas: a, context: o } = r, l = Cl(t), h = Zt.measureText(e || " ", t), u = h.lines, c = h.lineHeight, d = h.lineWidths, f = h.maxLineWidth, _ = h.fontProperties, b = a.height; + if (o.resetTransform(), o.scale(s, s), o.textBaseline = t.textBaseline, (p = t._stroke) != null && p.width) { + const v = t._stroke; + o.lineWidth = v.width, o.miterLimit = v.miterLimit, o.lineJoin = v.join, o.lineCap = v.cap; + } + o.font = l; + let m, x; + const g = t.dropShadow ? 2 : 1; + for (let v = 0; v < g; ++v) { + const D = t.dropShadow && v === 0, S = D ? Math.ceil(Math.max(1, b) + n * 2) : 0, A = S * s; + if (D) { + o.fillStyle = "black", o.strokeStyle = "black"; + const B = t.dropShadow, N = B.color, Y = B.alpha; + o.shadowColor = pe.shared.setValue(N).setAlpha(Y).toRgbaString(); + const F = B.blur * s, T = B.distance * s; + o.shadowBlur = F, o.shadowOffsetX = Math.cos(B.angle) * T, o.shadowOffsetY = Math.sin(B.angle) * T + A; + } else { + if (o.fillStyle = t._fill ? xa(t._fill, o, h, n * 2) : null, (y = t._stroke) != null && y.width) { + const B = t._stroke.width * 0.5 + n * 2; + o.strokeStyle = xa(t._stroke, o, h, B); + } + o.shadowColor = "black"; + } + let E = (c - _.fontSize) / 2; + c - _.fontSize < 0 && (E = 0); + const I = ((C = t._stroke) == null ? void 0 : C.width) ?? 0; + for (let B = 0; B < u.length; B++) + m = I / 2, x = I / 2 + B * c + _.ascent + E, t.align === "right" ? m += f - d[B] : t.align === "center" && (m += (f - d[B]) / 2), (w = t._stroke) != null && w.width && this._drawLetterSpacing( + u[B], + t, + r, + m + n, + x + n - S, + !0 + ), t._fill !== void 0 && this._drawLetterSpacing( + u[B], + t, + r, + m + n, + x + n - S + ); + } + } + /** + * Render the text with letter-spacing. + * + * This method handles rendering text with the correct letter spacing, using either: + * 1. Native letter spacing if supported by the browser + * 2. Manual letter spacing calculation if not natively supported + * + * For manual letter spacing, it calculates the position of each character + * based on its width and the desired spacing. + * @param text - The text to draw + * @param style - The text style to apply + * @param canvasAndContext - The canvas and context to draw to + * @param x - Horizontal position to draw the text + * @param y - Vertical position to draw the text + * @param isStroke - Whether to render the stroke (true) or fill (false) + * @private + */ + _drawLetterSpacing(e, t, n, s, r, a = !1) { + const { context: o } = n, l = t.letterSpacing; + let h = !1; + if (Zt.experimentalLetterSpacingSupported && (Zt.experimentalLetterSpacing ? (o.letterSpacing = `${l}px`, o.textLetterSpacing = `${l}px`, h = !0) : (o.letterSpacing = "0px", o.textLetterSpacing = "0px")), l === 0 || h) { + a ? o.strokeText(e, s, r) : o.fillText(e, s, r); + return; + } + let u = s; + const c = Zt.graphemeSegmenter(e); + let d = o.measureText(e).width, f = 0; + for (let _ = 0; _ < c.length; ++_) { + const b = c[_]; + a ? o.strokeText(b, u, r) : o.fillText(b, u, r); + let m = ""; + for (let x = _ + 1; x < c.length; ++x) + m += c[x]; + f = o.measureText(m).width, u += d - f + l, d = f; + } + } +} +const Sa = new Af(); +class Df extends vf { + constructor(...e) { + const t = Cf(e, "Text"); + super(t, nr), this.renderPipeId = "text", t.textureStyle && (this.textureStyle = t.textureStyle instanceof _i ? t.textureStyle : new _i(t.textureStyle)); + } + /** @private */ + updateBounds() { + const e = this._bounds, t = this._anchor; + let n = 0, s = 0; + if (this._style.trim) { + const { frame: r, canvasAndContext: a } = Sa.getCanvasAndContext({ + text: this.text, + style: this._style, + resolution: 1 + }); + Sa.returnCanvasAndContext(a), n = r.width, s = r.height; + } else { + const r = Zt.measureText( + this._text, + this._style + ); + n = r.width, s = r.height; + } + e.minX = -t._x * n, e.maxX = e.minX + n, e.minY = -t._y * s, e.maxY = e.minY + s; + } +} +Qe.add(Sh, kh); +const { + SvelteComponent: Ef, + append_hydration: $s, + assign: Ff, + attr: ke, + binding_callbacks: $f, + children: kn, + claim_element: Gl, + claim_space: ql, + claim_svg_element: es, + create_slot: Tf, + detach: gt, + element: Ul, + empty: ka, + get_all_dirty_from_scope: Mf, + get_slot_changes: Pf, + get_spread_update: If, + init: Rf, + insert_hydration: Rn, + listen: Bf, + noop: Lf, + safe_not_equal: Of, + set_dynamic_element_data: Aa, + set_style: Z, + space: Hl, + svg_element: ts, + toggle_class: be, + transition_in: Vl, + transition_out: Wl, + update_slot_base: zf +} = window.__gradio__svelte__internal; +function Da(i) { + let e, t, n, s, r; + return { + c() { + e = ts("svg"), t = ts("line"), n = ts("line"), this.h(); + }, + l(a) { + e = es(a, "svg", { class: !0, xmlns: !0, viewBox: !0 }); + var o = kn(e); + t = es(o, "line", { + x1: !0, + y1: !0, + x2: !0, + y2: !0, + stroke: !0, + "stroke-width": !0 + }), kn(t).forEach(gt), n = es(o, "line", { + x1: !0, + y1: !0, + x2: !0, + y2: !0, + stroke: !0, + "stroke-width": !0 + }), kn(n).forEach(gt), o.forEach(gt), this.h(); + }, + h() { + ke(t, "x1", "1"), ke(t, "y1", "9"), ke(t, "x2", "9"), ke(t, "y2", "1"), ke(t, "stroke", "gray"), ke(t, "stroke-width", "0.5"), ke(n, "x1", "5"), ke(n, "y1", "9"), ke(n, "x2", "9"), ke(n, "y2", "5"), ke(n, "stroke", "gray"), ke(n, "stroke-width", "0.5"), ke(e, "class", "resize-handle svelte-239wnu"), ke(e, "xmlns", "http://www.w3.org/2000/svg"), ke(e, "viewBox", "0 0 10 10"); + }, + m(a, o) { + Rn(a, e, o), $s(e, t), $s(e, n), s || (r = Bf( + e, + "mousedown", + /*resize*/ + i[27] + ), s = !0); + }, + p: Lf, + d(a) { + a && gt(e), s = !1, r(); + } + }; +} +function Nf(i) { + var c; + let e, t, n, s, r; + const a = ( + /*#slots*/ + i[31].default + ), o = Tf( + a, + i, + /*$$scope*/ + i[30], + null + ); + let l = ( + /*resizable*/ + i[19] && Da(i) + ), h = [ + { "data-testid": ( + /*test_id*/ + i[11] + ) }, + { id: ( + /*elem_id*/ + i[6] + ) }, + { + class: n = "block " + /*elem_classes*/ + (((c = i[7]) == null ? void 0 : c.join(" ")) || "") + " svelte-239wnu" + }, + { + dir: s = /*rtl*/ + i[20] ? "rtl" : "ltr" + } + ], u = {}; + for (let d = 0; d < h.length; d += 1) + u = Ff(u, h[d]); + return { + c() { + e = Ul( + /*tag*/ + i[25] + ), o && o.c(), t = Hl(), l && l.c(), this.h(); + }, + l(d) { + e = Gl( + d, + /*tag*/ + (i[25] || "null").toUpperCase(), + { + "data-testid": !0, + id: !0, + class: !0, + dir: !0 + } + ); + var f = kn(e); + o && o.l(f), t = ql(f), l && l.l(f), f.forEach(gt), this.h(); + }, + h() { + Aa( + /*tag*/ + i[25] + )(e, u), be( + e, + "hidden", + /*visible*/ + i[14] === !1 || /*visible*/ + i[14] === "hidden" + ), be( + e, + "padded", + /*padding*/ + i[10] + ), be( + e, + "flex", + /*flex*/ + i[1] + ), be( + e, + "border_focus", + /*border_mode*/ + i[9] === "focus" + ), be( + e, + "border_contrast", + /*border_mode*/ + i[9] === "contrast" + ), be(e, "hide-container", !/*explicit_call*/ + i[12] && !/*container*/ + i[13]), be( + e, + "fullscreen", + /*fullscreen*/ + i[0] + ), be( + e, + "animating", + /*fullscreen*/ + i[0] && /*preexpansionBoundingRect*/ + i[24] !== null + ), be( + e, + "auto-margin", + /*scale*/ + i[17] === null + ), Z( + e, + "height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*height*/ + i[2] + ) + ) + ), Z( + e, + "min-height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*min_height*/ + i[3] + ) + ) + ), Z( + e, + "max-height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*max_height*/ + i[4] + ) + ) + ), Z( + e, + "--start-top", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].top}px` : "0px" + ), Z( + e, + "--start-left", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].left}px` : "0px" + ), Z( + e, + "--start-width", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].width}px` : "0px" + ), Z( + e, + "--start-height", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].height}px` : "0px" + ), Z( + e, + "width", + /*fullscreen*/ + i[0] ? void 0 : typeof /*width*/ + i[5] == "number" ? `calc(min(${/*width*/ + i[5]}px, 100%))` : ( + /*get_dimension*/ + i[26]( + /*width*/ + i[5] + ) + ) + ), Z( + e, + "border-style", + /*variant*/ + i[8] + ), Z( + e, + "overflow", + /*allow_overflow*/ + i[15] ? ( + /*overflow_behavior*/ + i[16] + ) : "hidden" + ), Z( + e, + "flex-grow", + /*scale*/ + i[17] + ), Z(e, "min-width", `calc(min(${/*min_width*/ + i[18]}px, 100%))`), Z(e, "border-width", "var(--block-border-width)"); + }, + m(d, f) { + Rn(d, e, f), o && o.m(e, null), $s(e, t), l && l.m(e, null), i[32](e), r = !0; + }, + p(d, f) { + var _; + o && o.p && (!r || f[0] & /*$$scope*/ + 1073741824) && zf( + o, + a, + d, + /*$$scope*/ + d[30], + r ? Pf( + a, + /*$$scope*/ + d[30], + f, + null + ) : Mf( + /*$$scope*/ + d[30] + ), + null + ), /*resizable*/ + d[19] ? l ? l.p(d, f) : (l = Da(d), l.c(), l.m(e, null)) : l && (l.d(1), l = null), Aa( + /*tag*/ + d[25] + )(e, u = If(h, [ + (!r || f[0] & /*test_id*/ + 2048) && { "data-testid": ( + /*test_id*/ + d[11] + ) }, + (!r || f[0] & /*elem_id*/ + 64) && { id: ( + /*elem_id*/ + d[6] + ) }, + (!r || f[0] & /*elem_classes*/ + 128 && n !== (n = "block " + /*elem_classes*/ + (((_ = d[7]) == null ? void 0 : _.join(" ")) || "") + " svelte-239wnu")) && { class: n }, + (!r || f[0] & /*rtl*/ + 1048576 && s !== (s = /*rtl*/ + d[20] ? "rtl" : "ltr")) && { dir: s } + ])), be( + e, + "hidden", + /*visible*/ + d[14] === !1 || /*visible*/ + d[14] === "hidden" + ), be( + e, + "padded", + /*padding*/ + d[10] + ), be( + e, + "flex", + /*flex*/ + d[1] + ), be( + e, + "border_focus", + /*border_mode*/ + d[9] === "focus" + ), be( + e, + "border_contrast", + /*border_mode*/ + d[9] === "contrast" + ), be(e, "hide-container", !/*explicit_call*/ + d[12] && !/*container*/ + d[13]), be( + e, + "fullscreen", + /*fullscreen*/ + d[0] + ), be( + e, + "animating", + /*fullscreen*/ + d[0] && /*preexpansionBoundingRect*/ + d[24] !== null + ), be( + e, + "auto-margin", + /*scale*/ + d[17] === null + ), f[0] & /*fullscreen, height*/ + 5 && Z( + e, + "height", + /*fullscreen*/ + d[0] ? void 0 : ( + /*get_dimension*/ + d[26]( + /*height*/ + d[2] + ) + ) + ), f[0] & /*fullscreen, min_height*/ + 9 && Z( + e, + "min-height", + /*fullscreen*/ + d[0] ? void 0 : ( + /*get_dimension*/ + d[26]( + /*min_height*/ + d[3] + ) + ) + ), f[0] & /*fullscreen, max_height*/ + 17 && Z( + e, + "max-height", + /*fullscreen*/ + d[0] ? void 0 : ( + /*get_dimension*/ + d[26]( + /*max_height*/ + d[4] + ) + ) + ), f[0] & /*preexpansionBoundingRect*/ + 16777216 && Z( + e, + "--start-top", + /*preexpansionBoundingRect*/ + d[24] ? `${/*preexpansionBoundingRect*/ + d[24].top}px` : "0px" + ), f[0] & /*preexpansionBoundingRect*/ + 16777216 && Z( + e, + "--start-left", + /*preexpansionBoundingRect*/ + d[24] ? `${/*preexpansionBoundingRect*/ + d[24].left}px` : "0px" + ), f[0] & /*preexpansionBoundingRect*/ + 16777216 && Z( + e, + "--start-width", + /*preexpansionBoundingRect*/ + d[24] ? `${/*preexpansionBoundingRect*/ + d[24].width}px` : "0px" + ), f[0] & /*preexpansionBoundingRect*/ + 16777216 && Z( + e, + "--start-height", + /*preexpansionBoundingRect*/ + d[24] ? `${/*preexpansionBoundingRect*/ + d[24].height}px` : "0px" + ), f[0] & /*fullscreen, width*/ + 33 && Z( + e, + "width", + /*fullscreen*/ + d[0] ? void 0 : typeof /*width*/ + d[5] == "number" ? `calc(min(${/*width*/ + d[5]}px, 100%))` : ( + /*get_dimension*/ + d[26]( + /*width*/ + d[5] + ) + ) + ), f[0] & /*variant*/ + 256 && Z( + e, + "border-style", + /*variant*/ + d[8] + ), f[0] & /*allow_overflow, overflow_behavior*/ + 98304 && Z( + e, + "overflow", + /*allow_overflow*/ + d[15] ? ( + /*overflow_behavior*/ + d[16] + ) : "hidden" + ), f[0] & /*scale*/ + 131072 && Z( + e, + "flex-grow", + /*scale*/ + d[17] + ), f[0] & /*min_width*/ + 262144 && Z(e, "min-width", `calc(min(${/*min_width*/ + d[18]}px, 100%))`); + }, + i(d) { + r || (Vl(o, d), r = !0); + }, + o(d) { + Wl(o, d), r = !1; + }, + d(d) { + d && gt(e), o && o.d(d), l && l.d(), i[32](null); + } + }; +} +function Ea(i) { + let e; + return { + c() { + e = Ul("div"), this.h(); + }, + l(t) { + e = Gl(t, "DIV", { class: !0 }), kn(e).forEach(gt), this.h(); + }, + h() { + ke(e, "class", "placeholder svelte-239wnu"), Z( + e, + "height", + /*placeholder_height*/ + i[22] + "px" + ), Z( + e, + "width", + /*placeholder_width*/ + i[23] + "px" + ); + }, + m(t, n) { + Rn(t, e, n); + }, + p(t, n) { + n[0] & /*placeholder_height*/ + 4194304 && Z( + e, + "height", + /*placeholder_height*/ + t[22] + "px" + ), n[0] & /*placeholder_width*/ + 8388608 && Z( + e, + "width", + /*placeholder_width*/ + t[23] + "px" + ); + }, + d(t) { + t && gt(e); + } + }; +} +function Gf(i) { + let e, t, n, s = ( + /*tag*/ + i[25] && Nf(i) + ), r = ( + /*fullscreen*/ + i[0] && Ea(i) + ); + return { + c() { + s && s.c(), e = Hl(), r && r.c(), t = ka(); + }, + l(a) { + s && s.l(a), e = ql(a), r && r.l(a), t = ka(); + }, + m(a, o) { + s && s.m(a, o), Rn(a, e, o), r && r.m(a, o), Rn(a, t, o), n = !0; + }, + p(a, o) { + /*tag*/ + a[25] && s.p(a, o), /*fullscreen*/ + a[0] ? r ? r.p(a, o) : (r = Ea(a), r.c(), r.m(t.parentNode, t)) : r && (r.d(1), r = null); + }, + i(a) { + n || (Vl(s, a), n = !0); + }, + o(a) { + Wl(s, a), n = !1; + }, + d(a) { + a && (gt(e), gt(t)), s && s.d(a), r && r.d(a); + } + }; +} +function qf(i, e, t) { + let { $$slots: n = {}, $$scope: s } = e, { height: r = void 0 } = e, { min_height: a = void 0 } = e, { max_height: o = void 0 } = e, { width: l = void 0 } = e, { elem_id: h = "" } = e, { elem_classes: u = [] } = e, { variant: c = "solid" } = e, { border_mode: d = "base" } = e, { padding: f = !0 } = e, { type: _ = "normal" } = e, { test_id: b = void 0 } = e, { explicit_call: m = !1 } = e, { container: x = !0 } = e, { visible: g = !0 } = e, { allow_overflow: p = !0 } = e, { overflow_behavior: y = "auto" } = e, { scale: C = null } = e, { min_width: w = 0 } = e, { flex: v = !1 } = e, { resizable: D = !1 } = e, { rtl: S = !1 } = e, { fullscreen: A = !1 } = e, E = A, I, B = _ === "fieldset" ? "fieldset" : "div", N = 0, Y = 0, F = null; + function T($) { + A && $.key === "Escape" && t(0, A = !1); + } + const U = ($) => { + if ($ !== void 0) { + if (typeof $ == "number") + return $ + "px"; + if (typeof $ == "string") + return $; + } + }, O = ($) => { + let ne = $.clientY; + const we = (ve) => { + const me = ve.clientY - ne; + ne = ve.clientY, t(21, I.style.height = `${I.offsetHeight + me}px`, I); + }, _e = () => { + window.removeEventListener("mousemove", we), window.removeEventListener("mouseup", _e); + }; + window.addEventListener("mousemove", we), window.addEventListener("mouseup", _e); + }; + function ce($) { + $f[$ ? "unshift" : "push"](() => { + I = $, t(21, I); + }); + } + return i.$$set = ($) => { + "height" in $ && t(2, r = $.height), "min_height" in $ && t(3, a = $.min_height), "max_height" in $ && t(4, o = $.max_height), "width" in $ && t(5, l = $.width), "elem_id" in $ && t(6, h = $.elem_id), "elem_classes" in $ && t(7, u = $.elem_classes), "variant" in $ && t(8, c = $.variant), "border_mode" in $ && t(9, d = $.border_mode), "padding" in $ && t(10, f = $.padding), "type" in $ && t(28, _ = $.type), "test_id" in $ && t(11, b = $.test_id), "explicit_call" in $ && t(12, m = $.explicit_call), "container" in $ && t(13, x = $.container), "visible" in $ && t(14, g = $.visible), "allow_overflow" in $ && t(15, p = $.allow_overflow), "overflow_behavior" in $ && t(16, y = $.overflow_behavior), "scale" in $ && t(17, C = $.scale), "min_width" in $ && t(18, w = $.min_width), "flex" in $ && t(1, v = $.flex), "resizable" in $ && t(19, D = $.resizable), "rtl" in $ && t(20, S = $.rtl), "fullscreen" in $ && t(0, A = $.fullscreen), "$$scope" in $ && t(30, s = $.$$scope); + }, i.$$.update = () => { + i.$$.dirty[0] & /*fullscreen, old_fullscreen, element*/ + 538968065 && A !== E && (t(29, E = A), A ? (t(24, F = I.getBoundingClientRect()), t(22, N = I.offsetHeight), t(23, Y = I.offsetWidth), window.addEventListener("keydown", T)) : (t(24, F = null), window.removeEventListener("keydown", T))), i.$$.dirty[0] & /*visible*/ + 16384 && (g || t(1, v = !1)); + }, [ + A, + v, + r, + a, + o, + l, + h, + u, + c, + d, + f, + b, + m, + x, + g, + p, + y, + C, + w, + D, + S, + I, + N, + Y, + F, + B, + U, + O, + _, + E, + s, + n, + ce + ]; +} +class Uf extends Ef { + constructor(e) { + super(), Rf( + this, + e, + qf, + Gf, + Of, + { + height: 2, + min_height: 3, + max_height: 4, + width: 5, + elem_id: 6, + elem_classes: 7, + variant: 8, + border_mode: 9, + padding: 10, + type: 28, + test_id: 11, + explicit_call: 12, + container: 13, + visible: 14, + allow_overflow: 15, + overflow_behavior: 16, + scale: 17, + min_width: 18, + flex: 1, + resizable: 19, + rtl: 20, + fullscreen: 0 + }, + null, + [-1, -1] + ); + } +} +function ir() { + return { + async: !1, + breaks: !1, + extensions: null, + gfm: !0, + hooks: null, + pedantic: !1, + renderer: null, + silent: !1, + tokenizer: null, + walkTokens: null + }; +} +let qt = ir(); +function Yl(i) { + qt = i; +} +const Xl = /[&<>"']/, Hf = new RegExp(Xl.source, "g"), jl = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, Vf = new RegExp(jl.source, "g"), Wf = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" +}, Fa = (i) => Wf[i]; +function ze(i, e) { + if (e) { + if (Xl.test(i)) + return i.replace(Hf, Fa); + } else if (jl.test(i)) + return i.replace(Vf, Fa); + return i; +} +const Yf = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; +function Xf(i) { + return i.replace(Yf, (e, t) => (t = t.toLowerCase(), t === "colon" ? ":" : t.charAt(0) === "#" ? t.charAt(1) === "x" ? String.fromCharCode(parseInt(t.substring(2), 16)) : String.fromCharCode(+t.substring(1)) : "")); +} +const jf = /(^|[^\[])\^/g; +function ee(i, e) { + let t = typeof i == "string" ? i : i.source; + e = e || ""; + const n = { + replace: (s, r) => { + let a = typeof r == "string" ? r : r.source; + return a = a.replace(jf, "$1"), t = t.replace(s, a), n; + }, + getRegex: () => new RegExp(t, e) + }; + return n; +} +function $a(i) { + try { + i = encodeURI(i).replace(/%25/g, "%"); + } catch { + return null; + } + return i; +} +const An = { exec: () => null }; +function Ta(i, e) { + const t = i.replace(/\|/g, (r, a, o) => { + let l = !1, h = a; + for (; --h >= 0 && o[h] === "\\"; ) + l = !l; + return l ? "|" : " |"; + }), n = t.split(/ \|/); + let s = 0; + if (n[0].trim() || n.shift(), n.length > 0 && !n[n.length - 1].trim() && n.pop(), e) + if (n.length > e) + n.splice(e); + else + for (; n.length < e; ) + n.push(""); + for (; s < n.length; s++) + n[s] = n[s].trim().replace(/\\\|/g, "|"); + return n; +} +function ti(i, e, t) { + const n = i.length; + if (n === 0) + return ""; + let s = 0; + for (; s < n && i.charAt(n - s - 1) === e; ) + s++; + return i.slice(0, n - s); +} +function Zf(i, e) { + if (i.indexOf(e[1]) === -1) + return -1; + let t = 0; + for (let n = 0; n < i.length; n++) + if (i[n] === "\\") + n++; + else if (i[n] === e[0]) + t++; + else if (i[n] === e[1] && (t--, t < 0)) + return n; + return -1; +} +function Ma(i, e, t, n) { + const s = e.href, r = e.title ? ze(e.title) : null, a = i[1].replace(/\\([\[\]])/g, "$1"); + if (i[0].charAt(0) !== "!") { + n.state.inLink = !0; + const o = { + type: "link", + raw: t, + href: s, + title: r, + text: a, + tokens: n.inlineTokens(a) + }; + return n.state.inLink = !1, o; + } + return { + type: "image", + raw: t, + href: s, + title: r, + text: ze(a) + }; +} +function Kf(i, e) { + const t = i.match(/^(\s+)(?:```)/); + if (t === null) + return e; + const n = t[1]; + return e.split(` +`).map((s) => { + const r = s.match(/^\s+/); + if (r === null) + return s; + const [a] = r; + return a.length >= n.length ? s.slice(n.length) : s; + }).join(` +`); +} +class xi { + // set by the lexer + constructor(e) { + ie(this, "options"); + ie(this, "rules"); + // set by the lexer + ie(this, "lexer"); + this.options = e || qt; + } + space(e) { + const t = this.rules.block.newline.exec(e); + if (t && t[0].length > 0) + return { + type: "space", + raw: t[0] + }; + } + code(e) { + const t = this.rules.block.code.exec(e); + if (t) { + const n = t[0].replace(/^ {1,4}/gm, ""); + return { + type: "code", + raw: t[0], + codeBlockStyle: "indented", + text: this.options.pedantic ? n : ti(n, ` +`) + }; + } + } + fences(e) { + const t = this.rules.block.fences.exec(e); + if (t) { + const n = t[0], s = Kf(n, t[3] || ""); + return { + type: "code", + raw: n, + lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], + text: s + }; + } + } + heading(e) { + const t = this.rules.block.heading.exec(e); + if (t) { + let n = t[2].trim(); + if (/#$/.test(n)) { + const s = ti(n, "#"); + (this.options.pedantic || !s || / $/.test(s)) && (n = s.trim()); + } + return { + type: "heading", + raw: t[0], + depth: t[1].length, + text: n, + tokens: this.lexer.inline(n) + }; + } + } + hr(e) { + const t = this.rules.block.hr.exec(e); + if (t) + return { + type: "hr", + raw: t[0] + }; + } + blockquote(e) { + const t = this.rules.block.blockquote.exec(e); + if (t) { + let n = t[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, ` + $1`); + n = ti(n.replace(/^ *>[ \t]?/gm, ""), ` +`); + const s = this.lexer.state.top; + this.lexer.state.top = !0; + const r = this.lexer.blockTokens(n); + return this.lexer.state.top = s, { + type: "blockquote", + raw: t[0], + tokens: r, + text: n + }; + } + } + list(e) { + let t = this.rules.block.list.exec(e); + if (t) { + let n = t[1].trim(); + const s = n.length > 1, r = { + type: "list", + raw: "", + ordered: s, + start: s ? +n.slice(0, -1) : "", + loose: !1, + items: [] + }; + n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]"); + const a = new RegExp(`^( {0,3}${n})((?:[ ][^\\n]*)?(?:\\n|$))`); + let o = "", l = "", h = !1; + for (; e; ) { + let u = !1; + if (!(t = a.exec(e)) || this.rules.block.hr.test(e)) + break; + o = t[0], e = e.substring(o.length); + let c = t[2].split(` +`, 1)[0].replace(/^\t+/, (x) => " ".repeat(3 * x.length)), d = e.split(` +`, 1)[0], f = 0; + this.options.pedantic ? (f = 2, l = c.trimStart()) : (f = t[2].search(/[^ ]/), f = f > 4 ? 1 : f, l = c.slice(f), f += t[1].length); + let _ = !1; + if (!c && /^ *$/.test(d) && (o += d + ` +`, e = e.substring(d.length + 1), u = !0), !u) { + const x = new RegExp(`^ {0,${Math.min(3, f - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), g = new RegExp(`^ {0,${Math.min(3, f - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), p = new RegExp(`^ {0,${Math.min(3, f - 1)}}(?:\`\`\`|~~~)`), y = new RegExp(`^ {0,${Math.min(3, f - 1)}}#`); + for (; e; ) { + const C = e.split(` +`, 1)[0]; + if (d = C, this.options.pedantic && (d = d.replace(/^ {1,4}(?=( {4})*[^ ])/g, " ")), p.test(d) || y.test(d) || x.test(d) || g.test(e)) + break; + if (d.search(/[^ ]/) >= f || !d.trim()) + l += ` +` + d.slice(f); + else { + if (_ || c.search(/[^ ]/) >= 4 || p.test(c) || y.test(c) || g.test(c)) + break; + l += ` +` + d; + } + !_ && !d.trim() && (_ = !0), o += C + ` +`, e = e.substring(C.length + 1), c = d.slice(f); + } + } + r.loose || (h ? r.loose = !0 : /\n *\n *$/.test(o) && (h = !0)); + let b = null, m; + this.options.gfm && (b = /^\[[ xX]\] /.exec(l), b && (m = b[0] !== "[ ] ", l = l.replace(/^\[[ xX]\] +/, ""))), r.items.push({ + type: "list_item", + raw: o, + task: !!b, + checked: m, + loose: !1, + text: l, + tokens: [] + }), r.raw += o; + } + r.items[r.items.length - 1].raw = o.trimEnd(), r.items[r.items.length - 1].text = l.trimEnd(), r.raw = r.raw.trimEnd(); + for (let u = 0; u < r.items.length; u++) + if (this.lexer.state.top = !1, r.items[u].tokens = this.lexer.blockTokens(r.items[u].text, []), !r.loose) { + const c = r.items[u].tokens.filter((f) => f.type === "space"), d = c.length > 0 && c.some((f) => /\n.*\n/.test(f.raw)); + r.loose = d; + } + if (r.loose) + for (let u = 0; u < r.items.length; u++) + r.items[u].loose = !0; + return r; + } + } + html(e) { + const t = this.rules.block.html.exec(e); + if (t) + return { + type: "html", + block: !0, + raw: t[0], + pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", + text: t[0] + }; + } + def(e) { + const t = this.rules.block.def.exec(e); + if (t) { + const n = t[1].toLowerCase().replace(/\s+/g, " "), s = t[2] ? t[2].replace(/^<(.*)>$/, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3]; + return { + type: "def", + tag: n, + raw: t[0], + href: s, + title: r + }; + } + } + table(e) { + const t = this.rules.block.table.exec(e); + if (!t || !/[:|]/.test(t[2])) + return; + const n = Ta(t[1]), s = t[2].replace(/^\||\| *$/g, "").split("|"), r = t[3] && t[3].trim() ? t[3].replace(/\n[ \t]*$/, "").split(` +`) : [], a = { + type: "table", + raw: t[0], + header: [], + align: [], + rows: [] + }; + if (n.length === s.length) { + for (const o of s) + /^ *-+: *$/.test(o) ? a.align.push("right") : /^ *:-+: *$/.test(o) ? a.align.push("center") : /^ *:-+ *$/.test(o) ? a.align.push("left") : a.align.push(null); + for (const o of n) + a.header.push({ + text: o, + tokens: this.lexer.inline(o) + }); + for (const o of r) + a.rows.push(Ta(o, a.header.length).map((l) => ({ + text: l, + tokens: this.lexer.inline(l) + }))); + return a; + } + } + lheading(e) { + const t = this.rules.block.lheading.exec(e); + if (t) + return { + type: "heading", + raw: t[0], + depth: t[2].charAt(0) === "=" ? 1 : 2, + text: t[1], + tokens: this.lexer.inline(t[1]) + }; + } + paragraph(e) { + const t = this.rules.block.paragraph.exec(e); + if (t) { + const n = t[1].charAt(t[1].length - 1) === ` +` ? t[1].slice(0, -1) : t[1]; + return { + type: "paragraph", + raw: t[0], + text: n, + tokens: this.lexer.inline(n) + }; + } + } + text(e) { + const t = this.rules.block.text.exec(e); + if (t) + return { + type: "text", + raw: t[0], + text: t[0], + tokens: this.lexer.inline(t[0]) + }; + } + escape(e) { + const t = this.rules.inline.escape.exec(e); + if (t) + return { + type: "escape", + raw: t[0], + text: ze(t[1]) + }; + } + tag(e) { + const t = this.rules.inline.tag.exec(e); + if (t) + return !this.lexer.state.inLink && /^/i.test(t[0]) && (this.lexer.state.inLink = !1), !this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(t[0]) ? this.lexer.state.inRawBlock = !0 : this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0]) && (this.lexer.state.inRawBlock = !1), { + type: "html", + raw: t[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: !1, + text: t[0] + }; + } + link(e) { + const t = this.rules.inline.link.exec(e); + if (t) { + const n = t[2].trim(); + if (!this.options.pedantic && /^$/.test(n)) + return; + const a = ti(n.slice(0, -1), "\\"); + if ((n.length - a.length) % 2 === 0) + return; + } else { + const a = Zf(t[2], "()"); + if (a > -1) { + const l = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + a; + t[2] = t[2].substring(0, a), t[0] = t[0].substring(0, l).trim(), t[3] = ""; + } + } + let s = t[2], r = ""; + if (this.options.pedantic) { + const a = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(s); + a && (s = a[1], r = a[3]); + } else + r = t[3] ? t[3].slice(1, -1) : ""; + return s = s.trim(), /^$/.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), Ma(t, { + href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), + title: r && r.replace(this.rules.inline.anyPunctuation, "$1") + }, t[0], this.lexer); + } + } + reflink(e, t) { + let n; + if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) { + const s = (n[2] || n[1]).replace(/\s+/g, " "), r = t[s.toLowerCase()]; + if (!r) { + const a = n[0].charAt(0); + return { + type: "text", + raw: a, + text: a + }; + } + return Ma(n, r, n[0], this.lexer); + } + } + emStrong(e, t, n = "") { + let s = this.rules.inline.emStrongLDelim.exec(e); + if (!s || s[3] && n.match(/[\p{L}\p{N}]/u)) + return; + if (!(s[1] || s[2] || "") || !n || this.rules.inline.punctuation.exec(n)) { + const a = [...s[0]].length - 1; + let o, l, h = a, u = 0; + const c = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + for (c.lastIndex = 0, t = t.slice(-1 * e.length + a); (s = c.exec(t)) != null; ) { + if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) + continue; + if (l = [...o].length, s[3] || s[4]) { + h += l; + continue; + } else if ((s[5] || s[6]) && a % 3 && !((a + l) % 3)) { + u += l; + continue; + } + if (h -= l, h > 0) + continue; + l = Math.min(l, l + h + u); + const d = [...s[0]][0].length, f = e.slice(0, a + s.index + d + l); + if (Math.min(a, l) % 2) { + const b = f.slice(1, -1); + return { + type: "em", + raw: f, + text: b, + tokens: this.lexer.inlineTokens(b) + }; + } + const _ = f.slice(2, -2); + return { + type: "strong", + raw: f, + text: _, + tokens: this.lexer.inlineTokens(_) + }; + } + } + } + codespan(e) { + const t = this.rules.inline.code.exec(e); + if (t) { + let n = t[2].replace(/\n/g, " "); + const s = /[^ ]/.test(n), r = /^ /.test(n) && / $/.test(n); + return s && r && (n = n.substring(1, n.length - 1)), n = ze(n, !0), { + type: "codespan", + raw: t[0], + text: n + }; + } + } + br(e) { + const t = this.rules.inline.br.exec(e); + if (t) + return { + type: "br", + raw: t[0] + }; + } + del(e) { + const t = this.rules.inline.del.exec(e); + if (t) + return { + type: "del", + raw: t[0], + text: t[2], + tokens: this.lexer.inlineTokens(t[2]) + }; + } + autolink(e) { + const t = this.rules.inline.autolink.exec(e); + if (t) { + let n, s; + return t[2] === "@" ? (n = ze(t[1]), s = "mailto:" + n) : (n = ze(t[1]), s = n), { + type: "link", + raw: t[0], + text: n, + href: s, + tokens: [ + { + type: "text", + raw: n, + text: n + } + ] + }; + } + } + url(e) { + var n; + let t; + if (t = this.rules.inline.url.exec(e)) { + let s, r; + if (t[2] === "@") + s = ze(t[0]), r = "mailto:" + s; + else { + let a; + do + a = t[0], t[0] = ((n = this.rules.inline._backpedal.exec(t[0])) == null ? void 0 : n[0]) ?? ""; + while (a !== t[0]); + s = ze(t[0]), t[1] === "www." ? r = "http://" + t[0] : r = t[0]; + } + return { + type: "link", + raw: t[0], + text: s, + href: r, + tokens: [ + { + type: "text", + raw: s, + text: s + } + ] + }; + } + } + inlineText(e) { + const t = this.rules.inline.text.exec(e); + if (t) { + let n; + return this.lexer.state.inRawBlock ? n = t[0] : n = ze(t[0]), { + type: "text", + raw: t[0], + text: n + }; + } + } +} +const Qf = /^(?: *(?:\n|$))+/, Jf = /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, ep = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/, Ln = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/, tp = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, Zl = /(?:[*+-]|\d{1,9}[.)])/, Kl = ee(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g, Zl).replace(/blockCode/g, / {4}/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).getRegex(), sr = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/, np = /^[^\n]+/, rr = /(?!\s*\])(?:\\.|[^\[\]\\])+/, ip = ee(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label", rr).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(), sp = ee(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, Zl).getRegex(), $i = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul", ar = /|$))/, rp = ee("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))", "i").replace("comment", ar).replace("tag", $i).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(), Ql = ee(sr).replace("hr", Ln).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", $i).getRegex(), ap = ee(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Ql).getRegex(), or = { + blockquote: ap, + code: Jf, + def: ip, + fences: ep, + heading: tp, + hr: Ln, + html: rp, + lheading: Kl, + list: sp, + newline: Qf, + paragraph: Ql, + table: An, + text: np +}, Pa = ee("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", Ln).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", $i).getRegex(), op = { + ...or, + table: Pa, + paragraph: ee(sr).replace("hr", Ln).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", Pa).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", $i).getRegex() +}, lp = { + ...or, + html: ee(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", ar).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: An, + // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: ee(sr).replace("hr", Ln).replace("heading", ` *#{1,6} *[^ +]`).replace("lheading", Kl).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() +}, Jl = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, hp = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, eh = /^( {2,}|\\)\n(?!\s*$)/, up = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g, fp = ee(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/, "u").replace(/punct/g, On).getRegex(), pp = ee("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])", "gu").replace(/punct/g, On).getRegex(), _p = ee("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])", "gu").replace(/punct/g, On).getRegex(), mp = ee(/\\([punct])/, "gu").replace(/punct/g, On).getRegex(), gp = ee(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(), yp = ee(ar).replace("(?:-->|$)", "-->").getRegex(), bp = ee("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment", yp).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(), wi = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/, xp = ee(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label", wi).replace("href", /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(), th = ee(/^!?\[(label)\]\[(ref)\]/).replace("label", wi).replace("ref", rr).getRegex(), nh = ee(/^!?\[(ref)\](?:\[\])?/).replace("ref", rr).getRegex(), wp = ee("reflink|nolink(?!\\()", "g").replace("reflink", th).replace("nolink", nh).getRegex(), lr = { + _backpedal: An, + // only used for GFM url + anyPunctuation: mp, + autolink: gp, + blockSkip: dp, + br: eh, + code: hp, + del: An, + emStrongLDelim: fp, + emStrongRDelimAst: pp, + emStrongRDelimUnd: _p, + escape: Jl, + link: xp, + nolink: nh, + punctuation: cp, + reflink: th, + reflinkSearch: wp, + tag: bp, + text: up, + url: An +}, vp = { + ...lr, + link: ee(/^!?\[(label)\]\((.*?)\)/).replace("label", wi).getRegex(), + reflink: ee(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", wi).getRegex() +}, Ts = { + ...lr, + escape: ee(Jl).replace("])", "~|])").getRegex(), + url: ee(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, "i").replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ l + " ".repeat(h.length)); + let n, s, r, a; + for (; e; ) + if (!(this.options.extensions && this.options.extensions.block && this.options.extensions.block.some((o) => (n = o.call({ lexer: this }, e, t)) ? (e = e.substring(n.raw.length), t.push(n), !0) : !1))) { + if (n = this.tokenizer.space(e)) { + e = e.substring(n.raw.length), n.raw.length === 1 && t.length > 0 ? t[t.length - 1].raw += ` +` : t.push(n); + continue; + } + if (n = this.tokenizer.code(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && (s.type === "paragraph" || s.type === "text") ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n); + continue; + } + if (n = this.tokenizer.fences(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.heading(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.hr(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.blockquote(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.list(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.html(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.def(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && (s.type === "paragraph" || s.type === "text") ? (s.raw += ` +` + n.raw, s.text += ` +` + n.raw, this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : this.tokens.links[n.tag] || (this.tokens.links[n.tag] = { + href: n.href, + title: n.title + }); + continue; + } + if (n = this.tokenizer.table(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.lheading(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (r = e, this.options.extensions && this.options.extensions.startBlock) { + let o = 1 / 0; + const l = e.slice(1); + let h; + this.options.extensions.startBlock.forEach((u) => { + h = u.call({ lexer: this }, l), typeof h == "number" && h >= 0 && (o = Math.min(o, h)); + }), o < 1 / 0 && o >= 0 && (r = e.substring(0, o + 1)); + } + if (this.state.top && (n = this.tokenizer.paragraph(r))) { + s = t[t.length - 1], a && s.type === "paragraph" ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue.pop(), this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n), a = r.length !== e.length, e = e.substring(n.raw.length); + continue; + } + if (n = this.tokenizer.text(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && s.type === "text" ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue.pop(), this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n); + continue; + } + if (e) { + const o = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(o); + break; + } else + throw new Error(o); + } + } + return this.state.top = !0, t; + } + inline(e, t = []) { + return this.inlineQueue.push({ src: e, tokens: t }), t; + } + /** + * Lexing/Compiling + */ + inlineTokens(e, t = []) { + let n, s, r, a = e, o, l, h; + if (this.tokens.links) { + const u = Object.keys(this.tokens.links); + if (u.length > 0) + for (; (o = this.tokenizer.rules.inline.reflinkSearch.exec(a)) != null; ) + u.includes(o[0].slice(o[0].lastIndexOf("[") + 1, -1)) && (a = a.slice(0, o.index) + "[" + "a".repeat(o[0].length - 2) + "]" + a.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex)); + } + for (; (o = this.tokenizer.rules.inline.blockSkip.exec(a)) != null; ) + a = a.slice(0, o.index) + "[" + "a".repeat(o[0].length - 2) + "]" + a.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + for (; (o = this.tokenizer.rules.inline.anyPunctuation.exec(a)) != null; ) + a = a.slice(0, o.index) + "++" + a.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + for (; e; ) + if (l || (h = ""), l = !1, !(this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some((u) => (n = u.call({ lexer: this }, e, t)) ? (e = e.substring(n.raw.length), t.push(n), !0) : !1))) { + if (n = this.tokenizer.escape(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.tag(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && n.type === "text" && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (n = this.tokenizer.link(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.reflink(e, this.tokens.links)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && n.type === "text" && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (n = this.tokenizer.emStrong(e, a, h)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.codespan(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.br(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.del(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.autolink(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (!this.state.inLink && (n = this.tokenizer.url(e))) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (r = e, this.options.extensions && this.options.extensions.startInline) { + let u = 1 / 0; + const c = e.slice(1); + let d; + this.options.extensions.startInline.forEach((f) => { + d = f.call({ lexer: this }, c), typeof d == "number" && d >= 0 && (u = Math.min(u, d)); + }), u < 1 / 0 && u >= 0 && (r = e.substring(0, u + 1)); + } + if (n = this.tokenizer.inlineText(r)) { + e = e.substring(n.raw.length), n.raw.slice(-1) !== "_" && (h = n.raw.slice(-1)), l = !0, s = t[t.length - 1], s && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (e) { + const u = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(u); + break; + } else + throw new Error(u); + } + } + return t; + } +} +class vi { + constructor(e) { + ie(this, "options"); + this.options = e || qt; + } + code(e, t, n) { + var r; + const s = (r = (t || "").match(/^\S*/)) == null ? void 0 : r[0]; + return e = e.replace(/\n$/, "") + ` +`, s ? '
' + (n ? e : ze(e, !0)) + `
+` : "
" + (n ? e : ze(e, !0)) + `
+`; + } + blockquote(e) { + return `
+${e}
+`; + } + html(e, t) { + return e; + } + heading(e, t, n) { + return `${e} +`; + } + hr() { + return `
+`; + } + list(e, t, n) { + const s = t ? "ol" : "ul", r = t && n !== 1 ? ' start="' + n + '"' : ""; + return "<" + s + r + `> +` + e + " +`; + } + listitem(e, t, n) { + return `
  • ${e}
  • +`; + } + checkbox(e) { + return "'; + } + paragraph(e) { + return `

    ${e}

    +`; + } + table(e, t) { + return t && (t = `${t}`), ` + +` + e + ` +` + t + `
    +`; + } + tablerow(e) { + return ` +${e} +`; + } + tablecell(e, t) { + const n = t.header ? "th" : "td"; + return (t.align ? `<${n} align="${t.align}">` : `<${n}>`) + e + ` +`; + } + /** + * span level renderer + */ + strong(e) { + return `${e}`; + } + em(e) { + return `${e}`; + } + codespan(e) { + return `${e}`; + } + br() { + return "
    "; + } + del(e) { + return `${e}`; + } + link(e, t, n) { + const s = $a(e); + if (s === null) + return n; + e = s; + let r = '
    ", r; + } + image(e, t, n) { + const s = $a(e); + if (s === null) + return n; + e = s; + let r = `${n} 0 && d.tokens[0].type === "paragraph" ? (d.tokens[0].text = m + " " + d.tokens[0].text, d.tokens[0].tokens && d.tokens[0].tokens.length > 0 && d.tokens[0].tokens[0].type === "text" && (d.tokens[0].tokens[0].text = m + " " + d.tokens[0].tokens[0].text)) : d.tokens.unshift({ + type: "text", + text: m + " " + }) : b += m + " "; + } + b += this.parse(d.tokens, h), u += this.renderer.listitem(b, _, !!f); + } + n += this.renderer.list(u, o, l); + continue; + } + case "html": { + const a = r; + n += this.renderer.html(a.text, a.block); + continue; + } + case "paragraph": { + const a = r; + n += this.renderer.paragraph(this.parseInline(a.tokens)); + continue; + } + case "text": { + let a = r, o = a.tokens ? this.parseInline(a.tokens) : a.text; + for (; s + 1 < e.length && e[s + 1].type === "text"; ) + a = e[++s], o += ` +` + (a.tokens ? this.parseInline(a.tokens) : a.text); + n += t ? this.renderer.paragraph(o) : o; + continue; + } + default: { + const a = 'Token with "' + r.type + '" type was not found.'; + if (this.options.silent) + return console.error(a), ""; + throw new Error(a); + } + } + } + return n; + } + /** + * Parse Inline Tokens + */ + parseInline(e, t) { + t = t || this.renderer; + let n = ""; + for (let s = 0; s < e.length; s++) { + const r = e[s]; + if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[r.type]) { + const a = this.options.extensions.renderers[r.type].call({ parser: this }, r); + if (a !== !1 || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) { + n += a || ""; + continue; + } + } + switch (r.type) { + case "escape": { + const a = r; + n += t.text(a.text); + break; + } + case "html": { + const a = r; + n += t.html(a.text); + break; + } + case "link": { + const a = r; + n += t.link(a.href, a.title, this.parseInline(a.tokens, t)); + break; + } + case "image": { + const a = r; + n += t.image(a.href, a.title, a.text); + break; + } + case "strong": { + const a = r; + n += t.strong(this.parseInline(a.tokens, t)); + break; + } + case "em": { + const a = r; + n += t.em(this.parseInline(a.tokens, t)); + break; + } + case "codespan": { + const a = r; + n += t.codespan(a.text); + break; + } + case "br": { + n += t.br(); + break; + } + case "del": { + const a = r; + n += t.del(this.parseInline(a.tokens, t)); + break; + } + case "text": { + const a = r; + n += t.text(a.text); + break; + } + default: { + const a = 'Token with "' + r.type + '" type was not found.'; + if (this.options.silent) + return console.error(a), ""; + throw new Error(a); + } + } + } + return n; + } +} +class Dn { + constructor(e) { + ie(this, "options"); + this.options = e || qt; + } + /** + * Process markdown before marked + */ + preprocess(e) { + return e; + } + /** + * Process HTML after marked is finished + */ + postprocess(e) { + return e; + } + /** + * Process all tokens before walk tokens + */ + processAllTokens(e) { + return e; + } +} +ie(Dn, "passThroughHooks", /* @__PURE__ */ new Set([ + "preprocess", + "postprocess", + "processAllTokens" +])); +var Gt, Ms, ih; +class Sp { + constructor(...e) { + mr(this, Gt); + ie(this, "defaults", ir()); + ie(this, "options", this.setOptions); + ie(this, "parse", Nn(this, Gt, Ms).call(this, yt.lex, bt.parse)); + ie(this, "parseInline", Nn(this, Gt, Ms).call(this, yt.lexInline, bt.parseInline)); + ie(this, "Parser", bt); + ie(this, "Renderer", vi); + ie(this, "TextRenderer", hr); + ie(this, "Lexer", yt); + ie(this, "Tokenizer", xi); + ie(this, "Hooks", Dn); + this.use(...e); + } + /** + * Run callback for every token + */ + walkTokens(e, t) { + var s, r; + let n = []; + for (const a of e) + switch (n = n.concat(t.call(this, a)), a.type) { + case "table": { + const o = a; + for (const l of o.header) + n = n.concat(this.walkTokens(l.tokens, t)); + for (const l of o.rows) + for (const h of l) + n = n.concat(this.walkTokens(h.tokens, t)); + break; + } + case "list": { + const o = a; + n = n.concat(this.walkTokens(o.items, t)); + break; + } + default: { + const o = a; + (r = (s = this.defaults.extensions) == null ? void 0 : s.childTokens) != null && r[o.type] ? this.defaults.extensions.childTokens[o.type].forEach((l) => { + const h = o[l].flat(1 / 0); + n = n.concat(this.walkTokens(h, t)); + }) : o.tokens && (n = n.concat(this.walkTokens(o.tokens, t))); + } + } + return n; + } + use(...e) { + const t = this.defaults.extensions || { renderers: {}, childTokens: {} }; + return e.forEach((n) => { + const s = { ...n }; + if (s.async = this.defaults.async || s.async || !1, n.extensions && (n.extensions.forEach((r) => { + if (!r.name) + throw new Error("extension name required"); + if ("renderer" in r) { + const a = t.renderers[r.name]; + a ? t.renderers[r.name] = function(...o) { + let l = r.renderer.apply(this, o); + return l === !1 && (l = a.apply(this, o)), l; + } : t.renderers[r.name] = r.renderer; + } + if ("tokenizer" in r) { + if (!r.level || r.level !== "block" && r.level !== "inline") + throw new Error("extension level must be 'block' or 'inline'"); + const a = t[r.level]; + a ? a.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start])); + } + "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens); + }), s.extensions = t), n.renderer) { + const r = this.defaults.renderer || new vi(this.defaults); + for (const a in n.renderer) { + if (!(a in r)) + throw new Error(`renderer '${a}' does not exist`); + if (a === "options") + continue; + const o = a, l = n.renderer[o], h = r[o]; + r[o] = (...u) => { + let c = l.apply(r, u); + return c === !1 && (c = h.apply(r, u)), c || ""; + }; + } + s.renderer = r; + } + if (n.tokenizer) { + const r = this.defaults.tokenizer || new xi(this.defaults); + for (const a in n.tokenizer) { + if (!(a in r)) + throw new Error(`tokenizer '${a}' does not exist`); + if (["options", "rules", "lexer"].includes(a)) + continue; + const o = a, l = n.tokenizer[o], h = r[o]; + r[o] = (...u) => { + let c = l.apply(r, u); + return c === !1 && (c = h.apply(r, u)), c; + }; + } + s.tokenizer = r; + } + if (n.hooks) { + const r = this.defaults.hooks || new Dn(); + for (const a in n.hooks) { + if (!(a in r)) + throw new Error(`hook '${a}' does not exist`); + if (a === "options") + continue; + const o = a, l = n.hooks[o], h = r[o]; + Dn.passThroughHooks.has(a) ? r[o] = (u) => { + if (this.defaults.async) + return Promise.resolve(l.call(r, u)).then((d) => h.call(r, d)); + const c = l.call(r, u); + return h.call(r, c); + } : r[o] = (...u) => { + let c = l.apply(r, u); + return c === !1 && (c = h.apply(r, u)), c; + }; + } + s.hooks = r; + } + if (n.walkTokens) { + const r = this.defaults.walkTokens, a = n.walkTokens; + s.walkTokens = function(o) { + let l = []; + return l.push(a.call(this, o)), r && (l = l.concat(r.call(this, o))), l; + }; + } + this.defaults = { ...this.defaults, ...s }; + }), this; + } + setOptions(e) { + return this.defaults = { ...this.defaults, ...e }, this; + } + lexer(e, t) { + return yt.lex(e, t ?? this.defaults); + } + parser(e, t) { + return bt.parse(e, t ?? this.defaults); + } +} +Gt = new WeakSet(), Ms = function(e, t) { + return (n, s) => { + const r = { ...s }, a = { ...this.defaults, ...r }; + this.defaults.async === !0 && r.async === !1 && (a.silent || console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."), a.async = !0); + const o = Nn(this, Gt, ih).call(this, !!a.silent, !!a.async); + if (typeof n > "u" || n === null) + return o(new Error("marked(): input parameter is undefined or null")); + if (typeof n != "string") + return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected")); + if (a.hooks && (a.hooks.options = a), a.async) + return Promise.resolve(a.hooks ? a.hooks.preprocess(n) : n).then((l) => e(l, a)).then((l) => a.hooks ? a.hooks.processAllTokens(l) : l).then((l) => a.walkTokens ? Promise.all(this.walkTokens(l, a.walkTokens)).then(() => l) : l).then((l) => t(l, a)).then((l) => a.hooks ? a.hooks.postprocess(l) : l).catch(o); + try { + a.hooks && (n = a.hooks.preprocess(n)); + let l = e(n, a); + a.hooks && (l = a.hooks.processAllTokens(l)), a.walkTokens && this.walkTokens(l, a.walkTokens); + let h = t(l, a); + return a.hooks && (h = a.hooks.postprocess(h)), h; + } catch (l) { + return o(l); + } + }; +}, ih = function(e, t) { + return (n) => { + if (n.message += ` +Please report this to https://github.com/markedjs/marked.`, e) { + const s = "

    An error occurred:

    " + ze(n.message + "", !0) + "
    "; + return t ? Promise.resolve(s) : s; + } + if (t) + return Promise.reject(n); + throw n; + }; +}; +const Nt = new Sp(); +function J(i, e) { + return Nt.parse(i, e); +} +J.options = J.setOptions = function(i) { + return Nt.setOptions(i), J.defaults = Nt.defaults, Yl(J.defaults), J; +}; +J.getDefaults = ir; +J.defaults = qt; +J.use = function(...i) { + return Nt.use(...i), J.defaults = Nt.defaults, Yl(J.defaults), J; +}; +J.walkTokens = function(i, e) { + return Nt.walkTokens(i, e); +}; +J.parseInline = Nt.parseInline; +J.Parser = bt; +J.parser = bt.parse; +J.Renderer = vi; +J.TextRenderer = hr; +J.Lexer = yt; +J.lexer = yt.lex; +J.Tokenizer = xi; +J.Hooks = Dn; +J.parse = J; +J.options; +J.setOptions; +J.use; +J.walkTokens; +J.parseInline; +bt.parse; +yt.lex; +const kp = /[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g, Ap = Object.hasOwnProperty; +class sh { + /** + * Create a new slug class. + */ + constructor() { + this.occurrences, this.reset(); + } + /** + * Generate a unique slug. + * + * Tracks previously generated slugs: repeated calls with the same value + * will result in different slugs. + * Use the `slug` function to get same slugs. + * + * @param {string} value + * String of text to slugify + * @param {boolean} [maintainCase=false] + * Keep the current case, otherwise make all lowercase + * @return {string} + * A unique slug string + */ + slug(e, t) { + const n = this; + let s = Dp(e, t === !0); + const r = s; + for (; Ap.call(n.occurrences, s); ) + n.occurrences[r]++, s = r + "-" + n.occurrences[r]; + return n.occurrences[s] = 0, s; + } + /** + * Reset - Forget all previous slugs + * + * @return void + */ + reset() { + this.occurrences = /* @__PURE__ */ Object.create(null); + } +} +function Dp(i, e) { + return typeof i != "string" ? "" : (e || (i = i.toLowerCase()), i.replace(kp, "").replace(/ /g, "-")); +} +new sh(); +var Ep = { exports: {} }; +(function(i) { + var e = typeof window < "u" ? window : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? self : {}; + /** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */ + var t = function(n) { + var s = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i, r = 0, a = {}, o = { + /** + * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the + * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load + * additional languages or plugins yourself. + * + * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. + * + * You obviously have to change this value before the automatic highlighting started. To do this, you can add an + * empty Prism object into the global scope before loading the Prism script like this: + * + * ```js + * window.Prism = window.Prism || {}; + * Prism.manual = true; + * // add a new