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

View file

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

View file

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

View file

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

View file

@ -324,14 +324,15 @@ void EmptyUserpic::PaintSavedMessages(
int x,
int y,
int outerWidth,
int size) {
int size,
int radius) {
auto bg = QLinearGradient(x, y, x, y + size);
bg.setStops({
{ 0., st::historyPeerSavedMessagesBg->c },
{ 1., st::historyPeerSavedMessagesBg2->c }
});
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(
@ -341,20 +342,32 @@ void EmptyUserpic::PaintSavedMessages(
int outerWidth,
int size,
QBrush bg,
const style::color &fg) {
const style::color &fg,
int radius) {
x = style::RightToLeft() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p);
p.setBrush(std::move(bg));
p.setPen(Qt::NoPen);
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);
}
QImage EmptyUserpic::GenerateSavedMessages(int size) {
QImage EmptyUserpic::GenerateSavedMessages(int size, int radius) {
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 y,
int outerWidth,
int size) {
int size,
int radius) {
auto bg = QLinearGradient(x, y, x, y + size);
bg.setStops({
{ 0., st::historyPeerSavedMessagesBg->c },
{ 1., st::historyPeerSavedMessagesBg2->c }
});
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(
@ -380,20 +394,32 @@ void EmptyUserpic::PaintRepliesMessages(
int outerWidth,
int size,
QBrush bg,
const style::color &fg) {
const style::color &fg,
int radius) {
x = style::RightToLeft() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p);
p.setBrush(bg);
p.setPen(Qt::NoPen);
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);
}
QImage EmptyUserpic::GenerateRepliesMessages(int size) {
QImage EmptyUserpic::GenerateRepliesMessages(int size, int radius) {
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 y,
int outerWidth,
int size);
int size,
int radius = -1);
static void PaintSavedMessages(
QPainter &p,
int x,
@ -61,15 +62,17 @@ public:
int outerWidth,
int size,
QBrush bg,
const style::color &fg);
[[nodiscard]] static QImage GenerateSavedMessages(int size);
const style::color &fg,
int radius = -1);
[[nodiscard]] static QImage GenerateSavedMessages(int size, int radius = -1);
static void PaintRepliesMessages(
QPainter &p,
int x,
int y,
int outerWidth,
int size);
int size,
int radius = -1);
static void PaintRepliesMessages(
QPainter &p,
int x,
@ -77,8 +80,9 @@ public:
int outerWidth,
int size,
QBrush bg,
const style::color &fg);
[[nodiscard]] static QImage GenerateRepliesMessages(int size);
const style::color &fg,
int radius = -1);
[[nodiscard]] static QImage GenerateRepliesMessages(int size, int radius = -1);
~EmptyUserpic();

View file

@ -25,7 +25,8 @@ void ValidateUserpicCache(
const QImage *cloud,
const EmptyUserpic *empty,
int size,
bool forum) {
bool forum,
float64 radiusMultiplier) {
Expects(cloud != nullptr || empty != nullptr);
const auto full = QSize(size, size);
@ -41,6 +42,7 @@ void ValidateUserpicCache(
}
view.empty = empty;
view.forum = forumValue;
view.radiusMultiplier = radiusMultiplier;
view.paletteVersion = version;
if (cloud) {
@ -48,14 +50,14 @@ void ValidateUserpicCache(
full,
Qt::IgnoreAspectRatio,
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(
std::move(view.cached),
Images::CornersMask(size
* Ui::ForumUserpicRadiusMultiplier()
* view.radiusMultiplier
/ style::DevicePixelRatio()));
} else {
view.cached = Images::Circle(std::move(view.cached));
}
} else {
if (view.cached.size() != full) {
@ -64,16 +66,18 @@ void ValidateUserpicCache(
view.cached.fill(Qt::transparent);
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(
p,
0,
0,
size,
size,
size * Ui::ForumUserpicRadiusMultiplier());
size * view.radiusMultiplier);
} 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;
int paletteVersion : 31 = 0;
int forum : 1 = 0;
float64 radiusMultiplier = -1.0;
};
[[nodiscard]] bool PeerUserpicLoading(const PeerUserpicView &view);
@ -36,6 +37,7 @@ void ValidateUserpicCache(
const QImage *cloud,
const EmptyUserpic *empty,
int size,
bool forum);
bool forum,
float64 radiusMultiplier);
} // namespace Ui