updated to beta6

This commit is contained in:
Asturur 2017-08-14 09:57:47 +02:00
parent 4cccab8f51
commit d7d88fe5c8
5 changed files with 394 additions and 282 deletions

415
dist/fabric.js vendored
View file

@ -1,7 +1,7 @@
/* build: `node build.js modules=ALL exclude=json,gestures,accessors minifier=uglifyjs` */
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: '2.0.0-beta5' };
var fabric = fabric || { version: '2.0.0-beta6' };
if (typeof exports !== 'undefined') {
exports.fabric = fabric;
}
@ -122,10 +122,9 @@ fabric.devicePixelRatio = fabric.window.devicePixelRatio ||
1;
fabric.initFilterBackend = function() {
if (fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize) && fabric.enableGLFiltering) {
if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {
console.log('max texture size: ' + fabric.maxTextureSize);
return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }));
}
else if (fabric.Canvas2dFilterBackend) {
return (new fabric.Canvas2dFilterBackend());
@ -1002,16 +1001,13 @@ fabric.CommonMethods = {
},
/**
* Creates canvas element and initializes it via excanvas if necessary
* Creates canvas element
* @static
* @memberOf fabric.util
* @param {CanvasElement} [canvasEl] optional canvas element to initialize;
* when not given, element is created implicitly
* @return {CanvasElement} initialized canvas element
*/
createCanvasElement: function(canvasEl) {
canvasEl || (canvasEl = fabric.document.createElement('canvas'));
return canvasEl;
createCanvasElement: function() {
return fabric.document.createElement('canvas');
},
/**
@ -1096,7 +1092,7 @@ fabric.CommonMethods = {
target.skewY = 0;
target.flipX = false;
target.flipY = false;
target.setAngle(0);
target.rotate(0);
},
/**
@ -1630,6 +1626,7 @@ fabric.CommonMethods = {
/**
* Creates an empty object and copies all enumerable properties of another object to it
* @memberOf fabric.util.object
* TODO: this function return an empty object if you try to clone null
* @param {Object} object Object to clone
* @return {Object}
*/
@ -2654,6 +2651,8 @@ if (typeof console !== 'undefined') {
return fabric.window.setTimeout(callback, 1000 / 60);
};
var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;
/**
* requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/
* In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method
@ -2665,9 +2664,13 @@ if (typeof console !== 'undefined') {
return _requestAnimFrame.apply(fabric.window, arguments);
}
function cancelAnimFrame() {
return _cancelAnimFrame.apply(fabric.window, arguments);
}
fabric.util.animate = animate;
fabric.util.requestAnimFrame = requestAnimFrame;
fabric.util.cancelAnimFrame = cancelAnimFrame;
})();
@ -3165,7 +3168,7 @@ if (typeof console !== 'undefined') {
'stroke-opacity': 'strokeOpacity',
'stroke-width': 'strokeWidth',
'text-decoration': 'textDecoration',
'text-anchor': 'originX',
'text-anchor': 'textAnchor',
opacity: 'opacity'
},
@ -3224,7 +3227,7 @@ if (typeof console !== 'undefined') {
value *= parentAttributes.opacity;
}
}
else if (attr === 'originX' /* text-anchor */) {
else if (attr === 'textAnchor' /* text-anchor */) {
value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';
}
else {
@ -6635,14 +6638,14 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
/**
* @private
*/
_createCanvasElement: function(canvasEl) {
var element = fabric.util.createCanvasElement(canvasEl);
if (!element.style) {
element.style = { };
}
_createCanvasElement: function() {
var element = fabric.util.createCanvasElement();
if (!element) {
throw CANVAS_INIT_ERROR;
}
if (!element.style) {
element.style = { };
}
if (typeof element.getContext === 'undefined') {
throw CANVAS_INIT_ERROR;
}
@ -6678,7 +6681,13 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
* @param {HTMLElement} [canvasEl]
*/
_createLowerCanvas: function (canvasEl) {
this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(canvasEl);
// canvasEl === 'HTMLCanvasElement' does not work on jsdom/node
if (canvasEl && canvasEl.getContext) {
this.lowerCanvasEl = canvasEl;
}
else {
this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();
}
fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');
@ -6979,8 +6988,8 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
*/
renderAll: function () {
var canvasToDrawOn = this.contextContainer;
if (this.rendering) {
fabric.window.cancelAnimationFrame(this.rendering);
if (this.isRendering) {
fabric.util.cancelAnimFrame(this.isRendering);
}
this.renderCanvas(canvasToDrawOn, this._objects);
return this;
@ -7224,7 +7233,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
*/
_centerObject: function(object, center) {
object.setPositionByOrigin(center, 'center', 'center');
this.requestRenderAll();
this.renderOnAddRemove && this.requestRenderAll();
return this;
},
@ -9650,7 +9659,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
target.scaleY = 1;
target.skewX = 0;
target.skewY = 0;
target.setAngle(0);
target.rotate(0);
},
/**
@ -12729,7 +12738,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
_setOpacity: function(ctx) {
if (this.group && !this.group.transformDone) {
if (this.group && !this.group._transformDone) {
ctx.globalAlpha = this.getObjectOpacity();
}
else {
@ -12853,8 +12862,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @param {Object} filler fabric.Pattern or fabric.Gradient
*/
_applyPatternGradientTransform: function(ctx, filler) {
if (!filler.toLive) {
return;
if (!filler || !filler.toLive) {
return { offsetX: 0, offsetY: 0 };
}
var transform = filler.gradientTransform || filler.patternTransform;
var offsetX = -this.width / 2 + filler.offsetX || 0,
@ -12863,6 +12872,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
if (transform) {
ctx.transform.apply(ctx, transform);
}
return { offsetX: offsetX, offsetY: offsetY };
},
/**
@ -12912,15 +12922,13 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
},
/**
* This function is an helper for svg import. it removes the transform matrix
* and set to object properties that fabricjs can handle
* This function is an helper for svg import. it decoompose the transformMatrix
* and assign properties to object.
* untransformed coordinates
* @private
* @chainable
* @return {thisArg}
*/
_removeTransformMatrix: function() {
var center = this._findCenterFromElement();
_assignTransformMatrixProps: function() {
if (this.transformMatrix) {
var options = fabric.util.qrDecompose(this.transformMatrix);
this.flipX = false;
@ -12930,6 +12938,20 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
this.angle = options.angle;
this.skewX = options.skewX;
this.skewY = 0;
}
},
/**
* This function is an helper for svg import. it removes the transform matrix
* and set to object properties that fabricjs can handle
* @private
* @chainable
* @return {thisArg}
*/
_removeTransformMatrix: function() {
var center = this._findCenterFromElement();
if (this.transformMatrix) {
this._assignTransformMatrixProps();
center = fabric.util.transformPoint(center, this.transformMatrix);
}
this.transformMatrix = null;
@ -13182,12 +13204,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
},
/**
* Sets "angle" of an instance
* Sets "angle" of an instance with centered rotation
* @param {Number} angle Angle value (in degrees)
* @return {fabric.Object} thisArg
* @chainable
*/
setAngle: function(angle) {
rotate: function(angle) {
var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;
if (shouldCenterOrigin) {
@ -13269,16 +13291,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
return this;
},
/**
* Removes object from canvas to which it was added last
* @return {fabric.Object} thisArg
* @chainable
*/
remove: function() {
this.canvas && this.canvas.remove(this);
return this;
},
/**
* Returns coordinates of a pointer relative to an object
* @param {Event} e Event to operate upon
@ -13313,13 +13325,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);
/**
* Alias for {@link fabric.Object.prototype.setAngle}
* @alias rotate -> setAngle
* @memberOf fabric.Object
*/
fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;
extend(fabric.Object.prototype, fabric.Observable);
/**
@ -15510,8 +15515,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
parsedAttributes.x2 || 0,
parsedAttributes.y2 || 0
];
options.originX = 'left';
options.originY = 'top';
callback(new fabric.Line(points, extend(parsedAttributes, options)));
};
/* _FROM_SVG_END_ */
@ -15765,8 +15768,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;
parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;
parsedAttributes.originX = 'left';
parsedAttributes.originY = 'top';
callback(new fabric.Circle(extend(parsedAttributes, options)));
};
@ -16088,8 +16089,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;
parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;
parsedAttributes.originX = 'left';
parsedAttributes.originY = 'top';
callback(new fabric.Ellipse(extend(parsedAttributes, options)));
};
/* _FROM_SVG_END_ */
@ -16309,8 +16308,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
parsedAttributes.left = parsedAttributes.left || 0;
parsedAttributes.top = parsedAttributes.top || 0;
parsedAttributes.originX = 'left';
parsedAttributes.originY = 'top';
var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
rect.visible = rect.visible && rect.width > 0 && rect.height > 0;
callback(rect);
@ -16372,20 +16369,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
*/
points: null,
/**
* Minimum X from points values, necessary to offset points
* @type Number
* @default
*/
minX: 0,
/**
* Minimum Y from points values, necessary to offset points
* @type Number
* @default
*/
minY: 0,
cacheProperties: cacheProperties,
/**
@ -16411,34 +16394,47 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
options = options || {};
this.points = points || [];
this.callSuper('initialize', options);
this._calcDimensions();
if (!('top' in options)) {
this.top = this.minY;
var calcDim = this._calcDimensions();
if (typeof options.left === 'undefined') {
this.left = calcDim.left;
}
if (!('left' in options)) {
this.left = this.minX;
if (typeof options.top === 'undefined') {
this.top = calcDim.top;
}
this.width = calcDim.width;
this.height = calcDim.height;
this.pathOffset = {
x: this.minX + this.width / 2,
y: this.minY + this.height / 2
x: calcDim.left + this.width / 2,
y: calcDim.top + this.height / 2
};
},
/**
* Calculate the polygon min and max point from points array,
* returning an object with left, top, widht, height to measure the
* polygon size
* @return {Object} object.left X coordinate of the polygon leftmost point
* @return {Object} object.top Y coordinate of the polygon topmost point
* @return {Object} object.width distance between X coordinates of the polygon leftmost and rightmost point
* @return {Object} object.height distance between Y coordinates of the polygon topmost and bottommost point
* @private
*/
_calcDimensions: function() {
var points = this.points,
minX = min(points, 'x'),
minY = min(points, 'y'),
maxX = max(points, 'x'),
maxY = max(points, 'y');
minX = min(points, 'x') || 0,
minY = min(points, 'y') || 0,
maxX = max(points, 'x') || 0,
maxY = max(points, 'y') || 0,
width = (maxX - minX),
height = (maxY - minY);
this.width = (maxX - minX) || 0;
this.height = (maxY - minY) || 0;
this.minX = minX || 0;
this.minY = minY || 0;
return {
left: minX,
top: minY,
width: width,
height: height
};
},
/**
@ -16740,20 +16736,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
*/
path: null,
/**
* Minimum X from points values, necessary to offset points
* @type Number
* @default
*/
minX: 0,
/**
* Minimum Y from points values, necessary to offset points
* @type Number
* @default
*/
minY: 0,
cacheProperties: cacheProperties,
stateProperties: stateProperties,
@ -16797,30 +16779,20 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
_setPositionDimensions: function(options) {
var calcDim = this._parseDimensions();
this.minX = calcDim.left;
this.minY = calcDim.top;
this.width = calcDim.width;
this.height = calcDim.height;
if (typeof options.left === 'undefined') {
this.left = calcDim.left + (this.originX === 'center'
? this.width / 2
: this.originX === 'right'
? this.width
: 0);
this.left = calcDim.left;
}
if (typeof options.top === 'undefined') {
this.top = calcDim.top + (this.originY === 'center'
? this.height / 2
: this.originY === 'bottom'
? this.height
: 0);
this.top = calcDim.top;
}
this.pathOffset = this.pathOffset || {
x: this.minX + this.width / 2,
y: this.minY + this.height / 2
x: calcDim.left + this.width / 2,
y: calcDim.top + this.height / 2
};
},
@ -17627,8 +17599,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
*/
fabric.Path.fromElement = function(element, callback, options) {
var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);
parsedAttributes.originX = 'left';
parsedAttributes.originY = 'top';
callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));
};
/* _FROM_SVG_END_ */
@ -19069,7 +19039,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
straighten: function() {
this.setAngle(this._getAngleValueForStraighten());
this.rotate(this._getAngleValueForStraighten());
return this;
},
@ -19094,7 +19064,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
endValue: this._getAngleValueForStraighten(),
duration: this.FX_DURATION,
onChange: function(value) {
_this.setAngle(value);
_this.rotate(value);
onChange();
},
onComplete: function() {
@ -22926,6 +22896,104 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
})(typeof exports !== 'undefined' ? exports : this);
(function(global) {
'use strict';
var fabric = global.fabric || (global.fabric = { }),
filters = fabric.Image.filters,
createClass = fabric.util.createClass;
/**
* HueRotation filter class
* @class fabric.Image.filters.HueRotation
* @memberOf fabric.Image.filters
* @extends fabric.Image.filters.BaseFilter
* @see {@link fabric.Image.filters.HueRotation#initialize} for constructor definition
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
* @example
* var filter = new fabric.Image.filters.HueRotation({
* rotation: -0.5
* });
* object.filters.push(filter);
* object.applyFilters();
*/
filters.HueRotation = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.HueRotation.prototype */ {
/**
* Filter type
* @param {String} type
* @default
*/
type: 'HueRotation',
/**
* HueRotation value, from -1 to 1.
* the unit is radians
* @param {Number} myParameter
* @default
*/
rotation: 0,
/**
* Describe the property that is the filter parameter
* @param {String} m
* @default
*/
mainParameter: 'rotation',
calculateMatrix: function() {
var rad = this.rotation * Math.PI, cos = Math.cos(rad), sin = Math.sin(rad),
aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;
this.matrix = [
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
];
this.matrix[0] = cos + OneMinusCos / 3;
this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[6] = cos + aThird * OneMinusCos;
this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[12] = cos + aThird * OneMinusCos;
},
/**
* Apply this filter to the input image data provided.
*
* Determines whether to use WebGL or Canvas2D based on the options.webgl flag.
*
* @param {Object} options
* @param {Number} options.passes The number of filters remaining to be executed
* @param {Boolean} options.webgl Whether to use webgl to render the filter.
* @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.
* @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.
* @param {WebGLRenderingContext} options.context The GL context used for rendering.
* @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.
*/
applyTo: function(options) {
this.calculateMatrix();
fabric.Image.filters.BaseFilter.prototype.applyTo.call(this, options);
},
});
/**
* Returns filter instance from an object representation
* @static
* @param {Object} object Object to create an instance from
* @param {function} [callback] to be invoked after filter creation
* @return {fabric.Image.filters.HueRotation} Instance of fabric.Image.filters.HueRotation
*/
fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;
})(typeof exports !== 'undefined' ? exports : this);
(function(global) {
'use strict';
@ -23195,7 +23263,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
'fontStyle',
'underline',
'overline',
'linethrough'
'linethrough',
'textBackgroundColor',
],
/**
@ -23905,9 +23974,9 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
* @param {String} method Method name ("fillText" or "strokeText")
*/
_renderTextCommon: function(ctx, method) {
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();
ctx.save();
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(),
offsets = this._applyPatternGradientTransform(ctx, method === 'fillText' ? this.fill : this.stroke);
for (var i = 0, len = this._textLines.length; i < len; i++) {
var heightOfLine = this.getHeightOfLine(i),
maxHeight = heightOfLine / this.lineHeight,
@ -23916,12 +23985,13 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
method,
ctx,
this._textLines[i],
left + leftOffset,
top + lineHeights + maxHeight,
left + leftOffset - offsets.offsetX,
top + lineHeights + maxHeight - offsets.offsetY,
i
);
lineHeights += heightOfLine;
}
ctx.restore();
},
/**
@ -24338,7 +24408,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
return callback(null);
}
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES),
parsedAnchor = parsedAttributes.textAnchor || 'left';
options = fabric.util.object.extend((options ? clone(options) : { }), parsedAttributes);
options.top = options.top || 0;
@ -24366,10 +24437,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;
}
if (!options.originX) {
options.originX = 'left';
}
var textContent = '';
// The XML is not properly parsed in IE9 so a workaround to get
@ -24399,18 +24466,16 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
x/y attributes in SVG correspond to the bottom-left corner of text bounding box
fabric output by default at top, left.
*/
if (text.originX === 'center') {
if (parsedAnchor === 'center') {
offX = text.getScaledWidth() / 2;
}
if (text.originX === 'right') {
if (parsedAnchor === 'right') {
offX = text.getScaledWidth();
}
text.set({
left: text.left - offX,
top: text.top - (textHeight - text.fontSize * (0.18 + text._fontSizeFraction)) / text.lineHeight
});
text.originX = 'left';
text.originY = 'top';
callback(text);
};
/* _FROM_SVG_END_ */
@ -24660,20 +24725,22 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
* Gets style of a current selection/cursor (at the start position)
* @param {Number} [startIndex] Start index to get styles at
* @param {Number} [endIndex] End index to get styles at
* @param {Boolean} [endIndex] End index to get styles at
* @return {Object} styles Style object at a specified (or current) index
*/
getSelectionStyles: function(startIndex, endIndex) {
getSelectionStyles: function(startIndex, endIndex, complete) {
if (arguments.length === 2) {
if (endIndex && startIndex !== endIndex) {
var styles = [];
for (var i = startIndex; i < endIndex; i++) {
styles.push(this.getSelectionStyles(i));
styles.push(this.getSelectionStyles(i, i, complete));
}
return styles;
}
var loc = this.get2DCursorLocation(startIndex),
style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex);
style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) :
this._getStyleDeclaration(loc.lineIndex, loc.charIndex);
return style || {};
},
@ -25182,12 +25249,15 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
/**
* Selects entire text
* @return {fabric.IText} thisArg
* @chainable
*/
selectAll: function() {
this.selectionStart = 0;
this.selectionEnd = this._text.length;
this._fireSelectionChanged();
this._updateTextarea();
return this;
},
/**
@ -25316,6 +25386,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
/**
* Selects a line based on the index
* @param {Number} selectionStart Index of a character
* @return {fabric.IText} thisArg
* @chainable
*/
selectLine: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
@ -25326,6 +25398,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
return this;
},
/**
@ -25671,15 +25744,15 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
// remove and shift left on the same line
if (this.styles[lineStart]) {
styleObj = this.styles[lineStart];
var diff = charEnd - charStart;
var diff = charEnd - charStart, numericChar, _char;
for (i = charStart; i < charEnd; i++) {
delete styleObj[i];
}
for (i = charEnd; i < this._textLines[lineStart].length; i++) {
//shifting
if (styleObj[i]) {
styleObj[i - diff] = styleObj[i];
delete styleObj[i];
for (_char in this.styles[lineStart]) {
numericChar = parseInt(_char, 10);
if (numericChar >= charEnd) {
styleObj[numericChar - diff] = styleObj[_char];
delete styleObj[_char];
}
}
}
@ -25692,7 +25765,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
* @param {Number} offset Can any number?
*/
shiftLineStyles: function(lineIndex, offset) {
// shift all line styles by 1 upward
// shift all line styles by offset upward or downward
// do not clone deep. we need new array, not new style objects
var clonedStyles = clone(this.styles);
for (var line in this.styles) {
@ -25704,7 +25777,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
}
}
}
//TODO: evaluate if delete old style lines with offset -1
},
restartCursorIfNeeded: function() {
@ -25729,12 +25801,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
qty || (qty = 1);
this.shiftLineStyles(lineIndex, qty);
if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) {
currentCharStyle = this.styles[lineIndex][charIndex - 1];
if (this.styles[lineIndex]) {
currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1];
}
// we clone styles of all chars
// after cursor onto the last line
// after cursor onto the current line
for (var index in this.styles[lineIndex]) {
var numIndex = parseInt(index, 10);
if (numIndex >= charIndex) {
@ -25754,7 +25826,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
// we clone current char style onto the next (otherwise empty) line
while (qty > 1) {
qty--;
if (copiedStyle[qty]) {
if (copiedStyle && copiedStyle[qty]) {
this.styles[lineIndex + qty] = { 0: clone(copiedStyle[qty]) };
}
else if (currentCharStyle) {
@ -25779,7 +25851,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this.styles = {};
}
var currentLineStyles = this.styles[lineIndex],
currentLineStylesCloned = clone(currentLineStyles);
currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {};
quantity || (quantity = 1);
// shift all char styles by quantity forward
@ -25797,6 +25869,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this._forceClearCache = true;
if (copiedStyle) {
while (quantity--) {
if (!Object.keys(copiedStyle[quantity]).length) {
continue;
}
if (!this.styles[lineIndex]) {
this.styles[lineIndex] = {};
}
this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]);
}
return;
@ -25813,32 +25891,31 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
/**
* Inserts style object(s)
* @param {Array} insertedText Characters at the location where style is inserted
* @param {Number} start True if it's end of line
* @param {Number} start cursor index for inserting style
* @param {Array} [copiedStyle] array of style objects to insert.
*/
insertNewStyleBlock: function(insertedText, start, copiedStyle) {
var cursorLoc = this.get2DCursorLocation(start, true),
addingNewLines = 0, addingChars = 0;
addedLines = [0], linesLenght = 0;
for (var i = 0; i < insertedText.length; i++) {
if (insertedText[i] === '\n') {
if (addingChars) {
this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingChars, copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addingChars);
addingChars = 0;
}
addingNewLines++;
linesLenght++;
addedLines[linesLenght] = 0;
}
else {
if (addingNewLines) {
this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingNewLines, copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addingNewLines);
addingNewLines = 0;
}
addingChars++;
addedLines[linesLenght]++;
}
}
addingChars && this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingChars, copiedStyle);
addingNewLines && this.insertNewlineStyleObject(
cursorLoc.lineIndex, cursorLoc.charIndex, addingNewLines, copiedStyle);
if (addedLines[0] > 0) {
this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);
}
linesLenght && this.insertNewlineStyleObject(
cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLenght);
for (var i = 1; i <= linesLenght; i++) {
this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
}
},
/**
@ -26345,7 +26422,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
}
fabric.copiedText = this.getSelectedText();
fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd);
fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true);
this._copyDone = true;
},

18
dist/fabric.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/fabric.min.js.gz vendored

Binary file not shown.

241
dist/fabric.require.js vendored
View file

@ -1,5 +1,5 @@
var fabric = fabric || {
version: "2.0.0-beta5"
version: "2.0.0-beta6"
};
if (typeof exports !== "undefined") {
@ -50,7 +50,7 @@ fabric.enableGLFiltering = true;
fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1;
fabric.initFilterBackend = function() {
if (fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize) && fabric.enableGLFiltering) {
if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {
console.log("max texture size: " + fabric.maxTextureSize);
return new fabric.WebglFilterBackend({
tileSize: fabric.textureSize
@ -481,9 +481,8 @@ fabric.CommonMethods = {
}
ctx.restore();
},
createCanvasElement: function(canvasEl) {
canvasEl || (canvasEl = fabric.document.createElement("canvas"));
return canvasEl;
createCanvasElement: function() {
return fabric.document.createElement("canvas");
},
createImage: function() {
return fabric.document.createElement("img");
@ -520,7 +519,7 @@ fabric.CommonMethods = {
target.skewY = 0;
target.flipX = false;
target.flipY = false;
target.setAngle(0);
target.rotate(0);
},
getFunctionBody: function(fn) {
return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1];
@ -1429,11 +1428,16 @@ if (typeof console !== "undefined") {
var _requestAnimFrame = fabric.window.requestAnimationFrame || fabric.window.webkitRequestAnimationFrame || fabric.window.mozRequestAnimationFrame || fabric.window.oRequestAnimationFrame || fabric.window.msRequestAnimationFrame || function(callback) {
return fabric.window.setTimeout(callback, 1e3 / 60);
};
var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;
function requestAnimFrame() {
return _requestAnimFrame.apply(fabric.window, arguments);
}
function cancelAnimFrame() {
return _cancelAnimFrame.apply(fabric.window, arguments);
}
fabric.util.animate = animate;
fabric.util.requestAnimFrame = requestAnimFrame;
fabric.util.cancelAnimFrame = cancelAnimFrame;
})();
(function() {
@ -1719,7 +1723,7 @@ if (typeof console !== "undefined") {
"stroke-opacity": "strokeOpacity",
"stroke-width": "strokeWidth",
"text-decoration": "textDecoration",
"text-anchor": "originX",
"text-anchor": "textAnchor",
opacity: "opacity"
}, colorAttributes = {
stroke: "strokeOpacity",
@ -1761,7 +1765,7 @@ if (typeof console !== "undefined") {
if (parentAttributes && typeof parentAttributes.opacity !== "undefined") {
value *= parentAttributes.opacity;
}
} else if (attr === "originX") {
} else if (attr === "textAnchor") {
value = value === "start" ? "left" : value === "end" ? "right" : "center";
} else {
parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);
@ -3416,14 +3420,14 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
this._initPattern(color, property, callback);
return this;
},
_createCanvasElement: function(canvasEl) {
var element = fabric.util.createCanvasElement(canvasEl);
if (!element.style) {
element.style = {};
}
_createCanvasElement: function() {
var element = fabric.util.createCanvasElement();
if (!element) {
throw CANVAS_INIT_ERROR;
}
if (!element.style) {
element.style = {};
}
if (typeof element.getContext === "undefined") {
throw CANVAS_INIT_ERROR;
}
@ -3443,7 +3447,11 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
this.viewportTransform = this.viewportTransform.slice();
},
_createLowerCanvas: function(canvasEl) {
this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(canvasEl);
if (canvasEl && canvasEl.getContext) {
this.lowerCanvasEl = canvasEl;
} else {
this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();
}
fabric.util.addClass(this.lowerCanvasEl, "lower-canvas");
if (this.interactive) {
this._applyCanvasStyle(this.lowerCanvasEl);
@ -3592,8 +3600,8 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
},
renderAll: function() {
var canvasToDrawOn = this.contextContainer;
if (this.rendering) {
fabric.window.cancelAnimationFrame(this.rendering);
if (this.isRendering) {
fabric.util.cancelAnimFrame(this.isRendering);
}
this.renderCanvas(canvasToDrawOn, this._objects);
return this;
@ -3713,7 +3721,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
},
_centerObject: function(object, center) {
object.setPositionByOrigin(center, "center", "center");
this.requestRenderAll();
this.renderOnAddRemove && this.requestRenderAll();
return this;
},
toDatalessJSON: function(propertiesToInclude) {
@ -4868,7 +4876,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
target.scaleY = 1;
target.skewX = 0;
target.skewY = 0;
target.setAngle(0);
target.rotate(0);
},
_drawSelection: function(ctx) {
var groupSelector = this._groupSelector, left = groupSelector.left, top = groupSelector.top, aleft = abs(left), atop = abs(top);
@ -6374,7 +6382,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
this._removeShadow(ctx);
},
_setOpacity: function(ctx) {
if (this.group && !this.group.transformDone) {
if (this.group && !this.group._transformDone) {
ctx.globalAlpha = this.getObjectOpacity();
} else {
ctx.globalAlpha *= this.opacity;
@ -6452,8 +6460,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
},
_applyPatternGradientTransform: function(ctx, filler) {
if (!filler.toLive) {
return;
if (!filler || !filler.toLive) {
return {
offsetX: 0,
offsetY: 0
};
}
var transform = filler.gradientTransform || filler.patternTransform;
var offsetX = -this.width / 2 + filler.offsetX || 0, offsetY = -this.height / 2 + filler.offsetY || 0;
@ -6461,6 +6472,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
if (transform) {
ctx.transform.apply(ctx, transform);
}
return {
offsetX: offsetX,
offsetY: offsetY
};
},
_renderFill: function(ctx) {
if (!this.fill) {
@ -6494,8 +6509,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
y: this.top + this.height / 2
};
},
_removeTransformMatrix: function() {
var center = this._findCenterFromElement();
_assignTransformMatrixProps: function() {
if (this.transformMatrix) {
var options = fabric.util.qrDecompose(this.transformMatrix);
this.flipX = false;
@ -6505,6 +6519,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
this.angle = options.angle;
this.skewX = options.skewX;
this.skewY = 0;
}
},
_removeTransformMatrix: function() {
var center = this._findCenterFromElement();
if (this.transformMatrix) {
this._assignTransformMatrixProps();
center = fabric.util.transformPoint(center, this.transformMatrix);
}
this.transformMatrix = null;
@ -6597,7 +6617,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
this.set("fill", color);
return this;
},
setAngle: function(angle) {
rotate: function(angle) {
var shouldCenterOrigin = (this.originX !== "center" || this.originY !== "center") && this.centeredRotation;
if (shouldCenterOrigin) {
this._setOriginToCenter();
@ -6632,10 +6652,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
this.canvas && this.canvas.viewportCenterObject(this);
return this;
},
remove: function() {
this.canvas && this.canvas.remove(this);
return this;
},
getLocalPointer: function(e, pointer) {
pointer = pointer || this.canvas.getPointer(e);
var pClicked = new fabric.Point(pointer.x, pointer.y), objectLeftTop = this._getLeftTopCoords();
@ -6654,7 +6670,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
}
});
fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);
fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;
extend(fabric.Object.prototype, fabric.Observable);
fabric.Object.NUM_FRACTION_DIGITS = 2;
fabric.Object._fromObject = function(className, object, callback, extraParam) {
@ -7675,8 +7690,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
fabric.Line.fromElement = function(element, callback, options) {
options = options || {};
var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), points = [ parsedAttributes.x1 || 0, parsedAttributes.y1 || 0, parsedAttributes.x2 || 0, parsedAttributes.y2 || 0 ];
options.originX = "left";
options.originY = "top";
callback(new fabric.Line(points, extend(parsedAttributes, options)));
};
fabric.Line.fromObject = function(object, callback) {
@ -7770,8 +7783,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
}
parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;
parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;
parsedAttributes.originX = "left";
parsedAttributes.originY = "top";
callback(new fabric.Circle(extend(parsedAttributes, options)));
};
function isValidRadius(attributes) {
@ -7888,8 +7899,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);
parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;
parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;
parsedAttributes.originX = "left";
parsedAttributes.originY = "top";
callback(new fabric.Ellipse(extend(parsedAttributes, options)));
};
fabric.Ellipse.fromObject = function(object, callback) {
@ -7972,8 +7981,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);
parsedAttributes.left = parsedAttributes.left || 0;
parsedAttributes.top = parsedAttributes.top || 0;
parsedAttributes.originX = "left";
parsedAttributes.originY = "top";
var rect = new fabric.Rect(extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes));
rect.visible = rect.visible && rect.width > 0 && rect.height > 0;
callback(rect);
@ -7995,31 +8002,33 @@ fabric.util.object.extend(fabric.Object.prototype, {
fabric.Polyline = fabric.util.createClass(fabric.Object, {
type: "polyline",
points: null,
minX: 0,
minY: 0,
cacheProperties: cacheProperties,
initialize: function(points, options) {
options = options || {};
this.points = points || [];
this.callSuper("initialize", options);
this._calcDimensions();
if (!("top" in options)) {
this.top = this.minY;
var calcDim = this._calcDimensions();
if (typeof options.left === "undefined") {
this.left = calcDim.left;
}
if (!("left" in options)) {
this.left = this.minX;
if (typeof options.top === "undefined") {
this.top = calcDim.top;
}
this.width = calcDim.width;
this.height = calcDim.height;
this.pathOffset = {
x: this.minX + this.width / 2,
y: this.minY + this.height / 2
x: calcDim.left + this.width / 2,
y: calcDim.top + this.height / 2
};
},
_calcDimensions: function() {
var points = this.points, minX = min(points, "x"), minY = min(points, "y"), maxX = max(points, "x"), maxY = max(points, "y");
this.width = maxX - minX || 0;
this.height = maxY - minY || 0;
this.minX = minX || 0;
this.minY = minY || 0;
var points = this.points, minX = min(points, "x") || 0, minY = min(points, "y") || 0, maxX = max(points, "x") || 0, maxY = max(points, "y") || 0, width = maxX - minX, height = maxY - minY;
return {
left: minX,
top: minY,
width: width,
height: height
};
},
toObject: function(propertiesToInclude) {
return extend(this.callSuper("toObject", propertiesToInclude), {
@ -8144,8 +8153,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
fabric.Path = fabric.util.createClass(fabric.Object, {
type: "path",
path: null,
minX: 0,
minY: 0,
cacheProperties: cacheProperties,
stateProperties: stateProperties,
initialize: function(path, options) {
@ -8166,19 +8173,17 @@ fabric.util.object.extend(fabric.Object.prototype, {
},
_setPositionDimensions: function(options) {
var calcDim = this._parseDimensions();
this.minX = calcDim.left;
this.minY = calcDim.top;
this.width = calcDim.width;
this.height = calcDim.height;
if (typeof options.left === "undefined") {
this.left = calcDim.left + (this.originX === "center" ? this.width / 2 : this.originX === "right" ? this.width : 0);
this.left = calcDim.left;
}
if (typeof options.top === "undefined") {
this.top = calcDim.top + (this.originY === "center" ? this.height / 2 : this.originY === "bottom" ? this.height : 0);
this.top = calcDim.top;
}
this.pathOffset = this.pathOffset || {
x: this.minX + this.width / 2,
y: this.minY + this.height / 2
x: calcDim.left + this.width / 2,
y: calcDim.top + this.height / 2
};
},
_renderPathCommands: function(ctx) {
@ -8628,8 +8633,6 @@ fabric.util.object.extend(fabric.Object.prototype, {
fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat([ "d" ]);
fabric.Path.fromElement = function(element, callback, options) {
var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);
parsedAttributes.originX = "left";
parsedAttributes.originY = "top";
callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));
};
})(typeof exports !== "undefined" ? exports : this);
@ -9376,7 +9379,7 @@ fabric.util.object.extend(fabric.Object.prototype, {
return Math.round(angle / 90) * 90;
},
straighten: function() {
this.setAngle(this._getAngleValueForStraighten());
this.rotate(this._getAngleValueForStraighten());
return this;
},
fxStraighten: function(callbacks) {
@ -9387,7 +9390,7 @@ fabric.util.object.extend(fabric.Object.prototype, {
endValue: this._getAngleValueForStraighten(),
duration: this.FX_DURATION,
onChange: function(value) {
_this.setAngle(value);
_this.rotate(value);
onChange();
},
onComplete: function() {
@ -10928,6 +10931,34 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
};
})(typeof exports !== "undefined" ? exports : this);
(function(global) {
"use strict";
var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass;
filters.HueRotation = createClass(filters.ColorMatrix, {
type: "HueRotation",
rotation: 0,
mainParameter: "rotation",
calculateMatrix: function() {
var rad = this.rotation * Math.PI, cos = Math.cos(rad), sin = Math.sin(rad), aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;
this.matrix = [ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 ];
this.matrix[0] = cos + OneMinusCos / 3;
this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[6] = cos + aThird * OneMinusCos;
this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;
this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;
this.matrix[12] = cos + aThird * OneMinusCos;
},
applyTo: function(options) {
this.calculateMatrix();
fabric.Image.filters.BaseFilter.prototype.applyTo.call(this, options);
}
});
fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;
})(typeof exports !== "undefined" ? exports : this);
(function(global) {
"use strict";
var fabric = global.fabric || (global.fabric = {}), clone = fabric.util.object.clone, MIN_TEXT_WIDTH = 2, CACHE_FONT_SIZE = 200;
@ -10970,7 +11001,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
charSpacing: 0,
styles: null,
_measuringContext: null,
_styleProperties: [ "stroke", "strokeWidth", "fill", "fontFamily", "fontSize", "fontWeight", "fontStyle", "underline", "overline", "linethrough" ],
_styleProperties: [ "stroke", "strokeWidth", "fill", "fontFamily", "fontSize", "fontWeight", "fontStyle", "underline", "overline", "linethrough", "textBackgroundColor" ],
__charBounds: [],
initialize: function(text, options) {
this.styles = options ? options.styles || {} : {};
@ -11375,12 +11406,14 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
return -this.height / 2;
},
_renderTextCommon: function(ctx, method) {
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();
ctx.save();
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(), offsets = this._applyPatternGradientTransform(ctx, method === "fillText" ? this.fill : this.stroke);
for (var i = 0, len = this._textLines.length; i < len; i++) {
var heightOfLine = this.getHeightOfLine(i), maxHeight = heightOfLine / this.lineHeight, leftOffset = this._getLineLeftOffset(i);
this._renderTextLine(method, ctx, this._textLines[i], left + leftOffset, top + lineHeights + maxHeight, i);
this._renderTextLine(method, ctx, this._textLines[i], left + leftOffset - offsets.offsetX, top + lineHeights + maxHeight - offsets.offsetY, i);
lineHeights += heightOfLine;
}
ctx.restore();
},
_renderTextFill: function(ctx) {
if (!this.fill && !this.styleHas("fill")) {
@ -11596,7 +11629,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
if (!element) {
return callback(null);
}
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES), parsedAnchor = parsedAttributes.textAnchor || "left";
options = fabric.util.object.extend(options ? clone(options) : {}, parsedAttributes);
options.top = options.top || 0;
options.left = options.left || 0;
@ -11622,9 +11655,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
if (!("fontSize" in options)) {
options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;
}
if (!options.originX) {
options.originX = "left";
}
var textContent = "";
if (!("textContent" in element)) {
if ("firstChild" in element && element.firstChild !== null) {
@ -11637,18 +11667,16 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
}
textContent = textContent.replace(/^\s+|\s+$|\n+/g, "").replace(/\s+/g, " ");
var text = new fabric.Text(textContent, options), textHeightScaleFactor = text.getScaledHeight() / text.height, lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height, scaledDiff = lineHeightDiff * textHeightScaleFactor, textHeight = text.getScaledHeight() + scaledDiff, offX = 0;
if (text.originX === "center") {
if (parsedAnchor === "center") {
offX = text.getScaledWidth() / 2;
}
if (text.originX === "right") {
if (parsedAnchor === "right") {
offX = text.getScaledWidth();
}
text.set({
left: text.left - offX,
top: text.top - (textHeight - text.fontSize * (.18 + text._fontSizeFraction)) / text.lineHeight
});
text.originX = "left";
text.originY = "top";
callback(text);
};
fabric.Text.fromObject = function(object, callback) {
@ -11710,15 +11738,15 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
target: this
});
},
getSelectionStyles: function(startIndex, endIndex) {
if (arguments.length === 2) {
getSelectionStyles: function(startIndex, endIndex, complete) {
if (endIndex && startIndex !== endIndex) {
var styles = [];
for (var i = startIndex; i < endIndex; i++) {
styles.push(this.getSelectionStyles(i));
styles.push(this.getSelectionStyles(i, i, complete));
}
return styles;
}
var loc = this.get2DCursorLocation(startIndex), style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex);
var loc = this.get2DCursorLocation(startIndex), style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) : this._getStyleDeclaration(loc.lineIndex, loc.charIndex);
return style || {};
},
setSelectionStyles: function(styles) {
@ -12024,6 +12052,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this.selectionEnd = this._text.length;
this._fireSelectionChanged();
this._updateTextarea();
return this;
},
getSelectedText: function() {
return this._text.slice(this.selectionStart, this.selectionEnd).join("");
@ -12099,6 +12128,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
return this;
},
enterEditing: function(e) {
if (this.isEditing || !this.editable) {
@ -12349,14 +12379,15 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
} else {
if (this.styles[lineStart]) {
styleObj = this.styles[lineStart];
var diff = charEnd - charStart;
var diff = charEnd - charStart, numericChar, _char;
for (i = charStart; i < charEnd; i++) {
delete styleObj[i];
}
for (i = charEnd; i < this._textLines[lineStart].length; i++) {
if (styleObj[i]) {
styleObj[i - diff] = styleObj[i];
delete styleObj[i];
for (_char in this.styles[lineStart]) {
numericChar = parseInt(_char, 10);
if (numericChar >= charEnd) {
styleObj[numericChar - diff] = styleObj[_char];
delete styleObj[_char];
}
}
}
@ -12383,8 +12414,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
var currentCharStyle, newLineStyles = {}, somethingAdded = false;
qty || (qty = 1);
this.shiftLineStyles(lineIndex, qty);
if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) {
currentCharStyle = this.styles[lineIndex][charIndex - 1];
if (this.styles[lineIndex]) {
currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1];
}
for (var index in this.styles[lineIndex]) {
var numIndex = parseInt(index, 10);
@ -12401,7 +12432,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
}
while (qty > 1) {
qty--;
if (copiedStyle[qty]) {
if (copiedStyle && copiedStyle[qty]) {
this.styles[lineIndex + qty] = {
0: clone(copiedStyle[qty])
};
@ -12419,7 +12450,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
if (!this.styles) {
this.styles = {};
}
var currentLineStyles = this.styles[lineIndex], currentLineStylesCloned = clone(currentLineStyles);
var currentLineStyles = this.styles[lineIndex], currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {};
quantity || (quantity = 1);
for (var index in currentLineStylesCloned) {
var numericIndex = parseInt(index, 10);
@ -12433,6 +12464,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
this._forceClearCache = true;
if (copiedStyle) {
while (quantity--) {
if (!Object.keys(copiedStyle[quantity]).length) {
continue;
}
if (!this.styles[lineIndex]) {
this.styles[lineIndex] = {};
}
this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]);
}
return;
@ -12446,26 +12483,24 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
}
},
insertNewStyleBlock: function(insertedText, start, copiedStyle) {
var cursorLoc = this.get2DCursorLocation(start, true), addingNewLines = 0, addingChars = 0;
var cursorLoc = this.get2DCursorLocation(start, true), addedLines = [ 0 ], linesLenght = 0;
for (var i = 0; i < insertedText.length; i++) {
if (insertedText[i] === "\n") {
if (addingChars) {
this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingChars, copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addingChars);
addingChars = 0;
}
addingNewLines++;
linesLenght++;
addedLines[linesLenght] = 0;
} else {
if (addingNewLines) {
this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingNewLines, copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addingNewLines);
addingNewLines = 0;
}
addingChars++;
addedLines[linesLenght]++;
}
}
addingChars && this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingChars, copiedStyle);
addingNewLines && this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addingNewLines, copiedStyle);
if (addedLines[0] > 0) {
this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);
}
linesLenght && this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLenght);
for (var i = 1; i <= linesLenght; i++) {
this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
}
},
setSelectionStartEndWithShift: function(start, end, newSelection) {
if (newSelection <= start) {
@ -12792,7 +12827,7 @@ fabric.util.object.extend(fabric.IText.prototype, {
return;
}
fabric.copiedText = this.getSelectedText();
fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd);
fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true);
this._copyDone = true;
},
paste: function() {

View file

@ -2,7 +2,7 @@
"name": "fabric",
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
"homepage": "http://fabricjs.com/",
"version": "2.0.0-beta.5",
"version": "2.0.0-beta.6",
"author": "Juriy Zaytsev <kangax@gmail.com>",
"contributors": [
{