/*
MIT License

Copyright (c) 2012 - 2021 @jonobr1 / http://jono.fyi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var Two = (() => {
    var __defProp = Object.defineProperty;
    var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
    var __getOwnPropNames = Object.getOwnPropertyNames;
    var __hasOwnProp = Object.prototype.hasOwnProperty;
    var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
        enumerable: true,
        configurable: true,
        writable: true,
        value
    }) : obj[key] = value;
    var __export = (target, all) => {
        for (var name in all)
            __defProp(target, name, {get: all[name], enumerable: true});
    };
    var __copyProps = (to, from, except, desc) => {
        if (from && typeof from === "object" || typeof from === "function") {
            for (let key of __getOwnPropNames(from))
                if (!__hasOwnProp.call(to, key) && key !== except)
                    __defProp(to, key, {
                        get: () => from[key],
                        enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
                    });
        }
        return to;
    };
    var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", {value: true}), mod2);
    var __publicField = (obj, key, value) => {
        __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
        return value;
    };

    // src/two.js
    var two_exports = {};
    __export(two_exports, {
        default: () => Two
    });

    // src/utils/path-commands.js
    var Commands = {
        move: "M",
        line: "L",
        curve: "C",
        arc: "A",
        close: "Z"
    };

    // src/utils/math.js
    var math_exports = {};
    __export(math_exports, {
        HALF_PI: () => HALF_PI,
        NumArray: () => NumArray,
        TWO_PI: () => TWO_PI,
        decomposeMatrix: () => decomposeMatrix,
        getComputedMatrix: () => getComputedMatrix,
        getPoT: () => getPoT,
        lerp: () => lerp,
        mod: () => mod,
        setMatrix: () => setMatrix,
        toFixed: () => toFixed
    });

    // src/utils/root.js
    var root;
    if (typeof window !== "undefined") {
        root = window;
    } else if (typeof global !== "undefined") {
        root = global;
    } else if (typeof self !== "undefined") {
        root = self;
    }

    // src/utils/math.js
    var Matrix;
    var TWO_PI = Math.PI * 2;
    var HALF_PI = Math.PI * 0.5;

    function decomposeMatrix(matrix, b, c, d, e, f) {
        let a;
        if (arguments.length <= 1) {
            a = matrix.a;
            b = matrix.b;
            c = matrix.c;
            d = matrix.d;
            e = matrix.e;
            f = matrix.f;
        } else {
            a = matrix;
        }
        return {
            translateX: e,
            translateY: f,
            scaleX: Math.sqrt(a * a + b * b),
            scaleY: Math.sqrt(c * c + d * d),
            rotation: 180 * Math.atan2(b, a) / Math.PI
        };
    }

    function setMatrix(matrix) {
        Matrix = matrix;
    }

    function getComputedMatrix(object, matrix) {
        matrix = matrix && matrix.identity() || new Matrix();
        let parent = object;
        const matrices = [];
        while (parent && parent._matrix) {
            matrices.push(parent._matrix);
            parent = parent.parent;
        }
        matrices.reverse();
        for (let i = 0; i < matrices.length; i++) {
            const m = matrices[i];
            const e = m.elements;
            matrix.multiply(
                e[0],
                e[1],
                e[2],
                e[3],
                e[4],
                e[5],
                e[6],
                e[7],
                e[8],
                e[9]
            );
        }
        return matrix;
    }

    function lerp(a, b, t) {
        return t * (b - a) + a;
    }

    var pots = [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096];

    function getPoT(value) {
        let i = 0;
        while (pots[i] && pots[i] < value) {
            i++;
        }
        return pots[i];
    }

    function mod(v, l) {
        while (v < 0) {
            v += l;
        }
        return v % l;
    }

    var NumArray = root.Float32Array || Array;
    var floor = Math.floor;

    function toFixed(v) {
        return floor(v * 1e6) / 1e6;
    }

    // src/utils/curves.js
    var curves_exports = {};
    __export(curves_exports, {
        Curve: () => Curve,
        getAnchorsFromArcData: () => getAnchorsFromArcData,
        getComponentOnCubicBezier: () => getComponentOnCubicBezier,
        getControlPoints: () => getControlPoints,
        getCurveBoundingBox: () => getCurveBoundingBox,
        getCurveFromPoints: () => getCurveFromPoints,
        getCurveLength: () => getCurveLength,
        getReflection: () => getReflection,
        integrate: () => integrate,
        subdivide: () => subdivide
    });

    // src/events.js
    var Events = class {
        _events = {};
        _bound = false;

        constructor() {
        }

        addEventListener(name, handler) {
            const list = this._events[name] || (this._events[name] = []);
            list.push(handler);
            this._bound = true;
            return this;
        }

        on() {
            return this.addEventListener.apply(this, arguments);
        }

        bind() {
            return this.addEventListener.apply(this, arguments);
        }

        removeEventListener(name, handler) {
            if (!this._events) {
                return this;
            }
            if (!name && !handler) {
                this._events = {};
                this._bound = false;
                return this;
            }
            const names = name ? [name] : Object.keys(this._events);
            for (let i = 0, l = names.length; i < l; i++) {
                name = names[i];
                let list = this._events[name];
                if (list) {
                    let events = [];
                    if (handler) {
                        for (let j = 0, k = list.length; j < k; j++) {
                            let e = list[j];
                            e = e.handler ? e.handler : e;
                            if (handler !== e) {
                                events.push(e);
                            }
                        }
                    }
                    this._events[name] = events;
                }
            }
            return this;
        }

        off() {
            return this.removeEventListener.apply(this, arguments);
        }

        unbind() {
            return this.removeEventListener.apply(this, arguments);
        }

        dispatchEvent(name) {
            if (!this._events) {
                return this;
            }
            const args = Array.prototype.slice.call(arguments, 1);
            const events = this._events[name];
            if (events) {
                for (let i = 0; i < events.length; i++) {
                    events[i].call(this, ...args);
                }
            }
            return this;
        }

        trigger() {
            return this.dispatchEvent.apply(this, arguments);
        }

        listen(obj, name, handler) {
            const scope = this;
            if (obj) {
                e.obj = obj;
                e.name = name;
                e.handler = handler;
                obj.on(name, e);
            }

            function e() {
                handler.apply(scope, arguments);
            }

            return scope;
        }

        ignore(obj, name, handler) {
            obj.off(name, handler);
            return this;
        }
    };
    __publicField(Events, "Types", {
        play: "play",
        pause: "pause",
        update: "update",
        render: "render",
        resize: "resize",
        change: "change",
        remove: "remove",
        insert: "insert",
        order: "order",
        load: "load"
    });
    __publicField(Events, "Methods", [
        "addEventListener",
        "on",
        "removeEventListener",
        "off",
        "unbind",
        "dispatchEvent",
        "trigger",
        "listen",
        "ignore"
    ]);

    // src/vector.js
    var proto = {
        x: {
            enumerable: true,
            get: function () {
                return this._x;
            },
            set: function (v) {
                if (this._x !== v) {
                    this._x = v;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        y: {
            enumerable: true,
            get: function () {
                return this._y;
            },
            set: function (v) {
                if (this._y !== v) {
                    this._y = v;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        }
    };
    var _Vector = class extends Events {
        _x = 0;
        _y = 0;

        constructor(x = 0, y = 0) {
            super();
            for (let prop in proto) {
                Object.defineProperty(this, prop, proto[prop]);
            }
            this.x = x;
            this.y = y;
        }

        static add(v1, v2) {
            return new _Vector(v1.x + v2.x, v1.y + v2.y);
        }

        static sub(v1, v2) {
            return new _Vector(v1.x - v2.x, v1.y - v2.y);
        }

        static subtract(v1, v2) {
            return _Vector.sub(v1, v2);
        }

        static ratioBetween(v1, v2) {
            return (v1.x * v2.x + v1.y * v2.y) / (v1.length() * v2.length());
        }

        static angleBetween(v1, v2) {
            if (arguments.length >= 4) {
                const dx2 = arguments[0] - arguments[2];
                const dy2 = arguments[1] - arguments[3];
                return Math.atan2(dy2, dx2);
            }
            const dx = v1.x - v2.x;
            const dy = v1.y - v2.y;
            return Math.atan2(dy, dx);
        }

        static distanceBetween(v1, v2) {
            return Math.sqrt(_Vector.distanceBetweenSquared(v1, v2));
        }

        static distanceBetweenSquared(v1, v2) {
            const dx = v1.x - v2.x;
            const dy = v1.y - v2.y;
            return dx * dx + dy * dy;
        }

        set(x, y) {
            this.x = x;
            this.y = y;
            return this;
        }

        copy(v) {
            this.x = v.x;
            this.y = v.y;
            return this;
        }

        clear() {
            this.x = 0;
            this.y = 0;
            return this;
        }

        clone() {
            return new _Vector(this.x, this.y);
        }

        add(x, y) {
            if (arguments.length <= 0) {
                return this;
            } else if (arguments.length <= 1) {
                if (typeof x === "number") {
                    this.x += x;
                    this.y += x;
                } else if (x && typeof x.x === "number" && typeof x.y === "number") {
                    this.x += x.x;
                    this.y += x.y;
                }
            } else {
                this.x += x;
                this.y += y;
            }
            return this;
        }

        addSelf(v) {
            return this.add.apply(this, arguments);
        }

        sub(x, y) {
            if (arguments.length <= 0) {
                return this;
            } else if (arguments.length <= 1) {
                if (typeof x === "number") {
                    this.x -= x;
                    this.y -= x;
                } else if (x && typeof x.x === "number" && typeof x.y === "number") {
                    this.x -= x.x;
                    this.y -= x.y;
                }
            } else {
                this.x -= x;
                this.y -= y;
            }
            return this;
        }

        subtract() {
            return this.sub.apply(this, arguments);
        }

        subSelf(v) {
            return this.sub.apply(this, arguments);
        }

        subtractSelf(v) {
            return this.sub.apply(this, arguments);
        }

        multiply(x, y) {
            if (arguments.length <= 0) {
                return this;
            } else if (arguments.length <= 1) {
                if (typeof x === "number") {
                    this.x *= x;
                    this.y *= x;
                } else if (x && typeof x.x === "number" && typeof x.y === "number") {
                    this.x *= x.x;
                    this.y *= x.y;
                }
            } else {
                this.x *= x;
                this.y *= y;
            }
            return this;
        }

        multiplySelf(v) {
            return this.multiply.apply(this, arguments);
        }

        multiplyScalar(s) {
            return this.multiply(s);
        }

        divide(x, y) {
            if (arguments.length <= 0) {
                return this;
            } else if (arguments.length <= 1) {
                if (typeof x === "number") {
                    this.x /= x;
                    this.y /= x;
                } else if (x && typeof x.x === "number" && typeof x.y === "number") {
                    this.x /= x.x;
                    this.y /= x.y;
                }
            } else {
                this.x /= x;
                this.y /= y;
            }
            if (isNaN(this.x)) {
                this.x = 0;
            }
            if (isNaN(this.y)) {
                this.y = 0;
            }
            return this;
        }

        divideSelf(v) {
            return this.divide.apply(this, arguments);
        }

        divideScalar(s) {
            return this.divide(s);
        }

        negate() {
            return this.multiply(-1);
        }

        dot(v) {
            return this.x * v.x + this.y * v.y;
        }

        length() {
            return Math.sqrt(this.lengthSquared());
        }

        lengthSquared() {
            return this.x * this.x + this.y * this.y;
        }

        normalize() {
            return this.divideScalar(this.length());
        }

        distanceTo(v) {
            return Math.sqrt(this.distanceToSquared(v));
        }

        distanceToSquared(v) {
            const dx = this.x - v.x;
            const dy = this.y - v.y;
            return dx * dx + dy * dy;
        }

        setLength(l) {
            return this.normalize().multiplyScalar(l);
        }

        equals(v, eps) {
            eps = typeof eps === "undefined" ? 1e-4 : eps;
            return this.distanceTo(v) < eps;
        }

        lerp(v, t) {
            const x = (v.x - this.x) * t + this.x;
            const y = (v.y - this.y) * t + this.y;
            return this.set(x, y);
        }

        isZero(eps) {
            eps = typeof eps === "undefined" ? 1e-4 : eps;
            return this.length() < eps;
        }

        toString() {
            return this.x + ", " + this.y;
        }

        toObject() {
            return {x: this.x, y: this.y};
        }

        rotate(radians) {
            const x = this.x;
            const y = this.y;
            const cos7 = Math.cos(radians);
            const sin7 = Math.sin(radians);
            this.x = x * cos7 - y * sin7;
            this.y = x * sin7 + y * cos7;
            return this;
        }
    };
    var Vector = _Vector;
    __publicField(Vector, "zero", new _Vector());
    __publicField(Vector, "left", new _Vector(-1, 0));
    __publicField(Vector, "right", new _Vector(1, 0));
    __publicField(Vector, "up", new _Vector(0, -1));
    __publicField(Vector, "down", new _Vector(0, 1));

    // src/anchor.js
    var Anchor = class extends Vector {
        controls = {
            left: new Vector(),
            right: new Vector()
        };
        _command = Commands.move;
        _relative = true;
        _rx = 0;
        _ry = 0;
        _xAxisRotation = 0;
        _largeArcFlag = 0;
        _sweepFlag = 1;

        constructor(x = 0, y = 0, ax = 0, ay = 0, bx = 0, by = 0, command = Commands.move) {
            super(x, y);
            for (let prop in proto2) {
                Object.defineProperty(this, prop, proto2[prop]);
            }
            this.command = command;
            this.relative = true;
            const broadcast = Anchor.makeBroadcast(this);
            this.controls.left.set(ax, ay).addEventListener(Events.Types.change, broadcast);
            this.controls.right.set(bx, by).addEventListener(Events.Types.change, broadcast);
        }

        static makeBroadcast(scope) {
            return broadcast;

            function broadcast() {
                if (scope._bound) {
                    scope.dispatchEvent(Events.Types.change);
                }
            }
        }

        copy(v) {
            this.x = v.x;
            this.y = v.y;
            if (typeof v.command === "string") {
                this.command = v.command;
            }
            if (v.controls) {
                if (v.controls.left) {
                    this.controls.left.copy(v.controls.left);
                }
                if (v.controls.right) {
                    this.controls.right.copy(v.controls.right);
                }
            }
            if (typeof v.relative === "boolean") {
                this.relative = v.relative;
            }
            if (typeof v.rx === "number") {
                this.rx = v.rx;
            }
            if (typeof v.ry === "number") {
                this.ry = v.ry;
            }
            if (typeof v.xAxisRotation === "number") {
                this.xAxisRotation = v.xAxisRotation;
            }
            if (typeof v.largeArcFlag === "number") {
                this.largeArcFlag = v.largeArcFlag;
            }
            if (typeof v.sweepFlag === "number") {
                this.sweepFlag = v.sweepFlag;
            }
            return this;
        }

        clone() {
            return new Anchor().copy(this);
        }

        toObject() {
            return {
                x: this.x,
                y: this.y,
                command: this.command,
                relative: this.relative,
                controls: {
                    left: this.controls.left.toObject(),
                    right: this.controls.right.toObject()
                },
                rx: this.rx,
                ry: this.ry,
                xAxisRotation: this.xAxisRotation,
                largeArcFlag: this.largeArcFlag,
                sweepFlag: this.sweepFlag
            };
        }

        toString() {
            return JSON.stringify(this.toObject());
        }
    };
    var proto2 = {
        command: {
            enumerable: true,
            get: function () {
                return this._command;
            },
            set: function (command) {
                if (this._command !== command) {
                    this._command = command;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        relative: {
            enumerable: true,
            get: function () {
                return this._relative;
            },
            set: function (relative) {
                if (this._relative !== !!relative) {
                    this._relative = !!relative;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        rx: {
            enumerable: true,
            get: function () {
                return this._rx;
            },
            set: function (rx) {
                if (this._rx !== rx) {
                    this._rx = rx;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        ry: {
            enumerable: true,
            get: function () {
                return this._ry;
            },
            set: function (ry) {
                if (this._ry !== ry) {
                    this._ry = ry;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        xAxisRotation: {
            enumerable: true,
            get: function () {
                return this._xAxisRotation;
            },
            set: function (xAxisRotation) {
                if (this._xAxisRotation !== xAxisRotation) {
                    this._xAxisRotation = xAxisRotation;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        largeArcFlag: {
            enumerable: true,
            get: function () {
                return this._largeArcFlag;
            },
            set: function (largeArcFlag) {
                if (this._largeArcFlag !== largeArcFlag) {
                    this._largeArcFlag = largeArcFlag;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        },
        sweepFlag: {
            get: function () {
                return this._sweepFlag;
            },
            set: function (sweepFlag) {
                if (this._sweepFlag !== sweepFlag) {
                    this._sweepFlag = sweepFlag;
                    if (this._bound) {
                        this.dispatchEvent(Events.Types.change);
                    }
                }
            }
        }
    };

    // src/constants.js
    var count = 0;
    var Constants = {
        nextFrameID: null,
        Types: {
            webgl: "WebGLRenderer",
            svg: "SVGRenderer",
            canvas: "CanvasRenderer"
        },
        Version: "v0.8.12",
        PublishDate: "2023-10-16T17:55:26.551Z",
        Identifier: "two-",
        Resolution: 12,
        AutoCalculateImportedMatrices: true,
        Instances: [],
        uniqueId: function () {
            return count++;
        }
    };

    // src/utils/curves.js
    var Curve = {
        CollinearityEpsilon: Math.pow(10, -30),
        RecursionLimit: 16,
        CuspLimit: 0,
        Tolerance: {
            distance: 0.25,
            angle: 0,
            epsilon: Number.EPSILON
        },
        abscissas: [
            [0.5773502691896257],
            [0, 0.7745966692414834],
            [0.33998104358485626, 0.8611363115940526],
            [0, 0.5384693101056831, 0.906179845938664],
            [0.2386191860831969, 0.6612093864662645, 0.932469514203152],
            [0, 0.4058451513773972, 0.7415311855993945, 0.9491079123427585],
            [0.1834346424956498, 0.525532409916329, 0.7966664774136267, 0.9602898564975363],
            [0, 0.3242534234038089, 0.6133714327005904, 0.8360311073266358, 0.9681602395076261],
            [0.14887433898163122, 0.4333953941292472, 0.6794095682990244, 0.8650633666889845, 0.9739065285171717],
            [0, 0.26954315595234496, 0.5190961292068118, 0.7301520055740494, 0.8870625997680953, 0.978228658146057],
            [0.1252334085114689, 0.3678314989981802, 0.5873179542866175, 0.7699026741943047, 0.9041172563704749, 0.9815606342467192],
            [0, 0.2304583159551348, 0.44849275103644687, 0.6423493394403402, 0.8015780907333099, 0.9175983992229779, 0.9841830547185881],
            [0.10805494870734367, 0.31911236892788974, 0.5152486363581541, 0.6872929048116855, 0.827201315069765, 0.9284348836635735, 0.9862838086968123],
            [0, 0.20119409399743451, 0.3941513470775634, 0.5709721726085388, 0.7244177313601701, 0.8482065834104272, 0.937273392400706, 0.9879925180204854],
            [0.09501250983763744, 0.2816035507792589, 0.45801677765722737, 0.6178762444026438, 0.755404408355003, 0.8656312023878318, 0.9445750230732326, 0.9894009349916499]
        ],
        weights: [
            [1],
            [0.8888888888888888, 0.5555555555555556],
            [0.6521451548625461, 0.34785484513745385],
            [0.5688888888888889, 0.47862867049936647, 0.23692688505618908],
            [0.46791393457269104, 0.3607615730481386, 0.17132449237917036],
            [0.4179591836734694, 0.3818300505051189, 0.27970539148927664, 0.1294849661688697],
            [0.362683783378362, 0.31370664587788727, 0.22238103445337448, 0.10122853629037626],
            [0.3302393550012598, 0.31234707704000286, 0.26061069640293544, 0.1806481606948574, 0.08127438836157441],
            [0.29552422471475287, 0.26926671930999635, 0.21908636251598204, 0.1494513491505806, 0.06667134430868814],
            [0.2729250867779006, 0.26280454451024665, 0.23319376459199048, 0.18629021092773426, 0.1255803694649046, 0.05566856711617366],
            [0.24914704581340277, 0.2334925365383548, 0.20316742672306592, 0.16007832854334622, 0.10693932599531843, 0.04717533638651183],
            [0.2325515532308739, 0.22628318026289723, 0.2078160475368885, 0.17814598076194574, 0.13887351021978725, 0.09212149983772845, 0.04048400476531588],
            [0.2152638534631578, 0.2051984637212956, 0.18553839747793782, 0.15720316715819355, 0.12151857068790319, 0.08015808715976021, 0.03511946033175186],
            [0.2025782419255613, 0.19843148532711158, 0.1861610000155622, 0.16626920581699392, 0.13957067792615432, 0.10715922046717194, 0.07036604748810812, 0.03075324199611727],
            [0.1894506104550685, 0.18260341504492358, 0.16915651939500254, 0.14959598881657674, 0.12462897125553388, 0.09515851168249279, 0.062253523938647894, 0.027152459411754096]
        ]
    };

    function getComponentOnCubicBezier(t, a, b, c, d) {
        const k = 1 - t;
        return k * k * k * a + 3 * k * k * t * b + 3 * k * t * t * c + t * t * t * d;
    }

    function subdivide(x1, y1, x2, y2, x3, y3, x4, y4, limit) {
        limit = limit || Curve.RecursionLimit;
        const amount = limit + 1;
        if (Math.abs(x1 - x4) < 1e-3 && Math.abs(y1 - y4) < 1e-3) {
            return [new Anchor(x4, y4)];
        }
        const result = [];
        for (let i = 0; i < amount; i++) {
            const t = i / amount;
            const x = getComponentOnCubicBezier(t, x1, x2, x3, x4);
            const y = getComponentOnCubicBezier(t, y1, y2, y3, y4);
            result.push(new Anchor(x, y));
        }
        return result;
    }

    function getCurveLength(x1, y1, x2, y2, x3, y3, x4, y4, limit) {
        if (x1 === x2 && y1 === y2 && x3 === x4 && y3 === y4) {
            const dx = x4 - x1;
            const dy = y4 - y1;
            return Math.sqrt(dx * dx + dy * dy);
        }
        const ax = 9 * (x2 - x3) + 3 * (x4 - x1), bx = 6 * (x1 + x3) - 12 * x2, cx = 3 * (x2 - x1),
            ay = 9 * (y2 - y3) + 3 * (y4 - y1), by = 6 * (y1 + y3) - 12 * y2, cy = 3 * (y2 - y1);

        function integrand(t) {
            const dx = (ax * t + bx) * t + cx, dy = (ay * t + by) * t + cy;
            return Math.sqrt(dx * dx + dy * dy);
        }

        return integrate(
            integrand,
            0,
            1,
            limit || Curve.RecursionLimit
        );
    }

    function getCurveBoundingBox(x1, y1, x2, y2, x3, y3, x4, y4) {
        const tvalues = [];
        const bounds = [[], []];
        let a, b, c, t, t1, t2, b2ac, sqrtb2ac;
        for (let i = 0; i < 2; ++i) {
            if (i == 0) {
                b = 6 * x1 - 12 * x2 + 6 * x3;
                a = -3 * x1 + 9 * x2 - 9 * x3 + 3 * x4;
                c = 3 * x2 - 3 * x1;
            } else {
                b = 6 * y1 - 12 * y2 + 6 * y3;
                a = -3 * y1 + 9 * y2 - 9 * y3 + 3 * y4;
                c = 3 * y2 - 3 * y1;
            }
            if (Math.abs(a) < 1e-12) {
                if (Math.abs(b) < 1e-12) {
                    continue;
                }
                t = -c / b;
                if (0 < t && t < 1) {
                    tvalues.push(t);
                }
                continue;
            }
            b2ac = b * b - 4 * c * a;
            sqrtb2ac = Math.sqrt(b2ac);
            if (b2ac < 0) {
                continue;
            }
            t1 = (-b + sqrtb2ac) / (2 * a);
            if (0 < t1 && t1 < 1) {
                tvalues.push(t1);
            }
            t2 = (-b - sqrtb2ac) / (2 * a);
            if (0 < t2 && t2 < 1) {
                tvalues.push(t2);
            }
        }
        let j = tvalues.length;
        let jlen = j;
        let mt;
        while (j--) {
            t = tvalues[j];
            mt = 1 - t;
            bounds[0][j] = mt * mt * mt * x1 + 3 * mt * mt * t * x2 + 3 * mt * t * t * x3 + t * t * t * x4;
            bounds[1][j] = mt * mt * mt * y1 + 3 * mt * mt * t * y2 + 3 * mt * t * t * y3 + t * t * t * y4;
        }
        bounds[0][jlen] = x1;
        bounds[1][jlen] = y1;
        bounds[0][jlen + 1] = x4;
        bounds[1][jlen + 1] = y4;
        bounds[0].length = bounds[1].length = jlen + 2;
        return {
            min: {x: Math.min.apply(0, bounds[0]), y: Math.min.apply(0, bounds[1])},
            max: {x: Math.max.apply(0, bounds[0]), y: Math.max.apply(0, bounds[1])}
        };
    }

    function integrate(f, a, b, n) {
        let x = Curve.abscissas[n - 2], w = Curve.weights[n - 2], A = 0.5 * (b - a), B = A + a, i = 0, m = n + 1 >> 1,
            sum = n & 1 ? w[i++] * f(B) : 0;
        while (i < m) {
            const Ax = A * x[i];
            sum += w[i++] * (f(B + Ax) + f(B - Ax));
        }
        return A * sum;
    }

    function getCurveFromPoints(points, closed2) {
        const l = points.length, last = l - 1;
        for (let i = 0; i < l; i++) {
            const point = points[i];
            const prev = closed2 ? mod(i - 1, l) : Math.max(i - 1, 0);
            const next = closed2 ? mod(i + 1, l) : Math.min(i + 1, last);
            const a = points[prev];
            const b = point;
            const c = points[next];
            getControlPoints(a, b, c);
            b.command = i === 0 ? Commands.move : Commands.curve;
        }
    }

    function getControlPoints(a, b, c) {
        const a1 = Vector.angleBetween(a, b);
        const a2 = Vector.angleBetween(c, b);
        let d1 = Vector.distanceBetween(a, b);
        let d2 = Vector.distanceBetween(c, b);
        let mid = (a1 + a2) / 2;
        if (d1 < 1e-4 || d2 < 1e-4) {
            if (typeof b.relative === "boolean" && !b.relative) {
                b.controls.left.copy(b);
                b.controls.right.copy(b);
            }
            return b;
        }
        d1 *= 0.33;
        d2 *= 0.33;
        if (a2 < a1) {
            mid += HALF_PI;
        } else {
            mid -= HALF_PI;
        }
        b.controls.left.x = Math.cos(mid) * d1;
        b.controls.left.y = Math.sin(mid) * d1;
        mid -= Math.PI;
        b.controls.right.x = Math.cos(mid) * d2;
        b.controls.right.y = Math.sin(mid) * d2;
        if (typeof b.relative === "boolean" && !b.relative) {
            b.controls.left.x += b.x;
            b.controls.left.y += b.y;
            b.controls.right.x += b.x;
            b.controls.right.y += b.y;
        }
        return b;
    }

    function getReflection(a, b, relative) {
        return new Vector(
            2 * a.x - (b.x + a.x) - (relative ? a.x : 0),
            2 * a.y - (b.y + a.y) - (relative ? a.y : 0)
        );
    }

    function getAnchorsFromArcData(center, xAxisRotation, rx, ry, ts, td, ccw) {
        const resolution = Constants.Resolution;
        const anchors = [];
        for (let i = 0; i < resolution; i++) {
            let pct = (i + 1) / resolution;
            if (ccw) {
                pct = 1 - pct;
            }
            const theta = pct * td + ts;
            const x = rx * Math.cos(theta);
            const y = ry * Math.sin(theta);
            const anchor2 = new Anchor(x, y);
            anchor2.command = Commands.line;
            anchors.push(anchor2);
        }
    }

    // src/utils/device-pixel-ratio.js
    var devicePixelRatio = root.devicePixelRatio || 1;

    function getBackingStoreRatio(ctx) {
        return ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
    }

    function getRatio(ctx) {
        return devicePixelRatio / getBackingStoreRatio(ctx);
    }

    // src/utils/underscore.js
    var slice = Array.prototype.slice;

    function isArrayLike(collection) {
        if (collection === null || collection === void 0)
            return false;
        const length = collection.length;
        return typeof length == "number" && length >= 0 && length < 4294967296;
    }

    var _ = {
        isNaN: function (obj) {
            return typeof obj === "number" && obj !== +obj;
        },
        isElement: function (obj) {
            return !!(obj && obj.nodeType === 1);
        },
        isObject: function (obj) {
            const type = typeof obj;
            return type === "function" || type === "object" && !!obj;
        },
        extend: function (base) {
            const sources = slice.call(arguments, 1);
            for (let i = 0; i < sources.length; i++) {
                const obj = sources[i];
                for (let k in obj) {
                    base[k] = obj[k];
                }
            }
            return base;
        },
        defaults: function (base) {
            const sources = slice.call(arguments, 1);
            for (let i = 0; i < sources.length; i++) {
                const obj = sources[i];
                for (let k in obj) {
                    if (base[k] === void 0) {
                        base[k] = obj[k];
                    }
                }
            }
            return base;
        },
        each: function (obj, iteratee, context) {
            const ctx = context || this;
            const keys = !isArrayLike(obj) && Object.keys(obj);
            const length = (keys || obj).length;
            for (let i = 0; i < length; i++) {
                const k = keys ? keys[i] : i;
                iteratee.call(ctx, obj[k], k, obj);
            }
            return obj;
        },
        performance: root.performance && root.performance.now ? root.performance : Date
    };

    // src/element.js
    var Element = class extends Events {
        _flagId = false;
        _flagClassName = false;
        _renderer = {};
        _id = "";
        _className = "";
        classList = [];

        constructor() {
            super();
            for (let prop in proto3) {
                Object.defineProperty(this, prop, proto3[prop]);
            }
        }

        flagReset() {
            this._flagId = this._flagClassName = false;
        }
    };
    var proto3 = {
        renderer: {
            enumerable: false,
            get: function () {
                return this._renderer;
            }
        },
        id: {
            enumerable: true,
            get: function () {
                return this._id;
            },
            set: function (v) {
                const id = this._id;
                if (v === this._id) {
                    return;
                }
                this._id = v;
                this._flagId = true;
                if (this.parent) {
                    delete this.parent.children.ids[id];
                    this.parent.children.ids[this._id] = this;
                }
            }
        },
        className: {
            enumerable: true,
            get: function () {
                return this._className;
            },
            set: function (v) {
                if (this._className !== v) {
                    this._flagClassName = true;
                    this.classList = v.split(/\s+?/);
                    this._className = v;
                }
            }
        }
    };

    // src/matrix.js
    var cos = Math.cos;
    var sin = Math.sin;
    var tan = Math.tan;
    var array = [];
    var _Matrix = class extends Events {
        elements = new NumArray(9);
        manual = false;

        constructor(a, b, c, d, e, f) {
            super();
            let elements = a;
            if (!Array.isArray(elements)) {
                elements = Array.prototype.slice.call(arguments);
            }
            this.identity();
            if (elements.length > 0) {
                this.set(elements);
            }
        }

        static Multiply(A, B, C) {
            if (B.length <= 3) {
                const e = A;
                let x, y, z;
                const a = B[0] || 0, b = B[1] || 0, c = B[2] || 0;
                x = e[0] * a + e[1] * b + e[2] * c;
                y = e[3] * a + e[4] * b + e[5] * c;
                z = e[6] * a + e[7] * b + e[8] * c;
                return [x, y, z];
            }
            const A0 = A[0], A1 = A[1], A2 = A[2];
            const A3 = A[3], A4 = A[4], A5 = A[5];
            const A6 = A[6], A7 = A[7], A8 = A[8];
            const B0 = B[0], B1 = B[1], B2 = B[2];
            const B3 = B[3], B4 = B[4], B5 = B[5];
            const B6 = B[6], B7 = B[7], B8 = B[8];
            C = C || new NumArray(9);
            C[0] = A0 * B0 + A1 * B3 + A2 * B6;
            C[1] = A0 * B1 + A1 * B4 + A2 * B7;
            C[2] = A0 * B2 + A1 * B5 + A2 * B8;
            C[3] = A3 * B0 + A4 * B3 + A5 * B6;
            C[4] = A3 * B1 + A4 * B4 + A5 * B7;
            C[5] = A3 * B2 + A4 * B5 + A5 * B8;
            C[6] = A6 * B0 + A7 * B3 + A8 * B6;
            C[7] = A6 * B1 + A7 * B4 + A8 * B7;
            C[8] = A6 * B2 + A7 * B5 + A8 * B8;
            return C;
        }

        set(a, b, c, d, e, f, g, h, i) {
            if (typeof b === "undefined") {
                const elements = a;
                a = elements[0];
                b = elements[1];
                c = elements[2];
                d = elements[3];
                e = elements[4];
                f = elements[5];
                g = elements[6];
                h = elements[7];
                i = elements[8];
            }
            this.elements[0] = a;
            this.elements[1] = b;
            this.elements[2] = c;
            this.elements[3] = d;
            this.elements[4] = e;
            this.elements[5] = f;
            this.elements[6] = g;
            this.elements[7] = h;
            this.elements[8] = i;
            return this.trigger(Events.Types.change);
        }

        copy(m) {
            this.elements[0] = m.elements[0];
            this.elements[1] = m.elements[1];
            this.elements[2] = m.elements[2];
            this.elements[3] = m.elements[3];
            this.elements[4] = m.elements[4];
            this.elements[5] = m.elements[5];
            this.elements[6] = m.elements[6];
            this.elements[7] = m.elements[7];
            this.elements[8] = m.elements[8];
            this.manual = m.manual;
            return this.trigger(Events.Types.change);
        }

        identity() {
            this.elements[0] = _Matrix.Identity[0];
            this.elements[1] = _Matrix.Identity[1];
            this.elements[2] = _Matrix.Identity[2];
            this.elements[3] = _Matrix.Identity[3];
            this.elements[4] = _Matrix.Identity[4];
            this.elements[5] = _Matrix.Identity[5];
            this.elements[6] = _Matrix.Identity[6];
            this.elements[7] = _Matrix.Identity[7];
            this.elements[8] = _Matrix.Identity[8];
            return this.trigger(Events.Types.change);
        }

        multiply(a, b, c, d, e, f, g, h, i) {
            if (typeof b === "undefined") {
                this.elements[0] *= a;
                this.elements[1] *= a;
                this.elements[2] *= a;
                this.elements[3] *= a;
                this.elements[4] *= a;
                this.elements[5] *= a;
                this.elements[6] *= a;
                this.elements[7] *= a;
                this.elements[8] *= a;
                return this.trigger(Events.Types.change);
            }
            if (typeof c === "undefined") {
                c = 1;
            }
            if (typeof d === "undefined") {
                a = a || 0;
                b = b || 0;
                c = c || 0;
                e = this.elements;
                const x = e[0] * a + e[1] * b + e[2] * c;
                const y = e[3] * a + e[4] * b + e[5] * c;
                const z = e[6] * a + e[7] * b + e[8] * c;
                return [x, y, z];
            }
            const A = this.elements;
            const B = [a, b, c, d, e, f, g, h, i];
            const A0 = A[0], A1 = A[1], A2 = A[2];
            const A3 = A[3], A4 = A[4], A5 = A[5];
            const A6 = A[6], A7 = A[7], A8 = A[8];
            const B0 = B[0], B1 = B[1], B2 = B[2];
            const B3 = B[3], B4 = B[4], B5 = B[5];
            const B6 = B[6], B7 = B[7], B8 = B[8];
            this.elements[0] = A0 * B0 + A1 * B3 + A2 * B6;
            this.elements[1] = A0 * B1 + A1 * B4 + A2 * B7;
            this.elements[2] = A0 * B2 + A1 * B5 + A2 * B8;
            this.elements[3] = A3 * B0 + A4 * B3 + A5 * B6;
            this.elements[4] = A3 * B1 + A4 * B4 + A5 * B7;
            this.elements[5] = A3 * B2 + A4 * B5 + A5 * B8;
            this.elements[6] = A6 * B0 + A7 * B3 + A8 * B6;
            this.elements[7] = A6 * B1 + A7 * B4 + A8 * B7;
            this.elements[8] = A6 * B2 + A7 * B5 + A8 * B8;
            return this.trigger(Events.Types.change);
        }

        inverse(out) {
            const a = this.elements;
            out = out || new _Matrix();
            const a00 = a[0], a01 = a[1], a02 = a[2];
            const a10 = a[3], a11 = a[4], a12 = a[5];
            const a20 = a[6], a21 = a[7], a22 = a[8];
            const b01 = a22 * a11 - a12 * a21;
            const b11 = -a22 * a10 + a12 * a20;
            const b21 = a21 * a10 - a11 * a20;
            let det = a00 * b01 + a01 * b11 + a02 * b21;
            if (!det) {
                return null;
            }
            det = 1 / det;
            out.elements[0] = b01 * det;
            out.elements[1] = (-a22 * a01 + a02 * a21) * det;
            out.elements[2] = (a12 * a01 - a02 * a11) * det;
            out.elements[3] = b11 * det;
            out.elements[4] = (a22 * a00 - a02 * a20) * det;
            out.elements[5] = (-a12 * a00 + a02 * a10) * det;
            out.elements[6] = b21 * det;
            out.elements[7] = (-a21 * a00 + a01 * a20) * det;
            out.elements[8] = (a11 * a00 - a01 * a10) * det;
            return out;
        }

        scale(sx, sy) {
            const l = arguments.length;
            if (l <= 1) {
                sy = sx;
            }
            return this.multiply(sx, 0, 0, 0, sy, 0, 0, 0, 1);
        }

        rotate(Number2) {
            const c = cos(Number2);
            const s = sin(Number2);
            return this.multiply(c, -s, 0, s, c, 0, 0, 0, 1);
        }

        translate(x, y) {
            return this.multiply(1, 0, x, 0, 1, y, 0, 0, 1);
        }

        skewX(Number2) {
            const a = tan(Number2);
            return this.multiply(1, a, 0, 0, 1, 0, 0, 0, 1);
        }

        skewY(Number2) {
            const a = tan(Number2);
            return this.multiply(1, 0, 0, a, 1, 0, 0, 0, 1);
        }

        toString(fullMatrix) {
            array.length = 0;
            this.toTransformArray(fullMatrix, array);
            return array.map(toFixed).join(" ");
        }

        toTransformArray(fullMatrix, output) {
            const elements = this.elements;
            const hasOutput = !!output;
            const a = elements[0];
            const b = elements[1];
            const c = elements[2];
            const d = elements[3];
            const e = elements[4];
            const f = elements[5];
            if (fullMatrix) {
                const g = elements[6];
                const h = elements[7];
                const i = elements[8];
                if (hasOutput) {
                    output[0] = a;
                    output[1] = d;
                    output[2] = g;
                    output[3] = b;
                    output[4] = e;
                    output[5] = h;
                    output[6] = c;
                    output[7] = f;
                    output[8] = i;
                    return;
                }
                return [
                    a,
                    d,
                    g,
                    b,
                    e,
                    h,
                    c,
                    f,
                    i
                ];
            }
            if (hasOutput) {
                output[0] = a;
                output[1] = d;
                output[2] = b;
                output[3] = e;
                output[4] = c;
                output[5] = f;
                return;
            }
            return [
                a,
                d,
                b,
                e,
                c,
                f
            ];
        }

        toArray(fullMatrix, output) {
            const elements = this.elements;
            const hasOutput = !!output;
            const a = elements[0];
            const b = elements[1];
            const c = elements[2];
            const d = elements[3];
            const e = elements[4];
            const f = elements[5];
            if (fullMatrix) {
                const g = elements[6];
                const h = elements[7];
                const i = elements[8];
                if (hasOutput) {
                    output[0] = a;
                    output[1] = b;
                    output[2] = c;
                    output[3] = d;
                    output[4] = e;
                    output[5] = f;
                    output[6] = g;
                    output[7] = h;
                    output[8] = i;
                    return;
                }
                return [
                    a,
                    b,
                    c,
                    d,
                    e,
                    f,
                    g,
                    h,
                    i
                ];
            }
            if (hasOutput) {
                output[0] = a;
                output[1] = b;
                output[2] = c;
                output[3] = d;
                output[4] = e;
                output[5] = f;
                return;
            }
            return [
                a,
                b,
                c,
                d,
                e,
                f
            ];
        }

        toObject() {
            return {
                elements: this.toArray(true),
                manual: !!this.manual
            };
        }

        clone() {
            return new _Matrix().copy(this);
        }
    };
    var Matrix2 = _Matrix;
    __publicField(Matrix2, "Identity", [
        1,
        0,
        0,
        0,
        1,
        0,
        0,
        0,
        1
    ]);
    setMatrix(Matrix2);

    // src/shape.js
    var Shape = class extends Element {
        _flagMatrix = true;
        _flagScale = false;
        _matrix = null;
        _worldMatrix = null;
        _position = null;
        _rotation = 0;
        _scale = 1;
        _skewX = 0;
        _skewY = 0;

        constructor() {
            super();
            for (let prop in proto4) {
                Object.defineProperty(this, prop, proto4[prop]);
            }
            this._renderer.flagMatrix = FlagMatrix.bind(this);
            this.isShape = true;
            this.id = Constants.Identifier + Constants.uniqueId();
            this.matrix = new Matrix2();
            this.worldMatrix = new Matrix2();
            this.position = new Vector();
            this.rotation = 0;
            this.scale = 1;
            this.skewX = 0;
            this.skewY = 0;
        }

        get renderer() {
            return this._renderer;
        }

        set renderer(v) {
            this._renderer = v;
        }

        get translation() {
            return proto4.position.get.apply(this, arguments);
        }

        set translation(v) {
            proto4.position.set.apply(this, arguments);
        }

        addTo(group) {
            group.add(this);
            return this;
        }

        remove() {
            if (!this.parent) {
                return this;
            }
            this.parent.remove(this);
            return this;
        }

        clone(parent) {
            const clone = new Shape();
            clone.position.copy(this.position);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            if (parent) {
                parent.add(clone);
            }
            return clone._update();
        }

        _update(bubbles) {
            if (!this._matrix.manual && this._flagMatrix) {
                this._matrix.identity().translate(this.position.x, this.position.y);
                if (this._scale instanceof Vector) {
                    this._matrix.scale(this._scale.x, this._scale.y);
                } else {
                    this._matrix.scale(this._scale);
                }
                this._matrix.rotate(this.rotation);
                this._matrix.skewX(this.skewX);
                this._matrix.skewY(this.skewY);
            }
            if (bubbles) {
                if (this.parent && this.parent._update) {
                    this.parent._update();
                }
            }
            return this;
        }

        flagReset() {
            this._flagMatrix = this._flagScale = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var proto4 = {
        position: {
            enumerable: true,
            get: function () {
                return this._position;
            },
            set: function (v) {
                if (this._position) {
                    this._position.unbind(Events.Types.change, this._renderer.flagMatrix);
                }
                this._position = v;
                this._position.bind(Events.Types.change, this._renderer.flagMatrix);
                FlagMatrix.call(this);
            }
        },
        rotation: {
            enumerable: true,
            get: function () {
                return this._rotation;
            },
            set: function (v) {
                this._rotation = v;
                this._flagMatrix = true;
            }
        },
        scale: {
            enumerable: true,
            get: function () {
                return this._scale;
            },
            set: function (v) {
                if (this._scale instanceof Vector) {
                    this._scale.unbind(Events.Types.change, this._renderer.flagMatrix);
                }
                this._scale = v;
                if (this._scale instanceof Vector) {
                    this._scale.bind(Events.Types.change, this._renderer.flagMatrix);
                }
                this._flagMatrix = true;
                this._flagScale = true;
            }
        },
        skewX: {
            enumerable: true,
            get: function () {
                return this._skewX;
            },
            set: function (v) {
                this._skewX = v;
                this._flagMatrix = true;
            }
        },
        skewY: {
            enumerable: true,
            get: function () {
                return this._skewY;
            },
            set: function (v) {
                this._skewY = v;
                this._flagMatrix = true;
            }
        },
        matrix: {
            enumerable: true,
            get: function () {
                return this._matrix;
            },
            set: function (v) {
                this._matrix = v;
                this._flagMatrix = true;
            }
        },
        worldMatrix: {
            enumerable: true,
            get: function () {
                getComputedMatrix(this, this._worldMatrix);
                return this._worldMatrix;
            },
            set: function (v) {
                this._worldMatrix = v;
            }
        }
    };

    function FlagMatrix() {
        this._flagMatrix = true;
    }

    // src/collection.js
    var Collection = class extends Array {
        _events = new Events();

        get _bound() {
            return this._events._bound;
        }

        set _bound(v) {
            this._events._bound = v;
        }

        addEventListener() {
            return this._events.addEventListener.apply(this, arguments);
        }

        on() {
            return this._events.on.apply(this, arguments);
        }

        bind() {
            return this._events.bind.apply(this, arguments);
        }

        removeEventListener() {
            return this._events.removeEventListener.apply(this, arguments);
        }

        off() {
            return this._events.off.apply(this, arguments);
        }

        unbind() {
            return this._events.unbind.apply(this, arguments);
        }

        dispatchEvent() {
            return this._events.dispatchEvent.apply(this, arguments);
        }

        trigger() {
            return this._events.trigger.apply(this, arguments);
        }

        listen() {
            return this._events.listen.apply(this, arguments);
        }

        ignore() {
            return this._events.ignore.apply(this, arguments);
        }

        constructor() {
            super();
            if (arguments[0] && Array.isArray(arguments[0])) {
                if (arguments[0].length > 0) {
                    this.push.apply(this, arguments[0]);
                }
            } else if (arguments.length > 0) {
                this.push.apply(this, arguments);
            }
        }

        pop() {
            const popped = super.pop.apply(this, arguments);
            this.trigger(Events.Types.remove, [popped]);
            return popped;
        }

        shift() {
            const shifted = super.shift.apply(this, arguments);
            this.trigger(Events.Types.remove, [shifted]);
            return shifted;
        }

        push() {
            const pushed = super.push.apply(this, arguments);
            this.trigger(Events.Types.insert, arguments);
            return pushed;
        }

        unshift() {
            const unshifted = super.unshift.apply(this, arguments);
            this.trigger(Events.Types.insert, arguments);
            return unshifted;
        }

        splice() {
            const spliced = super.splice.apply(this, arguments);
            this.trigger(Events.Types.remove, spliced);
            if (arguments.length > 2) {
                const inserted = this.slice(arguments[0], arguments[0] + arguments.length - 2);
                this.trigger(Events.Types.insert, inserted);
                this.trigger(Events.Types.order);
            }
            return spliced;
        }

        sort() {
            super.sort.apply(this, arguments);
            this.trigger(Events.Types.order);
            return this;
        }

        reverse() {
            super.reverse.apply(this, arguments);
            this.trigger(Events.Types.order);
            return this;
        }

        indexOf() {
            return super.indexOf.apply(this, arguments);
        }

        map(func, scope) {
            const results = [];
            for (let key = 0; key < this.length; key++) {
                const value = this[key];
                let result;
                if (scope) {
                    result = func.call(scope, value, key);
                } else {
                    result = func(value, key);
                }
                results.push(result);
            }
            return results;
        }
    };

    // src/children.js
    var Children = class extends Collection {
        ids = {};

        constructor(children) {
            children = Array.isArray(children) ? children : Array.prototype.slice.call(arguments);
            super(children);
            this.attach(children);
            this.on(Events.Types.insert, this.attach);
            this.on(Events.Types.remove, this.detach);
        }

        attach(children) {
            for (let i = 0; i < children.length; i++) {
                const child = children[i];
                if (child && child.id) {
                    this.ids[child.id] = child;
                }
            }
            return this;
        }

        detach(children) {
            for (let i = 0; i < children.length; i++) {
                delete this.ids[children[i].id];
            }
            return this;
        }
    };

    // src/group.js
    var min = Math.min;
    var max = Math.max;
    var _Group = class extends Shape {
        _flagAdditions = false;
        _flagSubtractions = false;
        _flagOrder = false;
        _flagOpacity = true;
        _flagBeginning = false;
        _flagEnding = false;
        _flagLength = false;
        _flagMask = false;
        _fill = "#fff";
        _stroke = "#000";
        _linewidth = 1;
        _opacity = 1;
        _visible = true;
        _cap = "round";
        _join = "round";
        _miter = 4;
        _closed = true;
        _curved = false;
        _automatic = true;
        _beginning = 0;
        _ending = 1;
        _length = 0;
        _mask = null;

        constructor(children) {
            super();
            for (let prop in proto5) {
                Object.defineProperty(this, prop, proto5[prop]);
            }
            this._renderer.type = "group";
            this.additions = [];
            this.subtractions = [];
            this.children = Array.isArray(children) ? children : Array.prototype.slice.call(arguments);
        }

        static InsertChildren(children) {
            for (let i = 0; i < children.length; i++) {
                replaceParent.call(this, children[i], this);
            }
        }

        static RemoveChildren(children) {
            for (let i = 0; i < children.length; i++) {
                replaceParent.call(this, children[i]);
            }
        }

        static OrderChildren(children) {
            this._flagOrder = true;
        }

        clone(parent) {
            const clone = new _Group();
            const children = this.children.map(function (child) {
                return child.clone();
            });
            clone.add(children);
            clone.opacity = this.opacity;
            if (this.mask) {
                clone.mask = this.mask;
            }
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.className = this.className;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            if (parent) {
                parent.add(clone);
            }
            return clone._update();
        }

        toObject() {
            const result = {
                children: [],
                translation: this.translation.toObject(),
                rotation: this.rotation,
                scale: this.scale instanceof Vector ? this.scale.toObject() : this.scale,
                opacity: this.opacity,
                className: this.className,
                mask: this.mask ? this.mask.toObject() : null
            };
            if (this.matrix.manual) {
                result.matrix = this.matrix.toObject();
            }
            _.each(this.children, function (child, i) {
                result.children[i] = child.toObject();
            }, this);
            return result;
        }

        corner() {
            const rect = this.getBoundingClientRect(true);
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                child.translation.x -= rect.left;
                child.translation.y -= rect.top;
            }
            if (this.mask) {
                this.mask.translation.x -= rect.left;
                this.mask.translation.y -= rect.top;
            }
            return this;
        }

        center() {
            const rect = this.getBoundingClientRect(true);
            const cx = rect.left + rect.width / 2 - this.translation.x;
            const cy = rect.top + rect.height / 2 - this.translation.y;
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                if (child.isShape) {
                    child.translation.x -= cx;
                    child.translation.y -= cy;
                }
            }
            if (this.mask) {
                this.mask.translation.x -= cx;
                this.mask.translation.y -= cy;
            }
            return this;
        }

        getById(id) {
            let found = null;

            function search(node) {
                if (node.id === id) {
                    return node;
                } else if (node.children) {
                    for (let i = 0; i < node.children.length; i++) {
                        found = search(node.children[i]);
                        if (found) {
                            return found;
                        }
                    }
                }
                return null;
            }

            return search(this);
        }

        getByClassName(className) {
            const found = [];

            function search(node) {
                if (Array.prototype.indexOf.call(node.classList, className) >= 0) {
                    found.push(node);
                }
                if (node.children) {
                    for (let i = 0; i < node.children.length; i++) {
                        const child = node.children[i];
                        search(child);
                    }
                }
                return found;
            }

            return search(this);
        }

        getByType(type) {
            const found = [];

            function search(node) {
                if (node instanceof type) {
                    found.push(node);
                }
                if (node.children) {
                    for (let i = 0; i < node.children.length; i++) {
                        const child = node.children[i];
                        search(child);
                    }
                }
                return found;
            }

            return search(this);
        }

        add(objects) {
            if (!(objects instanceof Array)) {
                objects = Array.prototype.slice.call(arguments);
            } else {
                objects = objects.slice();
            }
            for (let i = 0; i < objects.length; i++) {
                const child = objects[i];
                if (!(child && child.id)) {
                    continue;
                }
                const index = Array.prototype.indexOf.call(this.children, child);
                if (index >= 0) {
                    this.children.splice(index, 1);
                }
                this.children.push(child);
            }
            return this;
        }

        remove(objects) {
            const l = arguments.length, grandparent = this.parent;
            if (l <= 0 && grandparent) {
                grandparent.remove(this);
                return this;
            }
            if (!(objects instanceof Array)) {
                objects = Array.prototype.slice.call(arguments);
            } else {
                objects = objects.slice();
            }
            for (let i = 0; i < objects.length; i++) {
                const object = objects[i];
                if (!object || !this.children.ids[object.id]) {
                    continue;
                }
                const index = this.children.indexOf(object);
                if (index >= 0) {
                    this.children.splice(index, 1);
                }
            }
            return this;
        }

        getBoundingClientRect(shallow) {
            let rect, matrix, tc, lc, rc, bc;
            this._update(true);
            let left = Infinity, right = -Infinity, top = Infinity, bottom = -Infinity;
            const regex3 = /texture|gradient/i;
            matrix = shallow ? this.matrix : this.worldMatrix;
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                if (!child.visible || regex3.test(child._renderer.type)) {
                    continue;
                }
                rect = child.getBoundingClientRect(shallow);
                tc = typeof rect.top !== "number" || _.isNaN(rect.top) || !isFinite(rect.top);
                lc = typeof rect.left !== "number" || _.isNaN(rect.left) || !isFinite(rect.left);
                rc = typeof rect.right !== "number" || _.isNaN(rect.right) || !isFinite(rect.right);
                bc = typeof rect.bottom !== "number" || _.isNaN(rect.bottom) || !isFinite(rect.bottom);
                if (tc || lc || rc || bc) {
                    continue;
                }
                if (shallow) {
                    const [ax, ay] = matrix.multiply(rect.left, rect.top);
                    const [bx, by] = matrix.multiply(rect.right, rect.top);
                    const [cx, cy] = matrix.multiply(rect.left, rect.bottom);
                    const [dx, dy] = matrix.multiply(rect.right, rect.bottom);
                    top = min(ay, by, cy, dy);
                    left = min(ax, bx, cx, dx);
                    right = max(ax, bx, cx, dx);
                    bottom = max(ay, by, cy, dy);
                } else {
                    top = min(rect.top, top);
                    left = min(rect.left, left);
                    right = max(rect.right, right);
                    bottom = max(rect.bottom, bottom);
                }
            }
            return {
                top,
                left,
                right,
                bottom,
                width: right - left,
                height: bottom - top
            };
        }

        noFill() {
            this.children.forEach(function (child) {
                child.noFill();
            });
            return this;
        }

        noStroke() {
            this.children.forEach(function (child) {
                child.noStroke();
            });
            return this;
        }

        subdivide() {
            const args = arguments;
            this.children.forEach(function (child) {
                child.subdivide.apply(child, args);
            });
            return this;
        }

        _update() {
            let i, l, child;
            if (this._flagBeginning || this._flagEnding) {
                const beginning = Math.min(this._beginning, this._ending);
                const ending = Math.max(this._beginning, this._ending);
                const length = this.length;
                let sum = 0;
                const bd = beginning * length;
                const ed = ending * length;
                for (i = 0; i < this.children.length; i++) {
                    child = this.children[i];
                    l = child.length;
                    if (bd > sum + l) {
                        child.beginning = 1;
                        child.ending = 1;
                    } else if (ed < sum) {
                        child.beginning = 0;
                        child.ending = 0;
                    } else if (bd > sum && bd < sum + l) {
                        child.beginning = (bd - sum) / l;
                        child.ending = 1;
                    } else if (ed > sum && ed < sum + l) {
                        child.beginning = 0;
                        child.ending = (ed - sum) / l;
                    } else {
                        child.beginning = 0;
                        child.ending = 1;
                    }
                    sum += l;
                }
            }
            return super._update.apply(this, arguments);
        }

        flagReset() {
            if (this._flagAdditions) {
                this.additions.length = 0;
                this._flagAdditions = false;
            }
            if (this._flagSubtractions) {
                this.subtractions.length = 0;
                this._flagSubtractions = false;
            }
            this._flagOrder = this._flagMask = this._flagOpacity = this._flagBeginning = this._flagEnding = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Group = _Group;
    __publicField(Group, "Children", Children);
    __publicField(Group, "Properties", [
        "fill",
        "stroke",
        "linewidth",
        "cap",
        "join",
        "miter",
        "closed",
        "curved",
        "automatic"
    ]);
    var proto5 = {
        visible: {
            enumerable: true,
            get: function () {
                return this._visible;
            },
            set: function (v) {
                this._flagVisible = this._visible !== v || this._flagVisible;
                this._visible = v;
            }
        },
        opacity: {
            enumerable: true,
            get: function () {
                return this._opacity;
            },
            set: function (v) {
                this._flagOpacity = this._opacity !== v || this._flagOpacity;
                this._opacity = v;
            }
        },
        beginning: {
            enumerable: true,
            get: function () {
                return this._beginning;
            },
            set: function (v) {
                this._flagBeginning = this._beginning !== v || this._flagBeginning;
                this._beginning = v;
            }
        },
        ending: {
            enumerable: true,
            get: function () {
                return this._ending;
            },
            set: function (v) {
                this._flagEnding = this._ending !== v || this._flagEnding;
                this._ending = v;
            }
        },
        length: {
            enumerable: true,
            get: function () {
                if (this._flagLength || this._length <= 0) {
                    this._length = 0;
                    if (!this.children) {
                        return this._length;
                    }
                    for (let i = 0; i < this.children.length; i++) {
                        const child = this.children[i];
                        this._length += child.length;
                    }
                }
                return this._length;
            }
        },
        fill: {
            enumerable: true,
            get: function () {
                return this._fill;
            },
            set: function (v) {
                this._fill = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.fill = v;
                }
            }
        },
        stroke: {
            enumerable: true,
            get: function () {
                return this._stroke;
            },
            set: function (v) {
                this._stroke = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.stroke = v;
                }
            }
        },
        linewidth: {
            enumerable: true,
            get: function () {
                return this._linewidth;
            },
            set: function (v) {
                this._linewidth = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.linewidth = v;
                }
            }
        },
        join: {
            enumerable: true,
            get: function () {
                return this._join;
            },
            set: function (v) {
                this._join = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.join = v;
                }
            }
        },
        miter: {
            enumerable: true,
            get: function () {
                return this._miter;
            },
            set: function (v) {
                this._miter = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.miter = v;
                }
            }
        },
        cap: {
            enumerable: true,
            get: function () {
                return this._cap;
            },
            set: function (v) {
                this._cap = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.cap = v;
                }
            }
        },
        closed: {
            enumerable: true,
            get: function () {
                return this._closed;
            },
            set: function (v) {
                this._closed = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.closed = v;
                }
            }
        },
        curved: {
            enumerable: true,
            get: function () {
                return this._curved;
            },
            set: function (v) {
                this._curved = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.curved = v;
                }
            }
        },
        automatic: {
            enumerable: true,
            get: function () {
                return this._automatic;
            },
            set: function (v) {
                this._automatic = v;
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    child.automatic = v;
                }
            }
        },
        children: {
            enumerable: true,
            get: function () {
                return this._children;
            },
            set: function (children) {
                const insertChildren = Group.InsertChildren.bind(this);
                const removeChildren = Group.RemoveChildren.bind(this);
                const orderChildren = Group.OrderChildren.bind(this);
                if (this._children) {
                    this._children.unbind();
                    if (this._children.length > 0) {
                        removeChildren(this._children);
                    }
                }
                this._children = new Children(children);
                this._children.bind(Events.Types.insert, insertChildren);
                this._children.bind(Events.Types.remove, removeChildren);
                this._children.bind(Events.Types.order, orderChildren);
                if (children.length > 0) {
                    insertChildren(children);
                }
            }
        },
        mask: {
            enumerable: true,
            get: function () {
                return this._mask;
            },
            set: function (v) {
                this._mask = v;
                this._flagMask = true;
                if (_.isObject(v) && !v.clip) {
                    v.clip = true;
                }
            }
        }
    };

    function replaceParent(child, newParent) {
        const parent = child.parent;
        let index;
        if (parent === newParent) {
            add();
            return;
        }
        if (parent && parent.children.ids[child.id]) {
            index = Array.prototype.indexOf.call(parent.children, child);
            parent.children.splice(index, 1);
            splice();
        }
        if (newParent) {
            add();
            return;
        }
        splice();
        if (parent._flagAdditions && parent.additions.length === 0) {
            parent._flagAdditions = false;
        }
        if (parent._flagSubtractions && parent.subtractions.length === 0) {
            parent._flagSubtractions = false;
        }
        delete child.parent;

        function add() {
            if (newParent.subtractions.length > 0) {
                index = Array.prototype.indexOf.call(newParent.subtractions, child);
                if (index >= 0) {
                    newParent.subtractions.splice(index, 1);
                }
            }
            if (newParent.additions.length > 0) {
                index = Array.prototype.indexOf.call(newParent.additions, child);
                if (index >= 0) {
                    newParent.additions.splice(index, 1);
                }
            }
            child.parent = newParent;
            newParent.additions.push(child);
            newParent._flagAdditions = true;
        }

        function splice() {
            index = Array.prototype.indexOf.call(parent.additions, child);
            if (index >= 0) {
                parent.additions.splice(index, 1);
            }
            index = Array.prototype.indexOf.call(parent.subtractions, child);
            if (index < 0) {
                parent.subtractions.push(child);
                parent._flagSubtractions = true;
            }
        }
    }

    // src/renderers/canvas.js
    var emptyArray = [];
    var max2 = Math.max;
    var min2 = Math.min;
    var abs = Math.abs;
    var sin2 = Math.sin;
    var cos2 = Math.cos;
    var acos = Math.acos;
    var sqrt = Math.sqrt;
    var canvas = {
        isHidden: /(undefined|none|transparent)/i,
        alignments: {
            left: "start",
            middle: "center",
            right: "end"
        },
        shim: function (elem, name) {
            elem.tagName = elem.nodeName = name || "canvas";
            elem.nodeType = 1;
            elem.getAttribute = function (prop) {
                return this[prop];
            };
            elem.setAttribute = function (prop, val) {
                this[prop] = val;
                return this;
            };
            return elem;
        },
        group: {
            renderChild: function (child) {
                canvas[child._renderer.type].render.call(child, this.ctx, true, this.clip);
            },
            render: function (ctx) {
                if (!this._visible) {
                    return this;
                }
                this._update();
                const matrix = this._matrix.elements;
                const parent = this.parent;
                this._renderer.opacity = this._opacity * (parent && parent._renderer ? parent._renderer.opacity : 1);
                const mask = this._mask;
                const defaultMatrix = isDefaultMatrix(matrix);
                const shouldIsolate = !defaultMatrix || !!mask;
                if (!this._renderer.context) {
                    this._renderer.context = {};
                }
                this._renderer.context.ctx = ctx;
                if (shouldIsolate) {
                    ctx.save();
                    if (!defaultMatrix) {
                        ctx.transform(
                            matrix[0],
                            matrix[3],
                            matrix[1],
                            matrix[4],
                            matrix[2],
                            matrix[5]
                        );
                    }
                }
                if (mask) {
                    canvas[mask._renderer.type].render.call(mask, ctx, true);
                }
                if (this._opacity > 0 && this._scale !== 0) {
                    for (let i = 0; i < this.children.length; i++) {
                        const child = this.children[i];
                        canvas[child._renderer.type].render.call(child, ctx);
                    }
                }
                if (shouldIsolate) {
                    ctx.restore();
                }
                return this.flagReset();
            }
        },
        path: {
            render: function (ctx, forced, parentClipped) {
                let matrix, stroke, linewidth, fill, opacity, visible, cap, join, miter, closed2, commands, length,
                    last, prev, a, b, c, d, ux, uy, vx, vy, ar, bl, br, cl, x, y, mask, clip, defaultMatrix, isOffset,
                    dashes, po;
                po = this.parent && this.parent._renderer ? this.parent._renderer.opacity : 1;
                mask = this._mask;
                clip = this._clip;
                opacity = this._opacity * (po || 1);
                visible = this._visible;
                if (!forced && (!visible || clip || opacity === 0)) {
                    return this;
                }
                this._update();
                matrix = this._matrix.elements;
                stroke = this._stroke;
                linewidth = this._linewidth;
                fill = this._fill;
                cap = this._cap;
                join = this._join;
                miter = this._miter;
                closed2 = this._closed;
                commands = this._renderer.vertices;
                length = commands.length;
                last = length - 1;
                defaultMatrix = isDefaultMatrix(matrix);
                dashes = this.dashes;
                if (!defaultMatrix) {
                    ctx.save();
                    ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
                }
                if (mask) {
                    canvas[mask._renderer.type].render.call(mask, ctx, true);
                }
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        canvas[fill._renderer.type].render.call(fill, ctx, this);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        canvas[stroke._renderer.type].render.call(stroke, ctx, this);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth;
                    }
                    if (miter) {
                        ctx.miterLimit = miter;
                    }
                    if (join) {
                        ctx.lineJoin = join;
                    }
                    if (!closed2 && cap) {
                        ctx.lineCap = cap;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                ctx.beginPath();
                let rx, ry, xAxisRotation, largeArcFlag, sweepFlag, ax, ay;
                for (let i = 0; i < length; i++) {
                    b = commands[i];
                    x = b.x;
                    y = b.y;
                    switch (b.command) {
                        case Commands.close:
                            ctx.closePath();
                            break;
                        case Commands.arc:
                            rx = b.rx;
                            ry = b.ry;
                            xAxisRotation = b.xAxisRotation;
                            largeArcFlag = b.largeArcFlag;
                            sweepFlag = b.sweepFlag;
                            prev = closed2 ? mod(i - 1, length) : max2(i - 1, 0);
                            a = commands[prev];
                            ax = a.x;
                            ay = a.y;
                            canvas.renderSvgArcCommand(
                                ctx,
                                ax,
                                ay,
                                rx,
                                ry,
                                largeArcFlag,
                                sweepFlag,
                                xAxisRotation,
                                x,
                                y
                            );
                            break;
                        case Commands.curve:
                            prev = closed2 ? mod(i - 1, length) : Math.max(i - 1, 0);
                            a = commands[prev];
                            ar = a.controls && a.controls.right || Vector.zero;
                            bl = b.controls && b.controls.left || Vector.zero;
                            if (a._relative) {
                                vx = ar.x + a.x;
                                vy = ar.y + a.y;
                            } else {
                                vx = ar.x;
                                vy = ar.y;
                            }
                            if (b._relative) {
                                ux = bl.x + b.x;
                                uy = bl.y + b.y;
                            } else {
                                ux = bl.x;
                                uy = bl.y;
                            }
                            ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
                            if (i >= last && closed2) {
                                c = d;
                                br = b.controls && b.controls.right || Vector.zero;
                                cl = c.controls && c.controls.left || Vector.zero;
                                if (b._relative) {
                                    vx = br.x + b.x;
                                    vy = br.y + b.y;
                                } else {
                                    vx = br.x;
                                    vy = br.y;
                                }
                                if (c._relative) {
                                    ux = cl.x + c.x;
                                    uy = cl.y + c.y;
                                } else {
                                    ux = cl.x;
                                    uy = cl.y;
                                }
                                x = c.x;
                                y = c.y;
                                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
                            }
                            break;
                        case Commands.line:
                            ctx.lineTo(x, y);
                            break;
                        case Commands.move:
                            d = b;
                            ctx.moveTo(x, y);
                            break;
                    }
                }
                if (closed2) {
                    ctx.closePath();
                }
                if (!clip && !parentClipped) {
                    if (!canvas.isHidden.test(fill)) {
                        isOffset = fill._renderer && fill._renderer.offset;
                        if (isOffset) {
                            ctx.save();
                            ctx.translate(
                                -fill._renderer.offset.x,
                                -fill._renderer.offset.y
                            );
                            ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
                        }
                        ctx.fill();
                        if (isOffset) {
                            ctx.restore();
                        }
                    }
                    if (!canvas.isHidden.test(stroke)) {
                        isOffset = stroke._renderer && stroke._renderer.offset;
                        if (isOffset) {
                            ctx.save();
                            ctx.translate(
                                -stroke._renderer.offset.x,
                                -stroke._renderer.offset.y
                            );
                            ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
                            ctx.lineWidth = linewidth / stroke._renderer.scale.x;
                        }
                        ctx.stroke();
                        if (isOffset) {
                            ctx.restore();
                        }
                    }
                }
                if (!defaultMatrix) {
                    ctx.restore();
                }
                if (clip && !parentClipped) {
                    ctx.clip();
                }
                if (dashes && dashes.length > 0) {
                    ctx.setLineDash(emptyArray);
                }
                return this.flagReset();
            }
        },
        points: {
            render: function (ctx, forced, parentClipped) {
                let me, stroke, linewidth, fill, opacity, visible, size, commands, length, b, x, y, defaultMatrix,
                    isOffset, dashes, po;
                po = this.parent && this.parent._renderer ? this.parent._renderer.opacity : 1;
                opacity = this._opacity * (po || 1);
                visible = this._visible;
                if (!forced && (!visible || opacity === 0)) {
                    return this;
                }
                this._update();
                me = this._matrix.elements;
                stroke = this._stroke;
                linewidth = this._linewidth;
                fill = this._fill;
                commands = this._renderer.collection;
                length = commands.length;
                defaultMatrix = isDefaultMatrix(me);
                dashes = this.dashes;
                size = this._size;
                if (!defaultMatrix) {
                    ctx.save();
                    ctx.transform(me[0], me[3], me[1], me[4], me[2], me[5]);
                }
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        canvas[fill._renderer.type].render.call(fill, ctx, this);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        canvas[stroke._renderer.type].render.call(stroke, ctx, this);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                ctx.beginPath();
                let radius = size * 0.5, m;
                if (!this._sizeAttenuation) {
                    m = this.worldMatrix.elements;
                    m = decomposeMatrix(m[0], m[3], m[1], m[4], m[2], m[5]);
                    radius /= Math.max(m.scaleX, m.scaleY);
                }
                for (let i = 0; i < length; i++) {
                    b = commands[i];
                    x = b.x;
                    y = b.y;
                    ctx.moveTo(x + radius, y);
                    ctx.arc(x, y, radius, 0, TWO_PI);
                }
                if (!parentClipped) {
                    if (!canvas.isHidden.test(fill)) {
                        isOffset = fill._renderer && fill._renderer.offset;
                        if (isOffset) {
                            ctx.save();
                            ctx.translate(
                                -fill._renderer.offset.x,
                                -fill._renderer.offset.y
                            );
                            ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
                        }
                        ctx.fill();
                        if (isOffset) {
                            ctx.restore();
                        }
                    }
                    if (!canvas.isHidden.test(stroke)) {
                        isOffset = stroke._renderer && stroke._renderer.offset;
                        if (isOffset) {
                            ctx.save();
                            ctx.translate(
                                -stroke._renderer.offset.x,
                                -stroke._renderer.offset.y
                            );
                            ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
                            ctx.lineWidth = linewidth / stroke._renderer.scale.x;
                        }
                        ctx.stroke();
                        if (isOffset) {
                            ctx.restore();
                        }
                    }
                }
                if (!defaultMatrix) {
                    ctx.restore();
                }
                if (dashes && dashes.length > 0) {
                    ctx.setLineDash(emptyArray);
                }
                return this.flagReset();
            }
        },
        text: {
            render: function (ctx, forced, parentClipped) {
                const po = this.parent && this.parent._renderer ? this.parent._renderer.opacity : 1;
                const opacity = this._opacity * po;
                const visible = this._visible;
                const mask = this._mask;
                const clip = this._clip;
                if (!forced && (!visible || clip || opacity === 0)) {
                    return this;
                }
                this._update();
                const matrix = this._matrix.elements;
                const stroke = this._stroke;
                const linewidth = this._linewidth;
                const fill = this._fill;
                const decoration = this._decoration;
                const defaultMatrix = isDefaultMatrix(matrix);
                const isOffset = fill._renderer && fill._renderer.offset && stroke._renderer && stroke._renderer.offset;
                const dashes = this.dashes;
                const alignment = canvas.alignments[this._alignment] || this._alignment;
                const baseline = this._baseline;
                let a, b, c, d, e, sx, sy, x1, y1, x2, y2;
                if (!defaultMatrix) {
                    ctx.save();
                    ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
                }
                if (mask) {
                    canvas[mask._renderer.type].render.call(mask, ctx, true);
                }
                if (!isOffset) {
                    ctx.font = [this._style, this._weight, this._size + "px/" + this._leading + "px", this._family].join(" ");
                }
                ctx.textAlign = alignment;
                ctx.textBaseline = baseline;
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        canvas[fill._renderer.type].render.call(fill, ctx, this);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        canvas[stroke._renderer.type].render.call(stroke, ctx, this);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                if (!clip && !parentClipped) {
                    if (!canvas.isHidden.test(fill)) {
                        if (fill._renderer && fill._renderer.offset) {
                            sx = fill._renderer.scale.x;
                            sy = fill._renderer.scale.y;
                            ctx.save();
                            ctx.translate(
                                -fill._renderer.offset.x,
                                -fill._renderer.offset.y
                            );
                            ctx.scale(sx, sy);
                            a = this._size / fill._renderer.scale.y;
                            b = this._leading / fill._renderer.scale.y;
                            ctx.font = [
                                this._style,
                                this._weight,
                                a + "px/",
                                b + "px",
                                this._family
                            ].join(" ");
                            c = fill._renderer.offset.x / fill._renderer.scale.x;
                            d = fill._renderer.offset.y / fill._renderer.scale.y;
                            ctx.fillText(this.value, c, d);
                            ctx.restore();
                        } else {
                            ctx.fillText(this.value, 0, 0);
                        }
                    }
                    if (!canvas.isHidden.test(stroke)) {
                        if (stroke._renderer && stroke._renderer.offset) {
                            sx = stroke._renderer.scale.x;
                            sy = stroke._renderer.scale.y;
                            ctx.save();
                            ctx.translate(
                                -stroke._renderer.offset.x,
                                -stroke._renderer.offset.y
                            );
                            ctx.scale(sx, sy);
                            a = this._size / stroke._renderer.scale.y;
                            b = this._leading / stroke._renderer.scale.y;
                            ctx.font = [
                                this._style,
                                this._weight,
                                a + "px/",
                                b + "px",
                                this._family
                            ].join(" ");
                            c = stroke._renderer.offset.x / stroke._renderer.scale.x;
                            d = stroke._renderer.offset.y / stroke._renderer.scale.y;
                            e = linewidth / stroke._renderer.scale.x;
                            ctx.lineWidth = e;
                            ctx.strokeText(this.value, c, d);
                            ctx.restore();
                        } else {
                            ctx.strokeText(this.value, 0, 0);
                        }
                    }
                }
                if (/(underline|strikethrough)/i.test(decoration)) {
                    const metrics = ctx.measureText(this.value);
                    let scalar = 1;
                    switch (decoration) {
                        case "underline":
                            y1 = metrics.actualBoundingBoxAscent;
                            y2 = metrics.actualBoundingBoxAscent;
                            break;
                        case "strikethrough":
                            y1 = 0;
                            y2 = 0;
                            scalar = 0.5;
                            break;
                    }
                    switch (baseline) {
                        case "top":
                            y1 += this._size * scalar;
                            y2 += this._size * scalar;
                            break;
                        case "baseline":
                        case "bottom":
                            y1 -= this._size * scalar;
                            y2 -= this._size * scalar;
                            break;
                    }
                    switch (alignment) {
                        case "left":
                        case "start":
                            x1 = 0;
                            x2 = metrics.width;
                            break;
                        case "right":
                        case "end":
                            x1 = -metrics.width;
                            x2 = 0;
                            break;
                        default:
                            x1 = -metrics.width / 2;
                            x2 = metrics.width / 2;
                    }
                    ctx.lineWidth = Math.max(Math.floor(this._size / 15), 1);
                    ctx.strokeStyle = ctx.fillStyle;
                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.stroke();
                }
                if (!defaultMatrix) {
                    ctx.restore();
                }
                if (clip && !parentClipped) {
                    ctx.clip();
                }
                if (dashes && dashes.length > 0) {
                    ctx.setLineDash(emptyArray);
                }
                return this.flagReset();
            }
        },
        "linear-gradient": {
            render: function (ctx, parent) {
                if (!parent) {
                    return;
                }
                this._update();
                if (!this._renderer.effect || this._flagEndPoints || this._flagStops || this._flagUnits) {
                    let rect;
                    let lx = this.left._x;
                    let ly = this.left._y;
                    let rx = this.right._x;
                    let ry = this.right._y;
                    if (/objectBoundingBox/i.test(this._units)) {
                        rect = parent.getBoundingClientRect(true);
                        lx = (lx - 0.5) * rect.width;
                        ly = (ly - 0.5) * rect.height;
                        rx = (rx - 0.5) * rect.width;
                        ry = (ry - 0.5) * rect.height;
                    }
                    this._renderer.effect = ctx.createLinearGradient(lx, ly, rx, ry);
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        this._renderer.effect.addColorStop(stop._offset, stop._color);
                    }
                }
                return this.flagReset();
            }
        },
        "radial-gradient": {
            render: function (ctx, parent) {
                if (!parent) {
                    return;
                }
                this._update();
                if (!this._renderer.effect || this._flagCenter || this._flagFocal || this._flagRadius || this._flagStops || this._flagUnits) {
                    let rect;
                    let cx = this.center._x;
                    let cy = this.center._y;
                    let fx = this.focal._x;
                    let fy = this.focal._y;
                    let radius = this._radius;
                    if (/objectBoundingBox/i.test(this._units)) {
                        rect = parent.getBoundingClientRect(true);
                        cx = cx * rect.width * 0.5;
                        cy = cy * rect.height * 0.5;
                        fx = fx * rect.width * 0.5;
                        fy = fy * rect.height * 0.5;
                        radius *= Math.min(rect.width, rect.height) * 0.5;
                    }
                    this._renderer.effect = ctx.createRadialGradient(
                        cx,
                        cy,
                        0,
                        fx,
                        fy,
                        radius
                    );
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        this._renderer.effect.addColorStop(stop._offset, stop._color);
                    }
                }
                return this.flagReset();
            }
        },
        texture: {
            render: function (ctx) {
                this._update();
                const image = this.image;
                if (!this._renderer.effect || (this._flagLoaded || this._flagImage || this._flagVideo || this._flagRepeat) && this.loaded) {
                    this._renderer.effect = ctx.createPattern(this.image, this._repeat);
                }
                if (this._flagOffset || this._flagLoaded || this._flagScale) {
                    if (!(this._renderer.offset instanceof Vector)) {
                        this._renderer.offset = new Vector();
                    }
                    this._renderer.offset.x = -this._offset.x;
                    this._renderer.offset.y = -this._offset.y;
                    if (image) {
                        this._renderer.offset.x += image.width / 2;
                        this._renderer.offset.y += image.height / 2;
                        if (this._scale instanceof Vector) {
                            this._renderer.offset.x *= this._scale.x;
                            this._renderer.offset.y *= this._scale.y;
                        } else {
                            this._renderer.offset.x *= this._scale;
                            this._renderer.offset.y *= this._scale;
                        }
                    }
                }
                if (this._flagScale || this._flagLoaded) {
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.copy(this._scale);
                    } else {
                        this._renderer.scale.set(this._scale, this._scale);
                    }
                }
                return this.flagReset();
            }
        },
        renderSvgArcCommand: function (ctx, ax, ay, rx, ry, largeArcFlag, sweepFlag, xAxisRotation, x, y) {
            xAxisRotation = xAxisRotation * Math.PI / 180;
            rx = abs(rx);
            ry = abs(ry);
            const dx2 = (ax - x) / 2;
            const dy2 = (ay - y) / 2;
            const x1p = cos2(xAxisRotation) * dx2 + sin2(xAxisRotation) * dy2;
            const y1p = -sin2(xAxisRotation) * dx2 + cos2(xAxisRotation) * dy2;
            const x1ps = x1p * x1p;
            const y1ps = y1p * y1p;
            let rxs = rx * rx;
            let rys = ry * ry;
            const cr = x1ps / rxs + y1ps / rys;
            if (cr > 1) {
                const s = sqrt(cr);
                rx = s * rx;
                ry = s * ry;
                rxs = rx * rx;
                rys = ry * ry;
            }
            const dq = rxs * y1ps + rys * x1ps;
            const pq = (rxs * rys - dq) / dq;
            let q = sqrt(max2(0, pq));
            if (largeArcFlag === sweepFlag)
                q = -q;
            const cxp = q * rx * y1p / ry;
            const cyp = -q * ry * x1p / rx;
            const cx = cos2(xAxisRotation) * cxp - sin2(xAxisRotation) * cyp + (ax + x) / 2;
            const cy = sin2(xAxisRotation) * cxp + cos2(xAxisRotation) * cyp + (ay + y) / 2;
            const startAngle = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
            const delta = svgAngle(
                (x1p - cxp) / rx,
                (y1p - cyp) / ry,
                (-x1p - cxp) / rx,
                (-y1p - cyp) / ry
            ) % TWO_PI;
            const endAngle = startAngle + delta;
            const clockwise = sweepFlag === 0;
            renderArcEstimate(
                ctx,
                cx,
                cy,
                rx,
                ry,
                startAngle,
                endAngle,
                clockwise,
                xAxisRotation
            );
        }
    };
    var Renderer = class extends Events {
        constructor(params) {
            super();
            const smoothing = params.smoothing !== false;
            this.domElement = params.domElement || document.createElement("canvas");
            this.ctx = this.domElement.getContext("2d");
            this.overdraw = params.overdraw || false;
            if (typeof this.ctx.imageSmoothingEnabled !== "undefined") {
                this.ctx.imageSmoothingEnabled = smoothing;
            }
            this.scene = new Group();
            this.scene.parent = this;
        }

        setSize(width, height, ratio) {
            this.width = width;
            this.height = height;
            this.ratio = typeof ratio === "undefined" ? getRatio(this.ctx) : ratio;
            this.domElement.width = width * this.ratio;
            this.domElement.height = height * this.ratio;
            if (this.domElement.style) {
                _.extend(this.domElement.style, {
                    width: width + "px",
                    height: height + "px"
                });
            }
            return this.trigger(Events.Types.resize, width, height, ratio);
        }

        render() {
            const isOne = this.ratio === 1;
            if (!isOne) {
                this.ctx.save();
                this.ctx.scale(this.ratio, this.ratio);
            }
            if (!this.overdraw) {
                this.ctx.clearRect(0, 0, this.width, this.height);
            }
            canvas.group.render.call(this.scene, this.ctx);
            if (!isOne) {
                this.ctx.restore();
            }
            return this;
        }
    };
    __publicField(Renderer, "Utils", canvas);

    function renderArcEstimate(ctx, ox, oy, rx, ry, startAngle, endAngle, clockwise, xAxisRotation) {
        const delta = endAngle - startAngle;
        const epsilon = Curve.Tolerance.epsilon;
        const samePoints = Math.abs(delta) < epsilon;
        let deltaAngle = mod(delta, TWO_PI);
        if (deltaAngle < epsilon) {
            if (samePoints) {
                deltaAngle = 0;
            } else {
                deltaAngle = TWO_PI;
            }
        }
        if (clockwise === true && !samePoints) {
            if (deltaAngle === TWO_PI) {
                deltaAngle = -TWO_PI;
            } else {
                deltaAngle = deltaAngle - TWO_PI;
            }
        }
        for (let i = 0; i < Constants.Resolution; i++) {
            const t = i / (Constants.Resolution - 1);
            const angle = startAngle + t * deltaAngle;
            let x = ox + rx * Math.cos(angle);
            let y = oy + ry * Math.sin(angle);
            if (xAxisRotation !== 0) {
                const cos7 = Math.cos(xAxisRotation);
                const sin7 = Math.sin(xAxisRotation);
                const tx = x - ox;
                const ty = y - oy;
                x = tx * cos7 - ty * sin7 + ox;
                y = tx * sin7 + ty * cos7 + oy;
            }
            ctx.lineTo(x, y);
        }
    }

    function svgAngle(ux, uy, vx, vy) {
        const dot = ux * vx + uy * vy;
        const len = sqrt(ux * ux + uy * uy) * sqrt(vx * vx + vy * vy);
        let ang = acos(max2(-1, min2(1, dot / len)));
        if (ux * vy - uy * vx < 0) {
            ang = -ang;
        }
        return ang;
    }

    function isDefaultMatrix(m) {
        return m[0] == 1 && m[3] == 0 && m[1] == 0 && m[4] == 1 && m[2] == 0 && m[5] == 0;
    }

    // src/utils/canvas-shim.js
    var CanvasShim = {
        Image: null,
        isHeadless: false,
        shim: function (canvas3, Image) {
            Renderer.Utils.shim(canvas3);
            if (typeof Image !== "undefined") {
                CanvasShim.Image = Image;
            }
            CanvasShim.isHeadless = true;
            return canvas3;
        }
    };

    // src/utils/dom.js
    var dom = {
        hasEventListeners: typeof root.addEventListener === "function",
        bind: function (elem, event, func, bool) {
            if (this.hasEventListeners) {
                elem.addEventListener(event, func, !!bool);
            } else {
                elem.attachEvent("on" + event, func);
            }
            return dom;
        },
        unbind: function (elem, event, func, bool) {
            if (dom.hasEventListeners) {
                elem.removeEventListeners(event, func, !!bool);
            } else {
                elem.detachEvent("on" + event, func);
            }
            return dom;
        },
        getRequestAnimationFrame: function () {
            const vendors = ["ms", "moz", "webkit", "o"];
            let lastTime = 0;
            let request = root.requestAnimationFrame;
            if (!request) {
                for (let i = 0; i < vendors.length; i++) {
                    request = root[vendors[i] + "RequestAnimationFrame"] || request;
                }
                request = request || fallbackRequest;
            }

            function fallbackRequest(callback, element) {
                const currTime = new Date().getTime();
                const timeToCall = Math.max(0, 16 - (currTime - lastTime));
                const id = root.setTimeout(nextRequest, timeToCall);
                lastTime = currTime + timeToCall;

                function nextRequest() {
                    callback(currTime + timeToCall);
                }

                return id;
            }

            return request;
        }
    };
    var temp = root.document ? root.document.createElement("div") : {};
    temp.id = "help-two-load";
    Object.defineProperty(dom, "temp", {
        enumerable: true,
        get: function () {
            if (_.isElement(temp) && !root.document.head.contains(temp)) {
                temp.style.display = "none";
                root.document.head.appendChild(temp);
            }
            return temp;
        }
    });

    // src/utils/error.js
    var TwoError = class extends Error {
        name = "Two.js";
        message;

        constructor(message) {
            super();
            this.message = message;
        }
    };

    // src/registry.js
    var Registry = class {
        map = {};

        constructor() {
        }

        add(id, obj) {
            this.map[id] = obj;
            return this;
        }

        remove(id) {
            delete this.map[id];
            return this;
        }

        get(id) {
            return this.map[id];
        }

        contains(id) {
            return id in this.map;
        }
    };

    // src/utils/shape.js
    function contains(path, t) {
        if (t === 0 || t === 1) {
            return true;
        }
        const length = path._length;
        const target = length * t;
        let elapsed = 0;
        for (let i = 0; i < path._lengths.length; i++) {
            const dist = path._lengths[i];
            if (elapsed >= target) {
                return target - elapsed >= 0;
            }
            elapsed += dist;
        }
        return false;
    }

    function getIdByLength(path, target) {
        const total = path._length;
        if (target <= 0) {
            return 0;
        } else if (target >= total) {
            return path._lengths.length - 1;
        }
        for (let i = 0, sum = 0; i < path._lengths.length; i++) {
            if (sum + path._lengths[i] >= target) {
                target -= sum;
                return Math.max(i - 1, 0) + target / path._lengths[i];
            }
            sum += path._lengths[i];
        }
        return -1;
    }

    function getCurveLength2(a, b, limit) {
        let x1, x2, x3, x4, y1, y2, y3, y4;
        const right = b.controls && b.controls.right;
        const left = a.controls && a.controls.left;
        x1 = b.x;
        y1 = b.y;
        x2 = (right || b).x;
        y2 = (right || b).y;
        x3 = (left || a).x;
        y3 = (left || a).y;
        x4 = a.x;
        y4 = a.y;
        if (right && b._relative) {
            x2 += b.x;
            y2 += b.y;
        }
        if (left && a._relative) {
            x3 += a.x;
            y3 += a.y;
        }
        return getCurveLength(x1, y1, x2, y2, x3, y3, x4, y4, limit);
    }

    function getSubdivisions(a, b, limit) {
        let x1, x2, x3, x4, y1, y2, y3, y4;
        const right = b.controls && b.controls.right;
        const left = a.controls && a.controls.left;
        x1 = b.x;
        y1 = b.y;
        x2 = (right || b).x;
        y2 = (right || b).y;
        x3 = (left || a).x;
        y3 = (left || a).y;
        x4 = a.x;
        y4 = a.y;
        if (right && b._relative) {
            x2 += b.x;
            y2 += b.y;
        }
        if (left && a._relative) {
            x3 += a.x;
            y3 += a.y;
        }
        return subdivide(x1, y1, x2, y2, x3, y3, x4, y4, limit);
    }

    // src/effects/stop.js
    var _Stop = class extends Element {
        _flagOffset = true;
        _flagOpacity = true;
        _flagColor = true;
        _offset = 0;
        _opacity = 1;
        _color = "#fff";

        constructor(offset, color, opacity) {
            super();
            for (let prop in proto6) {
                Object.defineProperty(this, prop, proto6[prop]);
            }
            this._renderer.type = "stop";
            this.offset = typeof offset === "number" ? offset : _Stop.Index <= 0 ? 0 : 1;
            this.opacity = typeof opacity === "number" ? opacity : 1;
            this.color = typeof color === "string" ? color : _Stop.Index <= 0 ? "#fff" : "#000";
            _Stop.Index = (_Stop.Index + 1) % 2;
        }

        clone(parent) {
            const clone = new _Stop();
            _.each(_Stop.Properties, function (property) {
                clone[property] = this[property];
            }, this);
            if (parent && parent.stops) {
                parent.stops.push(clone);
            }
            return clone;
        }

        toObject() {
            const result = {};
            _.each(_Stop.Properties, function (k) {
                result[k] = this[k];
            }, this);
            return result;
        }

        flagReset() {
            this._flagOffset = this._flagColor = this._flagOpacity = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Stop = _Stop;
    __publicField(Stop, "Index", 0);
    __publicField(Stop, "Properties", ["offset", "opacity", "color"]);
    var proto6 = {
        offset: {
            enumerable: true,
            get: function () {
                return this._offset;
            },
            set: function (v) {
                this._offset = v;
                this._flagOffset = true;
                if (this.parent) {
                    this.parent._flagStops = true;
                }
            }
        },
        opacity: {
            enumerable: true,
            get: function () {
                return this._opacity;
            },
            set: function (v) {
                this._opacity = v;
                this._flagOpacity = true;
                if (this.parent) {
                    this.parent._flagStops = true;
                }
            }
        },
        color: {
            enumerable: true,
            get: function () {
                return this._color;
            },
            set: function (v) {
                this._color = v;
                this._flagColor = true;
                if (this.parent) {
                    this.parent._flagStops = true;
                }
            }
        }
    };

    // src/effects/gradient.js
    var _Gradient = class extends Element {
        _flagStops = false;
        _flagSpread = false;
        _flagUnits = false;
        _spread = "";
        _units = "";

        constructor(stops) {
            super();
            for (let prop in proto7) {
                Object.defineProperty(this, prop, proto7[prop]);
            }
            this._renderer.type = "gradient";
            this.id = Constants.Identifier + Constants.uniqueId();
            this.classList = [];
            this._renderer.flagStops = FlagStops.bind(this);
            this._renderer.bindStops = BindStops.bind(this);
            this._renderer.unbindStops = UnbindStops.bind(this);
            this.spread = "pad";
            this.units = "objectBoundingBox";
            if (stops) {
                this.stops = stops;
            }
        }

        clone(parent) {
            const stops = this.stops.map(function (s) {
                return s.clone();
            });
            const clone = new _Gradient(stops);
            _.each(_Gradient.Properties, function (k) {
                clone[k] = this[k];
            }, this);
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const result = {
                stops: this.stops.map(function (s) {
                    return s.toObject();
                })
            };
            _.each(_Gradient.Properties, function (k) {
                result[k] = this[k];
            }, this);
            return result;
        }

        _update() {
            if (this._flagSpread || this._flagStops) {
                this.trigger(Events.Types.change);
            }
            return this;
        }

        flagReset() {
            this._flagSpread = this._flagUnits = this._flagStops = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Gradient = _Gradient;
    __publicField(Gradient, "Stop", Stop);
    __publicField(Gradient, "Properties", ["spread", "stops", "renderer", "units"]);
    var proto7 = {
        spread: {
            enumerable: true,
            get: function () {
                return this._spread;
            },
            set: function (v) {
                this._spread = v;
                this._flagSpread = true;
            }
        },
        units: {
            enumerable: true,
            get: function () {
                return this._units;
            },
            set: function (v) {
                this._units = v;
                this._flagUnits = true;
            }
        },
        stops: {
            enumerable: true,
            get: function () {
                return this._stops;
            },
            set: function (stops) {
                const bindStops = this._renderer.bindStops;
                const unbindStops = this._renderer.unbindStops;
                if (this._stops) {
                    this._stops.unbind(Events.Types.insert, bindStops).unbind(Events.Types.remove, unbindStops);
                }
                this._stops = new Collection((stops || []).slice(0));
                this._stops.bind(Events.Types.insert, bindStops).bind(Events.Types.remove, unbindStops);
                bindStops(this._stops);
            }
        }
    };

    function FlagStops() {
        this._flagStops = true;
    }

    function BindStops(items) {
        let i = items.length;
        while (i--) {
            items[i].bind(Events.Types.change, this._renderer.flagStops);
            items[i].parent = this;
        }
        this._renderer.flagStops();
    }

    function UnbindStops(items) {
        let i = items.length;
        while (i--) {
            items[i].unbind(Events.Types.change, this._renderer.flagStops);
            delete items[i].parent;
        }
        this._renderer.flagStops();
    }

    // src/effects/linear-gradient.js
    var _LinearGradient = class extends Gradient {
        _flagEndPoints = false;
        _left = null;
        _right = null;

        constructor(x1, y1, x2, y2, stops) {
            super(stops);
            for (let prop in proto8) {
                Object.defineProperty(this, prop, proto8[prop]);
            }
            this._renderer.type = "linear-gradient";
            this._renderer.flagEndPoints = FlagEndPoints.bind(this);
            this.left = new Vector();
            this.right = new Vector();
            if (typeof x1 === "number") {
                this.left.x = x1;
            }
            if (typeof y1 === "number") {
                this.left.y = y1;
            }
            if (typeof x2 === "number") {
                this.right.x = x2;
            }
            if (typeof y2 === "number") {
                this.right.y = y2;
            }
        }

        clone(parent) {
            const stops = this.stops.map(function (stop) {
                return stop.clone();
            });
            const clone = new _LinearGradient(
                this.left._x,
                this.left._y,
                this.right._x,
                this.right._y,
                stops
            );
            _.each(Gradient.Properties, function (k) {
                clone[k] = this[k];
            }, this);
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const result = super.toObject.call(this);
            result.left = this.left.toObject();
            result.right = this.right.toObject();
            return result;
        }

        _update() {
            if (this._flagEndPoints || this._flagSpread || this._flagStops) {
                this.trigger(Events.Types.change);
            }
            return this;
        }

        flagReset() {
            this._flagEndPoints = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var LinearGradient = _LinearGradient;
    __publicField(LinearGradient, "Properties", ["left", "right"]);
    __publicField(LinearGradient, "Stop", Stop);
    var proto8 = {
        left: {
            enumerable: true,
            get: function () {
                return this._left;
            },
            set: function (v) {
                if (this._left instanceof Vector) {
                    this._left.unbind(Events.Types.change, this._renderer.flagEndPoints);
                }
                this._left = v;
                this._left.bind(Events.Types.change, this._renderer.flagEndPoints);
                this._flagEndPoints = true;
            }
        },
        right: {
            enumerable: true,
            get: function () {
                return this._right;
            },
            set: function (v) {
                if (this._right instanceof Vector) {
                    this._right.unbind(Events.Types.change, this._renderer.flagEndPoints);
                }
                this._right = v;
                this._right.bind(Events.Types.change, this._renderer.flagEndPoints);
                this._flagEndPoints = true;
            }
        }
    };

    function FlagEndPoints() {
        this._flagEndPoints = true;
    }

    // src/effects/radial-gradient.js
    var _RadialGradient = class extends Gradient {
        _flagRadius = false;
        _flagCenter = false;
        _flagFocal = false;
        _radius = 0;
        _center = null;
        _focal = null;

        constructor(cx, cy, r, stops, fx, fy) {
            super(stops);
            for (let prop in proto9) {
                Object.defineProperty(this, prop, proto9[prop]);
            }
            this._renderer.type = "radial-gradient";
            this._renderer.flagCenter = FlagCenter.bind(this);
            this._renderer.flagFocal = FlagFocal.bind(this);
            this.center = new Vector();
            this.radius = typeof r === "number" ? r : 1;
            this.focal = new Vector();
            if (typeof cx === "number") {
                this.center.x = cx;
            }
            if (typeof cy === "number") {
                this.center.y = cy;
            }
            this.focal.copy(this.center);
            if (typeof fx === "number") {
                this.focal.x = fx;
            }
            if (typeof fy === "number") {
                this.focal.y = fy;
            }
        }

        clone(parent) {
            const stops = this.stops.map(function (stop) {
                return stop.clone();
            });
            const clone = new _RadialGradient(
                this.center._x,
                this.center._y,
                this._radius,
                stops,
                this.focal._x,
                this.focal._y
            );
            _.each(Gradient.Properties.concat(_RadialGradient.Properties), function (k) {
                clone[k] = this[k];
            }, this);
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const result = super.toObject.call(this);
            _.each(_RadialGradient.Properties, function (k) {
                result[k] = this[k];
            }, this);
            result.center = this.center.toObject();
            result.focal = this.focal.toObject();
            return result;
        }

        _update() {
            if (this._flagRadius || this._flatCenter || this._flagFocal || this._flagSpread || this._flagStops) {
                this.trigger(Events.Types.change);
            }
            return this;
        }

        flagReset() {
            this._flagRadius = this._flagCenter = this._flagFocal = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var RadialGradient = _RadialGradient;
    __publicField(RadialGradient, "Stop", Stop);
    __publicField(RadialGradient, "Properties", ["center", "radius", "focal"]);
    var proto9 = {
        radius: {
            enumerable: true,
            get: function () {
                return this._radius;
            },
            set: function (v) {
                this._radius = v;
                this._flagRadius = true;
            }
        },
        center: {
            enumerable: true,
            get: function () {
                return this._center;
            },
            set: function (v) {
                if (this._center) {
                    this._center.unbind(Events.Types.change, this._renderer.flagCenter);
                }
                this._center = v;
                this._center.bind(Events.Types.change, this._renderer.flagCenter);
                this._flagCenter = true;
            }
        },
        focal: {
            enumerable: true,
            get: function () {
                return this._focal;
            },
            set: function (v) {
                if (this._focal) {
                    this._focal.unbind(Events.Types.change, this._renderer.flagFocal);
                }
                this._focal = v;
                this._focal.bind(Events.Types.change, this._renderer.flagFocal);
                this._flagFocal = true;
            }
        }
    };

    function FlagCenter() {
        this._flagCenter = true;
    }

    function FlagFocal() {
        this._flagFocal = true;
    }

    // src/effects/texture.js
    var anchor;
    var regex = {
        video: /\.(mp4|webm|ogg)$/i,
        image: /\.(jpe?g|png|gif|tiff|webp)$/i,
        effect: /texture|gradient/i
    };
    if (root.document) {
        anchor = document.createElement("a");
    }
    var _Texture = class extends Element {
        _flagSrc = false;
        _flagImage = false;
        _flagVideo = false;
        _flagLoaded = false;
        _flagRepeat = false;
        _flagOffset = false;
        _flagScale = false;
        _src = "";
        _image = null;
        _loaded = false;
        _repeat = "no-repeat";
        _scale = 1;
        _offset = null;

        constructor(src, callback) {
            super();
            this._renderer = {};
            for (let prop in proto10) {
                Object.defineProperty(this, prop, proto10[prop]);
            }
            this._renderer.type = "texture";
            this._renderer.flagOffset = FlagOffset.bind(this);
            this._renderer.flagScale = FlagScale.bind(this);
            this.id = Constants.Identifier + Constants.uniqueId();
            this.classList = [];
            this.loaded = false;
            this.repeat = "no-repeat";
            this.offset = new Vector();
            if (typeof callback === "function") {
                const loaded = function () {
                    this.unbind(Events.Types.load, loaded);
                    if (typeof callback === "function") {
                        callback();
                    }
                }.bind(this);
                this.bind(Events.Types.load, loaded);
            }
            if (typeof src === "string") {
                this.src = src;
            } else if (typeof src === "object") {
                const elemString = Object.prototype.toString.call(src);
                if (elemString === "[object HTMLImageElement]" || elemString === "[object HTMLCanvasElement]" || elemString === "[object HTMLVideoElement]" || elemString === "[object Image]") {
                    this.image = src;
                }
            }
            this._update();
        }

        static getAbsoluteURL(path) {
            if (!anchor) {
                return path;
            }
            anchor.href = path;
            return anchor.href;
        }

        static loadHeadlessBuffer(texture, loaded) {
            texture.image.onload = loaded;
            texture.image.src = texture.src;
        }

        static getTag(image) {
            return image && image.nodeName && image.nodeName.toLowerCase() || "img";
        }

        static getImage(src) {
            const absoluteSrc = _Texture.getAbsoluteURL(src);
            if (_Texture.ImageRegistry.contains(absoluteSrc)) {
                return _Texture.ImageRegistry.get(absoluteSrc);
            }
            let image;
            if (CanvasShim.Image) {
                image = new CanvasShim.Image();
                Renderer.Utils.shim(image, "img");
            } else if (root.document) {
                if (regex.video.test(absoluteSrc)) {
                    image = document.createElement("video");
                } else {
                    image = document.createElement("img");
                }
            } else {
                console.warn("Two.js: no prototypical image defined for Two.Texture");
            }
            image.crossOrigin = "anonymous";
            image.referrerPolicy = "no-referrer";
            return image;
        }

        static load(texture, callback) {
            let image = texture.image;
            let tag = _Texture.getTag(image);
            if (texture._flagImage) {
                if (/canvas/i.test(tag)) {
                    _Texture.Register.canvas(texture, callback);
                } else {
                    texture._src = !CanvasShim.isHeadless && image.getAttribute("two-src") || image.src;
                    _Texture.Register[tag](texture, callback);
                }
            }
            if (texture._flagSrc) {
                if (!image) {
                    image = _Texture.getImage(texture.src);
                    texture.image = image;
                }
                tag = _Texture.getTag(image);
                _Texture.Register[tag](texture, callback);
            }
        }

        clone() {
            const clone = new _Texture(this.src);
            clone.repeat = this.repeat;
            clone.offset.copy(this.origin);
            clone.scale = this.scale;
            return clone;
        }

        toObject() {
            return {
                src: this.src,
                repeat: this.repeat,
                origin: this.origin.toObject(),
                scale: typeof this.scale === "number" ? this.scale : this.scale.toObject()
            };
        }

        _update() {
            if (this._flagSrc || this._flagImage) {
                this.trigger(Events.Types.change);
                if (this._flagSrc || this._flagImage) {
                    this.loaded = false;
                    _Texture.load(this, function () {
                        this.loaded = true;
                        this.trigger(Events.Types.change).trigger(Events.Types.load);
                    }.bind(this));
                }
            }
            if (this._image && this._image.readyState >= 4) {
                this._flagVideo = true;
            }
            return this;
        }

        flagReset() {
            this._flagSrc = this._flagImage = this._flagLoaded = this._flagRepeat = this._flagVideo = this._flagScale = this._flagOffset = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Texture = _Texture;
    __publicField(Texture, "Properties", [
        "src",
        "loaded",
        "repeat",
        "scale",
        "offset",
        "image"
    ]);
    __publicField(Texture, "RegularExpressions", regex);
    __publicField(Texture, "ImageRegistry", new Registry());
    __publicField(Texture, "Register", {
        canvas: function (texture, callback) {
            texture._src = "#" + texture.id;
            _Texture.ImageRegistry.add(texture.src, texture.image);
            if (typeof callback === "function") {
                callback();
            }
        },
        img: function (texture, callback) {
            const image = texture.image;
            const loaded = function (e) {
                if (!CanvasShim.isHeadless && image.removeEventListener && typeof image.removeEventListener === "function") {
                    image.removeEventListener("load", loaded, false);
                    image.removeEventListener("error", error, false);
                }
                if (typeof callback === "function") {
                    callback();
                }
            };
            const error = function (e) {
                if (!CanvasShim.isHeadless && typeof image.removeEventListener === "function") {
                    image.removeEventListener("load", loaded, false);
                    image.removeEventListener("error", error, false);
                }
                throw new TwoError("unable to load " + texture.src);
            };
            if (typeof image.width === "number" && image.width > 0 && typeof image.height === "number" && image.height > 0) {
                loaded();
            } else if (!CanvasShim.isHeadless && typeof image.addEventListener === "function") {
                image.addEventListener("load", loaded, false);
                image.addEventListener("error", error, false);
            }
            texture._src = _Texture.getAbsoluteURL(texture._src);
            if (!CanvasShim.isHeadless && image && image.getAttribute("two-src")) {
                return;
            }
            if (!CanvasShim.isHeadless) {
                image.setAttribute("two-src", texture.src);
            }
            _Texture.ImageRegistry.add(texture.src, image);
            if (CanvasShim.isHeadless) {
                _Texture.loadHeadlessBuffer(texture, loaded);
            } else {
                texture.image.src = texture.src;
            }
        },
        video: function (texture, callback) {
            if (CanvasShim.isHeadless) {
                throw new TwoError("video textures are not implemented in headless environments.");
            }
            const loaded = function (e) {
                texture.image.removeEventListener("canplaythrough", loaded, false);
                texture.image.removeEventListener("error", error, false);
                texture.image.width = texture.image.videoWidth;
                texture.image.height = texture.image.videoHeight;
                if (typeof callback === "function") {
                    callback();
                }
            };
            const error = function (e) {
                texture.image.removeEventListener("canplaythrough", loaded, false);
                texture.image.removeEventListener("error", error, false);
                throw new TwoError("unable to load " + texture.src);
            };
            texture._src = _Texture.getAbsoluteURL(texture._src);
            if (!texture.image.getAttribute("two-src")) {
                texture.image.setAttribute("two-src", texture.src);
                _Texture.ImageRegistry.add(texture.src, texture.image);
            }
            if (texture.image.readyState >= 4) {
                loaded();
            } else {
                texture.image.addEventListener("canplaythrough", loaded, false);
                texture.image.addEventListener("error", error, false);
                texture.image.src = texture.src;
                texture.image.load();
            }
        }
    });
    var proto10 = {
        src: {
            enumerable: true,
            get: function () {
                return this._src;
            },
            set: function (v) {
                this._src = v;
                this._flagSrc = true;
            }
        },
        loaded: {
            enumerable: true,
            get: function () {
                return this._loaded;
            },
            set: function (v) {
                this._loaded = v;
                this._flagLoaded = true;
            }
        },
        repeat: {
            enumerable: true,
            get: function () {
                return this._repeat;
            },
            set: function (v) {
                this._repeat = v;
                this._flagRepeat = true;
            }
        },
        image: {
            enumerable: true,
            get: function () {
                return this._image;
            },
            set: function (image) {
                const tag = Texture.getTag(image);
                let index;
                switch (tag) {
                    case "canvas":
                        index = "#" + image.id;
                        break;
                    default:
                        index = image.src;
                }
                if (Texture.ImageRegistry.contains(index)) {
                    this._image = Texture.ImageRegistry.get(image.src);
                } else {
                    this._image = image;
                }
                this._flagImage = true;
            }
        },
        offset: {
            enumerable: true,
            get: function () {
                return this._offset;
            },
            set: function (v) {
                if (this._offset) {
                    this._offset.unbind(Events.Types.change, this._renderer.flagOffset);
                }
                this._offset = v;
                this._offset.bind(Events.Types.change, this._renderer.flagOffset);
                this._flagOffset = true;
            }
        },
        scale: {
            enumerable: true,
            get: function () {
                return this._scale;
            },
            set: function (v) {
                if (this._scale instanceof Vector) {
                    this._scale.unbind(Events.Types.change, this._renderer.flagScale);
                }
                this._scale = v;
                if (this._scale instanceof Vector) {
                    this._scale.bind(Events.Types.change, this._renderer.flagScale);
                }
                this._flagScale = true;
            }
        }
    };

    function FlagOffset() {
        this._flagOffset = true;
    }

    function FlagScale() {
        this._flagScale = true;
    }

    // src/path.js
    var min3 = Math.min;
    var max3 = Math.max;
    var ceil = Math.ceil;
    var floor2 = Math.floor;
    var vector = new Vector();
    var _Path = class extends Shape {
        _flagVertices = true;
        _flagLength = true;
        _flagFill = true;
        _flagStroke = true;
        _flagLinewidth = true;
        _flagOpacity = true;
        _flagVisible = true;
        _flagCap = true;
        _flagJoin = true;
        _flagMiter = true;
        _flagMask = false;
        _flagClip = false;
        _length = 0;
        _fill = "#fff";
        _stroke = "#000";
        _linewidth = 1;
        _opacity = 1;
        _visible = true;
        _cap = "round";
        _join = "round";
        _miter = 4;
        _closed = true;
        _curved = false;
        _automatic = true;
        _beginning = 0;
        _ending = 1;
        _mask = null;
        _clip = false;
        _dashes = null;

        constructor(vertices, closed2, curved, manual) {
            super();
            for (let prop in proto11) {
                Object.defineProperty(this, prop, proto11[prop]);
            }
            this._renderer.type = "path";
            this._renderer.flagVertices = FlagVertices.bind(this);
            this._renderer.bindVertices = BindVertices.bind(this);
            this._renderer.unbindVertices = UnbindVertices.bind(this);
            this._renderer.flagFill = FlagFill.bind(this);
            this._renderer.flagStroke = FlagStroke.bind(this);
            this._renderer.vertices = [];
            this._renderer.collection = [];
            this.closed = !!closed2;
            this.curved = !!curved;
            this.beginning = 0;
            this.ending = 1;
            this.fill = "#fff";
            this.stroke = "#000";
            this.linewidth = 1;
            this.opacity = 1;
            this.className = "";
            this.visible = true;
            this.cap = "butt";
            this.join = "miter";
            this.miter = 4;
            this.vertices = vertices;
            this.automatic = !manual;
            this.dashes = [];
            this.dashes.offset = 0;
        }

        clone(parent) {
            const clone = new _Path();
            for (let j = 0; j < this.vertices.length; j++) {
                clone.vertices.push(this.vertices[j].clone());
            }
            for (let i = 0; i < _Path.Properties.length; i++) {
                const k = _Path.Properties[i];
                clone[k] = this[k];
            }
            clone.className = this.className;
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            if (parent) {
                parent.add(clone);
            }
            return clone._update();
        }

        toObject() {
            const result = {
                vertices: this.vertices.map(function (v) {
                    return v.toObject();
                })
            };
            _.each(_Path.Properties, function (k) {
                if (typeof this[k] !== "undefined") {
                    if (this[k].toObject) {
                        result[k] = this[k].toObject();
                    } else {
                        result[k] = this[k];
                    }
                }
            }, this);
            result.className = this.className;
            result.translation = this.translation.toObject();
            result.rotation = this.rotation;
            result.scale = this.scale instanceof Vector ? this.scale.toObject() : this.scale;
            result.skewX = this.skewX;
            result.skewY = this.skewY;
            if (this.matrix.manual) {
                result.matrix = this.matrix.toObject();
            }
            return result;
        }

        noFill() {
            this.fill = "none";
            return this;
        }

        noStroke() {
            this.stroke = "none";
            return this;
        }

        corner() {
            const rect = this.getBoundingClientRect(true);
            const hw = rect.width / 2;
            const hh = rect.height / 2;
            const cx = rect.left + rect.width / 2;
            const cy = rect.top + rect.height / 2;
            for (let i = 0; i < this.vertices.length; i++) {
                const v = this.vertices[i];
                v.x -= cx;
                v.y -= cy;
                v.x += hw;
                v.y += hh;
            }
            if (this.mask) {
                this.mask.translation.x -= cx;
                this.mask.translation.x += hw;
                this.mask.translation.y -= cy;
                this.mask.translation.y += hh;
            }
            return this;
        }

        center() {
            const rect = this.getBoundingClientRect(true);
            const cx = rect.left + rect.width / 2 - this.translation.x;
            const cy = rect.top + rect.height / 2 - this.translation.y;
            for (let i = 0; i < this.vertices.length; i++) {
                const v = this.vertices[i];
                v.x -= cx;
                v.y -= cy;
            }
            if (this.mask) {
                this.mask.translation.x -= cx;
                this.mask.translation.y -= cy;
            }
            return this;
        }

        getBoundingClientRect(shallow) {
            let matrix, border, l, i, v0, v1;
            let left = Infinity, right = -Infinity, top = Infinity, bottom = -Infinity;
            this._update(true);
            matrix = shallow ? this.matrix : this.worldMatrix;
            border = (this.linewidth || 0) / 2;
            l = this._renderer.vertices.length;
            if (this.linewidth > 0 || this.stroke && !/(transparent|none)/i.test(this.stroke)) {
                if (this.matrix.manual) {
                    const {scaleX, scaleY} = decomposeMatrix(
                        matrix.elements[0],
                        matrix.elements[3],
                        matrix.elements[1],
                        matrix.elements[4],
                        matrix.elements[2],
                        matrix.elements[5]
                    );
                    if (typeof scaleX === "number" && typeof scaleY === "number") {
                        border = Math.max(scaleX, scaleY) * (this.linewidth || 0) / 2;
                    }
                } else {
                    border *= typeof this.scale === "number" ? this.scale : Math.max(this.scale.x, this.scale.y);
                }
            }
            if (l <= 0) {
                return {
                    width: 0,
                    height: 0
                };
            }
            for (i = 0; i < l; i++) {
                v1 = this._renderer.vertices[i];
                v0 = this._renderer.vertices[(i + l - 1) % l];
                const [v0x, v0y] = matrix.multiply(v0.x, v0.y);
                const [v1x, v1y] = matrix.multiply(v1.x, v1.y);
                if (v0.controls && v1.controls) {
                    let rx = v0.controls.right.x;
                    let ry = v0.controls.right.y;
                    if (v0.relative) {
                        rx += v0.x;
                        ry += v0.y;
                    }
                    let [c0x, c0y] = matrix.multiply(rx, ry);
                    let lx = v1.controls.left.x;
                    let ly = v1.controls.left.y;
                    if (v1.relative) {
                        lx += v1.x;
                        ly += v1.y;
                    }
                    let [c1x, c1y] = matrix.multiply(lx, ly);
                    const bb = getCurveBoundingBox(
                        v0x,
                        v0y,
                        c0x,
                        c0y,
                        c1x,
                        c1y,
                        v1x,
                        v1y
                    );
                    top = min3(bb.min.y - border, top);
                    left = min3(bb.min.x - border, left);
                    right = max3(bb.max.x + border, right);
                    bottom = max3(bb.max.y + border, bottom);
                } else {
                    if (i <= 1) {
                        top = min3(v0y - border, top);
                        left = min3(v0x - border, left);
                        right = max3(v0x + border, right);
                        bottom = max3(v0y + border, bottom);
                    }
                    top = min3(v1y - border, top);
                    left = min3(v1x - border, left);
                    right = max3(v1x + border, right);
                    bottom = max3(v1y + border, bottom);
                }
            }
            return {
                top,
                left,
                right,
                bottom,
                width: right - left,
                height: bottom - top
            };
        }

        getPointAt(t, obj) {
            let ia, ib, result;
            let x, x1, x2, x3, x4, y, y1, y2, y3, y4, left, right;
            let target = this.length * Math.min(Math.max(t, 0), 1);
            const length = this.vertices.length;
            const last = length - 1;
            let a = null;
            let b = null;
            for (let i = 0, l = this._lengths.length, sum = 0; i < l; i++) {
                if (sum + this._lengths[i] >= target) {
                    if (this._closed) {
                        ia = mod(i, length);
                        ib = mod(i - 1, length);
                        if (i === 0) {
                            ia = ib;
                            ib = i;
                        }
                    } else {
                        ia = i;
                        ib = Math.min(Math.max(i - 1, 0), last);
                    }
                    a = this.vertices[ia];
                    b = this.vertices[ib];
                    target -= sum;
                    if (this._lengths[i] !== 0) {
                        t = target / this._lengths[i];
                    } else {
                        t = 0;
                    }
                    break;
                }
                sum += this._lengths[i];
            }
            if (a === null || b === null) {
                return null;
            }
            if (!a) {
                return b;
            } else if (!b) {
                return a;
            }
            right = b.controls && b.controls.right;
            left = a.controls && a.controls.left;
            x1 = b.x;
            y1 = b.y;
            x2 = (right || b).x;
            y2 = (right || b).y;
            x3 = (left || a).x;
            y3 = (left || a).y;
            x4 = a.x;
            y4 = a.y;
            if (right && b.relative) {
                x2 += b.x;
                y2 += b.y;
            }
            if (left && a.relative) {
                x3 += a.x;
                y3 += a.y;
            }
            x = getComponentOnCubicBezier(t, x1, x2, x3, x4);
            y = getComponentOnCubicBezier(t, y1, y2, y3, y4);
            const t1x = lerp(x1, x2, t);
            const t1y = lerp(y1, y2, t);
            const t2x = lerp(x2, x3, t);
            const t2y = lerp(y2, y3, t);
            const t3x = lerp(x3, x4, t);
            const t3y = lerp(y3, y4, t);
            const brx = lerp(t1x, t2x, t);
            const bry = lerp(t1y, t2y, t);
            const alx = lerp(t2x, t3x, t);
            const aly = lerp(t2y, t3y, t);
            if (_.isObject(obj)) {
                obj.x = x;
                obj.y = y;
                if (obj instanceof Anchor) {
                    obj.controls.left.x = brx;
                    obj.controls.left.y = bry;
                    obj.controls.right.x = alx;
                    obj.controls.right.y = aly;
                    if (!(typeof obj.relative === "boolean") || obj.relative) {
                        obj.controls.left.x -= x;
                        obj.controls.left.y -= y;
                        obj.controls.right.x -= x;
                        obj.controls.right.y -= y;
                    }
                }
                obj.t = t;
                return obj;
            }
            result = new Anchor(
                x,
                y,
                brx - x,
                bry - y,
                alx - x,
                aly - y,
                this._curved ? Commands.curve : Commands.line
            );
            result.t = t;
            return result;
        }

        plot() {
            if (this.curved) {
                getCurveFromPoints(this._collection, this.closed);
                return this;
            }
            for (let i = 0; i < this._collection.length; i++) {
                this._collection[i].command = i === 0 ? Commands.move : Commands.line;
            }
            return this;
        }

        subdivide(limit) {
            this._update();
            const last = this.vertices.length - 1;
            const closed2 = this._closed || this.vertices[last]._command === Commands.close;
            let b = this.vertices[last];
            let points = [], verts;
            _.each(this.vertices, function (a, i) {
                if (i <= 0 && !closed2) {
                    b = a;
                    return;
                }
                if (a.command === Commands.move) {
                    points.push(new Anchor(b.x, b.y));
                    if (i > 0) {
                        points[points.length - 1].command = Commands.line;
                    }
                    b = a;
                    return;
                }
                verts = getSubdivisions(a, b, limit);
                points = points.concat(verts);
                _.each(verts, function (v, i2) {
                    if (i2 <= 0 && b.command === Commands.move) {
                        v.command = Commands.move;
                    } else {
                        v.command = Commands.line;
                    }
                });
                if (i >= last) {
                    if (this._closed && this._automatic) {
                        b = a;
                        verts = getSubdivisions(a, b, limit);
                        points = points.concat(verts);
                        _.each(verts, function (v, i2) {
                            if (i2 <= 0 && b.command === Commands.move) {
                                v.command = Commands.move;
                            } else {
                                v.command = Commands.line;
                            }
                        });
                    } else if (closed2) {
                        points.push(new Anchor(a.x, a.y));
                    }
                    points[points.length - 1].command = closed2 ? Commands.close : Commands.line;
                }
                b = a;
            }, this);
            this._automatic = false;
            this._curved = false;
            this.vertices = points;
            return this;
        }

        _updateLength(limit, silent) {
            if (!silent) {
                this._update();
            }
            const length = this.vertices.length;
            const last = length - 1;
            const closed2 = false;
            let b = this.vertices[last];
            let sum = 0;
            if (typeof this._lengths === "undefined") {
                this._lengths = [];
            }
            _.each(this.vertices, function (a, i) {
                if (i <= 0 && !closed2 || a.command === Commands.move) {
                    b = a;
                    this._lengths[i] = 0;
                    return;
                }
                this._lengths[i] = getCurveLength2(a, b, limit);
                sum += this._lengths[i];
                if (i >= last && closed2) {
                    b = this.vertices[(i + 1) % length];
                    this._lengths[i + 1] = getCurveLength2(a, b, limit);
                    sum += this._lengths[i + 1];
                }
                b = a;
            }, this);
            this._length = sum;
            this._flagLength = false;
            return this;
        }

        _update() {
            if (this._flagVertices) {
                if (this._automatic) {
                    this.plot();
                }
                if (this._flagLength) {
                    this._updateLength(void 0, true);
                }
                const l = this._collection.length;
                const closed2 = this._closed;
                const beginning = Math.min(this._beginning, this._ending);
                const ending = Math.max(this._beginning, this._ending);
                const bid = getIdByLength(this, beginning * this._length);
                const eid = getIdByLength(this, ending * this._length);
                const low = ceil(bid);
                const high = floor2(eid);
                let left, right, prev, next, v, i;
                this._renderer.vertices.length = 0;
                for (i = 0; i < l; i++) {
                    if (this._renderer.collection.length <= i) {
                        this._renderer.collection.push(new Anchor());
                    }
                    if (i > high && !right) {
                        v = this._renderer.collection[i].copy(this._collection[i]);
                        this.getPointAt(ending, v);
                        v.command = this._renderer.collection[i].command;
                        this._renderer.vertices.push(v);
                        right = v;
                        prev = this._collection[i - 1];
                        if (prev && prev.controls) {
                            if (v.relative) {
                                v.controls.right.clear();
                            } else {
                                v.controls.right.copy(v);
                            }
                            if (prev.relative) {
                                this._renderer.collection[i - 1].controls.right.copy(prev.controls.right).lerp(Vector.zero, 1 - v.t);
                            } else {
                                this._renderer.collection[i - 1].controls.right.copy(prev.controls.right).lerp(prev, 1 - v.t);
                            }
                        }
                    } else if (i >= low && i <= high) {
                        v = this._renderer.collection[i].copy(this._collection[i]);
                        this._renderer.vertices.push(v);
                        if (i === high && contains(this, ending)) {
                            right = v;
                            if (!closed2 && right.controls) {
                                if (right.relative) {
                                    right.controls.right.clear();
                                } else {
                                    right.controls.right.copy(right);
                                }
                            }
                        } else if (i === low && contains(this, beginning)) {
                            left = v;
                            left.command = Commands.move;
                            if (!closed2 && left.controls) {
                                if (left.relative) {
                                    left.controls.left.clear();
                                } else {
                                    left.controls.left.copy(left);
                                }
                            }
                        }
                    }
                }
                if (low > 0 && !left) {
                    i = low - 1;
                    v = this._renderer.collection[i].copy(this._collection[i]);
                    this.getPointAt(beginning, v);
                    v.command = Commands.move;
                    this._renderer.vertices.unshift(v);
                    next = this._collection[i + 1];
                    if (next && next.controls) {
                        v.controls.left.clear();
                        if (next.relative) {
                            this._renderer.collection[i + 1].controls.left.copy(next.controls.left).lerp(Vector.zero, v.t);
                        } else {
                            vector.copy(next);
                            this._renderer.collection[i + 1].controls.left.copy(next.controls.left).lerp(next, v.t);
                        }
                    }
                }
            }
            Shape.prototype._update.apply(this, arguments);
            return this;
        }

        flagReset() {
            this._flagVertices = this._flagLength = this._flagFill = this._flagStroke = this._flagLinewidth = this._flagOpacity = this._flagVisible = this._flagCap = this._flagJoin = this._flagMiter = this._flagClip = false;
            Shape.prototype.flagReset.call(this);
            return this;
        }
    };
    var Path = _Path;
    __publicField(Path, "Properties", [
        "fill",
        "stroke",
        "linewidth",
        "opacity",
        "visible",
        "cap",
        "join",
        "miter",
        "closed",
        "curved",
        "automatic",
        "beginning",
        "ending"
    ]);
    __publicField(Path, "Utils", {
        getCurveLength: getCurveLength2
    });
    var proto11 = {
        linewidth: {
            enumerable: true,
            get: function () {
                return this._linewidth;
            },
            set: function (v) {
                this._linewidth = v;
                this._flagLinewidth = true;
            }
        },
        opacity: {
            enumerable: true,
            get: function () {
                return this._opacity;
            },
            set: function (v) {
                this._opacity = v;
                this._flagOpacity = true;
            }
        },
        visible: {
            enumerable: true,
            get: function () {
                return this._visible;
            },
            set: function (v) {
                this._visible = v;
                this._flagVisible = true;
            }
        },
        cap: {
            enumerable: true,
            get: function () {
                return this._cap;
            },
            set: function (v) {
                this._cap = v;
                this._flagCap = true;
            }
        },
        join: {
            enumerable: true,
            get: function () {
                return this._join;
            },
            set: function (v) {
                this._join = v;
                this._flagJoin = true;
            }
        },
        miter: {
            enumerable: true,
            get: function () {
                return this._miter;
            },
            set: function (v) {
                this._miter = v;
                this._flagMiter = true;
            }
        },
        fill: {
            enumerable: true,
            get: function () {
                return this._fill;
            },
            set: function (f) {
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.unbind(Events.Types.change, this._renderer.flagFill);
                }
                this._fill = f;
                this._flagFill = true;
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.bind(Events.Types.change, this._renderer.flagFill);
                }
            }
        },
        stroke: {
            enumerable: true,
            get: function () {
                return this._stroke;
            },
            set: function (f) {
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.unbind(Events.Types.change, this._renderer.flagStroke);
                }
                this._stroke = f;
                this._flagStroke = true;
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.bind(Events.Types.change, this._renderer.flagStroke);
                }
            }
        },
        length: {
            get: function () {
                if (this._flagLength) {
                    this._updateLength();
                }
                return this._length;
            }
        },
        closed: {
            enumerable: true,
            get: function () {
                return this._closed;
            },
            set: function (v) {
                this._closed = !!v;
                this._flagVertices = true;
            }
        },
        curved: {
            enumerable: true,
            get: function () {
                return this._curved;
            },
            set: function (v) {
                this._curved = !!v;
                this._flagVertices = true;
            }
        },
        automatic: {
            enumerable: true,
            get: function () {
                return this._automatic;
            },
            set: function (v) {
                if (v === this._automatic) {
                    return;
                }
                this._automatic = !!v;
                const method = this._automatic ? "ignore" : "listen";
                _.each(this.vertices, function (v2) {
                    v2[method]();
                });
            }
        },
        beginning: {
            enumerable: true,
            get: function () {
                return this._beginning;
            },
            set: function (v) {
                this._beginning = v;
                this._flagVertices = true;
            }
        },
        ending: {
            enumerable: true,
            get: function () {
                return this._ending;
            },
            set: function (v) {
                this._ending = v;
                this._flagVertices = true;
            }
        },
        vertices: {
            enumerable: true,
            get: function () {
                return this._collection;
            },
            set: function (vertices) {
                const bindVertices = this._renderer.bindVertices;
                const unbindVertices = this._renderer.unbindVertices;
                if (this._collection) {
                    this._collection.unbind(Events.Types.insert, bindVertices).unbind(Events.Types.remove, unbindVertices);
                }
                if (vertices instanceof Collection) {
                    this._collection = vertices;
                } else {
                    this._collection = new Collection(vertices || []);
                }
                this._collection.bind(Events.Types.insert, bindVertices).bind(Events.Types.remove, unbindVertices);
                bindVertices(this._collection);
            }
        },
        mask: {
            enumerable: true,
            get: function () {
                return this._mask;
            },
            set: function (v) {
                this._mask = v;
                this._flagMask = true;
                if (_.isObject(v) && !v.clip) {
                    v.clip = true;
                }
            }
        },
        clip: {
            enumerable: true,
            get: function () {
                return this._clip;
            },
            set: function (v) {
                this._clip = v;
                this._flagClip = true;
            }
        },
        dashes: {
            enumerable: true,
            get: function () {
                return this._dashes;
            },
            set: function (v) {
                if (typeof v.offset !== "number") {
                    v.offset = this.dashes && this._dashes.offset || 0;
                }
                this._dashes = v;
            }
        }
    };

    function FlagVertices() {
        this._flagVertices = true;
        this._flagLength = true;
        if (this.parent) {
            this.parent._flagLength = true;
        }
    }

    function BindVertices(items) {
        let i = items.length;
        while (i--) {
            items[i].bind(Events.Types.change, this._renderer.flagVertices);
        }
        this._renderer.flagVertices();
    }

    function UnbindVertices(items) {
        let i = items.length;
        while (i--) {
            items[i].unbind(Events.Types.change, this._renderer.flagVertices);
        }
        this._renderer.flagVertices();
    }

    function FlagFill() {
        this._flagFill = true;
    }

    function FlagStroke() {
        this._flagStroke = true;
    }

    // src/shapes/rectangle.js
    var _Rectangle = class extends Path {
        constructor(x, y, width, height) {
            const points = [
                new Anchor(),
                new Anchor(),
                new Anchor(),
                new Anchor()
            ];
            super(points, true, false, true);
            for (let prop in proto12) {
                Object.defineProperty(this, prop, proto12[prop]);
            }
            this.width = typeof width === "number" ? width : 1;
            this.height = typeof height === "number" ? height : 1;
            this.origin = new Vector();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
            this._update();
        }

        _flagWidth = 0;
        _flagHeight = 0;
        _width = 0;
        _height = 0;
        _origin = null;

        _update() {
            if (this._flagVertices || this._flagWidth || this._flagHeight) {
                const xr = this._width / 2;
                const yr = this._height / 2;
                if (!this._closed && this.vertices.length === 4) {
                    this.vertices.push(new Anchor());
                }
                this.vertices[0].set(-xr, -yr).sub(this._origin).command = Commands.move;
                this.vertices[1].set(xr, -yr).sub(this._origin).command = Commands.line;
                this.vertices[2].set(xr, yr).sub(this._origin).command = Commands.line;
                this.vertices[3].set(-xr, yr).sub(this._origin).command = Commands.line;
                if (this.vertices[4]) {
                    this.vertices[4].set(-xr, -yr).sub(this._origin).command = Commands.line;
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagWidth = this._flagHeight = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const clone = new _Rectangle(0, 0, this.width, this.height);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            object.width = this.width;
            object.height = this.height;
            object.origin = this.origin.toObject();
            return object;
        }
    };
    var Rectangle = _Rectangle;
    __publicField(Rectangle, "Properties", ["width", "height"]);
    var proto12 = {
        width: {
            enumerable: true,
            get: function () {
                return this._width;
            },
            set: function (v) {
                this._width = v;
                this._flagWidth = true;
            }
        },
        height: {
            enumerable: true,
            get: function () {
                return this._height;
            },
            set: function (v) {
                this._height = v;
                this._flagHeight = true;
            }
        },
        origin: {
            enumerable: true,
            get: function () {
                return this._origin;
            },
            set: function (v) {
                if (this._origin) {
                    this._origin.unbind(Events.Types.change, this._renderer.flagVertices);
                }
                this._origin = v;
                this._origin.bind(Events.Types.change, this._renderer.flagVertices);
                this._renderer.flagVertices();
            }
        }
    };

    // src/effects/sprite.js
    var _Sprite = class extends Rectangle {
        _flagTexture = false;
        _flagColumns = false;
        _flagRows = false;
        _flagFrameRate = false;
        _flagIndex = false;
        _amount = 1;
        _duration = 0;
        _startTime = 0;
        _playing = false;
        _firstFrame = 0;
        _lastFrame = 0;
        _loop = true;
        _texture = null;
        _columns = 1;
        _rows = 1;
        _frameRate = 0;
        _index = 0;
        _origin = null;

        constructor(path, ox, oy, cols, rows, frameRate) {
            super(ox, oy, 0, 0);
            for (let prop in proto13) {
                Object.defineProperty(this, prop, proto13[prop]);
            }
            this.noStroke();
            this.noFill();
            if (path instanceof Texture) {
                this.texture = path;
            } else if (typeof path === "string") {
                this.texture = new Texture(path);
            }
            this.origin = new Vector();
            this._update();
            if (typeof cols === "number") {
                this.columns = cols;
            }
            if (typeof rows === "number") {
                this.rows = rows;
            }
            if (typeof frameRate === "number") {
                this.frameRate = frameRate;
            }
            this.index = 0;
        }

        play(firstFrame, lastFrame, onLastFrame) {
            this._playing = true;
            this._firstFrame = 0;
            this._lastFrame = this.amount - 1;
            this._startTime = _.performance.now();
            if (typeof firstFrame === "number") {
                this._firstFrame = firstFrame;
            }
            if (typeof lastFrame === "number") {
                this._lastFrame = lastFrame;
            }
            if (typeof onLastFrame === "function") {
                this._onLastFrame = onLastFrame;
            } else {
                delete this._onLastFrame;
            }
            if (this._index !== this._firstFrame) {
                this._startTime -= 1e3 * Math.abs(this._index - this._firstFrame) / this._frameRate;
            }
            return this;
        }

        pause() {
            this._playing = false;
            return this;
        }

        stop() {
            this._playing = false;
            this._index = 0;
            return this;
        }

        clone(parent) {
            const clone = new _Sprite(
                this.texture,
                this.translation.x,
                this.translation.y,
                this.columns,
                this.rows,
                this.frameRate
            );
            if (this.playing) {
                clone.play(this._firstFrame, this._lastFrame);
                clone._loop = this._loop;
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            object.texture = this.texture.toObject();
            object.columns = this.columns;
            object.rows = this.rows;
            object.frameRate = this.frameRate;
            object.index = this.index;
            object._firstFrame = this._firstFrame;
            object._lastFrame = this._lastFrame;
            object._loop = this._loop;
            return object;
        }

        _update() {
            const effect = this._texture;
            const cols = this._columns;
            const rows = this._rows;
            let width, height, elapsed, amount, duration;
            let index, iw, ih, frames;
            if (effect) {
                if (this._flagColumns || this._flagRows) {
                    this._amount = this._columns * this._rows;
                }
                if (this._flagFrameRate) {
                    this._duration = 1e3 * this._amount / this._frameRate;
                }
                if (this._flagTexture) {
                    this.fill = effect;
                }
                if (effect.loaded) {
                    iw = effect.image.width;
                    ih = effect.image.height;
                    width = iw / cols;
                    height = ih / rows;
                    amount = this._amount;
                    if (this.width !== width) {
                        this.width = width;
                    }
                    if (this.height !== height) {
                        this.height = height;
                    }
                    if (this._playing && this._frameRate > 0) {
                        if (_.isNaN(this._lastFrame)) {
                            this._lastFrame = amount - 1;
                        }
                        elapsed = _.performance.now() - this._startTime;
                        frames = this._lastFrame + 1;
                        duration = 1e3 * (frames - this._firstFrame) / this._frameRate;
                        if (this._loop) {
                            elapsed = elapsed % duration;
                        } else {
                            elapsed = Math.min(elapsed, duration);
                        }
                        index = lerp(this._firstFrame, frames, elapsed / duration);
                        index = Math.floor(index);
                        if (index !== this._index) {
                            this._index = index;
                            if (index >= this._lastFrame - 1 && this._onLastFrame) {
                                this._onLastFrame();
                            }
                        }
                    }
                    const col = this._index % cols;
                    const row = Math.floor(this._index / cols);
                    const ox = -width * col + (iw - width) / 2;
                    const oy = -height * row + (ih - height) / 2;
                    if (ox !== effect.offset.x) {
                        effect.offset.x = ox;
                    }
                    if (oy !== effect.offset.y) {
                        effect.offset.y = oy;
                    }
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagTexture = this._flagColumns = this._flagRows = this._flagFrameRate = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Sprite = _Sprite;
    __publicField(Sprite, "Properties", [
        "texture",
        "columns",
        "rows",
        "frameRate",
        "index"
    ]);
    var proto13 = {
        texture: {
            enumerable: true,
            get: function () {
                return this._texture;
            },
            set: function (v) {
                this._texture = v;
                this._flagTexture = true;
            }
        },
        columns: {
            enumerable: true,
            get: function () {
                return this._columns;
            },
            set: function (v) {
                this._columns = v;
                this._flagColumns = true;
            }
        },
        rows: {
            enumerable: true,
            get: function () {
                return this._rows;
            },
            set: function (v) {
                this._rows = v;
                this._flagRows = true;
            }
        },
        frameRate: {
            enumerable: true,
            get: function () {
                return this._frameRate;
            },
            set: function (v) {
                this._frameRate = v;
                this._flagFrameRate = true;
            }
        },
        index: {
            enumerable: true,
            get: function () {
                return this._index;
            },
            set: function (v) {
                this._index = v;
                this._flagIndex = true;
            }
        }
    };

    // src/shapes/circle.js
    var cos3 = Math.cos;
    var sin3 = Math.sin;
    var _Circle = class extends Path {
        _flagRadius = false;
        _radius = 0;

        constructor(ox, oy, r, resolution) {
            const amount = resolution ? Math.max(resolution, 2) : 4;
            const points = [];
            for (let i = 0; i < amount; i++) {
                points.push(new Anchor(0, 0, 0, 0, 0, 0));
            }
            super(points, true, true, true);
            for (let prop in proto14) {
                Object.defineProperty(this, prop, proto14[prop]);
            }
            if (typeof r === "number") {
                this.radius = r;
            }
            this._update();
            if (typeof ox === "number") {
                this.translation.x = ox;
            }
            if (typeof oy === "number") {
                this.translation.y = oy;
            }
        }

        _update() {
            if (this._flagVertices || this._flagRadius) {
                let length = this.vertices.length;
                if (!this._closed && length > 2) {
                    length -= 1;
                }
                const c = 4 / 3 * Math.tan(Math.PI / (length * 2));
                const radius = this._radius;
                const rc = radius * c;
                for (let i = 0; i < this.vertices.length; i++) {
                    const pct = i / length;
                    const theta = pct * TWO_PI;
                    const x = radius * cos3(theta);
                    const y = radius * sin3(theta);
                    const lx = rc * cos3(theta - HALF_PI);
                    const ly = rc * sin3(theta - HALF_PI);
                    const rx = rc * cos3(theta + HALF_PI);
                    const ry = rc * sin3(theta + HALF_PI);
                    const v = this.vertices[i];
                    v.command = i === 0 ? Commands.move : Commands.curve;
                    v.set(x, y);
                    v.controls.left.set(lx, ly);
                    v.controls.right.set(rx, ry);
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagRadius = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const clone = new _Circle(0, 0, this.radius, this.vertices.length);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _Circle.Properties.length; i++) {
                const k = _Circle.Properties[i];
                object[k] = this[k];
            }
            return object;
        }
    };
    var Circle = _Circle;
    __publicField(Circle, "Properties", ["radius"]);
    var proto14 = {
        radius: {
            enumerable: true,
            get: function () {
                return this._radius;
            },
            set: function (v) {
                this._radius = v;
                this._flagRadius = true;
            }
        }
    };

    // src/shapes/ellipse.js
    var cos4 = Math.cos;
    var sin4 = Math.sin;
    var _Ellipse = class extends Path {
        _flagWidth = false;
        _flagHeight = false;
        _width = 0;
        _height = 0;

        constructor(x, y, rx, ry, resolution) {
            if (typeof ry !== "number" && typeof rx === "number") {
                ry = rx;
            }
            const amount = resolution ? Math.max(resolution, 2) : 4;
            const points = [];
            for (let i = 0; i < amount; i++) {
                points.push(new Anchor());
            }
            super(points, true, true, true);
            for (let prop in proto15) {
                Object.defineProperty(this, prop, proto15[prop]);
            }
            if (typeof rx === "number") {
                this.width = rx * 2;
            }
            if (typeof ry === "number") {
                this.height = ry * 2;
            }
            this._update();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
        }

        _update() {
            if (this._flagVertices || this._flagWidth || this._flagHeight) {
                let length = this.vertices.length;
                if (!this._closed && length > 2) {
                    length -= 1;
                }
                const c = 4 / 3 * Math.tan(Math.PI / (this.vertices.length * 2));
                const radiusX = this._width / 2;
                const radiusY = this._height / 2;
                for (let i = 0; i < this.vertices.length; i++) {
                    const pct = i / length;
                    const theta = pct * TWO_PI;
                    const x = radiusX * cos4(theta);
                    const y = radiusY * sin4(theta);
                    const lx = radiusX * c * cos4(theta - HALF_PI);
                    const ly = radiusY * c * sin4(theta - HALF_PI);
                    const rx = radiusX * c * cos4(theta + HALF_PI);
                    const ry = radiusY * c * sin4(theta + HALF_PI);
                    const v = this.vertices[i];
                    v.command = i === 0 ? Commands.move : Commands.curve;
                    v.set(x, y);
                    v.controls.left.set(lx, ly);
                    v.controls.right.set(rx, ry);
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagWidth = this._flagHeight = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const rx = this.width / 2;
            const ry = this.height / 2;
            const resolution = this.vertices.length;
            const clone = new _Ellipse(0, 0, rx, ry, resolution);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _Ellipse.Properties.length; i++) {
                const k = _Ellipse.Properties[i];
                object[k] = this[k];
            }
            return object;
        }
    };
    var Ellipse = _Ellipse;
    __publicField(Ellipse, "Properties", ["width", "height"]);
    var proto15 = {
        width: {
            enumerable: true,
            get: function () {
                return this._width;
            },
            set: function (v) {
                this._width = v;
                this._flagWidth = true;
            }
        },
        height: {
            enumerable: true,
            get: function () {
                return this._height;
            },
            set: function (v) {
                this._height = v;
                this._flagHeight = true;
            }
        }
    };

    // src/shapes/line.js
    var Line = class extends Path {
        constructor(x1, y1, x2, y2) {
            const points = [
                new Anchor(x1, y1),
                new Anchor(x2, y2)
            ];
            super(points);
            for (let prop in proto16) {
                Object.defineProperty(this, prop, proto16[prop]);
            }
            this.vertices[0].command = Commands.move;
            this.vertices[1].command = Commands.line;
            this.automatic = false;
        }
    };
    var proto16 = {
        left: {
            enumerable: true,
            get: function () {
                return this.vertices[0];
            },
            set: function (v) {
                if (_.isObject(v)) {
                    this.vertices.splice(0, 1, v);
                } else {
                    const error = new TwoError("Two.Line.x argument is not an object.");
                    console.warn(error.name, error.message);
                }
            }
        },
        right: {
            enumerable: true,
            get: function () {
                return this.vertices[1];
            },
            set: function (v) {
                if (_.isObject(v)) {
                    this.vertices.splice(1, 1, v);
                } else {
                    const error = new TwoError("Two.Line.y argument is not an object.");
                    console.warn(error.name, error.message);
                }
            }
        }
    };

    // src/shapes/rounded-rectangle.js
    var _RoundedRectangle = class extends Path {
        _flagWidth = false;
        _flagHeight = false;
        _flagRadius = false;
        _width = 0;
        _height = 0;
        _radius = 12;

        constructor(x, y, width, height, radius) {
            if (typeof radius === "undefined" && typeof width === "number" && typeof height === "number") {
                radius = Math.floor(Math.min(width, height) / 12);
            }
            const points = [];
            for (let i = 0; i < 10; i++) {
                points.push(
                    new Anchor(
                        0,
                        0,
                        0,
                        0,
                        0,
                        0,
                        i === 0 ? Commands.move : Commands.curve
                    )
                );
            }
            super(points);
            for (let prop in proto17) {
                Object.defineProperty(this, prop, proto17[prop]);
            }
            this.closed = true;
            this.automatic = false;
            this._renderer.flagRadius = FlagRadius.bind(this);
            if (typeof width === "number") {
                this.width = width;
            }
            if (typeof height === "number") {
                this.height = height;
            }
            if (typeof radius === "number") {
                this.radius = radius;
            }
            this._update();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
        }

        _update() {
            if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagRadius) {
                const width = this._width;
                const height = this._height;
                let rx, ry;
                if (this._radius instanceof Vector) {
                    rx = this._radius.x;
                    ry = this._radius.y;
                } else {
                    rx = this._radius;
                    ry = this._radius;
                }
                let v;
                let w = width / 2;
                let h = height / 2;
                v = this.vertices[0];
                v.x = -(w - rx);
                v.y = -h;
                v = this.vertices[1];
                v.x = w - rx;
                v.y = -h;
                v.controls.left.clear();
                v.controls.right.x = rx;
                v.controls.right.y = 0;
                v = this.vertices[2];
                v.x = w;
                v.y = -(h - ry);
                v.controls.right.clear();
                v.controls.left.clear();
                v = this.vertices[3];
                v.x = w;
                v.y = h - ry;
                v.controls.left.clear();
                v.controls.right.x = 0;
                v.controls.right.y = ry;
                v = this.vertices[4];
                v.x = w - rx;
                v.y = h;
                v.controls.right.clear();
                v.controls.left.clear();
                v = this.vertices[5];
                v.x = -(w - rx);
                v.y = h;
                v.controls.left.clear();
                v.controls.right.x = -rx;
                v.controls.right.y = 0;
                v = this.vertices[6];
                v.x = -w;
                v.y = h - ry;
                v.controls.left.clear();
                v.controls.right.clear();
                v = this.vertices[7];
                v.x = -w;
                v.y = -(h - ry);
                v.controls.left.clear();
                v.controls.right.x = 0;
                v.controls.right.y = -ry;
                v = this.vertices[8];
                v.x = -(w - rx);
                v.y = -h;
                v.controls.left.clear();
                v.controls.right.clear();
                v = this.vertices[9];
                v.copy(this.vertices[8]);
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagWidth = this._flagHeight = this._flagRadius = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const width = this.width;
            const height = this.height;
            const radius = this.radius;
            const clone = new _RoundedRectangle(0, 0, width, height, radius);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _RoundedRectangle.Properties.length; i++) {
                const k = _RoundedRectangle.Properties[i];
                object[k] = this[k];
            }
            object.radius = typeof this.radius === "number" ? this.radius : this.radius.toObject();
            return object;
        }
    };
    var RoundedRectangle = _RoundedRectangle;
    __publicField(RoundedRectangle, "Properties", ["width", "height", "radius"]);
    var proto17 = {
        width: {
            enumerable: true,
            get: function () {
                return this._width;
            },
            set: function (v) {
                this._width = v;
                this._flagWidth = true;
            }
        },
        height: {
            enumerable: true,
            get: function () {
                return this._height;
            },
            set: function (v) {
                this._height = v;
                this._flagHeight = true;
            }
        },
        radius: {
            enumerable: true,
            get: function () {
                return this._radius;
            },
            set: function (v) {
                if (this._radius instanceof Vector) {
                    this._radius.unbind(Events.Types.change, this._renderer.flagRadius);
                }
                this._radius = v;
                if (this._radius instanceof Vector) {
                    this._radius.bind(Events.Types.change, this._renderer.flagRadius);
                }
                this._flagRadius = true;
            }
        }
    };

    function FlagRadius() {
        this._flagRadius = true;
    }

    // src/text.js
    var canvas2;
    var min4 = Math.min;
    var max4 = Math.max;
    if (root.document) {
        canvas2 = document.createElement("canvas");
    }
    var _Text = class extends Shape {
        _flagValue = true;
        _flagFamily = true;
        _flagSize = true;
        _flagLeading = true;
        _flagAlignment = true;
        _flagBaseline = true;
        _flagStyle = true;
        _flagWeight = true;
        _flagDecoration = true;
        _flagFill = true;
        _flagStroke = true;
        _flagLinewidth = true;
        _flagOpacity = true;
        _flagVisible = true;
        _flagMask = false;
        _flagClip = false;
        _value = "";
        _family = "sans-serif";
        _size = 13;
        _leading = 17;
        _alignment = "center";
        _baseline = "middle";
        _style = "normal";
        _weight = 500;
        _decoration = "none";
        _fill = "#000";
        _stroke = "none";
        _linewidth = 1;
        _opacity = 1;
        _visible = true;
        _mask = null;
        _clip = false;
        _dashes = null;

        constructor(message, x, y, styles) {
            super();
            for (let prop in proto18) {
                Object.defineProperty(this, prop, proto18[prop]);
            }
            this._renderer.type = "text";
            this._renderer.flagFill = FlagFill2.bind(this);
            this._renderer.flagStroke = FlagStroke2.bind(this);
            this.value = message;
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
            this.dashes = [];
            this.dashes.offset = 0;
            if (!_.isObject(styles)) {
                return this;
            }
            for (let i = 0; i < _Text.Properties.length; i++) {
                const property = _Text.Properties[i];
                if (property in styles) {
                    this[property] = styles[property];
                }
            }
        }

        static Measure(text) {
            if (canvas2) {
                const ctx = canvas2.getContext("2d");
                ctx.font = [
                    text._style,
                    text._weight,
                    `${text._size}px/${text._leading}px`,
                    text._family
                ].join(" ");
                const metrics = ctx.measureText(text.value, 0, 0);
                const height = metrics.actualBoundingBoxDescent + metrics.actualBoundingBoxAscent;
                return {
                    width: metrics.width,
                    height
                };
            } else {
                const width = this.value.length * this.size * _Text.Ratio;
                const height = this.leading;
                console.warn("Two.Text: unable to accurately measure text, so using an approximation.");
                return {
                    width,
                    height
                };
            }
        }

        clone(parent) {
            const clone = new _Text(this.value);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            for (let i = 0; i < _Text.Properties.length; i++) {
                const prop = _Text.Properties[i];
                clone[prop] = this[prop];
            }
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            if (parent) {
                parent.add(clone);
            }
            return clone._update();
        }

        toObject() {
            const result = {
                translation: this.translation.toObject(),
                rotation: this.rotation,
                scale: this.scale
            };
            if (this.matrix.manual) {
                result.matrix = this.matrix.toObject();
            }
            for (let i = 0; i < _Text.Properties.length; i++) {
                const prop = _Text.Properties[i];
                result[prop] = this[prop];
            }
            return result;
        }

        noFill() {
            this.fill = "none";
            return this;
        }

        noStroke() {
            this.stroke = "none";
            this.linewidth = 0;
            return this;
        }

        getBoundingClientRect(shallow) {
            let matrix;
            let left, right, top, bottom;
            this._update(true);
            matrix = shallow ? this.matrix : this.worldMatrix;
            const {width, height} = _Text.Measure(this);
            const border = (this._linewidth || 0) / 2;
            switch (this.alignment) {
                case "left":
                    left = -border;
                    right = width + border;
                    break;
                case "right":
                    left = -(width + border);
                    right = border;
                    break;
                default:
                    left = -(width / 2 + border);
                    right = width / 2 + border;
            }
            switch (this.baseline) {
                case "middle":
                    top = -(height / 2 + border);
                    bottom = height / 2 + border;
                    break;
                default:
                    top = -(height + border);
                    bottom = border;
            }
            const [ax, ay] = matrix.multiply(left, top);
            const [bx, by] = matrix.multiply(left, bottom);
            const [cx, cy] = matrix.multiply(right, top);
            const [dx, dy] = matrix.multiply(right, bottom);
            top = min4(ay, by, cy, dy);
            left = min4(ax, bx, cx, dx);
            right = max4(ax, bx, cx, dx);
            bottom = max4(ay, by, cy, dy);
            return {
                top,
                left,
                right,
                bottom,
                width: right - left,
                height: bottom - top
            };
        }

        flagReset() {
            super.flagReset.call(this);
            this._flagValue = this._flagFamily = this._flagSize = this._flagLeading = this._flagAlignment = this._flagFill = this._flagStroke = this._flagLinewidth = this._flagOpacity = this._flagVisible = this._flagClip = this._flagDecoration = this._flagClassName = this._flagBaseline = this._flagWeight = this._flagStyle = false;
            return this;
        }
    };
    var Text = _Text;
    __publicField(Text, "Ratio", 0.6);
    __publicField(Text, "Properties", [
        "value",
        "family",
        "size",
        "leading",
        "alignment",
        "linewidth",
        "style",
        "weight",
        "decoration",
        "baseline",
        "opacity",
        "visible",
        "fill",
        "stroke"
    ]);
    var proto18 = {
        value: {
            enumerable: true,
            get: function () {
                return this._value;
            },
            set: function (v) {
                this._value = v;
                this._flagValue = true;
            }
        },
        family: {
            enumerable: true,
            get: function () {
                return this._family;
            },
            set: function (v) {
                this._family = v;
                this._flagFamily = true;
            }
        },
        size: {
            enumerable: true,
            get: function () {
                return this._size;
            },
            set: function (v) {
                this._size = v;
                this._flagSize = true;
            }
        },
        leading: {
            enumerable: true,
            get: function () {
                return this._leading;
            },
            set: function (v) {
                this._leading = v;
                this._flagLeading = true;
            }
        },
        alignment: {
            enumerable: true,
            get: function () {
                return this._alignment;
            },
            set: function (v) {
                this._alignment = v;
                this._flagAlignment = true;
            }
        },
        linewidth: {
            enumerable: true,
            get: function () {
                return this._linewidth;
            },
            set: function (v) {
                this._linewidth = v;
                this._flagLinewidth = true;
            }
        },
        style: {
            enumerable: true,
            get: function () {
                return this._style;
            },
            set: function (v) {
                this._style = v;
                this._flagStyle = true;
            }
        },
        weight: {
            enumerable: true,
            get: function () {
                return this._weight;
            },
            set: function (v) {
                this._weight = v;
                this._flagWeight = true;
            }
        },
        decoration: {
            enumerable: true,
            get: function () {
                return this._decoration;
            },
            set: function (v) {
                this._decoration = v;
                this._flagDecoration = true;
            }
        },
        baseline: {
            enumerable: true,
            get: function () {
                return this._baseline;
            },
            set: function (v) {
                this._baseline = v;
                this._flagBaseline = true;
            }
        },
        opacity: {
            enumerable: true,
            get: function () {
                return this._opacity;
            },
            set: function (v) {
                this._opacity = v;
                this._flagOpacity = true;
            }
        },
        visible: {
            enumerable: true,
            get: function () {
                return this._visible;
            },
            set: function (v) {
                this._visible = v;
                this._flagVisible = true;
            }
        },
        fill: {
            enumerable: true,
            get: function () {
                return this._fill;
            },
            set: function (f) {
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.unbind(Events.Types.change, this._renderer.flagFill);
                }
                this._fill = f;
                this._flagFill = true;
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.bind(Events.Types.change, this._renderer.flagFill);
                }
            }
        },
        stroke: {
            enumerable: true,
            get: function () {
                return this._stroke;
            },
            set: function (f) {
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.unbind(Events.Types.change, this._renderer.flagStroke);
                }
                this._stroke = f;
                this._flagStroke = true;
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.bind(Events.Types.change, this._renderer.flagStroke);
                }
            }
        },
        mask: {
            enumerable: true,
            get: function () {
                return this._mask;
            },
            set: function (v) {
                this._mask = v;
                this._flagMask = true;
                if (_.isObject(v) && !v.clip) {
                    v.clip = true;
                }
            }
        },
        clip: {
            enumerable: true,
            get: function () {
                return this._clip;
            },
            set: function (v) {
                this._clip = v;
                this._flagClip = true;
            }
        },
        dashes: {
            enumerable: true,
            get: function () {
                return this._dashes;
            },
            set: function (v) {
                if (typeof v.offset !== "number") {
                    v.offset = this.dashes && this._dashes.offset || 0;
                }
                this._dashes = v;
            }
        }
    };

    function FlagFill2() {
        this._flagFill = true;
    }

    function FlagStroke2() {
        this._flagStroke = true;
    }

    // src/utils/interpret-svg.js
    var regex2 = {
        path: /[+-]?(?:\d*\.\d+|\d+)(?:[eE][+-]\d+)?/g,
        cssBackgroundImage: /url\(['"]?#([\w\d-_]*)['"]?\)/i,
        unitSuffix: /[a-zA-Z%]*/i
    };
    var alignments = {
        start: "left",
        middle: "center",
        end: "right"
    };
    var reservedAttributesToRemove = ["id", "class", "transform", "xmlns", "viewBox"];
    var overwriteAttrs = ["x", "y", "width", "height", "href", "xlink:href"];

    function getAlignment(anchor2) {
        return alignments[anchor2];
    }

    function getBaseline(node) {
        const a = node.getAttribute("dominant-baseline");
        const b = node.getAttribute("alignment-baseline");
        return a || b;
    }

    function getTagName(tag) {
        return tag.replace(/svg:/ig, "").toLowerCase();
    }

    function applyTransformsToVector(transforms, vector2) {
        vector2.x += transforms.translateX;
        vector2.y += transforms.translateY;
        vector2.x *= transforms.scaleX;
        vector2.y *= transforms.scaleY;
        if (transforms.rotation !== 0) {
            const l = vector2.length();
            vector2.x = l * Math.cos(transforms.rotation);
            vector2.y = l * Math.sin(transforms.rotation);
        }
    }

    function extractCSSText(text, styles) {
        if (!styles) {
            styles = {};
        }
        const commands = text.split(";");
        for (let i = 0; i < commands.length; i++) {
            const command = commands[i].split(":");
            const name = command[0];
            const value = command[1];
            if (typeof name === "undefined" || typeof value === "undefined") {
                continue;
            }
            styles[name] = value.replace(/\s/, "");
        }
        return styles;
    }

    function getSvgStyles(node) {
        const styles = {};
        const attributes = getSvgAttributes(node);
        const length = Math.max(attributes.length, node.style.length);
        for (let i = 0; i < length; i++) {
            const command = node.style[i];
            const attribute = attributes[i];
            if (command) {
                styles[command] = node.style[command];
            }
            if (attribute) {
                styles[attribute] = node.getAttribute(attribute);
            }
        }
        return styles;
    }

    function getSvgAttributes(node) {
        const attributes = node.getAttributeNames();
        for (let i = 0; i < reservedAttributesToRemove.length; i++) {
            const keyword = reservedAttributesToRemove[i];
            const index = Array.prototype.indexOf.call(attributes, keyword);
            if (index >= 0) {
                attributes.splice(index, 1);
            }
        }
        return attributes;
    }

    function applySvgViewBox(node, value) {
        const elements = value.split(/[\s,]/);
        const x = -parseFloat(elements[0]);
        const y = -parseFloat(elements[1]);
        const width = parseFloat(elements[2]);
        const height = parseFloat(elements[3]);
        if (x && y) {
            for (let i = 0; i < node.children.length; i++) {
                const child = node.children[i];
                if ("translation" in child) {
                    child.translation.add(x, y);
                } else if ("x" in child) {
                    child.x = x;
                } else if ("y" in child) {
                    child.y = y;
                }
            }
        }
        const xExists = typeof node.x === "number";
        const yExists = typeof node.y === "number";
        const widthExists = typeof node.width === "number";
        const heightExists = typeof node.height === "number";
        if (xExists) {
            node.translation.x += node.x;
        }
        if (yExists) {
            node.translation.y += node.y;
        }
        if (widthExists || heightExists) {
            node.scale = new Vector(1, 1);
        }
        if (widthExists) {
            node.scale.x = node.width / width;
        }
        if (heightExists) {
            node.scale.y = node.height / height;
        }
        node.mask = new Rectangle(0, 0, width, height);
        node.mask.origin.set(-width / 2, -height / 2);
        return node;
    }

    function applySvgAttributes(node, elem, parentStyles) {
        const styles = {}, attributes = {}, extracted = {};
        let i, m, key, value, prop, attr;
        let transforms, x, y;
        let id, scene, ref, tagName;
        let ca, cb, cc, error;
        if (node === null) {
            return styles;
        }
        if (root.getComputedStyle) {
            const computedStyles = root.getComputedStyle(node);
            i = computedStyles.length;
            while (i--) {
                key = computedStyles[i];
                value = computedStyles[key];
                if (typeof value !== "undefined") {
                    styles[key] = value;
                }
            }
        }
        for (i = 0; i < node.attributes.length; i++) {
            attr = node.attributes[i];
            if (/style/i.test(attr.nodeName)) {
                extractCSSText(attr.value, extracted);
            } else {
                attributes[attr.nodeName] = attr.value;
            }
        }
        if (typeof styles.opacity !== "undefined") {
            styles["stroke-opacity"] = styles.opacity;
            styles["fill-opacity"] = styles.opacity;
            delete styles.opacity;
        }
        if (parentStyles) {
            _.defaults(styles, parentStyles);
        }
        _.extend(styles, extracted, attributes);
        styles.visible = !(typeof styles.display === "undefined" && /none/i.test(styles.display)) || typeof styles.visibility === "undefined" && /hidden/i.test(styles.visibility);
        for (key in styles) {
            value = styles[key];
            switch (key) {
                case "gradientTransform":
                    if (/none/i.test(value))
                        break;
                    m = node.gradientTransform && node.gradientTransform.baseVal && node.gradientTransform.baseVal.length > 0 ? node.gradientTransform.baseVal[0].matrix : node.getCTM ? node.getCTM() : null;
                    if (m === null)
                        break;
                    transforms = decomposeMatrix(m);
                    switch (elem._renderer.type) {
                        case "linear-gradient":
                            applyTransformsToVector(transforms, elem.left);
                            applyTransformsToVector(transforms, elem.right);
                            break;
                        case "radial-gradient":
                            elem.center.x += transforms.translateX;
                            elem.center.y += transforms.translateY;
                            elem.focal.x += transforms.translateX;
                            elem.focal.y += transforms.translateY;
                            elem.radius *= Math.max(transforms.scaleX, transforms.scaleY);
                            break;
                    }
                    break;
                case "transform":
                    if (/none/i.test(value))
                        break;
                    m = node.transform && node.transform.baseVal && node.transform.baseVal.length > 0 ? node.transform.baseVal[0].matrix : node.getCTM ? node.getCTM() : null;
                    if (m === null)
                        break;
                    if (Constants.AutoCalculateImportedMatrices) {
                        transforms = decomposeMatrix(m);
                        elem.translation.set(transforms.translateX, transforms.translateY);
                        elem.rotation = Math.PI * (transforms.rotation / 180);
                        elem.scale = new Vector(transforms.scaleX, transforms.scaleY);
                        x = parseFloat((styles.x + "").replace("px"));
                        y = parseFloat((styles.y + "").replace("px"));
                        if (x) {
                            elem.translation.x = x;
                        }
                        if (y) {
                            elem.translation.y = y;
                        }
                    } else {
                        m = node.getCTM();
                        elem._matrix.manual = true;
                        elem._matrix.set(m.a, m.b, m.c, m.d, m.e, m.f);
                    }
                    break;
                case "visible":
                    if (elem instanceof Group) {
                        elem._visible = value;
                        break;
                    }
                    elem.visible = value;
                    break;
                case "stroke-linecap":
                    if (elem instanceof Group) {
                        elem._cap = value;
                        break;
                    }
                    elem.cap = value;
                    break;
                case "stroke-linejoin":
                    if (elem instanceof Group) {
                        elem._join = value;
                        break;
                    }
                    elem.join = value;
                    break;
                case "stroke-miterlimit":
                    if (elem instanceof Group) {
                        elem._miter = value;
                        break;
                    }
                    elem.miter = value;
                    break;
                case "stroke-width":
                    if (elem instanceof Group) {
                        elem._linewidth = parseFloat(value);
                        break;
                    }
                    elem.linewidth = parseFloat(value);
                    break;
                case "opacity":
                case "stroke-opacity":
                case "fill-opacity":
                    if (elem instanceof Group) {
                        elem._opacity = parseFloat(value);
                        break;
                    }
                    elem.opacity = parseFloat(value);
                    break;
                case "clip-path":
                    if (regex2.cssBackgroundImage.test(value)) {
                        id = value.replace(regex2.cssBackgroundImage, "$1");
                        if (read.defs.current && read.defs.current.contains(id)) {
                            ref = read.defs.current.get(id);
                            if (ref && ref.childNodes.length > 0) {
                                ref = ref.childNodes[0];
                                tagName = getTagName(ref.nodeName);
                                elem.mask = read[tagName].call(this, ref, {});
                                switch (elem._renderer.type) {
                                    case "text":
                                    case "path":
                                        elem.position.add(elem.mask.position);
                                        elem.mask.position.clear();
                                        break;
                                }
                            }
                        }
                    }
                    break;
                case "fill":
                case "stroke":
                    prop = (elem instanceof Group ? "_" : "") + key;
                    if (regex2.cssBackgroundImage.test(value)) {
                        id = value.replace(regex2.cssBackgroundImage, "$1");
                        if (read.defs.current && read.defs.current.contains(id)) {
                            ref = read.defs.current.get(id);
                            if (!ref.object) {
                                tagName = getTagName(ref.nodeName);
                                ref.object = read[tagName].call(this, ref, {});
                            }
                            ref = ref.object;
                        } else {
                            scene = getScene(this);
                            ref = scene.getById(id);
                        }
                        elem[prop] = ref;
                    } else {
                        elem[prop] = value;
                    }
                    break;
                case "id":
                    elem.id = value;
                    break;
                case "class":
                case "className":
                    elem.classList = value.split(" ");
                    elem._flagClassName = true;
                    break;
                case "x":
                case "y":
                    ca = elem instanceof Gradient;
                    cb = elem instanceof LinearGradient;
                    cc = elem instanceof RadialGradient;
                    if (ca || cb || cc) {
                        break;
                    }
                    if (value.match("[a-z%]$") && !value.endsWith("px")) {
                        error = new TwoError(
                            "only pixel values are supported with the " + key + " attribute."
                        );
                        console.warn(error.name, error.message);
                    }
                    elem.translation[key] = parseFloat(value);
                    break;
                case "font-family":
                    if (elem instanceof Text) {
                        elem.family = value;
                    }
                    break;
                case "font-size":
                    if (elem instanceof Text) {
                        elem.size = value;
                    }
                    break;
                case "font-weight":
                    if (elem instanceof Text) {
                        elem.weight = value;
                    }
                    break;
                case "font-style":
                    if (elem instanceof Text) {
                        elem.style = value;
                    }
                    break;
                case "text-decoration":
                    if (elem instanceof Text) {
                        elem.decoration = value;
                    }
                    break;
                case "line-height":
                    if (elem instanceof Text) {
                        elem.leading = value;
                    }
                    break;
            }
        }
        if (Object.keys(node.dataset).length)
            elem.dataset = node.dataset;
        return styles;
    }

    function updateDefsCache(node, defsCache) {
        for (let i = 0, l = node.childNodes.length; i < l; i++) {
            const n = node.childNodes[i];
            if (!n.id)
                continue;
            const tagName = getTagName(node.nodeName);
            if (tagName === "#text")
                continue;
            defsCache.add(n.id, n);
        }
    }

    function getScene(node) {
        while (node.parent) {
            node = node.parent;
        }
        return node.scene;
    }

    var read = {
        svg: function (node) {
            const defs = read.defs.current = new Registry();
            const elements = node.getElementsByTagName("defs");
            for (let i = 0; i < elements.length; i++) {
                updateDefsCache(elements[i], defs);
            }
            const svg2 = read.g.call(this, node);
            const viewBox = node.getAttribute("viewBox");
            const x = node.getAttribute("x");
            const y = node.getAttribute("y");
            const width = node.getAttribute("width");
            const height = node.getAttribute("height");
            svg2.defs = defs;
            const viewBoxExists = viewBox !== null;
            const xExists = x !== null;
            const yExists = y !== null;
            const widthExists = width !== null;
            const heightExists = height !== null;
            if (xExists) {
                svg2.x = parseFloat(x.replace(regex2.unitSuffix, ""));
            }
            if (yExists) {
                svg2.y = parseFloat(y.replace(regex2.unitSuffix, ""));
            }
            if (widthExists) {
                svg2.width = parseFloat(width.replace(regex2.unitSuffix, ""));
            }
            if (heightExists) {
                svg2.height = parseFloat(height.replace(regex2.unitSuffix, ""));
            }
            if (viewBoxExists) {
                applySvgViewBox(svg2, viewBox);
            }
            delete read.defs.current;
            return svg2;
        },
        defs: function (node) {
            return null;
        },
        use: function (node, styles) {
            let error;
            const href = node.getAttribute("href") || node.getAttribute("xlink:href");
            if (!href) {
                error = new TwoError("encountered <use /> with no href.");
                console.warn(error.name, error.message);
                return null;
            }
            const id = href.slice(1);
            if (!read.defs.current.contains(id)) {
                error = new TwoError(
                    "unable to find element for reference " + href + "."
                );
                console.warn(error.name, error.message);
                return null;
            }
            const template = read.defs.current.get(id);
            const fullNode = template.cloneNode(true);
            for (let i = 0; i < node.attributes.length; i++) {
                const attr = node.attributes[i];
                const ca = overwriteAttrs.includes(attr.nodeName);
                const cb = !fullNode.hasAttribute(attr.nodeName);
                if (ca || cb) {
                    fullNode.setAttribute(attr.nodeName, attr.value);
                }
            }
            const tagName = getTagName(fullNode.nodeName);
            return read[tagName].call(this, fullNode, styles);
        },
        g: function (node, parentStyles) {
            const group = new Group();
            applySvgAttributes.call(this, node, group, parentStyles);
            this.add(group);
            const styles = getSvgStyles.call(this, node);
            for (let i = 0, l = node.childNodes.length; i < l; i++) {
                const n = node.childNodes[i];
                const tag = n.nodeName;
                if (!tag)
                    return;
                const tagName = getTagName(tag);
                if (tagName in read) {
                    const o = read[tagName].call(group, n, styles);
                    if (!!o && !o.parent) {
                        group.add(o);
                    }
                }
            }
            return group;
        },
        polygon: function (node, parentStyles) {
            let points;
            if (typeof node === "string") {
                points = node;
            } else {
                points = node.getAttribute("points");
            }
            const verts = [];
            points.replace(/(-?[\d.eE-]+)[,|\s](-?[\d.eE-]+)/g, function (match, p1, p2) {
                verts.push(new Anchor(parseFloat(p1), parseFloat(p2)));
            });
            const poly = new Path(verts, true).noStroke();
            poly.fill = "black";
            applySvgAttributes.call(this, node, poly, parentStyles);
            return poly;
        },
        polyline: function (node, parentStyles) {
            const poly = read.polygon.call(this, node, parentStyles);
            poly.closed = false;
            return poly;
        },
        path: function (node, parentStyles) {
            let path;
            if (typeof node === "string") {
                path = node;
                node = null;
            } else {
                path = node.getAttribute("d");
            }
            let points = [];
            let closed2 = false, relative = false;
            if (path) {
                let coord = new Anchor();
                let control, coords;
                let commands = path.match(/[a-df-z][^a-df-z]*/ig);
                const last = commands.length - 1;
                _.each(commands.slice(0), function (command, i) {
                    const items = command.slice(1).trim().match(regex2.path);
                    const type = command[0];
                    const lower = type.toLowerCase();
                    let bin, j, l, ct, times;
                    const result = [];
                    if (i === 0) {
                        commands = [];
                    }
                    switch (lower) {
                        case "h":
                        case "v":
                            if (items.length > 1) {
                                bin = 1;
                            }
                            break;
                        case "m":
                        case "l":
                        case "t":
                            if (items.length > 2) {
                                bin = 2;
                            }
                            break;
                        case "s":
                        case "q":
                            if (items.length > 4) {
                                bin = 4;
                            }
                            break;
                        case "c":
                            if (items.length > 6) {
                                bin = 6;
                            }
                            break;
                        case "a":
                            if (items.length > 7) {
                                bin = 7;
                            }
                            break;
                    }
                    if (bin) {
                        for (j = 0, l = items.length, times = 0; j < l; j += bin) {
                            ct = type;
                            if (times > 0) {
                                switch (type) {
                                    case "m":
                                        ct = "l";
                                        break;
                                    case "M":
                                        ct = "L";
                                        break;
                                }
                            }
                            result.push(ct + items.slice(j, j + bin).join(" "));
                            times++;
                        }
                        commands = Array.prototype.concat.apply(commands, result);
                    } else {
                        commands.push(command);
                    }
                });
                _.each(commands, function (command, i) {
                    let result, x, y;
                    const type = command[0];
                    const lower = type.toLowerCase();
                    coords = command.slice(1).trim().match(regex2.path);
                    relative = type === lower;
                    let x1, y1, x2, y2, x3, y3, x4, y4, reflection;
                    let a, b;
                    let anchor2, rx, ry, xAxisRotation, largeArcFlag, sweepFlag;
                    switch (lower) {
                        case "z":
                            if (i >= last) {
                                closed2 = true;
                            } else {
                                x = coord.x;
                                y = coord.y;
                                result = new Anchor(
                                    x,
                                    y,
                                    void 0,
                                    void 0,
                                    void 0,
                                    void 0,
                                    Commands.close
                                );
                                for (let j = points.length - 1; j >= 0; j--) {
                                    const point = points[j];
                                    if (/m/i.test(point.command)) {
                                        coord = point;
                                        break;
                                    }
                                }
                            }
                            break;
                        case "m":
                        case "l":
                            control = void 0;
                            x = parseFloat(coords[0]);
                            y = parseFloat(coords[1]);
                            result = new Anchor(
                                x,
                                y,
                                void 0,
                                void 0,
                                void 0,
                                void 0,
                                /m/i.test(lower) ? Commands.move : Commands.line
                            );
                            if (relative) {
                                result.addSelf(coord);
                            }
                            coord = result;
                            break;
                        case "h":
                        case "v":
                            a = /h/i.test(lower) ? "x" : "y";
                            b = /x/i.test(a) ? "y" : "x";
                            result = new Anchor(
                                void 0,
                                void 0,
                                void 0,
                                void 0,
                                void 0,
                                void 0,
                                Commands.line
                            );
                            result[a] = parseFloat(coords[0]);
                            result[b] = coord[b];
                            if (relative) {
                                result[a] += coord[a];
                            }
                            coord = result;
                            break;
                        case "c":
                        case "s":
                            x1 = coord.x;
                            y1 = coord.y;
                            if (!control) {
                                control = new Vector();
                            }
                            if (/c/i.test(lower)) {
                                x2 = parseFloat(coords[0]);
                                y2 = parseFloat(coords[1]);
                                x3 = parseFloat(coords[2]);
                                y3 = parseFloat(coords[3]);
                                x4 = parseFloat(coords[4]);
                                y4 = parseFloat(coords[5]);
                            } else {
                                reflection = getReflection(coord, control, relative);
                                x2 = reflection.x;
                                y2 = reflection.y;
                                x3 = parseFloat(coords[0]);
                                y3 = parseFloat(coords[1]);
                                x4 = parseFloat(coords[2]);
                                y4 = parseFloat(coords[3]);
                            }
                            if (relative) {
                                x2 += x1;
                                y2 += y1;
                                x3 += x1;
                                y3 += y1;
                                x4 += x1;
                                y4 += y1;
                            }
                            coord.controls.right.set(x2 - coord.x, y2 - coord.y);
                            result = new Anchor(
                                x4,
                                y4,
                                x3 - x4,
                                y3 - y4,
                                void 0,
                                void 0,
                                Commands.curve
                            );
                            coord = result;
                            control = result.controls.left;
                            break;
                        case "t":
                        case "q":
                            x1 = coord.x;
                            y1 = coord.y;
                            if (!control) {
                                control = new Vector();
                            }
                            if (/q/i.test(lower)) {
                                x2 = parseFloat(coords[0]);
                                y2 = parseFloat(coords[1]);
                                x3 = parseFloat(coords[0]);
                                y3 = parseFloat(coords[1]);
                                x4 = parseFloat(coords[2]);
                                y4 = parseFloat(coords[3]);
                            } else {
                                reflection = getReflection(coord, control, relative);
                                x2 = reflection.x;
                                y2 = reflection.y;
                                x3 = reflection.x;
                                y3 = reflection.y;
                                x4 = parseFloat(coords[0]);
                                y4 = parseFloat(coords[1]);
                            }
                            if (relative) {
                                x2 += x1;
                                y2 += y1;
                                x3 += x1;
                                y3 += y1;
                                x4 += x1;
                                y4 += y1;
                            }
                            coord.controls.right.set(
                                (x2 - coord.x) * 0.33,
                                (y2 - coord.y) * 0.33
                            );
                            result = new Anchor(
                                x4,
                                y4,
                                x3 - x4,
                                y3 - y4,
                                void 0,
                                void 0,
                                Commands.curve
                            );
                            coord = result;
                            control = result.controls.left;
                            break;
                        case "a":
                            x1 = coord.x;
                            y1 = coord.y;
                            rx = parseFloat(coords[0]);
                            ry = parseFloat(coords[1]);
                            xAxisRotation = parseFloat(coords[2]);
                            largeArcFlag = parseFloat(coords[3]);
                            sweepFlag = parseFloat(coords[4]);
                            x4 = parseFloat(coords[5]);
                            y4 = parseFloat(coords[6]);
                            if (relative) {
                                x4 += x1;
                                y4 += y1;
                            }
                            anchor2 = new Anchor(x4, y4);
                            anchor2.command = Commands.arc;
                            anchor2.rx = rx;
                            anchor2.ry = ry;
                            anchor2.xAxisRotation = xAxisRotation;
                            anchor2.largeArcFlag = largeArcFlag;
                            anchor2.sweepFlag = sweepFlag;
                            result = anchor2;
                            coord = anchor2;
                            control = void 0;
                            break;
                    }
                    if (result) {
                        if (Array.isArray(result)) {
                            points = points.concat(result);
                        } else {
                            points.push(result);
                        }
                    }
                });
            }
            path = new Path(points, closed2, void 0, true).noStroke();
            path.fill = "black";
            const rect = path.getBoundingClientRect(true);
            rect.centroid = {
                x: rect.left + rect.width / 2,
                y: rect.top + rect.height / 2
            };
            _.each(path.vertices, function (v) {
                v.subSelf(rect.centroid);
            });
            applySvgAttributes.call(this, node, path, parentStyles);
            path.translation.addSelf(rect.centroid);
            return path;
        },
        circle: function (node, parentStyles) {
            const x = parseFloat(node.getAttribute("cx"));
            const y = parseFloat(node.getAttribute("cy"));
            const r = parseFloat(node.getAttribute("r"));
            const circle = new Circle(0, 0, r).noStroke();
            circle.fill = "black";
            applySvgAttributes.call(this, node, circle, parentStyles);
            circle.translation.x = x;
            circle.translation.y = y;
            return circle;
        },
        ellipse: function (node, parentStyles) {
            const x = parseFloat(node.getAttribute("cx"));
            const y = parseFloat(node.getAttribute("cy"));
            const width = parseFloat(node.getAttribute("rx"));
            const height = parseFloat(node.getAttribute("ry"));
            const ellipse = new Ellipse(0, 0, width, height).noStroke();
            ellipse.fill = "black";
            applySvgAttributes.call(this, node, ellipse, parentStyles);
            ellipse.translation.x = x;
            ellipse.translation.y = y;
            return ellipse;
        },
        rect: function (node, parentStyles) {
            const rx = parseFloat(node.getAttribute("rx"));
            const ry = parseFloat(node.getAttribute("ry"));
            if (!_.isNaN(rx) || !_.isNaN(ry)) {
                return read["rounded-rect"](node);
            }
            const width = parseFloat(node.getAttribute("width"));
            const height = parseFloat(node.getAttribute("height"));
            const w2 = width / 2;
            const h2 = height / 2;
            const rect = new Rectangle(0, 0, width, height).noStroke();
            rect.fill = "black";
            applySvgAttributes.call(this, node, rect, parentStyles);
            rect.translation.x += w2;
            rect.translation.y += h2;
            return rect;
        },
        "rounded-rect": function (node, parentStyles) {
            const rx = parseFloat(node.getAttribute("rx")) || 0;
            const ry = parseFloat(node.getAttribute("ry")) || 0;
            const width = parseFloat(node.getAttribute("width"));
            const height = parseFloat(node.getAttribute("height"));
            const w2 = width / 2;
            const h2 = height / 2;
            const radius = new Vector(rx, ry);
            const rect = new RoundedRectangle(0, 0, width, height, radius).noStroke();
            rect.fill = "black";
            applySvgAttributes.call(this, node, rect, parentStyles);
            rect.translation.x += w2;
            rect.translation.y += h2;
            return rect;
        },
        line: function (node, parentStyles) {
            const x1 = parseFloat(node.getAttribute("x1"));
            const y1 = parseFloat(node.getAttribute("y1"));
            const x2 = parseFloat(node.getAttribute("x2"));
            const y2 = parseFloat(node.getAttribute("y2"));
            const line = new Line(x1, y1, x2, y2).noFill();
            applySvgAttributes.call(this, node, line, parentStyles);
            return line;
        },
        lineargradient: function (node, parentStyles) {
            let units = node.getAttribute("gradientUnits");
            let spread = node.getAttribute("spreadMethod");
            if (!units) {
                units = "objectBoundingBox";
            }
            if (!spread) {
                spread = "pad";
            }
            let x1 = parseFloat(node.getAttribute("x1") || 0);
            let y1 = parseFloat(node.getAttribute("y1") || 0);
            let x2 = parseFloat(node.getAttribute("x2") || 0);
            let y2 = parseFloat(node.getAttribute("y2") || 0);
            const ox = (x2 + x1) / 2;
            const oy = (y2 + y1) / 2;
            if (/userSpaceOnUse/i.test(units)) {
                x1 -= ox;
                y1 -= oy;
                x2 -= ox;
                y2 -= oy;
            }
            const stops = [];
            for (let i = 0; i < node.children.length; i++) {
                const child = node.children[i];
                let offset = child.getAttribute("offset");
                if (/%/ig.test(offset)) {
                    offset = parseFloat(offset.replace(/%/ig, "")) / 100;
                }
                offset = parseFloat(offset);
                let color = child.getAttribute("stop-color");
                let opacity = child.getAttribute("stop-opacity");
                let style = child.getAttribute("style");
                let matches;
                if (color === null) {
                    matches = style ? style.match(/stop-color:\s?([#a-fA-F0-9]*)/) : false;
                    color = matches && matches.length > 1 ? matches[1] : void 0;
                }
                if (opacity === null) {
                    matches = style ? style.match(/stop-opacity:\s?([0-9.-]*)/) : false;
                    opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;
                } else {
                    opacity = parseFloat(opacity);
                }
                stops.push(new Stop(offset, color, opacity));
            }
            const gradient = new LinearGradient(x1, y1, x2, y2, stops);
            gradient.spread = spread;
            gradient.units = units;
            applySvgAttributes.call(this, node, gradient, parentStyles);
            return gradient;
        },
        radialgradient: function (node, parentStyles) {
            let units = node.getAttribute("gradientUnits");
            let spread = node.getAttribute("spreadMethod");
            if (!units) {
                units = "objectBoundingBox";
            }
            if (!spread) {
                spread = "pad";
            }
            let cx = parseFloat(node.getAttribute("cx")) || 0;
            let cy = parseFloat(node.getAttribute("cy")) || 0;
            let r = parseFloat(node.getAttribute("r"));
            let fx = parseFloat(node.getAttribute("fx"));
            let fy = parseFloat(node.getAttribute("fy"));
            if (_.isNaN(fx)) {
                fx = cx;
            }
            if (_.isNaN(fy)) {
                fy = cy;
            }
            const ox = Math.abs(cx + fx) / 2;
            const oy = Math.abs(cy + fy) / 2;
            if (/userSpaceOnUse/i.test(units)) {
                cx -= ox;
                cy -= oy;
                fx -= ox;
                fy -= oy;
            }
            const stops = [];
            for (let i = 0; i < node.children.length; i++) {
                const child = node.children[i];
                let offset = child.getAttribute("offset");
                if (/%/ig.test(offset)) {
                    offset = parseFloat(offset.replace(/%/ig, "")) / 100;
                }
                offset = parseFloat(offset);
                let color = child.getAttribute("stop-color");
                let opacity = child.getAttribute("stop-opacity");
                let style = child.getAttribute("style");
                let matches;
                if (color === null) {
                    matches = style ? style.match(/stop-color:\s?([#a-fA-F0-9]*)/) : false;
                    color = matches && matches.length > 1 ? matches[1] : void 0;
                }
                if (opacity === null) {
                    matches = style ? style.match(/stop-opacity:\s?([0-9.-]*)/) : false;
                    opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;
                } else {
                    opacity = parseFloat(opacity);
                }
                stops.push(new Stop(offset, color, opacity));
            }
            const gradient = new RadialGradient(cx, cy, r, stops, fx, fy);
            gradient.spread = spread;
            gradient.units = units;
            applySvgAttributes.call(this, node, gradient, parentStyles);
            return gradient;
        },
        text: function (node, parentStyles) {
            const alignment = getAlignment(node.getAttribute("text-anchor")) || "left";
            const baseline = getBaseline(node) || "baseline";
            const message = node.textContent;
            const text = new Text(message);
            applySvgAttributes.call(this, node, text, parentStyles);
            text.alignment = alignment;
            text.baseline = baseline;
            return text;
        },
        clippath: function (node, parentStyles) {
            if (read.defs.current && !read.defs.current.contains(node.id)) {
                read.defs.current.add(node.id, node);
            }
            return null;
        },
        image: function (node, parentStyles) {
            let error;
            const href = node.getAttribute("href") || node.getAttribute("xlink:href");
            if (!href) {
                error = new TwoError("encountered <image /> with no href.");
                console.warn(error.name, error.message);
                return null;
            }
            const x = parseFloat(node.getAttribute("x")) || 0;
            const y = parseFloat(node.getAttribute("y")) || 0;
            const width = parseFloat(node.getAttribute("width"));
            const height = parseFloat(node.getAttribute("height"));
            const sprite = new Sprite(href, x, y);
            if (!_.isNaN(width)) {
                sprite.width = width;
            }
            if (!_.isNaN(height)) {
                sprite.height = height;
            }
            applySvgAttributes.call(this, node, sprite, parentStyles);
            return sprite;
        }
    };

    // src/utils/xhr.js
    function xhr(path, callback) {
        const xhr2 = new XMLHttpRequest();
        xhr2.open("GET", path);
        xhr2.onreadystatechange = function () {
            if (xhr2.readyState === 4 && xhr2.status === 200) {
                callback(xhr2.responseText);
            }
        };
        xhr2.send();
        return xhr2;
    }

    // src/effects/image-sequence.js
    var _ImageSequence = class extends Rectangle {
        _flagTextures = false;
        _flagFrameRate = false;
        _flagIndex = false;
        _amount = 1;
        _duration = 0;
        _index = 0;
        _startTime = 0;
        _playing = false;
        _firstFrame = 0;
        _lastFrame = 0;
        _loop = true;
        _textures = null;
        _frameRate = 0;
        _origin = null;

        constructor(paths, ox, oy, frameRate) {
            super(ox, oy, 0, 0);
            for (let prop in proto19) {
                Object.defineProperty(this, prop, proto19[prop]);
            }
            this._renderer.flagTextures = FlagTextures.bind(this);
            this._renderer.bindTextures = BindTextures.bind(this);
            this._renderer.unbindTextures = UnbindTextures.bind(this);
            this.noStroke();
            this.noFill();
            if (Array.isArray(paths)) {
                this.textures = paths.map(GenerateTexture.bind(this));
            } else {
                this.textures = [GenerateTexture(paths)];
            }
            this.origin = new Vector();
            this._update();
            if (typeof frameRate === "number") {
                this.frameRate = frameRate;
            } else {
                this.frameRate = _ImageSequence.DefaultFrameRate;
            }
            this.index = 0;
        }

        play(firstFrame, lastFrame, onLastFrame) {
            this._playing = true;
            this._firstFrame = 0;
            this._lastFrame = this.amount - 1;
            this._startTime = _.performance.now();
            if (typeof firstFrame === "number") {
                this._firstFrame = firstFrame;
            }
            if (typeof lastFrame === "number") {
                this._lastFrame = lastFrame;
            }
            if (typeof onLastFrame === "function") {
                this._onLastFrame = onLastFrame;
            } else {
                delete this._onLastFrame;
            }
            if (this._index !== this._firstFrame) {
                this._startTime -= 1e3 * Math.abs(this._index - this._firstFrame) / this._frameRate;
            }
            return this;
        }

        pause() {
            this._playing = false;
            return this;
        }

        stop() {
            this._playing = false;
            this._index = this._firstFrame;
            return this;
        }

        clone(parent) {
            const clone = new _ImageSequence(
                this.textures,
                this.translation.x,
                this.translation.y,
                this.frameRate
            );
            clone._loop = this._loop;
            if (this._playing) {
                clone.play();
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            object.textures = this.textures.map(function (texture) {
                return texture.toObject();
            });
            object.frameRate = this.frameRate;
            object.index = this.index;
            object._firstFrame = this._firstFrame;
            object._lastFrame = this._lastFrame;
            object._loop = this._loop;
            return object;
        }

        _update() {
            const effect = this._textures;
            let width, height, elapsed, amount, duration, texture;
            let index, frames;
            if (effect) {
                if (this._flagTextures) {
                    this._amount = effect.length;
                }
                if (this._flagFrameRate) {
                    this._duration = 1e3 * this._amount / this._frameRate;
                }
                if (this._playing && this._frameRate > 0) {
                    amount = this._amount;
                    if (_.isNaN(this._lastFrame)) {
                        this._lastFrame = amount - 1;
                    }
                    elapsed = _.performance.now() - this._startTime;
                    frames = this._lastFrame + 1;
                    duration = 1e3 * (frames - this._firstFrame) / this._frameRate;
                    if (this._loop) {
                        elapsed = elapsed % duration;
                    } else {
                        elapsed = Math.min(elapsed, duration);
                    }
                    index = lerp(this._firstFrame, frames, elapsed / duration);
                    index = Math.floor(index);
                    if (index !== this._index) {
                        this._index = index;
                        texture = effect[this._index];
                        if (texture.loaded) {
                            width = texture.image.width;
                            height = texture.image.height;
                            if (this.width !== width) {
                                this.width = width;
                            }
                            if (this.height !== height) {
                                this.height = height;
                            }
                            this.fill = texture;
                            if (index >= this._lastFrame - 1 && this._onLastFrame) {
                                this._onLastFrame();
                            }
                        }
                    }
                } else if (this._flagIndex || !(this.fill instanceof Texture)) {
                    texture = effect[this._index];
                    if (texture.loaded) {
                        width = texture.image.width;
                        height = texture.image.height;
                        if (this.width !== width) {
                            this.width = width;
                        }
                        if (this.height !== height) {
                            this.height = height;
                        }
                    }
                    this.fill = texture;
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagTextures = this._flagFrameRate = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var ImageSequence = _ImageSequence;
    __publicField(ImageSequence, "Properties", [
        "textures",
        "frameRate",
        "index"
    ]);
    __publicField(ImageSequence, "DefaultFrameRate", 30);
    var proto19 = {
        frameRate: {
            enumerable: true,
            get: function () {
                return this._frameRate;
            },
            set: function (v) {
                this._frameRate = v;
                this._flagFrameRate = true;
            }
        },
        index: {
            enumerable: true,
            get: function () {
                return this._index;
            },
            set: function (v) {
                this._index = v;
                this._flagIndex = true;
            }
        },
        textures: {
            enumerable: true,
            get: function () {
                return this._textures;
            },
            set: function (textures) {
                const bindTextures = this._renderer.bindTextures;
                const unbindTextures = this._renderer.unbindTextures;
                if (this._textures) {
                    this._textures.unbind(Events.Types.insert, bindTextures).unbind(Events.Types.remove, unbindTextures);
                }
                this._textures = new Collection((textures || []).slice(0));
                this._textures.bind(Events.Types.insert, bindTextures).bind(Events.Types.remove, unbindTextures);
                bindTextures(this._textures);
            }
        }
    };

    function FlagTextures() {
        this._flagTextures = true;
    }

    function BindTextures(items) {
        let i = items.length;
        while (i--) {
            items[i].bind(Events.Types.change, this._renderer.flagTextures);
        }
        this._renderer.flagTextures();
    }

    function UnbindTextures(items) {
        let i = items.length;
        while (i--) {
            items[i].unbind(Events.Types.change, this._renderer.flagTextures);
        }
        this._renderer.flagTextures();
    }

    function GenerateTexture(obj) {
        if (obj instanceof Texture) {
            return obj;
        } else if (typeof obj === "string") {
            return new Texture(obj);
        }
    }

    // src/shapes/arc-segment.js
    var _ArcSegment = class extends Path {
        _flagStartAngle = false;
        _flagEndAngle = false;
        _flagInnerRadius = false;
        _flagOuterRadius = false;
        _startAngle = 0;
        _endAngle = TWO_PI;
        _innerRadius = 0;
        _outerRadius = 0;

        constructor(x, y, ir, or, sa, ea, res) {
            const amount = res || Constants.Resolution * 3;
            const points = [];
            for (let i = 0; i < amount; i++) {
                points.push(new Anchor());
            }
            super(points, true, false, true);
            for (let prop in proto20) {
                Object.defineProperty(this, prop, proto20[prop]);
            }
            if (typeof ir === "number") {
                this.innerRadius = ir;
            }
            if (typeof or === "number") {
                this.outerRadius = or;
            }
            if (typeof sa === "number") {
                this.startAngle = sa;
            }
            if (typeof ea === "number") {
                this.endAngle = ea;
            }
            this._update();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
        }

        _update() {
            if (this._flagVertices || this._flagStartAngle || this._flagEndAngle || this._flagInnerRadius || this._flagOuterRadius) {
                const sa = this._startAngle;
                const ea = this._endAngle;
                const ir = this._innerRadius;
                const or = this._outerRadius;
                const connected = mod(sa, TWO_PI) === mod(ea, TWO_PI);
                const punctured = ir > 0;
                const vertices = this.vertices;
                let length = punctured ? vertices.length / 2 : vertices.length;
                let command, id = 0;
                let i, last, pct, v, theta, step, x, y, amp;
                if (connected) {
                    length--;
                } else if (!punctured) {
                    length -= 2;
                }
                for (i = 0, last = length - 1; i < length; i++) {
                    pct = i / last;
                    v = vertices[id];
                    theta = pct * (ea - sa) + sa;
                    step = (ea - sa) / length;
                    x = or * Math.cos(theta);
                    y = or * Math.sin(theta);
                    switch (i) {
                        case 0:
                            command = Commands.move;
                            break;
                        default:
                            command = Commands.curve;
                    }
                    v.command = command;
                    v.x = x;
                    v.y = y;
                    v.controls.left.clear();
                    v.controls.right.clear();
                    if (v.command === Commands.curve) {
                        amp = or * step / Math.PI;
                        v.controls.left.x = amp * Math.cos(theta - HALF_PI);
                        v.controls.left.y = amp * Math.sin(theta - HALF_PI);
                        v.controls.right.x = amp * Math.cos(theta + HALF_PI);
                        v.controls.right.y = amp * Math.sin(theta + HALF_PI);
                        if (i === 1) {
                            v.controls.left.multiplyScalar(2);
                        }
                        if (i === last) {
                            v.controls.right.multiplyScalar(2);
                        }
                    }
                    id++;
                }
                if (punctured) {
                    if (connected) {
                        vertices[id].command = Commands.close;
                        id++;
                    } else {
                        length--;
                        last = length - 1;
                    }
                    for (i = 0; i < length; i++) {
                        pct = i / last;
                        v = vertices[id];
                        theta = (1 - pct) * (ea - sa) + sa;
                        step = (ea - sa) / length;
                        x = ir * Math.cos(theta);
                        y = ir * Math.sin(theta);
                        command = Commands.curve;
                        if (i <= 0) {
                            command = connected ? Commands.move : Commands.line;
                        }
                        v.command = command;
                        v.x = x;
                        v.y = y;
                        v.controls.left.clear();
                        v.controls.right.clear();
                        if (v.command === Commands.curve) {
                            amp = ir * step / Math.PI;
                            v.controls.left.x = amp * Math.cos(theta + HALF_PI);
                            v.controls.left.y = amp * Math.sin(theta + HALF_PI);
                            v.controls.right.x = amp * Math.cos(theta - HALF_PI);
                            v.controls.right.y = amp * Math.sin(theta - HALF_PI);
                            if (i === 1) {
                                v.controls.left.multiplyScalar(2);
                            }
                            if (i === last) {
                                v.controls.right.multiplyScalar(2);
                            }
                        }
                        id++;
                    }
                    vertices[id].copy(vertices[0]);
                    vertices[id].command = Commands.line;
                } else if (!connected) {
                    vertices[id].command = Commands.line;
                    vertices[id].x = 0;
                    vertices[id].y = 0;
                    id++;
                    vertices[id].copy(vertices[0]);
                    vertices[id].command = Commands.line;
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            super.flagReset.call(this);
            this._flagStartAngle = this._flagEndAngle = this._flagInnerRadius = this._flagOuterRadius = false;
            return this;
        }

        clone(parent) {
            const ir = this.innerRadius;
            const or = this.outerRadius;
            const sa = this.startAngle;
            const ea = this.endAngle;
            const resolution = this.vertices.length;
            const clone = new _ArcSegment(0, 0, ir, or, sa, ea, resolution);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _ArcSegment.Properties.length; i++) {
                const k = _ArcSegment.Properties[i];
                object[k] = this[k];
            }
            return object;
        }
    };
    var ArcSegment = _ArcSegment;
    __publicField(ArcSegment, "Properties", ["startAngle", "endAngle", "innerRadius", "outerRadius"]);
    var proto20 = {
        startAngle: {
            enumerable: true,
            get: function () {
                return this._startAngle;
            },
            set: function (v) {
                this._startAngle = v;
                this._flagStartAngle = true;
            }
        },
        endAngle: {
            enumerable: true,
            get: function () {
                return this._endAngle;
            },
            set: function (v) {
                this._endAngle = v;
                this._flagEndAngle = true;
            }
        },
        innerRadius: {
            enumerable: true,
            get: function () {
                return this._innerRadius;
            },
            set: function (v) {
                this._innerRadius = v;
                this._flagInnerRadius = true;
            }
        },
        outerRadius: {
            enumerable: true,
            get: function () {
                return this._outerRadius;
            },
            set: function (v) {
                this._outerRadius = v;
                this._flagOuterRadius = true;
            }
        }
    };

    // src/shapes/points.js
    var ceil2 = Math.ceil;
    var floor3 = Math.floor;
    var _Points = class extends Shape {
        _flagVertices = true;
        _flagLength = true;
        _flagFill = true;
        _flagStroke = true;
        _flagLinewidth = true;
        _flagOpacity = true;
        _flagVisible = true;
        _flagSize = true;
        _flagSizeAttenuation = true;
        _length = 0;
        _fill = "#fff";
        _stroke = "#000";
        _linewidth = 1;
        _opacity = 1;
        _visible = true;
        _size = 1;
        _sizeAttenuation = false;
        _beginning = 0;
        _ending = 1;
        _dashes = null;

        constructor(vertices) {
            super();
            for (let prop in proto21) {
                Object.defineProperty(this, prop, proto21[prop]);
            }
            this._renderer.type = "points";
            this._renderer.flagVertices = FlagVertices.bind(this);
            this._renderer.bindVertices = BindVertices.bind(this);
            this._renderer.unbindVertices = UnbindVertices.bind(this);
            this._renderer.flagFill = FlagFill.bind(this);
            this._renderer.flagStroke = FlagStroke.bind(this);
            this._renderer.vertices = null;
            this._renderer.collection = null;
            this.sizeAttenuation = false;
            this.beginning = 0;
            this.ending = 1;
            this.fill = "#fff";
            this.stroke = "#000";
            this.className = "";
            this.visible = true;
            this.vertices = vertices;
            this.dashes = [];
            this.dashes.offset = 0;
        }

        clone(parent) {
            const clone = new _Points();
            for (let j = 0; j < this.vertices.length; j++) {
                clone.vertices.push(this.vertices[j].clone());
            }
            for (let i = 0; i < _Points.Properties.length; i++) {
                const k = _Points.Properties[i];
                clone[k] = this[k];
            }
            clone.className = this.className;
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            if (parent) {
                parent.add(clone);
            }
            return clone._update();
        }

        toObject() {
            const result = {
                vertices: this.vertices.map(function (v) {
                    return v.toObject();
                })
            };
            _.each(_Points.Properties, function (k) {
                result[k] = this[k];
            }, this);
            result.className = this.className;
            result.translation = this.translation.toObject();
            result.rotation = this.rotation;
            result.scale = this.scale instanceof Vector ? this.scale.toObject() : this.scale;
            result.skewX = this.skewX;
            result.skewY = this.skewY;
            if (this.matrix.manual) {
                result.matrix = this.matrix.toObject();
            }
            return result;
        }

        noFill = Path.prototype.noFill;
        noStroke = Path.prototype.noStroke;
        corner = Path.prototype.corner;
        center = Path.prototype.center;
        getBoundingClientRect = Path.prototype.getBoundingClientRect;

        subdivide(limit) {
            this._update();
            let points = [];
            for (let i = 0; i < this.vertices.length; i++) {
                const a = this.vertices[i];
                const b = this.vertices[i - 1];
                if (!b) {
                    continue;
                }
                const x1 = a.x;
                const y1 = a.y;
                const x2 = b.x;
                const y2 = b.y;
                const subdivisions = subdivide(x1, y1, x1, y1, x2, y2, x2, y2, limit);
                points = points.concat(subdivisions);
            }
            this.vertices = points;
            return this;
        }

        _updateLength = Path.prototype._updateLength;

        _update() {
            if (this._flagVertices) {
                if (this._flagLength) {
                    this._updateLength(void 0, true);
                }
                const beginning = Math.min(this._beginning, this._ending);
                const ending = Math.max(this._beginning, this._ending);
                const bid = getIdByLength(this, beginning * this._length);
                const eid = getIdByLength(this, ending * this._length);
                const low = ceil2(bid);
                const high = floor3(eid);
                let j = 0, v;
                this._renderer.vertices = [];
                this._renderer.collection = [];
                for (let i = 0; i < this._collection.length; i++) {
                    if (i >= low && i <= high) {
                        v = this._collection[i];
                        this._renderer.collection.push(v);
                        this._renderer.vertices[j * 2 + 0] = v.x;
                        this._renderer.vertices[j * 2 + 1] = v.y;
                        j++;
                    }
                }
            }
            super._update.apply(this, arguments);
            return this;
        }

        flagReset() {
            this._flagVertices = this._flagLength = this._flagFill = this._flagStroke = this._flagLinewidth = this._flagOpacity = this._flagVisible = this._flagSize = this._flagSizeAttenuation = false;
            super.flagReset.call(this);
            return this;
        }
    };
    var Points = _Points;
    __publicField(Points, "Properties", [
        "fill",
        "stroke",
        "linewidth",
        "opacity",
        "visible",
        "size",
        "sizeAttenuation",
        "beginning",
        "ending"
    ]);
    var proto21 = {
        linewidth: {
            enumerable: true,
            get: function () {
                return this._linewidth;
            },
            set: function (v) {
                this._linewidth = v;
                this._flagLinewidth = true;
            }
        },
        opacity: {
            enumerable: true,
            get: function () {
                return this._opacity;
            },
            set: function (v) {
                this._opacity = v;
                this._flagOpacity = true;
            }
        },
        visible: {
            enumerable: true,
            get: function () {
                return this._visible;
            },
            set: function (v) {
                this._visible = v;
                this._flagVisible = true;
            }
        },
        size: {
            enumerable: true,
            get: function () {
                return this._size;
            },
            set: function (v) {
                this._size = v;
                this._flagSize = true;
            }
        },
        sizeAttenuation: {
            enumerable: true,
            get: function () {
                return this._sizeAttenuation;
            },
            set: function (v) {
                this._sizeAttenuation = v;
                this._flagSizeAttenuation = true;
            }
        },
        fill: {
            enumerable: true,
            get: function () {
                return this._fill;
            },
            set: function (f) {
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.unbind(Events.Types.change, this._renderer.flagFill);
                }
                this._fill = f;
                this._flagFill = true;
                if (this._fill instanceof Gradient || this._fill instanceof LinearGradient || this._fill instanceof RadialGradient || this._fill instanceof Texture) {
                    this._fill.bind(Events.Types.change, this._renderer.flagFill);
                }
            }
        },
        stroke: {
            enumerable: true,
            get: function () {
                return this._stroke;
            },
            set: function (f) {
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.unbind(Events.Types.change, this._renderer.flagStroke);
                }
                this._stroke = f;
                this._flagStroke = true;
                if (this._stroke instanceof Gradient || this._stroke instanceof LinearGradient || this._stroke instanceof RadialGradient || this._stroke instanceof Texture) {
                    this._stroke.bind(Events.Types.change, this._renderer.flagStroke);
                }
            }
        },
        length: {
            get: function () {
                if (this._flagLength) {
                    this._updateLength();
                }
                return this._length;
            }
        },
        beginning: {
            enumerable: true,
            get: function () {
                return this._beginning;
            },
            set: function (v) {
                this._beginning = v;
                this._flagVertices = true;
            }
        },
        ending: {
            enumerable: true,
            get: function () {
                return this._ending;
            },
            set: function (v) {
                this._ending = v;
                this._flagVertices = true;
            }
        },
        vertices: {
            enumerable: true,
            get: function () {
                return this._collection;
            },
            set: function (vertices) {
                const bindVertices = this._renderer.bindVertices;
                const unbindVertices = this._renderer.unbindVertices;
                if (this._collection) {
                    this._collection.unbind(Events.Types.insert, bindVertices).unbind(Events.Types.remove, unbindVertices);
                }
                if (vertices instanceof Collection) {
                    this._collection = vertices;
                } else {
                    this._collection = new Collection(vertices || []);
                }
                this._collection.bind(Events.Types.insert, bindVertices).bind(Events.Types.remove, unbindVertices);
                bindVertices(this._collection);
            }
        },
        dashes: {
            enumerable: true,
            get: function () {
                return this._dashes;
            },
            set: function (v) {
                if (typeof v.offset !== "number") {
                    v.offset = this.dashes && this._dashes.offset || 0;
                }
                this._dashes = v;
            }
        }
    };

    // src/shapes/polygon.js
    var cos5 = Math.cos;
    var sin5 = Math.sin;
    var _Polygon = class extends Path {
        _flagWidth = false;
        _flagHeight = false;
        _flagSides = false;
        _radius = 0;
        _width = 0;
        _height = 0;
        _sides = 0;

        constructor(x, y, radius, sides) {
            sides = Math.max(sides || 0, 3);
            super();
            for (let prop in proto22) {
                Object.defineProperty(this, prop, proto22[prop]);
            }
            this.closed = true;
            this.automatic = false;
            if (typeof radius === "number") {
                this.radius = radius;
            }
            if (typeof sides === "number") {
                this.sides = sides;
            }
            this._update();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
        }

        _update() {
            if (this._flagVertices || this._flagWidth || this._flagHeight || this._flagSides) {
                const sides = this._sides;
                const amount = sides + 1;
                let length = this.vertices.length;
                if (length > sides) {
                    this.vertices.splice(sides - 1, length - sides);
                    length = sides;
                }
                for (let i = 0; i < amount; i++) {
                    const pct = (i + 0.5) / sides;
                    const theta = TWO_PI * pct + Math.PI / 2;
                    const x = this._width * cos5(theta) / 2;
                    const y = this._height * sin5(theta) / 2;
                    if (i >= length) {
                        this.vertices.push(new Anchor(x, y));
                    } else {
                        this.vertices[i].set(x, y);
                    }
                    this.vertices[i].command = i === 0 ? Commands.move : Commands.line;
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagWidth = this._flagHeight = this._flagSides = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const clone = new _Polygon(0, 0, 0, this.sides);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            clone.width = this.width;
            clone.height = this.height;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _Polygon.Properties.length; i++) {
                const k = _Polygon.Properties[i];
                object[k] = this[k];
            }
            return object;
        }
    };
    var Polygon = _Polygon;
    __publicField(Polygon, "Properties", ["width", "height", "sides"]);
    var proto22 = {
        radius: {
            enumerable: true,
            get: function () {
                return this._radius;
            },
            set: function (v) {
                this._radius = v;
                this.width = v * 2;
                this.height = v * 2;
            }
        },
        width: {
            enumerable: true,
            get: function () {
                return this._width;
            },
            set: function (v) {
                this._width = v;
                this._flagWidth = true;
                this._radius = Math.max(this.width, this.height) / 2;
            }
        },
        height: {
            enumerable: true,
            get: function () {
                return this._height;
            },
            set: function (v) {
                this._height = v;
                this._flagHeight = true;
                this._radius = Math.max(this.width, this.height) / 2;
            }
        },
        sides: {
            enumerable: true,
            get: function () {
                return this._sides;
            },
            set: function (v) {
                this._sides = v;
                this._flagSides = true;
            }
        }
    };

    // src/shapes/star.js
    var cos6 = Math.cos;
    var sin6 = Math.sin;
    var _Star = class extends Path {
        _flagInnerRadius = false;
        _flagOuterRadius = false;
        _flagSides = false;
        _innerRadius = 0;
        _outerRadius = 0;
        _sides = 0;

        constructor(x, y, innerRadius, outerRadius, sides) {
            if (arguments.length <= 3) {
                outerRadius = innerRadius;
                innerRadius = outerRadius / 2;
            }
            if (typeof sides !== "number" || sides <= 0) {
                sides = 5;
            }
            super();
            for (let prop in proto23) {
                Object.defineProperty(this, prop, proto23[prop]);
            }
            this.closed = true;
            this.automatic = false;
            if (typeof innerRadius === "number") {
                this.innerRadius = innerRadius;
            }
            if (typeof outerRadius === "number") {
                this.outerRadius = outerRadius;
            }
            if (typeof sides === "number") {
                this.sides = sides;
            }
            this._update();
            if (typeof x === "number") {
                this.translation.x = x;
            }
            if (typeof y === "number") {
                this.translation.y = y;
            }
        }

        _update() {
            if (this._flagVertices || this._flagInnerRadius || this._flagOuterRadius || this._flagSides) {
                const sides = this._sides * 2;
                const amount = sides + 1;
                let length = this.vertices.length;
                if (length > sides) {
                    this.vertices.splice(sides - 1, length - sides);
                    length = sides;
                }
                for (let i = 0; i < amount; i++) {
                    const pct = (i + 0.5) / sides;
                    const theta = TWO_PI * pct;
                    const r = (!(i % 2) ? this._innerRadius : this._outerRadius) / 2;
                    const x = r * cos6(theta);
                    const y = r * sin6(theta);
                    if (i >= length) {
                        this.vertices.push(new Anchor(x, y));
                    } else {
                        this.vertices[i].set(x, y);
                    }
                    this.vertices[i].command = i === 0 ? Commands.move : Commands.line;
                }
            }
            super._update.call(this);
            return this;
        }

        flagReset() {
            this._flagInnerRadius = this._flagOuterRadius = this._flagSides = false;
            super.flagReset.call(this);
            return this;
        }

        clone(parent) {
            const ir = this.innerRadius;
            const or = this.outerRadius;
            const sides = this.sides;
            const clone = new _Star(0, 0, ir, or, sides);
            clone.translation.copy(this.translation);
            clone.rotation = this.rotation;
            clone.scale = this.scale;
            clone.skewX = this.skewX;
            clone.skewY = this.skewY;
            if (this.matrix.manual) {
                clone.matrix.copy(this.matrix);
            }
            for (let i = 0; i < Path.Properties.length; i++) {
                const k = Path.Properties[i];
                clone[k] = this[k];
            }
            if (parent) {
                parent.add(clone);
            }
            return clone;
        }

        toObject() {
            const object = super.toObject.call(this);
            for (let i = 0; i < _Star.Properties.length; i++) {
                const k = _Star.Properties[i];
                object[k] = this[k];
            }
            return object;
        }
    };
    var Star = _Star;
    __publicField(Star, "Properties", ["innerRadius", "outerRadius", "sides"]);
    var proto23 = {
        innerRadius: {
            enumerable: true,
            get: function () {
                return this._innerRadius;
            },
            set: function (v) {
                this._innerRadius = v;
                this._flagInnerRadius = true;
            }
        },
        outerRadius: {
            enumerable: true,
            get: function () {
                return this._outerRadius;
            },
            set: function (v) {
                this._outerRadius = v;
                this._flagOuterRadius = true;
            }
        },
        sides: {
            enumerable: true,
            get: function () {
                return this._sides;
            },
            set: function (v) {
                this._sides = v;
                this._flagSides = true;
            }
        }
    };

    // src/renderers/svg.js
    var svg = {
        version: 1.1,
        ns: "http://www.w3.org/2000/svg",
        xlink: "http://www.w3.org/1999/xlink",
        alignments: {
            left: "start",
            center: "middle",
            right: "end"
        },
        createElement: function (name, attrs) {
            const tag = name;
            const elem = document.createElementNS(svg.ns, tag);
            if (tag === "svg") {
                attrs = _.defaults(attrs || {}, {
                    version: svg.version
                });
            }
            if (attrs && Object.keys(attrs).length > 0) {
                svg.setAttributes(elem, attrs);
            }
            return elem;
        },
        setAttributes: function (elem, attrs) {
            const keys = Object.keys(attrs);
            for (let i = 0; i < keys.length; i++) {
                if (/href/.test(keys[i])) {
                    elem.setAttributeNS(svg.xlink, keys[i], attrs[keys[i]]);
                } else {
                    elem.setAttribute(keys[i], attrs[keys[i]]);
                }
            }
            return this;
        },
        removeAttributes: function (elem, attrs) {
            for (let key in attrs) {
                elem.removeAttribute(key);
            }
            return this;
        },
        toString: function (points, closed2) {
            let l = points.length, last = l - 1, d, string = "";
            for (let i = 0; i < l; i++) {
                const b = points[i];
                const prev = closed2 ? mod(i - 1, l) : Math.max(i - 1, 0);
                const a = points[prev];
                let command, c;
                let vx, vy, ux, uy, ar, bl, br, cl;
                let rx, ry, xAxisRotation, largeArcFlag, sweepFlag;
                let x = toFixed(b.x);
                let y = toFixed(b.y);
                switch (b.command) {
                    case Commands.close:
                        command = Commands.close;
                        break;
                    case Commands.arc:
                        rx = b.rx;
                        ry = b.ry;
                        xAxisRotation = b.xAxisRotation;
                        largeArcFlag = b.largeArcFlag;
                        sweepFlag = b.sweepFlag;
                        command = Commands.arc + " " + rx + " " + ry + " " + xAxisRotation + " " + largeArcFlag + " " + sweepFlag + " " + x + " " + y;
                        break;
                    case Commands.curve:
                        ar = a.controls && a.controls.right || Vector.zero;
                        bl = b.controls && b.controls.left || Vector.zero;
                        if (a.relative) {
                            vx = toFixed(ar.x + a.x);
                            vy = toFixed(ar.y + a.y);
                        } else {
                            vx = toFixed(ar.x);
                            vy = toFixed(ar.y);
                        }
                        if (b.relative) {
                            ux = toFixed(bl.x + b.x);
                            uy = toFixed(bl.y + b.y);
                        } else {
                            ux = toFixed(bl.x);
                            uy = toFixed(bl.y);
                        }
                        command = (i === 0 ? Commands.move : Commands.curve) + " " + vx + " " + vy + " " + ux + " " + uy + " " + x + " " + y;
                        break;
                    case Commands.move:
                        d = b;
                        command = Commands.move + " " + x + " " + y;
                        break;
                    default:
                        command = b.command + " " + x + " " + y;
                }
                if (i >= last && closed2) {
                    if (b.command === Commands.curve) {
                        c = d;
                        br = b.controls && b.controls.right || b;
                        cl = c.controls && c.controls.left || c;
                        if (b.relative) {
                            vx = toFixed(br.x + b.x);
                            vy = toFixed(br.y + b.y);
                        } else {
                            vx = toFixed(br.x);
                            vy = toFixed(br.y);
                        }
                        if (c.relative) {
                            ux = toFixed(cl.x + c.x);
                            uy = toFixed(cl.y + c.y);
                        } else {
                            ux = toFixed(cl.x);
                            uy = toFixed(cl.y);
                        }
                        x = toFixed(c.x);
                        y = toFixed(c.y);
                        command += " C " + vx + " " + vy + " " + ux + " " + uy + " " + x + " " + y;
                    }
                    if (b.command !== Commands.close) {
                        command += " Z";
                    }
                }
                string += command + " ";
            }
            return string;
        },
        pointsToString: function (points, size) {
            let string = "";
            const r = size * 0.5;
            for (let i = 0; i < points.length; i++) {
                const x = points[i].x;
                const y = points[i].y - r;
                string += Commands.move + " " + x + " " + y + " ";
                string += "a " + r + " " + r + " 0 1 0 0.001 0 Z";
            }
            return string;
        },
        getClip: function (shape, domElement) {
            let clip = shape._renderer.clip;
            if (!clip) {
                clip = shape._renderer.clip = svg.createElement("clipPath", {
                    "clip-rule": "nonzero"
                });
            }
            if (clip.parentNode === null) {
                domElement.defs.appendChild(clip);
            }
            return clip;
        },
        defs: {
            update: function (domElement) {
                const {defs} = domElement;
                if (defs._flagUpdate) {
                    const children = Array.prototype.slice.call(
                        defs.children,
                        0
                    );
                    for (let i = 0; i < children.length; i++) {
                        const child = children[i];
                        const id = child.id;
                        const selector = `[fill="url(#${id})"],[stroke="url(#${id})"],[clip-path="url(#${id})"]`;
                        const exists = domElement.querySelector(selector);
                        if (!exists) {
                            defs.removeChild(child);
                        }
                    }
                    defs._flagUpdate = false;
                }
            }
        },
        group: {
            appendChild: function (object) {
                const elem = object._renderer.elem;
                if (!elem) {
                    return;
                }
                const tag = elem.nodeName;
                if (!tag || /(radial|linear)gradient/i.test(tag) || object._clip) {
                    return;
                }
                this.elem.appendChild(elem);
            },
            removeChild: function (object) {
                const elem = object._renderer.elem;
                if (!elem || elem.parentNode != this.elem) {
                    return;
                }
                const tag = elem.nodeName;
                if (!tag) {
                    return;
                }
                if (object._clip) {
                    return;
                }
                this.elem.removeChild(elem);
            },
            orderChild: function (object) {
                this.elem.appendChild(object._renderer.elem);
            },
            renderChild: function (child) {
                svg[child._renderer.type].render.call(child, this);
            },
            render: function (domElement) {
                if (!this._visible && !this._flagVisible || this._opacity === 0 && !this._flagOpacity) {
                    return this;
                }
                this._update();
                if (!this._renderer.elem) {
                    this._renderer.elem = svg.createElement("g", {
                        id: this.id
                    });
                    domElement.appendChild(this._renderer.elem);
                }
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                const context = {
                    domElement,
                    elem: this._renderer.elem
                };
                if (flagMatrix) {
                    this._renderer.elem.setAttribute("transform", "matrix(" + this._matrix.toString() + ")");
                }
                for (let i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    svg[child._renderer.type].render.call(child, domElement);
                }
                if (this._flagId) {
                    this._renderer.elem.setAttribute("id", this._id);
                }
                if (this._flagOpacity) {
                    this._renderer.elem.setAttribute("opacity", this._opacity);
                }
                if (this._flagVisible) {
                    this._renderer.elem.setAttribute("display", this._visible ? "inline" : "none");
                }
                if (this._flagClassName) {
                    this._renderer.elem.setAttribute("class", this.classList.join(" "));
                }
                if (this._flagAdditions) {
                    this.additions.forEach(svg.group.appendChild, context);
                }
                if (this._flagSubtractions) {
                    this.subtractions.forEach(svg.group.removeChild, context);
                }
                if (this._flagOrder) {
                    this.children.forEach(svg.group.orderChild, context);
                }
                if (this._flagMask) {
                    if (this._mask) {
                        svg[this._mask._renderer.type].render.call(this._mask, domElement);
                        this._renderer.elem.setAttribute("clip-path", "url(#" + this._mask.id + ")");
                    } else {
                        this._renderer.elem.removeAttribute("clip-path");
                    }
                }
                if (this.dataset) {
                    Object.assign(this._renderer.elem.dataset, this.dataset);
                }
                return this.flagReset();
            }
        },
        path: {
            render: function (domElement) {
                if (this._opacity === 0 && !this._flagOpacity) {
                    return this;
                }
                this._update();
                const changed = {};
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                if (flagMatrix) {
                    changed.transform = "matrix(" + this._matrix.toString() + ")";
                }
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagVertices) {
                    const vertices = svg.toString(this._renderer.vertices, this._closed);
                    changed.d = vertices;
                }
                if (this._fill && this._fill._renderer) {
                    this._renderer.hasFillEffect = true;
                    this._fill._update();
                    svg[this._fill._renderer.type].render.call(this._fill, domElement, true);
                }
                if (this._flagFill) {
                    changed.fill = this._fill && this._fill.id ? "url(#" + this._fill.id + ")" : this._fill;
                    if (this._renderer.hasFillEffect && typeof this._fill.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasFillEffect;
                    }
                }
                if (this._stroke && this._stroke._renderer) {
                    this._renderer.hasStrokeEffect = true;
                    this._stroke._update();
                    svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);
                }
                if (this._flagStroke) {
                    changed.stroke = this._stroke && this._stroke.id ? "url(#" + this._stroke.id + ")" : this._stroke;
                    if (this._renderer.hasStrokeEffect && typeof this._stroke.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasStrokeEffect;
                    }
                }
                if (this._flagLinewidth) {
                    changed["stroke-width"] = this._linewidth;
                }
                if (this._flagOpacity) {
                    changed["stroke-opacity"] = this._opacity;
                    changed["fill-opacity"] = this._opacity;
                }
                if (this._flagClassName) {
                    changed["class"] = this.classList.join(" ");
                }
                if (this._flagVisible) {
                    changed.visibility = this._visible ? "visible" : "hidden";
                }
                if (this._flagCap) {
                    changed["stroke-linecap"] = this._cap;
                }
                if (this._flagJoin) {
                    changed["stroke-linejoin"] = this._join;
                }
                if (this._flagMiter) {
                    changed["stroke-miterlimit"] = this._miter;
                }
                if (this.dashes && this.dashes.length > 0) {
                    changed["stroke-dasharray"] = this.dashes.join(" ");
                    changed["stroke-dashoffset"] = this.dashes.offset || 0;
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    this._renderer.elem = svg.createElement("path", changed);
                    domElement.appendChild(this._renderer.elem);
                } else {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                if (this._flagClip) {
                    const clip = svg.getClip(this, domElement);
                    const elem = this._renderer.elem;
                    if (this._clip) {
                        elem.removeAttribute("id");
                        clip.setAttribute("id", this.id);
                        clip.appendChild(elem);
                    } else {
                        clip.removeAttribute("id");
                        elem.setAttribute("id", this.id);
                        this.parent._renderer.elem.appendChild(elem);
                    }
                }
                if (this._flagMask) {
                    if (this._mask) {
                        svg[this._mask._renderer.type].render.call(this._mask, domElement);
                        this._renderer.elem.setAttribute("clip-path", "url(#" + this._mask.id + ")");
                    } else {
                        this._renderer.elem.removeAttribute("clip-path");
                    }
                }
                return this.flagReset();
            }
        },
        points: {
            render: function (domElement) {
                if (this._opacity === 0 && !this._flagOpacity) {
                    return this;
                }
                this._update();
                const changed = {};
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                if (flagMatrix) {
                    changed.transform = "matrix(" + this._matrix.toString() + ")";
                }
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagVertices || this._flagSize || this._flagSizeAttenuation) {
                    let size = this._size;
                    if (!this._sizeAttenuation) {
                        const me = this.worldMatrix.elements;
                        const m = decomposeMatrix(me[0], me[3], me[1], me[4], me[2], me[5]);
                        size /= Math.max(m.scaleX, m.scaleY);
                    }
                    const vertices = svg.pointsToString(this._renderer.collection, size);
                    changed.d = vertices;
                }
                if (this._fill && this._fill._renderer) {
                    this._renderer.hasFillEffect = true;
                    this._fill._update();
                    svg[this._fill._renderer.type].render.call(this._fill, domElement, true);
                }
                if (this._flagFill) {
                    changed.fill = this._fill && this._fill.id ? "url(#" + this._fill.id + ")" : this._fill;
                    if (this._renderer.hasFillEffect && typeof this._fill.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasFillEffect;
                    }
                }
                if (this._stroke && this._stroke._renderer) {
                    this._renderer.hasStrokeEffect = true;
                    this._stroke._update();
                    svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);
                }
                if (this._flagStroke) {
                    changed.stroke = this._stroke && this._stroke.id ? "url(#" + this._stroke.id + ")" : this._stroke;
                    if (this._renderer.hasStrokeEffect && typeof this._stroke.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasStrokeEffect;
                    }
                }
                if (this._flagLinewidth) {
                    changed["stroke-width"] = this._linewidth;
                }
                if (this._flagOpacity) {
                    changed["stroke-opacity"] = this._opacity;
                    changed["fill-opacity"] = this._opacity;
                }
                if (this._flagClassName) {
                    changed["class"] = this.classList.join(" ");
                }
                if (this._flagVisible) {
                    changed.visibility = this._visible ? "visible" : "hidden";
                }
                if (this.dashes && this.dashes.length > 0) {
                    changed["stroke-dasharray"] = this.dashes.join(" ");
                    changed["stroke-dashoffset"] = this.dashes.offset || 0;
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    this._renderer.elem = svg.createElement("path", changed);
                    domElement.appendChild(this._renderer.elem);
                } else {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                return this.flagReset();
            }
        },
        text: {
            render: function (domElement) {
                this._update();
                const changed = {};
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                if (flagMatrix) {
                    changed.transform = "matrix(" + this._matrix.toString() + ")";
                }
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagFamily) {
                    changed["font-family"] = this._family;
                }
                if (this._flagSize) {
                    changed["font-size"] = this._size;
                }
                if (this._flagLeading) {
                    changed["line-height"] = this._leading;
                }
                if (this._flagAlignment) {
                    changed["text-anchor"] = svg.alignments[this._alignment] || this._alignment;
                }
                if (this._flagBaseline) {
                    changed["alignment-baseline"] = changed["dominant-baseline"] = this._baseline;
                }
                if (this._flagStyle) {
                    changed["font-style"] = this._style;
                }
                if (this._flagWeight) {
                    changed["font-weight"] = this._weight;
                }
                if (this._flagDecoration) {
                    changed["text-decoration"] = this._decoration;
                }
                if (this._fill && this._fill._renderer) {
                    this._renderer.hasFillEffect = true;
                    this._fill._update();
                    svg[this._fill._renderer.type].render.call(this._fill, domElement, true);
                }
                if (this._flagFill) {
                    changed.fill = this._fill && this._fill.id ? "url(#" + this._fill.id + ")" : this._fill;
                    if (this._renderer.hasFillEffect && typeof this._fill.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasFillEffect;
                    }
                }
                if (this._stroke && this._stroke._renderer) {
                    this._renderer.hasStrokeEffect = true;
                    this._stroke._update();
                    svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);
                }
                if (this._flagStroke) {
                    changed.stroke = this._stroke && this._stroke.id ? "url(#" + this._stroke.id + ")" : this._stroke;
                    if (this._renderer.hasStrokeEffect && typeof this._stroke.id === "undefined") {
                        domElement.defs._flagUpdate = true;
                        delete this._renderer.hasStrokeEffect;
                    }
                }
                if (this._flagLinewidth) {
                    changed["stroke-width"] = this._linewidth;
                }
                if (this._flagOpacity) {
                    changed.opacity = this._opacity;
                }
                if (this._flagClassName) {
                    changed["class"] = this.classList.join(" ");
                }
                if (this._flagVisible) {
                    changed.visibility = this._visible ? "visible" : "hidden";
                }
                if (this.dashes && this.dashes.length > 0) {
                    changed["stroke-dasharray"] = this.dashes.join(" ");
                    changed["stroke-dashoffset"] = this.dashes.offset || 0;
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    this._renderer.elem = svg.createElement("text", changed);
                    domElement.appendChild(this._renderer.elem);
                } else {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                if (this._flagClip) {
                    const clip = svg.getClip(this, domElement);
                    const elem = this._renderer.elem;
                    if (this._clip) {
                        elem.removeAttribute("id");
                        clip.setAttribute("id", this.id);
                        clip.appendChild(elem);
                    } else {
                        clip.removeAttribute("id");
                        elem.setAttribute("id", this.id);
                        this.parent._renderer.elem.appendChild(elem);
                    }
                }
                if (this._flagMask) {
                    if (this._mask) {
                        svg[this._mask._renderer.type].render.call(this._mask, domElement);
                        this._renderer.elem.setAttribute("clip-path", "url(#" + this._mask.id + ")");
                    } else {
                        this._renderer.elem.removeAttribute("clip-path");
                    }
                }
                if (this._flagValue) {
                    this._renderer.elem.textContent = this._value;
                }
                return this.flagReset();
            }
        },
        "linear-gradient": {
            render: function (domElement, silent) {
                if (!silent) {
                    this._update();
                }
                const changed = {};
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagEndPoints) {
                    changed.x1 = this.left._x;
                    changed.y1 = this.left._y;
                    changed.x2 = this.right._x;
                    changed.y2 = this.right._y;
                }
                if (this._flagSpread) {
                    changed.spreadMethod = this._spread;
                }
                if (this._flagUnits) {
                    changed.gradientUnits = this._units;
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    this._renderer.elem = svg.createElement("linearGradient", changed);
                } else {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                if (this._renderer.elem.parentNode === null) {
                    domElement.defs.appendChild(this._renderer.elem);
                }
                if (this._flagStops) {
                    const lengthChanged = this._renderer.elem.childNodes.length !== this.stops.length;
                    if (lengthChanged) {
                        while (this._renderer.elem.lastChild) {
                            this._renderer.elem.removeChild(this._renderer.elem.lastChild);
                        }
                    }
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        const attrs = {};
                        if (stop._flagOffset) {
                            attrs.offset = 100 * stop._offset + "%";
                        }
                        if (stop._flagColor) {
                            attrs["stop-color"] = stop._color;
                        }
                        if (stop._flagOpacity) {
                            attrs["stop-opacity"] = stop._opacity;
                        }
                        if (!stop._renderer.elem) {
                            stop._renderer.elem = svg.createElement("stop", attrs);
                        } else {
                            svg.setAttributes(stop._renderer.elem, attrs);
                        }
                        if (lengthChanged) {
                            this._renderer.elem.appendChild(stop._renderer.elem);
                        }
                        stop.flagReset();
                    }
                }
                return this.flagReset();
            }
        },
        "radial-gradient": {
            render: function (domElement, silent) {
                if (!silent) {
                    this._update();
                }
                const changed = {};
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagCenter) {
                    changed.cx = this.center._x;
                    changed.cy = this.center._y;
                }
                if (this._flagFocal) {
                    changed.fx = this.focal._x;
                    changed.fy = this.focal._y;
                }
                if (this._flagRadius) {
                    changed.r = this._radius;
                }
                if (this._flagSpread) {
                    changed.spreadMethod = this._spread;
                }
                if (this._flagUnits) {
                    changed.gradientUnits = this._units;
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    this._renderer.elem = svg.createElement("radialGradient", changed);
                } else {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                if (this._renderer.elem.parentNode === null) {
                    domElement.defs.appendChild(this._renderer.elem);
                }
                if (this._flagStops) {
                    const lengthChanged = this._renderer.elem.childNodes.length !== this.stops.length;
                    if (lengthChanged) {
                        while (this._renderer.elem.lastChild) {
                            this._renderer.elem.removeChild(this._renderer.elem.lastChild);
                        }
                    }
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        const attrs = {};
                        if (stop._flagOffset) {
                            attrs.offset = 100 * stop._offset + "%";
                        }
                        if (stop._flagColor) {
                            attrs["stop-color"] = stop._color;
                        }
                        if (stop._flagOpacity) {
                            attrs["stop-opacity"] = stop._opacity;
                        }
                        if (!stop._renderer.elem) {
                            stop._renderer.elem = svg.createElement("stop", attrs);
                        } else {
                            svg.setAttributes(stop._renderer.elem, attrs);
                        }
                        if (lengthChanged) {
                            this._renderer.elem.appendChild(stop._renderer.elem);
                        }
                        stop.flagReset();
                    }
                }
                return this.flagReset();
            }
        },
        texture: {
            render: function (domElement, silent) {
                if (!silent) {
                    this._update();
                }
                const changed = {};
                const styles = {x: 0, y: 0};
                const image = this.image;
                if (this._flagId) {
                    changed.id = this._id;
                }
                if (this._flagLoaded && this.loaded) {
                    switch (image.nodeName.toLowerCase()) {
                        case "canvas":
                            styles.href = styles["xlink:href"] = image.toDataURL("image/png");
                            break;
                        case "img":
                        case "image":
                            styles.href = styles["xlink:href"] = this.src;
                            break;
                    }
                }
                if (this._flagOffset || this._flagLoaded || this._flagScale) {
                    changed.x = this._offset.x;
                    changed.y = this._offset.y;
                    if (image) {
                        changed.x -= image.width / 2;
                        changed.y -= image.height / 2;
                        if (this._scale instanceof Vector) {
                            changed.x *= this._scale.x;
                            changed.y *= this._scale.y;
                        } else {
                            changed.x *= this._scale;
                            changed.y *= this._scale;
                        }
                    }
                    if (changed.x > 0) {
                        changed.x *= -1;
                    }
                    if (changed.y > 0) {
                        changed.y *= -1;
                    }
                }
                if (this._flagScale || this._flagLoaded || this._flagRepeat) {
                    changed.width = 0;
                    changed.height = 0;
                    if (image) {
                        styles.width = changed.width = image.width;
                        styles.height = changed.height = image.height;
                        switch (this._repeat) {
                            case "no-repeat":
                                changed.width += 1;
                                changed.height += 1;
                                break;
                        }
                        if (this._scale instanceof Vector) {
                            changed.width *= this._scale.x;
                            changed.height *= this._scale.y;
                        } else {
                            changed.width *= this._scale;
                            changed.height *= this._scale;
                        }
                    }
                }
                if (this._flagScale || this._flagLoaded) {
                    if (!this._renderer.image) {
                        this._renderer.image = svg.createElement("image", styles);
                    } else {
                        svg.setAttributes(this._renderer.image, styles);
                    }
                }
                if (!this._renderer.elem) {
                    changed.id = this._id;
                    changed.patternUnits = "userSpaceOnUse";
                    this._renderer.elem = svg.createElement("pattern", changed);
                } else if (Object.keys(changed).length !== 0) {
                    svg.setAttributes(this._renderer.elem, changed);
                }
                if (this._renderer.elem.parentNode === null) {
                    domElement.defs.appendChild(this._renderer.elem);
                }
                if (this._renderer.elem && this._renderer.image && !this._renderer.appended) {
                    this._renderer.elem.appendChild(this._renderer.image);
                    this._renderer.appended = true;
                }
                return this.flagReset();
            }
        }
    };
    var Renderer2 = class extends Events {
        constructor(params) {
            super();
            this.domElement = params.domElement || svg.createElement("svg");
            this.scene = new Group();
            this.scene.parent = this;
            this.defs = svg.createElement("defs");
            this.defs._flagUpdate = false;
            this.domElement.appendChild(this.defs);
            this.domElement.defs = this.defs;
            this.domElement.style.overflow = "hidden";
        }

        setSize(width, height) {
            this.width = width;
            this.height = height;
            svg.setAttributes(this.domElement, {
                width,
                height
            });
            return this.trigger(Events.Types.resize, width, height);
        }

        render() {
            svg.group.render.call(this.scene, this.domElement);
            svg.defs.update(this.domElement);
            return this;
        }
    };
    __publicField(Renderer2, "Utils", svg);

    // src/utils/shaders.js
    var shaders = {
        create: function (gl, source, type) {
            const shader = gl.createShader(gl[type]);
            gl.shaderSource(shader, source);
            gl.compileShader(shader);
            const compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
            if (!compiled) {
                const error = gl.getShaderInfoLog(shader);
                gl.deleteShader(shader);
                throw new TwoError("unable to compile shader " + shader + ": " + error);
            }
            return shader;
        },
        types: {
            vertex: "VERTEX_SHADER",
            fragment: "FRAGMENT_SHADER"
        },
        path: {
            vertex: `
      precision mediump float;
      attribute vec2 a_position;

      uniform mat3 u_matrix;
      uniform vec2 u_resolution;
      uniform vec4 u_rect;

      varying vec2 v_textureCoords;

      void main() {
        vec2 rectCoords = (a_position * (u_rect.zw - u_rect.xy)) + u_rect.xy;
        vec2 projected = (u_matrix * vec3(rectCoords, 1.0)).xy;
        vec2 normal = projected / u_resolution;
        vec2 clipspace = (normal * 2.0) - 1.0;

        gl_Position = vec4(clipspace * vec2(1.0, -1.0), 0.0, 1.0);
        v_textureCoords = a_position;
      }
    `,
            fragment: `
      precision mediump float;

      uniform sampler2D u_image;
      varying vec2 v_textureCoords;

      void main() {
        vec4 texel = texture2D(u_image, v_textureCoords);
        if (texel.a == 0.0) {
          discard;
        }
        gl_FragColor = texel;
      }
    `
        },
        points: {
            vertex: `
      precision mediump float;
      attribute vec2 a_position;

      uniform float u_size;
      uniform mat3 u_matrix;
      uniform vec2 u_resolution;

      varying vec2 v_textureCoords;

      void main() {
        vec2 projected = (u_matrix * vec3(a_position, 1.0)).xy;
        vec2 normal = projected / u_resolution;
        vec2 clipspace = (normal * 2.0) - 1.0;

        gl_PointSize = u_size;
        gl_Position = vec4(clipspace * vec2(1.0, -1.0), 0.0, 1.0);
        v_textureCoords = a_position;
      }
    `,
            fragment: `
      precision mediump float;

      uniform sampler2D u_image;

      void main() {
        vec4 texel = texture2D(u_image, gl_PointCoord);
        if (texel.a == 0.0) {
          discard;
        }
        gl_FragColor = texel;
      }
    `
        }
    };

    // src/renderers/webgl.js
    var multiplyMatrix = Matrix2.Multiply;
    var identity = [1, 0, 0, 0, 1, 0, 0, 0, 1];
    var transformation = new NumArray(9);
    var CanvasUtils = Renderer.Utils;
    var quad = new NumArray([
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        1,
        1,
        0,
        1,
        1
    ]);
    var webgl = {
        precision: 0.9,
        isHidden: /(undefined|none|transparent)/i,
        canvas: root.document ? root.document.createElement("canvas") : {
            getContext: function () {
            }
        },
        alignments: {
            left: "start",
            middle: "center",
            right: "end"
        },
        matrix: new Matrix2(),
        group: {
            removeChild: function (child, gl) {
                if (child.children) {
                    for (let i = 0; i < child.children.length; i++) {
                        webgl.group.removeChild(child.children[i], gl);
                    }
                }
                if (child._renderer.texture) {
                    gl.deleteTexture(child._renderer.texture);
                    delete child._renderer.texture;
                }
                if (child._renderer.positionBuffer) {
                    gl.deleteBuffer(child._renderer.positionBuffer);
                    delete child._renderer.positionBuffer;
                }
            },
            render: function (gl, programs) {
                if (!this._visible) {
                    return;
                }
                this._update();
                const parent = this.parent;
                const flagParentMatrix = parent._matrix && parent._matrix.manual || parent._flagMatrix;
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                if (flagParentMatrix || flagMatrix) {
                    if (!this._renderer.matrix) {
                        this._renderer.matrix = new NumArray(9);
                    }
                    this._matrix.toTransformArray(true, transformation);
                    multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.x = this._scale.x;
                        this._renderer.scale.y = this._scale.y;
                    } else {
                        this._renderer.scale.x = this._scale;
                        this._renderer.scale.y = this._scale;
                    }
                    if (!/renderer/i.test(parent._renderer.type)) {
                        this._renderer.scale.x *= parent._renderer.scale.x;
                        this._renderer.scale.y *= parent._renderer.scale.y;
                    }
                    if (flagParentMatrix) {
                        this._flagMatrix = true;
                    }
                }
                if (this._mask) {
                    gl.clear(gl.STENCIL_BUFFER_BIT);
                    gl.enable(gl.STENCIL_TEST);
                    gl.stencilFunc(gl.ALWAYS, 1, 0);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
                    gl.colorMask(false, false, false, false);
                    webgl[this._mask._renderer.type].render.call(this._mask, gl, programs, this);
                    gl.stencilFunc(gl.EQUAL, 1, 255);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
                    gl.colorMask(true, true, true, true);
                }
                this._flagOpacity = parent._flagOpacity || this._flagOpacity;
                this._renderer.opacity = this._opacity * (parent && parent._renderer ? parent._renderer.opacity : 1);
                let i;
                if (this._flagSubtractions) {
                    for (i = 0; i < this.subtractions.length; i++) {
                        webgl.group.removeChild(this.subtractions[i], gl);
                    }
                }
                for (i = 0; i < this.children.length; i++) {
                    const child = this.children[i];
                    webgl[child._renderer.type].render.call(child, gl, programs);
                }
                if (this._mask) {
                    gl.disable(gl.STENCIL_TEST);
                }
                return this.flagReset();
            }
        },
        path: {
            updateCanvas: function (elem) {
                let prev, a, c, ux, uy, vx, vy, ar, bl, br, cl, x, y;
                let isOffset;
                const commands = elem._renderer.vertices;
                const canvas3 = this.canvas;
                const ctx = this.ctx;
                const scale = elem._renderer.scale;
                const stroke = elem._stroke;
                const linewidth = elem._linewidth;
                const fill = elem._fill;
                const opacity = elem._renderer.opacity || elem._opacity;
                const cap = elem._cap;
                const join = elem._join;
                const miter = elem._miter;
                const closed2 = elem._closed;
                const dashes = elem.dashes;
                const length = commands.length;
                const last = length - 1;
                canvas3.width = Math.max(Math.ceil(elem._renderer.rect.width * scale.x), 1);
                canvas3.height = Math.max(Math.ceil(elem._renderer.rect.height * scale.y), 1);
                const centroid = elem._renderer.rect.centroid;
                const cx = centroid.x;
                const cy = centroid.y;
                ctx.clearRect(0, 0, canvas3.width, canvas3.height);
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        webgl[fill._renderer.type].render.call(fill, ctx, elem);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        webgl[stroke._renderer.type].render.call(stroke, ctx, elem);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth;
                    }
                    if (miter) {
                        ctx.miterLimit = miter;
                    }
                    if (join) {
                        ctx.lineJoin = join;
                    }
                    if (!closed2 && cap) {
                        ctx.lineCap = cap;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                let d, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, ax, ay;
                ctx.save();
                ctx.scale(scale.x, scale.y);
                ctx.translate(cx, cy);
                ctx.beginPath();
                for (let i = 0; i < commands.length; i++) {
                    const b = commands[i];
                    x = b.x;
                    y = b.y;
                    switch (b.command) {
                        case Commands.close:
                            ctx.closePath();
                            break;
                        case Commands.arc:
                            rx = b.rx;
                            ry = b.ry;
                            xAxisRotation = b.xAxisRotation;
                            largeArcFlag = b.largeArcFlag;
                            sweepFlag = b.sweepFlag;
                            prev = closed2 ? mod(i - 1, length) : Math.max(i - 1, 0);
                            a = commands[prev];
                            ax = a.x;
                            ay = a.y;
                            CanvasUtils.renderSvgArcCommand(ctx, ax, ay, rx, ry, largeArcFlag, sweepFlag, xAxisRotation, x, y);
                            break;
                        case Commands.curve:
                            prev = closed2 ? mod(i - 1, length) : Math.max(i - 1, 0);
                            a = commands[prev];
                            ar = a.controls && a.controls.right || Vector.zero;
                            bl = b.controls && b.controls.left || Vector.zero;
                            if (a._relative) {
                                vx = ar.x + a.x;
                                vy = ar.y + a.y;
                            } else {
                                vx = ar.x;
                                vy = ar.y;
                            }
                            if (b._relative) {
                                ux = bl.x + b.x;
                                uy = bl.y + b.y;
                            } else {
                                ux = bl.x;
                                uy = bl.y;
                            }
                            ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
                            if (i >= last && closed2) {
                                c = d;
                                br = b.controls && b.controls.right || Vector.zero;
                                cl = c.controls && c.controls.left || Vector.zero;
                                if (b._relative) {
                                    vx = br.x + b.x;
                                    vy = br.y + b.y;
                                } else {
                                    vx = br.x;
                                    vy = br.y;
                                }
                                if (c._relative) {
                                    ux = cl.x + c.x;
                                    uy = cl.y + c.y;
                                } else {
                                    ux = cl.x;
                                    uy = cl.y;
                                }
                                x = c.x;
                                y = c.y;
                                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
                            }
                            break;
                        case Commands.line:
                            ctx.lineTo(x, y);
                            break;
                        case Commands.move:
                            d = b;
                            ctx.moveTo(x, y);
                            break;
                    }
                }
                if (closed2) {
                    ctx.closePath();
                }
                if (!webgl.isHidden.test(fill)) {
                    isOffset = fill._renderer && fill._renderer.offset;
                    if (isOffset) {
                        ctx.save();
                        ctx.translate(
                            -fill._renderer.offset.x,
                            -fill._renderer.offset.y
                        );
                        ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
                    }
                    ctx.fill();
                    if (isOffset) {
                        ctx.restore();
                    }
                }
                if (!webgl.isHidden.test(stroke)) {
                    isOffset = stroke._renderer && stroke._renderer.offset;
                    if (isOffset) {
                        ctx.save();
                        ctx.translate(
                            -stroke._renderer.offset.x,
                            -stroke._renderer.offset.y
                        );
                        ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
                        ctx.lineWidth = linewidth / stroke._renderer.scale.x;
                    }
                    ctx.stroke();
                    if (isOffset) {
                        ctx.restore();
                    }
                }
                ctx.restore();
            },
            getBoundingClientRect: function (vertices, border, rect) {
                let left = Infinity, right = -Infinity, top = Infinity, bottom = -Infinity, width, height;
                vertices.forEach(function (v) {
                    const x = v.x, y = v.y, controls = v.controls;
                    let a, b, c, d, cl, cr;
                    top = Math.min(y, top);
                    left = Math.min(x, left);
                    right = Math.max(x, right);
                    bottom = Math.max(y, bottom);
                    if (!v.controls) {
                        return;
                    }
                    cl = controls.left;
                    cr = controls.right;
                    if (!cl || !cr) {
                        return;
                    }
                    a = v._relative ? cl.x + x : cl.x;
                    b = v._relative ? cl.y + y : cl.y;
                    c = v._relative ? cr.x + x : cr.x;
                    d = v._relative ? cr.y + y : cr.y;
                    if (!a || !b || !c || !d) {
                        return;
                    }
                    top = Math.min(b, d, top);
                    left = Math.min(a, c, left);
                    right = Math.max(a, c, right);
                    bottom = Math.max(b, d, bottom);
                });
                if (typeof border === "number") {
                    top -= border;
                    left -= border;
                    right += border;
                    bottom += border;
                }
                width = right - left;
                height = bottom - top;
                rect.top = top;
                rect.left = left;
                rect.right = right;
                rect.bottom = bottom;
                rect.width = width;
                rect.height = height;
                if (!rect.centroid) {
                    rect.centroid = {};
                }
                rect.centroid.x = -left;
                rect.centroid.y = -top;
            },
            render: function (gl, programs, forcedParent) {
                if (!this._visible || !this._opacity) {
                    return this;
                }
                this._update();
                const parent = forcedParent || this.parent;
                const program = programs[this._renderer.type];
                const flagParentMatrix = parent._matrix.manual || parent._flagMatrix;
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                const parentChanged = this._renderer.parent !== parent;
                const flagTexture = this._flagVertices || this._flagFill || this._fill instanceof LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints) || this._fill instanceof RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal) || this._fill instanceof Texture && (this._fill._flagLoaded && this._fill.loaded || this._fill._flagImage || this._fill._flagVideo || this._fill._flagRepeat || this._fill._flagOffset || this._fill._flagScale) || this._stroke instanceof LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints) || this._stroke instanceof RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal) || this._stroke instanceof Texture && (this._stroke._flagLoaded && this._stroke.loaded || this._stroke._flagImage || this._stroke._flagVideo || this._stroke._flagRepeat || this._stroke._flagOffset || this._fill._flagScale) || this._flagStroke || this._flagLinewidth || this._flagOpacity || parent._flagOpacity || this._flagVisible || this._flagCap || this._flagJoin || this._flagMiter || this._flagScale || this.dashes && this.dashes.length > 0 || !this._renderer.texture;
                if (flagParentMatrix || flagMatrix || parentChanged) {
                    if (!this._renderer.matrix) {
                        this._renderer.matrix = new NumArray(9);
                    }
                    this._matrix.toTransformArray(true, transformation);
                    multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.x = this._scale.x * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale.y * parent._renderer.scale.y;
                    } else {
                        this._renderer.scale.x = this._scale * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale * parent._renderer.scale.y;
                    }
                    if (parentChanged) {
                        this._renderer.parent = parent;
                    }
                }
                if (this._mask) {
                    gl.clear(gl.STENCIL_BUFFER_BIT);
                    gl.enable(gl.STENCIL_TEST);
                    gl.stencilFunc(gl.ALWAYS, 1, 0);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
                    gl.colorMask(false, false, false, false);
                    webgl[this._mask._renderer.type].render.call(this._mask, gl, programs, this);
                    gl.stencilFunc(gl.EQUAL, 1, 255);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
                    gl.colorMask(true, true, true, true);
                }
                if (flagTexture) {
                    if (!this._renderer.rect) {
                        this._renderer.rect = {};
                    }
                    this._renderer.opacity = this._opacity * parent._renderer.opacity;
                    webgl.path.getBoundingClientRect(
                        this._renderer.vertices,
                        this._linewidth,
                        this._renderer.rect
                    );
                    webgl.updateTexture.call(webgl, gl, this);
                } else {
                    if (this._fill && this._fill._update) {
                        this._fill._update();
                    }
                    if (this._stroke && this._stroke._update) {
                        this._stroke._update();
                    }
                }
                if (this._clip && !forcedParent || !this._renderer.texture) {
                    return this;
                }
                if (programs.current !== program) {
                    gl.useProgram(program);
                    gl.bindBuffer(gl.ARRAY_BUFFER, programs.buffers.position);
                    gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
                    gl.enableVertexAttribArray(program.position);
                    gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);
                    if (!programs.resolution.flagged) {
                        gl.uniform2f(
                            gl.getUniformLocation(program, "u_resolution"),
                            programs.resolution.width,
                            programs.resolution.height
                        );
                    }
                    programs.current = program;
                }
                if (programs.resolution.flagged) {
                    gl.uniform2f(
                        gl.getUniformLocation(program, "u_resolution"),
                        programs.resolution.width,
                        programs.resolution.height
                    );
                }
                gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);
                const rect = this._renderer.rect;
                gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);
                gl.uniform4f(program.rect, rect.left, rect.top, rect.right, rect.bottom);
                gl.drawArrays(gl.TRIANGLES, 0, 6);
                if (this._mask) {
                    gl.disable(gl.STENCIL_TEST);
                }
                return this.flagReset();
            }
        },
        points: {
            updateCanvas: function (elem) {
                let isOffset;
                const canvas3 = this.canvas;
                const ctx = this.ctx;
                const stroke = elem._stroke;
                const linewidth = elem._linewidth;
                const fill = elem._fill;
                const opacity = elem._renderer.opacity || elem._opacity;
                const dashes = elem.dashes;
                const size = elem._size;
                let dimension = size;
                if (!webgl.isHidden.test(stroke)) {
                    dimension += linewidth;
                }
                canvas3.width = getPoT(dimension);
                canvas3.height = canvas3.width;
                const aspect = dimension / canvas3.width;
                const cx = canvas3.width / 2;
                const cy = canvas3.height / 2;
                ctx.clearRect(0, 0, canvas3.width, canvas3.height);
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        webgl[fill._renderer.type].render.call(fill, ctx, elem);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        webgl[stroke._renderer.type].render.call(stroke, ctx, elem);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth / aspect;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                ctx.save();
                ctx.translate(cx, cy);
                ctx.scale(webgl.precision, webgl.precision);
                ctx.beginPath();
                ctx.arc(0, 0, size / aspect * 0.5, 0, TWO_PI);
                ctx.restore();
                if (closed) {
                    ctx.closePath();
                }
                if (!webgl.isHidden.test(fill)) {
                    isOffset = fill._renderer && fill._renderer.offset;
                    if (isOffset) {
                        ctx.save();
                        ctx.translate(
                            -fill._renderer.offset.x,
                            -fill._renderer.offset.y
                        );
                        ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
                    }
                    ctx.fill();
                    if (isOffset) {
                        ctx.restore();
                    }
                }
                if (!webgl.isHidden.test(stroke)) {
                    isOffset = stroke._renderer && stroke._renderer.offset;
                    if (isOffset) {
                        ctx.save();
                        ctx.translate(
                            -stroke._renderer.offset.x,
                            -stroke._renderer.offset.y
                        );
                        ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
                        ctx.lineWidth = linewidth / stroke._renderer.scale.x;
                    }
                    ctx.stroke();
                    if (isOffset) {
                        ctx.restore();
                    }
                }
            },
            render: function (gl, programs, forcedParent) {
                if (!this._visible || !this._opacity) {
                    return this;
                }
                this._update();
                let size = this._size;
                const parent = forcedParent || this.parent;
                const program = programs[this._renderer.type];
                const sizeAttenuation = this._sizeAttenuation;
                const stroke = this._stroke;
                const linewidth = this._linewidth;
                const flagParentMatrix = parent._matrix.manual || parent._flagMatrix;
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                const parentChanged = this._renderer.parent !== parent;
                const commands = this._renderer.vertices;
                const length = this._renderer.collection.length;
                const flagVertices = this._flagVertices;
                const flagTexture = this._flagFill || this._fill instanceof LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints) || this._fill instanceof RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal) || this._fill instanceof Texture && (this._fill._flagLoaded && this._fill.loaded || this._fill._flagImage || this._fill._flagVideo || this._fill._flagRepeat || this._fill._flagOffset || this._fill._flagScale) || this._stroke instanceof LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints) || this._stroke instanceof RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal) || this._stroke instanceof Texture && (this._stroke._flagLoaded && this._stroke.loaded || this._stroke._flagImage || this._stroke._flagVideo || this._stroke._flagRepeat || this._stroke._flagOffset || this._fill._flagScale) || this._flagStroke || this._flagLinewidth || this._flagOpacity || parent._flagOpacity || this._flagVisible || this._flagScale || this.dashes && this.dashes.length > 0 || !this._renderer.texture;
                if (flagParentMatrix || flagMatrix || parentChanged) {
                    if (!this._renderer.matrix) {
                        this._renderer.matrix = new NumArray(9);
                    }
                    this._matrix.toTransformArray(true, transformation);
                    multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.x = this._scale.x * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale.y * parent._renderer.scale.y;
                    } else {
                        this._renderer.scale.x = this._scale * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale * parent._renderer.scale.y;
                    }
                    if (parentChanged) {
                        this._renderer.parent = parent;
                    }
                }
                if (flagVertices) {
                    const positionBuffer = this._renderer.positionBuffer;
                    if (positionBuffer) {
                        gl.deleteBuffer(positionBuffer);
                    }
                    this._renderer.positionBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.positionBuffer);
                    gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
                    gl.enableVertexAttribArray(program.position);
                    gl.bufferData(gl.ARRAY_BUFFER, commands, gl.STATIC_DRAW);
                }
                if (flagTexture) {
                    this._renderer.opacity = this._opacity * parent._renderer.opacity;
                    webgl.updateTexture.call(webgl, gl, this);
                } else {
                    if (this._fill && this._fill._update) {
                        this._fill._update();
                    }
                    if (this._stroke && this._stroke._update) {
                        this._stroke._update();
                    }
                }
                if (this._clip && !forcedParent || !this._renderer.texture) {
                    return this;
                }
                if (!webgl.isHidden.test(stroke)) {
                    size += linewidth;
                }
                size /= webgl.precision;
                if (sizeAttenuation) {
                    size *= Math.max(this._renderer.scale.x, this._renderer.scale.y);
                }
                if (programs.current !== program) {
                    gl.useProgram(program);
                    if (!programs.resolution.flagged) {
                        gl.uniform2f(
                            gl.getUniformLocation(program, "u_resolution"),
                            programs.resolution.width,
                            programs.resolution.height
                        );
                    }
                    programs.current = program;
                }
                if (programs.resolution.flagged) {
                    gl.uniform2f(
                        gl.getUniformLocation(program, "u_resolution"),
                        programs.resolution.width,
                        programs.resolution.height
                    );
                }
                gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);
                gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);
                gl.uniform1f(program.size, size * programs.resolution.ratio);
                gl.drawArrays(gl.POINTS, 0, length);
                return this.flagReset();
            }
        },
        text: {
            updateCanvas: function (elem) {
                const canvas3 = this.canvas;
                const ctx = this.ctx;
                const scale = elem._renderer.scale;
                const stroke = elem._stroke;
                const linewidth = elem._linewidth * scale;
                const fill = elem._fill;
                const opacity = elem._renderer.opacity || elem._opacity;
                const dashes = elem.dashes;
                const decoration = elem._decoration;
                canvas3.width = Math.max(Math.ceil(elem._renderer.rect.width * scale.x), 1);
                canvas3.height = Math.max(Math.ceil(elem._renderer.rect.height * scale.y), 1);
                const centroid = elem._renderer.rect.centroid;
                const cx = centroid.x;
                const cy = centroid.y;
                let a, b, c, d, e, sx, sy, x1, y1, x2, y2;
                const isOffset = fill._renderer && fill._renderer.offset && stroke._renderer && stroke._renderer.offset;
                ctx.clearRect(0, 0, canvas3.width, canvas3.height);
                if (!isOffset) {
                    ctx.font = [elem._style, elem._weight, elem._size + "px/" + elem._leading + "px", elem._family].join(" ");
                }
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";
                if (fill) {
                    if (typeof fill === "string") {
                        ctx.fillStyle = fill;
                    } else {
                        webgl[fill._renderer.type].render.call(fill, ctx, elem);
                        ctx.fillStyle = fill._renderer.effect;
                    }
                }
                if (stroke) {
                    if (typeof stroke === "string") {
                        ctx.strokeStyle = stroke;
                    } else {
                        webgl[stroke._renderer.type].render.call(stroke, ctx, elem);
                        ctx.strokeStyle = stroke._renderer.effect;
                    }
                    if (linewidth) {
                        ctx.lineWidth = linewidth;
                    }
                }
                if (typeof opacity === "number") {
                    ctx.globalAlpha = opacity;
                }
                if (dashes && dashes.length > 0) {
                    ctx.lineDashOffset = dashes.offset || 0;
                    ctx.setLineDash(dashes);
                }
                ctx.save();
                ctx.scale(scale.x, scale.y);
                ctx.translate(cx, cy);
                if (!webgl.isHidden.test(fill)) {
                    if (fill._renderer && fill._renderer.offset) {
                        sx = fill._renderer.scale.x;
                        sy = fill._renderer.scale.y;
                        ctx.save();
                        ctx.translate(
                            -fill._renderer.offset.x,
                            -fill._renderer.offset.y
                        );
                        ctx.scale(sx, sy);
                        a = elem._size / fill._renderer.scale.y;
                        b = elem._leading / fill._renderer.scale.y;
                        ctx.font = [
                            elem._style,
                            elem._weight,
                            a + "px/",
                            b + "px",
                            elem._family
                        ].join(" ");
                        c = fill._renderer.offset.x / fill._renderer.scale.x;
                        d = fill._renderer.offset.y / fill._renderer.scale.y;
                        ctx.fillText(elem.value, c, d);
                        ctx.restore();
                    } else {
                        ctx.fillText(elem.value, 0, 0);
                    }
                }
                if (!webgl.isHidden.test(stroke)) {
                    if (stroke._renderer && stroke._renderer.offset) {
                        sx = stroke._renderer.scale.x;
                        sy = stroke._renderer.scale.y;
                        ctx.save();
                        ctx.translate(
                            -stroke._renderer.offset.x,
                            -stroke._renderer.offset.y
                        );
                        ctx.scale(sx, sy);
                        a = elem._size / stroke._renderer.scale.y;
                        b = elem._leading / stroke._renderer.scale.y;
                        ctx.font = [
                            elem._style,
                            elem._weight,
                            a + "px/",
                            b + "px",
                            elem._family
                        ].join(" ");
                        c = stroke._renderer.offset.x / stroke._renderer.scale.x;
                        d = stroke._renderer.offset.y / stroke._renderer.scale.y;
                        e = linewidth / stroke._renderer.scale.x;
                        ctx.lineWidth = e;
                        ctx.strokeText(elem.value, c, d);
                        ctx.restore();
                    } else {
                        ctx.strokeText(elem.value, 0, 0);
                    }
                }
                if (/(underline|strikethrough)/i.test(decoration)) {
                    const metrics = ctx.measureText(elem.value);
                    switch (decoration) {
                        case "underline":
                            y1 = metrics.actualBoundingBoxAscent;
                            y2 = metrics.actualBoundingBoxAscent;
                            break;
                        case "strikethrough":
                            y1 = 0;
                            y2 = 0;
                            break;
                    }
                    x1 = -metrics.width / 2;
                    x2 = metrics.width / 2;
                    ctx.lineWidth = Math.max(Math.floor(elem._size / 15), 1);
                    ctx.strokeStyle = ctx.fillStyle;
                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.stroke();
                }
                ctx.restore();
            },
            getBoundingClientRect: function (elem, rect) {
                const ctx = webgl.ctx;
                ctx.font = [elem._style, elem._weight, elem._size + "px/" + elem._leading + "px", elem._family].join(" ");
                ctx.textAlign = "center";
                ctx.textBaseline = elem._baseline;
                let width = ctx.measureText(elem._value).width * 1.25;
                let height = Math.max(elem._size, elem._leading) * 1.25;
                if (this._linewidth && !webgl.isHidden.test(this._stroke)) {
                    width += this._linewidth * 2;
                    height += this._linewidth * 2;
                }
                const w = width / 2;
                const h = height / 2;
                switch (webgl.alignments[elem._alignment] || elem._alignment) {
                    case webgl.alignments.left:
                        rect.left = 0;
                        rect.right = width;
                        break;
                    case webgl.alignments.right:
                        rect.left = -width;
                        rect.right = 0;
                        break;
                    default:
                        rect.left = -w;
                        rect.right = w;
                }
                switch (elem._baseline) {
                    case "bottom":
                        rect.top = -height;
                        rect.bottom = 0;
                        break;
                    case "top":
                        rect.top = 0;
                        rect.bottom = height;
                        break;
                    default:
                        rect.top = -h;
                        rect.bottom = h;
                }
                rect.width = width;
                rect.height = height;
                if (!rect.centroid) {
                    rect.centroid = {};
                }
                rect.centroid.x = w;
                rect.centroid.y = h;
            },
            render: function (gl, programs, forcedParent) {
                if (!this._visible || !this._opacity) {
                    return this;
                }
                this._update();
                const parent = forcedParent || this.parent;
                const program = programs[this._renderer.type];
                const flagParentMatrix = parent._matrix.manual || parent._flagMatrix;
                const flagMatrix = this._matrix.manual || this._flagMatrix;
                const parentChanged = this._renderer.parent !== parent;
                const flagTexture = this._flagVertices || this._flagFill || this._fill instanceof LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints) || this._fill instanceof RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal) || this._fill instanceof Texture && (this._fill._flagLoaded && this._fill.loaded || this._fill._flagImage || this._fill._flagVideo || this._fill._flagRepeat || this._fill._flagOffset || this._fill._flagScale) || this._stroke instanceof LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints) || this._stroke instanceof RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal) || this._stroke instanceof Texture && (this._stroke._flagLoaded && this._stroke.loaded || this._stroke._flagImage || this._stroke._flagVideo || this._stroke._flagRepeat || this._stroke._flagOffset || this._fill._flagScale) || this._flagStroke || this._flagLinewidth || this._flagOpacity || parent._flagOpacity || this._flagVisible || this._flagScale || this._flagValue || this._flagFamily || this._flagSize || this._flagLeading || this._flagAlignment || this._flagBaseline || this._flagStyle || this._flagWeight || this._flagDecoration || this.dashes && this.dashes.length > 0 || !this._renderer.texture;
                if (flagParentMatrix || flagMatrix || parentChanged) {
                    if (!this._renderer.matrix) {
                        this._renderer.matrix = new NumArray(9);
                    }
                    this._matrix.toTransformArray(true, transformation);
                    multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.x = this._scale.x * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale.y * parent._renderer.scale.y;
                    } else {
                        this._renderer.scale.x = this._scale * parent._renderer.scale.x;
                        this._renderer.scale.y = this._scale * parent._renderer.scale.y;
                    }
                    if (parentChanged) {
                        this._renderer.parent = parent;
                    }
                }
                if (this._mask) {
                    gl.clear(gl.STENCIL_BUFFER_BIT);
                    gl.enable(gl.STENCIL_TEST);
                    gl.stencilFunc(gl.ALWAYS, 1, 0);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
                    gl.colorMask(false, false, false, false);
                    webgl[this._mask._renderer.type].render.call(this._mask, gl, programs, this);
                    gl.stencilFunc(gl.EQUAL, 1, 255);
                    gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
                    gl.colorMask(true, true, true, true);
                }
                if (flagTexture) {
                    if (!this._renderer.rect) {
                        this._renderer.rect = {};
                    }
                    this._renderer.opacity = this._opacity * parent._renderer.opacity;
                    webgl.text.getBoundingClientRect(this, this._renderer.rect);
                    webgl.updateTexture.call(webgl, gl, this);
                } else {
                    if (this._fill && this._fill._update) {
                        this._fill._update();
                    }
                    if (this._stroke && this._stroke._update) {
                        this._stroke._update();
                    }
                }
                if (this._clip && !forcedParent || !this._renderer.texture) {
                    return this;
                }
                if (programs.current !== program) {
                    gl.useProgram(program);
                    gl.bindBuffer(gl.ARRAY_BUFFER, programs.buffers.position);
                    gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
                    gl.enableVertexAttribArray(program.position);
                    gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);
                    if (!programs.resolution.flagged) {
                        gl.uniform2f(
                            gl.getUniformLocation(program, "u_resolution"),
                            programs.resolution.width,
                            programs.resolution.height
                        );
                    }
                    programs.current = program;
                }
                if (programs.resolution.flagged) {
                    gl.uniform2f(
                        gl.getUniformLocation(program, "u_resolution"),
                        programs.resolution.width,
                        programs.resolution.height
                    );
                }
                gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);
                const rect = this._renderer.rect;
                gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);
                gl.uniform4f(program.rect, rect.left, rect.top, rect.right, rect.bottom);
                gl.drawArrays(gl.TRIANGLES, 0, 6);
                if (this._mask) {
                    gl.disable(gl.STENCIL_TEST);
                }
                return this.flagReset();
            }
        },
        "linear-gradient": {
            render: function (ctx, parent) {
                if (!ctx.canvas.getContext("2d") || !parent) {
                    return;
                }
                this._update();
                if (!this._renderer.effect || this._flagEndPoints || this._flagStops || this._flagUnits) {
                    let rect;
                    let lx = this.left._x;
                    let ly = this.left._y;
                    let rx = this.right._x;
                    let ry = this.right._y;
                    if (/objectBoundingBox/i.test(this._units)) {
                        rect = parent.getBoundingClientRect(true);
                        lx = (lx - 0.5) * rect.width;
                        ly = (ly - 0.5) * rect.height;
                        rx = (rx - 0.5) * rect.width;
                        ry = (ry - 0.5) * rect.height;
                    }
                    this._renderer.effect = ctx.createLinearGradient(lx, ly, rx, ry);
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        this._renderer.effect.addColorStop(stop._offset, stop._color);
                    }
                }
                return this.flagReset();
            }
        },
        "radial-gradient": {
            render: function (ctx, parent) {
                if (!ctx.canvas.getContext("2d") || !parent) {
                    return;
                }
                this._update();
                if (!this._renderer.effect || this._flagCenter || this._flagFocal || this._flagRadius || this._flagStops || this._flagUnits) {
                    let rect;
                    let cx = this.center._x;
                    let cy = this.center._y;
                    let fx = this.focal._x;
                    let fy = this.focal._y;
                    let radius = this._radius;
                    if (/objectBoundingBox/i.test(this._units)) {
                        rect = parent.getBoundingClientRect(true);
                        cx = cx * rect.width * 0.5;
                        cy = cy * rect.height * 0.5;
                        fx = fx * rect.width * 0.5;
                        fy = fy * rect.height * 0.5;
                        radius *= Math.min(rect.width, rect.height) * 0.5;
                    }
                    this._renderer.effect = ctx.createRadialGradient(
                        cx,
                        cy,
                        0,
                        fx,
                        fy,
                        radius
                    );
                    for (let i = 0; i < this.stops.length; i++) {
                        const stop = this.stops[i];
                        this._renderer.effect.addColorStop(stop._offset, stop._color);
                    }
                }
                return this.flagReset();
            }
        },
        texture: {
            render: function (ctx, elem) {
                if (!ctx.canvas.getContext("2d")) {
                    return;
                }
                this._update();
                const image = this.image;
                if ((this._flagLoaded || this._flagImage || this._flagVideo || this._flagRepeat) && this.loaded) {
                    this._renderer.effect = ctx.createPattern(image, this._repeat);
                } else if (!this._renderer.effect) {
                    return this.flagReset();
                }
                if (this._flagOffset || this._flagLoaded || this._flagScale) {
                    if (!(this._renderer.offset instanceof Vector)) {
                        this._renderer.offset = new Vector();
                    }
                    this._renderer.offset.x = -this._offset.x;
                    this._renderer.offset.y = -this._offset.y;
                    if (image) {
                        this._renderer.offset.x += image.width / 2;
                        this._renderer.offset.y += image.height / 2;
                        if (this._scale instanceof Vector) {
                            this._renderer.offset.x *= this._scale.x;
                            this._renderer.offset.y *= this._scale.y;
                        } else {
                            this._renderer.offset.x *= this._scale;
                            this._renderer.offset.y *= this._scale;
                        }
                    }
                }
                if (this._flagScale || this._flagLoaded) {
                    if (!(this._renderer.scale instanceof Vector)) {
                        this._renderer.scale = new Vector();
                    }
                    if (this._scale instanceof Vector) {
                        this._renderer.scale.copy(this._scale);
                    } else {
                        this._renderer.scale.set(this._scale, this._scale);
                    }
                }
                return this.flagReset();
            }
        },
        updateTexture: function (gl, elem) {
            this[elem._renderer.type].updateCanvas.call(webgl, elem);
            if (this.canvas.width <= 0 || this.canvas.height <= 0) {
                if (elem._renderer.texture) {
                    gl.deleteTexture(elem._renderer.texture);
                }
                delete elem._renderer.texture;
                return;
            }
            if (!elem._renderer.texture) {
                elem._renderer.texture = gl.createTexture();
            }
            gl.bindTexture(gl.TEXTURE_2D, elem._renderer.texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.canvas);
        },
        program: {
            create: function (gl, shaders2) {
                let program, linked, error;
                program = gl.createProgram();
                _.each(shaders2, function (s) {
                    gl.attachShader(program, s);
                });
                gl.linkProgram(program);
                linked = gl.getProgramParameter(program, gl.LINK_STATUS);
                if (!linked) {
                    error = gl.getProgramInfoLog(program);
                    gl.deleteProgram(program);
                    throw new TwoError("unable to link program: " + error);
                }
                return program;
            }
        },
        TextureRegistry: new Registry()
    };
    webgl.ctx = webgl.canvas.getContext("2d");
    var Renderer3 = class extends Events {
        constructor(params) {
            super();
            let gl, program, vs, fs;
            this.domElement = params.domElement || document.createElement("canvas");
            if (typeof params.offscreenElement !== "undefined") {
                webgl.canvas = params.offscreenElement;
                webgl.ctx = webgl.canvas.getContext("2d");
            }
            this.scene = new Group();
            this.scene.parent = this;
            this._renderer = {
                type: "renderer",
                matrix: new NumArray(identity),
                scale: 1,
                opacity: 1
            };
            this._flagMatrix = true;
            params = _.defaults(params || {}, {
                antialias: false,
                alpha: true,
                premultipliedAlpha: true,
                stencil: true,
                preserveDrawingBuffer: true,
                overdraw: false
            });
            this.overdraw = params.overdraw;
            gl = this.ctx = this.domElement.getContext("webgl", params) || this.domElement.getContext("experimental-webgl", params);
            if (!this.ctx) {
                throw new TwoError(
                    "unable to create a webgl context. Try using another renderer."
                );
            }
            vs = shaders.create(gl, shaders.path.vertex, shaders.types.vertex);
            fs = shaders.create(gl, shaders.path.fragment, shaders.types.fragment);
            this.programs = {
                current: null,
                buffers: {
                    position: gl.createBuffer()
                },
                resolution: {
                    width: 0,
                    height: 0,
                    ratio: 1,
                    flagged: false
                }
            };
            program = this.programs.path = webgl.program.create(gl, [vs, fs]);
            this.programs.text = this.programs.path;
            program.position = gl.getAttribLocation(program, "a_position");
            program.matrix = gl.getUniformLocation(program, "u_matrix");
            program.rect = gl.getUniformLocation(program, "u_rect");
            const positionBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(program.position);
            gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);
            vs = shaders.create(gl, shaders.points.vertex, shaders.types.vertex);
            fs = shaders.create(gl, shaders.points.fragment, shaders.types.fragment);
            program = this.programs.points = webgl.program.create(gl, [vs, fs]);
            program.position = gl.getAttribLocation(program, "a_position");
            program.matrix = gl.getUniformLocation(program, "u_matrix");
            program.size = gl.getUniformLocation(program, "u_size");
            gl.enable(gl.BLEND);
            gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
        }

        setSize(width, height, ratio) {
            let w, h;
            const ctx = this.ctx;
            this.width = width;
            this.height = height;
            this.ratio = typeof ratio === "undefined" ? getRatio(ctx) : ratio;
            this.domElement.width = width * this.ratio;
            this.domElement.height = height * this.ratio;
            if (_.isObject(this.domElement.style)) {
                _.extend(this.domElement.style, {
                    width: width + "px",
                    height: height + "px"
                });
            }
            this._renderer.matrix[0] = this._renderer.matrix[4] = this._renderer.scale = this.ratio;
            this._flagMatrix = true;
            w = width * this.ratio;
            h = height * this.ratio;
            ctx.viewport(0, 0, w, h);
            this.programs.resolution.width = w;
            this.programs.resolution.height = h;
            this.programs.resolution.ratio = this.ratio;
            this.programs.resolution.flagged = true;
            return this.trigger(Events.Types.resize, width, height, ratio);
        }

        render() {
            const gl = this.ctx;
            if (!this.overdraw) {
                gl.clear(gl.COLOR_BUFFER_BIT);
            }
            webgl.group.render.call(this.scene, gl, this.programs);
            this._flagMatrix = false;
            this.programs.resolution.flagged = true;
            return this;
        }
    };
    __publicField(Renderer3, "Utils", webgl);

    // src/two.js
    var Utils = _.extend({
        Error: TwoError,
        getRatio,
        read,
        xhr
    }, _, CanvasShim, curves_exports, math_exports);
    var _Two = class {
        _events = new Events();

        get _bound() {
            return this._events._bound;
        }

        set _bound(v) {
            this._events._bound = v;
        }

        addEventListener() {
            return this._events.addEventListener.apply(this, arguments);
        }

        on() {
            return this._events.addEventListener.apply(this, arguments);
        }

        bind() {
            return this._events.addEventListener.apply(this, arguments);
        }

        removeEventListener() {
            return this._events.removeEventListener.apply(this, arguments);
        }

        off() {
            return this._events.removeEventListener.apply(this, arguments);
        }

        unbind() {
            return this._events.removeEventListener.apply(this, arguments);
        }

        dispatchEvent() {
            return this._events.dispatchEvent.apply(this, arguments);
        }

        trigger() {
            return this._events.dispatchEvent.apply(this, arguments);
        }

        listen() {
            return this._events.listen.apply(this, arguments);
        }

        ignore() {
            return this._events.ignore.apply(this, arguments);
        }

        type = "";
        renderer = null;
        scene = null;
        width = 0;
        height = 0;
        frameCount = 0;
        timeDelta = 0;
        playing = false;

        constructor(options) {
            const params = _.defaults(options || {}, {
                fullscreen: false,
                fitted: false,
                width: 640,
                height: 480,
                type: _Two.Types.svg,
                autostart: false
            });
            _.each(params, function (v, k) {
                if (/fullscreen/i.test(k) || /autostart/i.test(k)) {
                    return;
                }
                this[k] = v;
            }, this);
            if (_.isElement(params.domElement)) {
                const tagName = params.domElement.tagName.toLowerCase();
                if (!/^(CanvasRenderer-canvas|WebGLRenderer-canvas|SVGRenderer-svg)$/.test(this.type + "-" + tagName)) {
                    this.type = _Two.Types[tagName];
                }
            }
            this.renderer = new _Two[this.type](this);
            this.setPlaying(params.autostart);
            this.frameCount = 0;
            if (params.fullscreen) {
                this.fit = fitToWindow.bind(this);
                this.fit.domElement = window;
                this.fit.attached = true;
                _.extend(document.body.style, {
                    overflow: "hidden",
                    margin: 0,
                    padding: 0,
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    position: "fixed"
                });
                _.extend(this.renderer.domElement.style, {
                    display: "block",
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    position: "fixed"
                });
                dom.bind(this.fit.domElement, "resize", this.fit);
                this.fit();
            } else if (params.fitted) {
                this.fit = fitToParent.bind(this);
                _.extend(this.renderer.domElement.style, {
                    display: "block"
                });
            } else if (!_.isElement(params.domElement)) {
                this.renderer.setSize(params.width, params.height, this.ratio);
                this.width = params.width;
                this.height = params.height;
            }
            this.renderer.bind(Events.Types.resize, updateDimensions.bind(this));
            this.scene = this.renderer.scene;
            _Two.Instances.push(this);
            if (params.autostart) {
                raf.init();
            }
        }

        appendTo(elem) {
            elem.appendChild(this.renderer.domElement);
            if (this.fit) {
                if (this.fit.domElement !== window) {
                    this.fit.domElement = elem;
                    this.fit.attached = false;
                }
                this.update();
            }
            return this;
        }

        play() {
            this.playing = true;
            raf.init();
            return this.trigger(Events.Types.play);
        }

        pause() {
            this.playing = false;
            return this.trigger(Events.Types.pause);
        }

        setPlaying(p) {
            this.playing = p;
        }

        release(obj) {
            let i, v, child;
            if (!_.isObject(obj)) {
                return this.release(this.scene);
            }
            if (typeof obj.unbind === "function") {
                obj.unbind();
            }
            if (obj.vertices) {
                if (typeof obj.vertices.unbind === "function") {
                    obj.vertices.unbind();
                }
                for (i = 0; i < obj.vertices.length; i++) {
                    v = obj.vertices[i];
                    if (typeof v.unbind === "function") {
                        v.unbind();
                    }
                    if (v.controls) {
                        if (v.controls.left && typeof v.controls.left.unbind === "function") {
                            v.controls.left.unbind();
                        }
                        if (v.controls.right && typeof v.controls.right.unbind === "function") {
                            v.controls.right.unbind();
                        }
                    }
                }
            }
            if (obj.children) {
                for (i = 0; i < obj.children.length; i++) {
                    child = obj.children[i];
                    this.release(child);
                }
                if (typeof obj.children.unbind === "function") {
                    obj.children.unbind();
                }
            }
            return obj;
        }

        update() {
            const animated = !!this._lastFrame;
            const now = _.performance.now();
            if (animated) {
                this.timeDelta = parseFloat((now - this._lastFrame).toFixed(3));
            }
            this._lastFrame = now;
            if (this.fit && this.fit.domElement && !this.fit.attached) {
                dom.bind(this.fit.domElement, "resize", this.fit);
                this.fit.attached = true;
                this.fit();
            }
            const width = this.width;
            const height = this.height;
            const renderer = this.renderer;
            if (width !== renderer.width || height !== renderer.height) {
                renderer.setSize(width, height, this.ratio);
            }
            this.trigger(Events.Types.update, this.frameCount, this.timeDelta);
            return this.render();
        }

        render() {
            this.renderer.render();
            return this.trigger(Events.Types.render, this.frameCount++);
        }

        add(objects) {
            if (!(objects instanceof Array)) {
                objects = Array.prototype.slice.call(arguments);
            }
            this.scene.add(objects);
            return this;
        }

        remove(objects) {
            if (!(objects instanceof Array)) {
                objects = Array.prototype.slice.call(arguments);
            }
            this.scene.remove(objects);
            return this;
        }

        clear() {
            this.scene.remove(this.scene.children);
            return this;
        }

        makeLine(x1, y1, x2, y2) {
            const line = new Line(x1, y1, x2, y2);
            this.scene.add(line);
            return line;
        }

        makeArrow(x1, y1, x2, y2, size) {
            const headlen = typeof size === "number" ? size : 10;
            const angle = Math.atan2(y2 - y1, x2 - x1);
            const vertices = [
                new Anchor(x1, y1, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(x2, y2, void 0, void 0, void 0, void 0, Commands.line),
                new Anchor(
                    x2 - headlen * Math.cos(angle - Math.PI / 4),
                    y2 - headlen * Math.sin(angle - Math.PI / 4),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                ),
                new Anchor(x2, y2, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(
                    x2 - headlen * Math.cos(angle + Math.PI / 4),
                    y2 - headlen * Math.sin(angle + Math.PI / 4),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                )
            ];
            const path = new Path(vertices, false, false, true);
            path.noFill();
            path.cap = "round";
            path.join = "round";
            this.scene.add(path);
            return path;
        }

        /* IMN added */
        makeDobleArrow(x1, y1, x2, y2, size) {
            const headlen = typeof size === "number" ? size : 10;
            const angle = Math.atan2(y2 - y1, x2 - x1);
            const vertices = [
                new Anchor(x1, y1, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(
                    x1 + headlen * Math.cos(angle - Math.PI / 8),
                    y1 + headlen * Math.sin(angle - Math.PI / 8),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                ),
                new Anchor(x1, y1, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(
                    x1 + headlen * Math.cos(angle + Math.PI / 8),
                    y1 + headlen * Math.sin(angle + Math.PI / 8),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                ),
                new Anchor(x1, y1, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(x2, y2, void 0, void 0, void 0, void 0, Commands.line),
                new Anchor(
                    x2 - headlen * Math.cos(angle - Math.PI / 8),
                    y2 - headlen * Math.sin(angle - Math.PI / 8),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                ),
                new Anchor(x2, y2, void 0, void 0, void 0, void 0, Commands.move),
                new Anchor(
                    x2 - headlen * Math.cos(angle + Math.PI / 8),
                    y2 - headlen * Math.sin(angle + Math.PI / 8),
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    Commands.line
                )
            ];
            const path = new Path(vertices, false, false, true);
            path.noFill();
            path.cap = "round";
            path.join = "round";
            this.scene.add(path);
            return path;
        }

        makeRectangle(x, y, width, height) {
            const rect = new Rectangle(x, y, width, height);
            this.scene.add(rect);
            return rect;
        }

        makeRoundedRectangle(x, y, width, height, sides) {
            const rect = new RoundedRectangle(x, y, width, height, sides);
            this.scene.add(rect);
            return rect;
        }

        makeCircle(x, y, radius, resolution) {
            const circle = new Circle(x, y, radius, resolution);
            this.scene.add(circle);
            return circle;
        }

        makeEllipse(x, y, rx, ry, resolution) {
            const ellipse = new Ellipse(x, y, rx, ry, resolution);
            this.scene.add(ellipse);
            return ellipse;
        }

        makeStar(x, y, outerRadius, innerRadius, sides) {
            const star = new Star(x, y, outerRadius, innerRadius, sides);
            this.scene.add(star);
            return star;
        }

        makeCurve(points) {
            const l = arguments.length;
            if (!Array.isArray(points)) {
                points = [];
                for (let i = 0; i < l; i += 2) {
                    const x = arguments[i];
                    if (typeof x !== "number") {
                        break;
                    }
                    const y = arguments[i + 1];
                    points.push(new Anchor(x, y));
                }
            }
            const last = arguments[l - 1];
            const curve = new Path(points, !(typeof last === "boolean" ? last : void 0), true);
            const rect = curve.getBoundingClientRect();
            curve.center().translation.set(rect.left + rect.width / 2, rect.top + rect.height / 2);
            this.scene.add(curve);
            return curve;
        }

        makePolygon(x, y, radius, sides) {
            const poly = new Polygon(x, y, radius, sides);
            this.scene.add(poly);
            return poly;
        }

        makeArcSegment(x, y, innerRadius, outerRadius, startAngle, endAngle, resolution) {
            const arcSegment = new ArcSegment(
                x,
                y,
                innerRadius,
                outerRadius,
                startAngle,
                endAngle,
                resolution
            );
            this.scene.add(arcSegment);
            return arcSegment;
        }

        makePoints(p) {
            const l = arguments.length;
            let vertices = p;
            if (!Array.isArray(p)) {
                vertices = [];
                for (let i = 0; i < l; i += 2) {
                    const x = arguments[i];
                    if (typeof x !== "number") {
                        break;
                    }
                    const y = arguments[i + 1];
                    vertices.push(new Vector(x, y));
                }
            }
            const points = new Points(vertices);
            this.scene.add(points);
            return points;
        }

        makePath(p) {
            const l = arguments.length;
            let points = p;
            if (!Array.isArray(p)) {
                points = [];
                for (let i = 0; i < l; i += 2) {
                    const x = arguments[i];
                    if (typeof x !== "number") {
                        break;
                    }
                    const y = arguments[i + 1];
                    points.push(new Anchor(x, y));
                }
            }
            const last = arguments[l - 1];
            const path = new Path(points, !(typeof last === "boolean" ? last : void 0));
            const rect = path.getBoundingClientRect();
            if (typeof rect.top === "number" && typeof rect.left === "number" && typeof rect.right === "number" && typeof rect.bottom === "number") {
                path.center().translation.set(rect.left + rect.width / 2, rect.top + rect.height / 2);
            }
            this.scene.add(path);
            return path;
        }

        makeText(message, x, y, styles) {
            const text = new Text(message, x, y, styles);
            this.add(text);
            return text;
        }

        makeLinearGradient(x1, y1, x2, y2) {
            const stops = Array.prototype.slice.call(arguments, 4);
            const gradient = new LinearGradient(x1, y1, x2, y2, stops);
            this.add(gradient);
            return gradient;
        }

        makeRadialGradient(x1, y1, radius) {
            const stops = Array.prototype.slice.call(arguments, 3);
            const gradient = new RadialGradient(x1, y1, radius, stops);
            this.add(gradient);
            return gradient;
        }

        makeSprite(pathOrTexture, x, y, columns, rows, frameRate, autostart) {
            const sprite = new Sprite(pathOrTexture, x, y, columns, rows, frameRate);
            if (autostart) {
                sprite.play();
            }
            this.add(sprite);
            return sprite;
        }

        makeImageSequence(pathsOrTextures, x, y, frameRate, autostart) {
            const imageSequence = new ImageSequence(pathsOrTextures, x, y, frameRate);
            if (autostart) {
                imageSequence.play();
            }
            this.add(imageSequence);
            return imageSequence;
        }

        makeTexture(pathOrSource, callback) {
            const texture = new Texture(pathOrSource, callback);
            return texture;
        }

        makeGroup(objects) {
            if (!(objects instanceof Array)) {
                objects = Array.prototype.slice.call(arguments);
            }
            const group = new Group();
            this.scene.add(group);
            group.add(objects);
            return group;
        }

        interpret(svg2, shallow, add) {
            const tag = svg2.tagName.toLowerCase();
            add = typeof add !== "undefined" ? add : true;
            if (!(tag in read)) {
                return null;
            }
            const node = read[tag].call(this, svg2);
            if (add) {
                this.add(shallow && node instanceof Group ? node.children : node);
            } else if (node.parent) {
                node.remove();
            }
            return node;
        }

        load(pathOrSVGContent, callback) {
            const group = new Group();
            let elem, i, child;
            const attach = function (data) {
                dom.temp.innerHTML = data;
                for (i = 0; i < dom.temp.children.length; i++) {
                    elem = dom.temp.children[i];
                    child = this.interpret(elem, false, false);
                    if (child !== null) {
                        group.add(child);
                    }
                }
                if (typeof callback === "function") {
                    const svg2 = dom.temp.children.length <= 1 ? dom.temp.children[0] : dom.temp.children;
                    callback(group, svg2);
                }
            }.bind(this);
            if (/\.svg$/i.test(pathOrSVGContent)) {
                xhr(pathOrSVGContent, attach);
                return group;
            }
            attach(pathOrSVGContent);
            return group;
        }
    };
    var Two = _Two;
    __publicField(Two, "nextFrameID", Constants.nextFrameID);
    __publicField(Two, "Types", Constants.Types);
    __publicField(Two, "Version", Constants.Version);
    __publicField(Two, "PublishDate", Constants.PublishDate);
    __publicField(Two, "Identifier", Constants.Identifier);
    __publicField(Two, "Resolution", Constants.Resolution);
    __publicField(Two, "AutoCalculateImportedMatrices", Constants.AutoCalculateImportedMatrices);
    __publicField(Two, "Instances", Constants.Instances);
    __publicField(Two, "uniqueId", Constants.uniqueId);
    __publicField(Two, "Anchor", Anchor);
    __publicField(Two, "Collection", Collection);
    __publicField(Two, "Events", Events);
    __publicField(Two, "Group", Group);
    __publicField(Two, "Matrix", Matrix2);
    __publicField(Two, "Path", Path);
    __publicField(Two, "Registry", Registry);
    __publicField(Two, "Shape", Shape);
    __publicField(Two, "Text", Text);
    __publicField(Two, "Vector", Vector);
    __publicField(Two, "Gradient", Gradient);
    __publicField(Two, "ImageSequence", ImageSequence);
    __publicField(Two, "LinearGradient", LinearGradient);
    __publicField(Two, "RadialGradient", RadialGradient);
    __publicField(Two, "Sprite", Sprite);
    __publicField(Two, "Stop", Stop);
    __publicField(Two, "Texture", Texture);
    __publicField(Two, "ArcSegment", ArcSegment);
    __publicField(Two, "Circle", Circle);
    __publicField(Two, "Ellipse", Ellipse);
    __publicField(Two, "Line", Line);
    __publicField(Two, "Points", Points);
    __publicField(Two, "Polygon", Polygon);
    __publicField(Two, "Rectangle", Rectangle);
    __publicField(Two, "RoundedRectangle", RoundedRectangle);
    __publicField(Two, "Star", Star);
    __publicField(Two, "CanvasRenderer", Renderer);
    __publicField(Two, "SVGRenderer", Renderer2);
    __publicField(Two, "WebGLRenderer", Renderer3);
    __publicField(Two, "Commands", Commands);
    __publicField(Two, "Utils", Utils);

    function fitToWindow() {
        const wr = document.body.getBoundingClientRect();
        const width = this.width = wr.width;
        const height = this.height = wr.height;
        this.renderer.setSize(width, height, this.ratio);
    }

    function fitToParent() {
        const parent = this.renderer.domElement.parentElement;
        if (!parent) {
            console.warn("Two.js: Attempting to fit to parent, but no parent found.");
            return;
        }
        const wr = parent.getBoundingClientRect();
        const width = this.width = wr.width;
        const height = this.height = wr.height;
        this.renderer.setSize(width, height, this.ratio);
    }

    function updateDimensions(width, height) {
        this.width = width;
        this.height = height;
        this.trigger(Events.Types.resize, width, height);
    }

    var raf = dom.getRequestAnimationFrame();

    function loop() {
        for (let i = 0; i < Two.Instances.length; i++) {
            const t = Two.Instances[i];
            if (t.playing) {
                t.update();
            }
        }
        Two.nextFrameID = raf(loop);
    }

    raf.init = function () {
        loop();
        raf.init = function () {
        };
    };
    return __toCommonJS(two_exports);
})().default;

(function () {
    if (typeof exports === 'object' && typeof module !== 'undefined') {
        module.exports = Two
    }
})()