Skip to content

Commit

Permalink
Proposal for different lineJustify. (fabricjs#4437)
Browse files Browse the repository at this point in the history
* not even tested

* Small fixes (fabricjs#4441)

* fixed selection

* fixed svg export
  • Loading branch information
asturur authored Nov 12, 2017
1 parent e1c8d93 commit 57fe655
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 24 deletions.
16 changes: 10 additions & 6 deletions src/mixins/itext.svg_export.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
*/
_wrapSVGTextAndBg: function(markup, textAndBg) {
var noShadow = true, filter = this.getSvgFilter(),
style = filter === '' ? '' : ' style="' + filter + '"';

style = filter === '' ? '' : ' style="' + filter + '"',
textDecoration = this.getSvgTextDecoration(this);
markup.push(
'\t<g ', this.getSvgId(), 'transform="', this.getSvgTransform(), this.getSvgTransformMatrix(), '"',
style, '>\n',
Expand All @@ -46,7 +46,7 @@
(this.fontSize ? 'font-size="' + this.fontSize + '" ' : ''),
(this.fontStyle ? 'font-style="' + this.fontStyle + '" ' : ''),
(this.fontWeight ? 'font-weight="' + this.fontWeight + '" ' : ''),
(this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ' : ''),
(textDecoration ? 'text-decoration="' + textDecoration + '" ' : ''),
'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >\n',
textAndBg.textSpans.join(''),
'\t\t</text>\n',
Expand Down Expand Up @@ -102,6 +102,7 @@
_setSVGTextLineText: function(textSpans, lineIndex, textLeftOffset, textTopOffset) {
// set proper line offset
var lineHeight = this.getHeightOfLine(lineIndex),
isJustify = this.textAlign.indexOf('justify') !== -1,
actualStyle,
nextStyle,
charsToRender = '',
Expand All @@ -117,9 +118,12 @@
charBox = this.__charBounds[lineIndex][i];
if (boxWidth === 0) {
textLeftOffset += charBox.kernedWidth - charBox.width;
boxWidth += charBox.width;
}
else {
boxWidth += charBox.kernedWidth;
}
boxWidth += charBox.kernedWidth;
if (this.textAlign === 'justify' && !timeToRender) {
if (isJustify && !timeToRender) {
if (this._reSpaceAndTab.test(line[i])) {
timeToRender = true;
}
Expand All @@ -128,7 +132,7 @@
// if we have charSpacing, we render char by char
actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);
nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);
timeToRender = this._hasStyleChanged(actualStyle, nextStyle);
timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle);
}
if (timeToRender) {
style = this._getStyleDeclaration(lineIndex, i) || { };
Expand Down
19 changes: 11 additions & 8 deletions src/mixins/object.svg_export.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,18 @@
* @return {String}
*/
getSvgSpanStyles: function(style, useWhiteSpace) {
var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + '; ' : '',
fontFamily = style.fontFamily ? 'font-family: ' + style.fontFamily.replace(/"/g, '\'') + '; ' : '',
fontSize = style.fontSize ? 'font-size: ' + style.fontSize + '; ' : '',
fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + '; ' : '',
fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + '; ' : '',
var term = '; ',
strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',
fontFamily = style.fontFamily ? 'font-family: ' + style.fontFamily.replace(/"/g, '\'') + term : '',
fontSize = style.fontSize ? 'font-size: ' + style.fontSize + term : '',
fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + term : '',
fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',
fill = style.fill ? getSvgColorString('fill', style.fill) : '',
stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',
textDecoration = this.getSvgTextDecoration(style);

if (textDecoration) {
textDecoration = 'text-decoration: ' + textDecoration + term;
}
return [
stroke,
strokeWidth,
Expand All @@ -89,8 +92,8 @@

getSvgTextDecoration: function(style) {
if ('overline' in style || 'underline' in style || 'linethrough' in style) {
return 'text-decoration: ' + (style.overline ? 'overline ' : '') +
(style.underline ? 'underline ' : '') + (style.linethrough ? 'line-through ' : '') + ';';
return (style.overline ? 'overline ' : '') +
(style.underline ? 'underline ' : '') + (style.linethrough ? 'line-through ' : '');
}
return '';
},
Expand Down
3 changes: 2 additions & 1 deletion src/shapes/itext.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@

var selectionStart = this.inCompositionMode ? this.hiddenTextarea.selectionStart : this.selectionStart,
selectionEnd = this.inCompositionMode ? this.hiddenTextarea.selectionEnd : this.selectionEnd,
isJustify = this.textAlign.indexOf('justify') !== -1,
start = this.get2DCursorLocation(selectionStart),
end = this.get2DCursorLocation(selectionEnd),
startLine = start.lineIndex,
Expand All @@ -421,7 +422,7 @@
boxStart = this.__charBounds[startLine][startChar].left;
}
if (i >= startLine && i < endLine) {
boxEnd = this.getLineWidth(i) || 5; // WTF is this 5?
boxEnd = isJustify && !this.isEndOfWrapping(i) ? this.width : this.getLineWidth(i) || 5; // WTF is this 5?
}
else if (i === endLine) {
if (endChar === 0) {
Expand Down
45 changes: 38 additions & 7 deletions src/shapes/text.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@
linethrough: false,

/**
* Text alignment. Possible values: "left", "center", "right" or "justify".
* Text alignment. Possible values: "left", "center", "right", "justify",
* "justify-left", "justify-center" or "justify-right".
* @type String
* @default
*/
Expand Down Expand Up @@ -334,8 +335,8 @@
this._splitText();
this._clearCache();
this.width = this.calcTextWidth() || this.cursorWidth || MIN_TEXT_WIDTH;
if (this.textAlign === 'justify') {
// once text is misured we need to make space fatter to make justified text.
if (this.textAlign.indexOf('justify') !== -1) {
// once text is measured we need to make space fatter to make justified text.
this.enlargeSpaces();
}
this.height = this.calcTextHeight();
Expand All @@ -348,6 +349,9 @@
enlargeSpaces: function() {
var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;
for (var i = 0, len = this._textLines.length; i < len; i++) {
if (this.textAlign !== 'justify' && (i === len - 1 || this.isEndOfWrapping(i))) {
continue;
}
accumulatedSpace = 0;
line = this._textLines[i];
currentLineWidth = this.getLineWidth(i);
Expand All @@ -370,6 +374,15 @@
}
},

/**
* Detect if the text line is ended with an hard break
* text and itext do not have wrapping, return false
* @return {Boolean}
*/
isEndOfWrapping: function(lineIndex) {
return lineIndex === this._textLines.length - 1;
},

/**
* Returns string representation of an instance
* @return {String} String representation of text object
Expand Down Expand Up @@ -840,6 +853,7 @@
_renderChars: function(method, ctx, line, left, top, lineIndex) {
// set proper line offset
var lineHeight = this.getHeightOfLine(lineIndex),
isJustify = this.textAlign.indexOf('justify') !== -1,
actualStyle,
nextStyle,
charsToRender = '',
Expand All @@ -860,7 +874,7 @@
else {
boxWidth += charBox.kernedWidth;
}
if (this.textAlign === 'justify' && !timeToRender) {
if (isJustify && !timeToRender) {
if (this._reSpaceAndTab.test(line[i])) {
timeToRender = true;
}
Expand Down Expand Up @@ -920,14 +934,25 @@
* @param {Object} thisStyle
*/
_hasStyleChanged: function(prevStyle, thisStyle) {
return (prevStyle.fill !== thisStyle.fill ||
return prevStyle.fill !== thisStyle.fill ||
prevStyle.stroke !== thisStyle.stroke ||
prevStyle.strokeWidth !== thisStyle.strokeWidth ||
prevStyle.fontSize !== thisStyle.fontSize ||
prevStyle.fontFamily !== thisStyle.fontFamily ||
prevStyle.fontWeight !== thisStyle.fontWeight ||
prevStyle.fontStyle !== thisStyle.fontStyle
);
prevStyle.fontStyle !== thisStyle.fontStyle;
},

/**
* @private
* @param {Object} prevStyle
* @param {Object} thisStyle
*/
_hasStyleChangedForSvg: function(prevStyle, thisStyle) {
return this._hasStyleChanged(prevStyle, thisStyle) ||
prevStyle.overline !== thisStyle.overline ||
prevStyle.underline !== thisStyle.underline ||
prevStyle.linethrough !== thisStyle.linethrough;
},

/**
Expand All @@ -943,6 +968,12 @@
if (this.textAlign === 'right') {
return this.width - lineWidth;
}
if (this.textAlign === 'justify-center' && this.isEndOfWrapping(lineIndex)) {
return (this.width - lineWidth) / 2;
}
if (this.textAlign === 'justify-right' && this.isEndOfWrapping(lineIndex)) {
return this.width - lineWidth;
}
return 0;
},

Expand Down
20 changes: 19 additions & 1 deletion src/shapes/textbox.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
if (this.dynamicMinWidth > this.width) {
this._set('width', this.dynamicMinWidth);
}
if (this.textAlign === 'justify') {
if (this.textAlign.indexOf('justify') !== -1) {
// once text is measured we need to make space fatter to make justified text.
this.enlargeSpaces();
}
Expand Down Expand Up @@ -324,6 +324,24 @@
return graphemeLines;
},

/**
* Detect if the text line is ended with an hard break
* text and itext do not have wrapping, return false
* @param {Number} lineIndex text to split
* @return {Boolean}
*/
isEndOfWrapping: function(lineIndex) {
if (!this._styleMap[lineIndex + 1]) {
// is last line, return true;
return true;
}
if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {
// this is last line before a line break, return true;
return true;
}
return false;
},

/**
* Gets lines of text to render in the Textbox. This function calculates
* text wrapping on the fly every time it is called.
Expand Down
1 change: 0 additions & 1 deletion test/unit/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@
var groupObject = group.toObject();

fabric.Group.fromObject(groupObject, function(newGroupFromObject) {
console.log(newGroupFromObject._objects[0]);
assert.ok(newGroupFromObject._objects[0].oCoords.tl, 'acoords 0 are restored');
assert.ok(newGroupFromObject._objects[1].oCoords.tl, 'acoords 1 are restored');

Expand Down

0 comments on commit 57fe655

Please sign in to comment.