mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-03-17 14:30:24 +00:00
755 lines
29 KiB
JavaScript
755 lines
29 KiB
JavaScript
(function() {
|
|
|
|
QUnit.module('fabric.Text');
|
|
|
|
function createTextObject(text) {
|
|
return new fabric.Text(text || 'x');
|
|
}
|
|
|
|
var CHAR_WIDTH = 20;
|
|
|
|
var REFERENCE_TEXT_OBJECT = {
|
|
'version': fabric.version,
|
|
'type': 'text',
|
|
'originX': 'left',
|
|
'originY': 'top',
|
|
'left': 0,
|
|
'top': 0,
|
|
'width': CHAR_WIDTH,
|
|
'height': 45.2,
|
|
'fill': 'rgb(0,0,0)',
|
|
'stroke': null,
|
|
'strokeWidth': 1,
|
|
'strokeDashArray': null,
|
|
'strokeLineCap': 'butt',
|
|
'strokeDashOffset': 0,
|
|
'strokeLineJoin': 'miter',
|
|
'strokeMiterLimit': 4,
|
|
'scaleX': 1,
|
|
'scaleY': 1,
|
|
'angle': 0,
|
|
'flipX': false,
|
|
'flipY': false,
|
|
'opacity': 1,
|
|
'shadow': null,
|
|
'visible': true,
|
|
'clipTo': null,
|
|
'backgroundColor': '',
|
|
'text': 'x',
|
|
'fontSize': 40,
|
|
'fontWeight': 'normal',
|
|
'fontFamily': 'Times New Roman',
|
|
'fontStyle': 'normal',
|
|
'lineHeight': 1.16,
|
|
'underline': false,
|
|
'overline': false,
|
|
'linethrough': false,
|
|
'textAlign': 'left',
|
|
'textBackgroundColor': '',
|
|
'fillRule': 'nonzero',
|
|
'paintFirst': 'fill',
|
|
'globalCompositeOperation': 'source-over',
|
|
'skewX': 0,
|
|
'skewY': 0,
|
|
'transformMatrix': null,
|
|
'charSpacing': 0,
|
|
'styles': {}
|
|
};
|
|
|
|
QUnit.test('constructor', function(assert) {
|
|
assert.ok(fabric.Text);
|
|
var text = createTextObject();
|
|
|
|
assert.ok(text);
|
|
assert.ok(text instanceof fabric.Text);
|
|
assert.ok(text instanceof fabric.Object);
|
|
|
|
assert.equal(text.get('type'), 'text');
|
|
assert.equal(text.get('text'), 'x');
|
|
});
|
|
|
|
QUnit.test('toString', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text.toString === 'function');
|
|
assert.equal(text.toString(), '#<fabric.Text (1): { "text": "x", "fontFamily": "Times New Roman" }>');
|
|
});
|
|
|
|
QUnit.test('_getFontDeclaration', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text._getFontDeclaration === 'function', 'has a private method _getFontDeclaration');
|
|
var fontDecl = text._getFontDeclaration();
|
|
assert.ok(typeof fontDecl === 'string', 'it returns a string');
|
|
assert.equal(fontDecl, 'normal normal 40px "Times New Roman"');
|
|
text.fontFamily = '"Times New Roman"';
|
|
fontDecl = text._getFontDeclaration();
|
|
assert.equal(fontDecl, 'normal normal 40px "Times New Roman"');
|
|
text.fontFamily = '\'Times New Roman\'';
|
|
fontDecl = text._getFontDeclaration();
|
|
assert.equal(fontDecl, 'normal normal 40px \'Times New Roman\'');
|
|
});
|
|
|
|
fabric.Text.genericFonts.forEach(function(fontName) {
|
|
QUnit.test('_getFontDeclaration with genericFonts', function(assert) {
|
|
var text = createTextObject();
|
|
text.fontFamily = fontName;
|
|
var fontDecl = text._getFontDeclaration();
|
|
assert.equal(fontDecl, 'normal normal 40px ' + fontName, 'it does not quote ' + fontName);
|
|
text.fontFamily = fontName.toUpperCase();
|
|
var fontDecl = text._getFontDeclaration();
|
|
assert.equal(fontDecl, 'normal normal 40px ' + fontName.toUpperCase(), 'it uses a non case sensitive logic');
|
|
});
|
|
});
|
|
|
|
QUnit.test('toObject', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text.toObject === 'function');
|
|
assert.deepEqual(text.toObject(), REFERENCE_TEXT_OBJECT);
|
|
});
|
|
|
|
QUnit.test('complexity', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text.complexity === 'function');
|
|
assert.equal(text.complexity(), 1);
|
|
});
|
|
|
|
QUnit.test('set', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text.set === 'function');
|
|
assert.equal(text.set('text', 'bar'), text, 'should be chainable');
|
|
|
|
text.set({ left: 1234, top: 2345, angle: 55 });
|
|
|
|
assert.equal(text.get('left'), 1234);
|
|
assert.equal(text.get('top'), 2345);
|
|
assert.equal(text.get('angle'), 55);
|
|
});
|
|
|
|
QUnit.test('lineHeight with single line', function(assert) {
|
|
var text = createTextObject();
|
|
text.text = 'text with one line';
|
|
text.lineHeight = 2;
|
|
text.initDimensions();
|
|
var height = text.height;
|
|
text.lineHeight = 0.5;
|
|
text.initDimensions();
|
|
var heightNew = text.height;
|
|
assert.equal(height, heightNew, 'text height does not change with one single line');
|
|
});
|
|
|
|
QUnit.test('lineHeight with multi line', function(assert) {
|
|
var text = createTextObject();
|
|
text.text = 'text with\ntwo lines';
|
|
text.lineHeight = 0.1;
|
|
text.initDimensions();
|
|
var height = text.height,
|
|
minimumHeight = text.fontSize * text._fontSizeMult;
|
|
assert.equal(height > minimumHeight, true, 'text height is always bigger than minimum Height');
|
|
});
|
|
|
|
QUnit.test('set with "hash"', function(assert) {
|
|
var text = createTextObject();
|
|
|
|
text.set({ opacity: 0.123, fill: 'red', fontFamily: 'blah' });
|
|
|
|
assert.equal(text.opacity, 0.123);
|
|
assert.equal(text.fill, 'red');
|
|
assert.equal(text.fontFamily, 'blah');
|
|
});
|
|
|
|
QUnit.test('get bounding rect after init', function(assert) {
|
|
var string = 'Some long text, the quick brown fox jumps over the lazy dog etc... blah blah blah';
|
|
var text = new fabric.Text(string, {
|
|
left: 30,
|
|
top: 30,
|
|
fill: '#ffffff',
|
|
fontSize: 24,
|
|
fontWeight: 'normal',
|
|
fontFamily: 'Arial',
|
|
originY: 'bottom'
|
|
});
|
|
var br = text.getBoundingRect();
|
|
text.setCoords();
|
|
var br2 = text.getBoundingRect();
|
|
assert.deepEqual(br, br2, 'text bounding box is the same before and after calling setCoords');
|
|
});
|
|
|
|
QUnit.test('setShadow', function(assert) {
|
|
var text = createTextObject();
|
|
assert.ok(typeof text.setShadow === 'function');
|
|
assert.equal(text.setShadow('10px 8px 2px red'), text, 'should be chainable');
|
|
|
|
assert.ok(text.shadow instanceof fabric.Shadow, 'should inherit from fabric.Shadow');
|
|
assert.equal(text.shadow.color, 'red');
|
|
assert.equal(text.shadow.offsetX, 10);
|
|
assert.equal(text.shadow.offsetY, 8);
|
|
assert.equal(text.shadow.blur, 2);
|
|
});
|
|
|
|
QUnit.test('fabric.Text.fromObject', function(assert) {
|
|
var done = assert.async();
|
|
assert.ok(typeof fabric.Text.fromObject === 'function');
|
|
fabric.Text.fromObject(REFERENCE_TEXT_OBJECT, function(text) {
|
|
assert.deepEqual(text.toObject(), REFERENCE_TEXT_OBJECT);
|
|
done();
|
|
});
|
|
});
|
|
|
|
QUnit.test('fabric.Text.fromElement', function(assert) {
|
|
assert.ok(typeof fabric.Text.fromElement === 'function');
|
|
|
|
var elText = fabric.document.createElement('text');
|
|
elText.textContent = 'x';
|
|
|
|
fabric.Text.fromElement(elText, function(text) {
|
|
assert.ok(text instanceof fabric.Text);
|
|
var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), {
|
|
left: 0,
|
|
top: -14.05,
|
|
width: 8,
|
|
height: 18.08,
|
|
fontSize: 16,
|
|
originX: 'left'
|
|
});
|
|
assert.deepEqual(text.toObject(), expectedObject, 'parsed object is what expected');
|
|
});
|
|
});
|
|
|
|
QUnit.test('fabric.Text.fromElement with custom attributes', function(assert) {
|
|
|
|
var elTextWithAttrs = fabric.document.createElement('text');
|
|
elTextWithAttrs.textContent = 'x';
|
|
|
|
elTextWithAttrs.setAttribute('x', 10);
|
|
elTextWithAttrs.setAttribute('y', 20);
|
|
elTextWithAttrs.setAttribute('fill', 'rgb(255,255,255)');
|
|
elTextWithAttrs.setAttribute('opacity', 0.45);
|
|
elTextWithAttrs.setAttribute('stroke', 'blue');
|
|
elTextWithAttrs.setAttribute('stroke-width', 3);
|
|
elTextWithAttrs.setAttribute('stroke-dasharray', '5, 2');
|
|
elTextWithAttrs.setAttribute('stroke-linecap', 'round');
|
|
elTextWithAttrs.setAttribute('stroke-linejoin', 'bevil');
|
|
elTextWithAttrs.setAttribute('stroke-miterlimit', 5);
|
|
elTextWithAttrs.setAttribute('font-family', 'Monaco');
|
|
elTextWithAttrs.setAttribute('font-style', 'italic');
|
|
elTextWithAttrs.setAttribute('font-weight', 'bold');
|
|
elTextWithAttrs.setAttribute('font-size', '123');
|
|
elTextWithAttrs.setAttribute('letter-spacing', '1em');
|
|
elTextWithAttrs.setAttribute('text-decoration', 'underline');
|
|
elTextWithAttrs.setAttribute('text-anchor', 'middle');
|
|
|
|
fabric.Text.fromElement(elTextWithAttrs, function(textWithAttrs) {
|
|
// temp workaround for text objects not obtaining width under node
|
|
textWithAttrs.width = CHAR_WIDTH;
|
|
|
|
assert.ok(textWithAttrs instanceof fabric.Text);
|
|
|
|
var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), {
|
|
/* left varies slightly due to node-canvas rendering */
|
|
left: fabric.util.toFixed(textWithAttrs.left + '', 2),
|
|
top: -88.03,
|
|
width: CHAR_WIDTH,
|
|
height: 138.99,
|
|
fill: 'rgb(255,255,255)',
|
|
opacity: 0.45,
|
|
stroke: 'blue',
|
|
strokeWidth: 3,
|
|
strokeDashArray: [5, 2],
|
|
strokeLineCap: 'round',
|
|
strokeLineJoin: 'bevil',
|
|
strokeMiterLimit: 5,
|
|
fontFamily: 'Monaco',
|
|
paintFirst: 'fill',
|
|
fontStyle: 'italic',
|
|
charSpacing: 1000,
|
|
fontWeight: 'bold',
|
|
fontSize: 123,
|
|
underline: true,
|
|
});
|
|
|
|
assert.deepEqual(textWithAttrs.toObject(), expectedObject);
|
|
});
|
|
});
|
|
|
|
QUnit.test('empty fromElement', function(assert) {
|
|
fabric.Text.fromElement(null, function(text) {
|
|
assert.equal(text, null);
|
|
});
|
|
});
|
|
|
|
QUnit.test('dimensions after text change', function(assert) {
|
|
var text = new fabric.Text('x');
|
|
assert.equal(text.width, CHAR_WIDTH);
|
|
|
|
text.set('text', 'xx');
|
|
assert.equal(text.width, CHAR_WIDTH * 2);
|
|
});
|
|
|
|
QUnit.test('dimensions without text', function(assert) {
|
|
var text = new fabric.Text('');
|
|
assert.equal(text.width, 2);
|
|
});
|
|
|
|
QUnit.test('setting fontFamily', function(assert) {
|
|
var text = new fabric.Text('x');
|
|
text.path = 'foobar.js';
|
|
|
|
text.set('fontFamily', 'foobar');
|
|
assert.equal(text.get('fontFamily'), 'foobar');
|
|
|
|
text.set('fontFamily', '"Arial Black", Arial');
|
|
assert.equal(text.get('fontFamily'), '"Arial Black", Arial');
|
|
});
|
|
|
|
QUnit.test('text styleHas', function(assert) {
|
|
var text = new fabric.Text('xxxxxx\nx y');
|
|
text.styles = { };
|
|
assert.ok(typeof text.styleHas === 'function');
|
|
assert.equal(text.styleHas('stroke'), false, 'the text style has no stroke');
|
|
text.styles = { 1: { 0: { stroke: 'red' }}};
|
|
assert.equal(text.styleHas('stroke'), true, 'the text style has stroke');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle', function(assert) {
|
|
var text = new fabric.Text('xxxxxx\nx y');
|
|
text.styles = { 1: { 0: { stroke: 'red' }}};
|
|
text.stroke = 'red';
|
|
assert.ok(typeof text.cleanStyle === 'function');
|
|
text.cleanStyle('stroke');
|
|
assert.equal(text.styles[1], undefined, 'the style has been cleaned since stroke was equal to text property');
|
|
text.styles = { 1: { 0: { stroke: 'blue' }}};
|
|
text.stroke = 'red';
|
|
text.cleanStyle('stroke');
|
|
assert.equal(text.styles[1][0].stroke, 'blue', 'nothing to clean, style untouched');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle with different sub styles styles', function(assert) {
|
|
var text = new fabric.Text('xxxxxx\nx y');
|
|
text.styles = { 1: { 0: { fill: 'red' }, 1: { stroke: 'red' }, 2: { stroke: 'blue' }}};
|
|
text.stroke = 'red';
|
|
text.cleanStyle('stroke');
|
|
assert.equal(text.stroke, 'red', 'the stroke stays red');
|
|
assert.equal(text.styles[1][0].fill, 'red', 'the style has not been changed since it\'s a different property');
|
|
assert.equal(text.styles[1][0].stroke, undefined, 'the style has been cleaned since stroke was equal to text property');
|
|
assert.equal(text.styles[1][1], undefined, 'the style remains undefined');
|
|
assert.equal(text.styles[1][2].stroke, 'blue', 'the style remains unchanged');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle with undefined and set styles', function(assert) {
|
|
var text = new fabric.Text('xxxxxx\nx y');
|
|
text.styles = { 1: { 1: { stroke: 'red' }, 3: { stroke: 'red' }}};
|
|
text.stroke = 'red';
|
|
text.cleanStyle('stroke');
|
|
assert.equal(text.stroke, 'red', 'the stroke stays red');
|
|
assert.equal(text.styles[1], undefined, 'the style has been cleaned since stroke was equal to text property');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle with empty styles', function(assert) {
|
|
var text = new fabric.Text('xxxxxx\nx y');
|
|
text.styles = { 1: { 0: { }, 1: { }}, 2: { }, 3: { 4: { }}};
|
|
text.cleanStyle('any');
|
|
assert.equal(text.styles[1], undefined, 'the style has been cleaned since there were no usefull informations');
|
|
assert.equal(text.styles[2], undefined, 'the style has been cleaned since there were no usefull informations');
|
|
assert.equal(text.styles[3], undefined, 'the style has been cleaned since there were no usefull informations');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle with full style', function(assert) {
|
|
var text = new fabric.Text('xxx');
|
|
text.styles = { 0: { 0: { fill: 'blue' }, 1: { fill: 'blue' }, 2: { fill: 'blue' }}};
|
|
text.fill = 'black';
|
|
text.cleanStyle('fill');
|
|
assert.equal(text.fill, 'blue', 'the fill has been changed to blue');
|
|
assert.equal(text.styles[0], undefined, 'all the style has been removed');
|
|
});
|
|
|
|
QUnit.test('text cleanStyle with no relevant style', function(assert) {
|
|
var text = new fabric.Text('xxx');
|
|
text.styles = { 0: { 0: { other: 'value1' }, 1: { other: 'value2' }, 2: { other: 'value3' }}};
|
|
text.fill = 'black';
|
|
text.cleanStyle('fill');
|
|
assert.equal(text.fill, 'black', 'the fill remains black');
|
|
assert.equal(text.styles[0][0].other, 'value1', 'style remains the same');
|
|
assert.equal(text.styles[0][0].full, undefined, 'style remains undefined');
|
|
assert.equal(text.styles[0][1].other, 'value2', 'style remains the same');
|
|
assert.equal(text.styles[0][1].full, undefined, 'style remains undefined');
|
|
assert.equal(text.styles[0][2].other, 'value3', 'style remains the same');
|
|
assert.equal(text.styles[0][2].full, undefined, 'style remains undefined');
|
|
});
|
|
|
|
QUnit.test('text removeStyle with some style', function(assert) {
|
|
var text = new fabric.Text('xxx');
|
|
text.styles = { 0: { 0: { stroke: 'black', fill: 'blue' }, 1: { fill: 'blue' }, 2: { fill: 'blue' }}};
|
|
assert.ok(typeof text.removeStyle === 'function');
|
|
text.fill = 'red';
|
|
text.removeStyle('fill');
|
|
assert.equal(text.fill, 'red', 'the fill has not been changed');
|
|
assert.equal(text.styles[0][0].stroke, 'black', 'the non fill part of the style is still there');
|
|
assert.equal(text.styles[0][0].fill, undefined, 'the fill part of the style has been removed');
|
|
text.styles = { 0: { 0: { fill: 'blue' }, 1: { fill: 'blue' }, 2: { fill: 'blue' }}};
|
|
text.removeStyle('fill');
|
|
assert.equal(text.styles[0], undefined, 'the styles got empty and has been removed');
|
|
});
|
|
|
|
QUnit.test('getFontCache works with fontWeight numbers', function(assert) {
|
|
var text = new fabric.Text('xxx', { fontWeight: 400 });
|
|
text.initDimensions();
|
|
var cache = fabric.charWidthsCache[text.fontFamily.toLowerCase()];
|
|
var cacheProp = text.fontStyle + '_400';
|
|
assert.equal(cacheProp in cache, true, '400 is converted to string');
|
|
});
|
|
|
|
QUnit.test('getFontCache is case insensitive', function(assert) {
|
|
var text = new fabric.Text('xxx', { fontWeight: 'BOld', fontStyle: 'NormaL' });
|
|
text.initDimensions();
|
|
var text2 = new fabric.Text('xxx', { fontWeight: 'bOLd', fontStyle: 'nORMAl' });
|
|
text2.initDimensions();
|
|
var cache = text.getFontCache(text);
|
|
var cache2 = text2.getFontCache(text2);
|
|
assert.equal(cache, cache2, 'you get the same cache');
|
|
});
|
|
// moved
|
|
QUnit.test('getSelectionStyles with no arguments', function(assert) {
|
|
var iText = new fabric.Text('test foo bar-baz\nqux', {
|
|
styles: {
|
|
0: {
|
|
0: { textDecoration: 'underline' },
|
|
2: { textDecoration: 'overline' },
|
|
4: { textBackgroundColor: '#ffc' }
|
|
},
|
|
1: {
|
|
0: { fill: 'red' },
|
|
1: { fill: 'green' },
|
|
2: { fill: 'blue' }
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(typeof iText.getSelectionStyles, 'function');
|
|
|
|
assert.deepEqual(iText.getSelectionStyles(), []);
|
|
|
|
});
|
|
|
|
QUnit.test('getSelectionStyles with 2 args', function(assert) {
|
|
var iText = new fabric.Text('test foo bar-baz\nqux', {
|
|
styles: {
|
|
0: {
|
|
0: { textDecoration: 'underline' },
|
|
2: { textDecoration: 'overline' },
|
|
4: { textBackgroundColor: '#ffc' }
|
|
},
|
|
1: {
|
|
0: { fill: 'red' },
|
|
1: { fill: 'green' },
|
|
2: { fill: 'blue' }
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.deepEqual(iText.getSelectionStyles(0, 5), [
|
|
{ textDecoration: 'underline' },
|
|
{},
|
|
{ textDecoration: 'overline' },
|
|
{},
|
|
{ textBackgroundColor: '#ffc' },
|
|
]);
|
|
|
|
assert.deepEqual(iText.getSelectionStyles(2, 2), [
|
|
]);
|
|
});
|
|
|
|
QUnit.test('setSelectionStyles', function(assert) {
|
|
var iText = new fabric.Text('test foo bar-baz\nqux', {
|
|
styles: {
|
|
0: {
|
|
0: { fill: '#112233' },
|
|
2: { stroke: '#223344' }
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(typeof iText.setSelectionStyles, 'function');
|
|
|
|
iText.setSelectionStyles({
|
|
fill: 'red',
|
|
stroke: 'yellow'
|
|
});
|
|
|
|
assert.deepEqual(iText.styles[0][0], {
|
|
fill: '#112233'
|
|
});
|
|
|
|
iText.setSelectionStyles({
|
|
fill: 'red',
|
|
stroke: 'yellow'
|
|
}, 0, 1);
|
|
|
|
assert.deepEqual(iText.styles[0][0], {
|
|
fill: 'red',
|
|
stroke: 'yellow'
|
|
});
|
|
|
|
iText.setSelectionStyles({
|
|
fill: '#998877',
|
|
stroke: 'yellow'
|
|
}, 2, 3);
|
|
|
|
assert.deepEqual(iText.styles[0][2], {
|
|
fill: '#998877',
|
|
stroke: 'yellow'
|
|
});
|
|
});
|
|
|
|
QUnit.test('getStyleAtPosition', function(assert) {
|
|
var iText = new fabric.Text('test foo bar-baz\nqux', {
|
|
styles: {
|
|
0: {
|
|
0: { textDecoration: 'underline' },
|
|
2: { textDecoration: 'overline' },
|
|
4: { textBackgroundColor: '#ffc' }
|
|
},
|
|
1: {
|
|
0: { fill: 'red' },
|
|
1: { fill: 'green' },
|
|
2: { fill: 'blue' }
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(typeof iText.getStyleAtPosition, 'function');
|
|
|
|
assert.deepEqual(iText.getStyleAtPosition(2), { textDecoration: 'overline' });
|
|
|
|
assert.deepEqual(iText.getStyleAtPosition(1), { });
|
|
|
|
assert.deepEqual(iText.getStyleAtPosition(18), { fill: 'green' });
|
|
});
|
|
|
|
QUnit.test('_splitText', function(assert) {
|
|
var text = new fabric.Text('test foo bar-baz\nqux', {});
|
|
var test = text._splitText();
|
|
assert.equal(test.lines[0], 'test foo bar-baz', 'first line is correct');
|
|
assert.equal(test.lines[1], 'qux', 'second line is correct');
|
|
assert.deepEqual(test.graphemeLines[0], ['t','e','s','t',' ','f','o','o',' ','b','a','r','-','b','a','z'], 'first line is correct');
|
|
assert.deepEqual(test.graphemeLines[1], ['q','u','x'], 'second line is correct');
|
|
});
|
|
|
|
QUnit.test('getStyleAtPosition complete', function(assert) {
|
|
var iText = new fabric.Text('test foo bar-baz\nqux', {
|
|
styles: {
|
|
0: {
|
|
0: { underline: true },
|
|
2: { overline: true },
|
|
4: { textBackgroundColor: '#ffc' }
|
|
},
|
|
1: {
|
|
0: { fill: 'red' },
|
|
1: { fill: 'green' },
|
|
2: { fill: 'blue' }
|
|
}
|
|
}
|
|
});
|
|
|
|
var expectedStyle0 = {
|
|
stroke: null,
|
|
strokeWidth: 1,
|
|
fill: 'rgb(0,0,0)',
|
|
fontFamily: 'Times New Roman',
|
|
fontSize: 40,
|
|
fontWeight: 'normal',
|
|
fontStyle: 'normal',
|
|
underline: true,
|
|
overline: false,
|
|
linethrough: false,
|
|
textBackgroundColor: '',
|
|
deltaY: 0,
|
|
};
|
|
|
|
var expectedStyle2 = {
|
|
stroke: null,
|
|
strokeWidth: 1,
|
|
fill: 'rgb(0,0,0)',
|
|
fontFamily: 'Times New Roman',
|
|
fontSize: 40,
|
|
fontWeight: 'normal',
|
|
fontStyle: 'normal',
|
|
underline: false,
|
|
overline: true,
|
|
linethrough: false,
|
|
textBackgroundColor: '',
|
|
deltaY: 0,
|
|
};
|
|
|
|
assert.equal(typeof iText.getStyleAtPosition, 'function');
|
|
|
|
assert.deepEqual(iText.getStyleAtPosition(0, true), expectedStyle0, 'styles do match at 0');
|
|
|
|
assert.deepEqual(iText.getStyleAtPosition(2, true), expectedStyle2, 'styles do match at 2');
|
|
});
|
|
|
|
QUnit.test('toSVG with NUM_FRACTION_DIGITS', function(assert) {
|
|
var iText = new fabric.IText('test foo bar-baz', {
|
|
// makes weird numbers
|
|
styles: {
|
|
0: {
|
|
0: {
|
|
fill: 'red',
|
|
},
|
|
1: {
|
|
fill: 'blue',
|
|
},
|
|
2: {
|
|
fill: 'green',
|
|
},
|
|
3: {
|
|
fill: 'yellow',
|
|
},
|
|
4: {
|
|
fill: 'pink',
|
|
},
|
|
}
|
|
}
|
|
});
|
|
fabric.Object.NUM_FRACTION_DIGITS = 1;
|
|
var SVG_1 = iText.toSVG();
|
|
// var SVG_1_EXPECTED = '\t<g transform="translate(124.5 23.1)">\n\t\t<text xml:space="preserve" font-family="Times New Roman" font-size="40" font-style="normal" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; white-space: pre;" ><tspan x="-124" y="12.6" style="fill: rgb(255,0,0); ">t</tspan><tspan x="-112.9" y="12.6" style="fill: rgb(0,0,255); ">e</tspan><tspan x="-95.1" y="12.6" style="fill: rgb(0,128,0); ">s</tspan><tspan x="-79.6" y="12.6" style="fill: rgb(255,255,0); ">t</tspan><tspan x="-68.4" y="12.6" style="fill: rgb(255,192,203); white-space: pre; "> </tspan><tspan x="-58.4" y="12.6" >foo bar-baz</tspan></text>\n\t</g>\n';
|
|
//assert.equal(SVG_1, SVG_1_EXPECTED, 'numbers have max 1 decimal');
|
|
fabric.Object.NUM_FRACTION_DIGITS = 3;
|
|
var SVG_2 = iText.toSVG();
|
|
// var SVG_2_EXPECTED = '\t<g transform="translate(124.484 23.1)">\n\t\t<text xml:space="preserve" font-family="Times New Roman" font-size="40" font-style="normal" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; white-space: pre;" ><tspan x="-123.984" y="12.566" style="fill: rgb(255,0,0); ">t</tspan><tspan x="-112.871" y="12.566" style="fill: rgb(0,0,255); ">e</tspan><tspan x="-95.117" y="12.566" style="fill: rgb(0,128,0); ">s</tspan><tspan x="-79.551" y="12.566" style="fill: rgb(255,255,0); ">t</tspan><tspan x="-68.438" y="12.566" style="fill: rgb(255,192,203); white-space: pre; "> </tspan><tspan x="-58.438" y="12.566" >foo bar-baz</tspan></text>\n\t</g>\n';
|
|
//assert.equal(SVG_2, SVG_2_EXPECTED, 'numbers have max 3 decimal');
|
|
assert.ok(SVG_2.length > SVG_1.length, 'SVG 2 has more decimal');
|
|
// put back to 2 or break all tests
|
|
fabric.Object.NUM_FRACTION_DIGITS = 2;
|
|
});
|
|
|
|
QUnit.test('getSvgSpanStyles produces correct output', function(assert) {
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
fill: 'red',
|
|
strokeWidth: 30,
|
|
fontFamily: 'Verdana',
|
|
fontSize: 25,
|
|
};
|
|
var styleString = iText.getSvgSpanStyles(styleObject);
|
|
var expected = 'stroke-width: 30; font-family: \'Verdana\'; font-size: 25px; fill: rgb(255,0,0); ';
|
|
assert.equal(styleString, expected, 'style is as expected');
|
|
});
|
|
QUnit.test('getSvgSpanStyles produces correct output with useWhiteSpace', function(assert) {
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
fill: 'red',
|
|
strokeWidth: 30,
|
|
fontFamily: 'Verdana',
|
|
fontSize: 25,
|
|
};
|
|
var styleString = iText.getSvgSpanStyles(styleObject, true);
|
|
var expected = 'stroke-width: 30; font-family: \'Verdana\'; font-size: 25px; fill: rgb(255,0,0); white-space: pre; ';
|
|
assert.equal(styleString, expected, 'style is as expected');
|
|
});
|
|
QUnit.test('getSvgTextDecoration with overline true produces correct output', function(assert){
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
overline: true,
|
|
};
|
|
var styleString = iText.getSvgTextDecoration(styleObject);
|
|
var expected = 'overline ';
|
|
assert.equal(styleString, expected, 'style is as expected');
|
|
});
|
|
QUnit.test('getSvgTextDecoration with overline underline true produces correct output', function(assert){
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
overline: true,
|
|
underline: true,
|
|
};
|
|
var styleString = iText.getSvgTextDecoration(styleObject);
|
|
var expected = 'overline underline ';
|
|
assert.equal(styleString, expected, 'style is as expected with overline underline');
|
|
});
|
|
QUnit.test('getSvgTextDecoration with overline underline true produces correct output', function(assert){
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
overline: true,
|
|
underline: true,
|
|
linethrough: true,
|
|
};
|
|
var styleString = iText.getSvgTextDecoration(styleObject);
|
|
var expected = 'overline underline line-through ';
|
|
assert.equal(styleString, expected, 'style is as expected with overline underline');
|
|
});
|
|
|
|
QUnit.test('getSvgTextDecoration with overline underline true produces correct output', function(assert){
|
|
var iText = new fabric.IText('test foo bar-baz');
|
|
var styleObject = {
|
|
overline: true,
|
|
underline: true,
|
|
linethrough: true,
|
|
};
|
|
var styleString = iText.getSvgTextDecoration(styleObject);
|
|
var expected = 'overline underline line-through ';
|
|
assert.equal(styleString, expected, 'style is as expected with overline underline');
|
|
});
|
|
|
|
QUnit.test('text superscript', function(assert) {
|
|
var text = new fabric.Text('xxx', { styles: {
|
|
0: { 0: { stroke: 'black', fill: 'blue' }, 1: { fill: 'blue' }, 2: { fontSize: 4, deltaY: 20 }}
|
|
} });
|
|
assert.ok(typeof text.setSuperscript === 'function');
|
|
|
|
var size = text.fontSize;
|
|
var schema = text.superscript;
|
|
var styleFontSize = text.styles[0][2].fontSize;
|
|
var styleDeltaY = text.styles[0][2].deltaY;
|
|
text.setSuperscript(1, 2).setSuperscript(2, 3);
|
|
|
|
assert.equal(text.styles[0][0].fontSize, undefined, 'character 0: fontSize is not set');
|
|
assert.equal(text.styles[0][0].deltaY, undefined, 'character 0: deltaY is not set');
|
|
|
|
assert.equal(text.styles[0][1].fontSize, size * schema.size, 'character 1: fontSize has been set');
|
|
assert.equal(text.styles[0][1].deltaY, size * schema.baseline, 'character 1: deltaY has been set');
|
|
|
|
assert.equal(text.styles[0][2].fontSize, styleFontSize * schema.size, 'character 2: fontSize has been decreased');
|
|
assert.equal(text.styles[0][2].deltaY, styleDeltaY + styleFontSize * schema.baseline, 'character 2: deltaY has been decreased');
|
|
});
|
|
|
|
QUnit.test('text subscript', function(assert) {
|
|
var text = new fabric.Text('xxx', { styles: {
|
|
0: { 0: { stroke: 'black', fill: 'blue' }, 1: { fill: 'blue' }, 2: { fontSize: 4, deltaY: 20 }}
|
|
} });
|
|
assert.ok(typeof text.setSubscript === 'function');
|
|
|
|
var size = text.fontSize;
|
|
var schema = text.subscript;
|
|
var styleFontSize = text.styles[0][2].fontSize;
|
|
var styleDeltaY = text.styles[0][2].deltaY;
|
|
text.setSubscript(1,2).setSubscript(2,3);
|
|
|
|
assert.equal(text.styles[0][0].fontSize, undefined, 'character 0: fontSize is not set');
|
|
assert.equal(text.styles[0][0].deltaY, undefined, 'character 0: deltaY is not set');
|
|
|
|
assert.equal(text.styles[0][1].fontSize, size * schema.size, 'character 1: fontSize has been set');
|
|
assert.equal(text.styles[0][1].deltaY, size * schema.baseline, 'character 1: deltaY has been set');
|
|
|
|
assert.equal(text.styles[0][2].fontSize, styleFontSize * schema.size, 'character 2: fontSize has been decreased');
|
|
assert.equal(text.styles[0][2].deltaY, styleDeltaY + styleFontSize * schema.baseline, 'character 2: deltaY has been increased');
|
|
});
|
|
|
|
QUnit.test('getHeightOfLine measures height of aline', function(assert) {
|
|
var text = new fabric.Text('xxx\n');
|
|
var height1 = text.getHeightOfLine(0);
|
|
var height2 = text.getHeightOfLine(1);
|
|
assert.equal(Math.round(height1), 52, 'height of line with text is ok');
|
|
assert.equal(Math.round(height2), 52, 'height of empty line is ok');
|
|
assert.equal(height1, height2, 'should have same height');
|
|
});
|
|
|
|
QUnit.test('_measureChar handles 0 width chars', function(assert) {
|
|
fabric.charWidthsCache = {};
|
|
var zwc = '\u200b';
|
|
var text = new fabric.Text('');
|
|
var style = text.getCompleteStyleDeclaration(0, 0);
|
|
var box = text._measureChar('a', style, zwc, style);
|
|
var box2 = text._measureChar('a', style, zwc, style);
|
|
assert.equal(fabric.charWidthsCache[text.fontFamily.toLowerCase()].normal_normal[zwc], 0, 'zwc is a 0 width char');
|
|
assert.equal(box.kernedWidth, box2.kernedWidth, '2 measurements of the same string return the same number');
|
|
});
|
|
})();
|