Skip to content
Snippets Groups Projects
fabric.min.js 361 KiB
Newer Older
Carsten  Rose's avatar
Carsten Rose committed
5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000

            var d = t.getContext("2d"), g = d.getImageData(0, 0, e, o), p = d.getImageData(0, 0, a, l), v = g.data, b = p.data, m = u(this.lanczosLobes), y = this.rcpScaleX, _ = this.rcpScaleY, x = 2 / this.rcpScaleX, C = 2 / this.rcpScaleY, S = c(y * this.lanczosLobes / 2), w = c(_ * this.lanczosLobes / 2), O = {}, T = {}, j = {};
            return f(0)
        },
        bilinearFiltering: function (t, e, i, n, s) {
            var o, a, h, c, l, u, f, d, g, p, v, b, m, y = 0, _ = this.rcpScaleX, x = this.rcpScaleY, C = t.getContext("2d"), S = 4 * (e - 1), w = C.getImageData(0, 0, e, i), O = w.data, T = C.getImageData(0, 0, n, s), j = T.data;
            for (f = 0; f < s; f++)for (d = 0; d < n; d++)for (l = r(_ * d), u = r(x * f), g = _ * d - l, p = x * f - u, m = 4 * (u * e + l), v = 0; v < 4; v++)o = O[m + v], a = O[m + 4 + v], h = O[m + S + v], c = O[m + S + 4 + v], b = o * (1 - g) * (1 - p) + a * g * (1 - p) + h * p * (1 - g) + c * g * p, j[y++] = b;
            return T
        },
        hermiteFastResize: function (t, e, i, o, a) {
            for (var h = this.rcpScaleX, l = this.rcpScaleY, u = c(h / 2), f = c(l / 2), d = t.getContext("2d"), g = d.getImageData(0, 0, e, i), p = g.data, v = d.getImageData(0, 0, o, a), b = v.data, m = 0; m < a; m++)for (var y = 0; y < o; y++) {
                for (var _ = 4 * (y + m * o), x = 0, C = 0, S = 0, w = 0, O = 0, T = 0, j = 0, k = (m + .5) * l, M = r(m * l); M < (m + 1) * l; M++)for (var D = s(k - (M + .5)) / f, A = (y + .5) * h, P = D * D, E = r(y * h); E < (y + 1) * h; E++) {
                    var I = s(A - (E + .5)) / u, L = n(P + I * I);
                    L > 1 && L < -1 || (x = 2 * L * L * L - 3 * L * L + 1, x > 0 && (I = 4 * (E + M * e), j += x * p[I + 3], S += x, p[I + 3] < 255 && (x = x * p[I + 3] / 250), w += x * p[I], O += x * p[I + 1], T += x * p[I + 2], C += x))
                }
                b[_] = w / C, b[_ + 1] = O / C, b[_ + 2] = T / C, b[_ + 3] = j / S
            }
            return v
        },
        toObject: function () {
            return {
                type: this.type,
                scaleX: this.scaleX,
                scaleY: this.scaleY,
                resizeType: this.resizeType,
                lanczosLobes: this.lanczosLobes
            }
        }
    }), e.Image.filters.Resize.fromObject = e.Image.filters.BaseFilter.fromObject
}("undefined" != typeof exports ? exports : this),function (t) {
    "use strict";
    var e = t.fabric || (t.fabric = {}), i = e.util.object.extend, r = e.Image.filters, n = e.util.createClass;
    r.ColorMatrix = n(r.BaseFilter, {
        type: "ColorMatrix", initialize: function (t) {
            t || (t = {}), this.matrix = t.matrix || [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
        }, applyTo: function (t) {
            var e, i, r, n, s, o = t.getContext("2d"), a = o.getImageData(0, 0, t.width, t.height), h = a.data, c = h.length, l = this.matrix;
            for (e = 0; e < c; e += 4)i = h[e], r = h[e + 1], n = h[e + 2], s = h[e + 3], h[e] = i * l[0] + r * l[1] + n * l[2] + s * l[3] + l[4], h[e + 1] = i * l[5] + r * l[6] + n * l[7] + s * l[8] + l[9], h[e + 2] = i * l[10] + r * l[11] + n * l[12] + s * l[13] + l[14], h[e + 3] = i * l[15] + r * l[16] + n * l[17] + s * l[18] + l[19];
            o.putImageData(a, 0, 0)
        }, toObject: function () {
            return i(this.callSuper("toObject"), {type: this.type, matrix: this.matrix})
        }
    }), e.Image.filters.ColorMatrix.fromObject = e.Image.filters.BaseFilter.fromObject
}("undefined" != typeof exports ? exports : this),function (t) {
    "use strict";
    var e = t.fabric || (t.fabric = {}), i = e.util.object.extend, r = e.Image.filters, n = e.util.createClass;
    r.Contrast = n(r.BaseFilter, {
        type: "Contrast", initialize: function (t) {
            t = t || {}, this.contrast = t.contrast || 0
        }, applyTo: function (t) {
            for (var e = t.getContext("2d"), i = e.getImageData(0, 0, t.width, t.height), r = i.data, n = 259 * (this.contrast + 255) / (255 * (259 - this.contrast)), s = 0, o = r.length; s < o; s += 4)r[s] = n * (r[s] - 128) + 128, r[s + 1] = n * (r[s + 1] - 128) + 128, r[s + 2] = n * (r[s + 2] - 128) + 128;
            e.putImageData(i, 0, 0)
        }, toObject: function () {
            return i(this.callSuper("toObject"), {contrast: this.contrast})
        }
    }), e.Image.filters.Contrast.fromObject = e.Image.filters.BaseFilter.fromObject
}("undefined" != typeof exports ? exports : this),function (t) {
    "use strict";
    var e = t.fabric || (t.fabric = {}), i = e.util.object.extend, r = e.Image.filters, n = e.util.createClass;
    r.Saturate = n(r.BaseFilter, {
        type: "Saturate", initialize: function (t) {
            t = t || {}, this.saturate = t.saturate || 0
        }, applyTo: function (t) {
            for (var e, i = t.getContext("2d"), r = i.getImageData(0, 0, t.width, t.height), n = r.data, s = .01 * -this.saturate, o = 0, a = n.length; o < a; o += 4)e = Math.max(n[o], n[o + 1], n[o + 2]), n[o] += e !== n[o] ? (e - n[o]) * s : 0, n[o + 1] += e !== n[o + 1] ? (e - n[o + 1]) * s : 0, n[o + 2] += e !== n[o + 2] ? (e - n[o + 2]) * s : 0;
            i.putImageData(r, 0, 0)
        }, toObject: function () {
            return i(this.callSuper("toObject"), {saturate: this.saturate})
        }
    }), e.Image.filters.Saturate.fromObject = e.Image.filters.BaseFilter.fromObject
}("undefined" != typeof exports ? exports : this),function (t) {
    "use strict";
    var e = t.fabric || (t.fabric = {}), i = e.util.toFixed, r = e.Object.NUM_FRACTION_DIGITS, n = 2;
    if (e.Text)return void e.warn("fabric.Text is already defined");
    var s = e.Object.prototype.stateProperties.concat();
    s.push("fontFamily", "fontWeight", "fontSize", "text", "textDecoration", "textAlign", "fontStyle", "lineHeight", "textBackgroundColor", "charSpacing");
    var o = e.Object.prototype.cacheProperties.concat();
    o.push("fontFamily", "fontWeight", "fontSize", "text", "textDecoration", "textAlign", "fontStyle", "lineHeight", "textBackgroundColor", "charSpacing", "styles"), e.Text = e.util.createClass(e.Object, {
        _dimensionAffectingProps: ["fontSize", "fontWeight", "fontFamily", "fontStyle", "lineHeight", "text", "charSpacing", "textAlign"],
        _reNewline: /\r?\n/,
        _reSpacesAndTabs: /[ \t\r]+/g,
        type: "text",
        fontSize: 40,
        fontWeight: "normal",
        fontFamily: "Times New Roman",
        textDecoration: "",
        textAlign: "left",
        fontStyle: "",
        lineHeight: 1.16,
        textBackgroundColor: "",
        stateProperties: s,
        cacheProperties: o,
        stroke: null,
        shadow: null,
        _fontSizeFraction: .25,
        _fontSizeMult: 1.13,
        charSpacing: 0,
        initialize: function (t, e) {
            e = e || {}, this.text = t, this.__skipDimension = !0, this.callSuper("initialize", e), this.__skipDimension = !1, this._initDimensions(), this.setCoords(), this.setupState({propertySet: "_dimensionAffectingProps"})
        },
        _initDimensions: function (t) {
            this.__skipDimension || (t || (t = e.util.createCanvasElement().getContext("2d"), this._setTextStyles(t)), this._textLines = this._splitTextIntoLines(), this._clearCache(), this.width = this._getTextWidth(t) || this.cursorWidth || n, this.height = this._getTextHeight(t))
        },
        toString: function () {
            return "#<fabric.Text (" + this.complexity() + '): { "text": "' + this.text + '", "fontFamily": "' + this.fontFamily + '" }>'
        },
        _getCacheCanvasDimensions: function () {
            var t = this.callSuper("_getCacheCanvasDimensions"), e = this.fontSize;
            return t.width += e * t.zoomX, t.height += e * t.zoomY, t
        },
        _render: function (t) {
            this._setTextStyles(t), this.group && "path-group" === this.group.type && t.translate(this.left, this.top), this._renderTextLinesBackground(t), this._renderText(t), this._renderTextDecoration(t)
        },
        _renderText: function (t) {
            this._renderTextFill(t), this._renderTextStroke(t)
        },
        _setTextStyles: function (t) {
            t.textBaseline = "alphabetic", t.font = this._getFontDeclaration()
        },
        _getTextHeight: function () {
            return this._getHeightOfSingleLine() + (this._textLines.length - 1) * this._getHeightOfLine()
        },
        _getTextWidth: function (t) {
            for (var e = this._getLineWidth(t, 0), i = 1, r = this._textLines.length; i < r; i++) {
                var n = this._getLineWidth(t, i);
                n > e && (e = n)
            }
            return e
        },
        _renderChars: function (t, e, i, r, n) {
            var s, o, a = t.slice(0, -4);
            if (this[a].toLive) {
                var h = -this.width / 2 + this[a].offsetX || 0, c = -this.height / 2 + this[a].offsetY || 0;
                e.save(), e.translate(h, c), r -= h, n -= c
            }
            if (0 !== this.charSpacing) {
                var l = this._getWidthOfCharSpacing();
                i = i.split("");
                for (var u = 0, f = i.length; u < f; u++)s = i[u], o = e.measureText(s).width + l, e[t](s, r, n), r += o > 0 ? o : 0
            } else e[t](i, r, n);
            this[a].toLive && e.restore()
        },
        _renderTextLine: function (t, e, i, r, n, s) {
            n -= this.fontSize * this._fontSizeFraction;
            var o = this._getLineWidth(e, s);
            if ("justify" !== this.textAlign || this.width < o)return void this._renderChars(t, e, i, r, n, s);
            for (var a, h = i.split(/\s+/), c = 0, l = this._getWidthOfWords(e, h.join(" "), s, 0), u = this.width - l, f = h.length - 1, d = f > 0 ? u / f : 0, g = 0, p = 0, v = h.length; p < v; p++) {
                for (; " " === i[c] && c < i.length;)c++;
                a = h[p], this._renderChars(t, e, a, r + g, n, s, c), g += this._getWidthOfWords(e, a, s, c) + d, c += a.length
            }
        },
        _getWidthOfWords: function (t, e) {
            var i, r, n = t.measureText(e).width;
            return 0 !== this.charSpacing && (i = e.split("").length, r = i * this._getWidthOfCharSpacing(), n += r), n > 0 ? n : 0
        },
        _getLeftOffset: function () {
            return -this.width / 2
        },
        _getTopOffset: function () {
            return -this.height / 2
        },
        isEmptyStyles: function () {
            return !0
        },
        _renderTextCommon: function (t, e) {
            for (var i = 0, r = this._getLeftOffset(), n = this._getTopOffset(), s = 0, o = this._textLines.length; s < o; s++) {
                var a = this._getHeightOfLine(t, s), h = a / this.lineHeight, c = this._getLineWidth(t, s), l = this._getLineLeftOffset(c);
                this._renderTextLine(e, t, this._textLines[s], r + l, n + i + h, s), i += a
            }
        },
        _renderTextFill: function (t) {
            !this.fill && this.isEmptyStyles() || this._renderTextCommon(t, "fillText")
        },
        _renderTextStroke: function (t) {
            (this.stroke && 0 !== this.strokeWidth || !this.isEmptyStyles()) && (this.shadow && !this.shadow.affectStroke && this._removeShadow(t), t.save(), this._setLineDash(t, this.strokeDashArray), t.beginPath(), this._renderTextCommon(t, "strokeText"), t.closePath(), t.restore())
        },
        _getHeightOfLine: function () {
            return this._getHeightOfSingleLine() * this.lineHeight
        },
        _getHeightOfSingleLine: function () {
            return this.fontSize * this._fontSizeMult
        },
        _renderTextLinesBackground: function (t) {
            if (this.textBackgroundColor) {
                var e, i, r, n = 0, s = t.fillStyle;
                t.fillStyle = this.textBackgroundColor;
                for (var o = 0, a = this._textLines.length; o < a; o++)e = this._getHeightOfLine(t, o), i = this._getLineWidth(t, o), i > 0 && (r = this._getLineLeftOffset(i), t.fillRect(this._getLeftOffset() + r, this._getTopOffset() + n, i, e / this.lineHeight)), n += e;
                t.fillStyle = s, this._removeShadow(t)
            }
        },
        _getLineLeftOffset: function (t) {
            return "center" === this.textAlign ? (this.width - t) / 2 : "right" === this.textAlign ? this.width - t : 0
        },
        _clearCache: function () {
            this.__lineWidths = [], this.__lineHeights = []
        },
        _shouldClearDimensionCache: function () {
            var t = this._forceClearCache;
            return t || (t = this.hasStateChanged("_dimensionAffectingProps")), t && (this.saveState({propertySet: "_dimensionAffectingProps"}), this.dirty = !0), t
        },
        _getLineWidth: function (t, e) {
            if (this.__lineWidths[e])return this.__lineWidths[e] === -1 ? this.width : this.__lineWidths[e];
            var i, r, n = this._textLines[e];
            return i = "" === n ? 0 : this._measureLine(t, e), this.__lineWidths[e] = i, i && "justify" === this.textAlign && (r = n.split(/\s+/), r.length > 1 && (this.__lineWidths[e] = -1)), i
        },
        _getWidthOfCharSpacing: function () {
            return 0 !== this.charSpacing ? this.fontSize * this.charSpacing / 1e3 : 0
        },
        _measureLine: function (t, e) {
            var i, r, n = this._textLines[e], s = t.measureText(n).width, o = 0;
            return 0 !== this.charSpacing && (i = n.split("").length, o = (i - 1) * this._getWidthOfCharSpacing()), r = s + o, r > 0 ? r : 0
        },
        _renderTextDecoration: function (t) {
            function e(e) {
                var n, s, o, a, h, c, l, u = 0;
                for (n = 0, s = r._textLines.length; n < s; n++) {
                    for (h = r._getLineWidth(t, n), c = r._getLineLeftOffset(h), l = r._getHeightOfLine(t, n), o = 0, a = e.length; o < a; o++)t.fillRect(r._getLeftOffset() + c, u + (r._fontSizeMult - 1 + e[o]) * r.fontSize - i, h, r.fontSize / 15);
                    u += l
                }
            }

            if (this.textDecoration) {
                var i = this.height / 2, r = this, n = [];
                this.textDecoration.indexOf("underline") > -1 && n.push(.85), this.textDecoration.indexOf("line-through") > -1 && n.push(.43), this.textDecoration.indexOf("overline") > -1 && n.push(-.12), n.length > 0 && e(n)
            }
        },
        _getFontDeclaration: function () {
            return [e.isLikelyNode ? this.fontWeight : this.fontStyle, e.isLikelyNode ? this.fontStyle : this.fontWeight, this.fontSize + "px", e.isLikelyNode ? '"' + this.fontFamily + '"' : this.fontFamily].join(" ")
        },
        render: function (t, e) {
            this.visible && (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen() || (this._shouldClearDimensionCache() && (this._setTextStyles(t), this._initDimensions(t)), this.callSuper("render", t, e)))
        },
        _splitTextIntoLines: function () {
            return this.text.split(this._reNewline)
        },
        toObject: function (t) {
            var e = ["text", "fontSize", "fontWeight", "fontFamily", "fontStyle", "lineHeight", "textDecoration", "textAlign", "textBackgroundColor", "charSpacing"].concat(t);
            return this.callSuper("toObject", e)
        },
        toSVG: function (t) {
            this.ctx || (this.ctx = e.util.createCanvasElement().getContext("2d"));
            var i = this._createBaseSVGMarkup(), r = this._getSVGLeftTopOffsets(this.ctx), n = this._getSVGTextAndBg(r.textTop, r.textLeft);
            return this._wrapSVGTextAndBg(i, n), t ? t(i.join("")) : i.join("")
        },
        _getSVGLeftTopOffsets: function (t) {
            var e = this._getHeightOfLine(t, 0), i = -this.width / 2, r = 0;
            return {
                textLeft: i + (this.group && "path-group" === this.group.type ? this.left : 0),
                textTop: r + (this.group && "path-group" === this.group.type ? -this.top : 0),
                lineTop: e
            }
        },
        _wrapSVGTextAndBg: function (t, e) {
            var i = !0, r = this.getSvgFilter(), n = "" === r ? "" : ' style="' + r + '"';
            t.push("\t<g ", this.getSvgId(), 'transform="', this.getSvgTransform(), this.getSvgTransformMatrix(), '"', n, ">\n", 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 + '" ' : "", this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ' : "", 'style="', this.getSvgStyles(i), '" >\n', e.textSpans.join(""), "\t\t</text>\n", "\t</g>\n")
        },
        getSvgStyles: function (t) {
            var i = e.Object.prototype.getSvgStyles.call(this, t);
            return i + " white-space: pre;"
        },
        _getSVGTextAndBg: function (t, e) {
            var i = [], r = [], n = 0;
            this._setSVGBg(r);
            for (var s = 0, o = this._textLines.length; s < o; s++)this.textBackgroundColor && this._setSVGTextLineBg(r, s, e, t, n), this._setSVGTextLineText(s, i, n, e, t, r), n += this._getHeightOfLine(this.ctx, s);
            return {textSpans: i, textBgRects: r}
        },
        _setSVGTextLineText: function (t, n, s, o, a) {
            var h = this.fontSize * (this._fontSizeMult - this._fontSizeFraction) - a + s - this.height / 2;
            return "justify" === this.textAlign ? void this._setSVGTextLineJustifed(t, n, h, o) : void n.push('\t\t\t<tspan x="', i(o + this._getLineLeftOffset(this._getLineWidth(this.ctx, t)), r), '" ', 'y="', i(h, r), '" ', this._getFillAttributes(this.fill), ">", e.util.string.escapeXml(this._textLines[t]), "</tspan>\n")
        },
        _setSVGTextLineJustifed: function (t, n, s, o) {
            var a = e.util.createCanvasElement().getContext("2d");
            this._setTextStyles(a);
            var h, c, l = this._textLines[t], u = l.split(/\s+/), f = this._getWidthOfWords(a, u.join("")), d = this.width - f, g = u.length - 1, p = g > 0 ? d / g : 0, v = this._getFillAttributes(this.fill);
            for (o += this._getLineLeftOffset(this._getLineWidth(a, t)), t = 0, c = u.length; t < c; t++)h = u[t], n.push('\t\t\t<tspan x="', i(o, r), '" ', 'y="', i(s, r), '" ', v, ">", e.util.string.escapeXml(h), "</tspan>\n"), o += this._getWidthOfWords(a, h) + p
        },
        _setSVGTextLineBg: function (t, e, n, s, o) {
            t.push("\t\t<rect ", this._getFillAttributes(this.textBackgroundColor), ' x="', i(n + this._getLineLeftOffset(this._getLineWidth(this.ctx, e)), r), '" y="', i(o - this.height / 2, r), '" width="', i(this._getLineWidth(this.ctx, e), r), '" height="', i(this._getHeightOfLine(this.ctx, e) / this.lineHeight, r), '"></rect>\n')
        },
        _setSVGBg: function (t) {
            this.backgroundColor && t.push("\t\t<rect ", this._getFillAttributes(this.backgroundColor), ' x="', i(-this.width / 2, r), '" y="', i(-this.height / 2, r), '" width="', i(this.width, r), '" height="', i(this.height, r), '"></rect>\n')
        },
        _getFillAttributes: function (t) {
            var i = t && "string" == typeof t ? new e.Color(t) : "";
            return i && i.getSource() && 1 !== i.getAlpha() ? 'opacity="' + i.getAlpha() + '" fill="' + i.setAlpha(1).toRgb() + '"' : 'fill="' + t + '"'
        },
        _set: function (t, e) {
            this.callSuper("_set", t, e), this._dimensionAffectingProps.indexOf(t) > -1 && (this._initDimensions(), this.setCoords())
        },
        complexity: function () {
            return 1
        }
    }), e.Text.ATTRIBUTE_NAMES = e.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")), e.Text.DEFAULT_SVG_FONT_SIZE = 16, e.Text.fromElement = function (t, i) {
        if (!t)return null;
        var r = e.parseAttributes(t, e.Text.ATTRIBUTE_NAMES);
        i = e.util.object.extend(i ? e.util.object.clone(i) : {}, r), i.top = i.top || 0, i.left = i.left || 0, "dx"in r && (i.left += r.dx), "dy"in r && (i.top += r.dy), "fontSize"in i || (i.fontSize = e.Text.DEFAULT_SVG_FONT_SIZE), i.originX || (i.originX = "left");
        var n = "";
        "textContent"in t ? n = t.textContent : "firstChild"in t && null !== t.firstChild && "data"in t.firstChild && null !== t.firstChild.data && (n = t.firstChild.data), n = n.replace(/^\s+|\s+$|\n+/g, "").replace(/\s+/g, " ");
        var s = new e.Text(n, i), o = s.getHeight() / s.height, a = (s.height + s.strokeWidth) * s.lineHeight - s.height, h = a * o, c = s.getHeight() + h, l = 0;
        return "left" === s.originX && (l = s.getWidth() / 2), "right" === s.originX && (l = -s.getWidth() / 2), s.set({
            left: s.getLeft() + l,
            top: s.getTop() - c / 2 + s.fontSize * (.18 + s._fontSizeFraction) / s.lineHeight
        }), s
    }, e.Text.fromObject = function (t, i, r) {
        return e.Object._fromObject("Text", t, i, r, "text")
    }, e.util.createAccessors(e.Text)
}("undefined" != typeof exports ? exports : this),function () {
    var t = fabric.util.object.clone;
    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: "#333",
        cursorDelay: 1e3,
        cursorDuration: 600,
        styles: null,
        caching: !0,
        _reSpace: /\s|\n/,
        _currentCursorOpacity: 0,
        _selectionDirection: null,
        _abortCursorAnimation: !1,
        __widthOfSpace: [],
        initialize: function (t, e) {
            this.styles = e ? e.styles || {} : {}, this.callSuper("initialize", t, e), this.initBehavior()
        },
        _clearCache: function () {
            this.callSuper("_clearCache"), this.__widthOfSpace = []
        },
        isEmptyStyles: function () {
            if (!this.styles)return !0;
            var t = this.styles;
            for (var e in t)for (var i in t[e])for (var r in t[e][i])return !1;
            return !0
        },
        setSelectionStart: function (t) {
            t = Math.max(t, 0), this._updateAndFire("selectionStart", t)
        },
        setSelectionEnd: function (t) {
            t = Math.min(t, this.text.length), this._updateAndFire("selectionEnd", t)
        },
        _updateAndFire: function (t, e) {
            this[t] !== e && (this._fireSelectionChanged(), this[t] = e), this._updateTextarea()
        },
        _fireSelectionChanged: function () {
            this.fire("selection:changed"), this.canvas && this.canvas.fire("text:selection:changed", {target: this})
        },
        getSelectionStyles: function (t, e) {
            if (2 === arguments.length) {
                for (var i = [], r = t; r < e; r++)i.push(this.getSelectionStyles(r));
                return i
            }
            var n = this.get2DCursorLocation(t), s = this._getStyleDeclaration(n.lineIndex, n.charIndex);
            return s || {}
        },
        setSelectionStyles: function (t) {
            if (this.selectionStart === this.selectionEnd)this._extendStyles(this.selectionStart, t); else for (var e = this.selectionStart; e < this.selectionEnd; e++)this._extendStyles(e, t);
            return this._forceClearCache = !0, this
        },
        _extendStyles: function (t, e) {
            var i = this.get2DCursorLocation(t);
            this._getLineStyle(i.lineIndex) || this._setLineStyle(i.lineIndex, {}), this._getStyleDeclaration(i.lineIndex, i.charIndex) || this._setStyleDeclaration(i.lineIndex, i.charIndex, {}), fabric.util.object.extend(this._getStyleDeclaration(i.lineIndex, i.charIndex), e)
        },
        _initDimensions: function (t) {
            t || this.clearContextTop(), this.callSuper("_initDimensions", t)
        },
        render: function (t, e) {
            this.clearContextTop(), this.callSuper("render", t, e), this.cursorOffsetCache = {}, this.renderCursorOrSelection()
        },
        _render: function (t) {
            this.callSuper("_render", t), this.ctx = t
        },
        clearContextTop: function () {
            if (this.active && this.isEditing && this.canvas && this.canvas.contextTop) {
                var t = this.canvas.contextTop;
                t.save(), t.transform.apply(t, this.canvas.viewportTransform), this.transform(t), this.transformMatrix && t.transform.apply(t, this.transformMatrix), this._clearTextArea(t), t.restore()
            }
        },
        renderCursorOrSelection: function () {
            if (this.active && this.isEditing) {
                var t, e, i = this.text.split("");
                this.canvas && this.canvas.contextTop ? (e = this.canvas.contextTop, e.save(), e.transform.apply(e, this.canvas.viewportTransform), this.transform(e), this.transformMatrix && e.transform.apply(e, this.transformMatrix), this._clearTextArea(e)) : (e = this.ctx, e.save()), this.selectionStart === this.selectionEnd ? (t = this._getCursorBoundaries(i, "cursor"), this.renderCursor(t, e)) : (t = this._getCursorBoundaries(i, "selection"), this.renderSelection(i, t, e)), e.restore()
            }
        },
        _clearTextArea: function (t) {
            var e = this.width + 4, i = this.height + 4;
            t.clearRect(-e / 2, -i / 2, e, i)
        },
        get2DCursorLocation: function (t) {
            "undefined" == typeof t && (t = this.selectionStart);
            for (var e = this._textLines.length, i = 0; i < e; i++) {
                if (t <= this._textLines[i].length)return {lineIndex: i, charIndex: t};
                t -= this._textLines[i].length + 1
            }
            return {lineIndex: i - 1, charIndex: this._textLines[i - 1].length < t ? this._textLines[i - 1].length : t}
        },
        getCurrentCharStyle: function (t, e) {
            var i = this._getStyleDeclaration(t, 0 === e ? 0 : e - 1);
            return {
                fontSize: i && i.fontSize || this.fontSize,
                fill: i && i.fill || this.fill,
                textBackgroundColor: i && i.textBackgroundColor || this.textBackgroundColor,
                textDecoration: i && i.textDecoration || this.textDecoration,
                fontFamily: i && i.fontFamily || this.fontFamily,
                fontWeight: i && i.fontWeight || this.fontWeight,
                fontStyle: i && i.fontStyle || this.fontStyle,
                stroke: i && i.stroke || this.stroke,
                strokeWidth: i && i.strokeWidth || this.strokeWidth
            }
        },
        getCurrentCharFontSize: function (t, e) {
            var i = this._getStyleDeclaration(t, 0 === e ? 0 : e - 1);
            return i && i.fontSize ? i.fontSize : this.fontSize
        },
        getCurrentCharColor: function (t, e) {
            var i = this._getStyleDeclaration(t, 0 === e ? 0 : e - 1);
            return i && i.fill ? i.fill : this.cursorColor
        },
        _getCursorBoundaries: function (t, e) {
            var i = Math.round(this._getLeftOffset()), r = this._getTopOffset(), n = this._getCursorBoundariesOffsets(t, e);
            return {left: i, top: r, leftOffset: n.left + n.lineLeft, topOffset: n.top}
        },
        _getCursorBoundariesOffsets: function (t, e) {
            if (this.cursorOffsetCache && "top"in this.cursorOffsetCache)return this.cursorOffsetCache;
            for (var i, r = 0, n = 0, s = 0, o = 0, a = 0, h = 0; h < this.selectionStart; h++)"\n" === t[h] ? (a = 0, o += this._getHeightOfLine(this.ctx, n), n++, s = 0) : (a += this._getWidthOfChar(this.ctx, t[h], n, s), s++), r = this._getLineLeftOffset(this._getLineWidth(this.ctx, n));
            return "cursor" === e && (o += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, n) / this.lineHeight - this.getCurrentCharFontSize(n, s) * (1 - this._fontSizeFraction)), 0 !== this.charSpacing && s === this._textLines[n].length && (a -= this._getWidthOfCharSpacing()), i = {
                top: o,
                left: a > 0 ? a : 0,
                lineLeft: r
            }, this.cursorOffsetCache = i, this.cursorOffsetCache
        },
        renderCursor: function (t, e) {
            var i = this.get2DCursorLocation(), r = i.lineIndex, n = i.charIndex, s = this.getCurrentCharFontSize(r, n), o = t.leftOffset, a = this.scaleX * this.canvas.getZoom(), h = this.cursorWidth / a;
            e.fillStyle = this.getCurrentCharColor(r, n), e.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity, e.fillRect(t.left + o - h / 2, t.top + t.topOffset, h, s)
        },
        renderSelection: function (t, e, i) {
            i.fillStyle = this.selectionColor;
            for (var r = this.get2DCursorLocation(this.selectionStart), n = this.get2DCursorLocation(this.selectionEnd), s = r.lineIndex, o = n.lineIndex, a = s; a <= o; a++) {
                var h = this._getLineLeftOffset(this._getLineWidth(i, a)) || 0, c = this._getHeightOfLine(this.ctx, a), l = 0, u = 0, f = this._textLines[a];
                if (a === s) {
                    for (var d = 0, g = f.length; d < g; d++)d >= r.charIndex && (a !== o || d < n.charIndex) && (u += this._getWidthOfChar(i, f[d], a, d)), d < r.charIndex && (h += this._getWidthOfChar(i, f[d], a, d));
                    d === f.length && (u -= this._getWidthOfCharSpacing())
                } else if (a > s && a < o)u += this._getLineWidth(i, a) || 5; else if (a === o) {
                    for (var p = 0, v = n.charIndex; p < v; p++)u += this._getWidthOfChar(i, f[p], a, p);
                    n.charIndex === f.length && (u -= this._getWidthOfCharSpacing())
                }
                l = c, (this.lineHeight < 1 || a === o && this.lineHeight > 1) && (c /= this.lineHeight), i.fillRect(e.left + h, e.top + e.topOffset, u > 0 ? u : 0, c), e.topOffset += l
            }
        },
        _renderChars: function (t, e, i, r, n, s, o) {
            if (this.isEmptyStyles())return this._renderCharsFast(t, e, i, r, n);
            o = o || 0;
            var a, h, c = this._getHeightOfLine(e, s), l = "";
            e.save(), n -= c / this.lineHeight * this._fontSizeFraction;
            for (var u = o, f = i.length + o; u <= f; u++)a = a || this.getCurrentCharStyle(s, u), h = this.getCurrentCharStyle(s, u + 1), (this._hasStyleChanged(a, h) || u === f) && (this._renderChar(t, e, s, u - 1, l, r, n, c), l = "", a = h), l += i[u - o];
            e.restore()
        },
        _renderCharsFast: function (t, e, i, r, n) {
            "fillText" === t && this.fill && this.callSuper("_renderChars", t, e, i, r, n), "strokeText" === t && (this.stroke && this.strokeWidth > 0 || this.skipFillStrokeCheck) && this.callSuper("_renderChars", t, e, i, r, n)
        },
        _renderChar: function (t, e, i, r, n, s, o, a) {
            var h, c, l, u, f, d, g, p, v, b = this._getStyleDeclaration(i, r);
            if (b ? (c = this._getHeightOfChar(e, n, i, r), u = b.stroke, l = b.fill, d = b.textDecoration) : c = this.fontSize, u = (u || this.stroke) && "strokeText" === t, l = (l || this.fill) && "fillText" === t, b && e.save(), h = this._applyCharStylesGetWidth(e, n, i, r, b || null), d = d || this.textDecoration, b && b.textBackgroundColor && this._removeShadow(e), 0 !== this.charSpacing) {
                p = this._getWidthOfCharSpacing(), g = n.split(""), h = 0;
                for (var m, y = 0, _ = g.length; y < _; y++)m = g[y], l && e.fillText(m, s + h, o), u && e.strokeText(m, s + h, o), v = e.measureText(m).width + p, h += v > 0 ? v : 0
            } else l && e.fillText(n, s, o), u && e.strokeText(n, s, o);
            (d || "" !== d) && (f = this._fontSizeFraction * a / this.lineHeight, this._renderCharDecoration(e, d, s, o, f, h, c)), b && e.restore(), e.translate(h, 0)
        },
        _hasStyleChanged: function (t, e) {
            return t.fill !== e.fill || t.fontSize !== e.fontSize || t.textBackgroundColor !== e.textBackgroundColor || t.textDecoration !== e.textDecoration || t.fontFamily !== e.fontFamily || t.fontWeight !== e.fontWeight || t.fontStyle !== e.fontStyle || t.stroke !== e.stroke || t.strokeWidth !== e.strokeWidth
        },
        _renderCharDecoration: function (t, e, i, r, n, s, o) {
            if (e) {
                var a, h, c = o / 15, l = {
                    underline: r + o / 10,
                    "line-through": r - o * (this._fontSizeFraction + this._fontSizeMult - 1) + c,
                    overline: r - (this._fontSizeMult - this._fontSizeFraction) * o
                }, u = ["underline", "line-through", "overline"];
                for (a = 0; a < u.length; a++)h = u[a], e.indexOf(h) > -1 && t.fillRect(i, l[h], s, c)
            }
        },
        _renderTextLine: function (t, e, i, r, n, s) {
            this.isEmptyStyles() || (n += this.fontSize * (this._fontSizeFraction + .03)), this.callSuper("_renderTextLine", t, e, i, r, n, s)
        },
        _renderTextDecoration: function (t) {
            if (this.isEmptyStyles())return this.callSuper("_renderTextDecoration", t)
        },
        _renderTextLinesBackground: function (t) {
            this.callSuper("_renderTextLinesBackground", t);
            var e, i, r, n, s, o, a, h, c, l, u = 0, f = this._getLeftOffset(), d = this._getTopOffset(), g = "";
            t.save();
            for (var p = 0, v = this._textLines.length; p < v; p++)if (e = this._getHeightOfLine(t, p), n = this._textLines[p], "" !== n && this.styles && this._getLineStyle(p)) {
                i = this._getLineWidth(t, p), r = this._getLineLeftOffset(i), a = h = c = l = 0;
                for (var b = 0, m = n.length; b < m; b++)o = this._getStyleDeclaration(p, b) || {}, g !== o.textBackgroundColor && (l && c && (t.fillStyle = g, t.fillRect(a, h, c, l)), a = h = c = l = 0, g = o.textBackgroundColor || ""), o.textBackgroundColor ? (s = n[b], g === o.textBackgroundColor && (g = o.textBackgroundColor, a || (a = f + r + this._getWidthOfCharsAt(t, p, b)), h = d + u, c += this._getWidthOfChar(t, s, p, b), l = e / this.lineHeight)) : g = "";
                l && c && (t.fillStyle = g, t.fillRect(a, h, c, l), a = h = c = l = 0), u += e
            } else u += e;
            t.restore()
        },
        _getCacheProp: function (t, e) {
            return t + e.fontSize + e.fontWeight + e.fontStyle
        },
        _getFontCache: function (t) {
            return fabric.charWidthsCache[t] || (fabric.charWidthsCache[t] = {}), fabric.charWidthsCache[t]
        },
        _applyCharStylesGetWidth: function (e, i, r, n, s) {
            var o, a, h, c = s || this._getStyleDeclaration(r, n), l = t(c);
            if (this._applyFontStyles(l), h = this._getFontCache(l.fontFamily), a = this._getCacheProp(i, l), !c && h[a] && this.caching)return h[a];
            "string" == typeof l.shadow && (l.shadow = new fabric.Shadow(l.shadow));
            var u = l.fill || this.fill;
            return e.fillStyle = u.toLive ? u.toLive(e, this) : u, l.stroke && (e.strokeStyle = l.stroke && l.stroke.toLive ? l.stroke.toLive(e, this) : l.stroke), e.lineWidth = l.strokeWidth || this.strokeWidth, e.font = this._getFontDeclaration.call(l), l.shadow && (l.scaleX = this.scaleX, l.scaleY = this.scaleY, l.canvas = this.canvas, l.getObjectScaling = this.getObjectScaling, this._setShadow.call(l, e)), this.caching && h[a] ? h[a] : (o = e.measureText(i).width,
            this.caching && (h[a] = o), o)
        },
        _applyFontStyles: function (t) {
            t.fontFamily || (t.fontFamily = this.fontFamily), t.fontSize || (t.fontSize = this.fontSize), t.fontWeight || (t.fontWeight = this.fontWeight), t.fontStyle || (t.fontStyle = this.fontStyle)
        },
        _getStyleDeclaration: function (e, i, r) {
            return r ? this.styles[e] && this.styles[e][i] ? t(this.styles[e][i]) : {} : this.styles[e] && this.styles[e][i] ? this.styles[e][i] : null
        },
        _setStyleDeclaration: function (t, e, i) {
            this.styles[t][e] = i
        },
        _deleteStyleDeclaration: function (t, e) {
            delete this.styles[t][e]
        },
        _getLineStyle: function (t) {
            return this.styles[t]
        },
        _setLineStyle: function (t, e) {
            this.styles[t] = e
        },
        _deleteLineStyle: function (t) {
            delete this.styles[t]
        },
        _getWidthOfChar: function (t, e, i, r) {
            if (!this._isMeasuring && "justify" === this.textAlign && this._reSpacesAndTabs.test(e))return this._getWidthOfSpace(t, i);
            t.save();
            var n = this._applyCharStylesGetWidth(t, e, i, r);
            return 0 !== this.charSpacing && (n += this._getWidthOfCharSpacing()), t.restore(), n > 0 ? n : 0
        },
        _getHeightOfChar: function (t, e, i) {
            var r = this._getStyleDeclaration(e, i);
            return r && r.fontSize ? r.fontSize : this.fontSize
        },
        _getWidthOfCharsAt: function (t, e, i) {
            var r, n, s = 0;
            for (r = 0; r < i; r++)n = this._textLines[e][r], s += this._getWidthOfChar(t, n, e, r);
            return s
        },
        _measureLine: function (t, e) {
            this._isMeasuring = !0;
            var i = this._getWidthOfCharsAt(t, e, this._textLines[e].length);
            return 0 !== this.charSpacing && (i -= this._getWidthOfCharSpacing()), this._isMeasuring = !1, i > 0 ? i : 0
        },
        _getWidthOfSpace: function (t, e) {
            if (this.__widthOfSpace[e])return this.__widthOfSpace[e];
            var i = this._textLines[e], r = this._getWidthOfWords(t, i, e, 0), n = this.width - r, s = i.length - i.replace(this._reSpacesAndTabs, "").length, o = Math.max(n / s, t.measureText(" ").width);
            return this.__widthOfSpace[e] = o, o
        },
        _getWidthOfWords: function (t, e, i, r) {
            for (var n = 0, s = 0; s < e.length; s++) {
                var o = e[s];
                o.match(/\s/) || (n += this._getWidthOfChar(t, o, i, s + r))
            }
            return n
        },
        _getHeightOfLine: function (t, e) {
            if (this.__lineHeights[e])return this.__lineHeights[e];
            for (var i = this._textLines[e], r = this._getHeightOfChar(t, e, 0), n = 1, s = i.length; n < s; n++) {
                var o = this._getHeightOfChar(t, e, n);
                o > r && (r = o)
            }
            return this.__lineHeights[e] = r * this.lineHeight * this._fontSizeMult, this.__lineHeights[e]
        },
        _getTextHeight: function (t) {
            for (var e, i = 0, r = 0, n = this._textLines.length; r < n; r++)e = this._getHeightOfLine(t, r), i += r === n - 1 ? e / this.lineHeight : e;
            return i
        },
        toObject: function (e) {
            return fabric.util.object.extend(this.callSuper("toObject", e), {styles: t(this.styles, !0)})
        }
    }), fabric.IText.fromObject = function (t, e, i) {
        return fabric.Object._fromObject("IText", t, e, i, "text")
    }
}(),function () {
    var t = 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, this.callSuper("onDeselect")
        }, initAddedHandler: function () {
            var t = this;
            this.on("added", function () {
                var e = t.canvas;
                e && (e._hasITextHandlers || (e._hasITextHandlers = !0, t._initCanvasHandlers(e)), e._iTextInstances = e._iTextInstances || [], e._iTextInstances.push(t))
            })
        }, initRemovedHandler: function () {
            var t = this;
            this.on("removed", function () {
                var e = t.canvas;
                e && (e._iTextInstances = e._iTextInstances || [], fabric.util.removeFromArray(e._iTextInstances, t), 0 === e._iTextInstances.length && (e._hasITextHandlers = !1, t._removeCanvasHandlers(e)))
            })
        }, _initCanvasHandlers: function (t) {
            t._mouseUpITextHandler = function () {
                t._iTextInstances && t._iTextInstances.forEach(function (t) {
                    t.__isMousedown = !1
                })
            }.bind(this), t.on("mouse:up", t._mouseUpITextHandler)
        }, _removeCanvasHandlers: function (t) {
            t.off("mouse:up", t._mouseUpITextHandler)
        }, _tick: function () {
            this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, "_onTickComplete")
        }, _animateCursor: function (t, e, i, r) {
            var n;
            return n = {
                isAborted: !1, abort: function () {
                    this.isAborted = !0
                }
            }, t.animate("_currentCursorOpacity", e, {
                duration: i, onComplete: function () {
                    n.isAborted || t[r]()
                }, onChange: function () {
                    t.canvas && t.selectionStart === t.selectionEnd && t.renderCursorOrSelection()
                }, abort: function () {
                    return n.isAborted
                }
            }), n
        }, _onTickComplete: function () {
            var t = this;
            this._cursorTimeout1 && clearTimeout(this._cursorTimeout1), this._cursorTimeout1 = setTimeout(function () {
                t._currentTickCompleteState = t._animateCursor(t, 0, this.cursorDuration / 2, "_tick")
            }, 100)
        }, initDelayedCursor: function (t) {
            var e = this, i = t ? 0 : this.cursorDelay;
            this.abortCursorAnimation(), this._currentCursorOpacity = 1, this._cursorTimeout2 = setTimeout(function () {
                e._tick()
            }, i)
        }, abortCursorAnimation: function () {
            var t = this._currentTickState || this._currentTickCompleteState;
            this._currentTickState && this._currentTickState.abort(), this._currentTickCompleteState && this._currentTickCompleteState.abort(), clearTimeout(this._cursorTimeout1), clearTimeout(this._cursorTimeout2), this._currentCursorOpacity = 0, t && this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx)
        }, selectAll: function () {
            this.selectionStart = 0, this.selectionEnd = this.text.length, this._fireSelectionChanged(), this._updateTextarea()
        }, getSelectedText: function () {
            return this.text.slice(this.selectionStart, this.selectionEnd)
        }, findWordBoundaryLeft: function (t) {
            var e = 0, i = t - 1;
            if (this._reSpace.test(this.text.charAt(i)))for (; this._reSpace.test(this.text.charAt(i));)e++, i--;
            for (; /\S/.test(this.text.charAt(i)) && i > -1;)e++, i--;
            return t - e
        }, findWordBoundaryRight: function (t) {
            var e = 0, i = t;
            if (this._reSpace.test(this.text.charAt(i)))for (; this._reSpace.test(this.text.charAt(i));)e++, i++;
            for (; /\S/.test(this.text.charAt(i)) && i < this.text.length;)e++, i++;
            return t + e
        }, findLineBoundaryLeft: function (t) {
            for (var e = 0, i = t - 1; !/\n/.test(this.text.charAt(i)) && i > -1;)e++, i--;
            return t - e
        }, findLineBoundaryRight: function (t) {
            for (var e = 0, i = t; !/\n/.test(this.text.charAt(i)) && i < this.text.length;)e++, i++;
            return t + e
        }, getNumNewLinesInSelectedText: function () {
            for (var t = this.getSelectedText(), e = 0, i = 0, r = t.length; i < r; i++)"\n" === t[i] && e++;
            return e
        }, searchWordBoundary: function (t, e) {
            for (var i = this._reSpace.test(this.text.charAt(t)) ? t - 1 : t, r = this.text.charAt(i), n = /[ \n\.,;!\?\-]/; !n.test(r) && i > 0 && i < this.text.length;)i += e, r = this.text.charAt(i);
            return n.test(r) && "\n" !== r && (i += 1 === e ? 0 : 1), i
        }, selectWord: function (t) {
            t = t || this.selectionStart;
            var e = this.searchWordBoundary(t, -1), i = this.searchWordBoundary(t, 1);
            this.selectionStart = e, this.selectionEnd = i, this._fireSelectionChanged(), this._updateTextarea(), this.renderCursorOrSelection()
        }, selectLine: function (t) {
            t = t || this.selectionStart;
            var e = this.findLineBoundaryLeft(t), i = this.findLineBoundaryRight(t);
            this.selectionStart = e, this.selectionEnd = i, this._fireSelectionChanged(), this._updateTextarea()
        }, enterEditing: function (t) {
            if (!this.isEditing && this.editable)return this.canvas && this.exitEditingOnOthers(this.canvas), this.isEditing = !0, this.selected = !0, this.initHiddenTextarea(t), this.hiddenTextarea.focus(), 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.renderAll(), this) : this
        }, exitEditingOnOthers: function (t) {
            t._iTextInstances && t._iTextInstances.forEach(function (t) {
                t.selected = !1, t.isEditing && t.exitEditing()
            })
        }, initMouseMoveHandler: function () {
            this.canvas.on("mouse:move", this.mouseMoveHandler)
        }, mouseMoveHandler: function (t) {
            if (this.__isMousedown && this.isEditing) {
                var e = this.getSelectionStartFromPointer(t.e), i = this.selectionStart, r = this.selectionEnd;
                (e === this.__selectionStartOnMouseDown && i !== r || i !== e && r !== e) && (e > this.__selectionStartOnMouseDown ? (this.selectionStart = this.__selectionStartOnMouseDown, this.selectionEnd = e) : (this.selectionStart = e, this.selectionEnd = this.__selectionStartOnMouseDown), this.selectionStart === i && this.selectionEnd === r || (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
        }, _updateTextarea: function () {
            if (this.hiddenTextarea && !this.inCompositionMode && (this.cursorOffsetCache = {}, this.hiddenTextarea.value = this.text, this.hiddenTextarea.selectionStart = this.selectionStart, this.hiddenTextarea.selectionEnd = this.selectionEnd, this.selectionStart === this.selectionEnd)) {
                var t = this._calcTextareaPosition();
                this.hiddenTextarea.style.left = t.left, this.hiddenTextarea.style.top = t.top, this.hiddenTextarea.style.fontSize = t.fontSize
            }
        }, _calcTextareaPosition: function () {
            if (!this.canvas)return {x: 1, y: 1};
            var t = this.text.split(""), e = this._getCursorBoundaries(t, "cursor"), i = this.get2DCursorLocation(), r = i.lineIndex, n = i.charIndex, s = this.getCurrentCharFontSize(r, n), o = e.leftOffset, a = this.calcTransformMatrix(), h = {
                x: e.left + o,
                y: e.top + e.topOffset + s
            }, c = this.canvas.upperCanvasEl, l = c.width - s, u = c.height - s;
            return h = fabric.util.transformPoint(h, a), h = fabric.util.transformPoint(h, this.canvas.viewportTransform), h.x < 0 && (h.x = 0), h.x > l && (h.x = l), h.y < 0 && (h.y = 0), h.y > u && (h.y = u), h.x += this.canvas._offset.left, h.y += this.canvas._offset.top, {
                left: h.x + "px",
                top: h.y + "px",
                fontSize: s
            }
        }, _saveEditingProps: function () {
            this._savedProps = {
                hasControls: this.hasControls,
                borderColor: this.borderColor,
                lockMovementX: this.lockMovementX,
                lockMovementY: this.lockMovementY,
                hoverCursor: this.hoverCursor,
                defaultCursor: this.canvas && this.canvas.defaultCursor,
                moveCursor: this.canvas && this.canvas.moveCursor
            }
        }, _restoreEditingProps: function () {
            this._savedProps && (this.hoverCursor = this._savedProps.overCursor, this.hasControls = this._savedProps.hasControls, this.borderColor = this._savedProps.borderColor, 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 t = this._textBeforeEdit !== this.text;
            return this.selected = !1, this.isEditing = !1, this.selectable = !0, this.selectionEnd = this.selectionStart, this.hiddenTextarea && (this.hiddenTextarea.blur && this.hiddenTextarea.blur(), this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea), this.hiddenTextarea = null), this.abortCursorAnimation(), this._restoreEditingProps(), this._currentCursorOpacity = 0, this.fire("editing:exited"), t && this.fire("modified"), this.canvas && (this.canvas.off("mouse:move", this.mouseMoveHandler), this.canvas.fire("text:editing:exited", {target: this}), t && this.canvas.fire("object:modified", {target: this})), this
        }, _removeExtraneousStyles: function () {
            for (var t in this.styles)this._textLines[t] || delete this.styles[t]
        }, _removeCharsFromTo: function (t, e) {
            for (; e !== t;)this._removeSingleCharAndStyle(t + 1), e--;
            this.selectionStart = t, this.selectionEnd = t
        }, _removeSingleCharAndStyle: function (t) {
            var e = "\n" === this.text[t - 1], i = e ? t : t - 1;
            this.removeStyleObject(e, i), this.text = this.text.slice(0, t - 1) + this.text.slice(t), this._textLines = this._splitTextIntoLines()
        }, insertChars: function (t, e) {
            var i;
            if (this.selectionEnd - this.selectionStart > 1 && this._removeCharsFromTo(this.selectionStart, this.selectionEnd), !e && this.isEmptyStyles())return void this.insertChar(t, !1);
            for (var r = 0, n = t.length; r < n; r++)e && (i = fabric.util.object.clone(fabric.copiedTextStyle[r], !0)), this.insertChar(t[r], r < n - 1, i)
        }, insertChar: function (t, e, i) {
            var r = "\n" === this.text[this.selectionStart];
            this.text = this.text.slice(0, this.selectionStart) + t + this.text.slice(this.selectionEnd), this._textLines = this._splitTextIntoLines(), this.insertStyleObjects(t, r, i), this.selectionStart += t.length, this.selectionEnd = this.selectionStart, e || (this._updateTextarea(), this.setCoords(), this._fireSelectionChanged(), this.fire("changed"), this.restartCursorIfNeeded(), this.canvas && (this.canvas.fire("text:changed", {target: this}), this.canvas.renderAll()))
        }, restartCursorIfNeeded: function () {
            this._currentTickState && !this._currentTickState.isAborted && this._currentTickCompleteState && !this._currentTickCompleteState.isAborted || this.initDelayedCursor()
        }, insertNewlineStyleObject: function (e, i, r) {
            this.shiftLineStyles(e, 1);
            var n = {}, s = {};
            if (this.styles[e] && this.styles[e][i - 1] && (n = this.styles[e][i - 1]), r && n)s[0] = t(n), this.styles[e + 1] = s; else {
                var o = !1;
                for (var a in this.styles[e]) {
                    var h = parseInt(a, 10);
                    h >= i && (o = !0, s[h - i] = this.styles[e][a], delete this.styles[e][a])
                }
                o && (this.styles[e + 1] = s)
            }
            this._forceClearCache = !0
        }, insertCharStyleObject: function (e, i, r) {
            var n = this.styles[e], s = t(n);
            0 !== i || r || (i = 1);
            for (var o in s) {
                var a = parseInt(o, 10);
                a >= i && (n[a + 1] = s[a], s[a - 1] || delete n[a])
            }
            var h = r || t(n[i - 1]);
            h && (this.styles[e][i] = h), this._forceClearCache = !0
        }, insertStyleObjects: function (t, e, i) {
            var r = this.get2DCursorLocation(), n = r.lineIndex, s = r.charIndex;
            this._getLineStyle(n) || this._setLineStyle(n, {}), "\n" === t ? this.insertNewlineStyleObject(n, s, e) : this.insertCharStyleObject(n, s, i)
        }, shiftLineStyles: function (e, i) {
            var r = t(this.styles);
            for (var n in r) {
                var s = parseInt(n, 10);
                s <= e && delete r[s]
            }
            for (var n in this.styles) {
                var s = parseInt(n, 10);
                s > e && (this.styles[s + i] = r[s], r[s - i] || delete this.styles[s])
            }
        }, removeStyleObject: function (t, e) {
            var i = this.get2DCursorLocation(e), r = i.lineIndex, n = i.charIndex;
            this._removeStyleObject(t, i, r, n)
        }, _getTextOnPreviousLine: function (t) {
            return this._textLines[t - 1]
        }, _removeStyleObject: function (e, i, r, n) {
            if (e) {
                var s = this._getTextOnPreviousLine(i.lineIndex), o = s ? s.length : 0;
                this.styles[r - 1] || (this.styles[r - 1] = {});
                for (n in this.styles[r])this.styles[r - 1][parseInt(n, 10) + o] = this.styles[r][n];
                this.shiftLineStyles(i.lineIndex, -1)
            } else {
                var a = this.styles[r];
                a && delete a[n];
                var h = t(a);
                for (var c in h) {
                    var l = parseInt(c, 10);
                    l >= n && 0 !== l && (a[l - 1] = h[l], delete a[l])
                }
            }
        }, insertNewline: function () {
            this.insertChars("\n")
        }, setSelectionStartEndWithShift: function (t, e, i) {
            i <= t ? (e === t ? this._selectionDirection = "left" : "right" === this._selectionDirection && (this._selectionDirection = "left", this.selectionEnd = t), this.selectionStart = i) : i > t && i < e ? "right" === this._selectionDirection ? this.selectionEnd = i : this.selectionStart = i : (e === t ? this._selectionDirection = "right" : "left" === this._selectionDirection && (this._selectionDirection = "right", this.selectionStart = e), this.selectionEnd = i)
        }, setSelectionInBoundaries: function () {
            var t = this.text.length;
            this.selectionStart > t ? this.selectionStart = t : this.selectionStart < 0 && (this.selectionStart = 0), this.selectionEnd > t ? this.selectionEnd = t : 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.bind(this))
    }, onMouseDown: function (t) {
        this.__newClickTime = +new Date;
        var e = this.canvas.getPointer(t.e);
        this.isTripleClick(e, t.e) ? (this.fire("tripleclick", t), this._stopEvent(t.e)) : this.isDoubleClick(e) && (this.fire("dblclick", t), this._stopEvent(t.e)), this.__lastLastClickTime = this.__lastClickTime, this.__lastClickTime = this.__newClickTime, this.__lastPointer = e, this.__lastIsEditing = this.isEditing, this.__lastSelected = this.selected
    }, isDoubleClick: function (t) {
        return this.__newClickTime - this.__lastClickTime < 500 && this.__lastPointer.x === t.x && this.__lastPointer.y === t.y && this.__lastIsEditing
    }, isTripleClick: function (t) {
        return this.__newClickTime - this.__lastClickTime < 500 && this.__lastClickTime - this.__lastLastClickTime < 500 && this.__lastPointer.x === t.x && this.__lastPointer.y === t.y
    }, _stopEvent: function (t) {
        t.preventDefault && t.preventDefault(), t.stopPropagation && t.stopPropagation()
    }, initCursorSelectionHandlers: function () {
        this.initMousedownHandler(), this.initMouseupHandler(), this.initClicks()
    }, initClicks: function () {
        this.on("dblclick", function (t) {
            this.selectWord(this.getSelectionStartFromPointer(t.e))
        }), this.on("tripleclick", function (t) {
            this.selectLine(this.getSelectionStartFromPointer(t.e))
        })
    }, initMousedownHandler: function () {
        this.on("mousedown", function (t) {
            if (this.editable && (!t.e.button || 1 === t.e.button)) {
                var e = this.canvas.getPointer(t.e);
                this.__mousedownX = e.x, this.__mousedownY = e.y, this.__isMousedown = !0, this.selected && this.setCursorByClick(t.e), this.isEditing && (this.__selectionStartOnMouseDown = this.selectionStart, this.selectionStart === this.selectionEnd && this.abortCursorAnimation(), this.renderCursorOrSelection())
            }
        })
    }, _isObjectMoved: function (t) {
        var e = this.canvas.getPointer(t);
        return this.__mousedownX !== e.x || this.__mousedownY !== e.y
    }, initMouseupHandler: function () {
        this.on("mouseup", function (t) {
            this.__isMousedown = !1, !this.editable || this._isObjectMoved(t.e) || t.e.button && 1 !== t.e.button || (this.__lastSelected && !this.__corner && (this.enterEditing(t.e), this.selectionStart === this.selectionEnd ? this.initDelayedCursor(!0) : this.renderCursorOrSelection()), this.selected = !0)
        })
    }, setCursorByClick: function (t) {
        var e = this.getSelectionStartFromPointer(t), i = this.selectionStart, r = this.selectionEnd;
        t.shiftKey ? this.setSelectionStartEndWithShift(i, r, e) : (this.selectionStart = e, this.selectionEnd = e), this.isEditing && (this._fireSelectionChanged(), this._updateTextarea())
    }, getSelectionStartFromPointer: function (t) {
        for (var e, i, r = this.getLocalPointer(t), n = 0, s = 0, o = 0, a = 0, h = 0, c = this._textLines.length; h < c; h++) {
            i = this._textLines[h], o += this._getHeightOfLine(this.ctx, h) * this.scaleY;
            var l = this._getLineWidth(this.ctx, h), u = this._getLineLeftOffset(l);
            s = u * this.scaleX;
            for (var f = 0, d = i.length; f < d; f++) {
                if (n = s, s += this._getWidthOfChar(this.ctx, i[f], h, this.flipX ? d - f : f) * this.scaleX, !(o <= r.y || s <= r.x))return this._getNewSelectionStartFromOffset(r, n, s, a + h, d);
                a++
            }
            if (r.y < o)return this._getNewSelectionStartFromOffset(r, n, s, a + h - 1, d)
        }
        if ("undefined" == typeof e)return this.text.length
    }, _getNewSelectionStartFromOffset: function (t, e, i, r, n) {
        var s = t.x - e, o = i - t.x, a = o > s ? 0 : 1, h = r + a;
        return this.flipX && (h = n - h), h > this.text.length && (h = this.text.length), h
    }
}),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 t = this._calcTextareaPosition();
        this.hiddenTextarea.style.cssText = "position: absolute; top: " + t.top + "; left: " + t.left + "; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px; line-height: 1px; paddingーtop: " + t.fontSize + ";", 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.cut.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: {
        8: "removeChars",
        9: "exitEditing",
        27: "exitEditing",
        13: "insertNewline",
        33: "moveCursorUp",
        34: "moveCursorDown",
        35: "moveCursorRight",
        36: "moveCursorLeft",
        37: "moveCursorLeft",
        38: "moveCursorUp",
        39: "moveCursorRight",
        40: "moveCursorDown",
        46: "forwardDelete"
    },
    ctrlKeysMapUp: {67: "copy", 88: "cut"},
    ctrlKeysMapDown: {65: "selectAll"},
    onClick: function () {
        this.hiddenTextarea && this.hiddenTextarea.focus()
    },
    onKeyDown: function (t) {
        if (this.isEditing) {
            if (t.keyCode in this.keysMap)this[this.keysMap[t.keyCode]](t); else {
                if (!(t.keyCode in this.ctrlKeysMapDown && (t.ctrlKey || t.metaKey)))return;
                this[this.ctrlKeysMapDown[t.keyCode]](t)
            }
            t.stopImmediatePropagation(), t.preventDefault(), t.keyCode >= 33 && t.keyCode <= 40 ? (this.clearContextTop(), this.renderCursorOrSelection()) : this.canvas && this.canvas.renderAll()
        }
    },
    onKeyUp: function (t) {
        return !this.isEditing || this._copyDone ? void(this._copyDone = !1) : void(t.keyCode in this.ctrlKeysMapUp && (t.ctrlKey || t.metaKey) && (this[this.ctrlKeysMapUp[t.keyCode]](t), t.stopImmediatePropagation(), t.preventDefault(), this.canvas && this.canvas.renderAll()))
    },
    onInput: function (t) {
        if (this.isEditing && !this.inCompositionMode) {
            var e, i, r, n = this.selectionStart || 0, s = this.selectionEnd || 0, o = this.text.length, a = this.hiddenTextarea.value.length;
            a > o ? (r = "left" === this._selectionDirection ? s : n, e = a - o, i = this.hiddenTextarea.value.slice(r, r + e)) : (e = a - o + s - n, i = this.hiddenTextarea.value.slice(n, n + e)), this.insertChars(i), t.stopPropagation()
        }
    },
    onCompositionStart: function () {
        this.inCompositionMode = !0, this.prevCompositionLength = 0, this.compositionStart = this.selectionStart
    },
    onCompositionEnd: function () {
        this.inCompositionMode = !1
    },
    onCompositionUpdate: function (t) {
        var e = t.data;
        this.selectionStart = this.compositionStart, this.selectionEnd = this.selectionEnd === this.selectionStart ? this.compositionStart + this.prevCompositionLength : this.selectionEnd, this.insertChars(e, !1), this.prevCompositionLength = e.length
    },
    forwardDelete: function (t) {
        if (this.selectionStart === this.selectionEnd) {
            if (this.selectionStart === this.text.length)return;
            this.moveCursorRight(t)
        }
        this.removeChars(t)
    },
    copy: function (t) {
        if (this.selectionStart !== this.selectionEnd) {
            var e = this.getSelectedText(), i = this._getClipboardData(t);
            i && i.setData("text", e), fabric.copiedText = e, fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd), t.stopImmediatePropagation(), t.preventDefault(), this._copyDone = !0
        }
    },
    paste: function (t) {
        var e = null, i = this._getClipboardData(t), r = !0;
        i ? (e = i.getData("text").replace(/\r/g, ""), fabric.copiedTextStyle && fabric.copiedText === e || (r = !1)) : e = fabric.copiedText, e && this.insertChars(e, r), t.stopImmediatePropagation(), t.preventDefault()
    },
    cut: function (t) {
        this.selectionStart !== this.selectionEnd && (this.copy(t), this.removeChars(t))
    },
    _getClipboardData: function (t) {
        return t && t.clipboardData || fabric.window.clipboardData
    },
    _getWidthBeforeCursor: function (t, e) {
        for (var i, r = this._textLines[t].slice(0, e), n = this._getLineWidth(this.ctx, t), s = this._getLineLeftOffset(n), o = 0, a = r.length; o < a; o++)i = r[o], s += this._getWidthOfChar(this.ctx, i, t, o);
        return s
    },
    getDownCursorOffset: function (t, e) {
        var i = this._getSelectionForOffset(t, e), r = this.get2DCursorLocation(i), n = r.lineIndex;
        if (n === this._textLines.length - 1 || t.metaKey || 34 === t.keyCode)return this.text.length - i;
        var s = r.charIndex, o = this._getWidthBeforeCursor(n, s), a = this._getIndexOnLine(n + 1, o), h = this._textLines[n].slice(s);
        return h.length + a + 2
    },
    _getSelectionForOffset: function (t, e) {
        return t.shiftKey && this.selectionStart !== this.selectionEnd && e ? this.selectionEnd : this.selectionStart
    },
    getUpCursorOffset: function (t, e) {
        var i = this._getSelectionForOffset(t, e), r = this.get2DCursorLocation(i), n = r.lineIndex;
        if (0 === n || t.metaKey || 33 === t.keyCode)return -i;
        var s = r.charIndex, o = this._getWidthBeforeCursor(n, s), a = this._getIndexOnLine(n - 1, o), h = this._textLines[n].slice(0, s);
        return -this._textLines[n - 1].length + a - h.length
    },
    _getIndexOnLine: function (t, e) {
        for (var i, r = this._getLineWidth(this.ctx, t), n = this._textLines[t], s = this._getLineLeftOffset(r), o = s, a = 0, h = 0, c = n.length; h < c; h++) {
            var l = n[h], u = this._getWidthOfChar(this.ctx, l, t, h);
            if (o += u, o > e) {
                i = !0;
                var f = o - u, d = o, g = Math.abs(f - e), p = Math.abs(d - e);
                a = p < g ? h : h - 1;
                break
            }
        }
        return i || (a = n.length - 1), a
    },
    moveCursorDown: function (t) {
        this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length || this._moveCursorUpOrDown("Down", t)
    },
    moveCursorUp: function (t) {
        0 === this.selectionStart && 0 === this.selectionEnd || this._moveCursorUpOrDown("Up", t)
    },
    _moveCursorUpOrDown: function (t, e) {
        var i = "get" + t + "CursorOffset", r = this[i](e, "right" === this._selectionDirection);
        e.shiftKey ? this.moveCursorWithShift(r) : this.moveCursorWithoutShift(r), 0 !== r && (this.setSelectionInBoundaries(), this.abortCursorAnimation(), this._currentCursorOpacity = 1, this.initDelayedCursor(), this._fireSelectionChanged(), this._updateTextarea())
    },
    moveCursorWithShift: function (t) {
        var e = "left" === this._selectionDirection ? this.selectionStart + t : this.selectionEnd + t;
        return this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, e), 0 !== t
    },
    moveCursorWithoutShift: function (t) {
        return t < 0 ? (this.selectionStart += t, this.selectionEnd = this.selectionStart) : (this.selectionEnd += t, this.selectionStart = this.selectionEnd), 0 !== t
    },
    moveCursorLeft: function (t) {
        0 === this.selectionStart && 0 === this.selectionEnd || this._moveCursorLeftOrRight("Left", t)
    },
    _move: function (t, e, i) {
        var r;
        if (t.altKey)r = this["findWordBoundary" + i](this[e]); else {
            if (!t.metaKey && 35 !== t.keyCode && 36 !== t.keyCode)return this[e] += "Left" === i ? -1 : 1, !0;
            r = this["findLineBoundary" + i](this[e])
        }
        if (void 0 !== typeof r && this[e] !== r)return this[e] = r, !0
    },
    _moveLeft: function (t, e) {
        return this._move(t, e, "Left")
    },
    _moveRight: function (t, e) {
        return this._move(t, e, "Right")
    },
    moveCursorLeftWithoutShift: function (t) {