Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorCarl Schwan <carl@carlschwan.eu>2022-08-30 14:27:21 +0300
committerCarl Schwan <carl@carlschwan.eu>2022-09-09 14:37:51 +0300
commitf98ae2b5b0567f28a875106724c0475d6395f3c5 (patch)
treebc21874832e15741f4c5a9545138b3044f7c340b /lib
parent76f42e121b7aee17508feeb8e86ded55b9b78736 (diff)
Avatar new style
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Avatar/Avatar.php37
-rw-r--r--lib/private/Avatar/UserAvatar.php46
-rw-r--r--lib/public/Color.php8
-rw-r--r--lib/public/IAvatar.php6
4 files changed, 65 insertions, 32 deletions
diff --git a/lib/private/Avatar/Avatar.php b/lib/private/Avatar/Avatar.php
index 0eb8f8816d8..aec0f6e10f4 100644
--- a/lib/private/Avatar/Avatar.php
+++ b/lib/private/Avatar/Avatar.php
@@ -59,7 +59,7 @@ abstract class Avatar implements IAvatar {
private string $svgTemplate = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="{size}" height="{size}" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="#{fill}"></rect>
- <text x="50%" y="350" style="font-weight:normal;font-size:280px;font-family:\'Noto Sans\';text-anchor:middle;fill:#fff">{letter}</text>
+ <text x="50%" y="350" style="font-weight:normal;font-size:280px;font-family:\'Noto Sans\';text-anchor:middle;fill:#{fgFill}">{letter}</text>
</svg>';
public function __construct(LoggerInterface $logger) {
@@ -88,9 +88,9 @@ abstract class Avatar implements IAvatar {
/**
* @inheritdoc
*/
- public function get(int $size = 64) {
+ public function get(int $size = 64, bool $darkTheme = false) {
try {
- $file = $this->getFile($size);
+ $file = $this->getFile($size, $darkTheme);
} catch (NotFoundException $e) {
return false;
}
@@ -111,25 +111,27 @@ abstract class Avatar implements IAvatar {
* @return string
*
*/
- protected function getAvatarVector(int $size): string {
+ protected function getAvatarVector(int $size, bool $dark): string {
$userDisplayName = $this->getDisplayName();
- $bgRGB = $this->avatarBackgroundColor($userDisplayName);
- $bgHEX = sprintf("%02x%02x%02x", $bgRGB->red(), $bgRGB->green(), $bgRGB->blue());
+ $fgRGB = $this->avatarBackgroundColor($userDisplayName);
+ $bgRGB = $fgRGB->alphaBlending(0.1, $dark ? new Color(0, 0, 0) : new Color(255, 255, 255));
+ $fill = sprintf("%02x%02x%02x", $bgRGB->red(), $bgRGB->green(), $bgRGB->blue());
+ $fgFill = sprintf("%02x%02x%02x", $fgRGB->red(), $fgRGB->green(), $fgRGB->blue());
$text = $this->getAvatarText();
- $toReplace = ['{size}', '{fill}', '{letter}'];
- return str_replace($toReplace, [$size, $bgHEX, $text], $this->svgTemplate);
+ $toReplace = ['{size}', '{fill}', '{fgFill}', '{letter}'];
+ return str_replace($toReplace, [$size, $fill, $fgFill, $text], $this->svgTemplate);
}
/**
* Generate png avatar from svg with Imagick
*/
- protected function generateAvatarFromSvg(int $size): ?string {
+ protected function generateAvatarFromSvg(int $size, bool $dark): ?string {
if (!extension_loaded('imagick')) {
return null;
}
try {
- $font = __DIR__ . '/../../core/fonts/NotoSans-Regular.ttf';
- $svg = $this->getAvatarVector($size);
+ $font = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf';
+ $svg = $this->getAvatarVector($size, $dark);
$avatar = new Imagick();
$avatar->setFont($font);
$avatar->readImageBlob($svg);
@@ -145,9 +147,10 @@ abstract class Avatar implements IAvatar {
/**
* Generate png avatar with GD
*/
- protected function generateAvatar(string $userDisplayName, int $size): string {
+ protected function generateAvatar(string $userDisplayName, int $size, bool $dark): string {
$text = $this->getAvatarText();
- $backgroundColor = $this->avatarBackgroundColor($userDisplayName);
+ $textColor = $this->avatarBackgroundColor($userDisplayName);
+ $backgroundColor = $textColor->alphaBlending(0.1, $dark ? new Color() : new Color(255, 255, 255));
$im = imagecreatetruecolor($size, $size);
$background = imagecolorallocate(
@@ -156,7 +159,11 @@ abstract class Avatar implements IAvatar {
$backgroundColor->green(),
$backgroundColor->blue()
);
- $white = imagecolorallocate($im, 255, 255, 255);
+ $textColor = imagecolorallocate($im,
+ $textColor->red(),
+ $textColor->green(),
+ $textColor->blue()
+ );
imagefilledrectangle($im, 0, 0, $size, $size, $background);
$font = __DIR__ . '/../../../core/fonts/NotoSans-Regular.ttf';
@@ -166,7 +173,7 @@ abstract class Avatar implements IAvatar {
$im, $text, $font, (int)$fontSize
);
- imagettftext($im, $fontSize, 0, $x, $y, $white, $font, $text);
+ imagettftext($im, $fontSize, 0, $x, $y, $textColor, $font, $text);
ob_start();
imagepng($im);
diff --git a/lib/private/Avatar/UserAvatar.php b/lib/private/Avatar/UserAvatar.php
index f5a1d7e77b1..02fcfcb0fc8 100644
--- a/lib/private/Avatar/UserAvatar.php
+++ b/lib/private/Avatar/UserAvatar.php
@@ -208,7 +208,14 @@ class UserAvatar extends Avatar {
*
* @throws NotFoundException
*/
- private function getExtension(): string {
+ private function getExtension(bool $generated, bool $darkTheme): string {
+ if ($darkTheme && !$generated) {
+ if ($this->folder->fileExists('avatar-dark.jpg')) {
+ return 'jpg';
+ } elseif ($this->folder->fileExists('avatar-dark.png')) {
+ return 'png';
+ }
+ }
if ($this->folder->fileExists('avatar.jpg')) {
return 'jpg';
} elseif ($this->folder->fileExists('avatar.png')) {
@@ -228,25 +235,36 @@ class UserAvatar extends Avatar {
* @throws \OCP\Files\NotPermittedException
* @throws \OCP\PreConditionNotMetException
*/
- public function getFile(int $size): ISimpleFile {
+ public function getFile(int $size, bool $darkTheme = false): ISimpleFile {
+ $generated = $this->folder->fileExists('generated');
+
try {
- $ext = $this->getExtension();
+ $ext = $this->getExtension($generated, $darkTheme);
} catch (NotFoundException $e) {
- if (!$data = $this->generateAvatarFromSvg(1024)) {
- $data = $this->generateAvatar($this->getDisplayName(), 1024);
+ if (!$data = $this->generateAvatarFromSvg(1024, $darkTheme)) {
+ $data = $this->generateAvatar($this->getDisplayName(), 1024, $darkTheme);
}
- $avatar = $this->folder->newFile('avatar.png');
+ $avatar = $this->folder->newFile($darkTheme ? 'avatar-dark.png' : 'avatar.png');
$avatar->putContent($data);
$ext = 'png';
$this->folder->newFile('generated', '');
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', 'true');
+ $generated = true;
}
- if ($size === -1) {
- $path = 'avatar.' . $ext;
+ if ($generated) {
+ if ($size === -1) {
+ $path = 'avatar' . ($darkTheme ? '-dark' : '') . '.' . $ext;
+ } else {
+ $path = 'avatar' . ($darkTheme ? '-dark' : '') . '.' . $size . '.' . $ext;
+ }
} else {
- $path = 'avatar.' . $size . '.' . $ext;
+ if ($size === -1) {
+ $path = 'avatar.' . $ext;
+ } else {
+ $path = 'avatar.' . $size . '.' . $ext;
+ }
}
try {
@@ -255,11 +273,9 @@ class UserAvatar extends Avatar {
if ($size <= 0) {
throw new NotFoundException;
}
-
- // TODO: rework to integrate with the PlaceholderAvatar in a compatible way
- if ($this->folder->fileExists('generated')) {
- if (!$data = $this->generateAvatarFromSvg($size)) {
- $data = $this->generateAvatar($this->getDisplayName(), $size);
+ if ($generated) {
+ if (!$data = $this->generateAvatarFromSvg($size, $darkTheme)) {
+ $data = $this->generateAvatar($this->getDisplayName(), $size, $darkTheme);
}
} else {
$avatar = new \OCP\Image();
@@ -279,7 +295,7 @@ class UserAvatar extends Avatar {
}
if ($this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', null) === null) {
- $generated = $this->folder->fileExists('generated') ? 'true' : 'false';
+ $generated = $generated ? 'true' : 'false';
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', $generated);
}
diff --git a/lib/public/Color.php b/lib/public/Color.php
index e2cabd9c2fc..6c9a35ca49c 100644
--- a/lib/public/Color.php
+++ b/lib/public/Color.php
@@ -125,6 +125,14 @@ class Color {
return $palette;
}
+ public function alphaBlending(float $opacity, Color $source): Color {
+ return new Color(
+ (int)((1 - $opacity) * $source->red() + $opacity * $this->red()),
+ (int)((1 - $opacity) * $source->green() + $opacity * $this->green()),
+ (int)((1 - $opacity) * $source->blue() + $opacity * $this->blue())
+ );
+ }
+
/**
* Calculate steps between two Colors
* @param int $steps start color
diff --git a/lib/public/IAvatar.php b/lib/public/IAvatar.php
index d05a12e1dbf..f9fe9a645e6 100644
--- a/lib/public/IAvatar.php
+++ b/lib/public/IAvatar.php
@@ -39,10 +39,11 @@ interface IAvatar {
* Get the users avatar
*
* @param int $size size in px of the avatar, avatars are square, defaults to 64, -1 can be used to not scale the image
+ * @param bool $darkTheme Should the generated avatar be dark themed
* @return false|\OCP\IImage containing the avatar or false if there's no image
* @since 6.0.0 - size of -1 was added in 9.0.0
*/
- public function get(int $size = 64);
+ public function get(int $size = 64, bool $darkTheme = false);
/**
* Check if an avatar exists for the user
@@ -81,10 +82,11 @@ interface IAvatar {
* Get the file of the avatar
*
* @param int $size The desired image size. -1 can be used to not scale the image
+ * @param bool $darkTheme Should the generated avatar be dark themed
* @throws NotFoundException
* @since 9.0.0
*/
- public function getFile(int $size): ISimpleFile;
+ public function getFile(int $size, bool $darkTheme = false): ISimpleFile;
/**
* Get the avatar background color