Move Cufon methods to text.cufon. Move drawControls to Canvas (from StaticCanvas). Move dataURL-exporting methods to dataurl_exporter mixin.

This commit is contained in:
kangax 2013-06-06 12:31:32 +02:00
parent e1f93a3668
commit 51b7c09314
10 changed files with 501 additions and 515 deletions

View file

@ -147,6 +147,7 @@ var filesToInclude = [
ifSpecifiedInclude('interaction', 'src/mixins/canvas_events.mixin.js'),
'src/mixins/canvas_animation.mixin.js',
'src/mixins/canvas_dataurl_exporter.mixin.js',
ifSpecifiedInclude('serialization', 'src/mixins/canvas_serialization.mixin.js'),
ifSpecifiedInclude('gestures', 'src/mixins/canvas_gestures.mixin.js'),
@ -185,6 +186,7 @@ var filesToInclude = [
ifSpecifiedInclude('image_filters', 'src/filters/tint_filter.class.js'),
ifSpecifiedInclude('text', 'src/shapes/text.class.js'),
ifSpecifiedInclude('cufon', 'src/shapes/text.cufon.js'),
ifSpecifiedInclude('node', 'src/node.js')
];

504
dist/all.js vendored
View file

@ -5424,7 +5424,7 @@ fabric.util.string = {
this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2);
}
for (var i = 0; i < this.colorStops.length; i++) {
for (var i = 0, len = this.colorStops.length; i < len; i++) {
var color = this.colorStops[i].color,
opacity = this.colorStops[i].opacity,
offset = this.colorStops[i].offset;
@ -6412,6 +6412,7 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
extend(fabric.StaticCanvas.prototype, fabric.Observable);
extend(fabric.StaticCanvas.prototype, fabric.Collection);
extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);
extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
@ -6931,7 +6932,7 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
canvasToDrawOn.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
}
if (this.controlsAboveOverlay) {
if (this.controlsAboveOverlay && this.interactive) {
this.drawControls(canvasToDrawOn);
}
@ -6987,167 +6988,6 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
return this;
},
/**
* Draws objects' controls (borders/controls)
* @param {Object} ctx context to render controls on
*/
drawControls: function(ctx) {
var activeGroup = this.getActiveGroup();
if (activeGroup) {
ctx.save();
fabric.Group.prototype.transform.call(activeGroup, ctx);
activeGroup.drawBorders(ctx).drawControls(ctx);
ctx.restore();
}
else {
for (var i = 0, len = this._objects.length; i < len; ++i) {
if (!this._objects[i] || !this._objects[i].active) continue;
ctx.save();
fabric.Object.prototype.transform.call(this._objects[i], ctx);
this._objects[i].drawBorders(ctx).drawControls(ctx);
ctx.restore();
this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];
}
}
},
/**
* Exports canvas element to a dataurl image.
* @param {Object} options
*
* `format` the format of the output image. Either "jpeg" or "png".
* `quality` quality level (0..1)
* `multiplier` multiplier to scale by {Number}
*
* @return {String}
*/
toDataURL: function (options) {
options || (options = { });
var format = options.format || 'png',
quality = options.quality || 1,
multiplier = options.multiplier || 1;
if (multiplier !== 1) {
return this.__toDataURLWithMultiplier(format, quality, multiplier);
}
else {
return this.__toDataURL(format, quality);
}
},
/**
* @private
*/
__toDataURL: function(format, quality) {
this.renderAll(true);
var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
? canvasEl.toDataURL('image/' + format, quality)
: canvasEl.toDataURL('image/' + format);
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* @private
*/
__toDataURLWithMultiplier: function(format, quality, multiplier) {
var origWidth = this.getWidth(),
origHeight = this.getHeight(),
scaledWidth = origWidth * multiplier,
scaledHeight = origHeight * multiplier,
activeObject = this.getActiveObject(),
activeGroup = this.getActiveGroup(),
ctx = this.contextTop || this.contextContainer;
this.setWidth(scaledWidth).setHeight(scaledHeight);
ctx.scale(multiplier, multiplier);
if (activeGroup) {
// not removing group due to complications with restoring it with correct state afterwords
this._tempRemoveBordersControlsFromGroup(activeGroup);
}
else if (activeObject && this.deactivateAll) {
this.deactivateAll();
}
// restoring width, height for `renderAll` to draw
// background properly (while context is scaled)
this.width = origWidth;
this.height = origHeight;
this.renderAll(true);
var data = this.__toDataURL(format, quality);
ctx.scale(1 / multiplier, 1 / multiplier);
this.setWidth(origWidth).setHeight(origHeight);
if (activeGroup) {
this._restoreBordersControlsOnGroup(activeGroup);
}
else if (activeObject && this.setActiveObject) {
this.setActiveObject(activeObject);
}
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* Exports canvas element to a dataurl image (allowing to change image size via multiplier).
* @deprecated since 1.0.13
* @param {String} format (png|jpeg)
* @param {Number} multiplier
* @param {Number} quality (0..1)
* @return {String}
*/
toDataURLWithMultiplier: function (format, multiplier, quality) {
return this.toDataURL({
format: format,
multiplier: multiplier,
quality: quality
});
},
/**
* @private
*/
_tempRemoveBordersControlsFromGroup: function(group) {
group.origHasControls = group.hasControls;
group.origBorderColor = group.borderColor;
group.hasControls = true;
group.borderColor = 'rgba(0,0,0,0)';
group.forEachObject(function(o) {
o.origBorderColor = o.borderColor;
o.borderColor = 'rgba(0,0,0,0)';
});
},
/**
* @private
*/
_restoreBordersControlsOnGroup: function(group) {
group.hideControls = group.origHideControls;
group.borderColor = group.origBorderColor;
group.forEachObject(function(o) {
o.borderColor = o.origBorderColor;
delete o.origBorderColor;
});
},
/**
* Returns coordinates of a center of canvas.
* Returned value is an object with top and left properties
@ -7488,21 +7328,6 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
removeListener(fabric.window, 'resize', this._onResize);
}
return this;
},
/**
* @private
* @param {HTMLImageElement} imgEl
*/
_resizeImageToFit: function (imgEl) {
var imageWidth = imgEl.width || imgEl.offsetWidth,
widthScaleFactor = this.getWidth() / imageWidth;
// scale image down so that it has original dimensions when printed in large resolution
if (imageWidth) {
imgEl.width = imageWidth * widthScaleFactor;
}
}
});
@ -9228,6 +9053,32 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
this.fire('selection:cleared');
}
return this;
},
/**
* Draws objects' controls (borders/controls)
* @param {Object} ctx context to render controls on
*/
drawControls: function(ctx) {
var activeGroup = this.getActiveGroup();
if (activeGroup) {
ctx.save();
fabric.Group.prototype.transform.call(activeGroup, ctx);
activeGroup.drawBorders(ctx).drawControls(ctx);
ctx.restore();
}
else {
for (var i = 0, len = this._objects.length; i < len; ++i) {
if (!this._objects[i] || !this._objects[i].active) continue;
ctx.save();
fabric.Object.prototype.transform.call(this._objects[i], ctx);
this._objects[i].drawBorders(ctx).drawControls(ctx);
ctx.restore();
this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];
}
}
}
};
@ -9806,6 +9657,145 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
});
fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
/**
* Exports canvas element to a dataurl image.
* @param {Object} options
*
* `format` the format of the output image. Either "jpeg" or "png".
* `quality` quality level (0..1)
* `multiplier` multiplier to scale by {Number}
*
* @return {String}
*/
toDataURL: function (options) {
options || (options = { });
var format = options.format || 'png',
quality = options.quality || 1,
multiplier = options.multiplier || 1;
if (multiplier !== 1) {
return this.__toDataURLWithMultiplier(format, quality, multiplier);
}
else {
return this.__toDataURL(format, quality);
}
},
/**
* @private
*/
__toDataURL: function(format, quality) {
this.renderAll(true);
var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
? canvasEl.toDataURL('image/' + format, quality)
: canvasEl.toDataURL('image/' + format);
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* @private
*/
__toDataURLWithMultiplier: function(format, quality, multiplier) {
var origWidth = this.getWidth(),
origHeight = this.getHeight(),
scaledWidth = origWidth * multiplier,
scaledHeight = origHeight * multiplier,
activeObject = this.getActiveObject(),
activeGroup = this.getActiveGroup(),
ctx = this.contextTop || this.contextContainer;
this.setWidth(scaledWidth).setHeight(scaledHeight);
ctx.scale(multiplier, multiplier);
if (activeGroup) {
// not removing group due to complications with restoring it with correct state afterwords
this._tempRemoveBordersControlsFromGroup(activeGroup);
}
else if (activeObject && this.deactivateAll) {
this.deactivateAll();
}
// restoring width, height for `renderAll` to draw
// background properly (while context is scaled)
this.width = origWidth;
this.height = origHeight;
this.renderAll(true);
var data = this.__toDataURL(format, quality);
ctx.scale(1 / multiplier, 1 / multiplier);
this.setWidth(origWidth).setHeight(origHeight);
if (activeGroup) {
this._restoreBordersControlsOnGroup(activeGroup);
}
else if (activeObject && this.setActiveObject) {
this.setActiveObject(activeObject);
}
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* Exports canvas element to a dataurl image (allowing to change image size via multiplier).
* @deprecated since 1.0.13
* @param {String} format (png|jpeg)
* @param {Number} multiplier
* @param {Number} quality (0..1)
* @return {String}
*/
toDataURLWithMultiplier: function (format, multiplier, quality) {
return this.toDataURL({
format: format,
multiplier: multiplier,
quality: quality
});
},
/**
* @private
*/
_tempRemoveBordersControlsFromGroup: function(group) {
group.origHasControls = group.hasControls;
group.origBorderColor = group.borderColor;
group.hasControls = true;
group.borderColor = 'rgba(0,0,0,0)';
group.forEachObject(function(o) {
o.origBorderColor = o.borderColor;
o.borderColor = 'rgba(0,0,0,0)';
});
},
/**
* @private
*/
_restoreBordersControlsOnGroup: function(group) {
group.hideControls = group.origHideControls;
group.borderColor = group.origBorderColor;
group.forEachObject(function(o) {
o.borderColor = o.origBorderColor;
delete o.origBorderColor;
});
}
});
fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
/**
@ -16833,57 +16823,6 @@ fabric.Image.filters.Tint.fromObject = function(object) {
}
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
_renderViaCufon: function(ctx) {
var o = Cufon.textOptions || (Cufon.textOptions = { });
// export options to be used by cufon.js
o.left = this.left;
o.top = this.top;
o.context = ctx;
o.color = this.fill;
var el = this._initDummyElementForCufon();
// set "cursor" to top/left corner
this.transform(ctx);
// draw text
Cufon.replaceElement(el, {
engine: 'canvas',
separate: 'none',
fontFamily: this.fontFamily,
fontWeight: this.fontWeight,
textDecoration: this.textDecoration,
textShadow: this.textShadow,
textAlign: this.textAlign,
fontStyle: this.fontStyle,
lineHeight: this.lineHeight,
stroke: this.stroke,
strokeWidth: this.strokeWidth,
backgroundColor: this.backgroundColor,
textBackgroundColor: this.textBackgroundColor
});
// update width, height
this.width = o.width;
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._boundaries = o.boundaries;
this._shadowOffsets = o.shadowOffsets;
this._shadows = o.shadows || [ ];
el = null;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
@ -17289,32 +17228,6 @@ fabric.Image.filters.Tint.fromObject = function(object) {
].join(' ');
},
/**
* @private
*/
_initDummyElementForCufon: function() {
var el = fabric.document.createElement('pre'),
container = fabric.document.createElement('div');
// Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
container.appendChild(el);
if (typeof G_vmlCanvasManager === 'undefined') {
el.innerHTML = this.text;
}
else {
// IE 7 & 8 drop newlines and white space on text nodes
// see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
// see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
el.innerText = this.text.replace(/\r?\n/gi, '\r');
}
el.style.fontSize = this.fontSize + 'px';
el.style.letterSpacing = 'normal';
return el;
},
/**
* Renders text instance on a specified context
* @param {CanvasRenderingContext2D} ctx Context to render on
@ -17627,6 +17540,87 @@ fabric.Image.filters.Tint.fromObject = function(object) {
})(typeof exports !== 'undefined' ? exports : this);
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
fabric.util.object.extend(fabric.Text.prototype, {
_renderViaCufon: function(ctx) {
var o = Cufon.textOptions || (Cufon.textOptions = { });
// export options to be used by cufon.js
o.left = this.left;
o.top = this.top;
o.context = ctx;
o.color = this.fill;
var el = this._initDummyElementForCufon();
// set "cursor" to top/left corner
this.transform(ctx);
// draw text
Cufon.replaceElement(el, {
engine: 'canvas',
separate: 'none',
fontFamily: this.fontFamily,
fontWeight: this.fontWeight,
textDecoration: this.textDecoration,
textShadow: this.textShadow,
textAlign: this.textAlign,
fontStyle: this.fontStyle,
lineHeight: this.lineHeight,
stroke: this.stroke,
strokeWidth: this.strokeWidth,
backgroundColor: this.backgroundColor,
textBackgroundColor: this.textBackgroundColor
});
// update width, height
this.width = o.width;
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._boundaries = o.boundaries;
this._shadowOffsets = o.shadowOffsets;
this._shadows = o.shadows || [ ];
el = null;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
},
/**
* @private
*/
_initDummyElementForCufon: function() {
var el = fabric.document.createElement('pre'),
container = fabric.document.createElement('div');
// Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
container.appendChild(el);
if (typeof G_vmlCanvasManager === 'undefined') {
el.innerHTML = this.text;
}
else {
// IE 7 & 8 drop newlines and white space on text nodes
// see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
// see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
el.innerText = this.text.replace(/\r?\n/gi, '\r');
}
el.style.fontSize = this.fontSize + 'px';
el.style.letterSpacing = 'normal';
return el;
}
});
(function() {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {

10
dist/all.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/all.min.js.gz vendored

Binary file not shown.

View file

@ -937,6 +937,32 @@
this.fire('selection:cleared');
}
return this;
},
/**
* Draws objects' controls (borders/controls)
* @param {Object} ctx context to render controls on
*/
drawControls: function(ctx) {
var activeGroup = this.getActiveGroup();
if (activeGroup) {
ctx.save();
fabric.Group.prototype.transform.call(activeGroup, ctx);
activeGroup.drawBorders(ctx).drawControls(ctx);
ctx.restore();
}
else {
for (var i = 0, len = this._objects.length; i < len; ++i) {
if (!this._objects[i] || !this._objects[i].active) continue;
ctx.save();
fabric.Object.prototype.transform.call(this._objects[i], ctx);
this._objects[i].drawBorders(ctx).drawControls(ctx);
ctx.restore();
this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];
}
}
}
};

View file

@ -198,7 +198,7 @@
this.coords.x1, this.coords.y1, this.coords.r1, this.coords.x2, this.coords.y2, this.coords.r2);
}
for (var i = 0; i < this.colorStops.length; i++) {
for (var i = 0, len = this.colorStops.length; i < len; i++) {
var color = this.colorStops[i].color,
opacity = this.colorStops[i].opacity,
offset = this.colorStops[i].offset;

View file

@ -0,0 +1,137 @@
fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
/**
* Exports canvas element to a dataurl image.
* @param {Object} options
*
* `format` the format of the output image. Either "jpeg" or "png".
* `quality` quality level (0..1)
* `multiplier` multiplier to scale by {Number}
*
* @return {String}
*/
toDataURL: function (options) {
options || (options = { });
var format = options.format || 'png',
quality = options.quality || 1,
multiplier = options.multiplier || 1;
if (multiplier !== 1) {
return this.__toDataURLWithMultiplier(format, quality, multiplier);
}
else {
return this.__toDataURL(format, quality);
}
},
/**
* @private
*/
__toDataURL: function(format, quality) {
this.renderAll(true);
var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
? canvasEl.toDataURL('image/' + format, quality)
: canvasEl.toDataURL('image/' + format);
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* @private
*/
__toDataURLWithMultiplier: function(format, quality, multiplier) {
var origWidth = this.getWidth(),
origHeight = this.getHeight(),
scaledWidth = origWidth * multiplier,
scaledHeight = origHeight * multiplier,
activeObject = this.getActiveObject(),
activeGroup = this.getActiveGroup(),
ctx = this.contextTop || this.contextContainer;
this.setWidth(scaledWidth).setHeight(scaledHeight);
ctx.scale(multiplier, multiplier);
if (activeGroup) {
// not removing group due to complications with restoring it with correct state afterwords
this._tempRemoveBordersControlsFromGroup(activeGroup);
}
else if (activeObject && this.deactivateAll) {
this.deactivateAll();
}
// restoring width, height for `renderAll` to draw
// background properly (while context is scaled)
this.width = origWidth;
this.height = origHeight;
this.renderAll(true);
var data = this.__toDataURL(format, quality);
ctx.scale(1 / multiplier, 1 / multiplier);
this.setWidth(origWidth).setHeight(origHeight);
if (activeGroup) {
this._restoreBordersControlsOnGroup(activeGroup);
}
else if (activeObject && this.setActiveObject) {
this.setActiveObject(activeObject);
}
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* Exports canvas element to a dataurl image (allowing to change image size via multiplier).
* @deprecated since 1.0.13
* @param {String} format (png|jpeg)
* @param {Number} multiplier
* @param {Number} quality (0..1)
* @return {String}
*/
toDataURLWithMultiplier: function (format, multiplier, quality) {
return this.toDataURL({
format: format,
multiplier: multiplier,
quality: quality
});
},
/**
* @private
*/
_tempRemoveBordersControlsFromGroup: function(group) {
group.origHasControls = group.hasControls;
group.origBorderColor = group.borderColor;
group.hasControls = true;
group.borderColor = 'rgba(0,0,0,0)';
group.forEachObject(function(o) {
o.origBorderColor = o.borderColor;
o.borderColor = 'rgba(0,0,0,0)';
});
},
/**
* @private
*/
_restoreBordersControlsOnGroup: function(group) {
group.hideControls = group.origHideControls;
group.borderColor = group.origBorderColor;
group.forEachObject(function(o) {
o.borderColor = o.origBorderColor;
delete o.origBorderColor;
});
}
});

View file

@ -211,57 +211,6 @@
}
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
_renderViaCufon: function(ctx) {
var o = Cufon.textOptions || (Cufon.textOptions = { });
// export options to be used by cufon.js
o.left = this.left;
o.top = this.top;
o.context = ctx;
o.color = this.fill;
var el = this._initDummyElementForCufon();
// set "cursor" to top/left corner
this.transform(ctx);
// draw text
Cufon.replaceElement(el, {
engine: 'canvas',
separate: 'none',
fontFamily: this.fontFamily,
fontWeight: this.fontWeight,
textDecoration: this.textDecoration,
textShadow: this.textShadow,
textAlign: this.textAlign,
fontStyle: this.fontStyle,
lineHeight: this.lineHeight,
stroke: this.stroke,
strokeWidth: this.strokeWidth,
backgroundColor: this.backgroundColor,
textBackgroundColor: this.textBackgroundColor
});
// update width, height
this.width = o.width;
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._boundaries = o.boundaries;
this._shadowOffsets = o.shadowOffsets;
this._shadows = o.shadows || [ ];
el = null;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
@ -667,32 +616,6 @@
].join(' ');
},
/**
* @private
*/
_initDummyElementForCufon: function() {
var el = fabric.document.createElement('pre'),
container = fabric.document.createElement('div');
// Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
container.appendChild(el);
if (typeof G_vmlCanvasManager === 'undefined') {
el.innerHTML = this.text;
}
else {
// IE 7 & 8 drop newlines and white space on text nodes
// see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
// see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
el.innerText = this.text.replace(/\r?\n/gi, '\r');
}
el.style.fontSize = this.fontSize + 'px';
el.style.letterSpacing = 'normal';
return el;
},
/**
* Renders text instance on a specified context
* @param {CanvasRenderingContext2D} ctx Context to render on

79
src/shapes/text.cufon.js Normal file
View file

@ -0,0 +1,79 @@
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
fabric.util.object.extend(fabric.Text.prototype, {
_renderViaCufon: function(ctx) {
var o = Cufon.textOptions || (Cufon.textOptions = { });
// export options to be used by cufon.js
o.left = this.left;
o.top = this.top;
o.context = ctx;
o.color = this.fill;
var el = this._initDummyElementForCufon();
// set "cursor" to top/left corner
this.transform(ctx);
// draw text
Cufon.replaceElement(el, {
engine: 'canvas',
separate: 'none',
fontFamily: this.fontFamily,
fontWeight: this.fontWeight,
textDecoration: this.textDecoration,
textShadow: this.textShadow,
textAlign: this.textAlign,
fontStyle: this.fontStyle,
lineHeight: this.lineHeight,
stroke: this.stroke,
strokeWidth: this.strokeWidth,
backgroundColor: this.backgroundColor,
textBackgroundColor: this.textBackgroundColor
});
// update width, height
this.width = o.width;
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._boundaries = o.boundaries;
this._shadowOffsets = o.shadowOffsets;
this._shadows = o.shadows || [ ];
el = null;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
},
/**
* @private
*/
_initDummyElementForCufon: function() {
var el = fabric.document.createElement('pre'),
container = fabric.document.createElement('div');
// Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
container.appendChild(el);
if (typeof G_vmlCanvasManager === 'undefined') {
el.innerHTML = this.text;
}
else {
// IE 7 & 8 drop newlines and white space on text nodes
// see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
// see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
el.innerText = this.text.replace(/\r?\n/gi, '\r');
}
el.style.fontSize = this.fontSize + 'px';
el.style.letterSpacing = 'normal';
return el;
}
});

View file

@ -35,6 +35,7 @@
extend(fabric.StaticCanvas.prototype, fabric.Observable);
extend(fabric.StaticCanvas.prototype, fabric.Collection);
extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);
extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
@ -554,7 +555,7 @@
canvasToDrawOn.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
}
if (this.controlsAboveOverlay) {
if (this.controlsAboveOverlay && this.interactive) {
this.drawControls(canvasToDrawOn);
}
@ -610,167 +611,6 @@
return this;
},
/**
* Draws objects' controls (borders/controls)
* @param {Object} ctx context to render controls on
*/
drawControls: function(ctx) {
var activeGroup = this.getActiveGroup();
if (activeGroup) {
ctx.save();
fabric.Group.prototype.transform.call(activeGroup, ctx);
activeGroup.drawBorders(ctx).drawControls(ctx);
ctx.restore();
}
else {
for (var i = 0, len = this._objects.length; i < len; ++i) {
if (!this._objects[i] || !this._objects[i].active) continue;
ctx.save();
fabric.Object.prototype.transform.call(this._objects[i], ctx);
this._objects[i].drawBorders(ctx).drawControls(ctx);
ctx.restore();
this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];
}
}
},
/**
* Exports canvas element to a dataurl image.
* @param {Object} options
*
* `format` the format of the output image. Either "jpeg" or "png".
* `quality` quality level (0..1)
* `multiplier` multiplier to scale by {Number}
*
* @return {String}
*/
toDataURL: function (options) {
options || (options = { });
var format = options.format || 'png',
quality = options.quality || 1,
multiplier = options.multiplier || 1;
if (multiplier !== 1) {
return this.__toDataURLWithMultiplier(format, quality, multiplier);
}
else {
return this.__toDataURL(format, quality);
}
},
/**
* @private
*/
__toDataURL: function(format, quality) {
this.renderAll(true);
var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
? canvasEl.toDataURL('image/' + format, quality)
: canvasEl.toDataURL('image/' + format);
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* @private
*/
__toDataURLWithMultiplier: function(format, quality, multiplier) {
var origWidth = this.getWidth(),
origHeight = this.getHeight(),
scaledWidth = origWidth * multiplier,
scaledHeight = origHeight * multiplier,
activeObject = this.getActiveObject(),
activeGroup = this.getActiveGroup(),
ctx = this.contextTop || this.contextContainer;
this.setWidth(scaledWidth).setHeight(scaledHeight);
ctx.scale(multiplier, multiplier);
if (activeGroup) {
// not removing group due to complications with restoring it with correct state afterwords
this._tempRemoveBordersControlsFromGroup(activeGroup);
}
else if (activeObject && this.deactivateAll) {
this.deactivateAll();
}
// restoring width, height for `renderAll` to draw
// background properly (while context is scaled)
this.width = origWidth;
this.height = origHeight;
this.renderAll(true);
var data = this.__toDataURL(format, quality);
ctx.scale(1 / multiplier, 1 / multiplier);
this.setWidth(origWidth).setHeight(origHeight);
if (activeGroup) {
this._restoreBordersControlsOnGroup(activeGroup);
}
else if (activeObject && this.setActiveObject) {
this.setActiveObject(activeObject);
}
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
},
/**
* Exports canvas element to a dataurl image (allowing to change image size via multiplier).
* @deprecated since 1.0.13
* @param {String} format (png|jpeg)
* @param {Number} multiplier
* @param {Number} quality (0..1)
* @return {String}
*/
toDataURLWithMultiplier: function (format, multiplier, quality) {
return this.toDataURL({
format: format,
multiplier: multiplier,
quality: quality
});
},
/**
* @private
*/
_tempRemoveBordersControlsFromGroup: function(group) {
group.origHasControls = group.hasControls;
group.origBorderColor = group.borderColor;
group.hasControls = true;
group.borderColor = 'rgba(0,0,0,0)';
group.forEachObject(function(o) {
o.origBorderColor = o.borderColor;
o.borderColor = 'rgba(0,0,0,0)';
});
},
/**
* @private
*/
_restoreBordersControlsOnGroup: function(group) {
group.hideControls = group.origHideControls;
group.borderColor = group.origBorderColor;
group.forEachObject(function(o) {
o.borderColor = o.origBorderColor;
delete o.origBorderColor;
});
},
/**
* Returns coordinates of a center of canvas.
* Returned value is an object with top and left properties
@ -1111,21 +951,6 @@
removeListener(fabric.window, 'resize', this._onResize);
}
return this;
},
/**
* @private
* @param {HTMLImageElement} imgEl
*/
_resizeImageToFit: function (imgEl) {
var imageWidth = imgEl.width || imgEl.offsetWidth,
widthScaleFactor = this.getWidth() / imageWidth;
// scale image down so that it has original dimensions when printed in large resolution
if (imageWidth) {
imgEl.width = imageWidth * widthScaleFactor;
}
}
});