mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-09 22:34:43 +00:00
Merge pull request #2674 from asturur/justify-text-to-svg
Justify text to svg
This commit is contained in:
commit
0255ce9892
3 changed files with 62 additions and 13 deletions
|
|
@ -1008,7 +1008,7 @@
|
|||
return this.__widthOfSpace[lineIndex];
|
||||
}
|
||||
var line = this._textLines[lineIndex],
|
||||
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex),
|
||||
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0),
|
||||
widthDiff = this.width - wordsWidth,
|
||||
numSpaces = line.length - line.replace(this._reSpacesAndTabs, '').length,
|
||||
width = widthDiff / numSpaces;
|
||||
|
|
@ -1022,14 +1022,14 @@
|
|||
* @param {Number} line
|
||||
* @param {Number} lineIndex
|
||||
*/
|
||||
_getWidthOfWords: function (ctx, line, lineIndex) {
|
||||
_getWidthOfWords: function (ctx, line, lineIndex, charOffset) {
|
||||
var width = 0;
|
||||
|
||||
for (var charIndex = 0; charIndex < line.length; charIndex++) {
|
||||
var _char = line[charIndex];
|
||||
|
||||
if (!_char.match(/\s/)) {
|
||||
width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex);
|
||||
width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex + charOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -479,11 +479,12 @@
|
|||
|
||||
// stretch the line
|
||||
var words = line.split(/\s+/),
|
||||
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex),
|
||||
charOffset = 0,
|
||||
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0),
|
||||
widthDiff = this.width - wordsWidth,
|
||||
numSpaces = words.length - 1,
|
||||
spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,
|
||||
leftOffset = 0, charOffset = 0, word;
|
||||
leftOffset = 0, word;
|
||||
|
||||
for (var i = 0, len = words.length; i < len; i++) {
|
||||
while (line[charOffset] === ' ' && charOffset < line.length) {
|
||||
|
|
@ -491,7 +492,7 @@
|
|||
}
|
||||
word = words[i];
|
||||
this._renderChars(method, ctx, word, left + leftOffset, top, lineIndex, charOffset);
|
||||
leftOffset += ctx.measureText(word).width + spaceWidth;
|
||||
leftOffset += this._getWidthOfWords(ctx, word, lineIndex, charOffset) + spaceWidth;
|
||||
charOffset += word.length;
|
||||
}
|
||||
},
|
||||
|
|
@ -640,7 +641,7 @@
|
|||
ctx.fillStyle = this.textBackgroundColor;
|
||||
for (var i = 0, len = this._textLines.length; i < len; i++) {
|
||||
if (this._textLines[i] !== '') {
|
||||
lineWidth = this._getLineWidth(ctx, i);
|
||||
lineWidth = this.textAlign === 'justify' ? this.width : this._getLineWidth(ctx, i);
|
||||
lineLeftOffset = this._getLineLeftOffset(lineWidth);
|
||||
ctx.fillRect(
|
||||
this._getLeftOffset() + lineLeftOffset,
|
||||
|
|
@ -709,7 +710,7 @@
|
|||
width = 0;
|
||||
}
|
||||
else if (this.textAlign === 'justify' && this._cacheLinesWidth) {
|
||||
wordCount = line.split(' ');
|
||||
wordCount = line.split(/\s+/);
|
||||
//consider not justify last line, not for now.
|
||||
if (wordCount.length > 1) {
|
||||
width = this.width;
|
||||
|
|
@ -889,9 +890,9 @@
|
|||
(this.fontStyle ? 'font-style="' + this.fontStyle + '" ': ''),
|
||||
(this.fontWeight ? 'font-weight="' + this.fontWeight + '" ': ''),
|
||||
(this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ': ''),
|
||||
'style="', this.getSvgStyles(), '" >',
|
||||
'style="', this.getSvgStyles(), '" >\n',
|
||||
textAndBg.textSpans.join(''),
|
||||
'</text>\n',
|
||||
'\t\t</text>\n',
|
||||
'\t</g>\n'
|
||||
);
|
||||
},
|
||||
|
|
@ -927,8 +928,13 @@
|
|||
_setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) {
|
||||
var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction)
|
||||
- textTopOffset + height - this.height / 2;
|
||||
if (this.textAlign === 'justify') {
|
||||
// i call from here to do not intefere with IText
|
||||
this._setSVGTextLineJustifed(i, textSpans, yPos, textLeftOffset);
|
||||
return;
|
||||
}
|
||||
textSpans.push(
|
||||
'<tspan x="',
|
||||
'\t\t\t<tspan x="',
|
||||
toFixed(textLeftOffset + this._getLineLeftOffset(this._getLineWidth(this.ctx, i)), NUM_FRACTION_DIGITS), '" ',
|
||||
'y="',
|
||||
toFixed(yPos, NUM_FRACTION_DIGITS),
|
||||
|
|
@ -937,10 +943,40 @@
|
|||
// on containing <text> one doesn't work in Illustrator
|
||||
this._getFillAttributes(this.fill), '>',
|
||||
fabric.util.string.escapeXml(this._textLines[i]),
|
||||
'</tspan>'
|
||||
'</tspan>\n'
|
||||
);
|
||||
},
|
||||
|
||||
_setSVGTextLineJustifed: function(i, textSpans, yPos, textLeftOffset) {
|
||||
var ctx = fabric.util.createCanvasElement().getContext('2d');
|
||||
this._setTextStyles(ctx);
|
||||
var line = this._textLines[i],
|
||||
words = line.split(/\s+/),
|
||||
wordsWidth = this._getWidthOfWords(ctx, line),
|
||||
widthDiff = this.width - wordsWidth,
|
||||
numSpaces = words.length - 1,
|
||||
spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,
|
||||
word, attributes = this._getFillAttributes(this.fill);
|
||||
textLeftOffset += this._getLineLeftOffset(this._getLineWidth(ctx, i))
|
||||
for (var i = 0, len = words.length; i < len; i++) {
|
||||
word = words[i];
|
||||
textSpans.push(
|
||||
'\t\t\t<tspan x="',
|
||||
toFixed(textLeftOffset, NUM_FRACTION_DIGITS), '" ',
|
||||
'y="',
|
||||
toFixed(yPos, NUM_FRACTION_DIGITS),
|
||||
'" ',
|
||||
// doing this on <tspan> elements since setting opacity
|
||||
// on containing <text> one doesn't work in Illustrator
|
||||
attributes, '>',
|
||||
fabric.util.string.escapeXml(word),
|
||||
'</tspan>\n'
|
||||
);
|
||||
textLeftOffset += this._getWidthOfWords(ctx, word) + spaceWidth;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) {
|
||||
textBgRects.push(
|
||||
'\t\t<rect ',
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@
|
|||
'transformMatrix': null
|
||||
};
|
||||
|
||||
var TEXT_SVG = '\t<g transform="translate(10.5 26.72)">\n\t\t<text font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" ><tspan x="-10" y="8.98" fill="rgb(0,0,0)">x</tspan></text>\n\t</g>\n';
|
||||
var TEXT_SVG = '\t<g transform="translate(10.5 26.72)">\n\t\t<text font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" >\n\t\t\t<tspan x="-10" y="8.98" fill="rgb(0,0,0)">x</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
var TEXT_SVG_JUSTIFIED = '\t<g transform="translate(50.5 26.72)">\n\t\t<text font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" >\n\t\t\t<tspan x="-50" y="8.98" fill="rgb(0,0,0)">x</tspan>\n\t\t\t<tspan x="30" y="8.98" fill="rgb(0,0,0)">y</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
|
||||
test('constructor', function() {
|
||||
ok(fabric.Text);
|
||||
|
|
@ -261,5 +262,17 @@
|
|||
|
||||
equal(removeTranslate(text.toSVG()), removeTranslate(TEXT_SVG.replace('font-family="Times New Roman"', 'font-family="\'Arial Black\', Arial"')));
|
||||
});
|
||||
test('toSVG justified', function() {
|
||||
var text = new fabric.Text('x y');
|
||||
|
||||
function removeTranslate(str) {
|
||||
return str.replace(/translate\(.*?\)/, '');
|
||||
}
|
||||
|
||||
// temp workaround for text objects not obtaining width under node
|
||||
text.width = 100;
|
||||
text.textAlign = 'justify'
|
||||
equal(removeTranslate(text.toSVG()), removeTranslate(TEXT_SVG_JUSTIFIED));
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in a new issue