diff --git a/core/fonts/NotoSansHK-Regular.ttf b/core/fonts/NotoSansHK-Regular.ttf new file mode 100644 index 00000000000..2a62b9753dd Binary files /dev/null and b/core/fonts/NotoSansHK-Regular.ttf differ diff --git a/core/fonts/NotoSansJP-Regular.ttf b/core/fonts/NotoSansJP-Regular.ttf new file mode 100644 index 00000000000..b2dad730d76 Binary files /dev/null and b/core/fonts/NotoSansJP-Regular.ttf differ diff --git a/core/fonts/NotoSansKR-Regular.ttf b/core/fonts/NotoSansKR-Regular.ttf new file mode 100644 index 00000000000..1b14d32473b Binary files /dev/null and b/core/fonts/NotoSansKR-Regular.ttf differ diff --git a/core/fonts/NotoSansSC-Regular.ttf b/core/fonts/NotoSansSC-Regular.ttf new file mode 100644 index 00000000000..7056f5e97a8 Binary files /dev/null and b/core/fonts/NotoSansSC-Regular.ttf differ diff --git a/core/fonts/NotoSansTC-Regular.ttf b/core/fonts/NotoSansTC-Regular.ttf new file mode 100644 index 00000000000..e838ef549bb Binary files /dev/null and b/core/fonts/NotoSansTC-Regular.ttf differ diff --git a/lib/private/Avatar/Avatar.php b/lib/private/Avatar/Avatar.php index 7aa2d220b88..d11c0f394dc 100644 --- a/lib/private/Avatar/Avatar.php +++ b/lib/private/Avatar/Avatar.php @@ -14,6 +14,8 @@ use OCP\Color; use OCP\Files\NotFoundException; use OCP\IAvatar; use Psr\Log\LoggerInterface; +use OC\User\User; +use OCP\IConfig; /** * This class gets and sets users avatars. @@ -84,8 +86,7 @@ abstract class Avatar implements IAvatar { * @return string * */ - protected function getAvatarVector(int $size, bool $darkTheme): string { - $userDisplayName = $this->getDisplayName(); + protected function getAvatarVector(string $userDisplayName, int $size, bool $darkTheme): string { $fgRGB = $this->avatarBackgroundColor($userDisplayName); $bgRGB = $fgRGB->alphaBlending(0.1, $darkTheme ? new Color(0, 0, 0) : new Color(255, 255, 255)); $fill = sprintf('%02x%02x%02x', $bgRGB->red(), $bgRGB->green(), $bgRGB->blue()); @@ -95,10 +96,32 @@ abstract class Avatar implements IAvatar { return str_replace($toReplace, [$size, $fill, $fgFill, $text], $this->svgTemplate); } + /** + * Select the rendering font based on the user's display name and language + */ + private function getFont(string $userDisplayName): string { + if (preg_match('/\p{Han}/u', $userDisplayName) === 1) { + $userlang = $this->config->getUserValue($this->user->getUID(), 'core', 'lang', ''); + switch ($userlang) { + case 'zh_TW': + return __DIR__ . '/../../../core/fonts/NotoSansTC-Regular.ttf'; + case 'zh_HK': + return __DIR__ . '/../../../core/fonts/NotoSansHK-Regular.ttf'; + case 'ja': + return __DIR__ . '/../../../core/fonts/NotoSansJP-Regular.ttf'; + case 'ko': + return __DIR__ . '/../../../core/fonts/NotoSansKR-Regular.ttf'; + default: + return __DIR__ . '/../../../core/fonts/NotoSansSC-Regular.ttf'; + } + } + return __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf'; + } + /** * Generate png avatar from svg with Imagick */ - protected function generateAvatarFromSvg(int $size, bool $darkTheme): ?string { + protected function generateAvatarFromSvg(string $userDisplayName, int $size, bool $darkTheme): ?string { if (!extension_loaded('imagick')) { return null; } @@ -106,10 +129,11 @@ abstract class Avatar implements IAvatar { // Avatar generation breaks if RSVG format is enabled. Fall back to gd in that case if (in_array('RSVG', $formats, true)) { return null; - } + } + $text = $this->getAvatarText(); try { - $font = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf'; - $svg = $this->getAvatarVector($size, $darkTheme); + $font = $this->getFont($text); + $svg = $this->getAvatarVector($userDisplayName, $size, $darkTheme); $avatar = new Imagick(); $avatar->setFont($font); $avatar->readImageBlob($svg); @@ -151,7 +175,7 @@ abstract class Avatar implements IAvatar { } imagefilledrectangle($im, 0, 0, $size, $size, $background); - $font = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf'; + $font = $this->getFont($text); $fontSize = $size * 0.4; [$x, $y] = $this->imageTTFCenter( diff --git a/lib/private/Avatar/PlaceholderAvatar.php b/lib/private/Avatar/PlaceholderAvatar.php index 07c54f62713..c2120e37f22 100644 --- a/lib/private/Avatar/PlaceholderAvatar.php +++ b/lib/private/Avatar/PlaceholderAvatar.php @@ -87,8 +87,9 @@ class PlaceholderAvatar extends Avatar { throw new NotFoundException; } - if (!$data = $this->generateAvatarFromSvg($size, $darkTheme)) { - $data = $this->generateAvatar($this->getDisplayName(), $size, $darkTheme); + $userDisplayName = $this->getDisplayName(); + if (!$data = $this->generateAvatarFromSvg($userDisplayName, $size, $darkTheme)) { + $data = $this->generateAvatar($userDisplayName, $size, $darkTheme); } try { diff --git a/lib/private/Avatar/UserAvatar.php b/lib/private/Avatar/UserAvatar.php index bef0a20e7b8..4506a654b8e 100644 --- a/lib/private/Avatar/UserAvatar.php +++ b/lib/private/Avatar/UserAvatar.php @@ -26,9 +26,9 @@ class UserAvatar extends Avatar { public function __construct( private ISimpleFolder $folder, private IL10N $l, - private User $user, + protected User $user, LoggerInterface $logger, - private IConfig $config, + protected IConfig $config, ) { parent::__construct($logger); } @@ -201,8 +201,9 @@ class UserAvatar extends Avatar { try { $ext = $this->getExtension($generated, $darkTheme); } catch (NotFoundException $e) { - if (!$data = $this->generateAvatarFromSvg(1024, $darkTheme)) { - $data = $this->generateAvatar($this->getDisplayName(), 1024, $darkTheme); + $userDisplayName = $this->getDisplayName(); + if (!$data = $this->generateAvatarFromSvg($userDisplayName, 1024, $darkTheme)) { + $data = $this->generateAvatar($userDisplayName, 1024, $darkTheme); } $avatar = $this->folder->newFile($darkTheme ? 'avatar-dark.png' : 'avatar.png'); $avatar->putContent($data); @@ -234,8 +235,9 @@ class UserAvatar extends Avatar { throw new NotFoundException; } if ($generated) { - if (!$data = $this->generateAvatarFromSvg($size, $darkTheme)) { - $data = $this->generateAvatar($this->getDisplayName(), $size, $darkTheme); + $userDisplayName = $this->getDisplayName(); + if (!$data = $this->generateAvatarFromSvg($userDisplayName, $size, $darkTheme)) { + $data = $this->generateAvatar($userDisplayName, $size, $darkTheme); } } else { $avatar = new \OCP\Image();