mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-03-17 06:20:24 +00:00
196 lines
6.6 KiB
Diff
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};
|