Skip to content

Commit

Permalink
Add grapheme wrapping to textbox (#5479)
Browse files Browse the repository at this point in the history
* add grapheme wrapping

* added to Object
  • Loading branch information
asturur authored Jan 13, 2019
1 parent 402fe95 commit 9c35ed2
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 23 deletions.
37 changes: 26 additions & 11 deletions src/shapes/textbox.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@
*/
_dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),

/**
* Use this regular expression to split strings in breakable lines
* @private
*/
_wordJoiners: /[ \t\r\u200B\u200C]/,

/**
* Use this boolean property in order to split strings that have no white space concept.
* this is a cheap way to help with chinese/japaense
* @type Boolean
* @since 2.6.0
*/
splitByGrapheme: false,

/**
* Unlike superclass's version of this function, Textbox does not update
* its width.
Expand Down Expand Up @@ -300,19 +314,20 @@
* to.
*/
_wrapLine: function(_line, lineIndex, desiredWidth, reservedSpace) {
var lineWidth = 0,
graphemeLines = [],
line = [],
var lineWidth = 0,
splitByGrapheme = this.splitByGrapheme,
graphemeLines = [],
line = [],
// spaces in different languges?
words = _line.split(this._reSpaceAndTab),
word = '',
offset = 0,
infix = ' ',
wordWidth = 0,
infixWidth = 0,
words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),
word = '',
offset = 0,
infix = splitByGrapheme ? '' : ' ',
wordWidth = 0,
infixWidth = 0,
largestWordWidth = 0,
lineJustStarted = true,
additionalSpace = this._getWidthOfCharSpacing(),
additionalSpace = splitByGrapheme ? 0 : this._getWidthOfCharSpacing(),
reservedSpace = reservedSpace || 0;

desiredWidth -= reservedSpace;
Expand Down Expand Up @@ -406,7 +421,7 @@
* @return {Object} object representation of an instance
*/
toObject: function(propertiesToInclude) {
return this.callSuper('toObject', ['minWidth'].concat(propertiesToInclude));
return this.callSuper('toObject', ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude));
}
});

Expand Down
49 changes: 37 additions & 12 deletions test/unit/textbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@
opacity: 1,
shadow: null,
visible: true,
clipTo: null,
text: 'x',
fontSize: 40,
fontWeight: 'normal',
fontFamily: 'Times New Roman',
fontStyle: 'normal',
lineHeight: 1.16,
underline: false,
overline: false,
linethrough: false,
textAlign: 'left',
clipTo: null,
text: 'x',
fontSize: 40,
fontWeight: 'normal',
fontFamily: 'Times New Roman',
fontStyle: 'normal',
lineHeight: 1.16,
underline: false,
overline: false,
linethrough: false,
textAlign: 'left',
backgroundColor: '',
textBackgroundColor: '',
fillRule: 'nonzero',
Expand All @@ -52,7 +52,8 @@
transformMatrix: null,
charSpacing: 0,
styles: { },
minWidth: 20
minWidth: 20,
splitByGrapheme: false,
};

QUnit.test('constructor', function(assert) {
Expand Down Expand Up @@ -129,6 +130,30 @@
textbox.initDimensions();
assert.equal(textbox.textLines[0], 'xa', 'first line match expectations spacing 800');
});
QUnit.test('wrapping with different things', function(assert) {
var textbox = new fabric.Textbox('xa\u200Bxb\u200Bxc\u200Cxd\u200Cxe ya yb id', {
width: 16,
});
assert.equal(textbox.textLines[0], 'xa', '0 line match expectations');
assert.equal(textbox.textLines[1], 'xb', '1 line match expectations');
assert.equal(textbox.textLines[2], 'xc', '2 line match expectations');
assert.equal(textbox.textLines[3], 'xd', '3 line match expectations');
assert.equal(textbox.textLines[4], 'xe', '4 line match expectations');
assert.equal(textbox.textLines[5], 'ya', '5 line match expectations');
assert.equal(textbox.textLines[6], 'yb', '6 line match expectations');
});
QUnit.test('wrapping with splitByGrapheme', function(assert) {
var textbox = new fabric.Textbox('xaxbxcxdxeyaybid', {
width: 1,
splitByGrapheme: true,
});
assert.equal(textbox.textLines[0], 'x', '0 line match expectations splitByGrapheme');
assert.equal(textbox.textLines[1], 'a', '1 line match expectations splitByGrapheme');
assert.equal(textbox.textLines[2], 'x', '2 line match expectations splitByGrapheme');
assert.equal(textbox.textLines[3], 'b', '3 line match expectations splitByGrapheme');
assert.equal(textbox.textLines[4], 'x', '4 line match expectations splitByGrapheme');
assert.equal(textbox.textLines[5], 'c', '5 line match expectations splitByGrapheme');
});
QUnit.test('wrapping with custom space', function(assert) {
var textbox = new fabric.Textbox('xa xb xc xd xe ya yb id', {
width: 2000,
Expand Down

0 comments on commit 9c35ed2

Please sign in to comment.