[Option][GUI] Profile pic rounding
This commit is contained in:
parent
b5f7c798ac
commit
97039e8a19
8 changed files with 98 additions and 35 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue