Skip to content
Snippets Groups Projects
fabric.min.js 361 KiB
Newer Older
Carsten  Rose's avatar
Carsten Rose committed
        var e = !0;
        return this._selectionDirection = "left", this.selectionEnd === this.selectionStart && 0 !== this.selectionStart && (e = this._moveLeft(t, "selectionStart")), this.selectionEnd = this.selectionStart, e
    },
    moveCursorLeftWithShift: function (t) {
        return "right" === this._selectionDirection && this.selectionStart !== this.selectionEnd ? this._moveLeft(t, "selectionEnd") : 0 !== this.selectionStart ? (this._selectionDirection = "left", this._moveLeft(t, "selectionStart")) : void 0
    },
    moveCursorRight: function (t) {
        this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length || this._moveCursorLeftOrRight("Right", t)
    },
    _moveCursorLeftOrRight: function (t, e) {
        var i = "moveCursor" + t + "With";
        this._currentCursorOpacity = 1, i += e.shiftKey ? "Shift" : "outShift", this[i](e) && (this.abortCursorAnimation(), this.initDelayedCursor(), this._fireSelectionChanged(), this._updateTextarea())
    },
    moveCursorRightWithShift: function (t) {
        return "left" === this._selectionDirection && this.selectionStart !== this.selectionEnd ? this._moveRight(t, "selectionStart") : this.selectionEnd !== this.text.length ? (this._selectionDirection = "right", this._moveRight(t, "selectionEnd")) : void 0
    },
    moveCursorRightWithoutShift: function (t) {
        var e = !0;
        return this._selectionDirection = "right", this.selectionStart === this.selectionEnd ? (e = this._moveRight(t, "selectionStart"), this.selectionEnd = this.selectionStart) : this.selectionStart = this.selectionEnd, e
    },
    removeChars: function (t) {
        this.selectionStart === this.selectionEnd ? this._removeCharsNearCursor(t) : this._removeCharsFromTo(this.selectionStart, this.selectionEnd), this.set("dirty", !0), this.setSelectionEnd(this.selectionStart), this._removeExtraneousStyles(), this.canvas && this.canvas.renderAll(), this.setCoords(), this.fire("changed"), this.canvas && this.canvas.fire("text:changed", {target: this})
    },
    _removeCharsNearCursor: function (t) {
        if (0 !== this.selectionStart)if (t.metaKey) {
            var e = this.findLineBoundaryLeft(this.selectionStart);
            this._removeCharsFromTo(e, this.selectionStart), this.setSelectionStart(e)
        } else if (t.altKey) {
            var i = this.findWordBoundaryLeft(this.selectionStart);
            this._removeCharsFromTo(i, this.selectionStart), this.setSelectionStart(i)
        } else this._removeSingleCharAndStyle(this.selectionStart), this.setSelectionStart(this.selectionStart - 1)
    }
}),function () {
    var t = fabric.util.toFixed, e = fabric.Object.NUM_FRACTION_DIGITS;
    fabric.util.object.extend(fabric.IText.prototype, {
        _setSVGTextLineText: function (t, e, i, r, n, s) {
            this._getLineStyle(t) ? this._setSVGTextLineChars(t, e, i, r, s) : fabric.Text.prototype._setSVGTextLineText.call(this, t, e, i, r, n)
        }, _setSVGTextLineChars: function (t, e, i, r, n) {
            for (var s = this._textLines[t], o = 0, a = this._getLineLeftOffset(this._getLineWidth(this.ctx, t)) - this.width / 2, h = this._getSVGLineTopOffset(t), c = this._getHeightOfLine(this.ctx, t), l = 0, u = s.length; l < u; l++) {
                var f = this._getStyleDeclaration(t, l) || {};
                e.push(this._createTextCharSpan(s[l], f, a, h.lineTop + h.offset, o));
                var d = this._getWidthOfChar(this.ctx, s[l], t, l);
                f.textBackgroundColor && n.push(this._createTextCharBg(f, a, h.lineTop, c, d, o)), o += d
            }
        }, _getSVGLineTopOffset: function (t) {
            for (var e = 0, i = 0, r = 0; r < t; r++)e += this._getHeightOfLine(this.ctx, r);
            return i = this._getHeightOfLine(this.ctx, r), {
                lineTop: e,
                offset: (this._fontSizeMult - this._fontSizeFraction) * i / (this.lineHeight * this._fontSizeMult)
            }
        }, _createTextCharBg: function (i, r, n, s, o, a) {
            return ['\t\t<rect fill="', i.textBackgroundColor, '" x="', t(r + a, e), '" y="', t(n - this.height / 2, e), '" width="', t(o, e), '" height="', t(s / this.lineHeight, e), '"></rect>\n'].join("")
        }, _createTextCharSpan: function (i, r, n, s, o) {
            var a = this.getSvgStyles.call(fabric.util.object.extend({
                visible: !0,
                fill: this.fill,
                stroke: this.stroke,
                type: "text",
                getSvgFilter: fabric.Object.prototype.getSvgFilter
            }, r));
            return ['\t\t\t<tspan x="', t(n + o, e), '" y="', t(s - this.height / 2, e), '" ', r.fontFamily ? 'font-family="' + r.fontFamily.replace(/"/g, "'") + '" ' : "", r.fontSize ? 'font-size="' + r.fontSize + '" ' : "", r.fontStyle ? 'font-style="' + r.fontStyle + '" ' : "", r.fontWeight ? 'font-weight="' + r.fontWeight + '" ' : "", r.textDecoration ? 'text-decoration="' + r.textDecoration + '" ' : "", 'style="', a, '">', fabric.util.string.escapeXml(i), "</tspan>\n"].join("")
        }
    })
}(),function (t) {
    "use strict";
    var e = t.fabric || (t.fabric = {});
    e.Textbox = e.util.createClass(e.IText, e.Observable, {
        type: "textbox",
        minWidth: 20,
        dynamicMinWidth: 2,
        __cachedLines: null,
        lockScalingY: !0,
        lockScalingFlip: !0,
        noScaleCache: !1,
        initialize: function (t, i) {
            this.callSuper("initialize", t, i), this.setControlsVisibility(e.Textbox.getTextboxControlVisibility()), this.ctx = this.objectCaching ? this._cacheContext : e.util.createCanvasElement().getContext("2d"), this._dimensionAffectingProps.push("width")
        },
        _initDimensions: function (t) {
            this.__skipDimension || (t || (t = e.util.createCanvasElement().getContext("2d"), this._setTextStyles(t), this.clearContextTop()), this.dynamicMinWidth = 0, this._textLines = this._splitTextIntoLines(t), this.dynamicMinWidth > this.width && this._set("width", this.dynamicMinWidth), this._clearCache(), this.height = this._getTextHeight(t))
        },
        _generateStyleMap: function () {
            for (var t = 0, e = 0, i = 0, r = {}, n = 0; n < this._textLines.length; n++)"\n" === this.text[i] && n > 0 ? (e = 0, i++, t++) : " " === this.text[i] && n > 0 && (e++, i++), r[n] = {
                line: t,
                offset: e
            }, i += this._textLines[n].length, e += this._textLines[n].length;
            return r
        },
        _getStyleDeclaration: function (t, e, i) {
            if (this._styleMap) {
                var r = this._styleMap[t];
                if (!r)return i ? {} : null;
                t = r.line, e = r.offset + e
            }
            return this.callSuper("_getStyleDeclaration", t, e, i)
        },
        _setStyleDeclaration: function (t, e, i) {
            var r = this._styleMap[t];
            t = r.line, e = r.offset + e, this.styles[t][e] = i
        },
        _deleteStyleDeclaration: function (t, e) {
            var i = this._styleMap[t];
            t = i.line, e = i.offset + e, delete this.styles[t][e]
        },
        _getLineStyle: function (t) {
            var e = this._styleMap[t];
            return this.styles[e.line]
        },
        _setLineStyle: function (t, e) {
            var i = this._styleMap[t];
            this.styles[i.line] = e
        },
        _deleteLineStyle: function (t) {
            var e = this._styleMap[t];
            delete this.styles[e.line]
        },
        _wrapText: function (t, e) {
            var i, r = e.split(this._reNewline), n = [];
            for (i = 0; i < r.length; i++)n = n.concat(this._wrapLine(t, r[i], i));
            return n
        },
        _measureText: function (t, e, i, r) {
            var n = 0;
            r = r || 0;
            for (var s = 0, o = e.length; s < o; s++)n += this._getWidthOfChar(t, e[s], i, s + r);
            return n
        },
        _wrapLine: function (t, e, i) {
            for (var r = 0, n = [], s = "", o = e.split(" "), a = "", h = 0, c = " ", l = 0, u = 0, f = 0, d = !0, g = this._getWidthOfCharSpacing(), p = 0; p < o.length; p++)a = o[p], l = this._measureText(t, a, i, h), h += a.length, r += u + l - g, r >= this.width && !d ? (n.push(s), s = "", r = l, d = !0) : r += g, d || (s += c), s += a, u = this._measureText(t, c, i, h), h++, d = !1, l > f && (f = l);
            return p && n.push(s), f > this.dynamicMinWidth && (this.dynamicMinWidth = f - g), n
        },
        _splitTextIntoLines: function (t) {
            t = t || this.ctx;
            var e = this.textAlign;
            this._styleMap = null, t.save(), this._setTextStyles(t), this.textAlign = "left";
            var i = this._wrapText(t, this.text);
            return this.textAlign = e, t.restore(), this._textLines = i, this._styleMap = this._generateStyleMap(), i
        },
        setOnGroup: function (t, e) {
            "scaleX" === t && (this.set("scaleX", Math.abs(1 / e)), this.set("width", this.get("width") * e / ("undefined" == typeof this.__oldScaleX ? 1 : this.__oldScaleX)), this.__oldScaleX = e)
        },
        get2DCursorLocation: function (t) {
            "undefined" == typeof t && (t = this.selectionStart);
            for (var e = this._textLines.length, i = 0, r = 0; r < e; r++) {
                var n = this._textLines[r], s = n.length;
                if (t <= i + s)return {
                    lineIndex: r,
                    charIndex: t - i
                };
                i += s, "\n" !== this.text[i] && " " !== this.text[i] || i++
            }
            return {lineIndex: e - 1, charIndex: this._textLines[e - 1].length}
        },
        _getCursorBoundariesOffsets: function (t, e) {
            for (var i = 0, r = 0, n = this.get2DCursorLocation(), s = this._textLines[n.lineIndex].split(""), o = this._getLineLeftOffset(this._getLineWidth(this.ctx, n.lineIndex)), a = 0; a < n.charIndex; a++)r += this._getWidthOfChar(this.ctx, s[a], n.lineIndex, a);
            for (a = 0; a < n.lineIndex; a++)i += this._getHeightOfLine(this.ctx, a);
            return "cursor" === e && (i += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, n.lineIndex) / this.lineHeight - this.getCurrentCharFontSize(n.lineIndex, n.charIndex) * (1 - this._fontSizeFraction)), {
                top: i,
                left: r,
                lineLeft: o
            }
        },
        getMinWidth: function () {
            return Math.max(this.minWidth, this.dynamicMinWidth)
        },
        toObject: function (t) {
            return this.callSuper("toObject", ["minWidth"].concat(t))
        }
    }), e.Textbox.fromObject = function (t, i, r) {
        return e.Object._fromObject("Textbox", t, i, r, "text")
    }, e.Textbox.getTextboxControlVisibility = function () {
        return {tl: !1, tr: !1, br: !1, bl: !1, ml: !0, mt: !1, mr: !0, mb: !1, mtr: !0}
    }
}("undefined" != typeof exports ? exports : this),function () {
    var t = fabric.Canvas.prototype._setObjectScale;
    fabric.Canvas.prototype._setObjectScale = function (e, i, r, n, s, o, a) {
        var h = i.target;
        if (!(h instanceof fabric.Textbox))return t.call(fabric.Canvas.prototype, e, i, r, n, s, o, a);
        var c = h.width * (e.x / i.scaleX / (h.width + h.strokeWidth));
        return c >= h.getMinWidth() ? (h.set("width", c), !0) : void 0
    }, fabric.Group.prototype._refreshControlsVisibility = function () {
        if ("undefined" != typeof fabric.Textbox)for (var t = this._objects.length; t--;)if (this._objects[t]instanceof fabric.Textbox)return void this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility())
    }, fabric.util.object.extend(fabric.Textbox.prototype, {
        _removeExtraneousStyles: function () {
            for (var t in this._styleMap)this._textLines[t] || delete this.styles[this._styleMap[t].line]
        }, insertCharStyleObject: function (t, e, i) {
            var r = this._styleMap[t];
            t = r.line, e = r.offset + e, fabric.IText.prototype.insertCharStyleObject.apply(this, [t, e, i])
        }, insertNewlineStyleObject: function (t, e, i) {
            var r = this._styleMap[t];
            t = r.line, e = r.offset + e, fabric.IText.prototype.insertNewlineStyleObject.apply(this, [t, e, i])
        }, shiftLineStyles: function (t, e) {
            var i = this._styleMap[t];
            t = i.line, fabric.IText.prototype.shiftLineStyles.call(this, t, e)
        }, _getTextOnPreviousLine: function (t) {
            for (var e = this._textLines[t - 1]; this._styleMap[t - 2] && this._styleMap[t - 2].line === this._styleMap[t - 1].line;)e = this._textLines[t - 2] + e, t--;
            return e
        }, removeStyleObject: function (t, e) {
            var i = this.get2DCursorLocation(e), r = this._styleMap[i.lineIndex], n = r.line, s = r.offset + i.charIndex;
            this._removeStyleObject(t, i, n, s)
        }
    })
}(),function () {
    var t = fabric.IText.prototype._getNewSelectionStartFromOffset;
    fabric.IText.prototype._getNewSelectionStartFromOffset = function (e, i, r, n, s) {
        n = t.call(this, e, i, r, n, s);
        for (var o = 0, a = 0, h = 0; h < this._textLines.length && (o += this._textLines[h].length, !(o + a >= n)); h++)"\n" !== this.text[o + a] && " " !== this.text[o + a] || a++;
        return n - h + a
    }
}(),function () {
    function request(t, e, i) {
        var r = URL.parse(t);
        r.port || (r.port = 0 === r.protocol.indexOf("https:") ? 443 : 80);
        var n = 0 === r.protocol.indexOf("https:") ? HTTPS : HTTP, s = n.request({
            hostname: r.hostname,
            port: r.port,
            path: r.path,
            method: "GET"
        }, function (t) {
            var r = "";
            e && t.setEncoding(e), t.on("end", function () {
                i(r)
            }), t.on("data", function (e) {
                200 === t.statusCode && (r += e)
            })
        });
        s.on("error", function (t) {
            t.errno === process.ECONNREFUSED ? fabric.log("ECONNREFUSED: connection refused to " + r.hostname + ":" + r.port) : fabric.log(t.message), i(null)
        }), s.end()
    }

    function requestFs(t, e) {
        var i = require("fs");
        i.readFile(t, function (t, i) {
            if (t)throw fabric.log(t), t;
            e(i)
        })
    }

    if ("undefined" == typeof document || "undefined" == typeof window) {
        var DOMParser = require("xmldom").DOMParser, URL = require("url"), HTTP = require("http"), HTTPS = require("https"), Canvas = require("canvas"), Image = require("canvas").Image;
        fabric.util.loadImage = function (t, e, i) {
            function r(r) {
                r ? (n.src = new Buffer(r, "binary"), n._src = t, e && e.call(i, n)) : (n = null, e && e.call(i, null, !0))
            }

            var n = new Image;
            t && (t instanceof Buffer || 0 === t.indexOf("data")) ? (n.src = n._src = t, e && e.call(i, n)) : t && 0 !== t.indexOf("http") ? requestFs(t, r) : t ? request(t, "binary", r) : e && e.call(i, t)
        }, fabric.loadSVGFromURL = function (t, e, i) {
            t = t.replace(/^\n\s*/, "").replace(/\?.*$/, "").trim(), 0 !== t.indexOf("http") ? requestFs(t, function (t) {
                fabric.loadSVGFromString(t.toString(), e, i)
            }) : request(t, "", function (t) {
                fabric.loadSVGFromString(t, e, i)
            })
        }, fabric.loadSVGFromString = function (t, e, i) {
            var r = (new DOMParser).parseFromString(t);
            fabric.parseSVGDocument(r.documentElement, function (t, i) {
                e && e(t, i)
            }, i)
        }, fabric.util.getScript = function (url, callback) {
            request(url, "", function (body) {
                eval(body), callback && callback()
            })
        }, fabric.createCanvasForNode = function (t, e, i, r) {
            r = r || i;
            var n = fabric.document.createElement("canvas"), s = new Canvas(t || 600, e || 600, r), o = new Canvas(t || 600, e || 600, r);
            n.style = {}, n.width = s.width, n.height = s.height, i = i || {}, i.nodeCanvas = s, i.nodeCacheCanvas = o;
            var a = fabric.Canvas || fabric.StaticCanvas, h = new a(n, i);
            return h.nodeCanvas = s, h.nodeCacheCanvas = o, h.contextContainer = s.getContext("2d"), h.contextCache = o.getContext("2d"), h.Font = Canvas.Font, h
        };
        var originaInitStatic = fabric.StaticCanvas.prototype._initStatic;
        fabric.StaticCanvas.prototype._initStatic = function (t, e) {
            t = t || fabric.document.createElement("canvas"), this.nodeCanvas = new Canvas(t.width, t.height), this.nodeCacheCanvas = new Canvas(t.width, t.height), originaInitStatic.call(this, t, e), this.contextContainer = this.nodeCanvas.getContext("2d"), this.contextCache = this.nodeCacheCanvas.getContext("2d"), this.Font = Canvas.Font
        }, fabric.StaticCanvas.prototype.createPNGStream = function () {
            return this.nodeCanvas.createPNGStream()
        }, fabric.StaticCanvas.prototype.createJPEGStream = function (t) {
            return this.nodeCanvas.createJPEGStream(t)
        }, fabric.StaticCanvas.prototype._initRetinaScaling = function () {
            if (this._isRetinaScaling())return this.lowerCanvasEl.setAttribute("width", this.width * fabric.devicePixelRatio), this.lowerCanvasEl.setAttribute("height", this.height * fabric.devicePixelRatio), this.nodeCanvas.width = this.width * fabric.devicePixelRatio, this.nodeCanvas.height = this.height * fabric.devicePixelRatio, this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio), this
        }, fabric.Canvas && (fabric.Canvas.prototype._initRetinaScaling = fabric.StaticCanvas.prototype._initRetinaScaling);
        var origSetBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension;
        fabric.StaticCanvas.prototype._setBackstoreDimension = function (t, e) {
            return origSetBackstoreDimension.call(this, t, e), this.nodeCanvas[t] = e, this
        }, fabric.Canvas && (fabric.Canvas.prototype._setBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension)
    }
}();