"use strict";
"https" !== location.href.substr(0, 5) && (location.href = "https" + location.href.substr(4, location.href.length - 4));
const hrefUrl = new URL(window.location.href);
let parsedP,
    datetime,
    duration,
    speechRec,
    speech,
    language,
    languageTo,
    RoomURL = hrefUrl.protocol + "//" + hrefUrl.host + hrefUrl.pathname;
    this.mediaRecorders = {}; // Store multiple recorders
this.recordedBlobs = {};  // Store blobs per input type
let screenshareEnable = null; //store the screen shares value
const p             = hrefUrl.searchParams.get("p");
const course_id     = hrefUrl.searchParams.get("course_id");
const meeting_name  = hrefUrl.searchParams.get("meeting_name");
const section_id    = hrefUrl.searchParams.get("section_id");
p &&
    ((parsedP = JSON.parse(decodeURIComponent(escape(window.atob(p))))),
    (RoomURL += "?p=" + window.btoa(unescape(encodeURIComponent(decodeURIComponent(escape(window.atob(p))).replace('"admin":1', '"":""'))))),
    (duration = parsedP.duration),
    (datetime = parsedP.datetime),
    (language = parsedP.langFrom),
    (languageTo = parsedP.langTo));
const isAdmin = parsedP && 1 == parsedP.admin ? 1 : 0,
    roomPassword = parsedP && parsedP.pass ? parsedP.pass : null,
    agentId = parsedP && parsedP.agentId ? parsedP.agentId : null,
    disableAll = !(!parsedP || !parsedP.disable);
let notyf,
    liveStorage = window.localStorage;
const _PEER = {
        audioOn: '<i class="fas fa-microphone"></i>',
        audioOff: '<i class="fas fa-microphone-slash"></i>',
        videoOn: '<i class="fas fa-video"></i>',
        videoOff: '<i class="fas fa-video-slash"></i>',
        raiseHand: '<i style="color: var(--action-audio);" class="fas fa-hand-paper"></i>',
        thumb: '<i style="color: var(--yellow);" class="fa-solid fa-thumbs-up fa-bounce"></i>',
        heart: '<i style="color: var(--crimson);" class="fa-solid fa-heart fa-beat"></i>',
        applause: '<i style="color: var(--yellow);" class="fa-solid fa-hands-clapping fa-pulse"></i>',
        laugh: '<i style="color: var(--yellow);" class="fa-solid fa-face-laugh"></i>',
        surprise: '<i style="color: var(--yellow);" class="fa-solid fa-face-surprise"></i>',
        frown: '<i style="color: var(--yellow);" class="fa-solid fa-face-frown"></i>',
        sendFile: '<i class="fas fa-upload"></i>',
        sendMsg: '<i class="fas fa-comment"></i>',
        sendVideo: '<i class="fab fa-youtube"></i>',
        ejectPeer: '<i class="fas fa-sign-out"></i>',
        privateMessage: '<i class="fa-regular fa-comment"></i>',
        allMessage: '<i class="fa-regular fa-comments"></i>',
        reply: '<i class="fas fa-reply"></i>',
    },
    userAgent = navigator.userAgent.toLowerCase(),
    isTabletDevice = isTablet(userAgent),
    isIPadDevice = isIpad(userAgent),
    wbImageInput = "img/*",
    wbWidth = 900,
    wbHeight = 600;
    let rc = null,
    producer = null,
    attendeesCount = 0,
    waitingRoomAttendeesCount = 0,
    chatMessagesId = 0,
    room_id = location.pathname.substring(1),
    parent_id = parsedP && parsedP.parent ? parsedP.parent : room_id,
    peer_admin = isAdmin,
    peer_name = "",
    dva = !(!parsedP || !parsedP.disableAll || isAdmin),
    hoa = !1,
    isWaitingRoomEnabled = !1,
    breakoutRooms = !1,
    isScreenAllowed = !1,
    isWaitingRoomOpen = !1,
    peer_info = null,
    isAudioDevices = !1,
    isVideoDevices = !1,
    isAudioAllowed = !0,
    isVideoAllowed = !(parsedP && parsedP.disableVideo && !isAdmin),
    isRequest = !(!parsedP || !parsedP.request || isAdmin),
    isAudioVideoAllowed = !1,
    isVideoControlsOn = !1,
    isChatPasteTxt = !1,
    isChatGPTOn = !1,
    joinRoomWithoutAudioVideo = !0,
    joinRoomWithScreen = !1;
liveStorage.getItem("audio_off") && (isAudioAllowed = !1), liveStorage.getItem("video_off") && (isVideoAllowed = !1);
let producerId,
    audioStream,
    videoStream,
    streamS,
    activeCanvasElement,
    canvasElement,
    canvasElementBlur,
    videoElement,
    initAudioButton = null,
    initVideoButton = null,
    recTimer = null,
    recElapsedTime = null,
    wbCanvas = null,
    wbIsDrawing = !1,
    wbIsOpen = !1,
    wbIsRedoing = !1,
    wbIsEraser = !1,
    wbIsBgTransparent = !1,
    wbPop = [],
    coords = {},
    isVirtual = !1,
    isRoomLocked = !1,
    initStream = null,
    currentChatTargetId = "all",
    currentChatTargetName = "all",
    videoElementSelectedId = 0,
    audioInputElementSelectedId = 0,
    audioOutputElementSelectedId = 0;
const socket = io();

function getRandomNumber(e) { 
    let t = "",
        i = "0123456789",
        o = i.length;
    for (let e = 0; e < i.length; e++) t += i.charAt(Math.floor(Math.random() * o));
    return t;
}

function startRoom() {
    peer_name = getAttendeeName();
    const e = {
            stringify: function (e) {
                let t = { ct: e.ciphertext.toString(CryptoJS.enc.Base64) };
                return e.iv && (t.iv = e.iv.toString()), e.salt && (t.s = e.salt.toString()), JSON.stringify(t);
            },
            parse: function (e) {
                let t = JSON.parse(e),
                    i = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(t.ct) });
                return t.iv && (i.iv = CryptoJS.enc.Hex.parse(t.iv)), t.s && (i.salt = CryptoJS.enc.Hex.parse(t.s)), i;
            },
        },
        t = '{"ct":"' + smartVideo.config.turnon + '","iv":"09644439296d0d45c81236b5643e9662","s":"3132333435363738"}';
        
    //if (!CryptoJS.AES.decrypt(t, "aeNbaecqgc", { format: e }).toString(CryptoJS.enc.Utf8)) return;
    (peer_name = isAdmin ? smartVideo.config.agentName : peer_name),
        liveStorage.getItem("peer_name") && (peer_name = liveStorage.getItem("peer_name")),
        isAdmin && parsedP && parsedP.agentName && (peer_name = parsedP.agentName),
        !isAdmin && parsedP && parsedP.visitorName && (peer_name = parsedP.visitorName),
        !isAdmin && smartVideo.config.videoScreen.disableVideoAudio && (dva = !0),
        !isAdmin && smartVideo.config.videoScreen.hostOnlyAccess && (hoa = !0),
        smartVideo.config.videoScreen.admit && (isWaitingRoomEnabled = !0),
        !language && smartVideo.config.transcribe && smartVideo.config.transcribe.language && (language = smartVideo.config.transcribe.language),
        !languageTo && smartVideo.config.transcribe && smartVideo.config.transcribe.languageTo && (languageTo = smartVideo.config.transcribe.languageTo),
        DetectRTC.isMobileDevice ||
            (setTooltip("startAudioButton", smartVideo.msgStore.toggleAudio, "top"),
            setTooltip("stopAudioButton", smartVideo.msgStore.toggleAudio, "top"),
            setTooltip("startVideoButton", smartVideo.msgStore.toggleVideo, "top"),
            setTooltip("stopVideoButton", smartVideo.msgStore.toggleVideo, "top"),
            setTooltip("swapCameraButton", smartVideo.msgStore.cameraSwitch, "top"),
            setTooltip("chatButton", smartVideo.msgStore.startChat, "top"),
            setTooltip("startScreenButton", smartVideo.msgStore.startScreenshare, "top"),
            setTooltip("stopScreenButton", smartVideo.msgStore.stopScreenshare, "top"),
            setTooltip("whiteboardButton", smartVideo.msgStore.whiteboard, "top"),
            setTooltip("recordingButton", smartVideo.msgStore.recording, "top"),
            setTooltip("stoprecordingButton", smartVideo.msgStore.stopRecording, "top"),
            setTooltip("getSnapshot", smartVideo.msgStore.snapshot, "top"),
            setTooltip("settingsButton", smartVideo.msgStore.settings, "top"),
            setTooltip("participantsButton", smartVideo.msgStore.participants, "top"),
            setTooltip("breakoutButton", smartVideo.msgStore.breakoutRooms, "top"),
            setTooltip("reActionButtons", smartVideo.msgStore.reaction, "top"),
            setTooltip("exitButton", smartVideo.msgStore.exitMeeting, "top"),
            setTooltip("tabDevicesBtn", smartVideo.msgStore.devices, "top"),
            setTooltip("tabRoomBtn", smartVideo.msgStore.room, "top"),
            setTooltip("tabVideoPanelBtn", smartVideo.msgStore.videoPanel, "top"),
            setTooltip("tabVirtualBackgroundPanel", smartVideo.msgStore.virtualBackground, "top"),
            setTooltip("waitingAcceptAllBtn", smartVideo.msgStore.admitAcceptAll, "top"),
            setTooltip("waitingRejectAllBtn", smartVideo.msgStore.admitRejectAll, "top"),
            setTooltip("shareButton", smartVideo.msgStore.shareMeetingUrl, "top"),
            setTooltip("whiteboardPencilBtn", smartVideo.msgStore.drawingMode, "right"),
            setTooltip("whiteboardObjectBtn", smartVideo.msgStore.objectMode, "right"),
            setTooltip("whiteboardUndoBtn", smartVideo.msgStore.undo, "right"),
            setTooltip("whiteboardRedoBtn", smartVideo.msgStore.redo, "right"),
            setTooltip("whiteboardImgFileBtn", smartVideo.msgStore.addImageFile, "right"),
            setTooltip("whiteboardImgUrlBtn", smartVideo.msgStore.addImageUrl, "right"),
            setTooltip("whiteboardTextBtn", smartVideo.msgStore.addText, "right"),
            setTooltip("whiteboardLineBtn", smartVideo.msgStore.addLine, "right"),
            setTooltip("whiteboardRectBtn", smartVideo.msgStore.addRectangle, "right"),
            setTooltip("whiteboardTriangleBtn", "Add triangle", "right"),
            setTooltip("whiteboardCircleBtn", smartVideo.msgStore.addCircle, "right"),
            setTooltip("whiteboardSaveBtn", smartVideo.msgStore.save, "right"),
            setTooltip("whiteboardEraserBtn", smartVideo.msgStore.eraser, "right"),
            setTooltip("whiteboardCleanBtn", smartVideo.msgStore.clear, "right"),
            setTooltip("chatSendButton", smartVideo.msgStore.send, "top"),
            setTooltip("chatSpeechStartButton", smartVideo.msgStore.chatSpeechStart, "top"),
            setTooltip("chatCloseButton", smartVideo.msgStore.close, "bottom"),
            setTooltip("toggleShowAttendees", smartVideo.msgStore.toggleAttendees, "bottom"),
            setTooltip("toggleChatBackground", smartVideo.msgStore.toggleChatBackground, "bottom"),
            setTooltip("toggleChatPin", smartVideo.msgStore.toggleChatPin, "bottom"),
            setTooltip("raiseHandButtonMain", smartVideo.msgStore.raiseHand, "top"),
            setTooltip("lowerHandButtonMain", smartVideo.msgStore.lowerHand, "top"),
            setTooltip("wbDrawingColorEl", smartVideo.msgStore.pencilLabel, "right"),
            setTooltip("wbBackgroundColorEl", smartVideo.msgStore.backgroundLabel, "right"),
            setTooltip("thumb", smartVideo.msgStore.thumb, "bottom"),
            setTooltip("heart", smartVideo.msgStore.heart, "bottom"),
            setTooltip("laugh", smartVideo.msgStore.laugh, "bottom"),
            setTooltip("applause", smartVideo.msgStore.applause, "bottom"),
            setTooltip("surprise", smartVideo.msgStore.surprise, "bottom"),
            setTooltip("frown", smartVideo.msgStore.frown, "bottom")),
        setLocale("loading", smartVideo.msgStore.loading),
        setLocale("allowCameraMicrophone", smartVideo.msgStore.allowCameraMicrophone),
        setLocale("meetingUrl", smartVideo.msgStore.meetingUrl),
        setLocale("shareVideoLabel", smartVideo.msgStore.shareVideo),
        setLocale("closeVideoShare", smartVideo.msgStore.closeVideoShare),
        setLocale("raiseHand", smartVideo.msgStore.raiseHand),
        setLocale("lowerHand", smartVideo.msgStore.lowerHand),
        setLocale("lockRoom", smartVideo.msgStore.lockRoom),
        setLocale("unlockRoom", smartVideo.msgStore.unlockRoom),
        setLocale("copyMeetingUrlLabel", smartVideo.msgStore.copyMeetingUrlLabel),
        setLocale("emailInviteLabel", smartVideo.msgStore.emailInviteLabel),
        setPlaceholder("chatMessage", smartVideo.msgStore.chatMessage),
        setLocale("aspectRatio", smartVideo.msgStore.aspectRatio),
        setLocale("videoObjectFit", smartVideo.msgStore.videoObjectFit),
        setLocale("defaultValue", smartVideo.msgStore.default),
        setLocale("fill", smartVideo.msgStore.default),
        setLocale("contain", smartVideo.msgStore.contain),
        setLocale("cover", smartVideo.msgStore.cover),
        setLocale("scale-down", smartVideo.msgStore["scale-down"]),
        setLocale("none", smartVideo.msgStore.none),
        setLocale("sessionTimeLabel", smartVideo.msgStore.sessionTime),
        setLocale("pinGrid", smartVideo.msgStore.pinGrid),
        setLocale("vertical", smartVideo.msgStore.vertical),
        setLocale("horizontal", smartVideo.msgStore.horizontal),
        setLocale("top", smartVideo.msgStore.top),
        setLocale("settingsTitle", smartVideo.msgStore.devices),
        setValue("breakoutRoomsSubmit", smartVideo.msgStore.breakoutRoomsSubmit),
        setLocale("countRooms", smartVideo.msgStore.rooms),
        setLocale("waitingAcceptAllBtn", smartVideo.msgStore.admitAcceptAll),
        setLocale("waitingRejectAllBtn", smartVideo.msgStore.admitRejectAll),
        setupWhiteboard();
    let i = !0;//initDevices()
    (!!smartVideo.config.videoScreen.exitMeetingOnTimeAgent || !isAdmin) && duration && (i = checkAppointment()), i ? initDevices() : hide(initialScreen);
}
function setTooltip(e, t, i, o = !1) {
    if (!DetectRTC.isMobileDevice) {
        var n = document.getElementById(e);
        console.log("all id",n);
        if (n) {
            (n.title = t), (n.dataset.bsPlacement = i);
            // console.log("title:",n.title);
            // console.log("dataset:",n.dataset.bsPlacement);
            var r = new bootstrap.Tooltip(n, { boundary: document.body, trigger: "hover" });
            // console.log("r",r);
            n.addEventListener("click", function (e) {
                r.hide();
            });
        //    console.log("eventListner",n.addEventListener("click", function (e) {
        //     r.hide();
        // }))
        }
    }
}

function setLocale(e, t) {
    document.getElementById(e).innerHTML = t;
}
function setValue(e, t) {
    document.getElementById(e).value = t;
}
function setImageTitle(e, t) {
    document.getElementById(e).title = t;
}
function setPlaceholder(e, t) {
    document.getElementById(e).placeholder = t;
}
function setTerms() {
    smartVideo.config.videoScreen.terms &&
        (display(termsContainer, "flex"), setLocale("invalidTerms", smartVideo.msgStore.checkTerms), setLocale("termsCon", smartVideo.msgStore.termsCon), termsLink.setAttribute("href", smartVideo.config.videoScreen.terms));
}
async function initDevices() {
    dva
        ? ((isAudioAllowed = !1), (isVideoAllowed = !1), (isAudioVideoAllowed = !1))
        : ((isVideoAllowed = !(!isAdmin && smartVideo.config.videoScreen && smartVideo.config.videoScreen.disableVideo) && isVideoAllowed), await initAllDevices()),
        hide(initialScreen),
        display(greenRoom, "none"),
        display(simpleRoom, "none"),
        display(protectedRoom, "none"),
        display(videoMediaContainer, "none"),
        !isAdmin && smartVideo.config.serverSide && smartVideo.config.serverSide.loginForm
            ? entryFormProtected()
            : smartVideo.config.videoScreen && smartVideo.config.videoScreen.greenRoom
            ? dva
                ? entryFormSimple()
                : (setTerms(), entryForm())
            : (getAttendeeInfo(), joinRoom(peer_name, room_id)),
        isAudioAllowed || isVideoAllowed || joinRoomWithoutAudioVideo ? setButtonsInit() : openURL(`/permission?room_id=${room_id}&message=Not allowed both Audio and Video`);
}
async function initAllDevices() {
    (isVideoDevices && isAudioDevices) ||
        (await navigator.mediaDevices
            .getUserMedia({ video: !0, audio: !0 })
            .then((e) => {
                enumerateAllDevices(e), (videoStream = e);
            })
            .catch(() => {
                isVideoAllowed = !1;
            }));
}
function enumerateAllDevices(e) {
    navigator.mediaDevices
        .enumerateDevices()
        .then((e) =>
            e.forEach((e) => {
                let t = null,
                    i = null;
                "videoinput" === e.kind
                    ? ((t = videoSelect), (i = greenRoomVideoSelect))
                    : "audioinput" === e.kind
                    ? ((t = microphoneSelect), (i = greenRoomMicSelect))
                    : "audiooutput" === e.kind && ((t = speakerSelect), (i = greenRoomSpeakerSelect)),
                    t && addChild(e, [t, i]);
            })
        )
        .then(() => {
            setSelectsInit(), handleSelectsInit(), stopTracks(e), (isVideoDevices = !0), (isAudioDevices = !0);
            const t = "sinkId" in HTMLMediaElement.prototype;
            (speakerSelect.disabled = !t), t || hide(greenRoomSpeakerSelect.parentElement.parentElement), greenRoomVideoSelect.value && changeCamera(greenRoomVideoSelect.value);
        });
}
async function initVideoDevices() {
    isVideoDevices ||
        (await navigator.mediaDevices
            .getUserMedia({ video: !0 })
            .then((e) => {
                enumerateVideoDevices(e), (videoStream = e);
            })
            .catch(() => {
                isVideoAllowed = !1;
            }));
}
function enumerateVideoDevices(e) {
    navigator.mediaDevices
        .enumerateDevices()
        .then((e) =>
            e.forEach((e) => {
                let t = null,
                    i = null;
                "videoinput" === e.kind && ((t = videoSelect), (i = greenRoomVideoSelect)), t && addChild(e, [t, i]);
            })
        )
        .then(() => {
            stopTracks(e), (isVideoDevices = !0);
        });
}
async function initAudioDevices() {
    isAudioDevices ||
        (await navigator.mediaDevices
            .getUserMedia({ audio: !0 })
            .then((e) => {
                enumerateAudioDevices(e), (audioStream = e);
            })
            .catch(() => {
                isAudioAllowed = !1;
            }));
}
function enumerateAudioDevices(e) {
    navigator.mediaDevices
        .enumerateDevices()
        .then((e) =>
            e.forEach((e) => {
                let t = null,
                    i = null;
                "audioinput" === e.kind ? ((t = microphoneSelect), (i = greenRoomMicSelect)) : "audiooutput" === e.kind && ((t = speakerSelect), (i = greenRoomSpeakerSelect)), t && addChild(e, [t, i]);
            })
        )
        .then(() => {
            stopTracks(e), (isAudioDevices = !0);
            const t = "sinkId" in HTMLMediaElement.prototype;
            (speakerSelect.disabled = !t), t || hide(greenRoomSpeakerSelect.parentElement.parentElement);
        });
}
function stopTracks(e) {
    e &&
        e.getTracks().forEach((e) => {
            e.stop();
        });
}
function addChild(e, t) {
    let i = e.kind;
    t.forEach((t) => {
        let o = document.createElement("option");
        switch (((o.value = e.deviceId), i)) {
            case "videoinput":
                o.innerHTML = e.label || `camera ${t.length + 1}`;
                break;
            case "audioinput":
                o.innerHTML = e.label || `microphone ${t.length + 1}`;
                break;
            case "audiooutput":
                o.innerHTML = e.label || `speaker ${t.length + 1}`;
        }
        t.appendChild(o);
    });
}
function getAttendeeName() {
    let e = getRandomNumber();
    if (!e) return "Visitor-00";
    e.charCodeAt(0), e.charCodeAt(e.length - 1);
    for (var t = 0, i = 0; i < e.length; i++) t += e.charCodeAt(i);
    var o = t % 100;
    return smartVideo.config.entryForm && smartVideo.config.entryForm.visitorName_enabled ? "Visitor-" + parseInt(o + 1) : "";
}
function getAttendeeInfo() {
    peer_info = {
        join_data_time: getDataTimeString(),
        peer_uuid: getUUID(),
        peer_id: socket.id,
        peer_name: peer_name,
        peer_presenter: isAdmin,
        peer_audio: isAudioAllowed,
        peer_video: isVideoAllowed,
        peer_screen: isScreenAllowed,
        peer_hand: !1,
        is_desktop_device: !DetectRTC.isMobileDevice && !isTabletDevice && !isIPadDevice,
        is_mobile_device: DetectRTC.isMobileDevice,
        is_tablet_device: isTabletDevice,
        is_ipad_pro_device: isIPadDevice,
        os_name: DetectRTC.osName,
        os_version: DetectRTC.osVersion,
        browser_name: DetectRTC.browser.name,
        browser_version: DetectRTC.browser.version,
        user_agent: userAgent,
    };
}
var modal;
function toggleModal(e) {
    e ? modal.classList.add("show-modal") : modal.classList.remove("show-modal"), modal || (modal = document.getElementsByClassName("modal").classList.remove("show-modal"));
}
function setPeerReaction(e, t) {
    var i = rc.getId(t + "__actionbutton");
    switch (e) {
        case "thumb":
            i.className = "yellow fa-solid fa-thumbs-up";
            break;
        case "heart":
            i.className = "crimson fa-solid fa-heart";
            break;
        case "applause":
            i.className = "yellow fa-solid fa-hands-clapping";
            break;
        case "laugh":
            i.className = "yellow fa-solid fa-face-laugh";
            break;
        case "surprise":
            i.className = "yellow fa-solid fa-face-surprise";
            break;
        case "frown":
            i.className = "yellow fa-solid fa-face-frown";
    }
    (i.style.display = "flex"),
        setTimeout(() => {
            i.style.display = "none";
        }, 5e3);
}
function windowOnClick(e) {
    (e.target !== modal && "handleBackgroundButtons" !== e.target.className) || "actionModal" === e.target.id || toggleModal(!1);
}
function checkForms(e) {
    var t = !0;
    return (
        e.forEach((e) => {
            let i = !e.parentElement.parentElement.classList.contains("d-none"),
                o = !e.validity.tooShort && !e.validity.valueMissing;
            i && !o && (t = !1);
        }),
        t
    );
}
function entryForm() {
    display(greenRoom, "block");
    var e = document.querySelector("#greenRoomForm");
    e.addEventListener(
        "submit",
        function (t) {
            t.preventDefault(),
                t.stopPropagation(),
                e.classList.add("was-validated"),
                checkForms(document.querySelectorAll(".waiting-fields")) &&
                    (e.classList.add("was-validated"),
                    initStream && !joinRoomWithScreen && stopTracks(initStream),
                    (peer_name = document.getElementById("joinerName").value),
                    liveStorage.setItem("peer_name", peer_name),
                    getAttendeeInfo(),
                    joinRoom(peer_name, room_id));
        },
        
    ),
        setPlaceholder("joinerName", smartVideo.msgStore.enterYourName),
        setValue("joinMeeting", isAdmin ? smartVideo.msgStore.startMeeting : smartVideo.msgStore.joinMeeting),
        setValue("joinerName", peer_name),
        setLocale("invalidName", smartVideo.msgStore.enterYourName),
        display(videoMediaContainer, "none");
    var t = document.getElementById("initBackground"),
        i = document.getElementById("handleBackground");
    if (smartVideo.config.virtualBackground && (smartVideo.config.virtualBackground.blur || smartVideo.config.virtualBackground.backgrounds)) {
        if ((display(t, "var(--fa-display,inline-block)"), display(tabVirtualBackgroundPanel, "block"), smartVideo.config.virtualBackground.blur)) {
            if ((display(i), setImageTitle("handleBackground", smartVideo.msgStore.Blur), smartVideo.config.virtualBackground && smartVideo.config.virtualBackground.backgrounds)) {
                var o = document.getElementById("backgroundImages"),
                    n = document.getElementById("backgroundImagesSettings");
                postData("/server/script.php", { type: "getvirtualimages" }).then((e) => {
                    e.json().then(function (e) {
                        const t = "../img/virtual/";
                        e.forEach(function (e, i) {
                            let r = document.createElement("img");
                            r.setAttribute("src", t + e), r.setAttribute("id", e), r.setAttribute("width", "180"), r.setAttribute("class", "handleBackgroundButtons");
                            let s = document.createElement("img");
                            s.setAttribute("src", t + e),
                                s.setAttribute("id", e),
                                s.setAttribute("width", "180"),
                                s.setAttribute("class", "handleBackgroundButtons"),
                                o.append(r),
                                n.append(s),
                                r.addEventListener("click", handleBackground),
                                s.addEventListener("click", handleBackgroundSettings),
                                setTooltip(e, smartVideo.msgStore.virtualBackgroundImage, "top");
                        });
                    });
                });
            }
            (videoElement = document.getElementById("initVideo")),
                (canvasElement = document.createElement("canvas")),
                (canvasElementBlur = document.createElement("canvas")),
                (canvasElement.id = "backgroundCanvas"),
                canvasElement.setAttribute("playsinline", !0),
                (canvasElement.autoplay = !0),
                (canvasElement.hidden = !0),
                (canvasElementBlur.id = "backgroundCanvasBlur"),
                canvasElementBlur.setAttribute("playsinline", !0),
                (canvasElementBlur.autoplay = !0),
                (canvasElementBlur.hidden = !0),
                videoContainer.append(canvasElement),
                videoContainer.append(canvasElementBlur),
                (modalCloseButtonBack.onclick = () => {
                    toggleModal(!1);
                });
        }
        (modal = document.getElementById("backgroundImagesModal")), setImageTitle("handleNoneBackground", smartVideo.msgStore.none);
    }
}
function entryFormProtected() {
    display(protectedRoom, "flex"),
        setValue("joinMeetingProtected", smartVideo.msgStore.joinMeeting),
        setPlaceholder("nameProtected", smartVideo.msgStore.enterYourName),
        setPlaceholder("emailProtected", smartVideo.msgStore.enterYourEmail),
        setPlaceholder("passwordProtected", smartVideo.msgStore.enterYourPassword),
        setLocale("invalidProtectedName", smartVideo.msgStore.enterYourName),
        setLocale("invalidProtectedEmail", smartVideo.msgStore.enterYourEmail),
        setLocale("invalidProtectedPassword", smartVideo.msgStore.enterYourPassword),
        setLocale("meetingIsPrivate", smartVideo.msgStore.meetingIsPrivate),
        setLocale("provideCredentials", smartVideo.msgStore.provideCredentials);
    var e = document.querySelector("#protectedForm");
    e.addEventListener(
        "submit",
        function (t) {
            t.preventDefault(),
                t.stopPropagation(),
                e.classList.add("was-validated"),
                checkForms(document.querySelectorAll(".protected-fields")) &&
                    postData("/server/script.php", { type: "login", email: emailProtected.value, password: passwordProtected.value }).then((e) => {
                        e.text().then(function (e) {
                            204 == e
                                ? ((peer_name = nameProtected.value), liveStorage.setItem("peer_name", peer_name), getAttendeeInfo(), display(protectedRoom, "none"), entryForm())
                                : setNotify("error", smartVideo.msgStore.wrongRoomCredentials, "center", 1e4);
                        });
                    });
        },
        !1
    );
}
function entryFormSimple() {
    const urlParams = new URLSearchParams(window.location.search);
    //const myParam = urlParams.get('myParam');
    display(simpleRoom, "flex"), setValue("joinMeetingSimple", smartVideo.msgStore.joinMeeting), setPlaceholder("nameSimple", smartVideo.msgStore.enterYourName), setLocale("invalidSimpleName", smartVideo.msgStore.enterYourName);
    var e = document.querySelector("#simpleForm");
    let peerName = localStorage.getItem("peer_name");
    if (peerName) {
        let bName = document.getElementById("nameSimple");
        bName.value = peerName;

        const submitEvent = new Event("submit", { bubbles: true, cancelable: true });
        // Dispatch the event to trigger the listener
        e.dispatchEvent(submitEvent);
    }
    e.addEventListener(
        "submit",
        function (t) {
            if ((t.preventDefault(), t.stopPropagation(), e.classList.add("was-validated"), checkForms(document.querySelectorAll(".simple-fields")))) {
                display(simpleRoom, "none");
                let e = document.getElementById("nameSimple").value;
                (peer_name = e), liveStorage.setItem("peer_name", peer_name), getAttendeeInfo(), joinRoom(peer_name, room_id);
            }
        },
        !1
    );
    // console.log(urlParams);
    // console.log(urlParams.get("name"));
    if(urlParams.get("name") !=null && urlParams.get("name") !=""){
        document.getElementById("nameSimple").value = urlParams.get("name");
        display(simpleRoom, "none");
        (peer_name = urlParams.get("name")), liveStorage.setItem("peer_name", peer_name), getAttendeeInfo(), joinRoom(peer_name, room_id);
    }
}
function postData(e = "", t = {}) {
    return fetch(e, { method: "POST", mode: "cors", cache: "no-cache", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(t) });
}
function handleAudio(e) {
    (isAudioAllowed = !isAudioAllowed),
        isAudioAllowed ? liveStorage.removeItem("audio_off") : liveStorage.setItem("audio_off", !0),
        (e.target.className = "fas fa-microphone" + (isAudioAllowed ? "" : "-slash")),
        checkInitAudio(isAudioAllowed);
}
function handleVideo(e) {
    (isVideoAllowed = !isVideoAllowed), isVideoAllowed ? liveStorage.removeItem("video_off") : liveStorage.setItem("video_off", !0), (e.target.className = "fas fa-video" + (isVideoAllowed ? "" : "-slash")), checkInitVideo(isVideoAllowed);
}
function handleBackground(e) {
    setVideoDimensions(),
        "handleNoneBackground" === e.target.id
            ? (isVirtual = !0)
            : 1 == isVirtual && ((isVirtual = !1), display(canvasElement, "none"), display(canvasElementBlur, "none"), (videoElement.hidden = !1), (canvasElement.hidden = !0), (canvasElementBlur.hidden = !0)),
        (greenRoomVideoSelect.disabled = !isVideoAllowed),
        setColor(document.querySelector("#initBackground"), isVirtual ? "white" : "grey");
    const t = "handleBackground" === e.target.id ? 1 : 2;
    if ("handleBackground" !== e.target.id && "handleNoneBackground" !== e.target.id) {
        const t = "../img/virtual/";
        document.getElementById("backgroundImage").setAttribute("src", t + e.target.id);
    }
    changeVirtual(t, "initVideo");
}
function handleBackgroundSettings(e) {
    setVideoDimensions();
    let t = rc.getId(producerId);
    "handleNoneBackgroundSettings" === e.target.id
        ? (isVirtual = !0)
        : 1 == isVirtual && ((isVirtual = !1), display(canvasElement, "none"), display(canvasElementBlur, "none"), (t.hidden = !1), (canvasElement.hidden = !0), (canvasElementBlur.hidden = !0));
    const i = "handleBackgroundSettings" === e.target.id ? 1 : 2;
    if ("handleBackgroundSettings" !== e.target.id && "handleNoneBackgroundSettings" !== e.target.id) {
        const t = "../img/virtual/";
        document.getElementById("backgroundImage").setAttribute("src", t + e.target.id);
    }
    changeVirtual(i, producerId), rc.closeThenProduce(RoomClient.mediaType.video, videoSelect.value);
}
function checkInitVideo(e) {
    e ? greenRoomVideoSelect.value && changeCamera(greenRoomVideoSelect.value) : initStream && stopTracks(initStream), (greenRoomVideoSelect.disabled = !e);
}
function checkInitAudio(e) {
    (greenRoomMicSelect.disabled = !e), (greenRoomSpeakerSelect.disabled = !e);
}
function checkMedia() {
    let e = new URLSearchParams(window.location.search),
        t = e.get("audio"),
        i = e.get("video");
    if (t) {
        t = t.toLowerCase();
        let e = "1" === t || "true" === t;
        null != e && (isAudioAllowed = e);
    }
    if (i) {
        i = i.toLowerCase();
        let e = "1" === i || "true" === i;
        null != e && (isVideoAllowed = e);
    }
}
async function shareRoom(e = !1) {
    if (((document.getElementById("shareMeetingUrlLabel").innerHTML = RoomURL), navigator.share && e))
        try {
            await navigator.share({ url: RoomURL }), this.setNotify("info", smartVideo.msgStore.roomSharedSuccessfully, "top");
        } catch (e) {}
}
function makeRoomQR() {
    let e = DetectRTC.isMobileDevice ? 128 : 256;
    new QRious({ element: document.getElementById("qrRoom"), value: RoomURL }).set({ size: e });
}
function copyRoomURL() {
    let e = document.createElement("input");
    document.body.appendChild(e), (e.value = RoomURL), e.select(), e.setSelectionRange(0, 99999), navigator.clipboard.writeText(e.value), document.body.removeChild(e), setNotify("info", smartVideo.msgStore.roomCopyClipboard, "top");
}
function shareRoomByEmail(e) {
    let t = e.email,
        i = e.subject,
        o = e.body;
    window.open("mailto:" + t + "?subject=" + i + "&body=" + o);
}
function joinRoom(e, t) {
    hide(settingsButton),
    display(greenRoom, "none"),
        display(simpleRoom, "none"),
        display(protectedRoom, "none"),
        display(videoMediaContainer, "flex"),
        isAudioAllowed && stopTracks(audioStream),
        isVideoAllowed && stopTracks(videoStream),
        (rc && rc.isConnected()) ||
            ((rc = new RoomClient(
                localAudio,
                remoteAudios,
                videoMediaContainer,
                videoPinMediaContainer,
                window.mediasoupClient,
                socket,
                t,
                e,
                peer_info,
                isAudioAllowed,
                isVideoAllowed,
                isScreenAllowed,
                joinRoomWithScreen,
                meetingToDo,
                roomPassword
            )),
            duration && checkTimer(),
            handleRoomClientEvents());
}
function meetingToDo() {
    if (
        (DetectRTC.isMobileDevice ? (hide(actionButtons), show(actionButtonMobileMenu)) : (show(actionButtons), hide(actionButtonMobileMenu)),
        show(exitButton),
        // !dva && show(participantsButton),
        smartVideo.config.videoScreen && smartVideo.config.videoScreen.getSnapshot && show(getSnapshot),
        smartVideo.config.videoScreen && smartVideo.config.videoScreen.getReaction && show(reActionButtons),
        rc.peer_info.peer_admin
            ? (smartVideo.config.recording && smartVideo.config.recording.enabled ? show(recordingButton) : display(recordingButton, "none"),
              smartVideo.config.whiteboard && smartVideo.config.whiteboard.enabled ? show(whiteboardButton) : display(whiteboardButton, "none"),
              smartVideo.config.sharevideo && smartVideo.config.sharevideo.enabled ? show(videoShareButton) : display(videoShareButton, "none"),
              show(lockRoomButton))
            : (display(lockRoomButton, "none"), display(videoShareButton, "none")),
        show(chatButton),
        dva && show(raiseHandButtonMain),
        speechRecognition && smartVideo.config.transcribe && smartVideo.config.transcribe.enabled && ((speechRec = new SpeechRec()), speechRec.init(), show(chatSpeechStartButton)),
        DetectRTC.isMobileDevice
            ? (dva || disableAll || show(swapCameraButton), display(toggleChatPin, "none"))
            : ((navigator.getDisplayMedia || navigator.mediaDevices.getDisplayMedia) && (dva ? hide(startScreenButton) : show(startScreenButton)), display(toggleChatPin, "block")),
        "Safari" != DetectRTC.browser.name &&
            (document.onfullscreenchange = () => {
                document.fullscreenElement || (rc.isDocumentOnFullScreen = !1);
            }),
        dva ? (hide(settingsButton), hide(breakoutButton),hide(participantsButton)) : (show(settingsButton),show(participantsButton)),
        
        smartVideo.config.videoScreen && smartVideo.config.videoScreen.breakout && show(breakoutButton),
        show(raiseHandButton), show(whiteboardButton),
        show(isAudioAllowed ? stopAudioButton : startAudioButton),
        show(isVideoAllowed ? stopVideoButton : startVideoButton),
        !isAdmin && hoa && (hide(startAudioButton), hide(startVideoButton), hide(stopAudioButton), hide(stopVideoButton), hide(settingsButton)),
        disableAll && (hide(raiseHandButtonMain), hide(exitButton), hide(settingsButton)),
        handleButtons(),
        handleSelects(),
        handleInputs(),
        startSessionTimer(),
        smartVideo.config.transcribe && (smartVideo.config.transcribe.textSpeechChat || smartVideo.config.transcribe.textSpeechTranscribe))
    ) {
        (speech = new SpeechSynthesisUtterance()), (speech.lang = "en"), (speech.rate = 1), (speech.volume = 1), (speech.pitch = 1);
        let e = [];
        window.speechSynthesis.onvoiceschanged = () => {
            (e = window.speechSynthesis.getVoices()), (speech.voice = e[smartVideo.config.transcribe.textSpeechLang]);
        };
    }
    dva &&
        parsedP &&
        "config_broadcasting" == parsedP.config &&
        setTimeout(async function () {
            let e = await getRoomAttendeeVideo();
            console.log(e);
            if (smartVideo.config.recording && smartVideo.config.recording.saveServer && !e) {
                let e = "record_" + room_id;
                smartVideo.config.recording.filename && ((e = smartVideo.config.recording.filename), (e = e.replace("%room%", room_id))), (window.location = "/recordings/" + e + ".webm");
            }
        }, 1e3);
}
function hide(e) {
    e.className = "hidden";
}
function display(e, t) {
    (e.style.display = t), e.classList.remove("d-none");
}
function show(e) {
    e === stopAudioButton || e === stopVideoButton || e === stopRecordingButton || e === lowerHandButtonMain ? (e.className = "activeControl") : (e.className = "");
}
function disable(e, t) {
    e.disabled = t;
}
function setColor(e, t) {
    e === startAudioButton || e === startVideoButton || e === lowerHandButtonMain || e.setAttribute("style", "color: " + t + " !important");
}
function setBackgroundColor(e, t, i) {
    e.setAttribute("style", "background: " + t + " !important; color: " + i + " !important");
}
function startSessionTimer() {
    sessionTime.style.display = "inline";
    let e = Date.now();
    setInterval(function () {
        let t = Date.now() - e;
        sessionTime.innerHTML = " " + getTimeToString(t);
    }, 1e3);
}
function getTimeToString(e) {
    let t = e / 36e5,
        i = Math.floor(t),
        o = 60 * (t - i),
        n = Math.floor(o),
        r = 60 * (o - n),
        s = Math.floor(r);
    return `${i.toString().padStart(2, "0")}:${n.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
}
function secondsToHms(e) {
    e = Number(e);
    let t = Math.floor(e / 3600),
        i = Math.floor((e % 3600) / 60),
        o = Math.floor((e % 3600) % 60);
    return (t > 0 ? t + "h" : "") + " " + (i > 0 ? i + "m" : "") + " " + (o > 0 ? o + "s" : "");
}
function startRecordingTimer() {
    display(recordingStatus, "flex");
    let e = Date.now();
    recTimer = setInterval(function () {
        if (rc.isRecording()) {
            let t = Date.now() - e;
            recordingStatus.innerHTML = `<i id="recordingStatusButton" class="fa fa-circle fa-2xs blinking"></i> <span>${getTimeToString(t)}</span>`;
        }
    }, 1e3);
}
function stopRecordingTimer() {
    display(recordingStatus, "none"), clearInterval(recTimer);
}
function handleButtons() {
    // (actionButtonMobileMenu.onclick = () => {
    //     actionButtons.classList.contains("hidden") ? show(actionButtons) : hide(actionButtons);
    // })

    if (actionButtonMobileMenu) {
        actionButtonMobileMenu.onclick = () => {
            actionButtons.classList.contains("hidden") ? show(actionButtons) : hide(actionButtons);
        };
    }
    if (participantsButton) {
        participantsButton.onclick = () => {
            console.log("Participants button clicked");
            rc.toggleMyParticipants();
        };
    } else {
        console.error("participantsButton not found in DOM");
    }

    // Close button for the modal
    if (participantsCloseBtn) {
        participantsCloseBtn.onclick = () => {
            rc.toggleMyParticipants();
        };
    }
        (exitButton.onclick = () => {
            rc.exitRoom();
        }),
        (shareButton.onclick = () => {
            shareRoom(!0);
        }),
        (settingsButton.onclick = () => {
            rc.toggleMySettings(),
            console.log("Setting Button Click");
                document.querySelectorAll('a[data-bs-toggle="tab"]').forEach((e) => {
                    e.addEventListener("shown.bs.tab", function (e) {
                        rc.getId("settingsTitle").innerHTML = smartVideo.msgStore[e.target.id];
                    });
                });
        }),
        (mySettingsCloseBtn.onclick = () => {
            rc.toggleMySettings()
        }),
        (breakoutButton.onclick = () => {
            rc.toggleBreakout();
        }),
        (reActionButtons.onclick = () => {
            (rc.getId("reActionModalTitle").innerHTML = smartVideo.msgStore.reactionHeader), rc.toggleReactions();
        }),
        (chatButton.onclick = () => {
            rc.toggleChat();
        }),
        (toggleShowAttendees.onclick = () => {
            rc.toggleShowAttendees();
        }),
        (toggleChatBackground.onclick = () => {
            rc.toggleChatBackground();
        }),
        (toggleChatPin.onclick = () => {
            rc.isVideoPinned || rc.toggleChatPin();
        }),
        (chatCloseButton.onclick = () => {
            rc.toggleChat();
        }),
        (chatSendButton.onclick = () => {
            rc.sendMessage();
        }),
        (chatSpeechStartButton.onclick = () => {
            chatSpeechStartButton.classList.contains("activeControl") ? speechRec.startSpeech(!1) : speechRec.startSpeech(!0);
        }),
        (recordingButton.onclick = () => {
            rc.startRecording();
        }),
        (getSnapshot.onclick = () => {
            rc.getSnapshot();
        }),
        (stopRecordingButton.onclick = () => {
            rc.stopRecording();
        }),
        (swapCameraButton.onclick = () => {
            rc.closeThenProduce(RoomClient.mediaType.video, null, !0);
        }),
        (raiseHandButton.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "hand", !0);
        }),
        (lowerHandButton.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "hand", !1);
        }),
        (raiseHandButtonMain.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "hand", !0);
        }),
        (lowerHandButtonMain.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "hand", !1);
        }),
        (startAudioButton.onclick = () => {
            setAudioButtonsDisabled(!0),
                isAudioDevices || initAudioDevices(),
                rc.produce(RoomClient.mediaType.audio, microphoneSelect.value),
                rc.setPeer(peer_name, rc.peer_id, "audio", !0),
                hide(raiseHandButtonMain),
                hide(lowerHandButtonMain),
                liveStorage.removeItem("audio_off");
        }),
        (stopAudioButton.onclick = () => {
            setAudioButtonsDisabled(!0), liveStorage.setItem("audio_off", !0), rc.closeProducer(RoomClient.mediaType.audio), rc.setPeer(peer_name, rc.peer_id, "audio", !1), liveStorage.setItem("audio_off", !0);
        }),
        (startVideoButton.onclick = () => {
            liveStorage.removeItem("video_off"), setVideoButtonsDisabled(!0), isVideoDevices || initVideoDevices(), rc.produce(RoomClient.mediaType.video, videoSelect.value);
        }),
        (stopVideoButton.onclick = () => {
            liveStorage.setItem("video_off", !0), setVideoButtonsDisabled(!0), rc.closeProducer(RoomClient.mediaType.video);
        }),
        (startScreenButton.onclick = () => {
            rc.produce(RoomClient.mediaType.screen);
        }),
        (stopScreenButton.onclick = () => {
            rc.closeProducer(RoomClient.mediaType.screen);
        }),
        (videoShareButton.onclick = () => {
            toggleModal(!1), rc.shareVideo("all");
        }),
        (videoCloseBtn.onclick = () => {
            toggleModal(!1), rc.closeVideo(!0);
        }),
        (sendAbortBtn.onclick = () => {
            rc.abortFileTransfer();
        }),
        (receiveHideBtn.onclick = () => {
            rc.hideFileTransfer();
        }),
        (whiteboardButton.onclick = () => {
            console.log("WhiteBoard Button Click");
            toggleWhiteboard();
        }),
        (whiteboardPencilBtn.onclick = () => {
            whiteboardIsDrawingMode(!0);
        }),
        (whiteboardObjectBtn.onclick = () => {
            whiteboardIsDrawingMode(!1);
        }),
        (whiteboardUndoBtn.onclick = () => {
            whiteboard(getWhiteboardAction("undo"));
        }),
        (whiteboardRedoBtn.onclick = () => {
            whiteboard(getWhiteboardAction("redo"));
        }),
        (whiteboardSaveBtn.onclick = () => {
            wbCanvasSaveImg();
        }),
        (whiteboardImgFileBtn.onclick = () => {
            whiteboardAddObj("imgFile");
        }),
        (whiteboardImgUrlBtn.onclick = () => {
            whiteboardAddObj("imgUrl");
        }),
        (whiteboardTextBtn.onclick = () => {
            whiteboardAddObj("text");
        }),
        (whiteboardLineBtn.onclick = () => {
            whiteboardAddObj("line");
        }),
        (whiteboardRectBtn.onclick = () => {
            whiteboardAddObj("rect");
        }),
        (whiteboardTriangleBtn.onclick = () => {
            whiteboardAddObj("triangle");
        }),
        (whiteboardCircleBtn.onclick = () => {
            whiteboardAddObj("circle");
        }),
        (whiteboardEraserBtn.onclick = () => {
            whiteboardIsEraser(!0);
        }),
        (whiteboardCleanBtn.onclick = () => {
            confirmClearBoard();
        }),
        (whiteboardCloseBtn.onclick = () => {
            whiteboard(getWhiteboardAction("close"));
        }),
        (lockRoomButton.onclick = () => {
            rc.toggleMySettings(), rc.room("lock");
        }),
        (unlockRoomButton.onclick = () => {
            rc.toggleMySettings(), rc.room("unlock");
        }),
        (copyMeetingUrl.onclick = () => {
            copyRoomURL();
        }),
        (modalCloseButton.onclick = () => {
            toggleModal(!1);
        }),
        (breakoutCloseButton.onclick = () => {
            toggleModal(!1);
        }),
        (modalCloseButtonAction.onclick = () => {
            toggleModal(!1);
        }),
        (thumb.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "thumb", !0), toggleModal(!1);
        }),
        (heart.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "heart", !0), toggleModal(!1);
        }),
        (applause.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "applause", !0), toggleModal(!1);
        }),
        (laugh.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "laugh", !0), toggleModal(!1);
        }),
        (surprise.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "surprise", !0), toggleModal(!1);
        }),
        (frown.onclick = () => {
            rc.setPeer(peer_name, rc.peer_id, "frown", !0), toggleModal(!1);
        }),
        (emailInvite.onclick = () => {
            shareRoomByEmail({ email: "", subject: smartVideo.msgStore.emailInviteSubject, body: smartVideo.msgStore.emailInviteBody.replace("{{RoomURL}}", RoomURL) });
        })
    //     (participantsButton.onclick = () => {
    //         rc.toggleMyParticipants();
    //     }),
    //   (participantsCloseBtn.onclick = () => {
    //         rc.toggleMyParticipants(); 
    //     });

}



function setButtonsInit() {
    DetectRTC.isMobileDevice ||
        (setTooltip("initAudioButton", smartVideo.msgStore.enableDisableAudio, "top"),
        setTooltip("initVideoButton", smartVideo.msgStore.enableDisableVideo, "top"),
        setTooltip("initBackground", smartVideo.msgStore.enableVirtualBackground, "top"),
        setTooltip("handleBackground", smartVideo.msgStore.blurVb, "top"),
        setTooltip("handleNoneBackground", smartVideo.msgStore.noneVb, "top")),
        (initAudioButton = document.getElementById("initAudioButton")),
        (initVideoButton = document.getElementById("initVideoButton")),
        (isAudioVideoAllowed = isAudioAllowed && isVideoAllowed);
}
function handleSelectsInit() {
    (greenRoomVideoSelect.onchange = () => {
        changeCamera(greenRoomVideoSelect.value), (videoElementSelectedId = videoSelect.selectedIndex = greenRoomVideoSelect.selectedIndex), liveStorage.setItem("videoElementSelectedId", videoElementSelectedId);
    }),
        (greenRoomMicSelect.onchange = () => {
            (audioInputElementSelectedId = microphoneSelect.selectedIndex = greenRoomMicSelect.selectedIndex), liveStorage.setItem("audioInputElementSelectedId", audioInputElementSelectedId);
        }),
        (greenRoomSpeakerSelect.onchange = () => {
            (audioOutputElementSelectedId = speakerSelect.selectedIndex = greenRoomSpeakerSelect.selectedIndex), liveStorage.setItem("audioOutputElementSelectedId", audioOutputElementSelectedId);
        });
}
function setSelectsInit() {
    liveStorage.getItem("videoElementSelectedId") && (videoElementSelectedId = liveStorage.getItem("videoElementSelectedId")),
        liveStorage.getItem("audioInputElementSelectedId") && (audioInputElementSelectedId = liveStorage.getItem("audioInputElementSelectedId")),
        liveStorage.getItem("audioOutputElementSelectedId") && (audioOutputElementSelectedId = liveStorage.getItem("audioOutputElementSelectedId")),
        (greenRoomMicSelect.selectedIndex = audioOutputElementSelectedId),
        (greenRoomSpeakerSelect.selectedIndex = audioInputElementSelectedId),
        (greenRoomVideoSelect.selectedIndex = videoElementSelectedId),
        (microphoneSelect.selectedIndex = greenRoomMicSelect.selectedIndex),
        (speakerSelect.selectedIndex = greenRoomSpeakerSelect.selectedIndex),
        (videoSelect.selectedIndex = greenRoomVideoSelect.selectedIndex);
}
async function changeCamera(e) {
    initStream && (stopTracks(initStream), show(initVideo));
    const t = { audio: !1, video: { width: { ideal: 1280 }, height: { ideal: 720 }, deviceId: e, aspectRatio: 1.777, frameRate: { min: 5, ideal: 15, max: 30 } } };
    navigator.mediaDevices
        .getUserMedia(t)
        .then((e) => {
            (initVideo.className = "mirror"),
                (initVideo.srcObject = e),
                (initStream = e),
                (initAudioButton = document.getElementById("initAudioButton")),
                (initVideoButton = document.getElementById("initVideoButton")),
                isVideoAllowed || ((isVideoAllowed = !0), initVideoButton.click()),
                isAudioAllowed || ((isAudioAllowed = !0), initAudioButton.click());
        })
        .catch((e) => {
            setNotify("error", "Error while swapping camera" + e, "top-end");
        });
}
async function toggleScreenSharing() {
    initStream && (stopTracks(initStream), show(initVideo)),
        (joinRoomWithScreen = !joinRoomWithScreen),
        joinRoomWithScreen
            ? navigator.mediaDevices
                  .getDisplayMedia({ audio: !0, video: !0 })
                  .then((e) => {
                      (initVideo.srcObject = e), (initStream = e), show(initStopScreenButton), disable(greenRoomVideoSelect, !0), disable(initVideoButton, !0);
                  })
                  .catch((e) => ((joinRoomWithScreen = !1), checkInitVideo(isVideoAllowed)))
            : (checkInitVideo(isVideoAllowed), hide(initStopScreenButton), disable(greenRoomVideoSelect, !1), disable(initVideoButton, !1));
}
function handleSelects() {
    (videoSelect.onchange = () => {
        rc.closeThenProduce(RoomClient.mediaType.video, videoSelect.value), (videoElementSelectedId = videoSelect.selectedIndex), liveStorage.setItem("videoElementSelectedId", videoElementSelectedId);
    }),
        (microphoneSelect.onchange = () => {
            rc.closeThenProduce(RoomClient.mediaType.audio, microphoneSelect.value), (audioInputElementSelectedId = videoSelect.selectedIndex), liveStorage.setItem("audioInputElementSelectedId", audioInputElementSelectedId);
        }),
        (speakerSelect.onchange = () => {
            rc.attachSinkId(rc.myAudioEl, greenRoomSpeakerSelect.value), (audioOutputElementSelectedId = videoSelect.selectedIndex), liveStorage.setItem("audioOutputElementSelectedId", audioOutputElementSelectedId);
        }),
        (BtnAspectRatio.onchange = () => {
            setAspectRatio(BtnAspectRatio.value);
        }),
        (breakoutCountRooms.onchange = () => {
            for (var e = breakoutCountRooms.value; rc.getId("roomContainer").firstChild; ) rc.getId("roomContainer").removeChild(rc.getId("roomContainer").firstChild);
            for (let t = 1; t <= e; t++) {
                let e = document.querySelector("#roomInputTpl").cloneNode(!0);
                (e.id = "breakout" + t), (e.getElementsByTagName("input")[0].id = "breakoutInput" + t), rc.getId("roomContainer").appendChild(e), e.classList.remove("d-none"), setPlaceholder("breakoutInput" + t, "Room " + t);
            }
        }),
        (breakoutRoomsSubmit.onclick = () => {
            let e = !liveStorage.getItem("breakoutRooms" + parent_id);
            toggleModal(!1), rc.setBreakout(e);
        }),
        (BtnVideoObjectFit.onchange = () => {
            rc.handleVideoObjectFit(BtnVideoObjectFit.value);
        }),
        (BtnVideoObjectFit.selectedIndex = 2),
        (pinVideoPosition.onchange = () => {
            rc.togglePin(pinVideoPosition.value);
        }),
        (wbDrawingColorEl.onchange = () => {
            (wbCanvas.freeDrawingBrush.color = wbDrawingColorEl.value), whiteboardIsDrawingMode(!0);
        }),
        (wbBackgroundColorEl.onchange = () => {
            setWhiteboardBgColor(wbBackgroundColorEl.value);
        });
}
function handleInputs() {
    (chatMessage.onkeyup = (e) => {
        13 !== e.keyCode || (!DetectRTC.isMobileDevice && e.shiftKey) || (e.preventDefault(), chatSendButton.click());
    }),
        (chatMessage.oninput = function () {
            const e = { "<3": "❤️", "</3": "💔", ":D": "😀", ":)": "😃", ";)": "😉", ":(": "😒", ":p": "😛", ";p": "😜", ":'(": "😢", ":+1:": "👍" };
            for (let t in e) {
                let i = new RegExp(t.replace(/([()[{*+.$^\\|?])/g, "\\$1"), "gim");
                this.value = this.value.replace(i, e[t]);
            }
            rc.checkLineBreaks();
        }),
        (chatMessage.onpaste = () => {
            (isChatPasteTxt = !0), rc.checkLineBreaks();
        });
}
function handleRoomClientEvents() {
    rc.on(RoomClient.EVENTS.startRec, () => {
        startRecordingTimer();
    }),
        rc.on(RoomClient.EVENTS.pauseRec, () => {
            hide(pauseRecButton), show(resumeRecButton);
        }),
        rc.on(RoomClient.EVENTS.resumeRec, () => {
            hide(resumeRecButton), show(pauseRecButton);
        }),
        rc.on(RoomClient.EVENTS.stopRec, () => {
            stopRecordingTimer();
        }),
        rc.on(RoomClient.EVENTS.raiseHand, () => {
            hide(raiseHandButton), show(lowerHandButton), setColor(lowerHandButton, "green"), !isAdmin && raiseHandButtonMain && (hide(raiseHandButtonMain), show(lowerHandButtonMain));
        }),
        rc.on(RoomClient.EVENTS.lowerHand, () => {
            hide(lowerHandButton), show(raiseHandButton), !isAdmin && lowerHandButtonMain && (hide(lowerHandButtonMain), show(raiseHandButtonMain));
        }),
        rc.on(RoomClient.EVENTS.startAudio, () => {
            hoa || (hide(startAudioButton), show(stopAudioButton), setAudioButtonsDisabled(!1));
        }),
        rc.on(RoomClient.EVENTS.pauseAudio, () => {
            hoa || (hide(stopAudioButton), show(startAudioButton));
        }),
        rc.on(RoomClient.EVENTS.resumeAudio, () => {
            hoa || (hide(startAudioButton), show(stopAudioButton));
        }),
        rc.on(RoomClient.EVENTS.stopAudio, () => {
            hoa || (hide(stopAudioButton), show(startAudioButton), setAudioButtonsDisabled(!1));
        }),
        rc.on(RoomClient.EVENTS.startVideo, () => {
            hoa || (hide(startVideoButton), show(stopVideoButton), setVideoButtonsDisabled(!1));
        }),
        rc.on(RoomClient.EVENTS.pauseVideo, () => {
            hoa || (hide(stopVideoButton), show(startVideoButton));
        }),
        rc.on(RoomClient.EVENTS.resumeVideo, () => {
            hoa || (hide(startVideoButton), show(stopVideoButton));
        }),
        rc.on(RoomClient.EVENTS.stopVideo, () => {
            hoa || (hide(stopVideoButton), show(startVideoButton), setVideoButtonsDisabled(!1));
        }),
        rc.on(RoomClient.EVENTS.startScreen, () => {
            hide(startScreenButton), show(stopScreenButton);
        }),
        rc.on(RoomClient.EVENTS.pauseScreen, () => {}),
        rc.on(RoomClient.EVENTS.resumeScreen, () => {}),
        rc.on(RoomClient.EVENTS.stopScreen, () => {
            hide(stopScreenButton), show(startScreenButton);
        }),
        rc.on(RoomClient.EVENTS.roomLock, () => {
            isAdmin && (hide(lockRoomButton), show(unlockRoomButton));
        }),
        rc.on(RoomClient.EVENTS.roomUnlock, () => {
            isAdmin && (hide(unlockRoomButton), show(lockRoomButton));
        }),
        rc.on(RoomClient.EVENTS.exitRoom, () => {
            if (((window.onbeforeunload = null), parsedP && parsedP.parent)) {
                let e,
                    t = "";
                hrefUrl.searchParams.get("p") && ((e = parsedP.parent), delete parsedP.parent, (t = "?p=" + window.btoa(unescape(encodeURIComponent(JSON.stringify(parsedP)))))),
                    (location.href = hrefUrl.protocol + "//" + hrefUrl.host + "/" + e + t);
            } else smartVideo.config.videoScreen.exitMeeting ? (location.href = smartVideo.config.videoScreen.exitMeeting) : (location.href = "/");
        });
}
function setNotify(e, t, i, o = 3e3, n = !0, r) {
    let s = i.split("|"),
        a = s[1] || "center";
    notyf && notyf.dismissAll(),
        (notyf = new Notyf({
            duration: o,
            position: { x: a, y: s[0] },
            types: [
                { type: "warning", background: "var(--action-audio)", icon: { className: "material-icons", tagName: "i", text: "warning" }, dismissible: n },
                { type: "info", background: "var(--blue-bg)", dismissible: n },
                { type: "error", background: "indianred", dismissible: n },
            ],
        }));
    const c = notyf.open({ type: e, message: t });
    r &&
        c.on("click", ({ target: e, event: t }) => {
            r();
        });
}
function actionModal(e, t, i, o, n, r) {
    (modal = document.getElementById("actionModal")),
        toggleModal(!0),
        (document.getElementById("actionModalTitle").innerHTML = e),
        (document.getElementById("actionModalBody").innerHTML = t),
        (document.getElementById("actionModalOkButton").innerHTML = i),
        (document.getElementById("actionModalDismissButton").innerHTML = n),
        display(actionModalBody, t ? "flex" : "none"),
        display(actionModalOkButton, i ? "flex" : "none"),
        display(actionModalDismissButton, n ? "flex" : "none"),
        (actionModalDismissButton.onclick = () => {
            toggleModal(!1), r && r();
        }),
        (actionModalOkButton.onclick = () => {
            if ((toggleModal(!1), o))
                if (e === smartVideo.msgStore.fileShare) {
                    const e = document.getElementById("file").files[0];
                    o(e);
                } else if (e === smartVideo.msgStore.selectImage) {
                    const e = document.getElementById("selectImage").files[0];
                    o(e);
                } else if (e === smartVideo.msgStore.setRoomPassword) {
                    const e = document.getElementById("roomPass").value;
                    o(e);
                } else if (e === smartVideo.msgStore.shareYouTubeVideo) {
                    const e = document.getElementById("videoUrl").value;
                    o(e);
                } else if (e === smartVideo.msgStore.imageUrl) {
                    const e = document.getElementById("imageUrl").value;
                    o(e);
                } else if (e === smartVideo.msgStore.roomLocked) {
                    const e = document.getElementById("lockroom").value;
                    o(e);
                } else o();
        });
}
function saveDataToFile(e, t) {
    const i = document.createElement("a");
    (i.style.display = "none"),
        (i.href = e),
        (i.download = t),
        document.body.appendChild(i),
        i.click(),
        setTimeout(() => {
            document.body.removeChild(i), window.URL.revokeObjectURL(e);
        }, 100);
}
function saveObjToJsonFile(e, t) {
    const i = getDataTimeString();
    let o = document.createElement("a");
    (o.href = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(e, null, 1))),
        (o.download = `${i}-${t}.txt`),
        document.body.appendChild(o),
        o.click(),
        setTimeout(() => {
            document.body.removeChild(o);
        }, 100);
}
function getDataTimeString() {
    const e = new Date();
    return `${e.toISOString().split("T")[0]}-${e.toTimeString().split(" ")[0]}`;
}
function getUUID() {
    const e = ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (e) => (e ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (e / 4)))).toString(16));
    return window.localStorage.uuid ? window.localStorage.uuid : ((window.localStorage.uuid = e), e);
}
function toggleClassElements(e, t) {
    let i = rc.getEcN(e);
    for (let e = 0; e < i.length; e++) i[e].style.display = t;
}
function setAudioButtonsDisabled(e) {
    (startAudioButton.disabled = e), (stopAudioButton.disabled = e);
}
function setVideoButtonsDisabled(e) {
    (startVideoButton.disabled = e), (stopVideoButton.disabled = e);
}
async function sound(e) {
    // let t = "../media/" + e + ".mp3",
    //     i = new Audio(t);
    // try {
    //     (i.volume = 0.5), await i.play();
    // } catch (e) {
    //     (t = "../media/ringtone.mp3"), (i.volume = 0.5), await i.play();
    // }
}
function isImageURL(e) {
    return null != e.match(/\.(jpeg|jpg|gif|png|tiff|bmp)$/);
}
function isTablet(e) {
    return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(e);
}
function isIpad(e) {
    return /macintosh/.test(e) && "ontouchend" in document;
}
function openURL(e, t = !1) {
    t ? window.open(e, "_blank") : (window.location.href = e);
}
function setCookie(e, t, i) {
    let o = new Date();
    o.setTime(o.getTime() + 24 * i * 60 * 60 * 1e3);
    const n = "expires=" + o.toUTCString();
    document.cookie = e + "=" + t + "; " + n + "; path=/";
}
function getCookie(e) {
    const t = e + "=";
    let i;
    return (
        decodeURIComponent(document.cookie)
            .split("; ")
            .forEach((e) => {
                0 === e.indexOf(t) && (i = e.substring(t.length));
            }),
        i
    );
}
function isHtml(e) {
    var t = document.createElement("div");
    t.innerHTML = e;
    for (var i = t.childNodes, o = i.length; o--; ) if (1 == i[o].nodeType) return !0;
    return !1;
}
function toggleWhiteboard() {
    let e = rc.getId("whiteboard");
    e.classList.toggle("show"), (e.style.top = "50%"), (e.style.left = "50%"), (wbIsOpen = !wbIsOpen);
}
function setupWhiteboard() {
    setupWhiteboardCanvas(), setupWhiteboardCanvasSize(), setupWhiteboardLocalListners();
}
function setupWhiteboardCanvas() {
    (wbCanvas = new fabric.Canvas("wbCanvas")), (wbCanvas.freeDrawingBrush.color = "#484d75"), (wbCanvas.freeDrawingBrush.width = 3), whiteboardIsDrawingMode(!0);
}
function setupWhiteboardCanvasSize() {
    let e = [900, 600],
        t = window.innerWidth / e[0],
        i = window.innerHeight / e[1];
    t < i && t < 1
        ? (wbCanvas.setWidth(e[0] * t), wbCanvas.setHeight(e[1] * t), wbCanvas.setZoom(t), setWhiteboardSize(e[0] * t, e[1] * t))
        : t > i && i < 1
        ? (wbCanvas.setWidth(e[0] * i), wbCanvas.setHeight(e[1] * i), wbCanvas.setZoom(i), setWhiteboardSize(e[0] * i, e[1] * i))
        : (wbCanvas.setWidth(e[0]), wbCanvas.setHeight(e[1]), wbCanvas.setZoom(1), setWhiteboardSize(e[0], e[1])),
        wbCanvas.calcOffset(),
        wbCanvas.renderAll();
}
function setWhiteboardSize(e, t) {
    document.documentElement.style.setProperty("--wb-width", e), document.documentElement.style.setProperty("--wb-height", t);
}
function setWhiteboardBgColor(e) {
    whiteboard({ peer_name: peer_name, action: "bgcolor", color: e });
}
function whiteboardIsDrawingMode(e) {
    (wbCanvas.isDrawingMode = e),
        e
            ? (setBackgroundColor(whiteboardPencilBtn, "#484d75", "white"), setBackgroundColor(whiteboardObjectBtn, "white", "#484d75"), setBackgroundColor(whiteboardEraserBtn, "white", "#484d75"), (wbIsEraser = !1))
            : (setBackgroundColor(whiteboardPencilBtn, "white", "#484d75"), setBackgroundColor(whiteboardObjectBtn, "#484d75", "white"));
}
function whiteboardIsEraser(e) {
    whiteboardIsDrawingMode(!1), (wbIsEraser = e), setBackgroundColor(whiteboardEraserBtn, wbIsEraser ? "#484d75" : "white", wbIsEraser ? "white" : "#484d75");
}
function whiteboardAddObj(e) {
    switch (e) {
        case "imgUrl":
            var t = function (e) {
                let t = e;
                isImageURL(t)
                    ? fabric.Image.fromURL(t, function (e) {
                          addWbCanvasObj(e);
                      })
                    : setNotify("error", smartVideo.msgStore.urlNotValidImage, "top");
            };
            actionModal(smartVideo.msgStore.imageUrl, '<input class="form-control" type="text" required id="imageUrl">', smartVideo.msgStore.shareButton, t, smartVideo.msgStore.cancelButton);
            break;
        case "imgFile":
            t = function (e) {
                let t = e;
                if (t && t.size > 0) {
                    let e = new FileReader();
                    (e.onload = function (e) {
                        let t = new Image();
                        (t.src = e.target.result),
                            (t.onload = function () {
                                let e = new fabric.Image(t);
                                e.set({ top: 0, left: 0 }).scale(0.3), addWbCanvasObj(e);
                            });
                    }),
                        e.readAsDataURL(t);
                } else setNotify("error", smartVideo.msgStore.notValidFile, "top");
            };
            actionModal(smartVideo.msgStore.selectImage, '<input class="form-control" type="file" id="selectImage">', smartVideo.msgStore.okButton, t, smartVideo.msgStore.cancelButton);
            break;
        case "text":
            addWbCanvasObj(
                new fabric.IText(smartVideo.msgStore.enterText, { top: 0, left: 0, fontFamily: "Comfortaa", fill: wbCanvas.freeDrawingBrush.color, strokeWidth: wbCanvas.freeDrawingBrush.width, stroke: wbCanvas.freeDrawingBrush.color })
            );
            break;
        case "line":
            addWbCanvasObj(new fabric.Line([50, 100, 200, 200], { top: 0, left: 0, fill: wbCanvas.freeDrawingBrush.color, strokeWidth: wbCanvas.freeDrawingBrush.width, stroke: wbCanvas.freeDrawingBrush.color }));
            break;
        case "circle":
            addWbCanvasObj(new fabric.Circle({ radius: 50, fill: "transparent", stroke: wbCanvas.freeDrawingBrush.color, strokeWidth: wbCanvas.freeDrawingBrush.width }));
            break;
        case "rect":
            addWbCanvasObj(new fabric.Rect({ top: 0, left: 0, width: 150, height: 100, fill: "transparent", stroke: wbCanvas.freeDrawingBrush.color, strokeWidth: wbCanvas.freeDrawingBrush.width }));
            break;
        case "triangle":
            addWbCanvasObj(new fabric.Triangle({ top: 0, left: 0, width: 150, height: 100, fill: "transparent", stroke: wbCanvas.freeDrawingBrush.color, strokeWidth: wbCanvas.freeDrawingBrush.width }));
    }
}
function addWbCanvasObj(e) {
    e && (wbCanvas.add(e).setActiveObject(e), whiteboardIsDrawingMode(!1), whiteboardData());
}
function setupWhiteboardLocalListners() {
    wbCanvas.on("mouse:down", function (e) {
        mouseDown(e);
    }),
        wbCanvas.on("mouse:up", function () {
            mouseUp();
        }),
        wbCanvas.on("mouse:move", function () {
            mouseMove();
        }),
        wbCanvas.on("object:added", function () {
            objectAdded();
        });
}
function mouseDown(e) {
    (wbIsDrawing = !0), wbIsEraser && e.target && wbCanvas.remove(e.target);
}
function mouseUp() {
    (wbIsDrawing = !1), whiteboardData();
}
function mouseMove() {
    wbCanvas.hoverCursor = wbIsEraser ? "not-allowed" : "move";
}
function objectAdded() {
    wbIsRedoing || (wbPop = []), (wbIsRedoing = !1);
}
function wbCanvasBackgroundColor(e) {
    document.documentElement.style.setProperty("--wb-bg", e), (wbBackgroundColorEl.value = e), wbCanvas.setBackgroundColor(e), wbCanvas.renderAll();
}
function wbCanvasUndo() {
    wbCanvas._objects.length > 0 && (wbPop.push(wbCanvas._objects.pop()), wbCanvas.renderAll());
}
function wbCanvasRedo() {
    wbPop.length > 0 && ((wbIsRedoing = !0), wbCanvas.add(wbPop.pop()));
}
function wbCanvasSaveImg() {
    saveDataToFile(wbCanvas.toDataURL({ width: wbCanvas.getWidth(), height: wbCanvas.getHeight(), left: 0, top: 0, format: "png" }), "room_" + room_id + "_" + getDataTimeString() + "_whiteboard.png");
}
function whiteboardData() {
    if (rc.thereIsAttendees()) {
        let e = JSON.stringify(wbCanvas.toJSON());
        rc.socket.emit("whiteboardData", e);
    }
}
function JsonToWbCanvas(e) {
    /* THIS IS COMMENTED TO PREVENT OPENING WHITEBOARD ON STUDENTS END */

    // wbIsOpen || toggleWhiteboard(), wbCanvas.loadFromJSON(e), wbCanvas.renderAll();
}
function getWhiteboardAction(e) {
    return { peer_name: peer_name, action: e };
}
function confirmClearBoard() {
    actionModal(
        smartVideo.msgStore.cleanBoard,
        smartVideo.msgStore.sureCleanBoard,
        smartVideo.msgStore.yes,
        function () {
            whiteboard(getWhiteboardAction("clear"));
        },
        smartVideo.msgStore.no
    );
}
function whiteboard(e, t = !0) {
    switch ((t ? rc.thereIsAttendees() && isAdmin && rc.socket.emit("whiteboard", e) : setNotify("info", `${e.peer_name} ` + smartVideo.msgStore.whiteboard + `: ${e.action}`, "top"), e.action)) {
        case "bgcolor":
            wbCanvasBackgroundColor(e.color);
            break;
        case "undo":
            wbCanvasUndo();
            break;
        case "redo":
            wbCanvasRedo();
            break;
        case "clear":
            wbCanvas.clear();
            break;
        case "close":
            wbIsOpen && toggleWhiteboard();
    }
}
async function getRoomPeers() {
    let e = await rc.getRoomInfo();
    return new Map(JSON.parse(e.peers));
}
async function saveRoomPeers() {
    const e = await getRoomPeers();
    let t = [];
    for (let i of Array.from(e.keys())) t.push(e.get(i).peer_info);
    saveObjToJsonFile(t, "ATTENDEES");
}
async function getRoomAttendees() {
    let e = await getRoomPeers(),
        t = await getAttendeesChat(e);
    (attendeesCount = e.size), (chatAttendees.innerHTML = t);
    const i = document.querySelectorAll(".chat-attendee-li");
    for (const e of i)
        e.addEventListener("click", function (t) {
            (isChatGPTOn = !1),
                t.stopPropagation(),
                i.forEach((e) => {
                    e.classList.remove("active");
                });
            const o = e.dataset.id,
                n = e.dataset.name;
            if ("all" === o) {
                attendeeName.innerHTML = smartVideo.msgStore.publicChat;
                var r = '<a href="javascript:void(0);" class="btn btn-outline-secondary btn-sm float-left"><i class="fas fa-users fa-lg"></i></a>';
            } else "chatgpt" === o ? ((isChatGPTOn = !0), (attendeeName.innerHTML = smartVideo.msgStore.chatGPT), (r = '<a href="javascript:void(0);" class="btn btn-outline-secondary btn-sm float-left chatgpticon"><i class="fa-solid fa-code-compare"></i></a>')) : ((r = `<img src="${(r = getAttendeeAvatar(n))}" alt="${n}"></img>`), (attendeeName.innerHTML = smartVideo.msgStore.privateChatWith.replace("{{name}}", n)));
            e.classList.add("active"), window.roomClient.chatShow(o), (attendeeAvatar.innerHTML = r), (currentChatTargetId = o), (currentChatTargetName = n), "all" !== o && "chatgpt" !== o && rc.getId(o + "__badge").classList.add("d-none");
        });
    getAttendeesCount(attendeesCount, !1), setAttendeesTippy(e);
}
async function getRoomAttendeeVideo() {
    let e = await rc.getRoomInfo(),
        t = new Map(JSON.parse(e.peers));
    for (let e of Array.from(t.keys())) {
        if (t.get(e).peer_info.peer_video) return !0;
    }
    return !1;
}
async function getAttendeesChat(e) {
    let t = "";
    t = isAdmin
        ? `\n        <span class="btn btn-outline-secondary" id='hideAllButton' onclick="rc.peer('me','${rc.peer_id}','hide',true,true)">${_PEER.videoOff}</span>\n        <span class="btn btn-outline-secondary" id='muteAllButton' onclick="rc.peer('me','${rc.peer_id}','mute',true,true)">${_PEER.audioOff}</span>\n        <span class="btn btn-outline-secondary" id='sendAllButton' onclick="rc.selectFileToShare('${rc.peer_id}', true)">${_PEER.sendFile}</span>\n        <span class="btn btn-outline-secondary" id="ejectAllButton" onclick="rc.peer('me','${rc.peer_id}','eject',true,true)">${_PEER.ejectPeer}</span>\n        `
        : `\n        <span class="btn btn-outline-secondary" id='sendAllButton' onclick="rc.selectFileToShare('${rc.peer_id}', true)">${_PEER.sendFile}</span>\n        <span id="sendPublicButton" class="btn btn-outline-secondary">${_PEER.allMessage}</span>\n        `;
    let i =
        `\n    <li class="clearfix chat-attendee-li active" data-id="all" data-name="${smartVideo.msgStore.all}">\n        <a href="javascript:void(0);" class="btn btn-outline-secondary btn-sm float-left">\n            <i class="fas fa-users fa-lg"></i>\n        </a>\n        <div class="about px-5">\n            <div class="name">` +
        smartVideo.msgStore.all +
        ` <span id="attendeesCountSpan"></span></div>\n            <div class="status pt-1">${t}</div>\n        </div>\n    </li>`;
    smartVideo.config.videoScreen.enable_chat_gpt &&
        (i +=
            `\n    <li class="clearfix chat-attendee-li" data-id="chatgpt" data-name="${smartVideo.msgStore.chatGPT}">\n        <a href="javascript:void(0);" class="btn btn-outline-secondary btn-sm float-left chatgpticon">\n            <i class="fa-solid fa-code-compare"></i>\n        </a>\n        <div class="about px-5">\n            <div class="name">` +
            smartVideo.msgStore.chatGPT +
            "\n        </div>\n    </li>");
    for (let t of Array.from(e.keys())) {
        let o = e.get(t).peer_info,
            n = o.peer_name,
            r = o.peer_audio ? _PEER.audioOn : _PEER.audioOff,
            s = o.peer_audio ? "mute" : "unmute",
            a = o.peer_video ? _PEER.videoOn : _PEER.videoOff,
            c = o.peer_video ? "hide" : "unhide",
            l = _PEER.raiseHand,
            d = _PEER.ejectPeer,
            h = _PEER.sendFile,
            u = o.peer_id,
            f = getAttendeeAvatar(n),
            m = "";
        if (isAdmin) {
            m = `\n            <span class="btn btn-outline-secondary" id='${u}___pVideo' onclick="rc.peer('me',this.id,'${c}', true, false);">${a}</span>\n            <span class="btn btn-outline-secondary" id='${u}___pAudio' onclick="rc.peer('me',this.id, '${s}', true, false);">${r}</span>\n            ${`<span class="btn btn-outline-secondary ${
                o.peer_hand ? "" : "d-none"
            }" id='${u}___pHand' onclick="rc.peer('me',this.id,'lowerhand', true, false);">${l}</span>`}\n            <span class="btn btn-outline-secondary" id='${u}___pShare' onclick="rc.selectFileToShare('${u}', false);">${h}</span>\n            <span class="btn btn-outline-secondary" id='${u}___pEject' onclick="rc.peer('me',this.id,'eject', true, false);">${d}</span>\n        `;
        } else
            m = `\n            <span class="btn btn-outline-secondary" id='${u}___pShare' onclick="rc.selectFileToShare('${u}', false);">${h}</span>\n            <span class="btn btn-outline-secondary" id='${u}___pSendPrivate'>${_PEER.privateMessage}</span>\n            `;
        rc.peer_id !== u &&
            (i += `\n            <li class="clearfix chat-attendee-li" data-id="${u}" data-name="${n}">\n                <i class="fa-solid fa-envelope d-none attendees-envelopes" id="${u}__badge"></i>\n                <img src="${f}" alt="${n}">\n                <div class="about px-5">\n                    <div class="name">${n}</div>\n                    <div class="status pt-1">${m}</div>\n                </div>\n            </li>\n            `);
    }
    return (attendeeName.innerHTML = smartVideo.msgStore.publicChat), (attendeeAvatar.innerHTML = '<a href="javascript:void(0);" class="btn btn-outline-secondary btn-sm float-left"><i class="fas fa-users fa-lg"></i></a>'), i;
}
function checkAppointment() {
    let e = Date.now();
    datetime && (e = datetime);
    let t = new Date(),
        i = new Date(e);
    if ((i.setMinutes(i.getMinutes() + parseInt(duration)), t >= new Date(e) && i > t)) {
        if (smartVideo.config.videoScreen.exitMeetingOnTime) {
            let e = new Date(),
                t = i - e;
            setTimeout(function () {
                smartVideo.msgStore.meetingIsToEnd;
            }, i - e - 6e4),
                setTimeout(function () {
                    rc.exit();
                }, t);
        }
        return !0;
    }
    {
        let i = new Date(),
            o = new Date(e),
            n = Math.abs(o - i) / 1e3,
            r = Math.floor(n / 86400);
        n -= 86400 * r;
        let s = Math.floor(n / 3600) % 24;
        n -= 3600 * s;
        let a = Math.floor(n / 60) % 60;
        n -= 60 * a;
        let c = "";
        if (r > 0) {
            c = r + " " + (r > 1 ? smartVideo.msgStore.days : smartVideo.msgStore.day);
        }
        if (0 === r && s > 0) {
            c = s + " " + (s > 1 ? smartVideo.msgStore.hours : smartVideo.msgStore.hour);
        }
        if ((0 === r && 0 == s && a > 0 && (c = a + " " + smartVideo.msgStore.minutes), 0 === r && 0 == s && 0 == a && (c = smartVideo.msgStore.seconds), c && new Date(e) > t)) {
            let t = smartVideo.msgStore.notexactAppointment,
                i = getPrettyDate(new Date(e).getTime() / 1e3),
                o = t.replace("{{timemeeting}}", i);
            (o = o.replace("{{diffString}}", c)), setNotify("info", o, "top", 6e5);
            let n = new Date(),
                r = new Date(e) - n;
            r < 2147483640 &&
                setTimeout(function () {
                    window.location.reload();
                }, r);
        } else setNotify("info", smartVideo.msgStore.appointmentPast, "top", 6e5);
        return !1;
    }
}
function checkTimer() {
    const e = datetime || Date.now();
    let t = new Date(e);
    if ((t.setMinutes(t.getMinutes() + parseInt(duration)), smartVideo.config.videoScreen.meetingTimer)) {
        const e = new Date();
        setTimeout(function () {
            const e = new Date(t).getTime();
            let i = !1;
            function o(e) {
                setNotify("info", e, "top|right", 6e5, !0);
            }
            !(function t() {
                setTimeout(function () {
                    const n = new Date().getTime(),
                        r = e - n;
                    let s = Math.floor((r % 864e5) / 36e5),
                        a = Math.floor((r % 36e5) / 6e4),
                        c = Math.floor((r % 6e4) / 1e3);
                    a && c < 10 && (c = "0" + c), (s = s ? s + ":" : ""), (a = a ? a + ":" : "");
                    const l = s + a + c,
                        d = smartVideo.msgStore.meetingEndsIn.replace("{{timemeeting}}", l);
                    i ? (document.querySelector(".notyf__message").innerText = d) : o(d), (i = !0), r < 0 ? o(smartVideo.msgStore.meetingExpired) : t();
                }, 1e3);
            })();
        }, t - e - 12e4);
    }
}
function setAttendeesTippy(e) {
    if (!DetectRTC.isMobileDevice) {
        setTooltip("sendAllButton", smartVideo.msgStore.shareAll, "bottom"), setTooltip("ejectAllButton", smartVideo.msgStore.ejectAll, "bottom"), setTooltip("sendPublicButton", smartVideo.msgStore.publicChat, "bottom");
        for (let t of Array.from(e.keys())) {
            let i = e.get(t).peer_info.peer_id;
            setTooltip(i + "___pShare", smartVideo.msgStore.share, "bottom"), setTooltip(i + "___pEject", smartVideo.msgStore.eject, "bottom"), setTooltip(i + "___pSendPrivate", smartVideo.msgStore.sendPrivateMessasge, "bottom");
        }
    }
}
function getAttendeesCount(e) {
    (attendeesCountSpan.innerHTML = ` (${e})`), adaptAspectRatio(e);
}
function getAttendeeAvatar(e) {
    return rc.genAvatarSvg(e, 32);
}
function handleVideoObjectFit(e) {
    document.documentElement.style.setProperty("--videoObjFit", e);
}
function setVideoDimensions() {
    attendeesCount > 1 ? adaptAspectRatio(videoMediaContainer.childElementCount) : resizeVideoMedia();
}
function adaptAspectRatio(e) {
    let t,
        i = 1;
    switch (e) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 7:
        case 9:
            t = 2;
            break;
        case 5:
        case 6:
        case 10:
        case 11:
            t = 1;
            break;
        case 8:
            t = 3;
            break;
        default:
            t = 0;
    }
    switch (e) {
        case 3:
        case 9:
        case 10:
            i = 2;
            break;
        case 7:
        case 8:
        case 11:
            i = 1;
            break;
        default:
            i = 3;
    }
    e > 11 && ((t = 1), (i = 3)), (BtnAspectRatio.selectedIndex = DetectRTC.isMobileDevice ? i : t), setAspectRatio(BtnAspectRatio.selectedIndex);
}
function getPrettyDate(e) {
    let t = new Date(),
        i = String(t.getDate()).padStart(2, "0"),
        o = String(t.getMonth() + 1).padStart(2, "0"),
        n = t.getFullYear(),
        r = new Date(1e3 * e),
        s = r.getFullYear(),
        a = ("0" + (r.getMonth() + 1)).slice(-2),
        c = ("0" + r.getDate()).slice(-2),
        l = ("0" + r.getHours()).slice(-2),
        d = ("0" + r.getMinutes()).slice(-2);
    if (i == c && o == a && n == s) return l + ":" + d;
    {
        const e = smartVideo.config.videoScreen.dateFormat ? smartVideo.config.videoScreen.dateFormat : "default";
        return r.format(e);
    }
}


window.addEventListener("click", windowOnClick),
    (document.onkeydown = function (e) {
        "Escape" === e.key && (toggleModal(!1), (chatRoom.style.display = "none"));
    });
var dateFormat = (function () {
    var e = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
        t = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
        i = /[^-+\dA-Z]/g,
        o = function (e, t) {
            for (e = String(e), t = t || 2; e.length < t; ) e = "0" + e;
            return e;
        };
    return function (n, r, s, a) {
        var c = dateFormat;
        if ((1 != arguments.length || "[object String]" != Object.prototype.toString.call(n) || /\d/.test(n) || ((r = n), (n = void 0)), (n = n ? new Date(n) : new Date()), isNaN(n))) throw SyntaxError("invalid date");
        "UTC:" == (r = String(c.masks[r] || r || c.masks.default)).slice(0, 4) && ((r = r.slice(4)), (s = !0));
        var l = s ? "getUTC" : "get",
            d = n[l + "Date"](),
            h = n[l + "Day"](),
            u = n[l + "Month"](),
            f = n[l + "FullYear"](),
            m = n[l + "Hours"](),
            g = n[l + "Minutes"](),
            p = n[l + "Seconds"](),
            v = n[l + "Milliseconds"](),
            b = s ? 0 : n.getTimezoneOffset(),
            y = {
                d: d,
                dd: o(d),
                ddd: a.dayNames[h],
                dddd: a.dayNames[h + 7],
                m: u + 1,
                mm: o(u + 1),
                mmm: a.monthNames[u],
                mmmm: a.monthNames[u + 12],
                yy: String(f).slice(2),
                yyyy: f,
                h: m % 12 || 12,
                hh: o(m % 12 || 12),
                H: m,
                HH: o(m),
                M: g,
                MM: o(g),
                s: p,
                ss: o(p),
                l: o(v, 3),
                L: o(v > 99 ? Math.round(v / 10) : v),
                t: m < 12 ? "a" : "p",
                tt: m < 12 ? "am" : "pm",
                T: m < 12 ? "A" : "P",
                TT: m < 12 ? "AM" : "PM",
                Z: s ? "UTC" : (String(n).match(t) || [""]).pop().replace(i, ""),
                o: (b > 0 ? "-" : "+") + o(100 * Math.floor(Math.abs(b) / 60) + (Math.abs(b) % 60), 4),
                S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (((d % 100) - (d % 10) != 10) * d) % 10],
            };
        return r.replace(e, function (e) {
            return e in y ? y[e] : e.slice(1, e.length - 1);
        });
    };
})();
function changeVirtual(e, t) {
    var i,
        o = canvasElement.getContext("2d", { willReadFrequently: !0 });
    (activeCanvasElement = 1 === e ? canvasElementBlur : canvasElement),
        (videoElement = t ? document.getElementById(t) : videoElement),
        (videoElement.onplaying = () => {
            (canvasElementBlur.height = canvasElement.height = videoElement.videoHeight), (canvasElementBlur.width = canvasElement.width = videoElement.videoWidth);
        });
    let n = !0;
    async function r() {
        if (n) {
            n = !1;
            await i
                .segmentPerson(videoElement, {
                    flipHorizontal: smartVideo.config.videoScreen.localFeedMirrored,
                    internalResolution: "high",
                    segmentationThreshold: 0.7,
                    maxDetections: 10,
                    scoreThreshold: 0.2,
                    nmsRadius: 20,
                    minKeypointScore: 0.3,
                    refineSteps: 10,
                })
                .then((t) => {
                    !(function (t) {
                        const i = 10,
                            n = 3;
                        1 == e && canvasElementBlur.width > 0 && bodyPix.drawBokehEffect(canvasElementBlur, videoElement, t, i, n, smartVideo.config.videoScreen.localFeedMirrored);
                        if (2 == e) {
                            const e = { r: 0, g: 0, b: 0, a: 0 },
                                i = { r: 0, g: 0, b: 0, a: 255 };
                            let n = bodyPix.toMask(t, e, i);
                            if (n) {
                                let e = document.getElementById("backgroundImage");
                                o.putImageData(n, 0, 0),
                                    (o.globalCompositeOperation = "source-in"),
                                    o.drawImage(e, 0, 0, videoElement.width, videoElement.height),
                                    (o.globalCompositeOperation = "destination-over"),
                                    o.drawImage(videoElement, 0, 0, videoElement.width, videoElement.height),
                                    (o.globalCompositeOperation = "source-over");
                            }
                        }
                    })(t),
                        (n = !0);
                });
        }
        window.requestAnimationFrame(r);
    }
    isVirtual
        ? ((isVirtual = !1), display(canvasElement, "none"), display(canvasElementBlur, "none"), (videoElement.hidden = !1), (canvasElement.hidden = !0), (canvasElementBlur.hidden = !0))
        : ((videoElement.hidden = !0),
          1 === e
              ? ((canvasElementBlur.hidden = !1), (canvasElement.hidden = !0), display(canvasElementBlur, "block"), display(canvasElement, "none"))
              : 2 == e && ((canvasElementBlur.hidden = !0), (canvasElement.hidden = !1), display(canvasElement, "block"), display(canvasElementBlur, "none")),
          (isVirtual = !0),
          bodyPix
              .load({ architecture: "MobileNetV1", outputStride: 16, multiplier: 0.75, quantBytes: 2 })
              .then(function (n) {
                  (i = n),
                      (canvasElementBlur.height = canvasElement.height = videoElement.videoHeight),
                      (canvasElementBlur.width = canvasElement.width = videoElement.videoWidth),
                      2 == e && o.clearRect(0, 0, canvasElement.width, canvasElement.height),
                      "initVideo" === t && r();
              })
              .catch((e) => console.log(e)),
          (videoElement.onloadedmetadata = () => {
              (canvasElementBlur.height = canvasElement.height = videoElement.videoHeight), (canvasElementBlur.width = canvasElement.width = videoElement.videoWidth);
          }),
          "initVideo" !== t && videoElement.addEventListener("loadeddata", r));
}
(dateFormat.masks = {
    default: "dd-mm-yyyy HH:MM",
    shortDate: "m/d/yy HH:MM",
    mediumDate: "mmm d, yyyy HH:MM",
    longDate: "mmmm d, yyyy HH:MM",
    fullDate: "dddd, mmmm d, yyyy HH:MM",
    isoDate: "yyyy-mm-dd HH:MM",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
}),
    (Date.prototype.format = function (e, t) {
        let i = {
            dayNames: [
                smartVideo.msgStore.Sun,
                smartVideo.msgStore.Mon,
                smartVideo.msgStore.Tue,
                smartVideo.msgStore.Wed,
                smartVideo.msgStore.Thu,
                smartVideo.msgStore.Fri,
                smartVideo.msgStore.Sat,
                smartVideo.msgStore.Sunday,
                smartVideo.msgStore.Monday,
                smartVideo.msgStore.Tuesday,
                smartVideo.msgStore.Wednesday,
                smartVideo.msgStore.Thursday,
                smartVideo.msgStore.Friday,
                smartVideo.msgStore.Saturday,
            ],
            monthNames: [
                smartVideo.msgStore.Jan,
                smartVideo.msgStore.Feb,
                smartVideo.msgStore.Mar,
                smartVideo.msgStore.Apr,
                smartVideo.msgStore.May,
                smartVideo.msgStore.Jun,
                smartVideo.msgStore.Jul,
                smartVideo.msgStore.Aug,
                smartVideo.msgStore.Sep,
                smartVideo.msgStore.Oct,
                smartVideo.msgStore.Nov,
                smartVideo.msgStore.Dec,
                smartVideo.msgStore.January,
                smartVideo.msgStore.February,
                smartVideo.msgStore.March,
                smartVideo.msgStore.April,
                smartVideo.msgStore.May,
                smartVideo.msgStore.June,
                smartVideo.msgStore.July,
                smartVideo.msgStore.August,
                smartVideo.msgStore.September,
                smartVideo.msgStore.October,
                smartVideo.msgStore.November,
                smartVideo.msgStore.December,
            ],
        };
        return dateFormat(this, e, t, i);
    });
const html = { newline: "<br />", audioOn: "fas fa-microphone", audioOff: "fas fa-microphone-slash", userName: "username", userHand: "fas fa-hand-paper" },
    icons = { fileSend: '<i class="fa-solid fa-file-export"></i>', fileReceive: '<i class="fa-solid fa-file-import"></i>' },
    image = { audio: "../img/loader.gif", avatar: "../img/profile.png", poster: "../img/loader.gif" },
    mediaType = { audio: "audioType", audioTab: "audioTab", video: "videoType", camera: "cameraType", screen: "screenType", speaker: "speakerType" },
    _EVENTS = {
        openRoom: "openRoom",
        exitRoom: "exitRoom",
        startRec: "startRec",
        pauseRec: "pauseRec",
        resumeRec: "resumeRec",
        stopRec: "stopRec",
        raiseHand: "raiseHand",
        lowerHand: "lowerHand",
        startVideo: "startVideo",
        pauseVideo: "pauseVideo",
        resumeVideo: "resumeVideo",
        stopVideo: "stopVideo",
        startAudio: "startAudio",
        pauseAudio: "pauseAudio",
        resumeAudio: "resumeAudio",
        stopAudio: "stopAudio",
        startScreen: "startScreen",
        pauseScreen: "pauseScreen",
        resumeScreen: "resumeScreen",
        stopScreen: "stopScreen",
        roomLock: "roomLock",
        roomUnlock: "roomUnlock",
        admitOn: "admitOn",
        admitOff: "admitOff",
    };
let recordedBlobs, transcriptTimer, recognition;
class RoomClient {
    constructor(e, t, i, o, n, r, s, a, c, l, d, h, u, f, m, g,) {
        this.isScreenSharingActive = false; // Track if screen sharing is active
        (window.roomClient = this),
            (this.localAudioEl = e),
            (this.remoteAudioEl = t),
            (this.videoMediaContainer = i),
            (this.videoPinMediaContainer = o),
            (this.mediasoupClient = n),
            (this.socket = r),
            (this.room_id = s),
            (this.peer_id = r.id),
            (this.peer_name = a),
            (this.peer_info = c),
            (this.isAudioAllowed = l),
            (this.isVideoAllowed = d),
            (this.isScreenAllowed = h),
            (this.joinRoomWithScreen = u),
            (this.producerTransport = null),
            (this.consumerTransport = null),
            (this.device = null),
            (this.isMobileDevice = DetectRTC.isMobileDevice),
            (this._isConnected = !1),
            (this.isVideoOnFullScreen = !1),
            (this.isVideoFullScreenSupported = !c.is_mobile_device || "iOS" !== c.os_name),
            (this.isChatOpen = !1),
            (this.isChatEmojiOpen = !1),
            (this.showChatOnMessage = !0),
            (this.isChatBgTransparent = !1),
            (this.isVideoPinned = !1),
            (this.isChatPinned = !1),
            (this.pinnedVideoPlayerId = null),
            (this.camVideo = !1),
            (this.camera = "user"),
            (this.chatMessages = []),
            (this.leftMsgAvatar = null),
            (this.rightMsgAvatar = null),
            (this.localVideoStream = null),
            (this.localScreenStream = null),
            (this.localAudioStream = null),
            // (this.mediaRecorder = null),
            (this.recScreenStream = null),
            (this._isRecording = !1),
            (this._isStoppableRecording = !1),
            (this._isPausedRecording = !1),
            (this.RoomPassword = m),
            (this.fileToSend = null),
            (this.fileReader = null),
            (this.receiveBuffer = []),
            (this.receivedSize = 0),
            (this.incomingFileInfo = null),
            (this.incomingFileData = null),
            (this.sendInProgress = !1),
            (this.receiveInProgress = !1),
            (this.fileSharingInput = "*"),
            (this.chunkSize = 16384),
            (this.maxFileSize = 10485760),
            (this.forceVP8 = !1),
            (this.forceVP9 = !1),
            (this.forceH264 = !1),
            (this.enableWebcamLayers = !0),
            (this.enableSharingLayers = !1),
            (this.numSimulcastStreams = 3),
            (this.webcamScalabilityMode = "L3T3"),
            (this.sharingScalabilityMode = "L3T3"),
            (this.myVideoEl = null),
            (this.myAudioEl = null),
            (this.showPeerInfo = !1),
            (this.videoProducerId = null),
            (this.screenProducerId = null),
            (this.audioProducerId = null),
            (this.audioConsumers = new Map()),
            (this.consumers = new Map()),
            (this.producers = new Map()),
            (this.producerLabel = new Map()),
            (this.eventListeners = new Map()),
            window.fileBlob,
            window.fileFile,
            this.fileNameRecording,
            (this.isSendSaveRecording = !1),
            Object.keys(_EVENTS).forEach(
                function (e) {
                    this.eventListeners.set(e, []);
                }.bind(this)
            ),
            (this.socket.request = function (e, t = {}) {
                return new Promise((i, o) => {
                    r.emit(e, t, (e) => {
                        e.error ? o(e.error) : i(e);
                    });
                });
            }),
            this.createRoom(this.room_id).then(
                async function () {
                    if (m) {
                        let e = { action: "lock", password: m };
                        this.setRoomLocked(e);
                    }
                    this.room(isWaitingRoomEnabled ? "admitOn" : "admitOff"), this.waitingRoomToggle(), (this.peer_info.peer_admin = isAdmin);
                    let e = { room_id: this.room_id, peer_info: this.peer_info };
                    isWaitingRoomEnabled && !isAdmin && (e.peer_info.peer_waiting = !0),
                        await this.join(e),
                        this.initSockets(),
                        (this._isConnected = !0),
                        f(),
                        addEventListener("beforeunload", (e) => {
                            if (window.onbeforeunload) {
                                return window.roomClient.wantExit();
                            }
                        })
                        // This line is commented to prevent alert dialog 
                        // (onbeforeunload = (e) => this.wantExit());
                }.bind(this)
            );
    }
    async createRoom(e) {
        await this.socket.request("createRoom", { room_id: e }).catch((e) => {
            console.error("Create room error:", e);
        });
    }
    async join(e) {
        isRequest &&
            this.socket
                .request("requestSession", { room_id: room_id, peer_name: peer_name })
                .then(function () {}.bind(this))
                .catch((e) => {
                    console.error("request presence error:", e);
                }),
            this.socket
                .request("join", e)
                .then(
                    async function (e) {
                        return "isLocked" === e
                            ? (this.event(_EVENTS.roomLock), this.unlockTheRoom())
                            : "isAdmit" === e
                            ? (this.event(_EVENTS.admitOn), this.waitJoinConfirm())
                            : "isBreakout" === e
                            ? this.breakoutNotify()
                            : void (await this.joinAllowed(e));
                    }.bind(this)
                )
                .catch((e) => {
                    console.error("Join error:", e);
                });
    }
    async joinAllowed(e) {
        await this.handleRoomInfo(e);
        const t = await this.socket.request("getRouterRtpCapabilities");
        (this.device = await this.loadDevice(t)), await this.initTransports(this.device), await this.startLocalMedia(), this.socket.emit("getProducers");
    }
    async handleRoomInfo(e) {
        let t = new Map(JSON.parse(e.peers));
        attendeesCount = t.size;
        for (let e of Array.from(t.keys()).filter((e) => e == this.peer_id)) {
            t.get(e).peer_info;
        }
        adaptAspectRatio(attendeesCount);
        for (let e of Array.from(t.keys()).filter((e) => e !== this.peer_id)) {
            let i = t.get(e).peer_info;
            i.peer_video || (await this.removeVideo(i, !0)), i.peer_waiting && this.startWaitingRoom(i);
        }
        this.getAttendeesCount(), 1 == attendeesCount ? shareRoom() : (this.isScreenAllowed && this.shareScreen(), sound("joined"));
    }
    async loadDevice(e) {
        let t;
        try {
            t = new this.mediasoupClient.Device();
        } catch (e) {
            "UnsupportedError" === e.name && setNotify("error", smartVideo.msgStore.browserNotSupported, "center"), setNotify("error", smartVideo.msgStore.browserNotSupported + " " + e, "center");
        }
        return await t.load({ routerRtpCapabilities: e }), t;
    }
    async initTransports(e) {
        {
            const t = await this.socket.request("createWebRtcTransport", { forceTcp: !1, rtpCapabilities: e.rtpCapabilities });
            if (t.error) return void console.error("Create WebRtc Transport for Producer err: ", t.error);
            (this.producerTransport = e.createSendTransport(t)),
                this.producerTransport.on(
                    "connect",
                    async function ({ dtlsParameters: e }, i, o) {
                        this.socket.request("connectTransport", { dtlsParameters: e, transport_id: t.id }).then(i).catch(o);
                    }.bind(this)
                ),
                this.producerTransport.on(
                    "produce",
                    async function ({ kind: e, appData: t, rtpParameters: i }, o, n) {
                        try {
                            const { producer_id: n } = await this.socket.request("produce", { producerTransportId: this.producerTransport.id, kind: e, appData: t, rtpParameters: i });
                            o({ id: n });
                        } catch (e) {
                            n(e);
                        }
                    }.bind(this)
                ),
                this.producerTransport.on(
                    "connectionstatechange",
                    function (e) {
                        switch (e) {
                            case "connecting":
                            case "connected":
                            default:
                                break;
                            case "failed":
                                this.producerTransport.close();
                        }
                    }.bind(this)
                );
        }
        {
            const t = await this.socket.request("createWebRtcTransport", { forceTcp: !1 });
            if (t.error) return void console.error("Create WebRtc Transport for Consumer err: ", t.error);
            (this.consumerTransport = e.createRecvTransport(t)),
                this.consumerTransport.on(
                    "connect",
                    function ({ dtlsParameters: e }, t, i) {
                        this.socket.request("connectTransport", { transport_id: this.consumerTransport.id, dtlsParameters: e }).then(t).catch(i);
                    }.bind(this)
                ),
                this.consumerTransport.on(
                    "connectionstatechange",
                    async function (e) {
                        switch (e) {
                            case "connecting":
                            case "connected":
                            default:
                                break;
                            case "failed":
                                this.consumerTransport.close();
                        }
                    }.bind(this)
                );
        }
    }
    initSockets() {
        this.socket.on(
            "consumerClosed",
            function ({ consumer_id: e, consumer_kind: t }) {
                this.removeConsumer(e, t), getRoomAttendees();
            }.bind(this)
        ),
            this.socket.on(
                "removeVideo",
                function (e) {
                    this.removeVideo(e, !0), getRoomAttendees();
                }.bind(this)
            ),

            // Example: Detect when a screen share starts
            this.socket.on("newProducers", async (producers) => {
    for (const producer of producers) {
        if (producer.type === "screen") {
            await this.consume(producer.producer_id, producer.peer_name, producer.peer_info, producer.type);
            this.restartRecording(); // Restart recording to include the new screen share
        }
    }
            });
            this.socket.on(
                "removeMe",
                function (e) {
                    this.removeVideoOff(e.peer_id), this.waitingRoomRemoveMe(e.peer_id), (attendeesCount = e.peer_counts), adaptAspectRatio(attendeesCount), getRoomAttendees();
                }.bind(this)
            ),
            this.socket.on(
                "getAttendeesCount",
                function (e) {
                    (attendeesCount = e.peer_counts), adaptAspectRatio(attendeesCount);
                }.bind(this)
            ),
            this.socket.on(
                "newProducers",
                async function (e) {
                    if (e.length > 0) {
                        for (let { producer_id: t, peer_name: i, peer_info: o, type: n } of e) await this.consume(t, i, o, n);
                        getRoomAttendees();
                    }
                }.bind(this)
            ),
            this.socket.on(
                "message",
                async function (e) {
                    if (smartVideo.config.transcribe && smartVideo.config.transcribe.apiKey && languageTo) {
                        const t = await speechRec.translate(e.peer_msg, !0);
                        e.peer_msg = t;
                    }
                    this.showMessage(e);
                }.bind(this)
            ),
            this.socket.on(
                "transcript",
                function (e) {
                    this.showTranscribeMessage(e.peer_name + ": " + e.peer_msg);
                }.bind(this)
            ),
            this.socket.on(
                "room",
                function (e) {
                    this.room(e, !1);
                }.bind(this)
            ),
            this.socket.on(
                "roomPassword",
                function (e) {
                    this.roomPassword(e);
                }.bind(this)
            ),
            this.socket.on(
                "roomAdmit",
                function (e) {
                    this.roomWaitingRoom(e);
                }.bind(this)
            ),
            this.socket.on(
                "roomBreakout",
                function () {
                    let e = liveStorage.getItem("breakoutRooms" + parent_id) || breakoutRooms;
                    this.setPeer(this.peer_name, this.peer_id, "breakout", !0, !0, !1, e);
                }.bind(this)
            ),
            this.socket.on(
                "peer",
                function (e) {
                    this.peer(e.from_peer_name, e.peer_id, e.action, !1, e.broadcast);
                }.bind(this)
            ),
            this.socket.on(
                "setPeer",
                function (e) {
                    this.setPeer(e.peer_name, e.peer_id, e.type, e.status, !1, !1, e.data),
                        e.producer_id &&
                            "screen" == e.type &&
                            e.status &&
                            setTimeout(() => {
                                document.querySelector('[data-producer-id="' + e.producer_id + '"]').querySelector(".username").innerHTML += "&nbsp;" + smartVideo.msgStore.screenshare;
                            }, 100);
                }.bind(this)
            ),
            this.socket.on(
                "fileInfo",
                function (e) {
                    this.handleFileInfo(e);
                }.bind(this)
            ),
            this.socket.on(
                "file",
                function (e) {
                    this.handleFile(e);
                }.bind(this)
            ),
            this.socket.on(
                "shareMedia",
                function (e) {
                    this.shareMedia(e);
                }.bind(this)
            ),
            this.socket.on(
                "fileAbort",
                function (e) {
                    this.handleFileAbort(e);
                }.bind(this)
            ),
            this.socket.on(
                "whiteboardData",
                function (e) {
                    JsonToWbCanvas(e);
                }.bind(this)
            ),
            this.socket.on(
                "whiteboard",
                function (e) {
                    whiteboard(e, !1);
                }.bind(this)
            ),
            this.socket.on(
                "audioVolume",
                function (e) {
                    this.handleAudioVolume(e);
                }.bind(this)
            ),
            this.socket.on(
                "disconnect",
                function () {
                    (window.onbeforeunload = null), setNotify("error", smartVideo.msgStore.disconnectedFromServer, "top", 1e5);
                }.bind(this)
            ),
            this.socket.on(
                "connect",
                function () {
                    (window.onbeforeunload = null), window.location.reload();
                }.bind(this)
            ),
            this.socket.on(
                "startRecording",
                function (e) {
                    setNotify("info", smartVideo.msgStore.userStartRecording.replace("{{user}}", e.peer_name), "top", 1e4);
                }.bind(this)
            );
    }
    async startLocalMedia() {
        console.trace();
        console.log("startLocalMedia() invoked");
        
        this.isAudioAllowed ? this.produce(mediaType.audio, microphoneSelect.value) : setColor(startAudioButton, "red"),
            this.isVideoAllowed ? this.produce(mediaType.video, videoSelect.value) : (setColor(startVideoButton, "red"), this.removeVideo(this.peer_info, !1), this.sendVideoOff()),
            this.joinRoomWithScreen && this.produce(mediaType.screen, null, !1, !0);
            if (isAdmin) {
                let preloader = this.getId('loader');
                preloader.style.display = 'block';
                setTimeout(()=>{this.startRecording();}, 5000);
            }
       
    }
    async produce(e, t = null, i = false, o = false) {
        let n, r = {}, s = false, a = false;
    
        switch (e) {
            case mediaType.audio:
                this.isAudioAllowed = true;
                r = this.getAudioConstraints(t);
                s = true;
                break;
            case mediaType.video:
                r = i ? this.getCameraConstraints() : this.getVideoConstraints(t);
                break;
            case mediaType.screen:
                r = this.getScreenConstraints();
                a = true;
                setNotify("info", "Starting screen sharing. Recording will switch to screen content.", "top", 5000);
                break;
            default:
                return;
        }
    
        if ((this.device.canProduce("video") || s) && !this.producerLabel.has(e)) {
            try {
                this.ensureCanvasAndVideos();
                n = a
                    ? await navigator.mediaDevices.getDisplayMedia(r)
                    : await navigator.mediaDevices.getUserMedia(r);
                streamS = n;
                screenshareEnable = streamS;
    
                if (s) {
                    this.localAudioStream = n;
                } else if (a) {
                    this.localScreenStream = n;
                    this.screenVideo.srcObject = n;
                    this.screenVideo.onloadedmetadata = async () => {
                        try {
                            await this.screenVideo.play();
                            this.updateCanvasSize();
                            if (this._isRecording) {
                                await this.switchToScreenRecording();
                            } else {
                                this.drawToCanvas(); // Start drawing if not recording
                            }
                        } catch (err) {
                            console.error("Error playing screen video:", err);
                        }
                    };
                } else {
                    this.localVideoStream = n;
                    this.cameraVideo.srcObject = n;
                    this.cameraVideo.onloadedmetadata = async () => {
                        try {
                            await this.cameraVideo.play();
                            this.updateCanvasSize();
                            if (!this._isRecording) {
                                this.drawToCanvas(); // Start drawing if not recording
                            }
                        } catch (err) {
                            console.error("Error playing camera video:", err);
                        }
                    };
                }
    
                const t = { track: s ? n.getAudioTracks()[0] : n.getVideoTracks()[0], appData: { mediaType: e } };
                // Encoding and producer logic remains unchanged...
    
                const producer = await this.producerTransport.produce(t);
                this.producers.set(producer.id, producer);
                this.producerLabel.set(e, producer.id);
    
                if (a && n.getAudioTracks()[0]) await this.produceScreenAudio(n);
                if (s) this.audioProducerId = producer.id;
                else if (e === mediaType.video) this.videoProducerId = producer.id;
                else if (e === mediaType.screen) this.screenProducerId = producer.id;
    
                let mediaEl = await this.handleProducer(producer.id, e, n);
                producer.on("trackended", () => this.closeProducer(e));
                // Other event handlers remain unchanged...
    
                switch (e) {
                    case mediaType.audio:
                        this.setIsAudio(this.peer_id, true);
                        this.event(_EVENTS.startAudio);
                        break;
                    case mediaType.video:
                        this.setIsVideo(this.peer_id, true);
                        this.event(_EVENTS.startVideo);
                        break;
                    case mediaType.screen:
                        this.setIsScreen(true, producer.id);
                        this.event(_EVENTS.startScreen);
                        break;
                }
            } catch (e) {
                console.error("Produce error:", e);
            }
        }
    }
    async produceScreenAudio(e) {
        try {
            if (this.producerLabel.has(mediaType.audioTab)) return;
            const t = { track: e.getAudioTracks()[0], appData: { mediaType: mediaType.audio } },
                i = await this.producerTransport.produce(t);
            this.producers.set(i.id, i);
            const o = await this.handleProducer(i.id, mediaType.audio, e);
            i.on("trackended", () => {
                this.closeProducer(mediaType.audioTab);
            }),
                i.on("transportclose", () => {
                    o.srcObject.getTracks().forEach(function (e) {
                        e.stop();
                    }),
                        o.parentNode.removeChild(o),
                        this.producers.delete(i.id);
                }),
                i.on("close", () => {
                    o.srcObject.getTracks().forEach(function (e) {
                        e.stop();
                    }),
                        o.parentNode.removeChild(o),
                        this.producers.delete(i.id);
                }),
                this.producerLabel.set(mediaType.audioTab, i.id);
        } catch (e) {
            console.error("Produce error:", e);
        }
    }
    startMyAudio() {
        startAudioButton.click(), this.setIsAudio(this.peer_id, !0), this.event(_EVENTS.startAudio), setAudioButtonsDisabled(!1);
    }
    stopMyAudio() {
        stopAudioButton.click(), this.setIsAudio(this.peer_id, !1), this.event(_EVENTS.stopAudio), setAudioButtonsDisabled(!0);
    }
    getAudioConstraints(e) {
        let t = smartVideo.config.videoScreen.audioConstraint ? smartVideo.config.videoScreen.audioConstraint : { echoCancellation: !0, noiseSuppression: !0, sampleRate: 44100 };
        return (t.deviceId = e), { audio: t, video: !1 };
    }
    getCameraConstraints() {
        return (this.camera = "user" == this.camera ? "environment" : "user"), "user" != this.camera ? (this.camVideo = { facingMode: { exact: this.camera } }) : (this.camVideo = !0), { audio: !1, video: this.camVideo };
    }
    getVideoConstraints(e) {
        let t = {
            audio: !1,
            video: smartVideo.config.videoScreen.videoConstraint
                ? smartVideo.config.videoScreen.videoConstraint
                : { width: { min: 640, ideal: 1920, max: 3840 }, height: { min: 480, ideal: 1080, max: 2160 }, aspectRatio: 1.777, frameRate: { min: 5, ideal: 15, max: 30 } },
        };
        return (t.video.deviceId = e), t;
    }
    getScreenConstraints() {
        return smartVideo.config.videoScreen.screenConstraint ? smartVideo.config.videoScreen.screenConstraint : { video: { displaySurface: "browser" }, audio: { channelCount: 2, echoCancellation: !1, noiseSuppression: !1 } };
    }
    getWebCamEncoding() {
        let e, t;
        if (this.forceVP8) {
            if (((t = this.device.rtpCapabilities.codecs.find((e) => "video/vp8" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired VP8 codec+configuration is not supported");
        } else if (this.forceH264) {
            if (((t = this.device.rtpCapabilities.codecs.find((e) => "video/h264" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired H264 codec+configuration is not supported");
        } else if (this.forceVP9 && ((t = this.device.rtpCapabilities.codecs.find((e) => "video/vp9" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired VP9 codec+configuration is not supported");
        if (this.enableWebcamLayers) {
            const i = this.device.rtpCapabilities.codecs.find((e) => "video" === e.kind);
            (this.forceVP9 && t) || "video/vp9" === i.mimeType.toLowerCase()
                ? (e = [{ maxBitrate: 5e6, scalabilityMode: this.webcamScalabilityMode || "L3T3_KEY" }])
                : ((e = [{ scaleResolutionDownBy: 1, maxBitrate: 5e6, scalabilityMode: this.webcamScalabilityMode || "L1T3" }]),
                  this.numSimulcastStreams > 1 && e.unshift({ scaleResolutionDownBy: 2, maxBitrate: 1e6, scalabilityMode: this.webcamScalabilityMode || "L1T3" }),
                  this.numSimulcastStreams > 2 && e.unshift({ scaleResolutionDownBy: 4, maxBitrate: 5e5, scalabilityMode: this.webcamScalabilityMode || "L1T3" }));
        }
        return { encodings: e, codec: t };
    }
    getScreenEncoding() {
        let e, t;
        if (this.forceVP8) {
            if (((t = this.device.rtpCapabilities.codecs.find((e) => "video/vp8" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired VP8 codec+configuration is not supported");
        } else if (this.forceH264) {
            if (((t = this.device.rtpCapabilities.codecs.find((e) => "video/h264" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired H264 codec+configuration is not supported");
        } else if (this.forceVP9 && ((t = this.device.rtpCapabilities.codecs.find((e) => "video/vp9" === e.mimeType.toLowerCase())), !t)) throw new Error("Desired VP9 codec+configuration is not supported");
        if (this.enableSharingLayers) {
            const i = this.device.rtpCapabilities.codecs.find((e) => "video" === e.kind);
            (this.forceVP9 && t) || "video/vp9" === i.mimeType.toLowerCase()
                ? (e = [{ maxBitrate: 5e6, scalabilityMode: this.sharingScalabilityMode || "L3T3", dtx: !0 }])
                : ((e = [{ scaleResolutionDownBy: 1, maxBitrate: 5e6, scalabilityMode: this.sharingScalabilityMode || "L1T3", dtx: !0 }]),
                  this.numSimulcastStreams > 1 && e.unshift({ scaleResolutionDownBy: 2, maxBitrate: 1e6, scalabilityMode: this.sharingScalabilityMode || "L1T3", dtx: !0 }),
                  this.numSimulcastStreams > 2 && e.unshift({ scaleResolutionDownBy: 4, maxBitrate: 5e5, scalabilityMode: this.sharingScalabilityMode || "L1T3", dtx: !0 }));
        }
        return { encodings: e, codec: t };
    }
    closeThenProduce(e, t, i = !1) {
        this.closeProducer(e),
            setTimeout(function () {
                rc.produce(e, t, i);
            }, 1e3);
    }
    async handleProducer(e, t, i) {
        const o = smartVideo.config.videoScreen && smartVideo.config.videoScreen.lockedFeed && (t == mediaType.video) ? "videoContainerElementProducer" : "videoContainerProducer ";
        let n,
            r,
            s,
            a,
            c,
            l,
            d,
            h = t == mediaType.screen;
        switch (t) {
            case mediaType.video:
            case mediaType.screen:
                this.removeVideoOff(this.peer_id),
                    (r = document.createElement("div")),
                    (r.className = o),
                    (r.id = e + "__d"),
                    t === mediaType.video && isVirtual
                        ? ((n = videoElement),
                          n.setAttribute("playsinline", !0),
                          (n.autoplay = !0),
                          (activeCanvasElement.hidden = !1),
                          (videoElement.hidden = !0),
                          (d = activeCanvasElement),
                          d.setAttribute("id", "backgroundCanvas"),
                          d.setAttribute("playsinline", !0),
                          (d.autoplay = !0))
                        : ((n = document.createElement("video")), n.setAttribute("playsinline", !0), (n.autoplay = !0)),
                    n.setAttribute("id", e),
                    (n.id = e),
                    (n.poster = image.poster),
                    smartVideo.config.videoScreen && smartVideo.config.videoScreen.localFeedMirrored && t == mediaType.video ? (n.className = "self mirror") : (n.className = "self"),
                    (l = document.createElement("div")),
                    l.setAttribute("id", this.peer_id + "__ud"),
                    (l.className = "userMenuBar"),
                    (c = document.createElement("i")),
                    (c.id = this.peer_id + "__audio"),
                    (c.className = this.peer_info.peer_audio ? html.audioOn : html.audioOff),
                    (s = document.createElement("span")),
                    (s.id = this.peer_id + "__name"),
                    (s.className = html.userName),
                    (s.innerHTML = "&nbsp;" + this.peer_name),
                    (a = document.createElement("button")),
                    (a.id = this.peer_id + "__hand"),
                    (a.className = html.userHand),
                    r.append(n),
                    isVirtual && r.append(activeCanvasElement),
                    l.appendChild(c),
                    l.appendChild(a),
                    l.appendChild(s),
                    r.appendChild(l),
                    this.videoMediaContainer.appendChild(r),
                    this.attachMediaStream(n, i, t, "Producer"),
                    (this.myVideoEl = n),
                    this.handleDD(n.id, this.peer_id, !0),
                    h && this.handlePN(n.id, r.id, h),
                    document.getElementById(n.id).click();
                    this.checkPeerInfoStatus(this.peer_info),
                    smartVideo.config.recording.autoStart && isAdmin && t === mediaType.video,
                    attendeesCount <= 3 && t === mediaType.screen
                        ? (this.peer("me", this.peer_id + "___sStart", "screenStart", !0, !0, !1), setAspectRatio(2))
                        : (attendeesCount > 1 && this.peer("me", this.peer_id + "___sStop", "screenStop", !0, !0, !1), setVideoDimensions());
              
                        let videoPinMediaContainer = document.getElementById("videoPinMediaContainer");
                        let elements = document.querySelectorAll(".videoContainerElementProducer, .videoContainerElementcamera:first-child");
                        let startScreenButton = document.getElementById("startScreenButton");
                        let stopScreenButton = document.getElementById("stopScreenButton");

                        function updateStyles() {
                        if (videoPinMediaContainer && window.getComputedStyle(videoPinMediaContainer).display === "none") {
                        elements.forEach(element => {
                        element.style.width = "62.5rem";
                        element.style.height = "31.25rem";
                        element.style.position = "static"; 
                         });
                         } else {
                        elements.forEach(element => {
                        element.style.width = "300px";  
                        element.style.height = "200px";
                        element.style.position = "absolute"; 
                         });
                         }
          }


                       startScreenButton.onclick = () => {
                       rc.produce(RoomClient.mediaType.screen);
                       videoPinMediaContainer.style.display = "block"; // Simulating screen share UI change
                       updateStyles();
                       console.log("startProduce");
                       };

                       stopScreenButton.onclick = () => {
                       rc.closeProducer(RoomClient.mediaType.screen);
                       videoPinMediaContainer.style.display = "none"; // Resetting UI on stop
                       updateStyles();
                       console.log("stopProduce");
                       };


updateStyles();


                        break;
            case mediaType.audio:
                (n = document.createElement("audio")),
                    (n.id = e + "__localAudio"),
                    (n.controls = !1),
                    (n.autoplay = !0),
                    (n.muted = !0),
                    (n.volume = 0),
                    (this.myAudioEl = n),
                    this.localAudioEl.appendChild(n),
                    this.attachMediaStream(n, i, t, "Producer"),
                    this.isAudioAllowed && !speakerSelect.disabled && this.attachSinkId(n, speakerSelect.value);
        }
        return n;
    }
    pauseProducer(e) {
        if (!this.producerLabel.has(e)) return;
        let t = this.producerLabel.get(e);
        switch ((this.producers.get(t).pause(), e)) {
            case mediaType.audio:
                this.event(_EVENTS.pauseAudio);
                break;
            case mediaType.video:
                this.event(_EVENTS.pauseVideo);
                break;
            case mediaType.screen:
                this.event(_EVENTS.pauseScreen);
                break;
            default:
                return;
        }
    }
    resumeProducer(e) {
        if (!this.producerLabel.has(e)) return;
        let t = this.producerLabel.get(e);
        switch ((this.producers.get(t).resume(), e)) {
            case mediaType.audio:
                this.event(_EVENTS.resumeAudio);
                break;
            case mediaType.video:
                this.event(_EVENTS.resumeVideo);
                break;
            case mediaType.screen:
                this.event(_EVENTS.resumeScreen);
                break;
            default:
                return;
        }
    }
    async closeProducer(e) {
        if (!this.producerLabel.has(e)) return;
        // let ee = this.isRecording();
        // ee && this.stopRecording();
        let t = this.producerLabel.get(e),
            i = { peer_name: this.peer_name, producer_id: t, type: e, status: !1 };
        if ((this.socket.emit("producerClosed", i), this.producers.get(t).close(), this.producers.delete(t), this.producerLabel.delete(e), e !== mediaType.audio)) {
            let e = this.getId(t),
                i = this.getId(t + "__d");
            // if (e.srcObject.getTracks().length > 0) {
            //     console.log("stoopped");
            //     e.srcObject.getTracks()[0].stop();
            // }
            // const tracks = e.srcObject.getTracks();

            e.srcObject.getTracks().forEach(track => track.stop());
            e.srcObject = null;

            // e.srcObject.getTracks().forEach(function (e) {
            //     e.stop();
            // })
            i.parentNode.removeChild(i),
            this.isVideoPinned && this.pinnedVideoPlayerId == t && this.removeVideoPinMediaContainer(),
            setVideoDimensions();
        }
        if (e === mediaType.audio) {
            let e = this.getId(t + "__localAudio");
            e.srcObject.getTracks().forEach(function (e) {
                e.stop();
            }),
                this.localAudioEl.removeChild(e);
        }
        
        switch (e) {
            case mediaType.audio:
                this.setIsAudio(this.peer_id, !1), this.event(_EVENTS.stopAudio);
                console.log("audio stopped");
                break;
            case mediaType.video:
                this.setIsVideo(this.peer_id, !1), this.event(_EVENTS.stopVideo);
                console.log("video stopped");
                break;
            case mediaType.screen:
                this.setIsScreen(!1, t), this.event(_EVENTS.stopScreen);
                console.log("screen share stopped");
                // get the media track
                // const mediaTrack = await navigator.mediaDevices.getDisplayMedia().getTracks();
                // stop the media track to stop screen sharing
                // console.log(mediaTrack);
                // mediaTrack.stop();
                break;
            default:
                return;
        }
        screenshareEnable = null;
    }
    async produceScreenAudio(e) {
        try {
            if ((this.stopMyAudio(), this.producerLabel.has(mediaType.audio))) return;
            const t = { track: e.getAudioTracks()[0], appData: { mediaType: mediaType.audio } },
                i = await this.producerTransport.produce(t);
            this.producers.set(i.id, i);
            const o = await this.handleProducer(i.id, mediaType.audio, e);
            i.on("trackended", () => {
                this.closeProducer(mediaType.audio), this.startMyAudio();
            }),
                i.on("transportclose", () => {
                    o.srcObject.getTracks().forEach(function (e) {
                        e.stop();
                    }),
                        o.parentNode.removeChild(o),
                        this.producers.delete(i.id);
                }),
                i.on("close", () => {
                    o.srcObject.getTracks().forEach(function (e) {
                        e.stop();
                    }),
                        o.parentNode.removeChild(o),
                        this.producers.delete(i.id);
                }),
                this.producerLabel.set(mediaType.audio, i.id);
        } catch (e) {
            console.error("Produce error:", e);
        }
    }
    startMyAudio() {
        startAudioButton.click(), this.setIsAudio(this.peer_id, !0), this.event(_EVENTS.startAudio), setAudioButtonsDisabled(!1);
    }
    stopMyAudio() {
        stopAudioButton.click(), this.setIsAudio(this.peer_id, !1), this.event(_EVENTS.stopAudio), setAudioButtonsDisabled(!0);
    }
    async consume(e, t, i, o) {
        wbIsOpen && isAdmin && whiteboardData(),
            this.getConsumeStream(e, i.peer_id, o).then(
                function ({ consumer: o, stream: n, kind: r,type:k }) {
                    this.consumers.set(o.id, o);
                        //"video" === r ? this.handleConsumer(o.id, mediaType.video, n, t, i, e) : this.handleConsumer(o.id, mediaType.audio, n, t, i, e),

                        if(k == "video" && r == "video"){
                            this.handleConsumer(o.id, mediaType.video, n, t, i, e);
                        }else if(k == "screen" && r == "video"){
                            this.handleConsumer(o.id, mediaType.screen, n, t, i, e)
                        }else{
                            this.handleConsumer(o.id, mediaType.audio, n, t, i, e);
                        }
                        this._isStoppableRecording &&
                            (rc.stopRecording(),
                            setTimeout(function () {
                                rc.startRecording();
                            }, 500)),
                        o.on(
                            "trackended",
                            function () {
                                this.removeConsumer(o.id, o.kind);
                            }.bind(this)
                        ),
                        o.on(
                            "transportclose",
                            function () {
                                this.removeConsumer(o.id, o.kind);
                            }.bind(this)
                        );
                }.bind(this)
            );
    }
    async getConsumeStream(e, t, i) {
        const { rtpCapabilities: o } = this.device,
            n = await this.socket.request("consume", { rtpCapabilities: o, consumerTransportId: this.consumerTransport.id, producerId: e }),
            { id: r, kind: s, rtpParameters: a } = n,
            c = t + (i == mediaType.screen ? "-screen-sharing" : "-mic-webcam"),
            l = await this.consumerTransport.consume({ id: r, producerId: e, kind: s, rtpParameters: a, codecOptions: {}, streamId: c }),
            d = new MediaStream();
        //return d.addTrack(l.track), { consumer: l, stream: d, kind: s };
        return d.addTrack(l.track), { consumer: l, stream: d, kind: s,type:n.type == "simple" && n.kind != "audio" ? "screen" : "video" };
    }
    handleConsumer(e, t, i, o, n, r) {
        let s,
            a,
            c,
            l,
            d,
            h,
            u,
            f = n.peer_id,
            m = t == mediaType.screen;
        switch (t) {
            case mediaType.video:
            case mediaType.screen:
                let g = n.peer_audio;
                
                // this.removeVideoOff(f),
                    (a = document.createElement("div")),
                    //(a.className = "videoContainerElement"),
                    (a.className = t == mediaType.screen ? "videoContainerConsumer":" videoContainerElementConsumer"),
                    (a.id = e + "__d"),
                    (a.dataset.producerId = r),
                    (s = document.createElement("video")),
                    s.setAttribute("id", e),
                    !m && s.setAttribute("name", f),
                    s.setAttribute("playsinline", !0),
                    (s.autoplay = !0),
                    (s.className = ""),
                    (s.poster = image.poster),
                    (s.style.objectFit = m ? "contain" : "var(--videoObjFit)"),
                    (u = document.createElement("div")),
                    u.setAttribute("id", f + "__ud"),
                    (u.className = "userMenuBar"),
                    (d = document.createElement("i")),
                    (d.id = f + "__audio"),
                    (d.className = g ? html.audioOn : html.audioOff),
                    (l = document.createElement("button")),
                    (l.id = f + "__hand"),
                    (l.className = html.userHand),
                    (h = document.createElement("button")),
                    (h.id = f + "__actionbutton"),
                    isAdmin &&
                        l.addEventListener("click", () => {
                            this.setPeer(o, n.peer_id, "hand", !1), this.peer("me", n.peer_id, "lowerhand");
                        }),
                    (c = document.createElement("span")),
                    (c.id = f + "__name"),
                    (c.className = html.userName),
                    (c.innerHTML = "&nbsp;" + o),
                    n.peer_screen && (c.innerHTML += "&nbsp;" + smartVideo.msgStore.screenshare),
                    a.appendChild(s),
                    u.appendChild(l),
                    u.appendChild(h),
                    u.appendChild(d),
                    u.appendChild(c),
                    a.appendChild(u),
                    this.videoMediaContainer.appendChild(a),
                    this.attachMediaStream(s, i, t, "Consumer"),
                    this.handlePN(s.id, a.id, m),
                    this.handleZV(s.id),
                    this.handleDD(s.id, f),
                    this.checkPeerInfoStatus(n),
                    t == mediaType.screen ? document.getElementById(s.id).click():"",
                    setVideoDimensions(),
                    this.removeVideoOff(f);

                    let videoPinMediaContainer = document.getElementById("videoPinMediaContainer");
                    let elements = document.querySelectorAll(".videoContainerElementConsumer, .videoContainerElementcamera:first-child");
            
                    function updateStyles() {
                    if (videoPinMediaContainer && window.getComputedStyle(videoPinMediaContainer).display === "none") {
                    elements.forEach(element => {
                    element.style.width = "62.5rem";
                    element.style.height = "31.25rem";
                    element.style.position = "static"; 
                     });
                     } else {
                    elements.forEach(element => {
                    element.style.width = "300px";  
                    element.style.height = "200px";
                    element.style.position = "absolute"; 
                     });
                     }
      }




                const observer = new MutationObserver(() => {
                    updateStyles();
                });
                

                observer.observe(videoPinMediaContainer, { attributes: true, attributeFilter: ['style'] });
                

                  updateStyles();


                break;
            case mediaType.audio:
                (s = document.createElement("audio")), (s.id = e), (s.autoplay = !0), (s.audio = 1), this.remoteAudioEl.appendChild(s), this.attachMediaStream(s, i, t, "Consumer");
        }
        return s;
    }

    removeConsumer(e, t) {
        let i = this.getId(e);
        if (
            (i &&
                (i.srcObject.getTracks().forEach(function (e) {
                    e.stop();
                }),
                i.parentNode.removeChild(i)),
            "video" === t)
        ) {
            let t = this.getId(e + "__d");
            t && (t.parentNode.removeChild(t), this.isVideoPinned && this.pinnedVideoPlayerId == e && this.removeVideoPinMediaContainer()), setVideoDimensions();
        }
        if ("audio" === t) {
            let t = this.getMapKeyByValue(this.audioConsumers, e);
            if (t) {
                let e = this.getId(t);
                e && (e.style.display = "none"), this.audioConsumers.delete(t);
            }
        }
        this.consumers.delete(e), sound("left");
    }
    async removeVideo(e, t = !1) {
        console.log(e);
        
        console.trace();
        if ((smartVideo.config.videoScreen && smartVideo.config.videoScreen.disableAttendeeVideosOff) || isRequest) return;
        if (dva && 0 == e.peer_admin) return;
        let i, o, n, r, s, a, c;
     
        //   const l = smartVideo.config.videoScreen && smartVideo.config.videoScreen.lockedFeed && !t ? "videoContainerElementParticipant" : "videoContainerElementParticipant";
     
        const modalContainer = document.getElementById("participants");
            console.log("modalContainer:",modalContainer)
        if (!modalContainer) {
            console.error("ParticipantsModal not found!");
            return;
        }
        console.log("modalContainer After If Condition:", modalContainer)
     
       const ParticipantContainer = modalContainer.querySelector(".participantContainer");
       console.log("ParticipantContainer:", ParticipantContainer)

        let d = e.peer_id,
            h = e.peer_name,
            u = e.peer_audio;

            // Commented below line and added 2 new line due to split screen at students end
            this.removeVideoOff(d),
            // const videoOff = this.getId(d + "__videoOff");
            // videoOff.remove();

            (i = document.createElement("div")),
            i.className = "videoContainerElementParticipant";
            // (i.className = l),
            // (i.id = e.peer_uuid + "__d"),
            (i.id = d + "__videoOff");
            
            if (e.peer_screen == true) {
                (i.style.display = "none");
            }
            (c = document.createElement("div")),
            c.setAttribute("id", this.peer_id + "__ud"),
            (c.className = "userMenuBar"),
            
            (r = document.createElement("i")),
            (r.id = d + "__audio"),
            (r.className = u ? html.audioOn : html.audioOff),

            (o = document.createElement("img")),
            // (o = document.createElement("video")),
            // (o.setAttribute("playsinline", !0)),
            // (o.setAttribute("preload", "auto")),
            (o.className = "participantsImg"),
            (o.id = d + "__img"),

            // (o.id = e.peer_uuid),
            // (o.setAttribute("name", d)),
            (s = document.createElement("span")),
            (s.id = d + "__name"),
            (s.className = html.userName),
            (s.innerHTML = "&nbsp;" + h),

            (n = document.createElement("button")),
            (n.id = d + "__hand"),

            (a = document.createElement("button")),
            (a.id = d + "__actionbutton"),

            (n.className = html.userHand),
            isAdmin &&
                n.addEventListener("click", () => {
                    this.setPeer(h, e.peer_id, "hand", !1), this.peer("me", e.peer_id, "lowerhand");
                }),
            c.appendChild(a),
            c.appendChild(n),
            c.appendChild(r),
            c.appendChild(s),
            i.appendChild(o),
            i.appendChild(c), 
          //  this.videoMediaContainer.appendChild(i),
          ParticipantContainer.appendChild(i);
            this.handleDD(i.id, d, !t),
            this.setVideoAvatarImgName(o.id, h),
            (this.getId(o.id).style.display = "block"),
            setVideoDimensions();
    }

    

    removeVideoOff(e) {        
        let t = this.getId(e + "__videoOff");
        t && (t.parentNode.removeChild(t), setVideoDimensions());
    }
    // shareScreen() {
    //     if (!this.isMobileDevice && (navigator.getDisplayMedia || navigator.mediaDevices.getDisplayMedia)) {
    //         actionModal(
    //             smartVideo.msgStore.doYouShare,
    //             "",
    //             smartVideo.msgStore.yes,
    //             function () {
    //                 startScreenButton.click();
    //             },
    //             smartVideo.msgStore.no
    //         );
    //     }
    // }

    shareScreen() {
        if (!this.isMobileDevice && (navigator.getDisplayMedia || navigator.mediaDevices.getDisplayMedia)) {
            if (this.isScreenSharingActive) {
                console.log("Screen sharing is already active.");
                return; // Prevent starting multiple screen shares
            }

            actionModal(
                smartVideo.msgStore.doYouShare,
                "",
                smartVideo.msgStore.yes,
                () => {
                    this.startScreenSharing();
                },
                smartVideo.msgStore.no
            );
        }
    }

    startScreenSharing() {
        // Capture the screen
        navigator.mediaDevices.getDisplayMedia({ video: true })
            .then((screenStream) => {
                // Capture the camera
                navigator.mediaDevices.getUserMedia({ video: true, audio: true })
                    .then((cameraStream) => {
                        // Combine both streams into a single MediaStream
                        const combinedStream = new MediaStream([
                            ...screenStream.getTracks(),
                            ...cameraStream.getTracks()
                        ]);
    
                        // Start the recording
                        this.startRecording(combinedStream);
    
                        // Display the camera stream as a Picture-in-Picture (PIP)
                        this.attachCameraPIP(cameraStream);
    
                        this.isScreenSharingActive = true; // Set screen sharing as active
                        console.log("Screen and Camera sharing started");
    
                        // Handle the screen stream stop event
                        screenStream.onended = () => {
                            this.stopScreenSharing();
                        };
                        // Handle the camera stream stop event
                        cameraStream.onended = () => {
                            this.stopScreenSharing();
                        };
                    })
                    .catch((error) => {
                        console.error("Error accessing camera:", error);
                    });
            })
            .catch((error) => {
                console.error("Error starting screen sharing:", error);
            });
    }
    

    attachCameraPIP(cameraStream) {
        // Create a video element for the camera stream
        const videoElement = document.createElement('video');
        videoElement.srcObject = cameraStream;
        videoElement.style.position = 'absolute';
        videoElement.style.bottom = '20px';
        videoElement.style.right = '20px';
        videoElement.style.width = '150px'; // Adjust size as needed
        videoElement.style.height = '150px'; // Adjust size as needed
        videoElement.style.zIndex = '9999'; // Ensure it stays on top of screen sharing
    
        // Append the video element to the DOM
        document.body.appendChild(videoElement);
        
        // Play the video
        videoElement.play();
    }
    

    stopScreenSharing() {
        // Mark screen sharing as inactive and cleanup if necessary
        this.isScreenSharingActive = false;
        console.log("Screen sharing ended");

        // Optionally stop the stream or clean up other related states
    }
    async exit(e = !1, course_id = null) {
        console.log(course_id);
        let t = function () {
            (this._isConnected = !1), this.consumerTransport.close(), this.producerTransport.close(), this.socket.off("disconnect"), this.socket.off("newProducers"), this.socket.off("consumerClosed");
        }.bind(this);
        await this.stopRecording(),
            e
                ? t()
                : this.socket
                      .request("exitRoom")
                      .then((e) => "")
                      .catch((e) => console.warn("Exit Room ", e))
                      .finally(
                          function () {
                              t();
                          }.bind(this)
                      ),
            this.event(_EVENTS.exitRoom);
    }
    exitRoom() {
        console.log("exiting room");
        let e = this.isRecording();
        e && this.stopRecording();
        if (isAdmin) {
            actionModal(
                smartVideo.msgStore.sureLeaveMeeting,
                "",
                smartVideo.msgStore.yes,
                function () {
                    actionModal(
                        "Leave and End Meeting",
                        "",
                        "END FOR ALL",
                        function () {
                            let t = { from_peer_name: window.roomClient.peer_name, peer_id: window.roomClient.peer_id, action: "eject", broadcast: true };
                            let i = window.roomClient.getId("ejectAllButton");
                            i && (i.style.display = "none"), (attendeesCount = 1), window.roomClient.getAttendeesCount(attendeesCount), window.roomClient.socket.emit("peer", t);
                            window.roomClient.confirmPeerAction("eject",t),
                            (window.onbeforeunload = null);
                            setTimeout(() => {
                                if (course_id) {
                                    // redirect to lms
                                    window.location.href = "https://learn.fukeyeducation.com/user/course_form/course_edit/" + course_id;
                                } else {
                                    window.roomClient.exit(!1, course_id);
                                }
                            }, 2000);
                        },
                        "LEAVE MEETING",
                        function () {
                            (window.onbeforeunload = null), window.roomClient.exit();
                        }
                    );
                },
                smartVideo.msgStore.no,
                function () {
                    e && window.roomClient.startRecording();
                }
            );
        } else {
            actionModal(
                smartVideo.msgStore.sureLeaveMeeting,
                "",
                smartVideo.msgStore.yes,
                function () {
                    console.log(course_id),(window.onbeforeunload = null), window.roomClient.exit(!1, course_id);
                },
                smartVideo.msgStore.no,
                function () {
                    e && window.roomClient.startRecording();
                }
            );
        }

    }
    attachMediaStream(e, t, i, o) {
        let n;
        switch (i) {
            case mediaType.audio:
                n = t.getAudioTracks()[0];
                break;
            case mediaType.video:
            case mediaType.screen:
                n = t.getVideoTracks()[0];
        }
        const r = new MediaStream();
        r.addTrack(n), (e.srcObject = r);
    }
    async attachSinkId(e, t) {
        if (void 0 !== e.sinkId)
            e.setSinkId(t)
                .then(() => {})
                .catch((e) => {
                    let t = e,
                        i = this.getId("speakerSelect");
                    "SecurityError" === e.name && (t = smartVideo.msgStore.youNeedHttps + ` ${e}`),
                        console.error("Attach SinkId error: ", t),
                        setNotify("error", t, "top"),
                        (audioOutputElementSelectedId = i.selectedIndex = 0),
                        liveStorage.setItem("audioOutputElementSelectedId", audioOutputElementSelectedId);
                });
        else {
            let e = smartVideo.msgStore.browserNotSupportDevice;
            console.warn(e), setNotify("error", e, "top");
        }
    }
    event(e) {
        this.eventListeners.has(e) && this.eventListeners.get(e).forEach((e) => e());
    }
    on(e, t) {
        this.eventListeners.get(e).push(t);
    }
    setVideoAvatarImgName(e, t) {
        let i = this.getId(e);
        t ? i.setAttribute("src", this.genAvatarSvg(t, 250)) : i.setAttribute("src", image.avatar);
        // t ? i.setAttribute("poster", this.genAvatarSvg(t, 250)) : i.setAttribute("poster", image.avatar);
    }
    genAvatarSvg(e, t) {
        const i = e.charCodeAt(0),
            o = e.charCodeAt(1) || i,
            n = Math.pow(i, 7) % 200,
            r = Math.pow(o, 7) % 200,
            s = `rgb(${n}, ${r}, ${(n + r) % 200})`;
        let a = e.split(" ");
        a = a[1] ? a[0].substring(0, 1).toUpperCase() + a[1].substring(0, 1).toUpperCase() : e.substring(0, 2).toUpperCase();
        return (
            "data:image/svg+xml," +
            `\n        <svg xmlns="http://www.w3.org/2000/svg" \n        xmlns:xlink="http://www.w3.org/1999/xlink" \n        width="${t}px" \n        height="${t}px" \n        viewBox="0 0 ${t} ${t}" \n        version="1.1">\n            <circle \n                fill="${s}" \n                width="${t}" \n                height="${t}" \n                cx="${
                t / 2
            }" \n                cy="${t / 2}" \n                r="${
                t / 2
            }"\n            />\n            <text \n                x="50%" \n                y="50%" \n                style="color:#ffffff; \n                line-height:1; \n                font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif"\n                alignment-baseline="middle" \n                text-anchor="middle" \n                font-size="${Math.round(
                0.4 * t
            )}" \n                font-weight="normal" \n                dy=".1em" \n                dominant-baseline="middle" \n                fill="#ffffff">${a}\n            </text>\n        </svg>`
                .replace(/#/g, "%23")
                .replace(/"/g, "'")
                .replace(/&/g, "&amp;")
        );
    }
    setIsAudio(e, t) {
        this.peer_info.peer_audio = t;
        let i = this.getPeerAudioBtn(e);
        i && (i.className = this.peer_info.peer_audio ? html.audioOn : html.audioOff);
    }
    setIsVideo(e, t) {
        (this.peer_info.peer_video = t), this.peer_info.peer_video || (this.removeVideo(this.peer_info, !1), this.sendVideoOff());
        let i = this.getPeerVideoBtn(e);
        i && (i.className = this.peer_info.peer_audio ? html.audioOn : html.audioOff);
    }
    setIsScreen(e, t) {
        (this.peer_info.peer_screen = e),
            this.peer_info.peer_screen || this.peer_info.peer_video || (this.removeVideo(this.peer_info, !1), this.sendVideoOff()),
            (isScreenAllowed = e),
            this.setPeer(this.peer_name, this.peer_id, "screen", e, !0, t);
    }
    sendVideoOff() {
        this.socket.emit("removeVideo", this.peer_info);
    }
    isConnected() {
        return this._isConnected;
    }
    isRecording() {
        return this._isRecording;
    }
    static get mediaType() {
        return mediaType;
    }
    static get EVENTS() {
        return _EVENTS;
    }
    static get DEVICES_COUNT() {
        return DEVICES_COUNT;
    }
    getTimeNow() {
        const e = new Date();
        return String(e.getHours()).padStart(2, "0") + ":" + String(e.getMinutes()).padStart(2, "0");
    }
    getId(e) {
        return document.getElementById(e);
    }
    getName(e) {
        return document.getElementsByName(e);
    }
    getEcN(e) {
        return document.getElementsByClassName(e);
    }
    async getRoomInfo() {
        return await this.socket.request("getRoomInfo");
    }
    getAttendeesCount() {
        this.socket.emit("getAttendeesCount");
    }
    getPeerAudioBtn(e) {
        return this.getId(e + "__audio");
    }
    getPeerVideoBtn(e) {
        return this.getId(e + "___pVideo");
    }
    getPeerHandBtn(e) {
        return [this.getId(e + "__hand") || "", this.getId(e + "___pHand")];
    }
    getMapKeyByValue(e, t) {
        for (let [i, o] of e.entries()) if (o === t) return i;
    }
    showTranscribeMessage(e) {
        display(translateMessage, "block"),
            clearTimeout(transcriptTimer),
            (transcriptTimer = 0),
            (translateMessage.innerHTML = e),
            smartVideo.config.transcribe && smartVideo.config.transcribe.textSpeechTranscribe && ((speech.text = e), window.speechSynthesis.speak(speech)),
            (transcriptTimer = setTimeout(() => {
                display(translateMessage, "none"), (translateMessage.innerHTML = "");
            }, 1e4));
    }
    thereIsAttendees() {
        return this.consumers.size > 0 || attendeesCount > 1;
    }
    toggleMySettings() {
        toggleModal(!(modal = document.getElementById("settings")).classList.contains("show-modal"));
    }
    toggleMyParticipants() {
        toggleModal(!(modal = document.getElementById("participants")).classList.contains("show-modal"));
    }

    addBackToMainButton() {
        const e = hrefUrl.searchParams.get("p");
        let t = "",
            i = parsedP.parent;
        e && (delete parsedP.parent, (t = "?p=" + window.btoa(unescape(encodeURIComponent(JSON.stringify(parsedP))))));
        return `<a href="${hrefUrl.protocol + "//" + hrefUrl.host + "/" + i + t}" class="btn btn-primary" id="parentbutton">${smartVideo.msgStore.backToMainRoom}</a>&nbsp;`;
    }
    toggleBreakout(e = !1) {
        var t = (modal = document.getElementById("breakoutRoomsModal")).classList.contains("show-modal");
        isAdmin &&
            (setValue("breakoutRoomsSubmit", liveStorage.getItem("breakoutRooms" + parent_id) ? smartVideo.msgStore.breakoutRoomsSubmitStop : smartVideo.msgStore.breakoutRoomsSubmitStart),
            parsedP && parsedP.parent ? display(breacountContentManagement, "none") : display(breacountContentManagement, "block"));
        const i = JSON.parse(liveStorage.getItem("breakoutRooms" + parent_id));
        let o = "";
        (this.getId("breacountContentRooms").innerHTML = ""),
            i &&
                ((window.onbeforeunload = null),
                i.forEach(function (e, t) {
                    let i = {};
                    isAdmin && (i.admin = 1), parsedP && parsedP.config && (i.config = parsedP.config), (i.parent = room_id);
                    let n = Object.keys(i).length > 0 ? "?p=" + window.btoa(unescape(encodeURIComponent(JSON.stringify(i)))) : "",
                        r = hrefUrl.protocol + "//" + hrefUrl.host + "/" + e[0] + n,
                        s = e[1] || "Room " + (t + 1),
                        a = `<a href="${r}" class="btn btn-primary" id="btn${e[0]}">${s}</a>&nbsp;`;
                    o += a;
                }),
                parsedP && parsedP.parent && (o += this.addBackToMainButton()),
                (this.getId("breacountContentRooms").innerHTML = o)),
            isAdmin || (this.getId("breacountContentManagement").innerHTML = ""),
            parsedP && parsedP.parent && e && ((o += this.addBackToMainButton()), (this.getId("breacountContentRooms").innerHTML = o)),
            toggleModal(!t);
    }
    setBreakout(e) {
        e ? this.room("breakoutOn") : (this.setPeer(this.peer_name, this.peer_id, "breakout", !1), this.room("breakoutOff"));
    }
    toggleReactions() {
        toggleModal(!(modal = document.getElementById("reActionButtonsModal")).classList.contains("show-modal"));
    }
    toggleFullScreen(e = null) {
        let t = e || document.documentElement;
        (document.fullscreenEnabled = document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled),
            (document.exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen),
            (t.requestFullscreen = t.requestFullscreen || t.webkitRequestFullscreen || t.mozRequestFullScreen || t.msRequestFullScreen),
            document.fullscreenEnabled && (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement ? document.exitFullscreen() : t.requestFullscreen()),
            null == e && (this.isVideoOnFullScreen = document.fullscreenEnabled);
    }
    handleFS(e, t) {
        let i = this.getId(e),
            o = this.getId(t);
        o &&
            (setTooltip(t, "Full screen", "top"),
            o.addEventListener("click", () => {
                (i.style.pointerEvents = this.isVideoOnFullScreen ? "auto" : "none"), this.toggleFullScreen(i), (this.isVideoOnFullScreen = !this.isVideoOnFullScreen);
            })),
            i &&
                (i.addEventListener("fullscreenchange", (e) => {
                    document.fullscreenElement || ((i.style.pointerEvents = "auto"), (this.isVideoOnFullScreen = !1));
                }),
                i.addEventListener("webkitfullscreenchange", (e) => {
                    document.webkitIsFullScreen || ((i.style.pointerEvents = "auto"), (this.isVideoOnFullScreen = !1));
                }));
    }
    handleVideoObjectFit(e) {
        document.documentElement.style.setProperty("--videoObjFit", e);
    }
    handlePN(e, t, i = !1) {
        let o = this.getId(e),
            n = this.getId(e),
            r = this.getId(t);
        n &&
            o &&
            r &&
            n.addEventListener("click", () => {
                if (!this.isMobileDevice) {
                    if (((this.isVideoPinned = !this.isVideoPinned), this.isVideoPinned))
                        (o.style.objectFit = "contain"),
                            (r.className = ""),
                            (r.style.width = "100%"),
                            (r.style.height = "100%"),
                            this.togglePin(pinVideoPosition.value),
                            this.videoPinMediaContainer.appendChild(r),
                            (this.videoPinMediaContainer.style.display = "block"),
                            (this.pinnedVideoPlayerId = e);
                    else {
                        if (this.pinnedVideoPlayerId != o.id && ((this.isVideoPinned = !0), this.isScreenAllowed)) return;
                        i || (o.style.objectFit = "var(--videoObjFit)"), this.videoPinMediaContainer.removeChild(r), (r.className = "videoContainerElement"), this.videoMediaContainer.appendChild(r), this.removeVideoPinMediaContainer();
                    }
                    setVideoDimensions();
                }
            });
    }
    togglePin(e) {
        if (this.isVideoPinned) {
            switch ((this.isChatPinned && this.toggleChatPin(), e)) {
                case "top":
                    (this.videoPinMediaContainer.style.top = "25%"),
                        (this.videoPinMediaContainer.style.width = "100%"),
                        (this.videoPinMediaContainer.style.height = "100%"),
                        (this.videoMediaContainer.style.top = "0%"),
                        (this.videoMediaContainer.style.right = null),
                        (this.videoMediaContainer.style.width = null),
                        (this.videoMediaContainer.style.width = "100% !important"),
                        (this.videoMediaContainer.style.height = "25%");
                    break;
                case "vertical":
                    (this.videoPinMediaContainer.style.top = 0),
                        (this.videoPinMediaContainer.style.width = "85%"),
                        (this.videoPinMediaContainer.style.height = "100%"),
                        (this.videoMediaContainer.style.top = 0),
                        (this.videoMediaContainer.style.width = "100%"),
                        (this.videoMediaContainer.style.height = "100%"),
                        (this.videoMediaContainer.style.right = 0);
                    break;
                case "horizontal":
                    (this.videoPinMediaContainer.style.top = 0),
                        (this.videoPinMediaContainer.style.width = "100%"),
                        (this.videoPinMediaContainer.style.height = "75%"),
                        (this.videoMediaContainer.style.top = "75%"),
                        (this.videoMediaContainer.style.right = null),
                        (this.videoMediaContainer.style.width = null),
                        (this.videoMediaContainer.style.width = "100% !important"),
                        (this.videoMediaContainer.style.height = "25%");
            }
            resizeVideoMedia();
        }
    }
    toggleChatPin() {
        if (DetectRTC.isMobileDevice) return !1;
        const e = this.getId("plist");
        
        window.getComputedStyle(e).display && this.toggleShowAttendees(),
            this.isChatPinned
                ? ((chatRoom.style.width = "65%"),
                  (chatRoom.style.height = "100%"),
                  (chatRoom.style.marginRight = "auto"),
                  (this.videoMediaContainer.style.top = 0),
                  (this.videoMediaContainer.style.right = null),
                  (this.videoMediaContainer.style.width = "100vw"),
                  (this.videoMediaContainer.style.height = "100vh"),
                  (this.isChatPinned = !1),
                  (toggleChatPin.style.right = "8rem"),
                  togglePinRight.classList.remove("mirror"),
                  toggleChatBackground.classList.remove("d-none"))
                : ((chatRoom.style.width = "35%"),
                  (chatRoom.style.height = "100%"),
                  (chatRoom.style.marginRight = 0),
                  (this.videoMediaContainer.style.top = 0),
                  (this.videoMediaContainer.style.width = "65%"),
                  (this.videoMediaContainer.style.height = "100%"),
                  (this.isChatPinned = !0),
                  togglePinRight.classList.add("mirror"),
                  (toggleChatPin.style.right = "5.5rem"),
                  toggleChatBackground.classList.add("d-none")),
            resizeVideoMedia();
    }
    handleZV(e) {
        let t = this.getId(e),
            i = 1;
        t &&
            t.addEventListener("wheel", (e) => {
                e.preventDefault(), (e.wheelDelta ? e.wheelDelta : -e.deltaY) > 0 ? (i *= 1.2) : (i /= 1.2), i < 1 && (i = 1), (t.style.scale = i);
            });
    }
    removeVideoPinMediaContainer() {
        (this.videoPinMediaContainer.style.display = "none"),
            (this.videoMediaContainer.style.top = 0),
            (this.videoMediaContainer.style.right = null),
            (this.videoMediaContainer.style.width = "100vw"),
            (this.videoMediaContainer.style.height = "100vh"),
            (this.pinnedVideoPlayerId = null),
            (this.isVideoPinned = !1);
    }
    adaptVideoObjectFit(e) {
        (BtnVideoObjectFit.selectedIndex = e), BtnVideoObjectFit.onchange();
    }
    getSnapshot() {
        let e = document.createElement("script");
        e.setAttribute("src", "https://html2canvas.hertzen.com/dist/html2canvas.min.js"),
            e.setAttribute("type", "text/javascript"),
            e.setAttribute("async", !0),
            document.body.appendChild(e),
            e.addEventListener("load", () => {
                const e = document.body;
                html2canvas(e).then((e) => {
                    saveDataToFile(e.toDataURL(), "room_" + room_id + "_" + getDataTimeString() + "_snapshot.png");
                });
            }),
            e.addEventListener("error", (e) => {
                console.error("Error on loading file", e);
            });
    }
    toggleChat() {
        this.getId("plist").style.display = "none";
        let e = this.getId("chatRoom");
        e.classList.remove("container");
        e.style.marginLeft = "70vw";
        e.style.position="absolute";
        e.style.top="0";
        e.style.right="0";
        e.style.width="65%";
        e.style.padding="10px";
        e.style.overflow="hidden";
        e.style.zIndex="299";
        0 == this.isChatOpen ? ((e.style.display = "block"), (this.isChatOpen = !0), getRoomAttendees()) : (this.isVideoPinned || ((this.isChatPinned = !0), this.toggleChatPin()), (e.style.display = "none"), (this.isChatOpen = !1));
    }
    toggleShowAttendees() {
        let e = this.getId("plist"),
            h = this.getId("chatHistory"),
            t = this.getId("chatContent");
        "none" === window.getComputedStyle(e).display
            ? (display(e, "flex"), screen.width > 767)
            : (display(e, "none"), screen.width > 767 && ((t.style.marginLeft = "0"), (t.style.borderLeft = "0px"), (t.style.borderBottom = "0px"), (h.style.visibility = "visible")));
        // "none" === window.getComputedStyle(e).display
        //     ? (display(e, "flex"), screen.width > 767 && ((t.style.marginLeft = "280px"), (t.style.border = "1px solid #eaeaea")))
        //     : (display(e, "none"), screen.width > 767 && ((t.style.marginLeft = "0"), (t.style.borderLeft = "0px"), (t.style.borderBottom = "0px")));
    }
    toggleChatBackground() {
        (this.isChatBgTransparent = !this.isChatBgTransparent), this.isChatBgTransparent ? document.documentElement.style.setProperty("--chat-bg", "rgba(0, 0, 0, 0.100)") : document.documentElement.style.setProperty("--chat-bg", "#ffffff");
    }
    toggleChatEmoji() {
        this.getId("chatEmoji").classList.toggle("show"), (this.isChatEmojiOpen = !this.isChatEmojiOpen), (this.getId("chatEmojiButton").style.color = this.isChatEmojiOpen ? "#48b0f7" : "#4d5259");
    }
    addEmojiToMsg(e) {
        (msgerInput.value += e.native), toggleChatEmoji();
    }
    cleanMessage() {
        (chatMessage.value = ""), (chatMessage.style.height = "40px");
    }
    pasteMessage() {
        navigator.clipboard
            .readText()
            .then((e) => {
                (chatMessage.value += e), (isChatPasteTxt = !0), this.checkLineBreaks();
            })
            .catch((e) => {
                console.error("Failed to read clipboard contents: ", e);
            });
    }
    sendMessage() {
        this.thereIsAttendees() || isChatGPTOn || (this.cleanMessage(), (isChatPasteTxt = !1));
        let e = this.formatMsg(chatMessage.value.trim());
        if (!e) return this.cleanMessage();
        if (isChatGPTOn)
            this.socket
                .request("getChatGPT", { time: getDataTimeString(), room: this.room_id, name: this.peer_name, prompt: e })
                .then(
                    function (e) {
                        e && (this.setMsgAvatar("left", "ChatGPT"), this.appendMessage("left", this.leftMsgAvatar, "ChatGPT", "chatgpt", e, this.peer_id, this.peer_name, !0), this.cleanMessage());
                    }.bind(this)
                )
                .catch((e) => {
                    console.error("ChatGPT error:", e);
                });
        else {
            let t = { peer_name: this.peer_name, peer_id: this.peer_id, to_peer_id: currentChatTargetId, to_peer_name: currentChatTargetName, peer_msg: e };
            this.socket.emit("message", t);
        }
        this.setMsgAvatar("right", this.peer_name), this.appendMessage("right", this.rightMsgAvatar, this.peer_name, this.peer_id, e, currentChatTargetId, currentChatTargetName, !0), this.cleanMessage();
    }
    sendTranscribe(e) {
        let t = { peer_name: this.peer_name, to_peer_id: "all", peer_msg: e };
        this.socket.emit("transcript", t);
    }
    showMessage(e) {
        !this.isChatOpen && this.showChatOnMessage && this.toggleChat(),
            this.setMsgAvatar("left", e.peer_name),
            currentChatTargetId === e.peer_id || ("all" === currentChatTargetId && "all" === e.to_peer_id)
                ? this.appendMessage("left", this.leftMsgAvatar, e.peer_name, e.peer_id, e.peer_msg, e.to_peer_id, e.to_peer_name, !0)
                : (rc.getId(e.peer_id + "__badge").classList.remove("d-none"),
                  this.collectMessages(e.peer_id, e.peer_name, e.to_peer_id, e.to_peer_name, e.peer_msg, this.getTimeNow()),
                  chatMessagesId++,
                  setNotify("info", smartVideo.msgStore.newMessageFrom.replace("{{user}}", e.peer_name), "top")),
            this.showChatOnMessage || setNotify("info", smartVideo.msgStore.newMessageFrom.replace("{{user}}", e.peer_name), "top"),
            this.isChatOpen || sound("message"),
            smartVideo.config.transcribe && smartVideo.config.transcribe.textSpeechChat && ((speech.text = e.peer_msg), window.speechSynthesis.speak(speech));
    }
    setMsgAvatar(e, t) {
        let i = this.genAvatarSvg(t, 32);
        "left" === e ? (this.leftMsgAvatar = i) : (this.rightMsgAvatar = i);
    }
    appendMessage(e, t, i, o, n, r, s, a, c) {
        const l = n,
            d = c || this.getTimeNow();
        var h = "",
            u = "";
        if ("right" === e) {
            var f = `<small class="message-data-time">${smartVideo.msgStore.me}, ${d}</small>`;
            (h = "<br>"), (u = "float-right pt-3");
        } else {
            f = ` <img src="${t}" alt="${i}">\n            <small class="message-data-time">${i + ", " + d}</small>`;
        }
        const m = l;
        let g = `<li class="clearfix">\n                            <div class="message-data ${u}">\n                                ${f}\n                            </div>${h}\n                            <div class="message ${
            "right" == e ? "other" : "my"
        }-message float-${e}">${m}</div>\n                        </li>`;
        if ((chatBoard.insertAdjacentHTML("beforeend", g), (chatHistory.scrollTop += 500), a && (this.collectMessages(o, i, r, s, l, d), chatMessagesId++), a && smartVideo.config.serverSide && smartVideo.config.serverSide.chatHistory)) {
            postData("/server/script.php", { type: "addchat", roomId: room_id, message: m, from: i, to: s, agentId: agentId, datetime: d, agentName: isAdmin ? peer_name : "" }).then((e) => {});
        }
    }
    formatMsg(e) {
        const t = e;
        if (0 != t.trim().length)
            return this.isHtml(t)
                ? this.sanitizeHtml(t)
                : this.isValidHttpURL(t)
                ? isImageURL(t)
                    ? '<img src="' + t + '" alt="img" width="180" height="auto"/>'
                    : this.isImageURL(t)
                    ? this.getImage(t)
                    : this.getLink(t)
                : isChatPasteTxt && this.getLineBreaks(t) > 1
                ? ((isChatPasteTxt = !1), this.getPre(t))
                : this.getLineBreaks(t) > 1
                ? this.getPre(t)
                : t;
    }
    sanitizeHtml(e) {
        const t = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#039;", "/": "&#x2F;" };
        return e.replace(/[&<>"'/]/g, (e) => t[e]);
    }
    isHtml(e) {
        var t = document.createElement("div");
        t.innerHTML = e;
        for (var i = t.childNodes, o = i.length; o--; ) if (1 == i[o].nodeType) return !0;
        return !1;
    }
    isValidHttpURL(e) {
        return new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$", "i").test(e);
    }
    isImageURL(e) {
        return null != e.match(/\.(jpeg|jpg|gif|png|tiff|bmp)$/);
    }
    getImage(e) {
        const t = e,
            i = document.createElement("div"),
            o = document.createElement("img");
        return o.setAttribute("src", t), o.setAttribute("width", "200px"), o.setAttribute("height", "auto"), i.appendChild(o), i.firstChild.outerHTML;
    }
    getLink(e) {
        const t = e,
            i = document.createElement("a"),
            o = document.createElement("div"),
            n = document.createTextNode(t);
        return i.setAttribute("href", t), i.setAttribute("target", "_blank"), i.appendChild(n), o.appendChild(i), o.firstChild.outerHTML;
    }
    getPre(e) {
        const t = e,
            i = document.createElement("pre"),
            o = document.createElement("div");
        return (i.textContent = t), o.appendChild(i), o.firstChild.outerHTML;
    }
    getIframe(e) {
        const t = e,
            i = document.createElement("iframe"),
            o = document.createElement("div"),
            n = "na" == this.getVideoType(t) ? this.getYoutubeEmbed(t) : t;
        return (
            i.setAttribute("title", "Chat-IFrame"),
            i.setAttribute("src", n),
            i.setAttribute("width", "auto"),
            i.setAttribute("frameborder", "0"),
            i.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"),
            i.setAttribute("allowfullscreen", "allowfullscreen"),
            o.appendChild(i),
            o.firstChild.outerHTML
        );
    }
    getLineBreaks(e) {
        return (e.match(/\n/g) || []).length;
    }
    checkLineBreaks() {
        (chatMessage.style.height = ""), this.getLineBreaks(chatMessage.value) > 0 && (chatMessage.style.height = "200px");
    }
    collectMessages(e, t, i, o, n, r) {
        this.chatMessages.push({ fromId: e, fromName: t, toId: i, toName: o, msg: n, time: r });
    }
    chatShow(e) {
        let t = chatBoard.firstChild;
        for (; t; ) chatBoard.removeChild(t), (t = chatBoard.firstChild);
        this.chatMessages.forEach((t) => {
            if ((t.fromId === e && t.toId === this.peer_id) || (t.fromId === this.peer_id && t.toId === e) || ("all" === e && t.toId === e)) {
                if (t.fromId === this.peer_id) var i = "right";
                t.fromId === e && (i = "left");
                let o = getAttendeeAvatar(t.fromName);
                this.appendMessage(i, o, t.fromName, t.fromId, t.msg, t.toId, t.toName, !1, t.time);
            }
        });
    }
    getSupportedMimeTypes() {
        return ["video/webm;codecs=vp9,opus", "video/webm;codecs=vp8,opus", "video/webm;codecs=h264,opus", "video/mp4;codecs=h264,aac", "video/mp4"].filter((e) => MediaRecorder.isTypeSupported(e));
    }
    wantExit() {
        return (
            this.exit(),
            rc._isRecording && rc.stopRecording(!0),
            setTimeout(function () {
                setTimeout(function () {
                    rc._isRecording && rc.startRecording();
                }, 1e3);
            }, 1),
            "Warning for a leave"
        );
    }


    ensureCanvasAndVideos() {
        if (!this.canvas || !this.ctx) {
            this.canvas = document.createElement("canvas");
            this.ctx = this.canvas.getContext("2d");
            console.warn("Reinitialized this.canvas and this.ctx");
        }
        if (!this.screenVideo) {
            this.screenVideo = document.createElement("video");
            console.warn("Reinitialized this.screenVideo");
        }
        if (!this.cameraVideo) {
            this.cameraVideo = document.createElement("video");
            console.warn("Reinitialized this.cameraVideo");
        }
    }

    updateCanvasSize() {
        this.ensureCanvasAndVideos();
        let width, height;
        if (this.localScreenStream) {
            const settings = this.localScreenStream.getVideoTracks()[0].getSettings();
            width = settings.width || 1280;
            height = settings.height || 720;
        } else if (this.localVideoStream) {
            const settings = this.localVideoStream.getVideoTracks()[0].getSettings();
            width = settings.width || 640;
            height = settings.height || 480;
        } else {
            width = 640;
            height = 480;
        }
        this.canvas.width = width;
        this.canvas.height = height;
        console.log("Canvas resized to:", width, "x", height, "for room:", this.room_id);
    }
    drawToCanvas() {
        this.ensureCanvasAndVideos();
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    
        // Prioritize screen-sharing stream if active
        if (this.localScreenStream && this.screenVideo.readyState >= 2) {
            this.ctx.drawImage(this.screenVideo, 0, 0, this.canvas.width, this.canvas.height);
            // Add camera as Picture-in-Picture if available
            if (this.localVideoStream && this.cameraVideo.readyState >= 2) {
                const pipWidth = this.canvas.width / 4;
                const pipHeight = this.canvas.height / 4;
                this.ctx.drawImage(
                    this.cameraVideo,
                    this.canvas.width - pipWidth - 10,
                    this.canvas.height - pipHeight - 10,
                    pipWidth,
                    pipHeight
                );
            }
        } else if (this.localVideoStream && this.cameraVideo.readyState >= 2) {
            // Fallback to camera-only if no screen stream
            this.ctx.drawImage(this.cameraVideo, 0, 0, this.canvas.width, this.canvas.height);
        } else {
            // Draw a black background if no streams are available
            this.ctx.fillStyle = "black";
            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
        }
    
        // Continue the animation loop
        this.animationFrame = requestAnimationFrame(() => this.drawToCanvas());
    }
    async switchToCanvasRecording() {
        console.log("Switching to canvas recording - Current state:", {
            screenRecorderActive: this.screenRecorder && this.screenRecorder.state !== "inactive",
            videoStream: !!this.localVideoStream,
            audioStream: !!this.localAudioStream
        });
    
        if (this.screenRecorder && this.screenRecorder.state !== "inactive") {
            console.log("Stopping screen recorder...");
            this.screenRecorder.requestData();
            this.screenRecorder.stop();
            await new Promise(resolve => {
                this.screenRecorder.onstop = () => {
                    console.log("Screen recorder stopped - Chunks so far:", this.recordedChunks.length);
                    resolve();
                };
            });
            this.screenRecorder = null;
            this.isScreenRecording = false;
        }
    
        if (!this.localVideoStream || this.localVideoStream.getTracks().length === 0) {
            console.log("Reinitializing camera stream for room:", this.room_id);
            try {
                this.localVideoStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
                this.cameraVideo.srcObject = this.localVideoStream;
                await this.cameraVideo.play();
                console.log("Camera stream initialized - Tracks:", this.localVideoStream.getTracks().length);
            } catch (err) {
                console.error("Failed to reinitialize camera stream:", err);
                return;
            }
        }
    
        this.ensureCanvasAndVideos();
        this.updateCanvasSize();
        this.drawToCanvas();
    
        const canvasStream = this.canvas.captureStream(15);
        const audioTracks = this.localAudioStream ? this.localAudioStream.getAudioTracks() : [];
        this.combinedStream = new MediaStream([...canvasStream.getVideoTracks(), ...audioTracks]);
        console.log("Canvas stream created - Video tracks:", canvasStream.getVideoTracks().length, "Audio tracks:", audioTracks.length);
    
        this.cameraSegmentCount++;
        const mimeType = "video/mp4; codecs=avc1.42E01E,mp4a.40.2";
        console.log("Starting canvas recorder - MIME:", mimeType, "Segment:", this.cameraSegmentCount);
    
        this.currentRecorder = new MediaRecorder(this.combinedStream, { mimeType });
        this.currentRecorder.ondataavailable = (event) => {
            console.log("Canvas chunk received - Size:", event.data.size, "Segment:", this.cameraSegmentCount);
            if (event.data.size > 0) {
                this.recordedChunks.push({ type: "canvas", data: event.data, segment: this.cameraSegmentCount });
                console.log("Chunk added - Total chunks:", this.recordedChunks.length);
            } else {
                console.warn("Empty or corrupt chunk detected - Segment:", this.cameraSegmentCount);
            }
        };
        this.currentRecorder.onstop = () => {
            console.log("Canvas recorder stopped - Total chunks:", this.recordedChunks.length);
        };
        this.currentRecorder.start(5000);
        console.log("Canvas recording started - Segment:", this.cameraSegmentCount);
    }
    async switchToScreenRecording() {
        console.log("Switching to screen recording - Current state:", {
            canvasRecorderActive: this.currentRecorder && this.currentRecorder.state !== "inactive",
            screenStream: !!this.localScreenStream,
            audioStream: !!this.localAudioStream
        });
    
        if (this.currentRecorder && this.currentRecorder.state !== "inactive") {
            console.log("Stopping canvas recorder...");
            this.currentRecorder.requestData();
            this.currentRecorder.stop();
            await new Promise(resolve => {
                this.currentRecorder.onstop = () => {
                    console.log("Canvas recorder stopped - Chunks so far:", this.recordedChunks.length);
                    resolve();
                };
            });
            this.currentRecorder = null;
            cancelAnimationFrame(this.animationFrame);
        }
    
        if (!this.localScreenStream || this.localScreenStream.getTracks().length === 0) {
            console.error("No screen stream available for room:", this.room_id);
            return;
        }
    
        this.updateCanvasSize();
        this.drawToCanvas();
        const audioTracks = this.localAudioStream ? this.localAudioStream.getAudioTracks() : [];
        const screenStream = new MediaStream([...this.localScreenStream.getVideoTracks(), ...audioTracks]);
        console.log("Screen stream created - Video tracks:", this.localScreenStream.getVideoTracks().length, "Audio tracks:", audioTracks.length);
    
        this.screenSegmentCount++;
        const mimeType = "video/mp4; codecs=avc1.42E01E,mp4a.40.2";
        console.log("Starting screen recorder - MIME:", mimeType, "Segment:", this.screenSegmentCount);
    
        this.screenRecorder = new MediaRecorder(screenStream, { mimeType });
        this.screenRecorder.ondataavailable = (event) => {
            console.log("Screen chunk received - Size:", event.data.size, "Segment:", this.screenSegmentCount);
            if (event.data.size > 0) {
                this.recordedChunks.push({ type: "screen", data: event.data, segment: this.screenSegmentCount });
                console.log("Chunk added - Total chunks:", this.recordedChunks.length);
            } else {
                console.warn("Empty or corrupt chunk detected - Segment:", this.screenSegmentCount);
            }
        };
        this.screenRecorder.onstop = () => {
            console.log("Screen recorder stopped - Total chunks:", this.recordedChunks.length);
        };
        this.screenRecorder.onstart = () => {
            console.log("Screen recording started - Stream tracks:", screenStream.getTracks().length);
        };
        this.screenRecorder.start(5000);
        this.isScreenRecording = true;
        console.log("Screen recording started - Segment:", this.screenSegmentCount);
    }
    async startRecording() {
        try {
            console.log("Starting recording for room:", this.room_id);
            const date = new Date();
            this.fileNameRecording = `${date.toISOString().split("T")[0].replaceAll("-", "_")}_${date.toTimeString().split(" ")[0].replaceAll(":", "_")}`;
            this.isSendSaveRecording = false;
            this.recordedChunks = [];
            this.cameraSegmentCount = 0;
            this.screenSegmentCount = 0;
            console.log("Recording initialized - Filename:", this.fileNameRecording);
    
            await this.switchToCanvasRecording();
    
            this._isRecording = true;
            this._isStoppableRecording = true;
            this.event(_EVENTS.startRec);
            console.log("Recording flags set - isRecording:", this._isRecording);
    
            hide(recordingButton);
            hide(stopRecordingButton);
            let preloader = this.getId("loader");
            if (preloader) preloader.style.display = "none";
        } catch (err) {
            console.error("Error starting recording:", err);
            setNotify("error", `${smartVideo.msgStore.errorStreamRecord} ${err}`, "top");
            this._isRecording = false;
            this._isStoppableRecording = false;
        }
    }
    getNewStream(e, t) {
        let i = null,
            o = e ? e.getVideoTracks()[0] : void 0,
            n = t ? t.getAudioTracks()[0] : void 0;
        return o && n ? (i = new MediaStream([o, n])) : o ? (i = new MediaStream([o])) : n && (i = new MediaStream([n])), i;
    }
      
    handleMediaRecorderStart(e) {}
    handleMediaRecorderData(e) {
        // console.log(e);
        if (e.data && e.data.size > 0){ 
            recordedBlobs.push(e.data);
            let t = "record_" + room_id + "_" + `${window.roomClient.fileNameRecording}.mp4`;
            if (smartVideo.config.recording.filename) {
                let e = smartVideo.config.recording.filename;
                (e = e.replace("%room%", room_id)), (e = e.replace("%datetime%", `${window.roomClient.fileNameRecording}`)), (t = e + ".mp4");
            }
            window.roomClient.saveRecording(e.data, t);
        }
    }
    saveRecording(e, t) {
        const i = e,
            o = new FileReader();
        o.readAsArrayBuffer(i),
            (o.onload = async (e) => {
                const i = e.target.result,
                    o = 1e6,
                    n = e.target.result.byteLength / o;
                for (let e = 0; e < n + 1; e++) {
                    let n = i.slice(e * o, (e + 1) * o);
                    await fetch("/upload?fileName=" + t, { method: "POST", headers: { "content-type": "application/octet-stream", "content-length": n.length }, body: n });
                }
            });
    }
    handleMediaRecorderStop(e) {
        try {
            window.roomClient.stopRecording();
            window.roomClient.closeProducer(mediaType.screen);
        } catch (e) {
            console.warn("Recording save failed", e);
        }
    }
    async fileSetRecording() {
        console.log("Before saving - Total chunks:", this.recordedChunks.length, "Room:", this.room_id);
    
        // Group chunks into segments
        const segments = {};
        this.recordedChunks.forEach(chunk => {
            const key = `${chunk.type}_${chunk.segment}`;
            if (!segments[key]) segments[key] = [];
            segments[key].push(chunk.data);
        });
    
        // Save and upload segment files
        const segmentUploadPromises = [];
        for (const [key, chunks] of Object.entries(segments)) {
            const [type, segment] = key.split("_");
            const blob = new Blob(chunks, { type: "video/mp4" });
            const segmentFileName = `${type}_${segment}_${this.room_id}_${this.fileNameRecording}.mp4`;
    
            // Save locally for debugging purposes (optional)
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement("a");
            link.href = url;
            link.download = segmentFileName;
            document.body.appendChild(link);
            link.click();
            setTimeout(() => document.body.removeChild(link), 100);
            console.log(`${type} segment ${segment} saved locally - Chunks:`, chunks.length, "Size:", blob.size, "Room:", this.room_id);
    
            // Queue segment file for upload
            segmentUploadPromises.push(
                fetch("/upload?fileName=" + segmentFileName, {
                    method: "POST",
                    headers: {
                        "content-type": "application/octet-stream",
                        "content-length": blob.size.toString()
                    },
                    body: blob
                }).then(response => {
                    if (!response.ok) throw new Error(`Segment upload failed for ${segmentFileName} with status: ${response.status}`);
                    console.log(`Uploaded segment ${segmentFileName} - Size:`, blob.size, "Room:", this.room_id);
                }).catch(err => {
                    console.error(`Upload failed for ${segmentFileName}:`, err);
                    throw err; // Re-throw to catch in Promise.all
                })
            );
        }
    
        try {
            // Upload all segments
            await Promise.all(segmentUploadPromises);
            console.log("All segments uploaded successfully for room:", this.room_id);
    
            // Trigger server-side merge with segment information
            const finalFileName = `record_${this.room_id}_${this.fileNameRecording}.mp4`;
            const segmentNames = Object.keys(segments).map(key => {
                const [type, segment] = key.split("_");
                return `${type}_${segment}_${this.room_id}_${this.fileNameRecording}.mp4`;
            });
            const mergeUrl = `/merge?fileName=${finalFileName}&room_id=${this.room_id}&segments=${encodeURIComponent(JSON.stringify(segmentNames))}`;
            console.log("Sending merge request to:", mergeUrl);
    
            const mergeResponse = await fetch(mergeUrl, { method: "POST" });
            if (!mergeResponse.ok) {
                const errorText = await mergeResponse.text();
                throw new Error(`Merge request failed with status: ${mergeResponse.status}, response: ${errorText}`);
            }
    
            const mergedBlob = await mergeResponse.blob();
            const mergedUrl = window.URL.createObjectURL(mergedBlob);
            const mergedLink = document.createElement("a");
            mergedLink.href = mergedUrl;
            mergedLink.download = finalFileName;
            document.body.appendChild(mergedLink);
            mergedLink.click();
            setTimeout(() => document.body.removeChild(mergedLink), 100);
            console.log("Merged file downloaded - Total segments:", segmentNames.length, "Size:", mergedBlob.size, "Room:", this.room_id);
        } catch (err) {
            console.error("Error during segment upload or merge for room:", this.room_id, err);
        }
    
        // Clear recorded chunks after processing
        this.recordedChunks = [];
    }
    pauseRecording() {
        (this._isRecording = !1), (this._isPausedRecording = !0), this.mediaRecorder.pause(), this.event(_EVENTS.pauseRec);
    }
    resumeRecording() {
        (this._isRecording = !0), (this._isPausedRecording = !1), this.mediaRecorder.resume(), this.event(_EVENTS.resumeRec);
    }
    async stopRecording(e) {
        console.log("Stopping recording - Room:", this.room_id, "Force stop:", e);
        window.onbeforeunload = null;
    
        if (this._isRecording || this._isPausedRecording) {
            if (!e) this._isRecording = false;
    
            let screenPromise = Promise.resolve();
            if (this.isScreenRecording && this.screenRecorder && this.screenRecorder.state !== "inactive") {
                console.log("Stopping screen recorder...");
                this.screenRecorder.requestData();
                this.screenRecorder.stop();
                screenPromise = new Promise(resolve => {
                    this.screenRecorder.onstop = () => {
                        console.log("Screen recorder fully stopped - Chunks:", this.recordedChunks.length);
                        resolve();
                    };
                });
                this.screenRecorder = null;
                this.isScreenRecording = false;
            }
    
            let canvasPromise = Promise.resolve();
            if (this.currentRecorder && this.currentRecorder.state !== "inactive") {
                console.log("Stopping canvas recorder...");
                this.currentRecorder.requestData();
                this.currentRecorder.stop();
                canvasPromise = new Promise(resolve => {
                    this.currentRecorder.onstop = () => {
                        console.log("Canvas recorder fully stopped - Chunks:", this.recordedChunks.length);
                        resolve();
                    };
                });
                this.currentRecorder = null;
            }
    
            await Promise.all([screenPromise, canvasPromise]);
            console.log("All recorders stopped - Cleaning up streams...");
    
            if (this.combinedStream) this.combinedStream.getTracks().forEach(track => track.stop());
            if (this.localAudioStream) this.localAudioStream.getTracks().forEach(track => track.stop());
            if (this.localScreenStream) this.localScreenStream.getTracks().forEach(track => track.stop());
            if (this.animationFrame) cancelAnimationFrame(this.animationFrame);
    
            // Process and upload segments
            await this.fileSetRecording();
    
            this.getId("recordingStatus").innerHTML = "";
            this.event(_EVENTS.stopRec);
            show(recordingButton);
            hide(stopRecordingButton);
            this._isStoppableRecording = false;
            console.log("Recording stopped and segments processed - Final chunks:", this.recordedChunks.length);
        } else {
            console.log("No active recording to stop.");
        }
    }
      handleSF(e) {
        let t = e.split("___")[1],
            i = this.getId(e);
        i &&
            i.addEventListener("click", () => {
                this.selectFileToShare(t);
            });
    }
    handleDD(e, t, i = !1) {
        let o = this.getId(e);
        o &&
            (o.addEventListener("dragover", function (e) {
                e.preventDefault();
            }),
            o.addEventListener("drop", function (e) {
                if ((e.preventDefault(), i)) return setNotify("info", smartVideo.msgStore.ddSendYourself, "top");
                if (this.sendInProgress) return setNotify("info", smartVideo.msgStore.ddWaitForPrevious, "top");
                if (e.dataTransfer.items && e.dataTransfer.items.length > 1) return setNotify("info", smartVideo.msgStore.ddSingleFile, "top");
                if (e.dataTransfer.items) {
                    if (e.dataTransfer.items[0].webkitGetAsEntry().isDirectory) return setNotify("info", smartVideo.msgStore.ddSingleFile, "top");
                    var o = e.dataTransfer.items[0].getAsFile();
                    rc.sendFileInformations(o, t);
                } else rc.sendFileInformations(e.dataTransfer.files[0], t);
            }));
    }
    selectFileToShare(e, t = !1) {
        actionModal(
            smartVideo.msgStore.fileShare,
            '<input class="form-control" type="file" id="file">',
            smartVideo.msgStore.shareButton,
            function (i) {
                if (((window.roomClient.fileToSend = i), window.roomClient.fileToSend && window.roomClient.fileToSend.size > 0)) {
                    if (window.roomClient.fileToSend.size > window.roomClient.maxFileSize) return void setNotify("error", smartVideo.msgStore.exceededAllowedFileSize, "top");
                    if (!window.roomClient.thereIsAttendees()) return void setNotify("info", smartVideo.msgStore.noAttendeesDetected, "top");
                    window.roomClient.socket.emit("fileInfo", {
                        peer_id: e,
                        broadcast: t,
                        peer_name: window.roomClient.peer_name,
                        fileName: window.roomClient.fileToSend.name,
                        fileSize: window.roomClient.fileToSend.size,
                        fileType: window.roomClient.fileToSend.type,
                    }),
                        setTimeout(() => {
                            window.roomClient.sendFileData(e, t);
                        }, 1e3);
                } else setNotify("error", smartVideo.msgStore.notValidFile, "top");
            },
            smartVideo.msgStore.cancelButton
        );
    }
    sendFileInformations(e, t, i = !1) {
        if (((this.fileToSend = e), this.fileToSend && this.fileToSend.size > 0)) {
            if (!this.thereIsAttendees()) return setNotify("info", smartVideo.msgStore.noAttendeesDetected, "top");
            if (this.isHtml(this.fileToSend.name)) return setNotify("warning", smartVideo.msgStore.invalidFileName, "top", 5e3);
            const e = { peer_id: t, broadcast: i, peer_name: this.peer_name, fileName: this.fileToSend.name, fileSize: this.fileToSend.size, fileType: this.fileToSend.type };
            this.setMsgAvatar("right", this.peer_name),
                this.appendMessage(
                    "right",
                    this.rightMsgAvatar,
                    this.peer_name,
                    this.peer_id,
                    `${icons.fileSend}: \n                <br/> \n                <ul>\n                    <li>${smartVideo.msgStore.fileNameLabel} ${this.fileToSend.name}</li>\n                    <li>${
                        smartVideo.msgStore.fileSizeLabel
                    } ${this.bytesToSize(this.fileToSend.size)}</li>\n                </ul>`,
                    "all",
                    "all",
                    !0
                ),
                this.socket.emit("fileInfo", e),
                setTimeout(() => {
                    this.sendFileData(t, i);
                }, 1e3);
        } else setNotify("error", smartVideo.msgStore.fileNotSelectedEmpty, "top");
    }
    handleFileInfo(e) {
        (this.incomingFileInfo = e), (this.incomingFileData = []), (this.receiveBuffer = []), (this.receivedSize = 0);
        let t =
            smartVideo.msgStore.fileFromLabel +
            this.incomingFileInfo.peer_name +
            html.newline +
            smartVideo.msgStore.fileNameLabel +
            this.incomingFileInfo.fileName +
            html.newline +
            smartVideo.msgStore.fileTypeLabel +
            this.incomingFileInfo.fileType +
            html.newline +
            smartVideo.msgStore.fileSizeLabel +
            this.bytesToSize(this.incomingFileInfo.fileSize);
        (receiveFileInfo.innerHTML = t), (receiveFileDiv.style.display = "inline"), (receiveProgress.max = this.incomingFileInfo.fileSize), setNotify("info", t, "top"), (this.receiveInProgress = !0);
    }
    sendFileData(e, t) {
        (this.sendInProgress = !0),
            (sendFileInfo.innerHTML =
                smartVideo.msgStore.fileNameLabel +
                this.fileToSend.name +
                html.newline +
                smartVideo.msgStore.fileTypeLabel +
                this.fileToSend.type +
                html.newline +
                smartVideo.msgStore.fileSizeLabel +
                this.bytesToSize(this.fileToSend.size) +
                html.newline),
            (sendFileDiv.style.display = "inline"),
            (sendProgress.max = this.fileToSend.size),
            (this.fileReader = new FileReader());
        let i = 0;
        this.fileReader.addEventListener("error", (e) => console.error("fileReader error", e)),
            this.fileReader.addEventListener("abort", (e) => console.warn("fileReader aborted", e)),
            this.fileReader.addEventListener("load", (n) => {
                if (!this.sendInProgress) return;
                let r = { peer_id: e, broadcast: t, fileData: n.target.result };
                this.sendFSData(r),
                    (i += r.fileData.byteLength),
                    (sendProgress.value = i),
                    (sendFilePercentage.innerHTML = smartVideo.msgStore.sendProgress + ((i / this.fileToSend.size) * 100).toFixed(2) + "%"),
                    i === this.fileToSend.size && ((this.sendInProgress = !1), (sendFileDiv.style.display = "none"), setNotify("success", this.fileToSend.name + " " + smartVideo.msgStore.sentSuccessfully, "top")),
                    i < this.fileToSend.size && o(i);
            });
        const o = (e) => {
            const t = this.fileToSend.slice(i, e + this.chunkSize);
            this.fileReader.readAsArrayBuffer(t);
        };
        o(0);
    }
    sendFSData(e) {
        e && this.socket.emit("file", e);
    }
    abortFileTransfer() {
        this.fileReader && 1 === this.fileReader.readyState && (this.fileReader.abort(), (sendFileDiv.style.display = "none"), (this.sendInProgress = !1), this.socket.emit("fileAbort", { peer_name: this.peer_name }));
    }
    hideFileTransfer() {
        receiveFileDiv.style.display = "none";
    }
    handleFileAbort(e) {
        (this.receiveBuffer = []),
            (this.incomingFileData = []),
            (this.receivedSize = 0),
            (this.receiveInProgress = !1),
            (receiveFileDiv.style.display = "none"),
            setNotify("info", e.peer_name + " " + smartVideo.msgStore.abortedFileTransfer, "top");
    }
    handleFile(e) {
        this.receiveInProgress &&
            (this.receiveBuffer.push(e.fileData),
            (this.receivedSize += e.fileData.byteLength),
            (receiveProgress.value = this.receivedSize),
            (receiveFilePercentage.innerHTML = smartVideo.msgStore.receivedProgress + ((this.receivedSize / this.incomingFileInfo.fileSize) * 100).toFixed(2) + "%"),
            this.receivedSize === this.incomingFileInfo.fileSize && ((receiveFileDiv.style.display = "none"), (this.incomingFileData = this.receiveBuffer), (this.receiveBuffer = []), this.endFileDownload()));
    }
    endFileDownload() {
        const e = new Blob(this.incomingFileData),
            t = this.incomingFileInfo.fileName;
        if (((window.fileBlob = e), (window.fileFile = t), (this.incomingFileData = []), isImageURL(this.incomingFileInfo.fileName))) {
            const t = new FileReader();
            (t.onload = (e) => {
                actionModal(
                    smartVideo.msgStore.receivedFile,
                    this.incomingFileInfo.fileName + " " + smartVideo.msgStore.size + " " + this.bytesToSize(this.incomingFileInfo.fileSize),
                    smartVideo.msgStore.save,
                    function () {
                        window.roomClient.saveBlobToFile(window.fileBlob, window.fileFile);
                    },
                    smartVideo.msgStore.cancel
                );
            }),
                t.readAsDataURL(e);
        } else {
            actionModal(
                smartVideo.msgStore.receivedFile,
                this.incomingFileInfo.fileName + " " + smartVideo.msgStore.size + " " + this.bytesToSize(this.incomingFileInfo.fileSize),
                smartVideo.msgStore.save,
                function () {
                    window.roomClient.saveBlobToFile(window.fileBlob, window.fileFile);
                },
                smartVideo.msgStore.cancel
            );
        }
        this.setMsgAvatar("left", this.peer_name),
            this.appendMessage(
                "left",
                this.rightMsgAvatar,
                this.peer_name,
                this.peer_id,
                `${icons.fileSend} \n            <button onclick="window.roomClient.saveBlobToFile(window.fileBlob, window.fileFile);">${this.incomingFileInfo.fileName}</button></li>`,
                "all",
                "all",
                !0
            );
    }
    saveBlobToFile(e, t) {
        const i = window.URL.createObjectURL(e),
            o = document.createElement("a");
        (o.style.display = "none"),
            (o.href = i),
            (o.download = t),
            document.body.appendChild(o),
            o.click(),
            setTimeout(() => {
                document.body.removeChild(o), window.URL.revokeObjectURL(i);
            }, 100);
    }
    bytesToSize(e) {
        if (0 == e) return "0 Byte";
        let t = parseInt(Math.floor(Math.log(e) / Math.log(1024)));
        return Math.round(e / Math.pow(1024, t), 2) + " " + ["Bytes", "KB", "MB", "GB", "TB"][t];
    }
    toHtmlJson(e) {
        return "<pre>" + JSON.stringify(e, null, 4) + "</pre>";
    }
    handleSV(e) {
        let t = e.split("___")[1],
            i = this.getId(e);
        i &&
            i.addEventListener("click", () => {
                this.shareVideo(t);
            });
    }
    shareVideo(e = "all") {
        actionModal(
            smartVideo.msgStore.shareYouTubeVideo,
            '<input class="form-control" type="text" required id="videoUrl">',
            smartVideo.msgStore.shareButton,
            function (t) {
                if (!window.roomClient.thereIsAttendees()) return void setNotify("info", smartVideo.msgStore.noAttendeesDetected, "top");
                if (!window.roomClient.isVideoTypeSupported(t)) return void setNotify("info", martVideo.msgStore.videoTypeSupported, "top");
                let i = "na" == window.roomClient.getVideoType(t),
                    o = i ? window.roomClient.getYoutubeEmbed(t) : t;
                if (o) {
                    let t = { peer_id: e, peer_name: window.roomClient.peer_name, video_url: o, is_youtube: i, action: "open" };
                    window.roomClient.socket.emit("shareMedia", t), window.roomClient.openVideo(t);
                } else setNotify("error", smartVideo.msgStore.notValidYouTubeUrl, "top");
            },
            smartVideo.msgStore.cancelButton
        );
    }
    getVideoType(e) {
        return e.endsWith(".mp4") ? "video/mp4" : e.endsWith(".mp3") ? "video/mp3" : e.endsWith(".webm") ? "video/webm" : e.endsWith(".ogg") ? "video/ogg" : "na";
    }
    isVideoTypeSupported(e) {
        return !!(e.endsWith(".mp4") || e.endsWith(".mp3") || e.endsWith(".webm") || e.endsWith(".ogg") || e.includes("youtube.com"));
    }
    getYoutubeEmbed(e) {
        let t = e.match(/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/);
        return !(!t || 11 != t[7].length) && "https://www.youtube.com/embed/" + t[7] + "?autoplay=1";
    }
    shareMedia(e) {
        let t = e.peer_name;
        switch (e.action) {
            case "open":
                setNotify("info", `${t} <i class="fab fa-youtube"></i> ` + smartVideo.msgStore.openVideo, "top"), this.openVideo(e);
                break;
            case "close":
                setNotify("info", `${t} <i class="fab fa-youtube"></i> ` + smartVideo.msgStore.closeVideo, "top"), this.closeVideo();
        }
    }
    openVideo(e) {
        let t,
            i,
            o,
            n,
            r = e.peer_name,
            s = e.video_url,
            a = e.is_youtube,
            c = this.getVideoType(s);
        this.closeVideo(),
            show(videoCloseBtn),
            (t = document.createElement("div")),
            (t.className = "videoContainerElement"),
            (t.id = "__shareVideo"),
            (i = document.createElement("div")),
            i.setAttribute("id", "__videoBar"),
            (i.className = "videoMenuBar"),
            (o = document.createElement("button")),
            (o.className = "fas fa-times"),
            (o.id = "__videoExit"),
            a
                ? ((n = document.createElement("iframe")),
                  n.setAttribute("title", r),
                  n.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"),
                  n.setAttribute("frameborder", "0"),
                  n.setAttribute("allowfullscreen", !0))
                : ((n = document.createElement("video")), (n.type = c), (n.autoplay = !0), (n.controls = !0), "video/mp3" == c && (n.poster = image.audio)),
            n.setAttribute("id", "__videoShare"),
            n.setAttribute("src", s),
            n.setAttribute("width", "100%"),
            n.setAttribute("height", "100%"),
            i.appendChild(o),
            t.appendChild(n),
            t.appendChild(i),
            this.videoMediaContainer.appendChild(t),
            setVideoDimensions(),
            this.getId(o.id).addEventListener("click", (e) => {
                e.preventDefault(), this.closeVideo(!0);
            }),
            this.handlePN(n.id, t.id),
            this.isMobileDevice || setTooltip(o.id, smartVideo.msgStore.videoClose, "top");
    }
    closeVideo(e = !1, t = "all") {
        if (e) {
            let e = { peer_id: t, peer_name: this.peer_name, action: "close" };
            this.socket.emit("shareMedia", e);
        }
        let i = this.getId("__shareVideo");
        i && (hide(videoCloseBtn), i.parentNode.removeChild(i), this.isVideoPinned && "__videoShare" == this.pinnedVideoPlayerId && this.removeVideoPinMediaContainer(), setVideoDimensions());
    }
    room(e, t = !0) {
        let i = { action: e, password: null };
        if (t)
            switch (e) {
                case "lock":
                    actionModal(
                        smartVideo.msgStore.setRoomPassword,
                        '<input class="form-control" type="password" required id="roomPass">',
                        smartVideo.msgStore.okButton,
                        function (t) {
                            (i.password = t), window.roomClient.socket.emit("room", i), window.roomClient.roomStatus(e);
                        },
                        smartVideo.msgStore.cancelButton
                    );
                    break;
                case "breakoutOn":
                    const t = breakoutCountRooms.value;
                    let o = [];
                    for (let e = 1; e <= t; e++) {
                        let t = Math.random().toString(36).slice(2).substring(0, 10);
                        o.push([t, this.getId("breakoutInput" + e).value]);
                    }
                    (i = { action: e, room_id: this.room_id, peer_id: this.peer_id, peer_name: this.peer_name, broadcast: !1 }),
                        (breakoutRooms = JSON.stringify(o)),
                        liveStorage.setItem("breakoutRooms" + parent_id, breakoutRooms),
                        this.socket.emit("room", i),
                        this.roomStatus(e),
                        this.setPeer(this.peer_name, this.peer_id, "breakout", !0, !0, !1, breakoutRooms);
                    break;
                case "unlock":
                case "admitOn":
                case "admitOff":
                    this.socket.emit("room", i), this.roomStatus(e);
                    break;
                case "breakoutOff":
                    (i.rooms = liveStorage.getItem("breakoutRooms" + parent_id)), this.socket.emit("room", i), this.roomStatus(e), liveStorage.removeItem("breakoutRooms" + parent_id);
            }
        else this.roomStatus(e);
    }
    roomStatus(e) {
        switch (e) {
            case "lock":
                this.event(_EVENTS.roomLock), setNotify("info", smartVideo.msgStore.lockedRoomWithPassword, "top");
                break;
            case "unlock":
                this.event(_EVENTS.roomUnlock), setNotify("info", smartVideo.msgStore.unlockedRoom, "top");
                break;
            case "breakoutOff":
                parsedP && parsedP.parent && (setNotify("info", smartVideo.msgStore.redirectingMain, "top", 1e5), (window.onbeforeunload = null), liveStorage.removeItem("breakoutRooms" + parent_id), this.toggleBreakout(!0));
        }
    }
    startWaitingRoom(e) {
        let t = "",
            i = e.peer_id,
            o = e.peer_name,
            n = e.peer_name.replaceAll(" ", "_"),
            r = getAttendeeAvatar(o),
            s = this.getId("waitingTb"),
            a = `${n}___${i}___admitAccept`,
            c = `${n}___${i}___admitReject`;
        document.querySelector("#waitingRoom").addEventListener("click", function (e) {
            e.target.classList.contains("actionButton") && window.roomClient.waitingRoomAction(e.target.dataset.id, e.target.dataset.action);
        }),
            (t += `\n        <tr id='${i}'>\n            <td><img src="${r}"></td>\n            <td>${o}</td>\n            <td><button id=${a} class="actionButton" data-id="${a}" data-action="accept">${smartVideo.msgStore.admitAccept}</button></td>\n            <td><button id=${c} class="actionButton" data-id="${a}" data-action="reject">${smartVideo.msgStore.admitReject}</button></td>\n        </tr>\n        `),
            (s.innerHTML += t),
            waitingRoomAttendeesCount++,
            (waitingRoomHeaderTitle.innerText = smartVideo.msgStore.waitingUsers + " (" + waitingRoomAttendeesCount + ")"),
            isWaitingRoomOpen || this.waitingRoomToggle(),
            this.isMobileDevice || (setTooltip(a, smartVideo.msgStore.admitAccept, "top"), setTooltip(c, smartVideo.msgStore.admitReject, "top")),
            setNotify("info", o + smartVideo.msgStore.waitToAdmit, "top");
    }
    roomWaitingRoom(e) {
        switch (e.waiting_status) {
            case "waiting":
                isAdmin && this.startWaitingRoom(e);
                break;
            case "accept":
                this.joinAllowed(e.room),
                    (actionButtons.style.display = "flex"),
                    sound("waitingRoom"),
                    setNotify("info", smartVideo.msgStore.admitHostAccepted, "top"),
                    toggleModal(!1),
                    this.setPeer(peer_name, this.peer_info.peer_id, "waiting", !1);
                break;
            case "reject":
                toggleModal(!1);
                sound("waitingRoom"),
                    setNotify("error", smartVideo.msgStore.admissionRejectedText, "top", 3e5, !1, function () {
                        window.roomClient.exit();
                    });
        }
    }
    waitingRoomAction(e, t) {
        const i = e.split("___"),
            o = i[0],
            n = i[1],
            r = { room_id: this.room_id, peer_id: n, peer_name: o, waiting_status: t, broadcast: !1 };
        this.socket.emit("roomAdmit", r);
        const s = this.getId(n);
        s.parentNode.removeChild(s), waitingRoomAttendeesCount--, (waitingRoomHeaderTitle.innerText = smartVideo.msgStore.admissionUsers + " (" + waitingRoomAttendeesCount + ")"), 0 == waitingRoomAttendeesCount && this.waitingRoomToggle();
    }
    waitingAcceptAll() {
        if (waitingRoomAttendeesCount > 0) {
            const e = this.waitingRoomGetData("accept", this.waitingRoomGetPeerIds());
            this.socket.emit("roomAdmit", e), this.waitingRemoveAll();
        } else setNotify("info", smartVideo.msgStore.noWaitingUsers, "top");
    }
    waitingRejectAll() {
        if ((toggleModal(!1), waitingRoomAttendeesCount > 0)) {
            const e = this.waitingRoomGetData("reject", this.waitingRoomGetPeerIds());
            this.socket.emit("roomAdmit", e), this.waitingRemoveAll();
        } else setNotify("info", smartVideo.msgStore.noWaitingUsers, "top");
    }
    waitingRemoveAll() {
        toggleModal(!1);
        let e = waitingTb.getElementsByTagName("tr");
        for (let t = e.length - 1; t >= 0; t--) e[t].id && "waitingAll" != e[t].id && (e[t] && e[t].parentElement && e[t].parentElement.removeChild(e[t]), waitingRoomAttendeesCount--);
        (waitingRoomHeaderTitle.innerText = smartVideo.msgStore.admissionUsers + " (" + waitingRoomAttendeesCount + ")"), 0 == waitingRoomAttendeesCount && this.waitingRoomToggle();
    }
    waitingRoomRemoveMe(e) {
        toggleModal(!1);
        let t = waitingTb.getElementsByTagName("tr");
        for (let i = t.length - 1; i >= 0; i--) t[i].id && t[i].id == e && (t[i] && t[i].parentElement && t[i].parentElement.removeChild(t[i]), waitingRoomAttendeesCount--);
        (waitingRoomHeaderTitle.innerText = smartVideo.msgStore.admissionUsers + " (" + waitingRoomAttendeesCount + ")"), 0 == waitingRoomAttendeesCount && this.waitingRoomToggle();
    }
    waitingRoomGetPeerIds() {
        let e = [],
            t = waitingTb.getElementsByTagName("tr");
        for (let i = t.length - 1; i >= 0; i--) t[i].id && "waitingAll" != t[i].id && e.push(t[i].id);
        return e;
    }
    waitingRoomGetData(e, t = []) {
        return { room_id: this.room_id, peer_id: this.peer_id, peer_name: this.peer_name, peers_id: t, waiting_status: e, broadcast: !0 };
    }
    waitingRoomToggle() {
        (modal = this.getId("waitingRoom")), waitingRoomAttendeesCount > 0 && !isWaitingRoomOpen && isAdmin ? (toggleModal(!0), (isWaitingRoomOpen = !0), sound("waitingRoom")) : (toggleModal(!1), (isWaitingRoomOpen = !1));
    }
    roomPassword(e) {
        switch (e.password) {
            case "OK":
                this.joinAllowed(e.room);
                break;
            case "KO":
                this.roomIsLocked();
                break;
            case "admitOn":
                this.event(_EVENTS.admitOn), setNotify("info", "waitingRoom is enabled", "top");
                break;
            case "admitOff":
                this.event(_EVENTS.admitOff), setNotify("info", "waitingRoom is disabled", "top");
        }
    }
    unlockTheRoom() {
        actionModal(smartVideo.msgStore.roomLocked, '<input placeholder="' + smartVideo.msgStore.enterRoomPassword + '" class="form-control" type="password" id="lockroom">', smartVideo.msgStore.okButton, function (e) {
            let t = { action: "checkPassword", password: e };
            window.roomClient.socket.emit("room", t);
        });
    }
    roomIsLocked() {
        sound("eject"), this.event(_EVENTS.roomLock);
        setNotify("error", smartVideo.msgStore.wrongRoomPassword, "top", 3e5, !1, function () {
            (window.onbeforeunload = null), window.location.reload();
        });
    }
    waitJoinConfirm() {
        setNotify("warning", smartVideo.msgStore.waitingForAdminAccept, "top", 5e6);
    }
    breakoutNotify() {
        setNotify("warning", smartVideo.msgStore.breakoutNotify, "top", 5e6);
    }
    waitBreakoutConfirm(e) {
        const t = JSON.parse(e);
        let i = "";
        t &&
            (liveStorage.setItem("breakoutRooms" + parent_id, e),
            (window.onbeforeunload = null),
            t.forEach(function (e, t) {
                let o = {};
                o.parent = room_id;
                let n = Object.keys(o).length > 0 ? "?p=" + window.btoa(unescape(encodeURIComponent(JSON.stringify(o)))) : "",
                    r = hrefUrl.protocol + "//" + hrefUrl.host + "/" + e[0] + n,
                    s = e[1] || "Room " + (t + 1),
                    a = `<a href="${r}" class="btn btn-primary" id="btn${e[0]}">${s}</a>&nbsp;`;
                i += a;
            }),
            actionModal(smartVideo.msgStore.breakoutRooms, i, smartVideo.msgStore.leaveMeeting, function () {
                window.roomClient.exit();
            }));
    }
    handleAudioVolume(e) {
        let t = e.peer_id,
            i = (e.peer_name, this.getId(t + "_audio")),
            o = this.getId(t + "__audio"),
            n = this.getId(t + "___pAudio"),
            r = 10 * e.audioVolume,
            s = "#dc9d45",
            a = "#484d75";
        [50, 60, 70].includes(r) && (s = "orange"),
            [80, 90, 100].includes(r) && (s = "red"),
            i && (i.style.color = s),
            o && (o.style.color = s),
            n && (n.style.color = s),
            i && (i.parentElement.parentElement.style.borderColor = a),
            o && (o.parentElement.parentElement.style.borderColor = a),
            setTimeout(function () {
                (s = "white"),
                    i && (i.style.color = s),
                    o && (o.style.color = s),
                    n && (n.style.color = "#6c757d"),
                    i && (i.parentElement.parentElement.style.borderColor = "#858585"),
                    o && (o.parentElement.parentElement.style.borderColor = "#858585");
            }, 1e3);
    }
    handleAU(e) {
        let t = e.split("__")[0] + "___pAudio",
            i = this.getId(e);
        i &&
            i.addEventListener("click", (i) => {
                const o = this.getId(e)._tippy;
                o.destroy, i.target.className === html.audioOn ? (this.peer("me", t, "mute"), o.setContent(smartVideo.msgStore.unmute)) : (this.peer("me", t, "unmute"), o.setContent(smartVideo.msgStore.mute));
            });
    }
    peer(e, t, i, o = !0, n = !1) {
        let r = t.split("___")[0];
        if (o) {
            let e = { from_peer_name: this.peer_name, peer_id: r, action: i, broadcast: n };
            if (!this.thereIsAttendees()) return void setNotify("info", smartVideo.msgStore.noAttendeesDetected, "top");
            if ("mute" == i || "hide" == i || "unmute" == i || "unhide" == i || "lowerhand" == i) {
                if ((this.socket.emit("peer", e), "lowerhand" === i)) {
                    let t = this.getId(e.peer_id + "___pHand");
                    t && t.classList.add("d-none");
                }
            } else this.confirmPeerAction(i, e);
        } else
            switch (i) {
                case "eject":
                    (r === this.peer_id || n) &&
                        (sound(i),
                        setNotify("error", smartVideo.msgStore.willEjectFromRoom, "top", 3e5, !1),
                        setTimeout(() => {
                                window.location.href = "https://learn.fukeyeducation.com/home/end_live_class";
                        }, 2e3));
                    break;
                case "mute":
                    (r === this.peer_id || n) &&
                        (this.closeProducer(mediaType.audio),
                        this.setPeer(this.peer_name, this.peer_id, "audio", !1),
                        setNotify("warning", e + "  " + _PEER.audioOff + " " + smartVideo.msgStore.hasMuteYou, "top", 5e3),
                        hide(lowerHandButtonMain),
                        show(raiseHandButtonMain),
                        liveStorage.setItem("audio_off", !0));
                    break;
                case "lowerhand":
                    (r === this.peer_id || n) && this.setPeer(this.peer_name, this.peer_id, "hand", !1);
                    break;
                case "unmute":
                    (r === this.peer_id || n) &&
                        (this.produce(mediaType.audio),
                        this.setPeer(this.peer_name, this.peer_id, "audio", !0),
                        setNotify("warning", e + "  " + _PEER.audioOn + " " + smartVideo.msgStore.hasUnmuteYou, "top", 5e3),
                        hide(lowerHandButtonMain),
                        hide(raiseHandButtonMain),
                        liveStorage.removeItem("audio_off"));
                    break;
                case "hide":
                    (r === this.peer_id || n) && (this.closeProducer(mediaType.video), setNotify("warning", e + "  " + _PEER.videoOff + " " + smartVideo.msgStore.hasStopVideo, "top", 5e3), liveStorage.setItem("video_off", !0));
                    break;
                case "unhide":
                    (r === this.peer_id || n) &&
                        (this.setPeer(this.peer_name, this.peer_id, "video", !0),
                        this.produce(mediaType.video),
                        setNotify("warning", e + "  " + _PEER.videoOn + " " + smartVideo.msgStore.hasStartVideo, "top", 5e3),
                        liveStorage.removeItem("video_off"));
                    break;
                case "screenStart":
                    this.isMobileDevice || setAspectRatio(2);
                    break;
                case "screenStop":
                    this.isMobileDevice || setVideoDimensions();
            }
    }
    confirmPeerAction(e, t) {
        switch (e) {
            case "eject":
                actionModal(
                    t.broadcast ? smartVideo.msgStore.removeAllAttendees : smartVideo.msgStore.removeCurrentAttendee,
                    "",
                    smartVideo.msgStore.yes,
                    function () {
                        if (t.broadcast) {
                            let i = window.roomClient.getId(e + "AllButton");
                            i && (i.style.display = "none"), (attendeesCount = 1), getAttendeesCount(attendeesCount), window.roomClient.socket.emit("peer", t);
                        } else {
                            let e = window.roomClient.getId(t.peer_id);
                            e && e.parentNode.removeChild(e), attendeesCount--, getAttendeesCount(attendeesCount), window.roomClient.socket.emit("peer", t);
                        }
                    },
                    smartVideo.msgStore.no
                );
                break;
            case "screenStart":
            case "screenStop":
                setTimeout(() => {
                    this.socket.emit("peer", t);
                }, 2e3);
        }
    }
    searchPeer() {
        let e, t, i, o, n, r, s;
        for (e = this.getId("searchAttendees"), t = e.value.toUpperCase(), i = this.getId("myTable"), o = i.getElementsByTagName("tr"), r = 0; r < o.length; r++)
            (n = o[r].getElementsByTagName("td")[1]), n && ((s = n.textContent || n.innerText), s.toUpperCase().indexOf(t) > -1 ? (o[r].style.display = "") : (o[r].style.display = "none"));
    }
    setPeer(e, t, i, o, n = !0, r = !1, s = !1) {
        if (n) {
            switch (i) {
                case "audio":
                    this.setIsAudio(t, o);
                    break;
                case "video":
                    this.setIsVideo(t, o);
                    break;
                case "hand":
                    this.peer_info.peer_hand = o;
                    let e = this.getPeerHandBtn(t);
                    o
                        ? (e[0] && (e[0].style.display = "flex"), e[1] && e[1].classList.remove("d-none"), this.event(_EVENTS.raiseHand))
                        : (e[0] && (e[0].style.display = "none"), e[1] && e[1].classList.add("d-none"), this.event(_EVENTS.lowerHand));
            }
            let n = { peer_name: e, peer_id: t, type: i, status: o };
            r && (n.producer_id = r), "breakout" === i && (n.data = s), this.socket.emit("setPeer", n);
        } else
            switch (i) {
                case "audio":
                    this.setIsAudio(t, o);
                    break;
                case "video":
                    this.setIsVideo(t, o);
                    break;
                case "hand":
                    let n = this.getPeerHandBtn(t);
                    o
                        ? (n[0] && (n[0].style.display = "flex"), n[1] && n[1].classList.remove("d-none"), setNotify("warning", e + "  " + _PEER.raiseHand + " " + smartVideo.msgStore.raisedHand, "top", 5e3))
                        : (n[0] && (n[0].style.display = "none"), n[1] && n[1].classList.add("d-none"), this.event(_EVENTS.lowerHand));
                    break;
                case "thumb":
                case "heart":
                case "applause":
                case "laugh":
                case "surprise":
                case "frown":
                    setNotify("info", e + "  " + _PEER[i], "top", 5e3), setPeerReaction(i, t);
                    break;
                case "breakout":
                    this.waitBreakoutConfirm(s);
            }
    }
    checkPeerInfoStatus(e) {
        let t = e.peer_id;
        if (e.peer_hand) {
            let e = this.getPeerHandBtn(t);
            e[0] && (e[0].style.display = "flex"), e[1] && (e[1].style.display = "flex");
        }
    }
    setRoomLocked(e) {
        this.socket.emit("room", e), this.roomStatus("lock");
    }
}
let browserLanguage = navigator.language || navigator.userLanguage;
const speechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition,
    commands = {
        shareRoom: "share room",
        newRoom: "new room",
        leaveRoom: "exit room",
        audioOn: "start audio",
        audioOff: "stop audio",
        videoOn: "start video",
        videoOff: "stop video",
        screenOn: "start screen share",
        screenOff: "stop screen share",
        chatOn: "open chat",
        chatSend: "send chat message",
        chatOff: "close chat",
        chatGPTOn: "open chatGPT",
        chatGPTOff: "close chatGPT",
        whiteboardOn: "open whiteboard",
        whiteboardOff: "close whiteboard",
        recordingOn: "start recording",
        recordingPause: "pause recording",
        recordingResume: "resume recording",
        recordingOff: "stop recording",
        settingsOn: "open settings",
        settingsOff: "close settings",
        participantsOn: "opne participants",
        participantsOff: "close participants",
        fileShareOn: "open a file",
        fileShareOff: "close a file",
        videoShareOn: "share video",
        videoShareOff: "close video",
        swapCamera: "swap camera",
        raiseHand: "raise hand",
        lowerHand: "lower hand",
        roomLock: "lock room",
        roomUnlock: "unlock room",
        about: "show about",
        email: "open email",
        google: "open google",
        googleTr: "open google translate",
        youtube: "open youtube",
        facebook: "open facebook",
        linkedin: "open linkedin",
        twitter: "open twitter",
        tiktok: "open tiktok",
        github: "open github",
        survey: "open survey",
        stopRecognition: "stop voice recognition",
    },
    browser = {
        newroom: "/newroom",
        email: "mailto:?subject=&body=",
        google: "https://www.google.com",
        googleTr: "https://translate.google.com/",
        youtube: "https://www.youtube.com",
        facebook: "https://www.facebook.com",
        linkedin: "https://www.linkedin.com",
        twitter: "https://www.twitter.com",
        tiktok: "https://www.tiktok.com",
        github: "https://github.com/miroslavpejic85",
    };
class SpeechRec {
    init() {
        speechRecognition
            ? ((recognition = new speechRecognition()),
              (recognition.maxAlternatives = 1),
              (recognition.continuous = !0),
              (recognition.interimResults = !0),
              (recognition.onstart = function () {
                  chatSpeechStartButton.classList.add("activeControl"), setTooltip("chatSpeechStartButton", smartVideo.msgStore.chatSpeechStop, "top");
              }),
              (recognition.onresult = async (e) => {
                  let t = "",
                      i = "";
                  for (let o = e.resultIndex; o < e.results.length; ++o) e.results[o].isFinal ? (t += e.results[o][0].transcript) : (i += e.results[o][0].transcript);
                  if ((t && smartVideo.config.transcribe && smartVideo.config.transcribe.voiceCommands && this.execVoiceCommands(t.trim()), t && t != commands.chatSend))
                      if (smartVideo.config.transcribe && smartVideo.config.transcribe.enabled)
                          if (smartVideo.config.transcribe.apiKey && languageTo) {
                              let e = await this.translate(t, !1);
                              rc.sendTranscribe(e);
                          } else rc.sendTranscribe(t);
                      else chatMessage.value = t;
              }),
              (recognition.onerror = function (e) {
                  console.warn("Speech recognition error", e.error);
              }),
              (recognition.onend = function () {
                  chatSpeechStartButton.classList.remove("activeControl"), setTooltip("chatSpeechStartButton", smartVideo.msgStore.chatSpeechStart, "top");
              }))
            : (console.warn("This browser not supports webkitSpeechRecognition"), chatSpeechStartButton.classList.remove("activeControl"), setTooltip("chatSpeechStartButton", smartVideo.msgStore.chatSpeechStart, "top"));
    }
    async translate(e, t) {
        let i, o;
        isAdmin ? ((i = t ? languageTo : language), (o = t ? language : languageTo)) : ((i = t ? language : languageTo), (o = t ? languageTo : language));
        let n = "https://translation.googleapis.com/language/translate/v2?key=" + smartVideo.config.transcribe.apiKey;
        return (
            (n += "&source=" + i),
            (n += "&target=" + o),
            (n += "&q=" + encodeURIComponent(e)),
            fetch(n)
                .then((e) => e.json())
                .then((e) => e.data.translations[0].translatedText)
                .catch((e) => {
                    console.warn("Get translationss failed", e);
                })
        );
    }
    startSpeech(e) {
        if (e) {
            const e = !isAdmin && languageTo ? languageTo : language;
            (recognition.lang = smartVideo.config.transcribe && e ? e : browserLanguage), recognition.start();
        } else recognition.stop();
    }
}
function execVoiceCommands(e) {
    switch (e.trim().toLowerCase()) {
        case commands.shareRoom:
            printCommand(commands.shareRoom), shareButton.click();
            break;
        case commands.hideMe:
            printCommand(commands.hideMe), hideMeButton.click();
            break;
        case commands.showMe:
            printCommand(commands.showMe), hideMeButton.click();
            break;
        case commands.newRoom:
            printCommand(commands.newRoom), openURL(browser.newroom);
            break;
        case commands.leaveRoom:
            printCommand(commands.leaveRoom), exitButton.click();
            break;
        case commands.audioOn:
            printCommand(commands.audioOn), startAudioButton.click();
            break;
        case commands.audioOff:
            printCommand(commands.audioOff), stopAudioButton.click();
            break;
        case commands.videoOn:
            printCommand(commands.videoOn), startVideoButton.click();
            break;
        case commands.videoOff:
            printCommand(commands.videoOff), stopVideoButton.click();
            break;
        case commands.screenOn:
            printCommand(commands.screenOn), startScreenButton.click();
            break;
        case commands.screenOff:
            printCommand(commands.screenOff), stopScreenButton.click();
            break;
        case commands.chatOn:
            printCommand(commands.chatOn), chatButton.click();
            break;
        case commands.chatSend:
            printCommand(commands.chatSend), chatSendButton.click();
            break;
        case commands.chatOff:
            printCommand(commands.chatOff), chatCloseButton.click();
            break;
        case commands.whiteboardOn:
            printCommand(commands.whiteboardOn), whiteboardButton.click();
            break;
        case commands.chatGPTOn:
            printCommand(commands.chatGPTOn), chatGPTButton.click();
            break;
        case commands.chatGPTOff:
            printCommand(commands.chatGPTOff), chatGPTButton.click();
            break;
        case commands.whiteboardOff:
            printCommand(commands.whiteboardOff), whiteboardCloseBtn.click();
            break;
        case commands.recordingOn:
            printCommand(commands.recordingOn), startRecButton.click();
            break;
        case commands.recordingPause:
            printCommand(commands.recordingPause), pauseRecButton.click();
            break;
        case commands.recordingResume:
            printCommand(commands.recordingResume), recordingResume.click();
            break;
        case commands.recordingOff:
            printCommand(commands.recordingOff), stopRecButton.click();
            break;
        case commands.settingsOn:
            printCommand(commands.settingsOn), settingsButton.click();
            break;
        case commands.settingsOff:
            printCommand(commands.settingsOff), mySettingsCloseBtn.click();
            break;
        case commands.participantsOn:
            printCommand(commands.participantsOn), participantsButton.click();
            break;
        case commands.participantsOff:
            printCommand(commands.participantsOff), participantsCloseBtn.click();
            break;
        case commands.fileShareOn:
            printCommand(commands.fileShareOn), fileShareButton.click();
            break;
        case commands.fileShareOff:
            printCommand(commands.fileShareOff), sendAbortBtn.click();
            break;
        case commands.videoShareOn:
            printCommand(commands.videoShareOn), videoShareButton.click();
            break;
        case commands.videoShareOff:
            printCommand(commands.videoShareOff), videoCloseBtn.click();
            break;
        case commands.swapCamera:
            printCommand(commands.swapCamera), swapCameraButton.click();
            break;
        case commands.raiseHand:
            printCommand(commands.raiseHand), raiseHandButton.click();
            break;
        case commands.lowerHand:
            printCommand(commands.lowerHand), lowerHandButton.click();
            break;
        case commands.roomLock:
            printCommand(commands.roomLock), lockRoomButton.click();
            break;
        case commands.roomUnlock:
            printCommand(commands.roomUnlock), unlockRoomButton.click();
            break;
        case commands.about:
            printCommand(commands.about), aboutButton.click();
            break;
        case commands.email:
            printCommand(commands.email), openURL(browser.email, !0), sound("open");
            break;
        case commands.google:
            printCommand(commands.google), openURL(browser.google, !0), sound("open");
            break;
        case commands.googleTr:
            printCommand(commands.googleTr), openURL(browser.googleTr, !0), sound("open");
            break;
        case commands.youtube:
            printCommand(commands.youtube), openURL(browser.youtube, !0), sound("open");
            break;
        case commands.facebook:
            printCommand(commands.facebook), openURL(browser.facebook, !0), sound("open");
            break;
        case commands.linkedin:
            printCommand(commands.linkedin), openURL(browser.linkedin, !0), sound("open");
            break;
        case commands.twitter:
            printCommand(commands.twitter), openURL(browser.twitter, !0), sound("open");
            break;
        case commands.tiktok:
            printCommand(commands.tiktok), openURL(browser.tiktok, !0), sound("open");
            break;
        case commands.github:
            printCommand(commands.github), openURL(browser.github, !0), sound("open");
            break;
        case commands.survey:
            printCommand(commands.survey), openURL(url.survey, !0), sound("open");
            break;
        case commands.stopRecognition:
            printCommand(commands.stopRecognition), chatSpeechStopButton.click();
    }
}
function printCommand(e) {
    console.log("Detected", { command: e });
}
let customRatio = !0,
    ratios = ["0:0", "4:3", "16:9", "1:1", "1:2"],
    aspect = 2,
    ratio = getAspectRatio();
function getAspectRatio() {
    customRatio = 0 == aspect;
    var e = ratios[aspect].split(":");
    return e[1] / e[0];
}
function setAspectRatio(e) {
    (aspect = e), (ratio = getAspectRatio()), resizeVideoMedia();
}
function Area(e, t, i, o, n = 10) {
    ratio = customRatio ? 0.75 : ratio;
    let r = 0,
        s = 0,
        a = e * ratio + 2 * n;
    for (; r < t; ) s + e > i && ((s = 0), (a = a + e * ratio + 2 * n)), (s = s + e + 2 * n), r++;
    return !(a > o) && e;
}
function resizeVideoMedia() {
    let e = document.getElementById("videoMediaContainer"),
        t = document.getElementsByClassName("videoContainerElement");
    if (smartVideo.config.videoScreen && smartVideo.config.videoScreen.lockedFeed) {
        document.getElementsByClassName("videoContainerElement");
    }
    let i = e.offsetWidth - 6,
        o = e.offsetHeight - 6,
        n = 0,
        r = 4 * i;
    1 == e.childElementCount && (i -= r);
    let s = 1;
    for (; s < 5e3; ) {
        if (!1 === Area(s, t.length, i, o, 3)) {
            n = s - 1;
            break;
        }
        s++;
    }
    (n -= 6), setWidth(e, t, n, r, 3, o);
}
function isMobile() {

    var vendor = navigator.userAgent || navigator.vendor;

    vendor = vendor.toLowerCase();

    return !!(

      /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(

        vendor

      ) ||

      /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(

        vendor.substr(0, 4)

      ) || (/Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints && navigator.maxTouchPoints > 1)

    );

  }

  function isLandSpaceMobile(){

    if (window.matchMedia("(orientation: landscape)").matches) {

      return true;  

   }else{

    return false;

   }

  }


function setWidth(e, t, i, o, n, r) {
    ratio = customRatio ? 0.68 : ratio;
    if(isMobile()){
        i = window.innerWidth;
        console.log(i);
        console.log("onsize");
        console.log(ratio);
    }

    ratio = isLandSpaceMobile() ? 1 : ratio;
    //alert(ratio);
    let s = 1;
    smartVideo.config.videoScreen && smartVideo.config.videoScreen.lockedFeed && (s = 2);
    let a = e.childElementCount == s;
    for (let e = 0; e < t.length; e++)
        if (((t[e].style.width = i + "px"), (t[e].style.margin = n + "px"), (t[e].style.height = i * ratio + "px"), a)) {
            (t[e].style.width = o + "px"), (t[e].style.height = o * ratio + "px"), t[e].style.height.substring(0, t[e].style.height.length - 2) >= r && (t[e].style.height = r - 2 + "px");
            if (t.length === 2) {
                t[e].style.height = "50%";
            }
        }
    let c = document.getElementById("backgroundCanvas");
    document.getElementById("backgroundCanvasBlur");
    if (producerId && c) {
        let e = document.getElementById(producerId);
        e && ((c.width = e.width = i), (c.height = e.height = i * ratio));
    }
    let l = document.getElementById("initVideo");
    !l && producerId && (l = document.getElementById(producerId)),
        l && c && l.width !== l.clientWidth && ((l.width = c.width = l.clientWidth ? l.clientWidth : l.width), (l.height = c.height = l.clientHeight ? l.clientHeight : l.height), (c.style.top = l.style.top), (c.style.left = l.style.left));
}
/**
 * {@link https://github.com/muaz-khan/RecordRTC|RecordRTC} is a WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows.
 * @summary Record audio, video or screen inside the browser.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef RecordRTC
 * @class
 * @example
 * var recorder = RecordRTC(mediaStream or [arrayOfMediaStream], {
 *     type: 'video', // audio or video or gif or canvas
 *     recorderType: MediaStreamRecorder || CanvasRecorder || StereoAudioRecorder || Etc
 * });
 * recorder.startRecording();
 * @see For further information:
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - Single media-stream object, array of media-streams, html-canvas-element, etc.
 * @param {object} config - {type:"video", recorderType: MediaStreamRecorder, disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, desiredSampRate: 16000, video: HTMLVideoElement, etc.}
 */
function RecordRTC(e, t) {
    if (!e) throw "First parameter is required.";
    t = new RecordRTCConfiguration(e, (t = t || { type: "video" }));
    var i = this;
    function o(i) {
        i &&
            (t.initCallback = function () {
                i(), (i = t.initCallback = null);
            });
        var o = new GetRecorderType(e, t);
        (l = new o(e, t)).record(), c("recording"), t.disableLogs || console.log("Initialized recorderType:", l.constructor.name, "for output-type:", t.type);
    }
    function n(e) {
        if (((e = e || function () {}), l)) {
            if ("paused" === i.state)
                return (
                    i.resumeRecording(),
                    void setTimeout(function () {
                        n(e);
                    }, 1)
                );
            "recording" === i.state || t.disableLogs || console.warn('Recording state should be: "recording", however current state is: ', i.state),
                t.disableLogs || console.log("Stopped recording " + t.type + " stream."),
                "gif" !== t.type ? l.stop(o) : (l.stop(), o()),
                c("stopped");
        } else h();
        function o(o) {
            if (l) {
                Object.keys(l).forEach(function (e) {
                    "function" != typeof l[e] && (i[e] = l[e]);
                });
                var n = l.blob;
                
                if (!n) {
                    if (!o) throw "Recording failed.";
                    l.blob = n = o;
                }
                if ((n && !t.disableLogs && console.log(n.type, "->", bytesToSize(n.size)), e)) {
                    var r;
                    try {
                        r = URL.createObjectURL(n);
                    } catch (e) {}
                    "function" == typeof e.call ? e.call(i, r) : e(r);
                }
                t.autoWriteToDisk &&
                    s(function (e) {
                        var i = {};
                        (i[t.type + "Blob"] = e), DiskStorage.Store(i);
                    });
            } else "function" == typeof e.call ? e.call(i, "") : e("");
        }
    }
    function r(e) {
        postMessage(new FileReaderSync().readAsDataURL(e));
    }
    function s(e, i) {
        if (!e) throw "Pass a callback function over getDataURL.";
        var o = i ? i.blob : (l || {}).blob;
        if (!o)
            return (
                t.disableLogs || console.warn("Blob encoder did not finish its job yet."),
                void setTimeout(function () {
                    s(e, i);
                }, 1e3)
            );
        if ("undefined" == typeof Worker || navigator.mozGetUserMedia) {
            var n = new FileReader();
            n.readAsDataURL(o),
                (n.onload = function (t) {
                    e(t.target.result);
                });
        } else {
            var a = (function (e) {
                try {
                    var t = URL.createObjectURL(new Blob([e.toString(), "this.onmessage =  function (eee) {" + e.name + "(eee.data);}"], { type: "application/javascript" })),
                        i = new Worker(t);
                    return URL.revokeObjectURL(t), i;
                } catch (e) {}
            })(r);
            (a.onmessage = function (t) {
                e(t.data);
            }),
                a.postMessage(o);
        }
    }
    function a(e) {
        (e = e || 0),
            "paused" !== i.state
                ? "stopped" !== i.state &&
                  (e >= i.recordingDuration
                      ? n(i.onRecordingStopped)
                      : ((e += 1e3),
                        setTimeout(function () {
                            a(e);
                        }, 1e3)))
                : setTimeout(function () {
                      a(e);
                  }, 1e3);
    }
    function c(e) {
        i && ((i.state = e), "function" == typeof i.onStateChanged.call ? i.onStateChanged.call(i, e) : i.onStateChanged(e));
    }
    var l,
        d = 'It seems that recorder is destroyed or "startRecording" is not invoked for ' + t.type + " recorder.";
    function h() {
        !0 !== t.disableLogs && console.warn(d);
    }
    var u = {
        startRecording: function (n) {
            return (
                t.disableLogs || console.log("RecordRTC version: ", i.version),
                n && (t = new RecordRTCConfiguration(e, n)),
                t.disableLogs || console.log("started recording " + t.type + " stream."),
                l
                    ? (l.clearRecordedData(), l.record(), c("recording"), i.recordingDuration && a(), i)
                    : (o(function () {
                          i.recordingDuration && a();
                      }),
                      i)
            );
        },
        stopRecording: n,
        pauseRecording: function () {
            l ? ("recording" === i.state ? (c("paused"), l.pause(), t.disableLogs || console.log("Paused recording.")) : t.disableLogs || console.warn("Unable to pause the recording. Recording state: ", i.state)) : h();
        },
        resumeRecording: function () {
            l ? ("paused" === i.state ? (c("recording"), l.resume(), t.disableLogs || console.log("Resumed recording.")) : t.disableLogs || console.warn("Unable to resume the recording. Recording state: ", i.state)) : h();
        },
        initRecorder: o,
        setRecordingDuration: function (e, t) {
            if (void 0 === e) throw "recordingDuration is required.";
            if ("number" != typeof e) throw "recordingDuration must be a number.";
            return (
                (i.recordingDuration = e),
                (i.onRecordingStopped = t || function () {}),
                {
                    onRecordingStopped: function (e) {
                        i.onRecordingStopped = e;
                    },
                }
            );
        },
        clearRecordedData: function () {
            l ? (l.clearRecordedData(), t.disableLogs || console.log("Cleared old recorded data.")) : h();
        },
        getBlob: function () {
            if (l) return l.blob;
            h();
        },
        getDataURL: s,
        toURL: function () {
            if (l) return URL.createObjectURL(l.blob);
            h();
        },
        getInternalRecorder: function () {
            return l;
        },
        save: function (e) {
            l ? invokeSaveAsDialog(l.blob, e) : h();
        },
        getFromDisk: function (e) {
            l ? RecordRTC.getFromDisk(t.type, e) : h();
        },
        setAdvertisementArray: function (e) {
            t.advertisement = [];
            for (var i = e.length, o = 0; o < i; o++) t.advertisement.push({ duration: o, image: e[o] });
        },
        blob: null,
        bufferSize: 0,
        sampleRate: 0,
        buffer: null,
        reset: function () {
            "recording" !== i.state || t.disableLogs || console.warn("Stop an active recorder."), l && "function" == typeof l.clearRecordedData && l.clearRecordedData(), (l = null), c("inactive"), (i.blob = null);
        },
        onStateChanged: function (e) {
            t.disableLogs || console.log("Recorder state changed:", e);
        },
        state: "inactive",
        getState: function () {
            return i.state;
        },
        destroy: function () {
            var e = t.disableLogs;
            (t = { disableLogs: !0 }),
                i.reset(),
                c("destroyed"),
                (u = i = null),
                Storage.AudioContextConstructor && (Storage.AudioContextConstructor.close(), (Storage.AudioContextConstructor = null)),
                (t.disableLogs = e),
                t.disableLogs || console.log("RecordRTC is destroyed.");
        },
        version: "5.6.2",
    };
    if (!this) return (i = u), u;
    for (var f in u) this[f] = u[f];
    return (i = this), u;
}
/**
 * {@link RecordRTCConfiguration} is an inner/private helper for {@link RecordRTC}.
 * @summary It configures the 2nd parameter passed over {@link RecordRTC} and returns a valid "config" object.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef RecordRTCConfiguration
 * @class
 * @example
 * var options = RecordRTCConfiguration(mediaStream, options);
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {type:"video", disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, getNativeBlob:true, etc.}
 */
function RecordRTCConfiguration(e, t) {
    return (
        t.recorderType || t.type || (t.audio && t.video ? (t.type = "video") : t.audio && !t.video && (t.type = "audio")),
        t.recorderType &&
            !t.type &&
            (t.recorderType === WhammyRecorder || t.recorderType === CanvasRecorder || (void 0 !== WebAssemblyRecorder && t.recorderType === WebAssemblyRecorder)
                ? (t.type = "video")
                : t.recorderType === GifRecorder
                ? (t.type = "gif")
                : t.recorderType === StereoAudioRecorder
                ? (t.type = "audio")
                : t.recorderType === MediaStreamRecorder &&
                  ((getTracks(e, "audio").length && getTracks(e, "video").length) || (!getTracks(e, "audio").length && getTracks(e, "video").length)
                      ? (t.type = "video")
                      : getTracks(e, "audio").length && !getTracks(e, "video").length && (t.type = "audio"))),
        void 0 !== MediaStreamRecorder && "undefined" != typeof MediaRecorder && "requestData" in MediaRecorder.prototype && (t.mimeType || (t.mimeType = "video/mp4"), t.type || (t.type = t.mimeType.split("/")[0]), t.bitsPerSecond),
        t.type || (t.mimeType && (t.type = t.mimeType.split("/")[0]), t.type || (t.type = "audio")),
        t
    );
}
/**
 * {@link GetRecorderType} is an inner/private helper for {@link RecordRTC}.
 * @summary It returns best recorder-type available for your browser.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef GetRecorderType
 * @class
 * @example
 * var RecorderType = GetRecorderType(options);
 * var recorder = new RecorderType(options);
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {type:"video", disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, etc.}
 */ 
function GetRecorderType(e, t) {
    var i;
    return (
        (isChrome || isEdge || isOpera) && (i = StereoAudioRecorder),
        "undefined" != typeof MediaRecorder && "requestData" in MediaRecorder.prototype && !isChrome && (i = MediaStreamRecorder),
        "video" === t.type && (isChrome || isOpera) && ((i = WhammyRecorder), void 0 !== WebAssemblyRecorder && "undefined" != typeof ReadableStream && (i = WebAssemblyRecorder)),
        "gif" === t.type && (i = GifRecorder),
        "canvas" === t.type && (i = CanvasRecorder),
        isMediaRecorderCompatible() &&
            i !== CanvasRecorder &&
            i !== GifRecorder &&
            "undefined" != typeof MediaRecorder &&
            "requestData" in MediaRecorder.prototype &&
            (getTracks(e, "video").length || getTracks(e, "audio").length) &&
            ("audio" === t.type
                ? "function" == typeof MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported("audio/webm") && (i = MediaStreamRecorder)
                : "function" == typeof MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported("video/webm") && (i = MediaStreamRecorder)),
        e instanceof Array && e.length && (i = MultiStreamRecorder),
        t.recorderType && (i = t.recorderType),
        !t.disableLogs && i && i.name && console.log("Using recorderType:", i.name || i.constructor.name),
        !i && isSafari && (i = MediaStreamRecorder),
        i
    );
}
/**
 * MRecordRTC runs on top of {@link RecordRTC} to bring multiple recordings in a single place, by providing simple API.
 * @summary MRecordRTC stands for "Multiple-RecordRTC".
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef MRecordRTC
 * @class
 * @example
 * var recorder = new MRecordRTC();
 * recorder.addStream(MediaStream);
 * recorder.mediaType = {
 *     audio: true, // or StereoAudioRecorder or MediaStreamRecorder
 *     video: true, // or WhammyRecorder or MediaStreamRecorder or WebAssemblyRecorder or CanvasRecorder
 *     gif: true    // or GifRecorder
 * };
 * // mimeType is optional and should be set only in advance cases.
 * recorder.mimeType = {
 *     audio: 'audio/wav',
 *     video: 'video/webm',
 *     gif:   'image/gif'
 * };
 * recorder.startRecording();
 * @see For further information:
 * @see {@link https://github.com/muaz-khan/RecordRTC/tree/master/MRecordRTC|MRecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @requires {@link RecordRTC}
 */ 
function MRecordRTC(e) {
    (this.addStream = function (t) {
        t && (e = t);
    }),
        (this.mediaType = { audio: !0, video: !0 }),
        (this.startRecording = function () {
            var t,
                i = this.mediaType,
                o = this.mimeType || { audio: null, video: null, gif: null };
            if (
                ("function" != typeof i.audio && isMediaRecorderCompatible() && !getTracks(e, "audio").length && (i.audio = !1),
                "function" != typeof i.video && isMediaRecorderCompatible() && !getTracks(e, "video").length && (i.video = !1),
                "function" != typeof i.gif && isMediaRecorderCompatible() && !getTracks(e, "video").length && (i.gif = !1),
                !i.audio && !i.video && !i.gif)
            )
                throw "MediaStream must have either audio or video tracks.";
            if (
                (i.audio &&
                    ((t = null),
                    "function" == typeof i.audio && (t = i.audio),
                    (this.audioRecorder = new RecordRTC(e, {
                        type: "audio",
                        bufferSize: this.bufferSize,
                        sampleRate: this.sampleRate,
                        numberOfAudioChannels: this.numberOfAudioChannels || 2,
                        disableLogs: this.disableLogs,
                        recorderType: t,
                        mimeType: o.audio,
                        timeSlice: this.timeSlice,
                        onTimeStamp: this.onTimeStamp,
                    })),
                    i.video || this.audioRecorder.startRecording()),
                i.video)
            ) {
                (t = null), "function" == typeof i.video && (t = i.video);
                var n = e;
                if (isMediaRecorderCompatible() && i.audio && "function" == typeof i.audio) {
                    var r = getTracks(e, "video")[0];
                    isFirefox ? ((n = new MediaStream()).addTrack(r), t && t === WhammyRecorder && (t = MediaStreamRecorder)) : (n = new MediaStream()).addTrack(r);
                }
                (this.videoRecorder = new RecordRTC(n, {
                    type: "video",
                    video: this.video,
                    canvas: this.canvas,
                    frameInterval: this.frameInterval || 10,
                    disableLogs: this.disableLogs,
                    recorderType: t,
                    mimeType: o.video,
                    timeSlice: this.timeSlice,
                    onTimeStamp: this.onTimeStamp,
                    workerPath: this.workerPath,
                    webAssemblyPath: this.webAssemblyPath,
                    frameRate: this.frameRate,
                    bitrate: this.bitrate,
                })),
                    i.audio || this.videoRecorder.startRecording();
            }
            if (i.audio && i.video) {
                var s = this,
                    a = !0 === isMediaRecorderCompatible();
                ((i.audio instanceof StereoAudioRecorder && i.video) || (!0 !== i.audio && !0 !== i.video && i.audio !== i.video)) && (a = !1),
                    !0 === a
                        ? ((s.audioRecorder = null), s.videoRecorder.startRecording())
                        : s.videoRecorder.initRecorder(function () {
                              s.audioRecorder.initRecorder(function () {
                                  s.videoRecorder.startRecording(), s.audioRecorder.startRecording();
                              });
                          });
            }
            i.gif &&
                ((t = null),
                "function" == typeof i.gif && (t = i.gif),
                (this.gifRecorder = new RecordRTC(e, { type: "gif", frameRate: this.frameRate || 200, quality: this.quality || 10, disableLogs: this.disableLogs, recorderType: t, mimeType: o.gif })),
                this.gifRecorder.startRecording());
        }),
        (this.stopRecording = function (e) {
            (e = e || function () {}),
                this.audioRecorder &&
                    this.audioRecorder.stopRecording(function (t) {
                        e(t, "audio");
                    }),
                this.videoRecorder &&
                    this.videoRecorder.stopRecording(function (t) {
                        e(t, "video");
                    }),
                this.gifRecorder &&
                    this.gifRecorder.stopRecording(function (t) {
                        e(t, "gif");
                    });
        }),
        (this.pauseRecording = function () {
            this.audioRecorder && this.audioRecorder.pauseRecording(), this.videoRecorder && this.videoRecorder.pauseRecording(), this.gifRecorder && this.gifRecorder.pauseRecording();
        }),
        (this.resumeRecording = function () {
            this.audioRecorder && this.audioRecorder.resumeRecording(), this.videoRecorder && this.videoRecorder.resumeRecording(), this.gifRecorder && this.gifRecorder.resumeRecording();
        }),
        (this.getBlob = function (e) {
            var t = {};
            return this.audioRecorder && (t.audio = this.audioRecorder.getBlob()), this.videoRecorder && (t.video = this.videoRecorder.getBlob()), this.gifRecorder && (t.gif = this.gifRecorder.getBlob()), e && e(t), t;
        }),
        (this.destroy = function () {
            this.audioRecorder && (this.audioRecorder.destroy(), (this.audioRecorder = null)),
                this.videoRecorder && (this.videoRecorder.destroy(), (this.videoRecorder = null)),
                this.gifRecorder && (this.gifRecorder.destroy(), (this.gifRecorder = null));
        }),
        (this.getDataURL = function (e) {
            function t(e, t) {
                if ("undefined" != typeof Worker) {
                    var i = (function (e) {
                        var t,
                            i = URL.createObjectURL(new Blob([e.toString(), "this.onmessage =  function (eee) {" + e.name + "(eee.data);}"], { type: "application/javascript" })),
                            o = new Worker(i);
                        if (void 0 !== URL) t = URL;
                        else {
                            if ("undefined" == typeof webkitURL) throw "Neither URL nor webkitURL detected.";
                            t = webkitURL;
                        }
                        return t.revokeObjectURL(i), o;
                    })(function (e) {
                        postMessage(new FileReaderSync().readAsDataURL(e));
                    });
                    (i.onmessage = function (e) {
                        t(e.data);
                    }),
                        i.postMessage(e);
                } else {
                    var o = new FileReader();
                    o.readAsDataURL(e),
                        (o.onload = function (e) {
                            t(e.target.result);
                        });
                }
            }
            this.getBlob(function (i) {
                i.audio && i.video
                    ? t(i.audio, function (o) {
                          t(i.video, function (t) {
                              e({ audio: o, video: t });
                          });
                      })
                    : i.audio
                    ? t(i.audio, function (t) {
                          e({ audio: t });
                      })
                    : i.video &&
                      t(i.video, function (t) {
                          e({ video: t });
                      });
            });
        }),
        (this.writeToDisk = function () {
            RecordRTC.writeToDisk({ audio: this.audioRecorder, video: this.videoRecorder, gif: this.gifRecorder });
        }),
        (this.save = function (e) {
            (e = e || { audio: !0, video: !0, gif: !0 }).audio && this.audioRecorder && this.audioRecorder.save("string" == typeof e.audio ? e.audio : ""),
                e.video && this.videoRecorder && this.videoRecorder.save("string" == typeof e.video ? e.video : ""),
                e.gif && this.gifRecorder && this.gifRecorder.save("string" == typeof e.gif ? e.gif : "");
        });
}
window.onresize = () => {

    resizeVideoMedia()

},
    (RecordRTC.version = "5.6.2"),
    "undefined" != typeof module && (module.exports = RecordRTC),
    "function" == typeof define &&
        define.amd &&
        define("RecordRTC", [], function () {
            return RecordRTC;
        }),
    (RecordRTC.getFromDisk = function (e, t) {
        if (!t) throw "callback is mandatory.";
        console.log("Getting recorded " + ("all" === e ? "blobs" : e + " blob ") + " from disk!"),
            DiskStorage.Fetch(function (i, o) {
                "all" !== e && o === e + "Blob" && t && t(i), "all" === e && t && t(i, o.replace("Blob", ""));
            });
    }),
    (RecordRTC.writeToDisk = function (e) {
        console.log("Writing recorded blob(s) to disk!"),
            (e = e || {}).audio && e.video && e.gif
                ? e.audio.getDataURL(function (t) {
                      e.video.getDataURL(function (i) {
                          e.gif.getDataURL(function (e) {
                              DiskStorage.Store({ audioBlob: t, videoBlob: i, gifBlob: e });
                          });
                      });
                  })
                : e.audio && e.video
                ? e.audio.getDataURL(function (t) {
                      e.video.getDataURL(function (e) {
                          DiskStorage.Store({ audioBlob: t, videoBlob: e });
                      });
                  })
                : e.audio && e.gif
                ? e.audio.getDataURL(function (t) {
                      e.gif.getDataURL(function (e) {
                          DiskStorage.Store({ audioBlob: t, gifBlob: e });
                      });
                  })
                : e.video && e.gif
                ? e.video.getDataURL(function (t) {
                      e.gif.getDataURL(function (e) {
                          DiskStorage.Store({ videoBlob: t, gifBlob: e });
                      });
                  })
                : e.audio
                ? e.audio.getDataURL(function (e) {
                      DiskStorage.Store({ audioBlob: e });
                  })
                : e.video
                ? e.video.getDataURL(function (e) {
                      DiskStorage.Store({ videoBlob: e });
                  })
                : e.gif &&
                  e.gif.getDataURL(function (e) {
                      DiskStorage.Store({ gifBlob: e });
                  });
    }),
    (MRecordRTC.getFromDisk = RecordRTC.getFromDisk),
    (MRecordRTC.writeToDisk = RecordRTC.writeToDisk),
    void 0 !== RecordRTC && (RecordRTC.MRecordRTC = MRecordRTC);
var browserFakeUserAgent = "Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45";
!(function (e) {
    e &&
        "undefined" == typeof window &&
        "undefined" != typeof global &&
        ((global.navigator = { userAgent: browserFakeUserAgent, getUserMedia: function () {} }),
        global.console || (global.console = {}),
        (void 0 !== global.console.log && void 0 !== global.console.error) ||
            (global.console.error = global.console.log =
                global.console.log ||
                function () {
                    console.log(arguments);
                }),
        "undefined" == typeof document &&
            ((e.document = {
                documentElement: {
                    appendChild: function () {
                        return "";
                    },
                },
            }),
            (document.createElement = document.captureStream = document.mozCaptureStream = function () {
                var e = {
                    getContext: function () {
                        return e;
                    },
                    play: function () {},
                    pause: function () {},
                    drawImage: function () {},
                    toDataURL: function () {
                        return "";
                    },
                    style: {},
                };
                return e;
            }),
            (e.HTMLVideoElement = function () {})),
        "undefined" == typeof location && (e.location = { protocol: "file:", href: "", hash: "" }),
        "undefined" == typeof screen && (e.screen = { width: 0, height: 0 }),
        void 0 === URL &&
            (e.URL = {
                createObjectURL: function () {
                    return "";
                },
                revokeObjectURL: function () {
                    return "";
                },
            }),
        (e.window = global));
})("undefined" != typeof global ? global : null);
var requestAnimationFrame = window.requestAnimationFrame;
if (void 0 === requestAnimationFrame)
    if ("undefined" != typeof webkitRequestAnimationFrame) requestAnimationFrame = webkitRequestAnimationFrame;
    else if ("undefined" != typeof mozRequestAnimationFrame) requestAnimationFrame = mozRequestAnimationFrame;
    else if ("undefined" != typeof msRequestAnimationFrame) requestAnimationFrame = msRequestAnimationFrame;
    else if (void 0 === requestAnimationFrame) {
        var lastTime = 0;
        requestAnimationFrame = function (e, t) {
            var i = new Date().getTime(),
                o = Math.max(0, 16 - (i - lastTime)),
                n = setTimeout(function () {
                    e(i + o);
                }, o);
            return (lastTime = i + o), n;
        };
    }
var cancelAnimationFrame = window.cancelAnimationFrame;
void 0 === cancelAnimationFrame &&
    ("undefined" != typeof webkitCancelAnimationFrame
        ? (cancelAnimationFrame = webkitCancelAnimationFrame)
        : "undefined" != typeof mozCancelAnimationFrame
        ? (cancelAnimationFrame = mozCancelAnimationFrame)
        : "undefined" != typeof msCancelAnimationFrame
        ? (cancelAnimationFrame = msCancelAnimationFrame)
        : void 0 === cancelAnimationFrame &&
          (cancelAnimationFrame = function (e) {
              clearTimeout(e);
          }));
var AudioContext = window.AudioContext;
void 0 === AudioContext && ("undefined" != typeof webkitAudioContext && (AudioContext = webkitAudioContext), "undefined" != typeof mozAudioContext && (AudioContext = mozAudioContext));
var URL = window.URL;
void 0 === URL && "undefined" != typeof webkitURL && (URL = webkitURL),
    "undefined" != typeof navigator &&
        void 0 === navigator.getUserMedia &&
        (void 0 !== navigator.webkitGetUserMedia && (navigator.getUserMedia = navigator.webkitGetUserMedia), void 0 !== navigator.mozGetUserMedia && (navigator.getUserMedia = navigator.mozGetUserMedia));
var isEdge = !(-1 === navigator.userAgent.indexOf("Edge") || (!navigator.msSaveBlob && !navigator.msSaveOrOpenBlob)),
    isOpera = !!window.opera || -1 !== navigator.userAgent.indexOf("OPR/"),
    isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1 && "netscape" in window && / rv:/.test(navigator.userAgent),
    isChrome = (!isOpera && !isEdge && !!navigator.webkitGetUserMedia) || isElectron() || -1 !== navigator.userAgent.toLowerCase().indexOf("chrome/"),
    isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
isSafari && !isChrome && -1 !== navigator.userAgent.indexOf("CriOS") && ((isSafari = !1), (isChrome = !0));
var MediaStream = window.MediaStream;
function bytesToSize(e) {
    if (0 === e) return "0 Bytes";
    var t = parseInt(Math.floor(Math.log(e) / Math.log(1e3)), 10);
    return (e / Math.pow(1e3, t)).toPrecision(3) + " " + ["Bytes", "KB", "MB", "GB", "TB"][t];
}
function invokeSaveAsDialog(e, t) {
    if (!e) throw "Blob object is required.";
    if (!e.type)
        try {
            e.type = "video/mp4";
        } catch (e) {}
    var i = (e.type || "video/mp4").split("/")[1];
    if ((-1 !== i.indexOf(";") && (i = i.split(";")[0]), t && -1 !== t.indexOf("."))) {
        var o = t.split(".");
        (t = o[0]), (i = o[1]);
    }
    var n = (t || Math.round(9999999999 * Math.random()) + 888888888) + "." + i;
    if (void 0 !== navigator.msSaveOrOpenBlob) return navigator.msSaveOrOpenBlob(e, n);
    if (void 0 !== navigator.msSaveBlob) return navigator.msSaveBlob(e, n);
    var r = document.createElement("a");
    (r.href = URL.createObjectURL(e)),
        (r.download = n),
        (r.style = "display:none;opacity:0;color:transparent;"),
        (document.body || document.documentElement).appendChild(r),
        "function" == typeof r.click ? r.click() : ((r.target = "_blank"), r.dispatchEvent(new MouseEvent("click", { view: window, bubbles: !0, cancelable: !0 }))),
        URL.revokeObjectURL(r.href);
}
function isElectron() {
    return (
        ("undefined" != typeof window && "object" == typeof window.process && "renderer" === window.process.type) ||
        !("undefined" == typeof process || "object" != typeof process.versions || !process.versions.electron) ||
        ("object" == typeof navigator && "string" == typeof navigator.userAgent && navigator.userAgent.indexOf("Electron") >= 0)
    );
}
function getTracks(e, t) {
    return e && e.getTracks
        ? e.getTracks().filter(function (e) {
              return e.kind === (t || "audio");
          })
        : [];
}
function setSrcObject(e, t) {
    "srcObject" in t ? (t.srcObject = e) : "mozSrcObject" in t ? (t.mozSrcObject = e) : (t.srcObject = e);
}
function getSeekableBlob(e, t) {
    if ("undefined" == typeof EBML) throw new Error("Please link: https://www.webrtc-experiment.com/EBML.js");
    var i = new EBML.Reader(),
        o = new EBML.Decoder(),
        n = EBML.tools,
        r = new FileReader();
    (r.onload = function (e) {
        o.decode(this.result).forEach(function (e) {
            i.read(e);
        }),
            i.stop();
        var r = n.makeMetadataSeekable(i.metadatas, i.duration, i.cues),
            s = this.result.slice(i.metadataSize),
            a = new Blob([r, s], { type: "video/mp4" });
        t(a);
    }),
        r.readAsArrayBuffer(e);
}
void 0 === MediaStream && "undefined" != typeof webkitMediaStream && (MediaStream = webkitMediaStream),
    void 0 !== MediaStream &&
        void 0 === MediaStream.prototype.stop &&
        (MediaStream.prototype.stop = function () {
            this.getTracks().forEach(function (e) {
                e.stop();
            });
        }),
    void 0 !== RecordRTC && ((RecordRTC.invokeSaveAsDialog = invokeSaveAsDialog), (RecordRTC.getTracks = getTracks), (RecordRTC.getSeekableBlob = getSeekableBlob), (RecordRTC.bytesToSize = bytesToSize), (RecordRTC.isElectron = isElectron));
/**
 * Storage is a standalone object used by {@link RecordRTC} to store reusable objects e.g. "new AudioContext".
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @example
 * Storage.AudioContext === webkitAudioContext
 * @property {webkitAudioContext} AudioContext - Keeps a reference to AudioContext object.
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 */
var Storage = {};
function isMediaRecorderCompatible() {
    if (isFirefox || isSafari || isEdge) return !0;
    navigator.appVersion;
    var e,
        t,
        i = navigator.userAgent,
        o = "" + parseFloat(navigator.appVersion),
        n = parseInt(navigator.appVersion, 10);
    return (
        (isChrome || isOpera) && ((e = i.indexOf("Chrome")), (o = i.substring(e + 7))),
        -1 !== (t = o.indexOf(";")) && (o = o.substring(0, t)),
        -1 !== (t = o.indexOf(" ")) && (o = o.substring(0, t)),
        (n = parseInt("" + o, 10)),
        isNaN(n) && ((o = "" + parseFloat(navigator.appVersion)), (n = parseInt(navigator.appVersion, 10))),
        n >= 49
    );
}
/**
 * MediaStreamRecorder is an abstraction layer for {@link https://w3c.github.io/mediacapture-record/MediaRecorder.html|MediaRecorder API}. It is used by {@link RecordRTC} to record MediaStream(s) in both Chrome and Firefox.
 * @summary Runs top over {@link https://w3c.github.io/mediacapture-record/MediaRecorder.html|MediaRecorder API}.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://github.com/muaz-khan|Muaz Khan}
 * @typedef MediaStreamRecorder
 * @class
 * @example
 * var config = {
 *     mimeType: 'video/webm', // vp8, vp9, h264, mkv, opus/vorbis
 *     audioBitsPerSecond : 256 * 8 * 1024,
 *     videoBitsPerSecond : 256 * 8 * 1024,
 *     bitsPerSecond: 256 * 8 * 1024,  // if this is provided, skip above two
 *     checkForInactiveTracks: true,
 *     timeSlice: 1000, // concatenate intervals based blobs
 *     ondataavailable: function() {} // get intervals based blobs
 * }
 * var recorder = new MediaStreamRecorder(mediaStream, config);
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 *
 *     // or
 *     var blob = recorder.blob;
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {disableLogs:true, initCallback: function, mimeType: "video/webm", timeSlice: 1000}
 * @throws Will throw an error if first argument "MediaStream" is missing. Also throws error if "MediaRecorder API" are not supported by the browser.
 */ 
function MediaStreamRecorder(e, t) {
    var i = this;
    if (void 0 === e) throw 'First argument "MediaStream" is required.';
    if ("undefined" == typeof MediaRecorder) throw "Your browser does not support the Media Recorder API. Please try other modules e.g. WhammyRecorder or StereoAudioRecorder.";
    if ("audio" === (t = t || { mimeType: "video/mp4" }).type) {
        var o;
        if (getTracks(e, "video").length && getTracks(e, "audio").length) navigator.mozGetUserMedia ? (o = new MediaStream()).addTrack(getTracks(e, "audio")[0]) : (o = new MediaStream(getTracks(e, "audio"))), (e = o);
        (t.mimeType && -1 !== t.mimeType.toString().toLowerCase().indexOf("audio")) || (t.mimeType = isChrome ? "audio/webm" : "audio/ogg"),
            t.mimeType && "audio/ogg" !== t.mimeType.toString().toLowerCase() && navigator.mozGetUserMedia && (t.mimeType = "audio/ogg");
    }
    var n,
        r = [];
    function s() {
        i.timestamps.push(new Date().getTime()), "function" == typeof t.onTimeStamp && t.onTimeStamp(i.timestamps[i.timestamps.length - 1], i.timestamps);
    }
    function a(e) {
        return n && n.mimeType ? n.mimeType : e.mimeType || "video/mp4";
    }
    function c() {
        (r = []), (n = null), (i.timestamps = []);
    }
    (this.getArrayOfBlobs = function () {
        return r;
    }),
        (this.record = function () {
            (i.blob = null), i.clearRecordedData(), (i.timestamps = []), (l = []), (r = []);
            var o = t;
            t.disableLogs || console.log("Passing following config over MediaRecorder API.", o),
                n && (n = null),
                isChrome && !isMediaRecorderCompatible() && (o = "video/vp8"),
                "function" == typeof MediaRecorder.isTypeSupported &&
                    o.mimeType &&
                    (MediaRecorder.isTypeSupported(o.mimeType) || (t.disableLogs || console.warn("MediaRecorder API seems unable to record mimeType:", o.mimeType), (o.mimeType = "audio" === t.type ? "audio/webm" : "video/mp4")));
            try {
                (n = new MediaRecorder(e, o)), (t.mimeType = o.mimeType);
            } catch (t) {
                n = new MediaRecorder(e);
            }
            o.mimeType && !MediaRecorder.isTypeSupported && "canRecordMimeType" in n && !1 === n.canRecordMimeType(o.mimeType) && (t.disableLogs || console.warn("MediaRecorder API seems unable to record mimeType:", o.mimeType)),
                (n.ondataavailable = function (e) {
                    if ((e.data && l.push("ondataavailable: " + bytesToSize(e.data.size)), "number" != typeof t.timeSlice))
                        !e.data || !e.data.size || e.data.size < 100 || i.blob
                            ? i.recordingCallback && (i.recordingCallback(new Blob([], { type: a(o) })), (i.recordingCallback = null))
                            : ((i.blob = t.getNativeBlob ? e.data : new Blob([e.data], { type: a(o) })), i.recordingCallback && (i.recordingCallback(i.blob), (i.recordingCallback = null)));
                    else if (e.data && e.data.size && (r.push(e.data), s(), "function" == typeof t.ondataavailable)) {
                        var n = t.getNativeBlob ? e.data : new Blob([e.data], { type: a(o) });
                        t.ondataavailable(n);
                    }
                }),
                (n.onstart = function () {
                    l.push("started");
                }),
                (n.onpause = function () {
                    l.push("paused");
                }),
                (n.onresume = function () {
                    l.push("resumed");
                }),
                (n.onstop = function () {
                    l.push("stopped");
                }),
                (n.onerror = function (e) {
                    e &&
                        (e.name || (e.name = "UnknownError"),
                        l.push("error: " + e),
                        t.disableLogs ||
                            (-1 !== e.name.toString().toLowerCase().indexOf("invalidstate")
                                ? console.error("The MediaRecorder is not in a state in which the proposed operation is allowed to be executed.", e)
                                : -1 !== e.name.toString().toLowerCase().indexOf("notsupported")
                                ? console.error("MIME type (", o.mimeType, ") is not supported.", e)
                                : -1 !== e.name.toString().toLowerCase().indexOf("security")
                                ? console.error("MediaRecorder security error", e)
                                : "OutOfMemory" === e.name
                                ? console.error("The UA has exhaused the available memory. User agents SHOULD provide as much additional information as possible in the message attribute.", e)
                                : "IllegalStreamModification" === e.name
                                ? console.error(
                                      "A modification to the stream has occurred that makes it impossible to continue recording. An example would be the addition of a Track while recording is occurring. User agents SHOULD provide as much additional information as possible in the message attribute.",
                                      e
                                  )
                                : "OtherRecordingError" === e.name
                                ? console.error("Used for an fatal error other than those listed above. User agents SHOULD provide as much additional information as possible in the message attribute.", e)
                                : "GenericError" === e.name
                                ? console.error("The UA cannot provide the codec or recording option that has been requested.", e)
                                : console.error("MediaRecorder Error", e)),
                        (function (e) {
                            if (!i.manuallyStopped && n && "inactive" === n.state) return delete t.timeslice, void n.start(6e5);
                            setTimeout(void 0, 1e3);
                        })(),
                        "inactive" !== n.state && "stopped" !== n.state && n.stop());
                }),
                "number" == typeof t.timeSlice ? (s(), n.start(t.timeSlice)) : n.start(36e5),
                t.initCallback && t.initCallback();
        }),
        (this.timestamps = []),
        (this.stop = function (e) {
            (e = e || function () {}),
                (i.manuallyStopped = !0),
                n &&
                    ((this.recordingCallback = e),
                    "recording" === n.state && n.stop(),
                    "number" == typeof t.timeSlice &&
                        setTimeout(function () {
                            (i.blob = new Blob(r, { type: a(t) })), i.recordingCallback(i.blob);
                        }, 100));
        }),
        (this.pause = function () {
            n && "recording" === n.state && n.pause();
        }),
        (this.resume = function () {
            n && "paused" === n.state && n.resume();
        }),
        (this.clearRecordedData = function () {
            n && "recording" === n.state && i.stop(c), c();
        }),
        (this.getInternalRecorder = function () {
            return n;
        }),
        (this.blob = null),
        (this.getState = function () {
            return (n && n.state) || "inactive";
        });
    var l = [];
    (this.getAllStates = function () {
        return l;
    }),
        void 0 === t.checkForInactiveTracks && (t.checkForInactiveTracks = !1);
    i = this;
    !(function o() {
        if (n && !1 !== t.checkForInactiveTracks)
            return !1 ===
                (function () {
                    if ("active" in e) {
                        if (!e.active) return !1;
                    } else if ("ended" in e && e.ended) return !1;
                    return !0;
                })()
                ? (t.disableLogs || console.log("MediaStream seems stopped."), void i.stop())
                : void setTimeout(o, 1e3);
    })(),
        (this.name = "MediaStreamRecorder"),
        (this.toString = function () {
            return this.name;
        });
}
/**
 * StereoAudioRecorder is a standalone class used by {@link RecordRTC} to bring "stereo" audio-recording in chrome.
 * @summary JavaScript standalone object for stereo audio recording.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef StereoAudioRecorder
 * @class
 * @example
 * var recorder = new StereoAudioRecorder(MediaStream, {
 *     sampleRate: 44100,
 *     bufferSize: 4096
 * });
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {sampleRate: 44100, bufferSize: 4096, numberOfAudioChannels: 1, etc.}
 */
function StereoAudioRecorder(e, t) {
    if (!getTracks(e, "audio").length) throw "Your stream has no audio tracks.";
    var i,
        o = this,
        n = [],
        r = [],
        s = !1,
        a = 0,
        c = 2,
        l = (t = t || {}).desiredSampRate;
    function d() {
        if (!1 === t.checkForInactiveTracks) return !0;
        if ("active" in e) {
            if (!e.active) return !1;
        } else if ("ended" in e && e.ended) return !1;
        return !0;
    }
    function h(e, t) {
        function i(e, t) {
            var i,
                o = e.numberOfAudioChannels,
                n = e.leftBuffers.slice(0),
                r = e.rightBuffers.slice(0),
                s = e.sampleRate,
                a = e.internalInterleavedLength,
                c = e.desiredSampRate;
            function l(e, t, i) {
                var o = Math.round(e.length * (t / i)),
                    n = [],
                    r = Number((e.length - 1) / (o - 1));
                n[0] = e[0];
                for (var s = 1; s < o - 1; s++) {
                    var a = s * r,
                        c = Number(Math.floor(a)).toFixed(),
                        l = Number(Math.ceil(a)).toFixed(),
                        h = a - c;
                    n[s] = d(e[c], e[l], h);
                }
                return (n[o - 1] = e[e.length - 1]), n;
            }
            function d(e, t, i) {
                return e + (t - e) * i;
            }
            function h(e, t) {
                for (var i = new Float64Array(t), o = 0, n = e.length, r = 0; r < n; r++) {
                    var s = e[r];
                    i.set(s, o), (o += s.length);
                }
                return i;
            }
            function u(e, t, i) {
                for (var o = i.length, n = 0; n < o; n++) e.setUint8(t + n, i.charCodeAt(n));
            }
            2 === o && ((n = h(n, a)), (r = h(r, a)), c && ((n = l(n, c, s)), (r = l(r, c, s)))),
                1 === o && ((n = h(n, a)), c && (n = l(n, c, s))),
                c && (s = c),
                2 === o &&
                    (i = (function (e, t) {
                        for (var i = e.length + t.length, o = new Float64Array(i), n = 0, r = 0; r < i; ) (o[r++] = e[n]), (o[r++] = t[n]), n++;
                        return o;
                    })(n, r)),
                1 === o && (i = n);
            var f = i.length,
                m = new ArrayBuffer(44 + 2 * f),
                g = new DataView(m);
            u(g, 0, "RIFF"),
                g.setUint32(4, 36 + 2 * f, !0),
                u(g, 8, "WAVE"),
                u(g, 12, "fmt "),
                g.setUint32(16, 16, !0),
                g.setUint16(20, 1, !0),
                g.setUint16(22, o, !0),
                g.setUint32(24, s, !0),
                g.setUint32(28, s * o * 2, !0),
                g.setUint16(32, 2 * o, !0),
                g.setUint16(34, 16, !0),
                u(g, 36, "data"),
                g.setUint32(40, 2 * f, !0);
            for (var p = f, v = 44, b = 0; b < p; b++) g.setInt16(v, 32767 * i[b], !0), (v += 2);
            if (t) return t({ buffer: m, view: g });
            postMessage({ buffer: m, view: g });
        }
        if (e.noWorker)
            i(e, function (e) {
                t(e.buffer, e.view);
            });
        else {
            var o,
                n,
                r,
                s = ((o = i), (n = URL.createObjectURL(new Blob([o.toString(), ";this.onmessage =  function (eee) {" + o.name + "(eee.data);}"], { type: "application/javascript" }))), ((r = new Worker(n)).workerURL = n), r);
            (s.onmessage = function (e) {
                t(e.data.buffer, e.data.view), URL.revokeObjectURL(s.workerURL), s.terminate();
            }),
                s.postMessage(e);
        }
    }
    !0 === t.leftChannel && (c = 1),
        1 === t.numberOfAudioChannels && (c = 1),
        (!c || c < 1) && (c = 2),
        t.disableLogs || console.log("StereoAudioRecorder is set to record number of channels: " + c),
        void 0 === t.checkForInactiveTracks && (t.checkForInactiveTracks = !0),
        (this.record = function () {
            if (!1 === d()) throw "Please make sure MediaStream is active.";
            b(), (S = v = !1), (s = !0), void 0 !== t.timeSlice && _();
        }),
        (this.stop = function (e) {
            (e = e || function () {}),
                (s = !1),
                h({ desiredSampRate: l, sampleRate: p, numberOfAudioChannels: c, internalInterleavedLength: a, leftBuffers: n, rightBuffers: 1 === c ? [] : r, noWorker: t.noWorker }, function (t, i) {
                    (o.blob = new Blob([i], { type: "audio/wav" })), (o.buffer = new ArrayBuffer(i.buffer.byteLength)), (o.view = i), (o.sampleRate = l || p), (o.bufferSize = g), (o.length = a), (S = !1), e && e(o.blob);
                });
        }),
        void 0 === RecordRTC.Storage && (RecordRTC.Storage = { AudioContextConstructor: null, AudioContext: window.AudioContext || window.webkitAudioContext }),
        (RecordRTC.Storage.AudioContextConstructor && "closed" !== RecordRTC.Storage.AudioContextConstructor.state) || (RecordRTC.Storage.AudioContextConstructor = new RecordRTC.Storage.AudioContext());
    var u = RecordRTC.Storage.AudioContextConstructor,
        f = u.createMediaStreamSource(e),
        m = [0, 256, 512, 1024, 2048, 4096, 8192, 16384],
        g = void 0 === t.bufferSize ? 4096 : t.bufferSize;
    if ((-1 === m.indexOf(g) && (t.disableLogs || console.log("Legal values for buffer-size are " + JSON.stringify(m, null, "\t"))), u.createJavaScriptNode)) i = u.createJavaScriptNode(g, c, c);
    else {
        if (!u.createScriptProcessor) throw "WebAudio API has no support on this browser.";
        i = u.createScriptProcessor(g, c, c);
    }
    f.connect(i), t.bufferSize || (g = i.bufferSize);
    var p = void 0 !== t.sampleRate ? t.sampleRate : u.sampleRate || 44100;
    (p < 22050 || p > 96e3) && (t.disableLogs || console.log("sample-rate must be under range 22050 and 96000.")), t.disableLogs || (t.desiredSampRate && console.log("Desired sample-rate: " + t.desiredSampRate));
    var v = !1;
    function b() {
        (n = []),
            (r = []),
            (a = 0),
            (S = !1),
            (s = !1),
            (v = !1),
            (u = null),
            (o.leftchannel = n),
            (o.rightchannel = r),
            (o.numberOfAudioChannels = c),
            (o.desiredSampRate = l),
            (o.sampleRate = p),
            (o.recordingLength = a),
            (w = { left: [], right: [], recordingLength: 0 });
    }
    function y() {
        i && ((i.onaudioprocess = null), i.disconnect(), (i = null)), f && (f.disconnect(), (f = null)), b();
    }
    (this.pause = function () {
        v = !0;
    }),
        (this.resume = function () {
            if (!1 === d()) throw "Please make sure MediaStream is active.";
            if (!s) return t.disableLogs || console.log("Seems recording has been restarted."), void this.record();
            v = !1;
        }),
        (this.clearRecordedData = function () {
            (t.checkForInactiveTracks = !1), s && this.stop(y), y();
        }),
        (this.name = "StereoAudioRecorder"),
        (this.toString = function () {
            return this.name;
        });
    var S = !1;
    (i.onaudioprocess = function (e) {
        if (!v)
            if ((!1 === d() && (t.disableLogs || console.log("MediaStream seems stopped."), i.disconnect(), (s = !1)), s)) {
                S || ((S = !0), t.onAudioProcessStarted && t.onAudioProcessStarted(), t.initCallback && t.initCallback());
                var l = e.inputBuffer.getChannelData(0),
                    h = new Float32Array(l);
                if ((n.push(h), 2 === c)) {
                    var u = e.inputBuffer.getChannelData(1),
                        m = new Float32Array(u);
                    r.push(m);
                }
                (a += g), (o.recordingLength = a), void 0 !== t.timeSlice && ((w.recordingLength += g), w.left.push(h), 2 === c && w.right.push(m));
            } else f && (f.disconnect(), (f = null));
    }),
        u.createMediaStreamDestination ? i.connect(u.createMediaStreamDestination()) : i.connect(u.destination),
        (this.leftchannel = n),
        (this.rightchannel = r),
        (this.numberOfAudioChannels = c),
        (this.desiredSampRate = l),
        (this.sampleRate = p),
        (o.recordingLength = a);
    var w = { left: [], right: [], recordingLength: 0 };
    function _() {
        s &&
            "function" == typeof t.ondataavailable &&
            void 0 !== t.timeSlice &&
            (w.left.length
                ? (h({ desiredSampRate: l, sampleRate: p, numberOfAudioChannels: c, internalInterleavedLength: w.recordingLength, leftBuffers: w.left, rightBuffers: 1 === c ? [] : w.right }, function (e, i) {
                      var o = new Blob([i], { type: "audio/wav" });
                      t.ondataavailable(o), setTimeout(_, t.timeSlice);
                  }),
                  (w = { left: [], right: [], recordingLength: 0 }))
                : setTimeout(_, t.timeSlice));
    }
}
/**
 * CanvasRecorder is a standalone class used by {@link RecordRTC} to bring HTML5-Canvas recording into video WebM. It uses HTML2Canvas library and runs top over {@link Whammy}.
 * @summary HTML2Canvas recording into video WebM.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef CanvasRecorder
 * @class
 * @example
 * var recorder = new CanvasRecorder(htmlElement, { disableLogs: true, useWhammyRecorder: true });
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {HTMLElement} htmlElement - querySelector/getElementById/getElementsByTagName[0]/etc.
 * @param {object} config - {disableLogs:true, initCallback: function}
 */
function CanvasRecorder(e, t) {
    if ("undefined" == typeof html2canvas) throw "Please link: https://www.webrtc-experiment.com/screenshot.js";
    (t = t || {}).frameInterval || (t.frameInterval = 10);
    var i = !1;
    ["captureStream", "mozCaptureStream", "webkitCaptureStream"].forEach(function (e) {
        e in document.createElement("canvas") && (i = !0);
    });
    var o,
        n,
        r,
        s = !((!window.webkitRTCPeerConnection && !window.webkitGetUserMedia) || !window.chrome),
        a = 50,
        c = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
    if ((s && c && c[2] && (a = parseInt(c[2], 10)), s && a < 52 && (i = !1), t.useWhammyRecorder && (i = !1), i))
        if ((t.disableLogs || console.log("Your browser supports both MediRecorder API and canvas.captureStream!"), e instanceof HTMLCanvasElement)) o = e;
        else {
            if (!(e instanceof CanvasRenderingContext2D)) throw "Please pass either HTMLCanvasElement or CanvasRenderingContext2D.";
            o = e.canvas;
        }
    else navigator.mozGetUserMedia && (t.disableLogs || console.error("Canvas recording is NOT supported in Firefox."));
    (this.record = function () {
        if (((r = !0), i && !t.useWhammyRecorder)) {
            var e;
            "captureStream" in o ? (e = o.captureStream(25)) : "mozCaptureStream" in o ? (e = o.mozCaptureStream(25)) : "webkitCaptureStream" in o && (e = o.webkitCaptureStream(25));
            try {
                var s = new MediaStream();
                s.addTrack(getTracks(e, "video")[0]), (e = s);
            } catch (e) {}
            if (!e) throw "captureStream API are NOT available.";
            (n = new MediaStreamRecorder(e, { mimeType: t.mimeType || "video/mp4" })).record();
        } else (f.frames = []), (u = new Date().getTime()), h();
        t.initCallback && t.initCallback();
    }),
        (this.getWebPImages = function (i) {
            if ("canvas" === e.nodeName.toLowerCase()) {
                var o = f.frames.length;
                f.frames.forEach(function (e, i) {
                    var n = o - i;
                    t.disableLogs || console.log(n + "/" + o + " frames remaining"), t.onEncodingCallback && t.onEncodingCallback(n, o);
                    var r = e.image.toDataURL("image/webp", 1);
                    f.frames[i].image = r;
                }),
                    t.disableLogs || console.log("Generating WebM"),
                    i();
            } else i();
        }),
        (this.stop = function (e) {
            r = !1;
            var o = this;
            i && n
                ? n.stop(e)
                : this.getWebPImages(function () {
                      f.compile(function (i) {
                          t.disableLogs || console.log("Recording finished!"), (o.blob = i), o.blob.forEach && (o.blob = new Blob([], { type: "video/mp4" })), e && e(o.blob), (f.frames = []);
                      });
                  });
        });
    var l = !1;
    function d() {
        (f.frames = []), (r = !1), (l = !1);
    }
    function h() {
        if (l) return (u = new Date().getTime()), setTimeout(h, 500);
        if ("canvas" === e.nodeName.toLowerCase()) {
            var i = new Date().getTime() - u;
            return (
                (u = new Date().getTime()),
                f.frames.push({ image: ((o = document.createElement("canvas")), (n = o.getContext("2d")), (o.width = e.width), (o.height = e.height), n.drawImage(e, 0, 0), o), duration: i }),
                void (r && setTimeout(h, t.frameInterval))
            );
        }
        var o, n;
        html2canvas(e, {
            grabMouse: void 0 === t.showMousePointer || t.showMousePointer,
            onrendered: function (e) {
                var i = new Date().getTime() - u;
                if (!i) return setTimeout(h, t.frameInterval);
                (u = new Date().getTime()), f.frames.push({ image: e.toDataURL("image/webp", 1), duration: i }), r && setTimeout(h, t.frameInterval);
            },
        });
    }
    (this.pause = function () {
        (l = !0), n instanceof MediaStreamRecorder && n.pause();
    }),
        (this.resume = function () {
            (l = !1), n instanceof MediaStreamRecorder ? n.resume() : r || this.record();
        }),
        (this.clearRecordedData = function () {
            r && this.stop(d), d();
        }),
        (this.name = "CanvasRecorder"),
        (this.toString = function () {
            return this.name;
        });
    var u = new Date().getTime(),
        f = new Whammy.Video(100);
}
/**
 * WhammyRecorder is a standalone class used by {@link RecordRTC} to bring video recording in Chrome. It runs top over {@link Whammy}.
 * @summary Video recording feature in Chrome.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef WhammyRecorder
 * @class
 * @example
 * var recorder = new WhammyRecorder(mediaStream);
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {disableLogs: true, initCallback: function, video: HTMLVideoElement, etc.}
 */
function WhammyRecorder(e, t) {
    function i(e) {
        e = void 0 !== e ? e : 10;
        var t = new Date().getTime() - c;
        return t
            ? r
                ? ((c = new Date().getTime()), setTimeout(i, 100))
                : ((c = new Date().getTime()), a.paused && a.play(), h.drawImage(a, 0, 0, d.width, d.height), l.frames.push({ duration: t, image: d.toDataURL("image/webp") }), void (n || setTimeout(i, e, e)))
            : setTimeout(i, e, e);
    }
    function o(e, t, i, o, n) {
        var r = document.createElement("canvas");
        (r.width = d.width), (r.height = d.height);
        var s,
            a,
            c,
            l = r.getContext("2d"),
            h = [],
            u = -1 === t,
            f = t && t > 0 && t <= e.length ? t : e.length,
            m = 0,
            g = 0,
            p = 0,
            v = Math.sqrt(Math.pow(255, 2) + Math.pow(255, 2) + Math.pow(255, 2)),
            b = i && i >= 0 && i <= 1 ? i : 0,
            y = o && o >= 0 && o <= 1 ? o : 0,
            S = !1;
        (s = {
            length: f,
            functionToLoop: function (t, i) {
                var o,
                    n,
                    r,
                    s = function () {
                        (!S && r - o <= r * y) || (u && (S = !0), h.push(e[i])), t();
                    };
                if (S) s();
                else {
                    var a = new Image();
                    (a.onload = function () {
                        l.drawImage(a, 0, 0, d.width, d.height);
                        var e = l.getImageData(0, 0, d.width, d.height);
                        (o = 0), (n = e.data.length), (r = e.data.length / 4);
                        for (var t = 0; t < n; t += 4) {
                            var i = { r: e.data[t], g: e.data[t + 1], b: e.data[t + 2] };
                            Math.sqrt(Math.pow(i.r - m, 2) + Math.pow(i.g - g, 2) + Math.pow(i.b - p, 2)) <= v * b && o++;
                        }
                        s();
                    }),
                        (a.src = e[i].image);
                }
            },
            callback: function () {
                (h = h.concat(e.slice(f))).length <= 0 && h.push(e[e.length - 1]), n(h);
            },
        }),
            (a = -1),
            (c = s.length),
            (function e() {
                ++a !== c
                    ? setTimeout(function () {
                          s.functionToLoop(e, a);
                      }, 1)
                    : s.callback();
            })();
    }
    (t = t || {}).frameInterval || (t.frameInterval = 10),
        t.disableLogs || console.log("Using frames-interval:", t.frameInterval),
        (this.record = function () {
            t.width || (t.width = 320),
                t.height || (t.height = 240),
                t.video || (t.video = { width: t.width, height: t.height }),
                t.canvas || (t.canvas = { width: t.width, height: t.height }),
                (d.width = t.canvas.width || 320),
                (d.height = t.canvas.height || 240),
                (h = d.getContext("2d")),
                t.video && t.video instanceof HTMLVideoElement
                    ? ((a = t.video.cloneNode()), t.initCallback && t.initCallback())
                    : ((a = document.createElement("video")),
                      setSrcObject(e, a),
                      (a.onloadedmetadata = function () {
                          t.initCallback && t.initCallback();
                      }),
                      (a.width = t.video.width),
                      (a.height = t.video.height)),
                (a.muted = !0),
                a.play(),
                (c = new Date().getTime()),
                (l = new Whammy.Video()),
                t.disableLogs || (console.log("canvas resolutions", d.width, "*", d.height), console.log("video width/height", a.width || d.width, "*", a.height || d.height)),
                i(t.frameInterval);
        });
    var n = !1;
    this.stop = function (e) {
        (e = e || function () {}), (n = !0);
        var i = this;
        setTimeout(function () {
            o(l.frames, -1, null, null, function (o) {
                (l.frames = o),
                    t.advertisement && t.advertisement.length && (l.frames = t.advertisement.concat(l.frames)),
                    l.compile(function (t) {
                        (i.blob = t), i.blob.forEach && (i.blob = new Blob([], { type: "video/mp4" })), e && e(i.blob);
                    });
            });
        }, 10);
    };
    var r = !1;
    function s() {
        (l.frames = []), (n = !0), (r = !1);
    }
    (this.pause = function () {
        r = !0;
    }),
        (this.resume = function () {
            (r = !1), n && this.record();
        }),
        (this.clearRecordedData = function () {
            n || this.stop(s), s();
        }),
        (this.name = "WhammyRecorder"),
        (this.toString = function () {
            return this.name;
        });
    var a,
        c,
        l,
        d = document.createElement("canvas"),
        h = d.getContext("2d");
}
void 0 !== AudioContext ? (Storage.AudioContext = AudioContext) : "undefined" != typeof webkitAudioContext && (Storage.AudioContext = webkitAudioContext),
    void 0 !== RecordRTC && (RecordRTC.Storage = Storage),
    void 0 !== RecordRTC && (RecordRTC.MediaStreamRecorder = MediaStreamRecorder),
    void 0 !== RecordRTC && (RecordRTC.StereoAudioRecorder = StereoAudioRecorder),
    void 0 !== RecordRTC && (RecordRTC.CanvasRecorder = CanvasRecorder),
    void 0 !== RecordRTC && (RecordRTC.WhammyRecorder = WhammyRecorder);
/**
 * Whammy is a standalone class used by {@link RecordRTC} to bring video recording in Chrome. It is written by {@link https://github.com/antimatter15|antimatter15}
 * @summary A real time javascript webm encoder based on a canvas hack.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef Whammy
 * @class
 * @example
 * var recorder = new Whammy().Video(15);
 * recorder.add(context || canvas || dataURL);
 * var output = recorder.compile();
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 */
var Whammy = (function () {
    function e(e) {
        (this.frames = []), (this.duration = e || 1), (this.quality = 0.8);
    }
    function t(e) {
        function t(e, t, i) {
            return [{ data: e, id: 231 }].concat(
                i.map(function (e) {
                    var i = (function (e) {
                        var t = 0;
                        e.keyframe && (t |= 128);
                        e.invisible && (t |= 8);
                        e.lacing && (t |= e.lacing << 1);
                        e.discardable && (t |= 1);
                        if (e.trackNum > 127) throw "TrackNumber > 127 not supported";
                        return (
                            [128 | e.trackNum, e.timecode >> 8, 255 & e.timecode, t]
                                .map(function (e) {
                                    return String.fromCharCode(e);
                                })
                                .join("") + e.frame
                        );
                    })({ discardable: 0, frame: e.data.slice(4), invisible: 0, keyframe: 1, lacing: 0, trackNum: 1, timecode: Math.round(t) });
                    return (t += e.duration), { data: i, id: 163 };
                })
            );
        }
        function i(e) {
            for (var t = []; e > 0; ) t.push(255 & e), (e >>= 8);
            return new Uint8Array(t.reverse());
        }
        function o(e) {
            var t = [];
            e = (e.length % 8 ? new Array(9 - (e.length % 8)).join("0") : "") + e;
            for (var i = 0; i < e.length; i += 8) t.push(parseInt(e.substr(i, 8), 2));
            return new Uint8Array(t);
        }
        function n(e) {
            for (var t = [], r = 0; r < e.length; r++) {
                var s = e[r].data;
                "object" == typeof s && (s = n(s)),
                    "number" == typeof s && (s = o(s.toString(2))),
                    "string" == typeof s &&
                        (s = new Uint8Array(
                            s.split("").map(function (e) {
                                return e.charCodeAt(0);
                            })
                        ));
                var a = s.size || s.byteLength || s.length,
                    c = Math.ceil(Math.ceil(Math.log(a) / Math.log(2)) / 8),
                    l = a.toString(2),
                    d = new Array(7 * c + 7 + 1 - l.length).join("0") + l,
                    h = new Array(c).join("0") + "1" + d;
                t.push(i(e[r].id)), t.push(o(h)), t.push(s);
            }
            return new Blob(t, { type: "video/mp4" });
        }
        function r(e, t) {
            return parseInt(
                e
                    .substr(t + 4, 4)
                    .split("")
                    .map(function (e) {
                        var t = e.charCodeAt(0).toString(2);
                        return new Array(8 - t.length + 1).join("0") + t;
                    })
                    .join(""),
                2
            );
        }
        function s(e) {
            for (var t = 0, i = {}; t < e.length; ) {
                var o = e.substr(t, 4),
                    n = r(e, t),
                    a = e.substr(t + 4 + 4, n);
                (t += 8 + n), (i[o] = i[o] || []), "RIFF" === o || "LIST" === o ? i[o].push(s(a)) : i[o].push(a);
            }
            return i;
        }
        var a = new (function (e) {
            var i = (function (e) {
                if (!e[0]) return void postMessage({ error: "Something went wrong. Maybe WebP format is not supported in the current browser." });
                for (var t = e[0].width, i = e[0].height, o = e[0].duration, n = 1; n < e.length; n++) o += e[n].duration;
                return { duration: o, width: t, height: i };
            })(e);
            if (!i) return [];
            for (
                var o,
                    r = [
                        {
                            id: 440786851,
                            data: [
                                { data: 1, id: 17030 },
                                { data: 1, id: 17143 },
                                { data: 4, id: 17138 },
                                { data: 8, id: 17139 },
                                { data: "webm", id: 17026 },
                                { data: 2, id: 17031 },
                                { data: 2, id: 17029 },
                            ],
                        },
                        {
                            id: 408125543,
                            data: [
                                {
                                    id: 357149030,
                                    data: [
                                        { data: 1e6, id: 2807729 },
                                        { data: "whammy", id: 19840 },
                                        { data: "whammy", id: 22337 },
                                        {
                                            data:
                                                ((o = i.duration),
                                                [].slice
                                                    .call(new Uint8Array(new Float64Array([o]).buffer), 0)
                                                    .map(function (e) {
                                                        return String.fromCharCode(e);
                                                    })
                                                    .reverse()
                                                    .join("")),
                                            id: 17545,
                                        },
                                    ],
                                },
                                {
                                    id: 374648427,
                                    data: [
                                        {
                                            id: 174,
                                            data: [
                                                { data: 1, id: 215 },
                                                { data: 1, id: 29637 },
                                                { data: 0, id: 156 },
                                                { data: "und", id: 2274716 },
                                                { data: "V_VP8", id: 134 },
                                                { data: "VP8", id: 2459272 },
                                                { data: 1, id: 131 },
                                                {
                                                    id: 224,
                                                    data: [
                                                        { data: i.width, id: 176 },
                                                        { data: i.height, id: 186 },
                                                    ],
                                                },
                                            ],
                                        },
                                    ],
                                },
                            ],
                        },
                    ],
                    s = 0,
                    a = 0;
                s < e.length;

            ) {
                var c = [],
                    l = 0;
                do {
                    c.push(e[s]), (l += e[s].duration), s++;
                } while (s < e.length && l < 3e4);
                var d = { id: 524531317, data: t(a, 0, c) };
                r[1].data.push(d), (a += l);
            }
            return n(r);
        })(
            e.map(function (e) {
                var t = (function (e) {
                    for (var t = e.RIFF[0].WEBP[0], i = t.indexOf("*"), o = 0, n = []; o < 4; o++) n[o] = t.charCodeAt(i + 3 + o);
                    return { width: 16383 & ((n[1] << 8) | n[0]), height: 16383 & ((n[3] << 8) | n[2]), data: t, riff: e };
                })(s(atob(e.image.slice(23))));
                return (t.duration = e.duration), t;
            })
        );
        postMessage(a);
    }
    return (
        (e.prototype.add = function (e, t) {
            if (("canvas" in e && (e = e.canvas), "toDataURL" in e && (e = e.toDataURL("image/webp", this.quality)), !/^data:image\/webp;base64,/gi.test(e)))
                throw "Input must be formatted properly as a base64 encoded DataURI of type image/webp";
            this.frames.push({ image: e, duration: t || this.duration });
        }),
        (e.prototype.compile = function (e) {
            var i,
                o,
                n,
                r = ((i = t), (o = URL.createObjectURL(new Blob([i.toString(), "this.onmessage =  function (eee) {" + i.name + "(eee.data);}"], { type: "application/javascript" }))), (n = new Worker(o)), URL.revokeObjectURL(o), n);
            (r.onmessage = function (t) {
                t.data.error ? console.error(t.data.error) : e(t.data);
            }),
                r.postMessage(this.frames);
        }),
        { Video: e }
    );
})();
void 0 !== RecordRTC && (RecordRTC.Whammy = Whammy);
/**
 * DiskStorage is a standalone object used by {@link RecordRTC} to store recorded blobs in IndexedDB storage.
 * @summary Writing blobs into IndexedDB.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @example
 * DiskStorage.Store({
 *     audioBlob: yourAudioBlob,
 *     videoBlob: yourVideoBlob,
 *     gifBlob  : yourGifBlob
 * });
 * DiskStorage.Fetch(function(dataURL, type) {
 *     if(type === 'audioBlob') { }
 *     if(type === 'videoBlob') { }
 *     if(type === 'gifBlob')   { }
 * });
 * // DiskStorage.dataStoreName = 'recordRTC';
 * // DiskStorage.onError = function(error) { };
 * @property {function} init - This method must be called once to initialize IndexedDB ObjectStore. Though, it is auto-used internally.
 * @property {function} Fetch - This method fetches stored blobs from IndexedDB.
 * @property {function} Store - This method stores blobs in IndexedDB.
 * @property {function} onError - This function is invoked for any known/unknown error.
 * @property {string} dataStoreName - Name of the ObjectStore created in IndexedDB storage.
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 */ var DiskStorage = {
    init: function () {
        var e = this;
        if ("undefined" != typeof indexedDB && void 0 !== indexedDB.open) {
            var t,
                i = this.dbName || location.href.replace(/\/|:|#|%|\.|\[|\]/g, ""),
                o = indexedDB.open(i, 1);
            (o.onerror = e.onError),
                (o.onsuccess = function () {
                    (((t = o.result).onerror = e.onError), t.setVersion)
                        ? 1 !== t.version
                            ? (t.setVersion(1).onsuccess = function () {
                                  n(t), r();
                              })
                            : r()
                        : r();
                }),
                (o.onupgradeneeded = function (e) {
                    n(e.target.result);
                });
        } else console.error("IndexedDB API are not available in this browser.");
        function n(t) {
            t.createObjectStore(e.dataStoreName);
        }
        function r() {
            var i = t.transaction([e.dataStoreName], "readwrite");
            function o(t) {
                i.objectStore(e.dataStoreName).get(t).onsuccess = function (i) {
                    e.callback && e.callback(i.target.result, t);
                };
            }
            e.videoBlob && i.objectStore(e.dataStoreName).put(e.videoBlob, "videoBlob"),
                e.gifBlob && i.objectStore(e.dataStoreName).put(e.gifBlob, "gifBlob"),
                e.audioBlob && i.objectStore(e.dataStoreName).put(e.audioBlob, "audioBlob"),
                o("audioBlob"),
                o("videoBlob"),
                o("gifBlob");
        }
    },
    Fetch: function (e) {
        return (this.callback = e), this.init(), this;
    },
    Store: function (e) {
        return (this.audioBlob = e.audioBlob), (this.videoBlob = e.videoBlob), (this.gifBlob = e.gifBlob), this.init(), this;
    },
    onError: function (e) {
        console.error(JSON.stringify(e, null, "\t"));
    },
    dataStoreName: "recordRTC",
    dbName: null,
};
/**
 * GifRecorder is standalone calss used by {@link RecordRTC} to record video or canvas into animated gif.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef GifRecorder
 * @class
 * @example
 * var recorder = new GifRecorder(mediaStream || canvas || context, { onGifPreview: function, onGifRecordingStarted: function, width: 1280, height: 720, frameRate: 200, quality: 10 });
 * recorder.record();
 * recorder.stop(function(blob) {
 *     img.src = URL.createObjectURL(blob);
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object or HTMLCanvasElement or CanvasRenderingContext2D.
 * @param {object} config - {disableLogs:true, initCallback: function, width: 320, height: 240, frameRate: 200, quality: 10}
 */
function GifRecorder(e, t) {
    if ("undefined" == typeof GIFEncoder) {
        var i = document.createElement("script");
        (i.src = "https://www.webrtc-experiment.com/gif-recorder.js"), (document.body || document.documentElement).appendChild(i);
    }
    t = t || {};
    var o = e instanceof CanvasRenderingContext2D || e instanceof HTMLCanvasElement;
    (this.record = function () {
        "undefined" != typeof GIFEncoder && a
            ? (o ||
                  (t.width || (t.width = c.offsetWidth || 320),
                  t.height || (t.height = c.offsetHeight || 240),
                  t.video || (t.video = { width: t.width, height: t.height }),
                  t.canvas || (t.canvas = { width: t.width, height: t.height }),
                  (r.width = t.canvas.width || 320),
                  (r.height = t.canvas.height || 240),
                  (c.width = t.video.width || 320),
                  (c.height = t.video.height || 240)),
              (d = new GIFEncoder()).setRepeat(0),
              d.setDelay(t.frameRate || 200),
              d.setQuality(t.quality || 10),
              d.start(),
              "function" == typeof t.onGifRecordingStarted && t.onGifRecordingStarted(),
              Date.now(),
              (h = requestAnimationFrame(function e(i) {
                  if (!0 !== u.clearedRecordedData) {
                      if (n)
                          return setTimeout(function () {
                              e(i);
                          }, 100);
                      (h = requestAnimationFrame(e)),
                          void 0 === typeof l && (l = i),
                          i - l < 90 || (!o && c.paused && c.play(), o || s.drawImage(c, 0, 0, r.width, r.height), t.onGifPreview && t.onGifPreview(r.toDataURL("image/png")), d.addFrame(s), (l = i));
                  }
              })),
              t.initCallback && t.initCallback())
            : setTimeout(u.record, 1e3);
    }),
        (this.stop = function (e) {
            (e = e || function () {}), h && cancelAnimationFrame(h), Date.now(), (this.blob = new Blob([new Uint8Array(d.stream().bin)], { type: "image/gif" })), e(this.blob), (d.stream().bin = []);
        });
    var n = !1;
    (this.pause = function () {
        n = !0;
    }),
        (this.resume = function () {
            n = !1;
        }),
        (this.clearRecordedData = function () {
            (u.clearedRecordedData = !0), d && (d.stream().bin = []);
        }),
        (this.name = "GifRecorder"),
        (this.toString = function () {
            return this.name;
        });
    var r = document.createElement("canvas"),
        s = r.getContext("2d");
    o && (e instanceof CanvasRenderingContext2D ? (r = (s = e).canvas) : e instanceof HTMLCanvasElement && ((s = e.getContext("2d")), (r = e)));
    var a = !0;
    if (!o) {
        var c = document.createElement("video");
        (c.muted = !0),
            (c.autoplay = !0),
            (c.playsInline = !0),
            (a = !1),
            (c.onloadedmetadata = function () {
                a = !0;
            }),
            setSrcObject(e, c),
            c.play();
    }
    var l,
        d,
        h = null,
        u = this;
}
function MultiStreamsMixer(e, t) {
    var i;
    (i = "undefined" != typeof global ? global : null),
        void 0 === RecordRTC &&
            i &&
            "undefined" == typeof window &&
            "undefined" != typeof global &&
            ((global.navigator = { userAgent: "Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45", getUserMedia: function () {} }),
            global.console || (global.console = {}),
            (void 0 !== global.console.log && void 0 !== global.console.error) ||
                (global.console.error = global.console.log =
                    global.console.log ||
                    function () {
                        console.log(arguments);
                    }),
            "undefined" == typeof document &&
                ((i.document = {
                    documentElement: {
                        appendChild: function () {
                            return "";
                        },
                    },
                }),
                (document.createElement = document.captureStream = document.mozCaptureStream = function () {
                    var e = {
                        getContext: function () {
                            return e;
                        },
                        play: function () {},
                        pause: function () {},
                        drawImage: function () {},
                        toDataURL: function () {
                            return "";
                        },
                        style: {},
                    };
                    return e;
                }),
                (i.HTMLVideoElement = function () {})),
            "undefined" == typeof location && (i.location = { protocol: "file:", href: "", hash: "" }),
            "undefined" == typeof screen && (i.screen = { width: 0, height: 0 }),
            void 0 === l &&
                (i.URL = {
                    createObjectURL: function () {
                        return "";
                    },
                    revokeObjectURL: function () {
                        return "";
                    },
                }),
            (i.window = global)),
        (t = t || "multi-streams-mixer");
    var o = [],
        n = !1,
        r = document.createElement("canvas"),
        s = r.getContext("2d");
    (r.style.opacity = 0),
        (r.style.position = "absolute"),
        (r.style.zIndex = -1),
        (r.style.top = "-1000em"),
        (r.style.left = "-1000em"),
        (r.className = t),
        (document.body || document.documentElement).appendChild(r),
        (this.disableLogs = !1),
        (this.frameInterval = 10),
        (this.width = 360),
        (this.height = 240),
        (this.useGainNode = !0);
    var a = this,
        c = window.AudioContext;
    void 0 === c && ("undefined" != typeof webkitAudioContext && (c = webkitAudioContext), "undefined" != typeof mozAudioContext && (c = mozAudioContext));
    var l = window.URL;
    void 0 === l && "undefined" != typeof webkitURL && (l = webkitURL),
        "undefined" != typeof navigator &&
            void 0 === navigator.getUserMedia &&
            (void 0 !== navigator.webkitGetUserMedia && (navigator.getUserMedia = navigator.webkitGetUserMedia), void 0 !== navigator.mozGetUserMedia && (navigator.getUserMedia = navigator.mozGetUserMedia));
    var d = window.MediaStream;
    void 0 === d && "undefined" != typeof webkitMediaStream && (d = webkitMediaStream),
        void 0 !== d &&
            void 0 === d.prototype.stop &&
            (d.prototype.stop = function () {
                this.getTracks().forEach(function (e) {
                    e.stop();
                });
            });
    var h = {};
    function u() {
        if (!n) {
            var e = o.length,
                t = !1,
                i = [];
            if (
                (o.forEach(function (e) {
                    e.stream || (e.stream = {}), e.stream.fullcanvas ? (t = e) : i.push(e);
                }),
                t)
            )
                (r.width = t.stream.width), (r.height = t.stream.height);
            else if (i.length) {
                r.width = e > 1 ? 2 * i[0].width : i[0].width;
                var s = 1;
                (3 !== e && 4 !== e) || (s = 2), (5 !== e && 6 !== e) || (s = 3), (7 !== e && 8 !== e) || (s = 4), (9 !== e && 10 !== e) || (s = 5), (r.height = i[0].height * s);
            } else (r.width = a.width || 360), (r.height = a.height || 240);
            t && t instanceof HTMLVideoElement && f(t),
                i.forEach(function (e, t) {
                    f(e, t);
                }),
                setTimeout(u, a.frameInterval);
        }
    }
    function f(e, t) {
        if (!n) {
            var i = 0,
                o = 0,
                r = e.width,
                a = e.height;
            1 === t && (i = e.width),
                2 === t && (o = e.height),
                3 === t && ((i = e.width), (o = e.height)),
                4 === t && (o = 2 * e.height),
                5 === t && ((i = e.width), (o = 2 * e.height)),
                6 === t && (o = 3 * e.height),
                7 === t && ((i = e.width), (o = 3 * e.height)),
                0 !== t && void 0 !== e.stream.left && (i = e.stream.left),
                void 0 !== e.stream.top && (o = e.stream.top),
                void 0 !== e.stream.width && (r = e.stream.width),
                void 0 !== e.stream.height && (a = e.stream.height),
                s.drawImage(e, i, o, r, a),
                "function" == typeof e.stream.onRender && e.stream.onRender(s, i, o, r, a, t);
        }
    }
    function m(e) {
        var i = document.createElement("video");
        return (
            (function (e, t) {
                "srcObject" in t ? (t.srcObject = e) : "mozSrcObject" in t ? (t.mozSrcObject = e) : (t.srcObject = e);
            })(e, i),
            (i.className = t),
            (i.muted = !0),
            (i.volume = 0),
            (i.width = e.videoWidth || a.width || 360),
            (i.height = e.videoHeight || a.height || 240),
            i.play(),
            i
        );
    }
    function g(t) {
        (o = []),
            (t = t || e).forEach(function (e) {
                if (
                    e &&
                    e.getTracks().filter(function (e) {
                        return "video" === e.kind;
                    }).length
                ) {
                    var t = m(e);
                    (t.stream = e), o.push(t);
                }
            });
    }
    void 0 !== c ? (h.AudioContext = c) : "undefined" != typeof webkitAudioContext && (h.AudioContext = webkitAudioContext),
        (this.startDrawingFrames = function () {
            u();
        }),
        (this.appendStreams = function (t) {
            if (!t) throw "First parameter is required.";
            t instanceof Array || (t = [t]),
                t.forEach(function (t) {
                    var i = new d();
                    if (
                        t.getTracks().filter(function (e) {
                            return "video" === e.kind;
                        }).length
                    ) {
                        var n = m(t);
                        (n.stream = t),
                            o.push(n),
                            i.addTrack(
                                t.getTracks().filter(function (e) {
                                    return "video" === e.kind;
                                })[0]
                            );
                    }
                    if (
                        t.getTracks().filter(function (e) {
                            return "audio" === e.kind;
                        }).length
                    ) {
                        var r = a.audioContext.createMediaStreamSource(t);
                        (a.audioDestination = a.audioContext.createMediaStreamDestination()),
                            r.connect(a.audioDestination),
                            i.addTrack(
                                a.audioDestination.stream.getTracks().filter(function (e) {
                                    return "audio" === e.kind;
                                })[0]
                            );
                    }
                    e.push(i);
                });
        }),
        (this.releaseStreams = function () {
            (o = []),
                (n = !0),
                a.gainNode && (a.gainNode.disconnect(), (a.gainNode = null)),
                a.audioSources.length &&
                    (a.audioSources.forEach(function (e) {
                        e.disconnect();
                    }),
                    (a.audioSources = [])),
                a.audioDestination && (a.audioDestination.disconnect(), (a.audioDestination = null)),
                a.audioContext && a.audioContext.close(),
                (a.audioContext = null),
                s.clearRect(0, 0, r.width, r.height),
                r.stream && (r.stream.stop(), (r.stream = null));
        }),
        (this.resetVideoStreams = function (e) {
            !e || e instanceof Array || (e = [e]), g(e);
        }),
        (this.name = "MultiStreamsMixer"),
        (this.toString = function () {
            return this.name;
        }),
        (this.getMixedStream = function () {
            n = !1;
            var t = (function () {
                    var e;
                    g(),
                        "captureStream" in r
                            ? (e = r.captureStream())
                            : "mozCaptureStream" in r
                            ? (e = r.mozCaptureStream())
                            : a.disableLogs || console.error("Upgrade to latest Chrome or otherwise enable this flag: chrome://flags/#enable-experimental-web-platform-features");
                    var t = new d();
                    return (
                        e
                            .getTracks()
                            .filter(function (e) {
                                return "video" === e.kind;
                            })
                            .forEach(function (e) {
                                t.addTrack(e);
                            }),
                        (r.stream = t),
                        t
                    );
                })(),
                i = (function () {
                    h.AudioContextConstructor || (h.AudioContextConstructor = new h.AudioContext());
                    (a.audioContext = h.AudioContextConstructor), (a.audioSources = []), !0 === a.useGainNode && ((a.gainNode = a.audioContext.createGain()), a.gainNode.connect(a.audioContext.destination), (a.gainNode.gain.value = 0));
                    var t = 0;
                    if (
                        (e.forEach(function (e) {
                            if (
                                e &&
                                e.getTracks().filter(function (e) {
                                    return "audio" === e.kind;
                                }).length
                            ) {
                                t++;
                                var i = a.audioContext.createMediaStreamSource(e);
                                !0 === a.useGainNode && i.connect(a.gainNode), a.audioSources.push(i);
                            }
                        }),
                        !t)
                    )
                        return;
                    return (
                        (a.audioDestination = a.audioContext.createMediaStreamDestination()),
                        a.audioSources.forEach(function (e) {
                            e.connect(a.audioDestination);
                        }),
                        a.audioDestination.stream
                    );
                })();
            return (
                i &&
                    i
                        .getTracks()
                        .filter(function (e) {
                            return "audio" === e.kind;
                        })
                        .forEach(function (e) {
                            t.addTrack(e);
                        }),
                e.forEach(function (e) {
                    e && e.fullcanvas && !0;
                }),
                t
            );
        });
}
/**
 * MultiStreamRecorder can record multiple videos in single container.
 * @summary Multi-videos recorder.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef MultiStreamRecorder
 * @class
 * @example
 * var options = {
 *     mimeType: 'video/webm'
 * }
 * var recorder = new MultiStreamRecorder(ArrayOfMediaStreams, options);
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 *
 *     // or
 *     var blob = recorder.blob;
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStreams} mediaStreams - Array of MediaStreams.
 * @param {object} config - {disableLogs:true, frameInterval: 1, mimeType: "video/webm"}
 */
function MultiStreamRecorder(e, t) {
    e = e || [];
    var i,
        o,
        n = this;
    (t = t || { elementClass: "multi-streams-mixer", mimeType: "video/mp4", video: { width: 360, height: 240 } }).frameInterval || (t.frameInterval = 10),
        t.video || (t.video = {}),
        t.video.width || (t.video.width = 360),
        t.video.height || (t.video.height = 240),
        (this.record = function () {
            var n;
            (i = new MultiStreamsMixer(e, t.elementClass || "multi-streams-mixer")),
                ((n = []),
                e.forEach(function (e) {
                    getTracks(e, "video").forEach(function (e) {
                        n.push(e);
                    });
                }),
                n).length && ((i.frameInterval = t.frameInterval || 10), (i.width = t.video.width || 360), (i.height = t.video.height || 240), i.startDrawingFrames()),
                t.previewStream && "function" == typeof t.previewStream && t.previewStream(i.getMixedStream()),
                (o = new MediaStreamRecorder(i.getMixedStream(), t)).record();
        }),
        (this.stop = function (e) {
            o &&
                o.stop(function (t) {
                    (n.blob = t), e(t), n.clearRecordedData();
                });
        }),
        (this.pause = function () {
            o && o.pause();
        }),
        (this.resume = function () {
            o && o.resume();
        }),
        (this.clearRecordedData = function () {
            o && (o.clearRecordedData(), (o = null)), i && (i.releaseStreams(), (i = null));
        }),
        (this.addStreams = function (n) {
            if (!n) throw "First parameter is required.";
            n instanceof Array || (n = [n]), e.concat(n), o && i && (i.appendStreams(n), t.previewStream && "function" == typeof t.previewStream && t.previewStream(i.getMixedStream()));
        }),
        (this.resetVideoStreams = function (e) {
            i && (!e || e instanceof Array || (e = [e]), i.resetVideoStreams(e));
        }),
        (this.getMixer = function () {
            return i;
        }),
        (this.name = "MultiStreamRecorder"),
        (this.toString = function () {
            return this.name;
        });
}
/**
 * RecordRTCPromisesHandler adds promises support in {@link RecordRTC}. Try a {@link https://github.com/muaz-khan/RecordRTC/blob/master/simple-demos/RecordRTCPromisesHandler.html|demo here}
 * @summary Promises for {@link RecordRTC}
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef RecordRTCPromisesHandler
 * @class
 * @example
 * var recorder = new RecordRTCPromisesHandler(mediaStream, options);
 * recorder.startRecording()
 *         .then(successCB)
 *         .catch(errorCB);
 * // Note: You can access all RecordRTC API using "recorder.recordRTC" e.g.
 * recorder.recordRTC.onStateChanged = function(state) {};
 * recorder.recordRTC.setRecordingDuration(5000);
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - Single media-stream object, array of media-streams, html-canvas-element, etc.
 * @param {object} config - {type:"video", recorderType: MediaStreamRecorder, disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, etc.}
 * @throws Will throw an error if "new" keyword is not used to initiate "RecordRTCPromisesHandler". Also throws error if first argument "MediaStream" is missing.
 * @requires {@link RecordRTC}
 */
function RecordRTCPromisesHandler(e, t) {
    if (!this) throw 'Use "new RecordRTCPromisesHandler()"';
    if (void 0 === e) throw 'First argument "MediaStream" is required.';
    var i = this;
    (i.recordRTC = new RecordRTC(e, t)),
        (this.startRecording = function () {
            return new Promise(function (e, t) {
                try {
                    i.recordRTC.startRecording(), e();
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.stopRecording = function () {
            return new Promise(function (e, t) {
                try {
                    i.recordRTC.stopRecording(function (o) {
                        (i.blob = i.recordRTC.getBlob()), i.blob && i.blob.size ? e(o) : t("Empty blob.", i.blob);
                    });
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.pauseRecording = function () {
            return new Promise(function (e, t) {
                try {
                    i.recordRTC.pauseRecording(), e();
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.resumeRecording = function () {
            return new Promise(function (e, t) {
                try {
                    i.recordRTC.resumeRecording(), e();
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.getDataURL = function (e) {
            return new Promise(function (e, t) {
                try {
                    i.recordRTC.getDataURL(function (t) {
                        e(t);
                    });
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.getBlob = function () {
            return new Promise(function (e, t) {
                try {
                    e(i.recordRTC.getBlob());
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.getInternalRecorder = function () {
            return new Promise(function (e, t) {
                try {
                    e(i.recordRTC.getInternalRecorder());
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.reset = function () {
            return new Promise(function (e, t) {
                try {
                    e(i.recordRTC.reset());
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.destroy = function () {
            return new Promise(function (e, t) {
                try {
                    e(i.recordRTC.destroy());
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.getState = function () {
            return new Promise(function (e, t) {
                try {
                    e(i.recordRTC.getState());
                } catch (e) {
                    t(e);
                }
            });
        }),
        (this.blob = null),
        (this.version = "5.6.2");
}
/**
 * WebAssemblyRecorder lets you create webm videos in JavaScript via WebAssembly. The library consumes raw RGBA32 buffers (4 bytes per pixel) and turns them into a webm video with the given framerate and quality. This makes it compatible out-of-the-box with ImageData from a CANVAS. With realtime mode you can also use webm-wasm for streaming webm videos.
 * @summary Video recording feature in Chrome, Firefox and maybe Edge.
 * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
 * @author {@link https://MuazKhan.com|Muaz Khan}
 * @typedef WebAssemblyRecorder
 * @class
 * @example
 * var recorder = new WebAssemblyRecorder(mediaStream);
 * recorder.record();
 * recorder.stop(function(blob) {
 *     video.src = URL.createObjectURL(blob);
 * });
 * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
 * @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
 * @param {object} config - {webAssemblyPath:'webm-wasm.wasm',workerPath: 'webm-worker.js', frameRate: 30, width: 1920, height: 1080, bitrate: 1024, realtime: true}
 */
function WebAssemblyRecorder(e, t) {
    var i, o, n;
    function r() {
        return new ReadableStream({
            start: function (o) {
                var n = document.createElement("canvas"),
                    r = document.createElement("video"),
                    s = !0;
                (r.srcObject = e),
                    (r.muted = !0),
                    (r.height = t.height),
                    (r.width = t.width),
                    (r.volume = 0),
                    (r.onplaying = function () {
                        (n.width = t.width), (n.height = t.height);
                        var e = n.getContext("2d"),
                            a = 1e3 / t.frameRate,
                            c = setInterval(function () {
                                if ((i && (clearInterval(c), o.close()), s && ((s = !1), t.onVideoProcessStarted && t.onVideoProcessStarted()), e.drawImage(r, 0, 0), "closed" !== o._controlledReadableStream.state))
                                    try {
                                        o.enqueue(e.getImageData(0, 0, t.width, t.height));
                                    } catch (e) {}
                            }, a);
                    }),
                    r.play();
            },
        });
    }
    function s(e, c) {
        if (!t.workerPath && !c)
            return (
                (i = !1),
                void fetch("https://unpkg.com/webm-wasm@latest/dist/webm-worker.js").then(function (t) {
                    t.arrayBuffer().then(function (t) {
                        s(e, t);
                    });
                })
            );
        if (!t.workerPath && c instanceof ArrayBuffer) {
            var l = new Blob([c], { type: "text/javascript" });
            t.workerPath = URL.createObjectURL(l);
        }
        t.workerPath || console.error("workerPath parameter is missing."),
            (o = new Worker(t.workerPath)).postMessage(t.webAssemblyPath || "https://unpkg.com/webm-wasm@latest/dist/webm-wasm.wasm"),
            o.addEventListener("message", function (e) {
                "READY" === e.data
                    ? (o.postMessage({ width: t.width, height: t.height, bitrate: t.bitrate || 1200, timebaseDen: t.frameRate || 30, realtime: t.realtime }),
                      r().pipeTo(
                          new WritableStream({
                              write: function (e) {
                                  i ? console.error("Got image, but recorder is finished!") : o.postMessage(e.data.buffer, [e.data.buffer]);
                              },
                          })
                      ))
                    : e.data && (n || a.push(e.data));
            });
    }
    ("undefined" != typeof ReadableStream && "undefined" != typeof WritableStream) || console.error("Following polyfill is strongly recommended: https://unpkg.com/@mattiasbuelens/web-streams-polyfill/dist/polyfill.min.js"),
        ((t = t || {}).width = t.width || 640),
        (t.height = t.height || 480),
        (t.frameRate = t.frameRate || 30),
        (t.bitrate = t.bitrate || 1200),
        (t.realtime = t.realtime || !0),
        (this.record = function () {
            (a = []), (n = !1), (this.blob = null), s(e), "function" == typeof t.initCallback && t.initCallback();
        }),
        (this.pause = function () {
            n = !0;
        }),
        (this.resume = function () {
            n = !1;
        });
    var a = [];
    (this.stop = function (e) {
        i = !0;
        var t = this;
        !(function (e) {
            o
                ? (o.addEventListener("message", function (t) {
                      null === t.data && (o.terminate(), (o = null), e && e());
                  }),
                  o.postMessage(null))
                : e && e();
        })(function () {
            (t.blob = new Blob(a, { type: "video/mp4" })), e(t.blob);
        });
    }),
        (this.name = "WebAssemblyRecorder"),
        (this.toString = function () {
            return this.name;
        }),
        (this.clearRecordedData = function () {
            (a = []), (n = !1), (this.blob = null);
        }),
        (this.blob = null);
}
void 0 !== RecordRTC && (RecordRTC.DiskStorage = DiskStorage),
    void 0 !== RecordRTC && (RecordRTC.GifRecorder = GifRecorder),
    void 0 === RecordRTC &&
        ("undefined" != typeof module && (module.exports = MultiStreamsMixer),
        "function" == typeof define &&
            define.amd &&
            define("MultiStreamsMixer", [], function () {
                return MultiStreamsMixer;
            })),
    void 0 !== RecordRTC && (RecordRTC.MultiStreamRecorder = MultiStreamRecorder),
    void 0 !== RecordRTC && (RecordRTC.RecordRTCPromisesHandler = RecordRTCPromisesHandler),
    void 0 !== RecordRTC && (RecordRTC.WebAssemblyRecorder = WebAssemblyRecorder),
    (window.FontAwesomeKitConfig = {
        asyncLoading: { enabled: !1 },
        autoA11y: { enabled: !0 },
        baseUrl: "https://ka-f.fontawesome.com",
        baseUrlKit: "https://kit.fontawesome.com",
        detectConflictsUntil: null,
        iconUploads: {},
        id: 39495983,
        license: "free",
        method: "css",
        minify: { enabled: !0 },
        token: "d2f1016e6f",
        v4FontFaceShim: { enabled: !0 },
        v4shim: { enabled: !0 },
        v5FontFaceShim: { enabled: !1 },
        version: "6.0.0",
    }),
    (function (e) {
        "function" == typeof define && define.amd ? define("kit-loader", e) : e();
    })(function () {
        function e(t) {
            return (e =
                "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
                    ? function (e) {
                          return typeof e;
                      }
                    : function (e) {
                          return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
                      })(t);
        }
        function t(e, t, i) {
            return t in e ? Object.defineProperty(e, t, { value: i, enumerable: !0, configurable: !0, writable: !0 }) : (e[t] = i), e;
        }
        function i(e, t) {
            var i = Object.keys(e);
            if (Object.getOwnPropertySymbols) {
                var o = Object.getOwnPropertySymbols(e);
                t &&
                    (o = o.filter(function (t) {
                        return Object.getOwnPropertyDescriptor(e, t).enumerable;
                    })),
                    i.push.apply(i, o);
            }
            return i;
        }
        function o(e) {
            for (var o = 1; o < arguments.length; o++) {
                var n = null != arguments[o] ? arguments[o] : {};
                o % 2
                    ? i(Object(n), !0).forEach(function (i) {
                          t(e, i, n[i]);
                      })
                    : Object.getOwnPropertyDescriptors
                    ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n))
                    : i(Object(n)).forEach(function (t) {
                          Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
                      });
            }
            return e;
        }
        function n(e, t) {
            return (
                (function (e) {
                    if (Array.isArray(e)) return e;
                })(e) ||
                (function (e, t) {
                    if ("undefined" != typeof Symbol && Symbol.iterator in Object(e)) {
                        var i = [],
                            o = !0,
                            n = !1,
                            r = void 0;
                        try {
                            for (var s, a = e[Symbol.iterator](); !(o = (s = a.next()).done) && (i.push(s.value), !t || i.length !== t); o = !0);
                        } catch (e) {
                            (n = !0), (r = e);
                        } finally {
                            try {
                                o || null == a.return || a.return();
                            } finally {
                                if (n) throw r;
                            }
                        }
                        return i;
                    }
                })(e, t) ||
                (function (e, t) {
                    if (e) {
                        if ("string" == typeof e) return r(e, t);
                        var i = Object.prototype.toString.call(e).slice(8, -1);
                        return "Object" === i && e.constructor && (i = e.constructor.name), "Map" === i || "Set" === i ? Array.from(e) : "Arguments" === i || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i) ? r(e, t) : void 0;
                    }
                })(e, t) ||
                (function () {
                    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
                })()
            );
        }
        function r(e, t) {
            (null == t || t > e.length) && (t = e.length);
            for (var i = 0, o = new Array(t); i < t; i++) o[i] = e[i];
            return o;
        }
        function s(e, t) {
            var i = (t && t.addOn) || "",
                o = (t && t.baseFilename) || e.license + i,
                n = t && t.minify ? ".min" : "",
                r = (t && t.fileSuffix) || e.method,
                s = (t && t.subdir) || e.method;
            return e.baseUrl + "/releases/" + ("latest" === e.version ? "latest" : "v".concat(e.version)) + "/" + s + "/" + o + n + "." + r;
        }
        function a(e) {
            return e.baseUrlKit + "/" + e.token + "/" + e.id + "/kit-upload.css";
        }
        function c(e, t) {
            var i = t || ["fa"],
                o = "." + Array.prototype.join.call(i, ",."),
                n = e.querySelectorAll(o);
            Array.prototype.forEach.call(n, function (t) {
                var i = t.getAttribute("title");
                t.setAttribute("aria-hidden", "true");
                var o = !t.nextElementSibling || !t.nextElementSibling.classList.contains("sr-only");
                if (i && o) {
                    var n = e.createElement("span");
                    (n.innerHTML = i), n.classList.add("sr-only"), t.parentNode.insertBefore(n, t.nextSibling);
                }
            });
        }
        var l,
            d = function () {},
            h = "undefined" != typeof global && void 0 !== global.process && "function" == typeof global.process.emit,
            u = "undefined" == typeof setImmediate ? setTimeout : setImmediate,
            f = [];
        function m() {
            for (var e = 0; e < f.length; e++) f[e][0](f[e][1]);
            (f = []), (l = !1);
        }
        function g(e, t) {
            f.push([e, t]), l || ((l = !0), u(m, 0));
        }
        function p(e) {
            var t = e.owner,
                i = t._state,
                o = t._data,
                n = e[i],
                r = e.then;
            if ("function" == typeof n) {
                i = "fulfilled";
                try {
                    o = n(o);
                } catch (e) {
                    S(r, e);
                }
            }
            v(r, o) || ("fulfilled" === i && b(r, o), "rejected" === i && S(r, o));
        }
        function v(t, i) {
            var o;
            try {
                if (t === i) throw new TypeError("A promises callback cannot return that same promise.");
                if (i && ("function" == typeof i || "object" === e(i))) {
                    var n = i.then;
                    if ("function" == typeof n)
                        return (
                            n.call(
                                i,
                                function (e) {
                                    o || ((o = !0), i === e ? y(t, e) : b(t, e));
                                },
                                function (e) {
                                    o || ((o = !0), S(t, e));
                                }
                            ),
                            !0
                        );
                }
            } catch (e) {
                return o || S(t, e), !0;
            }
            return !1;
        }
        function b(e, t) {
            (e !== t && v(e, t)) || y(e, t);
        }
        function y(e, t) {
            "pending" === e._state && ((e._state = "settled"), (e._data = t), g(_, e));
        }
        function S(e, t) {
            "pending" === e._state && ((e._state = "settled"), (e._data = t), g(C, e));
        }
        function w(e) {
            e._then = e._then.forEach(p);
        }
        function _(e) {
            (e._state = "fulfilled"), w(e);
        }
        function C(e) {
            (e._state = "rejected"), w(e), !e._handled && h && global.process.emit("unhandledRejection", e._data, e);
        }
        function x(e) {
            global.process.emit("rejectionHandled", e);
        }
        function T(e) {
            if ("function" != typeof e) throw new TypeError("Promise resolver " + e + " is not a function");
            if (this instanceof T == 0) throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
            (this._then = []),
                (function (e, t) {
                    function i(e) {
                        S(t, e);
                    }
                    try {
                        e(function (e) {
                            b(t, e);
                        }, i);
                    } catch (e) {
                        i(e);
                    }
                })(e, this);
        }
        (T.prototype = {
            constructor: T,
            _state: "pending",
            _then: null,
            _data: void 0,
            _handled: !1,
            then: function (e, t) {
                var i = { owner: this, then: new this.constructor(d), fulfilled: e, rejected: t };
                return (!t && !e) || this._handled || ((this._handled = !0), "rejected" === this._state && h && g(x, this)), "fulfilled" === this._state || "rejected" === this._state ? g(p, i) : this._then.push(i), i.then;
            },
            catch: function (e) {
                return this.then(null, e);
            },
        }),
            (T.all = function (e) {
                if (!Array.isArray(e)) throw new TypeError("You must pass an array to Promise.all().");
                return new T(function (t, i) {
                    var o = [],
                        n = 0;
                    function r(e) {
                        return (
                            n++,
                            function (i) {
                                (o[e] = i), --n || t(o);
                            }
                        );
                    }
                    for (var s, a = 0; a < e.length; a++) (s = e[a]) && "function" == typeof s.then ? s.then(r(a), i) : (o[a] = s);
                    n || t(o);
                });
            }),
            (T.race = function (e) {
                if (!Array.isArray(e)) throw new TypeError("You must pass an array to Promise.race().");
                return new T(function (t, i) {
                    for (var o, n = 0; n < e.length; n++) (o = e[n]) && "function" == typeof o.then ? o.then(t, i) : t(o);
                });
            }),
            (T.resolve = function (t) {
                return t && "object" === e(t) && t.constructor === T
                    ? t
                    : new T(function (e) {
                          e(t);
                      });
            }),
            (T.reject = function (e) {
                return new T(function (t, i) {
                    i(e);
                });
            });
        var k = "function" == typeof Promise ? Promise : T;
        function R(e, t) {
            var i = t.fetch,
                o = t.XMLHttpRequest,
                n = t.token,
                r = e;
            return (
                "URLSearchParams" in window ? (r = new URL(e)).searchParams.set("token", n) : (r = r + "?token=" + encodeURIComponent(n)),
                (r = r.toString()),
                new k(function (e, t) {
                    if ("function" == typeof i)
                        i(r, { mode: "cors", cache: "default" })
                            .then(function (e) {
                                if (e.ok) return e.text();
                                throw new Error("");
                            })
                            .then(function (t) {
                                e(t);
                            })
                            .catch(t);
                    else if ("function" == typeof o) {
                        var n = new o();
                        n.addEventListener("loadend", function () {
                            this.responseText ? e(this.responseText) : t(new Error(""));
                        }),
                            ["abort", "error", "timeout"].map(function (e) {
                                n.addEventListener(e, function () {
                                    t(new Error(""));
                                });
                            }),
                            n.open("GET", r),
                            n.send();
                    } else t(new Error(""));
                })
            );
        }
        function O(e, t, i) {
            var o = e;
            return (
                [
                    [
                        /(url\("?)\.\.\/\.\.\/\.\./g,
                        function (e, i) {
                            return "".concat(i).concat(t);
                        },
                    ],
                    [
                        /(url\("?)\.\.\/webfonts/g,
                        function (e, o) {
                            return "".concat(o).concat(t, "/releases/v").concat(i, "/webfonts");
                        },
                    ],
                    [
                        /(url\("?)https:\/\/kit-free([^.])*\.fontawesome\.com/g,
                        function (e, i) {
                            return "".concat(i).concat(t);
                        },
                    ],
                ].forEach(function (e) {
                    var t = n(e, 2),
                        i = t[0],
                        r = t[1];
                    o = o.replace(i, r);
                }),
                o
            );
        }
        function A(e, t) {
            var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : function () {},
                n = t.document || n,
                r = c.bind(c, n, ["fa", "fab", "fas", "far", "fal", "fad", "fak"]),
                l = Object.keys(e.iconUploads || {}).length > 0;
            e.autoA11y.enabled && i(r);
            var d = [{ id: "fa-main", addOn: void 0 }];
            e.v4shim && e.v4shim.enabled && d.push({ id: "fa-v4-shims", addOn: "-v4-shims" }),
                e.v5FontFaceShim && e.v5FontFaceShim.enabled && d.push({ id: "fa-v5-font-face", addOn: "-v5-font-face" }),
                e.v4FontFaceShim && e.v4FontFaceShim.enabled && d.push({ id: "fa-v4-font-face", addOn: "-v4-font-face" }),
                l && d.push({ id: "fa-kit-upload", customCss: !0 });
            var h = d.map(function (i) {
                return new k(function (n, r) {
                    R(i.customCss ? a(e) : s(e, { addOn: i.addOn, minify: e.minify.enabled }), t)
                        .then(function (r) {
                            n(
                                M(
                                    r,
                                    o(
                                        o({}, t),
                                        {},
                                        {
                                            baseUrl: e.baseUrl,
                                            version: e.version,
                                            id: i.id,
                                            contentFilter: function (e, t) {
                                                return O(e, t.baseUrl, t.version);
                                            },
                                        }
                                    )
                                )
                            );
                        })
                        .catch(r);
                });
            });
            return k.all(h);
        }
        function M(e, t) {
            var i =
                    t.contentFilter ||
                    function (e, t) {
                        return e;
                    },
                o = document.createElement("style"),
                n = document.createTextNode(i(e, t));
            return o.appendChild(n), (o.media = "all"), t.id && o.setAttribute("id", t.id), t && t.detectingConflicts && t.detectionIgnoreAttr && o.setAttributeNode(document.createAttribute(t.detectionIgnoreAttr)), o;
        }
        function E(e, t) {
            (t.autoA11y = e.autoA11y.enabled),
                "pro" === e.license && ((t.autoFetchSvg = !0), (t.fetchSvgFrom = e.baseUrl + "/releases/" + ("latest" === e.version ? "latest" : "v".concat(e.version)) + "/svgs"), (t.fetchUploadedSvgFrom = e.uploadsUrl));
            var i = [];
            return (
                e.v4shim.enabled &&
                    i.push(
                        new k(function (i, n) {
                            R(s(e, { addOn: "-v4-shims", minify: e.minify.enabled }), t)
                                .then(function (e) {
                                    i(P(e, o(o({}, t), {}, { id: "fa-v4-shims" })));
                                })
                                .catch(n);
                        })
                    ),
                i.push(
                    new k(function (i, n) {
                        R(s(e, { minify: e.minify.enabled }), t)
                            .then(function (e) {
                                var n = P(e, o(o({}, t), {}, { id: "fa-main" }));
                                i(
                                    (function (e, t) {
                                        var i = t && void 0 !== t.autoFetchSvg ? t.autoFetchSvg : void 0,
                                            o = t && void 0 !== t.autoA11y ? t.autoA11y : void 0;
                                        return (
                                            void 0 !== o && e.setAttribute("data-auto-a11y", o ? "true" : "false"),
                                            i &&
                                                (e.setAttributeNode(document.createAttribute("data-auto-fetch-svg")),
                                                e.setAttribute("data-fetch-svg-from", t.fetchSvgFrom),
                                                e.setAttribute("data-fetch-uploaded-svg-from", t.fetchUploadedSvgFrom)),
                                            e
                                        );
                                    })(n, t)
                                );
                            })
                            .catch(n);
                    })
                ),
                k.all(i)
            );
        }
        function P(e, t) {
            var i = document.createElement("SCRIPT"),
                o = document.createTextNode(e);
            return i.appendChild(o), (i.referrerPolicy = "strict-origin"), t.id && i.setAttribute("id", t.id), t && t.detectingConflicts && t.detectionIgnoreAttr && i.setAttributeNode(document.createAttribute(t.detectionIgnoreAttr)), i;
        }
        function B(e) {
            var t,
                i = [],
                o = document,
                n = (o.documentElement.doScroll ? /^loaded|^c/ : /^loaded|^i|^c/).test(o.readyState);
            n ||
                o.addEventListener(
                    "DOMContentLoaded",
                    (t = function () {
                        for (o.removeEventListener("DOMContentLoaded", t), n = 1; (t = i.shift()); ) t();
                    })
                ),
                n ? setTimeout(e, 0) : i.push(e);
        }
        function D(e) {
            "undefined" != typeof MutationObserver && new MutationObserver(e).observe(document, { childList: !0, subtree: !0 });
        }
        try {
            if (window.FontAwesomeKitConfig) {
                var I = window.FontAwesomeKitConfig,
                    V = {
                        detectingConflicts: I.detectConflictsUntil && new Date() <= new Date(I.detectConflictsUntil),
                        detectionIgnoreAttr: "data-fa-detection-ignore",
                        fetch: window.fetch,
                        token: I.token,
                        XMLHttpRequest: window.XMLHttpRequest,
                        document: document,
                    },
                    L = document.currentScript,
                    F = L ? L.parentElement : document.head;
                (function () {
                    var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
                        t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
                    return "js" === e.method
                        ? E(e, t)
                        : "css" === e.method
                        ? A(e, t, function (e) {
                              B(e), D(e);
                          })
                        : void 0;
                })(I, V)
                    .then(function (e) {
                        e.map(function (e) {
                            try {
                                F.insertBefore(e, L ? L.nextSibling : null);
                            } catch (t) {
                                F.appendChild(e);
                            }
                        }),
                            V.detectingConflicts &&
                                L &&
                                B(function () {
                                    L.setAttributeNode(document.createAttribute(V.detectionIgnoreAttr));
                                    var e = (function (e, t) {
                                        var i = document.createElement("script");
                                        return (
                                            t && t.detectionIgnoreAttr && i.setAttributeNode(document.createAttribute(t.detectionIgnoreAttr)),
                                            (i.src = s(e, { baseFilename: "conflict-detection", fileSuffix: "js", subdir: "js", minify: e.minify.enabled })),
                                            i
                                        );
                                    })(I, V);
                                    document.body.appendChild(e);
                                });
                    })
                    .catch(function (e) {
                        console.error("".concat("Font Awesome Kit:", " ").concat(e));
                    });
            }
        } catch (e) {
            console.error("".concat("Font Awesome Kit:", " ").concat(e));
        }
    }),
    (function () {
        var e,
            t = "Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45";
        if ((b = "object" == typeof process && "object" == typeof process.versions && process.versions.node && !process.browser)) {
            var i = process.versions.node.toString().replace("v", "");
            t = "Nodejs/" + i + " (NodeOS) AppleWebKit/" + i + " (KHTML, like Gecko) Nodejs/" + i + " Nodejs/" + i;
        }
        (e = "undefined" != typeof global ? global : window),
            "undefined" == typeof window &&
                ("undefined" == typeof window && "undefined" != typeof global && ((global.navigator = { userAgent: t, getUserMedia: function () {} }), (e.window = global)),
                "undefined" == typeof location && (e.location = { protocol: "file:", href: "", hash: "" }),
                "undefined" == typeof screen && (e.screen = { width: 0, height: 0 }));
        var o = window.navigator;
        void 0 !== o ? (void 0 !== o.webkitGetUserMedia && (o.getUserMedia = o.webkitGetUserMedia), void 0 !== o.mozGetUserMedia && (o.getUserMedia = o.mozGetUserMedia)) : (o = { getUserMedia: function () {}, userAgent: t });
        var n = !!/Android|webOS|iPhone|iPad|iPod|BB10|BlackBerry|IEMobile|Opera Mini|Mobile|mobile/i.test(o.userAgent || ""),
            r = !(-1 === o.userAgent.indexOf("Edge") || (!o.msSaveOrOpenBlob && !o.msSaveBlob)),
            s = !!window.opera || o.userAgent.indexOf(" OPR/") >= 0,
            a = o.userAgent.toLowerCase().indexOf("firefox") > -1 && "netscape" in window && / rv:/.test(o.userAgent),
            c = /^((?!chrome|android).)*safari/i.test(o.userAgent),
            l = !!window.chrome && !s,
            d = "undefined" != typeof document && !!document.documentMode && !r;
        function h(e, t) {
            var i = 0,
                o = !1,
                n = window.setInterval(function () {
                    e() && (window.clearInterval(n), t(o)), i++ > 50 && (window.clearInterval(n), t((o = !0)));
                }, 10);
        }
        var u = {
            Android: function () {
                return o.userAgent.match(/Android/i);
            },
            BlackBerry: function () {
                return o.userAgent.match(/BlackBerry|BB10/i);
            },
            iOS: function () {
                return o.userAgent.match(/iPhone|iPad|iPod/i);
            },
            Opera: function () {
                return o.userAgent.match(/Opera Mini/i);
            },
            Windows: function () {
                return o.userAgent.match(/IEMobile/i);
            },
            any: function () {
                return u.Android() || u.BlackBerry() || u.iOS() || u.Opera() || u.Windows();
            },
            getOsName: function () {
                var e = "Unknown OS";
                return u.Android() && (e = "Android"), u.BlackBerry() && (e = "BlackBerry"), u.iOS() && (e = "iOS"), u.Opera() && (e = "Opera Mini"), u.Windows() && (e = "Windows"), e;
            },
        };
        var f = "Unknown OS",
            m = "Unknown OS Version";
        var g,
            p,
            v = (function () {
                for (
                    var e,
                        t = o.appVersion,
                        i = o.userAgent,
                        n = "-",
                        r = [
                            { s: "Chrome OS", r: /CrOS/ },
                            { s: "Windows 10", r: /(Windows 10.0|Windows NT 10.0)/ },
                            { s: "Windows 8.1", r: /(Windows 8.1|Windows NT 6.3)/ },
                            { s: "Windows 8", r: /(Windows 8|Windows NT 6.2)/ },
                            { s: "Windows 7", r: /(Windows 7|Windows NT 6.1)/ },
                            { s: "Windows Vista", r: /Windows NT 6.0/ },
                            { s: "Windows Server 2003", r: /Windows NT 5.2/ },
                            { s: "Windows XP", r: /(Windows NT 5.1|Windows XP)/ },
                            { s: "Windows 2000", r: /(Windows NT 5.0|Windows 2000)/ },
                            { s: "Windows ME", r: /(Win 9x 4.90|Windows ME)/ },
                            { s: "Windows 98", r: /(Windows 98|Win98)/ },
                            { s: "Windows 95", r: /(Windows 95|Win95|Windows_95)/ },
                            { s: "Windows NT 4.0", r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ },
                            { s: "Windows CE", r: /Windows CE/ },
                            { s: "Windows 3.11", r: /Win16/ },
                            { s: "Android", r: /Android/ },
                            { s: "Open BSD", r: /OpenBSD/ },
                            { s: "Sun OS", r: /SunOS/ },
                            { s: "Linux", r: /(Linux|X11)/ },
                            { s: "iOS", r: /(iPhone|iPad|iPod)/ },
                            { s: "Mac OS X", r: /Mac OS X/ },
                            { s: "Mac OS", r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ },
                            { s: "QNX", r: /QNX/ },
                            { s: "UNIX", r: /UNIX/ },
                            { s: "BeOS", r: /BeOS/ },
                            { s: "OS/2", r: /OS\/2/ },
                            { s: "Search Bot", r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ },
                        ],
                        s = 0;
                    (e = r[s]);
                    s++
                )
                    if (e.r.test(i)) {
                        n = e.s;
                        break;
                    }
                var a = "-";
                switch ((/Windows/.test(n) && (/Windows (.*)/.test(n) && (a = /Windows (.*)/.exec(n)[1]), (n = "Windows")), n)) {
                    case "Mac OS X":
                        /Mac OS X (10[\.\_\d]+)/.test(i) && (a = /Mac OS X (10[\.\_\d]+)/.exec(i)[1]);
                        break;
                    case "Android":
                        /Android ([\.\_\d]+)/.test(i) && (a = /Android ([\.\_\d]+)/.exec(i)[1]);
                        break;
                    case "iOS":
                        /OS (\d+)_(\d+)_?(\d+)?/.test(i) && (a = /OS (\d+)_(\d+)_?(\d+)?/.exec(t)) && a.length > 3 && (a = a[1] + "." + a[2] + "." + (0 | a[3]));
                }
                return { osName: n, osVersion: a };
            })();
        v && v.osName && "-" != v.osName ? ((f = v.osName), (m = v.osVersion)) : u.any() && "Android" == (f = u.getOsName()) && (m = !!(p = (g = (g || o.userAgent).toLowerCase()).match(/android\s([0-9\.]*)/)) && p[1]);
        var b = "object" == typeof process && "object" == typeof process.versions && process.versions.node;
        "Unknown OS" === f && b && ((f = "Nodejs"), (m = process.versions.node.toString().replace("v", "")));
        var y = !1,
            S = !1;
        ["captureStream", "mozCaptureStream", "webkitCaptureStream"].forEach(function (e) {
            "undefined" != typeof document && "function" == typeof document.createElement && (!y && e in document.createElement("canvas") && (y = !0), !S && e in document.createElement("video") && (S = !0));
        });
        var w = /^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/,
            _ = /([0-9]{1,3}(\.[0-9]{1,3}){3})/,
            C = /[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}/;
        var x = [],
            T = [],
            k = [],
            R = [];
        o.mediaDevices &&
            o.mediaDevices.enumerateDevices &&
            (o.enumerateDevices = function (e) {
                var t = o.mediaDevices.enumerateDevices();
                t && t.then
                    ? o.mediaDevices
                          .enumerateDevices()
                          .then(e)
                          .catch(function () {
                              e([]);
                          })
                    : e([]);
            });
        var O = !1;
        (("undefined" != typeof MediaStreamTrack && "getSources" in MediaStreamTrack) || (o.mediaDevices && o.mediaDevices.enumerateDevices)) && (O = !0);
        var A = !1,
            M = !1,
            E = !1,
            P = !1,
            B = !1;
        function D(e) {
            if (O)
                if (
                    (!o.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources && (o.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack)),
                    !o.enumerateDevices && o.enumerateDevices && (o.enumerateDevices = o.enumerateDevices.bind(o)),
                    o.enumerateDevices)
                ) {
                    (x = []), (T = []), (k = []), (R = []), (A = !1), (M = !1), (E = !1), (P = !1), (B = !1);
                    var t = {};
                    o.enumerateDevices(function (i) {
                        (x = []),
                            (T = []),
                            (k = []),
                            (R = []),
                            i.forEach(function (e) {
                                var i = {};
                                for (var o in e)
                                    try {
                                        "function" != typeof e[o] && (i[o] = e[o]);
                                    } catch (e) {}
                                t[i.deviceId + i.label + i.kind] ||
                                    ("audio" === i.kind && (i.kind = "audioinput"),
                                    "video" === i.kind && (i.kind = "videoinput"),
                                    i.deviceId || (i.deviceId = i.id),
                                    i.id || (i.id = i.deviceId),
                                    i.label
                                        ? ("videoinput" !== i.kind || B || (B = !0), "audioinput" !== i.kind || P || (P = !0))
                                        : ((i.isCustomLabel = !0),
                                          "videoinput" === i.kind
                                              ? (i.label = "Camera " + (R.length + 1))
                                              : "audioinput" === i.kind
                                              ? (i.label = "Microphone " + (T.length + 1))
                                              : "audiooutput" === i.kind
                                              ? (i.label = "Speaker " + (k.length + 1))
                                              : (i.label = "Please invoke getUserMedia once."),
                                          void 0 !== I &&
                                              I.browser.isChrome &&
                                              I.browser.version >= 46 &&
                                              !/^(https:|chrome-extension:)$/g.test(location.protocol || "") &&
                                              "undefined" != typeof document &&
                                              "string" == typeof document.domain &&
                                              document.domain.search &&
                                              -1 === document.domain.search(/localhost|127.0./g) &&
                                              (i.label = "HTTPs is required to get label of this " + i.kind + " device.")),
                                    "audioinput" === i.kind && ((A = !0), -1 === T.indexOf(i) && T.push(i)),
                                    "audiooutput" === i.kind && ((M = !0), -1 === k.indexOf(i) && k.push(i)),
                                    "videoinput" === i.kind && ((E = !0), -1 === R.indexOf(i) && R.push(i)),
                                    x.push(i),
                                    (t[i.deviceId + i.label + i.kind] = i));
                            }),
                            void 0 !== I &&
                                ((I.MediaDevices = x),
                                (I.hasMicrophone = A),
                                (I.hasSpeakers = M),
                                (I.hasWebcam = E),
                                (I.isWebsiteHasWebcamPermissions = B),
                                (I.isWebsiteHasMicrophonePermissions = P),
                                (I.audioInputDevices = T),
                                (I.audioOutputDevices = k),
                                (I.videoInputDevices = R)),
                            e && e();
                    });
                } else e && e();
            else e && e();
        }
        var I = window.DetectRTC || {};
        (I.browser = (function () {
            o.appVersion;
            var e,
                t,
                i,
                n = o.userAgent,
                h = o.appName,
                u = "" + parseFloat(o.appVersion),
                f = parseInt(o.appVersion, 10);
            if (s) {
                h = "Opera";
                try {
                    f = (u = o.userAgent.split("OPR/")[1].split(" ")[0]).split(".")[0];
                } catch (e) {
                    (u = "0.0.0.0"), (f = 0);
                }
            } else
                d
                    ? ((t = n.indexOf("rv:")) > 0 ? (u = n.substring(t + 3)) : ((t = n.indexOf("MSIE")), (u = n.substring(t + 5))), (h = "IE"))
                    : l
                    ? ((t = n.indexOf("Chrome")), (h = "Chrome"), (u = n.substring(t + 7)))
                    : c
                    ? -1 !== n.indexOf("CriOS")
                        ? ((t = n.indexOf("CriOS")), (h = "Chrome"), (u = n.substring(t + 6)))
                        : -1 !== n.indexOf("FxiOS")
                        ? ((t = n.indexOf("FxiOS")), (h = "Firefox"), (u = n.substring(t + 6)))
                        : ((t = n.indexOf("Safari")),
                          (h = "Safari"),
                          (u = n.substring(t + 7)),
                          -1 !== (t = n.indexOf("Version")) && (u = n.substring(t + 8)),
                          -1 !== o.userAgent.indexOf("Version/") && (u = o.userAgent.split("Version/")[1].split(" ")[0]))
                    : a
                    ? ((t = n.indexOf("Firefox")), (h = "Firefox"), (u = n.substring(t + 8)))
                    : (e = n.lastIndexOf(" ") + 1) < (t = n.lastIndexOf("/")) && ((h = n.substring(e, t)), (u = n.substring(t + 1)), h.toLowerCase() === h.toUpperCase() && (h = o.appName));
            return (
                r && ((h = "Edge"), (u = o.userAgent.split("Edge/")[1])),
                -1 !== (i = u.search(/[; \)]/)) && (u = u.substring(0, i)),
                (f = parseInt("" + u, 10)),
                isNaN(f) && ((u = "" + parseFloat(o.appVersion)), (f = parseInt(o.appVersion, 10))),
                { fullVersion: u, version: f, name: h, isPrivateBrowsing: !1 }
            );
        })()),
            (function (e) {
                var t;
                try {
                    if (window.webkitRequestFileSystem)
                        window.webkitRequestFileSystem(
                            window.TEMPORARY,
                            1,
                            function () {
                                t = !1;
                            },
                            function (e) {
                                t = !0;
                            }
                        );
                    else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) {
                        var i;
                        try {
                            (i = window.indexedDB.open("test")).onerror = function () {
                                return !0;
                            };
                        } catch (e) {
                            t = !0;
                        }
                        void 0 === t &&
                            h(
                                function () {
                                    return "done" === i.readyState;
                                },
                                function (e) {
                                    e || (t = !i.result);
                                }
                            );
                    } else if (
                        (function (e) {
                            var t = e.toLowerCase();
                            if (0 === t.indexOf("msie") && 0 === t.indexOf("trident")) return !1;
                            var i = /(?:msie|rv:)\s?([\d\.]+)/.exec(t);
                            return !!(i && parseInt(i[1], 10) >= 10);
                        })(window.navigator.userAgent)
                    ) {
                        t = !1;
                        try {
                            window.indexedDB || (t = !0);
                        } catch (e) {
                            t = !0;
                        }
                    } else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) {
                        try {
                            window.localStorage.setItem("test", 1);
                        } catch (e) {
                            t = !0;
                        }
                        void 0 === t && ((t = !1), window.localStorage.removeItem("test"));
                    }
                } catch (e) {
                    t = !1;
                }
                h(
                    function () {
                        return void 0 !== t;
                    },
                    function (i) {
                        e(t);
                    }
                );
            })(function (e) {
                I.browser.isPrivateBrowsing = !!e;
            }),
            (I.browser["is" + I.browser.name] = !0),
            (I.osName = f),
            (I.osVersion = m);
        "object" == typeof process && "object" == typeof process.versions && process.versions["node-webkit"];
        var V = !1;
        ["RTCPeerConnection", "webkitRTCPeerConnection", "mozRTCPeerConnection", "RTCIceGatherer"].forEach(function (e) {
            V || (e in window && (V = !0));
        }),
            (I.isWebRTCSupported = V),
            (I.isORTCSupported = "undefined" != typeof RTCIceGatherer);
        var L = !1;
        (((I.browser.isChrome && I.browser.version >= 35) || (I.browser.isFirefox && I.browser.version >= 34) || (I.browser.isEdge && I.browser.version >= 17) || ("Android" === I.osName && I.browser.isChrome)) && (L = !0),
        (o.getDisplayMedia || (o.mediaDevices && o.mediaDevices.getDisplayMedia)) && (L = !0),
        /^(https:|chrome-extension:)$/g.test(location.protocol || "")) ||
            ((("undefined" != typeof document && "string" == typeof document.domain && document.domain.search && -1 === document.domain.search(/localhost|127.0./g) && (I.browser.isChrome || I.browser.isEdge || I.browser.isOpera)) ||
                I.browser.isFirefox) &&
                (L = !1));
        I.isScreenCapturingSupported = L;
        var F = { isSupported: !1, isCreateMediaStreamSourceSupported: !1 };
        ["AudioContext", "webkitAudioContext", "mozAudioContext", "msAudioContext"].forEach(function (e) {
            F.isSupported || (e in window && ((F.isSupported = !0), window[e] && "createMediaStreamSource" in window[e].prototype && (F.isCreateMediaStreamSourceSupported = !0)));
        }),
            (I.isAudioContextSupported = F.isSupported),
            (I.isCreateMediaStreamSourceSupported = F.isCreateMediaStreamSourceSupported);
        var j = !1;
        I.browser.isChrome && I.browser.version > 31 && (j = !0), (I.isRtpDataChannelsSupported = j);
        var N = !1;
        ((I.browser.isFirefox && I.browser.version > 28) || (I.browser.isChrome && I.browser.version > 25) || (I.browser.isOpera && I.browser.version >= 11)) && (N = !0), (I.isSctpDataChannelsSupported = N), (I.isMobileDevice = n);
        var U = !1;
        (o.getUserMedia || (o.mediaDevices && o.mediaDevices.getUserMedia)) && (U = !0),
            I.browser.isChrome &&
                I.browser.version >= 46 &&
                !/^(https:|chrome-extension:)$/g.test(location.protocol || "") &&
                "undefined" != typeof document &&
                "string" == typeof document.domain &&
                document.domain.search &&
                -1 === document.domain.search(/localhost|127.0./g) &&
                (U = "Requires HTTPs"),
            "Nodejs" === I.osName && (U = !1),
            (I.isGetUserMediaSupported = U);
        var W,
            H,
            z,
            X = "";
        screen.width && (X += (screen.width ? screen.width : "") + " x " + (screen.height ? screen.height : ""));
        (I.displayResolution = X),
            (I.displayAspectRatio = ((W = screen.width),
            (H = screen.height),
            (z = (function e(t, i) {
                return 0 == i ? t : e(i, t % i);
            })(W, H)),
            W / z / (H / z)).toFixed(2)),
            (I.isCanvasSupportsStreamCapturing = y),
            (I.isVideoSupportsStreamCapturing = S),
            "Chrome" == I.browser.name &&
                I.browser.version >= 53 &&
                (I.isCanvasSupportsStreamCapturing || (I.isCanvasSupportsStreamCapturing = "Requires chrome flag: enable-experimental-web-platform-features"),
                I.isVideoSupportsStreamCapturing || (I.isVideoSupportsStreamCapturing = "Requires chrome flag: enable-experimental-web-platform-features")),
            (I.DetectLocalIPAddress = function (e, t) {
                if (I.isWebRTCSupported) {
                    var i = !0,
                        o = !0; 
                    !(function (e, t) {
                        if ("undefined" == typeof document || "function" != typeof document.getElementById) return;
                        var i = {},
                            o = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
                        if (!o) {
                            var n = document.getElementById("iframe");
                            if (!n) return;
                            var r = n.contentWindow;
                            o = r.RTCPeerConnection || r.mozRTCPeerConnection || r.webkitRTCPeerConnection;
                        }
                        if (!o) return;
                        var s = null;
                        "Chrome" === I.browser && I.browser.version < 58 && (s = { optional: [{ RtpDataChannels: !0 }] });
                        var a = new o({ iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }, s);
                        t && (a.addStream ? a.addStream(t) : a.addTrack && t.getTracks()[0] && a.addTrack(t.getTracks()[0], t));
                        function c(t) {
                            if (t) {
                                var o = _.exec(t);
                                if (o) {
                                    var n = o[1],
                                        r = t.match(w),
                                        s = !0;
                                    void 0 === i[n] && e(n, r, s), (i[n] = !0);
                                }
                            } else e();
                        }
                        if (
                            ((a.onicecandidate = function (e) {
                                e.candidate && e.candidate.candidate ? c(e.candidate.candidate) : c();
                            }),
                            !t)
                        )
                            try {
                                a.createDataChannel("sctp", {});
                            } catch (e) {}
                        I.isPromisesSupported
                            ? a.createOffer().then(function (e) {
                                  a.setLocalDescription(e).then(l);
                              })
                            : a.createOffer(
                                  function (e) {
                                      a.setLocalDescription(e, l, function () {});
                                  },
                                  function () {}
                              );
                        function l() {
                            a.localDescription.sdp.split("\n").forEach(function (e) {
                                e && 0 === e.indexOf("a=candidate:") && c(e);
                            });
                        }
                    })(function (t) {
                        t ? (t.match(w) ? e("Local: " + t, (i = !1), o) : t.match(C) ? e("Public: " + t, i, (o = !1)) : e("Public: " + t, i, o)) : e();
                    }, t);
                }
            }),
            (I.isWebSocketsSupported = "WebSocket" in window && 2 === window.WebSocket.CLOSING),
            (I.isWebSocketsBlocked = !I.isWebSocketsSupported),
            "Nodejs" === I.osName && ((I.isWebSocketsSupported = !0), (I.isWebSocketsBlocked = !1)),
            (I.checkWebSocketsSupport = function (e) {
                e = e || function () {};
                try {
                    var t,
                        i = new WebSocket("wss://echo.websocket.org:443/");
                    (i.onopen = function () {
                        (I.isWebSocketsBlocked = !1), (t = new Date().getTime()), i.send("ping");
                    }),
                        (i.onmessage = function () {
                            (I.WebsocketLatency = new Date().getTime() - t + "ms"), e(), i.close(), (i = null);
                        }),
                        (i.onerror = function () {
                            (I.isWebSocketsBlocked = !0), e();
                        });
                } catch (t) {
                    (I.isWebSocketsBlocked = !0), e();
                }
            }),
            (I.load = function (e) {
                D((e = e || function () {}));
            }),
            (I.MediaDevices = void 0 !== x ? x : []),
            (I.hasMicrophone = A),
            (I.hasSpeakers = M),
            (I.hasWebcam = E),
            (I.isWebsiteHasWebcamPermissions = B),
            (I.isWebsiteHasMicrophonePermissions = P),
            (I.audioInputDevices = T),
            (I.audioOutputDevices = k),
            (I.videoInputDevices = R);
        var G = !1;
        "undefined" != typeof document && "function" == typeof document.createElement && "setSinkId" in document.createElement("video") && (G = !0), (I.isSetSinkIdSupported = G);
        var Y = !1;
        I.browser.isFirefox && "undefined" != typeof mozRTCPeerConnection
            ? "getSenders" in mozRTCPeerConnection.prototype && (Y = !0)
            : I.browser.isChrome && "undefined" != typeof webkitRTCPeerConnection && "getSenders" in webkitRTCPeerConnection.prototype && (Y = !0),
            (I.isRTPSenderReplaceTracksSupported = Y);
        var q = !1;
        I.browser.isFirefox && I.browser.version > 38 && (q = !0), (I.isRemoteStreamProcessingSupported = q);
        var $ = !1;
        "undefined" != typeof MediaStreamTrack && "applyConstraints" in MediaStreamTrack.prototype && ($ = !0), (I.isApplyConstraintsSupported = $);
        var K = !1;
        I.browser.isFirefox && I.browser.version >= 43 && (K = !0), (I.isMultiMonitorScreenCapturingSupported = K), (I.isPromisesSupported = !!("Promise" in window)), (I.version = "1.4.1"), void 0 === I && (window.DetectRTC = {});
        var J = window.MediaStream;
        void 0 === J && "undefined" != typeof webkitMediaStream && (J = webkitMediaStream),
            (I.MediaStream = void 0 !== J && "function" == typeof J && Object.keys(J.prototype)),
            "undefined" != typeof MediaStreamTrack ? (I.MediaStreamTrack = Object.keys(MediaStreamTrack.prototype)) : (I.MediaStreamTrack = !1);
        var Z = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
        (I.RTCPeerConnection = void 0 !== Z && Object.keys(Z.prototype)),
            (window.DetectRTC = I),
            "undefined" != typeof module && (module.exports = I),
            "function" == typeof define &&
                define.amd &&
                define("DetectRTC", [], function () {
                    return I;
                });
    })(),
    (function (e, t) {
        "object" == typeof exports && "undefined" != typeof module ? (module.exports = t()) : "function" == typeof define && define.amd ? define(t) : (e.QRious = t());
    })(this, function () {
        function e(e, i) {
            var n;
            return "function" == typeof Object.create ? (n = Object.create(e)) : ((o.prototype = e), (n = new o()), (o.prototype = null)), i && t(!0, n, i), n;
        }
        function t(e, t, i) {
            for (var o, s, a = 0, c = (i = r.call(arguments, 2)).length; a < c; a++) for (o in (s = i[a])) (e && !n.call(s, o)) || (t[o] = s[o]);
        }
        function i() {}
        var o = function () {},
            n = Object.prototype.hasOwnProperty,
            r = Array.prototype.slice,
            s = function (i, o, n, r) {
                var s = this;
                return (
                    "string" != typeof i && ((r = n), (n = o), (o = i), (i = null)),
                    "function" != typeof o &&
                        ((r = n),
                        (n = o),
                        (o = function () {
                            return s.apply(this, arguments);
                        })),
                    t(!1, o, s, r),
                    (o.prototype = e(s.prototype, n)),
                    (o.prototype.constructor = o),
                    (o.class_ = i || s.class_),
                    (o.super_ = s),
                    o
                );
            };
        (i.class_ = "Nevis"), (i.super_ = Object), (i.extend = s);
        var a = i,
            c = a.extend(
                function (e, t, i) {
                    (this.qrious = e), (this.element = t), (this.element.qrious = e), (this.enabled = Boolean(i));
                },
                {
                    draw: function (e) {},
                    getElement: function () {
                        return this.enabled || ((this.enabled = !0), this.render()), this.element;
                    },
                    getModuleSize: function (e) {
                        var t = this.qrious,
                            i = t.padding || 0,
                            o = Math.floor((t.size - 2 * i) / e.width);
                        return Math.max(1, o);
                    },
                    getOffset: function (e) {
                        var t = this.qrious,
                            i = t.padding;
                        if (null != i) return i;
                        var o = this.getModuleSize(e),
                            n = Math.floor((t.size - o * e.width) / 2);
                        return Math.max(0, n);
                    },
                    render: function (e) {
                        this.enabled && (this.resize(), this.reset(), this.draw(e));
                    },
                    reset: function () {},
                    resize: function () {},
                }
            ),
            l = c.extend({
                draw: function (e) {
                    var t,
                        i,
                        o = this.qrious,
                        n = this.getModuleSize(e),
                        r = this.getOffset(e),
                        s = this.element.getContext("2d");
                    for (s.fillStyle = o.foreground, s.globalAlpha = o.foregroundAlpha, t = 0; t < e.width; t++) for (i = 0; i < e.width; i++) e.buffer[i * e.width + t] && s.fillRect(n * t + r, n * i + r, n, n);
                },
                reset: function () {
                    var e = this.qrious,
                        t = this.element.getContext("2d"),
                        i = e.size;
                    (t.lineWidth = 1), t.clearRect(0, 0, i, i), (t.fillStyle = e.background), (t.globalAlpha = e.backgroundAlpha), t.fillRect(0, 0, i, i);
                },
                resize: function () {
                    var e = this.element;
                    e.width = e.height = this.qrious.size;
                },
            }),
            d = a.extend(null, { BLOCK: [0, 11, 15, 19, 23, 27, 31, 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28] }),
            h = a.extend(null, {
                BLOCKS: [
                    1,
                    0,
                    19,
                    7,
                    1,
                    0,
                    16,
                    10,
                    1,
                    0,
                    13,
                    13,
                    1,
                    0,
                    9,
                    17,
                    1,
                    0,
                    34,
                    10,
                    1,
                    0,
                    28,
                    16,
                    1,
                    0,
                    22,
                    22,
                    1,
                    0,
                    16,
                    28,
                    1,
                    0,
                    55,
                    15,
                    1,
                    0,
                    44,
                    26,
                    2,
                    0,
                    17,
                    18,
                    2,
                    0,
                    13,
                    22,
                    1,
                    0,
                    80,
                    20,
                    2,
                    0,
                    32,
                    18,
                    2,
                    0,
                    24,
                    26,
                    4,
                    0,
                    9,
                    16,
                    1,
                    0,
                    108,
                    26,
                    2,
                    0,
                    43,
                    24,
                    2,
                    2,
                    15,
                    18,
                    2,
                    2,
                    11,
                    22,
                    2,
                    0,
                    68,
                    18,
                    4,
                    0,
                    27,
                    16,
                    4,
                    0,
                    19,
                    24,
                    4,
                    0,
                    15,
                    28,
                    2,
                    0,
                    78,
                    20,
                    4,
                    0,
                    31,
                    18,
                    2,
                    4,
                    14,
                    18,
                    4,
                    1,
                    13,
                    26,
                    2,
                    0,
                    97,
                    24,
                    2,
                    2,
                    38,
                    22,
                    4,
                    2,
                    18,
                    22,
                    4,
                    2,
                    14,
                    26,
                    2,
                    0,
                    116,
                    30,
                    3,
                    2,
                    36,
                    22,
                    4,
                    4,
                    16,
                    20,
                    4,
                    4,
                    12,
                    24,
                    2,
                    2,
                    68,
                    18,
                    4,
                    1,
                    43,
                    26,
                    6,
                    2,
                    19,
                    24,
                    6,
                    2,
                    15,
                    28,
                    4,
                    0,
                    81,
                    20,
                    1,
                    4,
                    50,
                    30,
                    4,
                    4,
                    22,
                    28,
                    3,
                    8,
                    12,
                    24,
                    2,
                    2,
                    92,
                    24,
                    6,
                    2,
                    36,
                    22,
                    4,
                    6,
                    20,
                    26,
                    7,
                    4,
                    14,
                    28,
                    4,
                    0,
                    107,
                    26,
                    8,
                    1,
                    37,
                    22,
                    8,
                    4,
                    20,
                    24,
                    12,
                    4,
                    11,
                    22,
                    3,
                    1,
                    115,
                    30,
                    4,
                    5,
                    40,
                    24,
                    11,
                    5,
                    16,
                    20,
                    11,
                    5,
                    12,
                    24,
                    5,
                    1,
                    87,
                    22,
                    5,
                    5,
                    41,
                    24,
                    5,
                    7,
                    24,
                    30,
                    11,
                    7,
                    12,
                    24,
                    5,
                    1,
                    98,
                    24,
                    7,
                    3,
                    45,
                    28,
                    15,
                    2,
                    19,
                    24,
                    3,
                    13,
                    15,
                    30,
                    1,
                    5,
                    107,
                    28,
                    10,
                    1,
                    46,
                    28,
                    1,
                    15,
                    22,
                    28,
                    2,
                    17,
                    14,
                    28,
                    5,
                    1,
                    120,
                    30,
                    9,
                    4,
                    43,
                    26,
                    17,
                    1,
                    22,
                    28,
                    2,
                    19,
                    14,
                    28,
                    3,
                    4,
                    113,
                    28,
                    3,
                    11,
                    44,
                    26,
                    17,
                    4,
                    21,
                    26,
                    9,
                    16,
                    13,
                    26,
                    3,
                    5,
                    107,
                    28,
                    3,
                    13,
                    41,
                    26,
                    15,
                    5,
                    24,
                    30,
                    15,
                    10,
                    15,
                    28,
                    4,
                    4,
                    116,
                    28,
                    17,
                    0,
                    42,
                    26,
                    17,
                    6,
                    22,
                    28,
                    19,
                    6,
                    16,
                    30,
                    2,
                    7,
                    111,
                    28,
                    17,
                    0,
                    46,
                    28,
                    7,
                    16,
                    24,
                    30,
                    34,
                    0,
                    13,
                    24,
                    4,
                    5,
                    121,
                    30,
                    4,
                    14,
                    47,
                    28,
                    11,
                    14,
                    24,
                    30,
                    16,
                    14,
                    15,
                    30,
                    6,
                    4,
                    117,
                    30,
                    6,
                    14,
                    45,
                    28,
                    11,
                    16,
                    24,
                    30,
                    30,
                    2,
                    16,
                    30,
                    8,
                    4,
                    106,
                    26,
                    8,
                    13,
                    47,
                    28,
                    7,
                    22,
                    24,
                    30,
                    22,
                    13,
                    15,
                    30,
                    10,
                    2,
                    114,
                    28,
                    19,
                    4,
                    46,
                    28,
                    28,
                    6,
                    22,
                    28,
                    33,
                    4,
                    16,
                    30,
                    8,
                    4,
                    122,
                    30,
                    22,
                    3,
                    45,
                    28,
                    8,
                    26,
                    23,
                    30,
                    12,
                    28,
                    15,
                    30,
                    3,
                    10,
                    117,
                    30,
                    3,
                    23,
                    45,
                    28,
                    4,
                    31,
                    24,
                    30,
                    11,
                    31,
                    15,
                    30,
                    7,
                    7,
                    116,
                    30,
                    21,
                    7,
                    45,
                    28,
                    1,
                    37,
                    23,
                    30,
                    19,
                    26,
                    15,
                    30,
                    5,
                    10,
                    115,
                    30,
                    19,
                    10,
                    47,
                    28,
                    15,
                    25,
                    24,
                    30,
                    23,
                    25,
                    15,
                    30,
                    13,
                    3,
                    115,
                    30,
                    2,
                    29,
                    46,
                    28,
                    42,
                    1,
                    24,
                    30,
                    23,
                    28,
                    15,
                    30,
                    17,
                    0,
                    115,
                    30,
                    10,
                    23,
                    46,
                    28,
                    10,
                    35,
                    24,
                    30,
                    19,
                    35,
                    15,
                    30,
                    17,
                    1,
                    115,
                    30,
                    14,
                    21,
                    46,
                    28,
                    29,
                    19,
                    24,
                    30,
                    11,
                    46,
                    15,
                    30,
                    13,
                    6,
                    115,
                    30,
                    14,
                    23,
                    46,
                    28,
                    44,
                    7,
                    24,
                    30,
                    59,
                    1,
                    16,
                    30,
                    12,
                    7,
                    121,
                    30,
                    12,
                    26,
                    47,
                    28,
                    39,
                    14,
                    24,
                    30,
                    22,
                    41,
                    15,
                    30,
                    6,
                    14,
                    121,
                    30,
                    6,
                    34,
                    47,
                    28,
                    46,
                    10,
                    24,
                    30,
                    2,
                    64,
                    15,
                    30,
                    17,
                    4,
                    122,
                    30,
                    29,
                    14,
                    46,
                    28,
                    49,
                    10,
                    24,
                    30,
                    24,
                    46,
                    15,
                    30,
                    4,
                    18,
                    122,
                    30,
                    13,
                    32,
                    46,
                    28,
                    48,
                    14,
                    24,
                    30,
                    42,
                    32,
                    15,
                    30,
                    20,
                    4,
                    117,
                    30,
                    40,
                    7,
                    47,
                    28,
                    43,
                    22,
                    24,
                    30,
                    10,
                    67,
                    15,
                    30,
                    19,
                    6,
                    118,
                    30,
                    18,
                    31,
                    47,
                    28,
                    34,
                    34,
                    24,
                    30,
                    20,
                    61,
                    15,
                    30,
                ],
                FINAL_FORMAT: [
                    30660,
                    29427,
                    32170,
                    30877,
                    26159,
                    25368,
                    27713,
                    26998,
                    21522,
                    20773,
                    24188,
                    23371,
                    17913,
                    16590,
                    20375,
                    19104,
                    13663,
                    12392,
                    16177,
                    14854,
                    9396,
                    8579,
                    11994,
                    11245,
                    5769,
                    5054,
                    7399,
                    6608,
                    1890,
                    597,
                    3340,
                    2107,
                ],
                LEVELS: { L: 1, M: 2, Q: 3, H: 4 },
            }),
            u = a.extend(null, {
                EXPONENT: [
                    1,
                    2,
                    4,
                    8,
                    16,
                    32,
                    64,
                    128,
                    29,
                    58,
                    116,
                    232,
                    205,
                    135,
                    19,
                    38,
                    76,
                    152,
                    45,
                    90,
                    180,
                    117,
                    234,
                    201,
                    143,
                    3,
                    6,
                    12,
                    24,
                    48,
                    96,
                    192,
                    157,
                    39,
                    78,
                    156,
                    37,
                    74,
                    148,
                    53,
                    106,
                    212,
                    181,
                    119,
                    238,
                    193,
                    159,
                    35,
                    70,
                    140,
                    5,
                    10,
                    20,
                    40,
                    80,
                    160,
                    93,
                    186,
                    105,
                    210,
                    185,
                    111,
                    222,
                    161,
                    95,
                    190,
                    97,
                    194,
                    153,
                    47,
                    94,
                    188,
                    101,
                    202,
                    137,
                    15,
                    30,
                    60,
                    120,
                    240,
                    253,
                    231,
                    211,
                    187,
                    107,
                    214,
                    177,
                    127,
                    254,
                    225,
                    223,
                    163,
                    91,
                    182,
                    113,
                    226,
                    217,
                    175,
                    67,
                    134,
                    17,
                    34,
                    68,
                    136,
                    13,
                    26,
                    52,
                    104,
                    208,
                    189,
                    103,
                    206,
                    129,
                    31,
                    62,
                    124,
                    248,
                    237,
                    199,
                    147,
                    59,
                    118,
                    236,
                    197,
                    151,
                    51,
                    102,
                    204,
                    133,
                    23,
                    46,
                    92,
                    184,
                    109,
                    218,
                    169,
                    79,
                    158,
                    33,
                    66,
                    132,
                    21,
                    42,
                    84,
                    168,
                    77,
                    154,
                    41,
                    82,
                    164,
                    85,
                    170,
                    73,
                    146,
                    57,
                    114,
                    228,
                    213,
                    183,
                    115,
                    230,
                    209,
                    191,
                    99,
                    198,
                    145,
                    63,
                    126,
                    252,
                    229,
                    215,
                    179,
                    123,
                    246,
                    241,
                    255,
                    227,
                    219,
                    171,
                    75,
                    150,
                    49,
                    98,
                    196,
                    149,
                    55,
                    110,
                    220,
                    165,
                    87,
                    174,
                    65,
                    130,
                    25,
                    50,
                    100,
                    200,
                    141,
                    7,
                    14,
                    28,
                    56,
                    112,
                    224,
                    221,
                    167,
                    83,
                    166,
                    81,
                    162,
                    89,
                    178,
                    121,
                    242,
                    249,
                    239,
                    195,
                    155,
                    43,
                    86,
                    172,
                    69,
                    138,
                    9,
                    18,
                    36,
                    72,
                    144,
                    61,
                    122,
                    244,
                    245,
                    247,
                    243,
                    251,
                    235,
                    203,
                    139,
                    11,
                    22,
                    44,
                    88,
                    176,
                    125,
                    250,
                    233,
                    207,
                    131,
                    27,
                    54,
                    108,
                    216,
                    173,
                    71,
                    142,
                    0,
                ],
                LOG: [
                    255,
                    0,
                    1,
                    25,
                    2,
                    50,
                    26,
                    198,
                    3,
                    223,
                    51,
                    238,
                    27,
                    104,
                    199,
                    75,
                    4,
                    100,
                    224,
                    14,
                    52,
                    141,
                    239,
                    129,
                    28,
                    193,
                    105,
                    248,
                    200,
                    8,
                    76,
                    113,
                    5,
                    138,
                    101,
                    47,
                    225,
                    36,
                    15,
                    33,
                    53,
                    147,
                    142,
                    218,
                    240,
                    18,
                    130,
                    69,
                    29,
                    181,
                    194,
                    125,
                    106,
                    39,
                    249,
                    185,
                    201,
                    154,
                    9,
                    120,
                    77,
                    228,
                    114,
                    166,
                    6,
                    191,
                    139,
                    98,
                    102,
                    221,
                    48,
                    253,
                    226,
                    152,
                    37,
                    179,
                    16,
                    145,
                    34,
                    136,
                    54,
                    208,
                    148,
                    206,
                    143,
                    150,
                    219,
                    189,
                    241,
                    210,
                    19,
                    92,
                    131,
                    56,
                    70,
                    64,
                    30,
                    66,
                    182,
                    163,
                    195,
                    72,
                    126,
                    110,
                    107,
                    58,
                    40,
                    84,
                    250,
                    133,
                    186,
                    61,
                    202,
                    94,
                    155,
                    159,
                    10,
                    21,
                    121,
                    43,
                    78,
                    212,
                    229,
                    172,
                    115,
                    243,
                    167,
                    87,
                    7,
                    112,
                    192,
                    247,
                    140,
                    128,
                    99,
                    13,
                    103,
                    74,
                    222,
                    237,
                    49,
                    197,
                    254,
                    24,
                    227,
                    165,
                    153,
                    119,
                    38,
                    184,
                    180,
                    124,
                    17,
                    68,
                    146,
                    217,
                    35,
                    32,
                    137,
                    46,
                    55,
                    63,
                    209,
                    91,
                    149,
                    188,
                    207,
                    205,
                    144,
                    135,
                    151,
                    178,
                    220,
                    252,
                    190,
                    97,
                    242,
                    86,
                    211,
                    171,
                    20,
                    42,
                    93,
                    158,
                    132,
                    60,
                    57,
                    83,
                    71,
                    109,
                    65,
                    162,
                    31,
                    45,
                    67,
                    216,
                    183,
                    123,
                    164,
                    118,
                    196,
                    23,
                    73,
                    236,
                    127,
                    12,
                    111,
                    246,
                    108,
                    161,
                    59,
                    82,
                    41,
                    157,
                    85,
                    170,
                    251,
                    96,
                    134,
                    177,
                    187,
                    204,
                    62,
                    90,
                    203,
                    89,
                    95,
                    176,
                    156,
                    169,
                    160,
                    81,
                    11,
                    245,
                    22,
                    235,
                    122,
                    117,
                    44,
                    215,
                    79,
                    174,
                    213,
                    233,
                    230,
                    231,
                    173,
                    232,
                    116,
                    214,
                    244,
                    234,
                    168,
                    80,
                    88,
                    175,
                ],
            }),
            f = a.extend(null, {
                BLOCK: [3220, 1468, 2713, 1235, 3062, 1890, 2119, 1549, 2344, 2936, 1117, 2583, 1330, 2470, 1667, 2249, 2028, 3780, 481, 4011, 142, 3098, 831, 3445, 592, 2517, 1776, 2234, 1951, 2827, 1070, 2660, 1345, 3177],
            }),
            m = a.extend(
                function (e) {
                    var t,
                        i,
                        o,
                        n,
                        r,
                        s = e.value.length;
                    for (
                        this._badness = [], this._level = h.LEVELS[e.level], this._polynomial = [], this._value = e.value, this._version = 0, this._stringBuffer = [];
                        this._version < 40 &&
                        (this._version++, (o = 4 * (this._level - 1) + 16 * (this._version - 1)), (n = h.BLOCKS[o++]), (r = h.BLOCKS[o++]), (t = h.BLOCKS[o++]), (i = h.BLOCKS[o]), !(s <= (o = t * (n + r) + r - 3 + (this._version <= 9))));

                    );
                    (this._dataBlock = t), (this._eccBlock = i), (this._neccBlock1 = n), (this._neccBlock2 = r);
                    var a = (this.width = 17 + 4 * this._version);
                    (this.buffer = m._createArray(a * a)),
                        (this._ecc = m._createArray(t + (t + i) * (n + r) + r)),
                        (this._mask = m._createArray((a * (a + 1) + 1) / 2)),
                        this._insertFinders(),
                        this._insertAlignments(),
                        (this.buffer[8 + a * (a - 8)] = 1),
                        this._insertTimingGap(),
                        this._reverseMask(),
                        this._insertTimingRowAndColumn(),
                        this._insertVersion(),
                        this._syncMask(),
                        this._convertBitStream(s),
                        this._calculatePolynomial(),
                        this._appendEccToData(),
                        this._interleaveBlocks(),
                        this._pack(),
                        this._finish();
                },
                {
                    _addAlignment: function (e, t) {
                        var i,
                            o = this.buffer,
                            n = this.width;
                        for (o[e + n * t] = 1, i = -2; i < 2; i++) (o[e + i + n * (t - 2)] = 1), (o[e - 2 + n * (t + i + 1)] = 1), (o[e + 2 + n * (t + i)] = 1), (o[e + i + 1 + n * (t + 2)] = 1);
                        for (i = 0; i < 2; i++) this._setMask(e - 1, t + i), this._setMask(e + 1, t - i), this._setMask(e - i, t - 1), this._setMask(e + i, t + 1);
                    },
                    _appendData: function (e, t, i, o) {
                        var n,
                            r,
                            s,
                            a = this._polynomial,
                            c = this._stringBuffer;
                        for (r = 0; r < o; r++) c[i + r] = 0;
                        for (r = 0; r < t; r++) {
                            if (255 !== (n = u.LOG[c[e + r] ^ c[i]])) for (s = 1; s < o; s++) c[i + s - 1] = c[i + s] ^ u.EXPONENT[m._modN(n + a[o - s])];
                            else for (s = i; s < i + o; s++) c[s] = c[s + 1];
                            c[i + o - 1] = 255 === n ? 0 : u.EXPONENT[m._modN(n + a[0])];
                        }
                    },
                    _appendEccToData: function () {
                        var e,
                            t = 0,
                            i = this._dataBlock,
                            o = this._calculateMaxLength(),
                            n = this._eccBlock;
                        for (e = 0; e < this._neccBlock1; e++) this._appendData(t, i, o, n), (t += i), (o += n);
                        for (e = 0; e < this._neccBlock2; e++) this._appendData(t, i + 1, o, n), (t += i + 1), (o += n);
                    },
                    _applyMask: function (e) {
                        var t,
                            i,
                            o,
                            n,
                            r = this.buffer,
                            s = this.width;
                        switch (e) {
                            case 0:
                                for (n = 0; n < s; n++) for (o = 0; o < s; o++) (o + n) & 1 || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 1:
                                for (n = 0; n < s; n++) for (o = 0; o < s; o++) 1 & n || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 2:
                                for (n = 0; n < s; n++) for (t = 0, o = 0; o < s; o++, t++) 3 === t && (t = 0), t || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 3:
                                for (i = 0, n = 0; n < s; n++, i++) for (3 === i && (i = 0), t = i, o = 0; o < s; o++, t++) 3 === t && (t = 0), t || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 4:
                                for (n = 0; n < s; n++) for (t = 0, i = (n >> 1) & 1, o = 0; o < s; o++, t++) 3 === t && ((t = 0), (i = !i)), i || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 5:
                                for (i = 0, n = 0; n < s; n++, i++) for (3 === i && (i = 0), t = 0, o = 0; o < s; o++, t++) 3 === t && (t = 0), (o & n & 1) + !(!t | !i) || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 6:
                                for (i = 0, n = 0; n < s; n++, i++) for (3 === i && (i = 0), t = 0, o = 0; o < s; o++, t++) 3 === t && (t = 0), ((o & n & 1) + (t && t === i)) & 1 || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                                break;
                            case 7:
                                for (i = 0, n = 0; n < s; n++, i++) for (3 === i && (i = 0), t = 0, o = 0; o < s; o++, t++) 3 === t && (t = 0), ((t && t === i) + ((o + n) & 1)) & 1 || this._isMasked(o, n) || (r[o + n * s] ^= 1);
                        }
                    },
                    _calculateMaxLength: function () {
                        return this._dataBlock * (this._neccBlock1 + this._neccBlock2) + this._neccBlock2;
                    },
                    _calculatePolynomial: function () {
                        var e,
                            t,
                            i = this._eccBlock,
                            o = this._polynomial;
                        for (o[0] = 1, e = 0; e < i; e++) {
                            for (o[e + 1] = 1, t = e; t > 0; t--) o[t] = o[t] ? o[t - 1] ^ u.EXPONENT[m._modN(u.LOG[o[t]] + e)] : o[t - 1];
                            o[0] = u.EXPONENT[m._modN(u.LOG[o[0]] + e)];
                        }
                        for (e = 0; e <= i; e++) o[e] = u.LOG[o[e]];
                    },
                    _checkBadness: function () {
                        var e,
                            t,
                            i,
                            o,
                            n,
                            r = 0,
                            s = this._badness,
                            a = this.buffer,
                            c = this.width;
                        for (n = 0; n < c - 1; n++)
                            for (o = 0; o < c - 1; o++)
                                ((a[o + c * n] && a[o + 1 + c * n] && a[o + c * (n + 1)] && a[o + 1 + c * (n + 1)]) || !(a[o + c * n] || a[o + 1 + c * n] || a[o + c * (n + 1)] || a[o + 1 + c * (n + 1)])) && (r += m.N2);
                        var l = 0;
                        for (n = 0; n < c; n++) {
                            for (i = 0, s[0] = 0, e = 0, o = 0; o < c; o++) e === (t = a[o + c * n]) ? s[i]++ : (s[++i] = 1), (l += (e = t) ? 1 : -1);
                            r += this._getBadness(i);
                        }
                        l < 0 && (l = -l);
                        var d = 0,
                            h = l;
                        for (h += h << 2, h <<= 1; h > c * c; ) (h -= c * c), d++;
                        for (r += d * m.N4, o = 0; o < c; o++) {
                            for (i = 0, s[0] = 0, e = 0, n = 0; n < c; n++) e === (t = a[o + c * n]) ? s[i]++ : (s[++i] = 1), (e = t);
                            r += this._getBadness(i);
                        }
                        return r;
                    },
                    _convertBitStream: function (e) {
                        var t,
                            i,
                            o = this._ecc,
                            n = this._version;
                        for (i = 0; i < e; i++) o[i] = this._value.charCodeAt(i);
                        var r = (this._stringBuffer = o.slice()),
                            s = this._calculateMaxLength();
                        e >= s - 2 && ((e = s - 2), n > 9 && e--);
                        var a = e;
                        if (n > 9) {
                            for (r[a + 2] = 0, r[a + 3] = 0; a--; ) (t = r[a]), (r[a + 3] |= 255 & (t << 4)), (r[a + 2] = t >> 4);
                            (r[2] |= 255 & (e << 4)), (r[1] = e >> 4), (r[0] = 64 | (e >> 12));
                        } else {
                            for (r[a + 1] = 0, r[a + 2] = 0; a--; ) (t = r[a]), (r[a + 2] |= 255 & (t << 4)), (r[a + 1] = t >> 4);
                            (r[1] |= 255 & (e << 4)), (r[0] = 64 | (e >> 4));
                        }
                        for (a = e + 3 - (n < 10); a < s; ) (r[a++] = 236), (r[a++] = 17);
                    },
                    _getBadness: function (e) {
                        var t,
                            i = 0,
                            o = this._badness;
                        for (t = 0; t <= e; t++) o[t] >= 5 && (i += m.N1 + o[t] - 5);
                        for (t = 3; t < e - 1; t += 2)
                            o[t - 2] === o[t + 2] && o[t + 2] === o[t - 1] && o[t - 1] === o[t + 1] && 3 * o[t - 1] === o[t] && (0 === o[t - 3] || t + 3 > e || 3 * o[t - 3] >= 4 * o[t] || 3 * o[t + 3] >= 4 * o[t]) && (i += m.N3);
                        return i;
                    },
                    _finish: function () {
                        this._stringBuffer = this.buffer.slice();
                        var e,
                            t,
                            i = 0,
                            o = 3e4;
                        for (t = 0; t < 8 && (this._applyMask(t), (e = this._checkBadness()) < o && ((o = e), (i = t)), 7 !== i); t++) this.buffer = this._stringBuffer.slice();
                        i !== t && this._applyMask(i), (o = h.FINAL_FORMAT[i + ((this._level - 1) << 3)]);
                        var n = this.buffer,
                            r = this.width;
                        for (t = 0; t < 8; t++, o >>= 1) 1 & o && ((n[r - 1 - t + 8 * r] = 1), t < 6 ? (n[8 + r * t] = 1) : (n[8 + r * (t + 1)] = 1));
                        for (t = 0; t < 7; t++, o >>= 1) 1 & o && ((n[8 + r * (r - 7 + t)] = 1), t ? (n[6 - t + 8 * r] = 1) : (n[7 + 8 * r] = 1));
                    },
                    _interleaveBlocks: function () {
                        var e,
                            t,
                            i = this._dataBlock,
                            o = this._ecc,
                            n = this._eccBlock,
                            r = 0,
                            s = this._calculateMaxLength(),
                            a = this._neccBlock1,
                            c = this._neccBlock2,
                            l = this._stringBuffer;
                        for (e = 0; e < i; e++) {
                            for (t = 0; t < a; t++) o[r++] = l[e + t * i];
                            for (t = 0; t < c; t++) o[r++] = l[a * i + e + t * (i + 1)];
                        }
                        for (t = 0; t < c; t++) o[r++] = l[a * i + e + t * (i + 1)];
                        for (e = 0; e < n; e++) for (t = 0; t < a + c; t++) o[r++] = l[s + e + t * n];
                        this._stringBuffer = o;
                    },
                    _insertAlignments: function () {
                        var e,
                            t,
                            i,
                            o = this._version,
                            n = this.width;
                        if (o > 1)
                            for (e = d.BLOCK[o], i = n - 7; ; ) {
                                for (t = n - 7; t > e - 3 && (this._addAlignment(t, i), !(t < e)); ) t -= e;
                                if (i <= e + 9) break;
                                (i -= e), this._addAlignment(6, i), this._addAlignment(i, 6);
                            }
                    },
                    _insertFinders: function () {
                        var e,
                            t,
                            i,
                            o,
                            n = this.buffer,
                            r = this.width;
                        for (e = 0; e < 3; e++) {
                            for (t = 0, o = 0, 1 === e && (t = r - 7), 2 === e && (o = r - 7), n[o + 3 + r * (t + 3)] = 1, i = 0; i < 6; i++)
                                (n[o + i + r * t] = 1), (n[o + r * (t + i + 1)] = 1), (n[o + 6 + r * (t + i)] = 1), (n[o + i + 1 + r * (t + 6)] = 1);
                            for (i = 1; i < 5; i++) this._setMask(o + i, t + 1), this._setMask(o + 1, t + i + 1), this._setMask(o + 5, t + i), this._setMask(o + i + 1, t + 5);
                            for (i = 2; i < 4; i++) (n[o + i + r * (t + 2)] = 1), (n[o + 2 + r * (t + i + 1)] = 1), (n[o + 4 + r * (t + i)] = 1), (n[o + i + 1 + r * (t + 4)] = 1);
                        }
                    },
                    _insertTimingGap: function () {
                        var e,
                            t,
                            i = this.width;
                        for (t = 0; t < 7; t++) this._setMask(7, t), this._setMask(i - 8, t), this._setMask(7, t + i - 7);
                        for (e = 0; e < 8; e++) this._setMask(e, 7), this._setMask(e + i - 8, 7), this._setMask(e, i - 8);
                    },
                    _insertTimingRowAndColumn: function () {
                        var e,
                            t = this.buffer,
                            i = this.width;
                        for (e = 0; e < i - 14; e++) 1 & e ? (this._setMask(8 + e, 6), this._setMask(6, 8 + e)) : ((t[8 + e + 6 * i] = 1), (t[6 + i * (8 + e)] = 1));
                    },
                    _insertVersion: function () {
                        var e,
                            t,
                            i,
                            o,
                            n = this.buffer,
                            r = this._version,
                            s = this.width;
                        if (r > 6)
                            for (e = f.BLOCK[r - 7], t = 17, i = 0; i < 6; i++)
                                for (o = 0; o < 3; o++, t--)
                                    1 & (t > 11 ? r >> (t - 12) : e >> t) ? ((n[5 - i + s * (2 - o + s - 11)] = 1), (n[2 - o + s - 11 + s * (5 - i)] = 1)) : (this._setMask(5 - i, 2 - o + s - 11), this._setMask(2 - o + s - 11, 5 - i));
                    },
                    _isMasked: function (e, t) {
                        var i = m._getMaskBit(e, t);
                        return 1 === this._mask[i];
                    },
                    _pack: function () {
                        var e,
                            t,
                            i,
                            o = 1,
                            n = 1,
                            r = this.width,
                            s = r - 1,
                            a = r - 1,
                            c = (this._dataBlock + this._eccBlock) * (this._neccBlock1 + this._neccBlock2) + this._neccBlock2;
                        for (t = 0; t < c; t++)
                            for (e = this._stringBuffer[t], i = 0; i < 8; i++, e <<= 1) {
                                128 & e && (this.buffer[s + r * a] = 1);
                                do {
                                    n ? s-- : (s++, o ? (0 !== a ? a-- : ((o = !o), 6 == (s -= 2) && (s--, (a = 9)))) : a !== r - 1 ? a++ : ((o = !o), 6 == (s -= 2) && (s--, (a -= 8)))), (n = !n);
                                } while (this._isMasked(s, a));
                            }
                    },
                    _reverseMask: function () {
                        var e,
                            t,
                            i = this.width;
                        for (e = 0; e < 9; e++) this._setMask(e, 8);
                        for (e = 0; e < 8; e++) this._setMask(e + i - 8, 8), this._setMask(8, e);
                        for (t = 0; t < 7; t++) this._setMask(8, t + i - 7);
                    },
                    _setMask: function (e, t) {
                        var i = m._getMaskBit(e, t);
                        this._mask[i] = 1;
                    },
                    _syncMask: function () {
                        var e,
                            t,
                            i = this.width;
                        for (t = 0; t < i; t++) for (e = 0; e <= t; e++) this.buffer[e + i * t] && this._setMask(e, t);
                    },
                },
                {
                    _createArray: function (e) {
                        var t,
                            i = [];
                        for (t = 0; t < e; t++) i[t] = 0;
                        return i;
                    },
                    _getMaskBit: function (e, t) {
                        var i;
                        return e > t && ((i = e), (e = t), (t = i)), (i = t), (i += t * t), (i >>= 1) + e;
                    },
                    _modN: function (e) {
                        for (; e >= 255; ) e = ((e -= 255) >> 8) + (255 & e);
                        return e;
                    },
                    N1: 3,
                    N2: 3,
                    N3: 40,
                    N4: 10,
                }
            ),
            g = m,
            p = c.extend({
                draw: function () {
                    this.element.src = this.qrious.toDataURL();
                },
                reset: function () {
                    this.element.src = "";
                },
                resize: function () {
                    var e = this.element;
                    e.width = e.height = this.qrious.size;
                },
            }),
            v = a.extend(
                function (e, t, i, o) {
                    (this.name = e), (this.modifiable = Boolean(t)), (this.defaultValue = i), (this._valueTransformer = o);
                },
                {
                    transform: function (e) {
                        var t = this._valueTransformer;
                        return "function" == typeof t ? t(e, this) : e;
                    },
                }
            ),
            b = a.extend(null, {
                abs: function (e) {
                    return null != e ? Math.abs(e) : null;
                },
                hasOwn: function (e, t) {
                    return Object.prototype.hasOwnProperty.call(e, t);
                },
                noop: function () {},
                toUpperCase: function (e) {
                    return null != e ? e.toUpperCase() : null;
                },
            }),
            y = a.extend(
                function (e) {
                    (this.options = {}),
                        e.forEach(function (e) {
                            this.options[e.name] = e;
                        }, this);
                },
                {
                    exists: function (e) {
                        return null != this.options[e];
                    },
                    get: function (e, t) {
                        return y._get(this.options[e], t);
                    },
                    getAll: function (e) {
                        var t,
                            i = this.options,
                            o = {};
                        for (t in i) b.hasOwn(i, t) && (o[t] = y._get(i[t], e));
                        return o;
                    },
                    init: function (e, t, i) {
                        var o, n;
                        for (o in ("function" != typeof i && (i = b.noop), this.options)) b.hasOwn(this.options, o) && ((n = this.options[o]), y._set(n, n.defaultValue, t), y._createAccessor(n, t, i));
                        this._setAll(e, t, !0);
                    },
                    set: function (e, t, i) {
                        return this._set(e, t, i);
                    },
                    setAll: function (e, t) {
                        return this._setAll(e, t);
                    },
                    _set: function (e, t, i, o) {
                        var n = this.options[e];
                        if (!n) throw new Error("Invalid option: " + e);
                        if (!n.modifiable && !o) throw new Error("Option cannot be modified: " + e);
                        return y._set(n, t, i);
                    },
                    _setAll: function (e, t, i) {
                        if (!e) return !1;
                        var o,
                            n = !1;
                        for (o in e) b.hasOwn(e, o) && this._set(o, e[o], t, i) && (n = !0);
                        return n;
                    },
                },
                {
                    _createAccessor: function (e, t, i) {
                        var o = {
                            get: function () {
                                return y._get(e, t);
                            },
                        };
                        e.modifiable &&
                            (o.set = function (o) {
                                y._set(e, o, t) && i(o, e);
                            }),
                            Object.defineProperty(t, e.name, o);
                    },
                    _get: function (e, t) {
                        return t["_" + e.name];
                    },
                    _set: function (e, t, i) {
                        var o = "_" + e.name,
                            n = i[o],
                            r = e.transform(null != t ? t : e.defaultValue);
                        return (i[o] = r), r !== n;
                    },
                }
            ),
            S = y,
            w = a.extend(
                function () {
                    this._services = {};
                },
                {
                    getService: function (e) {
                        var t = this._services[e];
                        if (!t) throw new Error("Service is not being managed with name: " + e);
                        return t;
                    },
                    setService: function (e, t) {
                        if (this._services[e]) throw new Error("Service is already managed with name: " + e);
                        t && (this._services[e] = t);
                    },
                }
            ),
            _ = new S([
                new v("background", !0, "white"),
                new v("backgroundAlpha", !0, 1, b.abs),
                new v("element"),
                new v("foreground", !0, "black"),
                new v("foregroundAlpha", !0, 1, b.abs),
                new v("level", !0, "L", b.toUpperCase),
                new v("mime", !0, "image/png"),
                new v("padding", !0, null, b.abs),
                new v("size", !0, 100, b.abs),
                new v("value", !0, ""),
            ]),
            C = new w(),
            x = a.extend(
                function (e) {
                    _.init(e, this, this.update.bind(this));
                    var t = _.get("element", this),
                        i = C.getService("element"),
                        o = t && i.isCanvas(t) ? t : i.createCanvas(),
                        n = t && i.isImage(t) ? t : i.createImage();
                    (this._canvasRenderer = new l(this, o, !0)), (this._imageRenderer = new p(this, n, n === t)), this.update();
                },
                {
                    get: function () {
                        return _.getAll(this);
                    },
                    set: function (e) {
                        _.setAll(e, this) && this.update();
                    },
                    toDataURL: function (e) {
                        return this.canvas.toDataURL(e || this.mime);
                    },
                    update: function () {
                        var e = new g({ level: this.level, value: this.value });
                        this._canvasRenderer.render(e), this._imageRenderer.render(e);
                    },
                },
                {
                    use: function (e) {
                        C.setService(e.getName(), e);
                    },
                }
            );
        Object.defineProperties(x.prototype, {
            canvas: {
                get: function () {
                    return this._canvasRenderer.getElement();
                },
            },
            image: {
                get: function () {
                    return this._imageRenderer.getElement();
                },
            },
        });
        var T = x,
            k = a
                .extend({ getName: function () {} })
                .extend({
                    createCanvas: function () {},
                    createImage: function () {},
                    getName: function () {
                        return "element";
                    },
                    isCanvas: function (e) {},
                    isImage: function (e) {},
                })
                .extend({
                    createCanvas: function () {
                        return document.createElement("canvas");
                    },
                    createImage: function () {
                        return document.createElement("img");
                    },
                    isCanvas: function (e) {
                        return e instanceof HTMLCanvasElement;
                    },
                    isImage: function (e) {
                        return e instanceof HTMLImageElement;
                    },
                });
        return T.use(new k()), T;
    });
var jsdom,
    virtualWindow,
    fabric = fabric || { version: "4.6.0" };
function resizeCanvasIfNeeded(e) {
    var t = e.targetCanvas,
        i = t.width,
        o = t.height,
        n = e.destinationWidth;
    e = e.destinationHeight;
    (i === n && o === e) || ((t.width = n), (t.height = e));
}
function copyGLTo2DDrawImage(e, t) {
    var i = e.canvas,
        o = t.targetCanvas;
    (e = o.getContext("2d")).translate(0, o.height), e.scale(1, -1), (t = i.height - o.height), e.drawImage(i, 0, t, o.width, o.height, 0, 0, o.width, o.height);
}
function copyGLTo2DPutImageData(e, t) {
    var i = t.targetCanvas.getContext("2d"),
        o = t.destinationWidth,
        n = t.destinationHeight,
        r = o * n * 4;
    (t = new Uint8Array(this.imageBuffer, 0, r)), (r = new Uint8ClampedArray(this.imageBuffer, 0, r));
    e.readPixels(0, 0, o, n, e.RGBA, e.UNSIGNED_BYTE, t), (n = new ImageData(r, o, n)), i.putImageData(n, 0, 0);
}
"undefined" != typeof exports
    ? (exports.fabric = fabric)
    : "function" == typeof define &&
      define.amd &&
      define([], function () {
          return fabric;
      }),
    "undefined" != typeof document && "undefined" != typeof window
        ? (document instanceof ("undefined" != typeof HTMLDocument ? HTMLDocument : Document) ? (fabric.document = document) : (fabric.document = document.implementation.createHTMLDocument("")), (fabric.window = window))
        : ((virtualWindow = new (jsdom = require("jsdom")).JSDOM(decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E"), {
              features: { FetchExternalResources: ["img"] },
              resources: "usable",
          }).window),
          (fabric.document = virtualWindow.document),
          (fabric.jsdomImplForWrapper = require("jsdom/lib/jsdom/living/generated/utils").implForWrapper),
          (fabric.nodeCanvas = require("jsdom/lib/jsdom/utils").Canvas),
          (fabric.window = virtualWindow),
          (DOMParser = fabric.window.DOMParser)),
    (fabric.isTouchSupported = "ontouchstart" in fabric.window || "ontouchstart" in fabric.document || (fabric.window && fabric.window.navigator && 0 < fabric.window.navigator.maxTouchPoints)),
    (fabric.isLikelyNode = "undefined" != typeof Buffer && "undefined" == typeof window),
    (fabric.SHARED_ATTRIBUTES = [
        "display",
        "transform",
        "fill",
        "fill-opacity",
        "fill-rule",
        "opacity",
        "stroke",
        "stroke-dasharray",
        "stroke-linecap",
        "stroke-dashoffset",
        "stroke-linejoin",
        "stroke-miterlimit",
        "stroke-opacity",
        "stroke-width",
        "id",
        "paint-order",
        "vector-effect",
        "instantiated_by_use",
        "clip-path",
    ]),
    (fabric.DPI = 96),
    (fabric.reNum = "(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:[eE][-+]?\\d+)?)"),
    (fabric.commaWsp = "(?:\\s+,?\\s*|,\\s*)"),
    (fabric.rePathCommand = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:[eE][-+]?\d+)?)/gi),
    (fabric.reNonWord = /[ \n\.,;!\?\-]/),
    (fabric.fontPaths = {}),
    (fabric.iMatrix = [1, 0, 0, 1, 0, 0]),
    (fabric.svgNS = "http://www.w3.org/2000/svg"),
    (fabric.perfLimitSizeTotal = 2097152),
    (fabric.maxCacheSideLimit = 4096),
    (fabric.minCacheSideLimit = 256),
    (fabric.charWidthsCache = {}),
    (fabric.textureSize = 2048),
    (fabric.disableStyleCopyPaste = !1),
    (fabric.enableGLFiltering = !0),
    (fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1),
    (fabric.browserShadowBlurConstant = 1),
    (fabric.arcToSegmentsCache = {}),
    (fabric.boundsOfCurveCache = {}),
    (fabric.cachesBoundsOfCurve = !0),
    (fabric.forceGLPutImageData = !1),
    (fabric.initFilterBackend = function () {
        return fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)
            ? (console.log("max texture size: " + fabric.maxTextureSize), new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }))
            : fabric.Canvas2dFilterBackend
            ? new fabric.Canvas2dFilterBackend()
            : void 0;
    }),
    "undefined" != typeof document && "undefined" != typeof window && (window.fabric = fabric),
    (function () {
        function e(e, t) {
            this.__eventListeners[e] && ((e = this.__eventListeners[e]), t ? (e[e.indexOf(t)] = !1) : fabric.util.array.fill(e, !1));
        }
        function t(e, t) {
            var i = function () {
                t.apply(this, arguments), this.off(e, i);
            }.bind(this);
            this.on(e, i);
        }
        fabric.Observable = {
            fire: function (e, t) {
                if (!this.__eventListeners) return this;
                var i = this.__eventListeners[e];
                if (!i) return this;
                for (var o = 0, n = i.length; o < n; o++) i[o] && i[o].call(this, t || {});
                return (
                    (this.__eventListeners[e] = i.filter(function (e) {
                        return !1 !== e;
                    })),
                    this
                );
            },
            on: function (e, t) {
                if ((this.__eventListeners || (this.__eventListeners = {}), 1 === arguments.length)) for (var i in e) this.on(i, e[i]);
                else this.__eventListeners[e] || (this.__eventListeners[e] = []), this.__eventListeners[e].push(t);
                return this;
            },
            once: function (e, i) {
                if (1 === arguments.length) for (var o in e) t.call(this, o, e[o]);
                else t.call(this, e, i);
                return this;
            },
            off: function (t, i) {
                if (!this.__eventListeners) return this;
                if (0 === arguments.length) for (t in this.__eventListeners) e.call(this, t);
                else if (1 === arguments.length && "object" == typeof arguments[0]) for (var o in t) e.call(this, o, t[o]);
                else e.call(this, t, i);
                return this;
            },
        };
    })(),
    (fabric.Collection = {
        _objects: [],
        add: function () {
            if ((this._objects.push.apply(this._objects, arguments), this._onObjectAdded)) for (var e = 0, t = arguments.length; e < t; e++) this._onObjectAdded(arguments[e]);
            return this.renderOnAddRemove && this.requestRenderAll(), this;
        },
        insertAt: function (e, t, i) {
            var o = this._objects;
            return i ? (o[t] = e) : o.splice(t, 0, e), this._onObjectAdded && this._onObjectAdded(e), this.renderOnAddRemove && this.requestRenderAll(), this;
        },
        remove: function () {
            for (var e, t = this._objects, i = !1, o = 0, n = arguments.length; o < n; o++) -1 !== (e = t.indexOf(arguments[o])) && ((i = !0), t.splice(e, 1), this._onObjectRemoved && this._onObjectRemoved(arguments[o]));
            return this.renderOnAddRemove && i && this.requestRenderAll(), this;
        },
        forEachObject: function (e, t) {
            for (var i = this.getObjects(), o = 0, n = i.length; o < n; o++) e.call(t, i[o], o, i);
            return this;
        },
        getObjects: function (e) {
            return void 0 === e
                ? this._objects.concat()
                : this._objects.filter(function (t) {
                      return t.type === e;
                  });
        },
        item: function (e) {
            return this._objects[e];
        },
        isEmpty: function () {
            return 0 === this._objects.length;
        },
        size: function () {
            return this._objects.length;
        },
        contains: function (e, t) {
            return (
                -1 < this._objects.indexOf(e) ||
                (!!t &&
                    this._objects.some(function (t) {
                        return "function" == typeof t.contains && t.contains(e, !0);
                    }))
            );
        },
        complexity: function () {
            return this._objects.reduce(function (e, t) {
                return e + (t.complexity ? t.complexity() : 0);
            }, 0);
        },
    }),
    (fabric.CommonMethods = {
        _setOptions: function (e) {
            for (var t in e) this.set(t, e[t]);
        },
        _initGradient: function (e, t) {
            !e || !e.colorStops || e instanceof fabric.Gradient || this.set(t, new fabric.Gradient(e));
        },
        _initPattern: function (e, t, i) {
            !e || !e.source || e instanceof fabric.Pattern ? i && i() : this.set(t, new fabric.Pattern(e, i));
        },
        _setObject: function (e) {
            for (var t in e) this._set(t, e[t]);
        },
        set: function (e, t) {
            return "object" == typeof e ? this._setObject(e) : this._set(e, t), this;
        },
        _set: function (e, t) {
            this[e] = t;
        },
        toggle: function (e) {
            var t = this.get(e);
            return "boolean" == typeof t && this.set(e, !t), this;
        },
        get: function (e) {
            return this[e];
        },
    }),
    (function (e) {
        var t = Math.sqrt,
            i = Math.atan2,
            o = Math.pow,
            n = Math.PI / 180,
            r = Math.PI / 2;
        fabric.util = {
            cos: function (e) {
                if (0 === e) return 1;
                switch ((e = e < 0 ? -e : e) / r) {
                    case 1:
                    case 3:
                        return 0;
                    case 2:
                        return -1;
                }
                return Math.cos(e);
            },
            sin: function (e) {
                if (0 === e) return 0;
                var t = e < 0 ? -1 : 1;
                switch (e / r) {
                    case 1:
                        return t;
                    case 2:
                        return 0;
                    case 3:
                        return -t;
                }
                return Math.sin(e);
            },
            removeFromArray: function (e, t) {
                return -1 !== (t = e.indexOf(t)) && e.splice(t, 1), e;
            },
            getRandomInt: function (e, t) {
                return Math.floor(Math.random() * (t - e + 1)) + e;
            },
            degreesToRadians: function (e) {
                return e * n;
            },
            radiansToDegrees: function (e) {
                return e / n;
            },
            rotatePoint: function (e, t, i) {
                return (e = new fabric.Point(e.x - t.x, e.y - t.y)), (i = fabric.util.rotateVector(e, i)), new fabric.Point(i.x, i.y).addEquals(t);
            },
            rotateVector: function (e, t) {
                var i = fabric.util.sin(t);
                t = fabric.util.cos(t);
                return { x: e.x * t - e.y * i, y: e.x * i + e.y * t };
            },
            transformPoint: function (e, t, i) {
                return i ? new fabric.Point(t[0] * e.x + t[2] * e.y, t[1] * e.x + t[3] * e.y) : new fabric.Point(t[0] * e.x + t[2] * e.y + t[4], t[1] * e.x + t[3] * e.y + t[5]);
            },
            makeBoundingBoxFromPoints: function (e, t) {
                if (t) for (var i = 0; i < e.length; i++) e[i] = fabric.util.transformPoint(e[i], t);
                var o = [e[0].x, e[1].x, e[2].x, e[3].x],
                    n = fabric.util.array.min(o),
                    r = fabric.util.array.max(o) - n,
                    s = [e[0].y, e[1].y, e[2].y, e[3].y];
                return { left: n, top: (o = fabric.util.array.min(s)), width: r, height: fabric.util.array.max(s) - o };
            },
            invertTransform: function (e) {
                var t = [(t = 1 / (e[0] * e[3] - e[1] * e[2])) * e[3], -t * e[1], -t * e[2], t * e[0]];
                e = fabric.util.transformPoint({ x: e[4], y: e[5] }, t, !0);
                return (t[4] = -e.x), (t[5] = -e.y), t;
            },
            toFixed: function (e, t) {
                return parseFloat(Number(e).toFixed(t));
            },
            parseUnit: function (e, t) {
                var i = /\D{0,2}$/.exec(e),
                    o = parseFloat(e);
                switch (((t = t || fabric.Text.DEFAULT_SVG_FONT_SIZE), i[0])) {
                    case "mm":
                        return (o * fabric.DPI) / 25.4;
                    case "cm":
                        return (o * fabric.DPI) / 2.54;
                    case "in":
                        return o * fabric.DPI;
                    case "pt":
                        return (o * fabric.DPI) / 72;
                    case "pc":
                        return ((o * fabric.DPI) / 72) * 12;
                    case "em":
                        return o * t;
                    default:
                        return o;
                }
            },
            falseFunction: function () {
                return !1;
            },
            getKlass: function (e, t) {
                return (e = fabric.util.string.camelize(e.charAt(0).toUpperCase() + e.slice(1))), fabric.util.resolveNamespace(t)[e];
            },
            getSvgAttributes: function (e) {
                var t = ["instantiated_by_use", "style", "id", "class"];
                switch (e) {
                    case "linearGradient":
                        t = t.concat(["x1", "y1", "x2", "y2", "gradientUnits", "gradientTransform"]);
                        break;
                    case "radialGradient":
                        t = t.concat(["gradientUnits", "gradientTransform", "cx", "cy", "r", "fx", "fy", "fr"]);
                        break;
                    case "stop":
                        t = t.concat(["offset", "stop-color", "stop-opacity"]);
                }
                return t;
            },
            resolveNamespace: function (t) {
                if (!t) return fabric;
                for (var i = t.split("."), o = i.length, n = e || fabric.window, r = 0; r < o; ++r) n = n[i[r]];
                return n;
            },
            loadImage: function (e, t, i, o) {
                var n, r;
                e
                    ? ((r = function () {
                          t && t.call(i, n, !1), (n = n.onload = n.onerror = null);
                      }),
                      ((n = fabric.util.createImage()).onload = r),
                      (n.onerror = function () {
                          fabric.log("Error loading " + n.src), t && t.call(i, null, !0), (n = n.onload = n.onerror = null);
                      }),
                      0 !== e.indexOf("data") && null != o && (n.crossOrigin = o),
                      "data:image/svg" === e.substring(0, 14) && ((n.onload = null), fabric.util.loadImageInDom(n, r)),
                      (n.src = e))
                    : t && t.call(i, e);
            },
            loadImageInDom: function (e, t) {
                var i = fabric.document.createElement("div");
                (i.style.width = i.style.height = "1px"),
                    (i.style.left = i.style.top = "-100%"),
                    (i.style.position = "absolute"),
                    i.appendChild(e),
                    fabric.document.querySelector("body").appendChild(i),
                    (e.onload = function () {
                        t(), i.parentNode.removeChild(i), (i = null);
                    });
            },
            enlivenObjects: function (e, t, i, o) {
                var n = [],
                    r = 0,
                    s = (e = e || []).length;
                function a() {
                    ++r === s &&
                        t &&
                        t(
                            n.filter(function (e) {
                                return e;
                            })
                        );
                }
                s
                    ? e.forEach(function (e, t) {
                          e && e.type
                              ? fabric.util.getKlass(e.type, i).fromObject(e, function (i, r) {
                                    r || (n[t] = i), o && o(e, i, r), a();
                                })
                              : a();
                      })
                    : t && t(n);
            },
            enlivenPatterns: function (e, t) {
                function i() {
                    ++n === r && t && t(o);
                }
                var o = [],
                    n = 0,
                    r = (e = e || []).length;
                r
                    ? e.forEach(function (e, t) {
                          e && e.source
                              ? new fabric.Pattern(e, function (e) {
                                    (o[t] = e), i();
                                })
                              : ((o[t] = e), i());
                      })
                    : t && t(o);
            },
            groupSVGElements: function (e, t, i) {
                return e && 1 === e.length
                    ? e[0]
                    : (t && (t.width && t.height ? (t.centerPoint = { x: t.width / 2, y: t.height / 2 }) : (delete t.width, delete t.height)), (t = new fabric.Group(e, t)), void 0 !== i && (t.sourcePath = i), t);
            },
            populateWithProperties: function (e, t, i) {
                if (i && "[object Array]" === Object.prototype.toString.call(i)) for (var o = 0, n = i.length; o < n; o++) i[o] in e && (t[i[o]] = e[i[o]]);
            },
            drawDashedLine: function (e, o, n, r, s, a) {
                var c = t((r = r - o) * r + (s = s - n) * s),
                    l = ((r = i(s, r)), a.length),
                    d = 0,
                    h = !0;
                for (e.save(), e.translate(o, n), e.moveTo(0, 0), e.rotate(r), o = 0; o < c; ) c < (o += a[d++ % l]) && (o = c), e[h ? "lineTo" : "moveTo"](o, 0), (h = !h);
                e.restore();
            },
            createCanvasElement: function () {
                return fabric.document.createElement("canvas");
            },
            copyCanvasElement: function (e) {
                var t = fabric.util.createCanvasElement();
                return (t.width = e.width), (t.height = e.height), t.getContext("2d").drawImage(e, 0, 0), t;
            },
            toDataURL: function (e, t, i) {
                return e.toDataURL("image/" + t, i);
            },
            createImage: function () {
                return fabric.document.createElement("img");
            },
            multiplyTransformMatrices: function (e, t, i) {
                return [e[0] * t[0] + e[2] * t[1], e[1] * t[0] + e[3] * t[1], e[0] * t[2] + e[2] * t[3], e[1] * t[2] + e[3] * t[3], i ? 0 : e[0] * t[4] + e[2] * t[5] + e[4], i ? 0 : e[1] * t[4] + e[3] * t[5] + e[5]];
            },
            qrDecompose: function (e) {
                var r = i(e[1], e[0]),
                    s = o(e[0], 2) + o(e[1], 2),
                    a = t(s),
                    c = (e[0] * e[3] - e[2] * e[1]) / a;
                s = i(e[0] * e[2] + e[1] * e[3], s);
                return { angle: r / n, scaleX: a, scaleY: c, skewX: s / n, skewY: 0, translateX: e[4], translateY: e[5] };
            },
            calcRotateMatrix: function (e) {
                if (!e.angle) return fabric.iMatrix.concat();
                var t = fabric.util.degreesToRadians(e.angle);
                return [(e = fabric.util.cos(t)), (t = fabric.util.sin(t)), -t, e, 0, 0];
            },
            calcDimensionsMatrix: function (e) {
                var t = void 0 === e.scaleX ? 1 : e.scaleX,
                    i = void 0 === e.scaleY ? 1 : e.scaleY,
                    o = [e.flipX ? -t : t, 0, 0, e.flipY ? -i : i, 0, 0];
                (t = fabric.util.multiplyTransformMatrices), (i = fabric.util.degreesToRadians);
                return e.skewX && (o = t(o, [1, 0, Math.tan(i(e.skewX)), 1], !0)), e.skewY ? t(o, [1, Math.tan(i(e.skewY)), 0, 1], !0) : o;
            },
            composeMatrix: function (e) {
                var t = [1, 0, 0, 1, e.translateX || 0, e.translateY || 0],
                    i = fabric.util.multiplyTransformMatrices;
                return e.angle && (t = i(t, fabric.util.calcRotateMatrix(e))), 1 !== e.scaleX || 1 !== e.scaleY || e.skewX || e.skewY || e.flipX || e.flipY ? i(t, fabric.util.calcDimensionsMatrix(e)) : t;
            },
            resetObjectTransform: function (e) {
                (e.scaleX = 1), (e.scaleY = 1), (e.skewX = 0), (e.skewY = 0), (e.flipX = !1), (e.flipY = !1), e.rotate(0);
            },
            saveObjectTransform: function (e) {
                return { scaleX: e.scaleX, scaleY: e.scaleY, skewX: e.skewX, skewY: e.skewY, angle: e.angle, left: e.left, flipX: e.flipX, flipY: e.flipY, top: e.top };
            },
            isTransparent: function (e, t, i, o) {
                0 < o && (o < t ? (t -= o) : (t = 0), o < i ? (i -= o) : (i = 0));
                for (var n = !0, r = e.getImageData(t, i, 2 * o || 1, 2 * o || 1), s = r.data.length, a = 3; a < s && !1 != (n = r.data[a] <= 0); a += 4);
                return (r = null), n;
            },
            parsePreserveAspectRatioAttribute: function (e) {
                var t,
                    i = "meet";
                return (
                    (e = e.split(" ")) && e.length && ("meet" !== (i = e.pop()) && "slice" !== i ? ((t = i), (i = "meet")) : e.length && (t = e.pop())),
                    { meetOrSlice: i, alignX: "none" !== t ? t.slice(1, 4) : "none", alignY: "none" !== t ? t.slice(5, 8) : "none" }
                );
            },
            clearFabricFontCache: function (e) {
                (e = (e || "").toLowerCase()) ? fabric.charWidthsCache[e] && delete fabric.charWidthsCache[e] : (fabric.charWidthsCache = {});
            },
            limitDimsByArea: function (e, t) {
                return (e = Math.sqrt(t * e)), (t = Math.floor(t / e)), { x: Math.floor(e), y: t };
            },
            capValue: function (e, t, i) {
                return Math.max(e, Math.min(t, i));
            },
            findScaleToFit: function (e, t) {
                return Math.min(t.width / e.width, t.height / e.height);
            },
            findScaleToCover: function (e, t) {
                return Math.max(t.width / e.width, t.height / e.height);
            },
            matrixToSVG: function (e) {
                return (
                    "matrix(" +
                    e
                        .map(function (e) {
                            return fabric.util.toFixed(e, fabric.Object.NUM_FRACTION_DIGITS);
                        })
                        .join(" ") +
                    ")"
                );
            },
            removeTransformFromObject: function (e, t) {
                (t = fabric.util.invertTransform(t)), (t = fabric.util.multiplyTransformMatrices(t, e.calcOwnMatrix())), fabric.util.applyTransformToObject(e, t);
            },
            addTransformToObject: function (e, t) {
                fabric.util.applyTransformToObject(e, fabric.util.multiplyTransformMatrices(t, e.calcOwnMatrix()));
            },
            applyTransformToObject: function (e, t) {
                var i = fabric.util.qrDecompose(t);
                t = new fabric.Point(i.translateX, i.translateY);
                (e.flipX = !1), (e.flipY = !1), e.set("scaleX", i.scaleX), e.set("scaleY", i.scaleY), (e.skewX = i.skewX), (e.skewY = i.skewY), (e.angle = i.angle), e.setPositionByOrigin(t, "center", "center");
            },
            sizeAfterTransform: function (e, t, i) {
                return (
                    (t = [
                        { x: -(e /= 2), y: -(t /= 2) },
                        { x: e, y: -t },
                        { x: -e, y: t },
                        { x: e, y: t },
                    ]),
                    (i = fabric.util.calcDimensionsMatrix(i)),
                    { x: (i = fabric.util.makeBoundingBoxFromPoints(t, i)).width, y: i.height }
                );
            },
        };
    })("undefined" != typeof exports ? exports : this),
    (function () {
        var e = Array.prototype.join,
            t = { m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7 },
            i = { m: "l", M: "L" };
        function o(e, t, i, o, r, s, a) {
            var c = Math.PI,
                l = (a * c) / 180,
                d = fabric.util.sin(l),
                h = fabric.util.cos(l),
                u = 0,
                f = 0,
                m = -h * e * 0.5 - d * t * 0.5,
                g = -h * t * 0.5 + d * e * 0.5,
                p = (i = Math.abs(i)) * i,
                v = (o = Math.abs(o)) * o,
                b = g * g,
                y = p * v - p * b - v * (S = m * m);
            a = 0;
            y < 0 ? ((i *= l = Math.sqrt(1 - y / (p * v))), (o *= l)) : (a = (r === s ? -1 : 1) * Math.sqrt(y / (p * b + v * S)));
            var S,
                w = h * (S = (a * i * g) / o) - d * (a = (-a * o * m) / i) + 0.5 * e,
                _ = d * S + h * a + 0.5 * t,
                C = n(1, 0, (m - S) / i, (g - a) / o);
            a = n((m - S) / i, (g - a) / o, (-m - S) / i, (-g - a) / o);
            0 === s && 0 < a ? (a -= 2 * c) : 1 === s && a < 0 && (a += 2 * c);
            for (var x, T, k, R, O, A, M, E, P, B, D, I, V, L = Math.ceil(Math.abs((a / c) * 2)), F = [], j = a / L, N = ((8 / 3) * Math.sin(j / 4) * Math.sin(j / 4)) / Math.sin(j / 2), U = C + j, W = 0; W < L; W++)
                (F[W] =
                    ((x = C),
                    (T = U),
                    (k = h),
                    (R = d),
                    (O = i),
                    (A = o),
                    (M = w),
                    (E = _),
                    (P = N),
                    (B = u),
                    (D = f),
                    void 0,
                    (I = fabric.util.cos(x)),
                    [
                        "C",
                        B + P * (-k * O * (V = fabric.util.sin(x)) - R * A * I),
                        D + P * (-R * O * V + k * A * I),
                        (M = k * O * (x = fabric.util.cos(T)) - R * A * (T = fabric.util.sin(T)) + M) + P * (k * O * T + R * A * x),
                        (E = R * O * x + k * A * T + E) + P * (R * O * T - k * A * x),
                        M,
                        E,
                    ])),
                    (u = F[W][5]),
                    (f = F[W][6]),
                    (C = U),
                    (U += j);
            return F;
        }
        function n(e, t, i, o) {
            return (e = Math.atan2(t, e)) <= (i = Math.atan2(o, i)) ? i - e : 2 * Math.PI - (e - i);
        }
        function r(t, i, o, n, r, s, a, c) {
            var l;
            if (fabric.cachesBoundsOfCurve && ((l = e.call(arguments)), fabric.boundsOfCurveCache[l])) return fabric.boundsOfCurveCache[l];
            for (var d, h, u, f = Math.sqrt, m = Math.min, g = Math.max, p = Math.abs, v = [], b = [[], []], y = 6 * t - 12 * o + 6 * r, S = -3 * t + 9 * o - 9 * r + 3 * a, w = 3 * o - 3 * t, _ = 0; _ < 2; ++_)
                0 < _ && ((y = 6 * i - 12 * n + 6 * s), (S = -3 * i + 9 * n - 9 * s + 3 * c), (w = 3 * n - 3 * i)),
                    p(S) < 1e-12 ? p(y) < 1e-12 || (0 < (d = -w / y) && d < 1 && v.push(d)) : (h = y * y - 4 * w * S) < 0 || (0 < (h = (-y + (u = f(h))) / (2 * S)) && h < 1 && v.push(h), 0 < (u = (-y - u) / (2 * S)) && u < 1 && v.push(u));
            for (var C, x = v.length, T = x; x--; ) (d = v[x]), (b[0][x] = (C = 1 - d) * C * C * t + 3 * C * C * d * o + 3 * C * d * d * r + d * d * d * a), (b[1][x] = C * C * C * i + 3 * C * C * d * n + 3 * C * d * d * s + d * d * d * c);
            return (
                (b[0][T] = t),
                (b[1][T] = i),
                (b[0][T + 1] = a),
                (b[1][T + 1] = c),
                (g = [
                    { x: m.apply(null, b[0]), y: m.apply(null, b[1]) },
                    { x: g.apply(null, b[0]), y: g.apply(null, b[1]) },
                ]),
                fabric.cachesBoundsOfCurve && (fabric.boundsOfCurveCache[l] = g),
                g
            );
        }
        function s(e, t, i) {
            for (var n = i[1], r = i[2], s = i[3], a = i[4], c = i[5], l = o(i[6] - e, i[7] - t, n, r, a, c, s), d = 0, h = l.length; d < h; d++)
                (l[d][1] += e), (l[d][2] += t), (l[d][3] += e), (l[d][4] += t), (l[d][5] += e), (l[d][6] += t);
            return l;
        }
        function a(e, t, i, o) {
            return Math.sqrt((i - e) * (i - e) + (o - t) * (o - t));
        }
        function c(e, t, i) {
            for (var o, n = { x: t, y: i }, r = 0, s = 1; s <= 100; s += 1) (o = e(s / 100)), (r += a(n.x, n.y, o.x, o.y)), (n = o);
            return r;
        }
        function l(e) {
            for (var t, i, o, n, r = 0, s = e.length, l = 0, d = 0, h = 0, u = 0, f = [], m = 0; m < s; m++) {
                switch (((o = { x: l, y: d, command: (t = e[m])[0] }), t[0])) {
                    case "M":
                        (o.length = 0), (h = l = t[1]), (u = d = t[2]);
                        break;
                    case "L":
                        (o.length = a(l, d, t[1], t[2])), (l = t[1]), (d = t[2]);
                        break;
                    case "C":
                        (i = (function (e, t, i, o, n, r, s, a) {
                            return function (c) {
                                var l = c * c * c,
                                    d = 3 * c * c * (1 - c),
                                    h = 3 * c * (1 - c) * (1 - c);
                                return { x: s * l + n * d + i * h + e * (c = (1 - c) * (1 - c) * (1 - c)), y: a * l + r * d + o * h + t * c };
                            };
                        })(l, d, t[1], t[2], t[3], t[4], t[5], t[6])),
                            (n = (function (e, t, i, o, n, r, s, a) {
                                return function (c) {
                                    var l = 1 - c;
                                    return Math.atan2(3 * l * l * (o - t) + 6 * l * c * (r - o) + 3 * c * c * (a - r), 3 * l * l * (i - e) + 6 * l * c * (n - i) + 3 * c * c * (s - n));
                                };
                            })(l, d, t[1], t[2], t[3], t[4], t[5], t[6])),
                            (o.iterator = i),
                            (o.angleFinder = n),
                            (o.length = c(i, l, d)),
                            (l = t[5]),
                            (d = t[6]);
                        break;
                    case "Q":
                        (i = (function (e, t, i, o, n, r) {
                            return function (s) {
                                var a = s * s,
                                    c = 2 * s * (1 - s);
                                return { x: n * a + i * c + e * (s = (1 - s) * (1 - s)), y: r * a + o * c + t * s };
                            };
                        })(l, d, t[1], t[2], t[3], t[4])),
                            (n = (function (e, t, i, o, n, r) {
                                return function (s) {
                                    var a = 1 - s;
                                    return Math.atan2(2 * a * (o - t) + 2 * s * (r - o), 2 * a * (i - e) + 2 * s * (n - i));
                                };
                            })(l, d, t[1], t[2], t[3], t[4])),
                            (o.iterator = i),
                            (o.angleFinder = n),
                            (o.length = c(i, l, d)),
                            (l = t[3]),
                            (d = t[4]);
                        break;
                    case "Z":
                    case "z":
                        (o.destX = h), (o.destY = u), (o.length = a(l, d, h, u)), (l = h), (d = u);
                }
                (r += o.length), f.push(o);
            }
            return f.push({ length: r, x: l, y: d }), f;
        }
        (fabric.util.joinPath = function (e) {
            return e
                .map(function (e) {
                    return e.join(" ");
                })
                .join(" ");
        }),
            (fabric.util.parsePath = function (e) {
                var o,
                    n,
                    r,
                    s,
                    a = [],
                    c = [],
                    l = fabric.rePathCommand,
                    d = "[-+]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][-+]?\\d+)?\\s*",
                    h = "(" + d + ")" + fabric.commaWsp,
                    u = "([01])" + fabric.commaWsp + "?",
                    f = new RegExp(h + "?" + h + "?" + h + u + u + h + "?(" + d + ")", "g");
                if (!e || !e.match) return a;
                for (var m, g = 0, p = (m = e.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi)).length; g < p; g++) {
                    (s = (o = m[g]).slice(1).trim()), (c.length = 0);
                    var v,
                        b = o.charAt(0),
                        y = [b];
                    if ("a" === b.toLowerCase()) for (; (v = f.exec(s)); ) for (var S = 1; S < v.length; S++) c.push(v[S]);
                    else for (; (r = l.exec(s)); ) c.push(r[0]);
                    S = 0;
                    for (var w = c.length; S < w; S++) (n = parseFloat(c[S])), isNaN(n) || y.push(n);
                    var _ = t[b.toLowerCase()],
                        C = i[b] || b;
                    if (y.length - 1 > _) for (var x = 1, T = y.length; x < T; x += _) a.push([b].concat(y.slice(x, x + _))), (b = C);
                    else a.push(y);
                }
                return a;
            }),
            (fabric.util.makePathSimpler = function (e) {
                for (var t, i, o, n, r, a = 0, c = 0, l = e.length, d = 0, h = 0, u = [], f = 0; f < l; ++f) {
                    switch (((i = !1), (t = e[f].slice(0))[0])) {
                        case "l":
                            (t[0] = "L"), (t[1] += a), (t[2] += c);
                        case "L":
                            (a = t[1]), (c = t[2]);
                            break;
                        case "h":
                            t[1] += a;
                        case "H":
                            (t[0] = "L"), (t[2] = c), (a = t[1]);
                            break;
                        case "v":
                            t[1] += c;
                        case "V":
                            (t[0] = "L"), (c = t[1]), (t[1] = a), (t[2] = c);
                            break;
                        case "m":
                            (t[0] = "M"), (t[1] += a), (t[2] += c);
                        case "M":
                            (a = t[1]), (c = t[2]), (d = t[1]), (h = t[2]);
                            break;
                        case "c":
                            (t[0] = "C"), (t[1] += a), (t[2] += c), (t[3] += a), (t[4] += c), (t[5] += a), (t[6] += c);
                        case "C":
                            (n = t[3]), (r = t[4]), (a = t[5]), (c = t[6]);
                            break;
                        case "s":
                            (t[0] = "S"), (t[1] += a), (t[2] += c), (t[3] += a), (t[4] += c);
                        case "S":
                            (r = "C" === o ? ((n = 2 * a - n), 2 * c - r) : ((n = a), c)), (a = t[3]), (c = t[4]), (t[0] = "C"), (t[5] = t[3]), (t[6] = t[4]), (t[3] = t[1]), (t[4] = t[2]), (t[1] = n), (t[2] = r), (n = t[3]), (r = t[4]);
                            break;
                        case "q":
                            (t[0] = "Q"), (t[1] += a), (t[2] += c), (t[3] += a), (t[4] += c);
                        case "Q":
                            (n = t[1]), (r = t[2]), (a = t[3]), (c = t[4]);
                            break;
                        case "t":
                            (t[0] = "T"), (t[1] += a), (t[2] += c);
                        case "T":
                            (r = "Q" === o ? ((n = 2 * a - n), 2 * c - r) : ((n = a), c)), (t[0] = "Q"), (a = t[1]), (c = t[2]), (t[1] = n), (t[2] = r), (t[3] = a), (t[4] = c);
                            break;
                        case "a":
                            (t[0] = "A"), (t[6] += a), (t[7] += c);
                        case "A":
                            (i = !0), (u = u.concat(s(a, c, t))), (a = t[6]), (c = t[7]);
                            break;
                        case "z":
                        case "Z":
                            (a = d), (c = h);
                    }
                    i || u.push(t), (o = t[0]);
                }
                return u;
            }),
            (fabric.util.getSmoothPathFromPoints = function (e, t) {
                var i,
                    o,
                    n = [],
                    r = new fabric.Point(e[0].x, e[0].y),
                    s = new fabric.Point(e[1].x, e[1].y),
                    a = e.length,
                    c = 1,
                    l = 0,
                    d = 2 < a;
                for (d && ((c = e[2].x < s.x ? -1 : e[2].x === s.x ? 0 : 1), (l = e[2].y < s.y ? -1 : e[2].y === s.y ? 0 : 1)), n.push(["M", r.x - c * (t = t || 0), r.y - l * t]), i = 1; i < a; i++)
                    r.eq(s) || ((o = r.midPointFrom(s)), n.push(["Q", r.x, r.y, o.x, o.y])), (r = e[i]), i + 1 < e.length && (s = e[i + 1]);
                return d && ((c = r.x > e[i - 2].x ? 1 : r.x === e[i - 2].x ? 0 : -1), (l = r.y > e[i - 2].y ? 1 : r.y === e[i - 2].y ? 0 : -1)), n.push(["L", r.x + c * t, r.y + l * t]), n;
            }),
            (fabric.util.getPathSegmentsInfo = l),
            (fabric.util.getBoundsOfCurve = r),
            (fabric.util.getPointOnPath = function (e, t, i) {
                i = i || l(e);
                for (var o = 0; 0 < t - i[o].length && o < i.length - 2; ) (t -= i[o].length), o++;
                var n,
                    r = i[o],
                    s = t / r.length,
                    c = r.command,
                    d = e[o];
                switch (c) {
                    case "M":
                        return { x: r.x, y: r.y, angle: 0 };
                    case "Z":
                    case "z":
                        return ((n = new fabric.Point(r.x, r.y).lerp(new fabric.Point(r.destX, r.destY), s)).angle = Math.atan2(r.destY - r.y, r.destX - r.x)), n;
                    case "L":
                        return ((n = new fabric.Point(r.x, r.y).lerp(new fabric.Point(d[1], d[2]), s)).angle = Math.atan2(d[2] - r.y, d[1] - r.x)), n;
                    case "C":
                    case "Q":
                        return (function (e, t) {
                            var i,
                                o,
                                n,
                                r = 0,
                                s = 0,
                                c = e.iterator,
                                l = { x: e.x, y: e.y },
                                d = 0.01;
                            for (e = e.angleFinder; s < t && r <= 1 && 1e-4 < d; ) (i = c(r)), (n = r), t < (o = a(l.x, l.y, i.x, i.y)) + s ? (r -= d /= 2) : ((l = i), (r += d), (s += o));
                            return (i.angle = e(n)), i;
                        })(r, t);
                }
            }),
            (fabric.util.transformPath = function (e, t, i) {
                return (
                    i && (t = fabric.util.multiplyTransformMatrices(t, [1, 0, 0, 1, -i.x, -i.y])),
                    e.map(function (e) {
                        for (var i = e.slice(0), o = {}, n = 1; n < e.length - 1; n += 2) (o.x = e[n]), (o.y = e[n + 1]), (o = fabric.util.transformPoint(o, t)), (i[n] = o.x), (i[n + 1] = o.y);
                        return i;
                    })
                );
            }),
            (fabric.util.fromArcToBeizers = s),
            (fabric.util.getBoundsOfArc = function (e, t, i, n, s, a, c, l, d) {
                for (var h, u = 0, f = 0, m = [], g = o(l - e, d - t, i, n, a, c, s), p = 0, v = g.length; p < v; p++)
                    (h = r(u, f, g[p][1], g[p][2], g[p][3], g[p][4], g[p][5], g[p][6])), m.push({ x: h[0].x + e, y: h[0].y + t }), m.push({ x: h[1].x + e, y: h[1].y + t }), (u = g[p][5]), (f = g[p][6]);
                return m;
            }),
            (fabric.util.drawArc = function (e, t, i, o) {
                s(t, i, (o = o.slice(0).unshift("X"))).forEach(function (t) {
                    e.bezierCurveTo.apply(e, t.slice(1));
                });
            });
    })(),
    (function () {
        var e = Array.prototype.slice;
        function t(e, t, i) {
            if (e && 0 !== e.length) {
                var o = e.length - 1,
                    n = t ? e[o][t] : e[o];
                if (t) for (; o--; ) i(e[o][t], n) && (n = e[o][t]);
                else for (; o--; ) i(e[o], n) && (n = e[o]);
                return n;
            }
        }
        fabric.util.array = {
            fill: function (e, t) {
                for (var i = e.length; i--; ) e[i] = t;
                return e;
            },
            invoke: function (t, i) {
                for (var o = e.call(arguments, 2), n = [], r = 0, s = t.length; r < s; r++) n[r] = o.length ? t[r][i].apply(t[r], o) : t[r][i].call(t[r]);
                return n;
            },
            min: function (e, i) {
                return t(e, i, function (e, t) {
                    return e < t;
                });
            },
            max: function (e, i) {
                return t(e, i, function (e, t) {
                    return t <= e;
                });
            },
        };
    })(),
    (function () {
        function e(t, i, o) {
            if (o)
                if (!fabric.isLikelyNode && i instanceof Element) t = i;
                else if (i instanceof Array) {
                    t = [];
                    for (var n = 0, r = i.length; n < r; n++) t[n] = e({}, i[n], o);
                } else if (i && "object" == typeof i) for (var s in i) "canvas" === s || "group" === s ? (t[s] = null) : i.hasOwnProperty(s) && (t[s] = e({}, i[s], o));
                else t = i;
            else for (var s in i) t[s] = i[s];
            return t;
        }
        (fabric.util.object = {
            extend: e,
            clone: function (t, i) {
                return e({}, t, i);
            },
        }),
            fabric.util.object.extend(fabric.util, fabric.Observable);
    })(),
    (fabric.util.string = {
        camelize: function (e) {
            return e.replace(/-+(.)?/g, function (e, t) {
                return t ? t.toUpperCase() : "";
            });
        },
        capitalize: function (e, t) {
            return e.charAt(0).toUpperCase() + (t ? e.slice(1) : e.slice(1).toLowerCase());
        },
        escapeXml: function (e) {
            return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        },
        graphemeSplit: function (e) {
            var t,
                i = 0,
                o = [];
            for (i = 0; i < e.length; i++)
                !1 !==
                    (t = (function (e, t) {
                        var i = e.charCodeAt(t);
                        if (isNaN(i)) return "";
                        if (i < 55296 || 57343 < i) return e.charAt(t);
                        if (55296 <= i && i <= 56319) {
                            if (e.length <= t + 1) throw "High surrogate without following low surrogate";
                            if ((i = e.charCodeAt(t + 1)) < 56320 || 57343 < i) throw "High surrogate without following low surrogate";
                            return e.charAt(t) + e.charAt(t + 1);
                        }
                        if (0 === t) throw "Low surrogate without preceding high surrogate";
                        if ((t = e.charCodeAt(t - 1)) < 55296 || 56319 < t) throw "Low surrogate without preceding high surrogate";
                        return !1;
                    })(e, i)) && o.push(t);
            return o;
        },
    }),
    (function () {
        function e() {}
        var t = Array.prototype.slice,
            i = (function () {
                for (var e in { toString: 1 }) if ("toString" === e) return !1;
                return !0;
            })();
        function o() {}
        function n(e) {
            for (var i = null, o = this; o.constructor.superclass; ) {
                var n = o.constructor.superclass.prototype[e];
                if (o[e] !== n) {
                    i = n;
                    break;
                }
                o = o.constructor.superclass.prototype;
            }
            return i ? (1 < arguments.length ? i.apply(this, t.call(arguments, 1)) : i.call(this)) : console.log("tried to callSuper " + e + ", method not found in prototype chain", this);
        }
        fabric.util.createClass = function () {
            var r = null,
                s = t.call(arguments, 0);
            function a() {
                this.initialize.apply(this, arguments);
            }
            "function" == typeof s[0] && (r = s.shift()), (a.superclass = r), (a.subclasses = []), r && ((o.prototype = r.prototype), (a.prototype = new o()), r.subclasses.push(a));
            for (var c = 0, l = s.length; c < l; c++)
                !(function (e, t, o) {
                    for (var n in t)
                        n in e.prototype && "function" == typeof e.prototype[n] && -1 < (t[n] + "").indexOf("callSuper")
                            ? (e.prototype[n] = (function (e) {
                                  return function () {
                                      var i = this.constructor.superclass;
                                      this.constructor.superclass = o;
                                      var n = t[e].apply(this, arguments);
                                      if (((this.constructor.superclass = i), "initialize" !== e)) return n;
                                  };
                              })(n))
                            : (e.prototype[n] = t[n]),
                            i && (t.toString !== Object.prototype.toString && (e.prototype.toString = t.toString), t.valueOf !== Object.prototype.valueOf && (e.prototype.valueOf = t.valueOf));
                })(a, s[c], r);
            return a.prototype.initialize || (a.prototype.initialize = e), ((a.prototype.constructor = a).prototype.callSuper = n), a;
        };
    })(),
    (function () {
        var e = !!fabric.document.createElement("div").attachEvent,
            t = ["touchstart", "touchmove", "touchend"];
        (fabric.util.addListener = function (t, i, o, n) {
            t && t.addEventListener(i, o, !e && n);
        }),
            (fabric.util.removeListener = function (t, i, o, n) {
                t && t.removeEventListener(i, o, !e && n);
            }),
            (fabric.util.getPointer = function (e) {
                var t = e.target,
                    i = fabric.util.getScrollLeftTop(t);
                return { x: (t = (e = (t = e).changedTouches) && e[0] ? e[0] : t).clientX + i.left, y: t.clientY + i.top };
            }),
            (fabric.util.isTouchEvent = function (e) {
                return -1 < t.indexOf(e.type) || "touch" === e.pointerType;
            });
    })(),
    (function () {
        var e = "string" == typeof (t = fabric.document.createElement("div")).style.opacity,
            t = "string" == typeof t.style.filter,
            i = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,
            o = function (e) {
                return e;
            };
        e
            ? (o = function (e, t) {
                  return (e.style.opacity = t), e;
              })
            : t &&
              (o = function (e, t) {
                  var o = e.style;
                  return (
                      e.currentStyle && !e.currentStyle.hasLayout && (o.zoom = 1),
                      i.test(o.filter) ? (o.filter = o.filter.replace(i, (t = 0.9999 <= t ? "" : "alpha(opacity=" + 100 * t + ")"))) : (o.filter += " alpha(opacity=" + 100 * t + ")"),
                      e
                  );
              }),
            (fabric.util.setStyle = function (e, t) {
                var i,
                    n = e.style;
                if (!n) return e;
                if ("string" == typeof t) return (e.style.cssText += ";" + t), -1 < t.indexOf("opacity") ? o(e, t.match(/opacity:\s*(\d?\.?\d*)/)[1]) : e;
                for (i in t) "opacity" === i ? o(e, t[i]) : (n["float" === i || "cssFloat" === i ? (void 0 === n.styleFloat ? "cssFloat" : "styleFloat") : i] = t[i]);
                return e;
            });
    })(),
    (function () {
        var e,
            t,
            i,
            o = Array.prototype.slice,
            n = function (e) {
                return o.call(e, 0);
            };
        try {
            t = n(fabric.document.childNodes) instanceof Array;
        } catch (t) {}
        function r(e, t) {
            var i,
                o = fabric.document.createElement(e);
            for (i in t) "class" === i ? (o.className = t[i]) : "for" === i ? (o.htmlFor = t[i]) : o.setAttribute(i, t[i]);
            return o;
        }
        function s(e) {
            for (
                var t = 0, i = 0, o = fabric.document.documentElement, n = fabric.document.body || { scrollLeft: 0, scrollTop: 0 };
                e &&
                (e.parentNode || e.host) &&
                ((e = e.parentNode || e.host) === fabric.document ? ((t = n.scrollLeft || o.scrollLeft || 0), (i = n.scrollTop || o.scrollTop || 0)) : ((t += e.scrollLeft || 0), (i += e.scrollTop || 0)),
                1 !== e.nodeType || "fixed" !== e.style.position);

            );
            return { left: t, top: i };
        }
        t ||
            (n = function (e) {
                for (var t = new Array(e.length), i = e.length; i--; ) t[i] = e[i];
                return t;
            }),
            (e =
                fabric.document.defaultView && fabric.document.defaultView.getComputedStyle
                    ? function (e, t) {
                          return (e = fabric.document.defaultView.getComputedStyle(e, null)) ? e[t] : void 0;
                      }
                    : function (e, t) {
                          var i = e.style[t];
                          return !i && e.currentStyle ? e.currentStyle[t] : i;
                      }),
            (t = fabric.document.documentElement.style),
            (i = "userSelect" in t ? "userSelect" : "MozUserSelect" in t ? "MozUserSelect" : "WebkitUserSelect" in t ? "WebkitUserSelect" : "KhtmlUserSelect" in t ? "KhtmlUserSelect" : ""),
            (fabric.util.makeElementUnselectable = function (e) {
                return void 0 !== e.onselectstart && (e.onselectstart = fabric.util.falseFunction), i ? (e.style[i] = "none") : "string" == typeof e.unselectable && (e.unselectable = "on"), e;
            }),
            (fabric.util.makeElementSelectable = function (e) {
                return void 0 !== e.onselectstart && (e.onselectstart = null), i ? (e.style[i] = "") : "string" == typeof e.unselectable && (e.unselectable = ""), e;
            }),
            (fabric.util.setImageSmoothing = function (e, t) {
                (e.imageSmoothingEnabled = e.imageSmoothingEnabled || e.webkitImageSmoothingEnabled || e.mozImageSmoothingEnabled || e.msImageSmoothingEnabled || e.oImageSmoothingEnabled), (e.imageSmoothingEnabled = t);
            }),
            (fabric.util.getById = function (e) {
                return "string" == typeof e ? fabric.document.getElementById(e) : e;
            }),
            (fabric.util.toArray = n),
            (fabric.util.addClass = function (e, t) {
                e && -1 === (" " + e.className + " ").indexOf(" " + t + " ") && (e.className += (e.className ? " " : "") + t);
            }),
            (fabric.util.makeElement = r),
            (fabric.util.wrapElement = function (e, t, i) {
                return "string" == typeof t && (t = r(t, i)), e.parentNode && e.parentNode.replaceChild(t, e), t.appendChild(e), t;
            }),
            (fabric.util.getScrollLeftTop = s),
            (fabric.util.getElementOffset = function (t) {
                var i,
                    o,
                    n = t && t.ownerDocument,
                    r = { left: 0, top: 0 },
                    a = { left: 0, top: 0 },
                    c = { borderLeftWidth: "left", borderTopWidth: "top", paddingLeft: "left", paddingTop: "top" };
                if (!n) return a;
                for (o in c) a[c[o]] += parseInt(e(t, o), 10) || 0;
                return (i = n.documentElement), void 0 !== t.getBoundingClientRect && (r = t.getBoundingClientRect()), (n = s(t)), { left: r.left + n.left - (i.clientLeft || 0) + a.left, top: r.top + n.top - (i.clientTop || 0) + a.top };
            }),
            (fabric.util.getNodeCanvas = function (e) {
                return (e = fabric.jsdomImplForWrapper(e))._canvas || e._image;
            }),
            (fabric.util.cleanUpJsdomNode = function (e) {
                !fabric.isLikelyNode || ((e = fabric.jsdomImplForWrapper(e)) && ((e._image = null), (e._canvas = null), (e._currentSrc = null), (e._attributes = null), (e._classList = null)));
            });
    })(),
    (function () {
        function e() {}
        fabric.util.request = function (t, i) {
            var o,
                n = (i = i || {}).method ? i.method.toUpperCase() : "GET",
                r = i.onComplete || function () {},
                s = new fabric.window.XMLHttpRequest(),
                a = i.body || i.parameters;
            return (
                (s.onreadystatechange = function () {
                    4 === s.readyState && (r(s), (s.onreadystatechange = e));
                }),
                "GET" === n && ((a = null), "string" == typeof i.parameters && ((o = t), (i = i.parameters), (t = o + (/\?/.test(o) ? "&" : "?") + i))),
                s.open(n, t, !0),
                ("POST" !== n && "PUT" !== n) || s.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"),
                s.send(a),
                s
            );
        };
    })(),
    (fabric.log = console.log),
    (fabric.warn = console.warn),
    (function () {
        function e() {
            return !1;
        }
        function t(e, t, i, o) {
            return -i * Math.cos((e / o) * (Math.PI / 2)) + i + t;
        }
        var i =
                fabric.window.requestAnimationFrame ||
                fabric.window.webkitRequestAnimationFrame ||
                fabric.window.mozRequestAnimationFrame ||
                fabric.window.oRequestAnimationFrame ||
                fabric.window.msRequestAnimationFrame ||
                function (e) {
                    return fabric.window.setTimeout(e, 1e3 / 60);
                },
            o = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;
        function n() {
            return i.apply(fabric.window, arguments);
        }
        (fabric.util.animate = function (i) {
            var o = !1;
            return (
                n(function (r) {
                    i = i || {};
                    var s,
                        a = r || +new Date(),
                        c = i.duration || 500,
                        l = a + c,
                        d = i.onChange || e,
                        h = i.abort || e,
                        u = i.onComplete || e,
                        f = i.easing || t,
                        m = "startValue" in i ? i.startValue : 0,
                        g = "endValue" in i ? i.endValue : 100,
                        p = i.byValue || g - m;
                    i.onStart && i.onStart(),
                        (function e(t) {
                            s = t || +new Date();
                            var i = (r = l < s ? c : s - a) / c,
                                r = ((t = f(r, m, p, c)), Math.abs((t - m) / p));
                            o || (h(t, r, i) ? u(g, 1, 1) : l < s ? (d(g, 1, 1), u(g, 1, 1)) : (d(t, r, i), n(e)));
                        })(a);
                }),
                function () {
                    o = !0;
                }
            );
        }),
            (fabric.util.requestAnimFrame = n),
            (fabric.util.cancelAnimFrame = function () {
                return o.apply(fabric.window, arguments);
            });
    })(),
    (function () {
        function e(e, t, i) {
            var o = "rgba(" + parseInt(e[0] + i * (t[0] - e[0]), 10) + "," + parseInt(e[1] + i * (t[1] - e[1]), 10) + "," + parseInt(e[2] + i * (t[2] - e[2]), 10);
            return (o += "," + (e && t ? parseFloat(e[3] + i * (t[3] - e[3])) : 1)) + ")";
        }
        fabric.util.animateColor = function (t, i, o, n) {
            t = new fabric.Color(t).getSource();
            var r = new fabric.Color(i).getSource(),
                s = n.onComplete,
                a = n.onChange;
            return (
                (n = n || {}),
                fabric.util.animate(
                    fabric.util.object.extend(n, {
                        duration: o || 500,
                        startValue: t,
                        endValue: r,
                        byValue: r,
                        easing: function (t, i, o, r) {
                            return e(i, o, n.colorEasing ? n.colorEasing(t, r) : 1 - Math.cos((t / r) * (Math.PI / 2)));
                        },
                        onComplete: function (t, i, o) {
                            if (s) return s(e(r, r, 0), i, o);
                        },
                        onChange: function (t, i, o) {
                            if (a) {
                                if (Array.isArray(t)) return a(e(t, t, 0), i, o);
                                a(t, i, o);
                            }
                        },
                    })
                )
            );
        };
    })(),
    (function () {
        function e(e, t, i, o) {
            return (o = e < Math.abs(t) ? ((e = t), i / 4) : 0 === t && 0 === e ? (i / (2 * Math.PI)) * Math.asin(1) : (i / (2 * Math.PI)) * Math.asin(t / e)), { a: e, c: t, p: i, s: o };
        }
        function t(e, t, i) {
            return e.a * Math.pow(2, 10 * --t) * Math.sin(((t * i - e.s) * (2 * Math.PI)) / e.p);
        }
        function i(e, t, i, n) {
            return i - o(n - e, 0, i, n) + t;
        }
        function o(e, t, i, o) {
            return (e /= o) < 1 / 2.75
                ? i * (7.5625 * e * e) + t
                : e < 2 / 2.75
                ? i * (7.5625 * (e -= 1.5 / 2.75) * e + 0.75) + t
                : e < 2.5 / 2.75
                ? i * (7.5625 * (e -= 2.25 / 2.75) * e + 0.9375) + t
                : i * (7.5625 * (e -= 2.625 / 2.75) * e + 0.984375) + t;
        }
        fabric.util.ease = {
            easeInQuad: function (e, t, i, o) {
                return i * (e /= o) * e + t;
            },
            easeOutQuad: function (e, t, i, o) {
                return -i * (e /= o) * (e - 2) + t;
            },
            easeInOutQuad: function (e, t, i, o) {
                return (e /= o / 2) < 1 ? (i / 2) * e * e + t : (-i / 2) * (--e * (e - 2) - 1) + t;
            },
            easeInCubic: function (e, t, i, o) {
                return i * (e /= o) * e * e + t;
            },
            easeOutCubic: function (e, t, i, o) {
                return i * ((e = e / o - 1) * e * e + 1) + t;
            },
            easeInOutCubic: function (e, t, i, o) {
                return (e /= o / 2) < 1 ? (i / 2) * e * e * e + t : (i / 2) * ((e -= 2) * e * e + 2) + t;
            },
            easeInQuart: function (e, t, i, o) {
                return i * (e /= o) * e * e * e + t;
            },
            easeOutQuart: function (e, t, i, o) {
                return -i * ((e = e / o - 1) * e * e * e - 1) + t;
            },
            easeInOutQuart: function (e, t, i, o) {
                return (e /= o / 2) < 1 ? (i / 2) * e * e * e * e + t : (-i / 2) * ((e -= 2) * e * e * e - 2) + t;
            },
            easeInQuint: function (e, t, i, o) {
                return i * (e /= o) * e * e * e * e + t;
            },
            easeOutQuint: function (e, t, i, o) {
                return i * ((e = e / o - 1) * e * e * e * e + 1) + t;
            },
            easeInOutQuint: function (e, t, i, o) {
                return (e /= o / 2) < 1 ? (i / 2) * e * e * e * e * e + t : (i / 2) * ((e -= 2) * e * e * e * e + 2) + t;
            },
            easeInSine: function (e, t, i, o) {
                return -i * Math.cos((e / o) * (Math.PI / 2)) + i + t;
            },
            easeOutSine: function (e, t, i, o) {
                return i * Math.sin((e / o) * (Math.PI / 2)) + t;
            },
            easeInOutSine: function (e, t, i, o) {
                return (-i / 2) * (Math.cos((Math.PI * e) / o) - 1) + t;
            },
            easeInExpo: function (e, t, i, o) {
                return 0 === e ? t : i * Math.pow(2, 10 * (e / o - 1)) + t;
            },
            easeOutExpo: function (e, t, i, o) {
                return e === o ? t + i : i * (1 - Math.pow(2, (-10 * e) / o)) + t;
            },
            easeInOutExpo: function (e, t, i, o) {
                return 0 === e ? t : e === o ? t + i : (e /= o / 2) < 1 ? (i / 2) * Math.pow(2, 10 * (e - 1)) + t : (i / 2) * (2 - Math.pow(2, -10 * --e)) + t;
            },
            easeInCirc: function (e, t, i, o) {
                return -i * (Math.sqrt(1 - (e /= o) * e) - 1) + t;
            },
            easeOutCirc: function (e, t, i, o) {
                return i * Math.sqrt(1 - (e = e / o - 1) * e) + t;
            },
            easeInOutCirc: function (e, t, i, o) {
                return (e /= o / 2) < 1 ? (-i / 2) * (Math.sqrt(1 - e * e) - 1) + t : (i / 2) * (Math.sqrt(1 - (e -= 2) * e) + 1) + t;
            },
            easeInElastic: function (i, o, n, r) {
                var s = 0;
                return 0 === i ? o : 1 == (i /= r) ? o + n : -t(e(n, n, (s = s || 0.3 * r), 1.70158), i, r) + o;
            },
            easeOutElastic: function (t, i, o, n) {
                return 0 === t ? i : 1 == (t /= n) ? i + o : (o = e(o, o, 0.3 * n, 1.70158)).a * Math.pow(2, -10 * t) * Math.sin(((t * n - o.s) * (2 * Math.PI)) / o.p) + o.c + i;
            },
            easeInOutElastic: function (i, o, n, r) {
                return 0 === i ? o : 2 == (i /= r / 2) ? o + n : ((n = e(n, n, r * (0.3 * 1.5), 1.70158)), i < 1 ? -0.5 * t(n, i, r) + o : n.a * Math.pow(2, -10 * --i) * Math.sin(((i * r - n.s) * (2 * Math.PI)) / n.p) * 0.5 + n.c + o);
            },
            easeInBack: function (e, t, i, o, n) {
                return i * (e /= o) * e * (((n = void 0 === n ? 1.70158 : n) + 1) * e - n) + t;
            },
            easeOutBack: function (e, t, i, o, n) {
                return i * ((e = e / o - 1) * e * (((n = void 0 === n ? 1.70158 : n) + 1) * e + n) + 1) + t;
            },
            easeInOutBack: function (e, t, i, o, n) {
                return void 0 === n && (n = 1.70158), (e /= o / 2) < 1 ? (i / 2) * (e * e * ((1 + (n *= 1.525)) * e - n)) + t : (i / 2) * ((e -= 2) * e * ((1 + (n *= 1.525)) * e + n) + 2) + t;
            },
            easeInBounce: i,
            easeOutBounce: o,
            easeInOutBounce: function (e, t, n, r) {
                return e < r / 2 ? 0.5 * i(2 * e, 0, n, r) + t : 0.5 * o(2 * e - r, 0, n, r) + 0.5 * n + t;
            },
        };
    })(),
    (function (e) {
        var t,
            i,
            o,
            n,
            r,
            s = e.fabric || (e.fabric = {}),
            a = s.util.object.extend,
            c = s.util.object.clone,
            l = s.util.toFixed,
            d = s.util.parseUnit,
            h = s.util.multiplyTransformMatrices,
            u = {
                cx: "left",
                x: "left",
                r: "radius",
                cy: "top",
                y: "top",
                display: "visible",
                visibility: "visible",
                transform: "transformMatrix",
                "fill-opacity": "fillOpacity",
                "fill-rule": "fillRule",
                "font-family": "fontFamily",
                "font-size": "fontSize",
                "font-style": "fontStyle",
                "font-weight": "fontWeight",
                "letter-spacing": "charSpacing",
                "paint-order": "paintFirst",
                "stroke-dasharray": "strokeDashArray",
                "stroke-dashoffset": "strokeDashOffset",
                "stroke-linecap": "strokeLineCap",
                "stroke-linejoin": "strokeLineJoin",
                "stroke-miterlimit": "strokeMiterLimit",
                "stroke-opacity": "strokeOpacity",
                "stroke-width": "strokeWidth",
                "text-decoration": "textDecoration",
                "text-anchor": "textAnchor",
                opacity: "opacity",
                "clip-path": "clipPath",
                "clip-rule": "clipRule",
                "vector-effect": "strokeUniform",
                "image-rendering": "imageSmoothing",
            },
            f = { stroke: "strokeOpacity", fill: "fillOpacity" },
            m = "font-size",
            g = "clip-path";
        function p(e) {
            return new RegExp("^(" + e.join("|") + ")\\b", "i");
        }
        function v(e, t) {
            for (var i, o = [], n = 0, r = t.length; n < r; n++) (i = t[n]), (i = e.getElementsByTagName(i)), (o = o.concat(Array.prototype.slice.call(i)));
            return o;
        }
        function b(e, t, i) {
            e[i] = Math.tan(s.util.degreesToRadians(t[0]));
        }
        function y(e, t) {
            var i,
                o = {};
            for (i in s.cssRules[t])
                if (
                    (function (e, t) {
                        var i,
                            o = !0;
                        return (
                            (i = S(e, t.pop())) &&
                                t.length &&
                                (o = (function (e, t) {
                                    for (var i, o = !0; e.parentNode && 1 === e.parentNode.nodeType && t.length; ) o && (i = t.pop()), (o = S((e = e.parentNode), i));
                                    return 0 === t.length;
                                })(e, t)),
                            i && o && 0 === t.length
                        );
                    })(e, i.split(" "))
                )
                    for (var n in s.cssRules[t][i]) o[n] = s.cssRules[t][i][n];
            return o;
        }
        function S(e, t) {
            var i,
                o = e.nodeName,
                n = e.getAttribute("class"),
                r = ((e = e.getAttribute("id")), new RegExp("^" + o, "i"));
            if (((t = t.replace(r, "")), e && t.length && ((r = new RegExp("#" + e + "(?![a-zA-Z\\-]+)", "i")), (t = t.replace(r, ""))), n && t.length))
                for (i = (n = n.split(" ")).length; i--; ) (r = new RegExp("\\." + n[i] + "(?![a-zA-Z\\-]+)", "i")), (t = t.replace(r, ""));
            return 0 === t.length;
        }
        function w(e, t) {
            var i;
            if ((i = e.getElementById ? e.getElementById(t) : i)) return i;
            for (var o, n = e.getElementsByTagName("*"), r = 0, s = n.length; r < s; r++) if (t === (o = n[r]).getAttribute("id")) return o;
        }
        (s.svgValidTagNamesRegEx = p(["path", "circle", "polygon", "polyline", "ellipse", "rect", "line", "image", "text"])),
            (s.svgViewBoxElementsRegEx = p(["symbol", "image", "marker", "pattern", "view", "svg"])),
            (s.svgInvalidAncestorsRegEx = p(["pattern", "defs", "symbol", "metadata", "clipPath", "mask", "desc"])),
            (s.svgValidParentsRegEx = p(["symbol", "g", "a", "svg", "clipPath", "defs"])),
            (s.cssRules = {}),
            (s.gradientDefs = {}),
            (s.clipPaths = {}),
            (s.parseTransformAttribute =
                ((t = s.iMatrix),
                (i = s.reNum),
                (e = s.commaWsp),
                (o =
                    "(?:(?:(matrix)\\s*\\(\\s*(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    ")\\s*\\))|(?:(translate)\\s*\\(\\s*(" +
                    i +
                    ")(?:" +
                    e +
                    "(" +
                    i +
                    "))?\\s*\\))|(?:(scale)\\s*\\(\\s*(" +
                    i +
                    ")(?:" +
                    e +
                    "(" +
                    i +
                    "))?\\s*\\))|(?:(rotate)\\s*\\(\\s*(" +
                    i +
                    ")(?:" +
                    e +
                    "(" +
                    i +
                    ")" +
                    e +
                    "(" +
                    i +
                    "))?\\s*\\))|(?:(skewX)\\s*\\(\\s*(" +
                    i +
                    ")\\s*\\))|(?:(skewY)\\s*\\(\\s*(" +
                    i +
                    ")\\s*\\)))"),
                (n = new RegExp("^\\s*(?:(?:" + o + "(?:" + e + "*" + o + ")*)?)\\s*$")),
                (r = new RegExp(o, "g")),
                function (e) {
                    var i = t.concat(),
                        a = [];
                    if (!e || (e && !n.test(e))) return i;
                    e.replace(r, function (e) {
                        var n,
                            r,
                            c,
                            l,
                            d,
                            h,
                            u = new RegExp(o).exec(e).filter(function (e) {
                                return !!e;
                            }),
                            f = ((e = u[1]), u.slice(2).map(parseFloat));
                        switch (e) {
                            case "translate":
                                (h = f), ((d = i)[4] = h[0]), 2 === h.length && (d[5] = h[1]);
                                break;
                            case "rotate":
                                (f[0] = s.util.degreesToRadians(f[0])),
                                    (n = i),
                                    (d = f),
                                    (r = s.util.cos(d[0])),
                                    (h = s.util.sin(d[0])),
                                    (l = c = 0),
                                    3 === d.length && ((c = d[1]), (l = d[2])),
                                    (n[0] = r),
                                    (n[1] = h),
                                    (n[2] = -h),
                                    (n[3] = r),
                                    (n[4] = c - (r * c - h * l)),
                                    (n[5] = l - (h * c + r * l));
                                break;
                            case "scale":
                                (c = i), (l = (r = f)[0]), (r = 2 === r.length ? r[1] : r[0]), (c[0] = l), (c[3] = r);
                                break;
                            case "skewX":
                                b(i, f, 2);
                                break;
                            case "skewY":
                                b(i, f, 1);
                                break;
                            case "matrix":
                                i = f;
                        }
                        a.push(i.concat()), (i = t.concat());
                    });
                    for (var c = a[0]; 1 < a.length; ) a.shift(), (c = s.util.multiplyTransformMatrices(c, a[0]));
                    return c;
                }));
        var _ = new RegExp("^\\s*(" + s.reNum + "+)\\s*,?\\s*(" + s.reNum + "+)\\s*,?\\s*(" + s.reNum + "+)\\s*,?\\s*(" + s.reNum + "+)\\s*$");
        function C(e) {
            if (!s.svgViewBoxElementsRegEx.test(e.nodeName)) return {};
            var t,
                i,
                o,
                n,
                r = e.getAttribute("viewBox"),
                a = 1,
                c = 1,
                l = e.getAttribute("width"),
                h = e.getAttribute("height"),
                u = e.getAttribute("x") || 0,
                f = e.getAttribute("y") || 0,
                m = e.getAttribute("preserveAspectRatio") || "",
                g = !r || !(r = r.match(_)),
                p = !l || !h || "100%" === l || "100%" === h,
                v = g && p,
                b = {},
                y = "",
                S = 0,
                w = 0;
            if (
                ((b.width = 0),
                (b.height = 0),
                (b.toBeParsed = v),
                g &&
                    (u || f) &&
                    e.parentNode &&
                    "#document" !== e.parentNode.nodeName &&
                    ((y = " translate(" + d(u) + " " + d(f) + ") "), (o = (e.getAttribute("transform") || "") + y), e.setAttribute("transform", o), e.removeAttribute("x"), e.removeAttribute("y")),
                v)
            )
                return b;
            if (g) return (b.width = d(l)), (b.height = d(h)), b;
            if (
                ((t = -parseFloat(r[1])),
                (i = -parseFloat(r[2])),
                (g = parseFloat(r[3])),
                (r = parseFloat(r[4])),
                (b.minX = t),
                (b.minY = i),
                (b.viewBoxWidth = g),
                (b.viewBoxHeight = r),
                p ? ((b.width = g), (b.height = r)) : ((b.width = d(l)), (b.height = d(h)), (a = b.width / g), (c = b.height / r)),
                "none" !== (m = s.util.parsePreserveAspectRatioAttribute(m)).alignX &&
                    ("meet" === m.meetOrSlice && (c = a = c < a ? c : a),
                    "slice" === m.meetOrSlice && (c = a = c < a ? a : c),
                    (S = b.width - g * a),
                    (w = b.height - r * a),
                    "Mid" === m.alignX && (S /= 2),
                    "Mid" === m.alignY && (w /= 2),
                    "Min" === m.alignX && (S = 0),
                    "Min" === m.alignY && (w = 0)),
                1 === a && 1 === c && 0 == t && 0 == i && 0 === u && 0 === f)
            )
                return b;
            if (((o = (y = (u || f) && "#document" !== e.parentNode.nodeName ? " translate(" + d(u) + " " + d(f) + ") " : y) + " matrix(" + a + " 0 0 " + c + " " + (t * a + S) + " " + (i * c + w) + ") "), "svg" === e.nodeName)) {
                for (n = e.ownerDocument.createElementNS(s.svgNS, "g"); e.firstChild; ) n.appendChild(e.firstChild);
                e.appendChild(n);
            } else (n = e).removeAttribute("x"), n.removeAttribute("y"), (o = n.getAttribute("transform") + o);
            return n.setAttribute("transform", o), b;
        }
        s.parseSVGDocument = function (e, t, i, o) {
            if (e) {
                !(function (e) {
                    for (var t = v(e, ["use", "svg:use"]), i = 0; t.length && i < t.length; ) {
                        var o = t[i];
                        if (null === (c = o.getAttribute("xlink:href") || o.getAttribute("href"))) return;
                        var n,
                            r = c.substr(1),
                            a = o.getAttribute("x") || 0,
                            c = o.getAttribute("y") || 0,
                            l = w(e, r).cloneNode(!0),
                            d = (l.getAttribute("transform") || "") + " translate(" + a + ", " + c + ")",
                            h = ((c = t.length), s.svgNS);
                        if ((C(l), /^svg$/i.test(l.nodeName))) {
                            for (var u, f = l.ownerDocument.createElementNS(h, "g"), m = 0, g = (u = l.attributes).length; m < g; m++) (n = u.item(m)), f.setAttributeNS(h, n.nodeName, n.nodeValue);
                            for (; l.firstChild; ) f.appendChild(l.firstChild);
                            l = f;
                        }
                        for (m = 0, g = (u = o.attributes).length; m < g; m++)
                            "x" !== (n = u.item(m)).nodeName &&
                                "y" !== n.nodeName &&
                                "xlink:href" !== n.nodeName &&
                                "href" !== n.nodeName &&
                                ("transform" === n.nodeName ? (d = n.nodeValue + " " + d) : l.setAttribute(n.nodeName, n.nodeValue));
                        l.setAttribute("transform", d), l.setAttribute("instantiated_by_use", "1"), l.removeAttribute("id"), o.parentNode.replaceChild(l, o), t.length === c && i++;
                    }
                })(e);
                var n = s.Object.__uid++,
                    r = C(e),
                    a = s.util.toArray(e.getElementsByTagName("*"));
                if (((r.crossOrigin = o && o.crossOrigin), (r.svgUid = n), 0 === a.length && s.isLikelyNode)) {
                    for (var l = [], d = 0, h = (a = e.selectNodes('//*[name(.)!="svg"]')).length; d < h; d++) l[d] = a[d];
                    a = l;
                }
                var u,
                    f = a.filter(function (e) {
                        return (
                            C(e),
                            s.svgValidTagNamesRegEx.test(e.nodeName.replace("svg:", "")) &&
                                !(function (e, t) {
                                    for (; (e = e && e.parentNode); ) if (e.nodeName && t.test(e.nodeName.replace("svg:", "")) && !e.getAttribute("instantiated_by_use")) return 1;
                                })(e, s.svgInvalidAncestorsRegEx)
                        );
                    });
                !f || (f && !f.length)
                    ? t && t([], {})
                    : ((u = {}),
                      a
                          .filter(function (e) {
                              return "clipPath" === e.nodeName.replace("svg:", "");
                          })
                          .forEach(function (e) {
                              var t = e.getAttribute("id");
                              u[t] = s.util.toArray(e.getElementsByTagName("*")).filter(function (e) {
                                  return s.svgValidTagNamesRegEx.test(e.nodeName.replace("svg:", ""));
                              });
                          }),
                      (s.gradientDefs[n] = s.getGradientDefs(e)),
                      (s.cssRules[n] = s.getCSSRules(e)),
                      (s.clipPaths[n] = u),
                      s.parseElements(
                          f,
                          function (e, i) {
                              t && (t(e, r, i, a), delete s.gradientDefs[n], delete s.cssRules[n], delete s.clipPaths[n]);
                          },
                          c(r),
                          i,
                          o
                      ));
            }
        };
        var x = new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*(" + s.reNum + "(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|" + s.reNum + "))?\\s+(.*)");
        a(s, {
            parseFontDeclaration: function (e, t) {
                var i,
                    o,
                    n,
                    r = e.match(x);
                r &&
                    ((i = r[1]),
                    (o = r[3]),
                    (n = r[4]),
                    (e = r[5]),
                    (r = r[6]),
                    i && (t.fontStyle = i),
                    o && (t.fontWeight = isNaN(parseFloat(o)) ? o : parseFloat(o)),
                    n && (t.fontSize = d(n)),
                    r && (t.fontFamily = r),
                    e && (t.lineHeight = "normal" === e ? 1 : e));
            },
            getGradientDefs: function (e) {
                var t,
                    i = v(e, ["linearGradient", "radialGradient", "svg:linearGradient", "svg:radialGradient"]),
                    o = 0,
                    n = {};
                for (o = i.length; o--; )
                    (t = i[o]).getAttribute("xlink:href") &&
                        (function e(t, i) {
                            var o = "xlink:href",
                                n = w(t, i.getAttribute(o).substr(1));
                            if (
                                (n && n.getAttribute(o) && e(t, n),
                                ["gradientTransform", "x1", "x2", "y1", "y2", "gradientUnits", "cx", "cy", "r", "fx", "fy"].forEach(function (e) {
                                    n && !i.hasAttribute(e) && n.hasAttribute(e) && i.setAttribute(e, n.getAttribute(e));
                                }),
                                !i.children.length)
                            )
                                for (var r = n.cloneNode(!0); r.firstChild; ) i.appendChild(r.firstChild);
                            i.removeAttribute(o);
                        })(e, t),
                        (n[t.getAttribute("id")] = t);
                return n;
            },
            parseAttributes: function (e, t, i) {
                if (e) {
                    var o,
                        n,
                        r = {};
                    void 0 === i && (i = e.getAttribute("svgUid")), e.parentNode && s.svgValidParentsRegEx.test(e.parentNode.nodeName) && (r = s.parseAttributes(e.parentNode, t, i));
                    var c = t.reduce(function (t, i) {
                        return (o = e.getAttribute(i)) && (t[i] = o), t;
                    }, {});
                    (i = a(y(e, i), s.parseStyleAttribute(e))), (c = a(c, i));
                    i[g] && e.setAttribute(g, i[g]), (n = i = r.fontSize || s.Text.DEFAULT_SVG_FONT_SIZE), c[m] && (c[m] = n = d(c[m], i));
                    var p,
                        v,
                        b,
                        S = {};
                    for (v in c)
                        (b = (function (e, t, i, o) {
                            var n,
                                r = "[object Array]" === Object.prototype.toString.call(t);
                            if (("fill" !== e && "stroke" !== e) || "none" !== t) {
                                if ("strokeUniform" === e) return "non-scaling-stroke" === t;
                                if ("strokeDashArray" === e) t = "none" === t ? null : t.replace(/,/g, " ").split(/\s+/).map(parseFloat);
                                else if ("transformMatrix" === e) t = i && i.transformMatrix ? h(i.transformMatrix, s.parseTransformAttribute(t)) : s.parseTransformAttribute(t);
                                else if ("visible" === e) (t = "none" !== t && "hidden" !== t), i && !1 === i.visible && (t = !1);
                                else if ("opacity" === e) (t = parseFloat(t)), i && void 0 !== i.opacity && (t *= i.opacity);
                                else if ("textAnchor" === e) t = "start" === t ? "left" : "end" === t ? "right" : "center";
                                else if ("charSpacing" === e) n = (d(t, o) / o) * 1e3;
                                else if ("paintFirst" === e) {
                                    var a = t.indexOf("fill");
                                    (i = t.indexOf("stroke")), (t = "fill");
                                    ((-1 < a && -1 < i && i < a) || (-1 === a && -1 < i)) && (t = "stroke");
                                } else {
                                    if ("href" === e || "xlink:href" === e || "font" === e) return t;
                                    if ("imageSmoothing" === e) return "optimizeQuality" === t;
                                    n = r ? t.map(d) : d(t, o);
                                }
                            } else t = "";
                            return !r && isNaN(n) ? t : n;
                        })((p = (b = v) in u ? u[b] : b), c[v], r, n)),
                            (S[p] = b);
                    return (
                        S && S.font && s.parseFontDeclaration(S.font, S),
                        (i = a(r, S)),
                        s.svgValidParentsRegEx.test(e.nodeName)
                            ? i
                            : (function (e) {
                                  for (var t in f)
                                      if (void 0 !== e[f[t]] && "" !== e[t]) {
                                          if (void 0 === e[t]) {
                                              if (!s.Object.prototype[t]) continue;
                                              e[t] = s.Object.prototype[t];
                                          }
                                          var i;
                                          0 !== e[t].indexOf("url(") && ((i = new s.Color(e[t])), (e[t] = i.setAlpha(l(i.getAlpha() * e[f[t]], 2)).toRgba()));
                                      }
                                  return e;
                              })(i)
                    );
                }
            },
            parseElements: function (e, t, i, o, n) {
                new s.ElementsParser(e, t, i, o, n).parse();
            },
            parseStyleAttribute: function (e) {
                var t,
                    i,
                    o,
                    n = {};
                return (
                    (e = e.getAttribute("style")) &&
                        ("string" == typeof e
                            ? ((t = n),
                              e
                                  .replace(/;\s*$/, "")
                                  .split(";")
                                  .forEach(function (e) {
                                      (e = e.split(":")), (i = e[0].trim().toLowerCase()), (o = e[1].trim()), (t[i] = o);
                                  }))
                            : (function (e, t) {
                                  var i, o, n;
                                  for (n in e) void 0 !== e[n] && ((i = n.toLowerCase()), (o = e[n]), (t[i] = o));
                              })(e, n)),
                    n
                );
            },
            parsePointsAttribute: function (e) {
                if (!e) return null;
                for (var t = [], i = 0, o = (e = (e = e.replace(/,/g, " ").trim()).split(/\s+/)).length; i < o; i += 2) t.push({ x: parseFloat(e[i]), y: parseFloat(e[i + 1]) });
                return t;
            },
            getCSSRules: function (e) {
                for (var t = e.getElementsByTagName("style"), i = {}, o = 0, n = t.length; o < n; o++) {
                    var r = t[o].textContent;
                    "" !== (r = r.replace(/\/\*[\s\S]*?\*\//g, "")).trim() &&
                        r
                            .match(/[^{]*\{[\s\S]*?\}/g)
                            .map(function (e) {
                                return e.trim();
                            })
                            .forEach(function (e) {
                                var t = e.match(/([\s\S]*?)\s*\{([^}]*)\}/),
                                    r = {},
                                    a = t[2]
                                        .trim()
                                        .replace(/;$/, "")
                                        .split(/\s*;\s*/);
                                for (o = 0, n = a.length; o < n; o++) {
                                    var c = (l = a[o].split(/\s*:\s*/))[0],
                                        l = l[1];
                                    r[c] = l;
                                }
                                (e = t[1]).split(",").forEach(function (e) {
                                    "" !== (e = e.replace(/^svg/i, "").trim()) && (i[e] ? s.util.object.extend(i[e], r) : (i[e] = s.util.object.clone(r)));
                                });
                            });
                }
                return i;
            },
            loadSVGFromURL: function (e, t, i, o) {
                (e = e.replace(/^\n\s*/, "").trim()),
                    new s.util.request(e, {
                        method: "get",
                        onComplete: function (e) {
                            if (!(e = e.responseXML) || !e.documentElement) return t && t(null), !1;
                            s.parseSVGDocument(
                                e.documentElement,
                                function (e, i, o, n) {
                                    t && t(e, i, o, n);
                                },
                                i,
                                o
                            );
                        },
                    });
            },
            loadSVGFromString: function (e, t, i, o) {
                (e = new s.window.DOMParser().parseFromString(e.trim(), "text/xml")),
                    s.parseSVGDocument(
                        e.documentElement,
                        function (e, i, o, n) {
                            t(e, i, o, n);
                        },
                        i,
                        o
                    );
            },
        });
    })("undefined" != typeof exports ? exports : this),
    (fabric.ElementsParser = function (e, t, i, o, n, r) {
        (this.elements = e), (this.callback = t), (this.options = i), (this.reviver = o), (this.svgUid = (i && i.svgUid) || 0), (this.parsingOptions = n), (this.regexUrl = /^url\(['"]?#([^'"]+)['"]?\)/g), (this.doc = r);
    }),
    (function (e) {
        (e.parse = function () {
            (this.instances = new Array(this.elements.length)), (this.numElements = this.elements.length), this.createObjects();
        }),
            (e.createObjects = function () {
                var e = this;
                this.elements.forEach(function (t, i) {
                    t.setAttribute("svgUid", e.svgUid), e.createObject(t, i);
                });
            }),
            (e.findTag = function (e) {
                return fabric[fabric.util.string.capitalize(e.tagName.replace("svg:", ""))];
            }),
            (e.createObject = function (e, t) {
                var i = this.findTag(e);
                if (i && i.fromElement)
                    try {
                        i.fromElement(e, this.createCallback(t, e), this.options);
                    } catch (e) {
                        fabric.log(e);
                    }
                else this.checkIfDone();
            }),
            (e.createCallback = function (e, t) {
                var i = this;
                return function (o) {
                    var n;
                    i.resolveGradient(o, t, "fill"),
                        i.resolveGradient(o, t, "stroke"),
                        o instanceof fabric.Image && o._originalElement && (n = o.parsePreserveAspectRatioAttribute(t)),
                        o._removeTransformMatrix(n),
                        i.resolveClipPath(o, t),
                        i.reviver && i.reviver(t, o),
                        (i.instances[e] = o),
                        i.checkIfDone();
                };
            }),
            (e.extractPropertyDefinition = function (e, t, i) {
                if (((e = e[t]), (t = this.regexUrl).test(e))) return (t.lastIndex = 0), (e = t.exec(e)[1]), (t.lastIndex = 0), fabric[i][this.svgUid][e];
            }),
            (e.resolveGradient = function (e, t, i) {
                var o = this.extractPropertyDefinition(e, i, "gradientDefs");
                o && ((t = t.getAttribute(i + "-opacity")), (t = fabric.Gradient.fromElement(o, e, t, this.options)), e.set(i, t));
            }),
            (e.createClipPathCallback = function (e, t) {
                return function (e) {
                    e._removeTransformMatrix(), (e.fillRule = e.clipRule), t.push(e);
                };
            }),
            (e.resolveClipPath = function (e, t) {
                var i,
                    o = this.extractPropertyDefinition(e, "clipPath", "clipPaths");
                if (o) {
                    for (var n = [], r = fabric.util.invertTransform(e.calcTransformMatrix()), s = o[0].parentNode, a = t; a.parentNode && a.getAttribute("clip-path") !== e.clipPath; ) a = a.parentNode;
                    a.parentNode.appendChild(s);
                    for (var c = 0; c < o.length; c++) (i = o[c]), this.findTag(i).fromElement(i, this.createClipPathCallback(e, n), this.options);
                    (o = 1 === n.length ? n[0] : new fabric.Group(n)),
                        (r = fabric.util.multiplyTransformMatrices(r, o.calcTransformMatrix())),
                        o.clipPath && this.resolveClipPath(o, a),
                        (r = fabric.util.qrDecompose(r)),
                        (o.flipX = !1),
                        (o.flipY = !1),
                        o.set("scaleX", r.scaleX),
                        o.set("scaleY", r.scaleY),
                        (o.angle = r.angle),
                        (o.skewX = r.skewX),
                        (o.skewY = 0),
                        o.setPositionByOrigin({ x: r.translateX, y: r.translateY }, "center", "center"),
                        (e.clipPath = o);
                } else delete e.clipPath;
            }),
            (e.checkIfDone = function () {
                0 == --this.numElements &&
                    ((this.instances = this.instances.filter(function (e) {
                        return null != e;
                    })),
                    this.callback(this.instances, this.elements));
            });
    })(fabric.ElementsParser.prototype),
    (function (e) {
        function t(e, t) {
            (this.x = e), (this.y = t);
        }
        (e = e.fabric || (e.fabric = {})).Point
            ? e.warn("fabric.Point is already defined")
            : ((e.Point = t).prototype = {
                  type: "point",
                  constructor: t,
                  add: function (e) {
                      return new t(this.x + e.x, this.y + e.y);
                  },
                  addEquals: function (e) {
                      return (this.x += e.x), (this.y += e.y), this;
                  },
                  scalarAdd: function (e) {
                      return new t(this.x + e, this.y + e);
                  },
                  scalarAddEquals: function (e) {
                      return (this.x += e), (this.y += e), this;
                  },
                  subtract: function (e) {
                      return new t(this.x - e.x, this.y - e.y);
                  },
                  subtractEquals: function (e) {
                      return (this.x -= e.x), (this.y -= e.y), this;
                  },
                  scalarSubtract: function (e) {
                      return new t(this.x - e, this.y - e);
                  },
                  scalarSubtractEquals: function (e) {
                      return (this.x -= e), (this.y -= e), this;
                  },
                  multiply: function (e) {
                      return new t(this.x * e, this.y * e);
                  },
                  multiplyEquals: function (e) {
                      return (this.x *= e), (this.y *= e), this;
                  },
                  divide: function (e) {
                      return new t(this.x / e, this.y / e);
                  },
                  divideEquals: function (e) {
                      return (this.x /= e), (this.y /= e), this;
                  },
                  eq: function (e) {
                      return this.x === e.x && this.y === e.y;
                  },
                  lt: function (e) {
                      return this.x < e.x && this.y < e.y;
                  },
                  lte: function (e) {
                      return this.x <= e.x && this.y <= e.y;
                  },
                  gt: function (e) {
                      return this.x > e.x && this.y > e.y;
                  },
                  gte: function (e) {
                      return this.x >= e.x && this.y >= e.y;
                  },
                  lerp: function (e, i) {
                      return void 0 === i && (i = 0.5), (i = Math.max(Math.min(1, i), 0)), new t(this.x + (e.x - this.x) * i, this.y + (e.y - this.y) * i);
                  },
                  distanceFrom: function (e) {
                      var t = this.x - e.x;
                      e = this.y - e.y;
                      return Math.sqrt(t * t + e * e);
                  },
                  midPointFrom: function (e) {
                      return this.lerp(e);
                  },
                  min: function (e) {
                      return new t(Math.min(this.x, e.x), Math.min(this.y, e.y));
                  },
                  max: function (e) {
                      return new t(Math.max(this.x, e.x), Math.max(this.y, e.y));
                  },
                  toString: function () {
                      return this.x + "," + this.y;
                  },
                  setXY: function (e, t) {
                      return (this.x = e), (this.y = t), this;
                  },
                  setX: function (e) {
                      return (this.x = e), this;
                  },
                  setY: function (e) {
                      return (this.y = e), this;
                  },
                  setFromPoint: function (e) {
                      return (this.x = e.x), (this.y = e.y), this;
                  },
                  swap: function (e) {
                      var t = this.x,
                          i = this.y;
                      (this.x = e.x), (this.y = e.y), (e.x = t), (e.y = i);
                  },
                  clone: function () {
                      return new t(this.x, this.y);
                  },
              });
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        function i(e) {
            (this.status = e), (this.points = []);
        }
        t.Intersection
            ? t.warn("fabric.Intersection is already defined")
            : ((t.Intersection = i),
              (t.Intersection.prototype = {
                  constructor: i,
                  appendPoint: function (e) {
                      return this.points.push(e), this;
                  },
                  appendPoints: function (e) {
                      return (this.points = this.points.concat(e)), this;
                  },
              }),
              (t.Intersection.intersectLineLine = function (e, o, n, r) {
                  var s,
                      a = (r.x - n.x) * (e.y - n.y) - (r.y - n.y) * (e.x - n.x),
                      c = (o.x - e.x) * (e.y - n.y) - (o.y - e.y) * (e.x - n.x);
                  return (
                      0 != (r = (r.y - n.y) * (o.x - e.x) - (r.x - n.x) * (o.y - e.y))
                          ? ((n = c / r), 0 <= (r = a / r) && r <= 1 && 0 <= n && n <= 1 ? (s = new i("Intersection")).appendPoint(new t.Point(e.x + r * (o.x - e.x), e.y + r * (o.y - e.y))) : (s = new i()))
                          : (s = new i(0 == a || 0 == c ? "Coincident" : "Parallel")),
                      s
                  );
              }),
              (t.Intersection.intersectLinePolygon = function (e, t, o) {
                  for (var n, r, s = new i(), a = o.length, c = 0; c < a; c++) (n = o[c]), (r = o[(c + 1) % a]), (r = i.intersectLineLine(e, t, n, r)), s.appendPoints(r.points);
                  return 0 < s.points.length && (s.status = "Intersection"), s;
              }),
              (t.Intersection.intersectPolygonPolygon = function (e, t) {
                  for (var o = new i(), n = e.length, r = 0; r < n; r++) {
                      var s = e[r],
                          a = e[(r + 1) % n];
                      a = i.intersectLinePolygon(s, a, t);
                      o.appendPoints(a.points);
                  }
                  return 0 < o.points.length && (o.status = "Intersection"), o;
              }),
              (t.Intersection.intersectPolygonRectangle = function (e, o, n) {
                  var r = o.min(n),
                      s = o.max(n),
                      a = new t.Point(s.x, r.y);
                  (o = new t.Point(r.x, s.y)), (n = i.intersectLinePolygon(r, a, e)), (a = i.intersectLinePolygon(a, s, e)), (s = i.intersectLinePolygon(s, o, e)), (r = i.intersectLinePolygon(o, r, e));
                  return (e = new i()).appendPoints(n.points), e.appendPoints(a.points), e.appendPoints(s.points), e.appendPoints(r.points), 0 < e.points.length && (e.status = "Intersection"), e;
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        function i(e) {
            e ? this._tryParsingColor(e) : this.setSource([0, 0, 0, 1]);
        }
        function o(e, t, i) {
            return i < 0 && (i += 1), 1 < i && --i, i < 1 / 6 ? e + 6 * (t - e) * i : i < 0.5 ? t : i < 2 / 3 ? e + (t - e) * (2 / 3 - i) * 6 : e;
        }
        t.Color
            ? t.warn("fabric.Color is already defined.")
            : ((t.Color = i),
              (t.Color.prototype = {
                  _tryParsingColor: function (e) {
                      var t;
                      (t = (t = (t = (t = (t = "transparent" === (e = e in i.colorNameMap ? i.colorNameMap[e] : e) ? [255, 255, 255, 0] : t) || i.sourceFromHex(e)) || i.sourceFromRgb(e)) || i.sourceFromHsl(e)) || [0, 0, 0, 1]) &&
                          this.setSource(t);
                  },
                  _rgbToHsl: function (e, i, o) {
                      var n,
                          r = t.util.array.max([(e /= 255), (i /= 255), (o /= 255)]),
                          s = t.util.array.min([e, i, o]),
                          a = (r + s) / 2;
                      if (r === s) n = l = 0;
                      else {
                          var c = r - s,
                              l = 0.5 < a ? c / (2 - r - s) : c / (r + s);
                          switch (r) {
                              case e:
                                  n = (i - o) / c + (i < o ? 6 : 0);
                                  break;
                              case i:
                                  n = (o - e) / c + 2;
                                  break;
                              case o:
                                  n = (e - i) / c + 4;
                          }
                          n /= 6;
                      }
                      return [Math.round(360 * n), Math.round(100 * l), Math.round(100 * a)];
                  },
                  getSource: function () {
                      return this._source;
                  },
                  setSource: function (e) {
                      this._source = e;
                  },
                  toRgb: function () {
                      var e = this.getSource();
                      return "rgb(" + e[0] + "," + e[1] + "," + e[2] + ")";
                  },
                  toRgba: function () {
                      var e = this.getSource();
                      return "rgba(" + e[0] + "," + e[1] + "," + e[2] + "," + e[3] + ")";
                  },
                  toHsl: function () {
                      var e = this.getSource();
                      return "hsl(" + (e = this._rgbToHsl(e[0], e[1], e[2]))[0] + "," + e[1] + "%," + e[2] + "%)";
                  },
                  toHsla: function () {
                      var e = this.getSource(),
                          t = this._rgbToHsl(e[0], e[1], e[2]);
                      return "hsla(" + t[0] + "," + t[1] + "%," + t[2] + "%," + e[3] + ")";
                  },
                  toHex: function () {
                      var e,
                          t = this.getSource(),
                          i = t[0].toString(16);
                      return (i = 1 === i.length ? "0" + i : i), (e = 1 === (e = t[1].toString(16)).length ? "0" + e : e), (t = 1 === (t = t[2].toString(16)).length ? "0" + t : t), i.toUpperCase() + e.toUpperCase() + t.toUpperCase();
                  },
                  toHexa: function () {
                      var e = this.getSource();
                      return (e = 1 === (e = (e = Math.round(255 * e[3])).toString(16)).length ? "0" + e : e), this.toHex() + e.toUpperCase();
                  },
                  getAlpha: function () {
                      return this.getSource()[3];
                  },
                  setAlpha: function (e) {
                      var t = this.getSource();
                      return (t[3] = e), this.setSource(t), this;
                  },
                  toGrayscale: function () {
                      var e = this.getSource(),
                          t = parseInt((0.3 * e[0] + 0.59 * e[1] + 0.11 * e[2]).toFixed(0), 10);
                      e = e[3];
                      return this.setSource([t, t, t, e]), this;
                  },
                  toBlackWhite: function (e) {
                      var t = (0.3 * (i = this.getSource())[0] + 0.59 * i[1] + 0.11 * i[2]).toFixed(0),
                          i = i[3];
                      return (e = e || 127), (t = Number(t) < Number(e) ? 0 : 255), this.setSource([t, t, t, i]), this;
                  },
                  overlayWith: function (e) {
                      e instanceof i || (e = new i(e));
                      for (var t = [], o = this.getAlpha(), n = this.getSource(), r = e.getSource(), s = 0; s < 3; s++) t.push(Math.round(0.5 * n[s] + 0.5 * r[s]));
                      return (t[3] = o), this.setSource(t), this;
                  },
              }),
              (t.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*((?:\d*\.?\d+)?)\s*)?\)$/i),
              (t.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/i),
              (t.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i),
              (t.Color.colorNameMap = {
                  aliceblue: "#F0F8FF",
                  antiquewhite: "#FAEBD7",
                  aqua: "#00FFFF",
                  aquamarine: "#7FFFD4",
                  azure: "#F0FFFF",
                  beige: "#F5F5DC",
                  bisque: "#FFE4C4",
                  black: "#000000",
                  blanchedalmond: "#FFEBCD",
                  blue: "#0000FF",
                  blueviolet: "#8A2BE2",
                  brown: "#A52A2A",
                  burlywood: "#DEB887",
                  cadetblue: "#5F9EA0",
                  chartreuse: "#7FFF00",
                  chocolate: "#D2691E",
                  coral: "#FF7F50",
                  cornflowerblue: "#6495ED",
                  cornsilk: "#FFF8DC",
                  crimson: "#DC143C",
                  cyan: "#00FFFF",
                  darkblue: "#00008B",
                  darkcyan: "#008B8B",
                  darkgoldenrod: "#B8860B",
                  darkgray: "#A9A9A9",
                  darkgrey: "#A9A9A9",
                  darkgreen: "#006400",
                  darkkhaki: "#BDB76B",
                  darkmagenta: "#8B008B",
                  darkolivegreen: "#556B2F",
                  darkorange: "#FF8C00",
                  darkorchid: "#9932CC",
                  darkred: "#8B0000",
                  darksalmon: "#E9967A",
                  darkseagreen: "#8FBC8F",
                  darkslateblue: "#483D8B",
                  darkslategray: "#2F4F4F",
                  darkslategrey: "#2F4F4F",
                  darkturquoise: "#00CED1",
                  darkviolet: "#9400D3",
                  deeppink: "#FF1493",
                  deepskyblue: "#00BFFF",
                  dimgray: "#696969",
                  dimgrey: "#696969",
                  dodgerblue: "#1E90FF",
                  firebrick: "#B22222",
                  floralwhite: "#FFFAF0",
                  forestgreen: "#228B22",
                  fuchsia: "#FF00FF",
                  gainsboro: "#DCDCDC",
                  ghostwhite: "#F8F8FF",
                  gold: "#FFD700",
                  goldenrod: "#DAA520",
                  gray: "#808080",
                  grey: "#808080",
                  green: "#008000",
                  greenyellow: "#ADFF2F",
                  honeydew: "#F0FFF0",
                  hotpink: "#FF69B4",
                  indianred: "#CD5C5C",
                  indigo: "#4B0082",
                  ivory: "#FFFFF0",
                  khaki: "#F0E68C",
                  lavender: "#E6E6FA",
                  lavenderblush: "#FFF0F5",
                  lawngreen: "#7CFC00",
                  lemonchiffon: "#FFFACD",
                  lightblue: "#ADD8E6",
                  lightcoral: "#F08080",
                  lightcyan: "#E0FFFF",
                  lightgoldenrodyellow: "#FAFAD2",
                  lightgray: "#D3D3D3",
                  lightgrey: "#D3D3D3",
                  lightgreen: "#90EE90",
                  lightpink: "#FFB6C1",
                  lightsalmon: "#FFA07A",
                  lightseagreen: "#20B2AA",
                  lightskyblue: "#87CEFA",
                  lightslategray: "#778899",
                  lightslategrey: "#778899",
                  lightsteelblue: "#B0C4DE",
                  lightyellow: "#FFFFE0",
                  lime: "#00FF00",
                  limegreen: "#32CD32",
                  linen: "#FAF0E6",
                  magenta: "#FF00FF",
                  maroon: "#800000",
                  mediumaquamarine: "#66CDAA",
                  mediumblue: "#0000CD",
                  mediumorchid: "#BA55D3",
                  mediumpurple: "#9370DB",
                  mediumseagreen: "#3CB371",
                  mediumslateblue: "#7B68EE",
                  mediumspringgreen: "#00FA9A",
                  mediumturquoise: "#48D1CC",
                  mediumvioletred: "#C71585",
                  midnightblue: "#191970",
                  mintcream: "#F5FFFA",
                  mistyrose: "#FFE4E1",
                  moccasin: "#FFE4B5",
                  navajowhite: "#FFDEAD",
                  navy: "#000080",
                  oldlace: "#FDF5E6",
                  olive: "#808000",
                  olivedrab: "#6B8E23",
                  orange: "#FFA500",
                  orangered: "#FF4500",
                  orchid: "#DA70D6",
                  palegoldenrod: "#EEE8AA",
                  palegreen: "#98FB98",
                  paleturquoise: "#AFEEEE",
                  palevioletred: "#DB7093",
                  papayawhip: "#FFEFD5",
                  peachpuff: "#FFDAB9",
                  peru: "#CD853F",
                  pink: "#FFC0CB",
                  plum: "#DDA0DD",
                  powderblue: "#B0E0E6",
                  purple: "#800080",
                  rebeccapurple: "#663399",
                  red: "#FF0000",
                  rosybrown: "#BC8F8F",
                  royalblue: "#4169E1",
                  saddlebrown: "#8B4513",
                  salmon: "#FA8072",
                  sandybrown: "#F4A460",
                  seagreen: "#2E8B57",
                  seashell: "#FFF5EE",
                  sienna: "#A0522D",
                  silver: "#C0C0C0",
                  skyblue: "#87CEEB",
                  slateblue: "#6A5ACD",
                  slategray: "#708090",
                  slategrey: "#708090",
                  snow: "#FFFAFA",
                  springgreen: "#00FF7F",
                  steelblue: "#4682B4",
                  tan: "#D2B48C",
                  teal: "#008080",
                  thistle: "#D8BFD8",
                  tomato: "#FF6347",
                  turquoise: "#40E0D0",
                  violet: "#EE82EE",
                  wheat: "#F5DEB3",
                  white: "#FFFFFF",
                  whitesmoke: "#F5F5F5",
                  yellow: "#FFFF00",
                  yellowgreen: "#9ACD32",
              }),
              (t.Color.fromRgb = function (e) {
                  return i.fromSource(i.sourceFromRgb(e));
              }),
              (t.Color.sourceFromRgb = function (e) {
                  var t = e.match(i.reRGBa);
                  if (t) {
                      var o = (parseInt(t[1], 10) / (/%$/.test(t[1]) ? 100 : 1)) * (/%$/.test(t[1]) ? 255 : 1),
                          n = (parseInt(t[2], 10) / (/%$/.test(t[2]) ? 100 : 1)) * (/%$/.test(t[2]) ? 255 : 1);
                      e = (parseInt(t[3], 10) / (/%$/.test(t[3]) ? 100 : 1)) * (/%$/.test(t[3]) ? 255 : 1);
                      return [parseInt(o, 10), parseInt(n, 10), parseInt(e, 10), t[4] ? parseFloat(t[4]) : 1];
                  }
              }),
              (t.Color.fromRgba = i.fromRgb),
              (t.Color.fromHsl = function (e) {
                  return i.fromSource(i.sourceFromHsl(e));
              }),
              (t.Color.sourceFromHsl = function (e) {
                  var t = e.match(i.reHSLa);
                  if (t) {
                      var n,
                          r,
                          s,
                          a = (((parseFloat(t[1]) % 360) + 360) % 360) / 360,
                          c = parseFloat(t[2]) / (/%$/.test(t[2]) ? 100 : 1);
                      e = parseFloat(t[3]) / (/%$/.test(t[3]) ? 100 : 1);
                      return (
                          0 == c ? (n = r = s = e) : ((n = o((c = 2 * e - (e = e <= 0.5 ? e * (1 + c) : e + c - e * c)), e, a + 1 / 3)), (r = o(c, e, a)), (s = o(c, e, a - 1 / 3))),
                          [Math.round(255 * n), Math.round(255 * r), Math.round(255 * s), t[4] ? parseFloat(t[4]) : 1]
                      );
                  }
              }),
              (t.Color.fromHsla = i.fromHsl),
              (t.Color.fromHex = function (e) {
                  return i.fromSource(i.sourceFromHex(e));
              }),
              (t.Color.sourceFromHex = function (e) {
                  if (e.match(i.reHex)) {
                      var t = 3 === (s = e.slice(e.indexOf("#") + 1)).length || 4 === s.length,
                          o = 8 === s.length || 4 === s.length,
                          n = t ? s.charAt(0) + s.charAt(0) : s.substring(0, 2),
                          r = t ? s.charAt(1) + s.charAt(1) : s.substring(2, 4),
                          s = ((e = t ? s.charAt(2) + s.charAt(2) : s.substring(4, 6)), o ? (t ? s.charAt(3) + s.charAt(3) : s.substring(6, 8)) : "FF");
                      return [parseInt(n, 16), parseInt(r, 16), parseInt(e, 16), parseFloat((parseInt(s, 16) / 255).toFixed(2))];
                  }
              }),
              (t.Color.fromSource = function (e) {
                  var t = new i();
                  return t.setSource(e), t;
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = ["e", "se", "s", "sw", "w", "nw", "n", "ne", "e"],
            o = ["ns", "nesw", "ew", "nwse"],
            n = {},
            r = "left",
            s = "top",
            a = "right",
            c = "bottom",
            l = "center",
            d = { top: c, bottom: s, left: a, right: r, center: l },
            h = t.util.radiansToDegrees,
            u =
                Math.sign ||
                function (e) {
                    return (0 < e) - (e < 0) || +e;
                };
        function f(e, t) {
            return (t = e.angle + h(Math.atan2(t.y, t.x)) + 360), Math.round((t % 360) / 45);
        }
        function m(e, i) {
            var o = i.transform.target,
                n = o.canvas,
                r = t.util.object.clone(i);
            (r.target = o), n && n.fire("object:" + e, r), o.fire(e, i);
        }
        function g(e, t) {
            return (e = e[(t = t.canvas).uniScaleKey]), (t.uniformScaling && !e) || (!t.uniformScaling && e);
        }
        function p(e) {
            return e.originX === l && e.originY === l;
        }
        function v(e, t, i) {
            var o = e.lockScalingX;
            e = e.lockScalingY;
            return !((!o || !e) && (t || (!o && !e) || !i) && (!o || "x" !== t) && (!e || "y" !== t));
        }
        function b(e, t, i, o) {
            return { e: e, transform: t, pointer: { x: i, y: o } };
        }
        function y(e) {
            return function (t, i, o, n) {
                var r = i.target,
                    s = r.getCenterPoint();
                (s = r.translateToOriginPoint(s, i.originX, i.originY)), (n = e(t, i, o, n));
                return r.setPositionByOrigin(s, i.originX, i.originY), n;
            };
        }
        function S(e, t) {
            return function (i, o, n, r) {
                var s = t(i, o, n, r);
                return s && m(e, b(i, o, n, r)), s;
            };
        }
        function w(e, i, o, n, r) {
            var s = e.target,
                a = s.controls[e.corner];
            (e = s.canvas.getZoom()), (e = s.padding / e);
            return (o = s.toLocalPoint(new t.Point(n, r), i, o)).x >= e && (o.x -= e), o.x <= -e && (o.x += e), o.y >= e && (o.y -= e), o.y <= e && (o.y += e), (o.x -= a.offsetX), (o.y -= a.offsetY), o;
        }
        function _(e) {
            return e.flipX !== e.flipY;
        }
        function C(e, t, i, o, n) {
            0 !== e[t] && ((o = (n / e._getTransformedDimensions()[o]) * e[i]), e.set(i, o));
        }
        function x(e, t, i, o) {
            var n,
                l = t.target,
                d = l._getTransformedDimensions(0, l.skewY);
            (i = w(t, t.originX, t.originY, i, o)), (o = Math.abs(2 * i.x) - d.x), (i = l.skewX);
            return (
                o < 2 ? (n = 0) : ((n = h(Math.atan2(o / l.scaleX, d.y / l.scaleY))), t.originX === r && t.originY === c && (n = -n), t.originX === a && t.originY === s && (n = -n), _(l) && (n = -n)),
                (t = i !== n) && ((i = l._getTransformedDimensions().y), l.set("skewX", n), C(l, "skewY", "scaleY", "y", i)),
                t
            );
        }
        function T(e, t, i, o) {
            var n,
                l = t.target,
                d = l._getTransformedDimensions(l.skewX, 0);
            (i = w(t, t.originX, t.originY, i, o)), (o = Math.abs(2 * i.y) - d.y), (i = l.skewY);
            return (
                o < 2 ? (n = 0) : ((n = h(Math.atan2(o / l.scaleY, d.x / l.scaleX))), t.originX === r && t.originY === c && (n = -n), t.originX === a && t.originY === s && (n = -n), _(l) && (n = -n)),
                (t = i !== n) && ((i = l._getTransformedDimensions().x), l.set("skewY", n), C(l, "skewX", "scaleX", "x", i)),
                t
            );
        }
        function k(e, t, i, o, n) {
            var r = t.target,
                s = r.lockScalingX,
                a = r.lockScalingY,
                c = (n = n || {}).by,
                l = g(e, r);
            (n = v(r, c, l)), (e = t.gestureScale);
            if (n) return !1;
            if (e) (h = t.scaleX * e), (f = t.scaleY * e);
            else {
                if (((n = w(t, t.originX, t.originY, i, o)), (e = "y" !== c ? u(n.x) : 1), (m = "x" !== c ? u(n.y) : 1), t.signX || (t.signX = e), t.signY || (t.signY = m), r.lockScalingFlip && (t.signX !== e || t.signY !== m))) return !1;
                var h, f;
                i = r._getTransformedDimensions();
                (f =
                    l && !c
                        ? ((o = Math.abs(n.x) + Math.abs(n.y)), (l = t.original), (o /= Math.abs((i.x * l.scaleX) / r.scaleX) + Math.abs((i.y * l.scaleY) / r.scaleY)), (h = l.scaleX * o), l.scaleY * o)
                        : ((h = Math.abs((n.x * r.scaleX) / i.x)), Math.abs((n.y * r.scaleY) / i.y))),
                    p(t) && ((h *= 2), (f *= 2)),
                    t.signX !== e && "y" !== c && ((t.originX = d[t.originX]), (h *= -1), (t.signX = e)),
                    t.signY !== m && "x" !== c && ((t.originY = d[t.originY]), (f *= -1), (t.signY = m));
            }
            t = r.scaleX;
            var m = r.scaleY;
            return c ? ("x" === c && r.set("scaleX", h), "y" === c && r.set("scaleY", f)) : (s || r.set("scaleX", h), a || r.set("scaleY", f)), t !== r.scaleX || m !== r.scaleY;
        }
        (n.scaleCursorStyleHandler = function (e, t, o) {
            var n = g(e, o);
            e = "";
            return 0 !== t.x && 0 === t.y ? (e = "x") : 0 === t.x && 0 !== t.y && (e = "y"), v(o, e, n) ? "not-allowed" : ((t = f(o, t)), i[t] + "-resize");
        }),
            (n.skewCursorStyleHandler = function (e, t, i) {
                return (0 !== t.x && i.lockSkewingY) || (0 !== t.y && i.lockSkewingX) ? "not-allowed" : ((t = f(i, t) % 4), o[t] + "-resize");
            }),
            (n.scaleSkewCursorStyleHandler = function (e, t, i) {
                return e[i.canvas.altActionKey] ? n.skewCursorStyleHandler(e, t, i) : n.scaleCursorStyleHandler(e, t, i);
            }),
            (n.rotationWithSnapping = S(
                "rotating",
                y(function (e, t, i, o) {
                    var n = t,
                        r = n.target,
                        s = r.translateToOriginPoint(r.getCenterPoint(), n.originX, n.originY);
                    return (
                        !r.lockRotation &&
                        ((t = Math.atan2(n.ey - s.y, n.ex - s.x)),
                        (o = Math.atan2(o - s.y, i - s.x)),
                        (i = h(o - t + n.theta)),
                        0 < r.snapAngle && ((o = r.snapAngle), (t = r.snapThreshold || o), (n = Math.ceil(i / o) * o), (o = Math.floor(i / o) * o), Math.abs(i - o) < t ? (i = o) : Math.abs(i - n) < t && (i = n)),
                        i < 0 && (i = 360 + i),
                        (s = r.angle !== (i %= 360)),
                        (r.angle = i),
                        s)
                    );
                })
            )),
            (n.scalingEqually = S(
                "scaling",
                y(function (e, t, i, o) {
                    return k(e, t, i, o);
                })
            )),
            (n.scalingX = S(
                "scaling",
                y(function (e, t, i, o) {
                    return k(e, t, i, o, { by: "x" });
                })
            )),
            (n.scalingY = S(
                "scaling",
                y(function (e, t, i, o) {
                    return k(e, t, i, o, { by: "y" });
                })
            )),
            (n.scalingYOrSkewingX = function (e, t, i, o) {
                return e[t.target.canvas.altActionKey] ? n.skewHandlerX(e, t, i, o) : n.scalingY(e, t, i, o);
            }),
            (n.scalingXOrSkewingY = function (e, t, i, o) {
                return e[t.target.canvas.altActionKey] ? n.skewHandlerY(e, t, i, o) : n.scalingX(e, t, i, o);
            }),
            (n.changeWidth = S(
                "resizing",
                y(function (e, t, i, o) {
                    var n = t.target,
                        r = w(t, t.originX, t.originY, i, o);
                    (i = n.strokeWidth / (n.strokeUniform ? n.scaleX : 1)), (o = p(t) ? 2 : 1), (t = n.width), (i = Math.abs((r.x * o) / n.scaleX) - i);
                    return n.set("width", Math.max(i, 0)), t !== i;
                })
            )),
            (n.skewHandlerX = function (e, t, i, o) {
                var n,
                    c = t.target,
                    d = c.skewX,
                    h = t.originY;
                return !c.lockSkewingX && (0 === d ? (n = 0 < w(t, l, l, i, o).x ? r : a) : (0 < d && (n = h === s ? r : a), d < 0 && (n = h === s ? a : r), _(c) && (n = n === r ? a : r)), (t.originX = n), S("skewing", y(x))(e, t, i, o));
            }),
            (n.skewHandlerY = function (e, t, i, o) {
                var n,
                    a = t.target,
                    d = a.skewY,
                    h = t.originX;
                return !a.lockSkewingY && (0 === d ? (n = 0 < w(t, l, l, i, o).y ? s : c) : (0 < d && (n = h === r ? s : c), d < 0 && (n = h === r ? c : s), _(a) && (n = n === s ? c : s)), (t.originY = n), S("skewing", y(T))(e, t, i, o));
            }),
            (n.dragHandler = function (e, t, i, o) {
                var n = t.target,
                    r = i - t.offsetX,
                    s = o - t.offsetY,
                    a = !n.get("lockMovementX") && n.left !== r,
                    c = !n.get("lockMovementY") && n.top !== s;
                return a && n.set("left", r), c && n.set("top", s), (a || c) && m("moving", b(e, t, i, o)), a || c;
            }),
            (n.scaleOrSkewActionName = function (e, t, i) {
                return (i = e[i.canvas.altActionKey]), 0 === t.x ? (i ? "skewX" : "scaleY") : 0 === t.y ? (i ? "skewY" : "scaleX") : void 0;
            }),
            (n.rotationStyleHandler = function (e, t, i) {
                return i.lockRotation ? "not-allowed" : t.cursorStyle;
            }),
            (n.fireEvent = m),
            (n.wrapWithFixedAnchor = y),
            (n.wrapWithFireEvent = S),
            (n.getLocalPoint = w),
            (t.controlsUtils = n);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = (e = e.fabric || (e.fabric = {})).util.degreesToRadians;
        ((e = e.controlsUtils).renderCircleControl = function (e, t, i, o, n) {
            o = o || {};
            var r,
                s = this.sizeX || o.cornerSize || n.cornerSize,
                a = this.sizeY || o.cornerSize || n.cornerSize,
                c = (h = (void 0 !== o.transparentCorners ? o : n).transparentCorners) ? "stroke" : "fill",
                l = !h && (o.cornerStrokeColor || n.cornerStrokeColor),
                d = t,
                h = i;
            e.save(),
                (e.fillStyle = o.cornerColor || n.cornerColor),
                (e.strokeStyle = o.cornerStrokeColor || n.cornerStrokeColor),
                a < s ? (e.scale(1, a / (r = s)), (h = (i * s) / a)) : s < a ? (e.scale(s / (r = a), 1), (d = (t * a) / s)) : (r = s),
                (e.lineWidth = 1),
                e.beginPath(),
                e.arc(d, h, r / 2, 0, 2 * Math.PI, !1),
                e[c](),
                l && e.stroke(),
                e.restore();
        }),
            (e.renderSquareControl = function (e, i, o, n, r) {
                n = n || {};
                var s = this.sizeX || n.cornerSize || r.cornerSize,
                    a = this.sizeY || n.cornerSize || r.cornerSize,
                    c = (h = (void 0 !== n.transparentCorners ? n : r).transparentCorners) ? "stroke" : "fill",
                    l = !h && (n.cornerStrokeColor || r.cornerStrokeColor),
                    d = s / 2,
                    h = a / 2;
                e.save(),
                    (e.fillStyle = n.cornerColor || r.cornerColor),
                    (e.strokeStyle = n.cornerStrokeColor || r.cornerStrokeColor),
                    (e.lineWidth = 1),
                    e.translate(i, o),
                    e.rotate(t(r.angle)),
                    e[c + "Rect"](-d, -h, s, a),
                    l && e.strokeRect(-d, -h, s, a),
                    e.restore();
            });
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        (t.Control = function (e) {
            for (var t in e) this[t] = e[t];
        }),
            (t.Control.prototype = {
                visible: !0,
                actionName: "scale",
                angle: 0,
                x: 0,
                y: 0,
                offsetX: 0,
                offsetY: 0,
                sizeX: null,
                sizeY: null,
                touchSizeX: null,
                touchSizeY: null,
                cursorStyle: "crosshair",
                withConnection: !1,
                actionHandler: function () {},
                mouseDownHandler: function () {},
                mouseUpHandler: function () {},
                getActionHandler: function () {
                    return this.actionHandler;
                },
                getMouseDownHandler: function () {
                    return this.mouseDownHandler;
                },
                getMouseUpHandler: function () {
                    return this.mouseUpHandler;
                },
                cursorStyleHandler: function (e, t) {
                    return t.cursorStyle;
                },
                getActionName: function (e, t) {
                    return t.actionName;
                },
                getVisibility: function (e, t) {
                    return (e = e._controlsVisibility) && void 0 !== e[t] ? e[t] : this.visible;
                },
                setVisibility: function (e) {
                    this.visible = e;
                },
                positionHandler: function (e, i) {
                    return t.util.transformPoint({ x: this.x * e.x + this.offsetX, y: this.y * e.y + this.offsetY }, i);
                },
                calcCornerCoords: function (e, i, o, n, r) {
                    var s,
                        a,
                        c,
                        l,
                        d,
                        h,
                        u = r ? this.touchSizeX : this.sizeX;
                    r = r ? this.touchSizeY : this.sizeY;
                    return (
                        u && r && u !== r
                            ? ((c = Math.atan2(r, u)),
                              (d = Math.sqrt(u * u + r * r) / 2),
                              (h = c - t.util.degreesToRadians(e)),
                              (l = Math.PI / 2 - c - t.util.degreesToRadians(e)),
                              (s = d * t.util.cos(h)),
                              (a = d * t.util.sin(h)),
                              (c = d * t.util.cos(l)),
                              (l = d * t.util.sin(l)))
                            : ((d = 0.7071067812 * (u && r ? u : i)), (h = t.util.degreesToRadians(45 - e)), (s = c = d * t.util.cos(h)), (a = l = d * t.util.sin(h))),
                        { tl: { x: o - l, y: n - c }, tr: { x: o + s, y: n - a }, bl: { x: o - s, y: n + a }, br: { x: o + l, y: n + c } }
                    );
                },
                render: function (e, i, o, n, r) {
                    ("circle" === ((n = n || {}).cornerStyle || r.cornerStyle) ? t.controlsUtils.renderCircleControl : t.controlsUtils.renderSquareControl).call(this, e, i, o, n, r);
                },
            });
    })("undefined" != typeof exports ? exports : this),
    (function () {
        var e = fabric.util.object.clone;
        (fabric.Gradient = fabric.util.createClass({
            offsetX: 0,
            offsetY: 0,
            gradientTransform: null,
            gradientUnits: "pixels",
            type: "linear",
            initialize: function (e) {
                (e = e || {}).coords || (e.coords = {});
                var t,
                    i = this;
                Object.keys(e).forEach(function (t) {
                    i[t] = e[t];
                }),
                    this.id ? (this.id += "_" + fabric.Object.__uid++) : (this.id = fabric.Object.__uid++),
                    (t = { x1: e.coords.x1 || 0, y1: e.coords.y1 || 0, x2: e.coords.x2 || 0, y2: e.coords.y2 || 0 }),
                    "radial" === this.type && ((t.r1 = e.coords.r1 || 0), (t.r2 = e.coords.r2 || 0)),
                    (this.coords = t),
                    (this.colorStops = e.colorStops.slice());
            },
            addColorStop: function (e) {
                for (var t in e) {
                    var i = new fabric.Color(e[t]);
                    this.colorStops.push({ offset: parseFloat(t), color: i.toRgb(), opacity: i.getAlpha() });
                }
                return this;
            },
            toObject: function (e) {
                var t = {
                    type: this.type,
                    coords: this.coords,
                    colorStops: this.colorStops,
                    offsetX: this.offsetX,
                    offsetY: this.offsetY,
                    gradientUnits: this.gradientUnits,
                    gradientTransform: this.gradientTransform && this.gradientTransform.concat(),
                };
                return fabric.util.populateWithProperties(this, t, e), t;
            },
            toSVG: function (t, i) {
                var o,
                    n = e(this.coords, !0),
                    r = ((i = i || {}), e(this.colorStops, !0)),
                    s = n.r1 > n.r2,
                    a = (this.gradientTransform || fabric.iMatrix).concat(),
                    c = -this.offsetX,
                    l = -this.offsetY,
                    d = !!i.additionalTransform,
                    h = "pixels" === this.gradientUnits ? "userSpaceOnUse" : "objectBoundingBox";
                if (
                    (r.sort(function (e, t) {
                        return e.offset - t.offset;
                    }),
                    "objectBoundingBox" == h ? ((c /= t.width), (l /= t.height)) : ((c += t.width / 2), (l += t.height / 2)),
                    "path" === t.type && "percentage" !== this.gradientUnits && ((c -= t.pathOffset.x), (l -= t.pathOffset.y)),
                    (a[4] -= c),
                    (a[5] -= l),
                    (h = 'id="SVGID_' + this.id + '" gradientUnits="' + h + '"'),
                    (h += ' gradientTransform="' + (d ? i.additionalTransform + " " : "") + fabric.util.matrixToSVG(a) + '" '),
                    "linear" === this.type
                        ? (o = ["<linearGradient ", h, ' x1="', n.x1, '" y1="', n.y1, '" x2="', n.x2, '" y2="', n.y2, '">\n'])
                        : "radial" === this.type && (o = ["<radialGradient ", h, ' cx="', s ? n.x1 : n.x2, '" cy="', s ? n.y1 : n.y2, '" r="', s ? n.r1 : n.r2, '" fx="', s ? n.x2 : n.x1, '" fy="', s ? n.y2 : n.y1, '">\n']),
                    "radial" === this.type)
                ) {
                    if (s) for ((r = r.concat()).reverse(), f = 0, m = r.length; f < m; f++) r[f].offset = 1 - r[f].offset;
                    if (0 < (s = Math.min(n.r1, n.r2))) for (var u = s / Math.max(n.r1, n.r2), f = 0, m = r.length; f < m; f++) r[f].offset += u * (1 - r[f].offset);
                }
                for (f = 0, m = r.length; f < m; f++) {
                    var g = r[f];
                    o.push("<stop ", 'offset="', 100 * g.offset + "%", '" style="stop-color:', g.color, void 0 !== g.opacity ? ";stop-opacity: " + g.opacity : ";", '"/>\n');
                }
                return o.push("linear" === this.type ? "</linearGradient>\n" : "</radialGradient>\n"), o.join("");
            },
            toLive: function (e) {
                var t,
                    i,
                    o,
                    n = fabric.util.object.clone(this.coords);
                if (this.type) {
                    for (
                        "linear" === this.type ? (t = e.createLinearGradient(n.x1, n.y1, n.x2, n.y2)) : "radial" === this.type && (t = e.createRadialGradient(n.x1, n.y1, n.r1, n.x2, n.y2, n.r2)), i = 0, o = this.colorStops.length;
                        i < o;
                        i++
                    ) {
                        var r = this.colorStops[i].color,
                            s = this.colorStops[i].opacity,
                            a = this.colorStops[i].offset;
                        void 0 !== s && (r = new fabric.Color(r).setAlpha(s).toRgba()), t.addColorStop(a, r);
                    }
                    return t;
                }
            },
        })),
            fabric.util.object.extend(fabric.Gradient, {
                fromElement: function (e, t, i, o) {
                    var n = (n = parseFloat(i) / (/%$/.test(i) ? 100 : 1)) < 0 ? 0 : 1 < n ? 1 : n;
                    isNaN(n) && (n = 1);
                    for (
                        var r,
                            s,
                            a,
                            c,
                            l,
                            d,
                            h = e.getElementsByTagName("stop"),
                            u = "userSpaceOnUse" === e.getAttribute("gradientUnits") ? "pixels" : "percentage",
                            f = e.getAttribute("gradientTransform") || "",
                            m = [],
                            g = 0,
                            p = 0,
                            v =
                                "linearGradient" === e.nodeName || "LINEARGRADIENT" === e.nodeName
                                    ? ((r = "linear"), { x1: (i = e).getAttribute("x1") || 0, y1: i.getAttribute("y1") || 0, x2: i.getAttribute("x2") || "100%", y2: i.getAttribute("y2") || 0 })
                                    : ((r = "radial"),
                                      {
                                          x1: (v = e).getAttribute("fx") || v.getAttribute("cx") || "50%",
                                          y1: v.getAttribute("fy") || v.getAttribute("cy") || "50%",
                                          r1: 0,
                                          x2: v.getAttribute("cx") || "50%",
                                          y2: v.getAttribute("cy") || "50%",
                                          r2: v.getAttribute("r") || "50%",
                                      }),
                            b = h.length;
                        b--;

                    )
                        m.push(
                            (function (e, t) {
                                var i,
                                    o,
                                    n,
                                    r = e.getAttribute("style"),
                                    s = e.getAttribute("offset") || 0;
                                if (((s = (s = parseFloat(s) / (/%$/.test(s) ? 100 : 1)) < 0 ? 0 : 1 < s ? 1 : s), r)) {
                                    var a = r.split(/\s*;\s*/);
                                    for ("" === a[a.length - 1] && a.pop(), n = a.length; n--; ) {
                                        var c = (l = a[n].split(/\s*:\s*/))[0].trim(),
                                            l = l[1].trim();
                                        "stop-color" === c ? (i = l) : "stop-opacity" === c && (o = l);
                                    }
                                }
                                return (
                                    (i = i || e.getAttribute("stop-color") || "rgb(0,0,0)"),
                                    (o = o || e.getAttribute("stop-opacity")),
                                    (e = (i = new fabric.Color(i)).getAlpha()),
                                    (o = isNaN(parseFloat(o)) ? 1 : parseFloat(o)),
                                    (o *= e * t),
                                    { offset: s, color: i.toRgb(), opacity: o }
                                );
                            })(h[b], n)
                        );
                    return (
                        (f = fabric.parseTransformAttribute(f)),
                        (s = v),
                        (a = o),
                        (c = u),
                        Object.keys(s).forEach(function (e) {
                            "Infinity" === (l = s[e])
                                ? (d = 1)
                                : "-Infinity" === l
                                ? (d = 0)
                                : ((d = parseFloat(s[e], 10)),
                                  "string" == typeof l &&
                                      /^(\d+\.\d+)%|(\d+)%$/.test(l) &&
                                      ((d *= 0.01), "pixels" === c && (("x1" !== e && "x2" !== e && "r2" !== e) || (d *= a.viewBoxWidth || a.width), ("y1" !== e && "y2" !== e) || (d *= a.viewBoxHeight || a.height)))),
                                (s[e] = d);
                        }),
                        "pixels" == u && ((g = -t.left), (p = -t.top)),
                        new fabric.Gradient({ id: e.getAttribute("id"), type: r, coords: v, colorStops: m, gradientUnits: u, gradientTransform: f, offsetX: g, offsetY: p })
                    );
                },
            });
    })(),
    (function () {
        var e = fabric.util.toFixed;
        fabric.Pattern = fabric.util.createClass({
            repeat: "repeat",
            offsetX: 0,
            offsetY: 0,
            crossOrigin: "",
            patternTransform: null,
            initialize: function (e, t) {
                var i;
                (e = e || {}),
                    (this.id = fabric.Object.__uid++),
                    this.setOptions(e),
                    !e.source || (e.source && "string" != typeof e.source)
                        ? t && t(this)
                        : (((i = this).source = fabric.util.createImage()),
                          fabric.util.loadImage(
                              e.source,
                              function (e, o) {
                                  (i.source = e), t && t(i, o);
                              },
                              null,
                              this.crossOrigin
                          ));
            },
            toObject: function (t) {
                var i,
                    o = fabric.Object.NUM_FRACTION_DIGITS;
                return (
                    "string" == typeof this.source.src ? (i = this.source.src) : "object" == typeof this.source && this.source.toDataURL && (i = this.source.toDataURL()),
                    (o = {
                        type: "pattern",
                        source: i,
                        repeat: this.repeat,
                        crossOrigin: this.crossOrigin,
                        offsetX: e(this.offsetX, o),
                        offsetY: e(this.offsetY, o),
                        patternTransform: this.patternTransform ? this.patternTransform.concat() : null,
                    }),
                    fabric.util.populateWithProperties(this, o, t),
                    o
                );
            },
            toSVG: function (e) {
                var t = "function" == typeof this.source ? this.source() : this.source,
                    i = t.width / e.width,
                    o = t.height / e.height,
                    n = this.offsetX / e.width,
                    r = this.offsetY / e.height;
                e = "";
                return (
                    ("repeat-x" !== this.repeat && "no-repeat" !== this.repeat) || ((o = 1), r && (o += Math.abs(r))),
                    ("repeat-y" !== this.repeat && "no-repeat" !== this.repeat) || ((i = 1), n && (i += Math.abs(n))),
                    t.src ? (e = t.src) : t.toDataURL && (e = t.toDataURL()),
                    '<pattern id="SVGID_' + this.id + '" x="' + n + '" y="' + r + '" width="' + i + '" height="' + o + '">\n<image x="0" y="0" width="' + t.width + '" height="' + t.height + '" xlink:href="' + e + '"></image>\n</pattern>\n'
                );
            },
            setOptions: function (e) {
                for (var t in e) this[t] = e[t];
            },
            toLive: function (e) {
                var t = this.source;
                if (!t) return "";
                if (void 0 !== t.src) {
                    if (!t.complete) return "";
                    if (0 === t.naturalWidth || 0 === t.naturalHeight) return "";
                }
                return e.createPattern(t, this.repeat);
            },
        });
    })(),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.toFixed;
        t.Shadow
            ? t.warn("fabric.Shadow is already defined.")
            : ((t.Shadow = t.util.createClass({
                  color: "rgb(0,0,0)",
                  blur: 0,
                  offsetX: 0,
                  offsetY: 0,
                  affectStroke: !1,
                  includeDefaultValues: !0,
                  nonScaling: !1,
                  initialize: function (e) {
                      for (var i in (e = "string" == typeof e ? this._parseShadow(e) : e)) this[i] = e[i];
                      this.id = t.Object.__uid++;
                  },
                  _parseShadow: function (e) {
                      var i = e.trim();
                      e = t.Shadow.reOffsetsAndBlur.exec(i) || [];
                      return { color: (i.replace(t.Shadow.reOffsetsAndBlur, "") || "rgb(0,0,0)").trim(), offsetX: parseFloat(e[1], 10) || 0, offsetY: parseFloat(e[2], 10) || 0, blur: parseFloat(e[3], 10) || 0 };
                  },
                  toString: function () {
                      return [this.offsetX, this.offsetY, this.blur, this.color].join("px ");
                  },
                  toSVG: function (e) {
                      var o = 40,
                          n = 40,
                          r = t.Object.NUM_FRACTION_DIGITS,
                          s = t.util.rotateVector({ x: this.offsetX, y: this.offsetY }, t.util.degreesToRadians(-e.angle)),
                          a = new t.Color(this.color);
                      return (
                          e.width && e.height && ((o = 100 * i((Math.abs(s.x) + this.blur) / e.width, r) + 20), (n = 100 * i((Math.abs(s.y) + this.blur) / e.height, r) + 20)),
                          e.flipX && (s.x *= -1),
                          e.flipY && (s.y *= -1),
                          '<filter id="SVGID_' +
                              this.id +
                              '" y="-' +
                              n +
                              '%" height="' +
                              (100 + 2 * n) +
                              '%" x="-' +
                              o +
                              '%" width="' +
                              (100 + 2 * o) +
                              '%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="' +
                              i(this.blur ? this.blur / 2 : 0, r) +
                              '"></feGaussianBlur>\n\t<feOffset dx="' +
                              i(s.x, r) +
                              '" dy="' +
                              i(s.y, r) +
                              '" result="oBlur" ></feOffset>\n\t<feFlood flood-color="' +
                              a.toRgb() +
                              '" flood-opacity="' +
                              a.getAlpha() +
                              '"/>\n\t<feComposite in2="oBlur" operator="in" />\n\t<feMerge>\n\t\t<feMergeNode></feMergeNode>\n\t\t<feMergeNode in="SourceGraphic"></feMergeNode>\n\t</feMerge>\n</filter>\n'
                      );
                  },
                  toObject: function () {
                      if (this.includeDefaultValues) return { color: this.color, blur: this.blur, offsetX: this.offsetX, offsetY: this.offsetY, affectStroke: this.affectStroke, nonScaling: this.nonScaling };
                      var e = {},
                          i = t.Shadow.prototype;
                      return (
                          ["color", "blur", "offsetX", "offsetY", "affectStroke", "nonScaling"].forEach(function (t) {
                              this[t] !== i[t] && (e[t] = this[t]);
                          }, this),
                          e
                      );
                  },
              })),
              (t.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:\.\d*)?(?:px)?(?:\s?|$))?(-?\d+(?:\.\d*)?(?:px)?(?:\s?|$))?(\d+(?:\.\d*)?(?:px)?)?(?:\s?|$)(?:$|\s)/));
    })("undefined" != typeof exports ? exports : this),
    (function () {
        var e, t, i, o, n, r, s, a, c;
        fabric.StaticCanvas
            ? fabric.warn("fabric.StaticCanvas is already defined.")
            : ((e = fabric.util.object.extend),
              (t = fabric.util.getElementOffset),
              (i = fabric.util.removeFromArray),
              (o = fabric.util.toFixed),
              (n = fabric.util.transformPoint),
              (r = fabric.util.invertTransform),
              (s = fabric.util.getNodeCanvas),
              (a = fabric.util.createCanvasElement),
              (c = new Error("Could not initialize `canvas` element")),
              (fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, {
                  initialize: function (e, t) {
                      (t = t || {}), (this.renderAndResetBound = this.renderAndReset.bind(this)), (this.requestRenderAllBound = this.requestRenderAll.bind(this)), this._initStatic(e, t);
                  },
                  backgroundColor: "",
                  backgroundImage: null,
                  overlayColor: "",
                  overlayImage: null,
                  includeDefaultValues: !0,
                  stateful: !1,
                  renderOnAddRemove: !0,
                  controlsAboveOverlay: !1,
                  allowTouchScrolling: !1,
                  imageSmoothingEnabled: !0,
                  viewportTransform: fabric.iMatrix.concat(),
                  backgroundVpt: !0,
                  overlayVpt: !0,
                  enableRetinaScaling: !0,
                  vptCoords: {},
                  skipOffscreen: !0,
                  clipPath: void 0,
                  _initStatic: function (e, t) {
                      var i = this.requestRenderAllBound;
                      (this._objects = []),
                          this._createLowerCanvas(e),
                          this._initOptions(t),
                          this.interactive || this._initRetinaScaling(),
                          t.overlayImage && this.setOverlayImage(t.overlayImage, i),
                          t.backgroundImage && this.setBackgroundImage(t.backgroundImage, i),
                          t.backgroundColor && this.setBackgroundColor(t.backgroundColor, i),
                          t.overlayColor && this.setOverlayColor(t.overlayColor, i),
                          this.calcOffset();
                  },
                  _isRetinaScaling: function () {
                      return 1 !== fabric.devicePixelRatio && this.enableRetinaScaling;
                  },
                  getRetinaScaling: function () {
                      return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
                  },
                  _initRetinaScaling: function () {
                      var e;
                      this._isRetinaScaling() &&
                          ((e = fabric.devicePixelRatio), this.__initRetinaScaling(e, this.lowerCanvasEl, this.contextContainer), this.upperCanvasEl && this.__initRetinaScaling(e, this.upperCanvasEl, this.contextTop));
                  },
                  __initRetinaScaling: function (e, t, i) {
                      t.setAttribute("width", this.width * e), t.setAttribute("height", this.height * e), i.scale(e, e);
                  },
                  calcOffset: function () {
                      return (this._offset = t(this.lowerCanvasEl)), this;
                  },
                  setOverlayImage: function (e, t, i) {
                      return this.__setBgOverlayImage("overlayImage", e, t, i);
                  },
                  setBackgroundImage: function (e, t, i) {
                      return this.__setBgOverlayImage("backgroundImage", e, t, i);
                  },
                  setOverlayColor: function (e, t) {
                      return this.__setBgOverlayColor("overlayColor", e, t);
                  },
                  setBackgroundColor: function (e, t) {
                      return this.__setBgOverlayColor("backgroundColor", e, t);
                  },
                  __setBgOverlayImage: function (e, t, i, o) {
                      return (
                          "string" == typeof t
                              ? fabric.util.loadImage(
                                    t,
                                    function (t, n) {
                                        var r;
                                        t && ((r = new fabric.Image(t, o)), ((this[e] = r).canvas = this)), i && i(t, n);
                                    },
                                    this,
                                    o && o.crossOrigin
                                )
                              : (o && t.setOptions(o), (this[e] = t) && (t.canvas = this), i && i(t, !1)),
                          this
                      );
                  },
                  __setBgOverlayColor: function (e, t, i) {
                      return (this[e] = t), this._initGradient(t, e), this._initPattern(t, e, i), this;
                  },
                  _createCanvasElement: function () {
                      var e = a();
                      if (!e) throw c;
                      if ((e.style || (e.style = {}), void 0 === e.getContext)) throw c;
                      return e;
                  },
                  _initOptions: function (e) {
                      var t = this.lowerCanvasEl;
                      this._setOptions(e),
                          (this.width = this.width || parseInt(t.width, 10) || 0),
                          (this.height = this.height || parseInt(t.height, 10) || 0),
                          this.lowerCanvasEl.style && ((t.width = this.width), (t.height = this.height), (t.style.width = this.width + "px"), (t.style.height = this.height + "px"), (this.viewportTransform = this.viewportTransform.slice()));
                  },
                  _createLowerCanvas: function (e) {
                      e && e.getContext ? (this.lowerCanvasEl = e) : (this.lowerCanvasEl = fabric.util.getById(e) || this._createCanvasElement()),
                          fabric.util.addClass(this.lowerCanvasEl, "lower-canvas"),
                          (this._originalCanvasStyle = this.lowerCanvasEl.style),
                          this.interactive && this._applyCanvasStyle(this.lowerCanvasEl),
                          (this.contextContainer = this.lowerCanvasEl.getContext("2d"));
                  },
                  getWidth: function () {
                      return this.width;
                  },
                  getHeight: function () {
                      return this.height;
                  },
                  setWidth: function (e, t) {
                      return this.setDimensions({ width: e }, t);
                  },
                  setHeight: function (e, t) {
                      return this.setDimensions({ height: e }, t);
                  },
                  setDimensions: function (e, t) {
                      var i, o;
                      for (o in ((t = t || {}), e)) (i = e[o]), t.cssOnly || (this._setBackstoreDimension(o, e[o]), (i += "px"), (this.hasLostContext = !0)), t.backstoreOnly || this._setCssDimension(o, i);
                      return this._isCurrentlyDrawing && this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(), this._initRetinaScaling(), this.calcOffset(), t.cssOnly || this.requestRenderAll(), this;
                  },
                  _setBackstoreDimension: function (e, t) {
                      return (this.lowerCanvasEl[e] = t), this.upperCanvasEl && (this.upperCanvasEl[e] = t), this.cacheCanvasEl && (this.cacheCanvasEl[e] = t), (this[e] = t), this;
                  },
                  _setCssDimension: function (e, t) {
                      return (this.lowerCanvasEl.style[e] = t), this.upperCanvasEl && (this.upperCanvasEl.style[e] = t), this.wrapperEl && (this.wrapperEl.style[e] = t), this;
                  },
                  getZoom: function () {
                      return this.viewportTransform[0];
                  },
                  setViewportTransform: function (e) {
                      var t,
                          i,
                          o,
                          n = this._activeObject,
                          r = this.backgroundImage,
                          s = this.overlayImage;
                      for (this.viewportTransform = e, i = 0, o = this._objects.length; i < o; i++) (t = this._objects[i]).group || t.setCoords(!0);
                      return n && n.setCoords(), r && r.setCoords(!0), s && s.setCoords(!0), this.calcViewportBoundaries(), this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  zoomToPoint: function (e, t) {
                      var i = e,
                          o = this.viewportTransform.slice(0);
                      return (e = n(e, r(this.viewportTransform))), (o[0] = t), (o[3] = t), (e = n(e, o)), (o[4] += i.x - e.x), (o[5] += i.y - e.y), this.setViewportTransform(o);
                  },
                  setZoom: function (e) {
                      return this.zoomToPoint(new fabric.Point(0, 0), e), this;
                  },
                  absolutePan: function (e) {
                      var t = this.viewportTransform.slice(0);
                      return (t[4] = -e.x), (t[5] = -e.y), this.setViewportTransform(t);
                  },
                  relativePan: function (e) {
                      return this.absolutePan(new fabric.Point(-e.x - this.viewportTransform[4], -e.y - this.viewportTransform[5]));
                  },
                  getElement: function () {
                      return this.lowerCanvasEl;
                  },
                  _onObjectAdded: function (e) {
                      this.stateful && e.setupState(), e._set("canvas", this), e.setCoords(), this.fire("object:added", { target: e }), e.fire("added");
                  },
                  _onObjectRemoved: function (e) {
                      this.fire("object:removed", { target: e }), e.fire("removed"), delete e.canvas;
                  },
                  clearContext: function (e) {
                      return e.clearRect(0, 0, this.width, this.height), this;
                  },
                  getContext: function () {
                      return this.contextContainer;
                  },
                  clear: function () {
                      return (
                          this.remove.apply(this, this.getObjects()),
                          (this.backgroundImage = null),
                          (this.overlayImage = null),
                          (this.backgroundColor = ""),
                          (this.overlayColor = ""),
                          this._hasITextHandlers && (this.off("mouse:up", this._mouseUpITextHandler), (this._iTextInstances = null), (this._hasITextHandlers = !1)),
                          this.clearContext(this.contextContainer),
                          this.fire("canvas:cleared"),
                          this.renderOnAddRemove && this.requestRenderAll(),
                          this
                      );
                  },
                  renderAll: function () {
                      var e = this.contextContainer;
                      return this.renderCanvas(e, this._objects), this;
                  },
                  renderAndReset: function () {
                      (this.isRendering = 0), this.renderAll();
                  },
                  requestRenderAll: function () {
                      return this.isRendering || (this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound)), this;
                  },
                  calcViewportBoundaries: function () {
                      var e = {},
                          t = this.width,
                          i = this.height,
                          o = r(this.viewportTransform);
                      return (e.tl = n({ x: 0, y: 0 }, o)), (e.br = n({ x: t, y: i }, o)), (e.tr = new fabric.Point(e.br.x, e.tl.y)), (e.bl = new fabric.Point(e.tl.x, e.br.y)), (this.vptCoords = e);
                  },
                  cancelRequestedRender: function () {
                      this.isRendering && (fabric.util.cancelAnimFrame(this.isRendering), (this.isRendering = 0));
                  },
                  renderCanvas: function (e, t) {
                      var i = this.viewportTransform,
                          o = this.clipPath;
                      this.cancelRequestedRender(),
                          this.calcViewportBoundaries(),
                          this.clearContext(e),
                          fabric.util.setImageSmoothing(e, this.imageSmoothingEnabled),
                          this.fire("before:render", { ctx: e }),
                          this._renderBackground(e),
                          e.save(),
                          e.transform(i[0], i[1], i[2], i[3], i[4], i[5]),
                          this._renderObjects(e, t),
                          e.restore(),
                          !this.controlsAboveOverlay && this.interactive && this.drawControls(e),
                          o && ((o.canvas = this), o.shouldCache(), (o._transformDone = !0), o.renderCache({ forClipping: !0 }), this.drawClipPathOnCanvas(e)),
                          this._renderOverlay(e),
                          this.controlsAboveOverlay && this.interactive && this.drawControls(e),
                          this.fire("after:render", { ctx: e });
                  },
                  drawClipPathOnCanvas: function (e) {
                      var t = this.viewportTransform,
                          i = this.clipPath;
                      e.save(),
                          e.transform(t[0], t[1], t[2], t[3], t[4], t[5]),
                          (e.globalCompositeOperation = "destination-in"),
                          i.transform(e),
                          e.scale(1 / i.zoomX, 1 / i.zoomY),
                          e.drawImage(i._cacheCanvas, -i.cacheTranslationX, -i.cacheTranslationY),
                          e.restore();
                  },
                  _renderObjects: function (e, t) {
                      for (var i = 0, o = t.length; i < o; ++i) t[i] && t[i].render(e);
                  },
                  _renderBackgroundOrOverlay: function (e, t) {
                      var i = this[t + "Color"],
                          o = this[t + "Image"],
                          n = this.viewportTransform;
                      t = this[t + "Vpt"];
                      (i || o) &&
                          (i &&
                              (e.save(),
                              e.beginPath(),
                              e.moveTo(0, 0),
                              e.lineTo(this.width, 0),
                              e.lineTo(this.width, this.height),
                              e.lineTo(0, this.height),
                              e.closePath(),
                              (e.fillStyle = i.toLive ? i.toLive(e, this) : i),
                              t && e.transform(n[0], n[1], n[2], n[3], n[4], n[5]),
                              e.transform(1, 0, 0, 1, i.offsetX || 0, i.offsetY || 0),
                              (i = i.gradientTransform || i.patternTransform) && e.transform(i[0], i[1], i[2], i[3], i[4], i[5]),
                              e.fill(),
                              e.restore()),
                          o && (e.save(), t && e.transform(n[0], n[1], n[2], n[3], n[4], n[5]), o.render(e), e.restore()));
                  },
                  _renderBackground: function (e) {
                      this._renderBackgroundOrOverlay(e, "background");
                  },
                  _renderOverlay: function (e) {
                      this._renderBackgroundOrOverlay(e, "overlay");
                  },
                  getCenter: function () {
                      return { top: this.height / 2, left: this.width / 2 };
                  },
                  centerObjectH: function (e) {
                      return this._centerObject(e, new fabric.Point(this.getCenter().left, e.getCenterPoint().y));
                  },
                  centerObjectV: function (e) {
                      return this._centerObject(e, new fabric.Point(e.getCenterPoint().x, this.getCenter().top));
                  },
                  centerObject: function (e) {
                      var t = this.getCenter();
                      return this._centerObject(e, new fabric.Point(t.left, t.top));
                  },
                  viewportCenterObject: function (e) {
                      var t = this.getVpCenter();
                      return this._centerObject(e, t);
                  },
                  viewportCenterObjectH: function (e) {
                      var t = this.getVpCenter();
                      return this._centerObject(e, new fabric.Point(t.x, e.getCenterPoint().y)), this;
                  },
                  viewportCenterObjectV: function (e) {
                      var t = this.getVpCenter();
                      return this._centerObject(e, new fabric.Point(e.getCenterPoint().x, t.y));
                  },
                  getVpCenter: function () {
                      var e = this.getCenter(),
                          t = r(this.viewportTransform);
                      return n({ x: e.left, y: e.top }, t);
                  },
                  _centerObject: function (e, t) {
                      return e.setPositionByOrigin(t, "center", "center"), e.setCoords(), this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  toDatalessJSON: function (e) {
                      return this.toDatalessObject(e);
                  },
                  toObject: function (e) {
                      return this._toObjectMethod("toObject", e);
                  },
                  toDatalessObject: function (e) {
                      return this._toObjectMethod("toDatalessObject", e);
                  },
                  _toObjectMethod: function (t, i) {
                      var o = this.clipPath,
                          n = { version: fabric.version, objects: this._toObjects(t, i) };
                      return o && !o.excludeFromExport && (n.clipPath = this._toObject(this.clipPath, t, i)), e(n, this.__serializeBgOverlay(t, i)), fabric.util.populateWithProperties(this, n, i), n;
                  },
                  _toObjects: function (e, t) {
                      return this._objects
                          .filter(function (e) {
                              return !e.excludeFromExport;
                          })
                          .map(function (i) {
                              return this._toObject(i, e, t);
                          }, this);
                  },
                  _toObject: function (e, t, i) {
                      var o;
                      return this.includeDefaultValues || ((o = e.includeDefaultValues), (e.includeDefaultValues = !1)), (i = e[t](i)), this.includeDefaultValues || (e.includeDefaultValues = o), i;
                  },
                  __serializeBgOverlay: function (e, t) {
                      var i = {},
                          o = this.backgroundImage,
                          n = this.overlayImage,
                          r = this.backgroundColor,
                          s = this.overlayColor;
                      return (
                          r && r.toObject ? r.excludeFromExport || (i.background = r.toObject(t)) : r && (i.background = r),
                          s && s.toObject ? s.excludeFromExport || (i.overlay = s.toObject(t)) : s && (i.overlay = s),
                          o && !o.excludeFromExport && (i.backgroundImage = this._toObject(o, e, t)),
                          n && !n.excludeFromExport && (i.overlayImage = this._toObject(n, e, t)),
                          i
                      );
                  },
                  svgViewportTransformation: !0,
                  toSVG: function (e, t) {
                      (e = e || {}).reviver = t;
                      var i = [];
                      return (
                          this._setSVGPreamble(i, e),
                          this._setSVGHeader(i, e),
                          this.clipPath && i.push('<g clip-path="url(#' + this.clipPath.clipPathId + ')" >\n'),
                          this._setSVGBgOverlayColor(i, "background"),
                          this._setSVGBgOverlayImage(i, "backgroundImage", t),
                          this._setSVGObjects(i, t),
                          this.clipPath && i.push("</g>\n"),
                          this._setSVGBgOverlayColor(i, "overlay"),
                          this._setSVGBgOverlayImage(i, "overlayImage", t),
                          i.push("</svg>"),
                          i.join("")
                      );
                  },
                  _setSVGPreamble: function (e, t) {
                      t.suppressPreamble ||
                          e.push('<?xml version="1.0" encoding="', t.encoding || "UTF-8", '" standalone="no" ?>\n', '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ', '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n');
                  },
                  _setSVGHeader: function (e, t) {
                      var i,
                          n = t.width || this.width,
                          r = t.height || this.height,
                          s = 'viewBox="0 0 ' + this.width + " " + this.height + '" ',
                          a = fabric.Object.NUM_FRACTION_DIGITS;
                      t.viewBox
                          ? (s = 'viewBox="' + t.viewBox.x + " " + t.viewBox.y + " " + t.viewBox.width + " " + t.viewBox.height + '" ')
                          : this.svgViewportTransformation && ((i = this.viewportTransform), (s = 'viewBox="' + o(-i[4] / i[0], a) + " " + o(-i[5] / i[3], a) + " " + o(this.width / i[0], a) + " " + o(this.height / i[3], a) + '" ')),
                          e.push(
                              "<svg ",
                              'xmlns="http://www.w3.org/2000/svg" ',
                              'xmlns:xlink="http://www.w3.org/1999/xlink" ',
                              'version="1.1" ',
                              'width="',
                              n,
                              '" ',
                              'height="',
                              r,
                              '" ',
                              s,
                              'xml:space="preserve">\n',
                              "<desc>Created with Fabric.js ",
                              fabric.version,
                              "</desc>\n",
                              "<defs>\n",
                              this.createSVGFontFacesMarkup(),
                              this.createSVGRefElementsMarkup(),
                              this.createSVGClipPathMarkup(t),
                              "</defs>\n"
                          );
                  },
                  createSVGClipPathMarkup: function (e) {
                      var t = this.clipPath;
                      return t ? ((t.clipPathId = "CLIPPATH_" + fabric.Object.__uid++), '<clipPath id="' + t.clipPathId + '" >\n' + this.clipPath.toClipPathSVG(e.reviver) + "</clipPath>\n") : "";
                  },
                  createSVGRefElementsMarkup: function () {
                      var e = this;
                      return ["background", "overlay"]
                          .map(function (t) {
                              var i = e[t + "Color"];
                              if (i && i.toLive) {
                                  var o = e[t + "Vpt"],
                                      n = e.viewportTransform;
                                  t = { width: e.width / (o ? n[0] : 1), height: e.height / (o ? n[3] : 1) };
                                  return i.toSVG(t, { additionalTransform: o ? fabric.util.matrixToSVG(n) : "" });
                              }
                          })
                          .join("");
                  },
                  createSVGFontFacesMarkup: function () {
                      var e,
                          t,
                          i,
                          o,
                          n,
                          r,
                          s,
                          a,
                          c,
                          l = "",
                          d = {},
                          h = fabric.fontPaths,
                          u = [];
                      for (
                          this._objects.forEach(function e(t) {
                              u.push(t), t._objects && t._objects.forEach(e);
                          }),
                              s = 0,
                              a = u.length;
                          s < a;
                          s++
                      )
                          if (((t = (e = u[s]).fontFamily), -1 !== e.type.indexOf("text") && !d[t] && h[t] && ((d[t] = !0), e.styles))) for (n in (i = e.styles)) for (r in (o = i[n])) !d[(t = o[r].fontFamily)] && h[t] && (d[t] = !0);
                      for (c in d) l += ["\t\t@font-face {\n", "\t\t\tfont-family: '", c, "';\n", "\t\t\tsrc: url('", h[c], "');\n", "\t\t}\n"].join("");
                      return l && ['\t<style type="text/css">', "<![CDATA[\n", l, "]]>", "</style>\n"].join("");
                  },
                  _setSVGObjects: function (e, t) {
                      for (var i, o = this._objects, n = 0, r = o.length; n < r; n++) (i = o[n]).excludeFromExport || this._setSVGObject(e, i, t);
                  },
                  _setSVGObject: function (e, t, i) {
                      e.push(t.toSVG(i));
                  },
                  _setSVGBgOverlayImage: function (e, t, i) {
                      this[t] && !this[t].excludeFromExport && this[t].toSVG && e.push(this[t].toSVG(i));
                  },
                  _setSVGBgOverlayColor: function (e, t) {
                      var i,
                          o = this[t + "Color"],
                          n = this.viewportTransform,
                          r = this.width,
                          s = this.height;
                      o &&
                          (o.toLive
                              ? ((i = o.repeat),
                                (n = fabric.util.invertTransform(n)),
                                (n = this[t + "Vpt"] ? fabric.util.matrixToSVG(n) : ""),
                                e.push(
                                    '<rect transform="' + n + " translate(",
                                    r / 2,
                                    ",",
                                    s / 2,
                                    ')"',
                                    ' x="',
                                    o.offsetX - r / 2,
                                    '" y="',
                                    o.offsetY - s / 2,
                                    '" ',
                                    'width="',
                                    "repeat-y" === i || "no-repeat" === i ? o.source.width : r,
                                    '" height="',
                                    "repeat-x" === i || "no-repeat" === i ? o.source.height : s,
                                    '" fill="url(#SVGID_' + o.id + ')"',
                                    "></rect>\n"
                                ))
                              : e.push('<rect x="0" y="0" width="100%" height="100%" ', 'fill="', o, '"', "></rect>\n"));
                  },
                  sendToBack: function (e) {
                      if (!e) return this;
                      var t,
                          o,
                          n,
                          r = this._activeObject;
                      if (e === r && "activeSelection" === e.type) for (t = (n = r._objects).length; t--; ) (o = n[t]), i(this._objects, o), this._objects.unshift(o);
                      else i(this._objects, e), this._objects.unshift(e);
                      return this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  bringToFront: function (e) {
                      if (!e) return this;
                      var t,
                          o,
                          n,
                          r = this._activeObject;
                      if (e === r && "activeSelection" === e.type) for (n = r._objects, t = 0; t < n.length; t++) (o = n[t]), i(this._objects, o), this._objects.push(o);
                      else i(this._objects, e), this._objects.push(e);
                      return this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  sendBackwards: function (e, t) {
                      if (!e) return this;
                      var o,
                          n,
                          r,
                          s,
                          a,
                          c = this._activeObject,
                          l = 0;
                      if (e === c && "activeSelection" === e.type) for (a = c._objects, o = 0; o < a.length; o++) (n = a[o]), 0 + l < (r = this._objects.indexOf(n)) && ((s = r - 1), i(this._objects, n), this._objects.splice(s, 0, n)), l++;
                      else 0 !== (r = this._objects.indexOf(e)) && ((s = this._findNewLowerIndex(e, r, t)), i(this._objects, e), this._objects.splice(s, 0, e));
                      return this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  _findNewLowerIndex: function (e, t, i) {
                      var o, n;
                      if (i) {
                          for (n = (o = t) - 1; 0 <= n; --n)
                              if (e.intersectsWithObject(this._objects[n]) || e.isContainedWithinObject(this._objects[n]) || this._objects[n].isContainedWithinObject(e)) {
                                  o = n;
                                  break;
                              }
                      } else o = t - 1;
                      return o;
                  },
                  bringForward: function (e, t) {
                      if (!e) return this;
                      var o,
                          n,
                          r,
                          s,
                          a,
                          c = this._activeObject,
                          l = 0;
                      if (e === c && "activeSelection" === e.type)
                          for (o = (a = c._objects).length; o--; ) (n = a[o]), (r = this._objects.indexOf(n)) < this._objects.length - 1 - l && ((s = r + 1), i(this._objects, n), this._objects.splice(s, 0, n)), l++;
                      else (r = this._objects.indexOf(e)) !== this._objects.length - 1 && ((s = this._findNewUpperIndex(e, r, t)), i(this._objects, e), this._objects.splice(s, 0, e));
                      return this.renderOnAddRemove && this.requestRenderAll(), this;
                  },
                  _findNewUpperIndex: function (e, t, i) {
                      var o, n, r;
                      if (i) {
                          for (n = (o = t) + 1, r = this._objects.length; n < r; ++n)
                              if (e.intersectsWithObject(this._objects[n]) || e.isContainedWithinObject(this._objects[n]) || this._objects[n].isContainedWithinObject(e)) {
                                  o = n;
                                  break;
                              }
                      } else o = t + 1;
                      return o;
                  },
                  moveTo: function (e, t) {
                      return i(this._objects, e), this._objects.splice(t, 0, e), this.renderOnAddRemove && this.requestRenderAll();
                  },
                  dispose: function () {
                      return (
                          this.isRendering && (fabric.util.cancelAnimFrame(this.isRendering), (this.isRendering = 0)),
                          this.forEachObject(function (e) {
                              e.dispose && e.dispose();
                          }),
                          (this._objects = []),
                          this.backgroundImage && this.backgroundImage.dispose && this.backgroundImage.dispose(),
                          (this.backgroundImage = null),
                          this.overlayImage && this.overlayImage.dispose && this.overlayImage.dispose(),
                          (this.overlayImage = null),
                          (this._iTextInstances = null),
                          (this.contextContainer = null),
                          this.lowerCanvasEl.classList.remove("lower-canvas"),
                          (this.lowerCanvasEl.style = this._originalCanvasStyle),
                          delete this._originalCanvasStyle,
                          this.lowerCanvasEl.setAttribute("width", this.width),
                          this.lowerCanvasEl.setAttribute("height", this.height),
                          fabric.util.cleanUpJsdomNode(this.lowerCanvasEl),
                          (this.lowerCanvasEl = void 0),
                          this
                      );
                  },
                  toString: function () {
                      return "#<fabric.Canvas (" + this.complexity() + "): { objects: " + this._objects.length + " }>";
                  },
              })),
              e(fabric.StaticCanvas.prototype, fabric.Observable),
              e(fabric.StaticCanvas.prototype, fabric.Collection),
              e(fabric.StaticCanvas.prototype, fabric.DataURLExporter),
              e(fabric.StaticCanvas, {
                  EMPTY_JSON: '{"objects": [], "background": "white"}',
                  supports: function (e) {
                      var t = a();
                      return t && t.getContext && (t = t.getContext("2d")) && "setLineDash" === e ? void 0 !== t.setLineDash : null;
                  },
              }),
              (fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject),
              fabric.isLikelyNode &&
                  ((fabric.StaticCanvas.prototype.createPNGStream = function () {
                      var e = s(this.lowerCanvasEl);
                      return e && e.createPNGStream();
                  }),
                  (fabric.StaticCanvas.prototype.createJPEGStream = function (e) {
                      var t = s(this.lowerCanvasEl);
                      return t && t.createJPEGStream(e);
                  })));
    })(),
    (fabric.BaseBrush = fabric.util.createClass({
        color: "rgb(0, 0, 0)",
        width: 1,
        shadow: null,
        strokeLineCap: "round",
        strokeLineJoin: "round",
        strokeMiterLimit: 10,
        strokeDashArray: null,
        limitedToCanvasSize: !1,
        _setBrushStyles: function () {
            var e = this.canvas.contextTop;
            (e.strokeStyle = this.color), (e.lineWidth = this.width), (e.lineCap = this.strokeLineCap), (e.miterLimit = this.strokeMiterLimit), (e.lineJoin = this.strokeLineJoin), e.setLineDash(this.strokeDashArray || []);
        },
        _saveAndTransform: function (e) {
            var t = this.canvas.viewportTransform;
            e.save(), e.transform(t[0], t[1], t[2], t[3], t[4], t[5]);
        },
        _setShadow: function () {
            var e, t, i, o;
            this.shadow &&
                ((e = this.canvas),
                (t = this.shadow),
                (i = e.contextTop),
                (o = e.getZoom()),
                e && e._isRetinaScaling() && (o *= fabric.devicePixelRatio),
                (i.shadowColor = t.color),
                (i.shadowBlur = t.blur * o),
                (i.shadowOffsetX = t.offsetX * o),
                (i.shadowOffsetY = t.offsetY * o));
        },
        needsFullRender: function () {
            return new fabric.Color(this.color).getAlpha() < 1 || !!this.shadow;
        },
        _resetShadow: function () {
            var e = this.canvas.contextTop;
            (e.shadowColor = ""), (e.shadowBlur = e.shadowOffsetX = e.shadowOffsetY = 0);
        },
        _isOutSideCanvas: function (e) {
            return e.x < 0 || e.x > this.canvas.getWidth() || e.y < 0 || e.y > this.canvas.getHeight();
        },
    })),
    (fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, {
        decimate: 0.4,
        initialize: function (e) {
            (this.canvas = e), (this._points = []);
        },
        _drawSegment: function (e, t, i) {
            return (i = t.midPointFrom(i)), e.quadraticCurveTo(t.x, t.y, i.x, i.y), i;
        },
        onMouseDown: function (e, t) {
            this.canvas._isMainEvent(t.e) && (this._prepareForDrawing(e), this._captureDrawingPath(e), this._render());
        },
        onMouseMove: function (e, t) {
            var i;
            this.canvas._isMainEvent(t.e) &&
                ((!0 === this.limitedToCanvasSize && this._isOutSideCanvas(e)) ||
                    (this._captureDrawingPath(e) &&
                        1 < this._points.length &&
                        (this.needsFullRender()
                            ? (this.canvas.clearContext(this.canvas.contextTop), this._render())
                            : ((t = (i = this._points).length),
                              (e = this.canvas.contextTop),
                              this._saveAndTransform(e),
                              this.oldEnd && (e.beginPath(), e.moveTo(this.oldEnd.x, this.oldEnd.y)),
                              (this.oldEnd = this._drawSegment(e, i[t - 2], i[t - 1], !0)),
                              e.stroke(),
                              e.restore()))));
        },
        onMouseUp: function (e) {
            return !this.canvas._isMainEvent(e.e) || ((this.oldEnd = void 0), this._finalizeAndAddPath(), !1);
        },
        _prepareForDrawing: function (e) {
            (e = new fabric.Point(e.x, e.y)), this._reset(), this._addPoint(e), this.canvas.contextTop.moveTo(e.x, e.y);
        },
        _addPoint: function (e) {
            return !((1 < this._points.length && e.eq(this._points[this._points.length - 1])) || (this._points.push(e), 0));
        },
        _reset: function () {
            (this._points = []), this._setBrushStyles(), this._setShadow();
        },
        _captureDrawingPath: function (e) {
            return (e = new fabric.Point(e.x, e.y)), this._addPoint(e);
        },
        _render: function () {
            var e,
                t,
                i,
                o = this.canvas.contextTop,
                n = this._points[0],
                r = this._points[1];
            for (
                this._saveAndTransform(o),
                    o.beginPath(),
                    2 === this._points.length && n.x === r.x && n.y === r.y && ((i = this.width / 1e3), (n = new fabric.Point(n.x, n.y)), (r = new fabric.Point(r.x, r.y)), (n.x -= i), (r.x += i)),
                    o.moveTo(n.x, n.y),
                    e = 1,
                    t = this._points.length;
                e < t;
                e++
            )
                this._drawSegment(o, n, r), (n = this._points[e]), (r = this._points[e + 1]);
            o.lineTo(n.x, n.y), o.stroke(), o.restore();
        },
        convertPointsToSVGPath: function (e) {
            var t = this.width / 1e3;
            return fabric.util.getSmoothPathFromPoints(e, t);
        },
        _isEmptySVGPath: function (e) {
            return "M 0 0 Q 0 0 0 0 L 0 0" === fabric.util.joinPath(e);
        },
        createPath: function (e) {
            return (
                (e = new fabric.Path(e, {
                    fill: null,
                    stroke: this.color,
                    strokeWidth: this.width,
                    strokeLineCap: this.strokeLineCap,
                    strokeMiterLimit: this.strokeMiterLimit,
                    strokeLineJoin: this.strokeLineJoin,
                    strokeDashArray: this.strokeDashArray,
                })),
                this.shadow && ((this.shadow.affectStroke = !0), (e.shadow = new fabric.Shadow(this.shadow))),
                e
            );
        },
        decimatePoints: function (e, t) {
            if (e.length <= 2) return e;
            for (var i = this.canvas.getZoom(), o = Math.pow(t / i, 2), n = e.length - 1, r = e[0], s = [r], a = 1; a < n - 1; a++) o <= Math.pow(r.x - e[a].x, 2) + Math.pow(r.y - e[a].y, 2) && ((r = e[a]), s.push(r));
            return s.push(e[n]), s;
        },
        _finalizeAndAddPath: function () {
            this.canvas.contextTop.closePath(), this.decimate && (this._points = this.decimatePoints(this._points, this.decimate));
            var e = this.convertPointsToSVGPath(this._points);
            this._isEmptySVGPath(e)
                ? this.canvas.requestRenderAll()
                : ((e = this.createPath(e)),
                  this.canvas.clearContext(this.canvas.contextTop),
                  this.canvas.fire("before:path:created", { path: e }),
                  this.canvas.add(e),
                  this.canvas.requestRenderAll(),
                  e.setCoords(),
                  this._resetShadow(),
                  this.canvas.fire("path:created", { path: e }));
        },
    })),
    (fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, {
        width: 10,
        initialize: function (e) {
            (this.canvas = e), (this.points = []);
        },
        drawDot: function (e) {
            var t = this.addPoint(e);
            e = this.canvas.contextTop;
            this._saveAndTransform(e), this.dot(e, t), e.restore();
        },
        dot: function (e, t) {
            (e.fillStyle = t.fill), e.beginPath(), e.arc(t.x, t.y, t.radius, 0, 2 * Math.PI, !1), e.closePath(), e.fill();
        },
        onMouseDown: function (e) {
            (this.points.length = 0), this.canvas.clearContext(this.canvas.contextTop), this._setShadow(), this.drawDot(e);
        },
        _render: function () {
            var e,
                t,
                i = this.canvas.contextTop,
                o = this.points;
            for (this._saveAndTransform(i), e = 0, t = o.length; e < t; e++) this.dot(i, o[e]);
            i.restore();
        },
        onMouseMove: function (e) {
            (!0 === this.limitedToCanvasSize && this._isOutSideCanvas(e)) || (this.needsFullRender() ? (this.canvas.clearContext(this.canvas.contextTop), this.addPoint(e), this._render()) : this.drawDot(e));
        },
        onMouseUp: function () {
            var e = this.canvas.renderOnAddRemove;
            this.canvas.renderOnAddRemove = !1;
            for (var t = [], i = 0, o = this.points.length; i < o; i++) {
                var n = this.points[i];
                n = new fabric.Circle({ radius: n.radius, left: n.x, top: n.y, originX: "center", originY: "center", fill: n.fill });
                this.shadow && (n.shadow = new fabric.Shadow(this.shadow)), t.push(n);
            }
            var r = new fabric.Group(t);
            (r.canvas = this.canvas),
                this.canvas.fire("before:path:created", { path: r }),
                this.canvas.add(r),
                this.canvas.fire("path:created", { path: r }),
                this.canvas.clearContext(this.canvas.contextTop),
                this._resetShadow(),
                (this.canvas.renderOnAddRemove = e),
                this.canvas.requestRenderAll();
        },
        addPoint: function (e) {
            var t = new fabric.Point(e.x, e.y),
                i = fabric.util.getRandomInt(Math.max(0, this.width - 20), this.width + 20) / 2;
            e = new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0, 100) / 100).toRgba();
            return (t.radius = i), (t.fill = e), this.points.push(t), t;
        },
    })),
    (fabric.SprayBrush = fabric.util.createClass(fabric.BaseBrush, {
        width: 10,
        density: 20,
        dotWidth: 1,
        dotWidthVariance: 1,
        randomOpacity: !1,
        optimizeOverlapping: !0,
        initialize: function (e) {
            (this.canvas = e), (this.sprayChunks = []);
        },
        onMouseDown: function (e) {
            (this.sprayChunks.length = 0), this.canvas.clearContext(this.canvas.contextTop), this._setShadow(), this.addSprayChunk(e), this.render(this.sprayChunkPoints);
        },
        onMouseMove: function (e) {
            (!0 === this.limitedToCanvasSize && this._isOutSideCanvas(e)) || (this.addSprayChunk(e), this.render(this.sprayChunkPoints));
        },
        onMouseUp: function () {
            var e = this.canvas.renderOnAddRemove;
            this.canvas.renderOnAddRemove = !1;
            for (var t = [], i = 0, o = this.sprayChunks.length; i < o; i++)
                for (var n = this.sprayChunks[i], r = 0, s = n.length; r < s; r++) {
                    var a = new fabric.Rect({ width: n[r].width, height: n[r].width, left: n[r].x + 1, top: n[r].y + 1, originX: "center", originY: "center", fill: this.color });
                    t.push(a);
                }
            this.optimizeOverlapping && (t = this._getOptimizedRects(t));
            var c = new fabric.Group(t);
            this.shadow && c.set("shadow", new fabric.Shadow(this.shadow)),
                this.canvas.fire("before:path:created", { path: c }),
                this.canvas.add(c),
                this.canvas.fire("path:created", { path: c }),
                this.canvas.clearContext(this.canvas.contextTop),
                this._resetShadow(),
                (this.canvas.renderOnAddRemove = e),
                this.canvas.requestRenderAll();
        },
        _getOptimizedRects: function (e) {
            for (var t, i = {}, o = 0, n = e.length; o < n; o++) i[(t = e[o].left + "" + e[o].top)] || (i[t] = e[o]);
            var r = [];
            for (t in i) r.push(i[t]);
            return r;
        },
        render: function (e) {
            var t,
                i,
                o = this.canvas.contextTop;
            for (o.fillStyle = this.color, this._saveAndTransform(o), t = 0, i = e.length; t < i; t++) {
                var n = e[t];
                void 0 !== n.opacity && (o.globalAlpha = n.opacity), o.fillRect(n.x, n.y, n.width, n.width);
            }
            o.restore();
        },
        _render: function () {
            var e,
                t,
                i = this.canvas.contextTop;
            for (i.fillStyle = this.color, this._saveAndTransform(i), e = 0, t = this.sprayChunks.length; e < t; e++) this.render(this.sprayChunks[e]);
            i.restore();
        },
        addSprayChunk: function (e) {
            this.sprayChunkPoints = [];
            for (var t = this.width / 2, i = 0; i < this.density; i++) {
                var o = fabric.util.getRandomInt(e.x - t, e.x + t),
                    n = fabric.util.getRandomInt(e.y - t, e.y + t),
                    r = this.dotWidthVariance ? fabric.util.getRandomInt(Math.max(1, this.dotWidth - this.dotWidthVariance), this.dotWidth + this.dotWidthVariance) : this.dotWidth;
                ((n = new fabric.Point(o, n)).width = r), this.randomOpacity && (n.opacity = fabric.util.getRandomInt(0, 100) / 100), this.sprayChunkPoints.push(n);
            }
            this.sprayChunks.push(this.sprayChunkPoints);
        },
    })),
    (fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
        getPatternSrc: function () {
            var e = fabric.util.createCanvasElement(),
                t = e.getContext("2d");
            return (e.width = e.height = 25), (t.fillStyle = this.color), t.beginPath(), t.arc(10, 10, 10, 0, 2 * Math.PI, !1), t.closePath(), t.fill(), e;
        },
        getPatternSrcFunction: function () {
            return String(this.getPatternSrc).replace("this.color", '"' + this.color + '"');
        },
        getPattern: function () {
            return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), "repeat");
        },
        _setBrushStyles: function () {
            this.callSuper("_setBrushStyles"), (this.canvas.contextTop.strokeStyle = this.getPattern());
        },
        createPath: function (e) {
            var t = this.callSuper("createPath", e);
            e = t._getLeftTopCoords().scalarAdd(t.strokeWidth / 2);
            return (t.stroke = new fabric.Pattern({ source: this.source || this.getPatternSrcFunction(), offsetX: -e.x, offsetY: -e.y })), t;
        },
    })),
    (function () {
        var e,
            t = fabric.util.getPointer,
            i = fabric.util.degreesToRadians,
            o = fabric.util.isTouchEvent;
        for (e in ((fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, {
            initialize: function (e, t) {
                (t = t || {}), (this.renderAndResetBound = this.renderAndReset.bind(this)), (this.requestRenderAllBound = this.requestRenderAll.bind(this)), this._initStatic(e, t), this._initInteractive(), this._createCacheCanvas();
            },
            uniformScaling: !0,
            uniScaleKey: "shiftKey",
            centeredScaling: !1,
            centeredRotation: !1,
            centeredKey: "altKey",
            altActionKey: "shiftKey",
            interactive: !0,
            selection: !0,
            selectionKey: "shiftKey",
            altSelectionKey: null,
            selectionColor: "rgba(100, 100, 255, 0.3)",
            selectionDashArray: [],
            selectionBorderColor: "rgba(255, 255, 255, 0.3)",
            selectionLineWidth: 1,
            selectionFullyContained: !1,
            hoverCursor: "move",
            moveCursor: "move",
            defaultCursor: "default",
            freeDrawingCursor: "crosshair",
            rotationCursor: "crosshair",
            notAllowedCursor: "not-allowed",
            containerClass: "canvas-container",
            perPixelTargetFind: !1,
            targetFindTolerance: 0,
            skipTargetFind: !1,
            isDrawingMode: !1,
            preserveObjectStacking: !1,
            snapAngle: 0,
            snapThreshold: null,
            stopContextMenu: !1,
            fireRightClick: !1,
            fireMiddleClick: !1,
            targets: [],
            _hoveredTarget: null,
            _hoveredTargets: [],
            _initInteractive: function () {
                (this._currentTransform = null),
                    (this._groupSelector = null),
                    this._initWrapperElement(),
                    this._createUpperCanvas(),
                    this._initEventListeners(),
                    this._initRetinaScaling(),
                    (this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this)),
                    this.calcOffset();
            },
            _chooseObjectsToRender: function () {
                var e,
                    t = this.getActiveObjects();
                if (0 < t.length && !this.preserveObjectStacking) {
                    for (var i = [], o = [], n = 0, r = this._objects.length; n < r; n++) (e = this._objects[n]), (-1 === t.indexOf(e) ? i : o).push(e);
                    1 < t.length && (this._activeObject._objects = o), i.push.apply(i, o);
                } else i = this._objects;
                return i;
            },
            renderAll: function () {
                !this.contextTopDirty || this._groupSelector || this.isDrawingMode || (this.clearContext(this.contextTop), (this.contextTopDirty = !1)), this.hasLostContext && this.renderTopLayer(this.contextTop);
                var e = this.contextContainer;
                return this.renderCanvas(e, this._chooseObjectsToRender()), this;
            },
            renderTopLayer: function (e) {
                e.save(),
                    this.isDrawingMode && this._isCurrentlyDrawing && (this.freeDrawingBrush && this.freeDrawingBrush._render(), (this.contextTopDirty = !0)),
                    this.selection && this._groupSelector && (this._drawSelection(e), (this.contextTopDirty = !0)),
                    e.restore();
            },
            renderTop: function () {
                var e = this.contextTop;
                return this.clearContext(e), this.renderTopLayer(e), this.fire("after:render"), this;
            },
            _normalizePointer: function (e, t) {
                return (e = e.calcTransformMatrix()), (e = fabric.util.invertTransform(e)), (t = this.restorePointerVpt(t)), fabric.util.transformPoint(t, e);
            },
            isTargetTransparent: function (e, t, i) {
                if (e.shouldCache() && e._cacheCanvas && e !== this._activeObject) {
                    var o = this._normalizePointer(e, { x: t, y: i }),
                        n = Math.max(e.cacheTranslationX + o.x * e.zoomX, 0),
                        r = Math.max(e.cacheTranslationY + o.y * e.zoomY, 0);
                    return fabric.util.isTransparent(e._cacheContext, Math.round(n), Math.round(r), this.targetFindTolerance);
                }
                return (
                    (o = this.contextCache),
                    (n = e.selectionBackgroundColor),
                    (r = this.viewportTransform),
                    (e.selectionBackgroundColor = ""),
                    this.clearContext(o),
                    o.save(),
                    o.transform(r[0], r[1], r[2], r[3], r[4], r[5]),
                    e.render(o),
                    o.restore(),
                    (e.selectionBackgroundColor = n),
                    fabric.util.isTransparent(o, t, i, this.targetFindTolerance)
                );
            },
            _isSelectionKeyPressed: function (e) {
                return "[object Array]" === Object.prototype.toString.call(this.selectionKey)
                    ? !!this.selectionKey.find(function (t) {
                          return !0 === e[t];
                      })
                    : e[this.selectionKey];
            },
            _shouldClearSelection: function (e, t) {
                var i = this.getActiveObjects(),
                    o = this._activeObject;
                return !t || (t && o && 1 < i.length && -1 === i.indexOf(t) && o !== t && !this._isSelectionKeyPressed(e)) || (t && !t.evented) || (t && !t.selectable && o && o !== t);
            },
            _shouldCenterTransform: function (e, t, i) {
                var o;
                if (e) return "scale" === t || "scaleX" === t || "scaleY" === t || "resizing" === t ? (o = this.centeredScaling || e.centeredScaling) : "rotate" === t && (o = this.centeredRotation || e.centeredRotation), o ? !i : i;
            },
            _getOriginFromCorner: function (e, t) {
                return (
                    (e = { x: e.originX, y: e.originY }),
                    "ml" === t || "tl" === t || "bl" === t ? (e.x = "right") : ("mr" !== t && "tr" !== t && "br" !== t) || (e.x = "left"),
                    "tl" === t || "mt" === t || "tr" === t ? (e.y = "bottom") : ("bl" !== t && "mb" !== t && "br" !== t) || (e.y = "top"),
                    e
                );
            },
            _getActionFromCorner: function (e, t, i, o) {
                return t && e ? (t = o.controls[t]).getActionName(i, t, o) : "drag";
            },
            _setupCurrentTransform: function (e, t, o) {
                var n, r, s, a, c;
                t &&
                    ((c = this.getPointer(e)),
                    (n = t.__corner),
                    (a = t.controls[n]),
                    (r = o && n ? a.getActionHandler(e, t, a) : fabric.controlsUtils.dragHandler),
                    (s = this._getActionFromCorner(o, n, e, t)),
                    (a = this._getOriginFromCorner(t, n)),
                    (o = e[this.centeredKey]),
                    (c = {
                        target: t,
                        action: s,
                        actionHandler: r,
                        corner: n,
                        scaleX: t.scaleX,
                        scaleY: t.scaleY,
                        skewX: t.skewX,
                        skewY: t.skewY,
                        offsetX: c.x - t.left,
                        offsetY: c.y - t.top,
                        originX: a.x,
                        originY: a.y,
                        ex: c.x,
                        ey: c.y,
                        lastX: c.x,
                        lastY: c.y,
                        theta: i(t.angle),
                        width: t.width * t.scaleX,
                        shiftKey: e.shiftKey,
                        altKey: o,
                        original: fabric.util.saveObjectTransform(t),
                    }),
                    this._shouldCenterTransform(t, s, o) && ((c.originX = "center"), (c.originY = "center")),
                    (c.original.originX = a.x),
                    (c.original.originY = a.y),
                    (this._currentTransform = c),
                    this._beforeTransform(e));
            },
            setCursor: function (e) {
                this.upperCanvasEl.style.cursor = e;
            },
            _drawSelection: function (e) {
                var t = this._groupSelector,
                    i = new fabric.Point(t.ex, t.ey),
                    o = fabric.util.transformPoint(i, this.viewportTransform),
                    n = new fabric.Point(t.ex + t.left, t.ey + t.top),
                    r = fabric.util.transformPoint(n, this.viewportTransform);
                (i = Math.min(o.x, r.x)), (t = Math.min(o.y, r.y)), (n = Math.max(o.x, r.x)), (o = Math.max(o.y, r.y)), (r = this.selectionLineWidth / 2);
                this.selectionColor && ((e.fillStyle = this.selectionColor), e.fillRect(i, t, n - i, o - t)),
                    this.selectionLineWidth &&
                        this.selectionBorderColor &&
                        ((e.lineWidth = this.selectionLineWidth),
                        (e.strokeStyle = this.selectionBorderColor),
                        (i += r),
                        (t += r),
                        (n -= r),
                        (o -= r),
                        fabric.Object.prototype._setLineDash.call(this, e, this.selectionDashArray),
                        e.strokeRect(i, t, n - i, o - t));
            },
            findTarget: function (e, t) {
                if (!this.skipTargetFind) {
                    var i,
                        n,
                        r = this.getPointer(e, !0),
                        s = this._activeObject,
                        a = this.getActiveObjects(),
                        c = o(e),
                        l = (1 < a.length && !t) || 1 === a.length;
                    if (((this.targets = []), l && s._findTargetCorner(r, c))) return s;
                    if (1 < a.length && !t && s === this._searchPossibleTargets([s], r)) return s;
                    if (1 === a.length && s === this._searchPossibleTargets([s], r)) {
                        if (!this.preserveObjectStacking) return s;
                        (i = s), (n = this.targets), (this.targets = []);
                    }
                    return (r = this._searchPossibleTargets(this._objects, r)), e[this.altSelectionKey] && r && i && r !== i && ((r = i), (this.targets = n)), r;
                }
            },
            _checkTarget: function (e, t, i) {
                if (t && t.visible && t.evented && t.containsPoint(e)) return !((this.perPixelTargetFind || t.perPixelTargetFind) && !t.isEditing) || !this.isTargetTransparent(t, i.x, i.y) || void 0;
            },
            _searchPossibleTargets: function (e, t) {
                for (var i, o, n = e.length; n--; ) {
                    var r = e[n],
                        s = r.group ? this._normalizePointer(r.group, t) : t;
                    if (this._checkTarget(s, r, t)) {
                        (i = e[n]).subTargetCheck && i instanceof fabric.Group && (o = this._searchPossibleTargets(i._objects, t)) && this.targets.push(o);
                        break;
                    }
                }
                return i;
            },
            restorePointerVpt: function (e) {
                return fabric.util.transformPoint(e, fabric.util.invertTransform(this.viewportTransform));
            },
            getPointer: function (e, i) {
                if (this._absolutePointer && !i) return this._absolutePointer;
                if (this._pointer && i) return this._pointer;
                var o = t(e),
                    n = this.upperCanvasEl,
                    r = n.getBoundingClientRect(),
                    s = r.width || 0;
                e = r.height || 0;
                return (
                    (s && e) || ("top" in r && "bottom" in r && (e = Math.abs(r.top - r.bottom)), "right" in r && "left" in r && (s = Math.abs(r.right - r.left))),
                    this.calcOffset(),
                    (o.x = o.x - this._offset.left),
                    (o.y = o.y - this._offset.top),
                    i || (o = this.restorePointerVpt(o)),
                    1 !== (i = this.getRetinaScaling()) && ((o.x /= i), (o.y /= i)),
                    (e = 0 === s || 0 === e ? { width: 1, height: 1 } : { width: n.width / s, height: n.height / e }),
                    { x: o.x * e.width, y: o.y * e.height }
                );
            },
            _createUpperCanvas: function () {
                var e = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ""),
                    t = this.lowerCanvasEl,
                    i = this.upperCanvasEl;
                i ? (i.className = "") : ((i = this._createCanvasElement()), (this.upperCanvasEl = i)),
                    fabric.util.addClass(i, "upper-canvas " + e),
                    this.wrapperEl.appendChild(i),
                    this._copyCanvasStyle(t, i),
                    this._applyCanvasStyle(i),
                    (this.contextTop = i.getContext("2d"));
            },
            _createCacheCanvas: function () {
                (this.cacheCanvasEl = this._createCanvasElement()), this.cacheCanvasEl.setAttribute("width", this.width), this.cacheCanvasEl.setAttribute("height", this.height), (this.contextCache = this.cacheCanvasEl.getContext("2d"));
            },
            _initWrapperElement: function () {
                (this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, "div", { class: this.containerClass })),
                    fabric.util.setStyle(this.wrapperEl, { width: this.width + "px", height: this.height + "px", position: "relative" }),
                    fabric.util.makeElementUnselectable(this.wrapperEl);
                if (!isAdmin) {
                    this.wrapperEl.style.pointerEvents = "none";
                    var leftOptions = document.getElementsByClassName('whiteboard-left-options');
                    if (leftOptions.length) { leftOptions[0].style.display = "none"; }
                }
            },
            _applyCanvasStyle: function (e) {
                var t = this.width || e.width,
                    i = this.height || e.height;
                fabric.util.setStyle(e, {
                    position: "absolute",
                    width: t + "px",
                    height: i + "px",
                    left: 0,
                    top: 0,
                    "touch-action": this.allowTouchScrolling ? "manipulation" : "none",
                    "-ms-touch-action": this.allowTouchScrolling ? "manipulation" : "none",
                }),
                    (e.width = t),
                    (e.height = i),
                    fabric.util.makeElementUnselectable(e);
            },
            _copyCanvasStyle: function (e, t) {
                t.style.cssText = e.style.cssText;
            },
            getSelectionContext: function () {
                return this.contextTop;
            },
            getSelectionElement: function () {
                return this.upperCanvasEl;
            },
            getActiveObject: function () {
                return this._activeObject;
            },
            getActiveObjects: function () {
                var e = this._activeObject;
                return e ? ("activeSelection" === e.type && e._objects ? e._objects.slice(0) : [e]) : [];
            },
            _onObjectRemoved: function (e) {
                e === this._activeObject && (this.fire("before:selection:cleared", { target: e }), this._discardActiveObject(), this.fire("selection:cleared", { target: e }), e.fire("deselected")),
                    e === this._hoveredTarget && ((this._hoveredTarget = null), (this._hoveredTargets = [])),
                    this.callSuper("_onObjectRemoved", e);
            },
            _fireSelectionEvents: function (e, t) {
                var i = !1,
                    o = this.getActiveObjects(),
                    n = [],
                    r = [];
                e.forEach(function (e) {
                    -1 === o.indexOf(e) && ((i = !0), e.fire("deselected", { e: t, target: e }), r.push(e));
                }),
                    o.forEach(function (o) {
                        -1 === e.indexOf(o) && ((i = !0), o.fire("selected", { e: t, target: o }), n.push(o));
                    }),
                    0 < e.length && 0 < o.length
                        ? i && this.fire("selection:updated", { e: t, selected: n, deselected: r, updated: n[0] || r[0], target: this._activeObject })
                        : 0 < o.length
                        ? this.fire("selection:created", { e: t, selected: n, target: this._activeObject })
                        : 0 < e.length && this.fire("selection:cleared", { e: t, deselected: r });
            },
            setActiveObject: function (e, t) {
                var i = this.getActiveObjects();
                return this._setActiveObject(e, t), this._fireSelectionEvents(i, t), this;
            },
            _setActiveObject: function (e, t) {
                return this._activeObject !== e && !!this._discardActiveObject(t, e) && !e.onSelect({ e: t }) && ((this._activeObject = e), !0);
            },
            _discardActiveObject: function (e, t) {
                var i = this._activeObject;
                if (i) {
                    if (i.onDeselect({ e: e, object: t })) return !1;
                    this._activeObject = null;
                }
                return !0;
            },
            discardActiveObject: function (e) {
                var t = this.getActiveObjects(),
                    i = this.getActiveObject();
                return t.length && this.fire("before:selection:cleared", { target: i, e: e }), this._discardActiveObject(e), this._fireSelectionEvents(t, e), this;
            },
            dispose: function () {
                var e = this.wrapperEl;
                return (
                    this.removeListeners(),
                    e.removeChild(this.upperCanvasEl),
                    e.removeChild(this.lowerCanvasEl),
                    (this.contextCache = null),
                    (this.contextTop = null),
                    ["upperCanvasEl", "cacheCanvasEl"].forEach(
                        function (e) {
                            fabric.util.cleanUpJsdomNode(this[e]), (this[e] = void 0);
                        }.bind(this)
                    ),
                    e.parentNode && e.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl),
                    delete this.wrapperEl,
                    fabric.StaticCanvas.prototype.dispose.call(this),
                    this
                );
            },
            clear: function () {
                return this.discardActiveObject(), this.clearContext(this.contextTop), this.callSuper("clear");
            },
            drawControls: function (e) {
                var t = this._activeObject;
                t && t._renderControls(e);
            },
            _toObject: function (e, t, i) {
                var o = this._realizeGroupTransformOnObject(e);
                i = this.callSuper("_toObject", e, t, i);
                return this._unwindGroupTransformOnObject(e, o), i;
            },
            _realizeGroupTransformOnObject: function (e) {
                if (e.group && "activeSelection" === e.group.type && this._activeObject === e.group) {
                    var t = {};
                    return (
                        ["angle", "flipX", "flipY", "left", "scaleX", "scaleY", "skewX", "skewY", "top"].forEach(function (i) {
                            t[i] = e[i];
                        }),
                        fabric.util.addTransformToObject(e, this._activeObject.calcOwnMatrix()),
                        t
                    );
                }
                return null;
            },
            _unwindGroupTransformOnObject: function (e, t) {
                t && e.set(t);
            },
            _setSVGObject: function (e, t, i) {
                var o = this._realizeGroupTransformOnObject(t);
                this.callSuper("_setSVGObject", e, t, i), this._unwindGroupTransformOnObject(t, o);
            },
            setViewportTransform: function (e) {
                this.renderOnAddRemove && this._activeObject && this._activeObject.isEditing && this._activeObject.clearContextTop(), fabric.StaticCanvas.prototype.setViewportTransform.call(this, e);
            },
        })),
        fabric.StaticCanvas))
            "prototype" !== e && (fabric.Canvas[e] = fabric.StaticCanvas[e]);
    })(),
    (function () {
        var e = fabric.util.addListener,
            t = fabric.util.removeListener,
            i = { passive: !1 };
        function o(e, t) {
            return e.button && e.button === t - 1;
        }
        fabric.util.object.extend(fabric.Canvas.prototype, {
            mainTouchId: null,
            _initEventListeners: function () {
                this.removeListeners(), this._bindEvents(), this.addOrRemove(e, "add");
            },
            _getEventPrefix: function () {
                return this.enablePointerEvents ? "pointer" : "mouse";
            },
            addOrRemove: function (e, t) {
                var o = this.upperCanvasEl,
                    n = this._getEventPrefix();
                e(fabric.window, "resize", this._onResize),
                    e(o, n + "down", this._onMouseDown),
                    e(o, n + "move", this._onMouseMove, i),
                    e(o, n + "out", this._onMouseOut),
                    e(o, n + "enter", this._onMouseEnter),
                    e(o, "wheel", this._onMouseWheel),
                    e(o, "contextmenu", this._onContextMenu),
                    e(o, "dblclick", this._onDoubleClick),
                    e(o, "dragover", this._onDragOver),
                    e(o, "dragenter", this._onDragEnter),
                    e(o, "dragleave", this._onDragLeave),
                    e(o, "drop", this._onDrop),
                    this.enablePointerEvents || e(o, "touchstart", this._onTouchStart, i),
                    "undefined" != typeof eventjs &&
                        t in eventjs &&
                        (eventjs[t](o, "gesture", this._onGesture),
                        eventjs[t](o, "drag", this._onDrag),
                        eventjs[t](o, "orientation", this._onOrientationChange),
                        eventjs[t](o, "shake", this._onShake),
                        eventjs[t](o, "longpress", this._onLongPress));
            },
            removeListeners: function () {
                this.addOrRemove(t, "remove");
                var e = this._getEventPrefix();
                t(fabric.document, e + "up", this._onMouseUp), t(fabric.document, "touchend", this._onTouchEnd, i), t(fabric.document, e + "move", this._onMouseMove, i), t(fabric.document, "touchmove", this._onMouseMove, i);
            },
            _bindEvents: function () {
                this.eventsBound ||
                    ((this._onMouseDown = this._onMouseDown.bind(this)),
                    (this._onTouchStart = this._onTouchStart.bind(this)),
                    (this._onMouseMove = this._onMouseMove.bind(this)),
                    (this._onMouseUp = this._onMouseUp.bind(this)),
                    (this._onTouchEnd = this._onTouchEnd.bind(this)),
                    (this._onResize = this._onResize.bind(this)),
                    (this._onGesture = this._onGesture.bind(this)),
                    (this._onDrag = this._onDrag.bind(this)),
                    (this._onShake = this._onShake.bind(this)),
                    (this._onLongPress = this._onLongPress.bind(this)),
                    (this._onOrientationChange = this._onOrientationChange.bind(this)),
                    (this._onMouseWheel = this._onMouseWheel.bind(this)),
                    (this._onMouseOut = this._onMouseOut.bind(this)),
                    (this._onMouseEnter = this._onMouseEnter.bind(this)),
                    (this._onContextMenu = this._onContextMenu.bind(this)),
                    (this._onDoubleClick = this._onDoubleClick.bind(this)),
                    (this._onDragOver = this._onDragOver.bind(this)),
                    (this._onDragEnter = this._simpleEventHandler.bind(this, "dragenter")),
                    (this._onDragLeave = this._simpleEventHandler.bind(this, "dragleave")),
                    (this._onDrop = this._simpleEventHandler.bind(this, "drop")),
                    (this.eventsBound = !0));
            },
            _onGesture: function (e, t) {
                this.__onTransformGesture && this.__onTransformGesture(e, t);
            },
            _onDrag: function (e, t) {
                this.__onDrag && this.__onDrag(e, t);
            },
            _onMouseWheel: function (e) {
                this.__onMouseWheel(e);
            },
            _onMouseOut: function (e) {
                var t = this._hoveredTarget;
                this.fire("mouse:out", { target: t, e: e }), (this._hoveredTarget = null), t && t.fire("mouseout", { e: e });
                var i = this;
                this._hoveredTargets.forEach(function (o) {
                    i.fire("mouse:out", { target: t, e: e }), o && t.fire("mouseout", { e: e });
                }),
                    (this._hoveredTargets = []),
                    this._iTextInstances &&
                        this._iTextInstances.forEach(function (e) {
                            e.isEditing && e.hiddenTextarea.focus();
                        });
            },
            _onMouseEnter: function (e) {
                this._currentTransform || this.findTarget(e) || (this.fire("mouse:over", { target: null, e: e }), (this._hoveredTarget = null), (this._hoveredTargets = []));
            },
            _onOrientationChange: function (e, t) {
                this.__onOrientationChange && this.__onOrientationChange(e, t);
            },
            _onShake: function (e, t) {
                this.__onShake && this.__onShake(e, t);
            },
            _onLongPress: function (e, t) {
                this.__onLongPress && this.__onLongPress(e, t);
            },
            _onDragOver: function (e) {
                e.preventDefault();
                var t = this._simpleEventHandler("dragover", e);
                this._fireEnterLeaveEvents(t, e);
            },
            _onContextMenu: function (e) {
                return this.stopContextMenu && (e.stopPropagation(), e.preventDefault()), !1;
            },
            _onDoubleClick: function (e) {
                this._cacheTransformEventData(e), this._handleEvent(e, "dblclick"), this._resetTransformEventData(e);
            },
            getPointerId: function (e) {
                var t = e.changedTouches;
                return t ? t[0] && t[0].identifier : this.enablePointerEvents ? e.pointerId : -1;
            },
            _isMainEvent: function (e) {
                return !0 === e.isPrimary || (!1 !== e.isPrimary && (("touchend" === e.type && 0 === e.touches.length) || !e.changedTouches || e.changedTouches[0].identifier === this.mainTouchId));
            },
            _onTouchStart: function (o) {
                o.preventDefault(), null === this.mainTouchId && (this.mainTouchId = this.getPointerId(o)), this.__onMouseDown(o), this._resetTransformEventData();
                var n = this.upperCanvasEl;
                o = this._getEventPrefix();
                e(fabric.document, "touchend", this._onTouchEnd, i), e(fabric.document, "touchmove", this._onMouseMove, i), t(n, o + "down", this._onMouseDown);
            },
            _onMouseDown: function (o) {
                this.__onMouseDown(o), this._resetTransformEventData();
                var n = this.upperCanvasEl;
                o = this._getEventPrefix();
                t(n, o + "move", this._onMouseMove, i), e(fabric.document, o + "up", this._onMouseUp), e(fabric.document, o + "move", this._onMouseMove, i);
            },
            _onTouchEnd: function (o) {
                var n, r;
                0 < o.touches.length ||
                    (this.__onMouseUp(o),
                    this._resetTransformEventData(),
                    (this.mainTouchId = null),
                    (n = this._getEventPrefix()),
                    t(fabric.document, "touchend", this._onTouchEnd, i),
                    t(fabric.document, "touchmove", this._onMouseMove, i),
                    (r = this)._willAddMouseDown && clearTimeout(this._willAddMouseDown),
                    (this._willAddMouseDown = setTimeout(function () {
                        e(r.upperCanvasEl, n + "down", r._onMouseDown), (r._willAddMouseDown = 0);
                    }, 400)));
            },
            _onMouseUp: function (o) {
                this.__onMouseUp(o), this._resetTransformEventData();
                var n = this.upperCanvasEl,
                    r = this._getEventPrefix();
                this._isMainEvent(o) && (t(fabric.document, r + "up", this._onMouseUp), t(fabric.document, r + "move", this._onMouseMove, i), e(n, r + "move", this._onMouseMove, i));
            },
            _onMouseMove: function (e) {
                !this.allowTouchScrolling && e.preventDefault && e.preventDefault(), this.__onMouseMove(e);
            },
            _onResize: function () {
                this.calcOffset();
            },
            _shouldRender: function (e) {
                var t = this._activeObject;
                return !!(!!t != !!e || (t && e && t !== e)) || (t && t.isEditing, !1);
            },
            __onMouseUp: function (e) {
                var t,
                    i = this._currentTransform,
                    n = this._groupSelector,
                    r = !1,
                    s = !n || (0 === n.left && 0 === n.top);
                if ((this._cacheTransformEventData(e), (n = this._target), this._handleEvent(e, "up:before"), o(e, 3))) this.fireRightClick && this._handleEvent(e, "up", 3, s);
                else {
                    if (o(e, 2)) return this.fireMiddleClick && this._handleEvent(e, "up", 2, s), void this._resetTransformEventData();
                    this.isDrawingMode && this._isCurrentlyDrawing
                        ? this._onMouseUpInDrawingMode(e)
                        : this._isMainEvent(e) &&
                          (i && (this._finalizeCurrentTransform(e), (r = i.actionPerformed)),
                          s || ((t = n === this._activeObject), this._maybeGroupObjects(e), (r = r || this._shouldRender(n) || (!t && n === this._activeObject))),
                          n &&
                              (n.selectable && n !== this._activeObject && "up" === n.activeOn
                                  ? (this.setActiveObject(n, e), (r = !0))
                                  : ((t = n._findTargetCorner(this.getPointer(e, !0), fabric.util.isTouchEvent(e))), (t = (t = n.controls[t]) && t.getMouseUpHandler(e, n, t)) && t(e, i, (i = this.getPointer(e)).x, i.y)),
                              (n.isMoving = !1)),
                          this._setCursorFromEvent(e, n),
                          this._handleEvent(e, "up", 1, s),
                          (this._groupSelector = null),
                          (this._currentTransform = null),
                          n && (n.__corner = 0),
                          r ? this.requestRenderAll() : s || this.renderTop());
                }
            },
            _simpleEventHandler: function (e, t) {
                var i = this.findTarget(t),
                    o = this.targets,
                    n = { e: t, target: i, subTargets: o };
                if ((this.fire(e, n), i && i.fire(e, n), !o)) return i;
                for (var r = 0; r < o.length; r++) o[r].fire(e, n);
                return i;
            },
            _handleEvent: function (e, t, i, o) {
                var n = this._target,
                    r = this.targets || [],
                    s = { e: e, target: n, subTargets: r, button: i || 1, isClick: o || !1, pointer: this._pointer, absolutePointer: this._absolutePointer, transform: this._currentTransform };
                "up" === t && ((s.currentTarget = this.findTarget(e)), (s.currentSubTargets = this.targets)), this.fire("mouse:" + t, s), n && n.fire("mouse" + t, s);
                for (var a = 0; a < r.length; a++) r[a].fire("mouse" + t, s);
            },
            _finalizeCurrentTransform: function (e) {
                var t = this._currentTransform,
                    i = t.target;
                e = { e: e, target: i, transform: t, action: t.action };
                i._scaling && (i._scaling = !1), i.setCoords(), (t.actionPerformed || (this.stateful && i.hasStateChanged())) && (t.actionPerformed && ((t = this._addEventOptions(e, t)), this._fire(t, e)), this._fire("modified", e));
            },
            _addEventOptions: function (e, t) {
                var i, o;
                switch (t.action) {
                    case "scaleX":
                        (i = "scaled"), (o = "x");
                        break;
                    case "scaleY":
                        (i = "scaled"), (o = "y");
                        break;
                    case "skewX":
                        (i = "skewed"), (o = "x");
                        break;
                    case "skewY":
                        (i = "skewed"), (o = "y");
                        break;
                    case "scale":
                        (i = "scaled"), (o = "equally");
                        break;
                    case "rotate":
                        i = "rotated";
                        break;
                    case "drag":
                        i = "moved";
                }
                return (e.by = o), i;
            },
            _onMouseDownInDrawingMode: function (e) {
                (this._isCurrentlyDrawing = !0), this.getActiveObject() && this.discardActiveObject(e).requestRenderAll();
                var t = this.getPointer(e);
                this.freeDrawingBrush.onMouseDown(t, { e: e, pointer: t }), this._handleEvent(e, "down");
            },
            _onMouseMoveInDrawingMode: function (e) {
                var t;
                this._isCurrentlyDrawing && ((t = this.getPointer(e)), this.freeDrawingBrush.onMouseMove(t, { e: e, pointer: t })), this.setCursor(this.freeDrawingCursor), this._handleEvent(e, "move");
            },
            _onMouseUpInDrawingMode: function (e) {
                var t = this.getPointer(e);
                (this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({ e: e, pointer: t })), this._handleEvent(e, "up");
            },
            __onMouseDown: function (e) {
                this._cacheTransformEventData(e), this._handleEvent(e, "down:before");
                var t,
                    i,
                    n,
                    r,
                    s,
                    a = this._target;
                o(e, 3)
                    ? this.fireRightClick && this._handleEvent(e, "down", 3)
                    : o(e, 2)
                    ? this.fireMiddleClick && this._handleEvent(e, "down", 2)
                    : this.isDrawingMode
                    ? this._onMouseDownInDrawingMode(e)
                    : this._isMainEvent(e) &&
                      (this._currentTransform ||
                          ((r = this._pointer),
                          (this._previousPointer = r),
                          (t = this._shouldRender(a)),
                          (i = this._shouldGroup(e, a)),
                          this._shouldClearSelection(e, a) ? this.discardActiveObject(e) : i && (this._handleGrouping(e, a), (a = this._activeObject)),
                          !this.selection || (a && (a.selectable || a.isEditing || a === this._activeObject)) || (this._groupSelector = { ex: this._absolutePointer.x, ey: this._absolutePointer.y, top: 0, left: 0 }),
                          a &&
                              ((n = a === this._activeObject),
                              a.selectable && "down" === a.activeOn && this.setActiveObject(a, e),
                              (s = a._findTargetCorner(this.getPointer(e, !0), fabric.util.isTouchEvent(e))),
                              (a.__corner = s),
                              a !== this._activeObject ||
                                  (!s && i) ||
                                  (this._setupCurrentTransform(e, a, n), (s = a.controls[s]), (r = this.getPointer(e)), (s = s && s.getMouseDownHandler(e, a, s)) && s(e, this._currentTransform, r.x, r.y))),
                          this._handleEvent(e, "down"),
                          (t || i) && this.requestRenderAll()));
            },
            _resetTransformEventData: function () {
                (this._target = null), (this._pointer = null), (this._absolutePointer = null);
            },
            _cacheTransformEventData: function (e) {
                this._resetTransformEventData(),
                    (this._pointer = this.getPointer(e, !0)),
                    (this._absolutePointer = this.restorePointerVpt(this._pointer)),
                    (this._target = this._currentTransform ? this._currentTransform.target : this.findTarget(e) || null);
            },
            _beforeTransform: function (e) {
                var t = this._currentTransform;
                this.stateful && t.target.saveState(), this.fire("before:transform", { e: e, transform: t });
            },
            __onMouseMove: function (e) {
                var t, i;
                this._handleEvent(e, "move:before"),
                    this._cacheTransformEventData(e),
                    this.isDrawingMode
                        ? this._onMouseMoveInDrawingMode(e)
                        : this._isMainEvent(e) &&
                          ((i = this._groupSelector)
                              ? ((t = this._absolutePointer), (i.left = t.x - i.ex), (i.top = t.y - i.ey), this.renderTop())
                              : this._currentTransform
                              ? this._transformObject(e)
                              : ((i = this.findTarget(e) || null), this._setCursorFromEvent(e, i), this._fireOverOutEvents(i, e)),
                          this._handleEvent(e, "move"),
                          this._resetTransformEventData());
            },
            _fireOverOutEvents: function (e, t) {
                var i = this._hoveredTarget,
                    o = this._hoveredTargets,
                    n = this.targets,
                    r = Math.max(o.length, n.length);
                this.fireSyntheticInOutEvents(e, t, { oldTarget: i, evtOut: "mouseout", canvasEvtOut: "mouse:out", evtIn: "mouseover", canvasEvtIn: "mouse:over" });
                for (var s = 0; s < r; s++) this.fireSyntheticInOutEvents(n[s], t, { oldTarget: o[s], evtOut: "mouseout", evtIn: "mouseover" });
                (this._hoveredTarget = e), (this._hoveredTargets = this.targets.concat());
            },
            _fireEnterLeaveEvents: function (e, t) {
                var i = this._draggedoverTarget,
                    o = this._hoveredTargets,
                    n = this.targets,
                    r = Math.max(o.length, n.length);
                this.fireSyntheticInOutEvents(e, t, { oldTarget: i, evtOut: "dragleave", evtIn: "dragenter" });
                for (var s = 0; s < r; s++) this.fireSyntheticInOutEvents(n[s], t, { oldTarget: o[s], evtOut: "dragleave", evtIn: "dragenter" });
                this._draggedoverTarget = e;
            },
            fireSyntheticInOutEvents: function (e, t, i) {
                var o,
                    n,
                    r = i.oldTarget,
                    s = r !== e,
                    a = i.canvasEvtIn,
                    c = i.canvasEvtOut;
                s && ((o = { e: t, target: e, previousTarget: r }), (n = { e: t, target: r, nextTarget: e })), (t = e && s), r && s && (c && this.fire(c, n), r.fire(i.evtOut, n)), t && (a && this.fire(a, o), e.fire(i.evtIn, o));
            },
            __onMouseWheel: function (e) {
                this._cacheTransformEventData(e), this._handleEvent(e, "wheel"), this._resetTransformEventData();
            },
            _transformObject: function (e) {
                var t = this.getPointer(e),
                    i = this._currentTransform;
                (i.reset = !1), (i.shiftKey = e.shiftKey), (i.altKey = e[this.centeredKey]), this._performTransformAction(e, i, t), i.actionPerformed && this.requestRenderAll();
            },
            _performTransformAction: function (e, t, i) {
                var o = i.x,
                    n = i.y,
                    r = t.action,
                    s = !1;
                (i = t.actionHandler) && (s = i(e, t, o, n)), "drag" === r && s && ((t.target.isMoving = !0), this.setCursor(t.target.moveCursor || this.moveCursor)), (t.actionPerformed = t.actionPerformed || s);
            },
            _fire: fabric.controlsUtils.fireEvent,
            _setCursorFromEvent: function (e, t) {
                if (!t) return this.setCursor(this.defaultCursor), !1;
                var i,
                    o = t.hoverCursor || this.hoverCursor;
                (i = (!(i = this._activeObject && "activeSelection" === this._activeObject.type ? this._activeObject : null) || !i.contains(t)) && t._findTargetCorner(this.getPointer(e, !0)))
                    ? this.setCursor(this.getCornerCursor(i, t, e))
                    : (t.subTargetCheck &&
                          this.targets
                              .concat()
                              .reverse()
                              .map(function (e) {
                                  o = e.hoverCursor || o;
                              }),
                      this.setCursor(o));
            },
            getCornerCursor: function (e, t, i) {
                return (e = t.controls[e]).cursorStyleHandler(i, e, t);
            },
        });
    })(),
    (function () {
        var e = Math.min,
            t = Math.max;
        fabric.util.object.extend(fabric.Canvas.prototype, {
            _shouldGroup: function (e, t) {
                var i = this._activeObject;
                return i && this._isSelectionKeyPressed(e) && t && t.selectable && this.selection && (i !== t || "activeSelection" === i.type) && !t.onSelect({ e: e });
            },
            _handleGrouping: function (e, t) {
                var i = this._activeObject;
                i.__corner || ((t !== i || ((t = this.findTarget(e, !0)) && t.selectable)) && (i && "activeSelection" === i.type ? this._updateActiveSelection(t, e) : this._createActiveSelection(t, e)));
            },
            _updateActiveSelection: function (e, t) {
                var i = this._activeObject,
                    o = i._objects.slice(0);
                i.contains(e)
                    ? (i.removeWithUpdate(e), (this._hoveredTarget = e), (this._hoveredTargets = this.targets.concat()), 1 === i.size() && this._setActiveObject(i.item(0), t))
                    : (i.addWithUpdate(e), (this._hoveredTarget = i), (this._hoveredTargets = this.targets.concat())),
                    this._fireSelectionEvents(o, t);
            },
            _createActiveSelection: function (e, t) {
                var i = this.getActiveObjects();
                e = this._createGroup(e);
                (this._hoveredTarget = e), this._setActiveObject(e, t), this._fireSelectionEvents(i, t);
            },
            _createGroup: function (e) {
                var t = this._objects;
                e = t.indexOf(this._activeObject) < t.indexOf(e) ? [this._activeObject, e] : [e, this._activeObject];
                return this._activeObject.isEditing && this._activeObject.exitEditing(), new fabric.ActiveSelection(e, { canvas: this });
            },
            _groupSelectedObjects: function (e) {
                var t = this._collectObjects(e);
                1 === t.length ? this.setActiveObject(t[0], e) : 1 < t.length && ((t = new fabric.ActiveSelection(t.reverse(), { canvas: this })), this.setActiveObject(t, e));
            },
            _collectObjects: function (i) {
                for (
                    var o,
                        n = [],
                        r = this._groupSelector.ex,
                        s = this._groupSelector.ey,
                        a = r + this._groupSelector.left,
                        c = s + this._groupSelector.top,
                        l = new fabric.Point(e(r, a), e(s, c)),
                        d = new fabric.Point(t(r, a), t(s, c)),
                        h = !this.selectionFullyContained,
                        u = r === a && s === c,
                        f = this._objects.length;
                    f-- &&
                    !(
                        (o = this._objects[f]) &&
                        o.selectable &&
                        o.visible &&
                        ((h && o.intersectsWithRect(l, d, !0)) || o.isContainedWithinRect(l, d, !0) || (h && o.containsPoint(l, null, !0)) || (h && o.containsPoint(d, null, !0))) &&
                        (n.push(o), u)
                    );

                );
                return 1 < n.length
                    ? n.filter(function (e) {
                          return !e.onSelect({ e: i });
                      })
                    : n;
            },
            _maybeGroupObjects: function (e) {
                this.selection && this._groupSelector && this._groupSelectedObjects(e), this.setCursor(this.defaultCursor), (this._groupSelector = null);
            },
        });
    })(),
    fabric.util.object.extend(fabric.StaticCanvas.prototype, {
        toDataURL: function (e) {
            var t = (e = e || {}).format || "png",
                i = e.quality || 1,
                o = (e.multiplier || 1) * (e.enableRetinaScaling ? this.getRetinaScaling() : 1);
            e = this.toCanvasElement(o, e);
            return fabric.util.toDataURL(e, t, i);
        },
        toCanvasElement: function (e, t) {
            var i = ((t = t || {}).width || this.width) * (e = e || 1),
                o = (t.height || this.height) * e,
                n = this.getZoom(),
                r = this.width,
                s = this.height,
                a = n * e,
                c = this.viewportTransform,
                l = (c[4] - (t.left || 0)) * e;
            (n = (c[5] - (t.top || 0)) * e), (t = this.interactive), (e = [a, 0, 0, a, l, n]), (a = this.enableRetinaScaling), (l = fabric.util.createCanvasElement()), (n = this.contextTop);
            return (
                (l.width = i),
                (l.height = o),
                (this.contextTop = null),
                (this.enableRetinaScaling = !1),
                (this.interactive = !1),
                (this.viewportTransform = e),
                (this.width = i),
                (this.height = o),
                this.calcViewportBoundaries(),
                this.renderCanvas(l.getContext("2d"), this._objects),
                (this.viewportTransform = c),
                (this.width = r),
                (this.height = s),
                this.calcViewportBoundaries(),
                (this.interactive = t),
                (this.enableRetinaScaling = a),
                (this.contextTop = n),
                l
            );
        },
    }),
    fabric.util.object.extend(fabric.StaticCanvas.prototype, {
        loadFromJSON: function (e, t, i) {
            if (e) {
                var o = "string" == typeof e ? JSON.parse(e) : fabric.util.object.clone(e),
                    n = this,
                    r = o.clipPath,
                    s = this.renderOnAddRemove;
                return (
                    (this.renderOnAddRemove = !1),
                    delete o.clipPath,
                    this._enlivenObjects(
                        o.objects,
                        function (e) {
                            n.clear(),
                                n._setBgOverlay(o, function () {
                                    r
                                        ? n._enlivenObjects([r], function (i) {
                                              (n.clipPath = i[0]), n.__setupCanvas.call(n, o, e, s, t);
                                          })
                                        : n.__setupCanvas.call(n, o, e, s, t);
                                });
                        },
                        i
                    ),
                    this
                );
            }
        },
        __setupCanvas: function (e, t, i, o) {
            var n = this;
            t.forEach(function (e, t) {
                n.insertAt(e, t);
            }),
                (this.renderOnAddRemove = i),
                delete e.objects,
                delete e.backgroundImage,
                delete e.overlayImage,
                delete e.background,
                delete e.overlay,
                this._setOptions(e),
                this.renderAll(),
                o && o();
        },
        _setBgOverlay: function (e, t) {
            var i,
                o = { backgroundColor: !1, overlayColor: !1, backgroundImage: !1, overlayImage: !1 };
            e.backgroundImage || e.overlayImage || e.background || e.overlay
                ? (this.__setBgOverlay(
                      "backgroundImage",
                      e.backgroundImage,
                      o,
                      (i = function () {
                          o.backgroundImage && o.overlayImage && o.backgroundColor && o.overlayColor && t && t();
                      })
                  ),
                  this.__setBgOverlay("overlayImage", e.overlayImage, o, i),
                  this.__setBgOverlay("backgroundColor", e.background, o, i),
                  this.__setBgOverlay("overlayColor", e.overlay, o, i))
                : t && t();
        },
        __setBgOverlay: function (e, t, i, o) {
            var n = this;
            if (!t) return (i[e] = !0), void (o && o());
            "backgroundImage" === e || "overlayImage" === e
                ? fabric.util.enlivenObjects([t], function (t) {
                      (n[e] = t[0]), (i[e] = !0), o && o();
                  })
                : this["set" + fabric.util.string.capitalize(e, !0)](t, function () {
                      (i[e] = !0), o && o();
                  });
        },
        _enlivenObjects: function (e, t, i) {
            e && 0 !== e.length
                ? fabric.util.enlivenObjects(
                      e,
                      function (e) {
                          t && t(e);
                      },
                      null,
                      i
                  )
                : t && t([]);
        },
        _toDataURL: function (e, t) {
            this.clone(function (i) {
                t(i.toDataURL(e));
            });
        },
        _toDataURLWithMultiplier: function (e, t, i) {
            this.clone(function (o) {
                i(o.toDataURLWithMultiplier(e, t));
            });
        },
        clone: function (e, t) {
            var i = JSON.stringify(this.toJSON(t));
            this.cloneWithoutData(function (t) {
                t.loadFromJSON(i, function () {
                    e && e(t);
                });
            });
        },
        cloneWithoutData: function (e) {
            var t = fabric.util.createCanvasElement();
            (t.width = this.width), (t.height = this.height);
            var i = new fabric.Canvas(t);
            this.backgroundImage
                ? (i.setBackgroundImage(this.backgroundImage.src, function () {
                      i.renderAll(), e && e(i);
                  }),
                  (i.backgroundImageOpacity = this.backgroundImageOpacity),
                  (i.backgroundImageStretch = this.backgroundImageStretch))
                : e && e(i);
        },
    }),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.util.object.clone,
            n = t.util.toFixed,
            r = t.util.string.capitalize,
            s = t.util.degreesToRadians;
        e = !t.isLikelyNode;
        t.Object ||
            ((t.Object = t.util.createClass(t.CommonMethods, {
                type: "object",
                originX: "left",
                originY: "top",
                top: 0,
                left: 0,
                width: 0,
                height: 0,
                scaleX: 1,
                scaleY: 1,
                flipX: !1,
                flipY: !1,
                opacity: 1,
                angle: 0,
                skewX: 0,
                skewY: 0,
                cornerSize: 13,
                touchCornerSize: 24,
                transparentCorners: !0,
                hoverCursor: null,
                moveCursor: null,
                padding: 0,
                borderColor: "rgb(178,204,255)",
                borderDashArray: null,
                cornerColor: "rgb(178,204,255)",
                cornerStrokeColor: null,
                cornerStyle: "rect",
                cornerDashArray: null,
                centeredScaling: !1,
                centeredRotation: !0,
                fill: "rgb(0,0,0)",
                fillRule: "nonzero",
                globalCompositeOperation: "source-over",
                backgroundColor: "",
                selectionBackgroundColor: "",
                stroke: null,
                strokeWidth: 1,
                strokeDashArray: null,
                strokeDashOffset: 0,
                strokeLineCap: "butt",
                strokeLineJoin: "miter",
                strokeMiterLimit: 4,
                shadow: null,
                borderOpacityWhenMoving: 0.4,
                borderScaleFactor: 1,
                minScaleLimit: 0,
                selectable: !0,
                evented: !0,
                visible: !0,
                hasControls: !0,
                hasBorders: !0,
                perPixelTargetFind: !1,
                includeDefaultValues: !0,
                lockMovementX: !1,
                lockMovementY: !1,
                lockRotation: !1,
                lockScalingX: !1,
                lockScalingY: !1,
                lockSkewingX: !1,
                lockSkewingY: !1,
                lockScalingFlip: !1,
                excludeFromExport: !1,
                objectCaching: e,
                statefullCache: !1,
                noScaleCache: !0,
                strokeUniform: !1,
                dirty: !0,
                __corner: 0,
                paintFirst: "fill",
                activeOn: "down",
                stateProperties: "top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit angle opacity fill globalCompositeOperation shadow visible backgroundColor skewX skewY fillRule paintFirst clipPath strokeUniform".split(
                    " "
                ),
                cacheProperties: "fill stroke strokeWidth strokeDashArray width height paintFirst strokeUniform strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit backgroundColor clipPath".split(" "),
                colorProperties: "fill stroke backgroundColor".split(" "),
                clipPath: void 0,
                inverted: !1,
                absolutePositioned: !1,
                initialize: function (e) {
                    e && this.setOptions(e);
                },
                _createCacheCanvas: function () {
                    (this._cacheProperties = {}), (this._cacheCanvas = t.util.createCanvasElement()), (this._cacheContext = this._cacheCanvas.getContext("2d")), this._updateCacheCanvas(), (this.dirty = !0);
                },
                _limitCacheSize: function (e) {
                    var i = t.perfLimitSizeTotal,
                        o = e.width,
                        n = e.height,
                        r = t.maxCacheSideLimit,
                        s = t.minCacheSideLimit;
                    if (o <= r && n <= r && o * n <= i) return o < s && (e.width = s), n < s && (e.height = s), e;
                    var a = t.util.limitDimsByArea(o / n, i),
                        c = t.util.capValue;
                    (i = c(s, a.x, r)), (r = c(s, a.y, r));
                    return i < o && ((e.zoomX /= o / i), (e.width = i), (e.capped = !0)), r < n && ((e.zoomY /= n / r), (e.height = r), (e.capped = !0)), e;
                },
                _getCacheCanvasDimensions: function () {
                    var e,
                        t = this.getTotalObjectScaling(),
                        i = ((e = this._getTransformedDimensions(0, 0)).x * t.scaleX) / this.scaleX;
                    return { width: 2 + i, height: 2 + (e = (e.y * t.scaleY) / this.scaleY), zoomX: t.scaleX, zoomY: t.scaleY, x: i, y: e };
                },
                _updateCacheCanvas: function () {
                    var e = this.canvas;
                    if (this.noScaleCache && e && e._currentTransform) {
                        var i = e._currentTransform.target,
                            o = e._currentTransform.action;
                        if (this === i && o.slice && "scale" === o.slice(0, 5)) return !1;
                    }
                    var n = this._cacheCanvas,
                        r = this._limitCacheSize(this._getCacheCanvasDimensions()),
                        s = t.minCacheSideLimit,
                        a = r.width,
                        c = r.height,
                        l = r.zoomX,
                        d = r.zoomY,
                        h = a !== this.cacheWidth || c !== this.cacheHeight,
                        u = this.zoomX !== l || this.zoomY !== d,
                        f = h || u,
                        m = 0;
                    (e = 0), (i = !1);
                    return (
                        h &&
                            ((o = this._cacheCanvas.width),
                            (u = this._cacheCanvas.height),
                            (i = (h = o < a || u < c) || ((a < 0.9 * o || c < 0.9 * u) && s < o && s < u)),
                            h && !r.capped && (s < a || s < c) && ((m = 0.1 * a), (e = 0.1 * c))),
                        this instanceof t.Text && this.path && ((i = f = !0), (m += this.getHeightOfLine(0) * this.zoomX), (e += this.getHeightOfLine(0) * this.zoomY)),
                        !!f &&
                            (i ? ((n.width = Math.ceil(a + m)), (n.height = Math.ceil(c + e))) : (this._cacheContext.setTransform(1, 0, 0, 1, 0, 0), this._cacheContext.clearRect(0, 0, n.width, n.height)),
                            (e = r.x / 2),
                            (r = r.y / 2),
                            (this.cacheTranslationX = Math.round(n.width / 2 - e) + e),
                            (this.cacheTranslationY = Math.round(n.height / 2 - r) + r),
                            (this.cacheWidth = a),
                            (this.cacheHeight = c),
                            this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY),
                            this._cacheContext.scale(l, d),
                            (this.zoomX = l),
                            (this.zoomY = d),
                            !0)
                    );
                },
                setOptions: function (e) {
                    this._setOptions(e), this._initGradient(e.fill, "fill"), this._initGradient(e.stroke, "stroke"), this._initPattern(e.fill, "fill"), this._initPattern(e.stroke, "stroke");
                },
                transform: function (e) {
                    var t = (this.group && !this.group._transformDone) || (this.group && this.canvas && e === this.canvas.contextTop);
                    t = this.calcTransformMatrix(!t);
                    e.transform(t[0], t[1], t[2], t[3], t[4], t[5]);
                },
                toObject: function (e) {
                    var i = t.Object.NUM_FRACTION_DIGITS;
                    i = {
                        type: this.type,
                        version: t.version,
                        originX: this.originX,
                        originY: this.originY,
                        left: n(this.left, i),
                        top: n(this.top, i),
                        width: n(this.width, i),
                        height: n(this.height, i),
                        fill: this.fill && this.fill.toObject ? this.fill.toObject() : this.fill,
                        stroke: this.stroke && this.stroke.toObject ? this.stroke.toObject() : this.stroke,
                        strokeWidth: n(this.strokeWidth, i),
                        strokeDashArray: this.strokeDashArray && this.strokeDashArray.concat(),
                        strokeLineCap: this.strokeLineCap,
                        strokeDashOffset: this.strokeDashOffset,
                        strokeLineJoin: this.strokeLineJoin,
                        strokeUniform: this.strokeUniform,
                        strokeMiterLimit: n(this.strokeMiterLimit, i),
                        scaleX: n(this.scaleX, i),
                        scaleY: n(this.scaleY, i),
                        angle: n(this.angle, i),
                        flipX: this.flipX,
                        flipY: this.flipY,
                        opacity: n(this.opacity, i),
                        shadow: this.shadow && this.shadow.toObject ? this.shadow.toObject() : this.shadow,
                        visible: this.visible,
                        backgroundColor: this.backgroundColor,
                        fillRule: this.fillRule,
                        paintFirst: this.paintFirst,
                        globalCompositeOperation: this.globalCompositeOperation,
                        skewX: n(this.skewX, i),
                        skewY: n(this.skewY, i),
                    };
                    return (
                        this.clipPath && !this.clipPath.excludeFromExport && ((i.clipPath = this.clipPath.toObject(e)), (i.clipPath.inverted = this.clipPath.inverted), (i.clipPath.absolutePositioned = this.clipPath.absolutePositioned)),
                        t.util.populateWithProperties(this, i, e),
                        this.includeDefaultValues ? i : this._removeDefaultValues(i)
                    );
                },
                toDatalessObject: function (e) {
                    return this.toObject(e);
                },
                _removeDefaultValues: function (e) {
                    var i = t.util.getKlass(e.type).prototype;
                    return (
                        i.stateProperties.forEach(function (t) {
                            "left" !== t &&
                                "top" !== t &&
                                (e[t] === i[t] && delete e[t], "[object Array]" === Object.prototype.toString.call(e[t]) && "[object Array]" === Object.prototype.toString.call(i[t]) && 0 === e[t].length && 0 === i[t].length && delete e[t]);
                        }),
                        e
                    );
                },
                toString: function () {
                    return "#<fabric." + r(this.type) + ">";
                },
                getObjectScaling: function () {
                    if (!this.group) return { scaleX: this.scaleX, scaleY: this.scaleY };
                    var e = t.util.qrDecompose(this.calcTransformMatrix());
                    return { scaleX: Math.abs(e.scaleX), scaleY: Math.abs(e.scaleY) };
                },
                getTotalObjectScaling: function () {
                    var e,
                        t = this.getObjectScaling(),
                        i = t.scaleX,
                        o = t.scaleY;
                    return this.canvas && ((i *= (e = this.canvas.getZoom()) * (t = this.canvas.getRetinaScaling())), (o *= e * t)), { scaleX: i, scaleY: o };
                },
                getObjectOpacity: function () {
                    var e = this.opacity;
                    return this.group && (e *= this.group.getObjectOpacity()), e;
                },
                _set: function (e, i) {
                    var o,
                        n = this[e] !== i;
                    return (
                        ("scaleX" === e || "scaleY" === e) && (i = this._constrainScale(i)),
                        "scaleX" === e && i < 0
                            ? ((this.flipX = !this.flipX), (i *= -1))
                            : "scaleY" === e && i < 0
                            ? ((this.flipY = !this.flipY), (i *= -1))
                            : "shadow" !== e || !i || i instanceof t.Shadow
                            ? "dirty" === e && this.group && this.group.set("dirty", i)
                            : (i = new t.Shadow(i)),
                        (this[e] = i),
                        n &&
                            ((o = this.group && this.group.isOnACache()),
                            -1 < this.cacheProperties.indexOf(e) ? ((this.dirty = !0), o && this.group.set("dirty", !0)) : o && -1 < this.stateProperties.indexOf(e) && this.group.set("dirty", !0)),
                        this
                    );
                },
                setOnGroup: function () {},
                getViewportTransform: function () {
                    return this.canvas && this.canvas.viewportTransform ? this.canvas.viewportTransform : t.iMatrix.concat();
                },
                isNotVisible: function () {
                    return 0 === this.opacity || (!this.width && !this.height && 0 === this.strokeWidth) || !this.visible;
                },
                render: function (e) {
                    this.isNotVisible() ||
                        (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) ||
                        (e.save(),
                        this._setupCompositeOperation(e),
                        this.drawSelectionBackground(e),
                        this.transform(e),
                        this._setOpacity(e),
                        this._setShadow(e, this),
                        this.shouldCache()
                            ? (this.renderCache(), this.drawCacheOnCanvas(e))
                            : (this._removeCacheCanvas(), (this.dirty = !1), this.drawObject(e), this.objectCaching && this.statefullCache && this.saveState({ propertySet: "cacheProperties" })),
                        e.restore());
                },
                renderCache: function (e) {
                    (e = e || {}),
                        this._cacheCanvas || this._createCacheCanvas(),
                        this.isCacheDirty() && (this.statefullCache && this.saveState({ propertySet: "cacheProperties" }), this.drawObject(this._cacheContext, e.forClipping), (this.dirty = !1));
                },
                _removeCacheCanvas: function () {
                    (this._cacheCanvas = null), (this.cacheWidth = 0), (this.cacheHeight = 0);
                },
                hasStroke: function () {
                    return this.stroke && "transparent" !== this.stroke && 0 !== this.strokeWidth;
                },
                hasFill: function () {
                    return this.fill && "transparent" !== this.fill;
                },
                needsItsOwnCache: function () {
                    return !("stroke" !== this.paintFirst || !this.hasFill() || !this.hasStroke() || "object" != typeof this.shadow) || !!this.clipPath;
                },
                shouldCache: function () {
                    return (this.ownCaching = this.needsItsOwnCache() || (this.objectCaching && (!this.group || !this.group.isOnACache()))), this.ownCaching;
                },
                willDrawShadow: function () {
                    return !!this.shadow && (0 !== this.shadow.offsetX || 0 !== this.shadow.offsetY);
                },
                drawClipPathOnCache: function (e) {
                    var i,
                        o = this.clipPath;
                    e.save(),
                        o.inverted ? (e.globalCompositeOperation = "destination-out") : (e.globalCompositeOperation = "destination-in"),
                        o.absolutePositioned && ((i = t.util.invertTransform(this.calcTransformMatrix())), e.transform(i[0], i[1], i[2], i[3], i[4], i[5])),
                        o.transform(e),
                        e.scale(1 / o.zoomX, 1 / o.zoomY),
                        e.drawImage(o._cacheCanvas, -o.cacheTranslationX, -o.cacheTranslationY),
                        e.restore();
                },
                drawObject: function (e, t) {
                    var i = this.fill,
                        o = this.stroke;
                    t ? ((this.fill = "black"), (this.stroke = ""), this._setClippingProperties(e)) : this._renderBackground(e), this._render(e), this._drawClipPath(e), (this.fill = i), (this.stroke = o);
                },
                _drawClipPath: function (e) {
                    var t = this.clipPath;
                    t && ((t.canvas = this.canvas), t.shouldCache(), (t._transformDone = !0), t.renderCache({ forClipping: !0 }), this.drawClipPathOnCache(e));
                },
                drawCacheOnCanvas: function (e) {
                    e.scale(1 / this.zoomX, 1 / this.zoomY), e.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);
                },
                isCacheDirty: function (e) {
                    return !(
                        this.isNotVisible() ||
                        ((!this._cacheCanvas || e || !this._updateCacheCanvas()) &&
                            (!(this.dirty || (this.clipPath && this.clipPath.absolutePositioned) || (this.statefullCache && this.hasStateChanged("cacheProperties"))) ||
                                (this._cacheCanvas && !e && ((t = this.cacheWidth / this.zoomX), (e = this.cacheHeight / this.zoomY), this._cacheContext.clearRect(-t / 2, -e / 2, t, e)), 0)))
                    );
                    var t;
                },
                _renderBackground: function (e) {
                    var t;
                    this.backgroundColor && ((t = this._getNonTransformedDimensions()), (e.fillStyle = this.backgroundColor), e.fillRect(-t.x / 2, -t.y / 2, t.x, t.y), this._removeShadow(e));
                },
                _setOpacity: function (e) {
                    this.group && !this.group._transformDone ? (e.globalAlpha = this.getObjectOpacity()) : (e.globalAlpha *= this.opacity);
                },
                _setStrokeStyles: function (e, t) {
                    var i = t.stroke;
                    i &&
                        ((e.lineWidth = t.strokeWidth),
                        (e.lineCap = t.strokeLineCap),
                        (e.lineDashOffset = t.strokeDashOffset),
                        (e.lineJoin = t.strokeLineJoin),
                        (e.miterLimit = t.strokeMiterLimit),
                        i.toLive
                            ? "percentage" === i.gradientUnits || i.gradientTransform || i.patternTransform
                                ? this._applyPatternForTransformedGradient(e, i)
                                : ((e.strokeStyle = i.toLive(e, this)), this._applyPatternGradientTransform(e, i))
                            : (e.strokeStyle = t.stroke));
                },
                _setFillStyles: function (e, t) {
                    var i = t.fill;
                    i && (i.toLive ? ((e.fillStyle = i.toLive(e, this)), this._applyPatternGradientTransform(e, t.fill)) : (e.fillStyle = i));
                },
                _setClippingProperties: function (e) {
                    (e.globalAlpha = 1), (e.strokeStyle = "transparent"), (e.fillStyle = "#000000");
                },
                _setLineDash: function (e, t) {
                    t && 0 !== t.length && (1 & t.length && t.push.apply(t, t), e.setLineDash(t));
                },
                _renderControls: function (e, i) {
                    var o = this.getViewportTransform(),
                        n = this.calcTransformMatrix(),
                        r = (void 0 !== (i = i || {}).hasBorders ? i : this).hasBorders,
                        a = (void 0 !== i.hasControls ? i : this).hasControls;
                    (n = t.util.multiplyTransformMatrices(o, n)), (n = t.util.qrDecompose(n));
                    e.save(),
                        e.translate(n.translateX, n.translateY),
                        (e.lineWidth = +this.borderScaleFactor),
                        this.group || (e.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1),
                        e.rotate(s(n.angle)),
                        i.forActiveSelection || this.group ? r && this.drawBordersInGroup(e, n, i) : r && this.drawBorders(e, i),
                        a && this.drawControls(e, i),
                        e.restore();
                },
                _setShadow: function (e) {
                    var i, o, n, r, s;
                    this.shadow &&
                        ((i = this.shadow),
                        (n = ((o = this.canvas) && o.viewportTransform[0]) || 1),
                        (r = (o && o.viewportTransform[3]) || 1),
                        (s = i.nonScaling ? { scaleX: 1, scaleY: 1 } : this.getObjectScaling()),
                        o && o._isRetinaScaling() && ((n *= t.devicePixelRatio), (r *= t.devicePixelRatio)),
                        (e.shadowColor = i.color),
                        (e.shadowBlur = (i.blur * t.browserShadowBlurConstant * (n + r) * (s.scaleX + s.scaleY)) / 4),
                        (e.shadowOffsetX = i.offsetX * n * s.scaleX),
                        (e.shadowOffsetY = i.offsetY * r * s.scaleY));
                },
                _removeShadow: function (e) {
                    this.shadow && ((e.shadowColor = ""), (e.shadowBlur = e.shadowOffsetX = e.shadowOffsetY = 0));
                },
                _applyPatternGradientTransform: function (e, t) {
                    if (!t || !t.toLive) return { offsetX: 0, offsetY: 0 };
                    var i = t.gradientTransform || t.patternTransform,
                        o = -this.width / 2 + t.offsetX || 0,
                        n = -this.height / 2 + t.offsetY || 0;
                    return "percentage" === t.gradientUnits ? e.transform(this.width, 0, 0, this.height, o, n) : e.transform(1, 0, 0, 1, o, n), i && e.transform(i[0], i[1], i[2], i[3], i[4], i[5]), { offsetX: o, offsetY: n };
                },
                _renderPaintInOrder: function (e) {
                    "stroke" === this.paintFirst ? (this._renderStroke(e), this._renderFill(e)) : (this._renderFill(e), this._renderStroke(e));
                },
                _render: function () {},
                _renderFill: function (e) {
                    this.fill && (e.save(), this._setFillStyles(e, this), "evenodd" === this.fillRule ? e.fill("evenodd") : e.fill(), e.restore());
                },
                _renderStroke: function (e) {
                    var t;
                    this.stroke &&
                        0 !== this.strokeWidth &&
                        (this.shadow && !this.shadow.affectStroke && this._removeShadow(e),
                        e.save(),
                        this.strokeUniform && this.group ? ((t = this.getObjectScaling()), e.scale(1 / t.scaleX, 1 / t.scaleY)) : this.strokeUniform && e.scale(1 / this.scaleX, 1 / this.scaleY),
                        this._setLineDash(e, this.strokeDashArray),
                        this._setStrokeStyles(e, this),
                        e.stroke(),
                        e.restore());
                },
                _applyPatternForTransformedGradient: function (e, i) {
                    var o,
                        n = this._limitCacheSize(this._getCacheCanvasDimensions()),
                        r = t.util.createCanvasElement(),
                        s = this.canvas.getRetinaScaling(),
                        a = n.x / this.scaleX / s,
                        c = n.y / this.scaleY / s;
                    (r.width = a),
                        (r.height = c),
                        (o = r.getContext("2d")).beginPath(),
                        o.moveTo(0, 0),
                        o.lineTo(a, 0),
                        o.lineTo(a, c),
                        o.lineTo(0, c),
                        o.closePath(),
                        o.translate(a / 2, c / 2),
                        o.scale(n.zoomX / this.scaleX / s, n.zoomY / this.scaleY / s),
                        this._applyPatternGradientTransform(o, i),
                        (o.fillStyle = i.toLive(e)),
                        o.fill(),
                        e.translate(-this.width / 2 - this.strokeWidth / 2, -this.height / 2 - this.strokeWidth / 2),
                        e.scale((s * this.scaleX) / n.zoomX, (s * this.scaleY) / n.zoomY),
                        (e.strokeStyle = o.createPattern(r, "no-repeat"));
                },
                _findCenterFromElement: function () {
                    return { x: this.left + this.width / 2, y: this.top + this.height / 2 };
                },
                _assignTransformMatrixProps: function () {
                    var e;
                    this.transformMatrix &&
                        ((e = t.util.qrDecompose(this.transformMatrix)), (this.flipX = !1), (this.flipY = !1), this.set("scaleX", e.scaleX), this.set("scaleY", e.scaleY), (this.angle = e.angle), (this.skewX = e.skewX), (this.skewY = 0));
                },
                _removeTransformMatrix: function (e) {
                    var i = this._findCenterFromElement();
                    this.transformMatrix && (this._assignTransformMatrixProps(), (i = t.util.transformPoint(i, this.transformMatrix))),
                        (this.transformMatrix = null),
                        e && ((this.scaleX *= e.scaleX), (this.scaleY *= e.scaleY), (this.cropX = e.cropX), (this.cropY = e.cropY), (i.x += e.offsetLeft), (i.y += e.offsetTop), (this.width = e.width), (this.height = e.height)),
                        this.setPositionByOrigin(i, "center", "center");
                },
                clone: function (e, i) {
                    (i = this.toObject(i)), this.constructor.fromObject ? this.constructor.fromObject(i, e) : t.Object._fromObject("Object", i, e);
                },
                cloneAsImage: function (e, i) {
                    return (i = this.toCanvasElement(i)), e && e(new t.Image(i)), this;
                },
                toCanvasElement: function (e) {
                    e = e || {};
                    var i = t.util,
                        o = i.saveObjectTransform(this),
                        n = this.group,
                        r = this.shadow,
                        s = Math.abs,
                        a = (e.multiplier || 1) * (e.enableRetinaScaling ? t.devicePixelRatio : 1);
                    delete this.group, e.withoutTransform && i.resetObjectTransform(this), e.withoutShadow && (this.shadow = null);
                    var c,
                        l = t.util.createCanvasElement(),
                        d = this.getBoundingRect(!0, !0),
                        h = this.shadow,
                        u = { x: 0, y: 0 };
                    return (
                        h && ((i = h.blur), (c = h.nonScaling ? { scaleX: 1, scaleY: 1 } : this.getObjectScaling()), (u.x = 2 * Math.round(s(h.offsetX) + i) * s(c.scaleX)), (u.y = 2 * Math.round(s(h.offsetY) + i) * s(c.scaleY))),
                        (c = d.width + u.x),
                        (u = d.height + u.y),
                        (l.width = Math.ceil(c)),
                        (l.height = Math.ceil(u)),
                        (u = new t.StaticCanvas(l, { enableRetinaScaling: !1, renderOnAddRemove: !1, skipOffscreen: !1 })),
                        "jpeg" === e.format && (u.backgroundColor = "#fff"),
                        this.setPositionByOrigin(new t.Point(u.width / 2, u.height / 2), "center", "center"),
                        (l = this.canvas),
                        u.add(this),
                        (e = u.toCanvasElement(a || 1, e)),
                        (this.shadow = r),
                        this.set("canvas", l),
                        n && (this.group = n),
                        this.set(o).setCoords(),
                        (u._objects = []),
                        u.dispose(),
                        (u = null),
                        e
                    );
                },
                toDataURL: function (e) {
                    return t.util.toDataURL(this.toCanvasElement((e = e || {})), e.format || "png", e.quality || 1);
                },
                isType: function (e) {
                    return this.type === e;
                },
                complexity: function () {
                    return 1;
                },
                toJSON: function (e) {
                    return this.toObject(e);
                },
                rotate: function (e) {
                    var t = ("center" !== this.originX || "center" !== this.originY) && this.centeredRotation;
                    return t && this._setOriginToCenter(), this.set("angle", e), t && this._resetOrigin(), this;
                },
                centerH: function () {
                    return this.canvas && this.canvas.centerObjectH(this), this;
                },
                viewportCenterH: function () {
                    return this.canvas && this.canvas.viewportCenterObjectH(this), this;
                },
                centerV: function () {
                    return this.canvas && this.canvas.centerObjectV(this), this;
                },
                viewportCenterV: function () {
                    return this.canvas && this.canvas.viewportCenterObjectV(this), this;
                },
                center: function () {
                    return this.canvas && this.canvas.centerObject(this), this;
                },
                viewportCenter: function () {
                    return this.canvas && this.canvas.viewportCenterObject(this), this;
                },
                getLocalPointer: function (e, i) {
                    return (i = i || this.canvas.getPointer(e)), (e = new t.Point(i.x, i.y)), (i = this._getLeftTopCoords()), { x: (e = this.angle ? t.util.rotatePoint(e, i, s(-this.angle)) : e).x - i.x, y: e.y - i.y };
                },
                _setupCompositeOperation: function (e) {
                    this.globalCompositeOperation && (e.globalCompositeOperation = this.globalCompositeOperation);
                },
            })),
            t.util.createAccessors && t.util.createAccessors(t.Object),
            i(t.Object.prototype, t.Observable),
            (t.Object.NUM_FRACTION_DIGITS = 2),
            (t.Object._fromObject = function (e, i, n, r) {
                var s = t[e];
                (i = o(i, !0)),
                    t.util.enlivenPatterns([i.fill, i.stroke], function (e) {
                        void 0 !== e[0] && (i.fill = e[0]),
                            void 0 !== e[1] && (i.stroke = e[1]),
                            t.util.enlivenObjects([i.clipPath], function (e) {
                                (i.clipPath = e[0]), (e = r ? new s(i[r], i) : new s(i)), n && n(e);
                            });
                    });
            }),
            (t.Object.__uid = 0));
    })("undefined" != typeof exports ? exports : this),
    (function () {
        var e = fabric.util.degreesToRadians,
            t = { left: -0.5, center: 0, right: 0.5 },
            i = { top: -0.5, center: 0, bottom: 0.5 };
        fabric.util.object.extend(fabric.Object.prototype, {
            translateToGivenOrigin: function (e, o, n, r, s) {
                var a = e.x,
                    c = e.y;
                return (
                    "string" == typeof o ? (o = t[o]) : (o -= 0.5),
                    "string" == typeof r ? (r = t[r]) : (r -= 0.5),
                    "string" == typeof n ? (n = i[n]) : (n -= 0.5),
                    "string" == typeof s ? (s = i[s]) : (s -= 0.5),
                    (n = s - n),
                    ((r -= o) || n) && ((o = this._getTransformedDimensions()), (a = e.x + r * o.x), (c = e.y + n * o.y)),
                    new fabric.Point(a, c)
                );
            },
            translateToCenterPoint: function (t, i, o) {
                return (o = this.translateToGivenOrigin(t, i, o, "center", "center")), this.angle ? fabric.util.rotatePoint(o, t, e(this.angle)) : o;
            },
            translateToOriginPoint: function (t, i, o) {
                return (o = this.translateToGivenOrigin(t, "center", "center", i, o)), this.angle ? fabric.util.rotatePoint(o, t, e(this.angle)) : o;
            },
            getCenterPoint: function () {
                var e = new fabric.Point(this.left, this.top);
                return this.translateToCenterPoint(e, this.originX, this.originY);
            },
            getPointByOrigin: function (e, t) {
                var i = this.getCenterPoint();
                return this.translateToOriginPoint(i, e, t);
            },
            toLocalPoint: function (t, i, o) {
                var n = this.getCenterPoint();
                (o = void 0 !== i && void 0 !== o ? this.translateToGivenOrigin(n, "center", "center", i, o) : new fabric.Point(this.left, this.top)), (t = new fabric.Point(t.x, t.y));
                return (t = this.angle ? fabric.util.rotatePoint(t, n, -e(this.angle)) : t).subtractEquals(o);
            },
            setPositionByOrigin: function (e, t, i) {
                (i = this.translateToCenterPoint(e, t, i)), (i = this.translateToOriginPoint(i, this.originX, this.originY)), this.set("left", i.x), this.set("top", i.y);
            },
            adjustPosition: function (i) {
                var o = e(this.angle),
                    n = this.getScaledWidth(),
                    r = fabric.util.cos(o) * n,
                    s = fabric.util.sin(o) * n;
                (o = "string" == typeof this.originX ? t[this.originX] : this.originX - 0.5), (n = "string" == typeof i ? t[i] : i - 0.5);
                (this.left += r * (n - o)), (this.top += s * (n - o)), this.setCoords(), (this.originX = i);
            },
            _setOriginToCenter: function () {
                (this._originalOriginX = this.originX), (this._originalOriginY = this.originY);
                var e = this.getCenterPoint();
                (this.originX = "center"), (this.originY = "center"), (this.left = e.x), (this.top = e.y);
            },
            _resetOrigin: function () {
                var e = this.translateToOriginPoint(this.getCenterPoint(), this._originalOriginX, this._originalOriginY);
                (this.originX = this._originalOriginX), (this.originY = this._originalOriginY), (this.left = e.x), (this.top = e.y), (this._originalOriginX = null), (this._originalOriginY = null);
            },
            _getLeftTopCoords: function () {
                return this.translateToOriginPoint(this.getCenterPoint(), "left", "top");
            },
        });
    })(),
    (function () {
        var e = fabric.util,
            t = e.degreesToRadians,
            i = e.multiplyTransformMatrices,
            o = e.transformPoint;
        e.object.extend(fabric.Object.prototype, {
            oCoords: null,
            aCoords: null,
            lineCoords: null,
            ownMatrixCache: null,
            matrixCache: null,
            controls: {},
            _getCoords: function (e, t) {
                return t ? (e ? this.calcACoords() : this.calcLineCoords()) : ((this.aCoords && this.lineCoords) || this.setCoords(!0), e ? this.aCoords : this.lineCoords);
            },
            getCoords: function (e, t) {
                return (t = this._getCoords(e, t)), [new fabric.Point(t.tl.x, t.tl.y), new fabric.Point(t.tr.x, t.tr.y), new fabric.Point(t.br.x, t.br.y), new fabric.Point(t.bl.x, t.bl.y)];
            },
            intersectsWithRect: function (e, t, i, o) {
                return (o = this.getCoords(i, o)), "Intersection" === fabric.Intersection.intersectPolygonRectangle(o, e, t).status;
            },
            intersectsWithObject: function (e, t, i) {
                return "Intersection" === fabric.Intersection.intersectPolygonPolygon(this.getCoords(t, i), e.getCoords(t, i)).status || e.isContainedWithinObject(this, t, i) || this.isContainedWithinObject(e, t, i);
            },
            isContainedWithinObject: function (e, t, i) {
                for (var o = this.getCoords(t, i), n = ((t = t ? e.aCoords : e.lineCoords), 0), r = e._getImageLines(t); n < 4; n++) if (!e.containsPoint(o[n], r)) return !1;
                return !0;
            },
            isContainedWithinRect: function (e, t, i, o) {
                return (o = this.getBoundingRect(i, o)).left >= e.x && o.left + o.width <= t.x && o.top >= e.y && o.top + o.height <= t.y;
            },
            containsPoint: function (e, t, i, o) {
                return (o = this._getCoords(i, o)), (t = t || this._getImageLines(o)), 0 !== (t = this._findCrossPoints(e, t)) && t % 2 == 1;
            },
            isOnScreen: function (e) {
                if (!this.canvas) return !1;
                var t = this.canvas.vptCoords.tl,
                    i = this.canvas.vptCoords.br;
                return (
                    !!this.getCoords(!0, e).some(function (e) {
                        return e.x <= i.x && e.x >= t.x && e.y <= i.y && e.y >= t.y;
                    }) ||
                    !!this.intersectsWithRect(t, i, !0, e) ||
                    this._containsCenterOfCanvas(t, i, e)
                );
            },
            _containsCenterOfCanvas: function (e, t, i) {
                return (t = { x: (e.x + t.x) / 2, y: (e.y + t.y) / 2 }), !!this.containsPoint(t, null, !0, i);
            },
            isPartiallyOnScreen: function (e) {
                if (!this.canvas) return !1;
                var t = this.canvas.vptCoords.tl,
                    i = this.canvas.vptCoords.br;
                return (
                    !!this.intersectsWithRect(t, i, !0, e) ||
                    (this.getCoords(!0, e).every(function (e) {
                        return (e.x >= i.x || e.x <= t.x) && (e.y >= i.y || e.y <= t.y);
                    }) &&
                        this._containsCenterOfCanvas(t, i, e))
                );
            },
            _getImageLines: function (e) {
                return { topline: { o: e.tl, d: e.tr }, rightline: { o: e.tr, d: e.br }, bottomline: { o: e.br, d: e.bl }, leftline: { o: e.bl, d: e.tl } };
            },
            _findCrossPoints: function (e, t) {
                var i,
                    o,
                    n,
                    r = 0;
                for (n in t)
                    if (
                        !(
                            ((o = t[n]).o.y < e.y && o.d.y < e.y) ||
                            (o.o.y >= e.y && o.d.y >= e.y) ||
                            ((o.o.x === o.d.x && o.o.x >= e.x ? o.o.x : ((i = (o.d.y - o.o.y) / (o.d.x - o.o.x)), -(e.y - 0 * e.x - (o.o.y - i * o.o.x)) / (0 - i))) >= e.x && (r += 1), 2 !== r)
                        )
                    )
                        break;
                return r;
            },
            getBoundingRect: function (t, i) {
                return (i = this.getCoords(t, i)), e.makeBoundingBoxFromPoints(i);
            },
            getScaledWidth: function () {
                return this._getTransformedDimensions().x;
            },
            getScaledHeight: function () {
                return this._getTransformedDimensions().y;
            },
            _constrainScale: function (e) {
                return Math.abs(e) < this.minScaleLimit ? (e < 0 ? -this.minScaleLimit : this.minScaleLimit) : 0 === e ? 1e-4 : e;
            },
            scale: function (e) {
                return this._set("scaleX", e), this._set("scaleY", e), this.setCoords();
            },
            scaleToWidth: function (e, t) {
                return (t = this.getBoundingRect(t).width / this.getScaledWidth()), this.scale(e / this.width / t);
            },
            scaleToHeight: function (e, t) {
                return (t = this.getBoundingRect(t).height / this.getScaledHeight()), this.scale(e / this.height / t);
            },
            calcCoords: function (e) {
                return e ? this.calcACoords() : this.calcOCoords();
            },
            calcLineCoords: function () {
                var i = this.getViewportTransform(),
                    n = this.padding,
                    r = t(this.angle),
                    s = ((r = (s = e.cos(r) * n) + (a = e.sin(r) * n)), s - a),
                    a = this.calcACoords();
                i = { tl: o(a.tl, i), tr: o(a.tr, i), bl: o(a.bl, i), br: o(a.br, i) };
                return n && ((i.tl.x -= s), (i.tl.y -= r), (i.tr.x += r), (i.tr.y -= s), (i.bl.x -= r), (i.bl.y += s), (i.br.x += s), (i.br.y += r)), i;
            },
            calcOCoords: function () {
                var e = this._calcRotateMatrix(),
                    t = this._calcTranslateMatrix(),
                    o = this.getViewportTransform(),
                    n = ((t = i(o, t)), i(t, e)),
                    r = ((n = i(n, [1 / o[0], 0, 0, 1 / o[3], 0, 0])), this._calculateCurrentDimensions()),
                    s = {};
                return (
                    this.forEachControl(function (e, t, i) {
                        s[t] = e.positionHandler(r, n, i);
                    }),
                    s
                );
            },
            calcACoords: function () {
                var e = this._calcRotateMatrix(),
                    t = this._calcTranslateMatrix(),
                    n = i(t, e);
                (e = (t = this._getTransformedDimensions()).x / 2), (t = t.y / 2);
                return { tl: o({ x: -e, y: -t }, n), tr: o({ x: e, y: -t }, n), bl: o({ x: -e, y: t }, n), br: o({ x: e, y: t }, n) };
            },
            setCoords: function (e) {
                return (this.aCoords = this.calcACoords()), (this.lineCoords = this.group ? this.aCoords : this.calcLineCoords()), e || ((this.oCoords = this.calcOCoords()), this._setCornerCoords && this._setCornerCoords()), this;
            },
            _calcRotateMatrix: function () {
                return e.calcRotateMatrix(this);
            },
            _calcTranslateMatrix: function () {
                var e = this.getCenterPoint();
                return [1, 0, 0, 1, e.x, e.y];
            },
            transformMatrixKey: function (e) {
                var t = "_",
                    i = "";
                return (
                    (i = !e && this.group ? this.group.transformMatrixKey(e) + t : i) +
                    this.top +
                    t +
                    this.left +
                    t +
                    this.scaleX +
                    t +
                    this.scaleY +
                    t +
                    this.skewX +
                    t +
                    this.skewY +
                    t +
                    this.angle +
                    t +
                    this.originX +
                    t +
                    this.originY +
                    t +
                    this.width +
                    t +
                    this.height +
                    t +
                    this.strokeWidth +
                    this.flipX +
                    this.flipY
                );
            },
            calcTransformMatrix: function (e) {
                var t = this.calcOwnMatrix();
                if (e || !this.group) return t;
                var o = this.transformMatrixKey(e);
                return (e = this.matrixCache || (this.matrixCache = {})).key === o ? e.value : (this.group && (t = i(this.group.calcTransformMatrix(!1), t)), (e.key = o), (e.value = t));
            },
            calcOwnMatrix: function () {
                var t = this.transformMatrixKey(!0),
                    i = this.ownMatrixCache || (this.ownMatrixCache = {});
                if (i.key === t) return i.value;
                var o = this._calcTranslateMatrix();
                o = { angle: this.angle, translateX: o[4], translateY: o[5], scaleX: this.scaleX, scaleY: this.scaleY, skewX: this.skewX, skewY: this.skewY, flipX: this.flipX, flipY: this.flipY };
                return (i.key = t), (i.value = e.composeMatrix(o)), i.value;
            },
            _calcDimensionsTransformMatrix: function (t, i, o) {
                return e.calcDimensionsMatrix({ skewX: t, skewY: i, scaleX: this.scaleX * (o && this.flipX ? -1 : 1), scaleY: this.scaleY * (o && this.flipY ? -1 : 1) });
            },
            _getNonTransformedDimensions: function () {
                var e = this.strokeWidth;
                return { x: this.width + e, y: this.height + e };
            },
            _getTransformedDimensions: function (t, i) {
                void 0 === t && (t = this.skewX), void 0 === i && (i = this.skewY);
                var o,
                    n = 0 === t && 0 === i,
                    r = this.strokeUniform ? ((o = this.width), this.height) : ((o = (r = this._getNonTransformedDimensions()).x), r.y);
                return n ? this._finalizeDimensions(o * this.scaleX, r * this.scaleY) : ((i = e.sizeAfterTransform(o, r, { scaleX: this.scaleX, scaleY: this.scaleY, skewX: t, skewY: i })), this._finalizeDimensions(i.x, i.y));
            },
            _finalizeDimensions: function (e, t) {
                return this.strokeUniform ? { x: e + this.strokeWidth, y: t + this.strokeWidth } : { x: e, y: t };
            },
            _calculateCurrentDimensions: function () {
                var e = this.getViewportTransform(),
                    t = this._getTransformedDimensions();
                return o(t, e, !0).scalarAdd(2 * this.padding);
            },
        });
    })(),
    fabric.util.object.extend(fabric.Object.prototype, {
        sendToBack: function () {
            return this.group ? fabric.StaticCanvas.prototype.sendToBack.call(this.group, this) : this.canvas && this.canvas.sendToBack(this), this;
        },
        bringToFront: function () {
            return this.group ? fabric.StaticCanvas.prototype.bringToFront.call(this.group, this) : this.canvas && this.canvas.bringToFront(this), this;
        },
        sendBackwards: function (e) {
            return this.group ? fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, e) : this.canvas && this.canvas.sendBackwards(this, e), this;
        },
        bringForward: function (e) {
            return this.group ? fabric.StaticCanvas.prototype.bringForward.call(this.group, this, e) : this.canvas && this.canvas.bringForward(this, e), this;
        },
        moveTo: function (e) {
            return this.group && "activeSelection" !== this.group.type ? fabric.StaticCanvas.prototype.moveTo.call(this.group, this, e) : this.canvas && this.canvas.moveTo(this, e), this;
        },
    }),
    (function () {
        function e(e, t) {
            if (t) {
                if (t.toLive) return e + ": url(#SVGID_" + t.id + "); ";
                var i;
                t = e + ": " + (i = new fabric.Color(t)).toRgb() + "; ";
                return 1 !== (i = i.getAlpha()) && (t += e + "-opacity: " + i.toString() + "; "), t;
            }
            return e + ": none; ";
        }
        var t = fabric.util.toFixed;
        fabric.util.object.extend(fabric.Object.prototype, {
            getSvgStyles: function (t) {
                var i = this.fillRule || "nonzero",
                    o = this.strokeWidth || "0",
                    n = this.strokeDashArray ? this.strokeDashArray.join(" ") : "none",
                    r = this.strokeDashOffset || "0",
                    s = this.strokeLineCap || "butt",
                    a = this.strokeLineJoin || "miter",
                    c = this.strokeMiterLimit || "4",
                    l = void 0 !== this.opacity ? this.opacity : "1",
                    d = this.visible ? "" : " visibility: hidden;",
                    h = t ? "" : this.getSvgFilter();
                t = e("fill", this.fill);
                return [
                    e("stroke", this.stroke),
                    "stroke-width: ",
                    o,
                    "; ",
                    "stroke-dasharray: ",
                    n,
                    "; ",
                    "stroke-linecap: ",
                    s,
                    "; ",
                    "stroke-dashoffset: ",
                    r,
                    "; ",
                    "stroke-linejoin: ",
                    a,
                    "; ",
                    "stroke-miterlimit: ",
                    c,
                    "; ",
                    t,
                    "fill-rule: ",
                    i,
                    "; ",
                    "opacity: ",
                    l,
                    ";",
                    h,
                    d,
                ].join("");
            },
            getSvgSpanStyles: function (t, i) {
                var o = "; ",
                    n = t.fontFamily ? "font-family: " + (-1 === t.fontFamily.indexOf("'") && -1 === t.fontFamily.indexOf('"') ? "'" + t.fontFamily + "'" : t.fontFamily) + o : "",
                    r = t.strokeWidth ? "stroke-width: " + t.strokeWidth + o : "",
                    s = ((n = n), t.fontSize ? "font-size: " + t.fontSize + "px" + o : ""),
                    a = t.fontStyle ? "font-style: " + t.fontStyle + o : "",
                    c = t.fontWeight ? "font-weight: " + t.fontWeight + o : "",
                    l = t.fill ? e("fill", t.fill) : "",
                    d = t.stroke ? e("stroke", t.stroke) : "",
                    h = this.getSvgTextDecoration(t);
                return [d, r, n, s, a, c, (h = h && "text-decoration: " + h + o), l, t.deltaY ? "baseline-shift: " + -t.deltaY + "; " : "", i ? "white-space: pre; " : ""].join("");
            },
            getSvgTextDecoration: function (e) {
                return ["overline", "underline", "line-through"]
                    .filter(function (t) {
                        return e[t.replace("-", "")];
                    })
                    .join(" ");
            },
            getSvgFilter: function () {
                return this.shadow ? "filter: url(#SVGID_" + this.shadow.id + ");" : "";
            },
            getSvgCommons: function () {
                return [this.id ? 'id="' + this.id + '" ' : "", this.clipPath ? 'clip-path="url(#' + this.clipPath.clipPathId + ')" ' : ""].join("");
            },
            getSvgTransform: function (e, t) {
                return (e = e ? this.calcTransformMatrix() : this.calcOwnMatrix()), 'transform="' + fabric.util.matrixToSVG(e) + (t || "") + '" ';
            },
            _setSVGBg: function (e) {
                var i;
                this.backgroundColor &&
                    ((i = fabric.Object.NUM_FRACTION_DIGITS),
                    e.push("\t\t<rect ", this._getFillAttributes(this.backgroundColor), ' x="', t(-this.width / 2, i), '" y="', t(-this.height / 2, i), '" width="', t(this.width, i), '" height="', t(this.height, i), '"></rect>\n'));
            },
            toSVG: function (e) {
                return this._createBaseSVGMarkup(this._toSVG(e), { reviver: e });
            },
            toClipPathSVG: function (e) {
                return "\t" + this._createBaseClipPathSVGMarkup(this._toSVG(e), { reviver: e });
            },
            _createBaseClipPathSVGMarkup: function (e, t) {
                var i = (t = t || {}).reviver,
                    o = t.additionalTransform || "";
                (t = [this.getSvgTransform(!0, o), this.getSvgCommons()].join("")), (o = e.indexOf("COMMON_PARTS"));
                return (e[o] = t), i ? i(e.join("")) : e.join("");
            },
            _createBaseSVGMarkup: function (e, t) {
                var i,
                    o = (t = t || {}).noStyle,
                    n = t.reviver,
                    r = o ? "" : 'style="' + this.getSvgStyles() + '" ',
                    s = t.withShadow ? 'style="' + this.getSvgFilter() + '" ' : "",
                    a = this.clipPath,
                    c = this.strokeUniform ? 'vector-effect="non-scaling-stroke" ' : "",
                    l = a && a.absolutePositioned,
                    d = this.stroke,
                    h = this.fill,
                    u = this.shadow,
                    f = [],
                    m = e.indexOf("COMMON_PARTS");
                t = t.additionalTransform;
                return (
                    a && ((a.clipPathId = "CLIPPATH_" + fabric.Object.__uid++), (i = '<clipPath id="' + a.clipPathId + '" >\n' + a.toClipPathSVG(n) + "</clipPath>\n")),
                    l && f.push("<g ", s, this.getSvgCommons(), " >\n"),
                    f.push("<g ", this.getSvgTransform(!1), l ? "" : s + this.getSvgCommons(), " >\n"),
                    (t = [r, c, o ? "" : this.addPaintOrder(), " ", t ? 'transform="' + t + '" ' : ""].join("")),
                    (e[m] = t),
                    h && h.toLive && f.push(h.toSVG(this)),
                    d && d.toLive && f.push(d.toSVG(this)),
                    u && f.push(u.toSVG(this)),
                    a && f.push(i),
                    f.push(e.join("")),
                    f.push("</g>\n"),
                    l && f.push("</g>\n"),
                    n ? n(f.join("")) : f.join("")
                );
            },
            addPaintOrder: function () {
                return "fill" !== this.paintFirst ? ' paint-order="' + this.paintFirst + '" ' : "";
            },
        });
    })(),
    (function () {
        var e = fabric.util.object.extend,
            t = "stateProperties";
        function i(t, i, o) {
            var n = {};
            o.forEach(function (e) {
                n[e] = t[e];
            }),
                e(t[i], n, !0);
        }
        fabric.util.object.extend(fabric.Object.prototype, {
            hasStateChanged: function (e) {
                var i = "_" + (e = e || t);
                return (
                    Object.keys(this[i]).length < this[e].length ||
                    !(function e(t, i, o) {
                        if (t === i) return 1;
                        if (Array.isArray(t)) {
                            if (Array.isArray(i) && t.length === i.length) {
                                for (var n = 0, r = t.length; n < r; n++) if (!e(t[n], i[n])) return;
                                return 1;
                            }
                        } else if (t && "object" == typeof t) {
                            var s,
                                a = Object.keys(t);
                            if (i && "object" == typeof i && (o || a.length === Object.keys(i).length)) {
                                for (n = 0, r = a.length; n < r; n++) if ("canvas" !== (s = a[n]) && "group" !== s && !e(t[s], i[s])) return;
                                return 1;
                            }
                        }
                    })(this[i], this, !0)
                );
            },
            saveState: function (e) {
                var o = (e && e.propertySet) || t,
                    n = "_" + o;
                return this[n] ? (i(this, n, this[o]), e && e.stateProperties && i(this, n, e.stateProperties), this) : this.setupState(e);
            },
            setupState: function (e) {
                var i = (e = e || {}).propertySet || t;
                return (this["_" + (e.propertySet = i)] = {}), this.saveState(e), this;
            },
        });
    })(),
    (function () {
        var e = fabric.util.degreesToRadians;
        fabric.util.object.extend(fabric.Object.prototype, {
            _findTargetCorner: function (e, t) {
                if (!this.hasControls || this.group || !this.canvas || this.canvas._activeObject !== this) return !1;
                var i,
                    o,
                    n = e.x,
                    r = e.y,
                    s = Object.keys(this.oCoords),
                    a = s.length - 1;
                for (this.__corner = 0; 0 <= a; a--)
                    if (((o = s[a]), this.isControlVisible(o) && ((i = this._getImageLines(t ? this.oCoords[o].touchCorner : this.oCoords[o].corner)), 0 !== (i = this._findCrossPoints({ x: n, y: r }, i)) && i % 2 == 1)))
                        return (this.__corner = o);
                return !1;
            },
            forEachControl: function (e) {
                for (var t in this.controls) e(this.controls[t], t, this);
            },
            _setCornerCoords: function () {
                var e,
                    t = this.oCoords;
                for (e in t) {
                    var i = this.controls[e];
                    (t[e].corner = i.calcCornerCoords(this.angle, this.cornerSize, t[e].x, t[e].y, !1)), (t[e].touchCorner = i.calcCornerCoords(this.angle, this.touchCornerSize, t[e].x, t[e].y, !0));
                }
            },
            drawSelectionBackground: function (t) {
                if (!this.selectionBackgroundColor || (this.canvas && !this.canvas.interactive) || (this.canvas && this.canvas._activeObject !== this)) return this;
                t.save();
                var i = this.getCenterPoint(),
                    o = this._calculateCurrentDimensions(),
                    n = this.canvas.viewportTransform;
                return t.translate(i.x, i.y), t.scale(1 / n[0], 1 / n[3]), t.rotate(e(this.angle)), (t.fillStyle = this.selectionBackgroundColor), t.fillRect(-o.x / 2, -o.y / 2, o.x, o.y), t.restore(), this;
            },
            drawBorders: function (e, t) {
                t = t || {};
                var i = this._calculateCurrentDimensions(),
                    o = this.borderScaleFactor,
                    n = i.x + o,
                    r = i.y + o,
                    s = ((o = (void 0 !== t.hasControls ? t : this).hasControls), !1);
                return (
                    e.save(),
                    (e.strokeStyle = t.borderColor || this.borderColor),
                    this._setLineDash(e, t.borderDashArray || this.borderDashArray),
                    e.strokeRect(-n / 2, -r / 2, n, r),
                    o &&
                        (e.beginPath(),
                        this.forEachControl(function (t, i, o) {
                            t.withConnection && t.getVisibility(o, i) && ((s = !0), e.moveTo(t.x * n, t.y * r), e.lineTo(t.x * n + t.offsetX, t.y * r + t.offsetY));
                        }),
                        s && e.stroke()),
                    e.restore(),
                    this
                );
            },
            drawBordersInGroup: function (e, t, i) {
                i = i || {};
                var o = fabric.util.sizeAfterTransform(this.width, this.height, t),
                    n = this.strokeWidth,
                    r = this.strokeUniform,
                    s = this.borderScaleFactor,
                    a = o.x + n * (r ? this.canvas.getZoom() : t.scaleX) + s;
                s = o.y + n * (r ? this.canvas.getZoom() : t.scaleY) + s;
                return e.save(), this._setLineDash(e, i.borderDashArray || this.borderDashArray), (e.strokeStyle = i.borderColor || this.borderColor), e.strokeRect(-a / 2, -s / 2, a, s), e.restore(), this;
            },
            drawControls: function (e, t) {
                (t = t || {}), e.save();
                var i,
                    o,
                    n = this.canvas.getRetinaScaling();
                return (
                    e.setTransform(n, 0, 0, n, 0, 0),
                    (e.strokeStyle = e.fillStyle = t.cornerColor || this.cornerColor),
                    this.transparentCorners || (e.strokeStyle = t.cornerStrokeColor || this.cornerStrokeColor),
                    this._setLineDash(e, t.cornerDashArray || this.cornerDashArray),
                    this.setCoords(),
                    this.group && (i = this.group.calcTransformMatrix()),
                    this.forEachControl(function (n, r, s) {
                        (o = s.oCoords[r]), n.getVisibility(s, r) && (i && (o = fabric.util.transformPoint(o, i)), n.render(e, o.x, o.y, t, s));
                    }),
                    e.restore(),
                    this
                );
            },
            isControlVisible: function (e) {
                return this.controls[e] && this.controls[e].getVisibility(this, e);
            },
            setControlVisible: function (e, t) {
                return this._controlsVisibility || (this._controlsVisibility = {}), (this._controlsVisibility[e] = t), this;
            },
            setControlsVisibility: function (e) {
                for (var t in (e = e || {})) this.setControlVisible(t, e[t]);
                return this;
            },
            onDeselect: function () {},
            onSelect: function () {},
        });
    })(),
    fabric.util.object.extend(fabric.StaticCanvas.prototype, {
        FX_DURATION: 500,
        fxCenterObjectH: function (e, t) {
            function i() {}
            var o = (t = t || {}).onComplete || i,
                n = t.onChange || i,
                r = this;
            return (
                fabric.util.animate({
                    startValue: e.left,
                    endValue: this.getCenter().left,
                    duration: this.FX_DURATION,
                    onChange: function (t) {
                        e.set("left", t), r.requestRenderAll(), n();
                    },
                    onComplete: function () {
                        e.setCoords(), o();
                    },
                }),
                this
            );
        },
        fxCenterObjectV: function (e, t) {
            function i() {}
            var o = (t = t || {}).onComplete || i,
                n = t.onChange || i,
                r = this;
            return (
                fabric.util.animate({
                    startValue: e.top,
                    endValue: this.getCenter().top,
                    duration: this.FX_DURATION,
                    onChange: function (t) {
                        e.set("top", t), r.requestRenderAll(), n();
                    },
                    onComplete: function () {
                        e.setCoords(), o();
                    },
                }),
                this
            );
        },
        fxRemove: function (e, t) {
            function i() {}
            var o = (t = t || {}).onComplete || i,
                n = t.onChange || i,
                r = this;
            return (
                fabric.util.animate({
                    startValue: e.opacity,
                    endValue: 0,
                    duration: this.FX_DURATION,
                    onChange: function (t) {
                        e.set("opacity", t), r.requestRenderAll(), n();
                    },
                    onComplete: function () {
                        r.remove(e), o();
                    },
                }),
                this
            );
        },
    }),
    fabric.util.object.extend(fabric.Object.prototype, {
        animate: function () {
            if (arguments[0] && "object" == typeof arguments[0]) {
                var e,
                    t,
                    i = [];
                for (e in arguments[0]) i.push(e);
                for (var o = 0, n = i.length; o < n; o++) (e = i[o]), (t = o !== n - 1), this._animate(e, arguments[0][e], arguments[1], t);
            } else this._animate.apply(this, arguments);
            return this;
        },
        _animate: function (e, t, i, o) {
            var n,
                r = this;
            (t = t.toString()), (i = i ? fabric.util.object.clone(i) : {}), ~e.indexOf(".") && (n = e.split("."));
            var s = -1 < r.colorProperties.indexOf(e) || (n && -1 < r.colorProperties.indexOf(n[1])),
                a = n ? this.get(n[0])[n[1]] : this.get(e);
            return (
                "from" in i || (i.from = a),
                s || (t = ~t.indexOf("=") ? a + parseFloat(t.replace("=", "")) : parseFloat(t)),
                (t = {
                    startValue: i.from,
                    endValue: t,
                    byValue: i.by,
                    easing: i.easing,
                    duration: i.duration,
                    abort:
                        i.abort &&
                        function (e, t, o) {
                            return i.abort.call(r, e, t, o);
                        },
                    onChange: function (t, s, a) {
                        n ? (r[n[0]][n[1]] = t) : r.set(e, t), o || (i.onChange && i.onChange(t, s, a));
                    },
                    onComplete: function (e, t, n) {
                        o || (r.setCoords(), i.onComplete && i.onComplete(e, t, n));
                    },
                }),
                s ? fabric.util.animateColor(t.startValue, t.endValue, t.duration, t) : fabric.util.animate(t)
            );
        },
    }),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.util.object.clone,
            n = { x1: 1, x2: 1, y1: 1, y2: 1 };
        function r(e, t) {
            var i = e.origin,
                o = e.axis1,
                n = e.axis2,
                r = e.dimension,
                s = t.nearest,
                a = t.center,
                c = t.farthest;
            return function () {
                switch (this.get(i)) {
                    case s:
                        return Math.min(this.get(o), this.get(n));
                    case a:
                        return Math.min(this.get(o), this.get(n)) + 0.5 * this.get(r);
                    case c:
                        return Math.max(this.get(o), this.get(n));
                }
            };
        }
        t.Line
            ? t.warn("fabric.Line is already defined")
            : ((t.Line = t.util.createClass(t.Object, {
                  type: "line",
                  x1: 0,
                  y1: 0,
                  x2: 0,
                  y2: 0,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("x1", "x2", "y1", "y2"),
                  initialize: function (e, t) {
                      (e = e || [0, 0, 0, 0]), this.callSuper("initialize", t), this.set("x1", e[0]), this.set("y1", e[1]), this.set("x2", e[2]), this.set("y2", e[3]), this._setWidthHeight(t);
                  },
                  _setWidthHeight: function (e) {
                      (e = e || {}),
                          (this.width = Math.abs(this.x2 - this.x1)),
                          (this.height = Math.abs(this.y2 - this.y1)),
                          (this.left = "left" in e ? e.left : this._getLeftToOriginX()),
                          (this.top = "top" in e ? e.top : this._getTopToOriginY());
                  },
                  _set: function (e, t) {
                      return this.callSuper("_set", e, t), void 0 !== n[e] && this._setWidthHeight(), this;
                  },
                  _getLeftToOriginX: r({ origin: "originX", axis1: "x1", axis2: "x2", dimension: "width" }, { nearest: "left", center: "center", farthest: "right" }),
                  _getTopToOriginY: r({ origin: "originY", axis1: "y1", axis2: "y2", dimension: "height" }, { nearest: "top", center: "center", farthest: "bottom" }),
                  _render: function (e) {
                      e.beginPath();
                      var t = this.calcLinePoints();
                      e.moveTo(t.x1, t.y1), e.lineTo(t.x2, t.y2), (e.lineWidth = this.strokeWidth), (t = e.strokeStyle), (e.strokeStyle = this.stroke || e.fillStyle), this.stroke && this._renderStroke(e), (e.strokeStyle = t);
                  },
                  _findCenterFromElement: function () {
                      return { x: (this.x1 + this.x2) / 2, y: (this.y1 + this.y2) / 2 };
                  },
                  toObject: function (e) {
                      return i(this.callSuper("toObject", e), this.calcLinePoints());
                  },
                  _getNonTransformedDimensions: function () {
                      var e = this.callSuper("_getNonTransformedDimensions");
                      return "butt" === this.strokeLineCap && (0 === this.width && (e.y -= this.strokeWidth), 0 === this.height && (e.x -= this.strokeWidth)), e;
                  },
                  calcLinePoints: function () {
                      var e = this.x1 <= this.x2 ? -1 : 1,
                          t = this.y1 <= this.y2 ? -1 : 1,
                          i = e * this.width * 0.5,
                          o = t * this.height * 0.5;
                      return { x1: i, x2: e * this.width * -0.5, y1: o, y2: t * this.height * -0.5 };
                  },
                  _toSVG: function () {
                      var e = this.calcLinePoints();
                      return ["<line ", "COMMON_PARTS", 'x1="', e.x1, '" y1="', e.y1, '" x2="', e.x2, '" y2="', e.y2, '" />\n'];
                  },
              })),
              (t.Line.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" "))),
              (t.Line.fromElement = function (e, o, n) {
                  n = n || {};
                  var r = t.parseAttributes(e, t.Line.ATTRIBUTE_NAMES);
                  e = [r.x1 || 0, r.y1 || 0, r.x2 || 0, r.y2 || 0];
                  o(new t.Line(e, i(r, n)));
              }),
              (t.Line.fromObject = function (e, i) {
                  var n = o(e, !0);
                  (n.points = [e.x1, e.y1, e.x2, e.y2]),
                      t.Object._fromObject(
                          "Line",
                          n,
                          function (e) {
                              delete e.points, i && i(e);
                          },
                          "points"
                      );
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = Math.PI;
        t.Circle
            ? t.warn("fabric.Circle is already defined.")
            : ((t.Circle = t.util.createClass(t.Object, {
                  type: "circle",
                  radius: 0,
                  startAngle: 0,
                  endAngle: 2 * i,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("radius", "startAngle", "endAngle"),
                  _set: function (e, t) {
                      return this.callSuper("_set", e, t), "radius" === e && this.setRadius(t), this;
                  },
                  toObject: function (e) {
                      return this.callSuper("toObject", ["radius", "startAngle", "endAngle"].concat(e));
                  },
                  _toSVG: function () {
                      var e,
                          o,
                          n,
                          r,
                          s = (this.endAngle - this.startAngle) % (2 * i);
                      return 0 == s
                          ? ["<circle ", "COMMON_PARTS", 'cx="0" cy="0" ', 'r="', this.radius, '" />\n']
                          : ((e = t.util.cos(this.startAngle) * this.radius),
                            (o = t.util.sin(this.startAngle) * this.radius),
                            (n = t.util.cos(this.endAngle) * this.radius),
                            (r = t.util.sin(this.endAngle) * this.radius),
                            ['<path d="M ' + e + " " + o, " A " + this.radius + " " + this.radius, " 0 ", +(i < s ? "1" : "0") + " 1", " " + n + " " + r, '" ', "COMMON_PARTS", " />\n"]);
                  },
                  _render: function (e) {
                      e.beginPath(), e.arc(0, 0, this.radius, this.startAngle, this.endAngle, !1), this._renderPaintInOrder(e);
                  },
                  getRadiusX: function () {
                      return this.get("radius") * this.get("scaleX");
                  },
                  getRadiusY: function () {
                      return this.get("radius") * this.get("scaleY");
                  },
                  setRadius: function (e) {
                      return (this.radius = e), this.set("width", 2 * e).set("height", 2 * e);
                  },
              })),
              (t.Circle.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat("cx cy r".split(" "))),
              (t.Circle.fromElement = function (e, i) {
                  var o = t.parseAttributes(e, t.Circle.ATTRIBUTE_NAMES);
                  if (!("radius" in (e = o) && 0 <= e.radius)) throw new Error("value of `r` attribute is required and can not be negative");
                  (o.left = (o.left || 0) - o.radius), (o.top = (o.top || 0) - o.radius), i(new t.Circle(o));
              }),
              (t.Circle.fromObject = function (e, i) {
                  t.Object._fromObject("Circle", e, i);
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        t.Triangle
            ? t.warn("fabric.Triangle is already defined")
            : ((t.Triangle = t.util.createClass(t.Object, {
                  type: "triangle",
                  width: 100,
                  height: 100,
                  _render: function (e) {
                      var t = this.width / 2,
                          i = this.height / 2;
                      e.beginPath(), e.moveTo(-t, i), e.lineTo(0, -i), e.lineTo(t, i), e.closePath(), this._renderPaintInOrder(e);
                  },
                  _toSVG: function () {
                      var e = this.width / 2,
                          t = this.height / 2;
                      return ["<polygon ", "COMMON_PARTS", 'points="', [-e + " " + t, "0 " + -t, e + " " + t].join(","), '" />'];
                  },
              })),
              (t.Triangle.fromObject = function (e, i) {
                  return t.Object._fromObject("Triangle", e, i);
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = 2 * Math.PI;
        t.Ellipse
            ? t.warn("fabric.Ellipse is already defined.")
            : ((t.Ellipse = t.util.createClass(t.Object, {
                  type: "ellipse",
                  rx: 0,
                  ry: 0,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("rx", "ry"),
                  initialize: function (e) {
                      this.callSuper("initialize", e), this.set("rx", (e && e.rx) || 0), this.set("ry", (e && e.ry) || 0);
                  },
                  _set: function (e, t) {
                      switch ((this.callSuper("_set", e, t), e)) {
                          case "rx":
                              (this.rx = t), this.set("width", 2 * t);
                              break;
                          case "ry":
                              (this.ry = t), this.set("height", 2 * t);
                      }
                      return this;
                  },
                  getRx: function () {
                      return this.get("rx") * this.get("scaleX");
                  },
                  getRy: function () {
                      return this.get("ry") * this.get("scaleY");
                  },
                  toObject: function (e) {
                      return this.callSuper("toObject", ["rx", "ry"].concat(e));
                  },
                  _toSVG: function () {
                      return ["<ellipse ", "COMMON_PARTS", 'cx="0" cy="0" ', 'rx="', this.rx, '" ry="', this.ry, '" />\n'];
                  },
                  _render: function (e) {
                      e.beginPath(), e.save(), e.transform(1, 0, 0, this.ry / this.rx, 0, 0), e.arc(0, 0, this.rx, 0, i, !1), e.restore(), this._renderPaintInOrder(e);
                  },
              })),
              (t.Ellipse.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" "))),
              (t.Ellipse.fromElement = function (e, i) {
                  ((e = t.parseAttributes(e, t.Ellipse.ATTRIBUTE_NAMES)).left = (e.left || 0) - e.rx), (e.top = (e.top || 0) - e.ry), i(new t.Ellipse(e));
              }),
              (t.Ellipse.fromObject = function (e, i) {
                  t.Object._fromObject("Ellipse", e, i);
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend;
        t.Rect
            ? t.warn("fabric.Rect is already defined")
            : ((t.Rect = t.util.createClass(t.Object, {
                  stateProperties: t.Object.prototype.stateProperties.concat("rx", "ry"),
                  type: "rect",
                  rx: 0,
                  ry: 0,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("rx", "ry"),
                  initialize: function (e) {
                      this.callSuper("initialize", e), this._initRxRy();
                  },
                  _initRxRy: function () {
                      this.rx && !this.ry ? (this.ry = this.rx) : this.ry && !this.rx && (this.rx = this.ry);
                  },
                  _render: function (e) {
                      var t = this.rx ? Math.min(this.rx, this.width / 2) : 0,
                          i = this.ry ? Math.min(this.ry, this.height / 2) : 0,
                          o = this.width,
                          n = this.height,
                          r = -this.width / 2,
                          s = -this.height / 2,
                          a = 0 !== t || 0 !== i,
                          c = 0.4477152502;
                      e.beginPath(),
                          e.moveTo(r + t, s),
                          e.lineTo(r + o - t, s),
                          a && e.bezierCurveTo(r + o - c * t, s, r + o, s + c * i, r + o, s + i),
                          e.lineTo(r + o, s + n - i),
                          a && e.bezierCurveTo(r + o, s + n - c * i, r + o - c * t, s + n, r + o - t, s + n),
                          e.lineTo(r + t, s + n),
                          a && e.bezierCurveTo(r + c * t, s + n, r, s + n - c * i, r, s + n - i),
                          e.lineTo(r, s + i),
                          a && e.bezierCurveTo(r, s + c * i, r + c * t, s, r + t, s),
                          e.closePath(),
                          this._renderPaintInOrder(e);
                  },
                  toObject: function (e) {
                      return this.callSuper("toObject", ["rx", "ry"].concat(e));
                  },
                  _toSVG: function () {
                      return ["<rect ", "COMMON_PARTS", 'x="', -this.width / 2, '" y="', -this.height / 2, '" rx="', this.rx, '" ry="', this.ry, '" width="', this.width, '" height="', this.height, '" />\n'];
                  },
              })),
              (t.Rect.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" "))),
              (t.Rect.fromElement = function (e, o, n) {
                  if (!e) return o(null);
                  (n = n || {}),
                      ((e = t.parseAttributes(e, t.Rect.ATTRIBUTE_NAMES)).left = e.left || 0),
                      (e.top = e.top || 0),
                      (e.height = e.height || 0),
                      (e.width = e.width || 0),
                      ((e = new t.Rect(i(n ? t.util.object.clone(n) : {}, e))).visible = e.visible && 0 < e.width && 0 < e.height),
                      o(e);
              }),
              (t.Rect.fromObject = function (e, i) {
                  return t.Object._fromObject("Rect", e, i);
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.util.array.min,
            n = t.util.array.max,
            r = t.util.toFixed;
        t.Polyline
            ? t.warn("fabric.Polyline is already defined")
            : ((t.Polyline = t.util.createClass(t.Object, {
                  type: "polyline",
                  points: null,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("points"),
                  initialize: function (e, t) {
                      (t = t || {}), (this.points = e || []), this.callSuper("initialize", t), this._setPositionDimensions(t);
                  },
                  _setPositionDimensions: function (e) {
                      var t,
                          i = this._calcDimensions(e);
                      (this.width = i.width),
                          (this.height = i.height),
                          e.fromSVG || (t = this.translateToGivenOrigin({ x: i.left - this.strokeWidth / 2, y: i.top - this.strokeWidth / 2 }, "left", "top", this.originX, this.originY)),
                          void 0 === e.left && (this.left = e.fromSVG ? i.left : t.x),
                          void 0 === e.top && (this.top = e.fromSVG ? i.top : t.y),
                          (this.pathOffset = { x: i.left + this.width / 2, y: i.top + this.height / 2 });
                  },
                  _calcDimensions: function () {
                      var e = this.points,
                          t = o(e, "x") || 0,
                          i = o(e, "y") || 0;
                      return { left: t, top: i, width: (n(e, "x") || 0) - t, height: (n(e, "y") || 0) - i };
                  },
                  toObject: function (e) {
                      return i(this.callSuper("toObject", e), { points: this.points.concat() });
                  },
                  _toSVG: function () {
                      for (var e = [], i = this.pathOffset.x, o = this.pathOffset.y, n = t.Object.NUM_FRACTION_DIGITS, s = 0, a = this.points.length; s < a; s++) e.push(r(this.points[s].x - i, n), ",", r(this.points[s].y - o, n), " ");
                      return ["<" + this.type + " ", "COMMON_PARTS", 'points="', e.join(""), '" />\n'];
                  },
                  commonRender: function (e) {
                      var t,
                          i = this.points.length,
                          o = this.pathOffset.x,
                          n = this.pathOffset.y;
                      if (!i || isNaN(this.points[i - 1].y)) return !1;
                      e.beginPath(), e.moveTo(this.points[0].x - o, this.points[0].y - n);
                      for (var r = 0; r < i; r++) (t = this.points[r]), e.lineTo(t.x - o, t.y - n);
                      return !0;
                  },
                  _render: function (e) {
                      this.commonRender(e) && this._renderPaintInOrder(e);
                  },
                  complexity: function () {
                      return this.get("points").length;
                  },
              })),
              (t.Polyline.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat()),
              (t.Polyline.fromElementGenerator = function (e) {
                  return function (o, n, r) {
                      if (!o) return n(null);
                      r = r || {};
                      var s = t.parsePointsAttribute(o.getAttribute("points"));
                      ((o = t.parseAttributes(o, t[e].ATTRIBUTE_NAMES)).fromSVG = !0), n(new t[e](s, i(o, r)));
                  };
              }),
              (t.Polyline.fromElement = t.Polyline.fromElementGenerator("Polyline")),
              (t.Polyline.fromObject = function (e, i) {
                  return t.Object._fromObject("Polyline", e, i, "points");
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        t.Polygon
            ? t.warn("fabric.Polygon is already defined")
            : ((t.Polygon = t.util.createClass(t.Polyline, {
                  type: "polygon",
                  _render: function (e) {
                      this.commonRender(e) && (e.closePath(), this._renderPaintInOrder(e));
                  },
              })),
              (t.Polygon.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat()),
              (t.Polygon.fromElement = t.Polyline.fromElementGenerator("Polygon")),
              (t.Polygon.fromObject = function (e, i) {
                  t.Object._fromObject("Polygon", e, i, "points");
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.array.min,
            o = t.util.array.max,
            n = t.util.object.extend,
            r = Object.prototype.toString,
            s = t.util.toFixed;
        t.Path
            ? t.warn("fabric.Path is already defined")
            : ((t.Path = t.util.createClass(t.Object, {
                  type: "path",
                  path: null,
                  cacheProperties: t.Object.prototype.cacheProperties.concat("path", "fillRule"),
                  stateProperties: t.Object.prototype.stateProperties.concat("path"),
                  initialize: function (e, i) {
                      this.callSuper("initialize", (i = i || {}));
                      var o = "[object Array]" === r.call((e = e || []));
                      (this.path = t.util.makePathSimpler(o ? e : t.util.parsePath(e))), this.path && t.Polyline.prototype._setPositionDimensions.call(this, i);
                  },
                  _renderPathCommands: function (e) {
                      var t,
                          i = 0,
                          o = 0,
                          n = 0,
                          r = 0,
                          s = 0,
                          a = 0,
                          c = -this.pathOffset.x,
                          l = -this.pathOffset.y;
                      e.beginPath();
                      for (var d = 0, h = this.path.length; d < h; ++d)
                          switch ((t = this.path[d])[0]) {
                              case "L":
                                  (n = t[1]), (r = t[2]), e.lineTo(n + c, r + l);
                                  break;
                              case "M":
                                  (i = n = t[1]), (o = r = t[2]), e.moveTo(n + c, r + l);
                                  break;
                              case "C":
                                  (n = t[5]), (r = t[6]), (s = t[3]), (a = t[4]), e.bezierCurveTo(t[1] + c, t[2] + l, s + c, a + l, n + c, r + l);
                                  break;
                              case "Q":
                                  e.quadraticCurveTo(t[1] + c, t[2] + l, t[3] + c, t[4] + l), (n = t[3]), (r = t[4]), (s = t[1]), (a = t[2]);
                                  break;
                              case "z":
                              case "Z":
                                  (n = i), (r = o), e.closePath();
                          }
                  },
                  _render: function (e) {
                      this._renderPathCommands(e), this._renderPaintInOrder(e);
                  },
                  toString: function () {
                      return "#<fabric.Path (" + this.complexity() + '): { "top": ' + this.top + ', "left": ' + this.left + " }>";
                  },
                  toObject: function (e) {
                      return n(this.callSuper("toObject", e), {
                          path: this.path.map(function (e) {
                              return e.slice();
                          }),
                      });
                  },
                  toDatalessObject: function (e) {
                      return (e = this.toObject(["sourcePath"].concat(e))).sourcePath && delete e.path, e;
                  },
                  _toSVG: function () {
                      return ["<path ", "COMMON_PARTS", 'd="', t.util.joinPath(this.path), '" stroke-linecap="round" ', "/>\n"];
                  },
                  _getOffsetTransform: function () {
                      var e = t.Object.NUM_FRACTION_DIGITS;
                      return " translate(" + s(-this.pathOffset.x, e) + ", " + s(-this.pathOffset.y, e) + ")";
                  },
                  toClipPathSVG: function (e) {
                      var t = this._getOffsetTransform();
                      return "\t" + this._createBaseClipPathSVGMarkup(this._toSVG(), { reviver: e, additionalTransform: t });
                  },
                  toSVG: function (e) {
                      var t = this._getOffsetTransform();
                      return this._createBaseSVGMarkup(this._toSVG(), { reviver: e, additionalTransform: t });
                  },
                  complexity: function () {
                      return this.path.length;
                  },
                  _calcDimensions: function () {
                      for (var e, n, r = [], s = [], a = 0, c = 0, l = 0, d = 0, h = 0, u = this.path.length; h < u; ++h) {
                          switch ((e = this.path[h])[0]) {
                              case "L":
                                  (l = e[1]), (d = e[2]), (n = []);
                                  break;
                              case "M":
                                  (a = l = e[1]), (c = d = e[2]), (n = []);
                                  break;
                              case "C":
                                  (n = t.util.getBoundsOfCurve(l, d, e[1], e[2], e[3], e[4], e[5], e[6])), (l = e[5]), (d = e[6]);
                                  break;
                              case "Q":
                                  (n = t.util.getBoundsOfCurve(l, d, e[1], e[2], e[1], e[2], e[3], e[4])), (l = e[3]), (d = e[4]);
                                  break;
                              case "z":
                              case "Z":
                                  (l = a), (d = c);
                          }
                          n.forEach(function (e) {
                              r.push(e.x), s.push(e.y);
                          }),
                              r.push(l),
                              s.push(d);
                      }
                      var f = i(r) || 0,
                          m = i(s) || 0;
                      return { left: f, top: m, width: (o(r) || 0) - f, height: (o(s) || 0) - m };
                  },
              })),
              (t.Path.fromObject = function (e, i) {
                  var o;
                  "string" == typeof e.sourcePath
                      ? ((o = e.sourcePath),
                        t.loadSVGFromURL(o, function (t) {
                            (t = t[0]).setOptions(e), i && i(t);
                        }))
                      : t.Object._fromObject("Path", e, i, "path");
              }),
              (t.Path.ATTRIBUTE_NAMES = t.SHARED_ATTRIBUTES.concat(["d"])),
              (t.Path.fromElement = function (e, i, o) {
                  ((e = t.parseAttributes(e, t.Path.ATTRIBUTE_NAMES)).fromSVG = !0), i(new t.Path(e.d, n(e, o)));
              }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.array.min,
            o = t.util.array.max;
        t.Group ||
            ((t.Group = t.util.createClass(t.Object, t.Collection, {
                type: "group",
                strokeWidth: 0,
                subTargetCheck: !1,
                cacheProperties: [],
                useSetOnGroup: !1,
                initialize: function (e, t, i) {
                    (t = t || {}), (this._objects = []), i && this.callSuper("initialize", t), (this._objects = e || []);
                    for (var o = this._objects.length; o--; ) this._objects[o].group = this;
                    i
                        ? this._updateObjectsACoords()
                        : ((i = t && t.centerPoint),
                          void 0 !== t.originX && (this.originX = t.originX),
                          void 0 !== t.originY && (this.originY = t.originY),
                          i || this._calcBounds(),
                          this._updateObjectsCoords(i),
                          delete t.centerPoint,
                          this.callSuper("initialize", t)),
                        this.setCoords();
                },
                _updateObjectsACoords: function () {
                    for (var e = this._objects.length; e--; ) this._objects[e].setCoords(!0);
                },
                _updateObjectsCoords: function (e) {
                    e = e || this.getCenterPoint();
                    for (var t = this._objects.length; t--; ) this._updateObjectCoords(this._objects[t], e);
                },
                _updateObjectCoords: function (e, t) {
                    var i = e.left,
                        o = e.top;
                    e.set({ left: i - t.x, top: o - t.y }), (e.group = this), e.setCoords(!0);
                },
                toString: function () {
                    return "#<fabric.Group: (" + this.complexity() + ")>";
                },
                addWithUpdate: function (e) {
                    var i = !!this.group;
                    return (
                        this._restoreObjectsState(),
                        t.util.resetObjectTransform(this),
                        e && (i && t.util.removeTransformFromObject(e, this.group.calcTransformMatrix()), this._objects.push(e), (e.group = this), e._set("canvas", this.canvas)),
                        this._calcBounds(),
                        this._updateObjectsCoords(),
                        (this.dirty = !0),
                        i ? this.group.addWithUpdate() : this.setCoords(),
                        this
                    );
                },
                removeWithUpdate: function (e) {
                    return this._restoreObjectsState(), t.util.resetObjectTransform(this), this.remove(e), this._calcBounds(), this._updateObjectsCoords(), this.setCoords(), (this.dirty = !0), this;
                },
                _onObjectAdded: function (e) {
                    (this.dirty = !0), (e.group = this), e._set("canvas", this.canvas);
                },
                _onObjectRemoved: function (e) {
                    (this.dirty = !0), delete e.group;
                },
                _set: function (e, i) {
                    var o = this._objects.length;
                    if (this.useSetOnGroup) for (; o--; ) this._objects[o].setOnGroup(e, i);
                    if ("canvas" === e) for (; o--; ) this._objects[o]._set(e, i);
                    t.Object.prototype._set.call(this, e, i);
                },
                toObject: function (e) {
                    var i = this.includeDefaultValues,
                        o = this._objects
                            .filter(function (e) {
                                return !e.excludeFromExport;
                            })
                            .map(function (t) {
                                var o = t.includeDefaultValues;
                                t.includeDefaultValues = i;
                                var n = t.toObject(e);
                                return (t.includeDefaultValues = o), n;
                            }),
                        n = t.Object.prototype.toObject.call(this, e);
                    return (n.objects = o), n;
                },
                toDatalessObject: function (e) {
                    var i,
                        o,
                        n = this.sourcePath;
                    return (
                        (o =
                            n ||
                            ((i = this.includeDefaultValues),
                            this._objects.map(function (t) {
                                var o = t.includeDefaultValues;
                                t.includeDefaultValues = i;
                                var n = t.toDatalessObject(e);
                                return (t.includeDefaultValues = o), n;
                            }))),
                        ((n = t.Object.prototype.toDatalessObject.call(this, e)).objects = o),
                        n
                    );
                },
                render: function (e) {
                    (this._transformDone = !0), this.callSuper("render", e), (this._transformDone = !1);
                },
                shouldCache: function () {
                    var e = t.Object.prototype.shouldCache.call(this);
                    if (e) for (var i = 0, o = this._objects.length; i < o; i++) if (this._objects[i].willDrawShadow()) return (this.ownCaching = !1);
                    return e;
                },
                willDrawShadow: function () {
                    if (t.Object.prototype.willDrawShadow.call(this)) return !0;
                    for (var e = 0, i = this._objects.length; e < i; e++) if (this._objects[e].willDrawShadow()) return !0;
                    return !1;
                },
                isOnACache: function () {
                    return this.ownCaching || (this.group && this.group.isOnACache());
                },
                drawObject: function (e) {
                    for (var t = 0, i = this._objects.length; t < i; t++) this._objects[t].render(e);
                    this._drawClipPath(e);
                },
                isCacheDirty: function (e) {
                    if (this.callSuper("isCacheDirty", e)) return !0;
                    if (!this.statefullCache) return !1;
                    for (var t, i, o = 0, n = this._objects.length; o < n; o++)
                        if (this._objects[o].isCacheDirty(!0)) return this._cacheCanvas && ((t = this.cacheWidth / this.zoomX), (i = this.cacheHeight / this.zoomY), this._cacheContext.clearRect(-t / 2, -i / 2, t, i)), !0;
                    return !1;
                },
                _restoreObjectsState: function () {
                    var e = this.calcOwnMatrix();
                    return (
                        this._objects.forEach(function (i) {
                            t.util.addTransformToObject(i, e), delete i.group, i.setCoords();
                        }),
                        this
                    );
                },
                realizeTransform: function (e, i) {
                    return t.util.addTransformToObject(e, i), e;
                },
                destroy: function () {
                    return (
                        this._objects.forEach(function (e) {
                            e.set("dirty", !0);
                        }),
                        this._restoreObjectsState()
                    );
                },
                toActiveSelection: function () {
                    if (this.canvas) {
                        var e = this._objects,
                            i = this.canvas;
                        this._objects = [];
                        var o = this.toObject();
                        delete o.objects;
                        var n = new t.ActiveSelection([]);
                        return (
                            n.set(o),
                            (n.type = "activeSelection"),
                            i.remove(this),
                            e.forEach(function (e) {
                                (e.group = n), (e.dirty = !0), i.add(e);
                            }),
                            (n.canvas = i),
                            (n._objects = e),
                            (i._activeObject = n).setCoords(),
                            n
                        );
                    }
                },
                ungroupOnCanvas: function () {
                    return this._restoreObjectsState();
                },
                setObjectsCoords: function () {
                    return (
                        this.forEachObject(function (e) {
                            e.setCoords(!0);
                        }),
                        this
                    );
                },
                _calcBounds: function (e) {
                    for (var t, i, o, n, r = [], s = [], a = ["tr", "br", "bl", "tl"], c = 0, l = this._objects.length, d = a.length; c < l; ++c) {
                        for (o = (t = this._objects[c]).calcACoords(), n = 0; n < d; n++) r.push(o[(i = a[n])].x), s.push(o[i].y);
                        t.aCoords = o;
                    }
                    this._getBounds(r, s, e);
                },
                _getBounds: function (e, n, r) {
                    var s = new t.Point(i(e), i(n)),
                        a = new t.Point(o(e), o(n)),
                        c = s.y || 0;
                    (e = s.x || 0), (n = a.x - s.x || 0), (s = a.y - s.y || 0);
                    (this.width = n), (this.height = s), r || this.setPositionByOrigin({ x: e, y: c }, "left", "top");
                },
                _toSVG: function (e) {
                    for (var t = ["<g ", "COMMON_PARTS", " >\n"], i = 0, o = this._objects.length; i < o; i++) t.push("\t\t", this._objects[i].toSVG(e));
                    return t.push("</g>\n"), t;
                },
                getSvgStyles: function () {
                    var e = void 0 !== this.opacity && 1 !== this.opacity ? "opacity: " + this.opacity + ";" : "",
                        t = this.visible ? "" : " visibility: hidden;";
                    return [e, this.getSvgFilter(), t].join("");
                },
                toClipPathSVG: function (e) {
                    for (var t = [], i = 0, o = this._objects.length; i < o; i++) t.push("\t", this._objects[i].toClipPathSVG(e));
                    return this._createBaseClipPathSVGMarkup(t, { reviver: e });
                },
            })),
            (t.Group.fromObject = function (e, i) {
                var o = e.objects,
                    n = t.util.object.clone(e, !0);
                delete n.objects,
                    "string" != typeof o
                        ? t.util.enlivenObjects(o, function (o) {
                              t.util.enlivenObjects([e.clipPath], function (n) {
                                  var r = t.util.object.clone(e, !0);
                                  (r.clipPath = n[0]), delete r.objects, i && i(new t.Group(o, r, !0));
                              });
                          })
                        : t.loadSVGFromURL(o, function (r) {
                              (r = t.util.groupSVGElements(r, e, o)).set(n), i && i(r);
                          });
            }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        t.ActiveSelection ||
            ((t.ActiveSelection = t.util.createClass(t.Group, {
                type: "activeSelection",
                initialize: function (e, i) {
                    (i = i || {}), (this._objects = e || []);
                    for (var o = this._objects.length; o--; ) this._objects[o].group = this;
                    i.originX && (this.originX = i.originX), i.originY && (this.originY = i.originY), this._calcBounds(), this._updateObjectsCoords(), t.Object.prototype.initialize.call(this, i), this.setCoords();
                },
                toGroup: function () {
                    var e = this._objects.concat();
                    this._objects = [];
                    var i = t.Object.prototype.toObject.call(this),
                        o = new t.Group([]);
                    return (
                        delete i.type,
                        o.set(i),
                        e.forEach(function (e) {
                            e.canvas.remove(e), (e.group = o);
                        }),
                        (o._objects = e),
                        this.canvas ? ((e = this.canvas).add(o), (e._activeObject = o).setCoords(), o) : o
                    );
                },
                onDeselect: function () {
                    return this.destroy(), !1;
                },
                toString: function () {
                    return "#<fabric.ActiveSelection: (" + this.complexity() + ")>";
                },
                shouldCache: function () {
                    return !1;
                },
                isOnACache: function () {
                    return !1;
                },
                _renderControls: function (e, t, i) {
                    e.save(), (e.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1), this.callSuper("_renderControls", e, t), void 0 === (i = i || {}).hasControls && (i.hasControls = !1), (i.forActiveSelection = !0);
                    for (var o = 0, n = this._objects.length; o < n; o++) this._objects[o]._renderControls(e, i);
                    e.restore();
                },
            })),
            (t.ActiveSelection.fromObject = function (e, i) {
                t.util.enlivenObjects(e.objects, function (o) {
                    delete e.objects, i && i(new t.ActiveSelection(o, e, !0));
                });
            }));
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = fabric.util.object.extend;
        e.fabric || (e.fabric = {}),
            e.fabric.Image
                ? fabric.warn("fabric.Image is already defined.")
                : ((fabric.Image = fabric.util.createClass(fabric.Object, {
                      type: "image",
                      strokeWidth: 0,
                      srcFromAttribute: !1,
                      _lastScaleX: 1,
                      _lastScaleY: 1,
                      _filterScalingX: 1,
                      _filterScalingY: 1,
                      minimumScaleTrigger: 0.5,
                      stateProperties: fabric.Object.prototype.stateProperties.concat("cropX", "cropY"),
                      cacheProperties: fabric.Object.prototype.cacheProperties.concat("cropX", "cropY"),
                      cacheKey: "",
                      cropX: 0,
                      cropY: 0,
                      imageSmoothing: !0,
                      initialize: function (e, t) {
                          (t = t || {}), (this.filters = []), (this.cacheKey = "texture" + fabric.Object.__uid++), this.callSuper("initialize", t), this._initElement(e, t);
                      },
                      getElement: function () {
                          return this._element || {};
                      },
                      setElement: function (e, t) {
                          return (
                              this.removeTexture(this.cacheKey),
                              this.removeTexture(this.cacheKey + "_filtered"),
                              (this._element = e),
                              (this._originalElement = e),
                              this._initConfig(t),
                              0 !== this.filters.length && this.applyFilters(),
                              this.resizeFilter && this.applyResizeFilters(),
                              this
                          );
                      },
                      removeTexture: function (e) {
                          var t = fabric.filterBackend;
                          t && t.evictCachesForKey && t.evictCachesForKey(e);
                      },
                      dispose: function () {
                          this.removeTexture(this.cacheKey),
                              this.removeTexture(this.cacheKey + "_filtered"),
                              (this._cacheContext = void 0),
                              ["_originalElement", "_element", "_filteredEl", "_cacheCanvas"].forEach(
                                  function (e) {
                                      fabric.util.cleanUpJsdomNode(this[e]), (this[e] = void 0);
                                  }.bind(this)
                              );
                      },
                      getCrossOrigin: function () {
                          return this._originalElement && (this._originalElement.crossOrigin || null);
                      },
                      getOriginalSize: function () {
                          var e = this.getElement();
                          return { width: e.naturalWidth || e.width, height: e.naturalHeight || e.height };
                      },
                      _stroke: function (e) {
                          var t, i;
                          this.stroke && 0 !== this.strokeWidth && ((t = this.width / 2), (i = this.height / 2), e.beginPath(), e.moveTo(-t, -i), e.lineTo(t, -i), e.lineTo(t, i), e.lineTo(-t, i), e.lineTo(-t, -i), e.closePath());
                      },
                      toObject: function (e) {
                          var i = [];
                          return (
                              this.filters.forEach(function (e) {
                                  e && i.push(e.toObject());
                              }),
                              (e = t(this.callSuper("toObject", ["cropX", "cropY"].concat(e)), { src: this.getSrc(), crossOrigin: this.getCrossOrigin(), filters: i })),
                              this.resizeFilter && (e.resizeFilter = this.resizeFilter.toObject()),
                              e
                          );
                      },
                      hasCrop: function () {
                          return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;
                      },
                      _toSVG: function () {
                          var e,
                              t,
                              i = [],
                              o = [],
                              n = this._element,
                              r = -this.width / 2,
                              s = -this.height / 2,
                              a = "",
                              c = "";
                          return n
                              ? (this.hasCrop() &&
                                    ((t = fabric.Object.__uid++),
                                    i.push('<clipPath id="imageCrop_' + t + '">\n', '\t<rect x="' + r + '" y="' + s + '" width="' + this.width + '" height="' + this.height + '" />\n', "</clipPath>\n"),
                                    (a = ' clip-path="url(#imageCrop_' + t + ')" ')),
                                this.imageSmoothing || (c = '" image-rendering="optimizeSpeed'),
                                o.push(
                                    "\t<image ",
                                    "COMMON_PARTS",
                                    'xlink:href="',
                                    this.getSvgSrc(!0),
                                    '" x="',
                                    r - this.cropX,
                                    '" y="',
                                    s - this.cropY,
                                    '" width="',
                                    n.width || n.naturalWidth,
                                    '" height="',
                                    n.height || n.height,
                                    c,
                                    '"',
                                    a,
                                    "></image>\n"
                                ),
                                (this.stroke || this.strokeDashArray) &&
                                    ((a = this.fill), (this.fill = null), (e = ["\t<rect ", 'x="', r, '" y="', s, '" width="', this.width, '" height="', this.height, '" style="', this.getSvgStyles(), '"/>\n']), (this.fill = a)),
                                (i = "fill" !== this.paintFirst ? i.concat(e, o) : i.concat(o, e)))
                              : [];
                      },
                      getSrc: function (e) {
                          return (e = e ? this._element : this._originalElement) ? (e.toDataURL ? e.toDataURL() : this.srcFromAttribute ? e.getAttribute("src") : e.src) : this.src || "";
                      },
                      setSrc: function (e, t, i) {
                          return (
                              fabric.util.loadImage(
                                  e,
                                  function (e, o) {
                                      this.setElement(e, i), this._setWidthHeight(), t && t(this, o);
                                  },
                                  this,
                                  i && i.crossOrigin
                              ),
                              this
                          );
                      },
                      toString: function () {
                          return '#<fabric.Image: { src: "' + this.getSrc() + '" }>';
                      },
                      applyResizeFilters: function () {
                          var e = this.resizeFilter,
                              t = this.minimumScaleTrigger,
                              i = (a = this.getTotalObjectScaling()).scaleX,
                              o = a.scaleY,
                              n = this._filteredEl || this._originalElement;
                          if ((this.group && this.set("dirty", !0), !e || (t < i && t < o))) return (this._element = n), (this._filterScalingX = 1), (this._filterScalingY = 1), (this._lastScaleX = i), void (this._lastScaleY = o);
                          fabric.filterBackend || (fabric.filterBackend = fabric.initFilterBackend());
                          var r = fabric.util.createCanvasElement(),
                              s = this._filteredEl ? this.cacheKey + "_filtered" : this.cacheKey,
                              a = n.width;
                          t = n.height;
                          (r.width = a),
                              (r.height = t),
                              (this._element = r),
                              (this._lastScaleX = e.scaleX = i),
                              (this._lastScaleY = e.scaleY = o),
                              fabric.filterBackend.applyFilters([e], n, a, t, this._element, s),
                              (this._filterScalingX = r.width / this._originalElement.width),
                              (this._filterScalingY = r.height / this._originalElement.height);
                      },
                      applyFilters: function (e) {
                          if (
                              ((e = (e = e || this.filters || []).filter(function (e) {
                                  return e && !e.isNeutralState();
                              })),
                              this.set("dirty", !0),
                              this.removeTexture(this.cacheKey + "_filtered"),
                              0 === e.length)
                          )
                              return (this._element = this._originalElement), (this._filteredEl = null), (this._filterScalingX = 1), (this._filterScalingY = 1), this;
                          var t = this._originalElement,
                              i = t.naturalWidth || t.width,
                              o = t.naturalHeight || t.height;
                          return (
                              this._element === this._originalElement
                                  ? (((t = fabric.util.createCanvasElement()).width = i), (t.height = o), (this._element = t), (this._filteredEl = t))
                                  : ((this._element = this._filteredEl), this._filteredEl.getContext("2d").clearRect(0, 0, i, o), (this._lastScaleX = 1), (this._lastScaleY = 1)),
                              fabric.filterBackend || (fabric.filterBackend = fabric.initFilterBackend()),
                              fabric.filterBackend.applyFilters(e, this._originalElement, i, o, this._element, this.cacheKey),
                              (this._originalElement.width === this._element.width && this._originalElement.height === this._element.height) ||
                                  ((this._filterScalingX = this._element.width / this._originalElement.width), (this._filterScalingY = this._element.height / this._originalElement.height)),
                              this
                          );
                      },
                      _render: function (e) {
                          fabric.util.setImageSmoothing(e, this.imageSmoothing), !0 !== this.isMoving && this.resizeFilter && this._needsResize() && this.applyResizeFilters(), this._stroke(e), this._renderPaintInOrder(e);
                      },
                      drawCacheOnCanvas: function (e) {
                          fabric.util.setImageSmoothing(e, this.imageSmoothing), fabric.Object.prototype.drawCacheOnCanvas.call(this, e);
                      },
                      shouldCache: function () {
                          return this.needsItsOwnCache();
                      },
                      _renderFill: function (e) {
                          var t,
                              i,
                              o,
                              n,
                              r,
                              s,
                              a,
                              c,
                              l,
                              d,
                              h,
                              u,
                              f,
                              m,
                              g,
                              p = this._element;
                          p &&
                              ((t = this._filterScalingX),
                              (i = this._filterScalingY),
                              (o = this.width),
                              (n = this.height),
                              (r = Math.min),
                              (m = (f = Math.max)(this.cropX, 0)),
                              (g = f(this.cropY, 0)),
                              (s = p.naturalWidth || p.width),
                              (a = p.naturalHeight || p.height),
                              (l = g * i),
                              (d = r(o * t, s - (c = m * t))),
                              (h = r(n * i, a - l)),
                              (u = -o / 2),
                              (f = -n / 2),
                              (m = r(o, s / t - m)),
                              (g = r(n, a / i - g)),
                              p && e.drawImage(p, c, l, d, h, u, f, m, g));
                      },
                      _needsResize: function () {
                          var e = this.getTotalObjectScaling();
                          return e.scaleX !== this._lastScaleX || e.scaleY !== this._lastScaleY;
                      },
                      _resetWidthHeight: function () {
                          this.set(this.getOriginalSize());
                      },
                      _initElement: function (e, t) {
                          this.setElement(fabric.util.getById(e), t), fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
                      },
                      _initConfig: function (e) {
                          this.setOptions((e = e || {})), this._setWidthHeight(e);
                      },
                      _initFilters: function (e, t) {
                          e && e.length
                              ? fabric.util.enlivenObjects(
                                    e,
                                    function (e) {
                                        t && t(e);
                                    },
                                    "fabric.Image.filters"
                                )
                              : t && t();
                      },
                      _setWidthHeight: function (e) {
                          e = e || {};
                          var t = this.getElement();
                          (this.width = e.width || t.naturalWidth || t.width || 0), (this.height = e.height || t.naturalHeight || t.height || 0);
                      },
                      parsePreserveAspectRatioAttribute: function () {
                          var e,
                              t = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ""),
                              i = this._element.width,
                              o = this._element.height,
                              n = 1,
                              r = 1,
                              s = 0,
                              a = 0,
                              c = 0,
                              l = 0,
                              d = this.width,
                              h = this.height,
                              u = { width: d, height: h };
                          return (
                              !t || ("none" === t.alignX && "none" === t.alignY)
                                  ? ((n = d / i), (r = h / o))
                                  : ("meet" === t.meetOrSlice &&
                                        ((e = (d - i * (n = r = fabric.util.findScaleToFit(this._element, u))) / 2),
                                        "Min" === t.alignX && (s = -e),
                                        "Max" === t.alignX && (s = e),
                                        (e = (h - o * r) / 2),
                                        "Min" === t.alignY && (a = -e),
                                        "Max" === t.alignY && (a = e)),
                                    "slice" === t.meetOrSlice &&
                                        ((e = i - d / (n = r = fabric.util.findScaleToCover(this._element, u))),
                                        "Mid" === t.alignX && (c = e / 2),
                                        "Max" === t.alignX && (c = e),
                                        (e = o - h / r),
                                        "Mid" === t.alignY && (l = e / 2),
                                        "Max" === t.alignY && (l = e),
                                        (i = d / n),
                                        (o = h / r))),
                              { width: i, height: o, scaleX: n, scaleY: r, offsetLeft: s, offsetTop: a, cropX: c, cropY: l }
                          );
                      },
                  })),
                  (fabric.Image.CSS_CANVAS = "canvas-img"),
                  (fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc),
                  (fabric.Image.fromObject = function (e, t) {
                      var i = fabric.util.object.clone(e);
                      fabric.util.loadImage(
                          i.src,
                          function (e, o) {
                              o
                                  ? t && t(null, !0)
                                  : fabric.Image.prototype._initFilters.call(i, i.filters, function (o) {
                                        (i.filters = o || []),
                                            fabric.Image.prototype._initFilters.call(i, [i.resizeFilter], function (o) {
                                                (i.resizeFilter = o[0]),
                                                    fabric.util.enlivenObjects([i.clipPath], function (o) {
                                                        (i.clipPath = o[0]), (o = new fabric.Image(e, i)), t(o, !1);
                                                    });
                                            });
                                    });
                          },
                          null,
                          i.crossOrigin
                      );
                  }),
                  (fabric.Image.fromURL = function (e, t, i) {
                      fabric.util.loadImage(
                          e,
                          function (e, o) {
                              t && t(new fabric.Image(e, i), o);
                          },
                          null,
                          i && i.crossOrigin
                      );
                  }),
                  (fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href crossOrigin image-rendering".split(" "))),
                  (fabric.Image.fromElement = function (e, i, o) {
                      (e = fabric.parseAttributes(e, fabric.Image.ATTRIBUTE_NAMES)), fabric.Image.fromURL(e["xlink:href"], i, t(o ? fabric.util.object.clone(o) : {}, e));
                  }));
    })("undefined" != typeof exports ? exports : this),
    fabric.util.object.extend(fabric.Object.prototype, {
        _getAngleValueForStraighten: function () {
            var e = this.angle % 360;
            return 0 < e ? 90 * Math.round((e - 1) / 90) : 90 * Math.round(e / 90);
        },
        straighten: function () {
            return this.rotate(this._getAngleValueForStraighten()), this;
        },
        fxStraighten: function (e) {
            function t() {}
            var i = (e = e || {}).onComplete || t,
                o = e.onChange || t,
                n = this;
            return (
                fabric.util.animate({
                    startValue: this.get("angle"),
                    endValue: this._getAngleValueForStraighten(),
                    duration: this.FX_DURATION,
                    onChange: function (e) {
                        n.rotate(e), o();
                    },
                    onComplete: function () {
                        n.setCoords(), i();
                    },
                }),
                this
            );
        },
    }),
    fabric.util.object.extend(fabric.StaticCanvas.prototype, {
        straightenObject: function (e) {
            return e.straighten(), this.requestRenderAll(), this;
        },
        fxStraightenObject: function (e) {
            return e.fxStraighten({ onChange: this.requestRenderAllBound }), this;
        },
    }),
    (fabric.isWebglSupported = function (e) {
        if (fabric.isLikelyNode) return !1;
        e = e || fabric.WebglFilterBackend.prototype.tileSize;
        var t,
            i,
            o,
            n = (r = document.createElement("canvas")).getContext("webgl") || r.getContext("experimental-webgl"),
            r = !1;
        if (n) {
            (fabric.maxTextureSize = n.getParameter(n.MAX_TEXTURE_SIZE)), (r = fabric.maxTextureSize >= e);
            for (var s = ["highp", "mediump", "lowp"], a = 0; a < 3; a++)
                if (((o = "precision " + s[a] + " float;\nvoid main(){}"), (i = (t = n).createShader(t.FRAGMENT_SHADER)), t.shaderSource(i, o), t.compileShader(i), t.getShaderParameter(i, t.COMPILE_STATUS))) {
                    fabric.webGlPrecision = s[a];
                    break;
                }
        }
        return (this.isSupported = r);
    }),
    ((fabric.WebglFilterBackend = function (e) {
        e && e.tileSize && (this.tileSize = e.tileSize), this.setupGLContext(this.tileSize, this.tileSize), this.captureGPUInfo();
    }).prototype = {
        tileSize: 2048,
        resources: {},
        setupGLContext: function (e, t) {
            this.dispose(), this.createWebGLCanvas(e, t), (this.aPosition = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1])), this.chooseFastestCopyGLTo2DMethod(e, t);
        },
        chooseFastestCopyGLTo2DMethod: function (e, t) {
            var i = void 0 !== window.performance;
            try {
                new ImageData(1, 1), (r = !0);
            } catch (e) {
                r = !1;
            }
            var o = "undefined" != typeof ArrayBuffer,
                n = "undefined" != typeof Uint8ClampedArray;
            if (i && r && o && n) {
                var r = fabric.util.createCanvasElement();
                if (((o = new ArrayBuffer(e * t * 4)), fabric.forceGLPutImageData)) return (this.imageBuffer = o), void (this.copyGLTo2D = copyGLTo2DPutImageData);
                (n = { imageBuffer: o, destinationWidth: e, destinationHeight: t, targetCanvas: r }),
                    (r.width = e),
                    (r.height = t),
                    (r = window.performance.now()),
                    copyGLTo2DDrawImage.call(n, this.gl, n),
                    (t = window.performance.now() - r),
                    (r = window.performance.now()),
                    copyGLTo2DPutImageData.call(n, this.gl, n),
                    window.performance.now() - r < t ? ((this.imageBuffer = o), (this.copyGLTo2D = copyGLTo2DPutImageData)) : (this.copyGLTo2D = copyGLTo2DDrawImage);
            }
        },
        createWebGLCanvas: function (e, t) {
            var i = fabric.util.createCanvasElement();
            (i.width = e),
                (i.height = t),
                (e = { alpha: !0, premultipliedAlpha: !1, depth: !1, stencil: !1, antialias: !1 }),
                (t = (t = i.getContext("webgl", e)) || i.getContext("experimental-webgl", e)) && (t.clearColor(0, 0, 0, 0), (this.canvas = i), (this.gl = t));
        },
        applyFilters: function (e, t, i, o, n, r) {
            var s,
                a = this.gl;
            r && (s = this.getCachedTexture(r, t));
            var c = {
                originalWidth: t.width || t.originalWidth,
                originalHeight: t.height || t.originalHeight,
                sourceWidth: i,
                sourceHeight: o,
                destinationWidth: i,
                destinationHeight: o,
                context: a,
                sourceTexture: this.createTexture(a, i, o, !s && t),
                targetTexture: this.createTexture(a, i, o),
                originalTexture: s || this.createTexture(a, i, o, !s && t),
                passes: e.length,
                webgl: !0,
                aPosition: this.aPosition,
                programCache: this.programCache,
                pass: 0,
                filterBackend: this,
                targetCanvas: n,
            };
            return (
                (t = a.createFramebuffer()),
                a.bindFramebuffer(a.FRAMEBUFFER, t),
                e.forEach(function (e) {
                    e && e.applyTo(c);
                }),
                resizeCanvasIfNeeded(c),
                this.copyGLTo2D(a, c),
                a.bindTexture(a.TEXTURE_2D, null),
                a.deleteTexture(c.sourceTexture),
                a.deleteTexture(c.targetTexture),
                a.deleteFramebuffer(t),
                n.getContext("2d").setTransform(1, 0, 0, 1, 0, 0),
                c
            );
        },
        dispose: function () {
            this.canvas && ((this.canvas = null), (this.gl = null)), this.clearWebGLCaches();
        },
        clearWebGLCaches: function () {
            (this.programCache = {}), (this.textureCache = {});
        },
        createTexture: function (e, t, i, o) {
            var n = e.createTexture();
            return (
                e.bindTexture(e.TEXTURE_2D, n),
                e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST),
                e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST),
                e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE),
                e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE),
                o ? e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, o) : e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, t, i, 0, e.RGBA, e.UNSIGNED_BYTE, null),
                n
            );
        },
        getCachedTexture: function (e, t) {
            return this.textureCache[e] ? this.textureCache[e] : ((t = this.createTexture(this.gl, t.width, t.height, t)), (this.textureCache[e] = t));
        },
        evictCachesForKey: function (e) {
            this.textureCache[e] && (this.gl.deleteTexture(this.textureCache[e]), delete this.textureCache[e]);
        },
        copyGLTo2D: copyGLTo2DDrawImage,
        captureGPUInfo: function () {
            if (this.gpuInfo) return this.gpuInfo;
            var e = this.gl,
                t = { renderer: "", vendor: "" };
            if (!e) return t;
            var i,
                o = e.getExtension("WEBGL_debug_renderer_info");
            return o && ((i = e.getParameter(o.UNMASKED_RENDERER_WEBGL)), (o = e.getParameter(o.UNMASKED_VENDOR_WEBGL)), i && (t.renderer = i.toLowerCase()), o && (t.vendor = o.toLowerCase())), (this.gpuInfo = t);
        },
    }),
    (function () {
        function e() {}
        (fabric.Canvas2dFilterBackend = function () {}).prototype = {
            evictCachesForKey: e,
            dispose: e,
            clearWebGLCaches: e,
            resources: {},
            applyFilters: function (e, t, i, o, n) {
                var r = n.getContext("2d");
                r.drawImage(t, 0, 0, i, o);
                var s = { sourceWidth: i, sourceHeight: o, imageData: r.getImageData(0, 0, i, o), originalEl: t, originalImageData: r.getImageData(0, 0, i, o), canvasEl: n, ctx: r, filterBackend: this };
                return (
                    e.forEach(function (e) {
                        e.applyTo(s);
                    }),
                    (s.imageData.width === i && s.imageData.height === o) || ((n.width = s.imageData.width), (n.height = s.imageData.height)),
                    r.putImageData(s.imageData, 0, 0),
                    s
                );
            },
        };
    })(),
    (fabric.Image = fabric.Image || {}),
    (fabric.Image.filters = fabric.Image.filters || {}),
    (fabric.Image.filters.BaseFilter = fabric.util.createClass({
        type: "BaseFilter",
        vertexSource: "attribute vec2 aPosition;\nvarying vec2 vTexCoord;\nvoid main() {\nvTexCoord = aPosition;\ngl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n}",
        fragmentSource: "precision highp float;\nvarying vec2 vTexCoord;\nuniform sampler2D uTexture;\nvoid main() {\ngl_FragColor = texture2D(uTexture, vTexCoord);\n}",
        initialize: function (e) {
            e && this.setOptions(e);
        },
        setOptions: function (e) {
            for (var t in e) this[t] = e[t];
        },
        createProgram: function (e, t, i) {
            (t = t || this.fragmentSource), (i = i || this.vertexSource), "highp" !== fabric.webGlPrecision && (t = t.replace(/precision highp float/g, "precision " + fabric.webGlPrecision + " float"));
            var o = e.createShader(e.VERTEX_SHADER);
            if ((e.shaderSource(o, i), e.compileShader(o), !e.getShaderParameter(o, e.COMPILE_STATUS))) throw new Error("Vertex shader compile error for " + this.type + ": " + e.getShaderInfoLog(o));
            if (((i = e.createShader(e.FRAGMENT_SHADER)), e.shaderSource(i, t), e.compileShader(i), !e.getShaderParameter(i, e.COMPILE_STATUS)))
                throw new Error("Fragment shader compile error for " + this.type + ": " + e.getShaderInfoLog(i));
            if (((t = e.createProgram()), e.attachShader(t, o), e.attachShader(t, i), e.linkProgram(t), !e.getProgramParameter(t, e.LINK_STATUS))) throw new Error('Shader link error for "${this.type}" ' + e.getProgramInfoLog(t));
            return (
                (o = this.getAttributeLocations(e, t)),
                ((i = this.getUniformLocations(e, t) || {}).uStepW = e.getUniformLocation(t, "uStepW")),
                (i.uStepH = e.getUniformLocation(t, "uStepH")),
                { program: t, attributeLocations: o, uniformLocations: i }
            );
        },
        getAttributeLocations: function (e, t) {
            return { aPosition: e.getAttribLocation(t, "aPosition") };
        },
        getUniformLocations: function () {
            return {};
        },
        sendAttributeData: function (e, t, i) {
            var o = t.aPosition;
            t = e.createBuffer();
            e.bindBuffer(e.ARRAY_BUFFER, t), e.enableVertexAttribArray(o), e.vertexAttribPointer(o, 2, e.FLOAT, !1, 0, 0), e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW);
        },
        _setupFrameBuffer: function (e) {
            var t,
                i,
                o = e.context;
            1 < e.passes
                ? ((t = e.destinationWidth),
                  (i = e.destinationHeight),
                  (e.sourceWidth === t && e.sourceHeight === i) || (o.deleteTexture(e.targetTexture), (e.targetTexture = e.filterBackend.createTexture(o, t, i))),
                  o.framebufferTexture2D(o.FRAMEBUFFER, o.COLOR_ATTACHMENT0, o.TEXTURE_2D, e.targetTexture, 0))
                : (o.bindFramebuffer(o.FRAMEBUFFER, null), o.finish());
        },
        _swapTextures: function (e) {
            e.passes--, e.pass++;
            var t = e.targetTexture;
            (e.targetTexture = e.sourceTexture), (e.sourceTexture = t);
        },
        isNeutralState: function () {
            var e = this.mainParameter,
                t = fabric.Image.filters[this.type].prototype;
            if (e) {
                if (Array.isArray(t[e])) {
                    for (var i = t[e].length; i--; ) if (this[e][i] !== t[e][i]) return !1;
                    return !0;
                }
                return t[e] === this[e];
            }
            return !1;
        },
        applyTo: function (e) {
            e.webgl ? (this._setupFrameBuffer(e), this.applyToWebGL(e), this._swapTextures(e)) : this.applyTo2d(e);
        },
        retrieveShader: function (e) {
            return e.programCache.hasOwnProperty(this.type) || (e.programCache[this.type] = this.createProgram(e.context)), e.programCache[this.type];
        },
        applyToWebGL: function (e) {
            var t = e.context,
                i = this.retrieveShader(e);
            0 === e.pass && e.originalTexture ? t.bindTexture(t.TEXTURE_2D, e.originalTexture) : t.bindTexture(t.TEXTURE_2D, e.sourceTexture),
                t.useProgram(i.program),
                this.sendAttributeData(t, i.attributeLocations, e.aPosition),
                t.uniform1f(i.uniformLocations.uStepW, 1 / e.sourceWidth),
                t.uniform1f(i.uniformLocations.uStepH, 1 / e.sourceHeight),
                this.sendUniformData(t, i.uniformLocations),
                t.viewport(0, 0, e.destinationWidth, e.destinationHeight),
                t.drawArrays(t.TRIANGLE_STRIP, 0, 4);
        },
        bindAdditionalTexture: function (e, t, i) {
            e.activeTexture(i), e.bindTexture(e.TEXTURE_2D, t), e.activeTexture(e.TEXTURE0);
        },
        unbindAdditionalTexture: function (e, t) {
            e.activeTexture(t), e.bindTexture(e.TEXTURE_2D, null), e.activeTexture(e.TEXTURE0);
        },
        getMainParameter: function () {
            return this[this.mainParameter];
        },
        setMainParameter: function (e) {
            this[this.mainParameter] = e;
        },
        sendUniformData: function () {},
        createHelpLayer: function (e) {
            var t;
            e.helpLayer || (((t = document.createElement("canvas")).width = e.sourceWidth), (t.height = e.sourceHeight), (e.helpLayer = t));
        },
        toObject: function () {
            var e = { type: this.type },
                t = this.mainParameter;
            return t && (e[t] = this[t]), e;
        },
        toJSON: function () {
            return this.toObject();
        },
    })),
    (fabric.Image.filters.BaseFilter.fromObject = function (e, t) {
        return (e = new fabric.Image.filters[e.type](e)), t && t(e), e;
    }),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.ColorMatrix = e(i.BaseFilter, {
            type: "ColorMatrix",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nuniform mat4 uColorMatrix;\nuniform vec4 uConstants;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ncolor *= uColorMatrix;\ncolor += uConstants;\ngl_FragColor = color;\n}",
            matrix: [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],
            mainParameter: "matrix",
            colorsOnly: !0,
            initialize: function (e) {
                this.callSuper("initialize", e), (this.matrix = this.matrix.slice(0));
            },
            applyTo2d: function (e) {
                for (var t, i, o, n, r = e.imageData.data, s = r.length, a = this.matrix, c = this.colorsOnly, l = 0; l < s; l += 4)
                    (t = r[l]),
                        (i = r[l + 1]),
                        (o = r[l + 2]),
                        c
                            ? ((r[l] = t * a[0] + i * a[1] + o * a[2] + 255 * a[4]), (r[l + 1] = t * a[5] + i * a[6] + o * a[7] + 255 * a[9]), (r[l + 2] = t * a[10] + i * a[11] + o * a[12] + 255 * a[14]))
                            : ((n = r[l + 3]),
                              (r[l] = t * a[0] + i * a[1] + o * a[2] + n * a[3] + 255 * a[4]),
                              (r[l + 1] = t * a[5] + i * a[6] + o * a[7] + n * a[8] + 255 * a[9]),
                              (r[l + 2] = t * a[10] + i * a[11] + o * a[12] + n * a[13] + 255 * a[14]),
                              (r[l + 3] = t * a[15] + i * a[16] + o * a[17] + n * a[18] + 255 * a[19]));
            },
            getUniformLocations: function (e, t) {
                return { uColorMatrix: e.getUniformLocation(t, "uColorMatrix"), uConstants: e.getUniformLocation(t, "uConstants") };
            },
            sendUniformData: function (e, t) {
                var i = [(o = this.matrix)[0], o[1], o[2], o[3], o[5], o[6], o[7], o[8], o[10], o[11], o[12], o[13], o[15], o[16], o[17], o[18]],
                    o = [o[4], o[9], o[14], o[19]];
                e.uniformMatrix4fv(t.uColorMatrix, !1, i), e.uniform4fv(t.uConstants, o);
            },
        })),
            (t.Image.filters.ColorMatrix.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Brightness = e(i.BaseFilter, {
            type: "Brightness",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uBrightness;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ncolor.rgb += uBrightness;\ngl_FragColor = color;\n}",
            brightness: 0,
            mainParameter: "brightness",
            applyTo2d: function (e) {
                if (0 !== this.brightness) for (var t = e.imageData.data, i = t.length, o = Math.round(255 * this.brightness), n = 0; n < i; n += 4) (t[n] = t[n] + o), (t[n + 1] = t[n + 1] + o), (t[n + 2] = t[n + 2] + o);
            },
            getUniformLocations: function (e, t) {
                return { uBrightness: e.getUniformLocation(t, "uBrightness") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uBrightness, this.brightness);
            },
        })),
            (t.Image.filters.Brightness.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.Image.filters;
        e = t.util.createClass;
        (o.Convolute = e(o.BaseFilter, {
            type: "Convolute",
            opaque: !1,
            matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],
            fragmentSource: {
                Convolute_3_1:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[9];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 0);\nfor (float h = 0.0; h < 3.0; h+=1.0) {\nfor (float w = 0.0; w < 3.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\ncolor += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\n}\n}\ngl_FragColor = color;\n}",
                Convolute_3_0:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[9];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 1);\nfor (float h = 0.0; h < 3.0; h+=1.0) {\nfor (float w = 0.0; w < 3.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\ncolor.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\n}\n}\nfloat alpha = texture2D(uTexture, vTexCoord).a;\ngl_FragColor = color;\ngl_FragColor.a = alpha;\n}",
                Convolute_5_1:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[25];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 0);\nfor (float h = 0.0; h < 5.0; h+=1.0) {\nfor (float w = 0.0; w < 5.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\ncolor += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\n}\n}\ngl_FragColor = color;\n}",
                Convolute_5_0:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[25];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 1);\nfor (float h = 0.0; h < 5.0; h+=1.0) {\nfor (float w = 0.0; w < 5.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\ncolor.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\n}\n}\nfloat alpha = texture2D(uTexture, vTexCoord).a;\ngl_FragColor = color;\ngl_FragColor.a = alpha;\n}",
                Convolute_7_1:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[49];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 0);\nfor (float h = 0.0; h < 7.0; h+=1.0) {\nfor (float w = 0.0; w < 7.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\ncolor += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\n}\n}\ngl_FragColor = color;\n}",
                Convolute_7_0:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[49];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 1);\nfor (float h = 0.0; h < 7.0; h+=1.0) {\nfor (float w = 0.0; w < 7.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\ncolor.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\n}\n}\nfloat alpha = texture2D(uTexture, vTexCoord).a;\ngl_FragColor = color;\ngl_FragColor.a = alpha;\n}",
                Convolute_9_1:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[81];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 0);\nfor (float h = 0.0; h < 9.0; h+=1.0) {\nfor (float w = 0.0; w < 9.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\ncolor += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\n}\n}\ngl_FragColor = color;\n}",
                Convolute_9_0:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform float uMatrix[81];\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = vec4(0, 0, 0, 1);\nfor (float h = 0.0; h < 9.0; h+=1.0) {\nfor (float w = 0.0; w < 9.0; w+=1.0) {\nvec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\ncolor.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\n}\n}\nfloat alpha = texture2D(uTexture, vTexCoord).a;\ngl_FragColor = color;\ngl_FragColor.a = alpha;\n}",
            },
            retrieveShader: function (e) {
                var t = Math.sqrt(this.matrix.length),
                    i = this.type + "_" + t + "_" + (this.opaque ? 1 : 0);
                t = this.fragmentSource[i];
                return e.programCache.hasOwnProperty(i) || (e.programCache[i] = this.createProgram(e.context, t)), e.programCache[i];
            },
            applyTo2d: function (e) {
                for (
                    var t,
                        i,
                        o,
                        n,
                        r,
                        s,
                        a,
                        c,
                        l,
                        d,
                        h,
                        u,
                        f = (u = e.imageData).data,
                        m = this.matrix,
                        g = Math.round(Math.sqrt(m.length)),
                        p = Math.floor(g / 2),
                        v = u.width,
                        b = u.height,
                        y = (u = e.ctx.createImageData(v, b)).data,
                        S = this.opaque ? 1 : 0,
                        w = 0;
                    w < b;
                    w++
                )
                    for (l = 0; l < v; l++) {
                        for (r = 4 * (w * v + l), h = n = o = i = t = 0; h < g; h++)
                            for (d = 0; d < g; d++)
                                (a = l + d - p), (s = w + h - p) < 0 || b <= s || a < 0 || v <= a || ((c = m[h * g + d]), (t += f[(a = 4 * (s * v + a))] * c), (i += f[1 + a] * c), (o += f[2 + a] * c), S || (n += f[3 + a] * c));
                        (y[r] = t), (y[1 + r] = i), (y[2 + r] = o), (y[3 + r] = S ? f[3 + r] : n);
                    }
                e.imageData = u;
            },
            getUniformLocations: function (e, t) {
                return { uMatrix: e.getUniformLocation(t, "uMatrix"), uOpaque: e.getUniformLocation(t, "uOpaque"), uHalfSize: e.getUniformLocation(t, "uHalfSize"), uSize: e.getUniformLocation(t, "uSize") };
            },
            sendUniformData: function (e, t) {
                e.uniform1fv(t.uMatrix, this.matrix);
            },
            toObject: function () {
                return i(this.callSuper("toObject"), { opaque: this.opaque, matrix: this.matrix });
            },
        })),
            (t.Image.filters.Convolute.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Grayscale = e(i.BaseFilter, {
            type: "Grayscale",
            fragmentSource: {
                average:
                    "precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat average = (color.r + color.b + color.g) / 3.0;\ngl_FragColor = vec4(average, average, average, color.a);\n}",
                lightness:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\ngl_FragColor = vec4(average, average, average, col.a);\n}",
                luminosity:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\ngl_FragColor = vec4(average, average, average, col.a);\n}",
            },
            mode: "average",
            mainParameter: "mode",
            applyTo2d: function (e) {
                for (var t, i = e.imageData.data, o = i.length, n = this.mode, r = 0; r < o; r += 4)
                    "average" === n
                        ? (t = (i[r] + i[r + 1] + i[r + 2]) / 3)
                        : "lightness" === n
                        ? (t = (Math.min(i[r], i[r + 1], i[r + 2]) + Math.max(i[r], i[r + 1], i[r + 2])) / 2)
                        : "luminosity" === n && (t = 0.21 * i[r] + 0.72 * i[r + 1] + 0.07 * i[r + 2]),
                        (i[r] = t),
                        (i[r + 1] = t),
                        (i[r + 2] = t);
            },
            retrieveShader: function (e) {
                var t,
                    i = this.type + "_" + this.mode;
                return e.programCache.hasOwnProperty(i) || ((t = this.fragmentSource[this.mode]), (e.programCache[i] = this.createProgram(e.context, t))), e.programCache[i];
            },
            getUniformLocations: function (e, t) {
                return { uMode: e.getUniformLocation(t, "uMode") };
            },
            sendUniformData: function (e, t) {
                e.uniform1i(t.uMode, 1);
            },
            isNeutralState: function () {
                return !1;
            },
        })),
            (t.Image.filters.Grayscale.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Invert = e(i.BaseFilter, {
            type: "Invert",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform int uInvert;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nif (uInvert == 1) {\ngl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\n} else {\ngl_FragColor = color;\n}\n}",
            invert: !0,
            mainParameter: "invert",
            applyTo2d: function (e) {
                for (var t = e.imageData.data, i = t.length, o = 0; o < i; o += 4) (t[o] = 255 - t[o]), (t[o + 1] = 255 - t[o + 1]), (t[o + 2] = 255 - t[o + 2]);
            },
            isNeutralState: function () {
                return !this.invert;
            },
            getUniformLocations: function (e, t) {
                return { uInvert: e.getUniformLocation(t, "uInvert") };
            },
            sendUniformData: function (e, t) {
                e.uniform1i(t.uInvert, this.invert);
            },
        })),
            (t.Image.filters.Invert.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.Image.filters;
        e = t.util.createClass;
        (o.Noise = e(o.BaseFilter, {
            type: "Noise",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uStepH;\nuniform float uNoise;\nuniform float uSeed;\nvarying vec2 vTexCoord;\nfloat rand(vec2 co, float seed, float vScale) {\nreturn fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\n}\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ncolor.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\ngl_FragColor = color;\n}",
            mainParameter: "noise",
            noise: 0,
            applyTo2d: function (e) {
                if (0 !== this.noise) for (var t, i = e.imageData.data, o = (i.length, this.noise), n = 0, r = i.length; n < r; n += 4) (t = (0.5 - Math.random()) * o), (i[n] += t), (i[n + 1] += t), (i[n + 2] += t);
            },
            getUniformLocations: function (e, t) {
                return { uNoise: e.getUniformLocation(t, "uNoise"), uSeed: e.getUniformLocation(t, "uSeed") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uNoise, this.noise / 255), e.uniform1f(t.uSeed, Math.random());
            },
            toObject: function () {
                return i(this.callSuper("toObject"), { noise: this.noise });
            },
        })),
            (t.Image.filters.Noise.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Pixelate = e(i.BaseFilter, {
            type: "Pixelate",
            blocksize: 4,
            mainParameter: "blocksize",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uBlocksize;\nuniform float uStepW;\nuniform float uStepH;\nvarying vec2 vTexCoord;\nvoid main() {\nfloat blockW = uBlocksize * uStepW;\nfloat blockH = uBlocksize * uStepW;\nint posX = int(vTexCoord.x / blockW);\nint posY = int(vTexCoord.y / blockH);\nfloat fposX = float(posX);\nfloat fposY = float(posY);\nvec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\nvec4 color = texture2D(uTexture, squareCoords);\ngl_FragColor = color;\n}",
            applyTo2d: function (e) {
                for (var t, i, o, n, r, s, a, c, l, d, h = (e = e.imageData).data, u = e.height, f = e.width, m = 0; m < u; m += this.blocksize)
                    for (i = 0; i < f; i += this.blocksize)
                        for (o = h[(t = 4 * m * f + 4 * i)], n = h[1 + t], r = h[2 + t], s = h[3 + t], l = Math.min(m + this.blocksize, u), d = Math.min(i + this.blocksize, f), a = m; a < l; a++)
                            for (c = i; c < d; c++) (h[(t = 4 * a * f + 4 * c)] = o), (h[1 + t] = n), (h[2 + t] = r), (h[3 + t] = s);
            },
            isNeutralState: function () {
                return 1 === this.blocksize;
            },
            getUniformLocations: function (e, t) {
                return { uBlocksize: e.getUniformLocation(t, "uBlocksize"), uStepW: e.getUniformLocation(t, "uStepW"), uStepH: e.getUniformLocation(t, "uStepH") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uBlocksize, this.blocksize);
            },
        })),
            (t.Image.filters.Pixelate.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.util.object.extend,
            o = t.Image.filters;
        e = t.util.createClass;
        (o.RemoveColor = e(o.BaseFilter, {
            type: "RemoveColor",
            color: "#FFFFFF",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform vec4 uLow;\nuniform vec4 uHigh;\nvarying vec2 vTexCoord;\nvoid main() {\ngl_FragColor = texture2D(uTexture, vTexCoord);\nif(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\ngl_FragColor.a = 0.0;\n}\n}",
            distance: 0.02,
            useAlpha: !1,
            applyTo2d: function (e) {
                for (var i, o, n, r = e.imageData.data, s = 255 * this.distance, a = [(e = new t.Color(this.color).getSource())[0] - s, e[1] - s, e[2] - s], c = [e[0] + s, e[1] + s, e[2] + s], l = 0; l < r.length; l += 4)
                    (i = r[l]), (o = r[l + 1]), (n = r[l + 2]), a[0] < i && a[1] < o && a[2] < n && i < c[0] && o < c[1] && n < c[2] && (r[l + 3] = 0);
            },
            getUniformLocations: function (e, t) {
                return { uLow: e.getUniformLocation(t, "uLow"), uHigh: e.getUniformLocation(t, "uHigh") };
            },
            sendUniformData: function (e, i) {
                var o = new t.Color(this.color).getSource(),
                    n = parseFloat(this.distance),
                    r = [0 + o[0] / 255 - n, 0 + o[1] / 255 - n, 0 + o[2] / 255 - n, 1];
                n = [o[0] / 255 + n, o[1] / 255 + n, o[2] / 255 + n, 1];
                e.uniform4fv(i.uLow, r), e.uniform4fv(i.uHigh, n);
            },
            toObject: function () {
                return i(this.callSuper("toObject"), { color: this.color, distance: this.distance });
            },
        })),
            (t.Image.filters.RemoveColor.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t,
            i = e.fabric || (e.fabric = {}),
            o = i.Image.filters,
            n = i.util.createClass,
            r = {
                Brownie: [0.5997, 0.34553, -0.27082, 0, 0.186, -0.0377, 0.86095, 0.15059, 0, -0.1449, 0.24113, -0.07441, 0.44972, 0, -0.02965, 0, 0, 0, 1, 0],
                Vintage: [0.62793, 0.32021, -0.03965, 0, 0.03784, 0.02578, 0.64411, 0.03259, 0, 0.02926, 0.0466, -0.08512, 0.52416, 0, 0.02023, 0, 0, 0, 1, 0],
                Kodachrome: [1.12855, -0.39673, -0.03992, 0, 0.24991, -0.16404, 1.08352, -0.05498, 0, 0.09698, -0.16786, -0.56034, 1.60148, 0, 0.13972, 0, 0, 0, 1, 0],
                Technicolor: [1.91252, -0.85453, -0.09155, 0, 0.04624, -0.30878, 1.76589, -0.10601, 0, -0.27589, -0.2311, -0.75018, 1.84759, 0, 0.12137, 0, 0, 0, 1, 0],
                Polaroid: [1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0],
                Sepia: [0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0],
                BlackWhite: [1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0, 1, 0],
            };
        for (t in r) (o[t] = n(o.ColorMatrix, { type: t, matrix: r[t], mainParameter: !1, colorsOnly: !0 })), (i.Image.filters[t].fromObject = i.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric,
            i = t.Image.filters;
        e = t.util.createClass;
        (i.BlendColor = e(i.BaseFilter, {
            type: "BlendColor",
            color: "#F95C63",
            mode: "multiply",
            alpha: 1,
            fragmentSource: {
                multiply: "gl_FragColor.rgb *= uColor.rgb;\n",
                screen: "gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\n",
                add: "gl_FragColor.rgb += uColor.rgb;\n",
                diff: "gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\n",
                subtract: "gl_FragColor.rgb -= uColor.rgb;\n",
                lighten: "gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\n",
                darken: "gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\n",
                exclusion: "gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\n",
                overlay:
                    "if (uColor.r < 0.5) {\ngl_FragColor.r *= 2.0 * uColor.r;\n} else {\ngl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\n}\nif (uColor.g < 0.5) {\ngl_FragColor.g *= 2.0 * uColor.g;\n} else {\ngl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\n}\nif (uColor.b < 0.5) {\ngl_FragColor.b *= 2.0 * uColor.b;\n} else {\ngl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\n}\n",
                tint: "gl_FragColor.rgb *= (1.0 - uColor.a);\ngl_FragColor.rgb += uColor.rgb;\n",
            },
            buildSource: function (e) {
                return (
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform vec4 uColor;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ngl_FragColor = color;\nif (color.a > 0.0) {\n" +
                    this.fragmentSource[e] +
                    "}\n}"
                );
            },
            retrieveShader: function (e) {
                var t,
                    i = this.type + "_" + this.mode;
                return e.programCache.hasOwnProperty(i) || ((t = this.buildSource(this.mode)), (e.programCache[i] = this.createProgram(e.context, t))), e.programCache[i];
            },
            applyTo2d: function (e) {
                for (var i, o, n, r = e.imageData.data, s = r.length, a = 1 - this.alpha, c = (e = new t.Color(this.color).getSource())[0] * this.alpha, l = e[1] * this.alpha, d = e[2] * this.alpha, h = 0; h < s; h += 4)
                    switch (((i = r[h]), (o = r[h + 1]), (n = r[h + 2]), this.mode)) {
                        case "multiply":
                            (r[h] = (i * c) / 255), (r[h + 1] = (o * l) / 255), (r[h + 2] = (n * d) / 255);
                            break;
                        case "screen":
                            (r[h] = 255 - ((255 - i) * (255 - c)) / 255), (r[h + 1] = 255 - ((255 - o) * (255 - l)) / 255), (r[h + 2] = 255 - ((255 - n) * (255 - d)) / 255);
                            break;
                        case "add":
                            (r[h] = i + c), (r[h + 1] = o + l), (r[h + 2] = n + d);
                            break;
                        case "diff":
                        case "difference":
                            (r[h] = Math.abs(i - c)), (r[h + 1] = Math.abs(o - l)), (r[h + 2] = Math.abs(n - d));
                            break;
                        case "subtract":
                            (r[h] = i - c), (r[h + 1] = o - l), (r[h + 2] = n - d);
                            break;
                        case "darken":
                            (r[h] = Math.min(i, c)), (r[h + 1] = Math.min(o, l)), (r[h + 2] = Math.min(n, d));
                            break;
                        case "lighten":
                            (r[h] = Math.max(i, c)), (r[h + 1] = Math.max(o, l)), (r[h + 2] = Math.max(n, d));
                            break;
                        case "overlay":
                            (r[h] = c < 128 ? (2 * i * c) / 255 : 255 - (2 * (255 - i) * (255 - c)) / 255),
                                (r[h + 1] = l < 128 ? (2 * o * l) / 255 : 255 - (2 * (255 - o) * (255 - l)) / 255),
                                (r[h + 2] = d < 128 ? (2 * n * d) / 255 : 255 - (2 * (255 - n) * (255 - d)) / 255);
                            break;
                        case "exclusion":
                            (r[h] = c + i - (2 * c * i) / 255), (r[h + 1] = l + o - (2 * l * o) / 255), (r[h + 2] = d + n - (2 * d * n) / 255);
                            break;
                        case "tint":
                            (r[h] = c + i * a), (r[h + 1] = l + o * a), (r[h + 2] = d + n * a);
                    }
            },
            getUniformLocations: function (e, t) {
                return { uColor: e.getUniformLocation(t, "uColor") };
            },
            sendUniformData: function (e, i) {
                var o = new t.Color(this.color).getSource();
                (o[0] = (this.alpha * o[0]) / 255), (o[1] = (this.alpha * o[1]) / 255), (o[2] = (this.alpha * o[2]) / 255), (o[3] = this.alpha), e.uniform4fv(i.uColor, o);
            },
            toObject: function () {
                return { type: this.type, color: this.color, mode: this.mode, alpha: this.alpha };
            },
        })),
            (t.Image.filters.BlendColor.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric,
            i = t.Image.filters;
        e = t.util.createClass;
        (i.BlendImage = e(i.BaseFilter, {
            type: "BlendImage",
            image: null,
            mode: "multiply",
            alpha: 1,
            vertexSource:
                "attribute vec2 aPosition;\nvarying vec2 vTexCoord;\nvarying vec2 vTexCoord2;\nuniform mat3 uTransformMatrix;\nvoid main() {\nvTexCoord = aPosition;\nvTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\ngl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n}",
            fragmentSource: {
                multiply:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform sampler2D uImage;\nuniform vec4 uColor;\nvarying vec2 vTexCoord;\nvarying vec2 vTexCoord2;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nvec4 color2 = texture2D(uImage, vTexCoord2);\ncolor.rgba *= color2.rgba;\ngl_FragColor = color;\n}",
                mask:
                    "precision highp float;\nuniform sampler2D uTexture;\nuniform sampler2D uImage;\nuniform vec4 uColor;\nvarying vec2 vTexCoord;\nvarying vec2 vTexCoord2;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nvec4 color2 = texture2D(uImage, vTexCoord2);\ncolor.a = color2.a;\ngl_FragColor = color;\n}",
            },
            retrieveShader: function (e) {
                var t = this.type + "_" + this.mode,
                    i = this.fragmentSource[this.mode];
                return e.programCache.hasOwnProperty(t) || (e.programCache[t] = this.createProgram(e.context, i)), e.programCache[t];
            },
            applyToWebGL: function (e) {
                var t = e.context,
                    i = this.createTexture(e.filterBackend, this.image);
                this.bindAdditionalTexture(t, i, t.TEXTURE1), this.callSuper("applyToWebGL", e), this.unbindAdditionalTexture(t, t.TEXTURE1);
            },
            createTexture: function (e, t) {
                return e.getCachedTexture(t.cacheKey, t._element);
            },
            calculateMatrix: function () {
                var e = this.image,
                    t = e._element.width,
                    i = e._element.height;
                return [1 / e.scaleX, 0, 0, 0, 1 / e.scaleY, 0, -e.left / t, -e.top / i, 1];
            },
            applyTo2d: function (e) {
                var i,
                    o,
                    n,
                    r,
                    s,
                    a,
                    c,
                    l,
                    d = e.imageData,
                    h = e.filterBackend.resources,
                    u = d.data,
                    f = u.length,
                    m = d.width,
                    g = d.height;
                e = this.image;
                h.blendImage || (h.blendImage = t.util.createCanvasElement()),
                    (h = (d = h.blendImage).getContext("2d")),
                    d.width !== m || d.height !== g ? ((d.width = m), (d.height = g)) : h.clearRect(0, 0, m, g),
                    h.setTransform(e.scaleX, 0, 0, e.scaleY, e.left, e.top),
                    h.drawImage(e._element, 0, 0, m, g);
                for (var p = h.getImageData(0, 0, m, g).data, v = 0; v < f; v += 4)
                    switch (((s = u[v]), (a = u[v + 1]), (c = u[v + 2]), (l = u[v + 3]), (i = p[v]), (o = p[v + 1]), (n = p[v + 2]), (r = p[v + 3]), this.mode)) {
                        case "multiply":
                            (u[v] = (s * i) / 255), (u[v + 1] = (a * o) / 255), (u[v + 2] = (c * n) / 255), (u[v + 3] = (l * r) / 255);
                            break;
                        case "mask":
                            u[v + 3] = r;
                    }
            },
            getUniformLocations: function (e, t) {
                return { uTransformMatrix: e.getUniformLocation(t, "uTransformMatrix"), uImage: e.getUniformLocation(t, "uImage") };
            },
            sendUniformData: function (e, t) {
                var i = this.calculateMatrix();
                e.uniform1i(t.uImage, 1), e.uniformMatrix3fv(t.uTransformMatrix, !1, i);
            },
            toObject: function () {
                return { type: this.type, image: this.image && this.image.toObject(), mode: this.mode, alpha: this.alpha };
            },
        })),
            (t.Image.filters.BlendImage.fromObject = function (e, i) {
                t.Image.fromObject(e.image, function (o) {
                    var n = t.util.object.clone(e);
                    (n.image = o), i(new t.Image.filters.BlendImage(n));
                });
            });
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = Math.pow,
            o = Math.floor,
            n = Math.sqrt,
            r = Math.abs,
            s = Math.round,
            a = Math.sin,
            c = Math.ceil,
            l = t.Image.filters;
        e = t.util.createClass;
        (l.Resize = e(l.BaseFilter, {
            type: "Resize",
            resizeType: "hermite",
            scaleX: 1,
            scaleY: 1,
            lanczosLobes: 3,
            getUniformLocations: function (e, t) {
                return { uDelta: e.getUniformLocation(t, "uDelta"), uTaps: e.getUniformLocation(t, "uTaps") };
            },
            sendUniformData: function (e, t) {
                e.uniform2fv(t.uDelta, this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height]), e.uniform1fv(t.uTaps, this.taps);
            },
            retrieveShader: function (e) {
                var t = this.getFilterWindow(),
                    i = this.type + "_" + t;
                return e.programCache.hasOwnProperty(i) || ((t = this.generateShader(t)), (e.programCache[i] = this.createProgram(e.context, t))), e.programCache[i];
            },
            getFilterWindow: function () {
                var e = this.tempScale;
                return Math.ceil(this.lanczosLobes / e);
            },
            getTaps: function () {
                for (var e = this.lanczosCreate(this.lanczosLobes), t = this.tempScale, i = this.getFilterWindow(), o = new Array(i), n = 1; n <= i; n++) o[n - 1] = e(n * t);
                return o;
            },
            generateShader: function (e) {
                for (var t = new Array(e), i = this.fragmentSourceTOP, o = 1; o <= e; o++) t[o - 1] = o + ".0 * uDelta";
                return (
                    (i += "uniform float uTaps[" + e + "];\n"),
                    (i += "void main() {\n"),
                    (i += "  vec4 color = texture2D(uTexture, vTexCoord);\n"),
                    (i += "  float sum = 1.0;\n"),
                    t.forEach(function (e, t) {
                        (i += "  color += texture2D(uTexture, vTexCoord + " + e + ") * uTaps[" + t + "];\n"), (i += "  color += texture2D(uTexture, vTexCoord - " + e + ") * uTaps[" + t + "];\n"), (i += "  sum += 2.0 * uTaps[" + t + "];\n");
                    }),
                    (i += "  gl_FragColor = color / sum;\n"),
                    (i += "}")
                );
            },
            fragmentSourceTOP: "precision highp float;\nuniform sampler2D uTexture;\nuniform vec2 uDelta;\nvarying vec2 vTexCoord;\n",
            applyTo: function (e) {
                e.webgl
                    ? (e.passes++,
                      (this.width = e.sourceWidth),
                      (this.horizontal = !0),
                      (this.dW = Math.round(this.width * this.scaleX)),
                      (this.dH = e.sourceHeight),
                      (this.tempScale = this.dW / this.width),
                      (this.taps = this.getTaps()),
                      (e.destinationWidth = this.dW),
                      this._setupFrameBuffer(e),
                      this.applyToWebGL(e),
                      this._swapTextures(e),
                      (e.sourceWidth = e.destinationWidth),
                      (this.height = e.sourceHeight),
                      (this.horizontal = !1),
                      (this.dH = Math.round(this.height * this.scaleY)),
                      (this.tempScale = this.dH / this.height),
                      (this.taps = this.getTaps()),
                      (e.destinationHeight = this.dH),
                      this._setupFrameBuffer(e),
                      this.applyToWebGL(e),
                      this._swapTextures(e),
                      (e.sourceHeight = e.destinationHeight))
                    : this.applyTo2d(e);
            },
            isNeutralState: function () {
                return 1 === this.scaleX && 1 === this.scaleY;
            },
            lanczosCreate: function (e) {
                return function (t) {
                    if (e <= t || t <= -e) return 0;
                    if (t < 1.1920929e-7 && -1.1920929e-7 < t) return 1;
                    var i = (t *= Math.PI) / e;
                    return ((a(t) / t) * a(i)) / i;
                };
            },
            applyTo2d: function (e) {
                var t = e.imageData,
                    i = this.scaleX,
                    o = this.scaleY;
                (this.rcpScaleX = 1 / i), (this.rcpScaleY = 1 / o);
                var n,
                    r = t.width;
                (t = t.height), (i = s(r * i)), (o = s(t * o));
                "sliceHack" === this.resizeType
                    ? (n = this.sliceByTwo(e, r, t, i, o))
                    : "hermite" === this.resizeType
                    ? (n = this.hermiteFastResize(e, r, t, i, o))
                    : "bilinear" === this.resizeType
                    ? (n = this.bilinearFiltering(e, r, t, i, o))
                    : "lanczos" === this.resizeType && (n = this.lanczosResize(e, r, t, i, o)),
                    (e.imageData = n);
            },
            sliceByTwo: function (e, i, n, r, s) {
                var a,
                    c,
                    l = e.imageData,
                    d = !1,
                    h = !1,
                    u = 0.5 * i,
                    f = 0.5 * n,
                    m = 0,
                    g = 0,
                    p = i,
                    v = 0;
                for (
                    (e = t.filterBackend.resources).sliceByTwo || (e.sliceByTwo = document.createElement("canvas")),
                        ((a = e.sliceByTwo).width < 1.5 * i || a.height < n) && ((a.width = 1.5 * i), (a.height = n)),
                        (c = a.getContext("2d")).clearRect(0, 0, 1.5 * i, n),
                        c.putImageData(l, 0, 0),
                        r = o(r),
                        s = o(s);
                    !d || !h;

                )
                    (n = f), r < o(0.5 * (i = u)) ? (u = o(0.5 * u)) : ((u = r), (d = !0)), s < o(0.5 * f) ? (f = o(0.5 * f)) : ((f = s), (h = !0)), c.drawImage(a, m, g, i, n, p, v, u, f), (m = p), (g = v), (v += f);
                return c.getImageData(m, g, r, s);
            },
            lanczosResize: function (e, t, s, a, l) {
                var d = e.imageData.data,
                    h = e.ctx.createImageData(a, l),
                    u = h.data,
                    f = this.lanczosCreate(this.lanczosLobes),
                    m = this.rcpScaleX,
                    g = this.rcpScaleY,
                    p = 2 / this.rcpScaleX,
                    v = 2 / this.rcpScaleY,
                    b = c((m * this.lanczosLobes) / 2),
                    y = c((g * this.lanczosLobes) / 2),
                    S = {},
                    w = {},
                    _ = {};
                return (function e(c) {
                    var C, x, T, k, R, O, A, M, E, P;
                    for (w.x = (c + 0.5) * m, _.x = o(w.x), C = 0; C < l; C++) {
                        for (w.y = (C + 0.5) * g, _.y = o(w.y), M = A = O = R = k = 0, x = _.x - b; x <= _.x + b; x++)
                            if (!(x < 0 || t <= x)) {
                                (E = o(1e3 * r(x - w.x))), S[E] || (S[E] = {});
                                for (var B = _.y - y; B <= _.y + y; B++)
                                    B < 0 ||
                                        s <= B ||
                                        ((P = o(1e3 * r(B - w.y))),
                                        S[E][P] || (S[E][P] = f(n(i(E * p, 2) + i(P * v, 2)) / 1e3)),
                                        0 < (P = S[E][P]) && ((k += P), (R += P * d[(T = 4 * (B * t + x))]), (O += P * d[T + 1]), (A += P * d[T + 2]), (M += P * d[T + 3])));
                            }
                        (u[(T = 4 * (C * a + c))] = R / k), (u[T + 1] = O / k), (u[T + 2] = A / k), (u[T + 3] = M / k);
                    }
                    return ++c < a ? e(c) : h;
                })(0);
            },
            bilinearFiltering: function (e, t, i, n, r) {
                for (var s, a, c, l, d, h, u, f, m, g, p, v = 0, b = this.rcpScaleX, y = this.rcpScaleY, S = 4 * (t - 1), w = e.imageData.data, _ = (e = e.ctx.createImageData(n, r)).data, C = 0; C < r; C++)
                    for (u = 0; u < n; u++)
                        for (f = b * u - (d = o(b * u)), m = y * C - (h = o(y * C)), p = 4 * (h * t + d), g = 0; g < 4; g++)
                            (s = w[p + g]), (a = w[4 + p + g]), (c = w[p + S + g]), (l = w[p + S + 4 + g]), (_[v++] = s * (1 - f) * (1 - m) + a * f * (1 - m) + c * m * (1 - f) + l * f * m);
                return e;
            },
            hermiteFastResize: function (e, t, i, s, a) {
                for (var l = this.rcpScaleX, d = this.rcpScaleY, h = c(l / 2), u = c(d / 2), f = e.imageData.data, m = (e = e.ctx.createImageData(s, a)).data, g = 0; g < a; g++)
                    for (var p = 0; p < s; p++) {
                        for (var v = 4 * (p + g * s), b = 0, y = 0, S = 0, w = 0, _ = 0, C = 0, x = 0, T = (g + 0.5) * d, k = o(g * d); k < (g + 1) * d; k++)
                            for (var R = r(T - (k + 0.5)) / u, O = (p + 0.5) * l, A = R * R, M = o(p * l); M < (p + 1) * l; M++) {
                                var E = r(O - (M + 0.5)) / h,
                                    P = n(A + E * E);
                                (1 < P && P < -1) ||
                                    (0 < (b = 2 * P * P * P - 3 * P * P + 1) &&
                                        ((x += b * f[3 + (E = 4 * (M + k * t))]), (S += b), (w += (b = f[3 + E] < 255 ? (b * f[3 + E]) / 250 : b) * f[E]), (_ += b * f[1 + E]), (C += b * f[2 + E]), (y += b)));
                            }
                        (m[v] = w / y), (m[1 + v] = _ / y), (m[2 + v] = C / y), (m[3 + v] = x / S);
                    }
                return e;
            },
            toObject: function () {
                return { type: this.type, scaleX: this.scaleX, scaleY: this.scaleY, resizeType: this.resizeType, lanczosLobes: this.lanczosLobes };
            },
        })),
            (t.Image.filters.Resize.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Contrast = e(i.BaseFilter, {
            type: "Contrast",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uContrast;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\ncolor.rgb = contrastF * (color.rgb - 0.5) + 0.5;\ngl_FragColor = color;\n}",
            contrast: 0,
            mainParameter: "contrast",
            applyTo2d: function (e) {
                if (0 !== this.contrast)
                    for (var t = e.imageData.data, i = t.length, o = (259 * ((e = Math.floor(255 * this.contrast)) + 255)) / (255 * (259 - e)), n = 0; n < i; n += 4)
                        (t[n] = o * (t[n] - 128) + 128), (t[n + 1] = o * (t[n + 1] - 128) + 128), (t[n + 2] = o * (t[n + 2] - 128) + 128);
            },
            getUniformLocations: function (e, t) {
                return { uContrast: e.getUniformLocation(t, "uContrast") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uContrast, this.contrast);
            },
        })),
            (t.Image.filters.Contrast.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Saturation = e(i.BaseFilter, {
            type: "Saturation",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uSaturation;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat rgMax = max(color.r, color.g);\nfloat rgbMax = max(rgMax, color.b);\ncolor.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\ncolor.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\ncolor.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\ngl_FragColor = color;\n}",
            saturation: 0,
            mainParameter: "saturation",
            applyTo2d: function (e) {
                if (0 !== this.saturation)
                    for (var t, i = e.imageData.data, o = i.length, n = -this.saturation, r = 0; r < o; r += 4)
                        (t = Math.max(i[r], i[r + 1], i[r + 2])), (i[r] += t !== i[r] ? (t - i[r]) * n : 0), (i[r + 1] += t !== i[r + 1] ? (t - i[r + 1]) * n : 0), (i[r + 2] += t !== i[r + 2] ? (t - i[r + 2]) * n : 0);
            },
            getUniformLocations: function (e, t) {
                return { uSaturation: e.getUniformLocation(t, "uSaturation") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uSaturation, -this.saturation);
            },
        })),
            (t.Image.filters.Saturation.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Vibrance = e(i.BaseFilter, {
            type: "Vibrance",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform float uVibrance;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat max = max(color.r, max(color.g, color.b));\nfloat avg = (color.r + color.g + color.b) / 3.0;\nfloat amt = (abs(max - avg) * 2.0) * uVibrance;\ncolor.r += max != color.r ? (max - color.r) * amt : 0.00;\ncolor.g += max != color.g ? (max - color.g) * amt : 0.00;\ncolor.b += max != color.b ? (max - color.b) * amt : 0.00;\ngl_FragColor = color;\n}",
            vibrance: 0,
            mainParameter: "vibrance",
            applyTo2d: function (e) {
                if (0 !== this.vibrance)
                    for (var t, i, o = e.imageData.data, n = o.length, r = -this.vibrance, s = 0; s < n; s += 4)
                        (t = Math.max(o[s], o[s + 1], o[s + 2])),
                            (i = (o[s] + o[s + 1] + o[s + 2]) / 3),
                            (i = ((2 * Math.abs(t - i)) / 255) * r),
                            (o[s] += t !== o[s] ? (t - o[s]) * i : 0),
                            (o[s + 1] += t !== o[s + 1] ? (t - o[s + 1]) * i : 0),
                            (o[s + 2] += t !== o[s + 2] ? (t - o[s + 2]) * i : 0);
            },
            getUniformLocations: function (e, t) {
                return { uVibrance: e.getUniformLocation(t, "uVibrance") };
            },
            sendUniformData: function (e, t) {
                e.uniform1f(t.uVibrance, -this.vibrance);
            },
        })),
            (t.Image.filters.Vibrance.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Blur = e(i.BaseFilter, {
            type: "Blur",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform vec2 uDelta;\nvarying vec2 vTexCoord;\nconst float nSamples = 15.0;\nvec3 v3offset = vec3(12.9898, 78.233, 151.7182);\nfloat random(vec3 scale) {\nreturn fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\n}\nvoid main() {\nvec4 color = vec4(0.0);\nfloat total = 0.0;\nfloat offset = random(v3offset);\nfor (float t = -nSamples; t <= nSamples; t++) {\nfloat percent = (t + offset - 0.5) / nSamples;\nfloat weight = 1.0 - abs(percent);\ncolor += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\ntotal += weight;\n}\ngl_FragColor = color / total;\n}",
            blur: 0,
            mainParameter: "blur",
            applyTo: function (e) {
                e.webgl
                    ? ((this.aspectRatio = e.sourceWidth / e.sourceHeight),
                      e.passes++,
                      this._setupFrameBuffer(e),
                      (this.horizontal = !0),
                      this.applyToWebGL(e),
                      this._swapTextures(e),
                      this._setupFrameBuffer(e),
                      (this.horizontal = !1),
                      this.applyToWebGL(e),
                      this._swapTextures(e))
                    : this.applyTo2d(e);
            },
            applyTo2d: function (e) {
                e.imageData = this.simpleBlur(e);
            },
            simpleBlur: function (e) {
                var i,
                    o,
                    n = e.filterBackend.resources,
                    r = e.imageData.width,
                    s = e.imageData.height;
                n.blurLayer1 || ((n.blurLayer1 = t.util.createCanvasElement()), (n.blurLayer2 = t.util.createCanvasElement())),
                    (i = n.blurLayer1),
                    (o = n.blurLayer2),
                    (i.width === r && i.height === s) || ((o.width = i.width = r), (o.height = i.height = s));
                var a,
                    c,
                    l,
                    d,
                    h = i.getContext("2d"),
                    u = o.getContext("2d"),
                    f = 0.06 * this.blur * 0.5;
                for (h.putImageData(e.imageData, 0, 0), u.clearRect(0, 0, r, s), d = -15; d <= 15; d++)
                    (l = f * (c = d / 15) * r + (a = (Math.random() - 0.5) / 4)), (u.globalAlpha = 1 - Math.abs(c)), u.drawImage(i, l, a), h.drawImage(o, 0, 0), (u.globalAlpha = 1), u.clearRect(0, 0, o.width, o.height);
                for (d = -15; d <= 15; d++)
                    (l = f * (c = d / 15) * s + (a = (Math.random() - 0.5) / 4)), (u.globalAlpha = 1 - Math.abs(c)), u.drawImage(i, a, l), h.drawImage(o, 0, 0), (u.globalAlpha = 1), u.clearRect(0, 0, o.width, o.height);
                return e.ctx.drawImage(i, 0, 0), (e = e.ctx.getImageData(0, 0, i.width, i.height)), (h.globalAlpha = 1), h.clearRect(0, 0, i.width, i.height), e;
            },
            getUniformLocations: function (e, t) {
                return { delta: e.getUniformLocation(t, "uDelta") };
            },
            sendUniformData: function (e, t) {
                var i = this.chooseRightDelta();
                e.uniform2fv(t.delta, i);
            },
            chooseRightDelta: function () {
                var e = 1,
                    t = [0, 0];
                return this.horizontal ? 1 < this.aspectRatio && (e = 1 / this.aspectRatio) : this.aspectRatio < 1 && (e = this.aspectRatio), (e = e * this.blur * 0.12), this.horizontal ? (t[0] = e) : (t[1] = e), t;
            },
        })),
            (i.Blur.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Gamma = e(i.BaseFilter, {
            type: "Gamma",
            fragmentSource:
                "precision highp float;\nuniform sampler2D uTexture;\nuniform vec3 uGamma;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nvec3 correction = (1.0 / uGamma);\ncolor.r = pow(color.r, correction.r);\ncolor.g = pow(color.g, correction.g);\ncolor.b = pow(color.b, correction.b);\ngl_FragColor = color;\ngl_FragColor.rgb *= color.a;\n}",
            gamma: [1, 1, 1],
            mainParameter: "gamma",
            initialize: function (e) {
                (this.gamma = [1, 1, 1]), i.BaseFilter.prototype.initialize.call(this, e);
            },
            applyTo2d: function (e) {
                var t,
                    i = e.imageData.data,
                    o = ((e = this.gamma), i.length),
                    n = 1 / e[0],
                    r = 1 / e[1],
                    s = 1 / e[2];
                for (this.rVals || ((this.rVals = new Uint8Array(256)), (this.gVals = new Uint8Array(256)), (this.bVals = new Uint8Array(256))), t = 0, o = 256; t < o; t++)
                    (this.rVals[t] = 255 * Math.pow(t / 255, n)), (this.gVals[t] = 255 * Math.pow(t / 255, r)), (this.bVals[t] = 255 * Math.pow(t / 255, s));
                for (t = 0, o = i.length; t < o; t += 4) (i[t] = this.rVals[i[t]]), (i[t + 1] = this.gVals[i[t + 1]]), (i[t + 2] = this.bVals[i[t + 2]]);
            },
            getUniformLocations: function (e, t) {
                return { uGamma: e.getUniformLocation(t, "uGamma") };
            },
            sendUniformData: function (e, t) {
                e.uniform3fv(t.uGamma, this.gamma);
            },
        })),
            (t.Image.filters.Gamma.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.Composed = e(i.BaseFilter, {
            type: "Composed",
            subFilters: [],
            initialize: function (e) {
                this.callSuper("initialize", e), (this.subFilters = this.subFilters.slice(0));
            },
            applyTo: function (e) {
                (e.passes += this.subFilters.length - 1),
                    this.subFilters.forEach(function (t) {
                        t.applyTo(e);
                    });
            },
            toObject: function () {
                return t.util.object.extend(this.callSuper("toObject"), {
                    subFilters: this.subFilters.map(function (e) {
                        return e.toObject();
                    }),
                });
            },
            isNeutralState: function () {
                return !this.subFilters.some(function (e) {
                    return !e.isNeutralState();
                });
            },
        })),
            (t.Image.filters.Composed.fromObject = function (e, i) {
                return (
                    (e = (e.subFilters || []).map(function (e) {
                        return new t.Image.filters[e.type](e);
                    })),
                    (e = new t.Image.filters.Composed({ subFilters: e })),
                    i && i(e),
                    e
                );
            });
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t = e.fabric || (e.fabric = {}),
            i = t.Image.filters;
        e = t.util.createClass;
        (i.HueRotation = e(i.ColorMatrix, {
            type: "HueRotation",
            rotation: 0,
            mainParameter: "rotation",
            calculateMatrix: function () {
                var e = this.rotation * Math.PI,
                    i = t.util.cos(e),
                    o = t.util.sin(e);
                (e = Math.sqrt(1 / 3) * o), (o = 1 - i);
                (this.matrix = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]),
                    (this.matrix[0] = i + o / 3),
                    (this.matrix[1] = (1 / 3) * o - e),
                    (this.matrix[2] = (1 / 3) * o + e),
                    (this.matrix[5] = (1 / 3) * o + e),
                    (this.matrix[6] = i + (1 / 3) * o),
                    (this.matrix[7] = (1 / 3) * o - e),
                    (this.matrix[10] = (1 / 3) * o - e),
                    (this.matrix[11] = (1 / 3) * o + e),
                    (this.matrix[12] = i + (1 / 3) * o);
            },
            isNeutralState: function (e) {
                return this.calculateMatrix(), i.BaseFilter.prototype.isNeutralState.call(this, e);
            },
            applyTo: function (e) {
                this.calculateMatrix(), i.BaseFilter.prototype.applyTo.call(this, e);
            },
        })),
            (t.Image.filters.HueRotation.fromObject = t.Image.filters.BaseFilter.fromObject);
    })("undefined" != typeof exports ? exports : this),
    (function (e) {
        var t,
            i = e.fabric || (e.fabric = {}),
            o = i.util.object.clone;
        i.Text
            ? i.warn("fabric.Text is already defined")
            : ((t = "fontFamily fontWeight fontSize text underline overline linethrough textAlign fontStyle lineHeight textBackgroundColor charSpacing styles direction path pathStartOffset pathSide".split(" ")),
              (i.Text = i.util.createClass(i.Object, {
                  _dimensionAffectingProps: ["fontSize", "fontWeight", "fontFamily", "fontStyle", "lineHeight", "text", "charSpacing", "textAlign", "styles", "path", "pathStartOffset", "pathSide"],
                  _reNewline: /\r?\n/,
                  _reSpacesAndTabs: /[ \t\r]/g,
                  _reSpaceAndTab: /[ \t\r]/,
                  _reWords: /\S+/g,
                  type: "text",
                  fontSize: 40,
                  fontWeight: "normal",
                  fontFamily: "Times New Roman",
                  underline: !1,
                  overline: !1,
                  linethrough: !1,
                  textAlign: "left",
                  fontStyle: "normal",
                  lineHeight: 1.16,
                  superscript: { size: 0.6, baseline: -0.35 },
                  subscript: { size: 0.6, baseline: 0.11 },
                  textBackgroundColor: "",
                  stateProperties: i.Object.prototype.stateProperties.concat(t),
                  cacheProperties: i.Object.prototype.cacheProperties.concat(t),
                  stroke: null,
                  shadow: null,
                  path: null,
                  pathStartOffset: 0,
                  pathSide: "left",
                  _fontSizeFraction: 0.222,
                  offsets: { underline: 0.1, linethrough: -0.315, overline: -0.88 },
                  _fontSizeMult: 1.13,
                  charSpacing: 0,
                  styles: null,
                  _measuringContext: null,
                  deltaY: 0,
                  direction: "ltr",
                  _styleProperties: ["stroke", "strokeWidth", "fill", "fontFamily", "fontSize", "fontWeight", "fontStyle", "underline", "overline", "linethrough", "deltaY", "textBackgroundColor"],
                  __charBounds: [],
                  CACHE_FONT_SIZE: 400,
                  MIN_TEXT_WIDTH: 2,
                  initialize: function (e, t) {
                      (this.styles = (t && t.styles) || {}),
                          (this.text = e),
                          (this.__skipDimension = !0),
                          this.callSuper("initialize", t),
                          this.path && this.setPathInfo(),
                          (this.__skipDimension = !1),
                          this.initDimensions(),
                          this.setCoords(),
                          this.setupState({ propertySet: "_dimensionAffectingProps" });
                  },
                  setPathInfo: function () {
                      var e = this.path;
                      e && (e.segmentsInfo = i.util.getPathSegmentsInfo(e.path));
                  },
                  getMeasuringContext: function () {
                      return i._measuringContext || (i._measuringContext = (this.canvas && this.canvas.contextCache) || i.util.createCanvasElement().getContext("2d")), i._measuringContext;
                  },
                  _splitText: function () {
                      var e = this._splitTextIntoLines(this.text);
                      return (this.textLines = e.lines), (this._textLines = e.graphemeLines), (this._unwrappedTextLines = e._unwrappedLines), (this._text = e.graphemeText), e;
                  },
                  initDimensions: function () {
                      this.__skipDimension ||
                          (this._splitText(),
                          this._clearCache(),
                          this.path ? ((this.width = this.path.width), (this.height = this.path.height)) : ((this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH), (this.height = this.calcTextHeight())),
                          -1 !== this.textAlign.indexOf("justify") && this.enlargeSpaces(),
                          this.saveState({ propertySet: "_dimensionAffectingProps" }));
                  },
                  enlargeSpaces: function () {
                      for (var e, t, i, o, n, r = 0, s = this._textLines.length; r < s; r++)
                          if (
                              ("justify" === this.textAlign || (r !== s - 1 && !this.isEndOfWrapping(r))) &&
                              ((t = 0), (i = this._textLines[r]), (e = this.getLineWidth(r)) < this.width && (n = this.textLines[r].match(this._reSpacesAndTabs)))
                          )
                              for (var a = n.length, c = (this.width - e) / a, l = 0, d = i.length; l <= d; l++)
                                  (o = this.__charBounds[r][l]), this._reSpaceAndTab.test(i[l]) ? ((o.width += c), (o.kernedWidth += c), (o.left += t), (t += c)) : (o.left += t);
                  },
                  isEndOfWrapping: function (e) {
                      return e === this._textLines.length - 1;
                  },
                  missingNewlineOffset: function () {
                      return 1;
                  },
                  toString: function () {
                      return "#<fabric.Text (" + this.complexity() + '): { "text": "' + this.text + '", "fontFamily": "' + this.fontFamily + '" }>';
                  },
                  _getCacheCanvasDimensions: function () {
                      var e = this.callSuper("_getCacheCanvasDimensions"),
                          t = this.fontSize;
                      return (e.width += t * e.zoomX), (e.height += t * e.zoomY), e;
                  },
                  _render: function (e) {
                      var t = this.path;
                      t && !t.isNotVisible() && t._render(e),
                          this._setTextStyles(e),
                          this._renderTextLinesBackground(e),
                          this._renderTextDecoration(e, "underline"),
                          this._renderText(e),
                          this._renderTextDecoration(e, "overline"),
                          this._renderTextDecoration(e, "linethrough");
                  },
                  _renderText: function (e) {
                      "stroke" === this.paintFirst ? (this._renderTextStroke(e), this._renderTextFill(e)) : (this._renderTextFill(e), this._renderTextStroke(e));
                  },
                  _setTextStyles: function (e, t, i) {
                      (e.textBaseline = "alphabetic"), (e.font = this._getFontDeclaration(t, i));
                  },
                  calcTextWidth: function () {
                      for (var e = this.getLineWidth(0), t = 1, i = this._textLines.length; t < i; t++) {
                          var o = this.getLineWidth(t);
                          e < o && (e = o);
                      }
                      return e;
                  },
                  _renderTextLine: function (e, t, i, o, n, r) {
                      this._renderChars(e, t, i, o, n, r);
                  },
                  _renderTextLinesBackground: function (e) {
                      if (this.textBackgroundColor || this.styleHas("textBackgroundColor")) {
                          for (var t, i, o, n, r = e.fillStyle, s = this._getLeftOffset(), a = this._getTopOffset(), c = 0, l = 0, d = this.path, h = 0, u = this._textLines.length; h < u; h++)
                              if (((t = this.getHeightOfLine(h)), this.textBackgroundColor || this.styleHas("textBackgroundColor", h))) {
                                  for (var f = this._textLines[h], m = this._getLineLeftOffset(h), g = ((l = 0), (c = 0), this.getValueOfPropertyAt(h, 0, "textBackgroundColor")), p = 0, v = f.length; p < v; p++)
                                      (i = this.__charBounds[h][p]),
                                          (o = this.getValueOfPropertyAt(h, p, "textBackgroundColor")),
                                          d
                                              ? (e.save(),
                                                e.translate(i.renderLeft, i.renderTop),
                                                e.rotate(i.angle),
                                                (e.fillStyle = o) && e.fillRect(-i.width / 2, (-t / this.lineHeight) * (1 - this._fontSizeFraction), i.width, t / this.lineHeight),
                                                e.restore())
                                              : o !== g
                                              ? ((n = s + m + c), "rtl" === this.direction && (n = this.width - n - l), (e.fillStyle = g) && e.fillRect(n, a, l, t / this.lineHeight), (c = i.left), (l = i.width), (g = o))
                                              : (l += i.kernedWidth);
                                  o && !d && ((n = s + m + c), "rtl" === this.direction && (n = this.width - n - l), (e.fillStyle = o), e.fillRect(n, a, l, t / this.lineHeight)), (a += t);
                              } else a += t;
                          (e.fillStyle = r), this._removeShadow(e);
                      }
                  },
                  getFontCache: function (e) {
                      var t = e.fontFamily.toLowerCase();
                      return i.charWidthsCache[t] || (i.charWidthsCache[t] = {}), (t = i.charWidthsCache[t])[(e = e.fontStyle.toLowerCase() + "_" + (e.fontWeight + "").toLowerCase())] || (t[e] = {}), t[e];
                  },
                  _measureChar: function (e, t, i, o) {
                      var n,
                          r,
                          s,
                          a,
                          c,
                          l = this.getFontCache(t),
                          d = i + e,
                          h = this._getFontDeclaration(t) === this._getFontDeclaration(o);
                      o = t.fontSize / this.CACHE_FONT_SIZE;
                      return (
                          i && void 0 !== l[i] && (s = l[i]),
                          void 0 !== l[e] && (a = n = l[e]),
                          h && void 0 !== l[d] && (a = (r = l[d]) - s),
                          (void 0 !== n && void 0 !== s && void 0 !== r) || ((c = this.getMeasuringContext()), this._setTextStyles(c, t, !0)),
                          void 0 === n && ((a = n = c.measureText(e).width), (l[e] = n)),
                          void 0 === s && h && i && ((s = c.measureText(i).width), (l[i] = s)),
                          h && void 0 === r && ((r = c.measureText(d).width), (a = (l[d] = r) - s)),
                          { width: n * o, kernedWidth: a * o }
                      );
                  },
                  getHeightOfChar: function (e, t) {
                      return this.getValueOfPropertyAt(e, t, "fontSize");
                  },
                  measureLine: function (e) {
                      return (e = this._measureLine(e)), 0 !== this.charSpacing && (e.width -= this._getWidthOfCharSpacing()), e.width < 0 && (e.width = 0), e;
                  },
                  _measureLine: function (e) {
                      var t,
                          o,
                          n,
                          r,
                          s,
                          a,
                          c = 0,
                          l = this._textLines[e],
                          d = new Array(l.length),
                          h = 0,
                          u = this.path,
                          f = "right" === this.pathSide;
                      for (this.__charBounds[e] = d, t = 0; t < l.length; t++) (o = l[t]), (r = this._getGraphemeBox(o, e, t, n)), (c += (d[t] = r).kernedWidth), (n = o);
                      if (((d[t] = { left: r ? r.left + r.width : 0, width: 0, kernedWidth: 0, height: this.fontSize }), u)) {
                          switch (((a = u.segmentsInfo[u.segmentsInfo.length - 1].length), ((s = i.util.getPointOnPath(u.path, 0, u.segmentsInfo)).x += u.pathOffset.x), (s.y += u.pathOffset.y), this.textAlign)) {
                              case "left":
                                  h = f ? a - c : 0;
                                  break;
                              case "center":
                                  h = (a - c) / 2;
                                  break;
                              case "right":
                                  h = f ? 0 : a - c;
                          }
                          for (h += this.pathStartOffset * (f ? -1 : 1), t = f ? l.length - 1 : 0; f ? 0 <= t : t < l.length; f ? t-- : t++)
                              (r = d[t]), a < h ? (h %= a) : h < 0 && (h += a), this._setGraphemeOnPath(h, r, s), (h += r.kernedWidth);
                      }
                      return { width: c, numOfSpaces: 0 };
                  },
                  _setGraphemeOnPath: function (e, t, o) {
                      var n = e + t.kernedWidth / 2;
                      (e = this.path), (e = i.util.getPointOnPath(e.path, n, e.segmentsInfo));
                      (t.renderLeft = e.x - o.x), (t.renderTop = e.y - o.y), (t.angle = e.angle + ("right" === this.pathSide ? Math.PI : 0));
                  },
                  _getGraphemeBox: function (e, t, i, o, n) {
                      var r = this.getCompleteStyleDeclaration(t, i),
                          s = o ? this.getCompleteStyleDeclaration(t, i - 1) : {},
                          a = this._measureChar(e, r, o, s);
                      (e = a.kernedWidth), (o = a.width);
                      return (
                          0 !== this.charSpacing && ((o += s = this._getWidthOfCharSpacing()), (e += s)),
                          (r = { width: o, left: 0, height: r.fontSize, kernedWidth: e, deltaY: r.deltaY }),
                          0 < i && !n && ((i = this.__charBounds[t][i - 1]), (r.left = i.left + i.width + a.kernedWidth - a.width)),
                          r
                      );
                  },
                  getHeightOfLine: function (e) {
                      if (this.__lineHeights[e]) return this.__lineHeights[e];
                      for (var t = this._textLines[e], i = this.getHeightOfChar(e, 0), o = 1, n = t.length; o < n; o++) i = Math.max(this.getHeightOfChar(e, o), i);
                      return (this.__lineHeights[e] = i * this.lineHeight * this._fontSizeMult);
                  },
                  calcTextHeight: function () {
                      for (var e, t = 0, i = 0, o = this._textLines.length; i < o; i++) (e = this.getHeightOfLine(i)), (t += i === o - 1 ? e / this.lineHeight : e);
                      return t;
                  },
                  _getLeftOffset: function () {
                      return "ltr" === this.direction ? -this.width / 2 : this.width / 2;
                  },
                  _getTopOffset: function () {
                      return -this.height / 2;
                  },
                  _renderTextCommon: function (e, t) {
                      e.save();
                      for (var i = 0, o = this._getLeftOffset(), n = this._getTopOffset(), r = 0, s = this._textLines.length; r < s; r++) {
                          var a = this.getHeightOfLine(r),
                              c = a / this.lineHeight,
                              l = this._getLineLeftOffset(r);
                          this._renderTextLine(t, e, this._textLines[r], o + l, n + i + c, r), (i += a);
                      }
                      e.restore();
                  },
                  _renderTextFill: function (e) {
                      (this.fill || this.styleHas("fill")) && this._renderTextCommon(e, "fillText");
                  },
                  _renderTextStroke: function (e) {
                      ((this.stroke && 0 !== this.strokeWidth) || !this.isEmptyStyles()) &&
                          (this.shadow && !this.shadow.affectStroke && this._removeShadow(e), e.save(), this._setLineDash(e, this.strokeDashArray), e.beginPath(), this._renderTextCommon(e, "strokeText"), e.closePath(), e.restore());
                  },
                  _renderChars: function (e, t, i, o, n, r) {
                      var s,
                          a,
                          c,
                          l,
                          d = this.getHeightOfLine(r),
                          h = -1 !== this.textAlign.indexOf("justify"),
                          u = "",
                          f = 0,
                          m = this.path,
                          g = !h && 0 === this.charSpacing && this.isEmptyStyles(r) && !m,
                          p = "ltr" === this.direction,
                          v = "ltr" === this.direction ? 1 : -1;
                      if ((t.save(), (n -= (d * this._fontSizeFraction) / this.lineHeight), g))
                          return t.canvas.setAttribute("dir", p ? "ltr" : "rtl"), (t.direction = p ? "ltr" : "rtl"), (t.textAlign = p ? "left" : "right"), this._renderChar(e, t, r, 0, i.join(""), o, n, d), void t.restore();
                      for (var b = 0, y = i.length - 1; b <= y; b++)
                          (c = b === y || this.charSpacing || m),
                              (u += i[b]),
                              (l = this.__charBounds[r][b]),
                              0 === f ? ((o += v * (l.kernedWidth - l.width)), (f += l.width)) : (f += l.kernedWidth),
                              (c = !(!h || c || !this._reSpaceAndTab.test(i[b])) || c) || ((s = s || this.getCompleteStyleDeclaration(r, b)), (a = this.getCompleteStyleDeclaration(r, b + 1)), (c = this._hasStyleChanged(s, a))),
                              c &&
                                  (m
                                      ? (t.save(), t.translate(l.renderLeft, l.renderTop), t.rotate(l.angle), this._renderChar(e, t, r, b, u, -f / 2, 0, d), t.restore())
                                      : ((l = o), t.canvas.setAttribute("dir", p ? "ltr" : "rtl"), (t.direction = p ? "ltr" : "rtl"), (t.textAlign = p ? "left" : "right"), this._renderChar(e, t, r, b, u, l, n, d)),
                                  (u = ""),
                                  (s = a),
                                  (o += v * f),
                                  (f = 0));
                      t.restore();
                  },
                  _applyPatternGradientTransformText: function (e) {
                      var t,
                          o = i.util.createCanvasElement(),
                          n = this.width + this.strokeWidth,
                          r = this.height + this.strokeWidth;
                      return (
                          (o.width = n),
                          (o.height = r),
                          (t = o.getContext("2d")).beginPath(),
                          t.moveTo(0, 0),
                          t.lineTo(n, 0),
                          t.lineTo(n, r),
                          t.lineTo(0, r),
                          t.closePath(),
                          t.translate(n / 2, r / 2),
                          (t.fillStyle = e.toLive(t)),
                          this._applyPatternGradientTransform(t, e),
                          t.fill(),
                          t.createPattern(o, "no-repeat")
                      );
                  },
                  handleFiller: function (e, t, i) {
                      var o, n;
                      return i.toLive
                          ? "percentage" === i.gradientUnits || i.gradientTransform || i.patternTransform
                              ? ((o = -this.width / 2), (n = -this.height / 2), e.translate(o, n), (e[t] = this._applyPatternGradientTransformText(i)), { offsetX: o, offsetY: n })
                              : ((e[t] = i.toLive(e, this)), this._applyPatternGradientTransform(e, i))
                          : ((e[t] = i), { offsetX: 0, offsetY: 0 });
                  },
                  _setStrokeStyles: function (e, t) {
                      return (
                          (e.lineWidth = t.strokeWidth),
                          (e.lineCap = this.strokeLineCap),
                          (e.lineDashOffset = this.strokeDashOffset),
                          (e.lineJoin = this.strokeLineJoin),
                          (e.miterLimit = this.strokeMiterLimit),
                          this.handleFiller(e, "strokeStyle", t.stroke)
                      );
                  },
                  _setFillStyles: function (e, t) {
                      return this.handleFiller(e, "fillStyle", t.fill);
                  },
                  _renderChar: function (e, t, i, o, n, r, s) {
                      var a,
                          c,
                          l = this._getStyleDeclaration(i, o);
                      (i = this.getCompleteStyleDeclaration(i, o)), (o = "fillText" === e && i.fill);
                      ((e = "strokeText" === e && i.stroke && i.strokeWidth) || o) &&
                          (t.save(),
                          o && (a = this._setFillStyles(t, i)),
                          e && (c = this._setStrokeStyles(t, i)),
                          (t.font = this._getFontDeclaration(i)),
                          l && l.textBackgroundColor && this._removeShadow(t),
                          l && l.deltaY && (s += l.deltaY),
                          o && t.fillText(n, r - a.offsetX, s - a.offsetY),
                          e && t.strokeText(n, r - c.offsetX, s - c.offsetY),
                          t.restore());
                  },
                  setSuperscript: function (e, t) {
                      return this._setScript(e, t, this.superscript);
                  },
                  setSubscript: function (e, t) {
                      return this._setScript(e, t, this.subscript);
                  },
                  _setScript: function (e, t, i) {
                      var o = this.get2DCursorLocation(e, !0),
                          n = this.getValueOfPropertyAt(o.lineIndex, o.charIndex, "fontSize");
                      (o = this.getValueOfPropertyAt(o.lineIndex, o.charIndex, "deltaY")), (i = { fontSize: n * i.size, deltaY: o + n * i.baseline });
                      return this.setSelectionStyles(i, e, t), this;
                  },
                  _hasStyleChanged: function (e, t) {
                      return (
                          e.fill !== t.fill ||
                          e.stroke !== t.stroke ||
                          e.strokeWidth !== t.strokeWidth ||
                          e.fontSize !== t.fontSize ||
                          e.fontFamily !== t.fontFamily ||
                          e.fontWeight !== t.fontWeight ||
                          e.fontStyle !== t.fontStyle ||
                          e.deltaY !== t.deltaY
                      );
                  },
                  _hasStyleChangedForSvg: function (e, t) {
                      return this._hasStyleChanged(e, t) || e.overline !== t.overline || e.underline !== t.underline || e.linethrough !== t.linethrough;
                  },
                  _getLineLeftOffset: function (e) {
                      var t = this.getLineWidth(e),
                          i = this.width - t,
                          o = this.textAlign,
                          n = this.direction;
                      (t = 0), (e = this.isEndOfWrapping(e));
                      return "justify" === o || ("justify-center" === o && !e) || ("justify-right" === o && !e) || ("justify-left" === o && !e)
                          ? 0
                          : ("center" === o && (t = i / 2), "right" === o && (t = i), "justify-center" === o && (t = i / 2), "justify-right" === o && (t = i), "rtl" === n && (t -= i), t);
                  },
                  _clearCache: function () {
                      (this.__lineWidths = []), (this.__lineHeights = []), (this.__charBounds = []);
                  },
                  _shouldClearDimensionCache: function () {
                      var e = this._forceClearCache;
                      return (e = e || this.hasStateChanged("_dimensionAffectingProps")) && ((this.dirty = !0), (this._forceClearCache = !1)), e;
                  },
                  getLineWidth: function (e) {
                      if (this.__lineWidths[e]) return this.__lineWidths[e];
                      var t = "" === this._textLines[e] ? 0 : this.measureLine(e).width;
                      return (this.__lineWidths[e] = t);
                  },
                  _getWidthOfCharSpacing: function () {
                      return 0 !== this.charSpacing ? (this.fontSize * this.charSpacing) / 1e3 : 0;
                  },
                  getValueOfPropertyAt: function (e, t, i) {
                      return ((t = this._getStyleDeclaration(e, t)) && void 0 !== t[i] ? t : this)[i];
                  },
                  _renderTextDecoration: function (e, t) {
                      if (this[t] || this.styleHas(t)) {
                          for (var i, o = this._getLeftOffset(), n = this._getTopOffset(), r = this.path, s = this._getWidthOfCharSpacing(), a = this.offsets[t], c = 0, l = this._textLines.length; c < l; c++)
                              if (((i = this.getHeightOfLine(c)), this[t] || this.styleHas(t, c))) {
                                  for (
                                      var d = this._textLines[c],
                                          h = i / this.lineHeight,
                                          u = this._getLineLeftOffset(c),
                                          f = 0,
                                          m = 0,
                                          g = this.getValueOfPropertyAt(c, 0, t),
                                          p = this.getValueOfPropertyAt(c, 0, "fill"),
                                          v = n + h * (1 - this._fontSizeFraction),
                                          b = this.getHeightOfChar(c, 0),
                                          y = this.getValueOfPropertyAt(c, 0, "deltaY"),
                                          S = 0,
                                          w = d.length;
                                      S < w;
                                      S++
                                  ) {
                                      var _ = this.__charBounds[c][S],
                                          C = this.getValueOfPropertyAt(c, S, t),
                                          x = this.getValueOfPropertyAt(c, S, "fill"),
                                          T = this.getHeightOfChar(c, S),
                                          k = this.getValueOfPropertyAt(c, S, "deltaY");
                                      r && C && x
                                          ? (e.save(), (e.fillStyle = p), e.translate(_.renderLeft, _.renderTop), e.rotate(_.angle), e.fillRect(-_.kernedWidth / 2, a * T + k, _.kernedWidth, this.fontSize / 15), e.restore())
                                          : (C !== g || x !== p || T !== b || k !== y) && 0 < m
                                          ? ((R = o + u + f),
                                            "rtl" === this.direction && (R = this.width - R - m),
                                            g && p && ((e.fillStyle = p), e.fillRect(R, v + a * b + y, m, this.fontSize / 15)),
                                            (f = _.left),
                                            (m = _.width),
                                            (g = C),
                                            (p = x),
                                            (b = T),
                                            (y = k))
                                          : (m += _.kernedWidth);
                                  }
                                  var R = o + u + f;
                                  "rtl" === this.direction && (R = this.width - R - m), (e.fillStyle = x), C && x && e.fillRect(R, v + a * b + y, m - s, this.fontSize / 15), (n += i);
                              } else n += i;
                          this._removeShadow(e);
                      }
                  },
                  _getFontDeclaration: function (e, t) {
                      var o = e || this,
                          n = this.fontFamily;
                      (e = -1 < i.Text.genericFonts.indexOf(n.toLowerCase())), (e = void 0 === n || -1 < n.indexOf("'") || -1 < n.indexOf(",") || -1 < n.indexOf('"') || e ? o.fontFamily : '"' + o.fontFamily + '"');
                      return [i.isLikelyNode ? o.fontWeight : o.fontStyle, i.isLikelyNode ? o.fontStyle : o.fontWeight, t ? this.CACHE_FONT_SIZE + "px" : o.fontSize + "px", e].join(" ");
                  },
                  render: function (e) {
                      this.visible && ((this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) || (this._shouldClearDimensionCache() && this.initDimensions(), this.callSuper("render", e)));
                  },
                  _splitTextIntoLines: function (e) {
                      for (var t = e.split(this._reNewline), o = new Array(t.length), n = ["\n"], r = [], s = 0; s < t.length; s++) (o[s] = i.util.string.graphemeSplit(t[s])), (r = r.concat(o[s], n));
                      return r.pop(), { _unwrappedLines: o, lines: t, graphemeText: r, graphemeLines: o };
                  },
                  toObject: function (e) {
                      return (e = t.concat(e)), ((e = this.callSuper("toObject", e)).styles = o(this.styles, !0)), e.path && (e.path = this.path.toObject()), e;
                  },
                  set: function (e, t) {
                      this.callSuper("set", e, t);
                      var i = !1,
                          o = !1;
                      if ("object" == typeof e) for (var n in e) "path" === n && this.setPathInfo(), (i = i || -1 !== this._dimensionAffectingProps.indexOf(n)), (o = o || "path" === n);
                      else (i = -1 !== this._dimensionAffectingProps.indexOf(e)), (o = "path" === e);
                      return o && this.setPathInfo(), i && (this.initDimensions(), this.setCoords()), this;
                  },
                  complexity: function () {
                      return 1;
                  },
              })),
              (i.Text.ATTRIBUTE_NAMES = i.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size letter-spacing text-decoration text-anchor".split(" "))),
              (i.Text.DEFAULT_SVG_FONT_SIZE = 16),
              (i.Text.fromElement = function (e, t, n) {
                  if (!e) return t(null);
                  var r = i.parseAttributes(e, i.Text.ATTRIBUTE_NAMES),
                      s = r.textAnchor || "left";
                  ((n = i.util.object.extend(n ? o(n) : {}, r)).top = n.top || 0),
                      (n.left = n.left || 0),
                      r.textDecoration &&
                          (-1 !== (a = r.textDecoration).indexOf("underline") && (n.underline = !0), -1 !== a.indexOf("overline") && (n.overline = !0), -1 !== a.indexOf("line-through") && (n.linethrough = !0), delete n.textDecoration),
                      "dx" in r && (n.left += r.dx),
                      "dy" in r && (n.top += r.dy),
                      "fontSize" in n || (n.fontSize = i.Text.DEFAULT_SVG_FONT_SIZE);
                  var a = "";
                  "textContent" in e ? (a = e.textContent) : "firstChild" in e && null !== e.firstChild && "data" in e.firstChild && null !== e.firstChild.data && (a = e.firstChild.data),
                      (a = a.replace(/^\s+|\s+$|\n+/g, "").replace(/\s+/g, " ")),
                      (r = n.strokeWidth),
                      (n.strokeWidth = 0),
                      (a = (e = new i.Text(a, n)).getScaledHeight() / e.height),
                      (n = ((e.height + e.strokeWidth) * e.lineHeight - e.height) * a),
                      (a = e.getScaledHeight() + n),
                      (n = 0),
                      "center" === s && (n = e.getScaledWidth() / 2),
                      "right" === s && (n = e.getScaledWidth()),
                      e.set({ left: e.left - n, top: e.top - (a - e.fontSize * (0.07 + e._fontSizeFraction)) / e.lineHeight, strokeWidth: void 0 !== r ? r : 1 }),
                      t(e);
              }),
              (i.Text.fromObject = function (e, t) {
                  var n = o(e),
                      r = e.path;
                  return (
                      delete n.path,
                      i.Object._fromObject(
                          "Text",
                          n,
                          function (e) {
                              r
                                  ? i.Object._fromObject(
                                        "Path",
                                        r,
                                        function (i) {
                                            e.set("path", i), t(e);
                                        },
                                        "path"
                                    )
                                  : t(e);
                          },
                          "text"
                      )
                  );
              }),
              (i.Text.genericFonts = ["sans-serif", "serif", "cursive", "fantasy", "monospace"]),
              i.util.createAccessors && i.util.createAccessors(i.Text));
    })("undefined" != typeof exports ? exports : this),
    fabric.util.object.extend(fabric.Text.prototype, {
        isEmptyStyles: function (e) {
            if (!this.styles) return !0;
            if (void 0 !== e && !this.styles[e]) return !0;
            var t,
                i = void 0 === e ? this.styles : { line: this.styles[e] };
            for (t in i) for (var o in i[t]) for (var n in i[t][o]) return !1;
            return !0;
        },
        styleHas: function (e, t) {
            if (!this.styles || !e || "" === e) return !1;
            if (void 0 !== t && !this.styles[t]) return !1;
            var i,
                o = void 0 === t ? this.styles : { 0: this.styles[t] };
            for (i in o) for (var n in o[i]) if (void 0 !== o[i][n][e]) return !0;
            return !1;
        },
        cleanStyle: function (e) {
            if (!this.styles || !e || "" === e) return !1;
            var t,
                i,
                o,
                n,
                r = this.styles,
                s = 0,
                a = !0,
                c = 0;
            for (o in r) {
                for (var l in ((t = 0), r[o])) s++, (n = r[o][l]).hasOwnProperty(e) ? (i ? n[e] !== i && (a = !1) : (i = n[e]), n[e] === this[e] && delete n[e]) : (a = !1), 0 !== Object.keys(n).length ? t++ : delete r[o][l];
                0 === t && delete r[o];
            }
            for (var d = 0; d < this._textLines.length; d++) c += this._textLines[d].length;
            a && s === c && ((this[e] = i), this.removeStyle(e));
        },
        removeStyle: function (e) {
            if (this.styles && e && "" !== e) {
                var t,
                    i,
                    o,
                    n = this.styles;
                for (i in n) {
                    for (o in (t = n[i])) delete t[o][e], 0 === Object.keys(t[o]).length && delete t[o];
                    0 === Object.keys(t).length && delete n[i];
                }
            }
        },
        _extendStyles: function (e, t) {
            (e = this.get2DCursorLocation(e)),
                this._getLineStyle(e.lineIndex) || this._setLineStyle(e.lineIndex),
                this._getStyleDeclaration(e.lineIndex, e.charIndex) || this._setStyleDeclaration(e.lineIndex, e.charIndex, {}),
                fabric.util.object.extend(this._getStyleDeclaration(e.lineIndex, e.charIndex), t);
        },
        get2DCursorLocation: function (e, t) {
            void 0 === e && (e = this.selectionStart);
            for (var i = t ? this._unwrappedTextLines : this._textLines, o = i.length, n = 0; n < o; n++) {
                if (e <= i[n].length) return { lineIndex: n, charIndex: e };
                e -= i[n].length + this.missingNewlineOffset(n);
            }
            return { lineIndex: n - 1, charIndex: i[n - 1].length < e ? i[n - 1].length : e };
        },
        getSelectionStyles: function (e, t, i) {
            void 0 === e && (e = this.selectionStart || 0), void 0 === t && (t = this.selectionEnd || e);
            for (var o = [], n = e; n < t; n++) o.push(this.getStyleAtPosition(n, i));
            return o;
        },
        getStyleAtPosition: function (e, t) {
            return (e = this.get2DCursorLocation(e)), (t ? this.getCompleteStyleDeclaration(e.lineIndex, e.charIndex) : this._getStyleDeclaration(e.lineIndex, e.charIndex)) || {};
        },
        setSelectionStyles: function (e, t, i) {
            void 0 === t && (t = this.selectionStart || 0), void 0 === i && (i = this.selectionEnd || t);
            for (var o = t; o < i; o++) this._extendStyles(o, e);
            return (this._forceClearCache = !0), this;
        },
        _getStyleDeclaration: function (e, t) {
            return (e = this.styles && this.styles[e]) ? e[t] : null;
        },
        getCompleteStyleDeclaration: function (e, t) {
            for (var i, o = this._getStyleDeclaration(e, t) || {}, n = {}, r = 0; r < this._styleProperties.length; r++) n[(i = this._styleProperties[r])] = (void 0 === o[i] ? this : o)[i];
            return n;
        },
        _setStyleDeclaration: function (e, t, i) {
            this.styles[e][t] = i;
        },
        _deleteStyleDeclaration: function (e, t) {
            delete this.styles[e][t];
        },
        _getLineStyle: function (e) {
            return !!this.styles[e];
        },
        _setLineStyle: function (e) {
            this.styles[e] = {};
        },
        _deleteLineStyle: function (e) {
            delete this.styles[e];
        },
    }),
    (function () {
        function e(e) {
            e.textDecoration &&
                (-1 < e.textDecoration.indexOf("underline") && (e.underline = !0),
                -1 < e.textDecoration.indexOf("line-through") && (e.linethrough = !0),
                -1 < e.textDecoration.indexOf("overline") && (e.overline = !0),
                delete e.textDecoration);
        }
        (fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, {
            type: "i-text",
            selectionStart: 0,
            selectionEnd: 0,
            selectionColor: "rgba(17,119,255,0.3)",
            isEditing: !1,
            editable: !0,
            editingBorderColor: "rgba(102,153,255,0.25)",
            cursorWidth: 2,
            cursorColor: "",
            cursorDelay: 1e3,
            cursorDuration: 600,
            caching: !0,
            hiddenTextareaContainer: null,
            _reSpace: /\s|\n/,
            _currentCursorOpacity: 0,
            _selectionDirection: null,
            _abortCursorAnimation: !1,
            __widthOfSpace: [],
            inCompositionMode: !1,
            initialize: function (e, t) {
                this.callSuper("initialize", e, t), this.initBehavior();
            },
            setSelectionStart: function (e) {
                (e = Math.max(e, 0)), this._updateAndFire("selectionStart", e);
            },
            setSelectionEnd: function (e) {
                (e = Math.min(e, this.text.length)), this._updateAndFire("selectionEnd", e);
            },
            _updateAndFire: function (e, t) {
                this[e] !== t && (this._fireSelectionChanged(), (this[e] = t)), this._updateTextarea();
            },
            _fireSelectionChanged: function () {
                this.fire("selection:changed"), this.canvas && this.canvas.fire("text:selection:changed", { target: this });
            },
            initDimensions: function () {
                this.isEditing && this.initDelayedCursor(), this.clearContextTop(), this.callSuper("initDimensions");
            },
            render: function (e) {
                this.clearContextTop(), this.callSuper("render", e), (this.cursorOffsetCache = {}), this.renderCursorOrSelection();
            },
            _render: function (e) {
                this.callSuper("_render", e);
            },
            clearContextTop: function (e) {
                var t, i;
                this.isEditing &&
                    this.canvas &&
                    this.canvas.contextTop &&
                    ((t = this.canvas.contextTop), (i = this.canvas.viewportTransform), t.save(), t.transform(i[0], i[1], i[2], i[3], i[4], i[5]), this.transform(t), this._clearTextArea(t), e || t.restore());
            },
            renderCursorOrSelection: function () {
                var e, t;
                this.isEditing &&
                    this.canvas &&
                    this.canvas.contextTop &&
                    ((e = this._getCursorBoundaries()), (t = this.canvas.contextTop), this.clearContextTop(!0), this.selectionStart === this.selectionEnd ? this.renderCursor(e, t) : this.renderSelection(e, t), t.restore());
            },
            _clearTextArea: function (e) {
                var t = this.width + 4,
                    i = this.height + 4;
                e.clearRect(-t / 2, -i / 2, t, i);
            },
            _getCursorBoundaries: function (e) {
                return void 0 === e && (e = this.selectionStart), { left: this._getLeftOffset(), top: this._getTopOffset(), leftOffset: (e = this._getCursorBoundariesOffsets(e)).left, topOffset: e.top };
            },
            _getCursorBoundariesOffsets: function (e) {
                if (this.cursorOffsetCache && "top" in this.cursorOffsetCache) return this.cursorOffsetCache;
                for (var t = 0, i = 0, o = this.get2DCursorLocation(e), n = o.charIndex, r = o.lineIndex, s = 0; s < r; s++) t += this.getHeightOfLine(s);
                return (
                    (e = this._getLineLeftOffset(r)),
                    (o = this.__charBounds[r][n]) && (i = o.left),
                    0 !== this.charSpacing && n === this._textLines[r].length && (i -= this._getWidthOfCharSpacing()),
                    (i = { top: t, left: e + (0 < i ? i : 0) }),
                    "rtl" === this.direction && (i.left *= -1),
                    (this.cursorOffsetCache = i),
                    this.cursorOffsetCache
                );
            },
            renderCursor: function (e, t) {
                var i = (a = this.get2DCursorLocation()).lineIndex,
                    o = 0 < a.charIndex ? a.charIndex - 1 : 0,
                    n = this.getValueOfPropertyAt(i, o, "fontSize"),
                    r = this.scaleX * this.canvas.getZoom(),
                    s = this.cursorWidth / r,
                    a = e.topOffset;
                r = this.getValueOfPropertyAt(i, o, "deltaY");
                (a += ((1 - this._fontSizeFraction) * this.getHeightOfLine(i)) / this.lineHeight - n * (1 - this._fontSizeFraction)),
                    this.inCompositionMode && this.renderSelection(e, t),
                    (t.fillStyle = this.cursorColor || this.getValueOfPropertyAt(i, o, "fill")),
                    (t.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity),
                    t.fillRect(e.left + e.leftOffset - s / 2, a + e.top + r, s, n);
            },
            renderSelection: function (e, t) {
                for (
                    var i = (this.inCompositionMode ? this.hiddenTextarea : this).selectionStart,
                        o = (this.inCompositionMode ? this.hiddenTextarea : this).selectionEnd,
                        n = -1 !== this.textAlign.indexOf("justify"),
                        r = ((i = this.get2DCursorLocation(i)), (o = this.get2DCursorLocation(o)), i.lineIndex),
                        s = o.lineIndex,
                        a = i.charIndex < 0 ? 0 : i.charIndex,
                        c = o.charIndex < 0 ? 0 : o.charIndex,
                        l = r;
                    l <= s;
                    l++
                ) {
                    var d,
                        h = this._getLineLeftOffset(l) || 0,
                        u = this.getHeightOfLine(l),
                        f = 0,
                        m = 0;
                    l === r && (f = this.__charBounds[r][a].left),
                        r <= l && l < s
                            ? (m = n && !this.isEndOfWrapping(l) ? this.width : this.getLineWidth(l) || 5)
                            : l === s && (m = 0 === c ? this.__charBounds[s][c].left : ((g = this._getWidthOfCharSpacing()), this.__charBounds[s][c - 1].left + this.__charBounds[s][c - 1].width - g)),
                        (d = u),
                        (this.lineHeight < 1 || (l === s && 1 < this.lineHeight)) && (u /= this.lineHeight);
                    var g = e.left + h + f;
                    (h = m - f), (m = u), (f = 0);
                    this.inCompositionMode ? ((t.fillStyle = this.compositionColor || "black"), (m = 1), (f = u)) : (t.fillStyle = this.selectionColor),
                        "rtl" === this.direction && (g = this.width - g - h),
                        t.fillRect(g, e.top + e.topOffset + f, h, m),
                        (e.topOffset += d);
                }
            },
            getCurrentCharFontSize: function () {
                var e = this._getCurrentCharIndex();
                return this.getValueOfPropertyAt(e.l, e.c, "fontSize");
            },
            getCurrentCharColor: function () {
                var e = this._getCurrentCharIndex();
                return this.getValueOfPropertyAt(e.l, e.c, "fill");
            },
            _getCurrentCharIndex: function () {
                var e = this.get2DCursorLocation(this.selectionStart, !0),
                    t = 0 < e.charIndex ? e.charIndex - 1 : 0;
                return { l: e.lineIndex, c: t };
            },
        })),
            (fabric.IText.fromObject = function (t, i) {
                if ((e(t), t.styles)) for (var o in t.styles) for (var n in t.styles[o]) e(t.styles[o][n]);
                fabric.Object._fromObject("IText", t, i, "text");
            });
    })(),
    (function () {
        var e = fabric.util.object.clone;
        fabric.util.object.extend(fabric.IText.prototype, {
            initBehavior: function () {
                this.initAddedHandler(), this.initRemovedHandler(), this.initCursorSelectionHandlers(), this.initDoubleClickSimulation(), (this.mouseMoveHandler = this.mouseMoveHandler.bind(this));
            },
            onDeselect: function () {
                this.isEditing && this.exitEditing(), (this.selected = !1);
            },
            initAddedHandler: function () {
                var e = this;
                this.on("added", function () {
                    var t = e.canvas;
                    t && (t._hasITextHandlers || ((t._hasITextHandlers = !0), e._initCanvasHandlers(t)), (t._iTextInstances = t._iTextInstances || []), t._iTextInstances.push(e));
                });
            },
            initRemovedHandler: function () {
                var e = this;
                this.on("removed", function () {
                    var t = e.canvas;
                    t && ((t._iTextInstances = t._iTextInstances || []), fabric.util.removeFromArray(t._iTextInstances, e), 0 === t._iTextInstances.length && ((t._hasITextHandlers = !1), e._removeCanvasHandlers(t)));
                });
            },
            _initCanvasHandlers: function (e) {
                (e._mouseUpITextHandler = function () {
                    e._iTextInstances &&
                        e._iTextInstances.forEach(function (e) {
                            e.__isMousedown = !1;
                        });
                }),
                    e.on("mouse:up", e._mouseUpITextHandler);
            },
            _removeCanvasHandlers: function (e) {
                e.off("mouse:up", e._mouseUpITextHandler);
            },
            _tick: function () {
                this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, "_onTickComplete");
            },
            _animateCursor: function (e, t, i, o) {
                var n = {
                    isAborted: !1,
                    abort: function () {
                        this.isAborted = !0;
                    },
                };
                return (
                    e.animate("_currentCursorOpacity", t, {
                        duration: i,
                        onComplete: function () {
                            n.isAborted || e[o]();
                        },
                        onChange: function () {
                            e.canvas && e.selectionStart === e.selectionEnd && e.renderCursorOrSelection();
                        },
                        abort: function () {
                            return n.isAborted;
                        },
                    }),
                    n
                );
            },
            _onTickComplete: function () {
                var e = this;
                this._cursorTimeout1 && clearTimeout(this._cursorTimeout1),
                    (this._cursorTimeout1 = setTimeout(function () {
                        e._currentTickCompleteState = e._animateCursor(e, 0, this.cursorDuration / 2, "_tick");
                    }, 100));
            },
            initDelayedCursor: function (e) {
                var t = this;
                e = e ? 0 : this.cursorDelay;
                this.abortCursorAnimation(),
                    (this._currentCursorOpacity = 1),
                    (this._cursorTimeout2 = setTimeout(function () {
                        t._tick();
                    }, e));
            },
            abortCursorAnimation: function () {
                var e = this._currentTickState || this._currentTickCompleteState,
                    t = this.canvas;
                this._currentTickState && this._currentTickState.abort(),
                    this._currentTickCompleteState && this._currentTickCompleteState.abort(),
                    clearTimeout(this._cursorTimeout1),
                    clearTimeout(this._cursorTimeout2),
                    (this._currentCursorOpacity = 0),
                    e && t && t.clearContext(t.contextTop || t.contextContainer);
            },
            selectAll: function () {
                return (this.selectionStart = 0), (this.selectionEnd = this._text.length), this._fireSelectionChanged(), this._updateTextarea(), this;
            },
            getSelectedText: function () {
                return this._text.slice(this.selectionStart, this.selectionEnd).join("");
            },
            findWordBoundaryLeft: function (e) {
                var t = 0,
                    i = e - 1;
                if (this._reSpace.test(this._text[i])) for (; this._reSpace.test(this._text[i]); ) t++, i--;
                for (; /\S/.test(this._text[i]) && -1 < i; ) t++, i--;
                return e - t;
            },
            findWordBoundaryRight: function (e) {
                var t = 0,
                    i = e;
                if (this._reSpace.test(this._text[i])) for (; this._reSpace.test(this._text[i]); ) t++, i++;
                for (; /\S/.test(this._text[i]) && i < this._text.length; ) t++, i++;
                return e + t;
            },
            findLineBoundaryLeft: function (e) {
                for (var t = 0, i = e - 1; !/\n/.test(this._text[i]) && -1 < i; ) t++, i--;
                return e - t;
            },
            findLineBoundaryRight: function (e) {
                for (var t = 0, i = e; !/\n/.test(this._text[i]) && i < this._text.length; ) t++, i++;
                return e + t;
            },
            searchWordBoundary: function (e, t) {
                for (var i = this._text, o = this._reSpace.test(i[e]) ? e - 1 : e, n = i[o], r = fabric.reNonWord; !r.test(n) && 0 < o && o < i.length; ) n = i[(o += t)];
                return r.test(n) && (o += 1 === t ? 0 : 1), o;
            },
            selectWord: function (e) {
                e = e || this.selectionStart;
                var t = this.searchWordBoundary(e, -1);
                e = this.searchWordBoundary(e, 1);
                (this.selectionStart = t), (this.selectionEnd = e), this._fireSelectionChanged(), this._updateTextarea(), this.renderCursorOrSelection();
            },
            selectLine: function (e) {
                e = e || this.selectionStart;
                var t = this.findLineBoundaryLeft(e);
                e = this.findLineBoundaryRight(e);
                return (this.selectionStart = t), (this.selectionEnd = e), this._fireSelectionChanged(), this._updateTextarea(), this;
            },
            enterEditing: function (e) {
                if (!this.isEditing && this.editable)
                    return (
                        this.canvas && (this.canvas.calcOffset(), this.exitEditingOnOthers(this.canvas)),
                        (this.isEditing = !0),
                        this.initHiddenTextarea(e),
                        this.hiddenTextarea.focus(),
                        (this.hiddenTextarea.value = this.text),
                        this._updateTextarea(),
                        this._saveEditingProps(),
                        this._setEditingProps(),
                        (this._textBeforeEdit = this.text),
                        this._tick(),
                        this.fire("editing:entered"),
                        this._fireSelectionChanged(),
                        this.canvas && (this.canvas.fire("text:editing:entered", { target: this }), this.initMouseMoveHandler(), this.canvas.requestRenderAll()),
                        this
                    );
            },
            exitEditingOnOthers: function (e) {
                e._iTextInstances &&
                    e._iTextInstances.forEach(function (e) {
                        (e.selected = !1), e.isEditing && e.exitEditing();
                    });
            },
            initMouseMoveHandler: function () {
                this.canvas.on("mouse:move", this.mouseMoveHandler);
            },
            mouseMoveHandler: function (e) {
                var t, i;
                this.__isMousedown &&
                    this.isEditing &&
                    ((t = this.getSelectionStartFromPointer(e.e)),
                    (i = this.selectionStart),
                    (e = this.selectionEnd),
                    ((t === this.__selectionStartOnMouseDown && i !== e) || (i !== t && e !== t)) &&
                        (t > this.__selectionStartOnMouseDown ? ((this.selectionStart = this.__selectionStartOnMouseDown), (this.selectionEnd = t)) : ((this.selectionStart = t), (this.selectionEnd = this.__selectionStartOnMouseDown)),
                        (this.selectionStart === i && this.selectionEnd === e) || (this.restartCursorIfNeeded(), this._fireSelectionChanged(), this._updateTextarea(), this.renderCursorOrSelection())));
            },
            _setEditingProps: function () {
                (this.hoverCursor = "text"),
                    this.canvas && (this.canvas.defaultCursor = this.canvas.moveCursor = "text"),
                    (this.borderColor = this.editingBorderColor),
                    (this.hasControls = this.selectable = !1),
                    (this.lockMovementX = this.lockMovementY = !0);
            },
            fromStringToGraphemeSelection: function (e, t, i) {
                var o = i.slice(0, e);
                o = fabric.util.string.graphemeSplit(o).length;
                return e === t ? { selectionStart: o, selectionEnd: o } : ((t = i.slice(e, t)), { selectionStart: o, selectionEnd: o + fabric.util.string.graphemeSplit(t).length });
            },
            fromGraphemeToStringSelection: function (e, t, i) {
                var o = i.slice(0, e).join("").length;
                return e === t ? { selectionStart: o, selectionEnd: o } : { selectionStart: o, selectionEnd: o + i.slice(e, t).join("").length };
            },
            _updateTextarea: function () {
                var e;
                (this.cursorOffsetCache = {}),
                    this.hiddenTextarea &&
                        (this.inCompositionMode ||
                            ((e = this.fromGraphemeToStringSelection(this.selectionStart, this.selectionEnd, this._text)), (this.hiddenTextarea.selectionStart = e.selectionStart), (this.hiddenTextarea.selectionEnd = e.selectionEnd)),
                        this.updateTextareaPosition());
            },
            updateFromTextArea: function () {
                var e;
                this.hiddenTextarea &&
                    ((this.cursorOffsetCache = {}),
                    (this.text = this.hiddenTextarea.value),
                    this._shouldClearDimensionCache() && (this.initDimensions(), this.setCoords()),
                    (e = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value)),
                    (this.selectionEnd = this.selectionStart = e.selectionEnd),
                    this.inCompositionMode || (this.selectionStart = e.selectionStart),
                    this.updateTextareaPosition());
            },
            updateTextareaPosition: function () {
                var e;
                this.selectionStart === this.selectionEnd && ((e = this._calcTextareaPosition()), (this.hiddenTextarea.style.left = e.left), (this.hiddenTextarea.style.top = e.top));
            },
            _calcTextareaPosition: function () {
                if (!this.canvas) return { x: 1, y: 1 };
                var e = this.inCompositionMode ? this.compositionStart : this.selectionStart,
                    t = this._getCursorBoundaries(e),
                    i = (a = this.get2DCursorLocation(e)).lineIndex,
                    o = a.charIndex,
                    n = this.getValueOfPropertyAt(i, o, "fontSize") * this.lineHeight,
                    r = t.leftOffset,
                    s = this.calcTransformMatrix(),
                    a = ((e = { x: t.left + r, y: t.top + t.topOffset + n }), this.canvas.getRetinaScaling());
                (t = (o = (i = this.canvas.upperCanvasEl).width / a) - n), (a = (r = i.height / a) - n), (o = i.clientWidth / o), (r = i.clientHeight / r), (e = fabric.util.transformPoint(e, s));
                return (
                    ((e = fabric.util.transformPoint(e, this.canvas.viewportTransform)).x *= o),
                    (e.y *= r),
                    e.x < 0 && (e.x = 0),
                    e.x > t && (e.x = t),
                    e.y < 0 && (e.y = 0),
                    e.y > a && (e.y = a),
                    (e.x += this.canvas._offset.left),
                    (e.y += this.canvas._offset.top),
                    { left: e.x + "px", top: e.y + "px", fontSize: n + "px", charHeight: n }
                );
            },
            _saveEditingProps: function () {
                this._savedProps = {
                    hasControls: this.hasControls,
                    borderColor: this.borderColor,
                    lockMovementX: this.lockMovementX,
                    lockMovementY: this.lockMovementY,
                    hoverCursor: this.hoverCursor,
                    selectable: this.selectable,
                    defaultCursor: this.canvas && this.canvas.defaultCursor,
                    moveCursor: this.canvas && this.canvas.moveCursor,
                };
            },
            _restoreEditingProps: function () {
                this._savedProps &&
                    ((this.hoverCursor = this._savedProps.hoverCursor),
                    (this.hasControls = this._savedProps.hasControls),
                    (this.borderColor = this._savedProps.borderColor),
                    (this.selectable = this._savedProps.selectable),
                    (this.lockMovementX = this._savedProps.lockMovementX),
                    (this.lockMovementY = this._savedProps.lockMovementY),
                    this.canvas && ((this.canvas.defaultCursor = this._savedProps.defaultCursor), (this.canvas.moveCursor = this._savedProps.moveCursor)));
            },
            exitEditing: function () {
                var e = this._textBeforeEdit !== this.text,
                    t = this.hiddenTextarea;
                return (
                    (this.selected = !1),
                    (this.isEditing = !1),
                    (this.selectionEnd = this.selectionStart),
                    t && (t.blur && t.blur(), t.parentNode && t.parentNode.removeChild(t)),
                    (this.hiddenTextarea = null),
                    this.abortCursorAnimation(),
                    this._restoreEditingProps(),
                    (this._currentCursorOpacity = 0),
                    this._shouldClearDimensionCache() && (this.initDimensions(), this.setCoords()),
                    this.fire("editing:exited"),
                    e && this.fire("modified"),
                    this.canvas && (this.canvas.off("mouse:move", this.mouseMoveHandler), this.canvas.fire("text:editing:exited", { target: this }), e && this.canvas.fire("object:modified", { target: this })),
                    this
                );
            },
            _removeExtraneousStyles: function () {
                for (var e in this.styles) this._textLines[e] || delete this.styles[e];
            },
            removeStyleFromTo: function (e, t) {
                (e = this.get2DCursorLocation(e, !0)), (t = this.get2DCursorLocation(t, !0));
                var i = e.lineIndex,
                    o = e.charIndex,
                    n = t.lineIndex,
                    r = t.charIndex;
                if (i !== n) {
                    if (this.styles[i]) for (d = o; d < this._unwrappedTextLines[i].length; d++) delete this.styles[i][d];
                    if (this.styles[n]) for (d = r; d < this._unwrappedTextLines[n].length; d++) (c = this.styles[n][d]) && (this.styles[i] || (this.styles[i] = {}), (this.styles[i][o + d - r] = c));
                    for (d = i + 1; d <= n; d++) delete this.styles[d];
                    this.shiftLineStyles(n, i - n);
                } else if (this.styles[i]) {
                    for (var s, a, c = this.styles[i], l = r - o, d = o; d < r; d++) delete c[d];
                    for (a in this.styles[i]) r <= (s = parseInt(a, 10)) && ((c[s - l] = c[a]), delete c[a]);
                }
            },
            shiftLineStyles: function (t, i) {
                var o,
                    n = e(this.styles);
                for (o in this.styles) {
                    var r = parseInt(o, 10);
                    t < r && ((this.styles[r + i] = n[r]), n[r - i] || delete this.styles[r]);
                }
            },
            restartCursorIfNeeded: function () {
                (this._currentTickState && !this._currentTickState.isAborted && this._currentTickCompleteState && !this._currentTickCompleteState.isAborted) || this.initDelayedCursor();
            },
            insertNewlineStyleObject: function (t, i, o, n) {
                var r,
                    s,
                    a = {},
                    c = !1,
                    l = this._unwrappedTextLines[t].length === i;
                for (s in (this.shiftLineStyles(t, (o = o || 1)), this.styles[t] && (r = this.styles[t][0 === i ? i : i - 1]), this.styles[t])) {
                    var d = parseInt(s, 10);
                    i <= d && ((c = !0), (a[d - i] = this.styles[t][s]), (l && 0 === i) || delete this.styles[t][s]);
                }
                var h = !1;
                for (c && !l && ((this.styles[t + o] = a), (h = !0)), h && o--; 0 < o; ) n && n[o - 1] ? (this.styles[t + o] = { 0: e(n[o - 1]) }) : r ? (this.styles[t + o] = { 0: e(r) }) : delete this.styles[t + o], o--;
                this._forceClearCache = !0;
            },
            insertCharStyleObject: function (t, i, o, n) {
                this.styles || (this.styles = {});
                var r,
                    s = this.styles[t],
                    a = s ? e(s) : {};
                for (r in ((o = o || 1), a)) {
                    var c = parseInt(r, 10);
                    i <= c && ((s[c + o] = a[c]), a[c - o] || delete s[c]);
                }
                if (((this._forceClearCache = !0), n)) for (; o--; ) Object.keys(n[o]).length && (this.styles[t] || (this.styles[t] = {}), (this.styles[t][i + o] = e(n[o])));
                else if (s) for (var l = s[i ? i - 1 : 1]; l && o--; ) this.styles[t][i + o] = e(l);
            },
            insertNewStyleBlock: function (e, t, i) {
                for (var o = this.get2DCursorLocation(t, !0), n = [0], r = 0, s = 0; s < e.length; s++) "\n" === e[s] ? (n[++r] = 0) : n[r]++;
                for (0 < n[0] && (this.insertCharStyleObject(o.lineIndex, o.charIndex, n[0], i), (i = i && i.slice(n[0] + 1))), r && this.insertNewlineStyleObject(o.lineIndex, o.charIndex + n[0], r), s = 1; s < r; s++)
                    0 < n[s] ? this.insertCharStyleObject(o.lineIndex + s, 0, n[s], i) : i && (this.styles[o.lineIndex + s][0] = i[0]), (i = i && i.slice(n[s] + 1));
                0 < n[s] && this.insertCharStyleObject(o.lineIndex + s, 0, n[s], i);
            },
            setSelectionStartEndWithShift: function (e, t, i) {
                i <= e
                    ? (t === e ? (this._selectionDirection = "left") : "right" === this._selectionDirection && ((this._selectionDirection = "left"), (this.selectionEnd = e)), (this.selectionStart = i))
                    : e < i && i < t
                    ? "right" === this._selectionDirection
                        ? (this.selectionEnd = i)
                        : (this.selectionStart = i)
                    : (t === e ? (this._selectionDirection = "right") : "left" === this._selectionDirection && ((this._selectionDirection = "right"), (this.selectionStart = t)), (this.selectionEnd = i));
            },
            setSelectionInBoundaries: function () {
                var e = this.text.length;
                this.selectionStart > e ? (this.selectionStart = e) : this.selectionStart < 0 && (this.selectionStart = 0), this.selectionEnd > e ? (this.selectionEnd = e) : this.selectionEnd < 0 && (this.selectionEnd = 0);
            },
        });
    })(),
    fabric.util.object.extend(fabric.IText.prototype, {
        initDoubleClickSimulation: function () {
            (this.__lastClickTime = +new Date()), (this.__lastLastClickTime = +new Date()), (this.__lastPointer = {}), this.on("mousedown", this.onMouseDown);
        },
        onMouseDown: function (e) {
            var t;
            this.canvas &&
                ((this.__newClickTime = +new Date()),
                (t = e.pointer),
                this.isTripleClick(t) && (this.fire("tripleclick", e), this._stopEvent(e.e)),
                (this.__lastLastClickTime = this.__lastClickTime),
                (this.__lastClickTime = this.__newClickTime),
                (this.__lastPointer = t),
                (this.__lastIsEditing = this.isEditing),
                (this.__lastSelected = this.selected));
        },
        isTripleClick: function (e) {
            return this.__newClickTime - this.__lastClickTime < 500 && this.__lastClickTime - this.__lastLastClickTime < 500 && this.__lastPointer.x === e.x && this.__lastPointer.y === e.y;
        },
        _stopEvent: function (e) {
            e.preventDefault && e.preventDefault(), e.stopPropagation && e.stopPropagation();
        },
        initCursorSelectionHandlers: function () {
            this.initMousedownHandler(), this.initMouseupHandler(), this.initClicks();
        },
        doubleClickHandler: function (e) {
            this.isEditing && this.selectWord(this.getSelectionStartFromPointer(e.e));
        },
        tripleClickHandler: function (e) {
            this.isEditing && this.selectLine(this.getSelectionStartFromPointer(e.e));
        },
        initClicks: function () {
            this.on("mousedblclick", this.doubleClickHandler), this.on("tripleclick", this.tripleClickHandler);
        },
        _mouseDownHandler: function (e) {
            !this.canvas ||
                !this.editable ||
                (e.e.button && 1 !== e.e.button) ||
                ((this.__isMousedown = !0),
                this.selected && ((this.inCompositionMode = !1), this.setCursorByClick(e.e)),
                this.isEditing && ((this.__selectionStartOnMouseDown = this.selectionStart), this.selectionStart === this.selectionEnd && this.abortCursorAnimation(), this.renderCursorOrSelection()));
        },
        _mouseDownHandlerBefore: function (e) {
            !this.canvas || !this.editable || (e.e.button && 1 !== e.e.button) || (this.selected = this === this.canvas._activeObject);
        },
        initMousedownHandler: function () {
            this.on("mousedown", this._mouseDownHandler), this.on("mousedown:before", this._mouseDownHandlerBefore);
        },
        initMouseupHandler: function () {
            this.on("mouseup", this.mouseUpHandler);
        },
        mouseUpHandler: function (e) {
            if (((this.__isMousedown = !1), !(!this.editable || this.group || (e.transform && e.transform.actionPerformed) || (e.e.button && 1 !== e.e.button)))) {
                if (this.canvas) {
                    var t = this.canvas._activeObject;
                    if (t && t !== this) return;
                }
                this.__lastSelected && !this.__corner
                    ? ((this.selected = !1), (this.__lastSelected = !1), this.enterEditing(e.e), this.selectionStart === this.selectionEnd ? this.initDelayedCursor(!0) : this.renderCursorOrSelection())
                    : (this.selected = !0);
            }
        },
        setCursorByClick: function (e) {
            var t = this.getSelectionStartFromPointer(e),
                i = this.selectionStart,
                o = this.selectionEnd;
            e.shiftKey ? this.setSelectionStartEndWithShift(i, o, t) : ((this.selectionStart = t), (this.selectionEnd = t)), this.isEditing && (this._fireSelectionChanged(), this._updateTextarea());
        },
        getSelectionStartFromPointer: function (e) {
            for (var t = this.getLocalPointer(e), i = 0, o = 0, n = 0, r = 0, s = 0, a = 0, c = this._textLines.length; a < c && n <= t.y; a++)
                (n += this.getHeightOfLine(a) * this.scaleY), 0 < (s = a) && (r += this._textLines[a - 1].length + this.missingNewlineOffset(a - 1));
            (o = this._getLineLeftOffset(s) * this.scaleX), (e = this._textLines[s]), "rtl" === this.direction && (t.x = this.width * this.scaleX - t.x + o);
            for (var l = 0, d = e.length; l < d && ((i = o), (o += this.__charBounds[s][l].kernedWidth * this.scaleX) <= t.x); l++) r++;
            return this._getNewSelectionStartFromOffset(t, i, o, r, d);
        },
        _getNewSelectionStartFromOffset: function (e, t, i, o, n) {
            return (e = o + ((t = e.x - t) < (e = i - e.x) || e < 0 ? 0 : 1)), (e = this.flipX ? n - e : e) > this._text.length ? this._text.length : e;
        },
    }),
    fabric.util.object.extend(fabric.IText.prototype, {
        initHiddenTextarea: function () {
            (this.hiddenTextarea = fabric.document.createElement("textarea")),
                this.hiddenTextarea.setAttribute("autocapitalize", "off"),
                this.hiddenTextarea.setAttribute("autocorrect", "off"),
                this.hiddenTextarea.setAttribute("autocomplete", "off"),
                this.hiddenTextarea.setAttribute("spellcheck", "false"),
                this.hiddenTextarea.setAttribute("data-fabric-hiddentextarea", ""),
                this.hiddenTextarea.setAttribute("wrap", "off");
            var e = this._calcTextareaPosition();
            (this.hiddenTextarea.style.cssText = "position: absolute; top: " + e.top + "; left: " + e.left + "; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px; paddingｰtop: " + e.fontSize + ";"),
                (this.hiddenTextareaContainer || fabric.document.body).appendChild(this.hiddenTextarea),
                fabric.util.addListener(this.hiddenTextarea, "keydown", this.onKeyDown.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "keyup", this.onKeyUp.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "input", this.onInput.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "copy", this.copy.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "cut", this.copy.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "paste", this.paste.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "compositionstart", this.onCompositionStart.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "compositionupdate", this.onCompositionUpdate.bind(this)),
                fabric.util.addListener(this.hiddenTextarea, "compositionend", this.onCompositionEnd.bind(this)),
                !this._clickHandlerInitialized && this.canvas && (fabric.util.addListener(this.canvas.upperCanvasEl, "click", this.onClick.bind(this)), (this._clickHandlerInitialized = !0));
        },
        keysMap: { 9: "exitEditing", 27: "exitEditing", 33: "moveCursorUp", 34: "moveCursorDown", 35: "moveCursorRight", 36: "moveCursorLeft", 37: "moveCursorLeft", 38: "moveCursorUp", 39: "moveCursorRight", 40: "moveCursorDown" },
        keysMapRtl: { 9: "exitEditing", 27: "exitEditing", 33: "moveCursorUp", 34: "moveCursorDown", 35: "moveCursorLeft", 36: "moveCursorRight", 37: "moveCursorRight", 38: "moveCursorUp", 39: "moveCursorLeft", 40: "moveCursorDown" },
        ctrlKeysMapUp: { 67: "copy", 88: "cut" },
        ctrlKeysMapDown: { 65: "selectAll" },
        onClick: function () {
            this.hiddenTextarea && this.hiddenTextarea.focus();
        },
        onKeyDown: function (e) {
            if (this.isEditing) {
                var t = "rtl" === this.direction ? this.keysMapRtl : this.keysMap;
                if (e.keyCode in t) this[t[e.keyCode]](e);
                else {
                    if (!(e.keyCode in this.ctrlKeysMapDown) || (!e.ctrlKey && !e.metaKey)) return;
                    this[this.ctrlKeysMapDown[e.keyCode]](e);
                }
                e.stopImmediatePropagation(), e.preventDefault(), 33 <= e.keyCode && e.keyCode <= 40 ? ((this.inCompositionMode = !1), this.clearContextTop(), this.renderCursorOrSelection()) : this.canvas && this.canvas.requestRenderAll();
            }
        },
        onKeyUp: function (e) {
            !this.isEditing || this._copyDone || this.inCompositionMode
                ? (this._copyDone = !1)
                : e.keyCode in this.ctrlKeysMapUp && (e.ctrlKey || e.metaKey) && (this[this.ctrlKeysMapUp[e.keyCode]](e), e.stopImmediatePropagation(), e.preventDefault(), this.canvas && this.canvas.requestRenderAll());
        },
        onInput: function (e) {
            var t = this.fromPaste;
            if (((this.fromPaste = !1), e && e.stopPropagation(), this.isEditing)) {
                var i,
                    o,
                    n,
                    r = this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,
                    s = this._text.length,
                    a = r.length,
                    c = a - s,
                    l = this.selectionStart,
                    d = this.selectionEnd,
                    h = l !== d;
                if ("" === this.hiddenTextarea.value) return (this.styles = {}), this.updateFromTextArea(), this.fire("changed"), void (this.canvas && (this.canvas.fire("text:changed", { target: this }), this.canvas.requestRenderAll()));
                var u = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value);
                e = l > u.selectionStart;
                h ? ((n = this._text.slice(l, d)), (c += d - l)) : a < s && (n = e ? this._text.slice(d + c, d) : this._text.slice(l, l - c)),
                    (u = r.slice(u.selectionEnd - c, u.selectionEnd)),
                    n &&
                        n.length &&
                        (u.length &&
                            ((i = this.getSelectionStyles(l, l + 1, !1)),
                            (i = u.map(function () {
                                return i[0];
                            }))),
                        (n = h ? ((o = l), d) : e ? ((o = d - n.length), d) : (o = d) + n.length),
                        this.removeStyleFromTo(o, n)),
                    u.length && (t && u.join("") === fabric.copiedText && !fabric.disableStyleCopyPaste && (i = fabric.copiedTextStyle), this.insertNewStyleBlock(u, l, i)),
                    this.updateFromTextArea(),
                    this.fire("changed"),
                    this.canvas && (this.canvas.fire("text:changed", { target: this }), this.canvas.requestRenderAll());
            }
        },
        onCompositionStart: function () {
            this.inCompositionMode = !0;
        },
        onCompositionEnd: function () {
            this.inCompositionMode = !1;
        },
        onCompositionUpdate: function (e) {
            (this.compositionStart = e.target.selectionStart), (this.compositionEnd = e.target.selectionEnd), this.updateTextareaPosition();
        },
        copy: function () {
            this.selectionStart !== this.selectionEnd &&
                ((fabric.copiedText = this.getSelectedText()),
                fabric.disableStyleCopyPaste ? (fabric.copiedTextStyle = null) : (fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, !0)),
                (this._copyDone = !0));
        },
        paste: function () {
            this.fromPaste = !0;
        },
        _getClipboardData: function (e) {
            return (e && e.clipboardData) || fabric.window.clipboardData;
        },
        _getWidthBeforeCursor: function (e, t) {
            var i = this._getLineLeftOffset(e);
            return 0 < t && (i += (t = this.__charBounds[e][t - 1]).left + t.width), i;
        },
        getDownCursorOffset: function (e, t) {
            var i = this._getSelectionForOffset(e, t),
                o = this.get2DCursorLocation(i);
            return (t = o.lineIndex) === this._textLines.length - 1 || e.metaKey || 34 === e.keyCode
                ? this._text.length - i
                : ((i = o.charIndex), (o = this._getWidthBeforeCursor(t, i)), (o = this._getIndexOnLine(t + 1, o)), this._textLines[t].slice(i).length + o + 1 + this.missingNewlineOffset(t));
        },
        _getSelectionForOffset: function (e, t) {
            return e.shiftKey && this.selectionStart !== this.selectionEnd && t ? this.selectionEnd : this.selectionStart;
        },
        getUpCursorOffset: function (e, t) {
            var i = this._getSelectionForOffset(e, t),
                o = this.get2DCursorLocation(i);
            return 0 === (t = o.lineIndex) || e.metaKey || 33 === e.keyCode
                ? -i
                : ((e = o.charIndex),
                  (i = this._getWidthBeforeCursor(t, e)),
                  (o = this._getIndexOnLine(t - 1, i)),
                  (i = this._textLines[t].slice(0, e)),
                  (e = this.missingNewlineOffset(t - 1)),
                  -this._textLines[t - 1].length + o - i.length + (1 - e));
        },
        _getIndexOnLine: function (e, t) {
            for (var i = this._textLines[e], o = this._getLineLeftOffset(e), n = 0, r = 0, s = i.length; r < s; r++)
                if (t < (o += l = this.__charBounds[e][r].width)) {
                    var a = !0,
                        c = o,
                        l = Math.abs(o - l - t);
                    n = Math.abs(c - t) < l ? r : r - 1;
                    break;
                }
            return a ? n : i.length - 1;
        },
        moveCursorDown: function (e) {
            (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) || this._moveCursorUpOrDown("Down", e);
        },
        moveCursorUp: function (e) {
            (0 === this.selectionStart && 0 === this.selectionEnd) || this._moveCursorUpOrDown("Up", e);
        },
        _moveCursorUpOrDown: function (e, t) {
            (e = this["get" + e + "CursorOffset"](t, "right" === this._selectionDirection)),
                t.shiftKey ? this.moveCursorWithShift(e) : this.moveCursorWithoutShift(e),
                0 !== e && (this.setSelectionInBoundaries(), this.abortCursorAnimation(), (this._currentCursorOpacity = 1), this.initDelayedCursor(), this._fireSelectionChanged(), this._updateTextarea());
        },
        moveCursorWithShift: function (e) {
            var t = "left" === this._selectionDirection ? this.selectionStart + e : this.selectionEnd + e;
            return this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, t), 0 !== e;
        },
        moveCursorWithoutShift: function (e) {
            return e < 0 ? ((this.selectionStart += e), (this.selectionEnd = this.selectionStart)) : ((this.selectionEnd += e), (this.selectionStart = this.selectionEnd)), 0 !== e;
        },
        moveCursorLeft: function (e) {
            (0 === this.selectionStart && 0 === this.selectionEnd) || this._moveCursorLeftOrRight("Left", e);
        },
        _move: function (e, t, i) {
            var o;
            if (e.altKey) o = this["findWordBoundary" + i](this[t]);
            else {
                if (!e.metaKey && 35 !== e.keyCode && 36 !== e.keyCode) return (this[t] += "Left" === i ? -1 : 1), !0;
                o = this["findLineBoundary" + i](this[t]);
            }
            if (this[t] !== o) return (this[t] = o), !0;
        },
        _moveLeft: function (e, t) {
            return this._move(e, t, "Left");
        },
        _moveRight: function (e, t) {
            return this._move(e, t, "Right");
        },
        moveCursorLeftWithoutShift: function (e) {
            var t = !0;
            return (this._selectionDirection = "left"), this.selectionEnd === this.selectionStart && 0 !== this.selectionStart && (t = this._moveLeft(e, "selectionStart")), (this.selectionEnd = this.selectionStart), t;
        },
        moveCursorLeftWithShift: function (e) {
            return "right" === this._selectionDirection && this.selectionStart !== this.selectionEnd
                ? this._moveLeft(e, "selectionEnd")
                : 0 !== this.selectionStart
                ? ((this._selectionDirection = "left"), this._moveLeft(e, "selectionStart"))
                : void 0;
        },
        moveCursorRight: function (e) {
            (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) || this._moveCursorLeftOrRight("Right", e);
        },
        _moveCursorLeftOrRight: function (e, t) {
            (e = "moveCursor" + e + "With"),
                (this._currentCursorOpacity = 1),
                t.shiftKey ? (e += "Shift") : (e += "outShift"),
                this[e](t) && (this.abortCursorAnimation(), this.initDelayedCursor(), this._fireSelectionChanged(), this._updateTextarea());
        },
        moveCursorRightWithShift: function (e) {
            return "left" === this._selectionDirection && this.selectionStart !== this.selectionEnd
                ? this._moveRight(e, "selectionStart")
                : this.selectionEnd !== this._text.length
                ? ((this._selectionDirection = "right"), this._moveRight(e, "selectionEnd"))
                : void 0;
        },
        moveCursorRightWithoutShift: function (e) {
            var t = !0;
            return (this._selectionDirection = "right"), this.selectionStart === this.selectionEnd ? ((t = this._moveRight(e, "selectionStart")), (this.selectionEnd = this.selectionStart)) : (this.selectionStart = this.selectionEnd), t;
        },
        removeChars: function (e, t) {
            this.removeStyleFromTo(e, (t = void 0 === t ? e + 1 : t)),
                this._text.splice(e, t - e),
                (this.text = this._text.join("")),
                this.set("dirty", !0),
                this._shouldClearDimensionCache() && (this.initDimensions(), this.setCoords()),
                this._removeExtraneousStyles();
        },
        insertChars: function (e, t, i, o) {
            i < (o = void 0 === o ? i : o) && this.removeStyleFromTo(i, o),
                (e = fabric.util.string.graphemeSplit(e)),
                this.insertNewStyleBlock(e, i, t),
                (this._text = [].concat(this._text.slice(0, i), e, this._text.slice(o))),
                (this.text = this._text.join("")),
                this.set("dirty", !0),
                this._shouldClearDimensionCache() && (this.initDimensions(), this.setCoords()),
                this._removeExtraneousStyles();
        },
    }),
    (function () {
        var e = fabric.util.toFixed,
            t = /  +/g;
        fabric.util.object.extend(fabric.Text.prototype, {
            _toSVG: function () {
                var e = this._getSVGLeftTopOffsets();
                e = this._getSVGTextAndBg(e.textTop, e.textLeft);
                return this._wrapSVGTextAndBg(e);
            },
            toSVG: function (e) {
                return this._createBaseSVGMarkup(this._toSVG(), { reviver: e, noStyle: !0, withShadow: !0 });
            },
            _getSVGLeftTopOffsets: function () {
                return { textLeft: -this.width / 2, textTop: -this.height / 2, lineTop: this.getHeightOfLine(0) };
            },
            _wrapSVGTextAndBg: function (e) {
                var t = this.getSvgTextDecoration(this);
                return [
                    e.textBgRects.join(""),
                    '\t\t<text xml:space="preserve" ',
                    this.fontFamily ? 'font-family="' + this.fontFamily.replace(/"/g, "'") + '" ' : "",
                    this.fontSize ? 'font-size="' + this.fontSize + '" ' : "",
                    this.fontStyle ? 'font-style="' + this.fontStyle + '" ' : "",
                    this.fontWeight ? 'font-weight="' + this.fontWeight + '" ' : "",
                    t ? 'text-decoration="' + t + '" ' : "",
                    'style="',
                    this.getSvgStyles(!0),
                    '"',
                    this.addPaintOrder(),
                    " >",
                    e.textSpans.join(""),
                    "</text>\n",
                ];
            },
            _getSVGTextAndBg: function (e, t) {
                var i,
                    o = [],
                    n = [],
                    r = e;
                this._setSVGBg(n);
                for (var s = 0, a = this._textLines.length; s < a; s++)
                    (i = this._getLineLeftOffset(s)), (this.textBackgroundColor || this.styleHas("textBackgroundColor", s)) && this._setSVGTextLineBg(n, s, t + i, r), this._setSVGTextLineText(o, s, t + i, r), (r += this.getHeightOfLine(s));
                return { textSpans: o, textBgRects: n };
            },
            _createTextCharSpan: function (i, o, n, r) {
                var s = i !== i.trim() || i.match(t),
                    a = (c = this.getSvgSpanStyles(o, s)) ? 'style="' + c + '"' : "",
                    c = ((s = o.deltaY), "");
                o = fabric.Object.NUM_FRACTION_DIGITS;
                return s && (c = ' dy="' + e(s, o) + '" '), ['<tspan x="', e(n, o), '" y="', e(r, o), '" ', c, a, ">", fabric.util.string.escapeXml(i), "</tspan>"].join("");
            },
            _setSVGTextLineText: function (e, t, i, o) {
                var n,
                    r,
                    s,
                    a,
                    c = this.getHeightOfLine(t),
                    l = -1 !== this.textAlign.indexOf("justify"),
                    d = "",
                    h = 0,
                    u = this._textLines[t];
                o += (c * (1 - this._fontSizeFraction)) / this.lineHeight;
                for (var f = 0, m = u.length - 1; f <= m; f++)
                    (a = f === m || this.charSpacing),
                        (d += u[f]),
                        (s = this.__charBounds[t][f]),
                        0 === h ? ((i += s.kernedWidth - s.width), (h += s.width)) : (h += s.kernedWidth),
                        (a = !(!l || a || !this._reSpaceAndTab.test(u[f])) || a) || ((n = n || this.getCompleteStyleDeclaration(t, f)), (r = this.getCompleteStyleDeclaration(t, f + 1)), (a = this._hasStyleChangedForSvg(n, r))),
                        a && ((a = this._getStyleDeclaration(t, f) || {}), e.push(this._createTextCharSpan(d, a, i, o)), (d = ""), (n = r), (i += h), (h = 0));
            },
            _pushTextBgRect: function (t, i, o, n, r, s) {
                var a = fabric.Object.NUM_FRACTION_DIGITS;
                t.push("\t\t<rect ", this._getFillAttributes(i), ' x="', e(o, a), '" y="', e(n, a), '" width="', e(r, a), '" height="', e(s, a), '"></rect>\n');
            },
            _setSVGTextLineBg: function (e, t, i, o) {
                for (var n, r, s = this._textLines[t], a = this.getHeightOfLine(t) / this.lineHeight, c = 0, l = 0, d = this.getValueOfPropertyAt(t, 0, "textBackgroundColor"), h = 0, u = s.length; h < u; h++)
                    (n = this.__charBounds[t][h]), (r = this.getValueOfPropertyAt(t, h, "textBackgroundColor")) !== d ? (d && this._pushTextBgRect(e, d, i + l, o, c, a), (l = n.left), (c = n.width), (d = r)) : (c += n.kernedWidth);
                r && this._pushTextBgRect(e, r, i + l, o, c, a);
            },
            _getFillAttributes: function (e) {
                var t = e && "string" == typeof e ? new fabric.Color(e) : "";
                return t && t.getSource() && 1 !== t.getAlpha() ? 'opacity="' + t.getAlpha() + '" fill="' + t.setAlpha(1).toRgb() + '"' : 'fill="' + e + '"';
            },
            _getSVGLineTopOffset: function (e) {
                for (var t, i = 0, o = 0; o < e; o++) i += this.getHeightOfLine(o);
                return (t = this.getHeightOfLine(o)), { lineTop: i, offset: ((this._fontSizeMult - this._fontSizeFraction) * t) / (this.lineHeight * this._fontSizeMult) };
            },
            getSvgStyles: function (e) {
                return fabric.Object.prototype.getSvgStyles.call(this, e) + " white-space: pre;";
            },
        });
    })(),
    (function (e) {
        var t = e.fabric || (e.fabric = {});
        (t.Textbox = t.util.createClass(t.IText, t.Observable, {
            type: "textbox",
            minWidth: 20,
            dynamicMinWidth: 2,
            __cachedLines: null,
            lockScalingFlip: !0,
            noScaleCache: !1,
            _dimensionAffectingProps: t.Text.prototype._dimensionAffectingProps.concat("width"),
            _wordJoiners: /[ \t\r]/,
            splitByGrapheme: !1,
            initDimensions: function () {
                this.__skipDimension ||
                    (this.isEditing && this.initDelayedCursor(),
                    this.clearContextTop(),
                    this._clearCache(),
                    (this.dynamicMinWidth = 0),
                    (this._styleMap = this._generateStyleMap(this._splitText())),
                    this.dynamicMinWidth > this.width && this._set("width", this.dynamicMinWidth),
                    -1 !== this.textAlign.indexOf("justify") && this.enlargeSpaces(),
                    (this.height = this.calcTextHeight()),
                    this.saveState({ propertySet: "_dimensionAffectingProps" }));
            },
            _generateStyleMap: function (e) {
                for (var t = 0, i = 0, o = 0, n = {}, r = 0; r < e.graphemeLines.length; r++)
                    "\n" === e.graphemeText[o] && 0 < r ? ((i = 0), o++, t++) : !this.splitByGrapheme && this._reSpaceAndTab.test(e.graphemeText[o]) && 0 < r && (i++, o++),
                        (n[r] = { line: t, offset: i }),
                        (o += e.graphemeLines[r].length),
                        (i += e.graphemeLines[r].length);
                return n;
            },
            styleHas: function (e, i) {
                var o;
                return !this._styleMap || this.isWrapping || ((o = this._styleMap[i]) && (i = o.line)), t.Text.prototype.styleHas.call(this, e, i);
            },
            isEmptyStyles: function (e) {
                if (!this.styles) return !0;
                var t,
                    i,
                    o,
                    n = 0,
                    r = !1,
                    s = this._styleMap[e],
                    a = this._styleMap[e + 1];
                for (o in (s && ((e = s.line), (n = s.offset)), a && ((r = a.line === e), (t = a.offset)), (i = void 0 === e ? this.styles : { line: this.styles[e] })))
                    for (var c in i[o]) if (n <= c && (!r || c < t)) for (var l in i[o][c]) return !1;
                return !0;
            },
            _getStyleDeclaration: function (e, t) {
                if (this._styleMap && !this.isWrapping) {
                    var i = this._styleMap[e];
                    if (!i) return null;
                    (e = i.line), (t = i.offset + t);
                }
                return this.callSuper("_getStyleDeclaration", e, t);
            },
            _setStyleDeclaration: function (e, t, i) {
                var o = this._styleMap[e];
                (e = o.line), (t = o.offset + t), (this.styles[e][t] = i);
            },
            _deleteStyleDeclaration: function (e, t) {
                var i = this._styleMap[e];
                (e = i.line), (t = i.offset + t), delete this.styles[e][t];
            },
            _getLineStyle: function (e) {
                return (e = this._styleMap[e]), !!this.styles[e.line];
            },
            _setLineStyle: function (e) {
                (e = this._styleMap[e]), (this.styles[e.line] = {});
            },
            _wrapText: function (e, t) {
                var i,
                    o = [];
                for (this.isWrapping = !0, i = 0; i < e.length; i++) o = o.concat(this._wrapLine(e[i], i, t));
                return (this.isWrapping = !1), o;
            },
            _measureWord: function (e, t, i) {
                var o,
                    n = 0;
                i = i || 0;
                for (var r = 0, s = e.length; r < s; r++) (n += this._getGraphemeBox(e[r], t, r + i, o, !0).kernedWidth), (o = e[r]);
                return n;
            },
            _wrapLine: function (e, i, o, n) {
                var r,
                    s,
                    a = 0,
                    c = this.splitByGrapheme,
                    l = [],
                    d = [],
                    h = c ? t.util.string.graphemeSplit(e) : e.split(this._wordJoiners),
                    u = 0,
                    f = c ? "" : " ",
                    m = 0,
                    g = 0,
                    p = !0,
                    v = this._getWidthOfCharSpacing();
                n = n || 0;
                0 === h.length && h.push([]), (o -= n);
                for (var b = 0; b < h.length; b++)
                    (r = c ? h[b] : t.util.string.graphemeSplit(h[b])),
                        (s = this._measureWord(r, i, u)),
                        (u += r.length),
                        o < (a += m + s - v) && !p ? (l.push(d), (d = []), (a = s), (p = !0)) : (a += v),
                        p || c || d.push(f),
                        (d = d.concat(r)),
                        (m = c ? 0 : this._measureWord([f], i, u)),
                        u++,
                        (p = !1),
                        g < s && (g = s);
                return b && l.push(d), g + n > this.dynamicMinWidth && (this.dynamicMinWidth = g - v + n), l;
            },
            isEndOfWrapping: function (e) {
                return !this._styleMap[e + 1] || this._styleMap[e + 1].line !== this._styleMap[e].line;
            },
            missingNewlineOffset: function (e) {
                return !this.splitByGrapheme || this.isEndOfWrapping(e) ? 1 : 0;
            },
            _splitTextIntoLines: function (e) {
                e = t.Text.prototype._splitTextIntoLines.call(this, e);
                for (var i = this._wrapText(e.lines, this.width), o = new Array(i.length), n = 0; n < i.length; n++) o[n] = i[n].join("");
                return (e.lines = o), (e.graphemeLines = i), e;
            },
            getMinWidth: function () {
                return Math.max(this.minWidth, this.dynamicMinWidth);
            },
            _removeExtraneousStyles: function () {
                var e,
                    t = {};
                for (e in this._styleMap) this._textLines[e] && (t[this._styleMap[e].line] = 1);
                for (e in this.styles) t[e] || delete this.styles[e];
            },
            toObject: function (e) {
                return this.callSuper("toObject", ["minWidth", "splitByGrapheme"].concat(e));
            },
        })),
            (t.Textbox.fromObject = function (e, i) {
                return t.Object._fromObject("Textbox", e, i, "text");
            });
    })("undefined" != typeof exports ? exports : this),
    (function () {
        var e = fabric.controlsUtils,
            t = e.scaleSkewCursorStyleHandler,
            i = e.scaleCursorStyleHandler,
            o = e.scalingEqually,
            n = e.scalingYOrSkewingX,
            r = e.scalingXOrSkewingY,
            s = e.scaleOrSkewActionName,
            a = fabric.Object.prototype.controls;
        (a.ml = new fabric.Control({ x: -0.5, y: 0, cursorStyleHandler: t, actionHandler: r, getActionName: s })),
            (a.mr = new fabric.Control({ x: 0.5, y: 0, cursorStyleHandler: t, actionHandler: r, getActionName: s })),
            (a.mb = new fabric.Control({ x: 0, y: 0.5, cursorStyleHandler: t, actionHandler: n, getActionName: s })),
            (a.mt = new fabric.Control({ x: 0, y: -0.5, cursorStyleHandler: t, actionHandler: n, getActionName: s })),
            (a.tl = new fabric.Control({ x: -0.5, y: -0.5, cursorStyleHandler: i, actionHandler: o })),
            (a.tr = new fabric.Control({ x: 0.5, y: -0.5, cursorStyleHandler: i, actionHandler: o })),
            (a.bl = new fabric.Control({ x: -0.5, y: 0.5, cursorStyleHandler: i, actionHandler: o })),
            (a.br = new fabric.Control({ x: 0.5, y: 0.5, cursorStyleHandler: i, actionHandler: o })),
            (a.mtr = new fabric.Control({ x: 0, y: -0.5, actionHandler: e.rotationWithSnapping, cursorStyleHandler: e.rotationStyleHandler, offsetY: -40, withConnection: !0, actionName: "rotate" })),
            fabric.Textbox &&
                (((o = fabric.Textbox.prototype.controls = {}).mtr = a.mtr),
                (o.tr = a.tr),
                (o.br = a.br),
                (o.tl = a.tl),
                (o.bl = a.bl),
                (o.mt = a.mt),
                (o.mb = a.mb),
                (o.mr = new fabric.Control({ x: 0.5, y: 0, actionHandler: e.changeWidth, cursorStyleHandler: t, actionName: "resizing" })),
                (o.ml = new fabric.Control({ x: -0.5, y: 0, actionHandler: e.changeWidth, cursorStyleHandler: t, actionName: "resizing" })));
    })();
var CryptoJS =
    CryptoJS ||
    (function (e, t) {
        var i = {},
            o = (i.lib = {}),
            n = function () {},
            r = (o.Base = {
                extend: function (e) {
                    n.prototype = this;
                    var t = new n();
                    return (
                        e && t.mixIn(e),
                        t.hasOwnProperty("init") ||
                            (t.init = function () {
                                t.$super.init.apply(this, arguments);
                            }),
                        (t.init.prototype = t),
                        (t.$super = this),
                        t
                    );
                },
                create: function () {
                    var e = this.extend();
                    return e.init.apply(e, arguments), e;
                },
                init: function () {},
                mixIn: function (e) {
                    for (var t in e) e.hasOwnProperty(t) && (this[t] = e[t]);
                    e.hasOwnProperty("toString") && (this.toString = e.toString);
                },
                clone: function () {
                    return this.init.prototype.extend(this);
                },
            }),
            s = (o.WordArray = r.extend({
                init: function (e, t) {
                    (e = this.words = e || []), (this.sigBytes = null != t ? t : 4 * e.length);
                },
                toString: function (e) {
                    return (e || c).stringify(this);
                },
                concat: function (e) {
                    var t = this.words,
                        i = e.words,
                        o = this.sigBytes;
                    if (((e = e.sigBytes), this.clamp(), o % 4)) for (var n = 0; n < e; n++) t[(o + n) >>> 2] |= ((i[n >>> 2] >>> (24 - (n % 4) * 8)) & 255) << (24 - ((o + n) % 4) * 8);
                    else if (65535 < i.length) for (n = 0; n < e; n += 4) t[(o + n) >>> 2] = i[n >>> 2];
                    else t.push.apply(t, i);
                    return (this.sigBytes += e), this;
                },
                clamp: function () {
                    var t = this.words,
                        i = this.sigBytes;
                    (t[i >>> 2] &= 4294967295 << (32 - (i % 4) * 8)), (t.length = e.ceil(i / 4));
                },
                clone: function () {
                    var e = r.clone.call(this);
                    return (e.words = this.words.slice(0)), e;
                },
                random: function (t) {
                    for (var i = [], o = 0; o < t; o += 4) i.push((4294967296 * e.random()) | 0);
                    return new s.init(i, t);
                },
            })),
            a = (i.enc = {}),
            c = (a.Hex = {
                stringify: function (e) {
                    var t = e.words;
                    e = e.sigBytes;
                    for (var i = [], o = 0; o < e; o++) {
                        var n = (t[o >>> 2] >>> (24 - (o % 4) * 8)) & 255;
                        i.push((n >>> 4).toString(16)), i.push((15 & n).toString(16));
                    }
                    return i.join("");
                },
                parse: function (e) {
                    for (var t = e.length, i = [], o = 0; o < t; o += 2) i[o >>> 3] |= parseInt(e.substr(o, 2), 16) << (24 - (o % 8) * 4);
                    return new s.init(i, t / 2);
                },
            }),
            l = (a.Latin1 = {
                stringify: function (e) {
                    var t = e.words;
                    e = e.sigBytes;
                    for (var i = [], o = 0; o < e; o++) i.push(String.fromCharCode((t[o >>> 2] >>> (24 - (o % 4) * 8)) & 255));
                    return i.join("");
                },
                parse: function (e) {
                    for (var t = e.length, i = [], o = 0; o < t; o++) i[o >>> 2] |= (255 & e.charCodeAt(o)) << (24 - (o % 4) * 8);
                    return new s.init(i, t);
                },
            }),
            d = (a.Utf8 = {
                stringify: function (e) {
                    try {
                        return decodeURIComponent(escape(l.stringify(e)));
                    } catch (e) {
                        throw Error("Malformed UTF-8 data");
                    }
                },
                parse: function (e) {
                    return l.parse(unescape(encodeURIComponent(e)));
                },
            }),
            h = (o.BufferedBlockAlgorithm = r.extend({
                reset: function () {
                    (this._data = new s.init()), (this._nDataBytes = 0);
                },
                _append: function (e) {
                    "string" == typeof e && (e = d.parse(e)), this._data.concat(e), (this._nDataBytes += e.sigBytes);
                },
                _process: function (t) {
                    var i = this._data,
                        o = i.words,
                        n = i.sigBytes,
                        r = this.blockSize,
                        a = n / (4 * r);
                    if (((t = (a = t ? e.ceil(a) : e.max((0 | a) - this._minBufferSize, 0)) * r), (n = e.min(4 * t, n)), t)) {
                        for (var c = 0; c < t; c += r) this._doProcessBlock(o, c);
                        (c = o.splice(0, t)), (i.sigBytes -= n);
                    }
                    return new s.init(c, n);
                },
                clone: function () {
                    var e = r.clone.call(this);
                    return (e._data = this._data.clone()), e;
                },
                _minBufferSize: 0,
            }));
        o.Hasher = h.extend({
            cfg: r.extend(),
            init: function (e) {
                (this.cfg = this.cfg.extend(e)), this.reset();
            },
            reset: function () {
                h.reset.call(this), this._doReset();
            },
            update: function (e) {
                return this._append(e), this._process(), this;
            },
            finalize: function (e) {
                return e && this._append(e), this._doFinalize();
            },
            blockSize: 16,
            _createHelper: function (e) {
                return function (t, i) {
                    return new e.init(i).finalize(t);
                };
            },
            _createHmacHelper: function (e) {
                return function (t, i) {
                    return new u.HMAC.init(e, i).finalize(t);
                };
            },
        });
        var u = (i.algo = {});
        return i;
    })(Math);
!(function () {
    var e = CryptoJS,
        t = e.lib.WordArray;
    e.enc.Base64 = {
        stringify: function (e) {
            var t = e.words,
                i = e.sigBytes,
                o = this._map;
            e.clamp(), (e = []);
            for (var n = 0; n < i; n += 3)
                for (
                    var r = (((t[n >>> 2] >>> (24 - (n % 4) * 8)) & 255) << 16) | (((t[(n + 1) >>> 2] >>> (24 - ((n + 1) % 4) * 8)) & 255) << 8) | ((t[(n + 2) >>> 2] >>> (24 - ((n + 2) % 4) * 8)) & 255), s = 0;
                    4 > s && n + 0.75 * s < i;
                    s++
                )
                    e.push(o.charAt((r >>> (6 * (3 - s))) & 63));
            if ((t = o.charAt(64))) for (; e.length % 4; ) e.push(t);
            return e.join("");
        },
        parse: function (e) {
            var i = e.length,
                o = this._map;
            (n = o.charAt(64)) && -1 != (n = e.indexOf(n)) && (i = n);
            for (var n = [], r = 0, s = 0; s < i; s++)
                if (s % 4) {
                    var a = o.indexOf(e.charAt(s - 1)) << ((s % 4) * 2),
                        c = o.indexOf(e.charAt(s)) >>> (6 - (s % 4) * 2);
                    (n[r >>> 2] |= (a | c) << (24 - (r % 4) * 8)), r++;
                }
            return t.create(n, r);
        },
        _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    };
})(),
    (function (e) {
        function t(e, t, i, o, n, r, s) {
            return (((e = e + ((t & i) | (~t & o)) + n + s) << r) | (e >>> (32 - r))) + t;
        }
        function i(e, t, i, o, n, r, s) {
            return (((e = e + ((t & o) | (i & ~o)) + n + s) << r) | (e >>> (32 - r))) + t;
        }
        function o(e, t, i, o, n, r, s) {
            return (((e = e + (t ^ i ^ o) + n + s) << r) | (e >>> (32 - r))) + t;
        }
        function n(e, t, i, o, n, r, s) {
            return (((e = e + (i ^ (t | ~o)) + n + s) << r) | (e >>> (32 - r))) + t;
        }
        for (var r = CryptoJS, s = (c = r.lib).WordArray, a = c.Hasher, c = r.algo, l = [], d = 0; 64 > d; d++) l[d] = (4294967296 * e.abs(e.sin(d + 1))) | 0;
        (c = c.MD5 = a.extend({
            _doReset: function () {
                this._hash = new s.init([1732584193, 4023233417, 2562383102, 271733878]);
            },
            _doProcessBlock: function (e, r) {
                for (var s = 0; 16 > s; s++) {
                    var a = e[(c = r + s)];
                    e[c] = (16711935 & ((a << 8) | (a >>> 24))) | (4278255360 & ((a << 24) | (a >>> 8)));
                }
                s = this._hash.words;
                var c = e[r + 0],
                    d = ((a = e[r + 1]), e[r + 2]),
                    h = e[r + 3],
                    u = e[r + 4],
                    f = e[r + 5],
                    m = e[r + 6],
                    g = e[r + 7],
                    p = e[r + 8],
                    v = e[r + 9],
                    b = e[r + 10],
                    y = e[r + 11],
                    S = e[r + 12],
                    w = e[r + 13],
                    _ = e[r + 14],
                    C = e[r + 15],
                    x = t((x = s[0]), (R = s[1]), (k = s[2]), (T = s[3]), c, 7, l[0]),
                    T = t(T, x, R, k, a, 12, l[1]),
                    k = t(k, T, x, R, d, 17, l[2]),
                    R = t(R, k, T, x, h, 22, l[3]);
                (x = t(x, R, k, T, u, 7, l[4])),
                    (T = t(T, x, R, k, f, 12, l[5])),
                    (k = t(k, T, x, R, m, 17, l[6])),
                    (R = t(R, k, T, x, g, 22, l[7])),
                    (x = t(x, R, k, T, p, 7, l[8])),
                    (T = t(T, x, R, k, v, 12, l[9])),
                    (k = t(k, T, x, R, b, 17, l[10])),
                    (R = t(R, k, T, x, y, 22, l[11])),
                    (x = t(x, R, k, T, S, 7, l[12])),
                    (T = t(T, x, R, k, w, 12, l[13])),
                    (k = t(k, T, x, R, _, 17, l[14])),
                    (x = i(x, (R = t(R, k, T, x, C, 22, l[15])), k, T, a, 5, l[16])),
                    (T = i(T, x, R, k, m, 9, l[17])),
                    (k = i(k, T, x, R, y, 14, l[18])),
                    (R = i(R, k, T, x, c, 20, l[19])),
                    (x = i(x, R, k, T, f, 5, l[20])),
                    (T = i(T, x, R, k, b, 9, l[21])),
                    (k = i(k, T, x, R, C, 14, l[22])),
                    (R = i(R, k, T, x, u, 20, l[23])),
                    (x = i(x, R, k, T, v, 5, l[24])),
                    (T = i(T, x, R, k, _, 9, l[25])),
                    (k = i(k, T, x, R, h, 14, l[26])),
                    (R = i(R, k, T, x, p, 20, l[27])),
                    (x = i(x, R, k, T, w, 5, l[28])),
                    (T = i(T, x, R, k, d, 9, l[29])),
                    (k = i(k, T, x, R, g, 14, l[30])),
                    (x = o(x, (R = i(R, k, T, x, S, 20, l[31])), k, T, f, 4, l[32])),
                    (T = o(T, x, R, k, p, 11, l[33])),
                    (k = o(k, T, x, R, y, 16, l[34])),
                    (R = o(R, k, T, x, _, 23, l[35])),
                    (x = o(x, R, k, T, a, 4, l[36])),
                    (T = o(T, x, R, k, u, 11, l[37])),
                    (k = o(k, T, x, R, g, 16, l[38])),
                    (R = o(R, k, T, x, b, 23, l[39])),
                    (x = o(x, R, k, T, w, 4, l[40])),
                    (T = o(T, x, R, k, c, 11, l[41])),
                    (k = o(k, T, x, R, h, 16, l[42])),
                    (R = o(R, k, T, x, m, 23, l[43])),
                    (x = o(x, R, k, T, v, 4, l[44])),
                    (T = o(T, x, R, k, S, 11, l[45])),
                    (k = o(k, T, x, R, C, 16, l[46])),
                    (x = n(x, (R = o(R, k, T, x, d, 23, l[47])), k, T, c, 6, l[48])),
                    (T = n(T, x, R, k, g, 10, l[49])),
                    (k = n(k, T, x, R, _, 15, l[50])),
                    (R = n(R, k, T, x, f, 21, l[51])),
                    (x = n(x, R, k, T, S, 6, l[52])),
                    (T = n(T, x, R, k, h, 10, l[53])),
                    (k = n(k, T, x, R, b, 15, l[54])),
                    (R = n(R, k, T, x, a, 21, l[55])),
                    (x = n(x, R, k, T, p, 6, l[56])),
                    (T = n(T, x, R, k, C, 10, l[57])),
                    (k = n(k, T, x, R, m, 15, l[58])),
                    (R = n(R, k, T, x, w, 21, l[59])),
                    (x = n(x, R, k, T, u, 6, l[60])),
                    (T = n(T, x, R, k, y, 10, l[61])),
                    (k = n(k, T, x, R, d, 15, l[62])),
                    (R = n(R, k, T, x, v, 21, l[63]));
                (s[0] = (s[0] + x) | 0), (s[1] = (s[1] + R) | 0), (s[2] = (s[2] + k) | 0), (s[3] = (s[3] + T) | 0);
            },
            _doFinalize: function () {
                var t = this._data,
                    i = t.words,
                    o = 8 * this._nDataBytes,
                    n = 8 * t.sigBytes;
                i[n >>> 5] |= 128 << (24 - (n % 32));
                var r = e.floor(o / 4294967296);
                for (
                    i[15 + (((n + 64) >>> 9) << 4)] = (16711935 & ((r << 8) | (r >>> 24))) | (4278255360 & ((r << 24) | (r >>> 8))),
                        i[14 + (((n + 64) >>> 9) << 4)] = (16711935 & ((o << 8) | (o >>> 24))) | (4278255360 & ((o << 24) | (o >>> 8))),
                        t.sigBytes = 4 * (i.length + 1),
                        this._process(),
                        i = (t = this._hash).words,
                        o = 0;
                    4 > o;
                    o++
                )
                    (n = i[o]), (i[o] = (16711935 & ((n << 8) | (n >>> 24))) | (4278255360 & ((n << 24) | (n >>> 8))));
                return t;
            },
            clone: function () {
                var e = a.clone.call(this);
                return (e._hash = this._hash.clone()), e;
            },
        })),
            (r.MD5 = a._createHelper(c)),
            (r.HmacMD5 = a._createHmacHelper(c));
    })(Math),
    (function () {
        var e,
            t = CryptoJS,
            i = (e = t.lib).Base,
            o = e.WordArray,
            n = ((e = t.algo).EvpKDF = i.extend({
                cfg: i.extend({ keySize: 4, hasher: e.MD5, iterations: 1 }),
                init: function (e) {
                    this.cfg = this.cfg.extend(e);
                },
                compute: function (e, t) {
                    for (var i = (a = this.cfg).hasher.create(), n = o.create(), r = n.words, s = a.keySize, a = a.iterations; r.length < s; ) {
                        c && i.update(c);
                        var c = i.update(e).finalize(t);
                        i.reset();
                        for (var l = 1; l < a; l++) (c = i.finalize(c)), i.reset();
                        n.concat(c);
                    }
                    return (n.sigBytes = 4 * s), n;
                },
            }));
        t.EvpKDF = function (e, t, i) {
            return n.create(i).compute(e, t);
        };
    })(),
    CryptoJS.lib.Cipher ||
        (function (e) {
            var t = (f = CryptoJS).lib,
                i = t.Base,
                o = t.WordArray,
                n = t.BufferedBlockAlgorithm,
                r = f.enc.Base64,
                s = f.algo.EvpKDF,
                a = (t.Cipher = n.extend({
                    cfg: i.extend(),
                    createEncryptor: function (e, t) {
                        return this.create(this._ENC_XFORM_MODE, e, t);
                    },
                    createDecryptor: function (e, t) {
                        return this.create(this._DEC_XFORM_MODE, e, t);
                    },
                    init: function (e, t, i) {
                        (this.cfg = this.cfg.extend(i)), (this._xformMode = e), (this._key = t), this.reset();
                    },
                    reset: function () {
                        n.reset.call(this), this._doReset();
                    },
                    process: function (e) {
                        return this._append(e), this._process();
                    },
                    finalize: function (e) {
                        return e && this._append(e), this._doFinalize();
                    },
                    keySize: 4,
                    ivSize: 4,
                    _ENC_XFORM_MODE: 1,
                    _DEC_XFORM_MODE: 2,
                    _createHelper: function (e) {
                        return {
                            encrypt: function (t, i, o) {
                                return ("string" == typeof i ? m : u).encrypt(e, t, i, o);
                            },
                            decrypt: function (t, i, o) {
                                return ("string" == typeof i ? m : u).decrypt(e, t, i, o);
                            },
                        };
                    },
                }));
            t.StreamCipher = a.extend({
                _doFinalize: function () {
                    return this._process(!0);
                },
                blockSize: 1,
            });
            var c = (f.mode = {}),
                l = function (e, t, i) {
                    var o = this._iv;
                    o ? (this._iv = undefined) : (o = this._prevBlock);
                    for (var n = 0; n < i; n++) e[t + n] ^= o[n];
                },
                d = (t.BlockCipherMode = i.extend({
                    createEncryptor: function (e, t) {
                        return this.Encryptor.create(e, t);
                    },
                    createDecryptor: function (e, t) {
                        return this.Decryptor.create(e, t);
                    },
                    init: function (e, t) {
                        (this._cipher = e), (this._iv = t);
                    },
                })).extend();
            (d.Encryptor = d.extend({
                processBlock: function (e, t) {
                    var i = this._cipher,
                        o = i.blockSize;
                    l.call(this, e, t, o), i.encryptBlock(e, t), (this._prevBlock = e.slice(t, t + o));
                },
            })),
                (d.Decryptor = d.extend({
                    processBlock: function (e, t) {
                        var i = this._cipher,
                            o = i.blockSize,
                            n = e.slice(t, t + o);
                        i.decryptBlock(e, t), l.call(this, e, t, o), (this._prevBlock = n);
                    },
                })),
                (c = c.CBC = d),
                (d = (f.pad = {}).Pkcs7 = {
                    pad: function (e, t) {
                        for (var i, n = ((i = (i = 4 * t) - (e.sigBytes % i)) << 24) | (i << 16) | (i << 8) | i, r = [], s = 0; s < i; s += 4) r.push(n);
                        (i = o.create(r, i)), e.concat(i);
                    },
                    unpad: function (e) {
                        e.sigBytes -= 255 & e.words[(e.sigBytes - 1) >>> 2];
                    },
                }),
                (t.BlockCipher = a.extend({
                    cfg: a.cfg.extend({ mode: c, padding: d }),
                    reset: function () {
                        a.reset.call(this);
                        var e = (t = this.cfg).iv,
                            t = t.mode;
                        if (this._xformMode == this._ENC_XFORM_MODE) var i = t.createEncryptor;
                        else (i = t.createDecryptor), (this._minBufferSize = 1);
                        this._mode = i.call(t, this, e && e.words);
                    },
                    _doProcessBlock: function (e, t) {
                        this._mode.processBlock(e, t);
                    },
                    _doFinalize: function () {
                        var e = this.cfg.padding;
                        if (this._xformMode == this._ENC_XFORM_MODE) {
                            e.pad(this._data, this.blockSize);
                            var t = this._process(!0);
                        } else (t = this._process(!0)), e.unpad(t);
                        return t;
                    },
                    blockSize: 4,
                }));
            var h = (t.CipherParams = i.extend({
                    init: function (e) {
                        this.mixIn(e);
                    },
                    toString: function (e) {
                        return (e || this.formatter).stringify(this);
                    },
                })),
                u =
                    ((c = (f.format = {}).OpenSSL = {
                        stringify: function (e) {
                            var t = e.ciphertext;
                            return ((e = e.salt) ? o.create([1398893684, 1701076831]).concat(e).concat(t) : t).toString(r);
                        },
                        parse: function (e) {
                            var t = (e = r.parse(e)).words;
                            if (1398893684 == t[0] && 1701076831 == t[1]) {
                                var i = o.create(t.slice(2, 4));
                                t.splice(0, 4), (e.sigBytes -= 16);
                            }
                            return h.create({ ciphertext: e, salt: i });
                        },
                    }),
                    (t.SerializableCipher = i.extend({
                        cfg: i.extend({ format: c }),
                        encrypt: function (e, t, i, o) {
                            o = this.cfg.extend(o);
                            var n = e.createEncryptor(i, o);
                            return (t = n.finalize(t)), (n = n.cfg), h.create({ ciphertext: t, key: i, iv: n.iv, algorithm: e, mode: n.mode, padding: n.padding, blockSize: e.blockSize, formatter: o.format });
                        },
                        decrypt: function (e, t, i, o) {
                            return (o = this.cfg.extend(o)), (t = this._parse(t, o.format)), e.createDecryptor(i, o).finalize(t.ciphertext);
                        },
                        _parse: function (e, t) {
                            return "string" == typeof e ? t.parse(e, this) : e;
                        },
                    }))),
                f = ((f.kdf = {}).OpenSSL = {
                    execute: function (e, t, i, n) {
                        return n || (n = o.random(8)), (e = s.create({ keySize: t + i }).compute(e, n)), (i = o.create(e.words.slice(t), 4 * i)), (e.sigBytes = 4 * t), h.create({ key: e, iv: i, salt: n });
                    },
                }),
                m = (t.PasswordBasedCipher = u.extend({
                    cfg: u.cfg.extend({ kdf: f }),
                    encrypt: function (e, t, i, o) {
                        return (i = (o = this.cfg.extend(o)).kdf.execute(i, e.keySize, e.ivSize)), (o.iv = i.iv), (e = u.encrypt.call(this, e, t, i.key, o)).mixIn(i), e;
                    },
                    decrypt: function (e, t, i, o) {
                        return (o = this.cfg.extend(o)), (t = this._parse(t, o.format)), (i = o.kdf.execute(i, e.keySize, e.ivSize, t.salt)), (o.iv = i.iv), u.decrypt.call(this, e, t, i.key, o);
                    },
                }));
        })(),
    (function () {
        for (var e = CryptoJS, t = e.lib.BlockCipher, i = e.algo, o = [], n = [], r = [], s = [], a = [], c = [], l = [], d = [], h = [], u = [], f = [], m = 0; 256 > m; m++) f[m] = 128 > m ? m << 1 : (m << 1) ^ 283;
        var g = 0,
            p = 0;
        for (m = 0; 256 > m; m++) {
            var v = ((v = p ^ (p << 1) ^ (p << 2) ^ (p << 3) ^ (p << 4)) >>> 8) ^ (255 & v) ^ 99;
            (o[g] = v), (n[v] = g);
            var b = f[g],
                y = f[b],
                S = f[y],
                w = (257 * f[v]) ^ (16843008 * v);
            (r[g] = (w << 24) | (w >>> 8)),
                (s[g] = (w << 16) | (w >>> 16)),
                (a[g] = (w << 8) | (w >>> 24)),
                (c[g] = w),
                (w = (16843009 * S) ^ (65537 * y) ^ (257 * b) ^ (16843008 * g)),
                (l[v] = (w << 24) | (w >>> 8)),
                (d[v] = (w << 16) | (w >>> 16)),
                (h[v] = (w << 8) | (w >>> 24)),
                (u[v] = w),
                g ? ((g = b ^ f[f[f[S ^ b]]]), (p ^= f[f[p]])) : (g = p = 1);
        }
        var _ = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54];
        i = i.AES = t.extend({
            _doReset: function () {
                for (var e = (i = this._key).words, t = i.sigBytes / 4, i = 4 * ((this._nRounds = t + 6) + 1), n = (this._keySchedule = []), r = 0; r < i; r++)
                    if (r < t) n[r] = e[r];
                    else {
                        var s = n[r - 1];
                        r % t
                            ? 6 < t && 4 == r % t && (s = (o[s >>> 24] << 24) | (o[(s >>> 16) & 255] << 16) | (o[(s >>> 8) & 255] << 8) | o[255 & s])
                            : ((s = (o[(s = (s << 8) | (s >>> 24)) >>> 24] << 24) | (o[(s >>> 16) & 255] << 16) | (o[(s >>> 8) & 255] << 8) | o[255 & s]), (s ^= _[(r / t) | 0] << 24)),
                            (n[r] = n[r - t] ^ s);
                    }
                for (e = this._invKeySchedule = [], t = 0; t < i; t++) (r = i - t), (s = t % 4 ? n[r] : n[r - 4]), (e[t] = 4 > t || 4 >= r ? s : l[o[s >>> 24]] ^ d[o[(s >>> 16) & 255]] ^ h[o[(s >>> 8) & 255]] ^ u[o[255 & s]]);
            },
            encryptBlock: function (e, t) {
                this._doCryptBlock(e, t, this._keySchedule, r, s, a, c, o);
            },
            decryptBlock: function (e, t) {
                var i = e[t + 1];
                (e[t + 1] = e[t + 3]), (e[t + 3] = i), this._doCryptBlock(e, t, this._invKeySchedule, l, d, h, u, n), (i = e[t + 1]), (e[t + 1] = e[t + 3]), (e[t + 3] = i);
            },
            _doCryptBlock: function (e, t, i, o, n, r, s, a) {
                for (var c = this._nRounds, l = e[t] ^ i[0], d = e[t + 1] ^ i[1], h = e[t + 2] ^ i[2], u = e[t + 3] ^ i[3], f = 4, m = 1; m < c; m++) {
                    var g = o[l >>> 24] ^ n[(d >>> 16) & 255] ^ r[(h >>> 8) & 255] ^ s[255 & u] ^ i[f++],
                        p = o[d >>> 24] ^ n[(h >>> 16) & 255] ^ r[(u >>> 8) & 255] ^ s[255 & l] ^ i[f++],
                        v = o[h >>> 24] ^ n[(u >>> 16) & 255] ^ r[(l >>> 8) & 255] ^ s[255 & d] ^ i[f++];
                    (u = o[u >>> 24] ^ n[(l >>> 16) & 255] ^ r[(d >>> 8) & 255] ^ s[255 & h] ^ i[f++]), (l = g), (d = p), (h = v);
                }
                (g = ((a[l >>> 24] << 24) | (a[(d >>> 16) & 255] << 16) | (a[(h >>> 8) & 255] << 8) | a[255 & u]) ^ i[f++]),
                    (p = ((a[d >>> 24] << 24) | (a[(h >>> 16) & 255] << 16) | (a[(u >>> 8) & 255] << 8) | a[255 & l]) ^ i[f++]),
                    (v = ((a[h >>> 24] << 24) | (a[(u >>> 16) & 255] << 16) | (a[(l >>> 8) & 255] << 8) | a[255 & d]) ^ i[f++]),
                    (u = ((a[u >>> 24] << 24) | (a[(l >>> 16) & 255] << 16) | (a[(d >>> 8) & 255] << 8) | a[255 & h]) ^ i[f++]),
                    (e[t] = g),
                    (e[t + 1] = p),
                    (e[t + 2] = v),
                    (e[t + 3] = u);
            },
            keySize: 8,
        });
        e.AES = t._createHelper(i);
    })(),
    (function (e) {
        const t = {
            msgStore: {},
            config: {},
            persistMsgStore: function (e) {
                try {
                    localStorage.setItem("msgStore", JSON.stringify(e)), (t.msgStore = e);
                } catch (e) {}
            },
            setCss: function () {
                // let t = parsedP && parsedP.config ? parsedP.config.split(".json")[0] : "";
                // if ((parsedP && !parsedP.config && parsedP.agentId && (t = parsedP.agentId), t)) {
                //     t = "../css/" + t + ".css?v=" + e.codeVersion;
                //     var i = document.createElement("link");
                //     i.setAttribute("rel", "stylesheet"), i.setAttribute("type", "text/css"), i.setAttribute("href", t), document.getElementsByTagName("head")[0].appendChild(i);
                // }
                startRoom();
            },
            setLanguage: function (i) {
                fetch("../locales/" + i + ".json?v=" + e.codeVersion)
                    .then((e) => e.json())
                    .then((e) => {
                        t.persistMsgStore(e);
                        const i = !(!t.config.serverSide || !t.config.serverSide.checkRoom),
                            o = !(!t.config.serverSide || !t.config.serverSide.payment_enabled);
                        if (i)
                            postData("/server/script.php", { type: "getroom", isAdmin: isAdmin, roomId: room_id }).then((e) => {
                                e.text().then(function (e) {
                                    e ? t.setCss() : (hide(initialScreen), setNotify("error", t.msgStore.roomNotAllowed, "center", 1e5));
                                });
                            });
                        else if (o) {
                            postData("/server/script.php", { type: "checkpayment", agentId: parsedP && parsedP.agentId ? parsedP.agentId : "" }).then((e) => {
                                e.text().then(function (e) {
                                    e ? t.setCss() : (hide(initialScreen), setNotify("error", t.msgStore.roomNotAllowed, "center", 1e5));
                                });
                            });
                        } else t.setCss();
                    })
                    .catch((e) => {
                        console.warn("Get locales failed, trying default", e), "en_US" != i && t.setLanguage("en_US");
                    });
            },
            initMsgStore: function (e) {
                t.setLanguage(e.lang);
            },
            init: function () {
                let i = parsedP && parsedP.config ? parsedP.config.split(".json")[0] : "config";
                parsedP && !parsedP.config && parsedP.agentId && (i = parsedP.agentId),
                    fetch("../config/" + i + ".json?v=" + e.codeVersion)
                        .then((e) => e.json())
                        .then((e) => {
                            if (
                                ((t.config = e), t.config.metaTitle && (document.title = t.config.metaTitle), hrefUrl.protocol + "//" + hrefUrl.host == "https://sfu.new-dev.com" && "math" !== room_id) &&
                                ((t.config.videoScreen.exitMeetingOnTime = !0), (t.config.videoScreen.exitMeetingOnTimeAgent = !0), (t.config.videoScreen.exitMeeting = "https://sfu.new-dev.com"), (duration = 10), !checkAppointment())
                            )
                                return !1;
                            if (t.config.turnon) {
                                const e = { lang: t.config.smartVideoLanguage };
                                t.initMsgStore(e);
                            } else {
                                async function e(e = "", t = {}) {
                                    return await fetch(e, { method: "POST", mode: "cors", cache: "no-cache", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(t) });
                                }
                                e("/server/script.php", { type: "getpk" }).then((e) => {
                                    e.text().then(function (e) {
                                        t.config.turnon = e;
                                        const i = { lang: t.config.smartVideoLanguage };
                                        t.initMsgStore(i);
                                    });
                                });
                            }
                        })
                        .catch((e) => {
                            (parsedP.config = "config"), this.init(), console.warn("Get config failed", e);
                        });
            },
        };
        e.smartVideo = t;
    })(window),
    smartVideo.init();

