@@ -405,7 +405,7 @@ class Cache {
405
405
}
406
406
const cache = new Cache();
407
407
408
- var version = "6.6.7 ";
408
+ var version = "6.7.0 ";
409
409
410
410
// use this syntax so babel plugin see this import here
411
411
const VERSION = version;
@@ -4831,6 +4831,68 @@ function getSvgRegex(arr) {
4831
4831
return new RegExp('^(' + arr.join('|') + ')\\b', 'i');
4832
4832
}
4833
4833
4834
+ const TEXT_DECORATION_THICKNESS = 'textDecorationThickness';
4835
+ const fontProperties = ['fontSize', 'fontWeight', 'fontFamily', 'fontStyle'];
4836
+ const textDecorationProperties = ['underline', 'overline', 'linethrough'];
4837
+ const textLayoutProperties = [...fontProperties, 'lineHeight', 'text', 'charSpacing', 'textAlign', 'styles', 'path', 'pathStartOffset', 'pathSide', 'pathAlign'];
4838
+ const additionalProps = [...textLayoutProperties, ...textDecorationProperties, 'textBackgroundColor', 'direction', TEXT_DECORATION_THICKNESS];
4839
+ const styleProperties = [...fontProperties, ...textDecorationProperties, STROKE, 'strokeWidth', FILL, 'deltaY', 'textBackgroundColor', TEXT_DECORATION_THICKNESS];
4840
+
4841
+ // @TODO: Many things here are configuration related and shouldn't be on the class nor prototype
4842
+ // regexes, list of properties that are not suppose to change by instances, magic consts.
4843
+ // this will be a separated effort
4844
+ const textDefaultValues = {
4845
+ _reNewline: reNewline,
4846
+ _reSpacesAndTabs: /[ \t\r]/g,
4847
+ _reSpaceAndTab: /[ \t\r]/,
4848
+ _reWords: /\S+/g,
4849
+ fontSize: 40,
4850
+ fontWeight: 'normal',
4851
+ fontFamily: 'Times New Roman',
4852
+ underline: false,
4853
+ overline: false,
4854
+ linethrough: false,
4855
+ textAlign: LEFT,
4856
+ fontStyle: 'normal',
4857
+ lineHeight: 1.16,
4858
+ textBackgroundColor: '',
4859
+ stroke: null,
4860
+ shadow: null,
4861
+ path: undefined,
4862
+ pathStartOffset: 0,
4863
+ pathSide: LEFT,
4864
+ pathAlign: 'baseline',
4865
+ charSpacing: 0,
4866
+ deltaY: 0,
4867
+ direction: 'ltr',
4868
+ CACHE_FONT_SIZE: 400,
4869
+ MIN_TEXT_WIDTH: 2,
4870
+ // Text magic numbers
4871
+ superscript: {
4872
+ size: 0.6,
4873
+ // fontSize factor
4874
+ baseline: -0.35 // baseline-shift factor (upwards)
4875
+ },
4876
+ subscript: {
4877
+ size: 0.6,
4878
+ // fontSize factor
4879
+ baseline: 0.11 // baseline-shift factor (downwards)
4880
+ },
4881
+ _fontSizeFraction: 0.222,
4882
+ offsets: {
4883
+ underline: 0.1,
4884
+ linethrough: -0.28167,
4885
+ // added 1/30 to original number
4886
+ overline: -0.81333 // added 1/15 to original number
4887
+ },
4888
+ _fontSizeMult: 1.13,
4889
+ [TEXT_DECORATION_THICKNESS]: 66.667 // before implementation was 1/15
4890
+ };
4891
+ const JUSTIFY = 'justify';
4892
+ const JUSTIFY_LEFT = 'justify-left';
4893
+ const JUSTIFY_RIGHT = 'justify-right';
4894
+ const JUSTIFY_CENTER = 'justify-center';
4895
+
4834
4896
var _templateObject$1, _templateObject2$1, _templateObject3$1;
4835
4897
4836
4898
// matches, e.g.: +14.56e-12, etc.
@@ -4872,7 +4934,8 @@ const svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'r
4872
4934
'clip-path': 'clipPath',
4873
4935
'clip-rule': 'clipRule',
4874
4936
'vector-effect': 'strokeUniform',
4875
- 'image-rendering': 'imageSmoothing'
4937
+ 'image-rendering': 'imageSmoothing',
4938
+ 'text-decoration-thickness': TEXT_DECORATION_THICKNESS
4876
4939
},
4877
4940
fSize = 'font-size',
4878
4941
cPath = 'clip-path';
@@ -10362,7 +10425,7 @@ var lang_string = /*#__PURE__*/Object.freeze({
10362
10425
*/
10363
10426
const hasStyleChanged = function (prevStyle, thisStyle) {
10364
10427
let forTextSpans = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
10365
- 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.textBackgroundColor !== thisStyle.textBackgroundColor || prevStyle.deltaY !== thisStyle.deltaY || forTextSpans && (prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough);
10428
+ 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.textDecorationThickness !== thisStyle.textDecorationThickness || prevStyle. textBackgroundColor !== thisStyle.textBackgroundColor || prevStyle.deltaY !== thisStyle.deltaY || forTextSpans && (prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough);
10366
10429
};
10367
10430
10368
10431
/**
@@ -10650,7 +10713,7 @@ function normalizeValue(attr, value, parentAttributes, fontSize) {
10650
10713
}
10651
10714
} else if (attr === 'textAnchor' /* text-anchor */) {
10652
10715
ouputValue = value === 'start' ? LEFT : value === 'end' ? RIGHT : CENTER;
10653
- } else if (attr === 'charSpacing') {
10716
+ } else if (attr === 'charSpacing' || attr === TEXT_DECORATION_THICKNESS ) {
10654
10717
// parseUnit returns px and we convert it to em
10655
10718
parsed = parseUnit(value, fontSize) / fontSize * 1000;
10656
10719
} else if (attr === 'paintFirst') {
@@ -18404,64 +18467,6 @@ _defineProperty(Polygon, "type", 'Polygon');
18404
18467
classRegistry.setClass(Polygon);
18405
18468
classRegistry.setSVGClass(Polygon);
18406
18469
18407
- const fontProperties = ['fontSize', 'fontWeight', 'fontFamily', 'fontStyle'];
18408
- const textDecorationProperties = ['underline', 'overline', 'linethrough'];
18409
- const textLayoutProperties = [...fontProperties, 'lineHeight', 'text', 'charSpacing', 'textAlign', 'styles', 'path', 'pathStartOffset', 'pathSide', 'pathAlign'];
18410
- const additionalProps = [...textLayoutProperties, ...textDecorationProperties, 'textBackgroundColor', 'direction'];
18411
- const styleProperties = [...fontProperties, ...textDecorationProperties, STROKE, 'strokeWidth', FILL, 'deltaY', 'textBackgroundColor'];
18412
-
18413
- // @TODO: Many things here are configuration related and shouldn't be on the class nor prototype
18414
- // regexes, list of properties that are not suppose to change by instances, magic consts.
18415
- // this will be a separated effort
18416
- const textDefaultValues = {
18417
- _reNewline: reNewline,
18418
- _reSpacesAndTabs: /[ \t\r]/g,
18419
- _reSpaceAndTab: /[ \t\r]/,
18420
- _reWords: /\S+/g,
18421
- fontSize: 40,
18422
- fontWeight: 'normal',
18423
- fontFamily: 'Times New Roman',
18424
- underline: false,
18425
- overline: false,
18426
- linethrough: false,
18427
- textAlign: LEFT,
18428
- fontStyle: 'normal',
18429
- lineHeight: 1.16,
18430
- superscript: {
18431
- size: 0.6,
18432
- // fontSize factor
18433
- baseline: -0.35 // baseline-shift factor (upwards)
18434
- },
18435
- subscript: {
18436
- size: 0.6,
18437
- // fontSize factor
18438
- baseline: 0.11 // baseline-shift factor (downwards)
18439
- },
18440
- textBackgroundColor: '',
18441
- stroke: null,
18442
- shadow: null,
18443
- path: undefined,
18444
- pathStartOffset: 0,
18445
- pathSide: LEFT,
18446
- pathAlign: 'baseline',
18447
- _fontSizeFraction: 0.222,
18448
- offsets: {
18449
- underline: 0.1,
18450
- linethrough: -0.315,
18451
- overline: -0.88
18452
- },
18453
- _fontSizeMult: 1.13,
18454
- charSpacing: 0,
18455
- deltaY: 0,
18456
- direction: 'ltr',
18457
- CACHE_FONT_SIZE: 400,
18458
- MIN_TEXT_WIDTH: 2
18459
- };
18460
- const JUSTIFY = 'justify';
18461
- const JUSTIFY_LEFT = 'justify-left';
18462
- const JUSTIFY_RIGHT = 'justify-right';
18463
- const JUSTIFY_CENTER = 'justify-center';
18464
-
18465
18470
class StyledText extends FabricObject {
18466
18471
/**
18467
18472
* Returns true if object has no styling or no styling in a line
@@ -18776,7 +18781,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
18776
18781
} = _ref;
18777
18782
const noShadow = true,
18778
18783
textDecoration = this.getSvgTextDecoration(this);
18779
- return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', this.fontFamily ? "font-family=\"".concat(this.fontFamily.replace(dblQuoteRegex, "'"), "\" ") : '', this.fontSize ? "font-size=\"".concat(this.fontSize, "\" ") : '' , this.fontStyle ? "font-style=\"".concat(this.fontStyle, "\" ") : '', this.fontWeight ? "font-weight=\"".concat(this.fontWeight, "\" ") : '', textDecoration ? "text-decoration=\"".concat(textDecoration, "\" ") : '', this.direction === 'rtl' ? "direction=\"".concat(this.direction, "\" ") : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
18784
+ return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', "font-family=\"".concat(this.fontFamily.replace(dblQuoteRegex, "'"), "\" "), "font-size=\"".concat(this.fontSize, "\" "), this.fontStyle ? "font-style=\"".concat(this.fontStyle, "\" ") : '', this.fontWeight ? "font-weight=\"".concat(this.fontWeight, "\" ") : '', textDecoration ? "text-decoration=\"".concat(textDecoration, "\" ") : '', this.direction === 'rtl' ? "direction=\"".concat(this.direction, "\" ") : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
18780
18785
}
18781
18786
18782
18787
/**
@@ -18933,7 +18938,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
18933
18938
* @return {String}
18934
18939
*/
18935
18940
getSvgStyles(skipShadow) {
18936
- return "".concat(super.getSvgStyles(skipShadow), " white-space: pre;");
18941
+ return "".concat(super.getSvgStyles(skipShadow), " text-decoration-thickness: ").concat(toFixed(this.textDecorationThickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS), "%; white-space: pre;");
18937
18942
}
18938
18943
18939
18944
/**
@@ -18951,10 +18956,19 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
18951
18956
fontSize,
18952
18957
fontStyle,
18953
18958
fontWeight,
18954
- deltaY
18959
+ deltaY,
18960
+ textDecorationThickness,
18961
+ linethrough,
18962
+ overline,
18963
+ underline
18955
18964
} = style;
18956
- const textDecoration = this.getSvgTextDecoration(style);
18957
- return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? "stroke-width: ".concat(strokeWidth, "; ") : '', fontFamily ? "font-family: ".concat(!fontFamily.includes("'") && !fontFamily.includes('"') ? "'".concat(fontFamily, "'") : fontFamily, "; ") : '', fontSize ? "font-size: ".concat(fontSize, "px; ") : '', fontStyle ? "font-style: ".concat(fontStyle, "; ") : '', fontWeight ? "font-weight: ".concat(fontWeight, "; ") : '', textDecoration ? "text-decoration: ".concat(textDecoration, "; ") : textDecoration, fill ? colorPropToSVG(FILL, fill) : '', deltaY ? "baseline-shift: ".concat(-deltaY, "; ") : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
18965
+ const textDecoration = this.getSvgTextDecoration({
18966
+ underline: underline !== null && underline !== void 0 ? underline : this.underline,
18967
+ overline: overline !== null && overline !== void 0 ? overline : this.overline,
18968
+ linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
18969
+ });
18970
+ const thickness = textDecorationThickness || this.textDecorationThickness;
18971
+ return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? "stroke-width: ".concat(strokeWidth, "; ") : '', fontFamily ? "font-family: ".concat(!fontFamily.includes("'") && !fontFamily.includes('"') ? "'".concat(fontFamily, "'") : fontFamily, "; ") : '', fontSize ? "font-size: ".concat(fontSize, "px; ") : '', fontStyle ? "font-style: ".concat(fontStyle, "; ") : '', fontWeight ? "font-weight: ".concat(fontWeight, "; ") : '', textDecoration ? "text-decoration: ".concat(textDecoration, "; text-decoration-thickness: ").concat(toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS), "%; ") : '', fill ? colorPropToSVG(FILL, fill) : '', deltaY ? "baseline-shift: ".concat(-deltaY, "; ") : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
18958
18972
}
18959
18973
18960
18974
/**
@@ -19971,6 +19985,7 @@ class FabricText extends StyledText {
19971
19985
const leftOffset = this._getLeftOffset(),
19972
19986
path = this.path,
19973
19987
charSpacing = this._getWidthOfCharSpacing(),
19988
+ offsetAligner = type === 'linethrough' ? 0.5 : type === 'overline' ? 1 : 0,
19974
19989
offsetY = this.offsets[type];
19975
19990
for (let i = 0, len = this._textLines.length; i < len; i++) {
19976
19991
const heightOfLine = this.getHeightOfLine(i);
@@ -19985,38 +20000,44 @@ class FabricText extends StyledText {
19985
20000
let boxWidth = 0;
19986
20001
let lastDecoration = this.getValueOfPropertyAt(i, 0, type);
19987
20002
let lastFill = this.getValueOfPropertyAt(i, 0, FILL);
19988
- let currentDecoration;
19989
- let currentFill;
20003
+ let lastTickness = this.getValueOfPropertyAt(i, 0, TEXT_DECORATION_THICKNESS);
20004
+ let currentDecoration = lastDecoration;
20005
+ let currentFill = lastFill;
20006
+ let currentTickness = lastTickness;
19990
20007
const top = topOffset + maxHeight * (1 - this._fontSizeFraction);
19991
20008
let size = this.getHeightOfChar(i, 0);
19992
20009
let dy = this.getValueOfPropertyAt(i, 0, 'deltaY');
19993
20010
for (let j = 0, jlen = line.length; j < jlen; j++) {
19994
20011
const charBox = this.__charBounds[i][j];
19995
20012
currentDecoration = this.getValueOfPropertyAt(i, j, type);
19996
20013
currentFill = this.getValueOfPropertyAt(i, j, FILL);
20014
+ currentTickness = this.getValueOfPropertyAt(i, j, TEXT_DECORATION_THICKNESS);
19997
20015
const currentSize = this.getHeightOfChar(i, j);
19998
20016
const currentDy = this.getValueOfPropertyAt(i, j, 'deltaY');
19999
20017
if (path && currentDecoration && currentFill) {
20018
+ const finalTickness = this.fontSize * currentTickness / 1000;
20000
20019
ctx.save();
20001
20020
// bug? verify lastFill is a valid fill here.
20002
20021
ctx.fillStyle = lastFill;
20003
20022
ctx.translate(charBox.renderLeft, charBox.renderTop);
20004
20023
ctx.rotate(charBox.angle);
20005
- ctx.fillRect(-charBox.kernedWidth / 2, offsetY * currentSize + currentDy, charBox.kernedWidth, this.fontSize / 15 );
20024
+ ctx.fillRect(-charBox.kernedWidth / 2, offsetY * currentSize + currentDy - offsetAligner * finalTickness , charBox.kernedWidth, finalTickness );
20006
20025
ctx.restore();
20007
- } else if ((currentDecoration !== lastDecoration || currentFill !== lastFill || currentSize !== size || currentDy !== dy) && boxWidth > 0) {
20026
+ } else if ((currentDecoration !== lastDecoration || currentFill !== lastFill || currentSize !== size || currentTickness !== lastTickness || currentDy !== dy) && boxWidth > 0) {
20027
+ const finalTickness = this.fontSize * lastTickness / 1000;
20008
20028
let drawStart = leftOffset + lineLeftOffset + boxStart;
20009
20029
if (this.direction === 'rtl') {
20010
20030
drawStart = this.width - drawStart - boxWidth;
20011
20031
}
20012
- if (lastDecoration && lastFill) {
20032
+ if (lastDecoration && lastFill && lastTickness ) {
20013
20033
// bug? verify lastFill is a valid fill here.
20014
20034
ctx.fillStyle = lastFill;
20015
- ctx.fillRect(drawStart, top + offsetY * size + dy, boxWidth, this.fontSize / 15 );
20035
+ ctx.fillRect(drawStart, top + offsetY * size + dy - offsetAligner * finalTickness , boxWidth, finalTickness );
20016
20036
}
20017
20037
boxStart = charBox.left;
20018
20038
boxWidth = charBox.width;
20019
20039
lastDecoration = currentDecoration;
20040
+ lastTickness = currentTickness;
20020
20041
lastFill = currentFill;
20021
20042
size = currentSize;
20022
20043
dy = currentDy;
@@ -20029,7 +20050,8 @@ class FabricText extends StyledText {
20029
20050
drawStart = this.width - drawStart - boxWidth;
20030
20051
}
20031
20052
ctx.fillStyle = currentFill;
20032
- currentDecoration && currentFill && ctx.fillRect(drawStart, top + offsetY * size + dy, boxWidth - charSpacing, this.fontSize / 15);
20053
+ const finalTickness = this.fontSize * currentTickness / 1000;
20054
+ currentDecoration && currentFill && currentTickness && ctx.fillRect(drawStart, top + offsetY * size + dy - offsetAligner * finalTickness, boxWidth - charSpacing, finalTickness);
20033
20055
topOffset += heightOfLine;
20034
20056
}
20035
20057
// if there is text background color no
0 commit comments