1
1
/* build: `node build.js modules=ALL exclude=json,gestures minifier=uglifyjs` */
2
2
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
3
3
4
- var fabric = fabric || { version: "1.5.0 " };
4
+ var fabric = fabric || { version: "1.6.0-rc.1 " };
5
5
if (typeof exports !== 'undefined') {
6
6
exports.fabric = fabric;
7
7
}
@@ -65,9 +65,9 @@ fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)';
65
65
* Device Pixel Ratio
66
66
* @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html
67
67
*/
68
- fabric.devicePixelRatio = fabric.window.devicePixelRatio ||
69
- fabric.window.webkitDevicePixelRatio ||
70
- fabric.window.mozDevicePixelRatio ||
68
+ fabric.devicePixelRatio = fabric.window.devicePixelRatio ||
69
+ fabric.window.webkitDevicePixelRatio ||
70
+ fabric.window.mozDevicePixelRatio ||
71
71
1;
72
72
73
73
@@ -12620,39 +12620,27 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
12620
12620
setCoords: function() {
12621
12621
var theta = degreesToRadians(this.angle),
12622
12622
vpt = this.getViewportTransform(),
12623
- f = function (p) {
12624
- return fabric.util.transformPoint(p, vpt);
12625
- },
12626
- p = this._calculateCurrentDimensions(false),
12627
- currentWidth = p.x, currentHeight = p.y;
12623
+ dim = this._calculateCurrentDimensions(true),
12624
+ currentWidth = dim.x, currentHeight = dim.y;
12628
12625
12629
12626
// If width is negative, make postive. Fixes path selection issue
12630
12627
if (currentWidth < 0) {
12631
12628
currentWidth = Math.abs(currentWidth);
12632
12629
}
12633
12630
12634
- var _hypotenuse = Math.sqrt(
12635
- Math.pow(currentWidth / 2, 2) +
12636
- Math.pow(currentHeight / 2, 2)),
12637
-
12638
- _angle = Math.atan(
12639
- isFinite(currentHeight / currentWidth)
12640
- ? currentHeight / currentWidth
12641
- : 0),
12642
-
12643
- // offset added for rotate and scale actions
12631
+ var sinTh = Math.sin(theta),
12632
+ cosTh = Math.cos(theta),
12633
+ _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,
12634
+ _hypotenuse = (currentWidth / Math.cos(_angle)) / 2,
12644
12635
offsetX = Math.cos(_angle + theta) * _hypotenuse,
12645
12636
offsetY = Math.sin(_angle + theta) * _hypotenuse,
12646
- sinTh = Math.sin(theta),
12647
- cosTh = Math.cos(theta),
12648
- coords = this.getCenterPoint(),
12649
- wh = new fabric.Point(currentWidth, currentHeight),
12650
- _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),
12651
- _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)),
12652
- bl = f(new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh))),
12653
- br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))),
12654
- tl = f(_tl),
12655
- tr = f(_tr),
12637
+
12638
+ // offset added for rotate and scale actions
12639
+ coords = fabric.util.transformPoint(this.getCenterPoint(), vpt),
12640
+ tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),
12641
+ tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),
12642
+ bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),
12643
+ br = new fabric.Point(coords.x + offsetX, coords.y + offsetY),
12656
12644
ml = new fabric.Point((tl.x + bl.x)/2, (tl.y + bl.y)/2),
12657
12645
mt = new fabric.Point((tr.x + tl.x)/2, (tr.y + tl.y)/2),
12658
12646
mr = new fabric.Point((br.x + tr.x)/2, (br.y + tr.y)/2),
@@ -13021,7 +13009,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
13021
13009
_setCornerCoords: function() {
13022
13010
var coords = this.oCoords,
13023
13011
newTheta = degreesToRadians(45 - this.angle),
13024
- cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2,
13012
+ /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */
13013
+ /* 0.707106 stands for sqrt(2)/2 */
13014
+ cornerHypotenuse = this.cornerSize * 0.707106,
13025
13015
cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),
13026
13016
sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),
13027
13017
x, y;
@@ -19796,10 +19786,11 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
19796
19786
}
19797
19787
this._textLines = this._splitTextIntoLines();
19798
19788
this._clearCache();
19799
- var currentTextAlign = this.textAlign;
19800
- this.textAlign = 'left';
19789
+ //if textAlign is 'justify' i have to disable caching
19790
+ //when calculating width of text and widths of line.
19791
+ this._cacheLinesWidth = (this.textAlign !== 'justify');
19801
19792
this.width = this._getTextWidth(ctx);
19802
- this.textAlign = currentTextAlign ;
19793
+ this._cacheLinesWidth = true ;
19803
19794
this.height = this._getTextHeight(ctx);
19804
19795
},
19805
19796
@@ -19818,14 +19809,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
19818
19809
*/
19819
19810
_render: function(ctx) {
19820
19811
this.clipTo && fabric.util.clipContext(this, ctx);
19821
- ctx.save();
19822
19812
this._setOpacity(ctx);
19823
19813
this._setShadow(ctx);
19824
19814
this._setupCompositeOperation(ctx);
19825
19815
this._renderTextBackground(ctx);
19816
+ this._setStrokeStyles(ctx);
19817
+ this._setFillStyles(ctx);
19826
19818
this._renderText(ctx);
19827
19819
this._renderTextDecoration(ctx);
19828
- ctx.restore();
19829
19820
this.clipTo && ctx.restore();
19830
19821
},
19831
19822
@@ -19838,16 +19829,18 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
19838
19829
this._translateForTextAlign(ctx);
19839
19830
this._renderTextFill(ctx);
19840
19831
this._renderTextStroke(ctx);
19841
-
19832
+ this._translateForTextAlign(ctx, true);
19842
19833
},
19843
19834
19844
19835
/**
19845
19836
* @private
19846
19837
* @param {CanvasRenderingContext2D} ctx Context to render on
19838
+ * @param {Boolean} back Indicates if translate back or forward
19847
19839
*/
19848
- _translateForTextAlign: function(ctx) {
19840
+ _translateForTextAlign: function(ctx, back ) {
19849
19841
if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
19850
- ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0);
19842
+ var sign = back ? -1 : 1;
19843
+ ctx.translate(this.textAlign === 'center' ? (sign * this.width / 2) : sign * this.width, 0);
19851
19844
}
19852
19845
},
19853
19846
@@ -20071,7 +20064,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20071
20064
return;
20072
20065
}
20073
20066
20074
- ctx.save();
20075
20067
ctx.fillStyle = this.backgroundColor;
20076
20068
20077
20069
ctx.fillRect(
@@ -20081,29 +20073,24 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20081
20073
this.height
20082
20074
);
20083
20075
20084
- ctx.restore();
20085
20076
},
20086
20077
20087
20078
/**
20088
20079
* @private
20089
20080
* @param {CanvasRenderingContext2D} ctx Context to render on
20090
20081
*/
20091
20082
_renderTextLinesBackground: function(ctx) {
20092
- var lineTopOffset = 0, heightOfLine = this._getHeightOfLine();
20093
20083
if (!this.textBackgroundColor) {
20094
20084
return;
20095
20085
}
20086
+ var lineTopOffset = 0, heightOfLine = this._getHeightOfLine(),
20087
+ lineWidth, lineLeftOffset;
20096
20088
20097
- ctx.save();
20098
20089
ctx.fillStyle = this.textBackgroundColor;
20099
-
20100
20090
for (var i = 0, len = this._textLines.length; i < len; i++) {
20101
-
20102
20091
if (this._textLines[i] !== '') {
20103
-
20104
- var lineWidth = this._getLineWidth(ctx, i),
20105
- lineLeftOffset = this._getLineLeftOffset(lineWidth);
20106
-
20092
+ lineWidth = this._getLineWidth(ctx, i);
20093
+ lineLeftOffset = this._getLineLeftOffset(lineWidth);
20107
20094
ctx.fillRect(
20108
20095
this._getLeftOffset() + lineLeftOffset,
20109
20096
this._getTopOffset() + lineTopOffset,
@@ -20113,7 +20100,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20113
20100
}
20114
20101
lineTopOffset += heightOfLine;
20115
20102
}
20116
- ctx.restore();
20117
20103
},
20118
20104
20119
20105
/**
@@ -20161,14 +20147,32 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20161
20147
/**
20162
20148
* @private
20163
20149
* @param {CanvasRenderingContext2D} ctx Context to render on
20150
+ * @param {Number} lineIndex line number
20164
20151
* @return {Number} Line width
20165
20152
*/
20166
20153
_getLineWidth: function(ctx, lineIndex) {
20167
20154
if (this.__lineWidths[lineIndex]) {
20168
20155
return this.__lineWidths[lineIndex];
20169
20156
}
20170
- this.__lineWidths[lineIndex] = ctx.measureText(this._textLines[lineIndex]).width;
20171
- return this.__lineWidths[lineIndex];
20157
+ var width, wordCount, line = this._textLines[lineIndex];
20158
+ if (line === '') {
20159
+ width = 0;
20160
+ }
20161
+ else if (this.textAlign === 'justify' && this._cacheLinesWidth) {
20162
+ wordCount = line.split(' ');
20163
+ //consider not justify last line, not for now.
20164
+ if (wordCount.length > 1) {
20165
+ width = this.width;
20166
+ }
20167
+ else {
20168
+ width = ctx.measureText(line).width;
20169
+ }
20170
+ }
20171
+ else {
20172
+ width = ctx.measureText(line).width;
20173
+ }
20174
+ this._cacheLinesWidth && (this.__lineWidths[lineIndex] = width);
20175
+ return width;
20172
20176
},
20173
20177
20174
20178
/**
@@ -20185,12 +20189,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20185
20189
20186
20190
/** @ignore */
20187
20191
function renderLinesAtOffset(offsets) {
20188
- var i, lineHeight = 0, len, j, oLen;
20192
+ var i, lineHeight = 0, len, j, oLen, lineWidth,
20193
+ lineLeftOffset, heightOfLine;
20194
+
20189
20195
for (i = 0, len = _this._textLines.length; i < len; i++) {
20190
20196
20191
- var lineWidth = _this._getLineWidth(ctx, i),
20192
- lineLeftOffset = _this._getLineLeftOffset(lineWidth),
20193
- heightOfLine = _this._getHeightOfLine(ctx, i);
20197
+ lineWidth = _this._getLineWidth(ctx, i),
20198
+ lineLeftOffset = _this._getLineLeftOffset(lineWidth),
20199
+ heightOfLine = _this._getHeightOfLine(ctx, i);
20194
20200
20195
20201
for (j = 0, oLen = offsets.length; j < oLen; j++) {
20196
20202
ctx.fillRect(
@@ -20212,7 +20218,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20212
20218
if (this.textDecoration.indexOf('overline') > -1) {
20213
20219
offsets.push(-0.12);
20214
20220
}
20215
-
20216
20221
if (offsets.length > 0) {
20217
20222
renderLinesAtOffset(offsets);
20218
20223
}
@@ -20250,8 +20255,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
20250
20255
if (!noTransform) {
20251
20256
this.transform(ctx);
20252
20257
}
20253
- this._setStrokeStyles(ctx);
20254
- this._setFillStyles(ctx);
20255
20258
if (this.transformMatrix) {
20256
20259
ctx.transform.apply(ctx, this.transformMatrix);
20257
20260
}
@@ -22716,7 +22719,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
22716
22719
fabric.document.body.appendChild(this.hiddenTextarea);
22717
22720
22718
22721
fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));
22719
- fabric.util.addListener(this.hiddenTextarea, 'keypress ', this.onKeyPress .bind(this));
22722
+ fabric.util.addListener(this.hiddenTextarea, 'input ', this.onInput .bind(this));
22720
22723
fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));
22721
22724
fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this));
22722
22725
@@ -22780,6 +22783,24 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
22780
22783
this.canvas && this.canvas.renderAll();
22781
22784
},
22782
22785
22786
+ /**
22787
+ * Handles onInput event
22788
+ * @param {Event} e Event object
22789
+ */
22790
+ onInput: function(e) {
22791
+ if (!this.isEditing || this._cancelOnInput) {
22792
+ this._cancelOnInput = false;
22793
+ return;
22794
+ }
22795
+ var offset = this.selectionStart || 0,
22796
+ textLength = this.text.length,
22797
+ newTextLength = this.hiddenTextarea.value.length,
22798
+ diff = newTextLength - textLength,
22799
+ charsToInsert = this.hiddenTextarea.value.slice(offset, offset + diff);
22800
+ this.insertChars(charsToInsert);
22801
+ e.stopPropagation();
22802
+ },
22803
+
22783
22804
/**
22784
22805
* Forward delete
22785
22806
*/
@@ -22835,6 +22856,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
22835
22856
if (copiedText) {
22836
22857
this.insertChars(copiedText, useCopiedStyle);
22837
22858
}
22859
+ this._cancelOnInput = true;
22838
22860
},
22839
22861
22840
22862
/**
@@ -22859,20 +22881,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
22859
22881
return e && (e.clipboardData || fabric.window.clipboardData);
22860
22882
},
22861
22883
22862
- /**
22863
- * Handles keypress event
22864
- * @param {Event} e Event object
22865
- */
22866
- onKeyPress: function(e) {
22867
- if (!this.isEditing || e.metaKey || e.ctrlKey) {
22868
- return;
22869
- }
22870
- if (e.which !== 0) {
22871
- this.insertChars(String.fromCharCode(e.which));
22872
- }
22873
- e.stopPropagation();
22874
- },
22875
-
22876
22884
/**
22877
22885
* Gets start offset of a selection
22878
22886
* @param {Event} e Event object
0 commit comments