mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-03 11:34:41 +00:00
commit
fd22edb289
16 changed files with 206 additions and 137 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */
|
||||
|
||||
var fabric = fabric || { version: "1.1.13" };
|
||||
var fabric = fabric || { version: "1.1.14" };
|
||||
|
||||
if (typeof exports !== 'undefined') {
|
||||
exports.fabric = fabric;
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -1,4 +1,4 @@
|
|||
### Fabric
|
||||
### Fabric
|
||||
[](http://travis-ci.org/#!/kangax/fabric.js)
|
||||
<a href="https://npmjs.org/package/fabric"><img src="https://badge.fury.io/js/fabric.png"></a>
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ Using Fabric.js, you can create and populate objects on canvas; objects like sim
|
|||
|
||||
### Goals
|
||||
|
||||
- Unit tested (1500+ tests at the moment)
|
||||
- Unit tested (1570+ tests at the moment)
|
||||
- Modular (~40 small "classes", modules, mixins)
|
||||
- Cross-browser
|
||||
- [Fast](https://github.com/kangax/fabric.js/wiki/Focus-on-speed)
|
||||
|
|
@ -106,6 +106,16 @@ These are the optional modules that could be specified for inclusion, when build
|
|||
- **gestures** — Adds support for multitouch gestures with help of [Event.js](https://github.com/mudcube/Event.js)
|
||||
- **object_straightening** — Adds support for rotating an object to one of 0, 90, 180, 270, etc. depending on which is angle is closer.
|
||||
|
||||
Additional flags for build script are:
|
||||
|
||||
- **no-strict** — Strips "use strict" directives from source
|
||||
- **no-svg-export** — Removes svg exporting functionality
|
||||
- **no-es5-compat** - Removes ES5 compat methods (Array.prototype.*, String.prototype.*, Function.prototype.*)
|
||||
|
||||
For example:
|
||||
|
||||
node build.js modules=ALL exclude=json no-strict no-svg-export
|
||||
|
||||
### Examples of use
|
||||
|
||||
#### Adding red rectangle to canvas
|
||||
|
|
|
|||
8
build.js
8
build.js
|
|
@ -30,6 +30,7 @@ else if (minifier === 'uglifyjs') {
|
|||
var includeAllModules = modulesToInclude.length === 1 && modulesToInclude[0] === 'ALL';
|
||||
var noStrict = 'no-strict' in buildArgsAsObject;
|
||||
var noSVGExport = 'no-svg-export' in buildArgsAsObject;
|
||||
var noES5Compat = 'no-es5-compat' in buildArgsAsObject;
|
||||
|
||||
var distFileContents =
|
||||
'/* build: `node build.js modules=' +
|
||||
|
|
@ -37,6 +38,7 @@ var distFileContents =
|
|||
(modulesToExclude.length ? (' exclude=' + modulesToExclude.join(',')) : '') +
|
||||
(noStrict ? ' no-strict' : '') +
|
||||
(noSVGExport ? ' no-svg-export' : '') +
|
||||
(noES5Compat ? ' no-es5-compat' : '') +
|
||||
'` */\n';
|
||||
|
||||
function appendFileContents(fileNames, callback) {
|
||||
|
|
@ -62,6 +64,9 @@ function appendFileContents(fileNames, callback) {
|
|||
if (noSVGExport) {
|
||||
strData = strData.replace(/\/\* _TO_SVG_START_ \*\/[\s\S]*\/\* _TO_SVG_END_ \*\//, '');
|
||||
}
|
||||
if (noES5Compat) {
|
||||
strData = strData.replace(/\/\* _ES5_COMPAT_START_ \*\/[\s\S]*\/\* _ES5_COMPAT_END_ \*\//, '');
|
||||
}
|
||||
distFileContents += (strData + '\n');
|
||||
readNextFile();
|
||||
});
|
||||
|
|
@ -142,7 +147,8 @@ var filesToInclude = [
|
|||
'src/object.class.js',
|
||||
'src/object_origin.mixin.js',
|
||||
'src/object_geometry.mixin.js',
|
||||
'src/stateful.mixin.js',
|
||||
|
||||
ifSpecifiedInclude('stateful', 'src/stateful.mixin.js'),
|
||||
|
||||
ifSpecifiedInclude('interaction', 'src/object_interactivity.mixin.js'),
|
||||
|
||||
|
|
|
|||
147
dist/all.js
vendored
147
dist/all.js
vendored
|
|
@ -1,7 +1,7 @@
|
|||
/* build: `node build.js modules=ALL exclude=gestures` */
|
||||
/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */
|
||||
|
||||
var fabric = fabric || { version: "1.1.13" };
|
||||
var fabric = fabric || { version: "1.1.14" };
|
||||
|
||||
if (typeof exports !== 'undefined') {
|
||||
exports.fabric = fabric;
|
||||
|
|
@ -2462,6 +2462,8 @@ fabric.Collection = {
|
|||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
/* _ES5_COMPAT_START_ */
|
||||
|
||||
if (!Array.prototype.indexOf) {
|
||||
/**
|
||||
* Finds index of an element in an array
|
||||
|
|
@ -2626,6 +2628,8 @@ fabric.Collection = {
|
|||
};
|
||||
}
|
||||
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
||||
/**
|
||||
* Invokes method on all items in a given array
|
||||
* @memberOf fabric.util.array
|
||||
|
|
@ -2748,6 +2752,7 @@ fabric.Collection = {
|
|||
|
||||
(function() {
|
||||
|
||||
/* _ES5_COMPAT_START_ */
|
||||
if (!String.prototype.trim) {
|
||||
/**
|
||||
* Trims a string (removing whitespace from the beginning and the end)
|
||||
|
|
@ -2759,6 +2764,7 @@ if (!String.prototype.trim) {
|
|||
return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
|
||||
};
|
||||
}
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
||||
/**
|
||||
* Camelizes a string
|
||||
|
|
@ -2807,6 +2813,7 @@ fabric.util.string = {
|
|||
};
|
||||
}());
|
||||
|
||||
/* _ES5_COMPAT_START_ */
|
||||
(function() {
|
||||
|
||||
var slice = Array.prototype.slice,
|
||||
|
|
@ -2842,6 +2849,8 @@ fabric.util.string = {
|
|||
}
|
||||
|
||||
})();
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
||||
(function() {
|
||||
|
||||
var slice = Array.prototype.slice, emptyFunction = function() { };
|
||||
|
|
@ -3456,9 +3465,6 @@ fabric.util.string = {
|
|||
scriptEl = fabric.document.createElement('script'),
|
||||
loading = true;
|
||||
|
||||
scriptEl.type = 'text/javascript';
|
||||
scriptEl.setAttribute('runat', 'server');
|
||||
|
||||
/** @ignore */
|
||||
scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
|
||||
if (loading) {
|
||||
|
|
@ -4182,6 +4188,34 @@ fabric.util.string = {
|
|||
return parsedPoints;
|
||||
}
|
||||
|
||||
function parseFontDeclaration(value, oStyle) {
|
||||
|
||||
// TODO: support non-px font size
|
||||
var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px\s+(.*)/);
|
||||
|
||||
if (!match) return;
|
||||
|
||||
var fontStyle = match[1];
|
||||
// Font variant is not used
|
||||
// var fontVariant = match[2];
|
||||
var fontWeight = match[3];
|
||||
var fontSize = match[4];
|
||||
var fontFamily = match[5];
|
||||
|
||||
if (fontStyle) {
|
||||
oStyle.fontStyle = fontStyle;
|
||||
}
|
||||
if (fontWeight) {
|
||||
oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
|
||||
}
|
||||
if (fontSize) {
|
||||
oStyle.fontSize = parseFloat(fontSize);
|
||||
}
|
||||
if (fontFamily) {
|
||||
oStyle.fontFamily = fontFamily;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses "style" attribute, retuning an object with values
|
||||
* @static
|
||||
|
|
@ -4196,16 +4230,20 @@ fabric.util.string = {
|
|||
if (!style) return oStyle;
|
||||
|
||||
if (typeof style === 'string') {
|
||||
style = style.replace(/;$/, '').split(';').forEach(function (current) {
|
||||
style.replace(/;$/, '').split(';').forEach(function (chunk) {
|
||||
|
||||
var pair = current.split(':');
|
||||
var pair = chunk.split(':');
|
||||
var attr = normalizeAttr(pair[0].trim().toLowerCase());
|
||||
var value = normalizeValue(attr, pair[1].trim());
|
||||
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
@ -4214,9 +4252,15 @@ fabric.util.string = {
|
|||
|
||||
var attr = normalizeAttr(prop.toLowerCase());
|
||||
var value = normalizeValue(attr, style[prop]);
|
||||
var parsed = parseFloat(value);
|
||||
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8845,6 +8889,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mousedown
|
||||
*/
|
||||
_onMouseDown: function (e) {
|
||||
this.__onMouseDown(e);
|
||||
|
|
@ -8861,6 +8906,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mouseup
|
||||
*/
|
||||
_onMouseUp: function (e) {
|
||||
this.__onMouseUp(e);
|
||||
|
|
@ -8877,6 +8923,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mousemove
|
||||
*/
|
||||
_onMouseMove: function (e) {
|
||||
e.preventDefault && e.preventDefault();
|
||||
|
|
@ -8969,7 +9016,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
* canvas so the current image can be placed on the top canvas and the rest
|
||||
* in on the container one.
|
||||
* @private
|
||||
* @param e {Event} Event object fired on mousedown
|
||||
* @param {Event} e Event object fired on mousedown
|
||||
*/
|
||||
__onMouseDown: function (e) {
|
||||
|
||||
|
|
@ -9004,6 +9051,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
this.deactivateAllWithDispatch();
|
||||
target && target.selectable && this.setActiveObject(target, e);
|
||||
}
|
||||
else if (this._shouldHandleGroupLogic(e, target)) {
|
||||
this._handleGroupLogic(e, target);
|
||||
target = this.getActiveGroup();
|
||||
}
|
||||
else {
|
||||
// determine if it's a drag or rotate case
|
||||
this.stateful && target.saveState();
|
||||
|
|
@ -9012,15 +9063,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
this.onBeforeScaleRotate(target);
|
||||
}
|
||||
|
||||
if (this._shouldHandleGroupLogic(e, target)) {
|
||||
this._handleGroupLogic(e, target);
|
||||
target = this.getActiveGroup();
|
||||
}
|
||||
else {
|
||||
if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
|
||||
this.deactivateAll();
|
||||
this.setActiveObject(target, e);
|
||||
}
|
||||
if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
|
||||
this.deactivateAll();
|
||||
this.setActiveObject(target, e);
|
||||
}
|
||||
|
||||
this._setupCurrentTransform(e, target);
|
||||
|
|
@ -9047,7 +9092,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
* all any other type of action.
|
||||
* In case of an image transformation only the top canvas will be rendered.
|
||||
* @private
|
||||
* @param e {Event} Event object fired on mousemove
|
||||
* @param {Event} e Event object fired on mousemove
|
||||
*/
|
||||
__onMouseMove: function (e) {
|
||||
|
||||
|
|
@ -9174,8 +9219,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|||
/**
|
||||
* Sets the cursor depending on where the canvas is being hovered.
|
||||
* Note: very buggy in Opera
|
||||
* @param e {Event} Event object
|
||||
* @param target {Object} Object that the mouse is hovering, if so.
|
||||
* @param {Event} e Event object
|
||||
* @param {Object} target Object that the mouse is hovering, if so.
|
||||
*/
|
||||
_setCursorFromEvent: function (e, target) {
|
||||
var s = this.upperCanvasEl.style;
|
||||
|
|
@ -10909,38 +10954,29 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|||
* @param {String} to One of left, center, right
|
||||
*/
|
||||
adjustPosition: function(to) {
|
||||
|
||||
var angle = degreesToRadians(this.angle);
|
||||
|
||||
var hypotHalf = this.getWidth() / 2;
|
||||
var xHalf = Math.cos(angle) * hypotHalf;
|
||||
var yHalf = Math.sin(angle) * hypotHalf;
|
||||
|
||||
var hypotFull = this.getWidth();
|
||||
var xFull = Math.cos(angle) * hypotFull;
|
||||
var yFull = Math.sin(angle) * hypotFull;
|
||||
|
||||
if (this.originX === 'center' && to === 'left' ||
|
||||
this.originX === 'right' && to === 'center') {
|
||||
// move half left
|
||||
this.left -= xHalf;
|
||||
this.top -= yHalf;
|
||||
}
|
||||
else if (this.originX === 'left' && to === 'center' ||
|
||||
this.originX === 'center' && to === 'right') {
|
||||
// move half right
|
||||
this.left += xHalf;
|
||||
this.top += yHalf;
|
||||
}
|
||||
else if (this.originX === 'left' && to === 'right') {
|
||||
// move full right
|
||||
this.left += xFull;
|
||||
this.top += yFull;
|
||||
}
|
||||
else if (this.originX === 'right' && to === 'left') {
|
||||
// move full left
|
||||
this.left -= xFull;
|
||||
this.top -= yFull;
|
||||
}
|
||||
|
||||
this.setCoords();
|
||||
|
|
@ -10956,23 +10992,14 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|||
var hypotHalf = this.getWidth() / 2;
|
||||
var xHalf = Math.cos(angle) * hypotHalf;
|
||||
var yHalf = Math.sin(angle) * hypotHalf;
|
||||
|
||||
var hypotFull = this.getWidth();
|
||||
var xFull = Math.cos(angle) * hypotFull;
|
||||
var yFull = Math.sin(angle) * hypotFull;
|
||||
|
||||
var x = this.left;
|
||||
var y = this.top;
|
||||
|
||||
if (this.originX === 'center') {
|
||||
// move half left
|
||||
if (this.originX === 'center' || this.originX === 'right') {
|
||||
x -= xHalf;
|
||||
y -= yHalf;
|
||||
}
|
||||
else if (this.originX === 'right') {
|
||||
// move full left
|
||||
x -= xFull;
|
||||
y -= yFull;
|
||||
if (this.originY === 'center' || this.originY === 'bottom') {
|
||||
y -= yHalf;
|
||||
}
|
||||
|
||||
return { x: x, y: y };
|
||||
|
|
@ -15269,23 +15296,17 @@ fabric.Image.filters.Grayscale = fabric.util.createClass( /** @lends fabric.Imag
|
|||
var context = canvasEl.getContext('2d'),
|
||||
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
|
||||
data = imageData.data,
|
||||
iLen = imageData.width,
|
||||
jLen = imageData.height,
|
||||
index, average, i, j;
|
||||
|
||||
for (i = 0; i < iLen; i++) {
|
||||
for (j = 0; j < jLen; j++) {
|
||||
|
||||
index = (i * 4) * jLen + (j * 4);
|
||||
average = (data[index] + data[index + 1] + data[index + 2]) / 3;
|
||||
|
||||
data[index] = average;
|
||||
data[index + 1] = average;
|
||||
data[index + 2] = average;
|
||||
}
|
||||
}
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
len = imageData.width * imageData.height * 4,
|
||||
index = 0,
|
||||
average;
|
||||
while (index < len) {
|
||||
average = (data[index] + data[index + 1] + data[index + 2]) / 3;
|
||||
data[index] = average;
|
||||
data[index + 1] = average;
|
||||
data[index + 2] = average;
|
||||
index += 4;
|
||||
}
|
||||
context.putImageData(imageData, 0, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
12
dist/all.min.js
vendored
12
dist/all.min.js
vendored
File diff suppressed because one or more lines are too long
BIN
dist/all.min.js.gz
vendored
BIN
dist/all.min.js.gz
vendored
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "fabric",
|
||||
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
|
||||
"version": "1.1.13",
|
||||
"version": "1.1.14",
|
||||
"author": "Juriy Zaytsev <kangax@gmail.com>",
|
||||
"keywords": ["canvas", "graphic", "graphics", "SVG", "node-canvas", "parser", "HTML5", "object model"],
|
||||
"repository": "git://github.com/kangax/fabric.js",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mousedown
|
||||
*/
|
||||
_onMouseDown: function (e) {
|
||||
this.__onMouseDown(e);
|
||||
|
|
@ -66,6 +67,7 @@
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mouseup
|
||||
*/
|
||||
_onMouseUp: function (e) {
|
||||
this.__onMouseUp(e);
|
||||
|
|
@ -82,6 +84,7 @@
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} e Event object fired on mousemove
|
||||
*/
|
||||
_onMouseMove: function (e) {
|
||||
e.preventDefault && e.preventDefault();
|
||||
|
|
@ -174,7 +177,7 @@
|
|||
* canvas so the current image can be placed on the top canvas and the rest
|
||||
* in on the container one.
|
||||
* @private
|
||||
* @param e {Event} Event object fired on mousedown
|
||||
* @param {Event} e Event object fired on mousedown
|
||||
*/
|
||||
__onMouseDown: function (e) {
|
||||
|
||||
|
|
@ -209,6 +212,10 @@
|
|||
this.deactivateAllWithDispatch();
|
||||
target && target.selectable && this.setActiveObject(target, e);
|
||||
}
|
||||
else if (this._shouldHandleGroupLogic(e, target)) {
|
||||
this._handleGroupLogic(e, target);
|
||||
target = this.getActiveGroup();
|
||||
}
|
||||
else {
|
||||
// determine if it's a drag or rotate case
|
||||
this.stateful && target.saveState();
|
||||
|
|
@ -217,15 +224,9 @@
|
|||
this.onBeforeScaleRotate(target);
|
||||
}
|
||||
|
||||
if (this._shouldHandleGroupLogic(e, target)) {
|
||||
this._handleGroupLogic(e, target);
|
||||
target = this.getActiveGroup();
|
||||
}
|
||||
else {
|
||||
if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
|
||||
this.deactivateAll();
|
||||
this.setActiveObject(target, e);
|
||||
}
|
||||
if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
|
||||
this.deactivateAll();
|
||||
this.setActiveObject(target, e);
|
||||
}
|
||||
|
||||
this._setupCurrentTransform(e, target);
|
||||
|
|
@ -252,7 +253,7 @@
|
|||
* all any other type of action.
|
||||
* In case of an image transformation only the top canvas will be rendered.
|
||||
* @private
|
||||
* @param e {Event} Event object fired on mousemove
|
||||
* @param {Event} e Event object fired on mousemove
|
||||
*/
|
||||
__onMouseMove: function (e) {
|
||||
|
||||
|
|
@ -379,8 +380,8 @@
|
|||
/**
|
||||
* Sets the cursor depending on where the canvas is being hovered.
|
||||
* Note: very buggy in Opera
|
||||
* @param e {Event} Event object
|
||||
* @param target {Object} Object that the mouse is hovering, if so.
|
||||
* @param {Event} e Event object
|
||||
* @param {Object} target Object that the mouse is hovering, if so.
|
||||
*/
|
||||
_setCursorFromEvent: function (e, target) {
|
||||
var s = this.upperCanvasEl.style;
|
||||
|
|
|
|||
|
|
@ -26,23 +26,17 @@ fabric.Image.filters.Grayscale = fabric.util.createClass( /** @lends fabric.Imag
|
|||
var context = canvasEl.getContext('2d'),
|
||||
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
|
||||
data = imageData.data,
|
||||
iLen = imageData.width,
|
||||
jLen = imageData.height,
|
||||
index, average, i, j;
|
||||
|
||||
for (i = 0; i < iLen; i++) {
|
||||
for (j = 0; j < jLen; j++) {
|
||||
|
||||
index = (i * 4) * jLen + (j * 4);
|
||||
average = (data[index] + data[index + 1] + data[index + 2]) / 3;
|
||||
|
||||
data[index] = average;
|
||||
data[index + 1] = average;
|
||||
data[index + 2] = average;
|
||||
}
|
||||
}
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
len = imageData.width * imageData.height * 4,
|
||||
index = 0,
|
||||
average;
|
||||
while (index < len) {
|
||||
average = (data[index] + data[index + 1] + data[index + 2]) / 3;
|
||||
data[index] = average;
|
||||
data[index + 1] = average;
|
||||
data[index + 2] = average;
|
||||
index += 4;
|
||||
}
|
||||
context.putImageData(imageData, 0, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -156,38 +156,29 @@
|
|||
* @param {String} to One of left, center, right
|
||||
*/
|
||||
adjustPosition: function(to) {
|
||||
|
||||
var angle = degreesToRadians(this.angle);
|
||||
|
||||
var hypotHalf = this.getWidth() / 2;
|
||||
var xHalf = Math.cos(angle) * hypotHalf;
|
||||
var yHalf = Math.sin(angle) * hypotHalf;
|
||||
|
||||
var hypotFull = this.getWidth();
|
||||
var xFull = Math.cos(angle) * hypotFull;
|
||||
var yFull = Math.sin(angle) * hypotFull;
|
||||
|
||||
if (this.originX === 'center' && to === 'left' ||
|
||||
this.originX === 'right' && to === 'center') {
|
||||
// move half left
|
||||
this.left -= xHalf;
|
||||
this.top -= yHalf;
|
||||
}
|
||||
else if (this.originX === 'left' && to === 'center' ||
|
||||
this.originX === 'center' && to === 'right') {
|
||||
// move half right
|
||||
this.left += xHalf;
|
||||
this.top += yHalf;
|
||||
}
|
||||
else if (this.originX === 'left' && to === 'right') {
|
||||
// move full right
|
||||
this.left += xFull;
|
||||
this.top += yFull;
|
||||
}
|
||||
else if (this.originX === 'right' && to === 'left') {
|
||||
// move full left
|
||||
this.left -= xFull;
|
||||
this.top -= yFull;
|
||||
}
|
||||
|
||||
this.setCoords();
|
||||
|
|
@ -203,23 +194,14 @@
|
|||
var hypotHalf = this.getWidth() / 2;
|
||||
var xHalf = Math.cos(angle) * hypotHalf;
|
||||
var yHalf = Math.sin(angle) * hypotHalf;
|
||||
|
||||
var hypotFull = this.getWidth();
|
||||
var xFull = Math.cos(angle) * hypotFull;
|
||||
var yFull = Math.sin(angle) * hypotFull;
|
||||
|
||||
var x = this.left;
|
||||
var y = this.top;
|
||||
|
||||
if (this.originX === 'center') {
|
||||
// move half left
|
||||
if (this.originX === 'center' || this.originX === 'right') {
|
||||
x -= xHalf;
|
||||
y -= yHalf;
|
||||
}
|
||||
else if (this.originX === 'right') {
|
||||
// move full left
|
||||
x -= xFull;
|
||||
y -= yFull;
|
||||
if (this.originY === 'center' || this.originY === 'bottom') {
|
||||
y -= yHalf;
|
||||
}
|
||||
|
||||
return { x: x, y: y };
|
||||
|
|
|
|||
|
|
@ -287,6 +287,34 @@
|
|||
return parsedPoints;
|
||||
}
|
||||
|
||||
function parseFontDeclaration(value, oStyle) {
|
||||
|
||||
// TODO: support non-px font size
|
||||
var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px\s+(.*)/);
|
||||
|
||||
if (!match) return;
|
||||
|
||||
var fontStyle = match[1];
|
||||
// Font variant is not used
|
||||
// var fontVariant = match[2];
|
||||
var fontWeight = match[3];
|
||||
var fontSize = match[4];
|
||||
var fontFamily = match[5];
|
||||
|
||||
if (fontStyle) {
|
||||
oStyle.fontStyle = fontStyle;
|
||||
}
|
||||
if (fontWeight) {
|
||||
oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
|
||||
}
|
||||
if (fontSize) {
|
||||
oStyle.fontSize = parseFloat(fontSize);
|
||||
}
|
||||
if (fontFamily) {
|
||||
oStyle.fontFamily = fontFamily;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses "style" attribute, retuning an object with values
|
||||
* @static
|
||||
|
|
@ -301,16 +329,20 @@
|
|||
if (!style) return oStyle;
|
||||
|
||||
if (typeof style === 'string') {
|
||||
style = style.replace(/;$/, '').split(';').forEach(function (current) {
|
||||
style.replace(/;$/, '').split(';').forEach(function (chunk) {
|
||||
|
||||
var pair = current.split(':');
|
||||
var pair = chunk.split(':');
|
||||
var attr = normalizeAttr(pair[0].trim().toLowerCase());
|
||||
var value = normalizeValue(attr, pair[1].trim());
|
||||
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
@ -319,9 +351,15 @@
|
|||
|
||||
var attr = normalizeAttr(prop.toLowerCase());
|
||||
var value = normalizeValue(attr, style[prop]);
|
||||
var parsed = parseFloat(value);
|
||||
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,9 +211,6 @@
|
|||
scriptEl = fabric.document.createElement('script'),
|
||||
loading = true;
|
||||
|
||||
scriptEl.type = 'text/javascript';
|
||||
scriptEl.setAttribute('runat', 'server');
|
||||
|
||||
/** @ignore */
|
||||
scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
|
||||
if (loading) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
/* _ES5_COMPAT_START_ */
|
||||
|
||||
if (!Array.prototype.indexOf) {
|
||||
/**
|
||||
* Finds index of an element in an array
|
||||
|
|
@ -166,6 +168,8 @@
|
|||
};
|
||||
}
|
||||
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
||||
/**
|
||||
* Invokes method on all items in a given array
|
||||
* @memberOf fabric.util.array
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* _ES5_COMPAT_START_ */
|
||||
(function() {
|
||||
|
||||
var slice = Array.prototype.slice,
|
||||
|
|
@ -32,4 +33,5 @@
|
|||
};
|
||||
}
|
||||
|
||||
})();
|
||||
})();
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
(function() {
|
||||
|
||||
/* _ES5_COMPAT_START_ */
|
||||
if (!String.prototype.trim) {
|
||||
/**
|
||||
* Trims a string (removing whitespace from the beginning and the end)
|
||||
|
|
@ -11,6 +12,7 @@ if (!String.prototype.trim) {
|
|||
return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
|
||||
};
|
||||
}
|
||||
/* _ES5_COMPAT_END_ */
|
||||
|
||||
/**
|
||||
* Camelizes a string
|
||||
|
|
|
|||
|
|
@ -155,6 +155,18 @@
|
|||
deepEqual(expectedObject, fabric.parseStyleAttribute(element));
|
||||
});
|
||||
|
||||
test('parseStyleAttribute with short font declaration', function() {
|
||||
var element = fabric.document.createElement('path');
|
||||
element.setAttribute('style', 'font: italic 12px Arial,Helvetica,sans-serif');
|
||||
|
||||
var expectedObject = {
|
||||
'fontSize': 12,
|
||||
'fontStyle': 'italic',
|
||||
'fontFamily': 'Arial,Helvetica,sans-serif'
|
||||
};
|
||||
deepEqual(expectedObject, fabric.parseStyleAttribute(element));
|
||||
});
|
||||
|
||||
test('parseAttributes (style to have higher priority than attribute)', function() {
|
||||
var element = fabric.document.createElement('path');
|
||||
element.setAttribute('style', 'fill:red');
|
||||
|
|
|
|||
Loading…
Reference in a new issue