Refactor icon unread counter painting.

This commit is contained in:
John Preston 2021-11-02 17:10:40 +04:00
parent 87af865604
commit aef45b3a1d
15 changed files with 300 additions and 258 deletions

View File

@ -141,12 +141,7 @@ Application::Application(not_null<Launcher*> launcher)
, _langpack(std::make_unique<Lang::Instance>())
, _langCloudManager(std::make_unique<Lang::CloudManager>(langpack()))
, _emojiKeywords(std::make_unique<ChatHelpers::EmojiKeywords>())
, _logo(Window::LoadLogo())
, _logoNoMargin(Window::LoadLogoNoMargin())
, _autoLockTimer([=] { checkAutoLock(); }) {
Expects(!_logo.isNull());
Expects(!_logoNoMargin.isNull());
Ui::Integration::Set(&_private->uiIntegration);
passcodeLockChanges(

View File

@ -145,12 +145,6 @@ public:
bool hideMediaView();
[[nodiscard]] QPoint getPointForCallPanelCenter() const;
[[nodiscard]] QImage logo() const {
return _logo;
}
[[nodiscard]] QImage logoNoMargin() const {
return _logoNoMargin;
}
void startSettingsAndBackground();
[[nodiscard]] Settings &settings() {
@ -354,9 +348,6 @@ private:
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;
const QImage _logo;
const QImage _logoNoMargin;
rpl::variable<bool> _passcodeLock;
bool _screenIsLocked = false;

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/click_handler_types.h"
#include "window/window_session_controller.h"
#include "window/main_window.h" // Window::LogoNoMargin.
#include "ui/image/image.h"
#include "ui/empty_userpic.h"
#include "ui/text/text_options.h"
@ -302,7 +303,7 @@ Image *PeerData::currentUserpic(
_userpicEmpty = nullptr;
} else if (isNotificationsUser()) {
static auto result = Image(
Core::App().logoNoMargin().scaledToWidth(
Window::LogoNoMargin().scaledToWidth(
kUserpicSize,
Qt::SmoothTransformation));
return &result;

View File

@ -81,17 +81,6 @@ void FeedLangTestingKey(int key) {
MainWindow::MainWindow(not_null<Window::Controller*> controller)
: Platform::MainWindow(controller) {
auto logo = Core::App().logo();
icon16 = logo.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = logo.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = logo.scaledToWidth(64, Qt::SmoothTransformation);
auto logoNoMargin = Core::App().logoNoMargin();
iconbig16 = logoNoMargin.scaledToWidth(16, Qt::SmoothTransformation);
iconbig32 = logoNoMargin.scaledToWidth(32, Qt::SmoothTransformation);
iconbig64 = logoNoMargin.scaledToWidth(64, Qt::SmoothTransformation);
resize(st::windowDefaultWidth, st::windowDefaultHeight);
setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
@ -842,122 +831,6 @@ void MainWindow::updateControlsGeometry() {
if (_main) _main->checkMainSectionToLayer();
}
void MainWindow::placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) {
QPainter p(&img);
QString cnt = (count < 100) ? QString("%1").arg(count) : QString("..%1").arg(count % 10, 1, 10, QChar('0'));
int32 cntSize = cnt.size();
p.setBrush(bg->b);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
int32 fontSize;
if (size == 16) {
fontSize = 8;
} else if (size == 32) {
fontSize = (cntSize < 2) ? 12 : 12;
} else {
fontSize = (cntSize < 2) ? 22 : 22;
}
style::font f = { fontSize, 0, 0 };
int32 w = f->width(cnt), d, r;
if (size == 16) {
d = (cntSize < 2) ? 2 : 1;
r = (cntSize < 2) ? 4 : 3;
} else if (size == 32) {
d = (cntSize < 2) ? 5 : 2;
r = (cntSize < 2) ? 8 : 7;
} else {
d = (cntSize < 2) ? 9 : 4;
r = (cntSize < 2) ? 16 : 14;
}
p.drawRoundedRect(QRect(shift.x() + size - w - d * 2, shift.y() + size - f->height, w + d * 2, f->height), r, r);
p.setFont(f->f);
p.setPen(color->p);
p.drawText(shift.x() + size - w - d, shift.y() + size - f->height + f->ascent, cnt);
}
QImage MainWindow::iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) {
bool layer = false;
if (size < 0) {
size = -size;
layer = true;
}
if (layer) {
if (size != 16 && size != 20 && size != 24) size = 32;
// platform/linux/main_window_linux depends on count used the same
// way for all the same (count % 1000) values.
QString cnt = (count < 1000) ? QString("%1").arg(count) : QString("..%1").arg(count % 100, 2, 10, QChar('0'));
QImage result(size, size, QImage::Format_ARGB32);
int32 cntSize = cnt.size();
result.fill(Qt::transparent);
{
QPainter p(&result);
p.setBrush(bg);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
int32 fontSize;
if (size == 16) {
fontSize = (cntSize < 2) ? 11 : ((cntSize < 3) ? 11 : 8);
} else if (size == 20) {
fontSize = (cntSize < 2) ? 14 : ((cntSize < 3) ? 13 : 10);
} else if (size == 24) {
fontSize = (cntSize < 2) ? 17 : ((cntSize < 3) ? 16 : 12);
} else {
fontSize = (cntSize < 2) ? 22 : ((cntSize < 3) ? 20 : 16);
}
style::font f = { fontSize, 0, 0 };
int32 w = f->width(cnt), d, r;
if (size == 16) {
d = (cntSize < 2) ? 5 : ((cntSize < 3) ? 2 : 1);
r = (cntSize < 2) ? 8 : ((cntSize < 3) ? 7 : 3);
} else if (size == 20) {
d = (cntSize < 2) ? 6 : ((cntSize < 3) ? 2 : 1);
r = (cntSize < 2) ? 10 : ((cntSize < 3) ? 9 : 5);
} else if (size == 24) {
d = (cntSize < 2) ? 7 : ((cntSize < 3) ? 3 : 1);
r = (cntSize < 2) ? 12 : ((cntSize < 3) ? 11 : 6);
} else {
d = (cntSize < 2) ? 9 : ((cntSize < 3) ? 4 : 2);
r = (cntSize < 2) ? 16 : ((cntSize < 3) ? 14 : 8);
}
p.drawRoundedRect(QRect(size - w - d * 2, size - f->height, w + d * 2, f->height), r, r);
p.setFont(f);
p.setPen(fg);
p.drawText(size - w - d, size - f->height + f->ascent, cnt);
}
return result;
} else {
if (size != 16 && size != 32) size = 64;
}
QImage img(smallIcon ? ((size == 16) ? iconbig16 : (size == 32 ? iconbig32 : iconbig64)) : ((size == 16) ? icon16 : (size == 32 ? icon32 : icon64)));
if (const auto controller = sessionController()) {
if (controller->session().supportMode()) {
Window::ConvertIconToBlack(img);
}
}
if (!count) return img;
if (smallIcon) {
placeSmallCounter(img, size, count, bg, QPoint(), fg);
} else {
QPainter p(&img);
p.drawPixmap(
size / 2,
size / 2,
Ui::PixmapFromImage(
iconWithCounter(-size / 2, count, bg, fg, false)));
}
return img;
}
void MainWindow::sendPaths() {
if (controller().locked()) {
return;

View File

@ -71,9 +71,6 @@ public:
void sendPaths();
QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override;
void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override;
bool contentOverlapped(const QRect &globalRect);
bool contentOverlapped(QWidget *w, QPaintEvent *e) {
return contentOverlapped(QRect(w->mapToGlobal(e->rect().topLeft()), e->rect().size()));
@ -148,8 +145,6 @@ private:
std::unique_ptr<Media::SystemMediaControlsManager> _mediaControlsManager;
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
crl::time _lastTrayClickTime = 0;
QPoint _lastMousePosition;
bool _activeForTrayIconAction = true;

View File

@ -305,7 +305,7 @@ QIcon TrayIconGen(int counter, bool muted) {
}
}
} else {
currentImageBack = Core::App().logo();
currentImageBack = Window::Logo();
}
if (dprSize(currentImageBack) != desiredSize) {
@ -324,20 +324,19 @@ QIcon TrayIconGen(int counter, bool muted) {
: st::trayCounterBg;
const auto &fg = st::trayCounterFg;
if (iconSize >= 22) {
auto layerSize = -16;
if (iconSize >= 48) {
layerSize = -32;
} else if (iconSize >= 36) {
layerSize = -24;
} else if (iconSize >= 32) {
layerSize = -20;
}
const auto layer = App::wnd()->iconWithCounter(
layerSize,
counter,
bg,
fg,
false);
const auto layerSize = (iconSize >= 48)
? 32
: (iconSize >= 36)
? 24
: (iconSize >= 32)
? 20
: 16;
const auto layer = Window::GenerateCounterLayer({
.size = layerSize,
.count = counter,
.bg = bg,
.fg = fg,
});
QPainter p(&iconImage);
p.drawImage(
@ -345,13 +344,12 @@ QIcon TrayIconGen(int counter, bool muted) {
iconImage.height() - layer.height() - 1,
layer);
} else {
App::wnd()->placeSmallCounter(
iconImage,
16,
counter,
bg,
QPoint(),
fg);
iconImage = Window::WithSmallCounter(std::move(iconImage), {
.size = 16,
.count = counter,
.bg = bg,
.fg = fg,
});
}
}

View File

@ -20,13 +20,6 @@ class MainWindow : public Window::MainWindow {
public:
explicit MainWindow(not_null<Window::Controller*> controller);
virtual QImage iconWithCounter(
int size,
int count,
style::color bg,
style::color fg,
bool smallIcon) = 0;
void psShowTrayMenu();
bool trayAvailable() {
@ -54,14 +47,6 @@ protected:
void psTrayMenuUpdated();
void psSetupTrayIcon();
virtual void placeSmallCounter(
QImage &img,
int size,
int count,
style::color bg,
const QPoint &shift,
style::color color) = 0;
private:
class Private;
friend class Private;

View File

@ -25,8 +25,6 @@ public:
bool psFilterNativeEvent(void *event);
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
int getCustomTitleHeight() const {
return _customTitleHeight;
}
@ -77,7 +75,6 @@ protected:
void psTrayMenuUpdated();
void psSetupTrayIcon();
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
void closeWithoutDestroy() override;
void createGlobalMenu() override;

View File

@ -13,7 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/win/windows_dlls.h"
#include "platform/win/windows_event_filter.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "mainwindow.h"
#include "main/main_session.h"
#include "base/crc32hash.h"
#include "base/platform/win/base_windows_wrl.h"
#include "base/platform/base_platform_info.h"
@ -59,47 +61,77 @@ constexpr auto kKeepActiveForTrayIcon = crl::time(500);
using namespace Microsoft::WRL;
HICON createHIconFromQIcon(const QIcon &icon, int xSize, int ySize) {
[[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
if (!icon.isNull()) {
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
if (!pm.isNull()) {
return qt_pixmapToWinHICON(pm);
const auto pixmap = icon.pixmap(icon.actualSize(size));
if (!pixmap.isNull()) {
return qt_pixmapToWinHICON(pixmap);
}
}
return nullptr;
}
HWND createTaskbarHider() {
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
HWND hWnd = 0;
[[nodiscard]] QImage IconWithCounter(
Window::CounterLayerArgs &&args,
Main::Session *session,
bool smallIcon) {
static constexpr auto kCount = 3;
static auto ScaledLogo = std::array<QImage, kCount>();
static auto ScaledLogoNoMargin = std::array<QImage, kCount>();
QString cn = QString("TelegramTaskbarHider");
LPCWSTR _cn = (LPCWSTR)cn.utf16();
WNDCLASSEX wc;
struct Dimensions {
int index = 0;
int size = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size) {
case 16:
return {
.index = 0,
.size = 16,
};
case 32:
return {
.index = 1,
.size = 32,
};
default:
return {
.index = 2,
.size = 64,
};
}
}();
Assert(d.index < kCount);
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = appinst;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = _cn;
wc.hIconSm = 0;
if (!RegisterClassEx(&wc)) {
DEBUG_LOG(("Application Error: could not register taskbar hider window class, error: %1").arg(GetLastError()));
return hWnd;
auto &scaled = smallIcon ? ScaledLogoNoMargin : ScaledLogo;
auto result = [&] {
auto &image = scaled[d.index];
if (image.isNull()) {
image = (smallIcon
? Window::LogoNoMargin()
: Window::Logo()).scaledToWidth(
d.size,
Qt::SmoothTransformation);
}
return image;
}();
if (session && session->supportMode()) {
Window::ConvertIconToBlack(result);
}
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0);
if (!hWnd) {
DEBUG_LOG(("Application Error: could not create taskbar hider window class, error: %1").arg(GetLastError()));
return hWnd;
if (!args.count) {
return result;
} else if (smallIcon) {
return Window::WithSmallCounter(std::move(result), std::move(args));
}
return hWnd;
QPainter p(&result);
const auto half = d.size / 2;
args.size = half;
p.drawPixmap(
half,
half,
Ui::PixmapFromImage(Window::GenerateCounterLayer(std::move(args))));
return result;
}
ComPtr<ITaskbarList3> taskbarList;
@ -202,7 +234,8 @@ void MainWindow::psSetupTrayIcon() {
if (!trayIcon) {
trayIcon = new QSystemTrayIcon(this);
auto icon = QIcon(Ui::PixmapFromImage(Core::App().logoNoMargin()));
const auto icon = QIcon(Ui::PixmapFromImage(
QImage(Window::LogoNoMargin())));
trayIcon->setIcon(icon);
connect(
@ -327,47 +360,72 @@ void MainWindow::unreadCounterChangedHook() {
void MainWindow::updateIconCounters() {
const auto counter = Core::App().unreadBadge();
const auto muted = Core::App().unreadBadgeMuted();
const auto controller = sessionController();
const auto session = controller ? &controller->session() : nullptr;
auto iconSizeSmall = QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
auto iconSizeBig = QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
const auto iconSizeSmall = QSize(
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON));
const auto iconSizeBig = QSize(
GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CYICON));
auto &bg = (muted ? st::trayCounterBgMute : st::trayCounterBg);
auto &fg = st::trayCounterFg;
auto iconSmallPixmap16 = Ui::PixmapFromImage(
iconWithCounter(16, counter, bg, fg, true));
auto iconSmallPixmap32 = Ui::PixmapFromImage(
iconWithCounter(32, counter, bg, fg, true));
const auto &bg = muted ? st::trayCounterBgMute : st::trayCounterBg;
const auto &fg = st::trayCounterFg;
const auto counterArgs = [&](int size, int counter) {
return Window::CounterLayerArgs{
.size = size,
.count = counter,
.bg = bg,
.fg = fg,
};
};
const auto iconWithCounter = [&](int size, int counter, bool smallIcon) {
return Ui::PixmapFromImage(IconWithCounter(
counterArgs(size, counter),
session,
smallIcon));
};
auto iconSmallPixmap16 = iconWithCounter(16, counter, true);
auto iconSmallPixmap32 = iconWithCounter(32, counter, true);
QIcon iconSmall, iconBig;
iconSmall.addPixmap(iconSmallPixmap16);
iconSmall.addPixmap(iconSmallPixmap32);
iconBig.addPixmap(Ui::PixmapFromImage(
iconWithCounter(32, taskbarList.Get() ? 0 : counter, bg, fg, false)));
iconBig.addPixmap(Ui::PixmapFromImage(
iconWithCounter(64, taskbarList.Get() ? 0 : counter, bg, fg, false)));
const auto bigCounter = taskbarList.Get() ? 0 : counter;
iconBig.addPixmap(iconWithCounter(32, bigCounter, false));
iconBig.addPixmap(iconWithCounter(64, bigCounter, false));
if (trayIcon) {
// Force Qt to use right icon size, not the larger one.
QIcon forTrayIcon;
forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 ? iconSmallPixmap32 : iconSmallPixmap16);
forTrayIcon.addPixmap(iconSizeSmall.width() >= 20
? iconSmallPixmap32
: iconSmallPixmap16);
trayIcon->setIcon(forTrayIcon);
}
psDestroyIcons();
ps_iconSmall = createHIconFromQIcon(iconSmall, iconSizeSmall.width(), iconSizeSmall.height());
ps_iconBig = createHIconFromQIcon(iconBig, iconSizeBig.width(), iconSizeBig.height());
SendMessage(ps_hWnd, WM_SETICON, 0, (LPARAM)ps_iconSmall);
SendMessage(ps_hWnd, WM_SETICON, 1, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall));
if (taskbarList.Get()) {
ps_iconSmall = NativeIcon(iconSmall, iconSizeSmall);
ps_iconBig = NativeIcon(iconBig, iconSizeBig);
SendMessage(ps_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)ps_iconSmall);
SendMessage(ps_hWnd, WM_SETICON, ICON_BIG, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall));
if (taskbarList) {
if (counter > 0) {
const auto pixmap = [&](int size) {
return Ui::PixmapFromImage(Window::GenerateCounterLayer(
counterArgs(size, counter)));
};
QIcon iconOverlay;
iconOverlay.addPixmap(Ui::PixmapFromImage(
iconWithCounter(-16, counter, bg, fg, false)));
iconOverlay.addPixmap(Ui::PixmapFromImage(
iconWithCounter(-32, counter, bg, fg, false)));
ps_iconOverlay = createHIconFromQIcon(iconOverlay, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
iconOverlay.addPixmap(pixmap(16));
iconOverlay.addPixmap(pixmap(32));
ps_iconOverlay = NativeIcon(iconOverlay, iconSizeSmall);
}
auto description = (counter > 0) ? tr::lng_unread_bar(tr::now, lt_count, counter) : QString();
taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.toStdWString().c_str());
const auto description = (counter > 0)
? tr::lng_unread_bar(tr::now, lt_count, counter).toStdWString()
: std::wstring();
taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.c_str());
}
psDestroyIcons();
SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}

View File

@ -30,8 +30,6 @@ public:
void psRefreshTaskbarIcon();
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
[[nodiscard]] static uint32 TaskbarCreatedMsgId();
static void TaskbarCreated();
@ -59,7 +57,6 @@ protected:
void psTrayMenuUpdated();
void psSetupTrayIcon();
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
void showTrayTooltip() override;

View File

@ -258,7 +258,7 @@ void NotificationsCount::prepareNotificationSampleSmall() {
void NotificationsCount::prepareNotificationSampleUserpic() {
if (_notificationSampleUserpic.isNull()) {
_notificationSampleUserpic = Ui::PixmapFromImage(
Core::App().logoNoMargin().scaled(
Window::LogoNoMargin().scaled(
st::notifyPhotoSize * cIntRetinaFactor(),
st::notifyPhotoSize * cIntRetinaFactor(),
Qt::IgnoreAspectRatio,

View File

@ -49,12 +49,14 @@ constexpr auto kSaveWindowPositionTimeout = crl::time(1000);
} // namespace
QImage LoadLogo() {
return QImage(qsl(":/gui/art/logo_256.png"));
const QImage &Logo() {
static const auto result = QImage(u":/gui/art/logo_256.png"_q);
return result;
}
QImage LoadLogoNoMargin() {
return QImage(qsl(":/gui/art/logo_256_no_margin.png"));
const QImage &LogoNoMargin() {
static const auto result = QImage(u":/gui/art/logo_256_no_margin.png"_q);
return result;
}
void ConvertIconToBlack(QImage &image) {
@ -105,7 +107,7 @@ void ConvertIconToBlack(QImage &image) {
}
QIcon CreateOfficialIcon(Main::Session *session) {
auto image = Core::IsAppLaunched() ? Core::App().logo() : LoadLogo();
auto image = Logo();
if (session && session->supportMode()) {
ConvertIconToBlack(image);
}
@ -156,6 +158,144 @@ QIcon CreateIcon(Main::Session *session) {
return result;
}
QImage GenerateCounterLayer(CounterLayerArgs &&args) {
// platform/linux/main_window_linux depends on count used the same
// way for all the same (count % 1000) values.
const auto count = args.count.value();
const auto text = (count < 1000)
? QString::number(count)
: u"..%1"_q.arg(count % 100, 2, 10, QChar('0'));
const auto textSize = text.size();
struct Dimensions {
int size = 0;
int font = 0;
int delta = 0;
int radius = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size.value()) {
case 16:
return {
.size = 16,
.font = ((textSize < 2) ? 11 : (textSize < 3) ? 11 : 8),
.delta = ((textSize < 2) ? 5 : (textSize < 3) ? 2 : 1),
.radius = ((textSize < 2) ? 8 : (textSize < 3) ? 7 : 3),
};
case 20:
return {
.size = 20,
.font = ((textSize < 2) ? 14 : (textSize < 3) ? 13 : 10),
.delta = ((textSize < 2) ? 6 : (textSize < 3) ? 2 : 1),
.radius = ((textSize < 2) ? 10 : (textSize < 3) ? 9 : 5),
};
case 24:
return {
.size = 24,
.font = ((textSize < 2) ? 17 : (textSize < 3) ? 16 : 12),
.delta = ((textSize < 2) ? 7 : (textSize < 3) ? 3 : 1),
.radius = ((textSize < 2) ? 12 : (textSize < 3) ? 11 : 6),
};
default:
return {
.size = 32,
.font = ((textSize < 2) ? 22 : (textSize < 3) ? 20 : 16),
.delta = ((textSize < 2) ? 9 : (textSize < 3) ? 4 : 2),
.radius = ((textSize < 2) ? 16 : (textSize < 3) ? 14 : 8),
};
}
}();
auto result = QImage(d.size, d.size, QImage::Format_ARGB32);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
const auto f = style::font{ d.font, 0, 0 };
const auto w = f->width(text);
p.setBrush(args.bg.value());
p.setPen(Qt::NoPen);
p.drawRoundedRect(
QRect(
d.size - w - d.delta * 2,
d.size - f->height,
w + d.delta * 2,
f->height),
d.radius,
d.radius);
p.setFont(f);
p.setPen(args.fg.value());
p.drawText(d.size - w - d.delta, d.size - f->height + f->ascent, text);
p.end();
return result;
}
QImage WithSmallCounter(QImage image, CounterLayerArgs &&args) {
const auto count = args.count.value();
const auto text = (count < 100)
? QString::number(count)
: QString("..%1").arg(count % 10, 1, 10, QChar('0'));
const auto textSize = text.size();
struct Dimensions {
int size = 0;
int font = 0;
int delta = 0;
int radius = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size.value()) {
case 16:
return {
.size = 16,
.font = 8,
.delta = ((textSize < 2) ? 2 : 1),
.radius = ((textSize < 2) ? 4 : 3),
};
case 32:
return {
.size = 32,
.font = 12,
.delta = ((textSize < 2) ? 5 : 2),
.radius = ((textSize < 2) ? 8 : 7),
};
default:
return {
.size = 64,
.font = 22,
.delta = ((textSize < 2) ? 9 : 4),
.radius = ((textSize < 2) ? 16 : 14),
};
}
}();
auto p = QPainter(&image);
auto hq = PainterHighQualityEnabler(p);
const auto f = style::font{ d.font, 0, 0 };
const auto w = f->width(text);
p.setBrush(args.bg.value());
p.setPen(Qt::NoPen);
p.drawRoundedRect(
QRect(
d.size - w - d.delta * 2,
d.size - f->height,
w + d.delta * 2,
f->height),
d.radius,
d.radius);
p.setFont(f);
p.setPen(args.fg.value());
p.drawText(d.size - w - d.delta, d.size - f->height + f->ascent, text);
p.end();
return image;
}
MainWindow::MainWindow(not_null<Controller*> controller)
: _controller(controller)
, _positionUpdatedTimer([=] { savePosition(); })

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h"
#include "base/object_ptr.h"
#include "core/core_settings.h"
#include "base/required.h"
#include <QtWidgets/QSystemTrayIcon>
@ -35,11 +36,21 @@ class SessionController;
class TitleWidget;
struct TermsLock;
QImage LoadLogo();
QImage LoadLogoNoMargin();
QIcon CreateIcon(Main::Session *session = nullptr);
[[nodiscard]] const QImage &Logo();
[[nodiscard]] const QImage &LogoNoMargin();
[[nodiscard]] QIcon CreateIcon(Main::Session *session = nullptr);
void ConvertIconToBlack(QImage &image);
struct CounterLayerArgs {
base::required<int> size = 16;
base::required<int> count = 1;
base::required<style::color> bg;
base::required<style::color> fg;
};
[[nodiscard]] QImage GenerateCounterLayer(CounterLayerArgs &&args);
[[nodiscard]] QImage WithSmallCounter(QImage image, CounterLayerArgs &&args);
class MainWindow : public Ui::RpWindow {
public:
explicit MainWindow(not_null<Controller*> controller);

View File

@ -87,7 +87,7 @@ Manager::QueuedNotification::QueuedNotification(
QPixmap Manager::hiddenUserpicPlaceholder() const {
if (_hiddenUserpicPlaceholder.isNull()) {
_hiddenUserpicPlaceholder = Ui::PixmapFromImage(
Core::App().logoNoMargin().scaled(
LogoNoMargin().scaled(
st::notifyPhotoSize,
st::notifyPhotoSize,
Qt::IgnoreAspectRatio,

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/notifications_utilities.h"
#include "window/main_window.h"
#include "base/platform/base_platform_file_utilities.h"
#include "base/random.h"
#include "core/application.h"
@ -79,7 +80,7 @@ QString CachedUserpics::get(
peer->saveUserpic(view, v.path, st::notifyMacPhotoSize);
}
} else {
Core::App().logoNoMargin().save(v.path, "PNG");
LogoNoMargin().save(v.path, "PNG");
}
i = _images.insert(key, v);
_someSavedFlag = true;