import * as PropertySymbol from '../../PropertySymbol.js';
const DEFAULT_MATRIX_JSON = {
    a: 1,
    b: 0,
    c: 0,
    d: 1,
    e: 0,
    f: 0,
    m11: 1,
    m12: 0,
    m13: 0,
    m14: 0,
    m21: 0,
    m22: 1,
    m23: 0,
    m24: 0,
    m31: 0,
    m32: 0,
    m33: 1,
    m34: 0,
    m41: 0,
    m42: 0,
    m43: 0,
    m44: 1,
    is2D: true,
    isIdentity: true
};
const TRANSFORM_REGEXP = /([a-zA-Z0-9]+)\(([^)]+)\)/gm;
const TRANSFORM_PARAMETER_SPLIT_REGEXP = /[\s,]+/;
/**
 * DOM Matrix.
 *
 * Based on:
 * - https://github.com/trusktr/geometry-interfaces
 * - https://github.com/thednp/dommatrix/tree/master
 * - https://github.com/jarek-foksa/geometry-polyfill/blob/master/geometry-polyfill.js
 * - https://github.com/Automattic/node-canvas/blob/master/lib/DOMMatrix.js
 *
 *
 * 3D Matrix:
 * _________________________
 * | m11 | m21 | m31 | m41 |
 * | m12 | m22 | m32 | m42 |
 * | m13 | m23 | m33 | m43 |
 * | m14 | m24 | m34 | m44 |
 * -------------------------̣
 *
 * 2D Matrix:
 * _________________________
 * | m11 | m21 | 0   | m41 |
 * | m12 | m22 | 0   | m42 |
 * | 0   | 0   | 1   | 0   |
 * | 0   | 0   | 0   | 1   |
 * -------------------------
 *
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly
 */
export default class DOMMatrixReadOnly {
    [PropertySymbol.m11] = 1;
    [PropertySymbol.m12] = 0;
    [PropertySymbol.m13] = 0;
    [PropertySymbol.m14] = 0;
    [PropertySymbol.m21] = 0;
    [PropertySymbol.m22] = 1;
    [PropertySymbol.m23] = 0;
    [PropertySymbol.m24] = 0;
    [PropertySymbol.m31] = 0;
    [PropertySymbol.m32] = 0;
    [PropertySymbol.m33] = 1;
    [PropertySymbol.m34] = 0;
    [PropertySymbol.m41] = 0;
    [PropertySymbol.m42] = 0;
    [PropertySymbol.m43] = 0;
    [PropertySymbol.m44] = 1;
    /**
     * Constructor.
     *
     * @param init Init parameter.
     */
    constructor(init) {
        if (init) {
            this[PropertySymbol.setMatrixValue](init);
        }
    }
    /**
     * Returns the `a` value of the matrix.
     */
    get a() {
        return this[PropertySymbol.m11];
    }
    /**
     * Returns the `b` value of the matrix.
     */
    get b() {
        return this[PropertySymbol.m12];
    }
    /**
     * Returns the `c` value of the matrix.
     */
    get c() {
        return this[PropertySymbol.m21];
    }
    /**
     * Returns the `d` value of the matrix.
     */
    get d() {
        return this[PropertySymbol.m22];
    }
    /**
     * Returns the `e` value of the matrix.
     */
    get e() {
        return this[PropertySymbol.m41];
    }
    /**
     * Returns the `f` value of the matrix.
     */
    get f() {
        return this[PropertySymbol.m42];
    }
    /**
     * Returns the `m11` value of the matrix.
     */
    get m11() {
        return this[PropertySymbol.m11];
    }
    /**
     * Returns the `m12` value of the matrix.
     */
    get m12() {
        return this[PropertySymbol.m12];
    }
    /**
     * Returns the `m13` value of the matrix.
     */
    get m13() {
        return this[PropertySymbol.m13];
    }
    /**
     * Returns the `m14` value of the matrix.
     */
    get m14() {
        return this[PropertySymbol.m14];
    }
    /**
     * Returns the `m21` value of the matrix.
     */
    get m21() {
        return this[PropertySymbol.m21];
    }
    /**
     * Returns the `m22` value of the matrix.
     */
    get m22() {
        return this[PropertySymbol.m22];
    }
    /**
     * Returns the `m23` value of the matrix.
     */
    get m23() {
        return this[PropertySymbol.m23];
    }
    /**
     * Returns the `m24` value of the matrix.
     */
    get m24() {
        return this[PropertySymbol.m24];
    }
    /**
     * Returns the `m31` value of the matrix.
     */
    get m31() {
        return this[PropertySymbol.m31];
    }
    /**
     * Returns the `m32` value of the matrix.
     */
    get m32() {
        return this[PropertySymbol.m32];
    }
    /**
     * Returns the `m33` value of the matrix.
     */
    get m33() {
        return this[PropertySymbol.m33];
    }
    /**
     * Returns the `m34` value of the matrix.
     */
    get m34() {
        return this[PropertySymbol.m34];
    }
    /**
     * Returns the `m41` value of the matrix.
     */
    get m41() {
        return this[PropertySymbol.m41];
    }
    /**
     * Returns the `m42` value of the matrix.
     */
    get m42() {
        return this[PropertySymbol.m42];
    }
    /**
     * Returns the `m43` value of the matrix.
     */
    get m43() {
        return this[PropertySymbol.m43];
    }
    /**
     * Returns the `m44` value of the matrix.
     */
    get m44() {
        return this[PropertySymbol.m44];
    }
    /**
     * A `Boolean` whose value is `true` if the matrix is the identity matrix.
     *
     * The identity matrix is one in which every value is 0 except those on the main diagonal from top-left to bottom-right corner (in other words, where the offsets in each direction are equal).
     *
     * @returns "true" if the matrix is the identity matrix.
     */
    get isIdentity() {
        return (this[PropertySymbol.m11] === 1 &&
            this[PropertySymbol.m12] === 0 &&
            this[PropertySymbol.m13] === 0 &&
            this[PropertySymbol.m14] === 0 &&
            this[PropertySymbol.m21] === 0 &&
            this[PropertySymbol.m22] === 1 &&
            this[PropertySymbol.m23] === 0 &&
            this[PropertySymbol.m24] === 0 &&
            this[PropertySymbol.m31] === 0 &&
            this[PropertySymbol.m32] === 0 &&
            this[PropertySymbol.m33] === 1 &&
            this[PropertySymbol.m34] === 0 &&
            this[PropertySymbol.m41] === 0 &&
            this[PropertySymbol.m42] === 0 &&
            this[PropertySymbol.m43] === 0 &&
            this[PropertySymbol.m44] === 1);
    }
    /**
     * A `Boolean` flag whose value is `true` if the matrix is a 2D matrix and `false` if the matrix is 3D.
     *
     * @returns "true" if the matrix is a 2D matrix.
     */
    get is2D() {
        return (this[PropertySymbol.m31] === 0 &&
            this[PropertySymbol.m32] === 0 &&
            this[PropertySymbol.m33] === 1 &&
            this[PropertySymbol.m34] === 0 &&
            this[PropertySymbol.m43] === 0 &&
            this[PropertySymbol.m44] === 1);
    }
    /**
     * Returns a *Float32Array* containing elements which comprise the matrix.
     *
     * The method can return either the 16 elements or the 6 elements depending on the value of the `is2D` parameter.
     *
     * @param [is2D] Set to `true` to return a 2D matrix.
     * @returns An *Array* representation of the matrix.
     */
    toFloat32Array(is2D) {
        return Float32Array.from(this[PropertySymbol.toArray](is2D));
    }
    /**
     * Returns a *Float64Array* containing elements which comprise the matrix.
     *
     * The method can return either the 16 elements or the 6 elements depending on the value of the `is2D` parameter.
     *
     * @param [is2D] Set to `true` to return a 2D matrix.
     * @returns An *Array* representation of the matrix
     */
    toFloat64Array(is2D) {
        return Float64Array.from(this[PropertySymbol.toArray](is2D));
    }
    /**
     * Returns a string representation of the matrix in `CSS` matrix syntax, using the appropriate `CSS` matrix notation.
     *
     * Examples:
     * - `matrix3d(m11, m12, m13, m14, m21, ...)`
     * - `matrix(a, b, c, d, e, f)`
     *
     * @returns A string representation of the matrix.
     */
    toString() {
        const is2D = this.is2D;
        const values = this[PropertySymbol.toArray](is2D).join(', ');
        const type = is2D ? 'matrix' : 'matrix3d';
        return `${type}(${values})`;
    }
    /**
     * Returns an Object that can be serialized to a JSON string.
     *
     * The result can be used as a second parameter for the `fromMatrix` static method to load values into another matrix instance.
     *
     * @returns An *Object* with matrix values.
     */
    toJSON() {
        const { is2D, isIdentity } = this;
        return {
            m11: this[PropertySymbol.m11],
            m12: this[PropertySymbol.m12],
            m13: this[PropertySymbol.m13],
            m14: this[PropertySymbol.m14],
            m21: this[PropertySymbol.m21],
            m22: this[PropertySymbol.m22],
            m23: this[PropertySymbol.m23],
            m24: this[PropertySymbol.m24],
            m31: this[PropertySymbol.m31],
            m32: this[PropertySymbol.m32],
            m33: this[PropertySymbol.m33],
            m34: this[PropertySymbol.m34],
            m41: this[PropertySymbol.m41],
            m42: this[PropertySymbol.m42],
            m43: this[PropertySymbol.m43],
            m44: this[PropertySymbol.m44],
            a: this[PropertySymbol.m11],
            b: this[PropertySymbol.m12],
            c: this[PropertySymbol.m21],
            d: this[PropertySymbol.m22],
            e: this[PropertySymbol.m41],
            f: this[PropertySymbol.m42],
            is2D,
            isIdentity
        };
    }
    /**
     * Returns a new DOMMatrix instance which is the result of this matrix multiplied by the passed matrix.
     *
     * @param secondMatrix DOMMatrix
     * @returns A new DOMMatrix object.
     */
    multiply(secondMatrix) {
        const matrix = new this.constructor(this);
        if (secondMatrix) {
            matrix[PropertySymbol.multiplySelf](secondMatrix);
        }
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a translation matrix containing the passed values.
     *
     * @param [x=0] X component of the translation value.
     * @param [y=0] Y component of the translation value.
     * @param [z=0] Z component of the translation value.
     * @returns The resulted matrix
     */
    translate(x = 0, y = 0, z = 0) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.translateSelf](x, y, z);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a scale 2D matrix containing the passed values.
     *
     * @param [scaleX] X-Axis scale.
     * @param [scaleY] Y-Axis scale.
     * @param [scaleZ] Z-Axis scale.
     * @param [originX] X-Axis scale.
     * @param [originY] Y-Axis scale.
     * @param [originZ] Z-Axis scale.
     * @returns The resulted matrix
     */
    scale(scaleX, scaleY, scaleZ = 1, originX = 0, originY = 0, originZ = 0) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.scaleSelf](scaleX, scaleY, scaleZ, originX, originY, originZ);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a scale 3D matrix containing the passed values.
     *
     * @param [scale] The scale factor.
     * @param [originX] X-Axis scale.
     * @param [originY] Y-Axis scale.
     * @param [originZ] Z-Axis scale.
     * @returns The resulted matrix
     */
    scale3d(scale = 1, originX = 0, originY = 0, originZ = 0) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.scale3dSelf](scale, originX, originY, originZ);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a scale 3D matrix containing the passed values.
     *
     * @param [scaleX] X-Axis scale.
     * @param [scaleY] Y-Axis scale.
     * @returns The resulted matrix
     */
    scaleNonUniform(scaleX = 1, scaleY = 1) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.scaleNonUniformSelf](scaleX, scaleY);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a rotation matrix with the given axis and `angle`.
     *
     * @param [x] The X component of the axis vector.
     * @param [y] The Y component of the axis vector.
     * @param [z] The Z component of the axis vector.
     * @param [angle] Angle of rotation about the axis vector, in degrees.
     * @returns The resulted matrix
     */
    rotateAxisAngle(x = 0, y = 0, z = 0, angle = 0) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.rotateAxisAngleSelf](x, y, z, angle);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by each of 3 rotation matrices about the major axes, first X, then Y, then Z.
     *
     * @param [x] X component of the rotation, or Z if Y and Z are null.
     * @param [y] Y component of the rotation value.
     * @param [z] Z component of the rotation value.
     * @returns The resulted matrix
     */
    rotate(x = 0, y, z) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.rotateSelf](x, y, z);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix post multiplied by a rotation matrix with the angle between the specified vector and (1, 0).
     *
     * @param [x] X-Axis skew.
     * @param [y] Y-Axis skew.
     */
    rotateFromVector(x = 0, y = 0) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.rotateFromVectorSelf](x, y);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance that specifies a skew transformation along X-Axis by the given angle.
     *
     * @param angle Angle amount in degrees to skew.
     * @returns The resulted matrix
     */
    skewX(angle) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.skewXSelf](angle);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance that specifies a skew transformation along Y-Axis by the given angle.
     *
     * @param angle Angle amount in degrees to skew.
     * @returns The resulted matrix
     */
    skewY(angle) {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.skewYSelf](angle);
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix flipped on X-axis.
     */
    flipX() {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.flipXSelf]();
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix flipped on Y-axis.
     */
    flipY() {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.flipYSelf]();
        return matrix;
    }
    /**
     * Returns a new DOMMatrix instance which is this matrix inversed.
     */
    inverse() {
        const matrix = new this.constructor(this);
        matrix[PropertySymbol.invertSelf]();
        return matrix;
    }
    /**
     * Returns a new DOMPoint instance with the vector transformed using the matrix.
     *
     * @param domPoint DOM point compatible object.
     * @returns A new DOMPoint object.
     */
    transformPoint(domPoint) {
        const xPoint = domPoint?.x ?? 0;
        const yPoint = domPoint?.y ?? 0;
        const zPoint = domPoint?.z ?? 0;
        const wPoint = domPoint?.w ?? 1;
        const x = this[PropertySymbol.m11] * xPoint +
            this[PropertySymbol.m21] * yPoint +
            this[PropertySymbol.m31] * zPoint +
            this[PropertySymbol.m41] * wPoint;
        const y = this[PropertySymbol.m12] * xPoint +
            this[PropertySymbol.m22] * yPoint +
            this[PropertySymbol.m32] * zPoint +
            this[PropertySymbol.m42] * wPoint;
        const z = this[PropertySymbol.m13] * xPoint +
            this[PropertySymbol.m23] * yPoint +
            this[PropertySymbol.m33] * zPoint +
            this[PropertySymbol.m43] * wPoint;
        const w = this[PropertySymbol.m14] * xPoint +
            this[PropertySymbol.m24] * yPoint +
            this[PropertySymbol.m34] * zPoint +
            this[PropertySymbol.m44] * wPoint;
        return new this[PropertySymbol.window].DOMPoint(x, y, z, w);
    }
    /**
     * The `setMatrixValue` method replaces the existing matrix with one computed in the browser (e.g.`matrix(1,0.25,-0.25,1,0,0)`).
     *
     * @param source A `DOMMatrix`, `Float32Array`, `Float64Array`, `Array`, or DOMMatrix compatible object to set the matrix values from.
     */
    [PropertySymbol.setMatrixValue](source) {
        let matrix = null;
        // String
        if (typeof source === 'string' && source.length && source !== 'none') {
            matrix = this.constructor[PropertySymbol.fromString](source);
        }
        // Array
        else if (Array.isArray(source) ||
            source instanceof Float64Array ||
            source instanceof Float32Array) {
            matrix = this.constructor[PropertySymbol.fromArray](source);
        }
        // DOMMatrixReadOnly or IDOMMatrixCompatibleObject
        else if (typeof source === 'object') {
            matrix = this.constructor.fromMatrix(source);
        }
        else {
            return;
        }
        this[PropertySymbol.m11] = matrix[PropertySymbol.m11];
        this[PropertySymbol.m12] = matrix[PropertySymbol.m12];
        this[PropertySymbol.m13] = matrix[PropertySymbol.m13];
        this[PropertySymbol.m14] = matrix[PropertySymbol.m14];
        this[PropertySymbol.m21] = matrix[PropertySymbol.m21];
        this[PropertySymbol.m22] = matrix[PropertySymbol.m22];
        this[PropertySymbol.m23] = matrix[PropertySymbol.m23];
        this[PropertySymbol.m24] = matrix[PropertySymbol.m24];
        this[PropertySymbol.m31] = matrix[PropertySymbol.m31];
        this[PropertySymbol.m32] = matrix[PropertySymbol.m32];
        this[PropertySymbol.m33] = matrix[PropertySymbol.m33];
        this[PropertySymbol.m34] = matrix[PropertySymbol.m34];
        this[PropertySymbol.m41] = matrix[PropertySymbol.m41];
        this[PropertySymbol.m42] = matrix[PropertySymbol.m42];
        this[PropertySymbol.m43] = matrix[PropertySymbol.m43];
        this[PropertySymbol.m44] = matrix[PropertySymbol.m44];
    }
    /**
     * Applies a multiply operation to the current matrix.
     *
     * @param matrixCompatibleObject Second matrix.
     */
    [PropertySymbol.multiplySelf](matrixCompatibleObject) {
        if (!matrixCompatibleObject) {
            return;
        }
        let matrix = matrixCompatibleObject;
        if (!(matrix instanceof DOMMatrixReadOnly)) {
            if (matrix?.m11 === undefined && matrix?.a !== undefined) {
                matrix = Object.assign({}, DEFAULT_MATRIX_JSON, matrix);
                matrix.m11 = matrix.a;
                matrix.m12 = matrix.b;
                matrix.m21 = matrix.c;
                matrix.m22 = matrix.d;
                matrix.m41 = matrix.e;
                matrix.m42 = matrix.f;
            }
            else {
                matrix = Object.assign({}, DEFAULT_MATRIX_JSON, matrix);
            }
        }
        const m11 = this[PropertySymbol.m11] * matrix.m11 +
            this[PropertySymbol.m21] * matrix.m12 +
            this[PropertySymbol.m31] * matrix.m13 +
            this[PropertySymbol.m41] * matrix.m14;
        const m21 = this[PropertySymbol.m11] * matrix.m21 +
            this[PropertySymbol.m21] * matrix.m22 +
            this[PropertySymbol.m31] * matrix.m23 +
            this[PropertySymbol.m41] * matrix.m24;
        const m31 = this[PropertySymbol.m11] * matrix.m31 +
            this[PropertySymbol.m21] * matrix.m32 +
            this[PropertySymbol.m31] * matrix.m33 +
            this[PropertySymbol.m41] * matrix.m34;
        const m41 = this[PropertySymbol.m11] * matrix.m41 +
            this[PropertySymbol.m21] * matrix.m42 +
            this[PropertySymbol.m31] * matrix.m43 +
            this[PropertySymbol.m41] * matrix.m44;
        const m12 = this[PropertySymbol.m12] * matrix.m11 +
            this[PropertySymbol.m22] * matrix.m12 +
            this[PropertySymbol.m32] * matrix.m13 +
            this[PropertySymbol.m42] * matrix.m14;
        const m22 = this[PropertySymbol.m12] * matrix.m21 +
            this[PropertySymbol.m22] * matrix.m22 +
            this[PropertySymbol.m32] * matrix.m23 +
            this[PropertySymbol.m42] * matrix.m24;
        const m32 = this[PropertySymbol.m12] * matrix.m31 +
            this[PropertySymbol.m22] * matrix.m32 +
            this[PropertySymbol.m32] * matrix.m33 +
            this[PropertySymbol.m42] * matrix.m34;
        const m42 = this[PropertySymbol.m12] * matrix.m41 +
            this[PropertySymbol.m22] * matrix.m42 +
            this[PropertySymbol.m32] * matrix.m43 +
            this[PropertySymbol.m42] * matrix.m44;
        const m13 = this[PropertySymbol.m13] * matrix.m11 +
            this[PropertySymbol.m23] * matrix.m12 +
            this[PropertySymbol.m33] * matrix.m13 +
            this[PropertySymbol.m43] * matrix.m14;
        const m23 = this[PropertySymbol.m13] * matrix.m21 +
            this[PropertySymbol.m23] * matrix.m22 +
            this[PropertySymbol.m33] * matrix.m23 +
            this[PropertySymbol.m43] * matrix.m24;
        const m33 = this[PropertySymbol.m13] * matrix.m31 +
            this[PropertySymbol.m23] * matrix.m32 +
            this[PropertySymbol.m33] * matrix.m33 +
            this[PropertySymbol.m43] * matrix.m34;
        const m43 = this[PropertySymbol.m13] * matrix.m41 +
            this[PropertySymbol.m23] * matrix.m42 +
            this[PropertySymbol.m33] * matrix.m43 +
            this[PropertySymbol.m43] * matrix.m44;
        const m14 = this[PropertySymbol.m14] * matrix.m11 +
            this[PropertySymbol.m24] * matrix.m12 +
            this[PropertySymbol.m34] * matrix.m13 +
            this[PropertySymbol.m44] * matrix.m14;
        const m24 = this[PropertySymbol.m14] * matrix.m21 +
            this[PropertySymbol.m24] * matrix.m22 +
            this[PropertySymbol.m34] * matrix.m23 +
            this[PropertySymbol.m44] * matrix.m24;
        const m34 = this[PropertySymbol.m14] * matrix.m31 +
            this[PropertySymbol.m24] * matrix.m32 +
            this[PropertySymbol.m34] * matrix.m33 +
            this[PropertySymbol.m44] * matrix.m34;
        const m44 = this[PropertySymbol.m14] * matrix.m41 +
            this[PropertySymbol.m24] * matrix.m42 +
            this[PropertySymbol.m34] * matrix.m43 +
            this[PropertySymbol.m44] * matrix.m44;
        this[PropertySymbol.m11] = m11;
        this[PropertySymbol.m12] = m12;
        this[PropertySymbol.m13] = m13;
        this[PropertySymbol.m14] = m14;
        this[PropertySymbol.m21] = m21;
        this[PropertySymbol.m22] = m22;
        this[PropertySymbol.m23] = m23;
        this[PropertySymbol.m24] = m24;
        this[PropertySymbol.m31] = m31;
        this[PropertySymbol.m32] = m32;
        this[PropertySymbol.m33] = m33;
        this[PropertySymbol.m34] = m34;
        this[PropertySymbol.m41] = m41;
        this[PropertySymbol.m42] = m42;
        this[PropertySymbol.m43] = m43;
        this[PropertySymbol.m44] = m44;
    }
    /**
     * Applies translate to the matrix.
     *
     * This method is equivalent to the CSS `translate3d()` function.
     *
     * @see https://drafts.csswg.org/css-transforms-1/#TranslateDefined
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3d
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param [x] X-Axis position.
     * @param [y] Y-Axis position.
     * @param [z] Z-Axis position.
     */
    [PropertySymbol.translateSelf](x = 0, y = 0, z = 0) {
        // prettier-ignore
        const translationMatrix = this.constructor[PropertySymbol.fromArray]([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            x, y, z, 1,
        ]);
        this[PropertySymbol.multiplySelf](translationMatrix);
    }
    /**
     * Applies a scale to the matrix.
     *
     * This method is equivalent to the CSS `scale()` function.
     *
     * @see https://drafts.csswg.org/css-transforms-1/#ScaleDefined
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param [scaleX] X-Axis scale.
     * @param [scaleY] Y-Axis scale.
     * @param [scaleZ] Z-Axis scale.
     * @param [originX] X-Axis scale.
     * @param [originY] Y-Axis scale.
     * @param [originZ] Z-Axis scale.
     */
    [PropertySymbol.scaleSelf](scaleX, scaleY, scaleZ = 1, originX = 0, originY = 0, originZ = 0) {
        // If scaleY is missing, set scaleY to the value of scaleX.
        scaleX = scaleX === undefined ? 1 : Number(scaleX);
        scaleY = scaleY === undefined ? scaleX : Number(scaleY);
        if (originX !== 0 || originY !== 0 || originZ !== 0) {
            this[PropertySymbol.translateSelf](originX, originY, originZ);
        }
        if (scaleX !== 1 || scaleY !== 1 || scaleZ !== 1) {
            // prettier-ignore
            this[PropertySymbol.multiplySelf](this.constructor[PropertySymbol.fromArray]([
                scaleX, 0, 0, 0,
                0, scaleY, 0, 0,
                0, 0, scaleZ, 0,
                0, 0, 0, 1,
            ]));
        }
        if (originX !== 0 || originY !== 0 || originZ !== 0) {
            this[PropertySymbol.translateSelf](-originX, -originY, -originZ);
        }
    }
    /**
     * Applies a scale to the matrix.
     *
     * This method is equivalent to the CSS `scale()` function.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale3d
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param [scale] The scale factor.
     * @param [originX] X-Axis scale.
     * @param [originY] Y-Axis scale.
     * @param [originZ] Z-Axis scale.
     */
    [PropertySymbol.scale3dSelf](scale = 1, originX = 0, originY = 0, originZ = 0) {
        if (originX !== 0 || originY !== 0 || originZ !== 0) {
            this[PropertySymbol.translateSelf](originX, originY, originZ);
        }
        if (scale !== 1) {
            // prettier-ignore
            this[PropertySymbol.multiplySelf](this.constructor[PropertySymbol.fromArray]([
                scale, 0, 0, 0,
                0, scale, 0, 0,
                0, 0, scale, 0,
                0, 0, 0, 1,
            ]));
        }
        if (originX !== 0 || originY !== 0 || originZ !== 0) {
            this[PropertySymbol.translateSelf](-originX, -originY, -originZ);
        }
    }
    /**
     * Applies a scale to the matrix.
     *
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param [scaleX] X-Axis scale.
     * @param [scaleY] Y-Axis scale.
     */
    [PropertySymbol.scaleNonUniformSelf](scaleX = 1, scaleY = 1) {
        if (scaleX === 1 && scaleY === 1) {
            return;
        }
        // prettier-ignore
        this[PropertySymbol.multiplySelf](this.constructor[PropertySymbol.fromArray]([
            scaleX, 0, 0, 0,
            0, scaleY, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1,
        ]));
    }
    /**
     * Applies a rotation to the matrix.
     *
     * This method is equivalent to the CSS `rotate3d()` function.
     *
     * @see https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-rotateaxisangleself
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d
     * @param [x] X-Axis vector.
     * @param [y] Y-Axis vector.
     * @param [z] Z-Axis vector.
     * @param [angle] Angle in degrees of the rotation.
     */
    [PropertySymbol.rotateAxisAngleSelf](x = 0, y = 0, z = 0, angle = 0) {
        x = Number(x);
        y = Number(y);
        z = Number(z);
        angle = Number(angle);
        if (isNaN(x) || isNaN(y) || isNaN(z) || isNaN(angle)) {
            throw new this[PropertySymbol.window].TypeError(`Failed to execute 'rotateAxisAngleSelf' on 'DOMMatrix': The arguments must be numbers.`);
        }
        const length = Math.hypot(x, y, z);
        if (length === 0) {
            return;
        }
        if (length !== 1) {
            x /= length;
            y /= length;
            z /= length;
        }
        // Degree to radian divided by 2
        const alpha = -((angle * Math.PI) / 360);
        const round = this.#round;
        const sc = Math.sin(alpha) * Math.cos(alpha);
        const sq = Math.sin(alpha) * Math.sin(alpha);
        // We round it as the calculation is off by about 0.000000000000001, which causes the matrix to be different from the browser.
        // The rounding doesn't solve the issue for all cases, it would be better to find a more accurate solution.
        const m11 = round(1 - 2 * (y * y + z * z) * sq);
        const m12 = round(2 * (x * y * sq + z * sc));
        const m13 = round(2 * (x * z * sq - y * sc));
        const m21 = round(2 * (x * y * sq - z * sc));
        const m22 = round(1 - 2 * (x * x + z * z) * sq);
        const m23 = round(2 * (y * z * sq + x * sc));
        const m31 = round(2 * (x * z * sq + y * sc));
        const m32 = round(2 * (y * z * sq - x * sc));
        const m33 = round(1 - 2 * (x * x + y * y) * sq);
        // prettier-ignore
        const matrix = this.constructor[PropertySymbol.fromArray]([
            m11, m21, m31, 0,
            m12, m22, m32, 0,
            m13, m23, m33, 0,
            0, 0, 0, 1
        ]);
        this[PropertySymbol.multiplySelf](matrix);
    }
    /**
     * Applies a rotation to the matrix.
     *
     * @see http://en.wikipedia.org/wiki/Rotation_matrix
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param [x] X-Axis rotation in degrees.
     * @param [y] Y-Axis rotation in degrees.
     * @param [z] Z-Axis rotation in degrees.
     */
    [PropertySymbol.rotateSelf](x = 0, y, z) {
        // If Y and Z are both missing, set Z to the value of X and set X and Y to 0.
        if (y === undefined && z === undefined) {
            z = x;
            x = 0;
            y = 0;
        }
        // If Y is still missing, set Y to 0.
        if (y === undefined) {
            y = 0;
        }
        // If Z is still missing, set Z to 0
        if (z === undefined) {
            z = 0;
        }
        x = Number(x);
        y = Number(y);
        z = Number(z);
        if (isNaN(x) || isNaN(y) || isNaN(z)) {
            throw new this[PropertySymbol.window].TypeError(`Failed to execute 'rotateSelf' on 'DOMMatrix': The arguments must be numbers.`);
        }
        if (z !== 0) {
            this[PropertySymbol.rotateAxisAngleSelf](0, 0, 1, z);
        }
        if (y !== 0) {
            this[PropertySymbol.rotateAxisAngleSelf](0, 1, 0, y);
        }
        if (x !== 0) {
            this[PropertySymbol.rotateAxisAngleSelf](1, 0, 0, x);
        }
    }
    /**
     * Modifies the matrix by rotating it by the angle between the specified vector and (1, 0).
     *
     * @param x The X component of the axis vector.
     * @param y The Y component of the axis vector.
     */
    [PropertySymbol.rotateFromVectorSelf](x = 0, y = 0) {
        if (x === 0 && y === 0) {
            return;
        }
        this[PropertySymbol.rotateSelf]((Math.atan2(y, x) * 180) / Math.PI);
    }
    /**
     * Applies a skew operation to the matrix on the X axis.
     *
     * This method is equivalent to the CSS `skewX()` function.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param angle Angle in degrees.
     */
    [PropertySymbol.skewXSelf](angle) {
        const matrix = Object.assign({}, DEFAULT_MATRIX_JSON);
        const value = Math.tan((angle * Math.PI) / 180);
        matrix.m21 = value;
        matrix.c = value;
        this[PropertySymbol.multiplySelf](matrix);
    }
    /**
     * Applies a skew operation to the matrix on the Y axis.
     *
     * This method is equivalent to the CSS `skewY()` function.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY
     * @see https://www.w3.org/TR/css-transforms-1/#transform-functions
     * @param angle Angle in degrees.
     */
    [PropertySymbol.skewYSelf](angle) {
        const matrix = Object.assign({}, DEFAULT_MATRIX_JSON);
        const value = Math.tan((angle * Math.PI) / 180);
        matrix.m12 = value;
        matrix.b = value;
        this[PropertySymbol.multiplySelf](matrix);
    }
    /**
     * Applies a flip operation to the matrix on the X axis.
     */
    [PropertySymbol.flipXSelf]() {
        // prettier-ignore
        const matrix = this.constructor[PropertySymbol.fromArray]([
            -1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]);
        this[PropertySymbol.multiplySelf](matrix);
    }
    /**
     * Applies a flip operation to the matrix on the Y axis.
     */
    [PropertySymbol.flipYSelf]() {
        // prettier-ignore
        const matrix = this.constructor[PropertySymbol.fromArray]([
            1, 0, 0, 0,
            0, -1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]);
        this[PropertySymbol.multiplySelf](matrix);
    }
    /**
     * Applies an inversion operation to the matrix.
     */
    [PropertySymbol.invertSelf]() {
        const m11 = this[PropertySymbol.m22] * this[PropertySymbol.m33] * this[PropertySymbol.m44] -
            this[PropertySymbol.m22] * this[PropertySymbol.m34] * this[PropertySymbol.m43] -
            this[PropertySymbol.m32] * this[PropertySymbol.m23] * this[PropertySymbol.m44] +
            this[PropertySymbol.m32] * this[PropertySymbol.m24] * this[PropertySymbol.m43] +
            this[PropertySymbol.m42] * this[PropertySymbol.m23] * this[PropertySymbol.m34] -
            this[PropertySymbol.m42] * this[PropertySymbol.m24] * this[PropertySymbol.m33];
        const m12 = -this[PropertySymbol.m12] * this[PropertySymbol.m33] * this[PropertySymbol.m44] +
            this[PropertySymbol.m12] * this[PropertySymbol.m34] * this[PropertySymbol.m43] +
            this[PropertySymbol.m32] * this[PropertySymbol.m13] * this[PropertySymbol.m44] -
            this[PropertySymbol.m32] * this[PropertySymbol.m14] * this[PropertySymbol.m43] -
            this[PropertySymbol.m42] * this[PropertySymbol.m13] * this[PropertySymbol.m34] +
            this[PropertySymbol.m42] * this[PropertySymbol.m14] * this[PropertySymbol.m33];
        const m13 = this[PropertySymbol.m12] * this[PropertySymbol.m23] * this[PropertySymbol.m44] -
            this[PropertySymbol.m12] * this[PropertySymbol.m24] * this[PropertySymbol.m43] -
            this[PropertySymbol.m22] * this[PropertySymbol.m13] * this[PropertySymbol.m44] +
            this[PropertySymbol.m22] * this[PropertySymbol.m14] * this[PropertySymbol.m43] +
            this[PropertySymbol.m42] * this[PropertySymbol.m13] * this[PropertySymbol.m24] -
            this[PropertySymbol.m42] * this[PropertySymbol.m14] * this[PropertySymbol.m23];
        const m14 = -this[PropertySymbol.m12] * this[PropertySymbol.m23] * this[PropertySymbol.m34] +
            this[PropertySymbol.m12] * this[PropertySymbol.m24] * this[PropertySymbol.m33] +
            this[PropertySymbol.m22] * this[PropertySymbol.m13] * this[PropertySymbol.m34] -
            this[PropertySymbol.m22] * this[PropertySymbol.m14] * this[PropertySymbol.m33] -
            this[PropertySymbol.m32] * this[PropertySymbol.m13] * this[PropertySymbol.m24] +
            this[PropertySymbol.m32] * this[PropertySymbol.m14] * this[PropertySymbol.m23];
        const det = this[PropertySymbol.m11] * m11 +
            this[PropertySymbol.m21] * m12 +
            this[PropertySymbol.m31] * m13 +
            this[PropertySymbol.m41] * m14;
        // If the current matrix is not invertible set all attributes to NaN and set is 2D to false.
        if (det === 0) {
            this[PropertySymbol.m11] = NaN;
            this[PropertySymbol.m12] = NaN;
            this[PropertySymbol.m13] = NaN;
            this[PropertySymbol.m14] = NaN;
            this[PropertySymbol.m21] = NaN;
            this[PropertySymbol.m22] = NaN;
            this[PropertySymbol.m23] = NaN;
            this[PropertySymbol.m24] = NaN;
            this[PropertySymbol.m31] = NaN;
            this[PropertySymbol.m32] = NaN;
            this[PropertySymbol.m33] = NaN;
            this[PropertySymbol.m34] = NaN;
            this[PropertySymbol.m41] = NaN;
            this[PropertySymbol.m42] = NaN;
            this[PropertySymbol.m43] = NaN;
            this[PropertySymbol.m44] = NaN;
            return;
        }
        const m21 = -this[PropertySymbol.m21] * this[PropertySymbol.m33] * this[PropertySymbol.m44] +
            this[PropertySymbol.m21] * this[PropertySymbol.m34] * this[PropertySymbol.m43] +
            this[PropertySymbol.m31] * this[PropertySymbol.m23] * this[PropertySymbol.m44] -
            this[PropertySymbol.m31] * this[PropertySymbol.m24] * this[PropertySymbol.m43] -
            this[PropertySymbol.m41] * this[PropertySymbol.m23] * this[PropertySymbol.m34] +
            this[PropertySymbol.m41] * this[PropertySymbol.m24] * this[PropertySymbol.m33];
        const m22 = this[PropertySymbol.m11] * this[PropertySymbol.m33] * this[PropertySymbol.m44] -
            this[PropertySymbol.m11] * this[PropertySymbol.m34] * this[PropertySymbol.m43] -
            this[PropertySymbol.m31] * this[PropertySymbol.m13] * this[PropertySymbol.m44] +
            this[PropertySymbol.m31] * this[PropertySymbol.m14] * this[PropertySymbol.m43] +
            this[PropertySymbol.m41] * this[PropertySymbol.m13] * this[PropertySymbol.m34] -
            this[PropertySymbol.m41] * this[PropertySymbol.m14] * this[PropertySymbol.m33];
        const m23 = -this[PropertySymbol.m11] * this[PropertySymbol.m23] * this[PropertySymbol.m44] +
            this[PropertySymbol.m11] * this[PropertySymbol.m24] * this[PropertySymbol.m43] +
            this[PropertySymbol.m21] * this[PropertySymbol.m13] * this[PropertySymbol.m44] -
            this[PropertySymbol.m21] * this[PropertySymbol.m14] * this[PropertySymbol.m43] -
            this[PropertySymbol.m41] * this[PropertySymbol.m13] * this[PropertySymbol.m24] +
            this[PropertySymbol.m41] * this[PropertySymbol.m14] * this[PropertySymbol.m23];
        const m24 = this[PropertySymbol.m11] * this[PropertySymbol.m23] * this[PropertySymbol.m34] -
            this[PropertySymbol.m11] * this[PropertySymbol.m24] * this[PropertySymbol.m33] -
            this[PropertySymbol.m21] * this[PropertySymbol.m13] * this[PropertySymbol.m34] +
            this[PropertySymbol.m21] * this[PropertySymbol.m14] * this[PropertySymbol.m33] +
            this[PropertySymbol.m31] * this[PropertySymbol.m13] * this[PropertySymbol.m24] -
            this[PropertySymbol.m31] * this[PropertySymbol.m14] * this[PropertySymbol.m23];
        const m31 = this[PropertySymbol.m21] * this[PropertySymbol.m32] * this[PropertySymbol.m44] -
            this[PropertySymbol.m21] * this[PropertySymbol.m34] * this[PropertySymbol.m42] -
            this[PropertySymbol.m31] * this[PropertySymbol.m22] * this[PropertySymbol.m44] +
            this[PropertySymbol.m31] * this[PropertySymbol.m24] * this[PropertySymbol.m42] +
            this[PropertySymbol.m41] * this[PropertySymbol.m22] * this[PropertySymbol.m34] -
            this[PropertySymbol.m41] * this[PropertySymbol.m24] * this[PropertySymbol.m32];
        const m32 = -this[PropertySymbol.m11] * this[PropertySymbol.m32] * this[PropertySymbol.m44] +
            this[PropertySymbol.m11] * this[PropertySymbol.m34] * this[PropertySymbol.m42] +
            this[PropertySymbol.m31] * this[PropertySymbol.m12] * this[PropertySymbol.m44] -
            this[PropertySymbol.m31] * this[PropertySymbol.m14] * this[PropertySymbol.m42] -
            this[PropertySymbol.m41] * this[PropertySymbol.m12] * this[PropertySymbol.m34] +
            this[PropertySymbol.m41] * this[PropertySymbol.m14] * this[PropertySymbol.m32];
        const m33 = this[PropertySymbol.m11] * this[PropertySymbol.m22] * this[PropertySymbol.m44] -
            this[PropertySymbol.m11] * this[PropertySymbol.m24] * this[PropertySymbol.m42] -
            this[PropertySymbol.m21] * this[PropertySymbol.m12] * this[PropertySymbol.m44] +
            this[PropertySymbol.m21] * this[PropertySymbol.m14] * this[PropertySymbol.m42] +
            this[PropertySymbol.m41] * this[PropertySymbol.m12] * this[PropertySymbol.m24] -
            this[PropertySymbol.m41] * this[PropertySymbol.m14] * this[PropertySymbol.m22];
        const m34 = -this[PropertySymbol.m11] * this[PropertySymbol.m22] * this[PropertySymbol.m34] +
            this[PropertySymbol.m11] * this[PropertySymbol.m24] * this[PropertySymbol.m32] +
            this[PropertySymbol.m21] * this[PropertySymbol.m12] * this[PropertySymbol.m34] -
            this[PropertySymbol.m21] * this[PropertySymbol.m14] * this[PropertySymbol.m32] -
            this[PropertySymbol.m31] * this[PropertySymbol.m12] * this[PropertySymbol.m24] +
            this[PropertySymbol.m31] * this[PropertySymbol.m14] * this[PropertySymbol.m22];
        const m41 = -this[PropertySymbol.m21] * this[PropertySymbol.m32] * this[PropertySymbol.m43] +
            this[PropertySymbol.m21] * this[PropertySymbol.m33] * this[PropertySymbol.m42] +
            this[PropertySymbol.m31] * this[PropertySymbol.m22] * this[PropertySymbol.m43] -
            this[PropertySymbol.m31] * this[PropertySymbol.m23] * this[PropertySymbol.m42] -
            this[PropertySymbol.m41] * this[PropertySymbol.m22] * this[PropertySymbol.m33] +
            this[PropertySymbol.m41] * this[PropertySymbol.m23] * this[PropertySymbol.m32];
        const m42 = this[PropertySymbol.m11] * this[PropertySymbol.m32] * this[PropertySymbol.m43] -
            this[PropertySymbol.m11] * this[PropertySymbol.m33] * this[PropertySymbol.m42] -
            this[PropertySymbol.m31] * this[PropertySymbol.m12] * this[PropertySymbol.m43] +
            this[PropertySymbol.m31] * this[PropertySymbol.m13] * this[PropertySymbol.m42] +
            this[PropertySymbol.m41] * this[PropertySymbol.m12] * this[PropertySymbol.m33] -
            this[PropertySymbol.m41] * this[PropertySymbol.m13] * this[PropertySymbol.m32];
        const m43 = -this[PropertySymbol.m11] * this[PropertySymbol.m22] * this[PropertySymbol.m43] +
            this[PropertySymbol.m11] * this[PropertySymbol.m23] * this[PropertySymbol.m42] +
            this[PropertySymbol.m21] * this[PropertySymbol.m12] * this[PropertySymbol.m43] -
            this[PropertySymbol.m21] * this[PropertySymbol.m13] * this[PropertySymbol.m42] -
            this[PropertySymbol.m41] * this[PropertySymbol.m12] * this[PropertySymbol.m23] +
            this[PropertySymbol.m41] * this[PropertySymbol.m13] * this[PropertySymbol.m22];
        const m44 = this[PropertySymbol.m11] * this[PropertySymbol.m22] * this[PropertySymbol.m33] -
            this[PropertySymbol.m11] * this[PropertySymbol.m23] * this[PropertySymbol.m32] -
            this[PropertySymbol.m21] * this[PropertySymbol.m12] * this[PropertySymbol.m33] +
            this[PropertySymbol.m21] * this[PropertySymbol.m13] * this[PropertySymbol.m32] +
            this[PropertySymbol.m31] * this[PropertySymbol.m12] * this[PropertySymbol.m23] -
            this[PropertySymbol.m31] * this[PropertySymbol.m13] * this[PropertySymbol.m22];
        this[PropertySymbol.m11] = m11 / det || 0;
        this[PropertySymbol.m12] = m12 / det || 0;
        this[PropertySymbol.m13] = m13 / det || 0;
        this[PropertySymbol.m14] = m14 / det || 0;
        this[PropertySymbol.m21] = m21 / det || 0;
        this[PropertySymbol.m22] = m22 / det || 0;
        this[PropertySymbol.m23] = m23 / det || 0;
        this[PropertySymbol.m24] = m24 / det || 0;
        this[PropertySymbol.m31] = m31 / det || 0;
        this[PropertySymbol.m32] = m32 / det || 0;
        this[PropertySymbol.m33] = m33 / det || 0;
        this[PropertySymbol.m34] = m34 / det || 0;
        this[PropertySymbol.m41] = m41 / det || 0;
        this[PropertySymbol.m42] = m42 / det || 0;
        this[PropertySymbol.m43] = m43 / det || 0;
        this[PropertySymbol.m44] = m44 / det || 0;
    }
    /**
     * Returns an *Array* containing elements which comprise the matrix.
     *
     * @param matrix Matrix to convert.
     * @param [is2D] If the matrix is 2D.
     * @returns Array representation of the matrix.
     */
    [PropertySymbol.toArray](is2D = false) {
        if (is2D) {
            return [
                this[PropertySymbol.m11],
                this[PropertySymbol.m12],
                this[PropertySymbol.m21],
                this[PropertySymbol.m22],
                this[PropertySymbol.m41],
                this[PropertySymbol.m42]
            ];
        }
        return [
            this[PropertySymbol.m11],
            this[PropertySymbol.m12],
            this[PropertySymbol.m13],
            this[PropertySymbol.m14],
            this[PropertySymbol.m21],
            this[PropertySymbol.m22],
            this[PropertySymbol.m23],
            this[PropertySymbol.m24],
            this[PropertySymbol.m31],
            this[PropertySymbol.m32],
            this[PropertySymbol.m33],
            this[PropertySymbol.m34],
            this[PropertySymbol.m41],
            this[PropertySymbol.m42],
            this[PropertySymbol.m43],
            this[PropertySymbol.m44]
        ];
    }
    /**
     * Rounds the value to the given number of decimals.
     *
     * @param value The value to round.
     * @param [decimals] The number of decimals to round to.
     */
    #round(value, decimals = 1e15) {
        return Math.round(value * decimals) / decimals;
    }
    /**
     * Returns a new `DOMMatrix` instance given an existing matrix.
     *
     * @param matrix Matrix.
     */
    static fromMatrix(matrix) {
        if (!(matrix instanceof DOMMatrixReadOnly)) {
            if (matrix?.m11 === undefined && matrix?.a !== undefined) {
                matrix = Object.assign({}, DEFAULT_MATRIX_JSON, matrix);
                matrix.m11 = matrix.a;
                matrix.m12 = matrix.b;
                matrix.m21 = matrix.c;
                matrix.m22 = matrix.d;
                matrix.m41 = matrix.e;
                matrix.m42 = matrix.f;
            }
            else {
                matrix = Object.assign({}, DEFAULT_MATRIX_JSON, matrix);
            }
        }
        return this[PropertySymbol.fromArray]([
            matrix.m11,
            matrix.m12,
            matrix.m13,
            matrix.m14,
            matrix.m21,
            matrix.m22,
            matrix.m23,
            matrix.m24,
            matrix.m31,
            matrix.m32,
            matrix.m33,
            matrix.m34,
            matrix.m41,
            matrix.m42,
            matrix.m43,
            matrix.m44
        ]);
    }
    /**
     * Returns a new `DOMMatrix` instance given an array of 16/6 floating point values.
     *
     * @param array An `Array` to feed values from.
     * @returns DOMMatrix instance.
     */
    static fromFloat32Array(array) {
        return this[PropertySymbol.fromArray](array);
    }
    /**
     * Returns a new `DOMMatrix` instance given an array of 16/6 floating point values.
     *
     * @param array An `Array` to feed values from.
     * @returns DOMMatrix instance.
     */
    static fromFloat64Array(array) {
        return this[PropertySymbol.fromArray](array);
    }
    /**
     * Returns a new `DOMMatrix` instance given an array of 16/6 floating point values.
     *
     * Conditions:
     * - If the array has six values, the result is a 2D matrix.
     * - If the array has 16 values, the result is a 3D matrix.
     * - Otherwise, a TypeError exception is thrown.
     *
     * @param array An `Array` to feed values from.
     * @returns DOMMatrix instance.
     */
    static [PropertySymbol.fromArray](array) {
        if (!(array instanceof Float64Array || array instanceof Float32Array || Array.isArray(array)) ||
            (array.length !== 6 && array.length !== 16)) {
            throw TypeError(`Failed to execute 'fromArray' on '${this.name}': '${String(array)}' is not a compatible array.`);
        }
        const matrix = new this();
        if (array.length === 16) {
            const [m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44] = array;
            matrix[PropertySymbol.m11] = m11;
            matrix[PropertySymbol.m12] = m12;
            matrix[PropertySymbol.m13] = m13;
            matrix[PropertySymbol.m14] = m14;
            matrix[PropertySymbol.m21] = m21;
            matrix[PropertySymbol.m22] = m22;
            matrix[PropertySymbol.m23] = m23;
            matrix[PropertySymbol.m24] = m24;
            matrix[PropertySymbol.m31] = m31;
            matrix[PropertySymbol.m32] = m32;
            matrix[PropertySymbol.m33] = m33;
            matrix[PropertySymbol.m34] = m34;
            matrix[PropertySymbol.m41] = m41;
            matrix[PropertySymbol.m42] = m42;
            matrix[PropertySymbol.m43] = m43;
            matrix[PropertySymbol.m44] = m44;
        }
        else if (array.length === 6) {
            const [m11, m12, m21, m22, m41, m42] = array;
            matrix[PropertySymbol.m11] = m11;
            matrix[PropertySymbol.m12] = m12;
            matrix[PropertySymbol.m21] = m21;
            matrix[PropertySymbol.m22] = m22;
            matrix[PropertySymbol.m41] = m41;
            matrix[PropertySymbol.m42] = m42;
        }
        return matrix;
    }
    /**
     * Returns a new `DOMMatrix` instance from a DOM transform string.
     *
     * @param source valid CSS transform string syntax.
     * @returns DOMMatrix instance.
     */
    static [PropertySymbol.fromString](source) {
        if (typeof source !== 'string') {
            throw TypeError(`Failed to execute 'setMatrixValue' on '${this.name}': Expected '${String(source)}' to be a string.`);
        }
        const domMatrix = new this();
        const regexp = new RegExp(TRANSFORM_REGEXP);
        let match;
        while ((match = regexp.exec(source))) {
            const name = match[1];
            const parameters = match[2].split(TRANSFORM_PARAMETER_SPLIT_REGEXP);
            for (let i = 0, max = parameters.length; i < max; i++) {
                parameters[i] = this[PropertySymbol.getLength](parameters[i]);
            }
            const [x, y, z, a] = parameters;
            switch (name) {
                case 'perspective':
                    if (!isNaN(x) && x !== 0 && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.m34] = -1 / x;
                    }
                    break;
                case 'translate':
                    if (!isNaN(x) && z === undefined) {
                        domMatrix[PropertySymbol.translateSelf](x, y || 0, 0);
                    }
                    break;
                case 'translate3d':
                    if (!isNaN(x) && !isNaN(y) && !isNaN(z)) {
                        domMatrix[PropertySymbol.translateSelf](x, y, z);
                    }
                    break;
                case 'translateX':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.translateSelf](x);
                    }
                    break;
                case 'translateY':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.translateSelf](0, x);
                    }
                    break;
                case 'translateZ':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.translateSelf](0, 0, x);
                    }
                    break;
                case 'matrix':
                case 'matrix3d':
                    if (parameters.length === 6 || parameters.length === 16) {
                        domMatrix[PropertySymbol.setMatrixValue](this[PropertySymbol.fromArray](parameters));
                    }
                    break;
                case 'rotate':
                case 'rotateZ':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.rotateSelf](0, 0, x);
                    }
                    break;
                case 'rotateX':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.rotateSelf](x, 0, 0);
                    }
                    break;
                case 'rotateY':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.rotateSelf](0, x, 0);
                    }
                case 'rotate3d':
                    if (!isNaN(x) && !isNaN(y) && !isNaN(z) && !isNaN(a)) {
                        domMatrix[PropertySymbol.rotateAxisAngleSelf](x, y, z, a);
                    }
                    break;
                case 'scale':
                    if (!isNaN(x) && x !== 1 && z === undefined) {
                        domMatrix[PropertySymbol.scaleSelf](x, isNaN(y) ? x : y);
                    }
                    break;
                case 'scale3d':
                    if (!isNaN(x) && !isNaN(y) && !isNaN(z)) {
                        domMatrix[PropertySymbol.scaleSelf](x, y, z);
                    }
                    break;
                case 'scaleX':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.scaleSelf](x, 1, 1);
                    }
                    break;
                case 'scaleY':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.scaleSelf](1, x, 1);
                    }
                    break;
                case 'scaleZ':
                    if (!isNaN(x) && y === undefined && z === undefined) {
                        domMatrix[PropertySymbol.scaleSelf](1, 1, x);
                    }
                    break;
                case 'skew':
                    if (!isNaN(x)) {
                        domMatrix[PropertySymbol.skewXSelf](x);
                    }
                    if (!isNaN(y)) {
                        domMatrix[PropertySymbol.skewYSelf](y);
                    }
                    break;
                case 'skewX':
                    if (!isNaN(x) && y === undefined) {
                        domMatrix[PropertySymbol.skewXSelf](x);
                    }
                    break;
                case 'skewY':
                    if (!isNaN(x) && y === undefined) {
                        domMatrix[PropertySymbol.skewYSelf](x);
                    }
                    break;
                default:
                    throw TypeError(`Failed to execute 'setMatrixValue' on '${this.name}': Unknown transform function '${match[1]}'.`);
            }
        }
        return domMatrix;
    }
    /**
     * Returns length.
     *
     * @param length Length to convert.
     * @returns Length.
     */
    static [PropertySymbol.getLength](length) {
        const value = parseFloat(length);
        const unit = length.replace(value.toString(), '');
        switch (unit) {
            case 'rem':
            case 'em':
            case 'vw':
            case 'vh':
            case '%':
            case 'vmin':
            case 'vmax':
                throw new SyntaxError(`Failed to construct '${this.name}': Lengths must be absolute, not relative`);
            case 'rad':
                return value * (180 / Math.PI);
            case 'turn':
                return value * 360;
            case 'px':
                return value;
            case 'cm':
                return value * 37.7812;
            case 'mm':
                return value * 3.7781;
            case 'in':
                return value * 96;
            case 'pt':
                return value * 1.3281;
            case 'pc':
                return value * 16;
            case 'Q':
                return value * 0.945;
            default:
                return value;
        }
    }
}
//# sourceMappingURL=DOMMatrixReadOnly.js.map