mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-27 07:52:57 +02:00
Support nice monoforum userpics.
This commit is contained in:
parent
dfb6600104
commit
d775760f98
19 changed files with 221 additions and 109 deletions
|
@ -559,7 +559,7 @@ void GroupInfoBox::prepare() {
|
|||
&_navigation->parentController()->window(),
|
||||
Ui::UserpicButton::Role::ChoosePhoto,
|
||||
st::defaultUserpicButton,
|
||||
(_type == Type::Forum));
|
||||
(_type == Type::Forum) ? Ui::PeerUserpicShape::Forum : Ui::PeerUserpicShape::Auto);
|
||||
_photo->showCustomOnChosen();
|
||||
_title.create(
|
||||
this,
|
||||
|
|
|
@ -604,7 +604,7 @@ void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
|||
container,
|
||||
userpicPeer,
|
||||
st::mainMenuUserpic,
|
||||
peer->userpicForceForumShape());
|
||||
peer->userpicShape());
|
||||
userpic->showSavedMessagesOnSelf(true);
|
||||
Ui::IconWithTitle(
|
||||
container,
|
||||
|
|
|
@ -427,20 +427,30 @@ QImage *PeerData::userpicCloudImage(Ui::PeerUserpicView &view) const {
|
|||
void PeerData::paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
const PaintUserpicContext &context) const {
|
||||
PaintUserpicContext context) const {
|
||||
if (const auto broadcast = monoforumBroadcast()) {
|
||||
if (context.shape == Ui::PeerUserpicShape::Auto) {
|
||||
context.shape = Ui::PeerUserpicShape::Monoforum;
|
||||
}
|
||||
broadcast->paintUserpic(p, view, context);
|
||||
return;
|
||||
}
|
||||
const auto size = context.size;
|
||||
const auto cloud = userpicCloudImage(view);
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
if (context.shape == Ui::PeerUserpicShape::Auto) {
|
||||
context.shape = isForum()
|
||||
? Ui::PeerUserpicShape::Forum
|
||||
: isMonoforum()
|
||||
? Ui::PeerUserpicShape::Monoforum
|
||||
: Ui::PeerUserpicShape::Circle;
|
||||
}
|
||||
Ui::ValidateUserpicCache(
|
||||
view,
|
||||
cloud,
|
||||
cloud ? nullptr : ensureEmptyUserpic().get(),
|
||||
size * ratio,
|
||||
context.forumLayout);
|
||||
context.shape);
|
||||
p.drawImage(QRect(context.position, QSize(size, size)), view.cached);
|
||||
}
|
||||
|
||||
|
@ -1176,8 +1186,12 @@ not_null<const PeerData*> PeerData::userpicPaintingPeer() const {
|
|||
return const_cast<PeerData*>(this)->userpicPaintingPeer();
|
||||
}
|
||||
|
||||
bool PeerData::userpicForceForumShape() const {
|
||||
return monoforumBroadcast() != nullptr;
|
||||
Ui::PeerUserpicShape PeerData::userpicShape() const {
|
||||
return isForum()
|
||||
? Ui::PeerUserpicShape::Forum
|
||||
: isMonoforum()
|
||||
? Ui::PeerUserpicShape::Monoforum
|
||||
: Ui::PeerUserpicShape::Circle;
|
||||
}
|
||||
|
||||
ChannelData *PeerData::monoforumBroadcast() const {
|
||||
|
|
|
@ -186,6 +186,12 @@ struct PeerBarDetails {
|
|||
int paysPerMessage = 0;
|
||||
};
|
||||
|
||||
struct PaintUserpicContext {
|
||||
QPoint position;
|
||||
int size = 0;
|
||||
Ui::PeerUserpicShape shape = Ui::PeerUserpicShape::Auto;
|
||||
};
|
||||
|
||||
class PeerData {
|
||||
protected:
|
||||
PeerData(not_null<Data::Session*> owner, PeerId id);
|
||||
|
@ -310,7 +316,7 @@ public:
|
|||
[[nodiscard]] not_null<const PeerData*> migrateToOrMe() const;
|
||||
[[nodiscard]] not_null<PeerData*> userpicPaintingPeer();
|
||||
[[nodiscard]] not_null<const PeerData*> userpicPaintingPeer() const;
|
||||
[[nodiscard]] bool userpicForceForumShape() const;
|
||||
[[nodiscard]] Ui::PeerUserpicShape userpicShape() const;
|
||||
|
||||
// isMonoforum() ? monoforumLink() : nullptr
|
||||
[[nodiscard]] ChannelData *monoforumBroadcast() const;
|
||||
|
@ -348,15 +354,10 @@ public:
|
|||
bool hasVideo);
|
||||
void setUserpicPhoto(const MTPPhoto &data);
|
||||
|
||||
struct PaintUserpicContext {
|
||||
QPoint position;
|
||||
int size = 0;
|
||||
bool forumLayout = false;
|
||||
};
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
const PaintUserpicContext &context) const;
|
||||
PaintUserpicContext context) const;
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
|
@ -367,7 +368,9 @@ public:
|
|||
paintUserpic(p, view, {
|
||||
.position = { x, y },
|
||||
.size = size,
|
||||
.forumLayout = !forceCircle && (isForum() || isMonoforum()),
|
||||
.shape = (forceCircle
|
||||
? Ui::PeerUserpicShape::Circle
|
||||
: Ui::PeerUserpicShape::Auto),
|
||||
});
|
||||
}
|
||||
void paintUserpicLeft(
|
||||
|
|
|
@ -196,7 +196,7 @@ bool HiddenSenderInfo::paintCustomUserpic(
|
|||
image.isNull() ? nullptr : &image,
|
||||
image.isNull() ? &emptyUserpic : nullptr,
|
||||
size * style::DevicePixelRatio(),
|
||||
false);
|
||||
Ui::PeerUserpicShape::Circle);
|
||||
p.drawImage(QRect(x, y, size, size), view.cached);
|
||||
return valid;
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ void Item::setupTop() {
|
|||
_top.get(),
|
||||
_thread->peer()->userpicPaintingPeer(),
|
||||
st::previewUserpic,
|
||||
_thread->peer()->userpicForceForumShape());
|
||||
_thread->peer()->userpicShape());
|
||||
if (userpic) {
|
||||
userpic->showSavedMessagesOnSelf(true);
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
|
|
@ -936,7 +936,7 @@ void TopBarWidget::refreshInfoButton() {
|
|||
Ui::UserpicButton::Role::Custom,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
st::topBarInfoButton,
|
||||
infoPeer->userpicForceForumShape());
|
||||
infoPeer->userpicShape());
|
||||
info->showSavedMessagesOnSelf(true);
|
||||
_info.destroy();
|
||||
_info = std::move(info);
|
||||
|
|
|
@ -632,7 +632,7 @@ Cover::Cover(
|
|||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
_st.photo,
|
||||
_peer->userpicForceForumShape()))
|
||||
_peer->userpicShape()))
|
||||
, _changePersonal((role == Role::Info
|
||||
|| topic
|
||||
|| !_peer->isUser()
|
||||
|
|
|
@ -39,11 +39,10 @@ QByteArray SessionSettings::serialize() const {
|
|||
+ Serialize::bytearraySize(autoDownload)
|
||||
+ sizeof(qint32) * 11
|
||||
+ (_mutePeriods.size() * sizeof(quint64))
|
||||
+ sizeof(qint32) * 2
|
||||
+ _hiddenPinnedMessages.size() * (sizeof(quint64) * 4)
|
||||
+ sizeof(qint32)
|
||||
+ sizeof(qint32) * 3
|
||||
+ _groupEmojiSectionHidden.size() * sizeof(quint64)
|
||||
+ sizeof(qint32) * 2;
|
||||
+ sizeof(qint32) * 3
|
||||
+ _hiddenPinnedMessages.size() * (sizeof(quint64) * 4);
|
||||
|
||||
auto result = QByteArray();
|
||||
result.reserve(size);
|
||||
|
|
|
@ -119,7 +119,7 @@ void InfoBox(
|
|||
data.bot,
|
||||
st::websiteBigUserpic)),
|
||||
st::sessionBigCoverPadding)->entity();
|
||||
userpic->forceForumShape(true);
|
||||
userpic->overrideShape(Ui::PeerUserpicShape::Forum);
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
const auto nameWrap = box->addRow(
|
||||
|
@ -224,25 +224,11 @@ PaintRoundImageCallback Row::generatePaintUserpicCallback(bool forceRound) {
|
|||
const auto peer = _data.bot;
|
||||
auto userpic = _userpic = peer->createUserpicView();
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
if (const auto cloud = peer->userpicCloudImage(userpic)) {
|
||||
Ui::ValidateUserpicCache(
|
||||
userpic,
|
||||
cloud,
|
||||
nullptr,
|
||||
size * ratio,
|
||||
true);
|
||||
p.drawImage(QRect(x, y, size, size), userpic.cached);
|
||||
} else {
|
||||
if (_emptyUserpic.isNull()) {
|
||||
_emptyUserpic = PeerData::GenerateUserpicImage(
|
||||
peer,
|
||||
_userpic,
|
||||
size * ratio,
|
||||
size * ratio * Ui::ForumUserpicRadiusMultiplier());
|
||||
}
|
||||
p.drawImage(QRect(x, y, size, size), _emptyUserpic);
|
||||
}
|
||||
peer->paintUserpic(p, _userpic, {
|
||||
.position = QPoint(x, y),
|
||||
.size = size,
|
||||
.shape = Ui::PeerUserpicShape::Forum,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ void VerticalButton::paintEvent(QPaintEvent *e) {
|
|||
.availableWidth = _st.nameWidth,
|
||||
.align = style::al_top,
|
||||
.paused = _delegate->buttonPaused(),
|
||||
.elisionLines = kMaxNameLines,
|
||||
});
|
||||
|
||||
const auto &state = _data.badges;
|
||||
|
|
|
@ -160,12 +160,12 @@ UserpicButton::UserpicButton(
|
|||
not_null<Window::Controller*> window,
|
||||
Role role,
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape)
|
||||
PeerUserpicShape shape)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(window->sessionController())
|
||||
, _window(window)
|
||||
, _forceForumShape(forceForumShape)
|
||||
, _shape(shape)
|
||||
, _role(role) {
|
||||
Expects(_role == Role::ChangePhoto || _role == Role::ChoosePhoto);
|
||||
|
||||
|
@ -181,13 +181,13 @@ UserpicButton::UserpicButton(
|
|||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape)
|
||||
PeerUserpicShape shape)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(controller)
|
||||
, _window(&controller->window())
|
||||
, _peer(peer)
|
||||
, _forceForumShape(forceForumShape)
|
||||
, _shape(shape)
|
||||
, _role(role)
|
||||
, _source(source) {
|
||||
if (_source == Source::Custom) {
|
||||
|
@ -203,11 +203,11 @@ UserpicButton::UserpicButton(
|
|||
QWidget *parent,
|
||||
not_null<PeerData*> peer,
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape)
|
||||
PeerUserpicShape shape)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _peer(peer)
|
||||
, _forceForumShape(forceForumShape)
|
||||
, _shape(shape)
|
||||
, _role(Role::Custom)
|
||||
, _source(Source::PeerPhoto) {
|
||||
Expects(_role != Role::OpenPhoto);
|
||||
|
@ -407,7 +407,7 @@ void UserpicButton::choosePhotoLocally() {
|
|||
CameraBox,
|
||||
_window,
|
||||
_peer,
|
||||
_forceForumShape,
|
||||
(_shape == PeerUserpicShape::Forum),
|
||||
callback(ChosenType::Set)));
|
||||
}, &st::menuIconPhotoSet);
|
||||
}
|
||||
|
@ -648,7 +648,8 @@ void UserpicButton::paintUserpicFrame(Painter &p, QPoint photoPosition) {
|
|||
auto size = QSize{ _st.photoSize, _st.photoSize };
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
request.outer = request.resize = size * ratio;
|
||||
if (useForumShape()) {
|
||||
if (_shape == PeerUserpicShape::Monoforum) {
|
||||
} else if (useForumShape()) {
|
||||
const auto radius = int(_st.photoSize
|
||||
* Ui::ForumUserpicRadiusMultiplier());
|
||||
if (_roundingCorners[0].width() != radius * ratio) {
|
||||
|
@ -661,7 +662,24 @@ void UserpicButton::paintUserpicFrame(Painter &p, QPoint photoPosition) {
|
|||
}
|
||||
request.mask = _ellipseMask;
|
||||
}
|
||||
p.drawImage(QRect(photoPosition, size), _streamed->frame(request));
|
||||
auto frame = _streamed->frame(request);
|
||||
|
||||
if (_shape == PeerUserpicShape::Monoforum) {
|
||||
if (_monoforumMask.isNull()) {
|
||||
_monoforumMask = MonoforumShapeMask(request.resize);
|
||||
}
|
||||
constexpr auto format = QImage::Format_ARGB32_Premultiplied;
|
||||
if (frame.format() != format) {
|
||||
frame = std::move(frame).convertToFormat(format);
|
||||
}
|
||||
auto q = QPainter(&frame);
|
||||
q.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
q.drawImage(
|
||||
QRect(QPoint(), frame.size() / frame.devicePixelRatio()),
|
||||
_monoforumMask);
|
||||
q.end();
|
||||
}
|
||||
p.drawImage(QRect(photoPosition, size), frame);
|
||||
if (!paused) {
|
||||
_streamed->markFrameShown();
|
||||
}
|
||||
|
@ -892,9 +910,8 @@ void UserpicButton::processNewPeerPhoto() {
|
|||
}
|
||||
|
||||
bool UserpicButton::useForumShape() const {
|
||||
return _forceForumShape
|
||||
|| (_peer && _peer->isForum())
|
||||
|| (_peer && _peer->isMonoforum());
|
||||
return (_shape == PeerUserpicShape::Forum)
|
||||
|| (_peer && _peer->isForum() && _shape == PeerUserpicShape::Auto);
|
||||
}
|
||||
|
||||
void UserpicButton::grabOldUserpic() {
|
||||
|
@ -946,8 +963,8 @@ void UserpicButton::switchChangePhotoOverlay(
|
|||
}
|
||||
}
|
||||
|
||||
void UserpicButton::forceForumShape(bool force) {
|
||||
_forceForumShape = force;
|
||||
void UserpicButton::overrideShape(PeerUserpicShape shape) {
|
||||
_shape = shape;
|
||||
prepare();
|
||||
}
|
||||
|
||||
|
@ -1083,28 +1100,11 @@ void UserpicButton::prepareUserpicPixmap() {
|
|||
_userpic = CreateSquarePixmap(size, [&](Painter &p) {
|
||||
if (_userpicHasImage) {
|
||||
if (_showPeerUserpic) {
|
||||
if (useForumShape()) {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
if (const auto cloud = _peer->userpicCloudImage(_userpicView)) {
|
||||
Ui::ValidateUserpicCache(
|
||||
_userpicView,
|
||||
cloud,
|
||||
nullptr,
|
||||
size * ratio,
|
||||
true);
|
||||
p.drawImage(QRect(0, 0, size, size), _userpicView.cached);
|
||||
} else {
|
||||
const auto empty = PeerData::GenerateUserpicImage(
|
||||
_peer,
|
||||
_userpicView,
|
||||
size * ratio,
|
||||
(size * ratio)
|
||||
* Ui::ForumUserpicRadiusMultiplier());
|
||||
p.drawImage(QRect(0, 0, size, size), empty);
|
||||
}
|
||||
} else {
|
||||
_peer->paintUserpic(p, _userpicView, 0, 0, size);
|
||||
}
|
||||
_peer->paintUserpic(p, _userpicView, {
|
||||
.position = QPoint(),
|
||||
.size = size,
|
||||
.shape = _shape,
|
||||
});
|
||||
} else if (_nonPersonalView) {
|
||||
using Size = Data::PhotoSize;
|
||||
if (const auto full = _nonPersonalView->image(Size::Large)) {
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
not_null<::Window::Controller*> window,
|
||||
Role role,
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape = false);
|
||||
PeerUserpicShape shape = PeerUserpicShape::Auto);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<::Window::SessionController*> controller,
|
||||
|
@ -70,12 +70,12 @@ public:
|
|||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape = false);
|
||||
PeerUserpicShape shape = PeerUserpicShape::Auto);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer, // Role::Custom, Source::PeerPhoto
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape = false);
|
||||
PeerUserpicShape shape = PeerUserpicShape::Auto);
|
||||
~UserpicButton();
|
||||
|
||||
enum class ChosenType {
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
bool enabled,
|
||||
Fn<void(ChosenImage)> chosen);
|
||||
void showSavedMessagesOnSelf(bool enabled);
|
||||
void forceForumShape(bool force);
|
||||
void overrideShape(PeerUserpicShape shape);
|
||||
|
||||
// Role::ChoosePhoto or Role::ChangePhoto
|
||||
[[nodiscard]] rpl::producer<ChosenImage> chosenImages() const {
|
||||
|
@ -163,8 +163,9 @@ private:
|
|||
::Window::SessionController *_controller = nullptr;
|
||||
::Window::Controller *_window = nullptr;
|
||||
PeerData *_peer = nullptr;
|
||||
bool _forceForumShape = false;
|
||||
PeerUserpicShape _shape = PeerUserpicShape::Auto;
|
||||
PeerUserpicView _userpicView;
|
||||
QImage _monoforumMask;
|
||||
std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
|
||||
Role _role = Role::ChangePhoto;
|
||||
bool _notShownYet = true;
|
||||
|
|
|
@ -250,22 +250,13 @@ QImage PeerUserpic::image(int size) {
|
|||
|
||||
auto p = Painter(&_frame);
|
||||
auto &view = _subscribed->view;
|
||||
if (!_forceRound) {
|
||||
_peer->paintUserpic(p, view, 0, 0, size);
|
||||
} else if (const auto cloud = _peer->userpicCloudImage(view)) {
|
||||
const auto full = size * style::DevicePixelRatio();
|
||||
Ui::ValidateUserpicCache(view, cloud, nullptr, full, false);
|
||||
p.drawImage(QRect(0, 0, size, size), view.cached);
|
||||
} else {
|
||||
const auto full = size * style::DevicePixelRatio();
|
||||
const auto r = full / 2.;
|
||||
const auto empty = PeerData::GenerateUserpicImage(
|
||||
_peer,
|
||||
view,
|
||||
full,
|
||||
r);
|
||||
p.drawImage(QRect(0, 0, size, size), empty);
|
||||
}
|
||||
_peer->paintUserpic(p, view, {
|
||||
.position = QPoint(),
|
||||
.size = size,
|
||||
.shape = (_forceRound
|
||||
? Ui::PeerUserpicShape::Circle
|
||||
: Ui::PeerUserpicShape::Auto),
|
||||
});
|
||||
}
|
||||
return _frame;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "styles/style_widgets.h" // style::IconButton
|
||||
#include "styles/style_info.h" // st::topBarCall
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
|
||||
namespace Ui {
|
||||
|
@ -366,6 +367,17 @@ void EmptyUserpic::paintSquare(
|
|||
});
|
||||
}
|
||||
|
||||
void EmptyUserpic::paintMonoforum(
|
||||
QPainter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
int size) const {
|
||||
paint(p, x, y, outerWidth, size, [&] {
|
||||
PaintMonoforumShape(p, QRect(x, y, size, size));
|
||||
});
|
||||
}
|
||||
|
||||
void EmptyUserpic::PaintSavedMessages(
|
||||
QPainter &p,
|
||||
int x,
|
||||
|
@ -649,4 +661,86 @@ void EmptyUserpic::fillString(const QString &name) {
|
|||
|
||||
EmptyUserpic::~EmptyUserpic() = default;
|
||||
|
||||
void PaintMonoforumShape(QPainter &p, QRect rect) {
|
||||
p.drawEllipse(rect);
|
||||
|
||||
auto path = QPainterPath();
|
||||
path.moveTo(
|
||||
rect.x() + rect.width() * 0.5,
|
||||
rect.y() + rect.height() * 0.5);
|
||||
path.arcTo(
|
||||
QRectF(
|
||||
rect.x() - rect.width() * 0.5,
|
||||
rect.y(),
|
||||
rect.width(),
|
||||
rect.height()),
|
||||
0,
|
||||
-90);
|
||||
path.arcTo(
|
||||
QRectF(
|
||||
rect.x() - rect.width() * 0.25,
|
||||
rect.y() - rect.height() * 2,
|
||||
rect.width() * 0.5,
|
||||
rect.height() * 3),
|
||||
-90,
|
||||
45);
|
||||
path.lineTo(
|
||||
rect.x() + rect.width() * 0.5,
|
||||
rect.y() + rect.height() * 0.5);
|
||||
p.drawPath(path);
|
||||
}
|
||||
|
||||
QImage MonoforumShapeMask(QSize size) {
|
||||
auto result = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
||||
result.fill(Qt::transparent);
|
||||
|
||||
QPainter p(&result);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setBrush(Qt::white);
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
PaintMonoforumShape(p, QRect(QPoint(), size));
|
||||
|
||||
p.end();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const QImage &MonoforumShapeMaskCached(QSize size) {
|
||||
const auto key = (uint64(uint32(size.width())) << 32)
|
||||
| uint64(uint32(size.height()));
|
||||
|
||||
static auto Masks = base::flat_map<uint64, QImage>();
|
||||
static auto Mutex = QMutex();
|
||||
auto lock = QMutexLocker(&Mutex);
|
||||
const auto i = Masks.find(key);
|
||||
if (i != end(Masks)) {
|
||||
return i->second;
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
auto mask = MonoforumShapeMask(size);
|
||||
|
||||
lock.relock();
|
||||
return Masks.emplace(key, std::move(mask)).first->second;
|
||||
}
|
||||
|
||||
QImage ApplyMonoforumShape(QImage image) {
|
||||
const auto size = image.size();
|
||||
auto mask = MonoforumShapeMaskCached(size);
|
||||
|
||||
constexpr auto format = QImage::Format_ARGB32_Premultiplied;
|
||||
if (image.format() != format) {
|
||||
image = std::move(image).convertToFormat(format);
|
||||
}
|
||||
auto p = QPainter(&image);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.drawImage(
|
||||
QRect(QPoint(), image.size() / image.devicePixelRatio()),
|
||||
mask);
|
||||
p.end();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -46,6 +46,12 @@ public:
|
|||
int y,
|
||||
int outerWidth,
|
||||
int size) const;
|
||||
void paintMonoforum(
|
||||
QPainter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
int size) const;
|
||||
[[nodiscard]] QPixmap generate(int size);
|
||||
[[nodiscard]] std::pair<uint64, uint64> uniqueKey() const;
|
||||
|
||||
|
@ -147,4 +153,9 @@ private:
|
|||
|
||||
};
|
||||
|
||||
void PaintMonoforumShape(QPainter &p, QRect rect);
|
||||
[[nodiscard]] QImage MonoforumShapeMask(QSize size);
|
||||
[[nodiscard]] const QImage &MonoforumShapeMaskCached(QSize size);
|
||||
[[nodiscard]] QImage ApplyMonoforumShape(QImage image);
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/userpic_view.h"
|
||||
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -25,14 +26,14 @@ void ValidateUserpicCache(
|
|||
const QImage *cloud,
|
||||
const EmptyUserpic *empty,
|
||||
int size,
|
||||
bool forum) {
|
||||
PeerUserpicShape shape) {
|
||||
Expects(cloud != nullptr || empty != nullptr);
|
||||
|
||||
const auto full = QSize(size, size);
|
||||
const auto version = style::PaletteVersion();
|
||||
const auto forumValue = forum ? 1 : 0;
|
||||
const auto shapeValue = static_cast<uint32>(shape) & 3;
|
||||
const auto regenerate = (view.cached.size() != QSize(size, size))
|
||||
|| (view.forum != forumValue)
|
||||
|| (view.shape != shapeValue)
|
||||
|| (cloud && !view.empty.null())
|
||||
|| (empty && empty != view.empty.get())
|
||||
|| (empty && view.paletteVersion != version);
|
||||
|
@ -40,7 +41,7 @@ void ValidateUserpicCache(
|
|||
return;
|
||||
}
|
||||
view.empty = empty;
|
||||
view.forum = forumValue;
|
||||
view.shape = shapeValue;
|
||||
view.paletteVersion = version;
|
||||
|
||||
if (cloud) {
|
||||
|
@ -48,7 +49,9 @@ void ValidateUserpicCache(
|
|||
full,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
if (forum) {
|
||||
if (shape == PeerUserpicShape::Monoforum) {
|
||||
view.cached = Ui::ApplyMonoforumShape(std::move(view.cached));
|
||||
} else if (shape == PeerUserpicShape::Forum) {
|
||||
view.cached = Images::Round(
|
||||
std::move(view.cached),
|
||||
Images::CornersMask(size
|
||||
|
@ -64,7 +67,9 @@ void ValidateUserpicCache(
|
|||
view.cached.fill(Qt::transparent);
|
||||
|
||||
auto p = QPainter(&view.cached);
|
||||
if (forum) {
|
||||
if (shape == PeerUserpicShape::Monoforum) {
|
||||
empty->paintMonoforum(p, 0, 0, size, size);
|
||||
} else if (shape == PeerUserpicShape::Forum) {
|
||||
empty->paintRounded(
|
||||
p,
|
||||
0,
|
||||
|
|
|
@ -17,6 +17,13 @@ class EmptyUserpic;
|
|||
|
||||
[[nodiscard]] float64 ForumUserpicRadiusMultiplier();
|
||||
|
||||
enum class PeerUserpicShape : uint8 {
|
||||
Auto,
|
||||
Circle,
|
||||
Forum,
|
||||
Monoforum,
|
||||
};
|
||||
|
||||
struct PeerUserpicView {
|
||||
[[nodiscard]] bool null() const {
|
||||
return cached.isNull() && !cloud && empty.null();
|
||||
|
@ -25,8 +32,8 @@ struct PeerUserpicView {
|
|||
QImage cached;
|
||||
std::shared_ptr<QImage> cloud;
|
||||
base::weak_ptr<const EmptyUserpic> empty;
|
||||
uint32 paletteVersion : 31 = 0;
|
||||
uint32 forum : 1 = 0;
|
||||
uint32 paletteVersion : 30 = 0;
|
||||
uint32 shape : 2 = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool PeerUserpicLoading(const PeerUserpicView &view);
|
||||
|
@ -36,6 +43,6 @@ void ValidateUserpicCache(
|
|||
const QImage *cloud,
|
||||
const EmptyUserpic *empty,
|
||||
int size,
|
||||
bool forum);
|
||||
PeerUserpicShape shape);
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -656,7 +656,7 @@ Notification::Notification(
|
|||
, _topicRootId(topicRootId)
|
||||
, _sublist(history->peer->monoforumSublistFor(monoforumPeerId))
|
||||
, _monoforumPeerId(monoforumPeerId)
|
||||
, _userpicView(_peer->createUserpicView())
|
||||
, _userpicView(_peer->userpicPaintingPeer()->createUserpicView())
|
||||
, _author(author)
|
||||
, _reaction(reaction)
|
||||
, _item(item)
|
||||
|
|
Loading…
Add table
Reference in a new issue