From 1d8e76aa086d4863c38bbca5c73d16a8e7eb7afe Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 29 Dec 2016 13:03:51 +0400 Subject: [PATCH] New empty user/chat photos: with filled background and initials. --- Telegram/Resources/colors.palette | 25 +- Telegram/Resources/icons/userpic_channel.png | Bin 1199 -> 0 bytes .../Resources/icons/userpic_channel@2x.png | Bin 4994 -> 0 bytes Telegram/Resources/icons/userpic_chat.png | Bin 1978 -> 0 bytes Telegram/Resources/icons/userpic_chat@2x.png | Bin 8906 -> 0 bytes Telegram/Resources/icons/userpic_person.png | Bin 1847 -> 0 bytes .../Resources/icons/userpic_person@2x.png | Bin 7707 -> 0 bytes Telegram/Resources/sample.tdesktop-theme | 25 +- Telegram/SourceFiles/boxes/addcontactbox.cpp | 2 +- Telegram/SourceFiles/boxes/confirmbox.cpp | 12 +- Telegram/SourceFiles/boxes/confirmbox.h | 1 + Telegram/SourceFiles/boxes/contactsbox.cpp | 4 +- Telegram/SourceFiles/boxes/contactsbox.h | 2 +- Telegram/SourceFiles/boxes/members_box.cpp | 2 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 6 +- Telegram/SourceFiles/boxes/send_files_box.h | 1 + Telegram/SourceFiles/core/utils.h | 17 +- .../SourceFiles/dialogs/dialogs_layout.cpp | 2 +- Telegram/SourceFiles/dialogswidget.cpp | 4 +- .../history/field_autocomplete.cpp | 4 +- Telegram/SourceFiles/history/history.style | 19 +- .../history/history_media_types.cpp | 17 +- .../SourceFiles/history/history_media_types.h | 1 + Telegram/SourceFiles/historywidget.cpp | 2 +- .../inline_bots/inline_bot_layout_item.cpp | 6 +- Telegram/SourceFiles/localstorage.cpp | 6 +- .../profile/profile_block_peer_list.cpp | 2 +- .../profile/profile_common_groups_section.cpp | 2 +- .../profile/profile_userpic_button.cpp | 2 +- Telegram/SourceFiles/structs.cpp | 225 +++++++++++++----- Telegram/SourceFiles/structs.h | 34 ++- .../ui/buttons/peer_avatar_button.cpp | 2 +- Telegram/SourceFiles/ui/images.h | 5 + .../window/notifications_manager_default.cpp | 4 +- .../window/window_theme_preview.cpp | 112 ++++++--- 35 files changed, 370 insertions(+), 176 deletions(-) delete mode 100644 Telegram/Resources/icons/userpic_channel.png delete mode 100644 Telegram/Resources/icons/userpic_channel@2x.png delete mode 100644 Telegram/Resources/icons/userpic_chat.png delete mode 100644 Telegram/Resources/icons/userpic_chat@2x.png delete mode 100644 Telegram/Resources/icons/userpic_person.png delete mode 100644 Telegram/Resources/icons/userpic_person@2x.png diff --git a/Telegram/Resources/colors.palette b/Telegram/Resources/colors.palette index 581147caf..325e91020 100644 --- a/Telegram/Resources/colors.palette +++ b/Telegram/Resources/colors.palette @@ -258,29 +258,22 @@ historyForwardChooseBg: #0000004c; historyForwardChooseFg: windowFgActive; historyPeer1NameFg: #c03d33; // red -historyPeer1UserpicBg: #ed9482; -historyPeer1UserpicFg: #d3644b; +historyPeer1UserpicBg: #e57979; historyPeer2NameFg: #4fad2d; // green -historyPeer2UserpicBg: #a8db92; -historyPeer2UserpicFg: #75c057; +historyPeer2UserpicBg: #80d066; historyPeer3NameFg: #d09306; // yellow -historyPeer3UserpicBg: #efd289; -historyPeer3UserpicFg: #e4a861; +historyPeer3UserpicBg: #ecd074; historyPeer4NameFg: windowActiveTextFg; // blue -historyPeer4UserpicBg: #8fbfe9; -historyPeer4UserpicFg: #649fd3; +historyPeer4UserpicBg: #6fb1e4; historyPeer5NameFg: #8544d6; // purple -historyPeer5UserpicBg: #9992e4; -historyPeer5UserpicFg: #7b72cf; +historyPeer5UserpicBg: #cc90e2; historyPeer6NameFg: #cd4073; // pink -historyPeer6UserpicBg: #ffa9c3; -historyPeer6UserpicFg: #e87497; +historyPeer6UserpicBg: #f078ae; historyPeer7NameFg: #2996ad; // sea -historyPeer7UserpicBg: #8eccdb; -historyPeer7UserpicFg: #5eb2c7; +historyPeer7UserpicBg: #73cdd0; historyPeer8NameFg: #ce671b; // orange -historyPeer8UserpicBg: #f7b37c; -historyPeer8UserpicFg: #de8d62; +historyPeer8UserpicBg: #fba76f; +historyPeerUserpicFg: windowFgActive; historyScrollBarBg: #556e837a; historyScrollBarBgOver: #556e83bc; diff --git a/Telegram/Resources/icons/userpic_channel.png b/Telegram/Resources/icons/userpic_channel.png deleted file mode 100644 index 1f5fd21f26656e57ddd87e0eb5cb9e51169c84b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1199 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 diff --git a/Telegram/Resources/icons/userpic_chat.png b/Telegram/Resources/icons/userpic_chat.png deleted file mode 100644 index 778e505c770b30458773f940138a57e7b7f9bc17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1978 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 diff --git a/Telegram/Resources/icons/userpic_person.png b/Telegram/Resources/icons/userpic_person.png deleted file mode 100644 index fb28bf3c53389b788fc37e861c6557f102015702..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1847 zcmV-72gvw|P) zFKpXP7>D2Pt1M0O$c&7P9I_yzNRxuXJYp17X0o86piTOuAdeJfBtu3S3Ccz?Y3fKa zkdSo5CNar~JK~aaZ|tVIrm6M`X~AMo}7KTJD-mL06|h(o=^vnJT6jj z$&rFfjuc#Sq~MYx1(zHtxa3H|B}WP_IZ|-RIi?PkK1ag2k(0A1HbUDwHvXU~N^z=Mim z7dpMMO9VF zkNIE(*Xwm$tyYBzMns&?=V)0L`LUN?u%>CaTrLZhyC#lf5harc$W(0G#$K<7i^YOO z?waLtiPdVAygo`HSWy&gx7*}WZ?jk|MEW{K9$;h9b$#z&fA+~}G$OAfVFjzIisSK^ z+Tp!4n@#e%5>l}5`_%3-5d;A$ib7srLJ77ki`v^xIF3VJXLl8Lvq`UCzow3`6DKDp z)DiCF2>vu<4k(HO%jFU@O{0#Inaj&d&~+UyFE6R1Y=l({u2d>Q$prvVRTXNr8g-1V zuoC>@#S7{PxmeFPbA**((OT~sDL5m~pFgLLkPE{ws3UBJmEdR3o>520g|6$=5w^lg zu&8jpw6GGKrYUuVT&x%OafFrNBuS_v0Rx9cV8(}3lO;aJS!)cnz7Mzvy^K8@;Qhi*a2STHuW6g${Pm8VU;u#0WI`QbCph;T zq~JZkeG3TkwY%%mYPHDj9DE3a!GQCQ0OSF#%X~hkc9okT2w2`E&gK-Yswz~gRq7bI zF-;R}+oq237id@90zFF2 zXPG%WJ0q_z;RFK!nx=`JPKVt-l{bmw7!AW9udBNXt8J9FF`v&_O(lN(_z`~m_yLp2 zM2L0VIuoy_ZN63)>*?2<%d7wOS#at2G>N>fWUY)q)j8fo`{3=zEsozGd=HS=MrT zdRl1fMZ8*6CwMC+50I&No>#csHG{!Ggr|&(DOgoi7HhIbqmfW+v4jxpI1a02v#Zq# zJ{}#-KKV!iSc-hmSvIGmoS1=RmEPfN9}EA zdc7X!(>8ek1ORL_8mz9jyAsDSb~+u7qG#R5B>P7(JP@9)JLjRyAn{ewFF?t|fQ_?X*3JnRKD zO~Y2JCG=+ATv#j?*lxG?eXY*-kJV}wyWOsAt&c#GBk&>f?~y!*n{mZ>7oKKWsLe@>(kpNs?fz)ygK=aU5K&R@9j#Iq*F1 zFTwu+z`yW^Mxz0rK7E3xPoIKBJYK$h3CG9B@a@~T>z`e3WoQ@%OsCUQEc8BfUcGvC zy`RVt0HC5MFdB`ZUa!+8lk9~kil9=dK$@mkH=n(G_fEvcFnM5GQQc^uxqe=h}>nb~Y61(%sLO{L(nBh(%K llHHMlOO6y=a-`sr^B+3xDzXtIZZ7};002ovPDHLkV1iItX~h5l diff --git a/Telegram/Resources/icons/userpic_person@2x.png b/Telegram/Resources/icons/userpic_person@2x.png deleted file mode 100644 index 4b63a71011dd03f857319b498ab60dcdc05cae22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7707 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 diff --git a/Telegram/Resources/sample.tdesktop-theme b/Telegram/Resources/sample.tdesktop-theme index 05c99a2d6..a1f2d88b2 100644 --- a/Telegram/Resources/sample.tdesktop-theme +++ b/Telegram/Resources/sample.tdesktop-theme @@ -214,29 +214,22 @@ historyUnreadBarFg: #538bb4; historyForwardChooseBg: #0000004c; historyForwardChooseFg: #ffffff; // windowActiveTextFg; historyPeer1NameFg: #c03d33; -historyPeer1UserpicBg: #ed9482; -historyPeer1UserpicFg: #d3644b; +historyPeer1UserpicBg: #e57979; historyPeer2NameFg: #4fad2d; -historyPeer2UserpicBg: #a8db92; -historyPeer2UserpicFg: #75c057; +historyPeer2UserpicBg: #80d066; historyPeer3NameFg: #d09306; -historyPeer3UserpicBg: #efd289; -historyPeer3UserpicFg: #e4a861; +historyPeer3UserpicBg: #ecd074; historyPeer4NameFg: #168acd; // windowShadowFg; -historyPeer4UserpicBg: #8fbfe9; -historyPeer4UserpicFg: #649fd3; +historyPeer4UserpicBg: #6fb1e4; historyPeer5NameFg: #8544d6; -historyPeer5UserpicBg: #9992e4; -historyPeer5UserpicFg: #7b72cf; +historyPeer5UserpicBg: #cc90e2; historyPeer6NameFg: #cd4073; -historyPeer6UserpicBg: #ffa9c3; -historyPeer6UserpicFg: #e87497; +historyPeer6UserpicBg: #f078ae; historyPeer7NameFg: #2996ad; -historyPeer7UserpicBg: #8eccdb; -historyPeer7UserpicFg: #5eb2c7; +historyPeer7UserpicBg: #73cdd0; historyPeer8NameFg: #ce671b; -historyPeer8UserpicBg: #f7b37c; -historyPeer8UserpicFg: #de8d62; +historyPeer8UserpicBg: #fba76f; +historyPeerUserpicFg: #ffffff; // windowActiveTextFg; historyScrollBarBg: #556e837a; historyScrollBarBgOver: #556e83bc; historyScrollBg: #556e834c; diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 037a5e19d..02a570031 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -1201,7 +1201,7 @@ void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) { void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected) const { auto peer = row.peer; - peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width()); + peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize); p.setPen(st::contactsNameFg); diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index f11226cf3..cba2f8959 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -462,7 +462,6 @@ void RichDeleteMessageBox::deleteAndClear() { ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants) : _title(this, st::confirmInviteTitle) , _status(this, st::confirmInviteStatus) -, _photo(chatDefPhoto(0)) , _participants(participants) { _title->setText(title); QString status; @@ -483,6 +482,9 @@ ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChat } } } + if (!_photo) { + _photoEmpty.set(0, title); + } } void ConfirmInviteBox::prepare() { @@ -528,12 +530,16 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) { Painter p(this); - p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize)); + if (_photo) { + p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize)); + } else { + _photoEmpty.paint(p, (width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, width(), st::confirmInvitePhotoSize); + } int sumWidth = _participants.size() * _userWidth; int left = (width() - sumWidth) / 2; for_const (auto user, _participants) { - user->paintUserpicLeft(p, st::confirmInviteUserPhotoSize, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width()); + user->paintUserpicLeft(p, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width(), st::confirmInviteUserPhotoSize); left += _userWidth; } } diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index f14b1ac80..068577d6a 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -207,6 +207,7 @@ private: object_ptr _title; object_ptr _status; ImagePtr _photo; + EmptyUserpic _photoEmpty; QVector _participants; int _userWidth = 0; diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index 12b908698..2e656a255 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -955,7 +955,7 @@ void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Cont checkedRatio = data->checkbox->checkedAnimationRatio(); data->checkbox->paint(p, ms, st::contactsPadding.left(), st::contactsPadding.top(), width()); } else { - peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width()); + peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize); } int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); @@ -1013,7 +1013,7 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i auto iconBorderPen = st::contactsPhotoCheckbox.check.border->p; iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth); - peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, width()); + peer->paintUserpicLeft(p, userpicLeft, userpicTop, width(), userpicRadius * 2); { PainterHighQualityEnabler hq(p); diff --git a/Telegram/SourceFiles/boxes/contactsbox.h b/Telegram/SourceFiles/boxes/contactsbox.h index 89bd546c0..6078ec410 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.h +++ b/Telegram/SourceFiles/boxes/contactsbox.h @@ -43,7 +43,7 @@ QString cantInviteError(); inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *peer) { return [peer](Painter &p, int x, int y, int outerWidth, int size) { - peer->paintUserpicLeft(p, size, x, y, outerWidth); + peer->paintUserpicLeft(p, x, y, outerWidth, size); }; } diff --git a/Telegram/SourceFiles/boxes/members_box.cpp b/Telegram/SourceFiles/boxes/members_box.cpp index e3a6054a6..daccc73fb 100644 --- a/Telegram/SourceFiles/boxes/members_box.cpp +++ b/Telegram/SourceFiles/boxes/members_box.cpp @@ -271,7 +271,7 @@ void MembersBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Membe data->ripple.reset(); } } - peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width()); + peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize); p.setPen(st::contactsNameFg); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index a12e23b28..8848a29e3 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -127,9 +127,11 @@ SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstn : _contactPhone(phone) , _contactFirstName(firstname) , _contactLastName(lastname) { - _nameText.setText(st::semiboldTextStyle, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions); + auto name = lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName); + _nameText.setText(st::semiboldTextStyle, name, _textNameOptions); _statusText = _contactPhone; _statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText)); + _contactPhotoEmpty.set(0, name); } void SendFilesBox::prepare() { @@ -280,7 +282,7 @@ void SendFilesBox::paintEvent(QPaintEvent *e) { auto &icon = _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument; icon.paintInCenter(p, inner); } else { - p.drawPixmapLeft(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), userDefPhoto(1)->pixCircled(st::msgFileSize)); + _contactPhotoEmpty.paint(p, x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), st::msgFileSize); } } else { QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width())); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index cca2759f3..62ab8a922 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -89,6 +89,7 @@ private: QString _contactPhone; QString _contactFirstName; QString _contactLastName; + EmptyUserpic _contactPhotoEmpty; base::lambda _confirmedCallback; base::lambda _cancelledCallback; diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h index 1f6433dd2..7626b9efc 100644 --- a/Telegram/SourceFiles/core/utils.h +++ b/Telegram/SourceFiles/core/utils.h @@ -320,21 +320,24 @@ inline T snap(const T &v, const T &_min, const T &_max) { template class ManagedPtr { public: - ManagedPtr() : ptr(0) { - } - ManagedPtr(T *p) : ptr(p) { + ManagedPtr() = default; + ManagedPtr(T *p) : _data(p) { } T *operator->() const { - return ptr; + return _data; } T *v() const { - return ptr; + return _data; + } + + explicit operator bool() const { + return _data != nullptr; } protected: + using Parent = ManagedPtr; + T *_data = nullptr; - T *ptr; - typedef ManagedPtr Parent; }; QString translitRusEng(const QString &rus); diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index ba405597f..5cf0f3451 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -66,7 +66,7 @@ void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *i if (onlyBackground) return; auto userpicPeer = (history->peer->migrateTo() ? history->peer->migrateTo() : history->peer); - userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth); + userpicPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth, st::dialogsPhotoSize); auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; auto namewidth = fullWidth - nameleft - st::dialogsPadding.x(); diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 01e73622d..9f985aa0a 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -297,7 +297,7 @@ void DialogsInner::paintPeerSearchResult(Painter &p, const PeerSearchResult *res auto peer = result->peer; auto userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer); - userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth()); + userpicPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth(), st::dialogsPhotoSize); auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; auto namewidth = fullWidth - nameleft - st::dialogsPadding.x(); @@ -344,7 +344,7 @@ void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackgro p.fillRect(fullRect, st::dialogsBg); if (onlyBackground) return; - _searchInPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth()); + _searchInPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth(), st::dialogsPhotoSize); auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; auto namewidth = fullWidth - nameleft - st::dialogsPadding.x() * 2 - st::dialogsCancelSearch.width; diff --git a/Telegram/SourceFiles/history/field_autocomplete.cpp b/Telegram/SourceFiles/history/field_autocomplete.cpp index b78c84945..69e606dac 100644 --- a/Telegram/SourceFiles/history/field_autocomplete.cpp +++ b/Telegram/SourceFiles/history/field_autocomplete.cpp @@ -618,7 +618,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) { } } user->loadUserpic(); - user->paintUserpicLeft(p, st::mentionPhotoSize, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width()); + user->paintUserpicLeft(p, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width(), st::mentionPhotoSize); p.setPen(selected ? st::mentionNameFgOver : st::mentionNameFg); user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth); @@ -663,7 +663,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) { toHighlight += '@' + user->username; } user->loadUserpic(); - user->paintUserpicLeft(p, st::mentionPhotoSize, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width()); + user->paintUserpicLeft(p, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width(), st::mentionPhotoSize); auto commandText = '/' + toHighlight; diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index b5c7d2c6e..d029356fd 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -145,23 +145,6 @@ historyViewsOutIcon: icon {{ "history_views", historyOutIconFg }}; historyViewsOutSelectedIcon: icon {{ "history_views", historyOutIconFgSelected }}; historyViewsInvertedIcon: icon {{ "history_views", historySendingInvertedIconFg }}; -historyPeer1UserpicPerson: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_person", historyPeer1UserpicFg }}; -historyPeer1UserpicChat: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_chat", historyPeer1UserpicFg }}; -historyPeer1UserpicChannel: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_channel", historyPeer1UserpicFg }}; -historyPeer2UserpicPerson: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_person", historyPeer2UserpicFg }}; -historyPeer2UserpicChat: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_chat", historyPeer2UserpicFg }}; -historyPeer2UserpicChannel: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_channel", historyPeer2UserpicFg }}; -historyPeer3UserpicPerson: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_person", historyPeer3UserpicFg }}; -historyPeer3UserpicChat: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_chat", historyPeer3UserpicFg }}; -historyPeer3UserpicChannel: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_channel", historyPeer3UserpicFg }}; -historyPeer4UserpicPerson: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_person", historyPeer4UserpicFg }}; -historyPeer4UserpicChat: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_chat", historyPeer4UserpicFg }}; -historyPeer4UserpicChannel: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_channel", historyPeer4UserpicFg }}; -historyPeer5UserpicPerson: icon {{ size(120px, 120px), historyPeer5UserpicBg }, { "userpic_person", historyPeer5UserpicFg }}; -historyPeer6UserpicPerson: icon {{ size(120px, 120px), historyPeer6UserpicBg }, { "userpic_person", historyPeer6UserpicFg }}; -historyPeer7UserpicPerson: icon {{ size(120px, 120px), historyPeer7UserpicBg }, { "userpic_person", historyPeer7UserpicFg }}; -historyPeer8UserpicPerson: icon {{ size(120px, 120px), historyPeer8UserpicBg }, { "userpic_person", historyPeer8UserpicFg }}; - historyComposeField: FlatTextarea { textColor: historyComposeAreaFg; bgColor: historyComposeAreaBg; @@ -391,6 +374,8 @@ historyBubbleTailInRightSelected: icon {{ "bubble_tail-flip_horizontal", msgInBg historyBubbleTailOutRight: icon {{ "bubble_tail-flip_horizontal", msgOutBg }}; historyBubbleTailOutRightSelected: icon {{ "bubble_tail-flip_horizontal", msgOutBgSelected }}; +historyPeerUserpicFont: semiboldFont; + historyStatusFg: windowSubTextFg; historyStatusFgActive: windowActiveTextFg; historyStatusFgTyping: historyStatusFgActive; diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 8c0f92b93..a41fb4daa 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -2235,16 +2235,17 @@ HistoryContact::HistoryContact(HistoryItem *parent, int32 userId, const QString , _lname(last) , _phone(App::formatPhone(phone)) { _name.setText(st::semiboldTextStyle, lng_full_name(lt_first_name, first, lt_last_name, last).trimmed(), _textNameOptions); - _phonew = st::normalFont->width(_phone); } void HistoryContact::initDimensions() { _maxw = st::msgFileMinWidth; - _contact = _userId ? App::userLoaded(_userId) : 0; + _contact = _userId ? App::userLoaded(_userId) : nullptr; if (_contact) { _contact->loadUserpic(); + } else { + _photoEmpty.set(qAbs(_userId ? _userId : _parent->id) % kUserColorsCount, _name.originalText()); } if (_contact && _contact->contact > 0) { _linkl = sendMessageClickHandler(_contact); @@ -2305,12 +2306,15 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top() - topMinus, st::msgFileThumbSize, st::msgFileThumbSize, width)); if (_contact) { - _contact->paintUserpic(p, st::msgFileThumbSize, rthumb.x(), rthumb.y()); + _contact->paintUserpic(p, rthumb.x(), rthumb.y(), st::msgFileThumbSize); } else { - p.drawPixmap(rthumb.topLeft(), userDefPhoto(qAbs(_userId) % kUserColorsCount)->pixCircled(st::msgFileThumbSize, st::msgFileThumbSize)); + _photoEmpty.paint(p, st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top() - topMinus, width, st::msgFileThumbSize); } if (selected) { - App::roundRect(p, rthumb, p.textPalette().selectOverlay, SelectedOverlaySmallCorners); + PainterHighQualityEnabler hq(p); + p.setBrush(p.textPalette().selectOverlay); + p.setPen(Qt::NoPen); + p.drawEllipse(rthumb); } bool over = ClickHandler::showAsActive(_linkl); @@ -2323,8 +2327,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T nameright = st::msgFilePadding.left(); statustop = st::msgFileStatusTop - topMinus; - QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top() - topMinus, st::msgFileSize, st::msgFileSize, width)); - p.drawPixmap(inner.topLeft(), userDefPhoto(qAbs(_parent->id) % kUserColorsCount)->pixCircled(st::msgFileSize, st::msgFileSize)); + _photoEmpty.paint(p, st::msgFilePadding.left(), st::msgFilePadding.top() - topMinus, width, st::msgFileSize); } int32 namewidth = width - nameleft - nameright; diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index 0e9dc6f62..e16987a65 100644 --- a/Telegram/SourceFiles/history/history_media_types.h +++ b/Telegram/SourceFiles/history/history_media_types.h @@ -636,6 +636,7 @@ private: int _phonew = 0; QString _fname, _lname, _phone; Text _name; + EmptyUserpic _photoEmpty; ClickHandlerPtr _linkl; int _linkw = 0; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 10fe2546b..fcd03cf5e 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -553,7 +553,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { // paint the userpic if it intersects the painted rect if (userpicTop + st::msgPhotoSize > r.top()) { - message->from()->paintUserpicLeft(p, st::msgPhotoSize, st::historyPhotoLeft, userpicTop, message->history()->width); + message->from()->paintUserpicLeft(p, st::historyPhotoLeft, userpicTop, message->history()->width, st::msgPhotoSize); } return true; }); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp index 4b9675248..3ccb9c1c4 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp @@ -146,7 +146,11 @@ ImagePtr ItemBase::getResultThumb() const { QPixmap ItemBase::getResultContactAvatar(int width, int height) const { if (_result->_type == Result::Type::Contact) { - return userDefPhoto(qHash(_result->_id) % kUserColorsCount)->pixCircled(width, height); + auto result = EmptyUserpic(qHash(_result->_id) % kUserColorsCount, _result->getLayoutTitle()).generate(width); + if (result.height() != height * cIntRetinaFactor()) { + result = result.scaled(QSize(width, height) * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + return std_::move(result); } return QPixmap(); } diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index be4196344..ba0780a9c 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -3874,7 +3874,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) { user->inputUser = MTP_inputUser(MTP_int(peerToUser(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access)); } - user->setUserpic(photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc)); + user->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); } } else if (result->isChat()) { ChatData *chat = result->asChat(); @@ -3902,7 +3902,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) { chat->input = MTP_inputPeerChat(MTP_int(peerToChat(chat->id))); chat->inputChat = MTP_int(peerToChat(chat->id)); - chat->setUserpic(photoLoc.isNull() ? ImagePtr(chatDefPhoto(chat->colorIndex)) : ImagePtr(photoLoc)); + chat->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); } } else if (result->isChannel()) { ChannelData *channel = result->asChannel(); @@ -3924,7 +3924,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) { channel->input = MTP_inputPeerChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); - channel->setUserpic(photoLoc.isNull() ? ImagePtr((channel->isMegagroup() ? chatDefPhoto(channel->colorIndex) : channelDefPhoto(channel->colorIndex))) : ImagePtr(photoLoc)); + channel->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); } } if (!wasLoaded) { diff --git a/Telegram/SourceFiles/profile/profile_block_peer_list.cpp b/Telegram/SourceFiles/profile/profile_block_peer_list.cpp index 069b413c3..c4ddcc820 100644 --- a/Telegram/SourceFiles/profile/profile_block_peer_list.cpp +++ b/Telegram/SourceFiles/profile/profile_block_peer_list.cpp @@ -96,7 +96,7 @@ void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool select } int skip = st::profileMemberPhotoPosition.x(); - item->peer->paintUserpicLeft(p, st::profileMemberPhotoSize, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width()); + item->peer->paintUserpicLeft(p, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width(), st::profileMemberPhotoSize); if (item->name.isEmpty()) { item->name.setText(st::msgNameStyle, App::peerName(item->peer), _textNameOptions); diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp index 4930077ab..3b5849397 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp @@ -236,7 +236,7 @@ void InnerWidget::paintRow(Painter &p, int index, TimeMs ms) { x += st::profileCommonGroupsPadding.left(); y += st::profileCommonGroupsPadding.top(); - item->peer->paintUserpic(p, st::profileCommonGroupsPhotoSize, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y); + item->peer->paintUserpic(p, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y, st::profileCommonGroupsPhotoSize); x += st::profileCommonGroupsPhotoSize + st::profileCommonGroupsNameLeft; y += st::profileCommonGroupsNameTop; diff --git a/Telegram/SourceFiles/profile/profile_userpic_button.cpp b/Telegram/SourceFiles/profile/profile_userpic_button.cpp index 3d346493a..fa401d104 100644 --- a/Telegram/SourceFiles/profile/profile_userpic_button.cpp +++ b/Telegram/SourceFiles/profile/profile_userpic_button.cpp @@ -115,7 +115,7 @@ QPixmap UserpicButton::prepareUserpicPixmap() const { image.fill(Qt::transparent); { Painter p(&image); - _peer->paintUserpic(p, width(), 0, 0); + _peer->paintUserpic(p, 0, 0, width()); } return App::pixmapFromImageInPlace(std_::move(image)); } diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index b0bc174ed..8d894744e 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -74,40 +74,140 @@ style::color peerColor(int index) { return peerColors[index]; } -ImagePtr userDefPhoto(int index) { - static const ImagePtr userDefPhotos[kUserColorsCount] = { - generateUserpicImage(st::historyPeer1UserpicPerson), - generateUserpicImage(st::historyPeer2UserpicPerson), - generateUserpicImage(st::historyPeer3UserpicPerson), - generateUserpicImage(st::historyPeer4UserpicPerson), - generateUserpicImage(st::historyPeer5UserpicPerson), - generateUserpicImage(st::historyPeer6UserpicPerson), - generateUserpicImage(st::historyPeer7UserpicPerson), - generateUserpicImage(st::historyPeer8UserpicPerson), +style::color peerUserpicColor(int index) { + static style::color peerColors[kUserColorsCount] = { + st::historyPeer1UserpicBg, + st::historyPeer2UserpicBg, + st::historyPeer3UserpicBg, + st::historyPeer4UserpicBg, + st::historyPeer5UserpicBg, + st::historyPeer6UserpicBg, + st::historyPeer7UserpicBg, + st::historyPeer8UserpicBg, }; - return userDefPhotos[index]; + return peerColors[index]; } -ImagePtr chatDefPhoto(int index) { - static const ImagePtr chatDefPhotos[kChatColorsCount] = { - generateUserpicImage(st::historyPeer1UserpicChat), - generateUserpicImage(st::historyPeer2UserpicChat), - generateUserpicImage(st::historyPeer3UserpicChat), - generateUserpicImage(st::historyPeer4UserpicChat), - }; - return chatDefPhotos[index]; +class EmptyUserpic::Impl { +public: + Impl(int index, const QString &name) : _color(peerUserpicColor(index)) { + fillString(name); + } + + void paint(Painter &p, int x, int y, int size); + +private: + void fillString(const QString &name); + + style::color _color; + QString _string; + +}; + +void EmptyUserpic::Impl::paint(Painter &p, int x, int y, int size) { + auto fontsize = (size * 13) / 33; + auto font = st::historyPeerUserpicFont->f; + font.setPixelSize(fontsize); + + PainterHighQualityEnabler hq(p); + p.setBrush(_color); + p.setPen(Qt::NoPen); + p.drawEllipse(x, y, size, size); + + p.setFont(font); + p.setBrush(Qt::NoBrush); + p.setPen(st::historyPeerUserpicFg); + p.drawText(QRect(x, y, size, size), _string, QTextOption(style::al_center)); } -ImagePtr channelDefPhoto(int index) { - static const ImagePtr channelDefPhotos[kChannelColorsCount] = { - generateUserpicImage(st::historyPeer1UserpicChannel), - generateUserpicImage(st::historyPeer2UserpicChannel), - generateUserpicImage(st::historyPeer3UserpicChannel), - generateUserpicImage(st::historyPeer4UserpicChannel), - }; - return channelDefPhotos[index]; +void EmptyUserpic::Impl::fillString(const QString &name) { + QList letters; + QList levels; + auto level = 0; + auto letterFound = false; + auto ch = name.constData(), end = ch + name.size(); + while (ch != end) { + auto emojiLength = 0; + if (auto emoji = emojiFromText(ch, end, &emojiLength)) { + ch += emojiLength; + } else if (ch->isHighSurrogate()) { + ++ch; + if (ch != end && ch->isLowSurrogate()) { + ++ch; + } + } else if (!letterFound && ch->isLetterOrNumber()) { + letterFound = true; + if (ch + 1 != end && chIsDiac(*(ch + 1))) { + letters.push_back(QString(ch, 2)); + levels.push_back(level); + ++ch; + } else { + letters.push_back(QString(ch, 1)); + levels.push_back(level); + } + ++ch; + } else { + if (*ch == ' ') { + level = 0; + letterFound = false; + } else if (letterFound && *ch == '-') { + level = 1; + letterFound = true; + } + ++ch; + } + } + + // We prefer the second letter to be after ' ', but it can also be after '-'. + _string = QString(); + if (!letters.isEmpty()) { + _string += letters.front(); + auto bestIndex = 0; + auto bestLevel = 2; + for (auto i = letters.size(); i != 1;) { + if (levels[--i] < bestLevel) { + bestIndex = i; + bestLevel = levels[i]; + } + } + if (bestIndex > 0) { + _string += letters[bestIndex]; + } + } + _string = _string.toUpper(); } +EmptyUserpic::EmptyUserpic() = default; + +EmptyUserpic::EmptyUserpic(int index, const QString &name) : _impl(std_::make_unique(index, name)) { +} + +void EmptyUserpic::set(int index, const QString &name) { + _impl = std_::make_unique(index, name); +} + +void EmptyUserpic::clear() { + _impl.reset(); +} + +void EmptyUserpic::paint(Painter &p, int x, int y, int outerWidth, int size) const { + t_assert(_impl != nullptr); + _impl->paint(p, rtl() ? (outerWidth - x - size) : x, y, size); +} + +QPixmap EmptyUserpic::generate(int size) { + auto result = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(cRetinaFactor()); + result.fill(Qt::transparent); + { + Painter p(&result); + paint(p, 0, 0, size, size); + } + return App::pixmapFromImageInPlace(std_::move(result)); +} + +EmptyUserpic::~EmptyUserpic() = default; + using UpdateFlag = Notify::PeerUpdate::Flag; NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats; @@ -115,9 +215,9 @@ NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersP PeerData::PeerData(const PeerId &id) : id(id) , colorIndex(peerColorIndex(id)) -, color(peerColor(colorIndex)) -, _userpic(isUser() ? userDefPhoto(colorIndex) : ((isChat() || isMegagroup()) ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex))) { +, color(peerColor(colorIndex)) { nameText.setText(st::msgNameStyle, QString(), _textNameOptions); + _userpicEmpty.set(colorIndex, QString()); } void PeerData::updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) { @@ -138,6 +238,9 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO ++nameVersion; name = newName; nameText.setText(st::msgNameStyle, name, _textNameOptions); + if (!_userpic) { + _userpicEmpty.set(colorIndex, name); + } Notify::PeerUpdate update(this); update.flags |= UpdateFlag::NameChanged; @@ -170,39 +273,55 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO void PeerData::setUserpic(ImagePtr userpic) { _userpic = userpic; + if (!_userpic || !_userpic->loaded()) { + _userpicEmpty.set(colorIndex, name); + } else { + _userpicEmpty.clear(); + } } ImagePtr PeerData::currentUserpic() const { - if (_userpic->loaded()) { - return _userpic; + if (_userpic) { + _userpic->load(); + if (_userpic->loaded()) { + _userpicEmpty.clear(); + return _userpic; + } } - _userpic->load(); - - if (isUser()) { - return userDefPhoto(colorIndex); - } else if (isMegagroup() || isChat()) { - return chatDefPhoto(colorIndex); - } - return channelDefPhoto(colorIndex); + return ImagePtr(); } -void PeerData::paintUserpic(Painter &p, int size, int x, int y) const { - p.drawPixmap(x, y, currentUserpic()->pixCircled(size, size)); +void PeerData::paintUserpic(Painter &p, int x, int y, int size) const { + if (auto userpic = currentUserpic()) { + p.drawPixmap(x, y, userpic->pixCircled(size, size)); + } else { + _userpicEmpty.paint(p, x, y, x + size + x, size); + } } StorageKey PeerData::userpicUniqueKey() const { - if (photoLoc.isNull() || !_userpic->loaded()) { + if (photoLoc.isNull() || !_userpic || !_userpic->loaded()) { return StorageKey(0, (isUser() ? 0x1000 : ((isChat() || isMegagroup()) ? 0x2000 : 0x3000)) | colorIndex); } return storageKey(photoLoc); } void PeerData::saveUserpic(const QString &path, int size) const { - currentUserpic()->pixRounded(size, size, ImageRoundRadius::Small).save(path, "PNG"); + genUserpic(size).save(path, "PNG"); } QPixmap PeerData::genUserpic(int size) const { - return currentUserpic()->pixRounded(size, size, ImageRoundRadius::Small); + if (auto userpic = currentUserpic()) { + return userpic->pixRounded(size, size, ImageRoundRadius::Small); + } + auto result = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(cRetinaFactor()); + result.fill(Qt::transparent); + { + Painter p(&result); + paintUserpic(p, 0, 0, size); + } + return App::pixmapFromImageInPlace(std_::move(result)); } const Text &BotCommand::descriptionText() const { @@ -225,17 +344,17 @@ void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer a const auto &d(p.c_userProfilePhoto()); newPhotoId = d.vphoto_id.v; newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small); - newPhoto = newPhotoLoc.isNull() ? userDefPhoto(colorIndex) : ImagePtr(newPhotoLoc); + newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc); //App::feedPhoto(App::photoFromUserPhoto(peerToUser(id), MTP_int(unixtime()), p)); } break; default: { newPhotoId = 0; if (id == ServiceUserId) { - if (_userpic.v() == userDefPhoto(colorIndex).v()) { + if (!_userpic) { newPhoto = ImagePtr(App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaledToWidth(160, Qt::SmoothTransformation)), "PNG"); } } else { - newPhoto = userDefPhoto(colorIndex); + newPhoto = ImagePtr(); } newPhotoLoc = StorageImageLocation(); } break; @@ -423,13 +542,13 @@ void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Loc newPhotoId = phId; } newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small); - newPhoto = newPhotoLoc.isNull() ? chatDefPhoto(colorIndex) : ImagePtr(newPhotoLoc); -// photoFull = ImagePtr(640, 640, d.vphoto_big, chatDefPhoto(colorIndex)); + newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc); +// photoFull = newPhoto ? ImagePtr(640, 640, d.vphoto_big, ImagePtr()) : ImagePtr(); } break; default: { newPhotoId = 0; newPhotoLoc = StorageImageLocation(); - newPhoto = chatDefPhoto(colorIndex); + newPhoto = ImagePtr(); // photoFull = ImagePtr(); } break; } @@ -479,13 +598,13 @@ void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see newPhotoId = phId; } newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small); - newPhoto = newPhotoLoc.isNull() ? (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex)) : ImagePtr(newPhotoLoc); -// photoFull = ImagePtr(640, 640, d.vphoto_big, (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex))); + newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc); +// photoFull = newPhoto ? ImagePtr(640, 640, d.vphoto_big, newPhoto) : ImagePtr(); } break; default: { newPhotoId = 0; newPhotoLoc = StorageImageLocation(); - newPhoto = (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex)); + newPhoto = ImagePtr(); // photoFull = ImagePtr(); } break; } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index f30c21c4e..854d17175 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -204,9 +204,30 @@ static constexpr int kChatColorsCount = 4; static constexpr int kChannelColorsCount = 4; style::color peerColor(int index); -ImagePtr userDefPhoto(int index); -ImagePtr chatDefPhoto(int index); -ImagePtr channelDefPhoto(int index); + +class EmptyUserpic { +public: + EmptyUserpic(); + EmptyUserpic(int index, const QString &name); + + void set(int index, const QString &name); + void clear(); + + explicit operator bool() const { + return (_impl != nullptr); + } + + void paint(Painter &p, int x, int y, int outerWidth, int size) const; + QPixmap generate(int size); + + ~EmptyUserpic(); + +private: + class Impl; + std_::unique_ptr _impl; + friend class Impl; + +}; static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL; @@ -292,9 +313,9 @@ public: style::color color; void setUserpic(ImagePtr userpic); - void paintUserpic(Painter &p, int size, int x, int y) const; - void paintUserpicLeft(Painter &p, int size, int x, int y, int w) const { - paintUserpic(p, size, rtl() ? (w - x - size) : x, y); + void paintUserpic(Painter &p, int x, int y, int size) const; + void paintUserpicLeft(Painter &p, int x, int y, int w, int size) const { + paintUserpic(p, rtl() ? (w - x - size) : x, y, size); } void loadUserpic(bool loadFirst = false, bool prior = true) { _userpic->load(loadFirst, prior); @@ -331,6 +352,7 @@ protected: ImagePtr _userpic; ImagePtr currentUserpic() const; + mutable EmptyUserpic _userpicEmpty; private: void fillNames(); diff --git a/Telegram/SourceFiles/ui/buttons/peer_avatar_button.cpp b/Telegram/SourceFiles/ui/buttons/peer_avatar_button.cpp index 136c04817..7b264c806 100644 --- a/Telegram/SourceFiles/ui/buttons/peer_avatar_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/peer_avatar_button.cpp @@ -36,7 +36,7 @@ PeerAvatarButton::PeerAvatarButton(QWidget *parent, PeerData *peer, const style: void PeerAvatarButton::paintEvent(QPaintEvent *e) { if (_peer) { Painter p(this); - _peer->paintUserpic(p, _st.photoSize, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2); + _peer->paintUserpic(p, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2, _st.photoSize); } } diff --git a/Telegram/SourceFiles/ui/images.h b/Telegram/SourceFiles/ui/images.h index bf54efad0..ac338b93b 100644 --- a/Telegram/SourceFiles/ui/images.h +++ b/Telegram/SourceFiles/ui/images.h @@ -444,6 +444,11 @@ public: ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr()); ImagePtr(int32 width, int32 height) : Parent(internal::getImage(width, height)) { } + + explicit operator bool() const { + return (_data != nullptr) && !_data->isNull(); + } + }; inline QSize shrinkToKeepAspect(int32 width, int32 height, int32 towidth, int32 toheight) { diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index cfed32531..b83406a61 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -612,7 +612,7 @@ void Notification::updateNotifyDisplay() { if (!options.hideNameAndPhoto) { _history->peer->loadUserpic(true, true); - _history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width()); + _history->peer->paintUserpicLeft(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize); } else { static QPixmap icon = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); icon.setDevicePixelRatio(cRetinaFactor()); @@ -680,7 +680,7 @@ void Notification::updatePeerPhoto() { auto img = _cache.toImage(); { Painter p(&img); - _peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width()); + _peer->paintUserpicLeft(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize); } _cache = App::pixmapFromImageInPlace(std_::move(img)); update(); diff --git a/Telegram/SourceFiles/window/window_theme_preview.cpp b/Telegram/SourceFiles/window/window_theme_preview.cpp index 19b717f1f..3f1bc9d08 100644 --- a/Telegram/SourceFiles/window/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/window_theme_preview.cpp @@ -34,6 +34,63 @@ namespace Window { namespace Theme { namespace { +QString fillLetters(const QString &name) { + QList letters; + QList levels; + auto level = 0; + auto letterFound = false; + auto ch = name.constData(), end = ch + name.size(); + while (ch != end) { + auto emojiLength = 0; + if (auto emoji = emojiFromText(ch, end, &emojiLength)) { + ch += emojiLength; + } else if (ch->isHighSurrogate()) { + ++ch; + if (ch != end && ch->isLowSurrogate()) { + ++ch; + } + } else if (!letterFound && ch->isLetterOrNumber()) { + letterFound = true; + if (ch + 1 != end && chIsDiac(*(ch + 1))) { + letters.push_back(QString(ch, 2)); + levels.push_back(level); + ++ch; + } else { + letters.push_back(QString(ch, 1)); + levels.push_back(level); + } + ++ch; + } else { + if (*ch == ' ') { + level = 0; + letterFound = false; + } else if (letterFound && *ch == '-') { + level = 1; + letterFound = true; + } + ++ch; + } + } + + // We prefer the second letter to be after ' ', but it can also be after '-'. + auto result = QString(); + if (!letters.isEmpty()) { + result += letters.front(); + auto bestIndex = 0; + auto bestLevel = 2; + for (auto i = letters.size(); i != 1;) { + if (levels[--i] < bestLevel) { + bestIndex = i; + bestLevel = levels[i]; + } + } + if (bestIndex > 0) { + result += letters[bestIndex]; + } + } + return result.toUpper(); +} + class Generator { public: Generator(const Instance &theme, const CurrentData ¤t); @@ -48,6 +105,7 @@ private: }; struct Row { Text name; + QString letters; enum class Type { User, Group, @@ -107,7 +165,7 @@ private: void paintBubble(const Bubble &bubble); void paintService(QString text); - void paintUserpic(int x, int y, Row::Type type, int index); + void paintUserpic(int x, int y, Row::Type type, int index, QString letters); void setTextPalette(const style::TextPalette &st); void restoreTextPalette(); @@ -156,6 +214,9 @@ void Generator::prepare() { void Generator::addRow(QString name, int peerIndex, QString date, QString text) { Row row; row.name.setText(st::msgNameStyle, name, _textNameOptions); + + row.letters = fillLetters(name); + row.peerIndex = peerIndex; row.date = date; row.text.setRichText(st::dialogsTextStyle, text, _textDlgOptions); @@ -503,7 +564,7 @@ void Generator::paintRow(const Row &row) { if (row.active || row.selected) { _p->fillRect(fullRect, row.active ? st::dialogsBgActive[_palette] : st::dialogsBgOver[_palette]); } - paintUserpic(x + st::dialogsPadding.x(), y + st::dialogsPadding.y(), row.type, row.peerIndex); + paintUserpic(x + st::dialogsPadding.x(), y + st::dialogsPadding.y(), row.type, row.peerIndex, row.letters); auto nameleft = x + st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; auto namewidth = x + fullWidth - nameleft - st::dialogsPadding.x(); @@ -763,38 +824,33 @@ void Generator::paintService(QString text) { _historyBottom = bubbleTop - st::msgServiceMargin.top(); } -void Generator::paintUserpic(int x, int y, Row::Type type, int index) { - const style::icon *userIcons[] = { - &st::historyPeer1UserpicPerson, - &st::historyPeer2UserpicPerson, - &st::historyPeer3UserpicPerson, - &st::historyPeer4UserpicPerson, - &st::historyPeer5UserpicPerson, - &st::historyPeer6UserpicPerson, - &st::historyPeer7UserpicPerson, - &st::historyPeer8UserpicPerson, +void Generator::paintUserpic(int x, int y, Row::Type type, int index, QString letters) { + style::color colors[] = { + st::historyPeer1UserpicBg, + st::historyPeer2UserpicBg, + st::historyPeer3UserpicBg, + st::historyPeer4UserpicBg, + st::historyPeer5UserpicBg, + st::historyPeer6UserpicBg, + st::historyPeer7UserpicBg, + st::historyPeer8UserpicBg, }; - const style::icon *chatIcons[] = { - &st::historyPeer1UserpicChat, - &st::historyPeer2UserpicChat, - &st::historyPeer3UserpicChat, - &st::historyPeer4UserpicChat, - }; - const style::icon *channelIcons[] = { - &st::historyPeer1UserpicChannel, - &st::historyPeer2UserpicChannel, - &st::historyPeer3UserpicChannel, - &st::historyPeer4UserpicChannel, - }; - auto userpic = (type == Row::Type::User) ? userIcons[index % base::array_size(userIcons)] : (type == Row::Type::Group) ? chatIcons[index % base::array_size(chatIcons)] : channelIcons[index % base::array_size(channelIcons)]; + auto color = colors[index % base::array_size(colors)]; - auto image = QImage(userpic->width() * cIntRetinaFactor(), userpic->height() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + auto image = QImage(st::dialogsPhotoSize * cIntRetinaFactor(), st::dialogsPhotoSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); image.setDevicePixelRatio(cRetinaFactor()); + image.fill(color[_palette]->c); { Painter p(&image); - userpic->paint(p, 0, 0, userpic->width()); + auto fontsize = (st::dialogsPhotoSize * 13) / 33; + auto font = st::historyPeerUserpicFont->f; + font.setPixelSize(fontsize); + + p.setFont(font); + p.setBrush(Qt::NoBrush); + p.setPen(st::historyPeerUserpicFg[_palette]); + p.drawText(QRect(0, 0, st::dialogsPhotoSize, st::dialogsPhotoSize), letters, QTextOption(style::al_center)); } - image = std_::move(image).scaled(st::dialogsPhotoSize * cIntRetinaFactor(), st::dialogsPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); Images::prepareCircle(image); _p->drawImage(rtl() ? (_rect.width() - x - st::dialogsPhotoSize) : x, y, image); }