From ea6dcf186bb14d1d6da836d99884a95991568c2e Mon Sep 17 00:00:00 2001 From: Anton Lavrevov Date: Wed, 10 Sep 2025 13:53:10 -0500 Subject: [PATCH] Fixed internal calculations for `TextPath` to return correct width and height --- CHANGELOG.md | 4 ++++ src/shapes/TextPath.ts | 4 ++-- test/unit/Text-test.ts | 17 +++++++++++++---- test/unit/TextPath-test.ts | 30 ++++++++++++++++++++++++++++-- test/unit/test-utils.ts | 8 ++++---- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 018acf46..985bc57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 10.0.2 (2025-09-10) + +- Fixed internal calculations for `TextPath` to return correct width and height + ## 10.0.1 (2025-09-09) - Fixed `line-through` render for center/right aligned text diff --git a/src/shapes/TextPath.ts b/src/shapes/TextPath.ts index 508394d9..487f8f4b 100644 --- a/src/shapes/TextPath.ts +++ b/src/shapes/TextPath.ts @@ -119,8 +119,8 @@ export class TextPath extends Shape { } const totalLength = this.pathLength; - // -1px for rounding of the last symbol - if (length - 1 > totalLength) { + + if (length > totalLength) { return null; } diff --git a/test/unit/Text-test.ts b/test/unit/Text-test.ts index 566573c5..2f4852d1 100644 --- a/test/unit/Text-test.ts +++ b/test/unit/Text-test.ts @@ -1112,10 +1112,19 @@ describe('Text', function () { layer.add(text); stage.add(layer); - var trace = - 'clearRect(0,0,578,200);save();transform(1,0,0,1,10,10);font=normal normal 40px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();save();beginPath();moveTo(54,44);lineTo(245,44);stroke();restore();fillStyle=black;fillText(hello world,54,34);save();beginPath();moveTo(54,24);lineTo(245,24);stroke();restore();restore();restore();'; - - assert.equal(layer.getContext().getTrace(false, true), trace); + if (Konva._renderBackend === 'node-canvas') { + var trace = + 'clearRect(0,0,578,200);save();transform(1,0,0,1,10,10);font=normal normal 40px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();save();beginPath();moveTo(54,44);lineTo(245,44);stroke();restore();fillStyle=black;fillText(hello world,54,34);save();beginPath();moveTo(54,24);lineTo(245,24);stroke();restore();restore();restore();'; + assert.equal(layer.getContext().getTrace(false, true), trace); + } else if (Konva._renderBackend === 'skia-canvas') { + var trace = + 'clearRect(0,0,578,200);save();transform(1,0,0,1,10,10);font=normal normal 40px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();save();beginPath();moveTo(54,43);lineTo(245,43);stroke();restore();fillStyle=black;fillText(hello world,54,33);save();beginPath();moveTo(54,23);lineTo(245,23);stroke();restore();restore();restore();'; + assert.equal(layer.getContext().getTrace(false, true), trace); + } else { + var trace = + 'clearRect(0,0,578,200);save();transform(1,0,0,1,10,10);font=normal normal 40px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();save();beginPath();moveTo(54,44);lineTo(245,44);stroke();restore();fillStyle=black;fillText(hello world,54,34);save();beginPath();moveTo(54,24);lineTo(245,24);stroke();restore();restore();restore();'; + assert.equal(layer.getContext().getTrace(false, true), trace); + } }); it('text multi line with underline and strike and gradient', function () { diff --git a/test/unit/TextPath-test.ts b/test/unit/TextPath-test.ts index e7c81ede..5d300952 100644 --- a/test/unit/TextPath-test.ts +++ b/test/unit/TextPath-test.ts @@ -4,7 +4,7 @@ import { addStage, Konva, cloneAndCompareLayer, - isBrowser, + assertAlmostEqual, } from './test-utils.ts'; describe('TextPath', function () { @@ -929,10 +929,36 @@ describe('TextPath', function () { layer.draw(); var rect = textpath.getClientRect(); - assert.equal(Math.round(rect.width), 299); + assert.equal(Math.round(rect.width), 298); assert.equal(Math.abs(Math.round(rect.height) - 171) < 2, true); }); + it('check path calculations', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + const textpath = new Konva.TextPath({ + align: 'center', + data: 'M 26.549722364755468 144.8125 A 20.34375 20.34375 0 1 0 26.549722364755468 185.5 A 20.34375 20.34375 0 1 0 26.549722364755468 144.8125', + fill: 'black', + fontFamily: 'Arial', + fontSize: 7, + fontStyle: 'normal normal', + letterSpacing: 0, + text: '1234567890qwertyuiop[asdfhjkllzxncnm,../', + textBaseline: 'middle', + visible: true, + x: 0, + y: 0, + }); + layer.add(textpath); + + const box = textpath.getSelfRect(); + assertAlmostEqual(box.width, 47, 1); + assertAlmostEqual(box.height, 47, 1); + }); + it.skip('check vertical text path', function () { var stage = addStage(); diff --git a/test/unit/test-utils.ts b/test/unit/test-utils.ts index 4919a7a0..2a03e138 100644 --- a/test/unit/test-utils.ts +++ b/test/unit/test-utils.ts @@ -395,12 +395,12 @@ export function simulatePointerUp(stage: Stage, pos: SimulatedPointerEvent) { // Konva.DD._endDragAfter(evt); } -function isClose(a, b) { - return Math.abs(a - b) < 0.000001; +function isClose(a, b, tol = 0.000001) { + return Math.abs(a - b) < tol; } -export const assertAlmostEqual = function (val1, val2) { - if (!isClose(val1, val2)) { +export const assertAlmostEqual = function (val1, val2, tol = 0.000001) { + if (!isClose(val1, val2, tol)) { throw new Error('Expected ' + val1 + ' to be almost equal to ' + val2); } };