Implement fabric.Text.fromElement. Closes #182.

This commit is contained in:
kangax 2012-08-11 18:59:53 +02:00
parent df02b880ae
commit 3ce8507932
11 changed files with 162 additions and 60 deletions

2
.sublime-project vendored
View file

@ -3,7 +3,7 @@
[
{
"path": ".",
"folder_exclude_patterns": ["tmp", "log"],
"folder_exclude_patterns": ["tmp", "log", "node_modules"],
"file_exclude_patterns": ["*.min.js", "*.gz", ".sublime-workspace"]
}
],

View file

@ -1,6 +1,6 @@
/*! Fabric.js Copyright 2008-2012, Printio (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: "0.8.45" };
var fabric = fabric || { version: "0.8.46" };
if (typeof exports != 'undefined') {
exports.fabric = fabric;

51
dist/all.js vendored
View file

@ -1,7 +1,7 @@
/* build: `node build.js modules=ALL` */
/*! Fabric.js Copyright 2008-2012, Printio (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: "0.8.45" };
var fabric = fabric || { version: "0.8.46" };
if (typeof exports != 'undefined') {
exports.fabric = fabric;
@ -3365,15 +3365,20 @@ fabric.util.string = {
clone = fabric.util.object.clone;
var attributesMap = {
'cx': 'left',
'x': 'left',
'cy': 'top',
'y': 'top',
'r': 'radius',
'fill-opacity': 'opacity',
'fill-rule': 'fillRule',
'stroke-width': 'strokeWidth',
'transform': 'transformMatrix'
'cx': 'left',
'x': 'left',
'cy': 'top',
'y': 'top',
'r': 'radius',
'fill-opacity': 'opacity',
'fill-rule': 'fillRule',
'stroke-width': 'strokeWidth',
'transform': 'transformMatrix',
'text-decoration': 'textDecoration',
'font-size': 'fontSize',
'font-weight': 'fontWeight',
'font-style': 'fontStyle',
'font-family': 'fontFamily'
};
function normalizeAttr(attr) {
@ -3788,7 +3793,7 @@ fabric.util.string = {
*/
fabric.parseSVGDocument = (function() {
var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image)$/;
var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/;
// http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
// \d doesn't quite cut it (as we need to match an actual float number)
@ -12636,7 +12641,7 @@ fabric.Image.filters.Tint.fromObject = function(object) {
initialize: function(text, options) {
this._initStateProperties();
this.text = text;
this.setOptions(options);
this.setOptions(options || { });
this.theta = this.angle * Math.PI / 180;
this._initDimensions();
this.setCoords();
@ -13265,6 +13270,14 @@ fabric.Image.filters.Tint.fromObject = function(object) {
}
});
/**
* List of attribute names to account for when parsing SVG element (used by `fabric.Text.fromElement`)
* @static
*/
fabric.Text.ATTRIBUTE_NAMES =
('x y fill fill-opacity opacity stroke stroke-width transform ' +
'font-family font-style font-weight font-size text-decoration').split(' ');
/**
* Returns fabric.Text instance from an object representation
* @static
@ -13280,10 +13293,20 @@ fabric.Image.filters.Tint.fromObject = function(object) {
* Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)
* @static
* @method fabric.Text.fromElement
* @param element
* @param options
* @return {fabric.Text} an instance
*/
fabric.Text.fromElement = function(element) {
// TODO (kangax): implement this
fabric.Text.fromElement = function(element, options) {
if (!element) {
return null;
}
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
var options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);
var text = new fabric.Text(element.textContent, options);
return text;
};
})(typeof exports != 'undefined' ? exports : this);

4
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

@ -1,12 +0,0 @@
body { font-family: Garamond, "Hoefler Text", "Times New Roman", Times, serif; margin: 0; }
#header { background: #333; margin: 0; padding: 0; color: #555; }
#header li { display: inline-block; }
#header li:after { content: "|"; }
#header li:last-child:after { content: ""; }
#header li a { display: inline-block; padding: 10px; color: pink; font-variant: small-caps; text-decoration: none; }
#header li a:hover, #header li a:focus { text-decoration: underline; }
#bd-wrapper { padding: 10px; }
pre { margin-top: 0; font-size: 12px; vertical-align: top; }

View file

@ -1,7 +1,7 @@
{
"name": "fabric",
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
"version": "0.8.45",
"version": "0.8.46",
"author": "Juriy Zaytsev <kangax@gmail.com>",
"keywords": ["canvas", "graphic", "graphics", "SVG", "node-canvas", "parser", "HTML5", "object model"],
"repository": "git://github.com/kangax/fabric.js",

View file

@ -13,15 +13,20 @@
clone = fabric.util.object.clone;
var attributesMap = {
'cx': 'left',
'x': 'left',
'cy': 'top',
'y': 'top',
'r': 'radius',
'fill-opacity': 'opacity',
'fill-rule': 'fillRule',
'stroke-width': 'strokeWidth',
'transform': 'transformMatrix'
'cx': 'left',
'x': 'left',
'cy': 'top',
'y': 'top',
'r': 'radius',
'fill-opacity': 'opacity',
'fill-rule': 'fillRule',
'stroke-width': 'strokeWidth',
'transform': 'transformMatrix',
'text-decoration': 'textDecoration',
'font-size': 'fontSize',
'font-weight': 'fontWeight',
'font-style': 'fontStyle',
'font-family': 'fontFamily'
};
function normalizeAttr(attr) {
@ -436,7 +441,7 @@
*/
fabric.parseSVGDocument = (function() {
var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image)$/;
var reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/;
// http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
// \d doesn't quite cut it (as we need to match an actual float number)

View file

@ -119,7 +119,7 @@
initialize: function(text, options) {
this._initStateProperties();
this.text = text;
this.setOptions(options);
this.setOptions(options || { });
this.theta = this.angle * Math.PI / 180;
this._initDimensions();
this.setCoords();
@ -748,6 +748,14 @@
}
});
/**
* List of attribute names to account for when parsing SVG element (used by `fabric.Text.fromElement`)
* @static
*/
fabric.Text.ATTRIBUTE_NAMES =
('x y fill fill-opacity opacity stroke stroke-width transform ' +
'font-family font-style font-weight font-size text-decoration').split(' ');
/**
* Returns fabric.Text instance from an object representation
* @static
@ -763,10 +771,20 @@
* Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)
* @static
* @method fabric.Text.fromElement
* @param element
* @param options
* @return {fabric.Text} an instance
*/
fabric.Text.fromElement = function(element) {
// TODO (kangax): implement this
fabric.Text.fromElement = function(element, options) {
if (!element) {
return null;
}
var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
var options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);
var text = new fabric.Text(element.textContent, options);
return text;
};
})(typeof exports != 'undefined' ? exports : this);

View file

@ -68,8 +68,11 @@
ok(rect instanceof fabric.Rect);
deepEqual(rect.toObject(), REFERENCE_RECT);
});
test('fabric.Rect.fromElement with custom attributes', function() {
var elRectWithAttrs = fabric.document.createElement('rect');
elRectWithAttrs.setAttribute('x', 10);
elRectWithAttrs.setAttribute('y', 20);
elRectWithAttrs.setAttribute('width', 222);
@ -98,7 +101,9 @@
ry: 12
});
deepEqual(rectWithAttrs.toObject(), expectedObject);
});
test('empty fromElement', function() {
ok(fabric.Rect.fromElement() === null);
});

View file

@ -1,21 +1,22 @@
(function() {
QUnit.module('fabric.Text');
function createTextObject() {
return new fabric.Text('foo', {
fontFamily: 'Modernist_One_400'
});
return new fabric.Text('foo');
}
var REFERENCE_TEXT_OBJECT = {
'type': 'text',
'left': 0,
'top': 0,
'width': 0,
'height': 0,
'width': 50,
'height': 52,
'fill': 'rgb(0,0,0)',
'overlayFill': null,
'stroke': null,
'strokeWidth': 1,
'strokeDashArray': null,
'scaleX': 1,
'scaleY': 1,
'angle': 0,
@ -23,22 +24,23 @@
'flipY': false,
'opacity': 1,
'selectable': true,
'hasControls': true,
'hasBorders': true,
'hasRotatingPoint': false,
'text': 'foo',
'fontSize': 40,
'fontWeight': 100,
'fontFamily': 'Modernist_One_400',
'lineHeight': 1.6,
'textDecoration': '',
'textShadow': null,
'textAlign': 'left',
'strokeStyle': '',
'fontFamily': 'Times New Roman',
'fontStyle': '',
'path': null,
'lineHeight': 1.3,
'textDecoration': '',
'textShadow': '',
'textAlign': 'left',
'path': null,
'strokeStyle': '',
'backgroundColor': ''
};
QUnit.module('fabric.Text');
test('constructor', function() {
ok(fabric.Text);
var text = createTextObject();
@ -54,7 +56,7 @@
test('toString', function() {
var text = createTextObject();
ok(typeof text.toString == 'function');
equal(text.toString(), '#<fabric.Text (0): { "text": "foo", "fontFamily": "Modernist_One_400" }>');
equal(text.toString(), '#<fabric.Text (0): { "text": "foo", "fontFamily": "Times New Roman" }>');
});
test('toObject', function() {
@ -118,4 +120,65 @@
deepEqual(text.toObject(), REFERENCE_TEXT_OBJECT);
});
});
test('fabric.Text.fromElement', function() {
ok(typeof fabric.Text.fromElement == 'function');
var elText = fabric.document.createElement('text');
elText.textContent = 'foo';
var text = fabric.Text.fromElement(elText);
ok(text instanceof fabric.Text);
// temp workaround for text objects not obtaining width under node
text.width = 50;
deepEqual(text.toObject(), REFERENCE_TEXT_OBJECT);
});
test('fabric.Text.fromElement with custom attributes', function() {
var elTextWithAttrs = fabric.document.createElement('text');
elTextWithAttrs.textContent = 'foo';
elTextWithAttrs.setAttribute('x', 10);
elTextWithAttrs.setAttribute('y', 20);
elTextWithAttrs.setAttribute('fill', 'rgb(255,255,255)');
elTextWithAttrs.setAttribute('fill-opacity', 0.45);
elTextWithAttrs.setAttribute('stroke', 'blue');
elTextWithAttrs.setAttribute('stroke-width', 3);
elTextWithAttrs.setAttribute('font-family', 'Monaco');
elTextWithAttrs.setAttribute('font-style', 'italic');
elTextWithAttrs.setAttribute('font-weight', 'bold');
elTextWithAttrs.setAttribute('font-size', '123');
elTextWithAttrs.setAttribute('text-decoration', 'underline');
var textWithAttrs = fabric.Text.fromElement(elTextWithAttrs);
// temp workaround for text objects not obtaining width under node
textWithAttrs.width = 50;
ok(textWithAttrs instanceof fabric.Text);
var expectedObject = fabric.util.object.extend(REFERENCE_TEXT_OBJECT, {
left: 10,
top: 20,
height: 159.9,
fill: 'rgb(255,255,255)',
opacity: 0.45,
stroke: 'blue',
strokeWidth: 3,
fontFamily: 'Monaco',
fontStyle: 'italic',
fontWeight: 'bold',
fontSize: 123,
textDecoration: 'underline'
});
deepEqual(textWithAttrs.toObject(), expectedObject);
});
test('empty fromElement', function() {
ok(fabric.Text.fromElement() === null);
});
})();