fabric.js/lib/excanvas-diff.patch
2014-02-23 20:16:20 +02:00

196 lines
6.6 KiB
Diff

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};