Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Textbox): expose methods for overrides + fix resize filckering #7806

Merged
merged 16 commits into from
Mar 25, 2022
5 changes: 3 additions & 2 deletions src/controls.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,9 +690,10 @@
strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),
multiplier = isTransformCentered(transform) ? 2 : 1,
oldWidth = target.width,
newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;
newWidth = Math.ceil(Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding);
target.set('width', Math.max(newWidth, 0));
return oldWidth !== newWidth;
// check against actual target width in case `newWidth` was rejected
return oldWidth !== target.width;
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/mixins/itext_behavior.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,12 @@
*/
fromStringToGraphemeSelection: function(start, end, text) {
var smallerTextStart = text.slice(0, start),
graphemeStart = fabric.util.string.graphemeSplit(smallerTextStart).length;
graphemeStart = this.graphemeSplit(smallerTextStart).length;
if (start === end) {
return { selectionStart: graphemeStart, selectionEnd: graphemeStart };
}
var smallerTextEnd = text.slice(start, end),
graphemeEnd = fabric.util.string.graphemeSplit(smallerTextEnd).length;
graphemeEnd = this.graphemeSplit(smallerTextEnd).length;
return { selectionStart: graphemeStart, selectionEnd: graphemeStart + graphemeEnd };
},

Expand Down
2 changes: 1 addition & 1 deletion src/mixins/itext_key_behavior.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (end > start) {
this.removeStyleFromTo(start, end);
}
var graphemes = fabric.util.string.graphemeSplit(text);
var graphemes = this.graphemeSplit(text);
this.insertNewStyleBlock(graphemes, start, style);
this._text = [].concat(this._text.slice(0, start), graphemes, this._text.slice(end));
this.text = this._text.join('');
Expand Down
11 changes: 10 additions & 1 deletion src/shapes/text.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,15 @@
this.callSuper('render', ctx);
},

/**
*
* @param {string} value
* @returns {string[]} array of graphemes
*/
graphemeSplit: function (value) {
return fabric.util.string.graphemeSplit(value);
},
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns the text as an array of lines.
* @param {String} text text to split
Expand All @@ -1523,7 +1532,7 @@
newLine = ['\n'],
newText = [];
for (var i = 0; i < lines.length; i++) {
newLines[i] = fabric.util.string.graphemeSplit(lines[i]);
newLines[i] = this.graphemeSplit(lines[i]);
newText = newText.concat(newLines[i], newLine);
}
newText.pop();
Expand Down
26 changes: 21 additions & 5 deletions src/shapes/textbox.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@
var wrapped = [], i;
this.isWrapping = true;
for (i = 0; i < lines.length; i++) {
wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth));
wrapped.push.apply(wrapped, this._wrapLine(lines[i], i, desiredWidth));
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
}
this.isWrapping = false;
return wrapped;
Expand All @@ -298,6 +298,15 @@
return width;
},

/**
*
* @param {string} value
* @returns {string[]} array of words
*/
wordSplit: function (value) {
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
return value.split(this._wordJoiners);
},

/**
* Wraps a line of text using the width of the Textbox and a context.
* @param {Array} line The grapheme array that represent the line
Expand All @@ -313,7 +322,7 @@
graphemeLines = [],
line = [],
// spaces in different languages?
words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),
words = splitByGrapheme ? this.graphemeSplit(_line) : this.wordSplit(_line),
word = '',
offset = 0,
infix = splitByGrapheme ? '' : ' ',
Expand All @@ -328,14 +337,21 @@
words.push([]);
}
desiredWidth -= reservedSpace;
for (var i = 0; i < words.length; i++) {
var data = words.map(function (word) {
// if using splitByGrapheme words are already in graphemes.
word = splitByGrapheme ? words[i] : fabric.util.string.graphemeSplit(words[i]);
word = splitByGrapheme ? word : this.graphemeSplit(word);
var width = this._measureWord(word, lineIndex);
largestWordWidth = Math.max(width, largestWordWidth);
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
return { word: word, width: width };
}.bind(this));
var maxWidth = Math.max(desiredWidth, largestWordWidth, this.dynamicMinWidth);
for (var i = 0; i < words.length; i++) {
word = data[i].word;
wordWidth = this._measureWord(word, lineIndex, offset);
offset += word.length;

lineWidth += infixWidth + wordWidth - additionalSpace;
if (lineWidth > desiredWidth && !lineJustStarted) {
if (lineWidth > maxWidth && !lineJustStarted) {
graphemeLines.push(line);
line = [];
lineWidth = wordWidth;
Expand Down
17 changes: 14 additions & 3 deletions test/unit/controls_handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,22 @@
});
QUnit.test('changeWidth changes the width', function(assert) {
assert.equal(transform.target.width, 100);
fabric.controlsUtils.changeWidth(eventData, transform, 200, 300);
var changed = fabric.controlsUtils.changeWidth(eventData, transform, 200, 300);
assert.ok(changed, 'control changed target');
assert.equal(transform.target.width, 199);
assert.equal(transform.target.left, 0);
assert.equal(transform.target.top, 0);
});
QUnit.test('changeWidth does not change the width', function (assert) {
var target = new fabric.Rect({ width: 100, height: 100, canvas });
target._set = () => { };
assert.equal(target.width, 100);
var changed = fabric.controlsUtils.changeWidth(eventData, Object.assign({}, transform, { target }), 200, 300);
assert.ok(!changed, 'control change was rejected');
assert.equal(target.width, 100);
assert.equal(target.left, 0);
assert.equal(target.top, 0);
});
QUnit.test('changeWidth changes the width with centered transform', function(assert) {
transform.originX = 'center';
transform.originY = 'center';
Expand All @@ -51,13 +62,13 @@
transform.target.strokeUniform = true;
transform.target.scaleX = 3;
fabric.controlsUtils.changeWidth(eventData, transform, 200, 300);
assert.equal(Math.floor(transform.target.width), 61);
assert.equal(Math.ceil(transform.target.width), 62);
});
QUnit.test('changeWidth changes the width with big strokeWidth + scaling', function(assert) {
transform.target.strokeWidth = 15;
transform.target.scaleX = 3;
fabric.controlsUtils.changeWidth(eventData, transform, 200, 300);
assert.equal(Math.floor(transform.target.width), 51);
assert.equal(Math.ceil(transform.target.width), 52);
});
QUnit.test('changeWidth will fire events on canvas and target resizing', function(assert) {
var done = assert.async();
Expand Down