diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3d4e08..f514cfb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 9.3.15 (2024-09-09) + +- fix letter spacing for Hindi text - ts fixes ### 9.3.14 (2024-07-16) diff --git a/src/shapes/Text.ts b/src/shapes/Text.ts index 07418fa0..476a7c90 100644 --- a/src/shapes/Text.ts +++ b/src/shapes/Text.ts @@ -13,12 +13,33 @@ import { _registerNode } from '../Global'; import { GetSet } from '../types'; -export function stringToArray(string: string) { - // we need to use `Array.from` because it can split unicode string correctly - // we also can use some regexp magic from lodash: - // https://github.com/lodash/lodash/blob/fb1f99d9d90ad177560d771bc5953a435b2dc119/lodash.toarray/index.js#L256 - // but I decided it is too much code for that small fix - return Array.from(string); +export function stringToArray(string: string): string[] { + // Use Unicode-aware splitting + return [...string].reduce((acc, char, index, array) => { + // Handle emoji sequences (including ZWJ sequences) + if ( + /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?(?:\u200D\p{Emoji_Presentation})+/u.test( + char + ) + ) { + acc.push(char); + } + // Handle regional indicator symbols (flags) + else if ( + /\p{Regional_Indicator}{2}/u.test(char + (array[index + 1] || '')) + ) { + acc.push(char + array[index + 1]); + } + // Handle Indic scripts and other combining characters + else if (index > 0 && /\p{Mn}|\p{Me}|\p{Mc}/u.test(char)) { + acc[acc.length - 1] += char; + } + // Handle other characters + else { + acc.push(char); + } + return acc; + }, [] as string[]); } export interface TextConfig extends ShapeConfig { diff --git a/test/unit/Text-test.ts b/test/unit/Text-test.ts index f95cb804..0c84ccd1 100644 --- a/test/unit/Text-test.ts +++ b/test/unit/Text-test.ts @@ -164,6 +164,34 @@ describe('Text', function () { compareLayerAndCanvas(layer, canvas, 254); }); + it('check hindi with letterSpacing', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + + var text = new Konva.Text({ + x: 10, + y: 10, + text: 'आपकी दौड़ के लिए परफेक्ट जूते!', + fontSize: 50, + letterSpacing: 10, + }); + + layer.add(text); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.textBaseline = 'middle'; + context.letterSpacing = '10px'; + context.font = 'normal normal 50px Arial'; + context.fillStyle = 'darkgrey'; + context.fillText('आपकी दौड़ के लिए परफेक्ट जूते!', 10, 10 + 25); + + if (isBrowser) { + compareLayerAndCanvas(layer, canvas, 254, 200); + } + }); + it('text cache with fill and shadow', function () { // TODO: on node-canvas it doesn't work // text scaling is not correct