diff --git a/src/Typography/Line.php b/src/Typography/Line.php index f9630cbc..62652192 100644 --- a/src/Typography/Line.php +++ b/src/Typography/Line.php @@ -36,7 +36,7 @@ class Line implements IteratorAggregate, Countable, Stringable protected PointInterface $position = new Point() ) { if (is_string($text)) { - $this->segments = explode(" ", $text); + $this->segments = $this->wordsSeperatedBySpaces($text) ? explode(" ", $text) : mb_str_split($text); } } @@ -88,7 +88,7 @@ class Line implements IteratorAggregate, Countable, Stringable /** * Count segments (individual words including punctuation marks) of line - * + * * @return int */ public function count(): int @@ -106,6 +106,23 @@ class Line implements IteratorAggregate, Countable, Stringable return mb_strlen((string) $this); } + /** + * Dermine if words are sperarated by spaces in the written language of the given text + */ + private function wordsSeperatedBySpaces(string $text): bool + { + return 1 !== preg_match( + '/[' . + '\x{4E00}-\x{9FFF}' . // CJK Unified Ideographs (chinese) + '\x{3400}-\x{4DBF}' . // CJK Unified Ideographs Extension A (chinese) + '\x{3040}-\x{309F}' . // hiragana (japanese) + '\x{30A0}-\x{30FF}' . // katakana (japanese) + '\x{0E00}-\x{0E7F}' . // thai + ']/u', + $text + ); + } + /** * Cast line to string * @@ -113,6 +130,12 @@ class Line implements IteratorAggregate, Countable, Stringable */ public function __toString(): string { - return implode(" ", $this->segments); + $string = implode("", $this->segments); + + if ($this->wordsSeperatedBySpaces($string)) { + return implode(" ", $this->segments); + } + + return $string; } } diff --git a/tests/Unit/Typography/LineTest.php b/tests/Unit/Typography/LineTest.php index b68bb3da..b876e567 100644 --- a/tests/Unit/Typography/LineTest.php +++ b/tests/Unit/Typography/LineTest.php @@ -4,10 +4,12 @@ declare(strict_types=1); namespace Intervention\Image\Tests\Unit\Typography; +use Generator; use Intervention\Image\Geometry\Point; use Intervention\Image\Tests\BaseTestCase; use Intervention\Image\Typography\Line; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; #[CoversClass(Line::class)] final class LineTest extends BaseTestCase @@ -18,10 +20,12 @@ final class LineTest extends BaseTestCase $this->assertInstanceOf(Line::class, $line); } - public function testToString(): void + #[DataProvider('toStringDataProvider')] + public function testToString(string $text, int $words): void { - $line = new Line('foo bar'); - $this->assertEquals('foo bar', (string) $line); + $line = new Line($text); + $this->assertEquals($words, $line->count()); + $this->assertEquals($text, (string) $line); } public function testSetGetPosition(): void @@ -75,4 +79,14 @@ final class LineTest extends BaseTestCase $this->assertEquals(2, $line->count()); $this->assertEquals(2, $result->count()); } + + public static function toStringDataProvider(): Generator + { + yield ['foo', 1]; + yield ['foo bar', 2]; + yield ['测试', 2]; // CJK Unified Ideographs + yield ['テスト', 3]; // japanese + yield ['ทดสอบ', 5]; // thai + yield ['这只是我写的一个测试。', 11]; // CJK Unified Ideographs + } }