diff --git a/dist/paper.d.ts b/dist/paper.d.ts index 39c66d8da9..64646b6e19 100644 --- a/dist/paper.d.ts +++ b/dist/paper.d.ts @@ -6538,6 +6538,11 @@ declare namespace paper { */ justification: string + /** + * The letter spacing of text content. + */ + letterSpacing: string + /** * Style objects don't need to be created directly. Just pass an object to @@ -6657,6 +6662,11 @@ declare namespace paper { */ justification: string + /** + * The letter spacing of text content. + */ + letterSpacing: string + } diff --git a/gulp/typescript/typescript-definition-test.ts b/gulp/typescript/typescript-definition-test.ts index 81020289a5..c4ce6935e4 100644 --- a/gulp/typescript/typescript-definition-test.ts +++ b/gulp/typescript/typescript-definition-test.ts @@ -892,6 +892,7 @@ style.fontWeight; style.fontSize; style.leading; style.justification; +style.letterSpacing; // @@ -977,6 +978,7 @@ textItem.fontWeight; textItem.fontSize; textItem.leading; textItem.justification; +textItem.letterSpacing; // diff --git a/src/style/Style.js b/src/style/Style.js index 72609b9197..4125653d67 100644 --- a/src/style/Style.js +++ b/src/style/Style.js @@ -96,6 +96,7 @@ var Style = Base.extend(new function() { fontWeight: 'normal', fontSize: 12, leading: null, + letterSpacing: 0, // Paragraphs justification: 'left' }), @@ -392,7 +393,7 @@ var Style = Base.extend(new function() { if (/pt|em|%|px/.test(fontSize)) fontSize = this.getView().getPixelSize(fontSize); return leading != null ? leading : fontSize * 1.2; - } + }, // DOCS: why isn't the example code showing up? /** @@ -702,4 +703,21 @@ var Style = Base.extend(new function() { * @values 'left', 'right', 'center' * @default 'left' */ + + /** + * The letter spacing of text content. + * + * @name Style#letterSpacing + * @type Number|String + * @default 0 + */ + getLetterSpacing: function getLetterSpacing() { + // Override letterSpacing to include px + // as the default unit, when not provided + var letterSpacing = getLetterSpacing.base.call(this); + if (typeof letterSpacing === 'number') { + return letterSpacing + 'px'; + } + return letterSpacing; + } }); diff --git a/src/svg/SvgStyles.js b/src/svg/SvgStyles.js index d9cbab1b42..7d1b61c1a8 100644 --- a/src/svg/SvgStyles.js +++ b/src/svg/SvgStyles.js @@ -41,6 +41,7 @@ var SvgStyles = Base.each({ center: 'middle', right: 'end' }], + letterSpacing: ['letter-spacing', 'string'], // Item opacity: ['opacity', 'number'], blendMode: ['mix-blend-mode', 'style'] diff --git a/src/text/PointText.js b/src/text/PointText.js index 8dd17c51a9..03879543c3 100644 --- a/src/text/PointText.js +++ b/src/text/PointText.js @@ -88,6 +88,7 @@ var PointText = TextItem.extend(/** @lends PointText# */{ shadowColor = ctx.shadowColor; ctx.font = style.getFontStyle(); ctx.textAlign = style.getJustification(); + ctx.letterSpacing = style.getLetterSpacing(); for (var i = 0, l = lines.length; i < l; i++) { // See Path._draw() for explanation about ctx.shadowColor ctx.shadowColor = shadowColor; @@ -108,7 +109,7 @@ var PointText = TextItem.extend(/** @lends PointText# */{ numLines = lines.length, justification = style.getJustification(), leading = style.getLeading(), - width = this.getView().getTextWidth(style.getFontStyle(), lines), + width = this.getView().getTextWidth(style.getFontStyle(), lines, style.getLetterSpacing()), x = 0; // Adjust for different justifications. if (justification !== 'left') diff --git a/src/text/TextItem.js b/src/text/TextItem.js index bb36dd48f1..825367fd0a 100644 --- a/src/text/TextItem.js +++ b/src/text/TextItem.js @@ -155,6 +155,14 @@ var TextItem = Item.extend(/** @lends TextItem# */{ * @default 'left' */ + /** + * The letter spacing of text content. + * + * @name Style#letterSpacing + * @type Number|String + * @default 0 + */ + /** * @bean * @private diff --git a/src/view/CanvasView.js b/src/view/CanvasView.js index cabb135938..d4c484d78e 100644 --- a/src/view/CanvasView.js +++ b/src/view/CanvasView.js @@ -113,16 +113,19 @@ var CanvasView = View.extend(/** @lends CanvasView# */{ return pixels; }, - getTextWidth: function(font, lines) { + getTextWidth: function(font, lines, letterSpacing) { var ctx = this._context, prevFont = ctx.font, + prevLetterSpacing = ctx.letterSpacing, width = 0; ctx.font = font; + ctx.letterSpacing = letterSpacing; // Measure the real width of the text. Unfortunately, there is no sane // way to measure text height with canvas. for (var i = 0, l = lines.length; i < l; i++) width = Math.max(width, ctx.measureText(lines[i]).width); ctx.font = prevFont; + ctx.letterSpacing = prevLetterSpacing; return width; }, diff --git a/test/helpers.js b/test/helpers.js index 9e909aa584..a84f2039eb 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -334,7 +334,7 @@ var compareItem = function(actual, expected, message, options, properties) { 'strokeColor', 'strokeCap', 'strokeJoin', 'dashArray', 'dashOffset', 'miterLimit']; if (expected instanceof TextItem) - styles.push('fontSize', 'font', 'leading', 'justification'); + styles.push('fontSize', 'font', 'leading', 'justification', 'letterSpacing'); compareProperties(actual.style, expected.style, styles, message + ' (#style)', options); } diff --git a/test/tests/Item_Bounds.js b/test/tests/Item_Bounds.js index 1156115e84..106d6685ec 100644 --- a/test/tests/Item_Bounds.js +++ b/test/tests/Item_Bounds.js @@ -103,6 +103,18 @@ test('text.bounds', function() { equals(text.bounds, new Rectangle(50, 87.4, 76.25, 16.8), 'text.bounds', { tolerance: 1.0 }); }); +test('text.bounds with letterSpacing', function() { + var text = new PointText({ + fontFamily: 'Arial, Helvetica', + fontSize: 14, + letterSpacing: 10, + fillColor: 'black', + point: [50, 100], + content: 'Hello World!' + }); + equals(text.bounds, new Rectangle(50, 87.4, 196, 16.8), 'text.bounds', { tolerance: 1.0 }); + }); + test('path.bounds', function() { var path = new Path([ new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)), diff --git a/test/tests/Item_Cloning.js b/test/tests/Item_Cloning.js index 404d79eb66..b6b0072a85 100644 --- a/test/tests/Item_Cloning.js +++ b/test/tests/Item_Cloning.js @@ -110,6 +110,7 @@ test('PointText#clone()', function() { fontSize: 20 }; pointText.justification = 'center'; + pointText.letterSpacing = '10px'; cloneAndCompare(pointText); });