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 1f5fd21f2..000000000
Binary files a/Telegram/Resources/icons/userpic_channel.png and /dev/null differ
diff --git a/Telegram/Resources/icons/userpic_channel@2x.png b/Telegram/Resources/icons/userpic_channel@2x.png
deleted file mode 100644
index d3301baaf..000000000
Binary files a/Telegram/Resources/icons/userpic_channel@2x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/userpic_chat.png b/Telegram/Resources/icons/userpic_chat.png
deleted file mode 100644
index 778e505c7..000000000
Binary files a/Telegram/Resources/icons/userpic_chat.png and /dev/null differ
diff --git a/Telegram/Resources/icons/userpic_chat@2x.png b/Telegram/Resources/icons/userpic_chat@2x.png
deleted file mode 100644
index cc2492297..000000000
Binary files a/Telegram/Resources/icons/userpic_chat@2x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/userpic_person.png b/Telegram/Resources/icons/userpic_person.png
deleted file mode 100644
index fb28bf3c5..000000000
Binary files a/Telegram/Resources/icons/userpic_person.png and /dev/null differ
diff --git a/Telegram/Resources/icons/userpic_person@2x.png b/Telegram/Resources/icons/userpic_person@2x.png
deleted file mode 100644
index 4b63a7101..000000000
Binary files a/Telegram/Resources/icons/userpic_person@2x.png and /dev/null differ
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<UserData*> &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<Ui::FlatLabel> _title;
 	object_ptr<Ui::FlatLabel> _status;
 	ImagePtr _photo;
+	EmptyUserpic _photoEmpty;
 	QVector<UserData*> _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<void(const QStringList &files, bool compressed, const QString &caption, bool ctrlShiftEnter)> _confirmedCallback;
 	base::lambda<void()> _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 <typename T>
 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>;
+	T *_data = nullptr;
 
-	T *ptr;
-	typedef ManagedPtr<T> 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<QString> letters;
+	QList<int> 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<Impl>(index, name)) {
+}
+
+void EmptyUserpic::set(int index, const QString &name) {
+	_impl = std_::make_unique<Impl>(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> _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<QString> letters;
+	QList<int> 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 &current);
@@ -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);
 }