This commit is contained in:
Andrea Bogazzi 2017-02-18 23:47:32 -05:00 committed by GitHub
parent 54f76a1066
commit 7a987faef2
12 changed files with 24 additions and 3136 deletions

View file

@ -1,19 +1,17 @@
language: node_js
node_js:
- "7"
- "6"
- "5"
- "4"
- "0.12"
- "0.11"
- "0.10"
env:
- CXX=g++-4.8
- CXX=g++-4.9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- g++-4.9
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq libgif-dev libpng-dev libjpeg8-dev libpango1.0-dev libcairo2-dev

View file

@ -1,6 +1,6 @@
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: "1.7.6" };
var fabric = fabric || { version: '1.7.6' };
if (typeof exports !== 'undefined') {
exports.fabric = fabric;
}
@ -13,23 +13,22 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
}
else {
// assume we're running under node.js when document/window are not present
fabric.document = require("jsdom")
fabric.document = require('jsdom')
.jsdom(
decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E")
);
decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'),
{ features: {
FetchExternalResources: ['img']
}
});
if (fabric.document.createWindow) {
fabric.window = fabric.document.createWindow();
} else {
fabric.window = fabric.document.parentWindow;
}
fabric.window = fabric.document.defaultView;
}
/**
* True when in environment that supports touch events
* @type boolean
*/
fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement;
fabric.isTouchSupported = 'ontouchstart' in fabric.document.documentElement;
/**
* True when in environment that's probably Node.js

View file

@ -1,196 +0,0 @@
Index: excanvas.js
===================================================================
--- excanvas.js (revision 63)
+++ excanvas.js (working copy)
@@ -255,6 +255,7 @@
o2.arcScaleX_ = o1.arcScaleX_;
o2.arcScaleY_ = o1.arcScaleY_;
o2.lineScale_ = o1.lineScale_;
+ o2.rotation_ = o1.rotation_; // used for images
}
var colorData = {
@@ -599,6 +600,7 @@
this.arcScaleX_ = 1;
this.arcScaleY_ = 1;
this.lineScale_ = 1;
+ this.rotation_ = 0;
}
var contextPrototype = CanvasRenderingContext2D_.prototype;
@@ -763,23 +765,31 @@
return gradient;
};
- contextPrototype.drawImage = function(image, var_args) {
+ contextPrototype.drawImage = function(image) {
var dx, dy, dw, dh, sx, sy, sw, sh;
-
+
+ // to fix new Image() we check the existance of runtimeStyle
+ var rts = image.runtimeStyle.width;
+
// to find the original width we overide the width and height
- var oldRuntimeWidth = image.runtimeStyle.width;
- var oldRuntimeHeight = image.runtimeStyle.height;
- image.runtimeStyle.width = 'auto';
- image.runtimeStyle.height = 'auto';
+ if(rts) {
+ var oldRuntimeWidth = image.runtimeStyle.width;
+ var oldRuntimeHeight = image.runtimeStyle.height;
+
+ image.runtimeStyle.width = 'auto';
+ image.runtimeStyle.height = 'auto';
+ }
// get the original size
var w = image.width;
var h = image.height;
-
+
// and remove overides
- image.runtimeStyle.width = oldRuntimeWidth;
- image.runtimeStyle.height = oldRuntimeHeight;
-
+ if(rts) {
+ image.runtimeStyle.width = oldRuntimeWidth;
+ image.runtimeStyle.height = oldRuntimeHeight;
+ }
+
if (arguments.length == 3) {
dx = arguments[1];
dy = arguments[2];
@@ -816,29 +826,44 @@
var W = 10;
var H = 10;
+
+ var scaleX = scaleY = 1;
+
+ // FIX: divs give better quality then vml image and also fixes transparent PNG's
+ vmlStr.push(' <div style="position:absolute;');
- // For some reason that I've now forgotten, using divs didn't work
- vmlStr.push(' <g_vml_:group',
- ' coordsize="', Z * W, ',', Z * H, '"',
- ' coordorigin="0,0"' ,
- ' style="width:', W, 'px;height:', H, 'px;position:absolute;');
-
// If filters are necessary (rotation exists), create them
// filters are bog-slow, so only create them if abbsolutely necessary
// The following check doesn't account for skews (which don't exist
// in the canvas spec (yet) anyway.
-
if (this.m_[0][0] != 1 || this.m_[0][1] ||
this.m_[1][1] != 1 || this.m_[1][0]) {
var filter = [];
- // Note the 12/21 reversal
- filter.push('M11=', this.m_[0][0], ',',
- 'M12=', this.m_[1][0], ',',
- 'M21=', this.m_[0][1], ',',
- 'M22=', this.m_[1][1], ',',
- 'Dx=', mr(d.x / Z), ',',
- 'Dy=', mr(d.y / Z), '');
+ // Scaling images using width & height instead of Transform Matrix
+ // because of quality loss
+ var c = mc(this.rotation_);
+ var s = ms(this.rotation_);
+
+ // Inverse rotation matrix
+ var irm = [
+ [c, -s, 0],
+ [s, c, 0],
+ [0, 0, 1]
+ ];
+
+ // Get unrotated matrix to get only scaling values
+ var urm = matrixMultiply(irm, this.m_);
+ scaleX = urm[0][0];
+ scaleY = urm[1][1];
+
+ // Apply only rotation and translation to Matrix
+ filter.push('M11=', c, ',',
+ 'M12=', -s, ',',
+ 'M21=', s, ',',
+ 'M22=', c, ',',
+ 'Dx=', d.x / Z, ',',
+ 'Dy=', d.y / Z);
// Bounding box calculation (need to minimize displayed area so that
// filters don't waste time on unused pixels.
@@ -853,23 +878,40 @@
vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
filter.join(''), ", sizingmethod='clip');");
-
} else {
vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
}
- vmlStr.push(' ">' ,
- '<g_vml_:image src="', image.src, '"',
- ' style="width:', Z * dw, 'px;',
- ' height:', Z * dh, 'px"',
- ' cropleft="', sx / w, '"',
- ' croptop="', sy / h, '"',
- ' cropright="', (w - sx - sw) / w, '"',
- ' cropbottom="', (h - sy - sh) / h, '"',
- ' />',
- '</g_vml_:group>');
+ vmlStr.push(' ">');
- this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join(''));
+ // Draw a special cropping div if needed
+ if (sx || sy) {
+ // Apply scales to width and height
+ vmlStr.push('<div style="overflow: hidden; width:', Math.ceil((dw + sx * dw / sw) * scaleX), 'px;',
+ ' height:', Math.ceil((dh + sy * dh / sh) * scaleY), 'px;',
+ ' filter:progid:DxImageTransform.Microsoft.Matrix(Dx=',
+ -sx * dw / sw * scaleX, ',Dy=', -sy * dh / sh * scaleY, ');">');
+ }
+
+
+ // Apply scales to width and height
+ vmlStr.push('<div style="width:', Math.round(scaleX * w * dw / sw), 'px;',
+ ' height:', Math.round(scaleY * h * dh / sh), 'px;',
+ ' filter:');
+
+ // If there is a globalAlpha, apply it to image
+ if(this.globalAlpha < 1) {
+ vmlStr.push(' progid:DXImageTransform.Microsoft.Alpha(opacity=' + (this.globalAlpha * 100) + ')');
+ }
+
+ vmlStr.push(' progid:DXImageTransform.Microsoft.AlphaImageLoader(src=', image.src, ',sizingMethod=scale)">');
+
+ // Close the crop div if necessary
+ if (sx || sy) vmlStr.push('</div>');
+
+ vmlStr.push('</div></div>');
+
+ this.element_.insertAdjacentHTML('beforeEnd', vmlStr.join(''));
};
contextPrototype.stroke = function(aFill) {
@@ -1155,6 +1197,8 @@
var c = mc(aRot);
var s = ms(aRot);
+ this.rotation_ += aRot;
+
var m1 = [
[c, s, 0],
[-s, c, 0],
@@ -1308,7 +1352,11 @@
}
var doc = this.element_.ownerDocument;
this.textMeasureEl_.innerHTML = '';
- this.textMeasureEl_.style.font = this.font;
+ // FIX: Apply current font style to textMeasureEl to get correct size
+ var fontStyle = getComputedStyle(processFontStyle(this.font), this.element_),
+ fontStyleString = buildStyle(fontStyle);
+ this.textMeasureEl_.style.font = fontStyleString;
+
// Don't use innerHTML or innerText because they allow markup/whitespace.
this.textMeasureEl_.appendChild(doc.createTextNode(text));
return {width: this.textMeasureEl_.offsetWidth};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -47,7 +47,7 @@
},
"optionalDependencies": {
"canvas": "1.6.x",
"jsdom": "3.x.x",
"jsdom": "9.x.x",
"xmldom": "0.1.x"
},
"devDependencies": {
@ -58,7 +58,7 @@
"onchange": "^3.0.2"
},
"engines": {
"node": ">=0.4.0"
"node": ">=4.0.0"
},
"main": "./dist/fabric.js"
}

View file

@ -1,9 +1,7 @@
(function() {
var degreesToRadians = fabric.util.degreesToRadians,
/* eslint-disable camelcase */
isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; };
/* eslint-enable camelcase */
var degreesToRadians = fabric.util.degreesToRadians;
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
/**
@ -312,7 +310,7 @@
}
break;
default:
isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size);
this.transparentCorners || ctx.clearRect(left, top, size, size);
ctx[methodName + 'Rect'](left, top, size, size);
if (stroke) {
ctx.strokeRect(left, top, size, size);

View file

@ -147,9 +147,6 @@
nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions),
nodeCacheCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions);
// jsdom doesn't create style on canvas element, so here be temp. workaround
canvasEl.style = { };
canvasEl.width = nodeCanvas.width;
canvasEl.height = nodeCanvas.height;
options = options || { };

View file

@ -433,22 +433,13 @@
/** @ignore */
replacement.width = canvasEl.width;
replacement.height = canvasEl.height;
if (fabric.isLikelyNode) {
replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);
// onload doesn't fire in some node versions, so we invoke callback manually
replacement.onload = function() {
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback(_this);
}
else {
replacement.onload = function() {
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback(_this);
replacement.onload = canvasEl = null;
};
replacement.src = canvasEl.toDataURL('image/png');
}
replacement.onload = canvasEl = null;
};
replacement.src = canvasEl.toDataURL('image/png');
return canvasEl;
},

View file

@ -191,14 +191,11 @@
}
var pointerX = function(event) {
// looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)
// is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]]
// need to investigate later
return (typeof event.clientX !== unknown ? event.clientX : 0);
return event.clientX;
},
pointerY = function(event) {
return (typeof event.clientY !== unknown ? event.clientY : 0);
return event.clientY;
};
function _getPointer(event, pageProp, clientProp) {

View file

@ -465,11 +465,6 @@
*/
createCanvasElement: function(canvasEl) {
canvasEl || (canvasEl = fabric.document.createElement('canvas'));
/* eslint-disable camelcase */
if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {
G_vmlCanvasManager.initElement(canvasEl);
}
/* eslint-enable camelcase */
return canvasEl;
},
@ -480,9 +475,7 @@
* @return {HTMLImageElement} HTML image element
*/
createImage: function() {
return fabric.isLikelyNode
? new (require('canvas').Image)()
: fabric.document.createElement('img');
return fabric.document.createElement('img');
},
/**

View file

@ -527,11 +527,6 @@
test('drawBorders', function() {
var cObj = new fabric.Object(), canvas = fabric.document.createElement('canvas');
//let excanvas kick in for IE8 and lower
if (!canvas.getContext && typeof G_vmlCanvasManager != 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var dummyContext = canvas.getContext('2d');
ok(typeof cObj.drawBorders == 'function');
@ -541,10 +536,6 @@
test('drawControls', function() {
var cObj = new fabric.Object(), canvas = fabric.document.createElement('canvas');
//let excanvas kick in for IE8 and lower
if (!canvas.getContext && typeof G_vmlCanvasManager != 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var dummyContext = canvas.getContext('2d');
ok(typeof cObj.drawControls == 'function');
equal(cObj.drawControls(dummyContext), cObj, 'chainable');