From 462b172991e37a686bb6f78b0419ead069a721a8 Mon Sep 17 00:00:00 2001 From: Kenneth Ormandy Date: Thu, 15 Feb 2024 22:22:32 -0800 Subject: [PATCH 1/4] Adds letter-spacing support --- dist/paper.d.ts | 10 ++++++++++ gulp/typescript/typescript-definition-test.ts | 2 ++ src/style/Style.js | 9 +++++++++ src/svg/SvgStyles.js | 1 + src/text/PointText.js | 1 + src/text/TextItem.js | 8 ++++++++ 6 files changed, 31 insertions(+) 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..e4c677d7e0 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' }), @@ -702,4 +703,12 @@ 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 + */ }); 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..183beafaef 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; 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 From a6f4cc89c5dcd47b53cfdcc8e851b7d64c33e0b2 Mon Sep 17 00:00:00 2001 From: Kenneth Ormandy Date: Thu, 15 Feb 2024 22:39:33 -0800 Subject: [PATCH 2/4] Adds bounds measurement with letter spacing --- src/text/PointText.js | 2 +- src/view/CanvasView.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/text/PointText.js b/src/text/PointText.js index 183beafaef..03879543c3 100644 --- a/src/text/PointText.js +++ b/src/text/PointText.js @@ -109,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/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; }, From 269d93440aff1a73ad79d3c83c1ab91877b90bc4 Mon Sep 17 00:00:00 2001 From: Kenneth Ormandy Date: Thu, 15 Feb 2024 22:59:18 -0800 Subject: [PATCH 3/4] Adds tests --- test/helpers.js | 2 +- test/tests/Item_Bounds.js | 12 ++++++++++++ test/tests/Item_Cloning.js | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) 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); }); From de8de03bc21f6a2c70f98cae878d88a426edf926 Mon Sep 17 00:00:00 2001 From: Kenneth Ormandy Date: Thu, 15 Feb 2024 23:04:29 -0800 Subject: [PATCH 4/4] Fixes support for providing letter spacing without a unit --- src/style/Style.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/style/Style.js b/src/style/Style.js index e4c677d7e0..4125653d67 100644 --- a/src/style/Style.js +++ b/src/style/Style.js @@ -393,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? /** @@ -711,4 +711,13 @@ var Style = Base.extend(new function() { * @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; + } });