Skip to content

Commit

Permalink
[Option][WIP] Profile pic rounding
Browse files Browse the repository at this point in the history
  • Loading branch information
EricKotato committed Jan 2, 2024
1 parent a31c5af commit 1904237
Show file tree
Hide file tree
Showing 22 changed files with 275 additions and 33 deletions.
2 changes: 2 additions & 0 deletions Telegram/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,8 @@ PRIVATE
kotato/boxes/kotato_unpin_box.h
kotato/kotato_lang.cpp
kotato/kotato_lang.h
kotato/kotato_radius.cpp
kotato/kotato_radius.h
kotato/kotato_settings.cpp
kotato/kotato_settings.h
kotato/kotato_settings_menu.cpp
Expand Down
5 changes: 2 additions & 3 deletions Telegram/SourceFiles/boxes/peer_list_box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "boxes/peer_list_box.h"

#include "kotato/kotato_radius.h"
#include "kotato/kotato_lang.h"
#include "history/history.h" // chatListNameSortKey.
#include "main/session/session_show.h"
Expand Down Expand Up @@ -900,9 +901,7 @@ void PeerListRow::createCheckbox(
const style::RoundImageCheckbox &st,
Fn<void()> updateCallback) {
const auto generateRadius = [=](int size) {
return (!special() && peer()->isForum())
? int(size * Ui::ForumUserpicRadiusMultiplier())
: std::optional<int>();
return int(size * Kotato::UserpicRadius(!special() && peer()->isForum()));
};
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(
st,
Expand Down
2 changes: 2 additions & 0 deletions Telegram/SourceFiles/core/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "core/launcher.h"

#include "kotato/kotato_radius.h"
#include "kotato/kotato_settings.h"
#include "kotato/kotato_version.h"
#include "platform/platform_launcher.h"
Expand Down Expand Up @@ -375,6 +376,7 @@ int Launcher::exec() {
Logs::start();
base::options::init(cWorkingDir() + "tdata/experimental_options.json");
Kotato::JsonSettings::Load();
Kotato::RefreshRadius();

// Must be called after options are inited.
initHighDpi();
Expand Down
24 changes: 22 additions & 2 deletions Telegram/SourceFiles/data/data_peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "data/data_peer.h"

#include "kotato/kotato_radius.h"
#include "data/data_user.h"
#include "data/data_chat.h"
#include "data/data_chat_participant_status.h"
Expand Down Expand Up @@ -382,6 +383,7 @@ QImage PeerData::generateUserpicImage(
Ui::PeerUserpicView &view,
int size,
std::optional<int> radius) const {
const auto radiusOption = Kotato::UserpicRadius(isForum());
if (const auto userpic = userpicCloudImage(view)) {
auto image = userpic->scaled(
{ size, size },
Expand All @@ -393,7 +395,13 @@ QImage PeerData::generateUserpicImage(
Images::CornersMask(radius / style::DevicePixelRatio()));
};
if (radius == 0) {
return image;
if (radiusOption == 0.0) {
return image;
} else if (radiusOption) {
return round(size * radiusOption);
} else {
return Images::Circle(std::move(image));
}
} else if (radius) {
return round(*radius);
} else if (isForum()) {
Expand All @@ -409,7 +417,19 @@ QImage PeerData::generateUserpicImage(

Painter p(&result);
if (radius == 0) {
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
if (radiusOption == 0.0) {
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
} else if (radiusOption) {
ensureEmptyUserpic()->paintRounded(
p,
0,
0,
size,
size,
size * radiusOption);
} else {
ensureEmptyUserpic()->paintCircle(p, 0, 0, size, size);
}
} else if (radius) {
ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size, *radius);
} else if (isForum()) {
Expand Down
3 changes: 2 additions & 1 deletion Telegram/SourceFiles/dialogs/dialogs_row.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "dialogs/dialogs_row.h"

#include "kotato/kotato_radius.h"
#include "ui/chat/chat_theme.h" // CountAverageColor.
#include "ui/color_contrast.h"
#include "ui/effects/outline_segments.h"
Expand Down Expand Up @@ -416,7 +417,7 @@ void Row::PaintCornerBadgeFrame(
: st::dialogsCallBadgeSize;
const auto stroke = st::dialogsOnlineBadgeStroke;
const auto skip = online
? st::dialogsOnlineBadgeSkip
? Kotato::UserpicOnlineBadgeSkip()
: st::dialogsCallBadgeSkip;
const auto shrink = (size / 2) * (1. - topLayerProgress);

Expand Down
3 changes: 2 additions & 1 deletion Telegram/SourceFiles/dialogs/ui/dialogs_video_userpic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "dialogs/ui/dialogs_video_userpic.h"

#include "kotato/kotato_radius.h"
#include "core/file_location.h"
#include "data/data_peer.h"
#include "data/data_photo.h"
Expand Down Expand Up @@ -100,7 +101,7 @@ Media::Clip::FrameRequest VideoUserpic::request(int size) const {
.frame = { size, size },
.outer = { size, size },
.factor = cIntRetinaFactor(),
.radius = ImageRoundRadius::Ellipse,
.radius = Kotato::UserpicRadius(),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "history/view/history_view_group_call_bar.h"

#include "kotato/kotato_radius.h"
#include "data/data_channel.h"
#include "data/data_user.h"
#include "data/data_changes.h"
Expand Down Expand Up @@ -59,7 +60,7 @@ void GenerateUserpicsInRow(
q.setCompositionMode(QPainter::CompositionMode_Source);
q.setBrush(Qt::NoBrush);
q.setPen(pen);
q.drawEllipse(x, 0, single, single);
Kotato::DrawUserpicShape(q, x, 0, single, single, single);
x -= single - shift;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For license and copyright information please follow this link:
*/
#include "history/view/reactions/history_view_reactions.h"

#include "kotato/kotato_radius.h"
#include "history/history_item.h"
#include "history/history.h"
#include "history/view/history_view_message.h"
Expand Down Expand Up @@ -338,6 +339,7 @@ void InlineList::paint(
const auto skip = (size - st::reactionInlineImage) / 2;
const auto inbubble = (_data.flags & InlineListData::Flag::InBubble);
const auto flipped = (_data.flags & Data::Flag::Flipped);
const auto radiusOption = Kotato::UserpicRadius();
p.setFont(st::semiboldFont);
for (const auto &button : _buttons) {
if (context.reactionInfo
Expand Down Expand Up @@ -381,7 +383,7 @@ void InlineList::paint(
}
p.setBrush(chosen ? st->msgServiceFg() : st->msgServiceBg());
}
const auto radius = geometry.height() / 2.;
const auto radius = geometry.height() * radiusOption;
const auto fill = geometry.marginsAdded({
flipped ? bubbleSkip : 0,
0,
Expand Down
143 changes: 143 additions & 0 deletions Telegram/SourceFiles/kotato/kotato_radius.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
This file is part of Kotatogram Desktop,
the unofficial app based on Telegram Desktop.
For license and copyright information please follow this link:
https://github.com/kotatogram/kotatogram-desktop/blob/dev/LEGAL
*/
#include "kotato/kotato_radius.h"

#include "kotato/kotato_settings.h"
#include "ui/painter.h"
#include "styles/style_chat.h"
#include "styles/style_dialogs.h"

namespace Kotato {
namespace {

struct Radius {
float64 userpicRadius = 0.5;
float64 forumUserpicRadius = 0.3;
bool useDefaultRadiusForForum = false;
style::point onlineBadgeSkip = st::dialogsOnlineBadgeSkip;
};

Radius radius;

} // namespace

void RefreshRadius() {
radius.userpicRadius = float64(JsonSettings::GetInt("userpic_corner_radius")) / 100.0;
radius.forumUserpicRadius = float64(JsonSettings::GetInt("userpic_corner_radius_forum")) / 100.0;
radius.useDefaultRadiusForForum = JsonSettings::GetBool("userpic_corner_radius_forum_use_default");
radius.onlineBadgeSkip = {
style::ConvertScale(int(2 * radius.userpicRadius) - 1),
style::ConvertScale(int(6 * radius.userpicRadius) - 1),
};
}

float64 UserpicRadius(bool isForum) {
if (isForum && !radius.useDefaultRadiusForForum) {
return radius.forumUserpicRadius;
}
return radius.userpicRadius;
}

void DrawUserpicShape(
QPainter &p,
QRect rect,
float64 size,
bool isForum) {
const auto r = UserpicRadius(isForum);
if (r >= 0.5) {
p.drawEllipse(rect);
} else if (r) {
p.drawRoundedRect(rect, size * r, size * r);
} else {
p.fillRect(rect, p.brush());
}
}

void DrawUserpicShape(
QPainter &p,
QRectF rect,
float64 size,
bool isForum) {
const auto r = UserpicRadius(isForum);
if (r >= 0.5) {
p.drawEllipse(rect);
} else if (r) {
p.drawRoundedRect(rect, size * r, size * r);
} else {
p.fillRect(rect, p.brush());
}
}

void DrawUserpicShape(
QPainter &p,
int x,
int y,
int w,
int h,
float64 size,
bool isForum) {
const auto r = UserpicRadius(isForum);
if (r >= 0.5) {
p.drawEllipse(x, y, w, h);
} else if (r) {
p.drawRoundedRect(x, y, w, h, size * r, size * r);
} else {
p.fillRect(x, y, w, h, p.brush());
}
}

style::point UserpicOnlineBadgeSkip() {
return radius.onlineBadgeSkip;
}

QPixmap MessageTailLeft(style::color color) {
const auto tail = st::historyBubbleTailInLeft;
QImage rect(tail.width(), tail.height(), QImage::Format_ARGB32_Premultiplied);
rect.fill(color->c);
{
auto p = QPainter(&rect);
PainterHighQualityEnabler hq(p);

p.setCompositionMode(QPainter::CompositionMode_Source);
p.setPen(Qt::NoPen);
p.setBrush(Qt::transparent);
p.drawRoundedRect(
tail.width()-st::msgPhotoSize+style::ConvertScale(1),
tail.height()-st::msgPhotoSize+style::ConvertScale(2),
st::msgPhotoSize,
st::msgPhotoSize,
st::msgPhotoSize * radius.userpicRadius,
st::msgPhotoSize * radius.userpicRadius);
}
return QPixmap::fromImage(rect);
}

QPixmap MessageTailRight(style::color color) {
const auto tail = st::historyBubbleTailInRight;
QImage rect(tail.width(), tail.height(), QImage::Format_ARGB32_Premultiplied);
rect.fill(color->c);
{
auto p = QPainter(&rect);
PainterHighQualityEnabler hq(p);

p.setCompositionMode(QPainter::CompositionMode_Source);
p.setPen(Qt::NoPen);
p.setBrush(Qt::transparent);
p.drawRoundedRect(
-style::ConvertScale(1),
tail.height()-st::msgPhotoSize+style::ConvertScale(2),
st::msgPhotoSize,
st::msgPhotoSize,
st::msgPhotoSize * radius.userpicRadius,
st::msgPhotoSize * radius.userpicRadius);
}
return QPixmap::fromImage(rect);
}


} // namespace Kotato
38 changes: 38 additions & 0 deletions Telegram/SourceFiles/kotato/kotato_radius.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
This file is part of Kotatogram Desktop,
the unofficial app based on Telegram Desktop.
For license and copyright information please follow this link:
https://github.com/kotatogram/kotatogram-desktop/blob/dev/LEGAL
*/
#pragma once

namespace Kotato {

void RefreshRadius();
float64 UserpicRadius(bool isForum = false);
void DrawUserpicShape(
QPainter &p,
QRect rect,
float64 size,
bool isForum = false);
void DrawUserpicShape(
QPainter &p,
QRectF rect,
float64 size,
bool isForum = false);
void DrawUserpicShape(
QPainter &p,
int x,
int y,
int w,
int h,
float64 size,
bool isForum = false);

style::point UserpicOnlineBadgeSkip();

QPixmap MessageTailLeft(style::color color);
QPixmap MessageTailRight(style::color color);

} // namespace Kotato
11 changes: 11 additions & 0 deletions Telegram/SourceFiles/kotato/kotato_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ const std::map<QString, Definition, std::greater<QString>> DefinitionMap {
.type = SettingType::IntSetting,
.defaultValue = 20,
.limitHandler = IntLimit(0, 200, 20), }},
{ "userpic_corner_radius", {
.type = SettingType::IntSetting,
.defaultValue = 50,
.limitHandler = IntLimit(0, 50), }},
{ "userpic_corner_radius_forum", {
.type = SettingType::IntSetting,
.defaultValue = 30,
.limitHandler = IntLimit(0, 50), }},
{ "userpic_corner_radius_forum_use_default", {
.type = SettingType::BoolSetting,
.defaultValue = false, }},
{ "always_show_top_userpic", {
.type = SettingType::BoolSetting,
.defaultValue = false, }},
Expand Down
5 changes: 2 additions & 3 deletions Telegram/SourceFiles/media/clip/media_clip_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ QImage PrepareFrame(
const auto needResize = (original.size() != request.frame);
const auto needOuterFill = request.outer.isValid()
&& (request.outer != request.frame);
const auto needRounding = (request.radius != ImageRoundRadius::None);
const auto needRounding = (request.radius > 0.0);
const auto colorizing = (request.colored.alpha() != 0);
if (!needResize
&& !needOuterFill
Expand Down Expand Up @@ -98,8 +98,7 @@ QImage PrepareFrame(
if (needRounding) {
cache = Images::Round(
std::move(cache),
request.radius,
request.corners);
Images::CornersMask((cache.width() * request.radius) / style::DevicePixelRatio()));
}
if (colorizing) {
cache = Images::Colored(std::move(cache), request.colored);
Expand Down
Loading

0 comments on commit 1904237

Please sign in to comment.