[Option][GUI] Profile pic rounding

This commit is contained in:
Eric Kotato 2023-06-17 03:00:56 +03:00
parent b5f7c798ac
commit 97039e8a19
8 changed files with 98 additions and 35 deletions

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_peer.h" #include "data/data_peer.h"
#include "kotato/kotato_settings.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_chat_participant_status.h" #include "data/data_chat_participant_status.h"
@ -55,6 +56,17 @@ constexpr auto kUserpicSize = 160;
using UpdateFlag = Data::PeerUpdate::Flag; using UpdateFlag = Data::PeerUpdate::Flag;
float64 KotatoImageRoundRadiusMultiplier() {
const auto radius = ::Kotato::JsonSettings::GetInt("userpic_corner_radius");
if (radius < 0) {
return -1.0;
} else if (radius) {
return radius / 10;
}
return 0.0;
}
} // namespace } // namespace
namespace Data { namespace Data {
@ -158,6 +170,7 @@ void PeerClickHandler::onClick(ClickContext context) const {
PeerData::PeerData(not_null<Data::Session*> owner, PeerId id) PeerData::PeerData(not_null<Data::Session*> owner, PeerId id)
: id(id) : id(id)
, _owner(owner) { , _owner(owner) {
_radiusMultiplier = KotatoImageRoundRadiusMultiplier();
} }
Data::Session &PeerData::owner() const { Data::Session &PeerData::owner() const {
@ -304,7 +317,8 @@ void PeerData::paintUserpic(
cloud, cloud,
cloud ? nullptr : ensureEmptyUserpic().get(), cloud ? nullptr : ensureEmptyUserpic().get(),
size * ratio, size * ratio,
isForum()); isForum(),
_radiusMultiplier);
p.drawImage(QRect(x, y, size, size), view.cached); p.drawImage(QRect(x, y, size, size), view.cached);
} }
@ -317,7 +331,10 @@ bool PeerData::hasUserpic() const {
} }
Ui::PeerUserpicView PeerData::activeUserpicView() { Ui::PeerUserpicView PeerData::activeUserpicView() {
return { .cloud = _userpic.empty() ? nullptr : _userpic.activeView() }; return {
.cloud = _userpic.empty() ? nullptr : _userpic.activeView(),
.radiusMultiplier = _radiusMultiplier
};
} }
Ui::PeerUserpicView PeerData::createUserpicView() { Ui::PeerUserpicView PeerData::createUserpicView() {
@ -326,7 +343,7 @@ Ui::PeerUserpicView PeerData::createUserpicView() {
} }
auto result = _userpic.createView(); auto result = _userpic.createView();
_userpic.load(&session(), userpicPhotoOrigin()); _userpic.load(&session(), userpicPhotoOrigin());
return { .cloud = result }; return { .cloud = result, .radiusMultiplier = _radiusMultiplier };
} }
bool PeerData::useEmptyUserpic(Ui::PeerUserpicView &view) const { bool PeerData::useEmptyUserpic(Ui::PeerUserpicView &view) const {
@ -357,8 +374,10 @@ QImage PeerData::generateUserpicImage(
return image; return image;
} else if (radius) { } else if (radius) {
return round(*radius); return round(*radius);
} else if (isForum()) { } else if (_radiusMultiplier > 0.0) {
return round(size * Ui::ForumUserpicRadiusMultiplier()); return round(size * _radiusMultiplier);
} else if (_radiusMultiplier == 0.0) {
return image;
} else { } else {
return Images::Circle(std::move(image)); return Images::Circle(std::move(image));
} }
@ -373,14 +392,16 @@ QImage PeerData::generateUserpicImage(
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size); ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
} else if (radius) { } else if (radius) {
ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size, *radius); ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size, *radius);
} else if (isForum()) { } else if (_radiusMultiplier > 0.0) {
ensureEmptyUserpic()->paintRounded( ensureEmptyUserpic()->paintRounded(
p, p,
0, 0,
0, 0,
size, size,
size, size,
size * Ui::ForumUserpicRadiusMultiplier()); size * _radiusMultiplier);
} else if (_radiusMultiplier == 0.0) {
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
} else { } else {
ensureEmptyUserpic()->paintCircle(p, 0, 0, size, size); ensureEmptyUserpic()->paintCircle(p, 0, 0, size, size);
} }

View file

@ -463,6 +463,7 @@ private:
QString _themeEmoticon; QString _themeEmoticon;
std::unique_ptr<Data::WallPaper> _wallPaper; std::unique_ptr<Data::WallPaper> _wallPaper;
float64 _radiusMultiplier = -1.0;
}; };
namespace Data { namespace Data {

View file

@ -165,7 +165,8 @@ bool HiddenSenderInfo::paintCustomUserpic(
image.isNull() ? nullptr : &image, image.isNull() ? nullptr : &image,
image.isNull() ? &emptyUserpic : nullptr, image.isNull() ? &emptyUserpic : nullptr,
size * style::DevicePixelRatio(), size * style::DevicePixelRatio(),
false); false,
-1.0);
p.drawImage(QRect(x, y, size, size), view.cached); p.drawImage(QRect(x, y, size, size), view.cached);
return valid; return valid;
} }

View file

@ -336,6 +336,10 @@ const std::map<QString, Definition, std::greater<QString>> DefinitionMap {
.type = SettingType::IntSetting, .type = SettingType::IntSetting,
.defaultValue = 20, .defaultValue = 20,
.limitHandler = IntLimit(0, 200, 20), }}, .limitHandler = IntLimit(0, 200, 20), }},
{ "userpic_corner_radius", {
.type = SettingType::IntSetting,
.defaultValue = -1,
.limitHandler = IntLimit(-1, 10), }},
}; };
using OldOptionKey = QString; using OldOptionKey = QString;

View file

@ -324,14 +324,15 @@ void EmptyUserpic::PaintSavedMessages(
int x, int x,
int y, int y,
int outerWidth, int outerWidth,
int size) { int size,
int radius) {
auto bg = QLinearGradient(x, y, x, y + size); auto bg = QLinearGradient(x, y, x, y + size);
bg.setStops({ bg.setStops({
{ 0., st::historyPeerSavedMessagesBg->c }, { 0., st::historyPeerSavedMessagesBg->c },
{ 1., st::historyPeerSavedMessagesBg2->c } { 1., st::historyPeerSavedMessagesBg2->c }
}); });
const auto &fg = st::historyPeerUserpicFg; const auto &fg = st::historyPeerUserpicFg;
PaintSavedMessages(p, x, y, outerWidth, size, QBrush(bg), fg); PaintSavedMessages(p, x, y, outerWidth, size, QBrush(bg), fg, radius);
} }
void EmptyUserpic::PaintSavedMessages( void EmptyUserpic::PaintSavedMessages(
@ -341,20 +342,32 @@ void EmptyUserpic::PaintSavedMessages(
int outerWidth, int outerWidth,
int size, int size,
QBrush bg, QBrush bg,
const style::color &fg) { const style::color &fg,
int radius) {
x = style::RightToLeft() ? (outerWidth - x - size) : x; x = style::RightToLeft() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.setBrush(std::move(bg)); p.setBrush(std::move(bg));
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.drawEllipse(x, y, size, size); switch (radius) {
case -1:
p.drawEllipse(x, y, size, size);
break;
case 0:
p.fillRect(x, y, size, size, p.brush());
break;
default:
p.drawRoundedRect(x, y, size, size, radius, radius);
}
PaintSavedMessagesInner(p, x, y, size, fg); PaintSavedMessagesInner(p, x, y, size, fg);
} }
QImage EmptyUserpic::GenerateSavedMessages(int size) { QImage EmptyUserpic::GenerateSavedMessages(int size, int radius) {
return Generate(size, [&](QPainter &p) { return Generate(size, [&](QPainter &p) {
PaintSavedMessages(p, 0, 0, size, size); PaintSavedMessages(p, 0, 0, size, size, radius);
}); });
} }
@ -363,14 +376,15 @@ void EmptyUserpic::PaintRepliesMessages(
int x, int x,
int y, int y,
int outerWidth, int outerWidth,
int size) { int size,
int radius) {
auto bg = QLinearGradient(x, y, x, y + size); auto bg = QLinearGradient(x, y, x, y + size);
bg.setStops({ bg.setStops({
{ 0., st::historyPeerSavedMessagesBg->c }, { 0., st::historyPeerSavedMessagesBg->c },
{ 1., st::historyPeerSavedMessagesBg2->c } { 1., st::historyPeerSavedMessagesBg2->c }
}); });
const auto &fg = st::historyPeerUserpicFg; const auto &fg = st::historyPeerUserpicFg;
PaintRepliesMessages(p, x, y, outerWidth, size, QBrush(bg), fg); PaintRepliesMessages(p, x, y, outerWidth, size, QBrush(bg), fg, radius);
} }
void EmptyUserpic::PaintRepliesMessages( void EmptyUserpic::PaintRepliesMessages(
@ -380,20 +394,32 @@ void EmptyUserpic::PaintRepliesMessages(
int outerWidth, int outerWidth,
int size, int size,
QBrush bg, QBrush bg,
const style::color &fg) { const style::color &fg,
int radius) {
x = style::RightToLeft() ? (outerWidth - x - size) : x; x = style::RightToLeft() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.setBrush(bg); p.setBrush(bg);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.drawEllipse(x, y, size, size); switch (radius) {
case -1:
p.drawEllipse(x, y, size, size);
break;
case 0:
p.fillRect(x, y, size, size, p.brush());
break;
default:
p.drawRoundedRect(x, y, size, size, radius, radius);
}
PaintRepliesMessagesInner(p, x, y, size, fg); PaintRepliesMessagesInner(p, x, y, size, fg);
} }
QImage EmptyUserpic::GenerateRepliesMessages(int size) { QImage EmptyUserpic::GenerateRepliesMessages(int size, int radius) {
return Generate(size, [&](QPainter &p) { return Generate(size, [&](QPainter &p) {
PaintRepliesMessages(p, 0, 0, size, size); PaintRepliesMessages(p, 0, 0, size, size, radius);
}); });
} }

View file

@ -53,7 +53,8 @@ public:
int x, int x,
int y, int y,
int outerWidth, int outerWidth,
int size); int size,
int radius = -1);
static void PaintSavedMessages( static void PaintSavedMessages(
QPainter &p, QPainter &p,
int x, int x,
@ -61,15 +62,17 @@ public:
int outerWidth, int outerWidth,
int size, int size,
QBrush bg, QBrush bg,
const style::color &fg); const style::color &fg,
[[nodiscard]] static QImage GenerateSavedMessages(int size); int radius = -1);
[[nodiscard]] static QImage GenerateSavedMessages(int size, int radius = -1);
static void PaintRepliesMessages( static void PaintRepliesMessages(
QPainter &p, QPainter &p,
int x, int x,
int y, int y,
int outerWidth, int outerWidth,
int size); int size,
int radius = -1);
static void PaintRepliesMessages( static void PaintRepliesMessages(
QPainter &p, QPainter &p,
int x, int x,
@ -77,8 +80,9 @@ public:
int outerWidth, int outerWidth,
int size, int size,
QBrush bg, QBrush bg,
const style::color &fg); const style::color &fg,
[[nodiscard]] static QImage GenerateRepliesMessages(int size); int radius = -1);
[[nodiscard]] static QImage GenerateRepliesMessages(int size, int radius = -1);
~EmptyUserpic(); ~EmptyUserpic();

View file

@ -25,7 +25,8 @@ void ValidateUserpicCache(
const QImage *cloud, const QImage *cloud,
const EmptyUserpic *empty, const EmptyUserpic *empty,
int size, int size,
bool forum) { bool forum,
float64 radiusMultiplier) {
Expects(cloud != nullptr || empty != nullptr); Expects(cloud != nullptr || empty != nullptr);
const auto full = QSize(size, size); const auto full = QSize(size, size);
@ -41,6 +42,7 @@ void ValidateUserpicCache(
} }
view.empty = empty; view.empty = empty;
view.forum = forumValue; view.forum = forumValue;
view.radiusMultiplier = radiusMultiplier;
view.paletteVersion = version; view.paletteVersion = version;
if (cloud) { if (cloud) {
@ -48,14 +50,14 @@ void ValidateUserpicCache(
full, full,
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation); Qt::SmoothTransformation);
if (forum) { if (view.radiusMultiplier < 0.0) {
view.cached = Images::Circle(std::move(view.cached));
} else if (view.radiusMultiplier > 0.0) {
view.cached = Images::Round( view.cached = Images::Round(
std::move(view.cached), std::move(view.cached),
Images::CornersMask(size Images::CornersMask(size
* Ui::ForumUserpicRadiusMultiplier() * view.radiusMultiplier
/ style::DevicePixelRatio())); / style::DevicePixelRatio()));
} else {
view.cached = Images::Circle(std::move(view.cached));
} }
} else { } else {
if (view.cached.size() != full) { if (view.cached.size() != full) {
@ -64,16 +66,18 @@ void ValidateUserpicCache(
view.cached.fill(Qt::transparent); view.cached.fill(Qt::transparent);
auto p = QPainter(&view.cached); auto p = QPainter(&view.cached);
if (forum) { if (view.radiusMultiplier < 0.0) {
empty->paintCircle(p, 0, 0, size, size);
} else if (view.radiusMultiplier > 0.0) {
empty->paintRounded( empty->paintRounded(
p, p,
0, 0,
0, 0,
size, size,
size, size,
size * Ui::ForumUserpicRadiusMultiplier()); size * view.radiusMultiplier);
} else { } else {
empty->paintCircle(p, 0, 0, size, size); empty->paintSquare(p, 0, 0, size, size);
} }
} }
} }

View file

@ -27,6 +27,7 @@ struct PeerUserpicView {
base::weak_ptr<const EmptyUserpic> empty; base::weak_ptr<const EmptyUserpic> empty;
int paletteVersion : 31 = 0; int paletteVersion : 31 = 0;
int forum : 1 = 0; int forum : 1 = 0;
float64 radiusMultiplier = -1.0;
}; };
[[nodiscard]] bool PeerUserpicLoading(const PeerUserpicView &view); [[nodiscard]] bool PeerUserpicLoading(const PeerUserpicView &view);
@ -36,6 +37,7 @@ void ValidateUserpicCache(
const QImage *cloud, const QImage *cloud,
const EmptyUserpic *empty, const EmptyUserpic *empty,
int size, int size,
bool forum); bool forum,
float64 radiusMultiplier);
} // namespace Ui } // namespace Ui