diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index c098d9c6671..4b9161df202 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -196,6 +196,14 @@ */ shadow: null, + /** + * fabric.Path that the text can follow. + * This feature is in BETA. + * @type fabric.Path + * @default + */ + path: null, + /** * @private */ @@ -1412,9 +1420,11 @@ 'textAlign', 'textBackgroundColor', 'charSpacing', + 'path' ].concat(propertiesToInclude); var obj = this.callSuper('toObject', additionalProperties); obj.styles = clone(this.styles, true); + obj.path = this.path && this.path.toObject(); return obj; }, @@ -1570,11 +1580,23 @@ * Returns fabric.Text instance from an object representation * @static * @memberOf fabric.Text - * @param {Object} object Object to create an instance from + * @param {Object} object plain js Object to create an instance from * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created */ fabric.Text.fromObject = function(object, callback) { - return fabric.Object._fromObject('Text', object, callback, 'text'); + var objectCopy = clone(object), path = object.path; + delete objectCopy.path; + return fabric.Object._fromObject('Text', objectCopy, function(textInstance) { + if (path) { + fabric.Object._fromObject('Path', path, function(pathInstance) { + textInstance.set('path', pathInstance); + callback(textInstance); + }, 'path'); + } + else { + callback(textInstance); + } + }, 'text'); }; fabric.Text.genericFonts = ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace']; diff --git a/test/unit/itext.js b/test/unit/itext.js index 022f300f8a1..563bb22d119 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -46,6 +46,7 @@ charSpacing: 0, styles: { }, strokeUniform: false, + path: null, }; diff --git a/test/unit/text.js b/test/unit/text.js index da5370fe324..aee6bf2baf3 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -52,6 +52,7 @@ skewY: 0, charSpacing: 0, styles: {}, + path: null, strokeUniform: false }; @@ -841,6 +842,28 @@ assert.equal(text.height, 100, 'text is big as the path height'); }); + QUnit.test('text with a path toObject', function(assert) { + var text = new fabric.Text('a', { + path: new fabric.Path('M0 0 h 100 v 100 h -100 z') + }); + var toObject = text.toObject(); + assert.ok(toObject.path, 'export has a path'); + }); + + QUnit.test('text with a path fromObject', function(assert) { + var done = assert.async(); + var text = new fabric.Text('a', { + path: new fabric.Path('M0 0 h 100 v 100 h -100 z') + }); + var toObject = text.toObject(); + fabric.Text.fromObject(toObject, function(text) { + assert.equal(text.path.type, 'path', 'the path is restored'); + assert.ok(text.path instanceof fabric.Path, 'the path is a path'); + assert.ok(toObject.path, 'the input has still a path property'); + done(); + }); + }); + QUnit.test('cacheProperties for text', function(assert) { var text = new fabric.Text('a'); assert.equal(text.cacheProperties.join('-'), 'fill-stroke-strokeWidth-strokeDashArray-width-height-paintFirst-strokeUniform-strokeLineCap-strokeDashOffset-strokeLineJoin-strokeMiterLimit-backgroundColor-clipPath-fontFamily-fontWeight-fontSize-text-underline-overline-linethrough-textAlign-fontStyle-lineHeight-textBackgroundColor-charSpacing-styles-path'); diff --git a/test/unit/textbox.js b/test/unit/textbox.js index 71e5dcc923d..793b30fd694 100644 --- a/test/unit/textbox.js +++ b/test/unit/textbox.js @@ -52,7 +52,8 @@ styles: { }, minWidth: 20, splitByGrapheme: false, - strokeUniform: false + strokeUniform: false, + path: null, }; QUnit.test('constructor', function(assert) {